mirror of
https://github.com/fortressforever/fortressforever-scripts.git
synced 2024-11-28 15:21:54 +00:00
1620 lines
54 KiB
Lua
1620 lines
54 KiB
Lua
-- base_cp.lua
|
|
|
|
-- if you want base cp with the default setup,
|
|
-- include base_cp_default.lua in your map's lua file
|
|
-- and then include base_cp.lua
|
|
|
|
function startup()
|
|
|
|
SetGameDescription( "Control Points" )
|
|
|
|
-- disable certain teams
|
|
for i,v in pairs(disabled_teams) do
|
|
SetPlayerLimit( v, -1 )
|
|
end
|
|
|
|
-- set up team limits
|
|
for i1,v1 in pairs(teams) do
|
|
local team = GetTeam(v1)
|
|
for i2,v2 in ipairs(team_info[team:GetTeamId()].class_limits) do
|
|
team:SetClassLimit( i2, v2 )
|
|
end
|
|
end
|
|
|
|
RemoveAllCPAmmoAndArmor()
|
|
|
|
for i,v in ipairs(command_points) do
|
|
RemoveSchedule( "cp" .. v.cp_number .. "_cap_timer" )
|
|
ResetCPCapping( v )
|
|
AddScheduleRepeating( "cp" .. v.cp_number .. "_cap_zone_timer", CAP_ZONE_TIMER_INTERVAL, cap_zone_timer, v )
|
|
end
|
|
end
|
|
|
|
function precache()
|
|
|
|
-- precache the cap sounds
|
|
for i in pairs(good_cap_sounds) do
|
|
PrecacheSound(good_cap_sounds[i])
|
|
PrecacheSound(bad_cap_sounds[i])
|
|
end
|
|
|
|
PrecacheSound("misc.thunder")
|
|
|
|
PrecacheSound("Buttons.snd9")
|
|
PrecacheSound("Buttons.snd45")
|
|
|
|
PrecacheSound("ff_cz2.teleport_exit")
|
|
|
|
PrecacheSound("k_lab.teleport_post_winddown")
|
|
PrecacheSound("novaprospekt.teleport_post_thunder")
|
|
PrecacheSound("NPC_Ichthyosaur.AttackGrowl")
|
|
PrecacheSound("Streetwar.d3_c17_11_die")
|
|
PrecacheSound("streetwar.Ba_UseConsoleSounds")
|
|
|
|
PrecacheSound( "yourteam.flagcap" )
|
|
PrecacheSound( "otherteam.flagcap" )
|
|
end
|
|
|
|
function PlayerStartTouchingCapZone( touch_entity, cp )
|
|
|
|
local player = CastToPlayer(touch_entity)
|
|
|
|
if PLAYER_TOUCHING_CP_ZONE[player:GetId()] == cp then return end
|
|
|
|
local team_number = player:GetTeamId()
|
|
|
|
PLAYER_TOUCHING_CP_ZONE[player:GetId()] = cp
|
|
|
|
cp.touching_players[team_number]:AddItem( player )
|
|
cp.former_touching_players[team_number]:RemoveItem( player )
|
|
cp.cap_speed[team_number] = cp.cap_speed[team_number] + ( player:MaxSpeed() / 10 )
|
|
|
|
if team_number ~= cp.defending_team then
|
|
player:SetCloakable( false )
|
|
end
|
|
|
|
local cp_zone_hudicon = cp_zone_icons[team_number]
|
|
AddHudIcon( player, cp_zone_hudicon.hudicon, cp_zone_hudicon.hudicon, cp_zone_hudicon.hudx, cp_zone_hudicon.hudy, cp_zone_hudicon.hudwidth, cp_zone_hudicon.hudheight, cp_zone_hudicon.hudalign )
|
|
|
|
end
|
|
|
|
function PlayerStopTouchingCapZone( touch_entity, cp )
|
|
|
|
local player = CastToPlayer(touch_entity)
|
|
|
|
if PLAYER_TOUCHING_CP_ZONE[player:GetId()] == nil then return end
|
|
|
|
local team_number = player:GetTeamId()
|
|
|
|
PLAYER_TOUCHING_CP_ZONE[player:GetId()] = nil
|
|
|
|
cp.touching_players[team_number]:RemoveItem( player )
|
|
cp.former_touching_players[team_number]:AddItem( player )
|
|
cp.cap_speed[team_number] = cp.cap_speed[team_number] - ( player:MaxSpeed() / 10 )
|
|
|
|
-- clamp
|
|
if cp.cap_speed[team_number] < 0 then
|
|
cp.cap_speed[team_number] = 0
|
|
end
|
|
|
|
player:SetCloakable( true )
|
|
|
|
RemoveHudItem( player, cp_zone_icons[team_number].hudicon )
|
|
|
|
end
|
|
|
|
|
|
function DrawCCAlarmIcon( cc_team_number )
|
|
|
|
-- check whether command centers are enabled
|
|
if not ENABLE_CC then return end
|
|
|
|
-- turn on alarm
|
|
if team_info[cc_team_number].cc_touch_count > 0 then
|
|
|
|
RemoveHudItemFromAll( cc_team_number .. "-ccalarmicon_neutral" )
|
|
AddHudIconToAll( team_info[cc_team_number].ccalarmicon, cc_team_number .. "-ccalarmicon", team_info[cc_team_number].ccalarmiconx, team_info[cc_team_number].ccalarmicony, team_info[cc_team_number].ccalarmiconwidth, team_info[cc_team_number].ccalarmiconheight, team_info[cc_team_number].ccalarmiconalign )
|
|
|
|
-- turn off alarm
|
|
else
|
|
|
|
RemoveHudItemFromAll( cc_team_number .. "-ccalarmicon" )
|
|
AddHudIconToAll( team_info[Team.kUnassigned].ccalarmicon, cc_team_number .. "-ccalarmicon_neutral", team_info[cc_team_number].ccalarmiconx, team_info[cc_team_number].ccalarmicony, team_info[cc_team_number].ccalarmiconwidth, team_info[cc_team_number].ccalarmiconheight, team_info[cc_team_number].ccalarmiconalign )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
function EntityStartTouchingCC( touch_entity, cc_team_number )
|
|
|
|
if ENTITY_TOUCHING_CC[touch_entity:GetId()] ~= nil then return end
|
|
|
|
ENTITY_TOUCHING_CC[touch_entity:GetId()] = cc_team_number
|
|
|
|
team_info[cc_team_number].cc_touch_count = team_info[cc_team_number].cc_touch_count + 1
|
|
|
|
-- turn on alarm
|
|
if team_info[cc_team_number].cc_touch_count > 0 then
|
|
|
|
OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_sound", "PlaySound" )
|
|
OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_light", "TurnOn" )
|
|
OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_beam", "Color", team_info[touch_entity:GetTeamId()].skybeam_color )
|
|
|
|
end
|
|
|
|
DrawCCAlarmIcon( cc_team_number )
|
|
|
|
end
|
|
|
|
function EntityStopTouchingCC( touch_entity, cc_team_number )
|
|
|
|
if ENTITY_TOUCHING_CC[touch_entity:GetId()] == nil then return end
|
|
|
|
ENTITY_TOUCHING_CC[touch_entity:GetId()] = nil
|
|
|
|
team_info[cc_team_number].cc_touch_count = team_info[cc_team_number].cc_touch_count - 1
|
|
|
|
-- turn off alarm
|
|
if team_info[cc_team_number].cc_touch_count <= 0 then
|
|
|
|
team_info[cc_team_number].cc_touch_count = 0
|
|
|
|
OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_sound", "StopSound" )
|
|
OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_light", "TurnOff" )
|
|
OutputEvent( team_info[cc_team_number].team_name .. "_cc_alarm_beam", "Color", team_info[Team.kUnassigned].skybeam_color )
|
|
|
|
end
|
|
|
|
DrawCCAlarmIcon( cc_team_number )
|
|
|
|
end
|
|
|
|
function player_disconnected( player )
|
|
|
|
if PLAYER_TOUCHING_CP_ZONE[player:GetId()] ~= nil then
|
|
PlayerStopTouchingCapZone( player, PLAYER_TOUCHING_CP_ZONE[player:GetId()] )
|
|
end
|
|
|
|
if ENTITY_TOUCHING_CC[player:GetId()] ~= nil then
|
|
EntityStopTouchingCC( player, ENTITY_TOUCHING_CC[player:GetId()] )
|
|
end
|
|
|
|
end
|
|
|
|
function player_switchteam( player, currentteam, desiredteam )
|
|
|
|
if PLAYER_TOUCHING_CP_ZONE[player:GetId()] ~= nil then
|
|
PlayerStopTouchingCapZone( player, PLAYER_TOUCHING_CP_ZONE[player:GetId()] )
|
|
end
|
|
|
|
if ENTITY_TOUCHING_CC[player:GetId()] ~= nil then
|
|
EntityStopTouchingCC( player, ENTITY_TOUCHING_CC[player:GetId()] )
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- timed scoring
|
|
-----------------------------------------------------------------------------
|
|
function cp_score_timer( cp_number, team_number )
|
|
|
|
local team = GetTeam(team_number)
|
|
team:AddScore(command_points[cp_number].point_value[team_number])
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- notify the players of the total cap.
|
|
-- Also, create a logic_relay in your map named fullcap_trigger to pass outputs to your entities.
|
|
-----------------------------------------------------------------------------
|
|
function complete_control_notification ( team_number )
|
|
|
|
local team = GetTeam(team_number)
|
|
SmartTeamSound(team, "yourteam.flagcap", "otherteam.flagcap")
|
|
SmartTeamSpeak(team, "CZ_GOTALL", "CZ_THEYGOTALL")
|
|
SmartTeamMessage(team, "#FF_CZ2_YOURTEAM_COMPLETE", "#FF_CZ2_OTHERTEAM_COMPLETE", Color.kGreen, Color.kRed)
|
|
OutputEvent( "fullcap_trigger", "Trigger" )
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- reset everything after the total cap.
|
|
-----------------------------------------------------------------------------
|
|
function complete_control_respawn ()
|
|
ApplyToAll( { AT.kRemovePacks, AT.kRemoveProjectiles, AT.kRespawnPlayers, AT.kRemoveBuildables, AT.kRemoveRagdolls, kReloadClips } )
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- emit a sound from an entity
|
|
-----------------------------------------------------------------------------
|
|
function EmitSound( entity, sound )
|
|
|
|
entity:EmitSound(sound)
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- remove all the ammo and armor from the entire map
|
|
-----------------------------------------------------------------------------
|
|
function RemoveAllCPAmmoAndArmor()
|
|
|
|
-- Remove all ammo and armor from CPs
|
|
local c = Collection()
|
|
c:GetByName(cp_ammo_and_armor_names, { CF.kNone })
|
|
for item in c.items do
|
|
item = CastToInfoScript(item)
|
|
item:Remove()
|
|
end
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- does the player have a flag?
|
|
-----------------------------------------------------------------------------
|
|
function PlayerHasFlag( player )
|
|
|
|
-- check if the player has a flag
|
|
for i,v in ipairs(flags) do
|
|
if player:HasItem(v) then
|
|
-- player has a flag
|
|
return true
|
|
end
|
|
end
|
|
|
|
-- player doesn't have a flag
|
|
return false
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- return carried flags
|
|
-----------------------------------------------------------------------------
|
|
function ReturnFlagFromPlayer( player )
|
|
|
|
-- Get all carried flags and ...
|
|
local c = Collection()
|
|
c:GetByName(flags, { CF.kInfoScript_Carried, })
|
|
|
|
-- ... return the flag that the player is carrying.
|
|
for item in c.items do
|
|
item = CastToInfoScript(item)
|
|
carrier = item:GetCarrier()
|
|
if player:GetId() == carrier:GetId() then
|
|
item:Return()
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- resupply a player when a cp is capped
|
|
-----------------------------------------------------------------------------
|
|
function CapResupply( player, scale, givethegoodshit )
|
|
|
|
-- give the player health and armor
|
|
if cap_resupply.health ~= nil and cap_resupply.health ~= 0 then player:AddHealth( cap_resupply.health * scale ) end
|
|
if cap_resupply.armor ~= nil and cap_resupply.armor ~= 0 then player:AddArmor( cap_resupply.armor * scale ) end
|
|
|
|
-- give the player ammo
|
|
if cap_resupply.nails ~= nil and cap_resupply.nails ~= 0 then player:AddAmmo( Ammo.kNails, cap_resupply.nails * scale ) end
|
|
if cap_resupply.shells ~= nil and cap_resupply.shells ~= 0 then player:AddAmmo( Ammo.kShells, cap_resupply.shells * scale ) end
|
|
if cap_resupply.rockets ~= nil and cap_resupply.rockets ~= 0 then player:AddAmmo( Ammo.kRockets, cap_resupply.rockets * scale ) end
|
|
if cap_resupply.cells ~= nil and cap_resupply.cells ~= 0 then player:AddAmmo( Ammo.kCells, cap_resupply.cells * scale ) end
|
|
|
|
if givethegoodshit then
|
|
-- give the player the good shit
|
|
if cap_resupply.detpacks ~= nil and cap_resupply.detpacks ~= 0 then player:AddAmmo( Ammo.kDetpack, cap_resupply.detpacks * scale ) end
|
|
if cap_resupply.mancannons ~= nil and cap_resupply.mancannons ~= 0 then player:AddAmmo( Ammo.kManCannon, cap_resupply.mancannons * scale ) end
|
|
if cap_resupply.gren1 ~= nil and cap_resupply.gren1 ~= 0 then player:AddAmmo( Ammo.kGren1, cap_resupply.gren1 * scale ) end
|
|
if cap_resupply.gren2 ~= nil and cap_resupply.gren2 ~= 0 then player:AddAmmo( Ammo.kGren2, cap_resupply.gren2 * scale ) end
|
|
end
|
|
|
|
end
|
|
|
|
function player_killed ( player_victim, 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()
|
|
end
|
|
|
|
-- if still no attacking player after all that, try the inflictor
|
|
if not player_attacker then
|
|
|
|
-- Entity that is attacking
|
|
local inflictor = damageinfo:GetInflictor()
|
|
|
|
if inflictor then
|
|
if IsSentrygun(inflictor) then
|
|
inflictor = CastToSentrygun(inflictor)
|
|
player_attacker = inflictor:GetOwner()
|
|
elseif IsDetpack(inflictor) then
|
|
inflictor = CastToDetpack(inflictor)
|
|
player_attacker = inflictor:GetOwner()
|
|
elseif IsDispenser(inflictor) then
|
|
inflictor = CastToDispenser(inflictor)
|
|
player_attacker = inflictor:GetOwner()
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
-- if still no attacking player after all that, forget about it
|
|
if not player_attacker then return end
|
|
|
|
-- if victim killed self or teammate do nothing
|
|
if (player_victim:GetId() == player_attacker:GetId()) or (player_victim:GetTeamId() == player_attacker:GetTeamId()) then return end
|
|
|
|
local player_victim_touching_cp = PLAYER_TOUCHING_CP_ZONE[player_victim:GetId()]
|
|
local player_attacker_touching_cp = PLAYER_TOUCHING_CP_ZONE[player_attacker:GetId()]
|
|
|
|
-- the victim is standing in a zone
|
|
if player_victim_touching_cp ~= nil then
|
|
|
|
-- the victim is defending a cp or trying to capture a neutral cp
|
|
if player_victim:GetTeamId() == player_victim_touching_cp.defending_team or player_victim_touching_cp.defending_team == Team.kUnassigned then
|
|
|
|
CapResupply( player_attacker, 0.25, false )
|
|
player_attacker:AddFortPoints((player_victim_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST")
|
|
|
|
-- the victim is trying to capture the attacker's cp
|
|
else
|
|
|
|
CapResupply( player_attacker, 0.25, false )
|
|
player_attacker:AddFortPoints((player_victim_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_DEFENDPOINT")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- the attacker is standing in a zone
|
|
if player_attacker_touching_cp ~= nil then
|
|
|
|
-- the attacker is defending a cp
|
|
if player_attacker:GetTeamId() == player_attacker_touching_cp.defending_team then
|
|
|
|
CapResupply( player_attacker, 0.25, false )
|
|
player_attacker:AddFortPoints((player_attacker_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_DEFENDPOINT")
|
|
|
|
-- the attacker is trying to capture a cp
|
|
else
|
|
|
|
CapResupply( player_attacker, 0.25, false )
|
|
player_attacker:AddFortPoints((player_attacker_touching_cp.point_value[player_attacker:GetTeamId()]) * 50, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- loop through all former players of each command point
|
|
for k,v in ipairs(command_points) do
|
|
|
|
-- victim's team
|
|
for i in v.former_touching_players[player_victim:GetTeamId()].items do
|
|
|
|
i = CastToPlayer( i )
|
|
|
|
-- the victim was in an active zone
|
|
if i:GetId() == player_victim:GetId() then
|
|
|
|
-- the victim is defending a cp or trying to capture a neutral cp
|
|
if player_victim:GetTeamId() == v.defending_team or v.defending_team == Team.kUnassigned then
|
|
|
|
CapResupply( player_attacker, 0.25, false )
|
|
player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST")
|
|
|
|
-- the victim is trying to capture the attacker's cp
|
|
else
|
|
|
|
CapResupply( player_attacker, 0.25, false )
|
|
player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_DEFENDPOINT_ASSIST")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-- attacker's team
|
|
for i in v.former_touching_players[player_attacker:GetTeamId()].items do
|
|
|
|
i = CastToPlayer( i )
|
|
|
|
-- the attacker was in an active zone
|
|
if i:GetId() == player_attacker:GetId() then
|
|
|
|
-- the attacker is defending a cp
|
|
if player_attacker:GetTeamId() == v.defending_team then
|
|
|
|
CapResupply( player_attacker, 0.25, false )
|
|
player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_DEFENDPOINT_ASSIST")
|
|
|
|
-- the attacker is trying to capture a cp
|
|
else
|
|
|
|
CapResupply( player_attacker, 0.25, false )
|
|
player_attacker:AddFortPoints((v.point_value[player_attacker:GetTeamId()]) * 25, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- change the cp's defending team, its related visuals, and its scoring
|
|
-----------------------------------------------------------------------------
|
|
function ChangeCPDefendingTeam( cp_number, new_defending_team )
|
|
|
|
local cp = command_points[cp_number]
|
|
|
|
-- Change the skybeam color
|
|
OutputEvent( "cp" .. cp_number .. "_skybeam", "Color", team_info[new_defending_team].skybeam_color )
|
|
|
|
-- Change the light color
|
|
for i in pairs(team_info) do
|
|
-- turn off all other lights as well
|
|
local input_name = "TurnOff"
|
|
local input2_name = "LightOff"
|
|
if i == new_defending_team then
|
|
input_name = "TurnOn"
|
|
input2_name = "LightOn"
|
|
end
|
|
OutputEvent( "cp" .. cp_number .. "_light_" .. team_info[i].team_name, input_name )
|
|
OutputEvent( "cp" .. cp_number .. "_spotlight_" .. team_info[i].team_name, input2_name )
|
|
end
|
|
|
|
-- Change the rotating flag around
|
|
OutputEvent( "cp" .. cp_number .. "_flag_rotator", "Reverse")
|
|
OutputEvent( "cp" .. cp_number .. "_flag", "Skin", team_info[new_defending_team].skin )
|
|
OutputEvent( "cp" .. cp_number .. "_flag", team_info[new_defending_team].flag_visibility)
|
|
|
|
-- remove old flaginfo icons and add new ones
|
|
RemoveHudItemFromAll( cp_number .. "-background-" .. cp.defending_team )
|
|
RemoveHudItemFromAll( cp_number .. "-foreground-" .. cp.defending_team )
|
|
|
|
AddHudIconToAll( icons[ new_defending_team ].teamicon, cp_number .. "-background-" .. new_defending_team, cp.hudposx, cp.hudposy, cp.hudwidth, cp.hudheight, cp.hudalign)
|
|
AddHudIconToAll( cp.hudstatusicon, cp_number .. "-foreground-" .. new_defending_team, cp.hudposx, cp.hudposy, cp.hudwidth, cp.hudheight, cp.hudalign)
|
|
|
|
local schedule_name = "cp" .. cp_number .. "_score_timer"
|
|
|
|
-- stop an existing timer
|
|
if cp.defending_team ~= Team.kUnassigned then
|
|
RemoveSchedule( schedule_name )
|
|
end
|
|
|
|
-- only worry with score timer for TEAM1 and TEAM2
|
|
if new_defending_team ~= Team.kUnassigned then
|
|
|
|
-- start the score timer
|
|
AddScheduleRepeating( schedule_name, cp.score_timer_interval[new_defending_team], cp_score_timer, cp_number, new_defending_team )
|
|
|
|
end
|
|
|
|
cp.defending_team = new_defending_team
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- restore all items in a CP
|
|
-----------------------------------------------------------------------------
|
|
function RestoreCPItems( cp_number, old_defending_team, new_defending_team )
|
|
|
|
local c = Collection()
|
|
c:GetByName( { "cp_cp" .. cp_number .. "_ammo", "cz2_cp" .. cp_number .. "_ammo", "cp_cp" .. cp_number .. "_armor", "cz2_cp" .. cp_number .. "_armor" }, { CF.kNone } )
|
|
for item in c.items do
|
|
item = CastToInfoScript(item)
|
|
|
|
-- restore this CP's ammo and armor
|
|
item:Restore()
|
|
|
|
-- Also set the touchflags so only the defending team can use the packs
|
|
item:SetTouchFlags(team_info[new_defending_team].touchflags)
|
|
end
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- reset team cp capping stuff
|
|
-----------------------------------------------------------------------------
|
|
function ResetTeamCPCapping( cp, team_number, do_total_reset, set_next_cap_zone_timer )
|
|
|
|
cp.cap_status[team_number] = 0
|
|
cp.next_cap_zone_timer[team_number] = set_next_cap_zone_timer
|
|
|
|
RemoveHudItemFromAll( cp.cp_number .. "-capstatusicon-" .. team_number )
|
|
RemoveHudItemFromAll( cp.cp_number .. "-caplockicon-" .. team_number )
|
|
OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[team_number].team_name .. "_capsprites", "HideSprite" )
|
|
OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[team_number].team_name .. "_capsound", "StopSound" )
|
|
|
|
if cp.former_touching_players[team_number]:Count() > 0 then
|
|
cp.former_touching_players[team_number]:RemoveAllItems()
|
|
end
|
|
|
|
if do_total_reset then
|
|
if cp.touching_players[team_number]:Count() > 0 then
|
|
cp.touching_players[team_number]:RemoveAllItems()
|
|
end
|
|
|
|
cp.cap_speed[team_number] = 0
|
|
end
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- reset all cp capping stuff
|
|
-----------------------------------------------------------------------------
|
|
function ResetCPCapping( cp )
|
|
|
|
for i,v in pairs(teams) do
|
|
ResetTeamCPCapping( cp, v, true, 0 )
|
|
end
|
|
|
|
end
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- the cp has definitely been captured
|
|
-----------------------------------------------------------------------------
|
|
function CaptureCP( cp_number, new_defending_team )
|
|
|
|
local cp = command_points[cp_number]
|
|
local old_defending_team = cp.defending_team
|
|
|
|
RestoreCPItems(cp_number, old_defending_team, new_defending_team)
|
|
|
|
-- Give points to team and player
|
|
local team = GetTeam(new_defending_team)
|
|
team:AddScore(cp.point_value[new_defending_team])
|
|
|
|
-- Find out if any team has complete control
|
|
local team_with_complete_control = Team.kUnassigned
|
|
local control_count = { [TEAM1] = 0, [TEAM2] = 0 }
|
|
control_count[new_defending_team] = 1
|
|
for i,v in ipairs(command_points) do
|
|
if v.defending_team ~= Team.kUnassigned and v.cp_number ~= cp_number then
|
|
control_count[v.defending_team] = control_count[v.defending_team] + 1
|
|
end
|
|
if control_count[v.defending_team] == CP_COUNT then
|
|
team_with_complete_control = v.defending_team
|
|
break
|
|
end
|
|
end
|
|
|
|
if team_with_complete_control ~= Team.kUnassigned then
|
|
|
|
if ENABLE_COMPLETE_CONTROL_POINTS then
|
|
-- Bonus points for complete control
|
|
team:AddScore(POINTS_FOR_COMPLETE_CONTROL)
|
|
end
|
|
|
|
if ENABLE_COMPLETE_CONTROL_RESET then
|
|
|
|
AddSchedule("complete_control_notification", 0.1, complete_control_notification, team_with_complete_control)
|
|
|
|
-- Reset all command points
|
|
for i,v in ipairs(command_points) do
|
|
ChangeCPDefendingTeam(v.cp_number, Team.kUnassigned)
|
|
ResetCPCapping( v )
|
|
end
|
|
|
|
-- reset colors of respawn beams
|
|
--OutputEvent( team_info[TEAM1].team_name .. "_respawn_beam", "Color", team_info[Team.kUnassigned].respawnbeam_color[0] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[1] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[2] )
|
|
--OutputEvent( team_info[TEAM2].team_name .. "_respawn_beam", "Color", team_info[Team.kUnassigned].respawnbeam_color[0] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[1] .. " " .. team_info[Team.kUnassigned].respawnbeam_color[2] )
|
|
|
|
if ENABLE_FLAGS then
|
|
-- Return all flags
|
|
local c = Collection()
|
|
c:GetByName(flags, { CF.kNone })
|
|
for item in c.items do
|
|
item = CastToInfoScript(item)
|
|
item:Return()
|
|
end
|
|
end
|
|
|
|
RemoveAllCPAmmoAndArmor()
|
|
|
|
if ENABLE_COMPLETE_CONTROL_RESPAWN then
|
|
AddSchedule("complete_control_respawn", 1.0, complete_control_respawn)
|
|
end
|
|
|
|
-- get out now if resetting
|
|
return
|
|
|
|
end
|
|
|
|
end
|
|
|
|
ChangeCPDefendingTeam(cp_number, new_defending_team)
|
|
|
|
-- change the colors this team's respawn beams
|
|
--local beam_team = team_info[new_defending_team]
|
|
--beam_team.respawnbeam_color[beam_team.color_index] = beam_team.respawnbeam_color[Team.kUnassigned] + (control_count[new_defending_team] * 35)
|
|
--OutputEvent( beam_team.team_name .. "_respawn_beam", "Color", beam_team.respawnbeam_color[0] .. " " .. beam_team.respawnbeam_color[1] .. " " .. beam_team.respawnbeam_color[2] )
|
|
|
|
SmartTeamMessage( team, "#FF_CZ2_YOURTEAM_CP" .. cp_number, "#FF_CZ2_OTHERTEAM_CP" .. cp_number, Color.kGreen, Color.kRed )
|
|
|
|
-- sounds will get more and more crazy
|
|
--SmartTeamSound( team, good_cap_sounds[control_count[new_defending_team]], bad_cap_sounds[control_count[new_defending_team]] )
|
|
|
|
-- caes: changed it to announce the cp number captured/lost
|
|
SmartTeamSpeak( team, good_cap_sounds[cp_number], bad_cap_sounds[cp_number] )
|
|
end
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- a cp's defending team successfully defended or capped
|
|
-----------------------------------------------------------------------------
|
|
function SuccessfulCPDefense( cp, team_number, is_a_cap )
|
|
|
|
-- reward the touching players
|
|
for i in cp.touching_players[team_number].items do
|
|
i = CastToPlayer( i )
|
|
if is_a_cap then
|
|
CapResupply( i, 1.00, is_a_cap )
|
|
i:AddFortPoints((cp.point_value[team_number]) * 100, "#FF_FORTPOINTS_CAPTUREPOINT")
|
|
i:SetCloakable( true )
|
|
else
|
|
CapResupply( i, 0.50, is_a_cap )
|
|
i:AddFortPoints((cp.point_value[team_number]) * 50, "#FF_FORTPOINTS_DEFENDPOINT")
|
|
end
|
|
end
|
|
|
|
-- reward the former touching players
|
|
for i in cp.former_touching_players[team_number].items do
|
|
i = CastToPlayer( i )
|
|
if is_a_cap then
|
|
CapResupply( i, 0.50, is_a_cap )
|
|
i:AddFortPoints((cp.point_value[team_number]) * 50, "#FF_FORTPOINTS_CAPTUREPOINT_ASSIST")
|
|
else
|
|
CapResupply( i, 0.25, is_a_cap )
|
|
i:AddFortPoints((cp.point_value[team_number]) * 25, "#FF_FORTPOINTS_DEFENDPOINT_ASSIST")
|
|
end
|
|
end
|
|
|
|
-- no need to keep them around for future rewards
|
|
cp.former_touching_players[team_number]:RemoveAllItems()
|
|
|
|
end
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- timed cp capping
|
|
-----------------------------------------------------------------------------
|
|
function cap_zone_timer( cp )
|
|
|
|
local new_defending_team = Team.kUnassigned
|
|
local other_team = Team.kUnassigned
|
|
local last_cap_status = {}
|
|
local total_cap_speed = 0
|
|
local total_cap_status = 0
|
|
|
|
for i,v in pairs(teams) do
|
|
total_cap_speed = total_cap_speed + cp.cap_speed[v]
|
|
total_cap_status = total_cap_status + cp.cap_status[v]
|
|
end
|
|
|
|
for i,v in pairs(teams) do
|
|
|
|
-- don't bother doing some stuff if nothing has changed
|
|
last_cap_status[v] = cp.cap_status[v]
|
|
|
|
-- after one team caps a cp, the other team can't touch that cp for X seconds
|
|
if cp.next_cap_zone_timer[v] > 0 then
|
|
|
|
cp.next_cap_zone_timer[v] = cp.next_cap_zone_timer[v] - CAP_ZONE_TIMER_INTERVAL
|
|
|
|
local lock_percent = math.min( 1.0, cp.next_cap_zone_timer[v] / cp.delay_before_retouch[v] )
|
|
local minlockhudwidth = cp.hudwidth * 0.333
|
|
local minlockhudheight = cp.hudheight * 0.333
|
|
|
|
AddHudIconToAll( icons[v].lockicon, cp.cp_number .. "-caplockicon-" .. v, cp.hudposx, cp.hudposy + cp_zone_icons[v].hudposy_offset, minlockhudwidth + ( (cp.hudwidth - minlockhudwidth) * lock_percent ), minlockhudheight + ( (cp.hudheight - minlockhudheight) * lock_percent ), cp.hudalign)
|
|
|
|
-- clamp
|
|
if cp.next_cap_zone_timer[v] <= 0 then
|
|
cp.next_cap_zone_timer[v] = 0
|
|
RemoveHudItemFromAll( cp.cp_number .. "-caplockicon-" .. v )
|
|
end
|
|
|
|
-- this team is standing in the zone
|
|
elseif cp.cap_speed[v] > 0 then
|
|
|
|
-- don't bother with cap_status calculations for the defending team
|
|
if v == cp.defending_team then
|
|
|
|
cp.cap_status[v] = cp.cap_requirement[v]
|
|
|
|
-- calculate cap status
|
|
else
|
|
|
|
-- every vote counts
|
|
local affected_cap_speed = cp.cap_speed[v] - ( total_cap_speed - cp.cap_speed[v] )
|
|
|
|
cp.cap_status[v] = cp.cap_status[v] + affected_cap_speed
|
|
|
|
-- clamp
|
|
if cp.cap_status[v] < 0 then
|
|
|
|
cp.cap_status[v] = 0
|
|
|
|
-- potential capping team
|
|
elseif cp.cap_status[v] >= cp.cap_requirement[v] then
|
|
|
|
new_defending_team = v
|
|
|
|
-- clamp
|
|
cp.cap_status[v] = cp.cap_requirement[v]
|
|
|
|
end
|
|
end
|
|
|
|
-- this team is not standing in the zone
|
|
else
|
|
if v == cp.defending_team then
|
|
-- don't bother with cap_status calculations for the defending team
|
|
cp.cap_status[v] = 0
|
|
else
|
|
-- decrease cap status
|
|
cp.cap_status[v] = cp.cap_status[v] - ( CAP_ZONE_NOTOUCH_SPEED + total_cap_speed )
|
|
|
|
-- clamp
|
|
if cp.cap_status[v] < 0 then
|
|
cp.cap_status[v] = 0
|
|
end
|
|
end
|
|
end
|
|
|
|
-- don't bother doing some stuff if nothing has changed
|
|
if cp.cap_status[v] ~= last_cap_status[v] then
|
|
|
|
-- draw the cap status icon
|
|
if cp.cap_status[v] > 0 then
|
|
|
|
local cap_percent = cp.cap_status[v] / cp.cap_requirement[v]
|
|
local minhudwidth = cp.hudwidth * 0.333
|
|
local minhudheight = cp.hudheight * 0.333
|
|
AddHudIconToAll( cp_zone_icons[v].hudicon, cp.cp_number .. "-capstatusicon-" .. v, cp.hudposx, cp.hudposy + cp_zone_icons[v].hudposy_offset, minhudwidth + ( (cp.hudwidth - minhudwidth) * cap_percent ), minhudheight + ( (cp.hudheight - minhudheight) * cap_percent ), cp.hudalign)
|
|
OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[v].team_name .. "_capsprites", "ShowSprite" )
|
|
OutputEvent( "cp" .. cp.cp_number .. "_" .. team_info[v].team_name .. "_capsound", "PlaySound" )
|
|
|
|
-- remove the cap status icon, remove former touching players, and reward defenders
|
|
else
|
|
|
|
-- reward the defenders
|
|
if v ~= cp.defending_team and cp.defending_team ~= Team.kUnassigned then
|
|
SuccessfulCPDefense( cp, cp.defending_team, false )
|
|
end
|
|
|
|
-- reset the other team's cp capping stuff
|
|
ResetTeamCPCapping( cp, v, false, 0 )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
if new_defending_team ~= v then
|
|
other_team = v
|
|
end
|
|
|
|
end
|
|
|
|
-- someone capped this cp
|
|
if new_defending_team ~= Team.kUnassigned then
|
|
|
|
-- cap the cp
|
|
SuccessfulCPDefense( cp, new_defending_team, true )
|
|
CaptureCP( cp.cp_number, new_defending_team )
|
|
|
|
-- reset the other team's cp capping stuff
|
|
ResetTeamCPCapping( cp, other_team, false, cp.delay_before_retouch[other_team] )
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- triggers
|
|
-----------------------------------------------------------------------------
|
|
|
|
cp_base_trigger = trigger_ff_script:new({ team = Team.kUnassigned, failtouch_message = "" })
|
|
|
|
function cp_base_trigger:allowed( allowed_entity )
|
|
|
|
if IsPlayer( allowed_entity ) then
|
|
local player = CastToPlayer( allowed_entity )
|
|
if player:GetTeamId() == self.team then
|
|
return EVENT_ALLOWED
|
|
end
|
|
end
|
|
return EVENT_DISALLOWED
|
|
end
|
|
|
|
function cp_base_trigger:onfailtouch( touch_entity )
|
|
|
|
if IsPlayer( touch_entity ) then
|
|
local player = CastToPlayer( touch_entity )
|
|
BroadCastMessageToPlayer( player, failtouch_message )
|
|
end
|
|
end
|
|
|
|
cp_team1_door_trigger = cp_base_trigger:new({ team = TEAM1 , failtouch_message = "#FF_NOTALLOWEDDOOR" })
|
|
cp_team2_door_trigger = cp_base_trigger:new({ team = TEAM2 , failtouch_message = "#FF_NOTALLOWEDDOOR" })
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- packs
|
|
-----------------------------------------------------------------------------
|
|
cp_base_pack = genericbackpack:new({
|
|
health = 100,
|
|
armor = 300,
|
|
nails = 200,
|
|
shells = 200,
|
|
rockets = 200,
|
|
cells = 200,
|
|
detpacks = 0,
|
|
mancannons = 0,
|
|
gren1 = 0,
|
|
gren2 = 0,
|
|
respawntime = 1,
|
|
touchflags = team_info[Team.kUnassigned].touchflags,
|
|
model = "models/items/backpack/backpack.mdl",
|
|
materializesound = "Item.Materialize",
|
|
touchsound = "Backpack.Touch",
|
|
cp_number = 0,
|
|
botgoaltype = Bot.kBackPack_Ammo,
|
|
})
|
|
|
|
function cp_base_pack:dropatspawn() return false end
|
|
|
|
cp_team1_respawn_pack = cp_base_pack:new( { touchflags = team_info[TEAM1].touchflags } )
|
|
cp_team2_respawn_pack = cp_base_pack:new( { touchflags = team_info[TEAM2].touchflags } )
|
|
|
|
cp_cp1_ammo = ammobackpack:new({cp_number = 1})
|
|
cp_cp2_ammo = ammobackpack:new({cp_number = 2})
|
|
cp_cp3_ammo = ammobackpack:new({cp_number = 3})
|
|
cp_cp4_ammo = ammobackpack:new({cp_number = 4})
|
|
cp_cp5_ammo = ammobackpack:new({cp_number = 5})
|
|
|
|
cp_cp1_armor = armorkit:new({cp_number = 1})
|
|
cp_cp2_armor = armorkit:new({cp_number = 2})
|
|
cp_cp3_armor = armorkit:new({cp_number = 3})
|
|
cp_cp4_armor = armorkit:new({cp_number = 4})
|
|
cp_cp5_armor = armorkit:new({cp_number = 5})
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- grenade packs
|
|
-----------------------------------------------------------------------------
|
|
cp_base_grenade_pack = cp_base_pack:new({
|
|
detpacks = 1,
|
|
mancannons = 1,
|
|
gren1 = 4,
|
|
gren2 = 4,
|
|
respawntime = 15,
|
|
touchflags = team_info[Team.kUnassigned].touchflags,
|
|
botgoaltype = Bot.kBackPack_Grenades,
|
|
})
|
|
|
|
cp_team1_grenade_pack = cp_base_grenade_pack:new( { touchflags = team_info[TEAM1].touchflags } )
|
|
cp_team2_grenade_pack = cp_base_grenade_pack:new( { touchflags = team_info[TEAM2].touchflags } )
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- cp zones
|
|
-----------------------------------------------------------------------------
|
|
|
|
cp_base_cp_zone = trigger_ff_script:new({
|
|
item = "",
|
|
team = 0,
|
|
botgoaltype = Bot.kFlagCap,
|
|
cp_number = 0,
|
|
})
|
|
|
|
function cp_base_cp_zone:ontrigger( trigger_entity )
|
|
|
|
-- check whether flags are used, and in turn wheter these triggers are used
|
|
if ENABLE_FLAGS or not ENABLE_CP_TELEPORTERS then return end
|
|
|
|
if IsPlayer( trigger_entity ) then
|
|
local player = CastToPlayer( trigger_entity )
|
|
|
|
-- Allow players on defending team to teleport back to base
|
|
if player:GetTeamId() == command_points[self.cp_number].defending_team then
|
|
|
|
if player:IsInUse() then
|
|
-- respawn the player
|
|
ApplyToPlayer( player, { AT.kRespawnPlayers, kReloadClips } )
|
|
|
|
OutputEvent( "cp" .. self.cp_number .. "_respawn_enter_sound", "PlaySound" )
|
|
AddSchedule("cp" .. self.cp_number .. "_respawn_" .. player:GetId(), 0.1, EmitSound, player, "ff_cz2.teleport_exit")
|
|
else
|
|
BroadCastMessageToPlayer(player, "#FF_CZ2_USE_RESPAWN")
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
function cp_base_cp_zone:ontouch( trigger_entity )
|
|
|
|
-- check whether flags are used, and in turn wheter these zones are used
|
|
if ENABLE_FLAGS then return end
|
|
|
|
if IsPlayer( trigger_entity ) then
|
|
local player = CastToPlayer( trigger_entity )
|
|
local cp = command_points[self.cp_number]
|
|
PlayerStartTouchingCapZone( player, cp )
|
|
end
|
|
|
|
end
|
|
|
|
function cp_base_cp_zone:onendtouch( trigger_entity )
|
|
|
|
-- check whether flags are used, and in turn wheter these zones are used
|
|
if ENABLE_FLAGS then return end
|
|
|
|
if IsPlayer( trigger_entity ) then
|
|
local player = CastToPlayer( trigger_entity )
|
|
local cp = command_points[self.cp_number]
|
|
PlayerStopTouchingCapZone( player, cp )
|
|
end
|
|
end
|
|
|
|
cp_cp1_cp_zone = cp_base_cp_zone:new({ cp_number = 1 })
|
|
cp_cp2_cp_zone = cp_base_cp_zone:new({ cp_number = 2 })
|
|
cp_cp3_cp_zone = cp_base_cp_zone:new({ cp_number = 3 })
|
|
cp_cp4_cp_zone = cp_base_cp_zone:new({ cp_number = 4 })
|
|
cp_cp5_cp_zone = cp_base_cp_zone:new({ cp_number = 5 })
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- cp triggers
|
|
-----------------------------------------------------------------------------
|
|
|
|
cp_base_cp_trigger = trigger_ff_script:new({
|
|
item = "",
|
|
team = 0,
|
|
botgoaltype = Bot.kFlagCap,
|
|
cp_number = 0,
|
|
})
|
|
|
|
function cp_base_cp_trigger:ontrigger( trigger_entity )
|
|
|
|
-- check whether flags are used, and in turn wheter these triggers are used
|
|
if not ENABLE_FLAGS or not ENABLE_CP_TELEPORTERS then return end
|
|
|
|
if IsPlayer( trigger_entity ) then
|
|
local player = CastToPlayer( trigger_entity )
|
|
|
|
-- Allow players on defending team to teleport back to base
|
|
if player:GetTeamId() == command_points[self.cp_number].defending_team then
|
|
|
|
if player:IsInUse() then
|
|
-- check if the player has a flag
|
|
for i,v in ipairs(flags) do
|
|
-- return the flag
|
|
if player:HasItem(v) then ReturnFlagFromPlayer(player) end
|
|
end
|
|
|
|
-- respawn the player
|
|
ApplyToPlayer( player, { AT.kRespawnPlayers, kReloadClips } )
|
|
|
|
OutputEvent( "cp" .. self.cp_number .. "_respawn_enter_sound", "PlaySound" )
|
|
AddSchedule("cp" .. self.cp_number .. "_respawn_" .. player:GetId(), 0.1, EmitSound, player, "ff_cz2.teleport_exit")
|
|
else
|
|
BroadCastMessageToPlayer(player, "#FF_CZ2_USE_RESPAWN")
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
function cp_base_cp_trigger:ontouch( trigger_entity )
|
|
|
|
-- check whether flags are used, and in turn wheter these triggers are used
|
|
if not ENABLE_FLAGS then return end
|
|
|
|
if IsPlayer( trigger_entity ) then
|
|
local player = CastToPlayer( trigger_entity )
|
|
local cp = command_points[self.cp_number]
|
|
|
|
-- No capping if player's team already defends this CP
|
|
if player:GetTeamId() == cp.defending_team then return end
|
|
|
|
-- get out if player doesn't have flag
|
|
if not PlayerHasFlag(player) then return end
|
|
|
|
ReturnFlagFromPlayer(player)
|
|
|
|
CaptureCP(self.cp_number, player:GetTeamId())
|
|
player:AddFortPoints((cp.point_value[player:GetTeamId()]) * 100, "#FF_FORTPOINTS_CAPTUREPOINT")
|
|
end
|
|
|
|
end
|
|
|
|
cp_cp1_cp_trigger = cp_base_cp_trigger:new({ cp_number = 1 })
|
|
cp_cp2_cp_trigger = cp_base_cp_trigger:new({ cp_number = 2 })
|
|
cp_cp3_cp_trigger = cp_base_cp_trigger:new({ cp_number = 3 })
|
|
cp_cp4_cp_trigger = cp_base_cp_trigger:new({ cp_number = 4 })
|
|
cp_cp5_cp_trigger = cp_base_cp_trigger:new({ cp_number = 5 })
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- flags
|
|
-----------------------------------------------------------------------------
|
|
|
|
cp_base_flag = info_ff_script:new({
|
|
name = "Base Flag",
|
|
team = 0,
|
|
model = "models/flag/flag.mdl",
|
|
tosssound = "Flag.Toss",
|
|
modelskin = 0,
|
|
dropnotouchtime = 2,
|
|
capnotouchtime = 2,
|
|
botgoaltype = Bot.kFlag,
|
|
hudicon = "",
|
|
hudx = 5,
|
|
hudy = 180,
|
|
hudalign = 1,
|
|
touchflags = team_info[Team.kUnassigned].touchflags
|
|
})
|
|
|
|
function cp_base_flag:precache()
|
|
PrecacheSound(self.tosssound)
|
|
info_ff_script.precache(self)
|
|
end
|
|
|
|
function cp_base_flag:spawn()
|
|
self.notouch = { }
|
|
info_ff_script.spawn(self)
|
|
end
|
|
|
|
function cp_base_flag:addnotouch(player_id, duration)
|
|
self.notouch[player_id] = duration
|
|
AddSchedule(self.name .. "-" .. player_id, duration, self.removenotouch, self, player_id)
|
|
end
|
|
|
|
function cp_base_flag.removenotouch(self, player_id)
|
|
self.notouch[player_id] = nil
|
|
end
|
|
|
|
function cp_base_flag:touch( touch_entity )
|
|
local player = CastToPlayer( touch_entity )
|
|
|
|
if player:GetTeamId() ~= self.team then return end
|
|
|
|
-- pickup if they can
|
|
if self.notouch[player:GetId()] then return end
|
|
|
|
-- make sure they don't have any flags already
|
|
for i,v in ipairs(flags) do
|
|
if player:HasItem(v) then return end
|
|
end
|
|
|
|
-- if the player is a spy, then force him to lose his disguise
|
|
player:SetDisguisable( false )
|
|
player:SetCloakable( false )
|
|
|
|
-- note: this seems a bit backwards (Pickup verb fits Player better)
|
|
local flag = CastToInfoScript(entity)
|
|
flag:Pickup(player)
|
|
player:AddEffect( EF.kSpeedlua1, -1, 0, FLAG_CARRIER_SPEED )
|
|
AddHudIcon( player, self.hudicon, flag:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign )
|
|
end
|
|
|
|
function cp_base_flag:onownerdie( owner_entity )
|
|
-- drop the flag
|
|
local flag = CastToInfoScript(entity)
|
|
flag:Drop(FLAG_RETURN_TIME, 0.0)
|
|
end
|
|
|
|
function cp_base_flag:onownerfeign( owner_entity )
|
|
-- drop the flag
|
|
local flag = CastToInfoScript(entity)
|
|
flag:Drop(FLAG_RETURN_TIME, 0.0)
|
|
end
|
|
function cp_base_flag:onownercloak( owner_entity )
|
|
-- drop the flag
|
|
local flag = CastToInfoScript(entity)
|
|
flag:Drop(FLAG_RETURN_TIME, 0.0)
|
|
end
|
|
function cp_base_flag:dropitemcmd( owner_entity )
|
|
-- throw the flag
|
|
local flag = CastToInfoScript(entity)
|
|
flag:Drop(FLAG_RETURN_TIME, FLAG_THROW_SPEED)
|
|
end
|
|
|
|
function cp_base_flag:ondrop( owner_entity )
|
|
local flag = CastToInfoScript(entity)
|
|
flag:EmitSound(self.tosssound)
|
|
end
|
|
|
|
function cp_base_flag:onloseitem( owner_entity )
|
|
-- let the player that lost the flag put on a disguise
|
|
local player = CastToPlayer( owner_entity )
|
|
player:SetDisguisable(true)
|
|
player:SetCloakable(true)
|
|
|
|
self:addnotouch(player:GetId(), self.capnotouchtime)
|
|
|
|
--player:RemoveEffect( EF.kSpeedlua1 )
|
|
-- remove flag icon from hud
|
|
local flag = CastToInfoScript(entity)
|
|
RemoveHudItem( player, flag:GetName() )
|
|
end
|
|
|
|
function cp_base_flag:onreturn( )
|
|
end
|
|
|
|
cp_team1_flag = cp_base_flag:new({
|
|
team = TEAM1,
|
|
modelskin = 0,
|
|
name = team_info[TEAM1].team_name .. " flag",
|
|
hudicon = "hud_flag_" .. team_info[TEAM1].team_name .. ".vtf",
|
|
hudx = 5,
|
|
hudy = 180,
|
|
hudwidth = 48,
|
|
hudheight = 48,
|
|
touchflags = team_info[TEAM1].touchflags
|
|
})
|
|
|
|
cp_team2_flag = cp_base_flag:new({
|
|
team = TEAM2,
|
|
modelskin = 1,
|
|
name = team_info[TEAM2].team_name .. " flag",
|
|
hudicon = "hud_flag_" .. team_info[TEAM2].team_name .. ".vtf",
|
|
hudx = 5,
|
|
hudy = 180,
|
|
hudwidth = 48,
|
|
hudheight = 48,
|
|
touchflags = team_info[TEAM2].touchflags
|
|
})
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- flag dispensers
|
|
-----------------------------------------------------------------------------
|
|
cp_base_flag_dispenser = trigger_ff_script:new({
|
|
name = "Base Flag Dispenser",
|
|
team = Team.kUnassigned,
|
|
dropnotouchtime = 2,
|
|
botgoaltype = Bot.kFlag,
|
|
hudicon = "",
|
|
hudx = 5,
|
|
hudy = 180,
|
|
hudwidth = 48,
|
|
hudheight = 48,
|
|
hudalign = 1,
|
|
flags = {"flag"}
|
|
})
|
|
|
|
function cp_base_flag_dispenser:allowed ( allowed_entity )
|
|
|
|
-- check whether flags are used, and in turn wheter these triggers are used
|
|
if not ENABLE_FLAGS then return EVENT_DISALLOWED end
|
|
|
|
if IsPlayer( allowed_entity ) then
|
|
local player = CastToPlayer( allowed_entity )
|
|
if player:GetTeamId() == self.team then
|
|
|
|
-- Player can't have a flag
|
|
local playerhasflag = false
|
|
|
|
for i,v in ipairs(self.flags) do
|
|
if player:HasItem(v) then
|
|
playerhasflag = true
|
|
break
|
|
end
|
|
end
|
|
|
|
-- get out if player doesn't have flag
|
|
if not playerhasflag then
|
|
return EVENT_ALLOWED
|
|
end
|
|
end
|
|
end
|
|
return EVENT_DISALLOWED
|
|
end
|
|
|
|
function cp_base_flag_dispenser:ontouch( trigger_entity )
|
|
|
|
-- check whether flags are used, and in turn wheter these triggers are used
|
|
if not ENABLE_FLAGS then return end
|
|
|
|
if IsPlayer( trigger_entity ) then
|
|
|
|
local player = CastToPlayer( trigger_entity )
|
|
|
|
local c = Collection()
|
|
c:GetByName( self.flags, { CF.kNone } )
|
|
-- give the player an inactive flag
|
|
for item in c.items do
|
|
item = CastToInfoScript(item)
|
|
if item:IsInactive() then
|
|
-- if the player is a spy, then force him to lose his disguise
|
|
player:SetDisguisable( false )
|
|
player:SetCloakable( false )
|
|
|
|
-- note: this seems a bit backwards (Pickup verb fits Player better)
|
|
item:Pickup(player)
|
|
player:AddEffect( EF.kSpeedlua1, -1, 0, FLAG_CARRIER_SPEED )
|
|
AddHudIcon( player, self.hudicon, item:GetName(), self.hudx, self.hudy, self.hudwidth, self.hudheight, self.hudalign )
|
|
|
|
player:EmitSound("Buttons.snd9")
|
|
|
|
-- all done
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
cp_team1_flag_dispenser = cp_base_flag_dispenser:new({
|
|
name = team_info[TEAM1].team_name .. " flag dispenser",
|
|
team = TEAM1,
|
|
hudicon = "hud_flag_" .. team_info[TEAM1].team_name .. ".vtf",
|
|
flags = { team_info[TEAM1].team_name .. "_flag" }
|
|
})
|
|
|
|
cp_team2_flag_dispenser = cp_base_flag_dispenser:new({
|
|
name = team_info[TEAM2].team_name .. " flag dispenser",
|
|
team = TEAM2,
|
|
hudicon = "hud_flag_" .. team_info[TEAM2].team_name .. ".vtf",
|
|
flags = { team_info[TEAM2].team_name .. "_flag" }
|
|
})
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- command centers
|
|
-----------------------------------------------------------------------------
|
|
|
|
cp_base_command_center = trigger_ff_script:new({ team = Team.kUnassigned, enemy_team = Team.kUnassigned })
|
|
function cp_base_command_center:onexplode( explosion_entity )
|
|
|
|
-- check whether command centers are enabled
|
|
if not ENABLE_CC then return EVENT_ALLOWED end
|
|
|
|
if IsDetpack( explosion_entity ) then
|
|
local detpack = CastToDetpack(explosion_entity)
|
|
|
|
-- don't let assholes destroy their own team's command center
|
|
if detpack:GetTeamId() == self.team then return EVENT_ALLOWED end
|
|
|
|
local points = CC_DESTROY_POINTS
|
|
for i,v in ipairs(command_points) do
|
|
if v.defending_team == self.team then
|
|
-- taking CP 1 away from team2 is worth more than taking CP 5 away from them
|
|
points = points + v.point_value[self.team]
|
|
|
|
-- Remove all ammo and armor from CPs
|
|
local c = Collection()
|
|
c:GetByName({"cp_cp" .. v.cp_number .. "_ammo", "cz2_cp" .. v.cp_number .. "_ammo", "cp_cp" .. v.cp_number .. "_armor", "cz2_cp" .. v.cp_number .. "_armor"}, { CF.kNone })
|
|
for item in c.items do
|
|
item = CastToInfoScript(item)
|
|
item:Remove()
|
|
end
|
|
|
|
-- reset the CP
|
|
ChangeCPDefendingTeam(v.cp_number, Team.kUnassigned)
|
|
end
|
|
|
|
-- reset the other team's cp capping stuff
|
|
ResetTeamCPCapping( v, self.team, false, v.delay_before_retouch[self.team] * 2.0 )
|
|
end
|
|
|
|
local team = detpack:GetTeam()
|
|
team:AddScore(points)
|
|
|
|
local player = detpack:GetOwner()
|
|
player:AddFortPoints(points * 100, "#FF_FORTPOINTS_DESTROY_CC" )
|
|
|
|
SmartSound(player, "misc.thunder", "misc.thunder", "misc.thunder")
|
|
SmartMessage(player, "#FF_CZ2_YOU_CC", "#FF_CZ2_YOURTEAM_CC", "#FF_CZ2_OTHERTEAM_CC", Color.kGreen, Color.kGreen, Color.kRed)
|
|
SpeakAll( team_info[self.team].detcc_sentence )
|
|
|
|
-- EntityStopTouchingCC( detpack, self.team )
|
|
|
|
end
|
|
|
|
return EVENT_ALLOWED
|
|
end
|
|
|
|
function cp_base_command_center:ontouch( trigger_entity )
|
|
|
|
-- check whether command centers are enabled
|
|
if not ENABLE_CC then return end
|
|
|
|
-- if IsDetpack( trigger_entity ) then
|
|
-- local detpack = CastToDetpack( trigger_entity )
|
|
-- if detpack:GetTeamId() ~= self.team then
|
|
-- EntityStartTouchingCC( detpack, self.team )
|
|
-- end
|
|
-- end
|
|
|
|
if IsPlayer( trigger_entity ) then
|
|
local player = CastToPlayer( trigger_entity )
|
|
if player:GetTeamId() ~= self.team then
|
|
EntityStartTouchingCC( player, self.team )
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
function cp_base_command_center:onendtouch( trigger_entity )
|
|
|
|
-- check whether command centers are enabled
|
|
if not ENABLE_CC then return end
|
|
|
|
-- if IsDetpack( trigger_entity ) then
|
|
-- local detpack = CastToDetpack( trigger_entity )
|
|
-- if detpack:GetTeamId() ~= self.team then
|
|
-- EntityStopTouchingCC( detpack, self.team )
|
|
-- end
|
|
-- end
|
|
|
|
if IsPlayer( trigger_entity ) then
|
|
local player = CastToPlayer( trigger_entity )
|
|
if player:GetTeamId() ~= self.team then
|
|
EntityStopTouchingCC( player, self.team )
|
|
end
|
|
end
|
|
end
|
|
|
|
cp_team1_command_center = cp_base_command_center:new({ team = TEAM1, enemy_team = TEAM2 })
|
|
cp_team2_command_center = cp_base_command_center:new({ team = TEAM2, enemy_team = TEAM1 })
|
|
|
|
|
|
-------------------------------------------
|
|
-- cc computers
|
|
-------------------------------------------
|
|
|
|
cp_base_cc_computer = trigger_ff_script:new({ prefix = "unassigned", enemy_team = Team.kUnassigned })
|
|
|
|
function cp_base_cc_computer:ontrigger( trigger_entity )
|
|
|
|
-- check whether command centers are enabled
|
|
if not ENABLE_CC then return end
|
|
|
|
if IsPlayer( trigger_entity ) then
|
|
local player = CastToPlayer( trigger_entity )
|
|
|
|
-- Allow spies to open the enemy doors
|
|
if player:GetTeamId() == self.enemy_team and player:GetClass() == Player.kSpy then
|
|
|
|
if player:IsInUse() then
|
|
for i,v in ipairs(doors) do
|
|
-- open each enemy door
|
|
OutputEvent( self.prefix .. v, "Open" )
|
|
end
|
|
else
|
|
-- tell the player they can open the enemy doors
|
|
BroadCastMessageToPlayer(player, "#FF_CZ2_USE_DOORS")
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
cp_team1_cc_computer = cp_base_cc_computer:new({ prefix = team_info[TEAM1].team_name, enemy_team = TEAM2 })
|
|
cp_team2_cc_computer = cp_base_cc_computer:new({ prefix = team_info[TEAM2].team_name, enemy_team = TEAM1 })
|
|
|
|
|
|
-------------------------------------------
|
|
-- cp flaginfo
|
|
-------------------------------------------
|
|
|
|
function flaginfo( player_entity )
|
|
|
|
local player = CastToPlayer( player_entity )
|
|
|
|
for i,v in ipairs(command_points) do
|
|
|
|
AddHudIcon( player, icons[ v.defending_team ].teamicon , v.cp_number .. "-background-" .. v.defending_team , command_points[v.cp_number].hudposx, command_points[v.cp_number].hudposy, command_points[v.cp_number].hudwidth, command_points[v.cp_number].hudheight, command_points[v.cp_number].hudalign)
|
|
AddHudIcon( player, command_points[v.cp_number].hudstatusicon, v.cp_number .. "-foreground-" .. v.defending_team , command_points[v.cp_number].hudposx, command_points[v.cp_number].hudposy, command_points[v.cp_number].hudwidth, command_points[v.cp_number].hudheight, command_points[v.cp_number].hudalign)
|
|
|
|
end
|
|
|
|
DrawCCAlarmIcon( TEAM1 )
|
|
DrawCCAlarmIcon( TEAM2 )
|
|
|
|
end
|
|
|
|
|
|
-------------------------------------------
|
|
-- cp teleporters
|
|
-------------------------------------------
|
|
|
|
trigger_teleport = trigger_ff_script:new({})
|
|
cp_base_teleporter = trigger_teleport:new({ cp_number = 0, next_teleport_tick = 0 })
|
|
|
|
function cp_base_teleporter:allowed( allowed_entity )
|
|
|
|
-- check whether cc-to-cp teleporters are enabled
|
|
if not ENABLE_CC or not ENABLE_CC_TELEPORTERS then return EVENT_DISALLOWED end
|
|
|
|
local stime = GetServerTime()
|
|
|
|
if self.next_teleport_tick > stime then return end
|
|
|
|
if IsPlayer( allowed_entity ) then
|
|
|
|
local player = CastToPlayer( allowed_entity )
|
|
-- Allow players on defending team to teleport to cp
|
|
if player:GetTeamId() == command_points[self.cp_number].defending_team then
|
|
|
|
if player:IsInUse() then
|
|
-- teleport the player
|
|
local team_name = team_info[player:GetTeamId()].team_name
|
|
|
|
if ENTITY_TOUCHING_CC[player:GetId()] ~= nil then
|
|
team_name = team_info[ENTITY_TOUCHING_CC[player:GetId()]].team_name
|
|
end
|
|
|
|
OutputEvent( team_name .. "_cp" .. self.cp_number .. "_teleport_enter_sound", "PlaySound" )
|
|
--OutputEvent( team_name .. "_cp" .. self.cp_number .. "_teleport_exit_sound", "PlaySound", "", 0.1 )
|
|
OutputEvent( team_name .. "_cp" .. self.cp_number .. "_teleport_tesla", "DoSpark", "", 0.1 )
|
|
|
|
--self.next_teleport_tick = stime + 1.0
|
|
|
|
ApplyToPlayer( player, { AT.kStopPrimedGrens, kReloadClips } )
|
|
|
|
return EVENT_ALLOWED
|
|
else
|
|
-- tell the player they can teleport
|
|
BroadCastMessageToPlayer(player, "#FF_CZ2_USE_TELEPORT")
|
|
end
|
|
|
|
end
|
|
end
|
|
|
|
return EVENT_DISALLOWED
|
|
|
|
end
|
|
|
|
-- team1 teleporters
|
|
cp_team1_teleporter_cp1 = cp_base_teleporter:new({ cp_number = 1 })
|
|
cp_team1_teleporter_cp2 = cp_base_teleporter:new({ cp_number = 2 })
|
|
cp_team1_teleporter_cp3 = cp_base_teleporter:new({ cp_number = 3 })
|
|
cp_team1_teleporter_cp4 = cp_base_teleporter:new({ cp_number = 4 })
|
|
cp_team1_teleporter_cp5 = cp_base_teleporter:new({ cp_number = 5 })
|
|
|
|
-- team2 teleporters
|
|
cp_team2_teleporter_cp1 = cp_base_teleporter:new({ cp_number = 1 })
|
|
cp_team2_teleporter_cp2 = cp_base_teleporter:new({ cp_number = 2 })
|
|
cp_team2_teleporter_cp3 = cp_base_teleporter:new({ cp_number = 3 })
|
|
cp_team2_teleporter_cp4 = cp_base_teleporter:new({ cp_number = 4 })
|
|
cp_team2_teleporter_cp5 = cp_base_teleporter:new({ cp_number = 5 })
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- locations
|
|
-----------------------------------------------------------------------------
|
|
|
|
location_cp1 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_ONE", team = NO_TEAM })
|
|
location_cp2 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_TWO", team = NO_TEAM })
|
|
location_cp3 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_THREE", team = NO_TEAM })
|
|
location_cp4 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_FOUR", team = NO_TEAM })
|
|
location_cp5 = location_info:new({ text = "#FF_LOCATION_COMMAND_POINT_FIVE", team = NO_TEAM })
|
|
|
|
location_cp1_path = location_info:new({ text = "#FF_LOCATION_CP1_PATH", team = TEAM1 })
|
|
location_cp2_path = location_info:new({ text = "#FF_LOCATION_CP2_PATH", team = TEAM1 })
|
|
location_cp3_path = location_info:new({ text = "#FF_LOCATION_CP3_PATH", team = NO_TEAM })
|
|
location_cp4_path = location_info:new({ text = "#FF_LOCATION_CP4_PATH", team = TEAM2 })
|
|
location_cp5_path = location_info:new({ text = "#FF_LOCATION_CP5_PATH", team = TEAM2 })
|
|
|
|
location_catacombs = location_info:new({ text = "#FF_LOCATION_CATACOMBS", team = NO_TEAM })
|
|
|
|
location_blue_base = location_info:new({ text = "#FF_LOCATION_BASE", team = TEAM1 })
|
|
location_blue_cc = location_info:new({ text = "#FF_LOCATION_COMMAND_CENTER", team = TEAM1 })
|
|
location_blue_outside_base = location_info:new({ text = "#FF_LOCATION_OUTSIDE_BASE", team = TEAM1 })
|
|
location_blue_canal = location_info:new({ text = "#FF_LOCATION_CANAL", team = TEAM1 })
|
|
location_blue_catacombs = location_info:new({ text = "#FF_LOCATION_CATACOMBS", team = TEAM1 })
|
|
|
|
location_red_base = location_info:new({ text = "#FF_LOCATION_BASE", team = TEAM2 })
|
|
location_red_cc = location_info:new({ text = "#FF_LOCATION_COMMAND_CENTER", team = TEAM2 })
|
|
location_red_outside_base = location_info:new({ text = "#FF_LOCATION_OUTSIDE_BASE", team = TEAM2 })
|
|
location_red_canal = location_info:new({ text = "#FF_LOCATION_CANAL", team = TEAM2 })
|
|
location_red_catacombs = location_info:new({ text = "#FF_LOCATION_CATACOMBS", team = TEAM2 })
|
|
|
|
|
|
-----------------------------------------------------------------------------
|
|
-- backwards compatiblity - use "cp_*" names in your map instead!
|
|
-----------------------------------------------------------------------------
|
|
base_team_trigger = cp_base_trigger
|
|
blue_door_trigger = cp_team1_door_trigger
|
|
red_door_trigger = cp_team2_door_trigger
|
|
|
|
cz2_base_pack = cp_base_pack
|
|
cz2_blue_respawn_pack = cp_team1_respawn_pack
|
|
cz2_red_respawn_pack = cp_team2_respawn_pack
|
|
|
|
cz2_cp1_ammo = cp_cp1_ammo
|
|
cz2_cp2_ammo = cp_cp2_ammo
|
|
cz2_cp3_ammo = cp_cp3_ammo
|
|
cz2_cp4_ammo = cp_cp4_ammo
|
|
cz2_cp5_ammo = cp_cp5_ammo
|
|
|
|
cz2_cp1_armor = cp_cp1_armor
|
|
cz2_cp2_armor = cp_cp2_armor
|
|
cz2_cp3_armor = cp_cp3_armor
|
|
cz2_cp4_armor = cp_cp4_armor
|
|
cz2_cp5_armor = cp_cp5_armor
|
|
|
|
cz2_base_grenade_pack = cp_base_grenade_pack
|
|
cz2_blue_grenade_pack = cp_team1_grenade_pack
|
|
cz2_red_grenade_pack = cp_team2_grenade_pack
|
|
|
|
base_cp_zone = cp_base_cp_zone
|
|
cp1_zone = cp_cp1_cp_zone
|
|
cp2_zone = cp_cp2_cp_zone
|
|
cp3_zone = cp_cp3_cp_zone
|
|
cp4_zone = cp_cp4_cp_zone
|
|
cp5_zone = cp_cp5_cp_zone
|
|
|
|
base_cp_trigger = cp_base_cp_trigger
|
|
cp1_trigger = cp_cp1_cp_trigger
|
|
cp2_trigger = cp_cp2_cp_trigger
|
|
cp3_trigger = cp_cp3_cp_trigger
|
|
cp4_trigger = cp_cp4_cp_trigger
|
|
cp5_trigger = cp_cp5_cp_trigger
|
|
|
|
base_cp_flag = cp_base_flag
|
|
blue_flag = cp_team1_flag
|
|
red_flag = cp_team2_flag
|
|
|
|
cp_base_flag_dispenser = base_cp_flag_dispenser
|
|
blue_flag_dispenser = cp_team1_flag_dispenser
|
|
red_flag_dispenser = cp_team2_flag_dispenser
|
|
|
|
base_command_center = cp_base_command_center
|
|
blue_command_center = cp_team1_command_center
|
|
red_command_center = cp_team2_command_center
|
|
|
|
base_cp_cc_computer = cp_base_cc_computer
|
|
blue_cc_computer = cp_team1_cc_computer
|
|
red_cc_computer = cp_team2_cc_computer
|
|
|
|
base_cp_teleporter = cp_base_teleporter
|
|
blue_teleporter_cp1 = cp_team1_teleporter_cp1
|
|
blue_teleporter_cp2 = cp_team1_teleporter_cp2
|
|
blue_teleporter_cp3 = cp_team1_teleporter_cp3
|
|
blue_teleporter_cp4 = cp_team1_teleporter_cp4
|
|
blue_teleporter_cp5 = cp_team1_teleporter_cp5
|
|
red_teleporter_cp1 = cp_team2_teleporter_cp1
|
|
red_teleporter_cp2 = cp_team2_teleporter_cp2
|
|
red_teleporter_cp3 = cp_team2_teleporter_cp3
|
|
red_teleporter_cp4 = cp_team2_teleporter_cp4
|
|
red_teleporter_cp5 = cp_team2_teleporter_cp5
|
|
|
|
|