-- 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