Code update, forgot to actually do this... *hides in a corner*

This commit is contained in:
Michael Fabain Dirks
2016-06-12 03:52:57 +02:00
parent b558d16daf
commit 2d3360ab82
35 changed files with 2832 additions and 63 deletions
+41 -41
View File
@@ -1,41 +1,41 @@
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
# Compiled Lua sources
luac.out
# luarocks build files
*.src.rock
*.zip
*.tar.gz
# Object files
*.o
*.os
*.ko
*.obj
*.elf
# Precompiled Headers
*.gch
*.pch
# Libraries
*.lib
*.a
*.la
*.lo
*.def
*.exp
# Shared objects (inc. Windows DLLs)
*.dll
*.so
*.so.*
*.dylib
# Executables
*.exe
*.out
*.app
*.i*86
*.x86_64
*.hex
+14
View File
@@ -0,0 +1,14 @@
Based on the original "Prop Hunt" game mode, Xaymar's Custom Prop Hunt brings you some much needed changes to freshen up the gamemode.
New features:
- Easy configuration - configuration is now stored inside data\prop_hunt\ as a key-values table!
- Default Taunts are no longer infringing on copyrighted material - taunt your life away as a streamer or YouTuber!
- Taunt Pack support - add new taunts by just downloading addons, no file modification needed!
- Prop Rotation - Hit F4 and dance- err I ment rotate!
Fixes:
- Camera can now no longer glitch through the world.
- Camera root position now closely follows the prop size.
- Prop sizes are now set correctly - previously you could make your way behind things with props way too big.
- Props can no longer heal themselves by becoming prop, they'll always keep the same percentage of health.
- Picking a prop is now more accurate, picking from where your camera is looking.
+7
View File
@@ -0,0 +1,7 @@
{
"title" : "Xaymar's Custom Prop Hunt ",
"type" : "gamemode",
"tags" : [ "fun" ],
"ignore" : [
]
}
@@ -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,50 @@
--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")
-- Called when we take damge
function ENT:OnTakeDamage(dmg)
local pl = self.Owner
local attacker = dmg:GetAttacker()
local inflictor = dmg:GetInflictor()
-- Health
if pl && pl:IsValid() && pl:Alive() && pl:IsPlayer() && attacker:IsPlayer() && dmg:GetDamage() > 0 then
pl:SetHealth(pl:Health() - dmg:GetDamage())
if pl:Health() <= 0 then
-- Figure out real attacker.
if inflictor && inflictor == attacker && inflictor:IsPlayer() then
inflictor = inflictor:GetActiveWeapon()
if !inflictor || inflictor == NULL then inflictor = attacker end
end
-- Kill player and remove the prop
pl:KillSilent()
pl:RemoveProp() -- Needs to be executed before net.Broadcast
-- Send kill message.
net.Start( "PlayerKilledByPlayer" )
net.WriteEntity( pl )
net.WriteString( inflictor:GetClass() )
net.WriteEntity( attacker )
net.Broadcast()
-- Broadcast same message to all players in console.
MsgAll(attacker:Name() .. " found and killed " .. pl:Name() .. "\n")
-- Increment frags and deaths.
attacker:AddFrags(1)
pl:AddDeaths(1)
-- Update attacker health
attacker:SetHealth(math.Clamp(attacker:Health() + GetConVar("HUNTER_KILL_BONUS"):GetInt(), 1, 100))
end
end
end
@@ -0,0 +1,46 @@
-- Entity information
ENT.Type = "anim"
ENT.Base = "base_anim"
-- Initialize
function ENT:Initialize()
self:SetModel("models/player/Kleiner.mdl")
self:DrawShadow(true);
-- Physical properties
self:SetSolid(SOLID_OBB)
-- Initialize Networked Variables
self:SetApplyNewAngles(false)
self:SetHealth(100)
if SERVER then self:SetMaxHealth(100) end
if CLIENT then self.Owner.ph_prop = self.Entity end
end
-- Set up shared Data.
function ENT:SetupDataTables()
self:NetworkVar( "Bool", 0, "ApplyNewAngles" )
end
-- Update position
function ENT:Think()
-- Calculate hull size.
local hullOBBMin = self:OBBMins()
local hullOBBMax = self:OBBMaxs()
local hullOBB = hullOBBMax - hullOBBMin
-- Shared update
local pos = -Vector(0, 0, hullOBBMin.z)
self:SetPos(self.Owner:GetPos() + pos)
self:SetVelocity(self:GetOwner():GetVelocity())
-- Server only updates
if SERVER then
-- Prevent confusion by updating angles only on the server.
if self:GetApplyNewAngles() then
self:SetAngles(Angle(0, self:GetOwner():GetAngles().yaw, 0))
end
self:NextThink( CurTime() )
end
end
@@ -0,0 +1,210 @@
-- SWEP Information
SWEP.Author = "Michael 'Xaymar' Dirks"
SWEP.Contact = "info@project-kube.de"
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
-- 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
-- Recoil
SWEP.Recoil = {}
SWEP.Recoil.SingleFire = 1.0
SWEP.Recoil.BurstFire = 4.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.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:EmitSound(self.Sound.NoPrimaryAmmo)
self:Reload()
return false
end
-- If no, emit empty sound for primary fire.
self: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.BurstFire == false) then
-- Single Mode: fire and take one bullet from the clip.
self:ShootBullet(self.Primary.Damage, bullet_count, 1.0 - self.PrimaryAccuracy)
self:TakePrimaryAmmo(1)
self:EmitSound(self.Sound.SingleFire)
self:SetNextPrimaryFire( CurTime() + 0.1 )
-- Apply recoil
self.Owner:ViewPunch( Angle(-1, 0, 0) * self.Recoil.SingleFire * (1 + (1 - self.PrimaryAccuracy)) )
-- 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:ShootBullet(self.Primary.Damage, bullet_count, 1.0 - self.PrimaryAccuracy)
self:TakePrimaryAmmo(bulletCount)
self:EmitSound(self.Sound.BurstFire)
self:SetNextPrimaryFire( CurTime() + 0.5 * (bulletCount / 3.0) )
-- Apply recoil
self.Owner:ViewPunch(Angle(-1, 0, 0) * self.Recoil.BurstFire * (bulletCount / 3.0) * (1 + (1 - self.PrimaryAccuracy)))
-- Decrease accuracy
self.PrimaryAccuracy = math.Clamp(self.PrimaryAccuracy - self.Accuracy.Primary.Reduction * bulletCount, self.Accuracy.Primary.Min, self.Accuracy.Primary.Max)
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:EmitSound(self.Sound.NoSecondaryAmmo)
self:SetNextSecondaryFire( CurTime() + 1.0 )
return false
else
self:SetClip2( 1 )
self.Owner:SetAmmo( self.Owner:GetAmmoCount( self:GetSecondaryAmmoType() ) - 1, self:GetSecondaryAmmoType() )
end
end
return true
end
function SWEP:SecondaryAttack()
-- Can't fire without Ammo
if (!self:CanSecondaryAttack()) then return end
-- Emit a sound.
self:EmitSound(self.Sound.SecondaryFire)
self:SetNextSecondaryFire( CurTime() + 1.0 )
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()
if self:DefaultReload(ACT_VM_RELOAD) then self:EmitSound(self.Sound.Reload) end
return
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,178 @@
-- Include the needed files
include("sh_init.lua")
--include("cl_hints.lua")
-- Draw round timeleft and hunter release timeleft
function HUDPaint()
if GetGlobalBool("InRound", false) then
local blindlock_time_left = (GetConVar("HUNTER_BLINDLOCK_TIME"):GetInt() - (CurTime() - GetGlobalFloat("RoundStartTime", 0))) + 1
if blindlock_time_left < 1 && blindlock_time_left > -6 then
blindlock_time_left_msg = "Hunters have been released!"
elseif blindlock_time_left > 0 then
blindlock_time_left_msg = "Hunters will be unblinded and released in "..string.ToMinutesSeconds(blindlock_time_left)
else
blindlock_time_left_msg = nil
end
if LocalPlayer():Team() == TEAM_HUNTERS && blindlock_time_left > 1 then
draw.RoundedBox(0, 0, 0, surface.ScreenWidth(), surface.ScreenHeight(), Color(20, 20, 20, 255))
end
if blindlock_time_left_msg then
surface.SetFont("MyFont")
local tw, th = surface.GetTextSize(blindlock_time_left_msg)
draw.RoundedBox(8, 20, 20, tw + 20, 26, Color(0, 0, 0, 75))
draw.DrawText(blindlock_time_left_msg, "MyFont", 31, 26, Color(255, 255, 0, 255), TEXT_ALIGN_LEFT)
end
end
end
hook.Add("HUDPaint", "PH_HUDPaint", HUDPaint)
-- Called immediately after starting the gamemode
function Initialize()
hullz = 80
--surface.CreateFont("Arial", 14, 1200, true, false, "ph_arial")
surface.CreateFont( "MyFont",
{
font = "Arial",
size = 14,
weight = 1200,
antialias = true,
underline = false
})
end
hook.Add("Initialize", "PH_Initialize", Initialize)
-- Resets the player hull
function ResetHull(um)
if LocalPlayer() && LocalPlayer():IsValid() then
LocalPlayer():ResetHull()
LocalPlayer():SetViewOffset(Vector(0, 0, 64))
LocalPlayer():SetViewOffsetDucked(Vector(0, 0, 28))
hullz = 80
end
end
usermessage.Hook("ResetHull", ResetHull)
-- Sets the local blind variable to be used in CalcView
function SetBlind(um)
blind = um:ReadBool()
end
usermessage.Hook("SetBlind", SetBlind)
function GM:ShouldDrawLocalPlayer()
return false
end
function GM:CalcView( ply, pos, ang, fov )
local view = {
origin = pos,
angles = ang,
fov = fov
}
if ply:Team() == TEAM_PROPS && ply:Alive() then
-- Fix lua errors by doing this instead.
if LocalPlayer().ThirdPersonDistance == nil then
LocalPlayer().ThirdPersonDistance = 100
end
-- Slowly return ThirdPersonDistance to 100
local traceDist = math.Clamp(LocalPlayer().ThirdPersonDistance * 0.98 + 100 * 0.02, 0, 100)
-- Trace a line to find the correct position for the camera.
local tracePos = pos
local trace = {
-- Start somewhat outside the prop.
start = tracePos - (ang:Forward() * 5),
endpos = tracePos - (ang:Forward() * (traceDist + 10)),
filter = function(ent)
if (ent == LocalPlayer() || ent == LocalPlayer().ph_prop || ent == LocalPlayer().ThirdPersonFilter || ent == ThirdPersonFilter) then
return false
elseif (ent:GetClass() == "ph_prop" || ent:GetClass() == "worldspawn") then
return false
end
return true
end
}
local traceResult = util.TraceLine(trace);
-- Readjust trace hit distance to force camera outside of the hit position.
if traceResult.Hit then
traceDist = math.max(traceResult.HitPos:Distance(tracePos) - 10, 0)
end
LocalPlayer().ThirdPersonDistance = traceDist
-- Correct view position
view.origin = tracePos - (ang:Forward() * traceDist)
--[[ else
local wep = ply:GetActiveWeapon()
if wep && wep != NULL then
local func = wep.GetViewModelPosition
if func then
view.vm_origin, view.vm_angles = func(wep, origin*1, angles*1) -- Note: *1 to copy the object so the child function can't edit it.
end
local func = wep.CalcView
if func then
view.origin, view.angles, view.fov = func(wep, pl, origin*1, angles*1, fov) -- Note: *1 to copy the object so the child function can't edit it.
end
end--]]
end
return view;
end
-- Render halos and player names.
function DrawPlayerNames(bDrawingDepth, bDrawingSkybox)
for i,v in ipairs(player.GetAll()) do
if v:Alive() && v != LocalPlayer() then
local pos = v:GetPos() + v:GetViewOffset() + Vector(0, 0, 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
cam.Start3D2D(pos, ang, 0.15)
draw.DrawText(v:GetName(), "Trebuchet24", 0, -draw.GetFontHeight("Trebuchet24"), healthCol, TEXT_ALIGN_CENTER)
cam.End3D2D()
end
end
end
end
hook.Add("PostDrawTranslucentRenderables", "PH_DrawPlayerNames", DrawPlayerNames)
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)
-- UMSG: Update player Hull and health.
function UMSGSetHull(um)
local hullOBBMin = um:ReadVector()
local hullOBBMax = um:ReadVector()
local new_health = um:ReadShort()
LocalPlayer():NewHull(hullOBBMin, hullOBBMax)
LocalPlayer():SetHealth(new_health)
end
usermessage.Hook("SetHull", UMSGSetHull)
@@ -0,0 +1,93 @@
surface.CreateFont( "GModWorldtip",
{
font = "Helvetica",
size = 20,
weight = 700
})
local cl_drawworldtooltips = CreateConVar( "cl_drawworldtooltips", "1", { FCVAR_ARCHIVE } )
local WorldTip = nil
local TipColor = Color( 250, 250, 200, 255 )
--
-- Adds a hint to the queue
--
function AddWorldTip( unused1, text, unused2, pos, ent )
WorldTip = {}
WorldTip.dietime = SysTime() + 0.05
WorldTip.text = text
WorldTip.pos = pos
WorldTip.ent = ent
end
local function DrawWorldTip( tip )
if ( IsValid( tip.ent ) ) then
tip.pos = tip.ent:GetPos()
end
local pos = tip.pos:ToScreen()
local black = Color( 0, 0, 0, 255 )
local tipcol = Color( TipColor.r, TipColor.g, TipColor.b, 255 )
local x = 0
local y = 0
local padding = 10
local offset = 50
surface.SetFont( "GModWorldtip" )
local w, h = surface.GetTextSize( tip.text )
x = pos.x - w
y = pos.y - h
x = x - offset
y = y - offset
draw.RoundedBox( 8, x-padding-2, y-padding-2, w+padding*2+4, h+padding*2+4, black )
local verts = {}
verts[1] = { x=x+w/1.5-2, y=y+h+2 }
verts[2] = { x=x+w+2, y=y+h/2-1 }
verts[3] = { x=pos.x-offset/2+2, y=pos.y-offset/2+2 }
draw.NoTexture()
surface.SetDrawColor( 0, 0, 0, tipcol.a )
surface.DrawPoly( verts )
draw.RoundedBox( 8, x-padding, y-padding, w+padding*2, h+padding*2, tipcol )
local verts = {}
verts[1] = { x=x+w/1.5, y=y+h }
verts[2] = { x=x+w, y=y+h/2 }
verts[3] = { x=pos.x-offset/2, y=pos.y-offset/2 }
draw.NoTexture()
surface.SetDrawColor( tipcol.r, tipcol.g, tipcol.b, tipcol.a )
surface.DrawPoly( verts )
draw.DrawText( tip.text, "GModWorldtip", x + w/2, y, black, TEXT_ALIGN_CENTER )
end
function GM:PaintWorldTips()
if ( !cl_drawworldtooltips:GetBool() ) then return end
if ( WorldTip && WorldTip.dietime > SysTime() ) then
DrawWorldTip( WorldTip )
end
end
@@ -0,0 +1,49 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Project Kube
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.
for k,v in ipairs(GAMEMODE.Hunter_Taunts) do
-- ToDo: string.GetFileFromFilename is broken!
--pcall(GAMEMODE.Config.Taunts.Add("TauntPackLoader."..string.GetFileFromFilename(v), v, TEAM_SEEKERES, nil))
end
for k,v in ipairs(GAMEMODE.Prop_Taunts) do
--pcall(GAMEMODE.Config.Taunts.Add("TauntPackLoader."..string.GetFileFromFilename(v), v, TEAM_HIDERS, nil))
end
-- Clean up after ourselves
GAMEMODE.Prop_Taunts = nil
GAMEMODE.Hunter_Taunts = nil
end
hook.Add("OnPropHuntInitialized", "CompatTauntPackLoader", CompatTauntPackLoader)
@@ -0,0 +1,401 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Project Kube
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.
--]]
--! Client Files
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("sh_init.lua")
--! Include shared lua.
include "sh_init.lua"
--! Include server lua.
include "server/config.lua"
include "server/console/variables.lua"
include "compat/compat_tauntpackloader.lua"
-- ------------------------------------------------------------------------- --
--! Gamemode
-- ------------------------------------------------------------------------- --
-- GameStates
GM_STATES_SETUP = 0
GM_STATES_HIDE = 1
GM_STATES_SEEK = 2
GM_STATES_SHAMING = 3 -- Do your best, hiders!
--! Initialize
function GM:Initialize()
self.State = GM_STATES_SETUP
self.StatePrev = self.State
--! Run any hooked functions that addons have registered for Prop Hunt.
hook.Run("OnPropHuntInitialized")
end
--! Check Victory and Loss conditions
function GM:Think()
if (self.State == GM_STATES_SETUP) then
--! GameState: Setup
-- Here we do all the stuff that would be ridiculous to do while playing.
if (self.StatePrev != self.State) then
game.CleanUpMap()
-- Assign correct teams depending on Sub-Gamemode.
if (self.Config.Modes.SwapTeams == 1) then
for i,pl in ipairs(player.GetAll()) do
if (pl:Team() == TEAM_HIDERS) then
pl:SetTeam(TEAM_SEEKERS)
elseif (pl:Team() == TEAM_SEEKERS) then
pl:SetTeam(TEAM_HIDERS)
end
end
elseif (self.Config.Modes.RandomizeTeams == 1) then
local plys = player.GetAll()
--local plyCount =
elseif (self.Config.Modes.TheDeadHunt == 1) then
end
-- Respawn players
for i,pl in ipairs(player.GetAll()) do
pl:Respawn()
end
end
-- Advanced to next GameState if we have enough players
self.StatePrev = self.State
self.State = GM_STATES_HIDE
elseif (self.State == GM_STATES_HIDE) then
elseif (self.State == GM_STATES_SEEK) then
elseif (self.State == GM_STATES_SHAMING) then
else
-- Invalid State, we have to reset
self.StatePrev = self.State
self.State = GM_STATES_SETUP
end
end
-- ------------------------------------------------------------------------- --
--! LEGACY CODE - TO BE REPLACED SOON
-- ------------------------------------------------------------------------- --
function GM:AllowPlayerPickup(player, entity)
return true
end
function AnnounceVictory(players, force)
for i,pl in ipairs(players) do
if pl:Alive() || force || pl:Team() == TEAM_SPECTATOR then
announcer = table.Random(VICTORY_SOUNDS);
print("Prop Hunt: '"..pl:GetName().."' announcing victory with '"..announcer.."'.")
pl:EmitSound(announcer, 200, 100, 0.5, CHAN_VOICE2)
end
end
end
function AnnounceLoss(players, force)
for i,pl in ipairs(players) do
if pl:Alive() || force || pl:Team() == TEAM_SPECTATOR then
announcer = table.Random(LOSS_SOUNDS);
print("Prop Hunt: '"..pl:GetName().."' announcing loss with '"..announcer.."'.")
pl:EmitSound(announcer, 100, 100, 0.5, CHAN_VOICE2)
end
end
end
-- If there is a mapfile send it to the client (sometimes servers want to change settings for certain maps)
if file.Exists("maps/"..game.GetMap()..".lua", "LUA") then
AddCSLuaFile("maps/"..game.GetMap()..".lua")
end
-- Server only constants
EXPLOITABLE_DOORS = {
"func_door",
"prop_door_rotating",
"func_door_rotating"
}
USABLE_PROP_ENTITIES = {
"prop_physics",
"prop_physics_multiplayer"
}
-- Send the required resources to the client
for _, announcer in pairs(LOSS_SOUNDS) do resource.AddFile("sound/"..announcer) end
for _, announcer in pairs(VICTORY_SOUNDS) do resource.AddFile("source/"..announcer) end
for _, taunt in pairs(HUNTER_TAUNTS) do resource.AddFile("sound/"..taunt) end
for _, taunt in pairs(PROP_TAUNTS) do resource.AddFile("sound/"..taunt) end
-- Called alot
function GM:CheckPlayerDeathRoundEnd()
if !GAMEMODE.RoundBased || !GAMEMODE:InRound() then
return
end
local Teams = GAMEMODE:GetTeamAliveCounts()
if table.Count(Teams) == 0 then
GAMEMODE:RoundEndWithResult(1001, "Draw, everyone loses!")
AnnounceLoss(player.GetAll(), true)
return
end
if table.Count(Teams) == 1 then
-- Play victory and loss sounds.
if Teams[0] == TEAM_HUNTERS then
AnnounceVictory(team.GetPlayers(TEAM_HUNTERS))
AnnounceLoss(team.GetPlayers(TEAM_PROPS))
elseif Teams[0] == TEAM_PROPS then
AnnounceLoss(team.GetPlayers(TEAM_HUNTERS))
AnnounceVictory(team.GetPlayers(TEAM_PROPS))
end
local TeamID = table.GetFirstKey(Teams)
GAMEMODE:RoundEndWithResult(TeamID, team.GetName(TeamID).." win!")
return
end
end
-- Called when an entity takes damage
function EntityTakeDamage(ent, dmginfo)
local att = dmginfo:GetAttacker()
if GAMEMODE:InRound() && ent && ent:GetClass() != "ph_prop" && !ent:IsPlayer() && att && att:IsPlayer() && att:Team() == TEAM_HUNTERS && att:Alive() then
att:SetHealth(att:Health() - GetConVar("HUNTER_FIRE_PENALTY"):GetInt())
if att:Health() <= 0 then
MsgAll(att:Name() .. " felt guilty for hurting so many innocent props and committed suicide\n")
att:Kill()
end
end
end
hook.Add("EntityTakeDamage", "PH_EntityTakeDamage", EntityTakeDamage)
-- Called when player tries to pickup a weapon
function GM:PlayerCanPickupWeapon(pl, ent)
if pl:Team() != TEAM_HUNTERS then
return false
end
return true
end
-- Called when player needs a model
function GM:PlayerSetModel(pl)
local player_model = pl:GetModel()
if pl:Team() == TEAM_HUNTERS then
player_model = "models/player/combine_super_soldier.mdl"
elseif pl:Team() == TEAM_PROPS then
player_model = "models/Gibs/Antlion_gib_small_3.mdl"
end
util.PrecacheModel(player_model)
pl:SetModel(player_model)
end
-- Called when a player tries to use an object
function GM:PlayerUse(pl, ent)
if !pl:Alive() || pl:Team() == TEAM_SPECTATOR then return false end
-- if pl:Team() == TEAM_PROPS && pl:IsOnGround() && !pl:Crouching() && table.HasValue(USABLE_PROP_ENTITIES, ent:GetClass()) && ent:GetModel() then
if pl:Team() == TEAM_PROPS && table.HasValue(USABLE_PROP_ENTITIES, ent:GetClass()) && ent:GetModel() then
if table.HasValue(BANNED_PROP_MODELS, ent:GetModel()) then
pl:ChatPrint("That prop has been banned by the server.")
elseif ent:GetPhysicsObject():IsValid() then -- && pl.ph_prop:GetModel() != ent:GetModel() then
local ent_health = math.Clamp(ent:GetPhysicsObject():GetVolume() / 250, 1, 200)
-- Prevent props from gaining health by changing.
local per = math.min(pl:Health() / pl:GetMaxHealth(), pl.tempHealthPc || 1.0)
if (pl.tempHealthPc == nil) || (per <= pl.tempHealthPc) then pl.tempHealthPc = per end
local new_health = math.Clamp(per * ent_health, 1, 200)
pl:SetJumpPower(math.Clamp(ent:GetPhysicsObject():GetVolume() / 333, 200, 600));
-- Set Prop Data
pl.ph_prop:SetHealth(new_health)
pl.ph_prop:SetMaxHealth(ent_health)
pl.ph_prop:SetModel(ent:GetModel())
pl.ph_prop:SetSkin(ent:GetSkin())
-- Update Hull and Health
pl:NewHull(ent:OBBMins(), ent:OBBMaxs())
pl:SetHealth(new_health)
pl:SetMaxHealth(ent_health)
umsg.Start("SetHull", pl)
umsg.Vector(ent:OBBMins())
umsg.Vector(ent:OBBMaxs())
umsg.Short(new_health)
umsg.End()
end
end
-- Prevent the door exploit
if table.HasValue(EXPLOITABLE_DOORS, ent:GetClass()) && pl.last_door_time && pl.last_door_time + 1 > CurTime() then
return false
end
pl.last_door_time = CurTime()
return true
end
-- Called when player presses [F3]. Plays a taunt for their team
function GM:ShowSpare1(pl)
if GAMEMODE:InRound() && pl:Alive() && (pl:Team() == TEAM_HUNTERS || pl:Team() == TEAM_PROPS) && pl.last_taunt_time + TAUNT_DELAY <= CurTime() && #PROP_TAUNTS > 1 && #HUNTER_TAUNTS > 1 then
-- repeat
if pl:Team() == TEAM_HUNTERS then
rand_taunt = table.Random(HUNTER_TAUNTS)
else
rand_taunt = table.Random(PROP_TAUNTS)
end
-- until rand_taunt != pl.last_taunt
pl.last_taunt_time = CurTime()
pl.last_taunt = rand_taunt
print("Prop Hunt: '"..pl:GetName().."' taunting with '"..rand_taunt.."'.")
local vol = 1.0
if pl:Team() == TEAM_HUNTERS then vol = vol * 0.5 end
pl:EmitSound(rand_taunt, 100, 100, vol, CHAN_VOICE2)
end
end
-- Allow player to rotate the prop. (Either F4 or ducking)
function GM:ShowSpare2(pl)
if pl:Alive() && (pl:Team() == TEAM_PROPS) then
pl.ph_prop:SetApplyNewAngles(!pl.ph_prop:GetApplyNewAngles())
-- pl.ph_prop:SetNewAngles(pl:GetAngles())
end
end
-- Called when the gamemode is initialized
function Initialize()
game.ConsoleCommand("mp_flashlight 0\n")
end
hook.Add("Initialize", "PH_Initialize", Initialize)
-- Called when a player leaves
function PlayerDisconnected(pl)
pl:RemoveProp()
end
hook.Add("PlayerDisconnected", "PH_PlayerDisconnected", PlayerDisconnected)
-- Called when the players spawns
function PlayerSpawn(pl)
pl:Blind(false)
pl:RemoveProp()
pl:SetColor( Color(255, 255, 255, 255))
pl:SetRenderMode( RENDERMODE_TRANSALPHA )
pl:UnLock()
pl:ResetHull()
pl:SetViewOffset(Vector(0, 0, 64))
pl:SetViewOffsetDucked(Vector(0, 0, 28))
pl.last_taunt_time = 0
pl:SetupHands()
umsg.Start("ResetHull", pl)
umsg.End()
-- umsg.Start("ThirdPerson", pl)
-- umsg.Bool(pl:Team() == TEAM_PROPS)
-- umsg.Entity(nil)
-- umsg.End()
pl:SetCollisionGroup(COLLISION_GROUP_PASSABLE_DOOR)
end
hook.Add("PlayerSpawn", "PH_PlayerSpawn", PlayerSpawn)
function GM:PlayerSetHandsModel( ply, ent )
local simplemodel = player_manager.TranslateToPlayerModelName( ply:GetModel() )
local info = player_manager.TranslatePlayerHands( simplemodel )
if ( info ) then
ent:SetModel( info.model )
ent:SetSkin( info.skin )
ent:SetBodyGroups( info.body )
end
end
-- Removes all weapons on a map
function RemoveWeaponsAndItems()
for _, wep in pairs(ents.FindByClass("weapon_*")) do
wep:Remove()
end
for _, item in pairs(ents.FindByClass("item_*")) do
item:Remove()
end
end
hook.Add("InitPostEntity", "PH_RemoveWeaponsAndItems", RemoveWeaponsAndItems)
-- Called when round ends
function RoundEnd()
for _, pl in pairs(team.GetPlayers(TEAM_HUNTERS)) do
pl:Blind(false)
pl:UnLock()
end
end
hook.Add("RoundEnd", "PH_RoundEnd", RoundEnd)
-- This is called when the round time ends (props win)
function GM:RoundTimerEnd()
if !GAMEMODE:InRound() then
return
end
GAMEMODE:RoundEndWithResult(TEAM_PROPS, "Props win!")
end
-- Called before start of round
function GM:OnPreRoundStart(num)
game.CleanUpMap()
if GetGlobalInt("RoundNumber") != 1 && (SWAP_TEAMS_EVERY_ROUND == 1 || ((team.GetScore(TEAM_PROPS) + team.GetScore(TEAM_HUNTERS)) > 0 || SWAP_TEAMS_POINTS_ZERO==1)) then
for _, pl in pairs(player.GetAll()) do
if pl:Team() == TEAM_PROPS || pl:Team() == TEAM_HUNTERS then
if pl:Team() == TEAM_PROPS then
pl:SetTeam(TEAM_HUNTERS)
else
pl:SetTeam(TEAM_PROPS)
end
pl:ChatPrint("Teams have been swapped!")
end
end
end
UTIL_StripAllPlayers()
UTIL_SpawnAllPlayers()
UTIL_FreezeAllPlayers()
end
@@ -0,0 +1,52 @@
-- Create new class
DEFINE_BASECLASS( "player_default" )
local CLASS = {}
-- Some settings for the class
CLASS.DisplayName = "Hider"
CLASS.WalkSpeed = 250
CLASS.CrouchedWalkSpeed = 0.2
CLASS.RunSpeed = 250
CLASS.DuckSpeed = 0.2
CLASS.DrawTeamRing = false
-- Called by spawn and sets loadout
function CLASS:Loadout(pl)
-- Props don't get anything
end
-- Called when player spawns with this class
function CLASS:OnSpawn(pl)
pl:SetColor( Color(255, 255, 255, 0))
pl.ph_prop = ents.Create("ph_prop")
pl.ph_prop:SetPos(pl:GetPos())
pl.ph_prop:SetAngles(pl:GetAngles())
pl.ph_prop:Spawn()
pl.ph_prop:SetOwner(pl)
pl:SetJumpPower(200);
-- Update Hull and Health
pl:SetHealth(100)
pl:SetMaxHealth(100)
pl.ph_prop:SetHealth(100)
pl.ph_prop:SetMaxHealth(100)
local hullMin = Vector(-20, -20, -10)
local hullMax = Vector( 20, 20, 60)
pl:NewHull(hullMin, hullMax)
umsg.Start("SetHull", pl)
umsg.Vector(hullMin)
umsg.Vector(hullMax)
umsg.Short(100)
umsg.End()
end
-- Called when a player dies with this class
function CLASS:OnDeath(pl, attacker, dmginfo)
pl:RemoveProp()
end
-- Register
player_manager.RegisterClass("Hider", CLASS)
@@ -0,0 +1,120 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Project Kube
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( "player_default" )
local SEEKER = {}
SEEKER.DisplayName = "Seeker"
SEEKER.WalkSpeed = 230 -- How fast to move when not running
SEEKER.RunSpeed = 460 -- How fast to move when running
SEEKER.CrouchedWalkSpeed = 0.2 -- Multiply move speed by this when crouching
SEEKER.DuckSpeed = 0.2 -- How fast to go from not ducking, to ducking
SEEKER.UnDuckSpeed = 0.2 -- How fast to go from ducking, to not ducking
SEEKER.JumpPower = 200 -- How powerful our jump should be
SEEKER.CanUseFlashlight = true -- Can we use the flashlight
SEEKER.MaxHealth = 100 -- Max health we can have
SEEKER.StartHealth = 100 -- How much health we start with
SEEKER.StartArmor = 0 -- How much armour we start with
SEEKER.DropWeaponOnDie = false -- Do we drop our weapon when we die
SEEKER.TeammateNoCollide = true -- Do we collide with teammates or run straight through them
SEEKER.AvoidPlayers = true -- Automatically swerves around other players
SEEKER.UseVMHands = true -- Uses viewmodel hands
-- Called by spawn and sets loadout
function SEEKER:Loadout(pl)
-- Give the weapons the admin told us to.
local weapons = string.Split(GM.Config.Seeker.Weapons, ",")
for i,weapon in ipairs(weapons) do
pl:Give(weapon)
end
-- Give the ammo the admin told us to.
local ammos = string.Split(GM.Config.Seeker.Ammo, ",")
for i,ammo in ipairs(ammos) do
local typeCount = string.Split(ammo, ":")
pl:GiveAmmo(typeCount[1], typeCount[0], true)
end
-- Default weapon stuff
local cl_defaultweapon = pl:GetInfo("cl_defaultweapon")
if pl:HasWeapon(cl_defaultweapon) then
pl:SelectWeapon(cl_defaultweapon)
end
end
-- Called when player spawns with this class
function SEEKER:OnSpawn(pl)
local unlock_time = math.Clamp(GetConVar("ph_rounds_blindtime"):GetInt() - (CurTime() - GetGlobalFloat("RoundStartTime", 0)), 0, GetConVar("ph_rounds_blindtime"):GetInt()) - 1
-- !TODO! ph_rounds_blindtime
--function MyLockFunc()
--function MyUnlockFunc()
local unblindfunc = function()
if pl:IsValid() == false then return end
--MyUnblindFunc(pl.Blind(false))
pl:Blind(false)
end
local lockfunc = function()
if pl:IsValid() == false then return end
--MyLockFunc(pl.Lock())
pl.Lock(pl)
end
local unlockfunc = function()
if pl:IsValid() == false then return end
--MyUnlockFunc(pl.UnLock())
pl.UnLock(pl)
end
if unlock_time > 2 then
pl:Blind(true)
timer.Simple(unlock_time, unblindfunc)
timer.Simple(1, lockfunc)
timer.Simple(unlock_time, unlockfunc)
end
pl:SetupHands()
end
function SEEKER:GetHandsModel()
return { model = "models/weapons/c_arms_combine.mdl", skin = 1, body = "0100000" }
end
-- Called when a player dies with this SEEKER
function SEEKER:OnDeath(pl, attacker, dmginfo)
pl:CreateRagdoll()
pl:UnLock()
end
-- Register
player_manager.RegisterClass("Seeker", SEEKER)
@@ -0,0 +1,433 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Project Kube
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 = { }
--! Basic Settings
-- Timelimit in minutes
GM.Config.TimeLimit = math.max(GetConVarNumber("mp_timelimit"),0)
-- You have to wait x seconds to taunt again.
GM.Config.TauntWaitTime = 5
-- Is sprinting enabled?
GM.Config.Sprinting = 0 --false
--! Round Settings
GM.Config.Rounds = {}
-- How many rounds should we attempt to have?
GM.Config.Rounds.Amount = 10
-- Rounds last x seconds.
GM.Config.Rounds.Time = 300
-- Time for HIders to hide.
GM.Config.Rounds.BlindTime = 30
--! Game Modes
GM.Config.Modes = {}
-- Sub-mode: Simple Team Swap
GM.Config.Modes.SwapTeams = 1--true
-- Sub-mode: Randomize Teams
GM.Config.Modes.RandomizeTeams = 0--false
-- Sub-mode: The Dead Hunt (Dead Prop becomes Hunter)
GM.Config.Modes.TheDeadHunt = 0--false
--! Seeker Settings
GM.Config.Seeker = {}
GM.Config.Seeker.HealthStart = 100
GM.Config.Seeker.HealthMax = 100
GM.Config.Seeker.HealthBonus = 10
GM.Config.Seeker.HealthPenalty = 1
GM.Config.Seeker.Weapons = "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun"
GM.Config.Seeker.Ammo = "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64"
--! Hider Settings
GM.Config.Hider = {}
GM.Config.Hider.HealthStart = 100
GM.Config.Hider.HealthMax = 100
GM.Config.Hider.HealthScaling = 1--true
GM.Config.Hider.HealthScalingMax = 200
--! 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.Debug then print("Prop Hunt.Taunts.Load: Loading taunt list from file '"..sTauntListFile.."'...") end
-- Safeguard against idiots.
if type(sTauntListFile) != "string" then
if GAMEMODE.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.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.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.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.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.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.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.Debug then print("Prop Hunt.Taunts.Save: Saving taunt list to file '"..sTauntListFile.."'...") end
-- Safeguard against idiots.
if type(sTauntListFile) != "string" then
if GAMEMODE.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.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.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.Debug then print("Prop Hunt.Taunts.Save: Failed to write to file.") end
return false
end
if GAMEMODE.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.Debug then print("Prop Hunt.Taunts.Add: Adding new taunt '"..sTauntName.."'...") end
-- Safeguard against idiots.
if type(sTauntName) != "string" then
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: <sTauntName> is not a string.") end
return false
end
if type(sSoundFile) != "string" then
if GAMEMODE.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.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.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.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.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.Debug then print("Prop Hunt.Taunts.Add: Team "..iTeamID.."' can't have taunts.") end
return false
end
end
if GAMEMODE.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.Debug then print("Prop Hunt.Taunts.Remove: Removing taunt '"..sTauntName.."'...") end
-- Safeguard against idiots.
if type(sTauntName) != "string" then
if GAMEMODE.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.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.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.Debug then print("Prop Hunt.Taunts.Remove: Team "..iTeamID.."' can't have taunts.") end
return false
end
end
if GAMEMODE.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.Debug then print("Prop Hunt.Announcers.Load: Loading announcer list from file '"..sAnnouncerListFile.."'...") end
-- Safeguard against idiots.
if type(sAnnouncerListFile) != "string" then
if GAMEMODE.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.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.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.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.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.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.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.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.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.Debug then print("Prop Hunt.Announcers.Save: Saving announcer list to file '"..sAnnouncerListFile.."'...") end
-- Safeguard against idiots.
if type(sAnnouncerListFile) != "string" then
if GAMEMODE.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.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.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.Debug then print("Prop Hunt.Announcers.Save: Failed to write to file.") end
return false
end
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Save: Complete.") end
return true
end
-- ToDo: Announcers.Add
-- ToDo: Announcers.Remove
-- ToDo: Announcers.Get(iType)
--! Whitelists and Blacklists
-- Hiders: Entity Whitelist (exact match)
GM.Config.EntityWhitelist = {
"prop_physics",
"prop_physics_multiplayer"
}
-- Hiders: Prop Blacklist (exact match)
GM.Config.PropBlacklist = {}
-- Both: Entity Use-abuse Blacklist (exact match)
GM.Config.EntityAbuseBlacklist = {
"func_door",
"func_door_rotating",
"prop_door_rotating"
}
@@ -0,0 +1,45 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Project Kube
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.
--]]
CreateConVar("ph_tauntwaittime", GM.Config.TauntWaitTime)
CreateConVar("ph_sprinting", GM.Config.Sprinting)
CreateConVar("ph_rounds", GM.Config.Rounds.Amount)
CreateConVar("ph_rounds_time", GM.Config.Rounds.Time)
CreateConVar("ph_rounds_blindtime", GM.Config.Rounds.BlindTime)
CreateConVar("ph_modes_swap", GM.Config.Modes.SwapTeams)
CreateConVar("ph_modes_randomize", GM.Config.Modes.RandomizeTeams)
CreateConVar("ph_modes_thedeadhunt", GM.Config.Modes.TheDeadHunt)
CreateConVar("ph_seeker_health", GM.Config.Seeker.HealthStart)
CreateConVar("ph_seeker_health_max", GM.Config.Seeker.HealthMax)
CreateConVar("ph_seeker_health_killbonus", GM.Config.Seeker.HealthBonus)
CreateConVar("ph_seeker_health_penalty", GM.Config.Seeker.HealthPenalty)
CreateConVar("ph_seeker_weapons", GM.Config.Seeker.Weapons)
CreateConVar("ph_seeker_ammo", GM.Config.Seeker.Ammo)
CreateConVar("ph_hider_health", GM.Config.Hider.HealthStart)
CreateConVar("ph_hider_health_max", GM.Config.Hider.HealthMax)
CreateConVar("ph_hider_health_scale", GM.Config.Hider.HealthScaling)
CreateConVar("ph_hider_health_scaled_max", GM.Config.Hider.HealthScalingMax)
@@ -0,0 +1,366 @@
if !file.IsDir("prop_hunt", "DATA") then file.CreateDir("prop_hunt") end
-- These are Models that the Prop team can not become.
-- Usually you'd put invisible or impossible to hit models in here.
BANNED_PROP_MODELS = {
"models/props/cs_assault/dollar.mdl",
"models/props/cs_assault/money.mdl",
"models/props/cs_office/snowman_arm.mdl",
"models/props_junk/garbage_plasticbottle001a.mdl",
"models/props/cs_office/projector_remote.mdl"
}
if (! file.Exists("prop_hunt/banned_props.txt", "DATA")) then
file.Write("prop_hunt/banned_props.txt", util.TableToKeyValues(BANNED_PROP_MODELS))
end
local fileContent = file.Read("prop_hunt/banned_props.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then BANNED_PROP_MODELS = fileTable end
end
-- 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"
}
if (! file.Exists("prop_hunt/sounds_loss.txt", "DATA")) then
file.Write("prop_hunt/sounds_loss.txt", util.TableToKeyValues(LOSS_SOUNDS))
end
local fileContent = file.Read("prop_hunt/sounds_loss.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then LOSS_SOUNDS = fileTable end
end
-- 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"
}
if (! file.Exists("prop_hunt/sounds_victory.txt", "DATA")) then
file.Write("prop_hunt/sounds_victory.txt", util.TableToKeyValues(VICTORY_SOUNDS))
end
local fileContent = file.Read("prop_hunt/sounds_victory.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then VICTORY_SOUNDS = fileTable end
end
-- 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"
}
if (! file.Exists("prop_hunt/sounds_taunt_hunter.txt", "DATA")) then
file.Write("prop_hunt/sounds_taunt_hunter.txt", util.TableToKeyValues(HUNTER_TAUNTS))
end
local fileContent = file.Read("prop_hunt/sounds_taunt_hunter.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then HUNTER_TAUNTS = fileTable end
end
-- 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"
}
if (! file.Exists("prop_hunt/sounds_taunt_prop.txt", "DATA")) then
file.Write("prop_hunt/sounds_taunt_prop.txt", util.TableToKeyValues(PROP_TAUNTS))
end
local fileContent = file.Read("prop_hunt/sounds_taunt_prop.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then PROP_TAUNTS = fileTable end
end
-- Maximum time (in minutes) for this fretta gamemode (Default: 30)
GAME_TIME = math.max(GetConVarNumber("mp_timelimit"),1)
-- Number of seconds hunters are blinded/locked at the beginning of the map (Default: 30)
CreateConVar("HUNTER_BLINDLOCK_TIME", "30", FCVAR_REPLICATED)
--Create the convars here
-- Health points removed from hunters when they shoot (Default: 5)
CreateConVar( "HUNTER_FIRE_PENALTY", "5", FCVAR_REPLICATED)
-- How much health to give back to the Hunter after killing a prop (Default: 20)
CreateConVar( "HUNTER_KILL_BONUS", "20", FCVAR_REPLICATED)
--Whether or not we include grenade launcher ammo (default: 1)
CreateConVar( "WEAPONS_ALLOW_GRENADE", "1", FCVAR_REPLICATED)
-- Seconds a player has to wait before they can taunt again (Default: 5)
TAUNT_DELAY = 2
-- Rounds played on a map (Default: 10)
ROUNDS_PER_MAP = 60
-- Time (in seconds) for each round (Default: 300)
ROUND_TIME = 300
-- Determains if players should be team swapped every round [0 = No, 1 = Yes] (Default: 1)
SWAP_TEAMS_EVERY_ROUND = 1
-- Update above values with values from configuration.
if (! file.Exists("prop_hunt/config.txt", "DATA")) then
file.Write("prop_hunt/config.txt", util.TableToKeyValues({
-- GAME_TIME = 30,
TAUNT_DELAY = 2,
ROUNDS_PER_MAP = 60,
ROUND_TIME = 300,
SWAP_TEAM_EVERY_ROUND = 1
}))
end
local fileContent = file.Read("prop_hunt/config.txt", "DATA");
if fileContent then
local fileTable = util.KeyValuesToTable(fileContent)
if fileTable then
-- if fileTable.GAME_TIME then GAME_TIME = fileTable.GAME_TIME end
if fileTable.TAUNT_DELAY then TAUNT_DELAY = fileTable.TAUNT_DELAY end
if fileTable.ROUNDS_PER_MAP then ROUNDS_PER_MAP = fileTable.ROUNDS_PER_MAP end
if fileTable.ROUND_TIME then ROUND_TIME = fileTable.ROUND_TIME end
if fileTable.SWAP_TEAM_EVERY_ROUND then ROUND_TIME = fileTable.SWAP_TEAM_EVERY_ROUND end
end
end
GAME_TIME = math.max(GetConVarNumber("mp_timelimit"),1)
@@ -0,0 +1,93 @@
-- Gamemode Information
GM.Name = "Prop Hunt"
GM.Author = "Michael 'Xaymar' Dirks (Based on Kow@lskis Version, Original by AMT)"
GM.Email = "michael.fabian.dirks@gmail.com"
GM.Website = "http://xaymar.com/"
GM.Debug = (cvars.Number("developer") != 0)
-- ToDo: Remove fretta as a base gamemode (it's outdated and doesn't help us much).
DeriveGamemode("fretta13")
-- Shared Lua Files
if SERVER then
AddCSLuaFile("sh_config.lua")
AddCSLuaFile("sh_player.lua")
end
-- Player Classes
if SERVER then
AddCSLuaFile("player_class/class_seeker.lua")
AddCSLuaFile("player_class/class_hider.lua")
end
include "player_class/class_seeker.lua"
include "player_class/class_hider.lua"
-- Set up Teams
TEAM_SPECTATOR = 0
TEAM_SEEKERS = 1
TEAM_HIDERS = 2
TEAM_HUNTERS = TEAM_SEEKERS -- Deprecated
TEAM_PROPS = TEAM_HIDERS -- Deprecated
function GM:CreateTeams()
-- Seekers: "Hunters"
team.SetUp(TEAM_SEEKERS, "Seekers", Color(153, 204, 255, 255))
team.SetSpawnPoint(TEAM_SEEKERS, {
"info_player_deathmatch",
"info_player_axis",
"info_player_combine",
"info_player_counterterrorist"
})
team.SetClass(TEAM_SEEKERS, { "Seeker" })
-- Hiders: "Props"
team.SetUp(TEAM_HIDERS, "Hiders", Color(255, 204, 153, 255))
team.SetSpawnPoint(TEAM_HIDERS, {
"info_player_deathmatch",
"info_player_allies",
"info_player_terrorist"
})
team.SetClass(TEAM_HIDERS, { "Hider" })
end
-- Gamemode Player Code & Data
include("sh_player.lua")
-- Gamemode Configuration Code & Data
include("sh_config.lua")
-- Include the configuration for this map
if file.Exists("maps/"..game.GetMap()..".lua", "LUA") || file.Exists("maps/"..game.GetMap()..".lua", "LUA") then
include("maps/"..game.GetMap()..".lua")
end
-- Help info
GM.Help = [[Prop Hunt is a twist on the classic backyard game Hide and Seek.
As a Prop you have ]]..GetConVar("HUNTER_BLINDLOCK_TIME"):GetInt()..[[ seconds to replicate an existing prop on the map and then find a good hiding spot. Press [E] to replicate the prop you are looking at. Your health is scaled based on the size of the prop you replicate.
As a Hunter you will be blindfolded for the first ]]..GetConVar("HUNTER_BLINDLOCK_TIME"):GetInt()..[[ seconds of the round while the Props hide. When your blindfold is taken off, you will need to find props controlled by players and kill them. Damaging non-player props will lower your health significantly. However, killing a Prop will increase your health by ]]..GetConVar("HUNTER_KILL_BONUS"):GetInt()..[[ points.
Both teams can press [F3] to play a taunt sound. Props can press F4 to enable rotation.]]
-- Fretta configuration
GM.AddFragsToTeamScore = true
GM.CanOnlySpectateOwnTeam = true
GM.Data = {}
GM.EnableFreezeCam = true
GM.GameLength = GAME_TIME
GM.NoAutomaticSpawning = true
GM.NoNonPlayerPlayerDamage = true
GM.NoPlayerPlayerDamage = true
GM.RoundBased = true
GM.RoundLimit = ROUNDS_PER_MAP
GM.RoundLength = ROUND_TIME
GM.RoundPreStartTime = 0
GM.SelectModel = false
GM.SuicideString = "couldn't take the pressure and committed suicide."
GM.TeamBased = true
@@ -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
@@ -0,0 +1,39 @@
--[[
The MIT License (MIT)
Copyright (c) 2015 Project Kube
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.
--]]
--! Our custom RoundManager
-- We need to keep track of three states in a round: Hide, Seek and PostRound.
--! Round States
ROUNDSTATE_HIDE = 1
ROUNDSTATE_SEEK = 2
ROUNDSTATE_POSTROUND = 3
function RoundManagerInit()
end
function RoundManagerAdvance()
end
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

@@ -0,0 +1,50 @@
<NotepadPlus>
<Project name="Prop Hunt">
<Folder name="gamemode">
<Folder name="compat">
<File name="gamemode\compat\compat_tauntpackloader.lua" />
</Folder>
<Folder name="player_class">
<File name="gamemode\player_class\class_seeker.lua" />
<File name="gamemode\player_class\class_hider.lua" />
</Folder>
<Folder name="server">
<Folder name="console">
<File name="gamemode\server\console\variables.lua" />
</Folder>
<File name="gamemode\server\config.lua" />
</Folder>
<File name="gamemode\cl_init.lua" />
<File name="gamemode\cl_worldtips.lua" />
<File name="gamemode\init.lua" />
<File name="gamemode\sh_config.lua" />
<File name="gamemode\sh_init.lua" />
<File name="gamemode\sh_player.lua" />
</Folder>
<Folder name="data">
<Folder name="prop_hunt">
<File name="data\prop_hunt\banned_props.txt" />
<File name="data\prop_hunt\config.txt" />
<File name="data\prop_hunt\sounds_loss.txt" />
<File name="data\prop_hunt\sounds_taunt_hunter.txt" />
<File name="data\prop_hunt\sounds_taunt_prop.txt" />
<File name="data\prop_hunt\sounds_victory.txt" />
</Folder>
</Folder>
<Folder name="entities">
<Folder name="entities">
<Folder name="ph_prop">
<File name="entities\entities\ph_prop\cl_init.lua" />
<File name="entities\entities\ph_prop\init.lua" />
<File name="entities\entities\ph_prop\shared.lua" />
</Folder>
</Folder>
<Folder name="weapons">
<File name="entities\weapons\weapon_ph_smg.lua" />
</Folder>
</Folder>
<File name="icon24.png" />
<File name="logo.png" />
<File name="xaymars_prop_hunt.txt" />
</Project>
</NotepadPlus>
@@ -0,0 +1,196 @@
"xaymars_prop_hunt"
{
"base" "base"
"title" "Prop Hunt"
"maps" "^ph_|^cs_|^de_|^ttt_"
"fretta_maps"
{
"1" "ph_"
"2" "cs_"
"3" "de_"
"4" "ttt_"
}
"selectable" "1"
"menusystem" "1"
"workshopid" "468149739"
"settings"
{
// Game Settings
1
{
"name" "mp_timelimit"
"text" "G: Time Limit"
"help" "Time Limit in Minutes for how long should we stay on one map. (0 to disable)"
"type" "Numeric"
"default" "20"
}
2
{
"name" "ph_sprinting"
"text" "G: Enable Sprinting"
"help" "Should sprinting be possible?"
"type" "CheckBox"
"default" "0"
}
3
{
"name" "ph_tauntwaittime"
"text" "G: Taunt Cooldown"
"help" "How much time must pass before another taunt may be played."
"type" "Numeric"
"default" "5"
}
// Round Settings
4
{
"name" "ph_rounds"
"text" "R: Rounds per Map"
"help" "How many rounds are played per map."
"type" "Numeric"
"default" "10"
}
5
{
"name" "ph_rounds_time"
"text" "R: Round Duration (Seconds)"
"help" "How long is each round going to last?"
"type" "Numeric"
"default" "300"
}
6
{
"name" "ph_rounds_blindtime"
"text" "R: Hiding Time (Seconds)"
"help" "How long are Seekers blinded in seconds?"
"type" "Numeric"
"default" "30"
}
7
{
"name" "ph_rounds_teams_swap"
"text" "R: Swap Teams every round?"
"help" "Should teams be swapped every round? (Can't be used with Randomize)"
"type" "CheckBox"
"default" "1"
}
8
{
"name" "ph_rounds_teams_randomize"
"text" "R: Randomize Teams every round?"
"help" "Should teams be randomized every round? (Can't be used with Swap)"
"type" "CheckBox"
"default" "0"
}
// Seeker Settings
9
{
"name" "ph_seeker_health"
"text" "S: Health"
"type" "Numeric"
"default" "100"
}
10
{
"name" "ph_seeker_health_max"
"text" "S: Max Health"
"type" "Numeric"
"default" "100"
}
11
{
"name" "ph_seeker_health_killbonus"
"text" "S: Health Kill-Bonus"
"help" "Health gained on kill."
"type" "Numeric"
"default" "10"
}
11
{
"name" "ph_seeker_health_penalty"
"text" "S: Health Penalty"
"help" "Health lost on wrong shot."
"type" "Numeric"
"default" "1"
}
12
{
"name" "ph_seeker_ammo_pistol"
"text" "S: Ammo for Pistol"
"type" "Numeric"
"default" "40"
}
13
{
"name" "ph_seeker_ammo_smg"
"text" "S: Ammo for SMG"
"type" "Numeric"
"default" "300"
}
14
{
"name" "ph_seeker_ammo_smggrenade"
"text" "S: Ammo for SMG Grenade"
"type" "Numeric"
"default" "1"
}
15
{
"name" "ph_seeker_ammo_shotgun"
"text" "S: Ammo for Shotgun"
"type" "Numeric"
"default" "60"
}
// Hider Settings
16
{
"name" "ph_hider_health"
"text" "H: Health"
"type" "Numeric"
"default" "100"
}
17
{
"name" "ph_hider_health_max"
"text" "H: Max Health"
"type" "Numeric"
"default" "100"
}
18
{
"name" "ph_hider_health_scale"
"text" "H: Enable Health Scaling"
"help" "Larger & heavier objects have more health, smaller less."
"type" "CheckBox"
"default" "1"
}
19
{
"name" "ph_hider_health_scaled_max"
"text" "H: Scaled Max Health"
"type" "Numeric"
"default" "200"
}
}
}
+22 -22
View File
@@ -1,22 +1,22 @@
The MIT License (MIT)
Copyright (c) 2016 Michael Fabian Dirks
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.
The MIT License (MIT)
Copyright (c) 2016 Michael Fabian Dirks
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.
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

+7
View File
@@ -0,0 +1,7 @@
@ECHO OFF
:: Retrieve Garry's Mod path from Regristry
:: FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
SET "GARRYSMODPATH=D:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
SET "PATH=%CD%;%GARRYSMODPATH%\bin;%PATH%"
CMD
+9
View File
@@ -0,0 +1,9 @@
@ECHO OFF
:: Fallback
SET "GARRYSMODPATH=D:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
:: Retrieve Garry's Mod path from Regristry
FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
"%GARRYSMODPATH%\bin\gmad.exe" create -folder "%CD%/Gamemode" -out "%CD%/Pack.gma"
PAUSE
+10
View File
@@ -0,0 +1,10 @@
@ECHO OFF
:: Fallback
SET "GARRYSMODPATH=D:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
:: Retrieve Garry's Mod path from Regristry
FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
SET /P CHANGES=Changes:
"%GARRYSMODPATH%\bin\gmpublish.exe" update -id 468149739 -icon "Logo.jpg" -addon "Pack.gma" -changes "%CHANGES%
PAUSE