fortressforever-scripts/maps/includes/base_hunted.lua

472 lines
14 KiB
Lua

-- base_hunted.lua
-----------------------------------------------------------------------------
-- includes
-----------------------------------------------------------------------------
IncludeScript("base_teamplay");
IncludeScript("base_location");
-----------------------------------------------------------------------------
-- Basic hunted-style gameplay. Respawns all players when the VIP is killed
-----------------------------------------------------------------------------
POINTS_PER_HUNTED_DEATH = 5
POINTS_PER_HUNTED_DEATH_FOR_ASSASSIN = 5
POINTS_PER_HUNTED_ESCAPE = 10
POINTS_PER_HUNTED_ESCAPE_FOR_HUNTED = 10
POINTS_PER_HUNTED_ESCAPE_FOR_BODYGUARDS = 10
POINTS_PER_HUNTED_ATTACK = 2
HUNTED_ALLIES_TEAM = Team.kRed
HUNTED_ENTITY = nil
LAST_HUNTED_LOCATION = nil
ESCAPE_DOOR_BUTTON_UNLOCKED = true
-- escape_door_top is also defined as a base_escape_door object down below
escape_door = {
entity_names = { "escape_door_top", "escape_door_bottom" },
isopen = false,
openicon = "hud_door_open.vtf",
closedicon = "hud_door_closed.vtf",
hudposx = 0,
hudposy = 32,
hudwidth = 64,
hudheight = 32,
hudalignx = 4,
hudaligny = 0
}
-- precache sounds
function precache()
PrecacheSound("ff_hunted.thunder")
PrecacheSound("ff_hunted.cheer")
PrecacheSound("ff_hunted.dying_bird")
PrecacheSound("ff_hunted.dying_bird_full")
PrecacheSound("ff_hunted.dying_bird_full")
PrecacheSound("ff_hunted.i_am_the_werewolf")
PrecacheSound("ff_hunted.i_fight_vampires")
PrecacheSound("ff_hunted.werewolf_howling")
PrecacheSound("ff_hunted.werewolf_movies")
PrecacheSound("ff_hunted.werewolves_howling")
PrecacheSound("otherteam.flagstolen")
end
function startup()
SetGameDescription( "Hunted" )
-- set up team names
SetTeamName( Team.kBlue, "The Hunted" )
SetTeamName( Team.kRed, "Bodyguards" )
SetTeamName( Team.kYellow, "Assassins" )
SetTeamName( Team.kGreen, "Green Kid Touchers" )
-- set up team limits
SetPlayerLimit( Team.kBlue, 1 ) -- There can be only one Highlander!
SetPlayerLimit( Team.kRed, 0 ) -- Unlimited bodyguards.
SetPlayerLimit( Team.kYellow, 6 ) -- Only 6 assassins, but can we dynamically change this based on maxplayers and/or the current playercount?
SetPlayerLimit( Team.kGreen, -1 ) -- Fuck green.
local team = GetTeam( Team.kBlue )
team:SetAllies( Team.kRed )
team:SetClassLimit( Player.kScout, -1 )
team:SetClassLimit( Player.kSniper, -1 )
team:SetClassLimit( Player.kSoldier, -1 )
team:SetClassLimit( Player.kDemoman, -1 )
team:SetClassLimit( Player.kMedic, -1 )
team:SetClassLimit( Player.kHwguy, -1 )
team:SetClassLimit( Player.kPyro, -1 )
team:SetClassLimit( Player.kSpy, -1 )
team:SetClassLimit( Player.kEngineer, -1 )
team:SetClassLimit( Player.kCivilian, 0 )
team = GetTeam( Team.kRed )
team:SetAllies( Team.kBlue )
team:SetClassLimit( Player.kScout, -1 )
team:SetClassLimit( Player.kSniper, 1 )
team:SetClassLimit( Player.kSoldier, 0 )
team:SetClassLimit( Player.kDemoman, -1 )
team:SetClassLimit( Player.kMedic, 0 )
team:SetClassLimit( Player.kHwguy, 0 )
team:SetClassLimit( Player.kPyro, 1 )
team:SetClassLimit( Player.kSpy, -1 )
team:SetClassLimit( Player.kEngineer, 0 )
team:SetClassLimit( Player.kCivilian, -1 )
team = GetTeam( Team.kYellow )
team:SetClassLimit( Player.kScout, -1 )
team:SetClassLimit( Player.kSniper, 0 )
team:SetClassLimit( Player.kSoldier, -1 )
team:SetClassLimit( Player.kDemoman, -1 )
team:SetClassLimit( Player.kMedic, -1 )
team:SetClassLimit( Player.kHwguy, -1 )
team:SetClassLimit( Player.kPyro, -1 )
team:SetClassLimit( Player.kSpy, 1 )
team:SetClassLimit( Player.kEngineer, -1 )
team:SetClassLimit( Player.kCivilian, -1 )
RemoveSchedule( "hunted_location_timer" )
AddScheduleRepeating( "hunted_location_timer" , 1.0, hunted_location_timer )
end
-------------------------------------------
-- hunted flaginfo
-------------------------------------------
function flaginfo( player_entity )
local player = CastToPlayer( player_entity )
if escape_door.isopen then
RemoveHudItem( player, "escape_door_closed" )
AddHudIcon( player, escape_door.openicon, "escape_door_open", escape_door.hudposx, escape_door.hudposy, escape_door.hudwidth, escape_door.hudheight, escape_door.hudalignx, escape_door.hudaligny )
else
RemoveHudItem( player, "escape_door_open" )
AddHudIcon( player, escape_door.closedicon, "escape_door_closed", escape_door.hudposx, escape_door.hudposy, escape_door.hudwidth, escape_door.hudheight, escape_door.hudalignx, escape_door.hudaligny )
end
end
function hunted_location_timer()
if HUNTED_ENTITY ~= nil then
local player = CastToPlayer( HUNTED_ENTITY )
if player:GetLocation() ~= LAST_HUNTED_LOCATION then
LAST_HUNTED_LOCATION = player:GetLocation()
RemoveHudItem( player, "hunted_location" )
AddHudTextToTeam( GetTeam(Team.kRed), "hunted_location", "Hunted Location: " .. player:GetLocation(), 4, 44, 0, 1 )
RemoveHudItemFromTeam( GetTeam(Team.kYellow), "hunted_location" )
end
elseif LAST_HUNTED_LOCATION ~= nil then
LAST_HUNTED_LOCATION = nil
RemoveHudItemFromAll( "hunted_location" )
end
end
function respawn_everyone()
ApplyToAll({ AT.kAllowRespawn, AT.kRespawnPlayers, AT.kRemoveProjectiles, AT.kStopPrimedGrens })
AddSchedule( "close_escape_doors", 4.0, close_escape_doors )
end
function close_escape_doors()
for i,v in ipairs(escape_door.entity_names) do
-- close each enemy escape door
OutputEvent( v, "Close" )
end
end
function lock_escape_door_button()
ESCAPE_DOOR_BUTTON_UNLOCKED = false
end
function unlock_escape_door_button()
ESCAPE_DOOR_BUTTON_UNLOCKED = true
end
function hunted_escape_notification()
BroadCastMessage( "The Hunted escaped!" )
BroadCastSound ( "ff_hunted.cheer" )
end
function player_ondamage( player, damageinfo )
-- if no damageinfo do nothing
if not damageinfo then return end
local attacker = damageinfo:GetAttacker()
local inflictor = damageinfo:GetInflictor()
-- hunted has body armor on and only takes damage from certain things
if player:GetTeamId() == Team.kBlue then
local weapon = damageinfo:GetInflictor():GetClassName()
local attacker_is_buildable = false
if IsSentrygun(attacker) or IsDispenser(attacker) or IsSentrygun(inflictor) or IsDispenser(inflictor) then
attacker_is_buildable = true
end
if attacker_is_buildable ~= true and weapon ~= "ff_weapon_sniperrifle" and weapon ~= "ff_weapon_crowbar" and weapon ~= "ff_projectile_dart" and weapon ~= "ff_weapon_knife" then
damageinfo:ScaleDamage(0)
else
-- BroadCastSound ( "ff_hunted.dying_bird" )
end
-- hunted also has quad damage
else
if IsPlayer( attacker ) then
attacker = CastToPlayer( attacker )
if attacker:GetTeamId() == Team.kBlue and player:GetTeamId() ~= HUNTED_ALLIES_TEAM then
damageinfo:ScaleDamage(4)
attacker:AddFortPoints( POINTS_PER_HUNTED_ATTACK * 10, "Hunted Attack" )
ConsoleToAll( "The Hunted, " .. attacker:GetName() .. ", dealt quad damage to" .. player:GetName() .. "!" )
end
end
end
end
function player_onkill( player )
-- Don't let blue hunted suicide.
if player:GetTeamId() == Team.kBlue then
return false
end
return true
end
-- We only care when The Hunted is killed by another player
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 player_victim:GetTeamId() == Team.kBlue then
ConsoleToAll( "The Hunted, " .. player_victim:GetName() .. ", was assassinated!" )
BroadCastMessage( "The Hunted was assassinated!" )
-- BroadCastSound ( "ff_hunted.werewolves_howling" )
BroadCastSound ( "ff_hunted.thunder" )
local team = GetTeam( Team.kYellow )
team:AddScore( POINTS_PER_HUNTED_DEATH )
ApplyToAll( { AT.kDisallowRespawn } )
AddSchedule("respawn_everyone", 2, respawn_everyone)
end
end
function player_disconnected( player )
if player:GetTeamId() == Team.kBlue then
HUNTED_ENTITY = nil
UpdateObjectiveIcon( player, HUNTED_ENTITY )
UpdateTeamObjectiveIcon( GetTeam(Team.kRed), HUNTED_ENTITY )
RemoveHudItemFromAll("hunted_location")
end
end
BLOCKTEAMCHANGE = {}
function player_switchteam( player, currentteam, desiredteam )
local i = player:GetId()
local stime = GetServerTime()
if desiredteam == Team.kBlue then
local delaytime = BLOCKTEAMCHANGE[i]
if delaytime ~= nil and delaytime > stime then
return false
end
BLOCKTEAMCHANGE[i] = stime + 10;
end
if player:GetTeamId() == Team.kBlue then
HUNTED_ENTITY = nil
UpdateObjectiveIcon( player, HUNTED_ENTITY )
UpdateTeamObjectiveIcon( GetTeam(Team.kRed), HUNTED_ENTITY )
RemoveHudItemFromAll("hunted_location")
end
return true
end
-- Give everyone a full resupply, but strip grenades from assassins
function player_spawn( player_entity )
local player = CastToPlayer( player_entity )
player:AddHealth( 100 )
player:AddArmor( 100 )
player:AddAmmo( Ammo.kNails, 300 )
player:AddAmmo( Ammo.kShells, 300 )
player:AddAmmo( Ammo.kRockets, 300 )
player:AddAmmo( Ammo.kCells, 300 )
player:AddAmmo( Ammo.kDetpack, 1 )
player:AddAmmo( Ammo.kManCannon, 1 )
if player:GetTeamId() ~= Team.kYellow then
player:AddAmmo( Ammo.kGren1, 4 )
player:AddAmmo( Ammo.kGren2, 4 )
end
-- AddHudText( player, "escape_door_text", "ESCAPE DOOR:", 0, 32, 4 )
if player:GetTeamId() == Team.kRed then
UpdateObjectiveIcon( player, HUNTED_ENTITY )
if HUNTED_ENTITY ~= nil then
local player_hunted = CastToPlayer( HUNTED_ENTITY )
AddHudText( player, "hunted_location", "Hunted Location: " .. player_hunted:GetLocation(), 4, 44, 0, 1 )
end
elseif player:GetTeamId() == Team.kYellow then
UpdateObjectiveIcon( player, nil )
else
HUNTED_ENTITY = player
UpdateObjectiveIcon( player, GetEntityByName("hunted_escape") )
UpdateTeamObjectiveIcon( GetTeam(Team.kRed), HUNTED_ENTITY )
end
-- if player:GetTeamId() == Team.kRed then
-- BroadCastSoundToPlayer(player, "ff_hunted.i_fight_vampires")
-- elseif player:GetTeamId() == Team.kYellow then
-- BroadCastSoundToPlayer(player, "ff_hunted.werewolf_howling")
-- else
-- BroadCastSoundToPlayer(player, "ff_hunted.i_am_the_werewolf")
-- end
end
-- escape portal entrance
hunted_escape = trigger_ff_script:new({
botgoaltype = Bot.kHuntedEscape,
team = Team.kBlue
})
-- escape touch
function hunted_escape:ontouch( touch_entity )
if IsPlayer( touch_entity ) then
local player = CastToPlayer( touch_entity )
if player:GetTeamId() == Team.kBlue then
player:AddFrags( POINTS_PER_HUNTED_ESCAPE_FOR_HUNTED )
player:AddFortPoints( POINTS_PER_HUNTED_ESCAPE_FOR_HUNTED * 10, "Hunted Escape" )
ConsoleToAll( "The Hunted, " .. player:GetName() .. ", escaped!" )
local team = GetTeam( Team.kBlue )
team:AddScore( POINTS_PER_HUNTED_ESCAPE )
team = GetTeam( Team.kRed )
team:AddScore( POINTS_PER_HUNTED_ESCAPE )
ApplyToAll({ AT.kAllowRespawn, AT.kRespawnPlayers, AT.kRemoveProjectiles, AT.kStopPrimedGrens })
AddSchedule( "hunted_escape_notification", 0.1, hunted_escape_notification )
AddSchedule( "close_escape_doors", 4.0, close_escape_doors )
end
end
end
base_escape_door = trigger_ff_script:new({})
function base_escape_door:onopen()
BroadCastMessage("Escape Door Open!")
BroadCastSound("otherteam.flagstolen")
escape_door.isopen = true
RemoveHudItemFromAll( "escape_door_closed" )
AddHudIconToAll( escape_door.openicon, "escape_door_open", escape_door.hudposx, escape_door.hudposy, escape_door.hudwidth, escape_door.hudheight, escape_door.hudalignx, escape_door.hudaligny )
end
function base_escape_door:onfullyclosed()
BroadCastMessage("Escape Door Closed!")
-- BroadCastSound("otherteam.flagstolen")
escape_door.isopen = false
RemoveHudItemFromAll( "escape_door_open" )
AddHudIconToAll( escape_door.closedicon, "escape_door_closed", escape_door.hudposx, escape_door.hudposy, escape_door.hudwidth, escape_door.hudheight, escape_door.hudalignx, escape_door.hudaligny )
end
escape_door_top = base_escape_door
base_escape_door_button = func_button:new({})
function base_escape_door_button:allowed( allowed_entity )
if IsPlayer( allowed_entity ) then
local player = CastToPlayer( allowed_entity )
if ESCAPE_DOOR_BUTTON_UNLOCKED then
lock_escape_door_button()
AddSchedule( "unlock_escape_door_button", 6.66, unlock_escape_door_button )
return EVENT_ALLOWED
end
end
return EVENT_DISALLOWED
end
-- TODO this doesn't work
function base_escape_door_button:onfailuse( use_entity )
if IsPlayer( use_entity ) then
local player = CastToPlayer( use_entity )
BroadCastMessageToPlayer( player, "#FF_NOTALLOWEDBUTTON" )
end
end
escape_door_button_left = base_escape_door_button
escape_door_button_right = base_escape_door_button
escape_door_button_inside = base_escape_door_button