Adjust paths to be lowercase (part 2)

Even though git internally knows the difference between upper and lower case, all of it's commands rely on the file system to do so as well. This results in incorrect behavior when renaming A to a for example, as the source and destination is identical on the file system according to git. Windows does support such renames, but git seems to shit itself.
This commit is contained in:
Michael Fabian 'Xaymar' Dirks
2017-11-24 01:58:54 +01:00
parent e8454d4d27
commit 6ad75df85d
45 changed files with 0 additions and 0 deletions
+7
View File
@@ -0,0 +1,7 @@
{
"title" : "Prop Hunt Extended",
"type" : "gamemode",
"tags" : [ "fun" ],
"ignore" : [
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1003 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

@@ -0,0 +1,8 @@
"TableToKeyValues"
{
"1" "models/props/cs_assault/dollar.mdl"
"2" "models/props/cs_assault/money.mdl"
"3" "models/props/cs_office/snowman_arm.mdl"
"4" "models/props_junk/garbage_plasticbottle001a.mdl"
"5" "models/props/cs_office/projector_remote.mdl"
}
@@ -0,0 +1,8 @@
"TableToKeyValues"
{
"TAUNT_DELAY" "0.1"
"ROUNDS_PER_MAP" "20"
"ROUND_TIME" "240"
"SWAP_TEAM_EVERY_ROUND" "1"
"GAME_TIME" "20"
}
@@ -0,0 +1,26 @@
"TableToKeyValues"
{
"1" "bot/aw_hell.wav"
"2" "bot/aww_man.wav"
"3" "bot/anyone_see_anything.wav"
"4" "bot/anyone_see_them.wav"
"5" "bot/come_out_and_fight_like_a_man.wav"
"6" "bot/come_out_wherever_you_are.wav"
"7" "bot/he_got_away.wav"
"8" "bot/he_got_away2.wav"
"9" "bot/i_dont_know_where_he_went.wav"
"10" "bot/i_got_nothing.wav"
"11" "bot/nothing_happening_over_here.wav"
"12" "bot/nothing_here.wav"
"13" "bot/nothing_moving_over_here.wav"
"14" "bot/thats_not_good.wav"
"15" "bot/theres_too_many.wav"
"16" "bot/theres_too_many_of_them.wav"
"17" "bot/theyre_all_over_the_place2.wav"
"18" "bot/theyre_everywhere2.wav"
"19" "bot/too_many2.wav"
"20" "bot/what_happened.wav"
"21" "bot/what_have_you_done.wav"
"22" "bot/where_are_they.wav"
"23" "bot/where_are_you_hiding.wav"
}
@@ -0,0 +1,20 @@
"TableToKeyValues"
{
"1" "bot/a_bunch_of_them.wav"
"2" "bot/come_out_and_fight_like_a_man.wav"
"3" "bot/come_out_wherever_you_are.wav"
"4" "bot/come_to_papa.wav"
"5" "bot/dont_worry_hell_get_it.wav"
"6" "bot/hang_on_i_heard_something.wav"
"7" "bot/hang_on_im_coming.wav"
"8" "bot/i_dont_think_so.wav"
"9" "bot/i_have_the_hostages.wav"
"10" "bot/i_see_our_target.wav"
"11" "bot/im_waiting_here.wav"
"12" "bot/keeping_an_eye_on_the_hostages.wav"
"13" "bot/nnno_sir.wav"
"14" "bot/spotted_the_delivery_boy.wav"
"15" "bot/target_acquired.wav"
"16" "bot/target_spotted.wav"
"17" "bot/you_heard_the_man_lets_go.wav"
}
@@ -0,0 +1,131 @@
"TableToKeyValues"
{
"1" "ambient/alarms/apc_alarm_pass1.wav"
"2" "ambient/alarms/manhack_alert_pass1.wav"
"3" "ambient/alarms/razortrain_horn1.wav"
"4" "ambient/alarms/scanner_alert_pass1.wav"
"5" "ambient/alarms/train_horn2.wav"
"6" "ambient/alarms/train_horn_distant1.wav"
"7" "ambient/alarms/warningbell1.wav"
"8" "ambient/energy/whiteflash.wav"
"9" "ambient/intro/alyxremove.wav"
"10" "ambient/intro/logosfx.wav"
"11" "ambient/levels/launch/1stfiringwarning.wav"
"12" "ambient/levels/launch/rockettakeoffblast.wav"
"13" "ambient/misc/ambulance1.wav"
"14" "ambient/misc/carhonk1.wav"
"15" "ambient/misc/carhonk2.wav"
"16" "ambient/misc/carhonk3.wav"
"17" "ambient/outro/gunshipcrash.wav"
"18" "ambient/3dmeagle.wav"
"19" "beams/beamstart5.wav"
"20" "buttons/bell1.wav"
"21" "buttons/weapon_cant_buy.wav"
"22" "common/bass.wav"
"23" "common/bugreporter_failed.wav"
"24" "common/warning.wav"
"25" "doors/door_squeek1.wav"
"26" "friends/friend_join.wav"
"27" "friends/friend_online.wav"
"28" "friends/message.wav"
"29" "hostage/hunuse/comeback.wav"
"30" "hostage/hunuse/dontleaveme.wav"
"31" "hostage/hunuse/yeahillstay.wav"
"32" "items/gift_drop.wav"
"33" "music/radio1.mp3"
"34" "phx/eggcrack.wav"
"35" "plats/elevbell1.wav"
"36" "player/headshot1.wav"
"37" "player/headshot2.wav"
"38" "player/sprayer.wav"
"39" "radio/enemydown.wav"
"40" "radio/go.wav"
"41" "radio/locknload.wav"
"42" "radio/negative.wav"
"43" "radio/rounddraw.wav"
"44" "radio/takepoint.wav"
"45" "resource/warning.wav"
"46" "ui/achievement_earned.wav"
"47" "ui/freeze_cam.wav"
"48" "vehicles/junker/radar_ping_friendly1.wav"
"49" "weapons/c4/c4_beep1.wav"
"50" "weapons/c4/c4_click.wav"
"51" "weapons/awp/awp1.wav"
"52" "vo/canals/female01/gunboat_giveemhell.wav"
"53" "vo/canals/female01/gunboat_justintime.wav"
"54" "vo/canals/female01/stn6_incoming.wav"
"55" "vo/canals/male01/gunboat_giveemhell.wav"
"56" "vo/canals/male01/gunboat_justintime.wav"
"57" "vo/canals/male01/stn6_incoming.wav"
"58" "vo/canals/al_radio_stn6.wav"
"59" "vo/canals/arrest_getgoing.wav"
"60" "vo/canals/arrest_helpme.wav"
"61" "vo/canals/arrest_lookingforyou.wav"
"62" "vo/canals/boxcar_lethimhelp.wav"
"63" "vo/canals/matt_closecall.wav"
"64" "vo/canals/premassacre.wav"
"65" "vo/ravenholm/aimforhead.wav"
"66" "vo/ravenholm/bucket_patience.wav"
"67" "vo/ravenholm/madlaugh01.wav"
"68" "vo/ravenholm/madlaugh02.wav"
"69" "vo/ravenholm/madlaugh03.wav"
"70" "vo/ravenholm/madlaugh04.wav"
"71" "weapons/strider_buster/ol12_stickybombcreator.wav"
"72" "weapons/c4/c4_explode1.wav"
"73" "weapons/357/357_fire2.wav"
"74" "weapons/357/357_fire3.wav"
"75" "weapons/scout/scout_fire-1.wav"
"76" "weapons/smokegrenade/sg_explode.wav"
"77" "weapons/grenade_launcher1.wav"
"78" "weapons/explode3.wav"
"79" "weapons/underwater_explode3.wav"
"80" "items/nvg_on.wav"
"81" "hostage/huse/letsdoit.wav"
"82" "hostage/huse/illfollow.wav"
"83" "hostage/huse/getouttahere.wav"
"84" "doors/door_screen_move1.wav"
"85" "doors/heavy_metal_stop1.wav"
"86" "doors/default_move.wav"
"87" "common/stuck2.wav"
"88" "ambient/water_splash1.wav"
"89" "ambient/water_splash2.wav"
"90" "ambient/water_splash3.wav"
"91" "ambient/weather/thunder1.wav"
"92" "ambient/weather/thunder2.wav"
"93" "ambient/weather/thunder3.wav"
"94" "ambient/weather/thunder4.wav"
"95" "ambient/weather/thunder5.wav"
"96" "ambient/weather/thunder6.wav"
"97" "ambient/outro/thunder7.wav"
"98" "ambient/voices/crying_loop1.wav"
"99" "ambient/voices/playground_memory.wav"
"100" "ambient/voices/f_scream1.wav"
"101" "ambient/voices/m_scream1.wav"
"102" "ambient/voices/cough1.wav"
"103" "ambient/voices/cough2.wav"
"104" "ambient/voices/cough3.wav"
"105" "ambient/voices/cough4.wav"
"106" "ambient/overhead/plane1.wav"
"107" "ambient/overhead/plane2.wav"
"108" "ambient/overhead/plane3.wav"
"109" "ambient/overhead/hel1.wav"
"110" "ambient/overhead/hel2.wav"
"111" "ambient/misc/truck_backup1.wav"
"112" "ambient/misc/truck_drive1.wav"
"113" "ambient/misc/truck_drive2.wav"
"114" "ambient/machines/pneumatic_drill_1.wav"
"115" "ambient/machines/pneumatic_drill_2.wav"
"116" "ambient/machines/pneumatic_drill_3.wav"
"117" "ambient/machines/pneumatic_drill_4.wav"
"118" "ambient/machines/station_train_squeel.wav"
"119" "ambient/machines/ticktock.wav"
"120" "ambient/creatures/teddy.wav"
"121" "ambient/creatures/town_child_scream1.wav"
"122" "ambient/creatures/town_moan1.wav"
"123" "ambient/creatures/town_muffled_cry1.wav"
"124" "ambient/creatures/town_scared_breathing1.wav"
"125" "ambient/creatures/town_scared_breathing2.wav"
"126" "ambient/creatures/town_scared_sob1.wav"
"127" "ambient/creatures/town_scared_sob2.wav"
"128" "ambient/creatures/town_zombie_call1.wav"
}
@@ -0,0 +1,52 @@
"TableToKeyValues"
{
"1" "bot/and_thats_how_its_done.wav"
"2" "bot/come_to_papa.wav"
"3" "bot/do_not_mess_with_me.wav"
"4" "bot/dropped_him.wav"
"5" "bot/enemy_down.wav"
"6" "bot/enemy_down2.wav"
"7" "bot/good_job_team.wav"
"8" "bot/got_him.wav"
"9" "bot/hes_broken.wav"
"10" "bot/hes_dead.wav"
"11" "bot/hes_done.wav"
"12" "bot/hes_down.wav"
"13" "bot/its_a_party.wav"
"14" "bot/i_am_dangerous.wav"
"15" "bot/i_am_on_fire.wav"
"16" "bot/i_got_more_where_that_came_from.wav"
"17" "bot/i_wasnt_worried_for_a_minute.wav"
"18" "bot/killed_him.wav"
"19" "bot/look_out_brag.wav"
"20" "bot/made_him_cry.wav"
"21" "bot/oh_yea.wav"
"22" "bot/oh_yea2.wav"
"23" "bot/owned.wav"
"24" "bot/ruined_his_day.wav"
"25" "bot/tag_them_and_bag_them.wav"
"26" "bot/thats_the_way_this_is_done.wav"
"27" "bot/that_was_a_close_one.wav"
"28" "bot/that_was_it.wav"
"29" "bot/that_was_the_last_guy.wav"
"30" "bot/that_was_the_last_one.wav"
"31" "bot/they_never_knew_what_hit_them.wav"
"32" "bot/they_will_not_escape.wav"
"33" "bot/they_wont_get_away.wav"
"34" "bot/they_wont_get_away2.wav"
"35" "bot/this_is_my_house.wav"
"36" "bot/took_him_down.wav"
"37" "bot/took_him_out.wav"
"38" "bot/took_him_out2.wav"
"39" "bot/wasted_him.wav"
"40" "bot/way_to_be_team.wav"
"41" "bot/well_done.wav"
"42" "bot/we_owned_them.wav"
"43" "bot/whew_that_was_close.wav"
"44" "bot/whoo.wav"
"45" "bot/whoo2.wav"
"46" "bot/whos_the_man.wav"
"47" "bot/who_wants_some_more.wav"
"48" "bot/yesss.wav"
"49" "bot/yesss2.wav"
}
@@ -0,0 +1,7 @@
-- Include needed files
include("shared.lua")
-- Draw entity model.
function ENT:Draw()
self:DrawModel()
end
@@ -0,0 +1,8 @@
--Thanks to Blasteh for gmod update the fix and nifnat for spectate fix!
-- Send required files to client
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("shared.lua")
-- Include needed files
include("shared.lua")
@@ -0,0 +1,37 @@
-- Entity information
ENT.Type = "anim"
ENT.Base = "base_anim"
-- Initialize
function ENT:Initialize()
self:SetModel("models/Kleiner.mdl")
self:SetCollisionGroup(COLLISION_GROUP_PLAYER)
self:SetSolid(SOLID_OBB)
self:SetRenderMode(RENDERMODE_TRANSALPHA)
self:SetColor(Color(255,255,255,255))
end
-- Update position
function ENT:Think()
local hullOBBMin = self:OBBMins()
local hullOBBMax = self:OBBMaxs()
local hullOBB = hullOBBMax - hullOBBMin
local pos = -Vector(0, 0, hullOBBMin.z)
self:SetPos(self.Owner:GetPos() + pos)
self:SetVelocity(self:GetOwner():GetVelocity())
-- Angles
if (self.Owner:GetNWBool("PropRotation")) then
self:ApplyRotation(self.Owner:EyeAngles())
end
end
function ENT:ApplyRotation(ang)
if !(GAMEMODE.Config.Hider:AllowFullRotation()) then
ang.p = 0
ang.r = 0
end
self:SetAngles(ang)
end
@@ -0,0 +1,251 @@
-- SWEP Information
SWEP.Author = "Michael 'Xaymar' Dirks"
SWEP.Contact = "info@project-kube.de"
SWEP.PrintName = "PH Submachine Gun"
SWEP.Purpose = "More accurate SMG for Prop Hunt."
SWEP.Instructions = "Fire away! Alternative fire to fire a grenade."
SWEP.Category = "Prop Hunt Weapons"
-- Weapon Information
SWEP.Weight = 5
SWEP.AutoSwitchTo = false
SWEP.AutoSwitchFrom = false
SWEP.Slot = 2
SWEP.SlotPos = 1
SWEP.DrawAmmo = true
SWEP.DrawCrosshair = true
-- Weapon is spawnable for everyone, not just administrators.
SWEP.Spawnable = true
SWEP.AdminSpawnable = true
-- Model
SWEP.ViewModel = "models/weapons/c_smg1.mdl"
SWEP.WorldModel = "models/weapons/w_smg1.mdl"
SWEP.UseHands = true
-- Primary Ammunition: SMG
SWEP.Primary.ClipSize = 45
SWEP.Primary.DefaultClip = 45
SWEP.Primary.Automatic = true
SWEP.Primary.Ammo = "SMG1"
SWEP.Primary.Damage = 5
SWEP.Primary.RefireTime = 0.1
-- Secondary Ammunition: SMG Grenades
SWEP.Secondary.ClipSize = 1
SWEP.Secondary.DefaultClip = 0
SWEP.Secondary.Automatic = false
SWEP.Secondary.Ammo = "SMG1_Grenade"
SWEP.Secondary.Damage = 100
SWEP.Secondary.RefireTime = 1.0
-- Recoil
SWEP.Recoil = {}
SWEP.Recoil.SingleFire = 0.2
SWEP.Recoil.BurstFire = 1.0
SWEP.Recoil.SecondaryFire = 8.0
-- Accuracy
SWEP.Accuracy = {}
SWEP.Accuracy.Primary = {}
SWEP.Accuracy.Primary.Min = 0.975
SWEP.Accuracy.Primary.Max = 1.00
SWEP.Accuracy.Primary.Reduction = 0.005
SWEP.Accuracy.Primary.Recovery = 0.0025
SWEP.Accuracy.Primary.Delay = 0.1
SWEP.Accuracy.Secondary = {}
SWEP.Accuracy.Secondary.Min = 1.00
SWEP.Accuracy.Secondary.Max = 1.00
SWEP.Accuracy.Secondary.Reduction = 0.00
SWEP.Accuracy.Secondary.Recovery = 0.00
SWEP.Accuracy.Secondary.Delay = 0.00
-- Sounds
SWEP.Sound = {}
SWEP.Sound.SwitchSingle = "weapons/smg1/switch_single.wav"
SWEP.Sound.SwitchBurst = "weapons/smg1/switch_burst.wav"
SWEP.Sound.SingleFire = "weapons/smg1/smg1_fire1.wav"
SWEP.Sound.BurstFire = "weapons/smg1/smg1_fireburst1.wav"
SWEP.Sound.SecondaryFire = "weapons/ar2/ar2_altfire.wav"
SWEP.Sound.Reload = "weapons/smg1/smg1_reload.wav"
SWEP.Sound.NoPrimaryAmmo = "weapons/pistol/pistol_empty.wav"
SWEP.Sound.NoSecondaryAmmo = "weapons/pistol/pistol_empty.wav"
-- Initialization
function SWEP:Initialize()
-- Set holding type to smg.
self:SetHoldType("smg");
-- Precache sounds for lagless experience.
for i,v in ipairs(self.Sound) do
util.PrecacheSound(v)
end
-- Initialize default values.
self.BurstFire = false
self:SetNWBool("BurstFire", false)
self.LastReload = CurTime()
self.PrimaryAccuracy = self.Accuracy.Primary.Max
self.LastPrimaryAttack = CurTime()
self.SecondaryAccuracy = self.Accuracy.Secondary.Max
self.LastSecondaryAttack = CurTime()
end
-- Primary Attack
function SWEP:CanPrimaryAttack()
-- Check if there is ammo in the clip.
if (self:Clip1() <= 0) then
-- If not, check if there's ammo available.
if (self:Ammo1() > 0) then
-- If yes, reload and wait for weapon to be ready again.
self.Weapon:EmitSound(self.Sound.NoPrimaryAmmo)
self:Reload()
return false
end
-- If no, emit empty sound for primary fire.
self.Weapon:EmitSound(self.Sound.NoPrimaryAmmo)
self:SetNextPrimaryFire(CurTime() + 0.1)
return false
end
-- Otherwise, return true.
return true
end
function SWEP:PrimaryAttack()
-- Can't fire without Ammo
if (!self:CanPrimaryAttack()) then return end
if (self:GetNWBool("BurstFire") == false) then
-- Single Mode: fire and take one bullet from the clip.
self:TakePrimaryAmmo(1)
self:SetNextPrimaryFire( CurTime() + self.Primary.RefireTime )
self.Weapon:EmitSound(self.Sound.SingleFire)
-- Apply recoil
if IsValid(self.Owner) then
self.Owner:ViewPunch( Angle(-1, 0, 0) * self.Recoil.SingleFire * (1 + (1 - self.PrimaryAccuracy)) )
self:ShootBullet(self.Primary.Damage, 1, 1.0 - self.PrimaryAccuracy)
end
-- Decrease accuracy
self.PrimaryAccuracy = math.Clamp(self.PrimaryAccuracy - self.Accuracy.Primary.Reduction, self.Accuracy.Primary.Min, self.Accuracy.Primary.Max)
else
-- Burst Mode: fire and take up to three bullets from the clip
local bulletCount = math.Clamp(self:Clip1(), 1, 3)
self:TakePrimaryAmmo(bulletCount)
self:SetNextPrimaryFire( CurTime() + self.Primary.RefireTime * bulletCount )
self.Weapon:EmitSound(self.Sound.BurstFire)
for i = 1, bulletCount do
if (IsValid(self)) && (IsValid(self.Owner)) then
-- Apply recoil & shoot
self.Owner:ViewPunch(Angle(-1, 0, 0) * self.Recoil.BurstFire * (1 + (1 - self.PrimaryAccuracy)))
self:ShootBullet(self.Primary.Damage, 1, 1.0 - self.PrimaryAccuracy)
-- Decrease accuracy
self.PrimaryAccuracy = math.Clamp(self.PrimaryAccuracy - self.Accuracy.Primary.Reduction, self.Accuracy.Primary.Min, self.Accuracy.Primary.Max)
end
end
end
-- Set Animation and attack time.
self:SendWeaponAnim(ACT_VM_PRIMARYATTACK)
self.LastPrimaryAttack = CurTime()
return
end
-- Secondary Attack
function SWEP:CanSecondaryAttack()
if (self:Clip2() == 0) then
if (self:Ammo2() == 0) then
self.Weapon:EmitSound(self.Sound.NoSecondaryAmmo)
self:SetNextSecondaryFire( CurTime() + 1.0 )
return false
else
self:SetClip2( 1 )
end
end
return true
end
function SWEP:SecondaryAttack()
-- Can't fire without Ammo
if (!self:CanSecondaryAttack()) then return end
self.Owner:SetAmmo( self.Owner:GetAmmoCount( self:GetSecondaryAmmoType() ) - 1, self:GetSecondaryAmmoType() )
-- Emit a sound.
self.Weapon:EmitSound(self.Sound.SecondaryFire)
self:SetNextSecondaryFire( CurTime() + self.Secondary.RefireTime )
self:TakeSecondaryAmmo(1)
-- Create grenade
if SERVER then
local grenade = ents.Create("grenade_ar2")
if (!IsValid(grenade)) then return end
grenade:SetPos( self.Owner:GetShootPos() + self.Owner:GetAimVector() * 30 )
grenade:SetVelocity( self.Owner:GetAimVector() * 1000 )
grenade:SetAngles( self.Owner:GetAngles() )
grenade:SetOwner( self.Owner )
grenade:Spawn()
grenade:SetPhysicsAttacker( self.Owner, 60 )
end
-- Set Animation and attack time.
self:SendWeaponAnim(ACT_VM_SECONDARYATTACK)
self.LastSecondaryAttack = CurTime()
return
end
-- Reload: Combination of reloading and switching fire type.
function SWEP:Reload()
-- Fix reload for secondary
if (self:Clip2() == 0) then
if (self:Ammo2() > 0) then
self:SetClip2( 1 )
end
end
if self:DefaultReload(ACT_VM_RELOAD) then
self.Weapon:EmitSound(self.Sound.Reload)
else
if (self.LastReload) && ((CurTime() - self.LastReload) > 1) then
self.BurstFire = !self:GetNWBool("BurstFire")
self.LastReload = CurTime()
if (self.BurstFire) then
self.Weapon:EmitSound(self.Sound.SwitchBurst)
if SERVER then self:GetOwner():ChatPrint("Weapon: BurstFire is now on.") end
else
self.Weapon:EmitSound(self.Sound.SwitchSingle)
if SERVER then self:GetOwner():ChatPrint("Weapon: BurstFire is now off.") end
end
if SERVER then self:SetNWBool("BurstFire", self.BurstFire) end
end
end
return
end
function SWEP:ShootEffects()
end
-- Think: Restore accuracy over time.
function SWEP:Think()
local ThinkTime = CurTime()
if (ThinkTime >= (self.LastPrimaryAttack + self.Accuracy.Primary.Delay)) then
self.PrimaryAccuracy = math.Clamp(self.PrimaryAccuracy + self.Accuracy.Primary.Recovery, self.Accuracy.Primary.Min, self.Accuracy.Primary.Max)
end
if (ThinkTime >= (self.LastSecondaryAttack + self.Accuracy.Secondary.Delay)) then
self.SecondaryAccuracy = math.Clamp(self.SecondaryAccuracy + self.Accuracy.Secondary.Recovery, self.Accuracy.Secondary.Min, self.Accuracy.Secondary.Max)
end
end
@@ -0,0 +1,259 @@
-- Sounds played by members of the losing team at the end of the round.
LOSS_SOUNDS = {
"bot/aw_hell.wav",
"bot/aww_man.wav",
"bot/anyone_see_anything.wav",
"bot/anyone_see_them.wav",
"bot/come_out_and_fight_like_a_man.wav",
"bot/come_out_wherever_you_are.wav",
"bot/he_got_away.wav",
"bot/he_got_away2.wav",
"bot/i_dont_know_where_he_went.wav",
"bot/i_got_nothing.wav",
"bot/nothing_happening_over_here.wav",
"bot/nothing_here.wav",
"bot/nothing_moving_over_here.wav",
"bot/thats_not_good.wav",
"bot/theres_too_many.wav",
"bot/theres_too_many_of_them.wav",
"bot/theyre_all_over_the_place2.wav",
"bot/theyre_everywhere2.wav",
"bot/too_many2.wav",
"bot/what_happened.wav",
"bot/what_have_you_done.wav",
"bot/where_are_they.wav",
"bot/where_are_you_hiding.wav"
}
-- Sounds played by members of the winning team at the end of the round.
VICTORY_SOUNDS = {
"bot/and_thats_how_its_done.wav",
"bot/come_to_papa.wav",
"bot/do_not_mess_with_me.wav",
"bot/dropped_him.wav",
"bot/enemy_down.wav",
"bot/enemy_down2.wav",
"bot/good_job_team.wav",
"bot/got_him.wav",
"bot/hes_broken.wav",
"bot/hes_dead.wav",
"bot/hes_done.wav",
"bot/hes_down.wav",
"bot/its_a_party.wav",
"bot/i_am_dangerous.wav",
"bot/i_am_on_fire.wav",
"bot/i_got_more_where_that_came_from.wav",
"bot/i_wasnt_worried_for_a_minute.wav",
"bot/killed_him.wav",
"bot/look_out_brag.wav",
"bot/made_him_cry.wav",
"bot/oh_yea.wav",
"bot/oh_yea2.wav",
"bot/owned.wav",
"bot/ruined_his_day.wav",
"bot/tag_them_and_bag_them.wav",
"bot/thats_the_way_this_is_done.wav",
"bot/that_was_a_close_one.wav",
"bot/that_was_it.wav",
"bot/that_was_the_last_guy.wav",
"bot/that_was_the_last_one.wav",
"bot/they_never_knew_what_hit_them.wav",
"bot/they_will_not_escape.wav",
"bot/they_wont_get_away.wav",
"bot/they_wont_get_away2.wav",
"bot/this_is_my_house.wav",
"bot/took_him_down.wav",
"bot/took_him_out.wav",
"bot/took_him_out2.wav",
"bot/wasted_him.wav",
"bot/way_to_be_team.wav",
"bot/well_done.wav",
"bot/we_owned_them.wav",
"bot/whew_that_was_close.wav",
"bot/whoo.wav",
"bot/whoo2.wav",
"bot/whos_the_man.wav",
"bot/who_wants_some_more.wav",
"bot/yesss.wav",
"bot/yesss2.wav"
}
-- Taunts played when Hunters hit their Spare1 binding.
HUNTER_TAUNTS = {
"bot/a_bunch_of_them.wav",
"bot/come_out_and_fight_like_a_man.wav",
"bot/come_out_wherever_you_are.wav",
"bot/come_to_papa.wav",
"bot/dont_worry_hell_get_it.wav",
"bot/hang_on_i_heard_something.wav",
"bot/hang_on_im_coming.wav",
"bot/i_dont_think_so.wav",
"bot/i_have_the_hostages.wav",
"bot/i_see_our_target.wav",
"bot/im_waiting_here.wav",
"bot/keeping_an_eye_on_the_hostages.wav",
"bot/nnno_sir.wav",
"bot/spotted_the_delivery_boy.wav",
"bot/target_acquired.wav",
"bot/target_spotted.wav",
"bot/you_heard_the_man_lets_go.wav"
}
-- Taunts played when Props hit their Spare1 binding.
PROP_TAUNTS = {
-- "ambient/alarms/apc_alarm_loop1.wav",
"ambient/alarms/apc_alarm_pass1.wav",
-- "ambient/alarms/citadel_alert_loop2.wav",
-- "ambient/alarms/city_firebell_loop1.wav",
-- "ambient/alarms/city_siren_loop2.wav",
-- "ambient/alarms/combine_bank_alarm_loop1.wav",
-- "ambient/alarms/combine_bank_alarm_loop4.wav",
-- "ambient/alarms/klaxon1.wav",
"ambient/alarms/manhack_alert_pass1.wav",
"ambient/alarms/razortrain_horn1.wav",
"ambient/alarms/scanner_alert_pass1.wav",
-- "ambient/alarms/siren.wav",
-- "ambient/alarms/train_crossing_bell_loop1.wav",
"ambient/alarms/train_horn2.wav",
"ambient/alarms/train_horn_distant1.wav",
"ambient/alarms/warningbell1.wav",
-- "ambient/chatter/cb_radio_chatter_1.wav",
-- "ambient/chatter/cb_radio_chatter_2.wav",
-- "ambient/chatter/cb_radio_chatter_3.wav",
"ambient/energy/whiteflash.wav",
"ambient/intro/alyxremove.wav",
"ambient/intro/logosfx.wav",
-- "ambient/levels/labs/teleport_alarm_loop1.wav",
"ambient/levels/launch/1stfiringwarning.wav",
"ambient/levels/launch/rockettakeoffblast.wav",
-- "ambient/levels/outland/basealarmloop.wav",
-- "ambient/machines/60hzhum.wav",
"ambient/misc/ambulance1.wav",
"ambient/misc/carhonk1.wav",
"ambient/misc/carhonk2.wav",
"ambient/misc/carhonk3.wav",
-- "ambient/music/bongo.wav",
-- "ambient/music/country_rock_am_radio_loop.wav",
-- "ambient/music/cubanmusic1.wav",
-- "ambient/music/dustmusic1.wav",
-- "ambient/music/dustmusic2.wav",
-- "ambient/music/dustmusic3.wav",
-- "ambient/music/flamenco.wav",
-- "ambient/music/latin.wav",
-- "ambient/music/mirame_radio_thru_wall.wav",
-- "ambient/music/piano1.wav",
-- "ambient/music/piano2.wav",
"ambient/outro/gunshipcrash.wav",
"ambient/3dmeagle.wav",
-- "ambient/guit1.wav",
-- "ambient/opera.wav",
-- "ambient/sheep.wav",
"beams/beamstart5.wav",
"buttons/bell1.wav",
"buttons/weapon_cant_buy.wav",
"common/bass.wav",
"common/bugreporter_failed.wav",
"common/warning.wav",
"doors/door_squeek1.wav",
"friends/friend_join.wav",
"friends/friend_online.wav",
"friends/message.wav",
"hostage/hunuse/comeback.wav",
"hostage/hunuse/dontleaveme.wav",
"hostage/hunuse/yeahillstay.wav",
"items/gift_drop.wav",
"music/radio1.mp3",
"phx/eggcrack.wav",
"plats/elevbell1.wav",
"player/headshot1.wav",
"player/headshot2.wav",
"player/sprayer.wav",
"radio/enemydown.wav",
"radio/go.wav",
"radio/locknload.wav",
"radio/negative.wav",
"radio/rounddraw.wav",
"radio/takepoint.wav",
"resource/warning.wav",
-- "test/temp/soundscape_test/tv_music.wav",
"ui/achievement_earned.wav",
"ui/freeze_cam.wav",
"vehicles/junker/radar_ping_friendly1.wav",
"weapons/c4/c4_beep1.wav",
"weapons/c4/c4_click.wav",
"weapons/awp/awp1.wav",
"vo/canals/female01/gunboat_giveemhell.wav",
"vo/canals/female01/gunboat_justintime.wav",
"vo/canals/female01/stn6_incoming.wav",
"vo/canals/male01/gunboat_giveemhell.wav",
"vo/canals/male01/gunboat_justintime.wav",
"vo/canals/male01/stn6_incoming.wav",
"vo/canals/al_radio_stn6.wav",
"vo/canals/arrest_getgoing.wav",
"vo/canals/arrest_helpme.wav",
"vo/canals/arrest_lookingforyou.wav",
"vo/canals/boxcar_lethimhelp.wav",
"vo/canals/matt_closecall.wav",
"vo/canals/premassacre.wav",
"vo/ravenholm/aimforhead.wav",
"vo/ravenholm/bucket_patience.wav",
"vo/ravenholm/madlaugh01.wav",
"vo/ravenholm/madlaugh02.wav",
"vo/ravenholm/madlaugh03.wav",
"vo/ravenholm/madlaugh04.wav",
"weapons/strider_buster/ol12_stickybombcreator.wav",
"weapons/c4/c4_explode1.wav",
"weapons/357/357_fire2.wav",
"weapons/357/357_fire3.wav",
"weapons/scout/scout_fire-1.wav",
"weapons/smokegrenade/sg_explode.wav",
"weapons/grenade_launcher1.wav",
"weapons/explode3.wav",
"weapons/underwater_explode3.wav",
"items/nvg_on.wav",
"hostage/huse/letsdoit.wav",
"hostage/huse/illfollow.wav",
"hostage/huse/getouttahere.wav",
"doors/door_screen_move1.wav",
"doors/heavy_metal_stop1.wav",
"doors/default_move.wav",
"common/stuck2.wav",
"ambient/water_splash1.wav",
"ambient/water_splash2.wav",
"ambient/water_splash3.wav",
"ambient/weather/thunder1.wav",
"ambient/weather/thunder2.wav",
"ambient/weather/thunder3.wav",
"ambient/weather/thunder4.wav",
"ambient/weather/thunder5.wav",
"ambient/weather/thunder6.wav",
"ambient/outro/thunder7.wav",
"ambient/voices/crying_loop1.wav",
"ambient/voices/playground_memory.wav",
"ambient/voices/f_scream1.wav",
"ambient/voices/m_scream1.wav",
"ambient/voices/cough1.wav",
"ambient/voices/cough2.wav",
"ambient/voices/cough3.wav",
"ambient/voices/cough4.wav",
"ambient/overhead/plane1.wav",
"ambient/overhead/plane2.wav",
"ambient/overhead/plane3.wav",
"ambient/overhead/hel1.wav",
"ambient/overhead/hel2.wav",
"ambient/misc/truck_backup1.wav",
"ambient/misc/truck_drive1.wav",
"ambient/misc/truck_drive2.wav",
"ambient/machines/pneumatic_drill_1.wav",
"ambient/machines/pneumatic_drill_2.wav",
"ambient/machines/pneumatic_drill_3.wav",
"ambient/machines/pneumatic_drill_4.wav",
"ambient/machines/station_train_squeel.wav",
"ambient/machines/ticktock.wav",
"ambient/creatures/teddy.wav",
"ambient/creatures/town_child_scream1.wav",
"ambient/creatures/town_moan1.wav",
"ambient/creatures/town_muffled_cry1.wav",
"ambient/creatures/town_scared_breathing1.wav",
"ambient/creatures/town_scared_breathing2.wav",
"ambient/creatures/town_scared_sob1.wav",
"ambient/creatures/town_scared_sob2.wav",
"ambient/creatures/town_zombie_call1.wav"
}
@@ -0,0 +1,253 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- ------------------------------------------------------------------------- --
--! Includes
-- ------------------------------------------------------------------------- --
include("sh_init.lua")
GM.UI = {}
include("client/cl_ui_help.lua")
include("client/cl_ui_teamselection.lua")
-- ------------------------------------------------------------------------- --
--! Code
-- ------------------------------------------------------------------------- --
function GM:Initialize()
print("-------------------------------------------------------------------------")
print("Prop Hunt CL: Initializing...")
print("Prop Hunt CL: Initializing Gamemode Data...")
self.Data = {}
print("Prop Hunt CL: Creating Fonts...")
surface.CreateFont("RobotoBoldCondensed160", {font="Roboto Bold Condensed", extended=true, size=160, weight=800, antialias=true})
print("Prop Hunt CL: Complete.")
print("-------------------------------------------------------------------------")
end
function GM:Think() end
function GM:InitialPlayerSpawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: InitialPlayerSpawn") end
-- Delay execution until LocalPlayer() is valid.
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
timer.Simple(.1, function() GAMEMODE:InitialPlayerSpawn() end)
return
end
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: InitialPlayerSpawn Valid") end
player_manager.RunClass(LocalPlayer(), "InitialClientSpawn")
end
function GM:PlayerSpawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: PlayerSpawn") end
-- Delay execution until LocalPlayer() is valid.
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
timer.Simple(.1, function() GAMEMODE:PlayerSpawn() end)
return
end
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: PlayerSpawn Valid") end
if !(LocalPlayer().Data) then
LocalPlayer().Data = {}
LocalPlayer().Data.ThirdPerson = true
end
player_manager.RunClass(LocalPlayer(), "ClientSpawn")
end
function GM:PostDrawViewModel( vm, ply, weapon )
if ( weapon.UseHands || !weapon:IsScripted() ) then
local hands = LocalPlayer():GetHands()
if ( IsValid( hands ) ) then hands:DrawModel() end
end
end
-- ------------------------------------------------------------------------- --
--! Player Manager Binding
-- ------------------------------------------------------------------------- --
function GM:HUDPaint() player_manager.RunClass(LocalPlayer(), "HUDPaint") end
function GM:CalcView(ply, pos, ang, fov, nearZ, farZ) return player_manager.RunClass(LocalPlayer(), "CalcView", {origin = pos, angles = ang, fov = fov, znear = nearZ, zfar = farZ}) end
function GM:GetHandsModel() return player_manager.RunClass(LocalPlayer(), "GetHandsModel") end
-- ------------------------------------------------------------------------- --
--! Gamemode Functionality
-- ------------------------------------------------------------------------- --
function GM:PlayerSetViewOffset(vo, voduck)
-- Delay execution until LocalPlayer() is valid.
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
if !(GAMEMODE.TempData) then GAMEMODE.TempData = {} end
GAMEMODE.TempData.ViewOffset = vo
GAMEMODE.TempData.ViewOffsetDuck = voduck
timer.Simple(.1, function()
GAMEMODE:PlayerSetViewOffset(GAMEMODE.TempData.ViewOffset, GAMEMODE.TempData.ViewOffsetDuck)
end)
return
end
LocalPlayer():SetViewOffset(vo)
LocalPlayer():SetViewOffsetDucked(voduck)
if LocalPlayer():Crouching() then
LocalPlayer():SetCurrentViewOffset(voduck)
else
LocalPlayer():SetCurrentViewOffset(vo)
end
end
function GM:PlayerSetHull(hullMin, hullMax)
-- Delay execution until LocalPlayer() is valid.
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
if !(GAMEMODE.TempData) then GAMEMODE.TempData = {} end
GAMEMODE.TempData.HullMin = hullMin
GAMEMODE.TempData.HullMax = hullMax
timer.Simple(.1, function()
GAMEMODE:PlayerSetHull(GAMEMODE.TempData.HullMin, GAMEMODE.TempData.HullMax) end)
return
end
if (hullMin == hullMax) && (hullMin == nil) then
LocalPlayer():ResetHull()
else
LocalPlayer():SetHull(hullMin, hullMax)
LocalPlayer():SetHullDuck(hullMin, hullMax)
end
end
-- ------------------------------------------------------------------------- --
--! Commands
-- ------------------------------------------------------------------------- --
function GM:OnContextMenuOpen()
end
function GM:OnContextMenuClose()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Toggled View Mode") end
LocalPlayer().Data.ThirdPerson = !LocalPlayer().Data.ThirdPerson
end
function GM:OnSpawnMenuOpen()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Enabling Prop Rotation") end
LocalPlayer():SetNWBool("PropRotation", true)
net.Start("PlayerEnablePropRotation")
net.WriteAngle(LocalPlayer():EyeAngles())
net.SendToServer()
end
function GM:OnSpawnMenuClose()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Disabling Prop Rotation") end
LocalPlayer():SetNWBool("PropRotation", false)
net.Start("PlayerDisablePropRotation")
net.WriteAngle(LocalPlayer():EyeAngles())
net.SendToServer()
end
function GM:ShowHelpUI()
self.UI.Help:Show()
end
concommand.Add("ph_show_help", function() GAMEMODE:ShowHelpUI() end)
function GM:ShowTeamSelection()
TeamSelectionUI:Show()
end
concommand.Add("ph_select_team", function() GAMEMODE:ShowTeamSelection() end)
-- ------------------------------------------------------------------------- --
--! Network Messages
-- ------------------------------------------------------------------------- --
net.Receive("PlayerManagerInitialClientSpawn", function(len, pl) GAMEMODE:InitialPlayerSpawn() end)
net.Receive("PlayerManagerClientSpawn", function(len, pl) GAMEMODE:PlayerSpawn() end)
net.Receive( "PlayerSetHull", function(len, pl)
local hullMin, hullMax = net.ReadVector(), net.ReadVector();
GAMEMODE:PlayerSetHull(hullMin, hullMax)
end)
net.Receive( "PlayerResetHull", function(len, pl) GAMEMODE:PlayerSetHull(nil, nil) end)
net.Receive( "PlayerViewOffset", function(len, pl)
local vo, voduck = net.ReadVector(), net.ReadVector()
GAMEMODE:PlayerSetViewOffset(vo, voduck)
end)
-- ------------------------------------------------------------------------- --
--! Special Drawing
-- ------------------------------------------------------------------------- --
function DrawNamePlates(bDrawingDepth, bDrawingSkybox)
if (!GAMEMODE.Config.NamePlates:Show()) then
return
end
local scale = GAMEMODE.Config.NamePlates:Scale()
local pls = team.GetPlayers(GAMEMODE.Teams.Seekers)
if (LocalPlayer():Team() == GAMEMODE.Teams.Hiders) then
pls = table.Add(pls, team.GetPlayers(GAMEMODE.Teams.Hiders))
end
for i,v in ipairs(pls) do
if (v:Alive() && v != LocalPlayer()) then
local color = HSVToColor(GAMEMODE.Config.NamePlates:TintHue(),
GAMEMODE.Config.NamePlates:TintSaturation(),
GAMEMODE.Config.NamePlates:TintValue())
if GAMEMODE.Config.NamePlates:TintHealth() then
local healthPrc = v:Health() / v:GetMaxHealth()
color = HSVToColor(120 * healthPrc, 1.0, 1.0)
elseif GAMEMODE.Config.NamePlates:TintTeam() then
color = team.GetColor(v:Team())
end
local pos = v:GetPos() + v:GetViewOffset() + Vector(0, 0, GAMEMODE.Config.NamePlates:Height())
local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x)
cam.Start3D2D(pos, ang, scale)
draw.DrawText(v:GetName(), "RobotoBoldCondensed160", 0, -draw.GetFontHeight("RobotoBoldCondensed160") / 2, color, TEXT_ALIGN_CENTER)
cam.End3D2D()
end
end
end
hook.Add("PostDrawTranslucentRenderables", "PHDrawNamePlates", DrawNamePlates)
-- ------------------------------------------------------------------------- --
--! Old Code
-- ------------------------------------------------------------------------- --
--[[
function DrawPlayerHalos(bDrawingDepth, bDrawingSkybox)
for i,v in ipairs(player.GetAll()) do
if v:Alive() then
local pos = v:GetPos() + Vector(0, 0, 1) * (v:OBBMaxs().z - v:OBBMins().z + 5)
local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x)
local healthPrc = v:Health() / v:GetMaxHealth()
local healthCol = HSVToColor(120 * healthPrc, 1.0, 1.0)
if v:Team() == TEAM_HUNTERS || LocalPlayer():Team() == TEAM_PROPS then
local ent = v
if v.ph_prop && v.ph_prop:IsValid() then ent = v.ph_prop end
halo.Add({ent}, healthCol, 2, 2, 1)
end
end
end
end
--hook.Add("PostDrawEffects", "PH_DrawPlayerHalos", DrawPlayerHalos)
]]
@@ -0,0 +1,82 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local PANEL = vgui.Create("DFrame")
PANEL:SetSize(640, 480)
PANEL:SetTitle("Help")
PANEL:SetDraggable(true)
PANEL:SetVisible(false)
PANEL:SetDraggable(true)
PANEL:SetSizable(true)
PANEL:ShowCloseButton(true)
PANEL:SetDeleteOnClose(false)
function PANEL:Show()
--self:SetSize(ScrW(), ScrH())
self:Center()
self:SetVisible(true)
self:SetFocusTopLevel(true)
self:SlideDown(.5)
self:MakePopup()
end
function PANEL:Hide()
self:Close()
self:SetVisible(false)
end
function PANEL:Paint(w, h)
draw.RoundedBox(0, 0, 0, w, h, Color(0,0,0,240))
end
-- Sheets
local Element = vgui.Create("DPropertySheet", PANEL)
function Element:PAINT(w,h)
draw.RoundedBox(0, 0, 0, w, h, Color(0,0,0,240))
end
Element:Dock(FILL)
PANEL.Sheets = Element
PANEL.Sheet = {}
-- Basic Info
local Element = vgui.Create("DPanel", PANEL.Sheets)
function Element:Paint(w,h) end
PANEL.Sheets:AddSheet("The Gamemode", Element)
PANEL.Sheet.TheGamemode = Element
local Element = vgui.Create("DLabel", PANEL.Sheet.TheGamemode)
Element:Dock(TOP)
Element:SetMultiline(true)
Element:SetText([[
Prop Hunt Extended is a Gamemode based on the original Prop Hunt Gamemode. It changes many gameplay elements and features, adding the ability to easily integrate Taunt Packs, Configure Game parameters, rotate your prop and much more.
]])
-- Settings
PANEL.SettingsSheet = vgui.Create("DPanel", PANEL.Sheets)
PANEL.Sheets:AddSheet("Settings", PANEL.SettingsSheet)
GM.UI.Help = PANEL
@@ -0,0 +1,88 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local PANEL = vgui.Create("DFrame")
PANEL:SetSize(400, 300)
PANEL:SetTitle("Select a Team")
PANEL:SetDraggable(true)
PANEL:SetVisible(false)
PANEL:SetDraggable(true)
PANEL:SetSizable(true)
PANEL:ShowCloseButton(true)
PANEL:SetDeleteOnClose(false)
TeamSelectionUI = {}
TeamSelectionUI.Frame = vgui.Create("DFrame")
TeamSelectionUI.Frame:SetPos(0, 0)
TeamSelectionUI.Frame:SetSize(400, 320)
TeamSelectionUI.Frame:Center()
TeamSelectionUI.Frame:SetTitle("Select a Team")
TeamSelectionUI.Frame:SetVisible(false)
TeamSelectionUI.Frame:SetDraggable(true)
TeamSelectionUI.Frame:SetSizable(false)
TeamSelectionUI.Frame:ShowCloseButton(true)
TeamSelectionUI.Frame:SetDeleteOnClose(false)
function TeamSelectionUI.Frame:Paint(w, h)
draw.RoundedBox(0, 0, 0, w, h, Color(0, 0, 0, 225))
end
function TeamSelectionUI:Show()
self.Frame:MakePopup()
TeamSelectionUI.Frame:SetVisible(true)
end
function TeamSelectionUI:Hide()
TeamSelectionUI.Frame:Close()
TeamSelectionUI.Frame:SetVisible(false)
end
TeamSelectionUI.SelectSeeker = vgui.Create("DButton", TeamSelectionUI.Frame)
TeamSelectionUI.SelectSeeker:SetPos(0, 20)
TeamSelectionUI.SelectSeeker:SetSize(200, 200)
TeamSelectionUI.SelectSeeker:SetText("Seeker")
TeamSelectionUI.SelectSeeker.DoClick = function()
TeamSelectionUI:Hide()
LocalPlayer():ConCommand("changeteam " .. tostring(GAMEMODE.Teams.Seekers))
end
TeamSelectionUI.SelectHider = vgui.Create("DButton", TeamSelectionUI.Frame)
TeamSelectionUI.SelectHider:SetPos(200, 20)
TeamSelectionUI.SelectHider:SetSize(200, 200)
TeamSelectionUI.SelectHider:SetText("Hiders")
TeamSelectionUI.SelectHider.DoClick = function()
TeamSelectionUI:Hide()
LocalPlayer():ConCommand("changeteam " .. tostring(GAMEMODE.Teams.Hiders))
end
TeamSelectionUI.Spectate = vgui.Create("DButton", TeamSelectionUI.Frame)
TeamSelectionUI.Spectate:SetPos(0, 220)
TeamSelectionUI.Spectate:SetSize(400, 100)
TeamSelectionUI.Spectate:SetText("Spectate")
TeamSelectionUI.Spectate.DoClick = function()
TeamSelectionUI:Hide()
LocalPlayer():ConCommand("changeteam " .. tostring(GAMEMODE.Teams.Spectators))
end
@@ -0,0 +1,30 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
local ELEMENT = {}
function ELEMENT:Paint()
end
vgui.Register("DMultilineLabel", ELEMENT, "Panel")
@@ -0,0 +1,68 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- This file adds compatability to the older Taunt Pack loader format, which
-- directly modifies the gamemode tables (something that shouldn't be done).
function CompatTauntPackLoader()
-- Prepare an empty table for the taunts.
GAMEMODE.Prop_Taunts = {}
GAMEMODE.Hunter_Taunts = {}
-- Run the old hook name.
hook.Run("ph_AddTaunts", nil)
-- Insert the taunts into the new structure (cvar).
Taunts = {}
for i,t in ipairs(GAMEMODE.Prop_Taunts) do
ty = type(t)
if (ty == "string") then
Taunts[#Taunts+1] = t
elseif (ty == "table") then
Taunts[#Taunts+1] = t[2]
-- for j,snd in ipairs(t) do
-- HiderTaunts[#HiderTaunts+1] = snd
-- end
end
end
GAMEMODE.Config.Taunt.HidersCacheStatic = Taunts
Taunts = {}
for i,t in ipairs(GAMEMODE.Hunter_Taunts) do
ty = type(t)
if (ty == "string") then
Taunts[#Taunts+1] = t
elseif (ty == "table") then
Taunts[#Taunts+1] = t[2]
-- for j,snd in ipairs(t) do
-- SeekerTaunts[#SeekerTaunts+1] = snd
-- end
end
end
GAMEMODE.Config.Taunt.SeekersCacheStatic = Taunts
-- Clean up after ourselves
GAMEMODE.Prop_Taunts = nil
GAMEMODE.Hunter_Taunts = nil
end
hook.Add("Initialize", "CompatTauntPackLoader", CompatTauntPackLoader)
@@ -0,0 +1,392 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- ------------------------------------------------------------------------- --
--! Downloadable Lua
-- ------------------------------------------------------------------------- --
-- Shared
AddCSLuaFile("sh_init.lua")
AddCSLuaFile("sh_config.lua")
AddCSLuaFile("player_class/class_default.lua")
AddCSLuaFile("player_class/class_spectator.lua")
AddCSLuaFile("player_class/class_seeker.lua")
AddCSLuaFile("player_class/class_hider.lua")
-- Client-Only
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("client/cl_ui_help.lua")
AddCSLuaFile("client/cl_ui_teamselection.lua")
-- ------------------------------------------------------------------------- --
--! Code
-- ------------------------------------------------------------------------- --
-- Shared
include "sh_init.lua"
-- Server Only
include "compat/compat_tauntpackloader.lua"
include "server/roundmanager.lua"
include "server/states/state_prematch.lua"
include "server/states/state_preround.lua"
include "server/states/state_hide.lua"
include "server/states/state_seek.lua"
include "server/states/state_postround.lua"
include "server/states/state_postmatch.lua"
function GM:Initialize()
print("-------------------------------------------------------------------------")
print("Prop Hunt: Initializing...")
print("Prop Hunt: Registering Networked Messages...")
util.AddNetworkString("PlayerManagerInitialClientSpawn")
util.AddNetworkString("PlayerManagerClientSpawn")
util.AddNetworkString("PlayerSetHull")
util.AddNetworkString("PlayerResetHull")
util.AddNetworkString("PlayerViewOffset")
util.AddNetworkString("PlayerRegisterPropEntity")
util.AddNetworkString("PlayerEnablePropRotation")
util.AddNetworkString("PlayerDisablePropRotation")
print("Prop Hunt: Initializing Gamemode Data...")
self.Data = {}
self.Data.StartTime = CurTime()
print("Prop Hunt: Setting initial RoundManager State...")
self.RoundManager:SetState(StatePreMatch)
print("Prop Hunt: Precaching...")
GAMEMODE.Config.Taunt:Seekers()
GAMEMODE.Config.Taunt:Hiders()
print("Prop Hunt: Complete.")
print("-------------------------------------------------------------------------")
end
function GM:Think()
self.RoundManager:Tick()
end
-- Player Connected
function GM:PlayerConnect(name, ip)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..name.."' connecting from IP '"..ip.."'.") end
end
-- Player Authenticated
function GM:PlayerAuthed(ply, steamid, uniqueid)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") authenticated.") end
end
-- Player Disconnected
function GM:PlayerDisconnected(ply)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") disconnected.") end
end
-- Player Spawn (Initial)
function GM:PlayerInitialSpawn(ply)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned for the first time, applying defaults...") end
if (!ply.Data) then
-- Initialize Data Structure
ply.Data = {}
ply.Data.Alive = false
ply.Data.AliveTime = 0
ply.Data.RandomWeight = 0 -- Higher means higher chance of becoming Seeker instead of Hider.
end
-- Kill Silently
ply:KillSilent()
-- Show Team Selection Menu
ply:SetTeam(GAMEMODE.Teams.Spectators)
self:ShowTeam(ply)
-- Bot: Auto Assign to Team
if (ply:IsBot()) then
if team.NumPlayers(self.Teams.Hiders) > team.NumPlayers(self.Teams.Seekers) then
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Seekers.") end
ply:SetTeam(self.Teams.Seekers)
else
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Hiders.") end
ply:SetTeam(self.Teams.Hiders)
end
end
-- Notify Player Manager
player_manager.RunClass(ply, "InitialSpawn")
-- Signal Client
net.Start("PlayerManagerInitialClientSpawn");net.Send(ply)
end
-- Player Spawn
function GM:PlayerSpawn(ply)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned in.") end
-- Player Manager: Assign Player Class
local class = team.GetClass(ply:Team())
if (class) then
if (ply.Data.Alive) then -- Alive Class
player_manager.SetPlayerClass(ply, class[1])
else -- Dead Class (Spectator)
player_manager.SetPlayerClass(ply, class[2])
end
else
player_manager.SetPlayerClass(ply, "Spectator")
end
-- Notify Player Manager
player_manager.OnPlayerSpawn(ply)
player_manager.RunClass(ply, "Spawn")
-- Some hooks are not called
hook.Call("PlayerSetModel", self, ply)
hook.Call("PlayerLoadout", self, ply)
-- Signal Client
net.Start("PlayerManagerClientSpawn");net.Send(ply)
end
-- Player requests Team Change
function GM:PlayerRequestTeam(ply, teamId)
if self:PlayerCanJoinTeam(ply, teamId) then
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") requested to join Team "..team.GetName(teamId)..".") end
if (ply:Team() != teamId) then
ply:KillSilent()
ply:SetTeam(teamId)
if (GetGlobalInt("RoundState", GAMEMODE.States.PreMatch) <= GAMEMODE.States.PreRound) then
ply.Alive = true
ply.AliveTime = CurTime()
end
else
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") attempted to rejoin the Team it is already in.") end
end
end
end
-- ------------------------------------------------------------------------- --
--! Player Manager Binding
-- ------------------------------------------------------------------------- --
function GM:PlayerLoadout(ply) player_manager.RunClass(ply, "Loadout") end
function GM:PlayerDeath(ply, inflictor, attacker)
player_manager.RunClass(ply, "Death", inflictor, attacker)
-- Signal Client Stuff
if IsValid(attacker) then
if attacker:IsPlayer() then
if (attacker == ply) then
net.Start("PlayerKilledSelf")
net.WriteEntity(ply)
net.Broadcast()
else
net.Start("PlayerKilledByPlayer")
net.WriteEntity(ply)
net.WriteString(inflictor:GetName())
net.WriteEntity(attacker)
net.Broadcast()
end
else
net.Start("PlayerKilled")
net.WriteEntity(ply)
net.WriteString(inflictor:GetName())
net.WriteString(attacker:GetClass())
net.Broadcast()
end
else
net.Start("PlayerKilled")
net.WriteEntity(ply)
net.WriteString(inflictor:GetName())
net.WriteString("World")
net.Broadcast()
end
end
function GM:PlayerSilentDeath(ply) player_manager.RunClass(ply, "SilentDeath") end
function GM:PostPlayerDeath(ply)
player_manager.RunClass(ply, "PostDeath")
-- Debug Mode: Respawn after Death
if (GAMEMODE.Config:Debug()) then
ply.Data.Alive = true
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Debug Mode active, Player "..ply:GetName().." was respawned.") end
end
end
function GM:DoPlayerDeath(ply, attacker, dmg) player_manager.RunClass(ply, "DoDeath", attacker, dmg) end
function GM:PlayerDeathThink(ply) return player_manager.RunClass(ply, "DeathThink") end
function GM:CanPlayerSuicide(ply) return player_manager.RunClass(ply, "CanSuicide") end
function GM:PlayerCanPickupWeapon(ply, weapon) return player_manager.RunClass(ply, "CanPickupWeapon", weapon) end
function GM:PlayerCanPickupItem(ply, item) return player_manager.RunClass(ply, "CanPickupItem", item) end
function GM:PlayerUse(ply, ent) return player_manager.RunClass(ply, "Use", ent) end
function GM:AllowPlayerPickup(ply, ent) return player_manager.RunClass(ply, "AllowPickup", ent) end
function GM:PlayerSetModel(ply) return player_manager.RunClass(ply, "SetModel") end
-- Called when an entity takes damage
function GM:EntityTakeDamage(ent, dmg)
local att = dmg:GetAttacker()
if (att) && (att:IsValid()) && (att:IsPlayer()) then
player_manager.RunClass(att, "DamageEntity", ent, att, dmg)
end
end
-- ------------------------------------------------------------------------- --
--! Gamemode Functionality
-- ------------------------------------------------------------------------- --
function GM:SetRound(Round)
SetGlobalInt("Round", Round)
end
function GM:SetRoundState(State)
SetGlobalInt("RoundState", State)
end
function GM:SetRoundTime(Time)
SetGlobalInt("RoundTime", Time)
end
function GM:SetRoundWinner(Winner)
SetGlobalInt("RoundWinner", Winner)
end
function GM:PlayerHullFromEntity(ply, ent)
if (ent) && (ent:IsValid()) then
local hmin, hmax = ent:OBBMins(), ent:OBBMaxs()
local hull = Vector(hmax.x - hmin.x, hmax.y - hmin.y, hmax.z - hmin.z)
if hull.x <= hull.y then
hull.y = hull.x
else
hull.x = hull.y
end
hull:Mul(0.5)
hull:Mul(0.95) -- Reduce size slightly
local hullmin = Vector(-hull.x, -hull.y, 0)
local hullmax = Vector(hull.x, hull.y, hull.z * 2)
ply:SetHull(hullmin, hullmax)
ply:SetHullDuck(hullmin, hullmax)
net.Start("PlayerSetHull")
net.WriteVector(hullmin)
net.WriteVector(hullmax)
net.Send(ply)
return {hullmin, hullmax}
else
ply:ResetHull()
net.Start("PlayerResetHull")
net.Send(ply)
return nil
end
end
function GM:PlayerSetViewOffset(ply, vo, voduck)
ply:SetViewOffset(vo)
ply:SetViewOffsetDucked(voduck)
if ply:Crouching() then
ply:SetCurrentViewOffset(voduck)
else
ply:SetCurrentViewOffset(vo)
end
-- Signal Client
net.Start("PlayerViewOffset")
net.WriteVector(vo)
net.WriteVector(voduck)
net.Send(ply)
end
-- ------------------------------------------------------------------------- --
--! Commands
-- ------------------------------------------------------------------------- --
-- F1/ShowHelp
function GM:ShowHelp(ply)
ply:ConCommand("ph_show_help")
end
-- F2/ShowTeam - Select Team
function GM:ShowTeam(ply)
ply:ConCommand("ph_select_team")
end
function GM:ShowSpare1(ply) player_manager.RunClass(ply, "ShowSpare1") end -- F3/ShowSpare1
function GM:ShowSpare2(ply) player_manager.RunClass(ply, "ShowSpare2") end -- F4/ShowSpare2
-- Debug Command: Print All Players
concommand.Add("ph_debug_printplayers", function(ply, cmd, args, argStr)
if GAMEMODE.Config:DebugLog() then
print ("All Players:")
for i,ply in ipairs(player.GetAll()) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..") - Team "..team.GetName(ply:Team()).. " - Alive "..tostring(ply.Data.Alive))
end
print ("Spectators:")
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Spectators)) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
end
print ("Seekers:")
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
end
print ("Hiders:")
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Hiders)) do
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
end
end
end, nil, nil, FCVAR_CLIENTCMD_CAN_EXECUTE + FCVAR_CHEAT)
-- Debug Command: Print All Players
concommand.Add("ph_debug_stats", function(ply, cmd, args, argStr)
if GAMEMODE.Config:DebugLog() then
for i,ply in ipairs(player.GetAll()) do
print(ply:GetName().." (SteamID: "..ply:SteamID()..")")
print(" Team: "..team.GetName(ply:Team()))
print(" Alive: "..tostring(ply.Data.Alive))
print(" AliveTime: "..tostring(ply.Data.AliveTime))
print(" Score: "..tostring(ply.Data.RandomWeight))
end
end
end, nil, nil, FCVAR_CLIENTCMD_CAN_EXECUTE + FCVAR_CHEAT)
-- ------------------------------------------------------------------------- --
--! Network Messages
-- ------------------------------------------------------------------------- --
net.Receive("PlayerEnablePropRotation", function(len, ply)
if (ply:Team() != GAMEMODE.Teams.Hiders) then
return
end
print("Prop Hunt: Enabling Prop Rotation")
ply:SetNWBool("PropRotation", true)
ply.Data.Prop:ApplyRotation(net.ReadAngle())
end)
net.Receive("PlayerDisablePropRotation", function(len, ply)
if (ply:Team() != GAMEMODE.Teams.Hiders) then
return
end
print("Prop Hunt: Disabling Prop Rotation")
ply:SetNWBool("PropRotation", false)
ply.Data.Prop:ApplyRotation(net.ReadAngle())
end)
@@ -0,0 +1,261 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
DEFINE_BASECLASS("player_default")
local CLASS = {}
CLASS.DisplayName = "Default"
CLASS.WalkSpeed = 250 -- How fast to move when not running
CLASS.RunSpeed = 500 -- How fast to move when running
CLASS.CrouchedWalkSpeed = 0.5 -- Multiply move speed by this when crouching
CLASS.DuckSpeed = 0.2 -- How fast to go from not ducking, to ducking
CLASS.UnDuckSpeed = 0.2 -- How fast to go from ducking, to not ducking
CLASS.JumpPower = 200 -- How powerful our jump should be
CLASS.CanUseFlashlight = false -- Can we use the flashlight
CLASS.MaxHealth = 100 -- Max health we can have
CLASS.StartHealth = 100 -- How much health we start with
CLASS.StartArmor = 0 -- How much armour we start with
CLASS.DropWeaponOnDie = false -- Do we drop our weapon when we die
CLASS.TeammateNoCollide = true -- Do we collide with teammates or run straight through them
CLASS.AvoidPlayers = true -- Automatically swerves around other players
CLASS.UseVMHands = true -- Uses viewmodel hands
-- ------------------------------------------------------------------------- --
--! Server-Side
-- ------------------------------------------------------------------------- --
-- Spawn
function CLASS:InitialSpawn() end
function CLASS:Spawn() end
function CLASS:Loadout() end
-- Damage
function CLASS:ShouldTakeDamage(attacker) return true end -- Should take damage from attacker?
function CLASS:Hurt(victim, attacker, healthRemaining, damageTaken) end -- Damage Taken
function CLASS:Damage(victim, attacker, healthRemaining, damageDealt) end -- Damage Dealt
function CLASS:DamageEntity(ent, attacker, dmginfo) end -- Damage Dealt To Entity
-- Death
function CLASS:Death(inflictor, attacker)
self.Player.Data.Alive = false
self.Player.Data.AliveTime = CurTime()
end
function CLASS:SilentDeath()
self.Player.Data.Alive = false
self.Player.Data.AliveTime = CurTime()
end
function CLASS:PostDeath() end
function CLASS:DoDeath() end
function CLASS:DeathThink()
if (CurTime() - self.Player.Data.AliveTime) > 5 then
self.Player:Spawn()
return true
end
return false
end
function CLASS:CanSuicide() return true end
-- Visible Stuff
function CLASS:SetModel() BaseClass.SetModel( self ) end
-- Interaction
function CLASS:Use(ent)
-- Entity must be valid and not a player.
if (!ent) || (!ent:IsValid()) || (ent:IsPlayer()) then
return false
end
-- Cool Down
if (self.Player.Data.UseTime) then
local timeSinceUse = (CurTime() - self.Player.Data.UseTime)
if (0.2 > timeSinceUse) then
return false
end
-- Abuse Blacklist (Buttons, Doors, etc)
if (5 > timeSinceUse) then
local abuseBlacklist = GAMEMODE.Config.Lists:AbuseBlacklist()
if (table.HasValue(abuseBlacklist, ent:GetClass())) then
return false
end
end
end
self.Player.Data.UseTime = CurTime()
return true
end
function CLASS:AllowPickup(ent) return false end
function CLASS:CanPickupWeapon(ent) return false end
function CLASS:CanPickupItem(ent) return false end
-- Menu (Always Server)
function CLASS:ShowSpare1()
local lastTaunt = (self.Player.Data.LastTaunt or 0)
if ((CurTime() - lastTaunt) <= GAMEMODE.Config.Taunt:Cooldown()) then
return true
end
self.Player.Data.LastTaunt = CurTime()
end
function CLASS:ShowSpare2() end
-- ------------------------------------------------------------------------- --
--! Shared
-- ------------------------------------------------------------------------- --
function CLASS:PostThink() end
function CLASS:Tick(mv) end
-- ------------------------------------------------------------------------- --
--! Client-Side
-- ------------------------------------------------------------------------- --
-- Spawn
function CLASS:InitialClientSpawn()
self.Player.Data = {}
self.Player.Data.ThirdPerson = false -- Default to FirstPerson View
end
function CLASS:ClientSpawn() end
-- View & HUD
function CLASS:GetHandsModel() return BaseClass.GetHandsModel(self) end
function CLASS:ShouldDrawLocal() return false end
function CLASS:HUDPaint()
local State = GetGlobalInt("RoundState", GAMEMODE.States.PreMatch)
if State == -1 then
return
end
-- Status Box at the top.
local statusW, statusH = 256,48
local statusX, statusY = ScrW() / 2 - statusW / 2, 0
draw.RoundedBox(0, statusX, statusY, statusW, statusH, Color(0,0,0,204)) -- Background
draw.RoundedBox(0, statusX, statusY+statusH, statusW, 4, team.GetColor(LocalPlayer():Team())) -- Team Bar
-- Title
surface.SetFont("Trebuchet18")
surface.SetTextColor(Color(255,255,255,255))
local titleText = ""
if (State == GAMEMODE.States.PreMatch) then
titleText = "Waiting for Players"
elseif (State == GAMEMODE.States.PreRound) then
titleText = "Preparing Round..."
elseif (State == GAMEMODE.States.Hide) then -- Hide
titleText = "Seekers unblinded in:"
elseif (State == GAMEMODE.States.Seek) then -- Seek
titleText = "Seek Time!"
elseif (State == GAMEMODE.States.PostRound) then -- Post Round
titleText = "Match Result:"
elseif (State == GAMEMODE.States.PostMatch) then -- Post Match
end
local w,h = surface.GetTextSize(titleText)
surface.SetTextPos(statusX + statusW/2 - w/2, statusY)
surface.DrawText(titleText)
-- Subtitle
local stateText = ""
surface.SetFont("Trebuchet24")
surface.SetTextColor(Color(255,255,255,255))
if (State == GAMEMODE.States.PreMatch) then
stateText = tostring(team.NumPlayers(GAMEMODE.Teams.Seekers)) .. " Seeker(s), " .. tostring(team.NumPlayers(GAMEMODE.Teams.Hiders)) .. " Hider(s)"
elseif (State == GAMEMODE.States.PreRound) then
stateText = "Initiating..."
elseif (State == GAMEMODE.States.Hide) -- Hide
|| (State == GAMEMODE.States.Seek) then -- Seek
local intTime = math.ceil(GetGlobalInt("RoundTime"))
local strTime = string.format("%d:%02d", math.floor(intTime / 60), math.ceil(intTime % 60))
stateText = strTime
elseif (State == GAMEMODE.States.PostRound) then -- Post Round
local victor = GAMEMODE:GetRoundWinner()
local victorName = "Draw"
if (victor == GAMEMODE.Teams.Spectator) then
victorName = "Draw"
elseif (victor == GAMEMODE.Teams.Hiders) then
victorName = "Hiders Win"
elseif (victor == GAMEMODE.Teams.Seekers) then
victorName = "Seekers Win"
end
stateText = victorName
surface.SetTextColor(team.GetColor(victor))
elseif (State == GAMEMODE.States.PostMatch) then -- Post Match
end
local w,h = surface.GetTextSize(stateText)
surface.SetTextPos(statusX + statusW/2 - w/2, statusY + 32 - h / 2)
surface.DrawText(stateText)
-- Death Notices
GAMEMODE:DrawDeathNotice((ScrW() - 192) / ScrW() , 24 / ScrH())
end
function CLASS:CalcView(camdata)
-- Config
local cameraCollision = GAMEMODE.Config.Camera:Collisions()
local cameraDistance = GAMEMODE.Config.Camera:Distance()
local cameraDistanceRight = GAMEMODE.Config.Camera:DistanceRight()
local cameraDistanceUp = GAMEMODE.Config.Camera:DistanceUp()
local cameraLag = GAMEMODE.Config.Camera:Lag()
local cameraLagInv = 1 - cameraLag
-- First/Third Person Target Distance
local targetDistance = 0
if (self.Player.Data.ThirdPerson) then -- Incremental Distance instead of instant.
targetDistance = cameraDistance
if (cameraCollision == true) then
-- Trace from Player to would-be camera position
local trace = {
start = camdata.origin,
endpos = camdata.origin - (camdata.angles:Forward() * cameraDistance),
--filter = { "worldspawn", "ph_prop", "player" },
--[-[
filter = function(ent)
local filter = { "worldspawn", "ph_prop", "player" }
if (ent:IsPlayer())
|| (table.HasValue(filter, ent:GetClass()))
|| (ent == LocalPlayer()) || (ent == LocalPlayer():GetHands()) then
return false
end
return true
end,
--]]
}
local result = util.TraceLine(trace)
-- The Camera has a Sphere radius of 10.
if (result.Hit) then -- Configurable?
targetDistance = math.Clamp(result.HitPos:Distance(camdata.origin), 0, cameraDistance)
end
end
else
targetDistance = 0
end
-- Fade between Target and Current Distance
self.Player.Data.ViewDistance = math.Clamp(((self.Player.Data.ViewDistance or targetDistance) * cameraLag) + (targetDistance * cameraLagInv), 0, GAMEMODE.Config.Camera:DistanceMax())
-- Adjust CamData and return
camdata.origin = camdata.origin - (camdata.angles:Forward() * math.Clamp(self.Player.Data.ViewDistance - 10, 0, self.Player.Data.ViewDistance)) + (camdata.angles:Right() * cameraDistanceRight) + (camdata.angles:Up() * cameraDistanceUp)
return camdata
end
-- ------------------------------------------------------------------------- --
--! Register
-- ------------------------------------------------------------------------- --
player_manager.RegisterClass( "Default", CLASS, "player_default")
@@ -0,0 +1,210 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
DEFINE_BASECLASS( "Default" )
local CLASS = {}
CLASS.DisplayName = "Hider"
CLASS.DuckSpeed = 0.0 -- How fast to go from not ducking, to ducking
CLASS.UnDuckSpeed = 0.0 -- How fast to go from ducking, to not ducking
CLASS.CanUseFlashlight = false -- Can we use the flashlight
CLASS.UseVMHands = false -- Uses viewmodel hands
-- ------------------------------------------------------------------------- --
--! Server-Side
-- ------------------------------------------------------------------------- --
-- Spawn
function CLASS:Spawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
BaseClass.Spawn(self, self.Player)
-- Settings
self.Player:SetMaxHealth(GAMEMODE.Config.Hider:HealthMax())
self.Player:SetHealth(GAMEMODE.Config.Hider:Health())
self.Player:SetRenderMode(RENDERMODE_TRANSALPHA)
self.Player:SetColor(Color(0,0,0,0))
-- Speed and Jump Power
self.Player:SetWalkSpeed(GAMEMODE.Config.Hider:WalkSpeed())
if (GAMEMODE.Config.Hider:Sprint()) then
self.Player:SetRunSpeed(GAMEMODE.Config.Hider:SprintSpeed())
else
self.Player:SetRunSpeed(GAMEMODE.Config.Hider:WalkSpeed())
end
self.Player:SetJumpPower(GAMEMODE.Config.Hider:JumpPower())
-- Hull & View Offset
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,72), Vector(0,0,72))
-- Collision Group
self.Player:SetCollisionGroup(COLLISION_GROUP_PLAYER)
self.Player:SetSolid(SOLID_VPHYSICS)
-- Prop Stuff
self.Player.Data.Prop = ents.Create("ph_prop")
self.Player.Data.Prop:SetOwner(self.Player)
self.Player.Data.Prop:Spawn()
self.Player:DeleteOnRemove(self.Player.Data.Prop)
-- Assign Hands (Auto Networked Sync!)
local oldhands = self.Player:GetHands()
if (IsValid(oldhands)) then oldhands:Remove() end
self.Player:SetHands(self.Player.Data.Prop)
end
-- Death
function CLASS:PostDeath(attacker, dmginfo)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") end
BaseClass.PostDeath(self, inflictor, attacker)
-- Delete Hands Model
if IsValid(self.Player:GetHands()) then
self.Player:GetHands():Remove()
end
if IsValid(self.Player.Data.Prop) then
self.Player.Data.Prop:Remove()
end
-- Collision Group
self.Player:SetCollisionGroup(COLLISION_GROUP_PLAYER)
-- Hull
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
-- Rendering
self.Player:SetRenderMode(RENDERMODE_NORMAL)
self.Player:SetColor(Color(255,255,255,255))
end
function CLASS:CanSuicide()
return true
end
function CLASS:DeathThink()
if 1 > (CurTime() - self.Player.Data.AliveTime) then
return false
end
self.Player:Spawn()
return true
end
-- Visible Stuff
function CLASS:SetModel() self.Player:SetModel("models/Gibs/Antlion_gib_small_3.mdl") end -- does "" even work?
-- Interaction
function CLASS:Use(ent)
if (!(BaseClass.Use(self, ent))) then
return false
end
-- Allow interacting while crouched instead of turning into the prop.
if (self.Player:Crouching()) then
return true
end
-- Check Lists and other Parameters
if (!table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass())) -- Class is not Whitelisted
|| (table.HasValue(GAMEMODE.Config.Lists:ModelBlacklist(), ent:GetModel())) -- Model is Blacklisted
|| !((ent:GetPhysicsObject()) && (ent:GetPhysicsObject():IsValid())) -- Entity doesn't have Physics
then
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") attempted to turn into "..ent:GetClass().." ("..ent:GetModel()..").") end
return true -- Use instead of erroring.
end
-- Turn into the prop
local eProp = self.Player:GetHands()
util.PrecacheModel(ent:GetModel())
eProp:SetModel(ent:GetModel())
eProp:SetSkin(ent:GetSkin())
eProp:SetHealth(100)
eProp:SetMaxHealth(100)
eProp:SetRenderMode(RENDERMODE_TRANSALPHA)
-- Hull (Optimize into single function? Code is repeated often)
local hull = GAMEMODE:PlayerHullFromEntity(self.Player, ent)
-- View Offset
local vo = Vector(0, 0, hull[2].z)
GAMEMODE:PlayerSetViewOffset(self.Player, vo, vo)
-- Health Scaling
if (GAMEMODE.Config.Hider:HealthScaling()) then
local prc = math.Clamp(self.Player:Health() / self.Player:GetMaxHealth(), 0, 1)
local maxhealth = math.Clamp(ent:GetPhysicsObject():GetVolume() / 250, 1, GAMEMODE.Config.Hider:HealthScalingMax())
local health = math.Clamp(maxhealth * prc, 1, maxhealth)
-- Set Health
self.Player:SetHealth(health)
self.Player:SetMaxHealth(maxhealth)
end
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") turned into "..ent:GetClass().." ("..ent:GetModel()..").") end
end
function CLASS:AllowPickup(ent) return true end
-- Menu Buttons
function CLASS:ShowSpare1()
if BaseClass.ShowSpare1(self) then return end
-- Play a taunt
local tauntList = GAMEMODE.Config.Taunt:Hiders()
local index = math.random(#tauntList)
self.Player:EmitSound(tauntList[index], SNDLVL_NORM, 100, 1, CHAN_VOICE)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") taunted with sound '"..tauntList[index].."'.") end
end
-- ------------------------------------------------------------------------- --
--! Shared
-- ------------------------------------------------------------------------- --
-- ------------------------------------------------------------------------- --
--! Client-Side
-- ------------------------------------------------------------------------- --
function CLASS:ClientSpawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
BaseClass.ClientSpawn(self, self.Player)
self.Player:SetRenderMode(RENDERMODE_TRANSALPHA)
end
function CLASS:ShouldDrawLocal()
if (self.Player.Data.ViewDistance or 0) >= 10 then
if (IsValid(self.Player:GetHands())) then
self.Player:GetHands():SetRenderMode(RENDERMODE_TRANSALPHA)
self.Player:GetHands():SetColor(Color(255, 255, 255, 127))
end
else
if (IsValid(self.Player:GetHands())) then
self.Player:GetHands():SetRenderMode(RENDERMODE_TRANSALPHA)
self.Player:GetHands():SetColor(Color(255, 255, 255, 0))
end
end
return (self.Player.Data.ViewDistance or 0) >= 10
end
-- Register
player_manager.RegisterClass("Hider", CLASS, "Default")
@@ -0,0 +1,224 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
--! This file defines the Seeker player class.
-- A seeker is someone who is looking for the hiders, using weapons or other
-- means of detecting idiots. Also someone who looks like a diaper baby.
-- Weapons and Ammo are granted upon spawn and have to be used sparingly or
-- they'll be stuck with the crowbar. Bad seeker, bad.
-- Gain health upon killing a hider, lose health when attacking non-hiders.
-- Death upon health reaching 0.
DEFINE_BASECLASS( "Default" )
local CLASS = {}
CLASS.DisplayName = "Seeker"
CLASS.CanUseFlashlight = true -- Can we use the flashlight
CLASS.MaxHealth = 100
CLASS.StartHealth = 100
CLASS.StartArmor = 0
CLASS.DropWeaponOnDie = true
-- ------------------------------------------------------------------------- --
--! Server-Side
-- ------------------------------------------------------------------------- --
-- Spawn
function CLASS:Spawn()
if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
BaseClass.Spawn(self)
-- Settings
self.Player:SetMaxHealth(GAMEMODE.Config.Seeker:HealthMax())
self.Player:SetHealth(GAMEMODE.Config.Seeker:Health())
self.Player:SetRenderMode(RENDERMODE_NORMAL)
self.Player:SetColor(Color(255,255,255,255))
-- Speed and Jump Power
self.Player:SetWalkSpeed(GAMEMODE.Config.Seeker:WalkSpeed())
if (GAMEMODE.Config.Seeker:Sprint()) then
self.Player:SetRunSpeed(GAMEMODE.Config.Seeker:SprintSpeed())
else
self.Player:SetRunSpeed(GAMEMODE.Config.Seeker:WalkSpeed())
end
self.Player:SetJumpPower(GAMEMODE.Config.Seeker:JumpPower())
-- Hull & View Offset
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,64), Vector(0,0,32))
end
function CLASS:Loadout()
-- Give the weapons the admin told us to.
local weapons = GAMEMODE.Config.Seeker:Weapons()
for i,weapon in ipairs(weapons) do
self.Player:Give(weapon)
end
-- Give the ammo the admin told us to.
local ammos = GAMEMODE.Config.Seeker:Ammo()
for i,ammo in ipairs(ammos) do
local typeCount = string.Split(ammo, ":")
self.Player:GiveAmmo(tonumber(typeCount[2]), typeCount[1], true)
end
-- Default weapon stuff
local cl_defaultweapon = self.Player:GetInfo("cl_defaultweapon")
if self.Player:HasWeapon(cl_defaultweapon) then
self.Player:SelectWeapon(cl_defaultweapon)
end
end
-- Damage
function CLASS:ShouldTakeDamage(attacker)
if (IsValid(attacker)) then
if (attacker:IsPlayer()) then
if (attacker:Team() == self.Player:Team()) then
local ffmode = GetConVarNumber("mp_friendlyfire")
if (ffmode == 0) then -- Not Allowed
return false
elseif (ffmode == 2) then -- Damage self instead
if (IsValid(attacker) && attacker:IsPlayer()) then
attacker:SetHealth(attacker:Health() - damageTaken)
end
return false
end
end
end
end
return true
end
function CLASS:DamageEntity(ent, att, dmg)
if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") damaged entity "..ent:GetClass()..".") end
-- Only take damage during this phase.
if (GAMEMODE:GetRoundState() == GAMEMODE.States.Seek) then
if IsValid(ent) && (!(ent:IsPlayer())) then
if (ent:GetClass() == "ph_prop") then
ent:GetOwner():TakeDamageInfo(dmg)
self.Player.Data.RandomWeight = self.Player.Data.RandomWeight - 1
elseif (ent:GetClass() == "func_breakable") then -- ToDo: Make Configurable which entities don't hurt?
else
att:TakeDamage(GAMEMODE.Config.Seeker:HealthPenalty(), ent, ent)
end
end
end
end
-- Death
function CLASS:Death(inflictor, attacker)
BaseClass.Death(self, inflictor, attacker)
if SERVER then
self.Player:SetShouldServerRagdoll(true)
--self.Player:CreateRagdoll()
end
end
function CLASS:PostDeath()
if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") end
BaseClass.PostDeath(self, inflictor, attacker)
self.Player:UnLock()
end
function CLASS:CanSuicide()
return true
end
function CLASS:DeathThink()
if (CurTime() - self.Player.Data.AliveTime) > 1 then
self.Player:Spawn()
return true
end
return false
end
-- Visible Stuff
function CLASS:SetModel()
local cl_playermodel = self.Player:GetInfo( "cl_playermodel" )
local modelname = player_manager.TranslatePlayerModel( cl_playermodel )
if !(util.IsValidModel(modelname)) then
modelname = "models/player/combine_super_soldier.mdl"
end
util.PrecacheModel(modelname)
self.Player:SetModel(modelname)
-- Hands
self.Player:SetupHands()
end
-- Interaction
function CLASS:AllowPickup(ent) return true end
function CLASS:CanPickupItem(ent) return true end
function CLASS:CanPickupWeapon(ent) return true end
-- Menu Buttons
function CLASS:ShowSpare1()
if BaseClass.ShowSpare1(self) then return end
-- Play a taunt
local tauntList = GAMEMODE.Config.Taunt:Seekers()
local index = math.random(#tauntList)
self.Player:EmitSound(tauntList[index], SNDLVL_NORM, 100, 1, CHAN_VOICE)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") taunted with sound '"..tauntList[index].."'.") end
end
-- ------------------------------------------------------------------------- --
--! Client-Side
-- ------------------------------------------------------------------------- --
function CLASS:ClientSpawn()
if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt CL: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
BaseClass.ClientSpawn(self)
end
function CLASS:HUDPaint()
BaseClass.HUDPaint(self)
local State = GetGlobalInt("RoundState", GAMEMODE.States.PreMatch)
if (State == GAMEMODE.States.Hide) then
local intTime = math.ceil(GetGlobalInt("RoundTime"))
local strTime = tostring(intTime)
-- Show Status at the center
surface.SetTextColor( 255, 255, 255, 255 )
if (intTime >= 1) then
surface.SetFont("CloseCaption_Bold")
local w,h = surface.GetTextSize("Unblinded in "..strTime.." seconds...")
surface.SetTextPos( ScrW()/2 - w / 2, ScrH()/2 - h / 2)
surface.DrawText("Unblinded in "..strTime.." seconds...")
else
surface.SetFont("PHHugeAssFont")
local w,h = surface.GetTextSize("NOW")
surface.SetTextPos( ScrW()/2 - w / 2, ScrH()/2 - h / 2)
surface.DrawText("NOW")
end
end
end
function CLASS:ShouldDrawLocal()
return (self.Player.Data.ViewDistance or 0) >= 10
end
-- Register
player_manager.RegisterClass("Seeker", CLASS, "Default")
@@ -0,0 +1,86 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
DEFINE_BASECLASS("Default")
local CLASS = {}
CLASS.DisplayName = "Spectator"
CLASS.DuckSpeed = 0.0 -- How fast to go from not ducking, to ducking
CLASS.UnDuckSpeed = 0.0 -- How fast to go from ducking, to not ducking
CLASS.CanUseFlashlight = false -- Can we use the flashlight
CLASS.UseVMHands = false -- Uses viewmodel hands
-- ------------------------------------------------------------------------- --
--! Server-Side
-- ------------------------------------------------------------------------- --
-- Spawn
function CLASS:Spawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
BaseClass.Spawn(self)
self.Player:Spectate(OBS_MODE_ROAMING)
self.Player:SetRenderMode(RENDERMODE_NONE)
-- View Offset & Hull
GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,0), Vector(0,0,0))
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
end
-- Death
function CLASS:PostDeath(inflictor, attacker)
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") end
BaseClass.PostDeath(self, inflictor, attacker)
self.Player:Spectate(OBS_MODE_NONE)
self.Player:UnSpectate()
-- Hull
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
self.Player:SetRenderMode(RENDERMODE_NORMAL)
end
-- Visible Stuff
function CLASS:SetModel()
self.Player:SetModel("")
-- Hands
self.Player:SetupHands()
end
-- Interaction
function CLASS:Use(ent) return false end
function CLASS:AllowPickup(ent) return false end
function CLASS:CanPickupWeapon(ent) return false end
function CLASS:CanPickupItem(ent) return false end
-- ------------------------------------------------------------------------- --
--! Client-Side
-- ------------------------------------------------------------------------- --
function CLASS:ClientSpawn()
if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end
end
function CLASS:ShouldDrawLocal() return false end
function CLASS:CalcView(camdata) return camdata end
player_manager.RegisterClass( "Spectator", CLASS, "Default")
@@ -0,0 +1,549 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
--! Initialize configuration table.
GM.Config = { }
GM.Config.ConVars = {}
-- ------------------------------------------------------------------------- --
--! Basic Settings
-- ------------------------------------------------------------------------- --
-- Debug Mode
GM.Config.ConVars.Debug = CreateConVar("ph_debug", 0, FCVAR_CHEAT + FCVAR_REPLICATED)
function GM.Config:Debug()
return self.ConVars.Debug:GetBool()
end
-- Game Mode (See sh_init.lua)
GM.Config.ConVars.GameMode = CreateConVar("ph_gamemode", GM.Modes.Original, FCVAR_REPLICATED)
function GM.Config:GameMode()
return self.ConVars.GameMode:GetInt()
end
-- Timelimit in minutes
GM.Config.ConVars.TimeLimit = GetConVar("mp_timelimit")
function GM.Config:TimeLimit()
return self.ConVars.TimeLimit:GetFloat()
end
-- Enable Sprinting?
GM.Config.ConVars.Sprinting = CreateConVar("ph_sprinting", 0, FCVAR_REPLICATED)
function GM.Config:Sprinting()
return self.ConVars.Sprinting:GetBool()
end
-- Taunt Cooldown (Seconds)
GM.Config.ConVars.TauntCoolDown = CreateConVar("ph_tauntcooldown", 5, FCVAR_REPLICATED)
function GM.Config:TauntCoolDown()
return self.ConVars.TauntCoolDown:GetFloat()
end
-- ------------------------------------------------------------------------- --
--! Round Settings
-- ------------------------------------------------------------------------- --
GM.Config.Round = {}
GM.Config.Round.ConVars = {}
-- How many rounds should the gamemode attempt to fit into the map timelimit, if there is any?
GM.Config.Round.ConVars.Amount = CreateConVar("ph_round_limit", 10, FCVAR_REPLICATED)
function GM.Config.Round:Amount()
return self.ConVars.Amount:GetInt()
end
-- Round Time Limit (Seconds, Default 3 minutes)
GM.Config.Round.ConVars.Time = CreateConVar("ph_round_timelimit", 180, FCVAR_REPLICATED)
function GM.Config.Round:Time()
return self.ConVars.Time:GetInt() - GAMEMODE.Config.Round:BlindTime()
end
-- For how many seconds are the Seekers blinded? (Seconds)
GM.Config.Round.ConVars.BlindTime = CreateConVar("ph_round_blindtime", 30, FCVAR_REPLICATED, "How long are hunters blinded? (positive values will be inside the round time limit, negative will add to the round time limit)")
function GM.Config.Round:BlindTime()
return self.ConVars.BlindTime:GetInt()
end
-- ------------------------------------------------------------------------- --
--! Seeker Settings
-- ------------------------------------------------------------------------- --
GM.Config.Seeker = {}
GM.Config.Seeker.ConVars = {}
GM.Config.Seeker.ConVars.Health = CreateConVar("ph_seeker_health", 100, FCVAR_REPLICATED)
function GM.Config.Seeker:Health()
return self.ConVars.Health:GetInt()
end
GM.Config.Seeker.ConVars.HealthMax = CreateConVar("ph_seeker_health_max", 100, FCVAR_REPLICATED)
function GM.Config.Seeker:HealthMax()
return self.ConVars.HealthMax:GetInt()
end
GM.Config.Seeker.ConVars.HealthBonus = CreateConVar("ph_seeker_health_bonus", 20, FCVAR_REPLICATED)
function GM.Config.Seeker:HealthBonus()
return self.ConVars.HealthBonus:GetInt()
end
GM.Config.Seeker.ConVars.HealthPenalty = CreateConVar("ph_seeker_health_penalty", 5, FCVAR_REPLICATED)
function GM.Config.Seeker:HealthPenalty()
return self.ConVars.HealthPenalty:GetInt()
end
GM.Config.Seeker.ConVars.Weapons = CreateConVar("ph_seeker_weapons", "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun", FCVAR_REPLICATED)
function GM.Config.Seeker:Weapons()
return string.Split(self.ConVars.Weapons:GetString(), ",")
end
GM.Config.Seeker.ConVars.Ammo = CreateConVar("ph_seeker_ammo", "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64", FCVAR_REPLICATED)
function GM.Config.Seeker:Ammo()
return string.Split(self.ConVars.Ammo:GetString(), ",")
end
-- ------------------------------------------------------------------------- --
--! Hider Settings
-- ------------------------------------------------------------------------- --
GM.Config.Hider = {}
GM.Config.Hider.ConVars = {}
GM.Config.Hider.ConVars.Health = CreateConVar("ph_hider_health", 100, FCVAR_REPLICATED)
function GM.Config.Hider:Health()
return self.ConVars.Health:GetInt()
end
GM.Config.Hider.ConVars.HealthMax = CreateConVar("ph_hider_health_max", 100, FCVAR_REPLICATED)
function GM.Config.Hider:HealthMax()
return self.ConVars.HealthMax:GetInt()
end
GM.Config.Hider.ConVars.HealthScaling = CreateConVar("ph_hider_health_scaling", 100, FCVAR_REPLICATED)
function GM.Config.Hider:HealthScaling()
return self.ConVars.HealthScaling:GetBool()
end
GM.Config.Hider.ConVars.HealthScalingMax = CreateConVar("ph_hider_health_scaling_max", 200, FCVAR_REPLICATED)
function GM.Config.Hider:HealthScalingMax()
return self.ConVars.HealthScalingMax:GetInt()
end
-- ------------------------------------------------------------------------- --
--! Whitelist & Blacklist
-- ------------------------------------------------------------------------- --
GM.Config.Lists = {}
GM.Config.Lists.ConVars = {}
GM.Config.Lists.ConCmds = {}
GM.Config.Lists.ConVars.ClassWhitelist = CreateConVar("ph_list_class_whitelist", "prop_physics,prop_physics_multiplayer,prop_physics_respawnable", FCVAR_REPLICATED)
function GM.Config.Lists:ClassWhitelist()
return string.Split(self.ConVars.ClassWhitelist:GetString(), ",")
end
-- Use Abuse Blacklist
GM.Config.Lists.ConVars.AbuseBlacklist = CreateConVar("ph_list_abuse_blacklist", "func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable", FCVAR_REPLICATED)
function GM.Config.Lists:AbuseBlacklist()
return string.Split(self.ConVars.AbuseBlacklist:GetString(), ",")
end
-- Model Blacklist
GM.Config.Lists.ModelBlacklist = {}
GM.Config.Lists.ModelBlacklist["models/props/cs_assault/dollar.mdl"] = true
GM.Config.Lists.ModelBlacklist["models/props/cs_assault/money.mdl"] = true
GM.Config.Lists.ModelBlacklist["models/props/cs_office/snowman_arm.mdl"] = true
GM.Config.Lists.ModelBlacklist["models/props/cs_office/projector_remote.mdl"] = true
--GM.Config.Lists.ModelBlacklist["models/props_junk/garbage_plasticbottle001a.mdl"] = true
GM.Config.Lists.ConCmds.ModelBlacklistList = concommand.Add("ph_list_model_blacklist_list", function(ply, cmd, args, argStr)
print("Model Blacklist:")
for k,v in pairs(GAMEMODE.Config.Lists.ModelBlacklist) do
print(" "..k)
end
end, "List all blacklisted models.")
GM.Config.Lists.ConCmds.ModelBlacklistClear = concommand.Add("ph_list_model_blacklist_list", function(ply, cmd, args, argStr)
GM.Config.Lists.ModelBlacklist = {}
end, "Clear blacklisted models.")
GM.Config.Lists.ConCmds.ModelBlacklistAdd = concommand.Add("ph_list_model_blacklist_add", function(ply, cmd, args, argStr)
if (table.count(args) > 0) then
GAMEMODE.Config.Lists.ModelBlacklist[args[1]] = true
else
print("Missing model name")
end
end, "Add a new blacklisted model.")
GM.Config.Lists.ConCmds.ModelBlacklistRemove = concommand.Add("ph_list_model_blacklist_remove", function(ply, cmd, args, argStr)
if (table.count(args) > 0) then
GAMEMODE.Config.Lists.ModelBlacklist[args[1]] = nil
else
print("Missing model name")
end
end, "Removes a blacklisted model.")
-- ------------------------------------------------------------------------- --
--! Taunts
-- ------------------------------------------------------------------------- --
-- GM.Config.Taunts = {
-- Seeker = { },
-- Hider = { },
-- }
-- -- Taunts.Clear()
-- --@desc: Clears the current taunt list.
-- GM.Config.Taunts.Clear = function()
-- this.Seeker = {}
-- this.Hider = {}
-- end
-- -- Taunts.Load(sTauntListFile)
-- --@desc: Loads the taunt list from disk.
-- --@param:
-- -- sTauntListFile - A string containing the path to the taunt list to load.
-- --@return: true or false depending on success.
-- GM.Config.Taunts.Load = function(sTauntListFile)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Loading taunt list from file '"..sTauntListFile.."'...") end
-- -- Safeguard against idiots.
-- if type(sTauntListFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: <sTauntListFile> is not a string.") end
-- return false
-- end
-- -- Given file must exist for us to continue.
-- if ! file.Exists(sTauntListFile, "GAME") then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: File not found.") end
-- return false
-- end
-- -- Read the file and check if it's empty.
-- sTauntListData = file.Read(sTauntListFile, "GAME")
-- if sTauntListData == "" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: File is empty.") end
-- return false
-- end
-- -- Convert JSON to a table for us to use.
-- sTauntList = util.JSONToTable(sTauntListData)
-- -- Is it nil? Then it's not valid JSON
-- if sTauntList == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: File contains invalid JSON.") end
-- return false
-- end
-- -- Finally, append the taunt lists.
-- if sTauntList.Seeker != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Adding Seeker taunts...") end
-- for k,v in pairs(sTauntList.Seeker) do
-- GAMEMODE.Taunts.Seeker[k] = v
-- end
-- end
-- if sTauntList.Hider != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Adding Hider taunts...") end
-- for k,v in pairs(sTauntList.Hider) do
-- GAMEMODE.Taunts.Hider[k] = v
-- end
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Complete.") end
-- return true
-- end
-- -- Taunts.Save(sTauntListFile)
-- --@desc: Saves the current taunt list to disk.
-- --@param:
-- -- sTauntListFile - A string containing the path to the file to save to.
-- --@return: true or false depending on success.
-- GM.Config.Taunts.Save = function(sTauntListFile)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Saving taunt list to file '"..sTauntListFile.."'...") end
-- -- Safeguard against idiots.
-- if type(sTauntListFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: <sTauntListFile> is not a string.") end
-- return false
-- end
-- -- File must not be nil, otherwise we can't write to it.
-- if sTauntListFile == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: No file given.") end
-- return false
-- end
-- -- Convert our taunt table to JSON.
-- sTauntListData = util.TableToJSON(GAMEMODE.Taunts);
-- if sTauntListData == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Corrupted GAMEMODE table.") end
-- return false
-- end
-- -- Write out JSON out to file
-- if ! file.Write(sTauntListFile, sTauntListData) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Failed to write to file.") end
-- return false
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Complete.") end
-- return true
-- end
-- -- Taunts.Add(sTauntName, sSoundFile, iTeamID, mPropFilter)
-- --@desc: Registers a new taunt with the given name, file, team and filter.
-- --@param:
-- -- sTauntName - The unique name of the taunt.
-- -- sSoundFile - A sound file to play when this taunt is selected.
-- -- iTeamID - The team that should receive the taunt or nil for all teams.
-- -- mPropFilter - A string or a table containing strings for props that should be able to use this taunt.
-- --@return: true or false depending on success.
-- GM.Config.Taunts.Add = function(sTauntName, sSoundFile, iTeamID, mPropFilter)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Adding new taunt '"..sTauntName.."'...") end
-- -- Safeguard against idiots.
-- if type(sTauntName) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <sTauntName> is not a string.") end
-- return false
-- end
-- if type(sSoundFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <sSoundFile> is not a string.") end
-- return false
-- end
-- if (type(iTeamID) != "number" && iTeamID != nil) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <iTeamID> is not a number or nil.") end
-- return false
-- end
-- if (type(mPropFilter) != "string" && type(mPropFilter) != "table" && mPropFilter != nil) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <mPropFilter> is not a string, table or nil.") end
-- return false
-- end
-- -- Check if the sound file actually exists
-- if !file.Exists("sound/"..sSoundFile, "GAME") then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: File '"..sSoundFile.."' does not exist.") end
-- return false
-- end
-- -- Make sure that our prop filter is a table listing the props it's supposed to work for.
-- if (mPropFilter == nil) then
-- mPropFilter = { }
-- elseif type(mPropFilter) == "string" then
-- mPropFilter = { mPropFilter }
-- end
-- -- Prepare Taunt table
-- Taunt = {
-- File = sSoundFile,
-- Filter = mPropFilter
-- }
-- -- If iTeamID is nil, both teams will receive the taunt.
-- if iTeamID == nil then
-- GAMEMODE.Taunts.Seeker[sTauntName] = Taunt
-- GAMEMODE.Taunts.Hider[sTauntName] = Taunt
-- else
-- -- Make sure that the team is valid.
-- if ! team.Valid(iTeamID) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Team "..iTeamID.."' does not exist.") end
-- return false
-- end
-- if (iTeamID == TEAM_SEEKERS) then
-- GAMEMODE.Taunts.Seeker[sTauntName] = Taunt
-- elseif (iTeamID == TEAM_HIDERS) then
-- GAMEMODE.Taunts.Hider[sTauntName] = Taunt
-- else
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Team "..iTeamID.."' can't have taunts.") end
-- return false
-- end
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Complete.") end
-- return true
-- end
-- -- Taunts.Remove(sTauntName, iTeamID)
-- --@desc: Removes a registered taunt with the given name and team.
-- --@param:
-- -- sTauntName - The unique name of the taunt.
-- -- iTeamID - The team that the taunt should be removed from or nil for all teams.
-- --@return: true or false depending on success.
-- GM.Config.Taunts.Remove = function(sTauntName, iTeamID)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Removing taunt '"..sTauntName.."'...") end
-- -- Safeguard against idiots.
-- if type(sTauntName) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: <sTauntName> is not a string.") end
-- return false
-- end
-- if (type(iTeamID) != "number" && iTeamID != nil) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: <iTeamID> is not a number or nil.") end
-- return false
-- end
-- -- if iTeamID is nil, both teams will have the taunt removed.
-- if (iTeamID == nil) then
-- GAMEMODE.Taunts.Seeker[sTauntName] = nil
-- GAMEMODE.Taunts.Hider[sTauntName] = nil
-- else
-- -- Make sure we have a valid Team.
-- if ! team.Valid(iTeamID) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Team "..iTeamID.."' does not exist.") end
-- return false
-- end
-- if iTeamID == TEAM_SEEKERS then
-- GAMEMODE.Taunts.Seeker[sTauntName] = nil
-- elseif iTeamID == TEAM_HIDERS then
-- GAMEMODE.Taunts.Hider[sTauntName] = nil
-- else
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Team "..iTeamID.."' can't have taunts.") end
-- return false
-- end
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Complete.") end
-- return true
-- end
-- -- ToDo: Taunts.Get(iTeamID, sPropName)
-- --! Announcers (Round Start, Unblind, Win, Loss)
-- GM.Config.Announcers = {
-- Start = { },
-- Unblind = { },
-- Win = { },
-- Loss = { }
-- }
-- -- Announcers.Clear()
-- --@desc: Clears the current announcer list.
-- GM.Config.Announcers.Clear = function()
-- Announcers.Start = { }
-- Announcers.Unblind = { }
-- Announcers.Win = { }
-- Announcers.Loss = { }
-- end
-- -- Announcers.Load(sAnnouncerListFile)
-- --@desc: Tries to load the given announcer list.
-- --@param:
-- -- sAnnouncerListFile - A string containing the path to the announcer list to load.
-- --@return: true or false depending on success.
-- GM.Config.Announcers.Load = function(sAnnouncerListFile)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Loading announcer list from file '"..sAnnouncerListFile.."'...") end
-- -- Safeguard against idiots.
-- if type(sAnnouncerListFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: <sAnnouncerListFile> is not a string.") end
-- return false
-- end
-- -- Given file must exist for us to continue.
-- if ! file.Exists(sAnnouncerListFile, "GAME") then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: File not found.") end
-- return false
-- end
-- -- Read the file and check if it's empty.
-- sAnnouncerListData = file.Read(sAnnouncerListFile, "GAME")
-- if sAnnouncerListData == "" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: File is empty.") end
-- return false
-- end
-- -- Convert JSON to a table for us to use.
-- sAnnouncerList = util.JSONToTable(sAnnouncerListData)
-- -- Is it nil? Then it's not valid JSON
-- if sAnnouncerList == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: File contains invalid JSON.") end
-- return false
-- end
-- -- Finally, insert the announcer lists.
-- if sAnnouncerList.Start != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Start announcers...") end
-- for k,v in pairs(sAnnouncerList.Start) do
-- GAMEMODE.Announcers.Start[k] = v
-- end
-- end
-- if sAnnouncerList.Unblind != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Unblind announcers...") end
-- for k,v in pairs(sAnnouncerList.Unblind) do
-- GAMEMODE.Announcers.Unblind[k] = v
-- end
-- end
-- if sAnnouncerList.Win != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Win announcers...") end
-- for k,v in pairs(sAnnouncerList.Win) do
-- GAMEMODE.Announcers.Win[k] = v
-- end
-- end
-- if sAnnouncerList.Loss != nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Loss announcers...") end
-- for k,v in pairs(sAnnouncerList.Loss) do
-- GAMEMODE.Announcers.Loss[k] = v
-- end
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Complete.") end
-- return true
-- end
-- -- Announcers.Save(sAnnouncerListFile)
-- --@desc: Saves the current taunt list to disk.
-- --@param:
-- -- sAnnouncerListFile - A string containing the path to the file to save to.
-- --@return: true or false depending on success.
-- GM.Config.Announcers.Save = function(sAnnouncerListFile)
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Saving announcer list to file '"..sAnnouncerListFile.."'...") end
-- -- Safeguard against idiots.
-- if type(sAnnouncerListFile) != "string" then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: <sAnnouncerListFile> is not a string.") end
-- return false
-- end
-- -- File must not be nil, otherwise we can't write to it.
-- if sAnnouncerListFile == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: No file given.") end
-- return false
-- end
-- -- Convert our taunt table to JSON.
-- sAnnouncerListData = util.TableToJSON(GAMEMODE.Announcers);
-- if sAnnouncerListData == nil then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Corrupted GAMEMODE table.") end
-- return false
-- end
-- -- Write out JSON out to file
-- if ! file.Write(sAnnouncerListFile, sAnnouncerListData) then
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Failed to write to file.") end
-- return false
-- end
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Complete.") end
-- return true
-- end
-- -- ToDo: Announcers.Add
-- -- ToDo: Announcers.Remove
-- -- ToDo: Announcers.Get(iType)
@@ -0,0 +1,63 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
GM.RoundManager = {}
GM.RoundManager.State = nil;
GM.RoundManager.NextState = nil;
function GM.RoundManager:Tick(...)
if (self.State != nil) then
if (self.State.Tick != nil) then
self.State:Tick(...)
end
end
-- Advance States
if (self.NextState != self.State) then
-- Call OnLeave(NewState)
if (self.State != nil) then
if (self.State.OnLeave != nil) then
self.State:OnLeave(self.NextState)
end
end
-- Call OnEnter(OldState)
if (self.NextState != nil) then
if (self.NextState.OnEnter != nil) then
self.NextState:OnEnter(self.State)
end
end
-- Set State
self.State = self.NextState
end
end
function GM.RoundManager:GetState()
return self.State
end
function GM.RoundManager:SetState(State)
self.NextState = State
end
@@ -0,0 +1,65 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
StateHide = {}
function StateHide:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StateHide: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.Hide)
-- Round Data
GAMEMODE.Data.RoundTime = math.abs(GAMEMODE.Config.Round:BlindTime())
GAMEMODE.Data.RoundStartTime = CurTime()
GAMEMODE:SetRoundTime(GAMEMODE.Data.RoundTime)
end
function StateHide:Tick()
-- Update Game Time
GAMEMODE.Data.RoundTime = math.abs(GAMEMODE.Config.Round:BlindTime()) - (CurTime() - GAMEMODE.Data.RoundStartTime)
GAMEMODE:SetRoundTime(GAMEMODE.Data.RoundTime)
-- Advance to Seeking State
if (GAMEMODE.Data.RoundTime <= 0) then
if GAMEMODE.Config:Debug() then print("StateHide: Advancing to Seek stage.") end
GAMEMODE.RoundManager:SetState(StateSeek)
end
-- Freeze Seekers
for i, ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do
ply:Freeze(true)
ply:Lock()
ply:ScreenFade(SCREENFADE.IN, color_black, 1, 9999)
end
-- ToDo: Logic for more game modes here?
end
function StateHide:OnLeave(NewState)
if GAMEMODE.Config:Debug() then print("StateHide: OnLeave") end
-- Fretta Hooks
hook.Run("PropHuntUnblind")
end
@@ -0,0 +1,54 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
StatePostMatch = {}
function StatePostMatch:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StatePostMatch: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PostMatch)
self.NextState = StatePreMatch
-- Check Change map conditions.
if ((GAMEMODE.Config:TimeLimit() > 0) && ((CurTime() - GAMEMODE.Data.StartTime) >= (GAMEMODE.Config:TimeLimit() * 60))) -- Over Time
|| (GAMEMODE:GetRound() >= GAMEMODE.Config.Round:Limit()) -- Over Round Limit
then
-- Advance to nothing
GAMEMODE:SetRoundState(-1)
self.NextState = nil
-- MapVote
if (MapVote != nil) then MapVote.Start(30, true, 30, "ph_") return end
end
end
function StatePostMatch:Tick()
-- Advance State
GAMEMODE.RoundManager:SetState(self.NextState)
end
function StatePostMatch:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StatePostMatch: OnLeave") end
end
@@ -0,0 +1,142 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
StatePostRound = {}
function StatePostRound:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StatePostRound: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PostRound)
GAMEMODE.Data.RoundStartTime = CurTime()
-- Fretta Hooks
hook.Run("RoundEnd")
end
function StatePostRound:Tick()
-- Advance State
if (CurTime() - GAMEMODE.Data.RoundStartTime) >= 5 then -- ToDo: configureable time?
GAMEMODE.RoundManager:SetState(StatePostMatch)
local players = team.GetPlayers(GAMEMODE.Teams.Seekers)
table.Add(players, team.GetPlayers(GAMEMODE.Teams.Hiders))
-- Assign end of round weighted points.
local aliveSeekers = 0
local aliveHiders = 0
for i,ply in ipairs(players) do
if ply:Alive() then
if (ply:Team() == GAMEMODE.Teams.Hiders) then
aliveHiders = aliveHiders + 1
elseif (ply:Team() == GAMEMODE.Teams.Seekers) then
aliveSeekers = aliveSeekers + 1
end
end
end
for i,ply in ipairs(players) do
local score = 0
if (ply:Team() == GAMEMODE:GetRoundWinner()) then
if (ply:Alive()) then
score = 2
else
score = 1
end
if (ply:Team() == GAMEMODE.Teams.Hiders) then
score = score * aliveHiders
elseif (ply:Team() == GAMEMODE.Teams.Seekers) then
score = -1 * score * aliveSeekers
end
end
ply.Data.RandomWeight = ply.Data.RandomWeight + score
end
-- Team Distribution
if (GAMEMODE.Config.Teams:Weighted() == true) then
-- Weighted Teams
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Randomizing Teams using weighted Score.") end
-- table.sort function returns true if it should a should be before b.
table.sort(players, function(a, b)
if (a.Data.RandomWeight == b.Data.RandomWeight) then
return math.random(100) > 50
else
return a.Data.RandomWeight > b.Data.RandomWeight
end
end)
elseif (GAMEMODE.Config.Teams:Randomize() == true) then
-- Randomize Teams
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Randomizing Teams.") end
table.sort(players, function(a,b)
return math.random(100) > 50
end)
else
-- Swap Teams
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Swapping Teams.") end
table.sort(players, function(a,b)
return math.random(100) > 50
end)
table.sort(players, function(a,b)
if (b:Team() == GAMEMODE.Teams.Seekers) then
return (a:Team() == GAMEMODE.Teams.Hiders)
end
return false
end)
end
-- Team Distribution Logic
local hiders, seekers = {}, {}
if (GAMEMODE.Config:GameType() == GAMEMODE.Types.Original) then
-- Game Mode: Basic
local plyCount, finalPlyCount = #players, math.max(math.ceil(#players / 2), 1)
for c = 1,finalPlyCount do
seekers[c] = table.remove(players, 1)
end
hiders = players
elseif (GAMEMODE.Config:GameType() == GAMEMODE.Types.TheDeadHunt) then
-- Game Mode: The Dead Hunt
local plyCount, finalPlyCount = #players, math.max(math.ceil(#players * GAMEMODE.Config.Teams:SeekerPercentage()), 1)
for c = 1,finalPlyCount do
seekers[c] = table.remove(players, 1)
end
hiders = players
end
-- Kill & Assign Teams
for i, ply in ipairs(hiders) do
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Assigned '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") to Team Hiders.") end
ply:KillSilent()
ply:SetTeam(GAMEMODE.Teams.Hiders)
end
for i, ply in ipairs(seekers) do
if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Assigned '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") to Team Seekers.") end
ply:KillSilent()
ply:SetTeam(GAMEMODE.Teams.Seekers)
end
end
end
function StatePostRound:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StatePostRound: OnLeave") end
end
@@ -0,0 +1,55 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- Precache Network Message
StatePreMatch = {}
function StatePreMatch:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StatePreMatch: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PreMatch)
math.randomseed(CurTime())
end
function StatePreMatch:Tick()
-- Debug: Auto Advance to PreRound State
if (GAMEMODE.Config:Debug()) then
if GAMEMODE.Config:DebugLog() then print("StatePreMatch: Advancing to StatePreRound") end
GAMEMODE.RoundManager:SetState(StatePreRound)
end
-- Game Mode: Basic
if (GAMEMODE.Config:GameType() == GAMEMODE.Types.Original) then
-- Both Teams must have at least 1 player.
if ((team.NumPlayers(GAMEMODE.Teams.Seekers) >= 1) && (team.NumPlayers(GAMEMODE.Teams.Hiders) >= 1)) then
GAMEMODE.RoundManager:SetState(StatePreRound)
if GAMEMODE.Config:DebugLog() then print("StatePreMatch: <Original> Have enough players to start match.") end
end
-- TODO: Other Gamemodes
end
end
function StatePreMatch:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StatePreMatch: OnLeave") end
end
@@ -0,0 +1,61 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
StatePreRound = {}
function StatePreRound:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StatePreRound: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.PreRound)
GAMEMODE:SetRound(GAMEMODE:GetRound() + 1)
-- Clean Up the Map
game.CleanUpMap()
end
function StatePreRound:Tick()
-- Advance State
GAMEMODE.RoundManager:SetState(StateHide)
end
function StatePreRound:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StatePreRound: OnLeave") end
-- Respawn Everyone
for i, ply in ipairs(player.GetAll()) do
ply:KillSilent()
ply.Data.Alive = true
ply:Spawn()
ply:ScreenFade(SCREENFADE.PURGE, color_black, 0, 0)
ply:ScreenFade(SCREENFADE.IN, color_black, 1, 0)
-- Weighted Score: Adjust towards other Team.
if (ply:Team() == GAMEMODE.Teams.Hiders) then
ply.Data.RandomWeight = ply.Data.RandomWeight + 1
elseif (ply:Team() == GAMEMODE.Teams.Seekers) then
ply.Data.RandomWeight = ply.Data.RandomWeight - 1
end
end
-- Fretta Hooks
hook.Run("RoundStart")
end
@@ -0,0 +1,95 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
StateSeek = {}
function StateSeek:OnEnter(OldState)
if GAMEMODE.Config:DebugLog() then print("StateSeek: OnEnter") end
GAMEMODE:SetRoundState(GAMEMODE.States.Seek)
-- Round Data
GAMEMODE.Data.RoundTime = GAMEMODE.Config.Round:Time()
-- Unfreeze Seekers
for i, ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do
ply:Freeze(false)
ply:UnLock()
ply:ScreenFade(SCREENFADE.PURGE, color_black, 0, 0)
ply:ScreenFade(SCREENFADE.IN, color_black, 1, 0)
end
end
function StateSeek:Tick()
-- Update Game Time
GAMEMODE.Data.RoundTime = GAMEMODE.Config.Round:Time() - (CurTime() - GAMEMODE.Data.RoundStartTime)
GAMEMODE:SetRoundTime(GAMEMODE.Data.RoundTime)
-- Victory Conditions
local hiders, seekers = team.GetPlayers(GAMEMODE.Teams.Hiders), team.GetPlayers(GAMEMODE.Teams.Seekers)
local hiderAlive, seekerAlive = false, false
if GAMEMODE.Config:Debug() then
hiderAlive = true;seekerAlive = true
end
for i,ply in ipairs(hiders) do
if (ply.Data.Alive) then
hiderAlive = true
end
end
for i,ply in ipairs(seekers) do
if (ply.Data.Alive) then
seekerAlive = true
end
end
if (hiderAlive == false) then
if (seekerAlive == false) then -- Draw, both teams dead.
GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Spectators)
GAMEMODE.RoundManager:SetState(StatePostRound)
else -- Seeker victory, Hiders dead
GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Seekers)
GAMEMODE.RoundManager:SetState(StatePostRound)
end
else
if (seekerAlive == false) then -- Hider Victory, Seeker dead.
GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Hiders)
GAMEMODE.RoundManager:SetState(StatePostRound)
else
if (GAMEMODE.Data.RoundTime <= 0) then -- No Time remaining
GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Hiders)
GAMEMODE.RoundManager:SetState(StatePostRound)
end
end
end
end
function StateSeek:OnLeave(NewState)
if GAMEMODE.Config:DebugLog() then print("StateSeek: OnLeave") end
if GAMEMODE:GetRoundWinner() == GAMEMODE.Teams.Seekers then
hook.Run("RoundVictorySeeker")
elseif GAMEMODE:GetRoundWinner() == GAMEMODE.Teams.Hiders then
hook.Run("RoundVictoryHider")
else
hook.Run("RoundVictoryDraw")
end
end
@@ -0,0 +1,464 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
--! Initialize configuration table.
GM.Config = { }
GM.Config.ConVars = {}
function CreateConVarIfNotExists(name, value, flags, helptext)
cv = GetConVar(name)
if (cv == nil) then
cv = CreateConVar(name, value, flags, helptext)
-- else
-- ncv = CreateConVar(name, value, flags, helptext)
end
return cv
end
-- ------------------------------------------------------------------------- --
--! Debug Settings
-- ------------------------------------------------------------------------- --
-- Debug Mode
GM.Config.ConVars.Debug = CreateConVarIfNotExists("ph_debug", "0", FCVAR_CHEAT + FCVAR_REPLICATED, "Prop Hunt: Enable Debug Mode")
function GM.Config:Debug()
return self.ConVars.Debug:GetBool()
end
-- Debug Log
GM.Config.ConVars.DebugLog = CreateConVarIfNotExists("ph_debug_log", "0", FCVAR_REPLICATED, "Prop Hunt: Enable Debug Logging")
function GM.Config:DebugLog()
return self.ConVars.DebugLog:GetBool()
end
-- ------------------------------------------------------------------------- --
--! Basic Settings
-- ------------------------------------------------------------------------- --
-- Game Mode (See sh_init.lua)
GM.Config.ConVars.GameType = CreateConVarIfNotExists("ph_gametype", GM.Types.Original, FCVAR_REPLICATED, "Prop Hunt: Which Game Type should be played? ("..GM.Types.Original.." = Original Prop Hunt, "..GM.Types.TheDeadHunt.." = The Dead Hunt Mode)")
function GM.Config:GameType()
return self.ConVars.GameType:GetInt()
end
-- Timelimit in minutes
GM.Config.ConVars.TimeLimit = CreateConVarIfNotExists("mp_timelimit", "20", FCVAR_REPLICATED, "Map Time Limit (in Minutes)")
function GM.Config:TimeLimit()
return self.ConVars.TimeLimit:GetFloat()
end
-- ------------------------------------------------------------------------- --
--! Round Settings
-- ------------------------------------------------------------------------- --
GM.Config.Round = {}
GM.Config.Round.ConVars = {}
-- How many rounds should the GM attempt to fit into the map timelimit, if there is any?
GM.Config.Round.ConVars.Limit = CreateConVarIfNotExists("ph_round_limit", "10", FCVAR_REPLICATED, "Round Manager: Maximum Rounds to Play on a single Map")
function GM.Config.Round:Limit()
return self.ConVars.Limit:GetInt()
end
-- Round Time Limit (Seconds, Default 3 minutes)
GM.Config.Round.ConVars.Time = CreateConVarIfNotExists("ph_round_timelimit", "180", FCVAR_REPLICATED, "Round Manager: Time Limit per Round (in Seconds)")
function GM.Config.Round:Time()
return math.max(self.ConVars.Time:GetFloat() - math.min(self:BlindTime(),0),0)
end
-- For how many seconds are the Seekers blinded? (Seconds)
GM.Config.Round.ConVars.BlindTime = CreateConVarIfNotExists("ph_round_blindtime", "-30", FCVAR_REPLICATED, "Round Manager: Blind Time for Seekers (in Seconds, positive takes away from ph_round_timelimit, negative adds extra time to ph_round_timelimit")
function GM.Config.Round:BlindTime()
return self.ConVars.BlindTime:GetFloat()
end
-- ------------------------------------------------------------------------- --
--! Team Settings
-- ------------------------------------------------------------------------- --
GM.Config.Teams = {}
GM.Config.Teams.ConVars = {}
-- Should teams be ranomized each round?
GM.Config.Teams.ConVars.Randomize = CreateConVarIfNotExists("ph_teams_randomize", "0", FCVAR_REPLICATED, "Teams: Randomize Each Round")
function GM.Config.Teams:Randomize()
return self.ConVars.Randomize:GetBool()
end
-- Should teams be using weighted randomization?
-- Weighted randomization works by using a score calculated over the entire session.
-- * Round Start: Adjust Score towards the other Team by 1 (Positive = Seeker, Negative = Hider)
-- * Round Win: Adjust score by how many players are still alive on the winning team towards the other team.
-- * Alive players get double the score.
GM.Config.Teams.ConVars.Weighted = CreateConVarIfNotExists("ph_teams_weighted", "1", FCVAR_REPLICATED, "Teams: Use Weighted Randomization")
function GM.Config.Teams:Weighted()
return self.ConVars.Weighted:GetBool()
end
-- The Dead Hunt: Percent of players to assign to seeker.
GM.Config.Teams.ConVars.SeekerPercentage = CreateConVarIfNotExists("ph_teams_seekerpct", "25", FCVAR_REPLICATED, "Teams: Initial percentage of Seekers in Dead Hunt Game Type")
function GM.Config.Teams:SeekerPercentage()
return self.ConVars.Teams:GetFloat() / 100
end
-- ------------------------------------------------------------------------- --
--! Seeker Settings
-- ------------------------------------------------------------------------- --
GM.Config.Seeker = {}
GM.Config.Seeker.ConVars = {}
GM.Config.Seeker.ConVars.Health = CreateConVarIfNotExists("ph_seeker_health", "100", FCVAR_REPLICATED, "Seekers: Initial Health")
function GM.Config.Seeker:Health()
return self.ConVars.Health:GetInt()
end
GM.Config.Seeker.ConVars.HealthMax = CreateConVarIfNotExists("ph_seeker_health_max", "100", FCVAR_REPLICATED, "Seekers: Maximum Health")
function GM.Config.Seeker:HealthMax()
return self.ConVars.HealthMax:GetInt()
end
GM.Config.Seeker.ConVars.HealthBonus = CreateConVarIfNotExists("ph_seeker_health_bonus", "20", FCVAR_REPLICATED, "Seekers: Health Bonus per Kill")
function GM.Config.Seeker:HealthBonus()
return self.ConVars.HealthBonus:GetInt()
end
GM.Config.Seeker.ConVars.HealthPenalty = CreateConVarIfNotExists("ph_seeker_health_penalty", "5", FCVAR_REPLICATED, "Seekers: Health Penalty per wrong Shot")
function GM.Config.Seeker:HealthPenalty()
return self.ConVars.HealthPenalty:GetInt()
end
GM.Config.Seeker.ConVars.Weapons = CreateConVarIfNotExists("ph_seeker_weapons", "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun", FCVAR_REPLICATED, "Seekers: Initial Weapons (Weapon,Weapon,...)")
function GM.Config.Seeker:Weapons()
return string.Split(self.ConVars.Weapons:GetString(), ",")
end
GM.Config.Seeker.ConVars.Ammo = CreateConVarIfNotExists("ph_seeker_ammo", "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64", FCVAR_REPLICATED, "Seekers: Initial Ammo (Ammo:Amount,Ammo:Amount,...)")
function GM.Config.Seeker:Ammo()
return string.Split(self.ConVars.Ammo:GetString(), ",")
end
GM.Config.Seeker.ConVars.WalkSpeed = CreateConVarIfNotExists("ph_seeker_walk_speed", "250", 0, "Seekers: Walk Speed")
function GM.Config.Seeker:WalkSpeed()
return self.ConVars.WalkSpeed:GetFloat()
end
GM.Config.Seeker.ConVars.Sprint = CreateConVarIfNotExists("ph_seeker_sprint", "1", FCVAR_REPLICATED, "Seekers: Allow Sprinting")
function GM.Config.Seeker:Sprint()
return self.ConVars.Sprint:GetBool()
end
GM.Config.Seeker.ConVars.SprintSpeed = CreateConVarIfNotExists("ph_seeker_sprint_speed", "500", 0, "Seekers: Sprint Speed")
function GM.Config.Seeker:SprintSpeed()
return self.ConVars.SprintSpeed:GetFloat()
end
GM.Config.Seeker.ConVars.JumpPower = CreateConVarIfNotExists("ph_seeker_jump_power", "200", 0, "Seekers: Jump Power")
function GM.Config.Seeker:JumpPower()
return self.ConVars.JumpPower:GetFloat()
end
-- ------------------------------------------------------------------------- --
--! Hider Settings
-- ------------------------------------------------------------------------- --
GM.Config.Hider = {}
GM.Config.Hider.ConVars = {}
GM.Config.Hider.ConVars.Health = CreateConVarIfNotExists("ph_hider_health", "100", FCVAR_REPLICATED, "Hiders: Initial Health")
function GM.Config.Hider:Health()
return self.ConVars.Health:GetInt()
end
GM.Config.Hider.ConVars.HealthMax = CreateConVarIfNotExists("ph_hider_health_max", "100", FCVAR_REPLICATED, "Hiders: Maximum Health")
function GM.Config.Hider:HealthMax()
return self.ConVars.HealthMax:GetInt()
end
GM.Config.Hider.ConVars.HealthScaling = CreateConVarIfNotExists("ph_hider_health_scaling", "1", FCVAR_REPLICATED, "Hiders: Enable Health Scaling")
function GM.Config.Hider:HealthScaling()
return self.ConVars.HealthScaling:GetBool()
end
GM.Config.Hider.ConVars.HealthScalingMax = CreateConVarIfNotExists("ph_hider_health_scaling_max", "200", FCVAR_REPLICATED, "Hiders: Maximum scaled Health")
function GM.Config.Hider:HealthScalingMax()
return self.ConVars.HealthScalingMax:GetInt()
end
GM.Config.Hider.ConVars.AllowFullRotation = CreateConVarIfNotExists("ph_hider_allow_full_rotation", "0", FCVAR_REPLICATED, "Hiders: Enable full 3D Rotation")
function GM.Config.Hider:AllowFullRotation()
return self.ConVars.AllowFullRotation:GetBool()
end
GM.Config.Hider.ConVars.WalkSpeed = CreateConVarIfNotExists("ph_hider_walk_speed", "250", 0, "Hiders: Walk Speed")
function GM.Config.Hider:WalkSpeed()
return self.ConVars.WalkSpeed:GetFloat()
end
GM.Config.Hider.ConVars.Sprint = CreateConVarIfNotExists("ph_hider_sprint", "0", FCVAR_REPLICATED, "Hiders: Allow Sprinting")
function GM.Config.Hider:Sprint()
return self.ConVars.Sprint:GetBool()
end
GM.Config.Hider.ConVars.SprintSpeed = CreateConVarIfNotExists("ph_hider_sprint_speed", "500", 0, "Hiders: Sprint Speed")
function GM.Config.Hider:SprintSpeed()
return self.ConVars.SprintSpeed:GetFloat()
end
GM.Config.Hider.ConVars.JumpPower = CreateConVarIfNotExists("ph_hider_jump_power", "200", 0, "Hiders: Jump Power")
function GM.Config.Hider:JumpPower()
return self.ConVars.JumpPower:GetFloat()
end
-- ------------------------------------------------------------------------- --
--! Whitelist & Blacklist
-- ------------------------------------------------------------------------- --
GM.Config.Lists = {}
GM.Config.Lists.ConVars = {}
-- Class Whitelist
GM.Config.Lists.ConVars.ClassWhitelist = CreateConVarIfNotExists("ph_list_class_whitelist", "prop_physics,prop_physics_multiplayer,prop_physics_respawnable", FCVAR_REPLICATED, "Anti-Cheat: Whitelisted Hider Classes")
function GM.Config.Lists:ClassWhitelist()
local str = self.ConVars.ClassWhitelist:GetString()
if (self.ClassWhitelistCache != str) then
self.ClassWhitelistCache = str
self.ClassWhitelistCacheTbl = string.Split(self.ClassWhitelistCache, ",")
end
return self.ClassWhitelistCacheTbl
end
-- Abuse Blacklist
GM.Config.Lists.ConVars.AbuseBlacklist = CreateConVarIfNotExists("ph_list_abuse_blacklist", "func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable", FCVAR_REPLICATED, "Anti-Cheat: Entity Abuse Blacklist")
function GM.Config.Lists:AbuseBlacklist()
local str = self.ConVars.AbuseBlacklist:GetString()
if (self.AbuseBlacklistCache != str) then
self.AbuseBlacklistCache = str
self.AbuseBlacklistCacheTbl = string.Split(self.AbuseBlacklistCache, ",")
end
return self.AbuseBlacklistCacheTbl
end
-- Model Blacklist
GM.Config.Lists.ConVars.ModelBlacklist = CreateConVarIfNotExists("ph_list_model_blacklist", "models/props/cs_assault/dollar.mdl,models/props/cs_assault/money.mdl,models/props/cs_office/snowman_arm.mdl,models/props/cs_office/projector_remote.mdl", FCVAR_REPLICATED, "Anti-Cheat: Model Abuse Blacklist")
function GM.Config.Lists:ModelBlacklist()
local str = self.ConVars.ModelBlacklist:GetString()
if (self.ModelBlacklistCache != str) then
self.ModelBlacklistCache = str
self.ModelBlacklistCacheTbl = string.Split(self.ModelBlacklistCache, ",")
end
return self.ModelBlacklistCacheTbl
end
-- ------------------------------------------------------------------------- --
--! Taunts
-- ------------------------------------------------------------------------- --
GM.Config.Taunt = {}
GM.Config.Taunt.ConVars = {}
-- Cooldown (Seconds)
GM.Config.Taunt.ConVars.Cooldown = CreateConVarIfNotExists("ph_taunt_cooldown", 5, FCVAR_REPLICATED, "Prop Hunt: Cooldown between Taunts")
function GM.Config.Taunt:Cooldown()
return self.ConVars.Cooldown:GetFloat()
end
-- Seeker
GM.Config.Taunt.SeekersCache = ""
GM.Config.Taunt.SeekersCacheDynamic = nil
GM.Config.Taunt.SeekersCacheStatic = nil
GM.Config.Taunt.SeekersCacheFull = nil
GM.Config.Taunt.ConVars.Seekers = CreateConVarIfNotExists("ph_taunt_seekers", "bot/a_bunch_of_them.wav,bot/come_out_and_fight_like_a_man.wav,bot/come_out_wherever_you_are.wav,bot/come_to_papa.wav,bot/dont_worry_hell_get_it.wav,bot/hang_on_i_heard_something.wav,bot/hang_on_im_coming.wav,bot/i_dont_think_so.wav,bot/i_have_the_hostages.wav,bot/i_see_our_target.wav,bot/im_waiting_here.wav,bot/keeping_an_eye_on_the_hostages.wav,bot/nnno_sir.wav,bot/spotted_the_delivery_boy.wav,bot/target_acquired.wav,bot/target_spotted.wav,bot/you_heard_the_man_lets_go.wav", 0, "Prop Hunt: Seeker Taunts")
function GM.Config.Taunt:Seekers()
local str = self.ConVars.Seekers:GetString()
if (self.SeekersCache != str) then
self.SeekersCache = str
self.SeekersCacheDynamic = string.Split(self.SeekersCache, ",")
self.SeekersCacheFull = table.Add(self.SeekersCacheDynamic, self.SeekersCacheStatic)
for i,snd in ipairs(self.SeekersCacheFull) do
util.PrecacheSound(snd)
end
end
return self.SeekersCacheFull
end
-- Hider
GM.Config.Taunt.HidersCache = ""
GM.Config.Taunt.HidersCacheDynamic = nil
GM.Config.Taunt.HidersCacheStatic = nil
GM.Config.Taunt.HidersCacheFull = nil
GM.Config.Taunt.ConVars.Hiders = CreateConVarIfNotExists("ph_taunt_hiders", "ambient/alarms/apc_alarm_pass1.wav,ambient/alarms/manhack_alert_pass1.wav,ambient/alarms/razortrain_horn1.wav,ambient/alarms/scanner_alert_pass1.wav,ambient/alarms/train_horn2.wav,ambient/alarms/train_horn_distant1.wav,ambient/alarms/warningbell1.wav,ambient/energy/whiteflash.wav,ambient/intro/alyxremove.wav,ambient/intro/logosfx.wav,ambient/levels/launch/1stfiringwarning.wav,ambient/levels/launch/rockettakeoffblast.wav,ambient/misc/ambulance1.wav,ambient/misc/carhonk1.wav,ambient/misc/carhonk2.wav,ambient/misc/carhonk3.wav,ambient/outro/gunshipcrash.wav,ambient/3dmeagle.wav,beams/beamstart5.wav,buttons/bell1.wav,buttons/weapon_cant_buy.wav,common/bass.wav,common/bugreporter_failed.wav,common/warning.wav,doors/door_squeek1.wav,friends/friend_join.wav,friends/friend_online.wav,friends/message.wav,hostage/hunuse/comeback.wav,hostage/hunuse/dontleaveme.wav,hostage/hunuse/yeahillstay.wav,items/gift_drop.wav,music/radio1.mp3,phx/eggcrack.wav,plats/elevbell1.wav,player/headshot1.wav,player/headshot2.wav,player/sprayer.wav,radio/enemydown.wav,radio/go.wav,radio/locknload.wav,radio/negative.wav,radio/rounddraw.wav,radio/takepoint.wav,resource/warning.wav,ui/achievement_earned.wav,ui/freeze_cam.wav,vehicles/junker/radar_ping_friendly1.wav,weapons/c4/c4_beep1.wav,weapons/c4/c4_click.wav,weapons/awp/awp1.wav,vo/canals/female01/gunboat_giveemhell.wav,vo/canals/female01/gunboat_justintime.wav,vo/canals/female01/stn6_incoming.wav,vo/canals/male01/gunboat_giveemhell.wav,vo/canals/male01/gunboat_justintime.wav,vo/canals/male01/stn6_incoming.wav,vo/canals/al_radio_stn6.wav,vo/canals/arrest_getgoing.wav,vo/canals/arrest_helpme.wav,vo/canals/arrest_lookingforyou.wav,vo/canals/boxcar_lethimhelp.wav,vo/canals/matt_closecall.wav,vo/canals/premassacre.wav,vo/ravenholm/aimforhead.wav,vo/ravenholm/bucket_patience.wav,vo/ravenholm/madlaugh01.wav,vo/ravenholm/madlaugh02.wav,vo/ravenholm/madlaugh03.wav,vo/ravenholm/madlaugh04.wav,weapons/strider_buster/ol12_stickybombcreator.wav,weapons/c4/c4_explode1.wav,weapons/357/357_fire2.wav,weapons/357/357_fire3.wav,weapons/scout/scout_fire-1.wav,weapons/smokegrenade/sg_explode.wav,weapons/grenade_launcher1.wav,weapons/explode3.wav,weapons/underwater_explode3.wav,items/nvg_on.wav,hostage/huse/letsdoit.wav,hostage/huse/illfollow.wav,hostage/huse/getouttahere.wav,doors/door_screen_move1.wav,doors/heavy_metal_stop1.wav,doors/default_move.wav,common/stuck2.wav,ambient/water_splash1.wav,ambient/water_splash2.wav,ambient/water_splash3.wav,ambient/weather/thunder1.wav,ambient/weather/thunder2.wav,ambient/weather/thunder3.wav,ambient/weather/thunder4.wav,ambient/weather/thunder5.wav,ambient/weather/thunder6.wav,ambient/outro/thunder7.wav,ambient/voices/crying_loop1.wav,ambient/voices/playground_memory.wav,ambient/voices/f_scream1.wav,ambient/voices/m_scream1.wav,ambient/voices/cough1.wav,ambient/voices/cough2.wav,ambient/voices/cough3.wav,ambient/voices/cough4.wav,ambient/overhead/plane1.wav,ambient/overhead/plane2.wav,ambient/overhead/plane3.wav,ambient/overhead/hel1.wav,ambient/overhead/hel2.wav,ambient/misc/truck_backup1.wav,ambient/misc/truck_drive1.wav,ambient/misc/truck_drive2.wav,ambient/machines/pneumatic_drill_1.wav,ambient/machines/pneumatic_drill_2.wav,ambient/machines/pneumatic_drill_3.wav,ambient/machines/pneumatic_drill_4.wav,ambient/machines/station_train_squeel.wav,ambient/machines/ticktock.wav,ambient/creatures/teddy.wav,ambient/creatures/town_child_scream1.wav,ambient/creatures/town_moan1.wav,ambient/creatures/town_muffled_cry1.wav,ambient/creatures/town_scared_breathing1.wav,ambient/creatures/town_scared_breathing2.wav,ambient/creatures/town_scared_sob1.wav,ambient/creatures/town_scared_sob2.wav,ambient/creatures/town_zombie_call1.wav", 0, "Prop Hunt: Hider Taunts")
function GM.Config.Taunt:Hiders()
local str = self.ConVars.Hiders:GetString()
if (self.HidersCacheDynamic == nil)
|| (self.HidersCache != str) then
self.HidersCache = str
self.HidersCacheDynamic = string.Split(self.HidersCache, ",")
self.HidersCacheFull = table.Add(self.HidersCacheDynamic, self.HidersCacheStatic)
for i,snd in ipairs(self.HidersCacheFull) do
util.PrecacheSound(snd)
end
end
return self.HidersCacheFull
end
-- ------------------------------------------------------------------------- --
--! Announcers
-- ------------------------------------------------------------------------- --
-- --! Announcers (Round Start, Unblind, Win, Loss)
-- GM.Config.Announcers = {
-- Start = { },
-- Unblind = { },
-- Win = { },
-- Loss = { }
-- }
-- ------------------------------------------------------------------------- --
--! Camera
-- ------------------------------------------------------------------------- --
GM.Config.Camera = {}
GM.Config.Camera.ConVars = {}
-- Allow Camera No Clip
GM.Config.Camera.ConVars.AllowNoClip = CreateConVarIfNotExists("ph_camera_allow_noclip", "0", FCVAR_REPLICATED, "Camera: Allow clients to disable camera collision.")
function GM.Config.Camera:AllowNoClip()
return self.ConVars.AllowNoClip:GetBool()
end
-- Camera Distance Maximum
GM.Config.Camera.ConVars.DistanceMax = CreateConVarIfNotExists("ph_camera_distance_max", "150", FCVAR_REPLICATED, "Camera: Maximum allowed distance to player.")
function GM.Config.Camera:DistanceMax()
return self.ConVars.DistanceMax:GetFloat()
end
-- Camera Distance Minimum
GM.Config.Camera.ConVars.DistanceMin = CreateConVarIfNotExists("ph_camera_distance_min", "30", FCVAR_REPLICATED, "Camera: Minimum allowed distance to player.")
function GM.Config.Camera:DistanceMin()
return self.ConVars.DistanceMin:GetFloat()
end
-- Camera Distance Right Maximum
GM.Config.Camera.ConVars.DistanceRightRange = CreateConVarIfNotExists("ph_camera_distance_right_range", "20", FCVAR_REPLICATED, "Camera: Horizontal allowed camera distance range.")
function GM.Config.Camera:DistanceRightRange()
return self.ConVars.DistanceRightRange:GetFloat()
end
-- Camera Distance Up Maximum
GM.Config.Camera.ConVars.DistanceUpRange = CreateConVarIfNotExists("ph_camera_distance_up_range", "20", FCVAR_REPLICATED, "Camera: Vertical allowed camera distance range.")
function GM.Config.Camera:DistanceUpRange()
return self.ConVars.DistanceUpRange:GetFloat()
end
-- Lag Minimum
GM.Config.Camera.ConVars.LagMinimum = CreateConVarIfNotExists("ph_camera_lag_min", "0.01", FCVAR_REPLICATED, "Camera: Minimum Camera Lag.")
function GM.Config.Camera:LagMinimum()
return self.ConVars.LagMinimum:GetFloat()
end
-- Lag Maximum
GM.Config.Camera.ConVars.LagMaximum = CreateConVarIfNotExists("ph_camera_lag_max", "0.95", FCVAR_REPLICATED, "Camera: Maximum Camera Lag.")
function GM.Config.Camera:LagMaximum()
return self.ConVars.LagMaximum:GetFloat()
end
if CLIENT then
-- Collisions
GM.Config.Camera.ConVars.Collisions = CreateConVarIfNotExists("ph_camera_collisions", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Enable collisions with the world and objects in it.")
function GM.Config.Camera:Collisions()
if self:AllowNoClip() then
return self.ConVars.Collisions:GetBool()
else
return true
end
end
-- Distance
GM.Config.Camera.ConVars.Distance = CreateConVarIfNotExists("ph_camera_distance", "100", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Ideal Distance to player.")
function GM.Config.Camera:Distance()
return math.Clamp(self.ConVars.Distance:GetFloat(), self:DistanceMin(), self:DistanceMax())
end
-- Distance Right
GM.Config.Camera.ConVars.DistanceRight = CreateConVarIfNotExists("ph_camera_distance_right", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Ideal Distance to player horizontally.")
function GM.Config.Camera:DistanceRight()
return math.Clamp(self.ConVars.DistanceRight:GetFloat(), -self:DistanceRightRange(), self:DistanceRightRange())
end
-- Distance Up
GM.Config.Camera.ConVars.DistanceUp = CreateConVarIfNotExists("ph_camera_distance_up", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Ideal Distance to player vertically.")
function GM.Config.Camera:DistanceUp()
return math.Clamp(self.ConVars.DistanceUp:GetFloat(), -self:DistanceUpRange(), self:DistanceUpRange())
end
-- Lag
GM.Config.Camera.ConVars.Lag = CreateConVarIfNotExists("ph_camera_lag", "0.95", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Percentage of camera lag (higher = slower, lower = faster).")
function GM.Config.Camera:Lag()
return math.Clamp(self.ConVars.Lag:GetFloat(), self:LagMinimum(), self:LagMaximum())
end
end
-- ------------------------------------------------------------------------- --
--! Name Plates
-- ------------------------------------------------------------------------- --
GM.Config.NamePlates = {}
GM.Config.NamePlates.ConVars = {}
if CLIENT then
-- Show
GM.Config.NamePlates.ConVars.Show = CreateConVarIfNotExists("ph_nameplates_show", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Show a name plate above each player in your team (or all players if spectating).")
function GM.Config.NamePlates:Show()
return self.ConVars.Show:GetBool()
end
-- Scale
GM.Config.NamePlates.ConVars.Scale = CreateConVarIfNotExists("ph_nameplates_scale", "0.05", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: World scale of name plate, a setting of 1 means 1px = 1unit.")
function GM.Config.NamePlates:Scale()
return self.ConVars.Scale:GetFloat()
end
-- Height
GM.Config.NamePlates.ConVars.Height = CreateConVarIfNotExists("ph_nameplates_height", "10", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Height above player.")
function GM.Config.NamePlates:Height()
return self.ConVars.Height:GetFloat()
end
-- Tint Color
GM.Config.NamePlates.ConVars.TintHue = CreateConVarIfNotExists("ph_nameplates_tint_hue", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint hue.")
function GM.Config.NamePlates:TintHue()
return self.ConVars.TintHue:GetFloat()
end
GM.Config.NamePlates.ConVars.TintSaturation = CreateConVarIfNotExists("ph_nameplates_tint_saturation", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint saturation.")
function GM.Config.NamePlates:TintSaturation()
return self.ConVars.TintSaturation:GetFloat()
end
GM.Config.NamePlates.ConVars.TintValue = CreateConVarIfNotExists("ph_nameplates_tint_value", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint value.")
function GM.Config.NamePlates:TintValue()
return self.ConVars.TintValue:GetFloat()
end
-- Tint By Health
GM.Config.NamePlates.ConVars.TintHealth = CreateConVarIfNotExists("ph_nameplates_tint_health", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint the nameplate using their health percent.")
function GM.Config.NamePlates:TintHealth()
return self.ConVars.TintHealth:GetBool()
end
-- Tint By Team
GM.Config.NamePlates.ConVars.TintTeam = CreateConVarIfNotExists("ph_nameplates_tint_team", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Nameplates: Tint the nameplate with the team colors.")
function GM.Config.NamePlates:TintTeam()
return self.ConVars.TintTeam:GetBool()
end
end
@@ -0,0 +1,146 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Xaymar
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
--]]
-- ------------------------------------------------------------------------- --
--! Gamemode Information
-- ------------------------------------------------------------------------- --
GM.Name = "Prop Hunt Extended"
GM.Author = "Michael Fabian 'Xaymar' Dirks"
GM.Email = "info@xaymar.com"
GM.Website = "http://xaymar.com/"
GM.TeamBased = true
GM.AllowAutoTeam = true
GM.SecondsBetweenTeamSwitches = 10
-- ------------------------------------------------------------------------- --
--! Code
-- ------------------------------------------------------------------------- --
-- Game States
GM.States = {}
GM.States.PreMatch = 0
GM.States.PreRound = 1
GM.States.Hide = 2
GM.States.Seek = 3
GM.States.PostRound = 4
GM.States.PostMatch = 5
-- Game Modes
GM.Types = {}
GM.Types.Original = 0
GM.Types.TheDeadHunt = 1 -- One Hunter, Dead Prop become Hunter, Props can't see each other.
-- Teams
GM.Teams = {}
GM.Teams.Spectators = 0
GM.Teams.Seekers = 1
GM.Teams.Hiders = 2
function GM:CreateTeams()
-- Specators
team.SetUp(self.Teams.Spectators, "Spectators", Color(127, 127, 127, 255))
team.SetSpawnPoint(self.Teams.Spectators, {
"info_player_deathmatch",
"info_player_combine",
"info_player_counterterrorist",
"info_player_allies",
"info_player_terrorist",
"info_player_start"
})
team.SetClass(self.Teams.Spectators, { "Spectator", "Spectator" })
-- Seekers: "Hunters"
team.SetUp(self.Teams.Seekers, "Seekers", Color(0, 128, 255, 255))
team.SetSpawnPoint(self.Teams.Seekers, {
"info_player_start",
"info_player_spawn",
"info_player_deathmatch",
"info_player_combine",
"info_player_counterterrorist"
})
team.SetClass(self.Teams.Seekers, { "Seeker", "Spectator" })
-- Hiders: "Props"
team.SetUp(self.Teams.Hiders, "Hiders", Color(255, 128, 0, 255))
team.SetSpawnPoint(self.Teams.Hiders, {
"info_player_start",
"info_player_spawn",
"info_player_deathmatch",
"info_player_allies",
"info_player_terrorist"
})
team.SetClass(self.Teams.Hiders, { "Hider", "Spectator" })
end
-- ------------------------------------------------------------------------- --
--! Player Manager Binding
-- ------------------------------------------------------------------------- --
function GM:PlayerPostThink(ply)
return player_manager.RunClass(ply, "PostThink")
end
function GM:PlayerTick(ply, mv)
return player_manager.RunClass(ply, "Tick", mv)
end
function GM:PlayerHurt(victim, attacker, healthRemaining, damageTaken)
player_manager.RunClass(victim, "Hurt", victim, attacker, healthRemaining, damageTaken)
if (IsValid(attacker) && attacker:IsPlayer()) then
player_manager.RunClass(attacker, "Damage", victim, attacker, healthRemaining, damageTaken)
end
end
function GM:PlayerShouldTakeDamage(victim, attacker)
return player_manager.RunClass(victim, "ShouldTakeDamage", attacker)
end
-- ------------------------------------------------------------------------- --
--! Gamemode Functionality
-- ------------------------------------------------------------------------- --
function GM:GetRound()
return GetGlobalInt("Round", 0)
end
function GM:GetRoundState()
return GetGlobalInt("RoundState", self.States.PreMatch)
end
function GM:GetRoundTime()
return GetGlobalInt("RoundTime", 0)
end
function GM:GetRoundWinner()
return GetGlobalInt("RoundWinner", GAMEMODE.Teams.Spectator)
end
-- ------------------------------------------------------------------------- --
--! Includes
-- ------------------------------------------------------------------------- --
include "sh_config.lua"
-- Player Classes
include "player_class/class_default.lua"
include "player_class/class_spectator.lua"
include "player_class/class_seeker.lua"
include "player_class/class_hider.lua"
@@ -0,0 +1,49 @@
-- Finds the player meta table or terminates
local meta = FindMetaTable("Player")
if !meta then return end
-- Blinds the player by setting view out into the void
function meta:Blind(bool)
if !self:IsValid() then return end
if SERVER then
umsg.Start("SetBlind", self)
if bool then
umsg.Bool(true)
else
umsg.Bool(false)
end
umsg.End()
elseif CLIENT then
blind = bool
end
end
-- Blinds the player by setting view out into the void
function meta:RemoveProp()
if CLIENT || !self:IsValid() then return end
if self.ph_prop && self.ph_prop:IsValid() then
self.ph_prop:Remove()
self.ph_prop = nil
end
end
-- Sets a new Hull for a player.
function meta:NewHull(hullOBBMin, hullOBBMax)
if !self:IsValid() then return end
if hullOBBMax == nil then return end
if hullOBBMin == nil then return end
local hullOBB = hullOBBMax - hullOBBMin
local hullOBBXY = math.max(hullOBB.x, hullOBB.y)
local xyMul = 0.5
local hullMin = Vector(-hullOBBXY * xyMul, -hullOBBXY * xyMul, 0)
local hullMax = Vector( hullOBBXY * xyMul, hullOBBXY * xyMul, hullOBB.z)
self:SetHull(hullMin, hullMax)
self:SetHullDuck(hullMin, hullMax)
self:SetViewOffset(Vector(0, 0, hullOBB.z))
self:SetViewOffsetDucked(Vector(0, 0, hullOBB.z / 2.0))
end
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

@@ -0,0 +1,243 @@
"prophuntextended"
{
"base" "base"
"title" "Prop Hunt Extended"
"maps" "^ph_"
"menusystem" "1"
"workshopid" "468149739"
"settings"
{
// Debug Settings
1
{
"name" "ph_debug"
"text" "Enable Debug Mode"
"type" "CheckBox"
"default" "0"
}
2
{
"name" "ph_debug_log"
"text" "Enable Debug Logging"
"type" "CheckBox"
"default" "1"
}
// Basic Settings
11
{
"name" "ph_gametype"
"text" "Game Type to use"
"type" "Numeric"
"default" "0"
}
12
{
"name" "mp_timelimit"
"text" "Map Time Limit"
"type" "Numeric"
"default" "0"
}
13
{
"name" "ph_sprinting"
"text" "Enable Sprinting"
"type" "CheckBox"
"default" "0"
}
// Round Settings
21
{
"name" "ph_round_limit"
"text" "Maximum Rounds Played"
"type" "Numeric"
"default" "10"
}
22
{
"name" "ph_round_timelimit"
"text" "Time Limit per Round"
"type" "Numeric"
"default" "180"
}
23
{
"name" "ph_round_blindtime"
"text" "Seeker Blind time per Round"
"type" "Numeric"
"default" "-30"
}
// Team Settings
31
{
"name" "ph_teams_randomize"
"text" "Randomize Teams"
"type" "CheckBox"
"default" "1"
}
32
{
"name" "ph_teams_weighted"
"text" "Randomize with weighted Score"
"type" "CheckBox"
"default" "1"
}
33
{
"name" "ph_teams_seekerpct"
"text" "Pct of Pl. becoming Seeker"
"type" "Numeric"
"default" "25"
}
// Seeker Settings
41
{
"name" "ph_seeker_health"
"text" "Seeker Health"
"type" "Numeric"
"default" "100"
}
42
{
"name" "ph_seeker_health_max"
"text" "Seeker Max Health"
"type" "Numeric"
"default" "100"
}
43
{
"name" "ph_seeker_health_bonus"
"text" "Seeker Health Kill-Bonus"
"type" "Numeric"
"default" "20"
}
44
{
"name" "ph_seeker_health_penalty"
"text" "Seeker Health Penalty"
"type" "Numeric"
"default" "5"
}
45
{
"name" "ph_seeker_weapons"
"text" "Seeker Weapons"
"type" "Text"
"default" "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun"
}
46
{
"name" "ph_seeker_ammo"
"text" "Seeker Ammo"
"type" "Text"
"default" "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64"
}
// Hider Settings
51
{
"name" "ph_hider_health"
"text" "Hider Health"
"type" "Numeric"
"default" "100"
}
52
{
"name" "ph_hider_health_max"
"text" "Hider Max Health"
"type" "Numeric"
"default" "100"
}
53
{
"name" "ph_hider_health_scaling"
"text" "Hider Enable Health Scaling"
"type" "CheckBox"
"default" "1"
}
54
{
"name" "ph_hider_health_scaling_max"
"text" "Hider Scaled Max Health"
"type" "Numeric"
"default" "200"
}
55
{
"name" "ph_hider_allow_full_rotation"
"text" "Hider 3-Dimensional Rotation"
"type" "CheckBox"
"default" "0"
}
// Whitelist & Blacklist
61
{
"name" "ph_list_class_whitelist"
"text" "Allowed Entity Classes"
"type" "Text"
"default" "ph_prop,prop_physics,prop_physics_multiplayer,prop_physics_respawnable"
}
62
{
"name" "ph_list_abuse_blacklist"
"text" "Abuse Blacklist"
"type" "Text"
"default" "func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable"
}
63
{
"name" "ph_list_model_blacklist"
"text" "Model Blacklist"
"type" "Text"
"default" "models/props/cs_assault/dollar.mdl,models/props/cs_assault/money.mdl,models/props/cs_office/snowman_arm.mdl,models/props/cs_office/projector_remote.mdl"
}
// Taunts
71
{
"name" "ph_taunt_cooldown"
"text" "Cooldown for Taunts"
"type" "Numeric"
"default" "5"
}
72
{
"name" "ph_taunt_seekers"
"text" "Seeker Taunts"
"type" "Text"
"default" "bot/a_bunch_of_them.wav,bot/come_out_and_fight_like_a_man.wav,bot/come_out_wherever_you_are.wav,bot/come_to_papa.wav,bot/dont_worry_hell_get_it.wav,bot/hang_on_i_heard_something.wav,bot/hang_on_im_coming.wav,bot/i_dont_think_so.wav,bot/i_have_the_hostages.wav,bot/i_see_our_target.wav,bot/im_waiting_here.wav,bot/keeping_an_eye_on_the_hostages.wav,bot/nnno_sir.wav,bot/spotted_the_delivery_boy.wav,bot/target_acquired.wav,bot/target_spotted.wav,bot/you_heard_the_man_lets_go.wav"
}
73
{
"name" "ph_taunt_hiders"
"text" "Hider Taunts"
"type" "Text"
"default" "ambient/alarms/apc_alarm_pass1.wav,ambient/alarms/manhack_alert_pass1.wav,ambient/alarms/razortrain_horn1.wav,ambient/alarms/scanner_alert_pass1.wav,ambient/alarms/train_horn2.wav,ambient/alarms/train_horn_distant1.wav,ambient/alarms/warningbell1.wav,ambient/energy/whiteflash.wav,ambient/intro/alyxremove.wav,ambient/intro/logosfx.wav,ambient/levels/launch/1stfiringwarning.wav,ambient/levels/launch/rockettakeoffblast.wav,ambient/misc/ambulance1.wav,ambient/misc/carhonk1.wav,ambient/misc/carhonk2.wav,ambient/misc/carhonk3.wav,ambient/outro/gunshipcrash.wav,ambient/3dmeagle.wav,beams/beamstart5.wav,buttons/bell1.wav,buttons/weapon_cant_buy.wav,common/bass.wav,common/bugreporter_failed.wav,common/warning.wav,doors/door_squeek1.wav,friends/friend_join.wav,friends/friend_online.wav,friends/message.wav,hostage/hunuse/comeback.wav,hostage/hunuse/dontleaveme.wav,hostage/hunuse/yeahillstay.wav,items/gift_drop.wav,music/radio1.mp3,phx/eggcrack.wav,plats/elevbell1.wav,player/headshot1.wav,player/headshot2.wav,player/sprayer.wav,radio/enemydown.wav,radio/go.wav,radio/locknload.wav,radio/negative.wav,radio/rounddraw.wav,radio/takepoint.wav,resource/warning.wav,ui/achievement_earned.wav,ui/freeze_cam.wav,vehicles/junker/radar_ping_friendly1.wav,weapons/c4/c4_beep1.wav,weapons/c4/c4_click.wav,weapons/awp/awp1.wav,vo/canals/female01/gunboat_giveemhell.wav,vo/canals/female01/gunboat_justintime.wav,vo/canals/female01/stn6_incoming.wav,vo/canals/male01/gunboat_giveemhell.wav,vo/canals/male01/gunboat_justintime.wav,vo/canals/male01/stn6_incoming.wav,vo/canals/al_radio_stn6.wav,vo/canals/arrest_getgoing.wav,vo/canals/arrest_helpme.wav,vo/canals/arrest_lookingforyou.wav,vo/canals/boxcar_lethimhelp.wav,vo/canals/matt_closecall.wav,vo/canals/premassacre.wav,vo/ravenholm/aimforhead.wav,vo/ravenholm/bucket_patience.wav,vo/ravenholm/madlaugh01.wav,vo/ravenholm/madlaugh02.wav,vo/ravenholm/madlaugh03.wav,vo/ravenholm/madlaugh04.wav,weapons/strider_buster/ol12_stickybombcreator.wav,weapons/c4/c4_explode1.wav,weapons/357/357_fire2.wav,weapons/357/357_fire3.wav,weapons/scout/scout_fire-1.wav,weapons/smokegrenade/sg_explode.wav,weapons/grenade_launcher1.wav,weapons/explode3.wav,weapons/underwater_explode3.wav,items/nvg_on.wav,hostage/huse/letsdoit.wav,hostage/huse/illfollow.wav,hostage/huse/getouttahere.wav,doors/door_screen_move1.wav,doors/heavy_metal_stop1.wav,doors/default_move.wav,common/stuck2.wav,ambient/water_splash1.wav,ambient/water_splash2.wav,ambient/water_splash3.wav,ambient/weather/thunder1.wav,ambient/weather/thunder2.wav,ambient/weather/thunder3.wav,ambient/weather/thunder4.wav,ambient/weather/thunder5.wav,ambient/weather/thunder6.wav,ambient/outro/thunder7.wav,ambient/voices/crying_loop1.wav,ambient/voices/playground_memory.wav,ambient/voices/f_scream1.wav,ambient/voices/m_scream1.wav,ambient/voices/cough1.wav,ambient/voices/cough2.wav,ambient/voices/cough3.wav,ambient/voices/cough4.wav,ambient/overhead/plane1.wav,ambient/overhead/plane2.wav,ambient/overhead/plane3.wav,ambient/overhead/hel1.wav,ambient/overhead/hel2.wav,ambient/misc/truck_backup1.wav,ambient/misc/truck_drive1.wav,ambient/misc/truck_drive2.wav,ambient/machines/pneumatic_drill_1.wav,ambient/machines/pneumatic_drill_2.wav,ambient/machines/pneumatic_drill_3.wav,ambient/machines/pneumatic_drill_4.wav,ambient/machines/station_train_squeel.wav,ambient/machines/ticktock.wav,ambient/creatures/teddy.wav,ambient/creatures/town_child_scream1.wav,ambient/creatures/town_moan1.wav,ambient/creatures/town_muffled_cry1.wav,ambient/creatures/town_scared_breathing1.wav,ambient/creatures/town_scared_breathing2.wav,ambient/creatures/town_scared_sob1.wav,ambient/creatures/town_scared_sob2.wav,ambient/creatures/town_zombie_call1.wav"
}
}
}