function GM:SetRoundWinner( ply, resulttext ) SetGlobalEntity( "RoundWinner", ply ) SetGlobalString( "RRText", tostring(resulttext) ) end function GM:SetRoundResult( i, resulttext ) SetGlobalInt( "RoundResult", i ) SetGlobalString( "RRText", tostring(resulttext) ) end function GM:ClearRoundResult() SetGlobalEntity( "RoundWinner", NULL ) SetGlobalInt( "RoundResult", 0 ) SetGlobalString( "RRText", "" ) end function GM:SetInRound( b ) SetGlobalBool( "InRound", b ) end function GM:InRound() return GetGlobalBool( "InRound", false ) end --[[ FUEL SPAWNING 1 Players: Dont spawn anything 2 Players: Spawn one fuel can 4 times during the round 4 Players: Spawn two fuel cans 4 times during a round 6 Players: Spawn two fuel cans 4 times during a round 8 Players: Spawn three fuel cans 4 times. 10 Players: Spawn three fuel cans ]] function GM:OnRoundStart( num ) UTIL_UnFreezeAllPlayers() for k,v in pairs(player.GetAll()) do v:SetMainScore(0) end //Choose some fuel pods to spawn as neutral things self:SpawnSomeFuel() DF_FIRST_BLOOD = true end function GM:SpawnSomeFuel(NotFirst) local amount = #player.GetAll() * 0.5 if( !GAMEMODE:InRound() ) then return end local tab = ents.FindByClass("df_fuel_node") local good_ones = {} for k,v in pairs(tab) do if !ValidEntity(v:GetPod()) and v.Team == 0 then table.insert(good_ones, v) end end if #tab - #good_ones - 2 > math.floor(amount / 2) then //If there are more than a certain amount of neut's already dont bother. Minus two for the fuel factor ones timer.Create( "FuelSpawnTimer", 60, 0, GAMEMODE.SpawnSomeFuel, GAMEMODE, true ) return end for i=1, math.Clamp(amount, 1, #good_ones) do local tab = ents.FindByClass("df_fuel_node") local good_ones = {} for k,v in pairs(tab) do if !ValidEntity(v:GetPod()) and v.Team == 0 then table.insert(good_ones, v) end end local node = table.Random(good_ones) node:SpawnPod() end while (#ents.FindByClass("df_fuel_node") < amount) do local node = table.Random(good_ones) node:SpawnPod() end if NotFirst then for k,v in pairs(player.GetAll()) do v:PrintCenter("Let's mix this up a little. More fuel spawned!",6, 2) end end local delay = self.RoundLength / self.FuelSpawnTimes timer.Create( "FuelSpawnTimer", delay, 0, GAMEMODE.SpawnSomeFuel, GAMEMODE, true ) end function GM:OnRoundEnd( num ) //GAMEMODE:GetRocket(TEAM_RED).dt.Fuel = 0 //GAMEMODE:GetRocket(TEAM_BLUE).dt.Fuel = 0 for k,v in pairs(player.GetAll()) do v:KillSilent() end //for k,v in pairs(GAMEMODE:GetFuelPods()) do //v:Remove() //end end function GM:OnRoundResult( result, resulttext ) // The fact that result might not be a team // shouldn't matter when calling this.. team.AddScore( result, 1 ) end function GM:OnRoundWinner( ply, resulttext ) // Do whatever you want to do with the winner here (this is only called in Free For All gamemodes)... ply:AddFrags( 1 ) end function GM:OnPreRoundStart( num ) UTIL_StripAllPlayers() //UTIL_SpawnAllPlayers() UTIL_FreezeAllPlayers() for k,v in pairs(ents.FindByClass("df_rocket")) do v:Reset() // in case it launched end self.RoundPostLength = 20 GAMEMODE:GetRocket(TEAM_RED).dt.Fuel = 0 GAMEMODE:GetRocket(TEAM_BLUE).dt.Fuel = 0 for k,v in pairs(GAMEMODE:GetFuelPods()) do v:Remove() end end function GM:CanStartRound( iNum ) return true end function GM:StartRoundBasedGame() GAMEMODE:PreRoundStart( 1 ) end // Number of rounds function GM:GetRoundLimit() return GAMEMODE.RoundLimit; end // Has the round limit been reached? function GM:HasReachedRoundLimit( iNum ) local iRoundLimit = GAMEMODE:GetRoundLimit(); if( iRoundLimit > 0 && iNum > iRoundLimit ) then return true end return false end // This is for the timer-based game end. set this to return true if you want it to end mid-round function GM:CanEndRoundBasedGame() return false end // You can add round time by calling this (takes time in seconds) function GM:AddRoundTime( iAddedTime ) if( !GAMEMODE:InRound() ) then // don't add time if round is not in progress return end SetGlobalFloat( "RoundEndTime", GetGlobalFloat( "RoundEndTime", CurTime() ) + iAddedTime ); timer.Adjust( "RoundEndTimer", GetGlobalFloat( "RoundEndTime" ) - GetGlobalFloat( "RoundStartTime" ), 0, function() GAMEMODE:RoundTimerEnd() end ); local rf = RecipientFilter() rf:AddAllPlayers() umsg.Start( "RoundAddedTime", rf ); // send a umsg so you can do something with the HUD umsg.Float( iAddedTime ); // time added umsg.End(); end // This gets the timer for a round (you can make round number dependant round lengths, or make it cvar controlled) function GM:GetRoundTime( iRoundNumber ) return GAMEMODE.RoundLength; end // // Internal, override OnPreRoundStart if you want to do stuff here // function GM:PreRoundStart( iNum ) // Should the game end? if( CurTime() >= GAMEMODE.GetTimeLimit() || GAMEMODE:HasReachedRoundLimit( iNum ) ) then GAMEMODE:EndOfGame( true ); return; end if ( !GAMEMODE:CanStartRound( iNum ) ) then timer.Simple( 1, function() GAMEMODE:PreRoundStart( iNum ) end ) // In a second, check to see if we can start return; end timer.Simple( GAMEMODE.RoundPreStartTime, function() GAMEMODE:RoundStart() end ) SetGlobalInt( "RoundNumber", iNum ) SetGlobalFloat( "RoundStartTime", CurTime() + GAMEMODE.RoundPreStartTime ) GAMEMODE:ClearRoundResult() GAMEMODE:OnPreRoundStart( GetGlobalInt( "RoundNumber" ) ) GAMEMODE:SetInRound( true ) end // // Internal, override OnRoundStart if you want to do stuff here // function GM:RoundStart() local roundNum = GetGlobalInt( "RoundNumber" ); local roundDuration = GAMEMODE:GetRoundTime( roundNum ) GAMEMODE:OnRoundStart( roundNum ) timer.Create( "RoundEndTimer", roundDuration, 0, function() GAMEMODE:RoundTimerEnd() end ) timer.Create( "CheckRoundEnd", 1, 0, function() GAMEMODE:CheckRoundEnd() end ) SetGlobalFloat( "RoundEndTime", CurTime() + roundDuration ); end // // Decide what text should show when a team/player wins // function GM:ProcessResultText( result, resulttext ) if ( resulttext == nil ) then resulttext = "" end //the result could either be a number or a player! // for a free for all you could do... if type(result) == "Player" and ValidEntity( result ) then return result:Name().." is the winner" or whatever return resulttext end // // Round Ended with Result // function GM:RoundEndWithResult( result, resulttext ) resulttext = GAMEMODE:ProcessResultText( result, resulttext ) if type( result ) == "number" then // the result is a team ID GAMEMODE:SetRoundResult( result, resulttext ) GAMEMODE:RoundEnd() GAMEMODE:OnRoundResult( result, resulttext ) else // the result is a player GAMEMODE:SetRoundWinner( result, resulttext ) GAMEMODE:RoundEnd() GAMEMODE:OnRoundWinner( result, resulttext ) end end // // Internal, override OnRoundEnd if you want to do stuff here // function GM:RoundEnd() if ( !GAMEMODE:InRound() ) then // if someone uses RoundEnd incorrectly then do a trace. MsgN("WARNING: RoundEnd being called while gamemode not in round...") debug.Trace() return end GAMEMODE:OnRoundEnd( GetGlobalInt( "RoundNumber" ) ) self:SetInRound( false ) timer.Destroy( "RoundEndTimer" ) timer.Destroy( "CheckRoundEnd" ) SetGlobalFloat( "RoundEndTime", -1 ) timer.Simple( GAMEMODE.RoundPostLength, function() GAMEMODE:PreRoundStart( GetGlobalInt( "RoundNumber" )+1 ) end ) end function GM:GetTeamAliveCounts() local TeamCounter = {} for k,v in pairs( player.GetAll() ) do if ( v:Alive() && v:Team() > 0 && v:Team() < 1000 ) then TeamCounter[ v:Team() ] = TeamCounter[ v:Team() ] or 0 TeamCounter[ v:Team() ] = TeamCounter[ v:Team() ] + 1 end end return TeamCounter end // // For round based games that end when a team is dead // function GM:CheckPlayerDeathRoundEnd() if ( !GAMEMODE.RoundBased ) then return end if ( !GAMEMODE:InRound() ) then return end if ( GAMEMODE.RoundEndsWhenOneTeamAlive ) then local Teams = GAMEMODE:GetTeamAliveCounts() if ( table.Count( Teams ) == 0 ) then GAMEMODE:RoundEndWithResult( 1001, "Draw, everyone loses!" ) return end if ( table.Count( Teams ) == 1 ) then local TeamID = table.GetFirstKey( Teams ) GAMEMODE:RoundEndWithResult( TeamID ) return end end end hook.Add( "PlayerDisconnect", "RoundCheck_PlayerDisconnect", function() timer.Simple( 0.2, function() GAMEMODE:CheckPlayerDeathRoundEnd() end ) end ) hook.Add( "PostPlayerDeath", "RoundCheck_PostPlayerDeath", function() timer.Simple( 0.2, function() GAMEMODE:CheckPlayerDeathRoundEnd() end ) end ) // // You should use this to check any round end conditions // function GM:CheckRoundEnd() // Do checks.. // if something then call GAMEMODE:RoundEndWithResult( TEAM_BLUE, "Team Blue Ate All The Mushrooms!" ) // OR for a free for all you could do something like... GAMEMODE:RoundEndWithResult( SomePlayer ) end function GM:CheckRoundEndInternal() if ( !GAMEMODE:InRound() ) then return end GAMEMODE:CheckRoundEnd() timer.Create( "CheckRoundEnd", 1, 0, function() GAMEMODE:CheckRoundEndInternal() end ) end // // This is called when the round time ends. // function GM:RoundTimerEnd() if ( !GAMEMODE:InRound() ) then return end for k,v in pairs(self:GetFuelPods()) do overtime = false; if ValidEntity(v.dt.OwnerPlane) then overtime = true end if overtime then timer.Create( "RoundEndTimer", 3, 0, function() GAMEMODE:RoundTimerEnd() end ) for k,v in pairs(player.GetAll()) do v:PrintCenter("OVERTIME!", 1, 2) end self:SetOverTime(true) return end 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 if GAMEMODE:GetRocket(TEAM_RED).dt.Fuel > GAMEMODE:GetRocket(TEAM_BLUE).dt.Fuel then self:RoundEndWithResult(TEAM_RED, "Team red fueled their rocket!") GAMEMODE:GetRocket(TEAM_RED):Launch() local cam_pos = Vector(0,0,0) for k,v in pairs(ents.FindByClass("df_fuel_node")) do if v.Team == TEAM_RED then cam_pos = v:GetPos() end end umsg.Start("df_startrocketcam") umsg.Short(TEAM_RED) umsg.Vector(cam_pos) umsg.End() elseif GAMEMODE:GetRocket(TEAM_RED).dt.Fuel < GAMEMODE:GetRocket(TEAM_BLUE).dt.Fuel then self:RoundEndWithResult(TEAM_BLUE, "Team blue fueled their rocket!") GAMEMODE:GetRocket(TEAM_BLUE):Launch() local cam_pos = Vector(0,0,0) for k,v in pairs(ents.FindByClass("df_fuel_node")) do if v.Team == TEAM_BLUE then cam_pos = v:GetPos() end end umsg.Start("df_startrocketcam") umsg.Short(TEAM_BLUE) umsg.Vector(cam_pos) umsg.End() else GAMEMODE:RoundEndWithResult( -1, "Stalemate. A draw this time!" ) end end end // // 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