Lua:Fretta
From GMod Wiki
Go to: Fretta |
Lua: Fretta Tutorial |
Description: | Details the steps to create a Fretta Gamemode |
Original Author: | by Rambo_6 |
Created: | August 8, 2009 |
This tutorial requires the basic understanding of Lua.
Tutorial #1: The basics of Fretta
So you have your brand new empty gamemode folder all ready to begin working on. Firstly, start with shared.lua.
This is what your shared.lua should look like off the bat. Just copy and paste this. Then, edit each variable to what you require for your gamemode. For this example I'm going to make a simple free for all deathmatch where the player with the most kills wins.
GM.Name = "Revolver Fight" GM.Author = "Rambo_6" GM.Email = "" GM.Website = "" GM.Help = "Kill the other team or something" GM.Data = {} DeriveGamemode( "fretta" ) IncludePlayerClasses() // Automatically includes files in "gamemode/player_class" GM.TeamBased = false // Team based game or a Free For All game? GM.AllowAutoTeam = true GM.AllowSpectating = true GM.SecondsBetweenTeamSwitches = 10 GM.GameLength = 15 GM.RoundLimit = 10 // Maximum amount of rounds to be played in round based games GM.VotingDelay = 5 // Delay between end of game, and vote. if you want to display any extra screens before the vote pops up GM.NoPlayerSuicide = false GM.NoPlayerDamage = false GM.NoPlayerSelfDamage = false // Allow players to hurt themselves? GM.NoPlayerTeamDamage = false // Allow team-members to hurt each other? GM.NoPlayerPlayerDamage = false // Allow players to hurt each other? GM.NoNonPlayerPlayerDamage = false // Allow damage from non players (physics, fire etc) GM.NoPlayerFootsteps = false // When true, all players have silent footsteps GM.PlayerCanNoClip = false // When true, players can use noclip without sv_cheats GM.TakeFragOnSuicide = false // -1 frag on suicide GM.MaximumDeathLength = 10 // Player will respawn if death length > this (can be 0 to disable) GM.MinimumDeathLength = 5 // Player has to be dead for at least this long GM.AutomaticTeamBalance = false // Teams will be periodically balanced GM.ForceJoinBalancedTeams = false // Players won't be allowed to join a team if it has more players than another team GM.RealisticFallDamage = false GM.AddFragsToTeamScore = false // Adds player's individual kills to team score (must be team based) GM.NoAutomaticSpawning = false // Players don't spawn automatically when they die, some other system spawns them GM.RoundBased = true // Round based, like CS GM.RoundLength = 60 * 2 // Round length, in seconds GM.RoundPreStartTime = 5 // Preperation time before a round starts GM.RoundPostLength = 5 // Seconds to show the 'x team won!' screen at the end of a round GM.RoundEndsWhenOneTeamAlive = false // CS Style rules GM.EnableFreezeCam = false // TF2 Style Freezecam GM.DeathLingerTime = 3 // The time between you dying and it going into spectator mode, 0 disables GM.SelectModel = true // Can players use the playermodel picker in the F1 menu? GM.SelectColor = true // Can players modify the colour of their name? (ie.. no teams) GM.PlayerRingSize = 48 // How big are the colored rings under the player's feet (if they are enabled) ? GM.HudSkin = "SimpleSkin" GM.ValidSpectatorModes = { OBS_MODE_CHASE, OBS_MODE_IN_EYE, OBS_MODE_ROAMING } GM.ValidSpectatorEntities = { "player" } // Entities we can spectate GM.CanOnlySpectateOwnTeam = false // you can only spectate players on your own team
So there you have the backbone of the gamemode, all of the basic rules and settings. Now you create your teams in the same file.
TEAM_HUMAN = 1 function GM:CreateTeams() if ( !GAMEMODE.TeamBased ) then return end team.SetUp( TEAM_HUMAN, "Human Dudes", Color( 50, 255, 50 ), true ) team.SetSpawnPoint( TEAM_HUMAN, { "info_player_start", "info_player_terrorist", "info_player_rebel", "info_player_deathmatch" } ) team.SetClass( TEAM_HUMAN, { "Human" } ) // "Human" is the class we want players to use team.SetUp( TEAM_SPECTATOR, "Spectators", Color( 200, 200, 200 ), true ) team.SetSpawnPoint( TEAM_SPECTATOR, { "info_player_start", "info_player_terrorist", "info_player_counterterrorist", "info_player_combine", "info_player_rebel" } ) end
Note that we've set a specific class for the Human Dudes to use. Let's code that next.
Now you need to make a folder called "player_class" in the same folder as shared.lua. In that folder, make a lua file called "class_human" or something similar that is easy to recognize.
In that file, put this:
local CLASS = {} CLASS.DisplayName = "Revolver Dude" CLASS.WalkSpeed = 400 CLASS.CrouchedWalkSpeed = 0.2 CLASS.RunSpeed = 600 CLASS.DuckSpeed = 0.2 CLASS.JumpPower = 200 CLASS.PlayerModel = "models/player/breen.mdl" CLASS.DrawTeamRing = true CLASS.DrawViewModel = true CLASS.CanUseFlashlight = true CLASS.MaxHealth = 100 CLASS.StartHealth = 100 CLASS.StartArmor = 0 CLASS.RespawnTime = 0 // 0 means use the default spawn time chosen by gamemode CLASS.DropWeaponOnDie = false CLASS.TeammateNoCollide = false CLASS.AvoidPlayers = false // Automatically avoid players that we're no colliding CLASS.Selectable = true // When false, this disables all the team checking CLASS.FullRotation = false // Allow the player's model to rotate upwards, etc etc function CLASS:Loadout( pl ) pl:Give( "weapon_357" ) end function CLASS:OnSpawn( pl ) end function CLASS:OnDeath( pl, attacker, dmginfo ) end function CLASS:Think( pl ) end function CLASS:Move( pl, mv ) end function CLASS:OnKeyPress( pl, key ) end function CLASS:OnKeyRelease( pl, key ) end function CLASS:ShouldDrawLocalPlayer( pl ) return false end function CLASS:CalcView( ply, origin, angles, fov ) end player_class.Register( "Human", CLASS )
This is your barebones "Human" class for the player. The benefit of having these functions here instead of just using the gamemode hooks is that it's all compartmentalized and way tidier. This makes it way easier to create different classes with different abilities, loadouts, etc.
Of course if you aren't using any of the hooks I've pasted here you can just chop them out of the class and nothing will happen. This is just a simple barebones class that spawns as Breen with a revolver.
So now that you have your teams, basic gamemode rules and player classes set up, let's finish up by doing the round-based stuff.
In this example, I've made rounds last 2 minutes. At the end of each round i want to pick the player with the most kills and declare him the winner. Alternatively, the round could end early if a player reaches 10 kills. So in init.lua, I'd do this:
// This is called every second to see if we can end the round function GM:CheckRoundEnd() if ( !GAMEMODE:InRound() ) then return end for k,v in pairs( team.GetPlayers( TEAM_HUMAN ) ) do if v:Frags() >= 10 then GAMEMODE:RoundEndWithResult( v ) end end end // This is called after a player wins in a free for all function GM:OnRoundWinner( ply, resulttext ) ply:AddScore( 1 ) // Let's pretend we have AddScore for brevity's sake end // Called when the round ends function GM:OnRoundEnd( num ) for k,v in pairs( team.GetPlayers( TEAM_HUMAN ) ) do v:SetFrags( 0 ) // Reset their frags for next round end end
These are the basic 4 functions that you'll probably need to use. There are some other ones that are also useful such as:
- OnRoundStart - Called when the round begins
- GetRoundTime - You can edit this to modify how long certain rounds last.
- ProcessResultText - Choose what text is displayed when the round ends here.
Then you'd edit CheckRoundEnd to search for the player with the least kills.
Or if you want no kill limit, use RoundTimerEnd and SelectCurrentlyWinningPlayer to check which player has the least kills when the round ends, then make them the winner.
This is what RoundTimerEnd and SelectCurrentlyWinningPlayer look like by default:
// // This is called when time runs out and there is no winner chosen yet (free for all gamemodes only) // By default it chooses the player with the most frags but you can edit this to do what you need.. // function GM:SelectCurrentlyWinningPlayer() local winner local topscore = 0 for k,v in pairs( player.GetAll() ) do if v:Frags() > topscore and v:Team() != TEAM_CONNECTING and v:Team() != TEAM_UNASSIGNED and v:Team() != TEAM_SPECTATOR then winner = v topscore = v:Frags() end end return winner end // // This is called when the round time ends. // function GM:RoundTimerEnd() if ( !GAMEMODE:InRound() ) then return end if ( !GAMEMODE.TeamBased ) then local ply = GAMEMODE:SelectCurrentlyWinningPlayer() if ply then GAMEMODE:RoundEndWithResult( ply, "Time Up" ) else GAMEMODE:RoundEndWithResult( -1, "Time Up" ) end else GAMEMODE:RoundEndWithResult( -1, "Time Up" ) end end
So there we have a barebones revolver deathmatch gamemode. Easy, right?