fortressforever-scripts/maps/includes/base_idzone.lua

898 lines
30 KiB
Lua

-- base_idzone.lua
-- Invade / Defend the Zone gametype
-----------------------------------------------------------------------------
-- includes
-----------------------------------------------------------------------------
IncludeScript("base_teamplay")
-----------------------------------------------------------------------------
-- global overrides that you can do what you want with
-----------------------------------------------------------------------------
FORT_POINTS_PER_INITIAL_TOUCH = 200
FORT_POINTS_PER_PERIOD = 50
FORT_POINTS_PER_DEFEND = 100
POINTS_PER_INITIAL_TOUCH = 1
POINTS_PER_PERIOD = 1
DELAY_BEFORE_PERIOD_POINTS = 2
PERIOD_TIME = 1
INITIAL_ROUND_PERIOD = 60
ROUND_SETUP_PERIOD = 17
DEFENSE_PERIOD_TIME = 60
POINTS_PER_DEFENSE_PERIOD = 1
DEFAULT_POINTS_TO_CAP = 10
NUMBER_OF_CAP_POINTS = 3
DELAY_BEFORE_TEAMSWITCH = 2
DELAY_AFTER_CAP = 3
ZONE_COLOR = "blue"
-----------------------------------------------------------------------------
-- global variables and other shit that shouldn't be messed with
-----------------------------------------------------------------------------
phase = 1
zone_points = 0
zone_max_points = DEFAULT_POINTS_TO_CAP
zone_scoring = false
draw_hud = true
attackers = Team.kBlue
defenders = Team.kRed
scoring_team = Team.kRed
local teamdata = {
[Team.kBlue] = { skin = "0", beamcolour = "0 0 255" },
[Team.kRed] = { skin = "1", beamcolour = "255 0 0" }
}
-- stores ID's of attackers in the cap room
local zone_collection = Collection()
-- stores if the player has touched the cap point (for 1 touch per death)
local playerTouchedTable = {}
-----------------------------------------------------------------------------
-- functions that do sh... stuff
-----------------------------------------------------------------------------
-- sounds, right?
function precache()
PrecacheSound("otherteam.flagstolen") -- doors open sound
PrecacheSound("otherteam.drop") -- warning sound
PrecacheSound("yourteam.flagreturn") -- scoring sound
PrecacheSound("misc.bloop") -- minutes remaining
PrecacheSound("misc.doop") -- attackers capping sound
end
-- pretty standard setup, aside from scoring starting
function startup()
SetGameDescription( "Invade Defend the Zone" )
-- set up team limits on each team
SetPlayerLimit( Team.kBlue, 0 )
SetPlayerLimit( Team.kRed, 0 )
SetPlayerLimit( Team.kYellow, -1 )
SetPlayerLimit( Team.kGreen, -1 )
SetTeamName( attackers, "Attackers" )
SetTeamName( defenders, "Defenders" )
-- Making the game not suck.
local team = GetTeam(attackers)
team:SetClassLimit(Player.kCivilian, -1)
team:SetClassLimit(Player.kSniper, 1)
team:SetClassLimit(Player.kEngineer, 2)
team:SetClassLimit(Player.kDemoman, 2)
team:SetClassLimit(Player.kHwguy, 2)
team:SetClassLimit(Player.kPyro, 2)
team = GetTeam(defenders)
team:SetClassLimit(Player.kCivilian, -1)
team:SetClassLimit(Player.kScout, -1)
team:SetClassLimit(Player.kMedic, -1)
team:SetClassLimit(Player.kSniper, 1)
team:SetClassLimit(Player.kEngineer, 2)
team:SetClassLimit(Player.kDemoman, 2)
team:SetClassLimit(Player.kHwguy, 2)
team:SetClassLimit(Player.kPyro, 2)
AddSchedule( "round_start", INITIAL_ROUND_PERIOD, round_start)
if INITIAL_ROUND_PERIOD > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_PERIOD - 30 , schedulemessagetoall, "#ADZ_30SecWarning" ) end
if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_PERIOD - 10 , schedulemessagetoall, "#ADZ_10SecWarning" ) end
-- sounds
if INITIAL_ROUND_PERIOD > 30 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_PERIOD - 30 , schedulesound, "misc.bloop" ) end
if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_PERIOD - 10 , schedulesound, "misc.bloop" ) end
if INITIAL_ROUND_PERIOD > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_PERIOD - 5 , schedulecountdown, 5 ) end
if INITIAL_ROUND_PERIOD > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_PERIOD - 4 , schedulecountdown, 4 ) end
if INITIAL_ROUND_PERIOD > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_PERIOD - 3 , schedulecountdown, 3 ) end
if INITIAL_ROUND_PERIOD > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_PERIOD - 2 , schedulecountdown, 2 ) end
if INITIAL_ROUND_PERIOD > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_PERIOD - 1 , schedulecountdown, 1 ) end
zone_max_points = zone1.pointstocap
-- calculate defense period points
local total_points_to_reset = 1
for i=1,NUMBER_OF_CAP_POINTS do
local t_points = getfield("zone"..i..".pointstocap")
total_points_to_reset = total_points_to_reset + t_points
end
local timelimit = GetConvar( "mp_timelimit" )
-- convert mp_timelimit from minutes to seconds and divide by the number of rounds minus initial round period
POINTS_PER_DEFENSE_PERIOD = total_points_to_reset / (timelimit / (DEFENSE_PERIOD_TIME / 60))
POINTS_PER_DEFENSE_PERIOD = math.ceil(POINTS_PER_DEFENSE_PERIOD)
update_zone_all( )
AddScheduleRepeating( "period_scoring_sched", PERIOD_TIME, period_scoring )
AddScheduleRepeating( "defense_period_scoring_sched", DEFENSE_PERIOD_TIME, defenders_scoring )
end
-----------------------------------------------------------------------------
-- player_ functions
-----------------------------------------------------------------------------
-- on player spawn
function player_spawn( player_entity )
local player = CastToPlayer( player_entity )
player:AddHealth( 100 )
player:AddArmor( 300 )
player:AddAmmo( Ammo.kNails, 400 )
player:AddAmmo( Ammo.kShells, 400 )
player:AddAmmo( Ammo.kRockets, 400 )
player:AddAmmo( Ammo.kCells, 400 )
player:RemoveAmmo( Ammo.kManCannon, 1 )
player:SetCloakable( true )
player:SetDisguisable( true )
update_zone_player( player )
-- give demo 1 mirv, and only 1 mirv
if player:GetClass() == Player.kDemoman or player:GetClass() == Player.kEngineer then
player:RemoveAmmo( Ammo.kGren2, 4 )
player:AddAmmo( Ammo.kGren2, 1 )
end
if player:GetTeamId() == attackers then
local attackers_objective = GetEntityByName( "zone"..phase )
UpdateObjectiveIcon( player, attackers_objective )
else
UpdateObjectiveIcon( player, nil )
player:RemoveAmmo( Ammo.kDetpack, 1 )
end
-- wtf, scout or med on d? are you mental?
if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then
local classt = "Scout"
if player:GetClass() == Player.kMedic then classt = "Medic" end
local id = player:GetId()
AddSchedule("force_changemessage"..id, 2, schedulechangemessage, player, "No "..classt.."s on defense. Autoswitching to Soldier." )
AddSchedule("force_change"..id, 2, forcechange, player)
end
-- remove any players not on a team from playertouchedtable
for playerx, recordx in pairs(playerTouchedTable) do
if GetPlayerByID( playerx ) then
local playert = GetPlayerByID( playerx )
if ( playert:GetTeamId() ~= attackers ) then
playerTouchedTable[playerx] = nil
end
end
end
if player:GetTeamId() ~= attackers then return end
-- add to table and reset touched to 0
playerTouchedTable[player:GetId()] = {touched = false, allowed = true}
end
-- needed so that people who switch team are removed from the cap room collection properly.
function player_switchteam ( player, oldteam, newteam )
if oldteam == attackers then
base_zone_trigger:onendtouch( player )
end
return true
end
-- on player killed
function player_killed ( player, damageinfo )
-- if no damageinfo do nothing
if not damageinfo then return end
-- Entity that is attacking
local attacker = damageinfo:GetAttacker()
-- If no attacker do nothing
if not attacker then return end
local player_attacker = nil
-- get the attacking player
if IsPlayer(attacker) then
attacker = CastToPlayer(attacker)
player_attacker = attacker
elseif IsSentrygun(attacker) then
attacker = CastToSentrygun(attacker)
player_attacker = attacker:GetOwner()
elseif IsDetpack(attacker) then
attacker = CastToDetpack(attacker)
player_attacker = attacker:GetOwner()
elseif IsDispenser(attacker) then
attacker = CastToDispenser(attacker)
player_attacker = attacker:GetOwner()
else
return
end
-- if still no attacking player after all that, forget about it
if not player_attacker then return end
-- If player killed self or teammate do nothing
if (player:GetId() == player_attacker:GetId()) or (player:GetTeamId() == player_attacker:GetTeamId()) then
return
end
-- If player is an attacker, then do stuff
if player:GetTeamId() == attackers then
-- Check if he's in the cap point
for playerx in zone_collection.items do
playerx = CastToPlayer(playerx)
if playerx:GetId() == player:GetId() then
player_attacker:AddFortPoints( FORT_POINTS_PER_DEFEND, "Defending the Point" )
-- for safety, remove player from collection
zone_collection:RemoveItem( player )
-- also for safety, if no more players, reset the cap
if zone_collection:Count() == 0 then
update_zone_all( )
zone_turnoff( phase )
end
return
end
end
end
end
function player_ondamage ( player, damageinfo )
-- if no damageinfo do nothing
if not damageinfo then return end
-- Get Damage Force
local damage = damageinfo:GetDamage()
-- Entity that is attacking
local attacker = damageinfo:GetAttacker()
-- If no attacker do nothing
if not attacker then return end
local player_attacker = nil
-- get the attacking player
if IsPlayer(attacker) then
attacker = CastToPlayer(attacker)
player_attacker = attacker
elseif IsSentrygun(attacker) then
attacker = CastToSentrygun(attacker)
player_attacker = attacker:GetOwner()
elseif IsDetpack(attacker) then
attacker = CastToDetpack(attacker)
player_attacker = attacker:GetOwner()
elseif IsDispenser(attacker) then
attacker = CastToDispenser(attacker)
player_attacker = attacker:GetOwner()
else
return
end
-- if still no attacking player after all that, forget about it
if not player_attacker then return end
-- If player killed self or teammate do nothing
if (player:GetId() == player_attacker:GetId()) or (player:GetTeamId() == player_attacker:GetTeamId()) then
return
end
-- If player is an attacker, then do stuff
if player:GetTeamId() == attackers then
-- Check if he's in the cap point
for playerx in zone_collection.items do
playerx = CastToPlayer(playerx)
if playerx:GetId() == player:GetId() then
if (damage > 100) then damage = 100 end
player_attacker:AddFortPoints( damage, "Protecting the Point" )
return
end
end
end
end
-----------------------------------------------------------------------------
-- on cap
-----------------------------------------------------------------------------
function zone_cap( cap_phase )
zone_collection:RemoveAllItems()
zone_turnoff( phase )
zone_points = 0
-- reset touches
for playerx, recordx in pairs(playerTouchedTable) do
if GetPlayerByID( playerx ) then
local playert = GetPlayerByID( playerx )
if ( playert:GetTeamId() == attackers ) then
-- add to table and reset touched to 0
playerTouchedTable[playert:GetId()] = {touched = false, allowed = true}
end
end
end
draw_hud = false
if phase == NUMBER_OF_CAP_POINTS then
onreset_outputs()
-- it's the last round. end and stuff
phase = 1
-- run custom round reset stuff
AddSchedule( "onroundreset_sched", DELAY_BEFORE_TEAMSWITCH, onroundreset )
else
oncap_outputs()
phase = phase + 1
AddSchedule( "aftercap_sched", DELAY_AFTER_CAP, oncap_outputs_nextphase )
AddSchedule( "aftercap_sched2", DELAY_AFTER_CAP, oncap_nextphase )
end
update_zone_all( )
end
-----------------------------------------------------------------------------
-- round functions
-----------------------------------------------------------------------------
-- Opens the gates and schedules the round's end.
function round_start()
-- Opens the gates and all that lovely stuff
OpenDoor("frontgate")
BroadCastMessage( "#FF_AD_GATESOPEN" )
BroadCastSound( "otherteam.flagstolen" )
SpeakAll( "AD_GATESOPEN" )
openstartdoor()
end
-- Checks to see if it's the first or second round, then either swaps teams, or ends the game.
function onroundreset()
if attackers == Team.kBlue then
attackers = Team.kRed
defenders = Team.kBlue
onswitch_bluetodef()
else
attackers = Team.kBlue
defenders = Team.kRed
onswitch_redtodef()
end
-- objective icon
UpdateTeamObjectiveIcon( GetTeam(attackers), nil )
UpdateTeamObjectiveIcon( GetTeam(defenders), nil )
-- switch them team names
SetTeamName( attackers, "Attackers" )
SetTeamName( defenders, "Defenders" )
-- reset them limits
team = GetTeam(defenders)
team:SetClassLimit(Player.kCivilian, -1)
team:SetClassLimit(Player.kScout, -1)
team:SetClassLimit(Player.kMedic, -1)
team = GetTeam(attackers)
team:SetClassLimit(Player.kCivilian, -1)
team:SetClassLimit(Player.kScout, 0)
team:SetClassLimit(Player.kMedic, 0)
-- reset schedules
AddSchedule( "round_start", INITIAL_ROUND_PERIOD, round_start)
-- reset player touched table
playerTouchedTable = {}
-- remove all leftovers from the cap point collection
zone_collection:RemoveAllItems()
-- respawn the players
RespawnAllPlayers()
-- MORE scheduled message loveliness.
if INITIAL_ROUND_PERIOD > 30 then AddSchedule( "dooropen30sec" , INITIAL_ROUND_PERIOD - 30 , schedulemessagetoall, "#ADZ_30SecWarning" ) end
if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10sec" , INITIAL_ROUND_PERIOD - 10 , schedulemessagetoall, "#ADZ_10SecWarning" ) end
-- sounds
if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen30secsound" , INITIAL_ROUND_PERIOD - 30 , schedulesound, "misc.bloop" ) end
if INITIAL_ROUND_PERIOD > 10 then AddSchedule( "dooropen10secsound" , INITIAL_ROUND_PERIOD - 10 , schedulesound, "misc.bloop" ) end
if INITIAL_ROUND_PERIOD > 5 then AddSchedule( "dooropen5seccount" , INITIAL_ROUND_PERIOD - 5 , schedulecountdown, 5 ) end
if INITIAL_ROUND_PERIOD > 4 then AddSchedule( "dooropen4seccount" , INITIAL_ROUND_PERIOD - 4 , schedulecountdown, 4 ) end
if INITIAL_ROUND_PERIOD > 3 then AddSchedule( "dooropen3seccount" , INITIAL_ROUND_PERIOD - 3 , schedulecountdown, 3 ) end
if INITIAL_ROUND_PERIOD > 2 then AddSchedule( "dooropen2seccount" , INITIAL_ROUND_PERIOD - 2 , schedulecountdown, 2 ) end
if INITIAL_ROUND_PERIOD > 1 then AddSchedule( "dooropen1seccount" , INITIAL_ROUND_PERIOD - 1 , schedulecountdown, 1 ) end
DeleteSchedule( "defense_period_scoring_sched" )
AddScheduleRepeating( "defense_period_scoring_sched", DEFENSE_PERIOD_TIME, defenders_scoring )
draw_hud = true
update_zone_all( )
onswitch()
end
-----------------------------------------------------------------------------
-- zone functions
-----------------------------------------------------------------------------
function zone_turnon( cp_num )
zone_on_outputs()
-- init scoring
AddSchedule( "period_init", DELAY_BEFORE_PERIOD_POINTS, init_scoring, team )
AddSchedule( "period_init_alarm", DELAY_BEFORE_PERIOD_POINTS - 1, init_scoring_alarm )
end
function zone_turnoff( cp_num )
zone_off_outputs()
-- stop scoring
zone_scoring = false
end
function oncap_nextphase()
draw_hud = true
update_zone_all( )
-- update objective icon
local attackers_objective = GetEntityByName( "zone"..phase )
UpdateTeamObjectiveIcon( GetTeam(attackers), attackers_objective )
UpdateTeamObjectiveIcon( GetTeam(defenders), nil )
end
-----------------------------------------------------------------------------
-- output functions
-----------------------------------------------------------------------------
function zone_on_outputs()
return
end
function zone_off_outputs()
return
end
function onswitch_bluetodef()
return
end
function onswitch_redtodef()
return
end
function onswitch()
return
end
function openstartdoor()
return
end
function oncap_outputs()
return
end
function oncap_outputs_nextphase()
return
end
function onreset_outputs()
return
end
-----------------------------------------------------------------------------
-- hud
-----------------------------------------------------------------------------
function update_zone_all( )
RemoveHudItemFromAll( "Zone_Status" )
RemoveHudItemFromAll( "Zone_Status_BG" )
RemoveHudItemFromAll( "Zone_Status_Points" )
RemoveHudItemFromAll( "Zone_Team"..attackers )
RemoveHudItemFromAll( "Zone_Team"..defenders )
RemoveHudItemFromAll( "Zone_Team_Text"..attackers )
RemoveHudItemFromAll( "Zone_Team_Text"..defenders )
if draw_hud then
AddHudIconToAll( "hud_statusbar_256.vtf", "Zone_Status_BG", -64, 36, 128, 16, 3 )
AddHudTextToTeam( GetTeam(attackers), "Zone_Team_Text"..attackers, "Attacking Zone "..phase, 33, 56, 4, 0 )
AddHudTextToTeam( GetTeam(defenders), "Zone_Team_Text"..defenders, "Defending Zone "..phase, 33, 56, 4, 0 )
AddHudTextToAll( "Zone_Status_Points", zone_points.." / "..zone_max_points, 40, 56, 2, 0 )
AddHudIconToTeam( GetTeam(attackers), "hud_offense.vtf", "Zone_Team"..attackers, -92, 38, 24, 24, 3 )
AddHudIconToTeam( GetTeam(defenders), "hud_defense.vtf", "Zone_Team"..defenders, -92, 38, 24, 24, 3 )
local max_width = 124
if zone_points > 0 then
bar_width = zone_points / zone_max_points * max_width
if zone_collection:Count() > 0 then
AddHudIconToAll( "hud_statusbar_"..ZONE_COLOR.."_active.vtf", "Zone_Status", -62, 36, bar_width, 16, 3 )
else
AddHudIconToAll( "hud_statusbar_"..ZONE_COLOR..".vtf", "Zone_Status", -62, 36, bar_width, 16, 3 )
end
end
end
end
function update_zone_player( player )
RemoveHudItem( player, "Zone_Status" )
RemoveHudItem( player, "Zone_Status_BG" )
RemoveHudItem( player, "Zone_Status_Points" )
RemoveHudItem( player, "Zone_Team"..attackers )
RemoveHudItem( player, "Zone_Team"..defenders )
RemoveHudItem( player, "Zone_Team_Text"..attackers )
RemoveHudItem( player, "Zone_Team_Text"..defenders )
if draw_hud then
AddHudIcon( player, "hud_statusbar_256.vtf", "Zone_Status_BG", -64, 36, 128, 16, 3 )
AddHudText( player, "Zone_Status_Points", zone_points.." / "..zone_max_points, 40, 56, 2, 0 )
if player:GetTeamId() == attackers then
AddHudIcon( player, "hud_offense.vtf", "Zone_Team"..attackers, -92, 38, 24, 24, 3 )
AddHudText( player, "Zone_Team_Text"..attackers, "Attacking Zone "..phase, 33, 56, 4, 0 )
else
AddHudIcon( player, "hud_defense.vtf", "Zone_Team"..defenders, -92, 38, 24, 24, 3 )
AddHudText( player, "Zone_Team_Text"..defenders, "Defending Zone "..phase, 33, 56, 4, 0 )
end
local max_width = 124
if zone_points > 0 then
bar_width = zone_points / zone_max_points * max_width
if zone_collection:Count() > 0 then
AddHudIcon( player, "hud_statusbar_"..ZONE_COLOR.."_active.vtf", "Zone_Status", -62, 36, bar_width, 16, 3 )
else
AddHudIcon( player, "hud_statusbar_"..ZONE_COLOR..".vtf", "Zone_Status", -62, 36, bar_width, 16, 3 )
end
end
end
end
-----------------------------------------------------------------------------
-- base_zone_trigger
-----------------------------------------------------------------------------
-- capture room
base_zone_trigger = trigger_ff_script:new({ phase = 0, pointstocap = DEFAULT_POINTS_TO_CAP })
zone1 = base_zone_trigger:new({phase=1})
zone2 = base_zone_trigger:new({phase=2})
zone3 = base_zone_trigger:new({phase=3})
zone4 = base_zone_trigger:new({phase=4})
zone5 = base_zone_trigger:new({phase=5})
zone6 = base_zone_trigger:new({phase=6})
zone7 = base_zone_trigger:new({phase=7})
zone8 = base_zone_trigger:new({phase=8})
-- registers attackers as they enter the cap room
function base_zone_trigger:ontouch( trigger_entity )
if IsPlayer( trigger_entity ) then
local player = CastToPlayer( trigger_entity )
if phase ~= self.phase then return end
if player:GetTeamId() == defenders then return end
player:SetCloakable( false )
player:SetDisguisable( false )
update_zone_all( )
local playerid = player:GetId()
zone_collection:AddItem( player )
local team = GetTeam(attackers)
-- if it's the first touch, give points and stuff
if playerTouchedTable[playerid].touched == false then
team:AddScore( POINTS_PER_INITIAL_TOUCH )
player:AddFortPoints( FORT_POINTS_PER_INITIAL_TOUCH, "Initial Point Touch" )
zone_points = zone_points + POINTS_PER_INITIAL_TOUCH
update_zone_all( )
if zone_points >= self.pointstocap then
zone_cap( self.phase )
return
end
SmartTeamSound( GetTeam(defenders), "yourteam.flagreturn", "misc.doop" )
playerTouchedTable[playerid].touched = true
elseif zone_collection:Count() == 1 then
SmartTeamSound( GetTeam(defenders), "otherteam.drop", nil )
end
if zone_collection:Count() == 1 then
-- activate the cap point, bro
update_zone_all( )
zone_turnon( self.phase )
end
end
end
-- deregisters attackers as they enter the cap room. Checks to see if all attackers have left.
function base_zone_trigger:onendtouch( trigger_entity )
if IsPlayer( trigger_entity ) then
local player = CastToPlayer( trigger_entity )
if player:GetTeamId() == defenders then return end
player:SetCloakable( true )
player:SetDisguisable( true )
zone_collection:RemoveItem( player )
local team = GetTeam(defenders)
if zone_collection:Count() == 0 then
update_zone_all( )
zone_turnoff( self.phase )
end
end
end
-- empties the collection if no-one in in the room. Shouldn't really be nessecary.
function base_zone_trigger:oninactive()
-- Clear out the flags in the collection
DeleteSchedule( "period_scoring" )
DeleteSchedule( "period_init" )
DeleteSchedule( "period_init_alarm" )
zone_collection:RemoveAllItems()
update_zone_status( false )
zone_turnoff( self.phase )
end
-----------------------------------------------------------------------------
-- scoring
-----------------------------------------------------------------------------
-- Adds points based on time inside cap room and number of attackers inside cap room
function period_scoring( )
if zone_scoring then
local team = GetTeam( attackers )
team:AddScore( POINTS_PER_PERIOD )
zone_points = zone_points + POINTS_PER_PERIOD
update_zone_all( )
SmartTeamSound( GetTeam(defenders), "yourteam.flagreturn", "misc.doop" )
for player in zone_collection.items do
player = CastToPlayer(player)
if player ~= nil then
player:AddFortPoints( FORT_POINTS_PER_PERIOD, "Touching the Point" )
else
ConsoleToAll("LUA ERROR: player_addfortpoints: Unable to find player")
end
end
end
-- cap zone if the points say to
if zone_points >= zone_max_points then
zone_cap( phase )
end
end
-- Initializes the period_scoring (allows for a delay after initial touch)
function init_scoring( team )
if zone_collection:Count() > 0 then
zone_scoring = true
end
end
-- Initializes the period_scoring (allows for a delay after initial touch)
function init_scoring_alarm( )
if zone_collection:Count() > 0 then
SmartTeamSound( GetTeam(defenders), "otherteam.drop", nil )
end
end
-- Adds points based on time inside cap room and number of attackers inside cap room
function defenders_scoring( )
local team = GetTeam( defenders )
team:AddScore( POINTS_PER_DEFENSE_PERIOD )
end
-----------------------------------------------------------------------------
-- misc functions
-----------------------------------------------------------------------------
-- Sends a message to all after the determined time
function schedulechangemessage( player, message )
if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then
BroadCastMessageToPlayer( player, message )
end
end
-- reset everything
function RespawnAllPlayers()
ApplyToAll({ AT.kRemovePacks, AT.kRemoveProjectiles, AT.kRespawnPlayers, AT.kRemoveBuildables, AT.kRemoveRagdolls, AT.kStopPrimedGrens, AT.kReloadClips, AT.kAllowRespawn, AT.kReturnDroppedItems })
end
-- force a scout/med to switch to soli if they haven't
function forcechange( player )
if (player:GetClass() == Player.kScout or player:GetClass() == Player.kMedic) and (player:GetTeamId() == defenders) then
ApplyToPlayer( player, { AT.kChangeClassSoldier, AT.kRespawnPlayers } )
end
end
-- Sends a message to all after the determined time
function schedulemessagetoall( message )
BroadCastMessage( message )
end
-- Plays a sound to all after the determined time
function schedulesound( sound )
BroadCastSound( sound )
end
function schedulecountdown( time )
BroadCastMessage( ""..time.."" )
SpeakAll( "AD_" .. time .. "SEC" )
end
-----------------------------------------------------------------------------
-- Entity definitions (flags/command points/backpacks etc.)
-----------------------------------------------------------------------------
-- respawns
base_attacker_spawn = info_ff_teamspawn:new({ phase = 0, validspawn = function(self,player)
return player:GetTeamId() == attackers and phase == self.phase
end })
base_defender_spawn = info_ff_teamspawn:new({ phase = 0, validspawn = function(self,player)
return player:GetTeamId() == defenders and phase == self.phase
end })
zone1_attacker = base_attacker_spawn:new({phase=1})
zone2_attacker = base_attacker_spawn:new({phase=2})
zone3_attacker = base_attacker_spawn:new({phase=3})
zone4_attacker = base_attacker_spawn:new({phase=4})
zone5_attacker = base_attacker_spawn:new({phase=5})
zone6_attacker = base_attacker_spawn:new({phase=6})
zone7_attacker = base_attacker_spawn:new({phase=7})
zone8_attacker = base_attacker_spawn:new({phase=8})
zone1_defender = base_defender_spawn:new({phase=1})
zone2_defender = base_defender_spawn:new({phase=2})
zone3_defender = base_defender_spawn:new({phase=3})
zone4_defender = base_defender_spawn:new({phase=4})
zone5_defender = base_defender_spawn:new({phase=5})
zone6_defender = base_defender_spawn:new({phase=6})
zone7_defender = base_defender_spawn:new({phase=7})
zone8_defender = base_defender_spawn:new({phase=8})
-- generic respawns
attacker_spawn = info_ff_teamspawn:new({ validspawn = function(self,player)
return player:GetTeamId() == attackers
end })
defender_spawn = info_ff_teamspawn:new({ validspawn = function(self,player)
return player:GetTeamId() == defenders
end })
-----------------------------------------------------------------------------
-- Generic Backpack
-----------------------------------------------------------------------------
genericbackpack = info_ff_script:new({
health = 0,
armor = 0,
grenades = 0,
shells = 0,
nails = 0,
rockets = 0,
cells = 0,
detpacks = 0,
mancannons = 0,
gren1 = 0,
gren2 = 0,
respawntime = 5,
model = "models/items/healthkit.mdl",
materializesound = "Item.Materialize",
touchsound = "HealthKit.Touch",
notallowedmsg = "#FF_NOTALLOWEDPACK",
touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed, AllowFlags.kYellow, AllowFlags.kGreen}
})
function genericbackpack:dropatspawn() return false end
function genericbackpack:precache( )
-- precache sounds
PrecacheSound(self.materializesound)
PrecacheSound(self.touchsound)
-- precache models
PrecacheModel(self.model)
end
function genericbackpack:touch( touch_entity )
if IsPlayer( touch_entity ) then
local player = CastToPlayer( touch_entity )
local dispensed = 0
-- give player some health and armor
if self.health ~= nil and self.health ~= 0 then dispensed = dispensed + player:AddHealth( self.health ) end
if self.armor ~= nil and self.armor ~= 0 then dispensed = dispensed + player:AddArmor( self.armor ) end
-- give player ammo
if self.nails ~= nil and self.nails ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kNails, self.nails) end
if self.shells ~= nil and self.shells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kShells, self.shells) end
if self.rockets ~= nil and self.rockets ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kRockets, self.rockets) end
if self.cells ~= nil and self.cells ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kCells, self.cells) end
if self.detpacks ~= nil and self.detpacks ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kDetpack, self.detpacks) end
if self.mancannons ~= nil and self.mancannons ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kManCannon, self.mancannons) end
if self.gren1 ~= nil and self.gren1 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren1, self.gren1) end
if self.gren2 ~= nil and self.gren2 ~= 0 then dispensed = dispensed + player:AddAmmo(Ammo.kGren2, self.gren2) end
-- if the player took ammo, then have the backpack respawn with a delay
if dispensed >= 1 then
local backpack = CastToInfoScript(entity);
if backpack then
backpack:EmitSound(self.touchsound);
backpack:Respawn(self.respawntime);
end
end
end
end
function genericbackpack:materialize( )
entity:EmitSound(self.materializesound)
end
-- from http://www.lua.org/pil/14.1.html
function getfield (f)
local v = _G -- start with the table of globals
for w in string.gfind(f, "[%w_]+") do
v = v[w]
end
return v
end
function setfield (f, v)
local t = _G -- start with the table of globals
for w, d in string.gfind(f, "([%w_]+)(.?)") do
if d == "." then -- not last field?
t[w] = t[w] or {} -- create table if absent
t = t[w] -- get the table
else -- last field
t[w] = v -- do the assignment
end
end
end