-- base_training.lua -- contains common useful functionality for maps that include training elements. IncludeScript("base_teamplay") IncludeScript("base_respawnturret") ----------------------------------------------------------------------------- -- helper functions ----------------------------------------------------------------------------- function restoreEntityByName(name) local e = GetInfoScriptByName(name) if e ~= nil then e:Restore() end end ----------------------------------------------------------------------------- -- glass ----------------------------------------------------------------------------- breakable_glass = info_ff_script:new({ }) function breakable_glass:spawn() end function breakable_glass:OnBreak() if self.BotSignal ~= nil then bot.signal(self.BotSignal.."_OnBreak") end end function breakable_glass:ondamage() end ----------------------------------------------------------------------------- -- Class specific trainer spawns ----------------------------------------------------------------------------- training_spawn = info_ff_script:new({ name="Trainer", model="", botteam=Team.kYellow, botclass=0, botgoaltype=Bot.kTrainerSpawn, }) function training_spawn:spawn() info_ff_script.spawn(self) local info = CastToInfoScript(entity) info:SpawnBot(self.name, self.botteam, self.botclass); end scout_trainer = training_spawn:new({ name="Scout Instructor", botclass=Player.kScout, }) sniper_trainer = training_spawn:new({ name="Sniper Instructor", botclass=Player.kSniper, }) soldier_trainer = training_spawn:new({ name="Soldier Instructor", botclass=Player.kSoldier, }) demoman_trainer = training_spawn:new({ name="Demo-man Instructor", botclass=Player.kDemoman, }) medic_trainer = training_spawn:new({ name="Medic Instructor", botclass=Player.kMedic, }) hwguy_trainer = training_spawn:new({ name="HwGuy Instructor", botclass=Player.kHwguy, }) pyro_trainer = training_spawn:new({ name="Pyro Instructor", botclass=Player.kPyro, }) engineer_trainer = training_spawn:new({ name="Engineer Instructor", botclass=Player.kEngineer, }) spy_trainer = training_spawn:new({ name="Spy Instructor", botclass=Player.kSpy, }) civilian_trainer = training_spawn:new({ name="Civilian Instructor", botclass=Player.kCivilian, }) random_target = training_spawn:new({ name="Target", botclass=Player.kRandom, }) ----------------------------------------------------------------------------- -- Training buttons ----------------------------------------------------------------------------- train_button = func_button:new({}) function train_button:allowed() return true end function train_button:ondamage() end function train_button:ontouch() end function train_button:onuse() if self.restoreentity ~= nil then local e = GetInfoScriptByName(self.restoreentity) if e ~= nil then e:Restore() else ConsoleToAll("Could not restore " .. self.restoreentity) end end bot.signal(entity:GetName()) ConsoleToAll(entity:GetName() .. " onuse") end function train_button:onfailuse() ConsoleToAll("button failuse") end ----------------------------------------------------------------------------- -- Fake weapon pickups ----------------------------------------------------------------------------- fakeweapon_spawn = info_ff_script:new({ model = "models/items/backpack/backpack.mdl", weaponname = "ff_weapon_crowbar", ammo = {}, touchsound = "HealthKit.Touch", materializesound = "Item.Materialize", respawntime = 5, removeOnSpawn = false, touchflags = {AllowFlags.kOnlyPlayers,AllowFlags.kBlue, AllowFlags.kRed, AllowFlags.kYellow, AllowFlags.kGreen} }) function fakeweapon_spawn:spawn() -- temporary override --self.model = "models/items/backpack/backpack.mdl" info_ff_script.spawn(self) local info = CastToInfoScript(entity) if self.removeOnSpawn then info:Remove() end end function fakeweapon_spawn:precache( ) PrecacheSound(self.materializesound) PrecacheSound(self.touchsound) --PrecacheModel(self.model) end function fakeweapon_spawn:materialize( ) entity:EmitSound(self.materializesound) end function fakeweapon_spawn:touch( touch_entity ) if IsPlayer( touch_entity ) then local player = CastToPlayer( touch_entity ) local dispensed = 0 if self.weaponclass ~= nil and not player:OwnsWeaponType(self.weaponclass) then player:GiveWeapon(self.weaponclass) dispensed = dispensed + 1 end if self.weaponclass2 ~= nil and not player:OwnsWeaponType(self.weaponclass2) then player:GiveWeapon(self.weaponclass2) dispensed = dispensed + 1 end -- give player some health and armor if self.health ~= nil and self.health ~= 0 then player:AddHealth(self.health) end if self.armor ~= nil and self.armor ~= 0 then player:AddArmor(self.armor) end -- give the player some ammo if self.nails ~= nil and self.nails ~= 0 then player:AddAmmo(Ammo.kNails, self.nails) end if self.shells ~= nil and self.shells ~= 0 then player:AddAmmo(Ammo.kShells, self.shells) end if self.rockets ~= nil and self.rockets ~= 0 then player:AddAmmo(Ammo.kRockets, self.rockets) end if self.cells ~= nil and self.cells ~= 0 then player:AddAmmo(Ammo.kCells, self.cells) end if self.detpacks ~= nil and self.detpacks ~= 0 then player:AddAmmo(Ammo.kDetpack, self.detpacks) end if self.mancannons ~= nil and self.mancannons ~= 0 then player:AddAmmo(Ammo.kManCannon, self.mancannons) end if self.gren1 ~= nil and self.gren1 ~= 0 then player:AddAmmo(Ammo.kGren1, self.gren1) end if self.gren2 ~= nil and self.gren2 ~= 0 then player:AddAmmo(Ammo.kGren2, self.gren2) end if dispensed > 0 then local item = CastToInfoScript(entity); item:EmitSound(self.touchsound) -- Do this or don't call Respawn? --item:SetStartOrigin(item:GetOrigin()) --item:SetStartAngles(item:GetAngles()) --item:Remove() --item:Respawn(self.respawntime); end end end function fakeweapon_spawn:add_weapon( weaponname ) ConsoleToAll("fakeweapon_spawn:add_weapon " .. weaponname) self.weaponclass2 = weaponname end ----------------------------------------------------------------------------- -- Weapon pickup variations. ----------------------------------------------------------------------------- weapon_assaultcannon = fakeweapon_spawn:new({ model = "models/weapons/assaultcannon/w_assaultcannon.mdl", weaponclass = "ff_weapon_assaultcannon", shells = 400 }) weapon_autorifle = fakeweapon_spawn:new({ model = "models/weapons/autorifle/w_autorifle.mdl", weaponclass = "ff_weapon_autorifle", shells = 400 }) weapon_crowbar = fakeweapon_spawn:new({ model = "models/weapons/crowbar/w_crowbar.mdl", weaponclass = "ff_weapon_crowbar", }) weapon_flamethrower = fakeweapon_spawn:new({ model = "models/weapons/flamethrower/w_flamethrower.mdl", weaponclass = "ff_weapon_flamethrower", cells = 400 }) weapon_grenadelauncher = fakeweapon_spawn:new({ model = "models/weapons/grenadelauncher/w_grenadelauncher.mdl", weaponclass = "ff_weapon_grenadelauncher", rockets = 400 }) weapon_incendiarycannon = fakeweapon_spawn:new({ model = "models/weapons/incendiarycannon/w_incendiarycannon.mdl", weaponclass = "ff_weapon_ic", rockets = 400 }) weapon_knife = fakeweapon_spawn:new({ model = "models/weapons/knife/w_knife.mdl", weaponclass = "ff_weapon_knife" }) weapon_medkit = fakeweapon_spawn:new({ model = "models/weapons/medkit/w_medkit.mdl", weaponclass = "ff_weapon_medkit" }) weapon_nailgun = fakeweapon_spawn:new({ model = "models/weapons/nailgun/w_nailgun.mdl", weaponclass = "ff_weapon_nailgun", nails = 400 }) weapon_pipelauncher = fakeweapon_spawn:new({ model = "models/weapons/pipelauncher/w_pipelauncher.mdl", weaponclass = "ff_weapon_pipelauncher", rockets = 400 }) weapon_railgun = fakeweapon_spawn:new({ model = "models/weapons/railgun/w_railgun.mdl", weaponclass = "ff_weapon_railgun", nails = 400 }) weapon_rpg = fakeweapon_spawn:new({ model = "models/weapons/rpg/w_rpg.mdl", weaponclass = "ff_weapon_rpg", rockets = 400 }) weapon_shotgun = fakeweapon_spawn:new({ model = "models/weapons/shotgun/w_shotgun.mdl", weaponclass = "ff_weapon_shotgun", shells = 400 }) weapon_sniperrifle = fakeweapon_spawn:new({ model = "models/weapons/sniperrifle/w_sniperrifle.mdl", weaponclass = "ff_weapon_sniperrifle", nails = 400 }) weapon_spanner = fakeweapon_spawn:new({ model = "models/weapons/spanner/w_spanner.mdl", weaponclass = "ff_weapon_spanner" }) weapon_supernailgun = fakeweapon_spawn:new({ model = "models/weapons/supernailgun/w_supernailgun.mdl", weaponclass = "ff_weapon_supernailgun", nails = 400 }) weapon_supershotgun = fakeweapon_spawn:new({ model = "models/weapons/supershotgun/w_supershotgun.mdl", weaponclass = "ff_weapon_supershotgun", shells = 400 }) weapon_tommygun = fakeweapon_spawn:new({ model = "models/weapons/tommygun/w_tommygun.mdl", weaponclass = "ff_weapon_tommygun", shells = 400 }) weapon_tranq = fakeweapon_spawn:new({ model = "models/weapons/tranq/w_tranq.mdl", weaponclass = "ff_weapon_tranq", nails = 400 }) weapon_umbrella = fakeweapon_spawn:new({ model = "models/weapons/umbrella/w_umbrella.mdl", weaponclass = "ff_weapon_umbrella" }) grenade_pack = fakeweapon_spawn:new({ model = "models/items/backpack/backpack.mdl", gren1 = 4, gren2 = 4 }) weapon_sentry = fakeweapon_spawn:new({ weaponclass = "ff_weapon_deploysentrygun" }) weapon_dispenser = fakeweapon_spawn:new({ weaponclass = "ff_weapon_deploydispenser" }) ----------------------------------------------------------------------------- -- class scanner triggers ----------------------------------------------------------------------------- function perform_player_scan(player, expectedclass, respawnturret) if expectedclass ~= player:GetClass() then BroadCastMessage("Wrong Class") respawnturret.killplayer = true else --BroadCastMessage("Wrong Class") end end scanner_class = trigger_ff_script:new({ }) function scanner_class:ontouch( touch_entity ) if IsPlayer( touch_entity ) then local p = CastToPlayer( touch_entity ) if not p:IsBot() then AddSchedule("perform_player_scan", 0, perform_player_scan, p, self.class, self.turret) end end end function scanner_class:onendtouch() RemoveSchedule("perform_player_scan") end scout_scanner = scanner_class:new({ class=Player.kScout, }) sniper_scanner = scanner_class:new({ class=Player.kSniper, }) soldier_scanner = scanner_class:new({ class=Player.kSoldier, }) demoman_scanner = scanner_class:new({ class=Player.kDemoman, }) medic_scanner = scanner_class:new({ class=Player.kMedic, }) hwguy_scanner = scanner_class:new({ class=Player.kHwguy, }) pyro_scanner = scanner_class:new({ class=Player.kPyro, }) engineer_scanner = scanner_class:new({ class=Player.kEngineer, }) spy_scanner = scanner_class:new({ class=Player.kSpy, }) civilian_scanner = scanner_class:new({ class=Player.kCivilian, }) ----------------------------------------------------------------------------- -- class turrets ----------------------------------------------------------------------------- scanner_turret = respawnturret:new({ team = Team.kGreen }) function scanner_turret:deploydelay( target_entity ) return 0.5 end function scanner_turret:validtarget( target_entity ) --local entity = GetEntity(ent_id) if self.killplayer then local player = CastToPlayer( target_entity ) if player ~= nil and not player:IsBot() then return true end end if not AreTeamsAllied(self.team, target_entity:GetTeamId()) then return true end return false end scout_turret = scanner_turret:new({ class=Player.kScout, }) sniper_turret = scanner_turret:new({ class=Player.kSniper, }) soldier_turret = scanner_turret:new({ class=Player.kSoldier, }) demoman_turret = scanner_turret:new({ class=Player.kDemoman, }) medic_turret = scanner_turret:new({ class=Player.kMedic, }) hwguy_turret = scanner_turret:new({ class=Player.kHwguy, }) pyro_turret = scanner_turret:new({ class=Player.kPyro, }) engineer_turret = scanner_turret:new({ class=Player.kEngineer, }) spy_turret = scanner_turret:new({ class=Player.kSpy, }) civilian_turret = scanner_turret:new({ class=Player.kCivilian, }) ----------------------------------------------------------------------------- -- class holograms ----------------------------------------------------------------------------- base_hologram = info_ff_script:new({ model = "models/player/pyro/pyro.mdl", renderfx = RenderFx.kHologram }) scout_hologram = base_hologram:new({ model = "models/player/scout/scout.mdl" }) sniper_hologram = base_hologram:new({ model = "models/player/sniper/sniper.mdl" }) soldier_hologram = base_hologram:new({ model = "models/player/soldier/soldier.mdl" }) demoman_hologram = base_hologram:new({ model = "models/player/demoman/demoman.mdl" }) medic_hologram = base_hologram:new({ model = "models/player/medic/medic.mdl" }) hwguy_hologram = base_hologram:new({ model = "models/player/hwguy/hwguy.mdl" }) pyro_hologram = base_hologram:new({ model = "models/player/pyro/pyro.mdl" }) engineer_hologram = base_hologram:new({ model = "models/player/engineer/engineer.mdl" }) spy_hologram = base_hologram:new({ model = "models/player/spy/spy.mdl" }) ----------------------------------------------------------------------------- -- Beams ----------------------------------------------------------------------------- base_beam = baseclass:new({ startstate="on",startcolor="0 255 0" }) function base_beam:spawn() if startstate == "on" then OutputEvent( entity:GetName(), "TurnOn" ) else OutputEvent( entity:GetName(), "TurnOff" ) end if startstate ~= nil then OutputEvent( entity:GetName(), "Color", startcolor ) end end function base_beam:turnon() OutputEvent( entity:GetName(), "TurnOn" ) end function base_beam:turnoff() OutputEvent( entity:GetName(), "TurnOff" ) end function base_beam:setcolor(newcolor) if newcolor ~= nil then OutputEvent( entity:GetName(), "Color", newcolor ) end end ----------------------------------------------------------------------------- -- training room triggers ----------------------------------------------------------------------------- training_room = trigger_ff_script:new({ }) function training_room:allowed() -- if self.restrictClass ~= nil then -- entity:EmitSound(self.speakOnceOnEnter) -- end return EVENT_ALLOWED end function training_room:ontrigger() --ConsoleToAll("training_room:ontrigger() ") end function training_room:ontouch( touch_entity ) if IsPlayer( touch_entity ) then local p = CastToPlayer( touch_entity ) if not p:IsBot() then bot.signal(entity:GetName()) end end ------------------ ConsoleToAll(entity:GetName() .. " ontouch") ------------------ end function training_room:onendtouch() ------------------ ConsoleToAll(entity:GetName() .. " onendtouch") ------------------ end function training_room:onfailtouch() end function training_room:onexplode() return EVENT_ALLOWED end function training_room:onbuild() return EVENT_ALLOWED end function training_room:onfailuse() end function training_room:onuse() end function training_room:onactive() end function training_room:oninactive() end function training_room:onremoved() end function training_room:onrestored() end function training_room:spawn() end ----------------------------------------------------------------------------- -- current training status ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- -- bot helper functions ----------------------------------------------------------------------------- function restore_entity(entname) local info = GetInfoScriptByName(entname) if info ~= nil then info:Restore() end end function remove_entity(entname) local info = GetInfoScriptByName(entname) if info ~= nil then info:Remove() end end function update_grenadecount(entname, g1, g2) local info = GetInfoScriptByName(entname) if info ~= nil then info.gren1 = tonumber(g1) info.gren2 = tonumber(g2) end end function vec_tostring(v) return string.format("%f %f %f", v.x, v.y, v.z) end bot = {} bot.spawnAtEntity = function(spawnent, name, team, class) local info = GetInfoScriptByName(spawnent) if info ~= nil then info:SpawnBot(name, team, class); end end bot.sendMsg = function(botname, msg, d1, d2, d3) local p = GetPlayerByName(botname) if p ~= nil then p:SendBotMessage(msg, d1, d2, d3) else ConsoleToAll("bot.sendMsg: player not found: " .. botname) end end bot.signal = function(signalname) SendBotSignal(signalname) end bot.moveTo = function(botname, targetentity) local e = GetEntityByName(targetentity) if e ~= nil then local epos = e:GetOrigin() local eface = e:GetAbsFacing() -- convert epos to string bot.sendMsg(botname, "run_to", vec_tostring(epos), vec_tostring(eface)) end end bot.setIdlePoint = function(botname, targetentity) local e = GetEntityByName(targetentity) if e ~= nil then local epos = e:GetOrigin() local eface = e:GetAbsFacing() -- convert epos to string bot.sendMsg(botname, "set_idle_position", vec_tostring(epos), vec_tostring(eface)) end end bot.leaveGame = function(botname) bot.sendMsg(botname, "leave_game") end -- teleportTo(botname, targetEntName) -- local p = GetPlayerByName(botname) -- local e = GetEntityByName(targetentity) -- if p ~= nil and e ~= nil then -- p:SetOrigin(e:GetOrigin()) -- p:SetAngles(e:GetAngles()) -- else -- ConsoleToAll("teleportTo: player not found: " .. botname) -- end -- end function player_giveweapon(weaponname, as) local c = Collection() c:GetByFilter({ CF.kHumanPlayers }) for temp in c.items do local player = CastToPlayer( temp ) local autoselect = false if as == "true" then autoselect = true end player:GiveWeapon(weaponname, autoselect) end end function player_giveammo(ammoname, amount) local c = Collection() c:GetByFilter({ CF.kHumanPlayers }) for temp in c.items do local player = CastToPlayer( temp ) if ammoname == "nails" then player:AddAmmo(Ammo.kNails, tonumber(amount)) end if ammoname == "shells" then player:AddAmmo(Ammo.kShells, tonumber(amount)) end if ammoname == "rockets" then player:AddAmmo(Ammo.kRockets, tonumber(amount)) end if ammoname == "cells" then player:AddAmmo(Ammo.kCells, tonumber(amount)) end if ammoname == "detpack" then player:AddAmmo(Ammo.kDetpack, tonumber(amount)) end if ammoname == "mancannon" then player:AddAmmo(Ammo.kManCannon, tonumber(amount)) end if ammoname == "gren1" then player:AddAmmo(Ammo.kGren1, tonumber(amount)) end if ammoname == "gren2" then player:AddAmmo(Ammo.kGren2, tonumber(amount)) end end end function player_removeweapon(weaponname) local c = Collection() c:GetByFilter({ CF.kHumanPlayers }) for temp in c.items do local player = CastToPlayer( temp ) player:RemoveWeapon(weaponname) end end function player_givedetpack() local c = Collection() c:GetByFilter({ CF.kHumanPlayers }) for temp in c.items do local player = CastToPlayer( temp ) player:AddAmmo(Ammo.kDetpack, 1) end end function player_givemancannon() local c = Collection() c:GetByFilter({ CF.kHumanPlayers }) for temp in c.items do local player = CastToPlayer( temp ) player:AddAmmo(Ammo.kManCannon, 1) end end function player_givegren1() local c = Collection() c:GetByFilter({ CF.kHumanPlayers }) for temp in c.items do local player = CastToPlayer( temp ) player:AddAmmo(Ammo.kGren1, 4) end end function player_givegren2() local c = Collection() c:GetByFilter({ CF.kHumanPlayers }) for temp in c.items do local player = CastToPlayer( temp ) player:AddAmmo(Ammo.kGren2, 4) end end function player_removehealth(playername, amt) p = GetPlayerByName(playername) if p ~= nil then p:AddHealth(-tonumber(amt)) else ConsoleToAll("player_removehealth: Unable to find " .. playername) end end function player_removearmor(playername, amt) p = GetPlayerByName(playername) if p ~= nil then p:RemoveArmor(tonumber(amt)) else ConsoleToAll("player_removehealth: Unable to find " .. playername) end end function player_forcerespawn(playername, amt) p = GetPlayerByName(playername) if p ~= nil then ApplyToPlayer(p, { AT.kRespawnPlayers }) else ConsoleToAll("player_forcerespawn: Unable to find " .. playername) end end function broadcast_message(message) BroadCastMessage(message) end function training_intro(classname) if classname == "Scout" then BroadCastSound("training.fem_scout_ovr") elseif classname == "Sniper" then BroadCastSound("training.fem_sniper_ovr") elseif classname == "Soldier" then BroadCastSound("training.fem_soldier_ovr") elseif classname == "Demoman" then BroadCastSound("training.fem_demo_ovr") elseif classname == "Medic" then BroadCastSound("training.fem_medic_ovr") elseif classname == "HwGuy" then BroadCastSound("training.fem_hwguy_ovr") elseif classname == "Pyro" then BroadCastSound("training.fem_pyro_ovr") elseif classname == "Spy" then BroadCastSound("training.fem_spy_ovr") elseif classname == "Engineer" then BroadCastSound("training.fem_engy_ovr") end end function section_complete(sectionname, room) BroadCastSound("training.section_complete") end function training_complete(classname) if classname == "Scout" then BroadCastSound("training.fem_scout_comp") elseif classname == "Sniper" then BroadCastSound("training.fem_sniper_comp") elseif classname == "Soldier" then BroadCastSound("training.fem_soldier_comp") elseif classname == "Demoman" then BroadCastSound("training.fem_demo_comp") elseif classname == "Medic" then BroadCastSound("training.fem_medic_comp") elseif classname == "HwGuy" then BroadCastSound("training.fem_hwguy_comp") elseif classname == "Pyro" then BroadCastSound("training.fem_pyro_comp") elseif classname == "Spy" then BroadCastSound("training.fem_spy_comp") elseif classname == "Engineer" then BroadCastSound("training.fem_engy_comp") end end function training_classname(classId) if classId == Player.kScout then return "Scout" end if classId == Player.kSniper then return "Sniper" end if classId == Player.kSoldier then return "Soldier" end if classId == Player.kDemoman then return "Demoman" end if classId == Player.kMedic then return "Medic" end if classId == Player.kHwguy then return "HwGuy" end if classId == Player.kPyro then return "Pyro" end if classId == Player.kSpy then return "Spy" end if classId == Player.kEngineer then return "Engineer" end if classId == Player.kCivilian then return "Civilian" end end