Code update, forgot to actually do this... *hides in a corner*
This commit is contained in:
+41
-41
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
Binary file not shown.
|
After Width: | Height: | Size: 321 KiB |
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user