409 lines
10 KiB
Lua
409 lines
10 KiB
Lua
|
|
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
|
|
|
|
--//moved to prop hunt's init.lua
|
|
-- fretta_waitforplayers = CreateConVar( "fretta_waitforplayers", "1", { FCVAR_ARCHIVE } )
|
|
|
|
function GM:OnRoundStart( num )
|
|
|
|
UTIL_UnFreezeAllPlayers()
|
|
|
|
hook.Call("PH_OnRoundStart", nil, num)
|
|
|
|
end
|
|
|
|
--local bAlreadyStarted = false
|
|
--[[moved to prop hunt's init.lua
|
|
function GM:OnRoundEnd( num )
|
|
|
|
// Check if fretta_waitforplayers is true
|
|
// This is a fast implementation for a waiting system
|
|
// Make optimisations if needed
|
|
if ( fretta_waitforplayers:GetBool() ) then
|
|
|
|
// Take away a round number quickly before it adds another when there are not enough players
|
|
// Set to false
|
|
if ( ( team.NumPlayers( TEAM_HUNTERS ) < 1 ) || ( team.NumPlayers( TEAM_PROPS ) < 1 ) ) then
|
|
|
|
bAlreadyStarted = false
|
|
|
|
end
|
|
|
|
// Check if the round was already started before so we count it as a fully played round
|
|
if ( !bAlreadyStarted ) then
|
|
|
|
SetGlobalInt( "RoundNumber", GetGlobalInt( "RoundNumber" )-1 )
|
|
|
|
end
|
|
|
|
// Set to true
|
|
if ( ( team.NumPlayers( TEAM_HUNTERS ) >= 1 ) && ( team.NumPlayers( TEAM_PROPS ) >= 1 ) ) then
|
|
|
|
bAlreadyStarted = true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
]]--
|
|
function GM:OnRoundEnd(num)
|
|
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 )
|
|
|
|
game.CleanUpMap()
|
|
|
|
UTIL_StripAllPlayers()
|
|
UTIL_SpawnAllPlayers()
|
|
UTIL_FreezeAllPlayers()
|
|
|
|
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
|
|
--MapVote.Start()
|
|
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.Create( "RoundStartTimer", GAMEMODE.RoundPreStartTime, 1, 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
|
|
//
|
|
--[[ moved to prop hunt's init.lua
|
|
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 );
|
|
|
|
// Check if fretta_waitforplayers is true
|
|
// This is a fast implementation for a waiting system
|
|
// Make optimisations if needed
|
|
if ( fretta_waitforplayers:GetBool() ) then
|
|
|
|
// Pause these timers if there are not enough players on the teams in the server
|
|
if ( ( team.NumPlayers( TEAM_HUNTERS ) < 1 ) || ( team.NumPlayers( TEAM_PROPS ) < 1 ) ) then
|
|
|
|
if ( timer.Exists( "RoundEndTimer" ) && timer.Exists( "CheckRoundEnd" ) ) then
|
|
|
|
timer.Pause( "RoundEndTimer" )
|
|
timer.Pause( "CheckRoundEnd" )
|
|
|
|
SetGlobalFloat( "RoundEndTime", -1 );
|
|
|
|
PrintMessage( HUD_PRINTTALK, "There's not enough players to start the game." )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
// Send this as a global boolean
|
|
SetGlobalBool( "RoundWaitForPlayers", fretta_waitforplayers:GetBool() )
|
|
|
|
end
|
|
]]--
|
|
-- default fretta on round start.
|
|
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 IsValid( 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 )
|
|
|
|
hook.Call("PH_RoundEnd", nil)
|
|
|
|
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( "PlayerDisconnected", "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
|
|
|
|
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
|
|
|
|
//
|
|
// 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
|