diff --git a/Media/icon24.png b/Media/icon24.png new file mode 100644 index 0000000..68a25b6 Binary files /dev/null and b/Media/icon24.png differ diff --git a/Media/logo_wide.png b/Media/logo_wide.png new file mode 100644 index 0000000..5d390f9 Binary files /dev/null and b/Media/logo_wide.png differ diff --git a/Media/team_hiders.png b/Media/team_hiders.png new file mode 100644 index 0000000..d54ed2b Binary files /dev/null and b/Media/team_hiders.png differ diff --git a/Media/team_seekers.png b/Media/team_seekers.png new file mode 100644 index 0000000..c8482f7 Binary files /dev/null and b/Media/team_seekers.png differ diff --git a/Source/gamemodes/prophuntextended/content/materials/gamemode/teams/team_hiders.png b/Source/gamemodes/prophuntextended/content/materials/gamemode/teams/team_hiders.png new file mode 100644 index 0000000..d54ed2b Binary files /dev/null and b/Source/gamemodes/prophuntextended/content/materials/gamemode/teams/team_hiders.png differ diff --git a/Source/gamemodes/prophuntextended/content/materials/gamemode/teams/team_seekers.png b/Source/gamemodes/prophuntextended/content/materials/gamemode/teams/team_seekers.png new file mode 100644 index 0000000..c8482f7 Binary files /dev/null and b/Source/gamemodes/prophuntextended/content/materials/gamemode/teams/team_seekers.png differ diff --git a/Source/gamemodes/prophuntextended/entities/entities/ph_prop/shared.lua b/Source/gamemodes/prophuntextended/entities/entities/ph_prop/shared.lua index e969442..ada4014 100644 --- a/Source/gamemodes/prophuntextended/entities/entities/ph_prop/shared.lua +++ b/Source/gamemodes/prophuntextended/entities/entities/ph_prop/shared.lua @@ -23,7 +23,15 @@ function ENT:Think() -- Angles if (self.Owner:GetNWBool("PropRotation")) then - self:SetAngles(self.Owner:EyeAngles()) + self:ApplyRotation(self.Owner:EyeAngles()) end end +function ENT:ApplyRotation(ang) + if !(GAMEMODE.Config.Hider:AllowFullRotation()) then + ang.p = 0 + ang.r = 0 + end + self:SetAngles(ang) +end + diff --git a/Source/gamemodes/prophuntextended/gamemode/__sh_config.lua b/Source/gamemodes/prophuntextended/gamemode/__sh_config.lua new file mode 100644 index 0000000..21d8442 --- /dev/null +++ b/Source/gamemodes/prophuntextended/gamemode/__sh_config.lua @@ -0,0 +1,259 @@ +-- Sounds played by members of the losing team at the end of the round. +LOSS_SOUNDS = { + "bot/aw_hell.wav", + "bot/aww_man.wav", + "bot/anyone_see_anything.wav", + "bot/anyone_see_them.wav", + "bot/come_out_and_fight_like_a_man.wav", + "bot/come_out_wherever_you_are.wav", + "bot/he_got_away.wav", + "bot/he_got_away2.wav", + "bot/i_dont_know_where_he_went.wav", + "bot/i_got_nothing.wav", + "bot/nothing_happening_over_here.wav", + "bot/nothing_here.wav", + "bot/nothing_moving_over_here.wav", + "bot/thats_not_good.wav", + "bot/theres_too_many.wav", + "bot/theres_too_many_of_them.wav", + "bot/theyre_all_over_the_place2.wav", + "bot/theyre_everywhere2.wav", + "bot/too_many2.wav", + "bot/what_happened.wav", + "bot/what_have_you_done.wav", + "bot/where_are_they.wav", + "bot/where_are_you_hiding.wav" +} +-- Sounds played by members of the winning team at the end of the round. +VICTORY_SOUNDS = { + "bot/and_thats_how_its_done.wav", + "bot/come_to_papa.wav", + "bot/do_not_mess_with_me.wav", + "bot/dropped_him.wav", + "bot/enemy_down.wav", + "bot/enemy_down2.wav", + "bot/good_job_team.wav", + "bot/got_him.wav", + "bot/hes_broken.wav", + "bot/hes_dead.wav", + "bot/hes_done.wav", + "bot/hes_down.wav", + "bot/its_a_party.wav", + "bot/i_am_dangerous.wav", + "bot/i_am_on_fire.wav", + "bot/i_got_more_where_that_came_from.wav", + "bot/i_wasnt_worried_for_a_minute.wav", + "bot/killed_him.wav", + "bot/look_out_brag.wav", + "bot/made_him_cry.wav", + "bot/oh_yea.wav", + "bot/oh_yea2.wav", + "bot/owned.wav", + "bot/ruined_his_day.wav", + "bot/tag_them_and_bag_them.wav", + "bot/thats_the_way_this_is_done.wav", + "bot/that_was_a_close_one.wav", + "bot/that_was_it.wav", + "bot/that_was_the_last_guy.wav", + "bot/that_was_the_last_one.wav", + "bot/they_never_knew_what_hit_them.wav", + "bot/they_will_not_escape.wav", + "bot/they_wont_get_away.wav", + "bot/they_wont_get_away2.wav", + "bot/this_is_my_house.wav", + "bot/took_him_down.wav", + "bot/took_him_out.wav", + "bot/took_him_out2.wav", + "bot/wasted_him.wav", + "bot/way_to_be_team.wav", + "bot/well_done.wav", + "bot/we_owned_them.wav", + "bot/whew_that_was_close.wav", + "bot/whoo.wav", + "bot/whoo2.wav", + "bot/whos_the_man.wav", + "bot/who_wants_some_more.wav", + "bot/yesss.wav", + "bot/yesss2.wav" +} +-- Taunts played when Hunters hit their Spare1 binding. +HUNTER_TAUNTS = { + "bot/a_bunch_of_them.wav", + "bot/come_out_and_fight_like_a_man.wav", + "bot/come_out_wherever_you_are.wav", + "bot/come_to_papa.wav", + "bot/dont_worry_hell_get_it.wav", + "bot/hang_on_i_heard_something.wav", + "bot/hang_on_im_coming.wav", + "bot/i_dont_think_so.wav", + "bot/i_have_the_hostages.wav", + "bot/i_see_our_target.wav", + "bot/im_waiting_here.wav", + "bot/keeping_an_eye_on_the_hostages.wav", + "bot/nnno_sir.wav", + "bot/spotted_the_delivery_boy.wav", + "bot/target_acquired.wav", + "bot/target_spotted.wav", + "bot/you_heard_the_man_lets_go.wav" +} +-- Taunts played when Props hit their Spare1 binding. +PROP_TAUNTS = { +-- "ambient/alarms/apc_alarm_loop1.wav", + "ambient/alarms/apc_alarm_pass1.wav", +-- "ambient/alarms/citadel_alert_loop2.wav", +-- "ambient/alarms/city_firebell_loop1.wav", +-- "ambient/alarms/city_siren_loop2.wav", +-- "ambient/alarms/combine_bank_alarm_loop1.wav", +-- "ambient/alarms/combine_bank_alarm_loop4.wav", +-- "ambient/alarms/klaxon1.wav", + "ambient/alarms/manhack_alert_pass1.wav", + "ambient/alarms/razortrain_horn1.wav", + "ambient/alarms/scanner_alert_pass1.wav", +-- "ambient/alarms/siren.wav", +-- "ambient/alarms/train_crossing_bell_loop1.wav", + "ambient/alarms/train_horn2.wav", + "ambient/alarms/train_horn_distant1.wav", + "ambient/alarms/warningbell1.wav", +-- "ambient/chatter/cb_radio_chatter_1.wav", +-- "ambient/chatter/cb_radio_chatter_2.wav", +-- "ambient/chatter/cb_radio_chatter_3.wav", + "ambient/energy/whiteflash.wav", + "ambient/intro/alyxremove.wav", + "ambient/intro/logosfx.wav", +-- "ambient/levels/labs/teleport_alarm_loop1.wav", + "ambient/levels/launch/1stfiringwarning.wav", + "ambient/levels/launch/rockettakeoffblast.wav", +-- "ambient/levels/outland/basealarmloop.wav", +-- "ambient/machines/60hzhum.wav", + "ambient/misc/ambulance1.wav", + "ambient/misc/carhonk1.wav", + "ambient/misc/carhonk2.wav", + "ambient/misc/carhonk3.wav", +-- "ambient/music/bongo.wav", +-- "ambient/music/country_rock_am_radio_loop.wav", +-- "ambient/music/cubanmusic1.wav", +-- "ambient/music/dustmusic1.wav", +-- "ambient/music/dustmusic2.wav", +-- "ambient/music/dustmusic3.wav", +-- "ambient/music/flamenco.wav", +-- "ambient/music/latin.wav", +-- "ambient/music/mirame_radio_thru_wall.wav", +-- "ambient/music/piano1.wav", +-- "ambient/music/piano2.wav", + "ambient/outro/gunshipcrash.wav", + "ambient/3dmeagle.wav", +-- "ambient/guit1.wav", +-- "ambient/opera.wav", +-- "ambient/sheep.wav", + "beams/beamstart5.wav", + "buttons/bell1.wav", + "buttons/weapon_cant_buy.wav", + "common/bass.wav", + "common/bugreporter_failed.wav", + "common/warning.wav", + "doors/door_squeek1.wav", + "friends/friend_join.wav", + "friends/friend_online.wav", + "friends/message.wav", + "hostage/hunuse/comeback.wav", + "hostage/hunuse/dontleaveme.wav", + "hostage/hunuse/yeahillstay.wav", + "items/gift_drop.wav", + "music/radio1.mp3", + "phx/eggcrack.wav", + "plats/elevbell1.wav", + "player/headshot1.wav", + "player/headshot2.wav", + "player/sprayer.wav", + "radio/enemydown.wav", + "radio/go.wav", + "radio/locknload.wav", + "radio/negative.wav", + "radio/rounddraw.wav", + "radio/takepoint.wav", + "resource/warning.wav", +-- "test/temp/soundscape_test/tv_music.wav", + "ui/achievement_earned.wav", + "ui/freeze_cam.wav", + "vehicles/junker/radar_ping_friendly1.wav", + "weapons/c4/c4_beep1.wav", + "weapons/c4/c4_click.wav", + "weapons/awp/awp1.wav", + "vo/canals/female01/gunboat_giveemhell.wav", + "vo/canals/female01/gunboat_justintime.wav", + "vo/canals/female01/stn6_incoming.wav", + "vo/canals/male01/gunboat_giveemhell.wav", + "vo/canals/male01/gunboat_justintime.wav", + "vo/canals/male01/stn6_incoming.wav", + "vo/canals/al_radio_stn6.wav", + "vo/canals/arrest_getgoing.wav", + "vo/canals/arrest_helpme.wav", + "vo/canals/arrest_lookingforyou.wav", + "vo/canals/boxcar_lethimhelp.wav", + "vo/canals/matt_closecall.wav", + "vo/canals/premassacre.wav", + "vo/ravenholm/aimforhead.wav", + "vo/ravenholm/bucket_patience.wav", + "vo/ravenholm/madlaugh01.wav", + "vo/ravenholm/madlaugh02.wav", + "vo/ravenholm/madlaugh03.wav", + "vo/ravenholm/madlaugh04.wav", + "weapons/strider_buster/ol12_stickybombcreator.wav", + "weapons/c4/c4_explode1.wav", + "weapons/357/357_fire2.wav", + "weapons/357/357_fire3.wav", + "weapons/scout/scout_fire-1.wav", + "weapons/smokegrenade/sg_explode.wav", + "weapons/grenade_launcher1.wav", + "weapons/explode3.wav", + "weapons/underwater_explode3.wav", + "items/nvg_on.wav", + "hostage/huse/letsdoit.wav", + "hostage/huse/illfollow.wav", + "hostage/huse/getouttahere.wav", + "doors/door_screen_move1.wav", + "doors/heavy_metal_stop1.wav", + "doors/default_move.wav", + "common/stuck2.wav", + "ambient/water_splash1.wav", + "ambient/water_splash2.wav", + "ambient/water_splash3.wav", + "ambient/weather/thunder1.wav", + "ambient/weather/thunder2.wav", + "ambient/weather/thunder3.wav", + "ambient/weather/thunder4.wav", + "ambient/weather/thunder5.wav", + "ambient/weather/thunder6.wav", + "ambient/outro/thunder7.wav", + "ambient/voices/crying_loop1.wav", + "ambient/voices/playground_memory.wav", + "ambient/voices/f_scream1.wav", + "ambient/voices/m_scream1.wav", + "ambient/voices/cough1.wav", + "ambient/voices/cough2.wav", + "ambient/voices/cough3.wav", + "ambient/voices/cough4.wav", + "ambient/overhead/plane1.wav", + "ambient/overhead/plane2.wav", + "ambient/overhead/plane3.wav", + "ambient/overhead/hel1.wav", + "ambient/overhead/hel2.wav", + "ambient/misc/truck_backup1.wav", + "ambient/misc/truck_drive1.wav", + "ambient/misc/truck_drive2.wav", + "ambient/machines/pneumatic_drill_1.wav", + "ambient/machines/pneumatic_drill_2.wav", + "ambient/machines/pneumatic_drill_3.wav", + "ambient/machines/pneumatic_drill_4.wav", + "ambient/machines/station_train_squeel.wav", + "ambient/machines/ticktock.wav", + "ambient/creatures/teddy.wav", + "ambient/creatures/town_child_scream1.wav", + "ambient/creatures/town_moan1.wav", + "ambient/creatures/town_muffled_cry1.wav", + "ambient/creatures/town_scared_breathing1.wav", + "ambient/creatures/town_scared_breathing2.wav", + "ambient/creatures/town_scared_sob1.wav", + "ambient/creatures/town_scared_sob2.wav", + "ambient/creatures/town_zombie_call1.wav" +} \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/cl_init.lua b/Source/gamemodes/prophuntextended/gamemode/cl_init.lua index 391c388..0a20741 100644 --- a/Source/gamemodes/prophuntextended/gamemode/cl_init.lua +++ b/Source/gamemodes/prophuntextended/gamemode/cl_init.lua @@ -51,7 +51,7 @@ end function GM:Think() end function GM:InitialPlayerSpawn() - print("Prop Hunt CL: InitialPlayerSpawn") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: InitialPlayerSpawn") end -- Delay execution until LocalPlayer() is valid. if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then @@ -59,13 +59,13 @@ function GM:InitialPlayerSpawn() return end - print("Prop Hunt CL: InitialPlayerSpawn Valid") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: InitialPlayerSpawn Valid") end player_manager.RunClass(LocalPlayer(), "InitialClientSpawn") end function GM:PlayerSpawn() - print("Prop Hunt CL: PlayerSpawn") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: PlayerSpawn") end -- Delay execution until LocalPlayer() is valid. if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then @@ -73,7 +73,7 @@ function GM:PlayerSpawn() return end - print("Prop Hunt CL: PlayerSpawn Valid") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: PlayerSpawn Valid") end if !(LocalPlayer().Data) then LocalPlayer().Data = {} @@ -106,8 +106,9 @@ function GM:PlayerSetViewOffset(vo, voduck) if !(GAMEMODE.TempData) then GAMEMODE.TempData = {} end GAMEMODE.TempData.ViewOffset = vo GAMEMODE.TempData.ViewOffsetDuck = voduck - - timer.Simple(.1, function() GAMEMODE:PlayerSetViewOffset(GAMEMODE.TempData.ViewOffset, GAMEMODE.TempData.ViewOffsetDuck) end) + timer.Simple(.1, function() + GAMEMODE:PlayerSetViewOffset(GAMEMODE.TempData.ViewOffset, GAMEMODE.TempData.ViewOffsetDuck) + end) return end @@ -126,8 +127,8 @@ function GM:PlayerSetHull(hullMin, hullMax) if !(GAMEMODE.TempData) then GAMEMODE.TempData = {} end GAMEMODE.TempData.HullMin = hullMin GAMEMODE.TempData.HullMax = hullMax - - timer.Simple(.1, function() GAMEMODE:PlayerSetHull(GAMEMODE.TempData.HullMin, GAMEMODE.TempData.HullMax) end) + timer.Simple(.1, function() + GAMEMODE:PlayerSetHull(GAMEMODE.TempData.HullMin, GAMEMODE.TempData.HullMax) end) return end @@ -146,20 +147,24 @@ function GM:OnContextMenuOpen() end function GM:OnContextMenuClose() - print("Prop Hunt CL: Toggled View Mode") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Toggled View Mode") end LocalPlayer().Data.ThirdPerson = !LocalPlayer().Data.ThirdPerson end function GM:OnSpawnMenuOpen() - print("Prop Hunt CL: Enabling Prop Rotation") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Enabling Prop Rotation") end LocalPlayer():SetNWBool("PropRotation", true) - net.Start("PlayerEnablePropRotation");net.SendToServer() + net.Start("PlayerEnablePropRotation") + net.WriteAngle(LocalPlayer():EyeAngles()) + net.SendToServer() end function GM:OnSpawnMenuClose() - print("Prop Hunt CL: Disabling Prop Rotation") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Disabling Prop Rotation") end LocalPlayer():SetNWBool("PropRotation", false) - net.Start("PlayerDisablePropRotation");net.SendToServer() + net.Start("PlayerDisablePropRotation") + net.WriteAngle(LocalPlayer():EyeAngles()) + net.SendToServer() end function GM:ShowHelpUI() diff --git a/Source/gamemodes/prophuntextended/gamemode/client/cl_ui_help.lua b/Source/gamemodes/prophuntextended/gamemode/client/cl_ui_help.lua index d6b2ab4..fa3ee74 100644 --- a/Source/gamemodes/prophuntextended/gamemode/client/cl_ui_help.lua +++ b/Source/gamemodes/prophuntextended/gamemode/client/cl_ui_help.lua @@ -23,7 +23,7 @@ --]] local PANEL = vgui.Create("DFrame") -PANEL:SetSize(400, 300) +PANEL:SetSize(640, 480) PANEL:SetTitle("Help") PANEL:SetDraggable(true) PANEL:SetVisible(false) @@ -32,30 +32,51 @@ PANEL:SetSizable(true) PANEL:ShowCloseButton(true) PANEL:SetDeleteOnClose(false) -function PANEL:Init() - DFrame.Init(self) - - -- Sheets - self.Sheets = vgui.Create("DPropertySheet", self) - self.Sheets:Dock(FILL) - - -- Basic Info - self.BasicInfoSheet = vgui.Create("DPanel", self.Sheets) - function self.BasicInfoSheet:Paint(w, h) - draw.RoundedBox(4, 0, 0, 100, 100, Color(0,128,255)) - end - self.Sheets:AddSheet("The Gamemode", self.BasicInfoSheet) - - -end - function PANEL:Show() - self:SetSize(ScrW(), ScrH()) + --self:SetSize(ScrW(), ScrH()) self:Center() self:SetVisible(true) self:SetFocusTopLevel(true) self:SlideDown(.5) self:MakePopup() end +function PANEL:Hide() + self:Close() + self:SetVisible(false) +end -GAMEMODE.UI.Help = PANEL \ No newline at end of file +function PANEL:Paint(w, h) + draw.RoundedBox(0, 0, 0, w, h, Color(0,0,0,240)) +end + +-- Sheets +local Element = vgui.Create("DPropertySheet", PANEL) +function Element:PAINT(w,h) + draw.RoundedBox(0, 0, 0, w, h, Color(0,0,0,240)) +end +Element:Dock(FILL) +PANEL.Sheets = Element +PANEL.Sheet = {} + +-- Basic Info +local Element = vgui.Create("DPanel", PANEL.Sheets) +function Element:Paint(w,h) end +PANEL.Sheets:AddSheet("The Gamemode", Element) +PANEL.Sheet.TheGamemode = Element + +local Element = vgui.Create("DLabel", PANEL.Sheet.TheGamemode) +Element:Dock(TOP) +Element:SetMultiline(true) +Element:SetText([[ + Prop Hunt Extended is a Gamemode based on the original Prop Hunt Gamemode. It changes many gameplay elements and features, adding the ability to easily integrate Taunt Packs, Configure Game parameters, rotate your prop and much more. +]]) + + + +-- Settings +PANEL.SettingsSheet = vgui.Create("DPanel", PANEL.Sheets) +PANEL.Sheets:AddSheet("Settings", PANEL.SettingsSheet) + + + +GM.UI.Help = PANEL \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/client/cl_ui_teamselection.lua b/Source/gamemodes/prophuntextended/gamemode/client/cl_ui_teamselection.lua index e3956a6..8bad797 100644 --- a/Source/gamemodes/prophuntextended/gamemode/client/cl_ui_teamselection.lua +++ b/Source/gamemodes/prophuntextended/gamemode/client/cl_ui_teamselection.lua @@ -22,6 +22,19 @@ SOFTWARE. --]] +local PANEL = vgui.Create("DFrame") +PANEL:SetSize(400, 300) +PANEL:SetTitle("Select a Team") +PANEL:SetDraggable(true) +PANEL:SetVisible(false) +PANEL:SetDraggable(true) +PANEL:SetSizable(true) +PANEL:ShowCloseButton(true) +PANEL:SetDeleteOnClose(false) + + + + TeamSelectionUI = {} TeamSelectionUI.Frame = vgui.Create("DFrame") TeamSelectionUI.Frame:SetPos(0, 0) diff --git a/Source/gamemodes/prophuntextended/gamemode/client/derma/dmultilinelabel.lua b/Source/gamemodes/prophuntextended/gamemode/client/derma/dmultilinelabel.lua new file mode 100644 index 0000000..ab12831 --- /dev/null +++ b/Source/gamemodes/prophuntextended/gamemode/client/derma/dmultilinelabel.lua @@ -0,0 +1,30 @@ +--[[ + The MIT License (MIT) + + Copyright (c) 2015 Xaymar + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +--]] + +local ELEMENT = {} +function ELEMENT:Paint() + +end + +vgui.Register("DMultilineLabel", ELEMENT, "Panel") \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/compat/compat_tauntpackloader.lua b/Source/gamemodes/prophuntextended/gamemode/compat/compat_tauntpackloader.lua index 4af0561..79ab521 100644 --- a/Source/gamemodes/prophuntextended/gamemode/compat/compat_tauntpackloader.lua +++ b/Source/gamemodes/prophuntextended/gamemode/compat/compat_tauntpackloader.lua @@ -33,17 +33,36 @@ function CompatTauntPackLoader() -- 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)) + -- Insert the taunts into the new structure (cvar). + Taunts = {} + for i,t in ipairs(GAMEMODE.Prop_Taunts) do + ty = type(t) + if (ty == "string") then + Taunts[#Taunts+1] = t + elseif (ty == "table") then + Taunts[#Taunts+1] = t[2] +-- for j,snd in ipairs(t) do +-- HiderTaunts[#HiderTaunts+1] = snd +-- end + end end - for k,v in ipairs(GAMEMODE.Prop_Taunts) do - --pcall(GAMEMODE.Config.Taunts.Add("TauntPackLoader."..string.GetFileFromFilename(v), v, TEAM_HIDERS, nil)) + GAMEMODE.Config.Taunt.HidersCacheStatic = Taunts + Taunts = {} + for i,t in ipairs(GAMEMODE.Hunter_Taunts) do + ty = type(t) + if (ty == "string") then + Taunts[#Taunts+1] = t + elseif (ty == "table") then + Taunts[#Taunts+1] = t[2] +-- for j,snd in ipairs(t) do +-- SeekerTaunts[#SeekerTaunts+1] = snd +-- end + end end + GAMEMODE.Config.Taunt.SeekersCacheStatic = Taunts -- Clean up after ourselves GAMEMODE.Prop_Taunts = nil GAMEMODE.Hunter_Taunts = nil end -hook.Add("OnPropHuntInitialized", "CompatTauntPackLoader", CompatTauntPackLoader) \ No newline at end of file +hook.Add("Initialize", "CompatTauntPackLoader", CompatTauntPackLoader) \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/init.lua b/Source/gamemodes/prophuntextended/gamemode/init.lua index 9ca09c9..b98c950 100644 --- a/Source/gamemodes/prophuntextended/gamemode/init.lua +++ b/Source/gamemodes/prophuntextended/gamemode/init.lua @@ -28,7 +28,6 @@ -- Shared AddCSLuaFile("sh_init.lua") AddCSLuaFile("sh_config.lua") -AddCSLuaFile("sh_player.lua") AddCSLuaFile("player_class/class_default.lua") AddCSLuaFile("player_class/class_spectator.lua") AddCSLuaFile("player_class/class_seeker.lua") @@ -46,7 +45,6 @@ AddCSLuaFile("client/cl_ui_teamselection.lua") include "sh_init.lua" -- Server Only -include "server/config.lua" include "compat/compat_tauntpackloader.lua" include "server/roundmanager.lua" include "server/states/state_prematch.lua" @@ -63,7 +61,6 @@ function GM:Initialize() print("Prop Hunt: Registering Networked Messages...") util.AddNetworkString("PlayerManagerInitialClientSpawn") util.AddNetworkString("PlayerManagerClientSpawn") - util.AddNetworkString("PlayerSetHull") util.AddNetworkString("PlayerResetHull") util.AddNetworkString("PlayerViewOffset") @@ -73,10 +70,15 @@ function GM:Initialize() print("Prop Hunt: Initializing Gamemode Data...") self.Data = {} + self.Data.StartTime = CurTime() print("Prop Hunt: Setting initial RoundManager State...") self.RoundManager:SetState(StatePreMatch) + print("Prop Hunt: Precaching...") + GAMEMODE.Config.Taunt:Seekers() + GAMEMODE.Config.Taunt:Hiders() + print("Prop Hunt: Complete.") print("-------------------------------------------------------------------------") end @@ -87,28 +89,29 @@ end -- Player Connected function GM:PlayerConnect(name, ip) - print("Prop Hunt: Player '"..name.."' connecting from IP '"..ip.."'.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..name.."' connecting from IP '"..ip.."'.") end end -- Player Authenticated function GM:PlayerAuthed(ply, steamid, uniqueid) - print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") authenticated.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") authenticated.") end end -- Player Disconnected function GM:PlayerDisconnected(ply) - print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") disconnected.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") disconnected.") end end -- Player Spawn (Initial) function GM:PlayerInitialSpawn(ply) - print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned for the first time, applying defaults...") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned for the first time, applying defaults...") end if (!ply.Data) then -- Initialize Data Structure ply.Data = {} ply.Data.Alive = false ply.Data.AliveTime = 0 + ply.Data.RandomWeight = 0 -- Higher means higher chance of becoming Seeker instead of Hider. end -- Kill Silently @@ -121,10 +124,10 @@ function GM:PlayerInitialSpawn(ply) -- Bot: Auto Assign to Team if (ply:IsBot()) then if team.NumPlayers(self.Teams.Hiders) > team.NumPlayers(self.Teams.Seekers) then - print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Seekers.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Seekers.") end ply:SetTeam(self.Teams.Seekers) else - print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Hiders.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Hiders.") end ply:SetTeam(self.Teams.Hiders) end end @@ -138,7 +141,7 @@ end -- Player Spawn function GM:PlayerSpawn(ply) - print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned in.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned in.") end -- Player Manager: Assign Player Class local class = team.GetClass(ply:Team()) @@ -167,7 +170,7 @@ end -- Player requests Team Change function GM:PlayerRequestTeam(ply, teamId) if self:PlayerCanJoinTeam(ply, teamId) then - print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") requested to join Team "..team.GetName(teamId)..".") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") requested to join Team "..team.GetName(teamId)..".") end if (ply:Team() != teamId) then ply:KillSilent() @@ -178,7 +181,7 @@ function GM:PlayerRequestTeam(ply, teamId) ply.AliveTime = CurTime() end else - print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") attempted to rejoin the Team it is already in.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") attempted to rejoin the Team it is already in.") end end end end @@ -187,7 +190,38 @@ end --! Player Manager Binding -- ------------------------------------------------------------------------- -- function GM:PlayerLoadout(ply) player_manager.RunClass(ply, "Loadout") end -function GM:PlayerDeath(ply, inflictor, attacker) player_manager.RunClass(ply, "Death", inflictor, attacker) end +function GM:PlayerDeath(ply, inflictor, attacker) + player_manager.RunClass(ply, "Death", inflictor, attacker) + + -- Signal Client Stuff + if IsValid(attacker) then + if attacker:IsPlayer() then + if (attacker == ply) then + net.Start("PlayerKilledSelf") + net.WriteEntity(ply) + net.Broadcast() + else + net.Start("PlayerKilledByPlayer") + net.WriteEntity(ply) + net.WriteString(inflictor:GetName()) + net.WriteEntity(attacker) + net.Broadcast() + end + else + net.Start("PlayerKilled") + net.WriteEntity(ply) + net.WriteString(inflictor:GetName()) + net.WriteString(attacker:GetClass()) + net.Broadcast() + end + else + net.Start("PlayerKilled") + net.WriteEntity(ply) + net.WriteString(inflictor:GetName()) + net.WriteString("World") + net.Broadcast() + end +end function GM:PlayerSilentDeath(ply) player_manager.RunClass(ply, "SilentDeath") end function GM:PostPlayerDeath(ply) player_manager.RunClass(ply, "PostDeath") @@ -195,10 +229,10 @@ function GM:PostPlayerDeath(ply) -- Debug Mode: Respawn after Death if (GAMEMODE.Config:Debug()) then ply.Data.Alive = true - print("Prop Hunt: Debug Mode active, Player "..ply:GetName().." was respawned.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Debug Mode active, Player "..ply:GetName().." was respawned.") end end end ---function GM:DoPlayerDeath(ply, attacker, dmg) player_manager.RunClass(ply, "DoDeath", attacker, dmg) end +function GM:DoPlayerDeath(ply, attacker, dmg) player_manager.RunClass(ply, "DoDeath", attacker, dmg) end function GM:PlayerDeathThink(ply) return player_manager.RunClass(ply, "DeathThink") end function GM:CanPlayerSuicide(ply) return player_manager.RunClass(ply, "CanSuicide") end function GM:PlayerCanPickupWeapon(ply, weapon) return player_manager.RunClass(ply, "CanPickupWeapon", weapon) end @@ -219,6 +253,10 @@ end -- ------------------------------------------------------------------------- -- --! Gamemode Functionality -- ------------------------------------------------------------------------- -- +function GM:SetRound(Round) + SetGlobalInt("Round", Round) +end + function GM:SetRoundState(State) SetGlobalInt("RoundState", State) end @@ -241,6 +279,7 @@ function GM:PlayerHullFromEntity(ply, ent) hull.x = hull.y end hull:Mul(0.5) + hull:Mul(0.95) -- Reduce size slightly local hullmin = Vector(-hull.x, -hull.y, 0) local hullmax = Vector(hull.x, hull.y, hull.z * 2) @@ -289,153 +328,65 @@ function GM:ShowTeam(ply) ply:ConCommand("ph_select_team") end --- F3/ShowSpare1 -function GM:ShowSpare1(ply) end - --- F4/ShowSpare2 -function GM:ShowSpare2(ply) end +function GM:ShowSpare1(ply) player_manager.RunClass(ply, "ShowSpare1") end -- F3/ShowSpare1 +function GM:ShowSpare2(ply) player_manager.RunClass(ply, "ShowSpare2") end -- F4/ShowSpare2 -- Debug Command: Print All Players concommand.Add("ph_debug_printplayers", function(ply, cmd, args, argStr) - print ("All Players:") - for i,ply in ipairs(player.GetAll()) do - print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..") - Team "..team.GetName(ply:Team()).. " - Alive "..tostring(ply.Data.Alive)) + if GAMEMODE.Config:DebugLog() then + print ("All Players:") + for i,ply in ipairs(player.GetAll()) do + print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..") - Team "..team.GetName(ply:Team()).. " - Alive "..tostring(ply.Data.Alive)) + end + + print ("Spectators:") + for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Spectators)) do + print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")") + end + + print ("Seekers:") + for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do + print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")") + end + + print ("Hiders:") + for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Hiders)) do + print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")") + end end - - print ("Spectators:") - for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Spectators)) do - print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")") - end - - print ("Seekers:") - for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do - print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")") - end - - print ("Hiders:") - for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Hiders)) do - print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")") - end - end, nil, nil, FCVAR_CLIENTCMD_CAN_EXECUTE + FCVAR_CHEAT) +-- Debug Command: Print All Players +concommand.Add("ph_debug_stats", function(ply, cmd, args, argStr) + if GAMEMODE.Config:DebugLog() then + for i,ply in ipairs(player.GetAll()) do + print(ply:GetName().." (SteamID: "..ply:SteamID()..")") + print(" Team: "..team.GetName(ply:Team())) + print(" Alive: "..tostring(ply.Data.Alive)) + print(" AliveTime: "..tostring(ply.Data.AliveTime)) + print(" Score: "..tostring(ply.Data.RandomWeight)) + end + end +end, nil, nil, FCVAR_CLIENTCMD_CAN_EXECUTE + FCVAR_CHEAT) + + + -- ------------------------------------------------------------------------- -- --! Network Messages -- ------------------------------------------------------------------------- -- net.Receive("PlayerEnablePropRotation", function(len, ply) + if (ply:Team() != GAMEMODE.Teams.Hiders) then + return + end print("Prop Hunt: Enabling Prop Rotation") ply:SetNWBool("PropRotation", true) + ply.Data.Prop:ApplyRotation(net.ReadAngle()) end) net.Receive("PlayerDisablePropRotation", function(len, ply) + if (ply:Team() != GAMEMODE.Teams.Hiders) then + return + end print("Prop Hunt: Disabling Prop Rotation") ply:SetNWBool("PropRotation", false) -end) - - --- ------------------------------------------------------------------------- -- ---! LEGACY CODE - TO BE REPLACED SOON --- ------------------------------------------------------------------------- -- ---[[ -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 - --- 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 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 - --- 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) - -]] \ No newline at end of file + ply.Data.Prop:ApplyRotation(net.ReadAngle()) +end) \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/player_class/class_default.lua b/Source/gamemodes/prophuntextended/gamemode/player_class/class_default.lua index 47bfabf..03fb6fd 100644 --- a/Source/gamemodes/prophuntextended/gamemode/player_class/class_default.lua +++ b/Source/gamemodes/prophuntextended/gamemode/player_class/class_default.lua @@ -49,6 +49,7 @@ function CLASS:Spawn() end function CLASS:Loadout() end -- Damage +function CLASS:ShouldTakeDamage(attacker) return true end -- Should take damage from attacker? function CLASS:Hurt(victim, attacker, healthRemaining, damageTaken) end -- Damage Taken function CLASS:Damage(victim, attacker, healthRemaining, damageDealt) end -- Damage Dealt function CLASS:DamageEntity(ent, attacker, dmginfo) end -- Damage Dealt To Entity @@ -63,9 +64,7 @@ function CLASS:SilentDeath() self.Player.Data.AliveTime = CurTime() end function CLASS:PostDeath() end - function CLASS:DoDeath() end - function CLASS:DeathThink() if (CurTime() - self.Player.Data.AliveTime) > 5 then self.Player:Spawn() @@ -73,7 +72,6 @@ function CLASS:DeathThink() end return false end - function CLASS:CanSuicide() return true end -- Visible Stuff @@ -109,6 +107,16 @@ function CLASS:AllowPickup(ent) return false end function CLASS:CanPickupWeapon(ent) return false end function CLASS:CanPickupItem(ent) return false end +-- Menu (Always Server) +function CLASS:ShowSpare1() + local lastTaunt = (self.Player.Data.LastTaunt or 0) + if ((CurTime() - lastTaunt) <= GAMEMODE.Config.Taunt:Cooldown()) then + return true + end + self.Player.Data.LastTaunt = CurTime() +end +function CLASS:ShowSpare2() end + -- ------------------------------------------------------------------------- -- --! Shared -- ------------------------------------------------------------------------- -- @@ -130,72 +138,52 @@ function CLASS:GetHandsModel() return BaseClass.GetHandsModel(self) end function CLASS:ShouldDrawLocal() return false end function CLASS:HUDPaint() local State = GetGlobalInt("RoundState", GAMEMODE.States.PreMatch) + if State == -1 then + return + end - -- Show Status at the top center - local statusX, statusY, statusW, statusH - statusW = 192 - statusH = 64 - statusX = ScrW() / 2 - statusW / 2 - statusY = 16 + -- Status Box at the top. + local statusW, statusH = 256,48 + local statusX, statusY = ScrW() / 2 - statusW / 2, 0 + draw.RoundedBox(0, statusX, statusY, statusW, statusH, Color(0,0,0,204)) -- Background + draw.RoundedBox(0, statusX, statusY+statusH, statusW, 4, team.GetColor(LocalPlayer():Team())) -- Team Bar - -- Status - if (State == GAMEMODE.States.PreMatch) then -- Pre Match - draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204)) - surface.SetFont( "Trebuchet24" ) - surface.SetTextColor( 255, 255, 255, 255 ) - local w,h = surface.GetTextSize("Waiting for Players") - surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/2 - h / 2) - surface.DrawText("Waiting for Players") - elseif (State == GAMEMODE.States.PreRound) then -- Pre Round - draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204)) - surface.SetFont( "Trebuchet24" ) - surface.SetTextColor( 255, 255, 255, 255 ) - local w,h = surface.GetTextSize("Preparing...") - surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/2 - h / 2) - surface.DrawText( "Preparing..." ) + -- Title + surface.SetFont("Trebuchet18") + surface.SetTextColor(Color(255,255,255,255)) + local titleText = "" + if (State == GAMEMODE.States.PreMatch) then + titleText = "Waiting for Players" + elseif (State == GAMEMODE.States.PreRound) then + titleText = "Preparing Round..." elseif (State == GAMEMODE.States.Hide) then -- Hide - local strTime = tostring(math.ceil(GetGlobalInt("RoundTime"))) - - -- Show Status at the top center - draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204)) - surface.SetTextColor(255,255,255,255) - surface.SetFont("Trebuchet18") - local w,h = surface.GetTextSize("Seekers unblinded in:") - surface.SetTextPos(statusX + statusW/2 - w / 2, statusY + statusH/4 - h / 2) - surface.DrawText("Seekers unblinded in:") - - surface.SetFont( "Trebuchet24" ) - local w,h = surface.GetTextSize(strTime.." Seconds!") - surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/1.5 - h / 2) - surface.DrawText(strTime.." Seconds!") + titleText = "Seekers unblinded in:" elseif (State == GAMEMODE.States.Seek) then -- Seek + titleText = "Seek Time!" + elseif (State == GAMEMODE.States.PostRound) then -- Post Round + titleText = "Match Result:" + elseif (State == GAMEMODE.States.PostMatch) then -- Post Match + end + local w,h = surface.GetTextSize(titleText) + surface.SetTextPos(statusX + statusW/2 - w/2, statusY) + surface.DrawText(titleText) + + -- Subtitle + local stateText = "" + surface.SetFont("Trebuchet24") + surface.SetTextColor(Color(255,255,255,255)) + if (State == GAMEMODE.States.PreMatch) then + stateText = tostring(team.NumPlayers(GAMEMODE.Teams.Seekers)) .. " Seeker(s), " .. tostring(team.NumPlayers(GAMEMODE.Teams.Hiders)) .. " Hider(s)" + elseif (State == GAMEMODE.States.PreRound) then + stateText = "Initiating..." + elseif (State == GAMEMODE.States.Hide) -- Hide + || (State == GAMEMODE.States.Seek) then -- Seek local intTime = math.ceil(GetGlobalInt("RoundTime")) local strTime = string.format("%d:%02d", math.floor(intTime / 60), math.ceil(intTime % 60)) - - -- Show Status at the top center - draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204)) - surface.SetTextColor(255,255,255,255) - surface.SetFont("Trebuchet18") - local w,h = surface.GetTextSize("Hunting Time!") - surface.SetTextPos(statusX + statusW/2 - w / 2, statusY + statusH/4 - h / 2) - surface.DrawText("Hunting Time!") - - surface.SetFont( "Trebuchet24" ) - local w,h = surface.GetTextSize(strTime) - surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/1.5 - h / 2) - surface.DrawText(strTime) - + stateText = strTime elseif (State == GAMEMODE.States.PostRound) then -- Post Round - -- Show Status at the top center - draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204)) - surface.SetTextColor(255,255,255,255) - surface.SetFont("Trebuchet18") - local w,h = surface.GetTextSize("Match Result") - surface.SetTextPos(statusX + statusW/2 - w / 2, statusY + statusH/4 - h / 2) - surface.DrawText("Match Result") - local victor = GAMEMODE:GetRoundWinner() - local victorName = "Unknown" + local victorName = "Draw" if (victor == GAMEMODE.Teams.Spectator) then victorName = "Draw" elseif (victor == GAMEMODE.Teams.Hiders) then @@ -203,17 +191,69 @@ function CLASS:HUDPaint() elseif (victor == GAMEMODE.Teams.Seekers) then victorName = "Seekers Win" end + stateText = victorName surface.SetTextColor(team.GetColor(victor)) - - surface.SetFont( "Trebuchet24" ) - local w,h = surface.GetTextSize(victorName) - surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/1.5 - h / 2) - surface.DrawText(victorName) elseif (State == GAMEMODE.States.PostMatch) then -- Post Match end + local w,h = surface.GetTextSize(stateText) + surface.SetTextPos(statusX + statusW/2 - w/2, statusY + 32 - h / 2) + surface.DrawText(stateText) + + -- Death Notices + GAMEMODE:DrawDeathNotice((ScrW() - 192) / ScrW() , 24 / ScrH()) +end +function CLASS:CalcView(camdata) + -- Config + local cameraCollision = GAMEMODE.Config.Camera:Collisions() + local cameraDistance = GAMEMODE.Config.Camera:Distance() + local cameraDistanceRight = GAMEMODE.Config.Camera:DistanceRight() + local cameraDistanceUp = GAMEMODE.Config.Camera:DistanceUp() + local cameraLag = GAMEMODE.Config.Camera:Lag() + local cameraLagInv = 1 - cameraLag + + -- First/Third Person Target Distance + local targetDistance = 0 + if (self.Player.Data.ThirdPerson) then -- Incremental Distance instead of instant. + targetDistance = cameraDistance + + if (cameraCollision == true) then + -- Trace from Player to would-be camera position + local trace = { + start = camdata.origin, + endpos = camdata.origin - (camdata.angles:Forward() * cameraDistance), + --filter = { "worldspawn", "ph_prop", "player" }, + --[-[ + filter = function(ent) + local filter = { "worldspawn", "ph_prop", "player" } + + if (ent:IsPlayer()) + || (table.HasValue(filter, ent:GetClass())) + || (ent == LocalPlayer()) || (ent == LocalPlayer():GetHands()) then + return false + end + return true + end, + --]] + } + local result = util.TraceLine(trace) + + -- The Camera has a Sphere radius of 10. + if (result.Hit) then -- Configurable? + targetDistance = math.Clamp(result.HitPos:Distance(camdata.origin), 0, cameraDistance) + end + end + else + targetDistance = 0 + end + + -- Fade between Target and Current Distance + self.Player.Data.ViewDistance = math.Clamp(((self.Player.Data.ViewDistance or targetDistance) * cameraLag) + (targetDistance * cameraLagInv), 0, GAMEMODE.Config.Camera:DistanceMax()) + + -- Adjust CamData and return + camdata.origin = camdata.origin - (camdata.angles:Forward() * math.Clamp(self.Player.Data.ViewDistance - 10, 0, self.Player.Data.ViewDistance)) + (camdata.angles:Right() * cameraDistanceRight) + (camdata.angles:Up() * cameraDistanceUp) + return camdata end -function CLASS:CalcView(camdata) return camdata end -- ------------------------------------------------------------------------- -- --! Register diff --git a/Source/gamemodes/prophuntextended/gamemode/player_class/class_hider.lua b/Source/gamemodes/prophuntextended/gamemode/player_class/class_hider.lua index 10034fd..48f1510 100644 --- a/Source/gamemodes/prophuntextended/gamemode/player_class/class_hider.lua +++ b/Source/gamemodes/prophuntextended/gamemode/player_class/class_hider.lua @@ -35,26 +35,31 @@ CLASS.UseVMHands = false -- Uses viewmodel hands -- ------------------------------------------------------------------------- -- -- Spawn function CLASS:Spawn() - print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end BaseClass.Spawn(self, self.Player) - - -- Sprinting - if (!GAMEMODE.Config:Sprinting()) then - self.Player:SetRunSpeed(self.WalkSpeed) - end - + -- Settings self.Player:SetMaxHealth(GAMEMODE.Config.Hider:HealthMax()) self.Player:SetHealth(GAMEMODE.Config.Hider:Health()) self.Player:SetRenderMode(RENDERMODE_TRANSALPHA) self.Player:SetColor(Color(0,0,0,0)) + -- Speed and Jump Power + self.Player:SetWalkSpeed(GAMEMODE.Config.Hider:WalkSpeed()) + if (GAMEMODE.Config.Hider:Sprint()) then + self.Player:SetRunSpeed(GAMEMODE.Config.Hider:SprintSpeed()) + else + self.Player:SetRunSpeed(GAMEMODE.Config.Hider:WalkSpeed()) + end + self.Player:SetJumpPower(GAMEMODE.Config.Hider:JumpPower()) + -- Hull & View Offset GAMEMODE:PlayerHullFromEntity(self.Player, nil) GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,72), Vector(0,0,72)) -- Collision Group self.Player:SetCollisionGroup(COLLISION_GROUP_PLAYER) + self.Player:SetSolid(SOLID_VPHYSICS) -- Prop Stuff self.Player.Data.Prop = ents.Create("ph_prop") @@ -70,7 +75,7 @@ end -- Death function CLASS:PostDeath(attacker, dmginfo) - print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") end BaseClass.PostDeath(self, inflictor, attacker) -- Delete Hands Model @@ -120,11 +125,11 @@ function CLASS:Use(ent) end -- Check Lists and other Parameters - if (!table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass()))-- Class is not Whitelisted - || (GAMEMODE.Config.Lists.ModelBlacklist[ent:GetModel()]) -- Model is Blacklisted - || !((ent:GetPhysicsObject()) && (ent:GetPhysicsObject():IsValid())) -- Entity doesn't have Physics + if (!table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass())) -- Class is not Whitelisted + || (table.HasValue(GAMEMODE.Config.Lists:ModelBlacklist(), ent:GetModel())) -- Model is Blacklisted + || !((ent:GetPhysicsObject()) && (ent:GetPhysicsObject():IsValid())) -- Entity doesn't have Physics then - print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") attempted to turn into "..ent:GetClass().." ("..ent:GetModel()..").") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") attempted to turn into "..ent:GetClass().." ("..ent:GetModel()..").") end return true -- Use instead of erroring. end @@ -155,11 +160,22 @@ function CLASS:Use(ent) self.Player:SetMaxHealth(maxhealth) end - print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") turned into "..ent:GetClass().." ("..ent:GetModel()..").") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") turned into "..ent:GetClass().." ("..ent:GetModel()..").") end end function CLASS:AllowPickup(ent) return true end +-- Menu Buttons +function CLASS:ShowSpare1() + if BaseClass.ShowSpare1(self) then return end + + -- Play a taunt + local tauntList = GAMEMODE.Config.Taunt:Hiders() + local index = math.random(#tauntList) + self.Player:EmitSound(tauntList[index], SNDLVL_NORM, 100, 1, CHAN_VOICE) + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") taunted with sound '"..tauntList[index].."'.") end +end + -- ------------------------------------------------------------------------- -- --! Shared -- ------------------------------------------------------------------------- -- @@ -168,71 +184,26 @@ function CLASS:AllowPickup(ent) return true end --! Client-Side -- ------------------------------------------------------------------------- -- function CLASS:ClientSpawn() - print("Prop Hunt CL: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end BaseClass.ClientSpawn(self, self.Player) self.Player:SetRenderMode(RENDERMODE_TRANSALPHA) end function CLASS:ShouldDrawLocal() - return false -end - -function CLASS:CalcView(camdata) - -- ThirdPerson Settings (ToDo: client config maybe?) - local maxViewDist = 100 - local viewDist = self.Player.Data.ViewDistance or 0 - - -- First/Third - if (self.Player.Data.ThirdPerson) then + if (self.Player.Data.ViewDistance or 0) >= 10 then if (IsValid(self.Player:GetHands())) then self.Player:GetHands():SetRenderMode(RENDERMODE_TRANSALPHA) self.Player:GetHands():SetColor(Color(255, 255, 255, 127)) end - - -- Incremental Distance instead of instant. - viewDist = math.Clamp(viewDist * 0.95 + maxViewDist * 0.05, 0, maxViewDist) -- Zoom Out else if (IsValid(self.Player:GetHands())) then self.Player:GetHands():SetRenderMode(RENDERMODE_TRANSALPHA) self.Player:GetHands():SetColor(Color(255, 255, 255, 0)) end - - viewDist = math.Clamp(viewDist * 0.95, 0, maxViewDist) -- Zoom In end - -- Trace from Player to would-be camera position - local trace = { - start = camdata.origin, - endpos = camdata.origin - (camdata.angles:Forward() * viewDist), - --filter = { "worldspawn", "ph_prop" }, - filter = function(ent) - local filter = { "worldspawn", "ph_prop" } - - if (ent:IsPlayer()) - || (table.HasValue(filter, ent:GetClass())) - || (ent == LocalPlayer()) || (ent == LocalPlayer():GetHands()) then - return false - end - return true - end - } - local result = util.TraceLine(trace) - - -- The Camera has a Sphere radius of 10. - if (result.Hit) then -- Configurable? - viewDist = math.Clamp(result.HitPos:Distance(camdata.origin), 0, maxViewDist) - end - - -- Store ViewDistance - self.Player.Data.ViewDistance = viewDist - - -- Adjust CamData - camdata.origin = camdata.origin - (camdata.angles:Forward() * math.Clamp(viewDist - 10, 0, maxViewDist)) - camdata.drawviewer = false - - -- Return - return camdata + return (self.Player.Data.ViewDistance or 0) >= 10 end -- Register diff --git a/Source/gamemodes/prophuntextended/gamemode/player_class/class_seeker.lua b/Source/gamemodes/prophuntextended/gamemode/player_class/class_seeker.lua index a059fa7..b7827f4 100644 --- a/Source/gamemodes/prophuntextended/gamemode/player_class/class_seeker.lua +++ b/Source/gamemodes/prophuntextended/gamemode/player_class/class_seeker.lua @@ -44,20 +44,24 @@ CLASS.DropWeaponOnDie = true -- ------------------------------------------------------------------------- -- -- Spawn function CLASS:Spawn() - print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") + if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end BaseClass.Spawn(self) - - -- Sprinting - if (GAMEMODE.Config:Sprinting()) then - self.Player:SetRunSpeed(self.WalkSpeed) - end - + -- Settings self.Player:SetMaxHealth(GAMEMODE.Config.Seeker:HealthMax()) self.Player:SetHealth(GAMEMODE.Config.Seeker:Health()) self.Player:SetRenderMode(RENDERMODE_NORMAL) self.Player:SetColor(Color(255,255,255,255)) + -- Speed and Jump Power + self.Player:SetWalkSpeed(GAMEMODE.Config.Seeker:WalkSpeed()) + if (GAMEMODE.Config.Seeker:Sprint()) then + self.Player:SetRunSpeed(GAMEMODE.Config.Seeker:SprintSpeed()) + else + self.Player:SetRunSpeed(GAMEMODE.Config.Seeker:WalkSpeed()) + end + self.Player:SetJumpPower(GAMEMODE.Config.Seeker:JumpPower()) + -- Hull & View Offset GAMEMODE:PlayerHullFromEntity(self.Player, nil) GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,64), Vector(0,0,32)) @@ -85,15 +89,33 @@ function CLASS:Loadout() end -- Damage -function CLASS:Damage(victim, attacker, healthRemaining, damageDealt) end +function CLASS:ShouldTakeDamage(attacker) + if (IsValid(attacker)) then + if (attacker:IsPlayer()) then + if (attacker:Team() == self.Player:Team()) then + local ffmode = GetConVarNumber("mp_friendlyfire") + if (ffmode == 0) then -- Not Allowed + return false + elseif (ffmode == 2) then -- Damage self instead + if (IsValid(attacker) && attacker:IsPlayer()) then + attacker:SetHealth(attacker:Health() - damageTaken) + end + return false + end + end + end + end + return true +end function CLASS:DamageEntity(ent, att, dmg) - print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") damaged entity "..ent:GetClass()..".") + if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") damaged entity "..ent:GetClass()..".") end -- Only take damage during this phase. if (GAMEMODE:GetRoundState() == GAMEMODE.States.Seek) then if IsValid(ent) && (!(ent:IsPlayer())) then if (ent:GetClass() == "ph_prop") then ent:GetOwner():TakeDamageInfo(dmg) + self.Player.Data.RandomWeight = self.Player.Data.RandomWeight - 1 elseif (ent:GetClass() == "func_breakable") then -- ToDo: Make Configurable which entities don't hurt? else att:TakeDamage(GAMEMODE.Config.Seeker:HealthPenalty(), ent, ent) @@ -106,11 +128,14 @@ end function CLASS:Death(inflictor, attacker) BaseClass.Death(self, inflictor, attacker) - self.Player:CreateRagdoll() + if SERVER then + self.Player:SetShouldServerRagdoll(true) + --self.Player:CreateRagdoll() + end end function CLASS:PostDeath() - print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") + if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") end BaseClass.PostDeath(self, inflictor, attacker) self.Player:UnLock() @@ -148,11 +173,22 @@ function CLASS:AllowPickup(ent) return true end function CLASS:CanPickupItem(ent) return true end function CLASS:CanPickupWeapon(ent) return true end +-- Menu Buttons +function CLASS:ShowSpare1() + if BaseClass.ShowSpare1(self) then return end + + -- Play a taunt + local tauntList = GAMEMODE.Config.Taunt:Seekers() + local index = math.random(#tauntList) + self.Player:EmitSound(tauntList[index], SNDLVL_NORM, 100, 1, CHAN_VOICE) + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") taunted with sound '"..tauntList[index].."'.") end +end + -- ------------------------------------------------------------------------- -- --! Client-Side -- ------------------------------------------------------------------------- -- function CLASS:ClientSpawn() - print("Prop Hunt CL: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") + if (GAMEMODE.Config:DebugLog()) then print("Prop Hunt CL: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end BaseClass.ClientSpawn(self) end @@ -181,53 +217,7 @@ function CLASS:HUDPaint() end function CLASS:ShouldDrawLocal() - return self.Player.Data.ThirdPerson -end - -function CLASS:CalcView(camdata) - -- ThirdPerson Settings (ToDo: client config maybe?) - local maxViewDist = 100 - local viewDist = self.Player.Data.ViewDistance or 0 - - -- First/Third - if (self.Player.Data.ThirdPerson) then - viewDist = math.Clamp(viewDist * 0.95 + maxViewDist * 0.05, 0, maxViewDist) -- Zoom Out - else - viewDist = math.Clamp(viewDist * 0.95, 0, maxViewDist) -- Zoom In - end - - -- Trace from Player to would-be camera position - local trace = { - start = camdata.origin, - endpos = camdata.origin - (camdata.angles:Forward() * viewDist), - --filter = { "worldspawn", "ph_prop" }, - filter = function(ent) - local filter = { "worldspawn", "ph_prop" } - - if (ent:IsPlayer()) - || (table.HasValue(filter, ent:GetClass())) - || (ent == LocalPlayer()) || (ent == LocalPlayer():GetHands()) then - return false - end - return true - end - } - local result = util.TraceLine(trace) - - -- The Camera has a Sphere radius of 10. - if (result.Hit) then -- Configurable? - viewDist = math.Clamp(result.HitPos:Distance(camdata.origin), 0, maxViewDist) - end - - -- Store ViewDistance - self.Player.Data.ViewDistance = viewDist - - -- Adjust CamData - camdata.origin = camdata.origin - (camdata.angles:Forward() * math.Clamp(viewDist - 10, 0, maxViewDist)) - --camdata.drawviewer = false - - -- Return - return camdata + return (self.Player.Data.ViewDistance or 0) >= 10 end -- Register diff --git a/Source/gamemodes/prophuntextended/gamemode/player_class/class_spectator.lua b/Source/gamemodes/prophuntextended/gamemode/player_class/class_spectator.lua index d7dd2a2..fe345a4 100644 --- a/Source/gamemodes/prophuntextended/gamemode/player_class/class_spectator.lua +++ b/Source/gamemodes/prophuntextended/gamemode/player_class/class_spectator.lua @@ -35,7 +35,7 @@ CLASS.UseVMHands = false -- Uses viewmodel hands -- ------------------------------------------------------------------------- -- -- Spawn function CLASS:Spawn() - print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end BaseClass.Spawn(self) self.Player:Spectate(OBS_MODE_ROAMING) @@ -48,7 +48,7 @@ end -- Death function CLASS:PostDeath(inflictor, attacker) - print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.") end BaseClass.PostDeath(self, inflictor, attacker) self.Player:Spectate(OBS_MODE_NONE) @@ -77,9 +77,10 @@ function CLASS:CanPickupItem(ent) return false end --! Client-Side -- ------------------------------------------------------------------------- -- function CLASS:ClientSpawn() - print("Prop Hunt CL: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") + if GAMEMODE.Config:DebugLog() then print("Prop Hunt CL: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.") end end function CLASS:ShouldDrawLocal() return false end +function CLASS:CalcView(camdata) return camdata end player_manager.RegisterClass( "Spectator", CLASS, "Default") \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/server/states/state_hide.lua b/Source/gamemodes/prophuntextended/gamemode/server/states/state_hide.lua index c1fc858..8c67f92 100644 --- a/Source/gamemodes/prophuntextended/gamemode/server/states/state_hide.lua +++ b/Source/gamemodes/prophuntextended/gamemode/server/states/state_hide.lua @@ -25,7 +25,7 @@ StateHide = {} function StateHide:OnEnter(OldState) - if GAMEMODE.Config:Debug() then print("StateHide: OnEnter") end + if GAMEMODE.Config:DebugLog() then print("StateHide: OnEnter") end GAMEMODE:SetRoundState(GAMEMODE.States.Hide) -- Round Data @@ -59,4 +59,7 @@ end function StateHide:OnLeave(NewState) if GAMEMODE.Config:Debug() then print("StateHide: OnLeave") end + + -- Fretta Hooks + hook.Run("PropHuntUnblind") end \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/server/states/state_postmatch.lua b/Source/gamemodes/prophuntextended/gamemode/server/states/state_postmatch.lua index e6cefe3..4f9312f 100644 --- a/Source/gamemodes/prophuntextended/gamemode/server/states/state_postmatch.lua +++ b/Source/gamemodes/prophuntextended/gamemode/server/states/state_postmatch.lua @@ -25,15 +25,30 @@ StatePostMatch = {} function StatePostMatch:OnEnter(OldState) - if GAMEMODE.Config:Debug() then print("StatePostMatch: OnEnter") end + if GAMEMODE.Config:DebugLog() then print("StatePostMatch: OnEnter") end GAMEMODE:SetRoundState(GAMEMODE.States.PostMatch) + + self.NextState = StatePreMatch + + -- Check Change map conditions. + if ((GAMEMODE.Config:TimeLimit() > 0) && ((CurTime() - GAMEMODE.Data.StartTime) >= (GAMEMODE.Config:TimeLimit() * 60))) -- Over Time + || (GAMEMODE:GetRound() >= GAMEMODE.Config.Round:Limit()) -- Over Round Limit + then + + -- Advance to nothing + GAMEMODE:SetRoundState(-1) + self.NextState = nil + + -- MapVote + if (MapVote != nil) then MapVote.Start(30, true, 30, "ph_") return end + end end function StatePostMatch:Tick() -- Advance State - GAMEMODE.RoundManager:SetState(StatePreMatch) + GAMEMODE.RoundManager:SetState(self.NextState) end function StatePostMatch:OnLeave(NewState) - if GAMEMODE.Config:Debug() then print("StatePostMatch: OnLeave") end + if GAMEMODE.Config:DebugLog() then print("StatePostMatch: OnLeave") end end \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/server/states/state_postround.lua b/Source/gamemodes/prophuntextended/gamemode/server/states/state_postround.lua index fc1d304..5539916 100644 --- a/Source/gamemodes/prophuntextended/gamemode/server/states/state_postround.lua +++ b/Source/gamemodes/prophuntextended/gamemode/server/states/state_postround.lua @@ -25,35 +25,118 @@ StatePostRound = {} function StatePostRound:OnEnter(OldState) - if GAMEMODE.Config:Debug() then print("StatePostRound: OnEnter") end + if GAMEMODE.Config:DebugLog() then print("StatePostRound: OnEnter") end GAMEMODE:SetRoundState(GAMEMODE.States.PostRound) GAMEMODE.Data.RoundStartTime = CurTime() + + -- Fretta Hooks + hook.Run("RoundEnd") end function StatePostRound:Tick() -- Advance State if (CurTime() - GAMEMODE.Data.RoundStartTime) >= 5 then -- ToDo: configureable time? GAMEMODE.RoundManager:SetState(StatePostMatch) + local players = team.GetPlayers(GAMEMODE.Teams.Seekers) + table.Add(players, team.GetPlayers(GAMEMODE.Teams.Hiders)) + + -- Assign end of round weighted points. + local aliveSeekers = 0 + local aliveHiders = 0 + for i,ply in ipairs(players) do + if ply:Alive() then + if (ply:Team() == GAMEMODE.Teams.Hiders) then + aliveHiders = aliveHiders + 1 + elseif (ply:Team() == GAMEMODE.Teams.Seekers) then + aliveSeekers = aliveSeekers + 1 + end + end + end + for i,ply in ipairs(players) do + local score = 0 + if (ply:Team() == GAMEMODE:GetRoundWinner()) then + if (ply:Alive()) then + score = 2 + else + score = 1 + end + if (ply:Team() == GAMEMODE.Teams.Hiders) then + score = score * aliveHiders + elseif (ply:Team() == GAMEMODE.Teams.Seekers) then + score = -1 * score * aliveSeekers + end + end + ply.Data.RandomWeight = ply.Data.RandomWeight + score + end + + -- Team Distribution + if (GAMEMODE.Config.Teams:Weighted() == true) then + -- Weighted Teams + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Randomizing Teams using weighted Score.") end + + -- table.sort function returns true if it should a should be before b. + table.sort(players, function(a, b) + if (a.Data.RandomWeight == b.Data.RandomWeight) then + return math.random(100) > 50 + else + return a.Data.RandomWeight > b.Data.RandomWeight + end + end) + elseif (GAMEMODE.Config.Teams:Randomize() == true) then + -- Randomize Teams + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Randomizing Teams.") end + + table.sort(players, function(a,b) + return math.random(100) > 50 + end) + else + -- Swap Teams + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Swapping Teams.") end + + table.sort(players, function(a,b) + return math.random(100) > 50 + end) + table.sort(players, function(a,b) + if (b:Team() == GAMEMODE.Teams.Seekers) then + return (a:Team() == GAMEMODE.Teams.Hiders) + end + return false + end) + end + + -- Team Distribution Logic + local hiders, seekers = {}, {} + if (GAMEMODE.Config:GameType() == GAMEMODE.Types.Original) then + -- Game Mode: Basic + local plyCount, finalPlyCount = #players, math.max(math.ceil(#players / 2), 1) + for c = 1,finalPlyCount do + seekers[c] = table.remove(players, 1) + end + hiders = players + elseif (GAMEMODE.Config:GameType() == GAMEMODE.Types.TheDeadHunt) then + -- Game Mode: The Dead Hunt + local plyCount, finalPlyCount = #players, math.max(math.ceil(#players * GAMEMODE.Config.Teams:SeekerPercentage()), 1) + for c = 1,finalPlyCount do + seekers[c] = table.remove(players, 1) + end + hiders = players + end + + -- Kill & Assign Teams + for i, ply in ipairs(hiders) do + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Assigned '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") to Team Hiders.") end + ply:KillSilent() + ply:SetTeam(GAMEMODE.Teams.Hiders) + end + for i, ply in ipairs(seekers) do + if GAMEMODE.Config:DebugLog() then print("Prop Hunt: Assigned '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") to Team Seekers.") end + ply:KillSilent() + ply:SetTeam(GAMEMODE.Teams.Seekers) + end end end function StatePostRound:OnLeave(NewState) - if GAMEMODE.Config:Debug() then print("StatePostRound: OnLeave") end - - -- Game Mode: Basic - if (GAMEMODE.Config:GameMode() == GAMEMODE.Modes.Original) then - -- Swap Teams - local hiders, seekers = team.GetPlayers(GAMEMODE.Teams.Hiders), team.GetPlayers(GAMEMODE.Teams.Seekers) - for i, ply in ipairs(hiders) do - ply:KillSilent() - ply:SetTeam(GAMEMODE.Teams.Seekers) - end - for i, ply in ipairs(seekers) do - ply:KillSilent() - ply:SetTeam(GAMEMODE.Teams.Hiders) - end - - -- TODO: Other Gamemodes - end + if GAMEMODE.Config:DebugLog() then print("StatePostRound: OnLeave") end end \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/server/states/state_prematch.lua b/Source/gamemodes/prophuntextended/gamemode/server/states/state_prematch.lua index 6947701..017745e 100644 --- a/Source/gamemodes/prophuntextended/gamemode/server/states/state_prematch.lua +++ b/Source/gamemodes/prophuntextended/gamemode/server/states/state_prematch.lua @@ -26,29 +26,30 @@ StatePreMatch = {} function StatePreMatch:OnEnter(OldState) - if GAMEMODE.Config:Debug() then print("StatePreMatch: OnEnter") end + if GAMEMODE.Config:DebugLog() then print("StatePreMatch: OnEnter") end GAMEMODE:SetRoundState(GAMEMODE.States.PreMatch) - SetGlobalInt("Round", GetGlobalInt("Round", 0) + 1) + math.randomseed(CurTime()) end function StatePreMatch:Tick() -- Debug: Auto Advance to PreRound State if (GAMEMODE.Config:Debug()) then - print("StatePreMatch: Advancing to StatePreRound") + if GAMEMODE.Config:DebugLog() then print("StatePreMatch: Advancing to StatePreRound") end GAMEMODE.RoundManager:SetState(StatePreRound) end -- Game Mode: Basic - if (GAMEMODE.Config:GameMode() == GAMEMODE.Modes.Original) then + if (GAMEMODE.Config:GameType() == GAMEMODE.Types.Original) then -- Both Teams must have at least 1 player. if ((team.NumPlayers(GAMEMODE.Teams.Seekers) >= 1) && (team.NumPlayers(GAMEMODE.Teams.Hiders) >= 1)) then GAMEMODE.RoundManager:SetState(StatePreRound) + if GAMEMODE.Config:DebugLog() then print("StatePreMatch: Have enough players to start match.") end end -- TODO: Other Gamemodes end end function StatePreMatch:OnLeave(NewState) - if GAMEMODE.Config:Debug() then print("StatePreMatch: OnLeave") end + if GAMEMODE.Config:DebugLog() then print("StatePreMatch: OnLeave") end end \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/server/states/state_preround.lua b/Source/gamemodes/prophuntextended/gamemode/server/states/state_preround.lua index f9ccec2..b829222 100644 --- a/Source/gamemodes/prophuntextended/gamemode/server/states/state_preround.lua +++ b/Source/gamemodes/prophuntextended/gamemode/server/states/state_preround.lua @@ -25,8 +25,9 @@ StatePreRound = {} function StatePreRound:OnEnter(OldState) - if GAMEMODE.Config:Debug() then print("StatePreRound: OnEnter") end + if GAMEMODE.Config:DebugLog() then print("StatePreRound: OnEnter") end GAMEMODE:SetRoundState(GAMEMODE.States.PreRound) + GAMEMODE:SetRound(GAMEMODE:GetRound() + 1) -- Clean Up the Map game.CleanUpMap() @@ -37,7 +38,7 @@ function StatePreRound:Tick() GAMEMODE.RoundManager:SetState(StateHide) end function StatePreRound:OnLeave(NewState) - if GAMEMODE.Config:Debug() then print("StatePreRound: OnLeave") end + if GAMEMODE.Config:DebugLog() then print("StatePreRound: OnLeave") end -- Respawn Everyone for i, ply in ipairs(player.GetAll()) do @@ -46,5 +47,15 @@ function StatePreRound:OnLeave(NewState) ply:Spawn() ply:ScreenFade(SCREENFADE.PURGE, color_black, 0, 0) ply:ScreenFade(SCREENFADE.IN, color_black, 1, 0) + + -- Weighted Score: Adjust towards other Team. + if (ply:Team() == GAMEMODE.Teams.Hiders) then + ply.Data.RandomWeight = ply.Data.RandomWeight + 1 + elseif (ply:Team() == GAMEMODE.Teams.Seekers) then + ply.Data.RandomWeight = ply.Data.RandomWeight - 1 + end end + + -- Fretta Hooks + hook.Run("RoundStart") end \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/server/states/state_seek.lua b/Source/gamemodes/prophuntextended/gamemode/server/states/state_seek.lua index a84a251..930e6d8 100644 --- a/Source/gamemodes/prophuntextended/gamemode/server/states/state_seek.lua +++ b/Source/gamemodes/prophuntextended/gamemode/server/states/state_seek.lua @@ -25,7 +25,7 @@ StateSeek = {} function StateSeek:OnEnter(OldState) - if GAMEMODE.Config:Debug() then print("StateSeek: OnEnter") end + if GAMEMODE.Config:DebugLog() then print("StateSeek: OnEnter") end GAMEMODE:SetRoundState(GAMEMODE.States.Seek) -- Round Data @@ -75,7 +75,7 @@ function StateSeek:Tick() GAMEMODE.RoundManager:SetState(StatePostRound) else if (GAMEMODE.Data.RoundTime <= 0) then -- No Time remaining - GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Hiders) + GAMEMODE:SetRoundWinner(GAMEMODE.Teams.Hiders) GAMEMODE.RoundManager:SetState(StatePostRound) end end @@ -83,5 +83,13 @@ function StateSeek:Tick() end function StateSeek:OnLeave(NewState) - if GAMEMODE.Config:Debug() then print("StateSeek: OnLeave") end + if GAMEMODE.Config:DebugLog() then print("StateSeek: OnLeave") end + + if GAMEMODE:GetRoundWinner() == GAMEMODE.Teams.Seekers then + hook.Run("RoundVictorySeeker") + elseif GAMEMODE:GetRoundWinner() == GAMEMODE.Teams.Hiders then + hook.Run("RoundVictoryHider") + else + hook.Run("RoundVictoryDraw") + end end \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/sh_config.lua b/Source/gamemodes/prophuntextended/gamemode/sh_config.lua index 2324120..65ac1c0 100644 --- a/Source/gamemodes/prophuntextended/gamemode/sh_config.lua +++ b/Source/gamemodes/prophuntextended/gamemode/sh_config.lua @@ -1,294 +1,413 @@ --- 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 +--[[ + The MIT License (MIT) + + Copyright (c) 2015 Xaymar + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +--]] + +--! Initialize configuration table. +GM.Config = { } +GM.Config.ConVars = {} + +function CreateConVarIfNotExists(name, value, flags, helptext) + cv = GetConVar(name) + if (cv == nil) then + cv = CreateConVar(name, value, flags, helptext) +-- else +-- ncv = CreateConVar(name, value, flags, helptext) + end + return cv end --- 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 +-- ------------------------------------------------------------------------- -- +--! Debug Settings +-- ------------------------------------------------------------------------- -- +-- Debug Mode + +GM.Config.ConVars.Debug = CreateConVarIfNotExists("ph_debug", "0", FCVAR_CHEAT + FCVAR_REPLICATED, "Prop Hunt: Enable Debug Mode") +function GM.Config:Debug() + return self.ConVars.Debug:GetBool() end --- 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 +-- Debug Log +GM.Config.ConVars.DebugLog = CreateConVarIfNotExists("ph_debug_log", "0", FCVAR_REPLICATED, "Prop Hunt: Enable Debug Logging") +function GM.Config:DebugLog() + return self.ConVars.DebugLog:GetBool() end --- 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)) +-- ------------------------------------------------------------------------- -- +--! Basic Settings +-- ------------------------------------------------------------------------- -- +-- Game Mode (See sh_init.lua) +GM.Config.ConVars.GameType = CreateConVarIfNotExists("ph_gametype", GM.Types.Original, FCVAR_REPLICATED, "Prop Hunt: Which Game Type should be played? ("..GM.Types.Original.." = Original Prop Hunt, "..GM.Types.TheDeadHunt.." = The Dead Hunt Mode)") +function GM.Config:GameType() + return self.ConVars.GameType:GetInt() end -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 + +-- Timelimit in minutes +GM.Config.ConVars.TimeLimit = CreateConVarIfNotExists("mp_timelimit", "20", FCVAR_REPLICATED, "Map Time Limit (in Minutes)") +function GM.Config:TimeLimit() + return self.ConVars.TimeLimit:GetFloat() +end + +-- ------------------------------------------------------------------------- -- +--! Round Settings +-- ------------------------------------------------------------------------- -- +GM.Config.Round = {} +GM.Config.Round.ConVars = {} + +-- How many rounds should the GM attempt to fit into the map timelimit, if there is any? +GM.Config.Round.ConVars.Limit = CreateConVarIfNotExists("ph_round_limit", "10", FCVAR_REPLICATED, "Round Manager: Maximum Rounds to Play on a single Map") +function GM.Config.Round:Limit() + return self.ConVars.Limit:GetInt() +end + +-- Round Time Limit (Seconds, Default 3 minutes) +GM.Config.Round.ConVars.Time = CreateConVarIfNotExists("ph_round_timelimit", "180", FCVAR_REPLICATED, "Round Manager: Time Limit per Round (in Seconds)") +function GM.Config.Round:Time() + return math.max(self.ConVars.Time:GetFloat() - math.min(self:BlindTime(),0),0) +end + +-- For how many seconds are the Seekers blinded? (Seconds) +GM.Config.Round.ConVars.BlindTime = CreateConVarIfNotExists("ph_round_blindtime", "-30", FCVAR_REPLICATED, "Round Manager: Blind Time for Seekers (in Seconds, positive takes away from ph_round_timelimit, negative adds extra time to ph_round_timelimit") +function GM.Config.Round:BlindTime() + return self.ConVars.BlindTime:GetFloat() +end + +-- ------------------------------------------------------------------------- -- +--! Team Settings +-- ------------------------------------------------------------------------- -- +GM.Config.Teams = {} +GM.Config.Teams.ConVars = {} + +-- Should teams be ranomized each round? +GM.Config.Teams.ConVars.Randomize = CreateConVarIfNotExists("ph_teams_randomize", "0", FCVAR_REPLICATED, "Teams: Randomize Each Round") +function GM.Config.Teams:Randomize() + return self.ConVars.Randomize:GetBool() +end + +-- Should teams be using weighted randomization? +-- Weighted randomization works by using a score calculated over the entire session. +-- * Round Start: Adjust Score towards the other Team by 1 (Positive = Seeker, Negative = Hider) +-- * Round Win: Adjust score by how many players are still alive on the winning team towards the other team. +-- * Alive players get double the score. +GM.Config.Teams.ConVars.Weighted = CreateConVarIfNotExists("ph_teams_weighted", "1", FCVAR_REPLICATED, "Teams: Use Weighted Randomization") +function GM.Config.Teams:Weighted() + return self.ConVars.Weighted:GetBool() +end + +-- The Dead Hunt: Percent of players to assign to seeker. +GM.Config.Teams.ConVars.SeekerPercentage = CreateConVarIfNotExists("ph_teams_seekerpct", "25", FCVAR_REPLICATED, "Teams: Initial percentage of Seekers in Dead Hunt Game Type") +function GM.Config.Teams:SeekerPercentage() + return self.ConVars.Teams:GetFloat() / 100 +end + +-- ------------------------------------------------------------------------- -- +--! Seeker Settings +-- ------------------------------------------------------------------------- -- +GM.Config.Seeker = {} +GM.Config.Seeker.ConVars = {} + +GM.Config.Seeker.ConVars.Health = CreateConVarIfNotExists("ph_seeker_health", "100", FCVAR_REPLICATED, "Seekers: Initial Health") +function GM.Config.Seeker:Health() + return self.ConVars.Health:GetInt() +end + +GM.Config.Seeker.ConVars.HealthMax = CreateConVarIfNotExists("ph_seeker_health_max", "100", FCVAR_REPLICATED, "Seekers: Maximum Health") +function GM.Config.Seeker:HealthMax() + return self.ConVars.HealthMax:GetInt() +end + +GM.Config.Seeker.ConVars.HealthBonus = CreateConVarIfNotExists("ph_seeker_health_bonus", "20", FCVAR_REPLICATED, "Seekers: Health Bonus per Kill") +function GM.Config.Seeker:HealthBonus() + return self.ConVars.HealthBonus:GetInt() +end + +GM.Config.Seeker.ConVars.HealthPenalty = CreateConVarIfNotExists("ph_seeker_health_penalty", "5", FCVAR_REPLICATED, "Seekers: Health Penalty per wrong Shot") +function GM.Config.Seeker:HealthPenalty() + return self.ConVars.HealthPenalty:GetInt() +end + +GM.Config.Seeker.ConVars.Weapons = CreateConVarIfNotExists("ph_seeker_weapons", "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun", FCVAR_REPLICATED, "Seekers: Initial Weapons (Weapon,Weapon,...)") +function GM.Config.Seeker:Weapons() + return string.Split(self.ConVars.Weapons:GetString(), ",") +end + +GM.Config.Seeker.ConVars.Ammo = CreateConVarIfNotExists("ph_seeker_ammo", "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64", FCVAR_REPLICATED, "Seekers: Initial Ammo (Ammo:Amount,Ammo:Amount,...)") +function GM.Config.Seeker:Ammo() + return string.Split(self.ConVars.Ammo:GetString(), ",") +end + +GM.Config.Seeker.ConVars.WalkSpeed = CreateConVarIfNotExists("ph_seeker_walk_speed", "250", 0, "Seekers: Walk Speed") +function GM.Config.Seeker:WalkSpeed() + return self.ConVars.WalkSpeed:GetFloat() +end + +GM.Config.Seeker.ConVars.Sprint = CreateConVarIfNotExists("ph_seeker_sprint", "1", FCVAR_REPLICATED, "Seekers: Allow Sprinting") +function GM.Config.Seeker:Sprint() + return self.ConVars.Sprint:GetBool() +end + +GM.Config.Seeker.ConVars.SprintSpeed = CreateConVarIfNotExists("ph_seeker_sprint_speed", "500", 0, "Seekers: Sprint Speed") +function GM.Config.Seeker:SprintSpeed() + return self.ConVars.SprintSpeed:GetFloat() +end + +GM.Config.Seeker.ConVars.JumpPower = CreateConVarIfNotExists("ph_seeker_jump_power", "200", 0, "Seekers: Jump Power") +function GM.Config.Seeker:JumpPower() + return self.ConVars.JumpPower:GetFloat() +end + +-- ------------------------------------------------------------------------- -- +--! Hider Settings +-- ------------------------------------------------------------------------- -- +GM.Config.Hider = {} +GM.Config.Hider.ConVars = {} + +GM.Config.Hider.ConVars.Health = CreateConVarIfNotExists("ph_hider_health", "100", FCVAR_REPLICATED, "Hiders: Initial Health") +function GM.Config.Hider:Health() + return self.ConVars.Health:GetInt() +end + +GM.Config.Hider.ConVars.HealthMax = CreateConVarIfNotExists("ph_hider_health_max", "100", FCVAR_REPLICATED, "Hiders: Maximum Health") +function GM.Config.Hider:HealthMax() + return self.ConVars.HealthMax:GetInt() +end + +GM.Config.Hider.ConVars.HealthScaling = CreateConVarIfNotExists("ph_hider_health_scaling", "1", FCVAR_REPLICATED, "Hiders: Enable Health Scaling") +function GM.Config.Hider:HealthScaling() + return self.ConVars.HealthScaling:GetBool() +end + +GM.Config.Hider.ConVars.HealthScalingMax = CreateConVarIfNotExists("ph_hider_health_scaling_max", "200", FCVAR_REPLICATED, "Hiders: Maximum scaled Health") +function GM.Config.Hider:HealthScalingMax() + return self.ConVars.HealthScalingMax:GetInt() +end + +GM.Config.Hider.ConVars.AllowFullRotation = CreateConVarIfNotExists("ph_hider_allow_full_rotation", "0", FCVAR_REPLICATED, "Hiders: Enable full 3D Rotation") +function GM.Config.Hider:AllowFullRotation() + return self.ConVars.AllowFullRotation:GetBool() +end + +GM.Config.Hider.ConVars.WalkSpeed = CreateConVarIfNotExists("ph_hider_walk_speed", "250", 0, "Hiders: Walk Speed") +function GM.Config.Hider:WalkSpeed() + return self.ConVars.WalkSpeed:GetFloat() +end + +GM.Config.Hider.ConVars.Sprint = CreateConVarIfNotExists("ph_hider_sprint", "0", FCVAR_REPLICATED, "Hiders: Allow Sprinting") +function GM.Config.Hider:Sprint() + return self.ConVars.Sprint:GetBool() +end + +GM.Config.Hider.ConVars.SprintSpeed = CreateConVarIfNotExists("ph_hider_sprint_speed", "500", 0, "Hiders: Sprint Speed") +function GM.Config.Hider:SprintSpeed() + return self.ConVars.SprintSpeed:GetFloat() +end + +GM.Config.Hider.ConVars.JumpPower = CreateConVarIfNotExists("ph_hider_jump_power", "200", 0, "Hiders: Jump Power") +function GM.Config.Hider:JumpPower() + return self.ConVars.JumpPower:GetFloat() +end + +-- ------------------------------------------------------------------------- -- +--! Whitelist & Blacklist +-- ------------------------------------------------------------------------- -- +GM.Config.Lists = {} +GM.Config.Lists.ConVars = {} + +-- Class Whitelist +GM.Config.Lists.ConVars.ClassWhitelist = CreateConVarIfNotExists("ph_list_class_whitelist", "prop_physics,prop_physics_multiplayer,prop_physics_respawnable", FCVAR_REPLICATED, "Anti-Cheat: Whitelisted Hider Classes") +function GM.Config.Lists:ClassWhitelist() + local str = self.ConVars.ClassWhitelist:GetString() + if (self.ClassWhitelistCache != str) then + self.ClassWhitelistCache = str + self.ClassWhitelistCacheTbl = string.Split(self.ClassWhitelistCache, ",") + end + return self.ClassWhitelistCacheTbl +end + +-- Abuse Blacklist +GM.Config.Lists.ConVars.AbuseBlacklist = CreateConVarIfNotExists("ph_list_abuse_blacklist", "func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable", FCVAR_REPLICATED, "Anti-Cheat: Entity Abuse Blacklist") +function GM.Config.Lists:AbuseBlacklist() + local str = self.ConVars.AbuseBlacklist:GetString() + if (self.AbuseBlacklistCache != str) then + self.AbuseBlacklistCache = str + self.AbuseBlacklistCacheTbl = string.Split(self.AbuseBlacklistCache, ",") + end + return self.AbuseBlacklistCacheTbl +end + +-- Model Blacklist +GM.Config.Lists.ConVars.ModelBlacklist = CreateConVarIfNotExists("ph_list_model_blacklist", "models/props/cs_assault/dollar.mdl,models/props/cs_assault/money.mdl,models/props/cs_office/snowman_arm.mdl,models/props/cs_office/projector_remote.mdl", FCVAR_REPLICATED, "Anti-Cheat: Model Abuse Blacklist") +function GM.Config.Lists:ModelBlacklist() + local str = self.ConVars.ModelBlacklist:GetString() + if (self.ModelBlacklistCache != str) then + self.ModelBlacklistCache = str + self.ModelBlacklistCacheTbl = string.Split(self.ModelBlacklistCache, ",") + end + return self.ModelBlacklistCacheTbl +end + +-- ------------------------------------------------------------------------- -- +--! Taunts +-- ------------------------------------------------------------------------- -- +GM.Config.Taunt = {} +GM.Config.Taunt.ConVars = {} + +-- Cooldown (Seconds) +GM.Config.Taunt.ConVars.Cooldown = CreateConVarIfNotExists("ph_taunt_cooldown", 5, FCVAR_REPLICATED, "Prop Hunt: Cooldown between Taunts") +function GM.Config.Taunt:Cooldown() + return self.ConVars.Cooldown:GetFloat() +end + +-- Seeker +GM.Config.Taunt.SeekersCache = "" +GM.Config.Taunt.SeekersCacheDynamic = nil +GM.Config.Taunt.SeekersCacheStatic = nil +GM.Config.Taunt.SeekersCacheFull = nil +GM.Config.Taunt.ConVars.Seekers = CreateConVarIfNotExists("ph_taunt_seekers", "bot/a_bunch_of_them.wav,bot/come_out_and_fight_like_a_man.wav,bot/come_out_wherever_you_are.wav,bot/come_to_papa.wav,bot/dont_worry_hell_get_it.wav,bot/hang_on_i_heard_something.wav,bot/hang_on_im_coming.wav,bot/i_dont_think_so.wav,bot/i_have_the_hostages.wav,bot/i_see_our_target.wav,bot/im_waiting_here.wav,bot/keeping_an_eye_on_the_hostages.wav,bot/nnno_sir.wav,bot/spotted_the_delivery_boy.wav,bot/target_acquired.wav,bot/target_spotted.wav,bot/you_heard_the_man_lets_go.wav", 0, "Prop Hunt: Seeker Taunts") +function GM.Config.Taunt:Seekers() + local str = self.ConVars.Seekers:GetString() + if (self.SeekersCache != str) then + self.SeekersCache = str + self.SeekersCacheDynamic = string.Split(self.SeekersCache, ",") + self.SeekersCacheFull = table.Add(self.SeekersCacheDynamic, self.SeekersCacheStatic) + for i,snd in ipairs(self.SeekersCacheFull) do + util.PrecacheSound(snd) + end + end + return self.SeekersCacheFull +end + +-- Hider +GM.Config.Taunt.HidersCache = "" +GM.Config.Taunt.HidersCacheDynamic = nil +GM.Config.Taunt.HidersCacheStatic = nil +GM.Config.Taunt.HidersCacheFull = nil +GM.Config.Taunt.ConVars.Hiders = CreateConVarIfNotExists("ph_taunt_hiders", "ambient/alarms/apc_alarm_pass1.wav,ambient/alarms/manhack_alert_pass1.wav,ambient/alarms/razortrain_horn1.wav,ambient/alarms/scanner_alert_pass1.wav,ambient/alarms/train_horn2.wav,ambient/alarms/train_horn_distant1.wav,ambient/alarms/warningbell1.wav,ambient/energy/whiteflash.wav,ambient/intro/alyxremove.wav,ambient/intro/logosfx.wav,ambient/levels/launch/1stfiringwarning.wav,ambient/levels/launch/rockettakeoffblast.wav,ambient/misc/ambulance1.wav,ambient/misc/carhonk1.wav,ambient/misc/carhonk2.wav,ambient/misc/carhonk3.wav,ambient/outro/gunshipcrash.wav,ambient/3dmeagle.wav,beams/beamstart5.wav,buttons/bell1.wav,buttons/weapon_cant_buy.wav,common/bass.wav,common/bugreporter_failed.wav,common/warning.wav,doors/door_squeek1.wav,friends/friend_join.wav,friends/friend_online.wav,friends/message.wav,hostage/hunuse/comeback.wav,hostage/hunuse/dontleaveme.wav,hostage/hunuse/yeahillstay.wav,items/gift_drop.wav,music/radio1.mp3,phx/eggcrack.wav,plats/elevbell1.wav,player/headshot1.wav,player/headshot2.wav,player/sprayer.wav,radio/enemydown.wav,radio/go.wav,radio/locknload.wav,radio/negative.wav,radio/rounddraw.wav,radio/takepoint.wav,resource/warning.wav,ui/achievement_earned.wav,ui/freeze_cam.wav,vehicles/junker/radar_ping_friendly1.wav,weapons/c4/c4_beep1.wav,weapons/c4/c4_click.wav,weapons/awp/awp1.wav,vo/canals/female01/gunboat_giveemhell.wav,vo/canals/female01/gunboat_justintime.wav,vo/canals/female01/stn6_incoming.wav,vo/canals/male01/gunboat_giveemhell.wav,vo/canals/male01/gunboat_justintime.wav,vo/canals/male01/stn6_incoming.wav,vo/canals/al_radio_stn6.wav,vo/canals/arrest_getgoing.wav,vo/canals/arrest_helpme.wav,vo/canals/arrest_lookingforyou.wav,vo/canals/boxcar_lethimhelp.wav,vo/canals/matt_closecall.wav,vo/canals/premassacre.wav,vo/ravenholm/aimforhead.wav,vo/ravenholm/bucket_patience.wav,vo/ravenholm/madlaugh01.wav,vo/ravenholm/madlaugh02.wav,vo/ravenholm/madlaugh03.wav,vo/ravenholm/madlaugh04.wav,weapons/strider_buster/ol12_stickybombcreator.wav,weapons/c4/c4_explode1.wav,weapons/357/357_fire2.wav,weapons/357/357_fire3.wav,weapons/scout/scout_fire-1.wav,weapons/smokegrenade/sg_explode.wav,weapons/grenade_launcher1.wav,weapons/explode3.wav,weapons/underwater_explode3.wav,items/nvg_on.wav,hostage/huse/letsdoit.wav,hostage/huse/illfollow.wav,hostage/huse/getouttahere.wav,doors/door_screen_move1.wav,doors/heavy_metal_stop1.wav,doors/default_move.wav,common/stuck2.wav,ambient/water_splash1.wav,ambient/water_splash2.wav,ambient/water_splash3.wav,ambient/weather/thunder1.wav,ambient/weather/thunder2.wav,ambient/weather/thunder3.wav,ambient/weather/thunder4.wav,ambient/weather/thunder5.wav,ambient/weather/thunder6.wav,ambient/outro/thunder7.wav,ambient/voices/crying_loop1.wav,ambient/voices/playground_memory.wav,ambient/voices/f_scream1.wav,ambient/voices/m_scream1.wav,ambient/voices/cough1.wav,ambient/voices/cough2.wav,ambient/voices/cough3.wav,ambient/voices/cough4.wav,ambient/overhead/plane1.wav,ambient/overhead/plane2.wav,ambient/overhead/plane3.wav,ambient/overhead/hel1.wav,ambient/overhead/hel2.wav,ambient/misc/truck_backup1.wav,ambient/misc/truck_drive1.wav,ambient/misc/truck_drive2.wav,ambient/machines/pneumatic_drill_1.wav,ambient/machines/pneumatic_drill_2.wav,ambient/machines/pneumatic_drill_3.wav,ambient/machines/pneumatic_drill_4.wav,ambient/machines/station_train_squeel.wav,ambient/machines/ticktock.wav,ambient/creatures/teddy.wav,ambient/creatures/town_child_scream1.wav,ambient/creatures/town_moan1.wav,ambient/creatures/town_muffled_cry1.wav,ambient/creatures/town_scared_breathing1.wav,ambient/creatures/town_scared_breathing2.wav,ambient/creatures/town_scared_sob1.wav,ambient/creatures/town_scared_sob2.wav,ambient/creatures/town_zombie_call1.wav", 0, "Prop Hunt: Hider Taunts") +function GM.Config.Taunt:Hiders() + local str = self.ConVars.Hiders:GetString() + if (self.HidersCacheDynamic == nil) + || (self.HidersCache != str) then + self.HidersCache = str + self.HidersCacheDynamic = string.Split(self.HidersCache, ",") + self.HidersCacheFull = table.Add(self.HidersCacheDynamic, self.HidersCacheStatic) + for i,snd in ipairs(self.HidersCacheFull) do + util.PrecacheSound(snd) + end + end + return self.HidersCacheFull +end + +-- ------------------------------------------------------------------------- -- +--! Announcers +-- ------------------------------------------------------------------------- -- + +-- --! Announcers (Round Start, Unblind, Win, Loss) +-- GM.Config.Announcers = { + -- Start = { }, + -- Unblind = { }, + -- Win = { }, + -- Loss = { } +-- } + +-- ------------------------------------------------------------------------- -- +--! Camera +-- ------------------------------------------------------------------------- -- +GM.Config.Camera = {} +GM.Config.Camera.ConVars = {} + +-- Allow Camera No Clip +GM.Config.Camera.ConVars.AllowNoClip = CreateConVarIfNotExists("ph_camera_allow_noclip", "0", FCVAR_REPLICATED, "Camera: Allow clients to disable camera collision.") +function GM.Config.Camera:AllowNoClip() + return self.ConVars.AllowNoClip:GetBool() +end + +-- Camera Distance Maximum +GM.Config.Camera.ConVars.DistanceMax = CreateConVarIfNotExists("ph_camera_distance_max", "150", FCVAR_REPLICATED, "Camera: Maximum allowed distance to player.") +function GM.Config.Camera:DistanceMax() + return self.ConVars.DistanceMax:GetFloat() +end + +-- Camera Distance Minimum +GM.Config.Camera.ConVars.DistanceMin = CreateConVarIfNotExists("ph_camera_distance_min", "30", FCVAR_REPLICATED, "Camera: Minimum allowed distance to player.") +function GM.Config.Camera:DistanceMin() + return self.ConVars.DistanceMin:GetFloat() +end + +-- Camera Distance Right Maximum +GM.Config.Camera.ConVars.DistanceRightRange = CreateConVarIfNotExists("ph_camera_distance_right_range", "20", FCVAR_REPLICATED, "Camera: Horizontal allowed camera distance range.") +function GM.Config.Camera:DistanceRightRange() + return self.ConVars.DistanceRightRange:GetFloat() +end + +-- Camera Distance Up Maximum +GM.Config.Camera.ConVars.DistanceUpRange = CreateConVarIfNotExists("ph_camera_distance_up_range", "20", FCVAR_REPLICATED, "Camera: Vertical allowed camera distance range.") +function GM.Config.Camera:DistanceUpRange() + return self.ConVars.DistanceUpRange:GetFloat() +end + +-- Lag Minimum +GM.Config.Camera.ConVars.LagMinimum = CreateConVarIfNotExists("ph_camera_lag_min", "0.01", FCVAR_REPLICATED, "Camera: Minimum Camera Lag.") +function GM.Config.Camera:LagMinimum() + return self.ConVars.LagMinimum:GetFloat() +end + +-- Lag Maximum +GM.Config.Camera.ConVars.LagMaximum = CreateConVarIfNotExists("ph_camera_lag_max", "0.95", FCVAR_REPLICATED, "Camera: Maximum Camera Lag.") +function GM.Config.Camera:LagMaximum() + return self.ConVars.LagMaximum:GetFloat() +end + +if CLIENT then + -- Collisions + GM.Config.Camera.ConVars.Collisions = CreateConVarIfNotExists("ph_camera_collisions", "1", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Enable collisions with the world and objects in it.") + function GM.Config.Camera:Collisions() + if self:AllowNoClip() then + return self.ConVars.Collisions:GetBool() + else + return true + end + end + + -- Distance + GM.Config.Camera.ConVars.Distance = CreateConVarIfNotExists("ph_camera_distance", "100", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Ideal Distance to player.") + function GM.Config.Camera:Distance() + return math.Clamp(self.ConVars.Distance:GetFloat(), self:DistanceMin(), self:DistanceMax()) + end + + -- Distance Right + GM.Config.Camera.ConVars.DistanceRight = CreateConVarIfNotExists("ph_camera_distance_right", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Ideal Distance to player horizontally.") + function GM.Config.Camera:DistanceRight() + return math.Clamp(self.ConVars.DistanceRight:GetFloat(), -self:DistanceRightRange(), self:DistanceRightRange()) + end + + -- Distance Up + GM.Config.Camera.ConVars.DistanceUp = CreateConVarIfNotExists("ph_camera_distance_up", "0", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Ideal Distance to player vertically.") + function GM.Config.Camera:DistanceUp() + return math.Clamp(self.ConVars.DistanceUp:GetFloat(), -self:DistanceUpRange(), self:DistanceUpRange()) + end + + -- Lag + GM.Config.Camera.ConVars.Lag = CreateConVarIfNotExists("ph_camera_lag", "0.95", FCVAR_ARCHIVE + FCVAR_CLIENTDLL, "Camera: Percentage of camera lag (higher = slower, lower = faster).") + function GM.Config.Camera:Lag() + return math.Clamp(self.ConVars.Lag:GetFloat(), self:LagMinimum(), self:LagMaximum()) + end end \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/gamemode/sh_init.lua b/Source/gamemodes/prophuntextended/gamemode/sh_init.lua index 36a57ba..f233cb5 100644 --- a/Source/gamemodes/prophuntextended/gamemode/sh_init.lua +++ b/Source/gamemodes/prophuntextended/gamemode/sh_init.lua @@ -34,15 +34,6 @@ GM.TeamBased = true GM.AllowAutoTeam = true GM.SecondsBetweenTeamSwitches = 10 --- ------------------------------------------------------------------------- -- ---! Includes --- ------------------------------------------------------------------------- -- --- Player Classes -include "player_class/class_default.lua" -include "player_class/class_spectator.lua" -include "player_class/class_seeker.lua" -include "player_class/class_hider.lua" - -- ------------------------------------------------------------------------- -- --! Code -- ------------------------------------------------------------------------- -- @@ -56,10 +47,9 @@ GM.States.PostRound = 4 GM.States.PostMatch = 5 -- Game Modes -GM.Modes = {} -GM.Modes.Original = 0 -GM.Modes.SwizzleEffect = 1 -- Randomizes Teams each Round -GM.Modes.TheDeadHunt = 2 -- One Hunter, Dead Prop become Hunter, Props can't see each other. +GM.Types = {} +GM.Types.Original = 0 +GM.Types.TheDeadHunt = 1 -- One Hunter, Dead Prop become Hunter, Props can't see each other. -- Teams GM.Teams = {} @@ -75,13 +65,15 @@ function GM:CreateTeams() "info_player_combine", "info_player_counterterrorist", "info_player_allies", - "info_player_terrorist" + "info_player_terrorist", + "info_player_start" }) team.SetClass(self.Teams.Spectators, { "Spectator", "Spectator" }) -- Seekers: "Hunters" team.SetUp(self.Teams.Seekers, "Seekers", Color(0, 128, 255, 255)) team.SetSpawnPoint(self.Teams.Seekers, { + "info_player_start", "info_player_spawn", "info_player_deathmatch", "info_player_combine", @@ -92,6 +84,7 @@ function GM:CreateTeams() -- Hiders: "Props" team.SetUp(self.Teams.Hiders, "Hiders", Color(255, 128, 0, 255)) team.SetSpawnPoint(self.Teams.Hiders, { + "info_player_start", "info_player_spawn", "info_player_deathmatch", "info_player_allies", @@ -112,17 +105,23 @@ function GM:PlayerTick(ply, mv) end function GM:PlayerHurt(victim, attacker, healthRemaining, damageTaken) - if (victim != nil && victim:IsPlayer()) then - player_manager.RunClass(victim, "Hurt", victim, attacker, healthRemaining, damageTaken) - end - if (attacker != nil && attacker:IsPlayer()) then + player_manager.RunClass(victim, "Hurt", victim, attacker, healthRemaining, damageTaken) + + if (IsValid(attacker) && attacker:IsPlayer()) then player_manager.RunClass(attacker, "Damage", victim, attacker, healthRemaining, damageTaken) end end +function GM:PlayerShouldTakeDamage(victim, attacker) + return player_manager.RunClass(victim, "ShouldTakeDamage", attacker) +end -- ------------------------------------------------------------------------- -- --! Gamemode Functionality -- ------------------------------------------------------------------------- -- +function GM:GetRound() + return GetGlobalInt("Round", 0) +end + function GM:GetRoundState() return GetGlobalInt("RoundState", self.States.PreMatch) end @@ -133,4 +132,15 @@ end function GM:GetRoundWinner() return GetGlobalInt("RoundWinner", GAMEMODE.Teams.Spectator) -end \ No newline at end of file +end + +-- ------------------------------------------------------------------------- -- +--! Includes +-- ------------------------------------------------------------------------- -- +include "sh_config.lua" + +-- Player Classes +include "player_class/class_default.lua" +include "player_class/class_spectator.lua" +include "player_class/class_seeker.lua" +include "player_class/class_hider.lua" \ No newline at end of file diff --git a/Source/gamemodes/prophuntextended/prophuntextended.txt b/Source/gamemodes/prophuntextended/prophuntextended.txt index dfce58b..2bde58a 100644 --- a/Source/gamemodes/prophuntextended/prophuntextended.txt +++ b/Source/gamemodes/prophuntextended/prophuntextended.txt @@ -2,181 +2,242 @@ { "base" "base" "title" "Prop Hunt Extended" - "maps" "^ph_|^cs_|^de_|^ttt_" + "maps" "^ph_" "menusystem" "1" "workshopid" "468149739" "settings" { - // Game Settings + // Debug Settings 1 { - "name" "ph_gamemode" - "text" "G: Game Mode" - "help" "0: Basic, 1: Swizzle Effect (Random Teams), 2: The Dead Hunt (One Hunter, Dead Props become Hunters)" - "type" "Numeric" + "name" "ph_debug" + "text" "Enable Debug Mode" + "type" "CheckBox" "default" "0" } 2 { - "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" - } - - 3 - { - "name" "ph_sprinting" - "text" "G: Enable Sprinting" - "help" "Should sprinting be possible?" + "name" "ph_debug_log" + "text" "Enable Debug Logging" "type" "CheckBox" - "default" "0" + "default" "1" } - - 4 - { - "name" "ph_tauntcooldown" - "text" "G: Taunt Cooldown" - "help" "How much time must pass before another taunt may be played." - "type" "Numeric" - "default" "5" - } - - // Round Settings - 10 - { - "name" "ph_round_limit" - "text" "R: Rounds per Map" - "help" "How many rounds are played per map." - "type" "Numeric" - "default" "10" - } - + + // Basic Settings 11 { - "name" "ph_round_timelimit" - "text" "R: Round Duration (Seconds)" - "help" "How long is each round going to last?" + "name" "ph_gametype" + "text" "Game Type to use" "type" "Numeric" - "default" "300" + "default" "0" } 12 { - "name" "ph_round_blindtime" - "text" "R: Hiding Time (Seconds)" - "help" "How long are hunters blinded? (positive values will be inside the round time limit, negative will add to the round time limit)" + "name" "mp_timelimit" + "text" "Map Time Limit" "type" "Numeric" - "default" "30" - } - - // Seeker Settings - 20 - { - "name" "ph_seeker_health" - "text" "S: Health" - "type" "Numeric" - "default" "100" + "default" "0" } + 13 + { + "name" "ph_sprinting" + "text" "Enable Sprinting" + "type" "CheckBox" + "default" "0" + } + + // Round Settings 21 { - "name" "ph_seeker_health_max" - "text" "S: Max Health" + "name" "ph_round_limit" + "text" "Maximum Rounds Played" "type" "Numeric" - "default" "100" + "default" "10" } 22 { - "name" "ph_seeker_health_bonus" - "text" "S: Health Kill-Bonus" - "help" "Health gained on kill." + "name" "ph_round_timelimit" + "text" "Time Limit per Round" "type" "Numeric" - "default" "20" + "default" "180" } 23 { - "name" "ph_seeker_health_penalty" - "text" "S: Health Penalty" - "help" "Health lost on wrong shot." + "name" "ph_round_blindtime" + "text" "Seeker Blind time per Round" "type" "Numeric" - "default" "5" - } - - 24 - { - "name" "ph_seeker_weapons" - "text" "S: Weapons to be given to Seekers" - "help" "Format: Weapon,Weapon,..." - "type" "Text" - "default" "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun,weapon_physcannon" - } - - 25 - { - "name" "ph_seeker_ammo" - "text" "S: Ammo to give to Seekers" - "help" "Format: Name:Amount,Name:Amount,..." - "type" "Text" - "default" "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64" - } - - // Hider Settings - 30 - { - "name" "ph_hider_health" - "text" "H: Health" - "type" "Numeric" - "default" "100" + "default" "-30" } + // Team Settings 31 { - "name" "ph_hider_health_max" - "text" "H: Max Health" - "type" "Numeric" - "default" "100" + "name" "ph_teams_randomize" + "text" "Randomize Teams" + "type" "CheckBox" + "default" "1" } 32 { - "name" "ph_hider_health_scaling" - "text" "H: Enable Health Scaling" - "help" "Larger & heavier objects have more health, smaller less." + "name" "ph_teams_weighted" + "text" "Randomize with weighted Score" "type" "CheckBox" "default" "1" } 33 + { + "name" "ph_teams_seekerpct" + "text" "Pct of Pl. becoming Seeker" + "type" "Numeric" + "default" "25" + } + + // Seeker Settings + 41 + { + "name" "ph_seeker_health" + "text" "Seeker Health" + "type" "Numeric" + "default" "100" + } + + 42 + { + "name" "ph_seeker_health_max" + "text" "Seeker Max Health" + "type" "Numeric" + "default" "100" + } + + 43 + { + "name" "ph_seeker_health_bonus" + "text" "Seeker Health Kill-Bonus" + "type" "Numeric" + "default" "20" + } + + 44 + { + "name" "ph_seeker_health_penalty" + "text" "Seeker Health Penalty" + "type" "Numeric" + "default" "5" + } + + 45 + { + "name" "ph_seeker_weapons" + "text" "Seeker Weapons" + "type" "Text" + "default" "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun" + } + + 46 + { + "name" "ph_seeker_ammo" + "text" "Seeker Ammo" + "type" "Text" + "default" "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64" + } + + // Hider Settings + 51 + { + "name" "ph_hider_health" + "text" "Hider Health" + "type" "Numeric" + "default" "100" + } + + 52 + { + "name" "ph_hider_health_max" + "text" "Hider Max Health" + "type" "Numeric" + "default" "100" + } + + 53 + { + "name" "ph_hider_health_scaling" + "text" "Hider Enable Health Scaling" + "type" "CheckBox" + "default" "1" + } + + 54 { "name" "ph_hider_health_scaling_max" - "text" "H: Scaled Max Health" + "text" "Hider Scaled Max Health" "type" "Numeric" "default" "200" } + 55 + { + "name" "ph_hider_allow_full_rotation" + "text" "Hider 3-Dimensional Rotation" + "type" "CheckBox" + "default" "0" + } + // Whitelist & Blacklist - 40 + 61 { "name" "ph_list_class_whitelist" - "text" "L: Allowed Entity Classes" - "help" "Hiders can only use these for changing model and skin." + "text" "Allowed Entity Classes" "type" "Text" "default" "ph_prop,prop_physics,prop_physics_multiplayer,prop_physics_respawnable" } - 41 + 62 { "name" "ph_list_abuse_blacklist" - "text" "L: Abuse Blacklist" - "help" "Fix interact spam with certain entities so that all areas stay accessible." + "text" "Abuse Blacklist" "type" "Text" - "default" ""func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable"" + "default" "func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable" + } + + 63 + { + "name" "ph_list_model_blacklist" + "text" "Model Blacklist" + "type" "Text" + "default" "models/props/cs_assault/dollar.mdl,models/props/cs_assault/money.mdl,models/props/cs_office/snowman_arm.mdl,models/props/cs_office/projector_remote.mdl" + } + + // Taunts + 71 + { + "name" "ph_taunt_cooldown" + "text" "Cooldown for Taunts" + "type" "Numeric" + "default" "5" + } + + 72 + { + "name" "ph_taunt_seekers" + "text" "Seeker Taunts" + "type" "Text" + "default" "bot/a_bunch_of_them.wav,bot/come_out_and_fight_like_a_man.wav,bot/come_out_wherever_you_are.wav,bot/come_to_papa.wav,bot/dont_worry_hell_get_it.wav,bot/hang_on_i_heard_something.wav,bot/hang_on_im_coming.wav,bot/i_dont_think_so.wav,bot/i_have_the_hostages.wav,bot/i_see_our_target.wav,bot/im_waiting_here.wav,bot/keeping_an_eye_on_the_hostages.wav,bot/nnno_sir.wav,bot/spotted_the_delivery_boy.wav,bot/target_acquired.wav,bot/target_spotted.wav,bot/you_heard_the_man_lets_go.wav" + } + + 73 + { + "name" "ph_taunt_hiders" + "text" "Hider Taunts" + "type" "Text" + "default" "ambient/alarms/apc_alarm_pass1.wav,ambient/alarms/manhack_alert_pass1.wav,ambient/alarms/razortrain_horn1.wav,ambient/alarms/scanner_alert_pass1.wav,ambient/alarms/train_horn2.wav,ambient/alarms/train_horn_distant1.wav,ambient/alarms/warningbell1.wav,ambient/energy/whiteflash.wav,ambient/intro/alyxremove.wav,ambient/intro/logosfx.wav,ambient/levels/launch/1stfiringwarning.wav,ambient/levels/launch/rockettakeoffblast.wav,ambient/misc/ambulance1.wav,ambient/misc/carhonk1.wav,ambient/misc/carhonk2.wav,ambient/misc/carhonk3.wav,ambient/outro/gunshipcrash.wav,ambient/3dmeagle.wav,beams/beamstart5.wav,buttons/bell1.wav,buttons/weapon_cant_buy.wav,common/bass.wav,common/bugreporter_failed.wav,common/warning.wav,doors/door_squeek1.wav,friends/friend_join.wav,friends/friend_online.wav,friends/message.wav,hostage/hunuse/comeback.wav,hostage/hunuse/dontleaveme.wav,hostage/hunuse/yeahillstay.wav,items/gift_drop.wav,music/radio1.mp3,phx/eggcrack.wav,plats/elevbell1.wav,player/headshot1.wav,player/headshot2.wav,player/sprayer.wav,radio/enemydown.wav,radio/go.wav,radio/locknload.wav,radio/negative.wav,radio/rounddraw.wav,radio/takepoint.wav,resource/warning.wav,ui/achievement_earned.wav,ui/freeze_cam.wav,vehicles/junker/radar_ping_friendly1.wav,weapons/c4/c4_beep1.wav,weapons/c4/c4_click.wav,weapons/awp/awp1.wav,vo/canals/female01/gunboat_giveemhell.wav,vo/canals/female01/gunboat_justintime.wav,vo/canals/female01/stn6_incoming.wav,vo/canals/male01/gunboat_giveemhell.wav,vo/canals/male01/gunboat_justintime.wav,vo/canals/male01/stn6_incoming.wav,vo/canals/al_radio_stn6.wav,vo/canals/arrest_getgoing.wav,vo/canals/arrest_helpme.wav,vo/canals/arrest_lookingforyou.wav,vo/canals/boxcar_lethimhelp.wav,vo/canals/matt_closecall.wav,vo/canals/premassacre.wav,vo/ravenholm/aimforhead.wav,vo/ravenholm/bucket_patience.wav,vo/ravenholm/madlaugh01.wav,vo/ravenholm/madlaugh02.wav,vo/ravenholm/madlaugh03.wav,vo/ravenholm/madlaugh04.wav,weapons/strider_buster/ol12_stickybombcreator.wav,weapons/c4/c4_explode1.wav,weapons/357/357_fire2.wav,weapons/357/357_fire3.wav,weapons/scout/scout_fire-1.wav,weapons/smokegrenade/sg_explode.wav,weapons/grenade_launcher1.wav,weapons/explode3.wav,weapons/underwater_explode3.wav,items/nvg_on.wav,hostage/huse/letsdoit.wav,hostage/huse/illfollow.wav,hostage/huse/getouttahere.wav,doors/door_screen_move1.wav,doors/heavy_metal_stop1.wav,doors/default_move.wav,common/stuck2.wav,ambient/water_splash1.wav,ambient/water_splash2.wav,ambient/water_splash3.wav,ambient/weather/thunder1.wav,ambient/weather/thunder2.wav,ambient/weather/thunder3.wav,ambient/weather/thunder4.wav,ambient/weather/thunder5.wav,ambient/weather/thunder6.wav,ambient/outro/thunder7.wav,ambient/voices/crying_loop1.wav,ambient/voices/playground_memory.wav,ambient/voices/f_scream1.wav,ambient/voices/m_scream1.wav,ambient/voices/cough1.wav,ambient/voices/cough2.wav,ambient/voices/cough3.wav,ambient/voices/cough4.wav,ambient/overhead/plane1.wav,ambient/overhead/plane2.wav,ambient/overhead/plane3.wav,ambient/overhead/hel1.wav,ambient/overhead/hel2.wav,ambient/misc/truck_backup1.wav,ambient/misc/truck_drive1.wav,ambient/misc/truck_drive2.wav,ambient/machines/pneumatic_drill_1.wav,ambient/machines/pneumatic_drill_2.wav,ambient/machines/pneumatic_drill_3.wav,ambient/machines/pneumatic_drill_4.wav,ambient/machines/station_train_squeel.wav,ambient/machines/ticktock.wav,ambient/creatures/teddy.wav,ambient/creatures/town_child_scream1.wav,ambient/creatures/town_moan1.wav,ambient/creatures/town_muffled_cry1.wav,ambient/creatures/town_scared_breathing1.wav,ambient/creatures/town_scared_breathing2.wav,ambient/creatures/town_scared_sob1.wav,ambient/creatures/town_scared_sob2.wav,ambient/creatures/town_zombie_call1.wav" } } }