Initial Reupload

This commit is contained in:
Lucas Magnien
2019-05-28 09:16:53 +02:00
parent c7dea7beef
commit ded79721a1
368 changed files with 12298 additions and 2 deletions

View File

@@ -0,0 +1,135 @@
-- For the love of furry heck, THIS PLACE NEEDS A CLEAN!
-- Props will autotaunt at specified intervals
local isEnabled = false
local isProp = false
local delay = 45
local started = false
local timerID = "ph_autotaunt_timer"
local teamCheckTimer = "ph_autotaunt_teamchecktimer"
local xStart
local xEnd
local y
local w = 140
local h = 30
local previousTime
local tweenTime = 0
local function TimeLeft()
local ply = LocalPlayer()
local lastTauntTime = ply:GetNWFloat("LastTauntTime")
local nextTauntTime = lastTauntTime + delay
local currentTime = CurTime()
return nextTauntTime - currentTime
end
-- a: amplitude
-- p: period
local function outElastic(t, b, c, d, a, p)
local pi = math.pi
if t == 0 then return b end
t = t / d
if t == 1 then return b + c end
if not p then p = d * 0.3 end
local s
if not a or a < math.abs(c) then
a = c
s = p / 4
else
s = p / (2 * pi) * math.asin(c / a)
end
return a * math.pow(2, - 10 * t) * math.sin((t * d - s) * (2 * pi) / p) + c + b
end
local function AutoTauntPaint()
if !isEnabled || !isProp || !started then return; end
if tweenTime < 1 then
x = outElastic(tweenTime, xStart, xEnd - xStart, 1, 1, 0.5)
local cTime = CurTime()
tweenTime = tweenTime + (cTime - previousTime)
previousTime = cTime
end
local timeLeft = math.ceil(TimeLeft())
local percentage = timeLeft / delay
local txt = "Auto taunting in " .. timeLeft
draw.RoundedBox(5, x, y, w, h, Color(0, 0, 0, 200))
draw.RoundedBox(5, x + 5, y + 5, (w - 10) * percentage, h - 10, Color(200, 0, 0, 200))
draw.DrawText(txt, "HunterBlindLockFont", x + 70, ScrH() - 57, Color(255, 255, 255, 255), TEXT_ALIGN_CENTER)
end
hook.Add("HUDPaint", "PH_AutoTauntPaint", AutoTauntPaint)
local function RemoveTimer()
if timer.Exists(timerID) then
timer.Destroy(timerID)
end
end
local function CheckAutoTaunt()
local timeLeft = TimeLeft()
local ply = LocalPlayer()
-- Stop everything under these conditions
if !ply:Alive() || ply:Team() != TEAM_PROPS then
started = false
RemoveTimer()
printVerbose("[PH:E AutoTaunt] Blocked!")
return
end
end
local function Setup()
local ply = LocalPlayer()
isEnabled = GetConVar("ph_autotaunt_enabled"):GetBool()
isProp = ply:Team() == TEAM_PROPS
started = true
previousTime = CurTime()
tweenTime = 0
if isEnabled && isProp then
delay = GetConVar("ph_autotaunt_delay"):GetInt()
timer.Create(timerID, 1, 0, CheckAutoTaunt)
end
end
local function CheckPlayer()
local ply = LocalPlayer()
if ply:Alive() && ply:Team() == TEAM_PROPS then
if timer.Exists(teamCheckTimer) then
timer.Destroy(teamCheckTimer)
end
Setup()
return true
end
return false
end
local function AutoTauntSpawn()
xStart = ScrW() + 200
xEnd = ScrW() - 195
y = ScrH() - 65
if !CheckPlayer() then
timer.Create(teamCheckTimer, 0.1, 10, CheckPlayer)
end
end
net.Receive("AutoTauntSpawn", function() AutoTauntSpawn() end)
local function AutoTauntRoundEnd()
started = false
RemoveTimer()
end
net.Receive("AutoTauntRoundEnd", function() AutoTauntRoundEnd() end)

View File

@@ -0,0 +1,66 @@
hook.Add("PH_CustomTabMenu", "PHE.About", function(tab, pVgui)
surface.CreateFont("PHE.TitleFont",
{
font = "Roboto",
size = 40,
weight = 700,
antialias = true,
shadow = true
})
local panel = vgui.Create("DPanel", tab)
panel:SetBackgroundColor(Color(40,40,40,120))
local scroll = vgui.Create( "DScrollPanel", panel )
scroll:Dock(FILL)
local grid = vgui.Create("DGrid", scroll)
grid:Dock(NODOCK)
grid:SetPos(10,10)
grid:SetCols(1)
grid:SetColWide(800)
grid:SetRowHeight(50)
local label = {
title = "Prop Hunt: Enhanced",
author = "Enhanced by: Wolvindra-Vinzuerio & D4UNKN0WNM4N.",
version = GAMEMODE._VERSION,
rev = GAMEMODE.REVISION,
credits = "Yam, Godfather, adk, Lucas2107, Jonpopnycorn, Thundernerd",
lgit = "https://github.com/Vinzuerio/ph-enhanced/",
lhome = "https://prophunt.wolvindra.net/",
ldonate = GAMEMODE.DONATEURL,
lwiki = "https://prophunt.wolvindra.net/?go=phe_faq",
lklog = "https://prophunt.wolvindra.net/?go=changelog",
lplugins = "https://prophunt.wolvindra.net/?go=plugins"
}
pVgui("","label","PHE.TitleFont",grid, label.title )
pVgui("","label","Trebuchet24",grid, "Current Version: "..label.version.." | Current Revision: "..label.rev)
pVgui("","label","Trebuchet24",grid, "If you are enjoyed with the gamemode, Please support by Donating!" )
pVgui("spacer0","spacer",nil,grid,"" )
pVgui("","label",false,grid, "Changelog & Updates" )
pVgui("","btn",{max = 2,textdata = {
[1] = {"See Changelog", function() gui.OpenURL(label.lklog); tab:GetParent():Close() end},
[2] = {"Check for Updates",
function()
LocalPlayer():ConCommand("ph_check_update")
Derma_Message("Check on your console by pressing [~] or F10 key!","Checking Updates","OK, Got it!")
end},
}},grid,"")
pVgui("spacer1","spacer",nil,grid,"" )
pVgui("","label",false,grid, "Helpful External Links & Credits" )
pVgui("","btn",{max = 4,textdata = {
[1] = {"DONATE to PH:E Project", function() gui.OpenURL(label.ldonate) end},
[2] = {"PH:E Official Homepage", function() gui.OpenURL(label.lhome) end},
[3] = {"GitHub Repository", function() gui.OpenURL(label.lgit) end},
[4] = {"PH:E Manuals & Wiki", function() gui.OpenURL(label.lwiki) end},
[4] = {"PH:E Addons/Plugins", function() gui.OpenURL(label.lplugins) end}
}},grid,"")
pVgui("spacer1","spacer",nil,grid,"" )
pVgui("","label","Trebuchet24",grid, "Special Thanks for the support, suggestion & contributing:\n"..label.credits )
tab:AddSheet("About & Credits",panel,"icon16/information.png")
end)

View File

@@ -0,0 +1,265 @@
surface.CreateFont("PHE.HealthFont",
{
font = "Roboto",
size = 56,
weight = 650,
antialias = true,
shadow = true
})
surface.CreateFont("PHE.AmmoFont",
{
font = "Roboto",
size = 86,
weight = 500,
antialias = true,
shadow = true
})
surface.CreateFont("PHE.ArmorFont",
{
font = "Roboto",
size = 32,
weight = 500,
antialias = true,
shadow = true
})
surface.CreateFont("PHE.TopBarFont",
{
font = "Roboto",
size = 20,
weight = 500,
antialias = true,
shadow = true
})
surface.CreateFont("PHE.TopBarFontTeam",
{
font = "Roboto",
size = 60,
weight = 650,
antialias = true,
shadow = true
})
-- Hides HUD
local hide = {
["CHudHealth"] = true,
["CHudBattery"] = true,
["CHudAmmo"] = true,
["CHudSecondaryAmmo"] = true
}
hook.Add("HUDShouldDraw", "PHE.ShouldHideHUD", function(hudname)
if GetConVar("ph_hud_use_new"):GetBool() then
if (hide[hudname]) then return false end
end
end)
local curteam
local mat = {
[1] = Material("vgui/phehud/res_hp_1"),
[2] = Material("vgui/phehud/res_hp_2"),
}
local indic = {
rotate = { mat = Material("vgui/phehud/i_rotate"), [0] = Color(190,190,190,255), [1] = Color(255,255,0,255) },
halo = { mat = Material("vgui/phehud/i_halo"), [0] = Color(190,190,190,255), [1] = Color(0,255,0,255) },
light = { mat = Material("vgui/phehud/i_light"), [0] = Color(190,190,190,255), [1] = Color(255,255,0,255) },
armor = { mat = Material("vgui/phehud/i_shield"), [0] = Color(190,190,190,255), [1] = Color(80,190,255,255) }
}
local hudtopbar = {
mat = Material("vgui/phehud/hud_topbar"),
x = 0,
y = 60
}
local matw = Material("vgui/phehud/res_wep")
local ava
if (IsValid(ava)) then ava:Remove() ava = nil end
local pos = { x = 0, y = ScrH()-130 }
local posw = { x = ScrW() - 480, y = ScrH()-130 }
local hp
local armor
local hpcolor
local bar = {
hp = { h = 5, col = Color(250,40,10,240) },
am = { h = 5, col = Color(80,190,255,220) }
}
local Rstate = 0
net.Receive("PHE.rotateState", function() Rstate = net.ReadInt(2) end)
local function PopulateAliveTeam(tm)
local tim = team.GetPlayers(tm)
local liveply = liveply or 0
for _,pl in pairs(tim) do
if IsValid(pl) && pl:Alive() then liveply = liveply + 1 end
end
return liveply
end
local state = false
local disabledcolor = Color(100,100,100,255)
hook.Add("HUDPaint", "PHE.MainHUD", function()
if GetConVar("ph_hud_use_new"):GetBool() then state = true else state = false end;
if IsValid(LocalPlayer()) && LocalPlayer():Alive() && state && (LocalPlayer():Team() == TEAM_HUNTERS or LocalPlayer():Team() == TEAM_PROPS) then
-- Begin Player Info
if not IsValid(ava) then
ava = vgui.Create("AvatarMask")
ava:SetPos(16, pos.y+18)
ava:SetSize(86,86)
ava:SetPlayer(LocalPlayer(),128)
ava:SetVisible(true)
end
-- Player Info
curteam = LocalPlayer():Team()
hp = LocalPlayer():Health()
armor = LocalPlayer():Armor()
surface.SetDrawColor( 255, 255, 255, 255 )
surface.SetMaterial( mat[curteam] )
surface.DrawTexturedRect( pos.x, pos.y, 480, 120 )
draw.DrawText( "HEALTH", "Trebuchet24", pos.x + 175, pos.y + 14, color_white, TEXT_ALIGN_LEFT )
if hp < 0 then hp = 0 end
if armor < 0 then armor = 0 end
if hp < 30 then
hpcolor = Color( 255, 1 * (hp*8), 1 * (hp*8), 255 )
else
hpcolor = Color( 255, 255, 255, 255 )
end
-- hp bar
if hp > 100 then hpx = 100 else hpx = hp end
if armor > 100 then armx = 100 else armx = armor end
surface.SetDrawColor(bar.hp.col)
surface.DrawRect(pos.x + 175, pos.y + 57, 1*(hpx*2.9), bar.hp.h)
surface.SetDrawColor(bar.am.col)
surface.DrawRect(pos.x + 175, pos.y + 62, 1*(armx*2.9), bar.am.h)
draw.DrawText( hp, "PHE.HealthFont", pos.x + 350, pos.y - 4, hpcolor, TEXT_ALIGN_RIGHT )
draw.DrawText( " / "..armor, "PHE.ArmorFont", pos.x + 350, pos.y + 14, Color( 255,255,255,255 ), TEXT_ALIGN_LEFT )
if LocalPlayer():Team() == TEAM_HUNTERS then
surface.SetDrawColor(disabledcolor)
else
surface.SetDrawColor( indic.rotate[Rstate] )
end
surface.SetMaterial( indic.rotate.mat )
surface.DrawTexturedRect( pos.x + (168), pos.y + 74, 32, 32 )
if LocalPlayer():Team() == TEAM_HUNTERS then
surface.SetDrawColor(disabledcolor)
else
surface.SetDrawColor( indic.light[CL_GLOBAL_LIGHT_STATE] )
end
surface.SetMaterial( indic.light.mat )
surface.DrawTexturedRect( pos.x + (216), pos.y + 74, 32, 32 )
if LocalPlayer():Team() == TEAM_HUNTERS then
surface.SetDrawColor(disabledcolor)
else
surface.SetDrawColor( indic.halo[tonumber(GetConVar("ph_cl_halos"):GetInt())])
end
surface.SetMaterial( indic.halo.mat )
surface.DrawTexturedRect( pos.x + (264), pos.y + 74, 32, 32 )
if LocalPlayer():Armor() < 10 then
surface.SetDrawColor( indic.armor[0] )
else
surface.SetDrawColor( indic.armor[1] )
end
surface.SetMaterial( indic.armor.mat )
surface.DrawTexturedRect (pos.x + (312), pos.y + (2*37), 32, 32 )
end
-- Weapon HUD
if IsValid(LocalPlayer()) && LocalPlayer():Alive() && state && LocalPlayer():Team() == TEAM_HUNTERS then
surface.SetDrawColor( 255, 255, 255, 255 )
surface.SetMaterial( matw )
surface.DrawTexturedRect( posw.x, posw.y, 480, 120 )
local curWep = LocalPlayer():GetActiveWeapon()
local clip
local maxclip
local mag
local mag2
local name
local percent
draw.DrawText( "AMMO", "Trebuchet24", posw.x + (256), posw.y + 14, color_white, TEXT_ALIGN_LEFT )
if IsValid(curWep) then
clip = curWep:Clip1()
maxclip = curWep:GetMaxClip1()
mag = LocalPlayer():GetAmmoCount(curWep:GetPrimaryAmmoType())
mag2 = LocalPlayer():GetAmmoCount(curWep:GetSecondaryAmmoType())
name = language.GetPhrase(curWep:GetPrintName())
if clip < 0 then clip = 0 end
if maxclip < 0 then maxclip = 0 end
if (clip < 0 || maxclip < 0) then
percent = 0
else
percent = math.Round(clip / maxclip * 300)
end
surface.SetDrawColor(255,200,15,255)
surface.DrawRect(posw.x + 8, posw.y + 58, percent, 8)
draw.DrawText( clip, "PHE.HealthFont", posw.x + 136, posw.y -4, color_white, TEXT_ALIGN_RIGHT )
draw.DrawText( " / "..mag, "PHE.ArmorFont", posw.x + 136, posw.y + 14, color_white, TEXT_ALIGN_LEFT )
draw.DrawText( mag2, "PHE.AmmoFont", ScrW()-58, posw.y + 14, color_white, TEXT_ALIGN_CENTER )
draw.DrawText( name, "PHE.TopBarFont", posw.x + 136, posw.y + 80, color_white, TEXT_ALIGN_LEFT )
end
end
if IsValid(LocalPlayer()) && !LocalPlayer():Alive() then
if IsValid(ava) then
ava:SetVisible(false)
ava:Remove()
end
end
if IsValid(LocalPlayer()) && !state then
if IsValid(ava) then
ava:SetVisible(false)
ava:Remove()
end
end
if IsValid(LocalPlayer()) && (LocalPlayer():Team() == TEAM_SPECTATOR or LocalPlayer():Team() == TEAM_UNASSIGNED) then
if IsValid(ava) then
ava:SetVisible(false)
ava:Remove()
end
end
-- the Team Bar. This requires at least 4 players to get this displayed.
if GetConVar("ph_show_team_topbar"):GetBool() then
if ((player.GetCount() >= 4 && LocalPlayer():Alive()) && (LocalPlayer():Team() != TEAM_UNASSIGNED && LocalPlayer():Team() != TEAM_SPECTATOR)) then
surface.SetDrawColor( 255, 255, 255, 255 )
surface.SetMaterial( hudtopbar.mat )
surface.DrawTexturedRect( hudtopbar.x, hudtopbar.y, 400, 50 )
-- Draw Props
draw.DrawText( "Props", "PHE.TopBarFont", 4, hudtopbar.y + 2, Color(255,255,255,255), TEXT_ALIGN_LEFT )
draw.DrawText( tostring(PopulateAliveTeam(TEAM_PROPS)), "PHE.TopBarFontTeam", 96, hudtopbar.y - 8, Color(255,255,255,255), TEXT_ALIGN_LEFT )
-- Draw Hunters
draw.DrawText( "Hunter", "PHE.TopBarFont", 300, hudtopbar.y + 22, Color(255,255,255,255), TEXT_ALIGN_LEFT )
draw.DrawText( tostring(PopulateAliveTeam(TEAM_HUNTERS)), "PHE.TopBarFontTeam", 220, hudtopbar.y - 8, Color(255,255,255,255), TEXT_ALIGN_LEFT )
end
end
end)

View File

@@ -0,0 +1,83 @@
-- Credit goes to this topic:
-- https://gmod.facepunch.com/f/gmoddev/ngzz/Circle-avatars/1/
local function MakeCirclePoly( _x, _y, _r, _points )
local _u = ( _x + _r * 320 ) - _x;
local _v = ( _y + _r * 320 ) - _y;
local _slices = ( 2 * math.pi ) / _points;
local _poly = { };
for i = 0, _points - 1 do
local _angle = ( _slices * i ) % _points;
local x = _x + _r * math.cos( _angle );
local y = _y + _r * math.sin( _angle );
table.insert( _poly, { x = x, y = y, u = _u, v = _v } )
end
return _poly;
end
local PANEL = {}
function PANEL:Init()
self.Avatar = vgui.Create("AvatarImage", self)
self.Avatar:SetPaintedManually(true)
self.material = Material( "effects/flashlight001" )
self:OnSizeChanged(self:GetWide(), self:GetTall())
end
function PANEL:PerformLayout()
self:OnSizeChanged(self:GetWide(), self:GetTall())
end
function PANEL:SetSteamID(...)
self.Avatar:SetSteamID(...)
end
function PANEL:SetPlayer(...)
self.Avatar:SetPlayer(...)
end
function PANEL:OnSizeChanged(w, h)
self.Avatar:SetSize(self:GetWide(), self:GetTall())
self.points = math.Max((self:GetWide()/4), 32)
self.poly = MakeCirclePoly(self:GetWide()/2, self:GetTall()/2, self:GetWide()/2, self.points)
end
function PANEL:DrawMask(w, h)
draw.NoTexture();
surface.SetMaterial(self.material);
surface.SetDrawColor(color_white);
surface.DrawPoly(self.poly);
end
function PANEL:Paint(w, h)
render.ClearStencil()
render.SetStencilEnable(true)
render.SetStencilWriteMask(1)
render.SetStencilTestMask(1)
render.SetStencilFailOperation( STENCILOPERATION_REPLACE )
render.SetStencilPassOperation( STENCILOPERATION_ZERO )
render.SetStencilZFailOperation( STENCILOPERATION_ZERO )
render.SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_NEVER )
render.SetStencilReferenceValue( 1 )
self:DrawMask(w, h)
render.SetStencilFailOperation(STENCILOPERATION_ZERO)
render.SetStencilPassOperation(STENCILOPERATION_REPLACE)
render.SetStencilZFailOperation(STENCILOPERATION_ZERO)
render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL)
render.SetStencilReferenceValue(1)
self.Avatar:SetPaintedManually(false)
self.Avatar:PaintManual()
self.Avatar:SetPaintedManually(true)
render.SetStencilEnable(false)
render.ClearStencil()
end
vgui.Register("AvatarMask", PANEL)

View File

@@ -0,0 +1,461 @@
CreateClientConVar("ph_cl_halos", "1", true, true, "Toggle Enable/Disable Halo effects when choosing a prop.")
CreateClientConVar("ph_cl_pltext", "1", true, false, "Options for Text above players. 0 = Disable. 1 = Enable.")
CreateClientConVar("ph_cl_endround_sound", "1", true, false, "Play a sound when round ends? 0 to disable.")
CreateClientConVar("ph_cl_autoclose_taunt", "1", true, false, "Auto close the taunt window (When Double Clicking on them)?")
CreateClientConVar("ph_cl_spec_hunter_line", "1", true, false, "Draw a line on hunters so we can see their aim in spectator mode.")
CreateClientConVar("cl_enable_luckyballs_icon", "1", true,false, "Enable 'Lucky ball' icon to be displayed once they spawned")
CreateClientConVar("cl_enable_devilballs_icon", "1", true,false, "Enable 'Devil ball' icon to be displayed once they spawned")
CreateClientConVar("ph_hud_use_new", "1", true, false, "Use new PH: Enhanced HUD")
CreateClientConVar("ph_show_team_topbar", "1", true, false, "Show total alive team players bar on the top left (Experimental)")
CreateClientConVar("ph_show_custom_crosshair","1",true,false,"Show custom crosshair for props")
CreateClientConVar("ph_show_tutor_control","1",true,false,"Show 'Prop Gameplay Control' hud on each prop spawns. This only show twice and reset until map changes/user disconnect.")
surface.CreateFont( "HunterBlindLockFont",
{
font = "Arial",
size = 14,
weight = 1200,
antialias = true,
underline = false
})
surface.CreateFont("TrebuchetBig", {
font = "Impact",
size = 40
})
include("sh_init.lua")
include("sh_config.lua")
CL_GLOBAL_LIGHT_STATE = 0
include("cl_hud_mask.lua")
include("cl_hud.lua")
include("cl_menu.lua")
include("cl_tauntwindow.lua")
include("cl_targetid.lua")
include("cl_autotaunt.lua")
include("cl_credits.lua")
-- Called immediately after starting the gamemode
function Initialize()
cHullz = 64
client_prop_light = false
blind = false
CL_GLIMPCAM = 0
MAT_LASERDOT = Material("sprites/glow04_noz")
end
hook.Add("Initialize", "PH_Initialize", Initialize)
-- Decides where the player view should be (forces third person for props)
function GM:CalcView(pl, origin, angles, fov)
local view = {}
if blind then
view.origin = Vector(20000, 0, 0)
view.angles = Angle(0, 0, 0)
view.fov = fov
return view
end
view.origin = origin
view.angles = angles
view.fov = fov
-- Give the active weapon a go at changing the viewmodel position
if pl:Team() == TEAM_PROPS && pl:Alive() then
if GetConVar("ph_prop_camera_collisions"):GetBool() then
local trace = {}
local filterent = ents.FindByClass("ph_prop")
table.insert(filterent, pl)
if cHullz < 24 then
trace.start = origin + Vector(0, 0, cHullz + (24-cHullz))
trace.endpos = origin + Vector(0, 0, cHullz + (24-cHullz)) + (angles:Forward() * -80)
elseif cHullz > 84 then
trace.start = origin + Vector(0, 0, cHullz - 84)
trace.endpos = origin + Vector(0, 0, cHullz - 84) + (angles:Forward() * -80)
else
trace.start = origin + Vector(0, 0, 8)
trace.endpos = origin + Vector(0, 0, 8) + (angles:Forward() * -80)
end
trace.filter = filterent
local tr = util.TraceLine(trace)
view.origin = tr.HitPos
else
if cHullz < 24 then
view.origin = origin + Vector(0, 0, cHullz + (24-cHullz)) + (angles:Forward() * -80)
elseif cHullz > 84 then
view.origin = origin + Vector(0, 0, cHullz - 84) + (angles:Forward() * -80)
else
view.origin = origin + Vector(0, 0, 8) + (angles:Forward() * -80)
end
end
elseif pl:Team() == TEAM_HUNTERS && pl:Alive() then
local wep = pl:GetActiveWeapon()
if wep && wep != NULL then
local func = wep.GetViewModelPosition
if func then
view.vm_origin, view.vm_angles = func(wep, origin*1, angles*1)
end
local func = wep.CalcView
if func then
view.origin, view.angles, view.fov = func(wep, pl, origin*1, angles*1, fov)
end
end
-- hunter glimpse of thirdperson
if CL_GLIMPCAM > CurTime() then
local trace = {}
trace.start = origin
trace.endpos = origin + (angles:Forward() * -80)
trace.filter = player.GetAll()
trace.maxs = Vector(4, 4, 4)
trace.mins = Vector(-4, -4, -4)
local tr = util.TraceHull(trace)
view.drawviewer = true
view.origin = tr.HitPos
end
end
return view
end
local mat = "prophunt_enhanced/sprites/luckyball"
local pointer = "prophunt_enhanced/sprites/luckyball_pointer"
local dmat = "prophunt_enhanced/sprites/devilball"
local dpointer = "prophunt_enhanced/sprites/devilball_pointer"
local crosshair = Material("vgui/hud_crosshair")
-- Draw round timeleft and hunter release timeleft
function HUDPaint()
-- Draw player texts
if GetConVar("ph_enable_plnames"):GetBool() && GetConVar("ph_cl_pltext"):GetBool() && LocalPlayer():Team() != TEAM_SPECTATOR then
for _, pl in pairs(player.GetAll()) do
if pl != LocalPlayer() && (pl && pl:IsValid() && pl:Alive() && pl:Team() == LocalPlayer():Team()) then
local addvector = Vector(0, 0, math.Clamp(pl:EyePos():Distance(LocalPlayer():EyePos())*0.04, 16, 64))
-- todo: text will disappear in a specified distance.
draw.DrawText(pl:Name().." ("..pl:Health().."%)", "TargetIDSmall", (pl:EyePos() + addvector):ToScreen().x, (pl:EyePos() + addvector):ToScreen().y, team.GetColor(pl:Team()), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER)
end
end
end
-- Hunter Blindlock Time
if GetGlobalBool("InRound", false) then
local blindlock_time_left = (GetConVarNumber("ph_hunter_blindlock_time") - (CurTime() - GetGlobalFloat("RoundStartTime", 0))) + 1
if blindlock_time_left < 1 && blindlock_time_left > -6 then
blindlock_time_left_msg = "Ready or not, here we come!"
elseif blindlock_time_left > 0 then
blindlock_time_left_msg = "Hunters will be unblinded and released in "..string.ToMinutesSeconds(blindlock_time_left)
else
blindlock_time_left_msg = nil
end
if blindlock_time_left_msg then
surface.SetFont("HunterBlindLockFont")
local tw, th = surface.GetTextSize(blindlock_time_left_msg)
draw.RoundedBox(8, 20, 20, tw + 20, 26, Color(0, 0, 0, 75))
draw.DrawText(blindlock_time_left_msg, "HunterBlindLockFont", 31, 26, Color(255, 255, 0, 255), TEXT_ALIGN_LEFT)
end
end
-- Draw Lucky Balls Icon
if GetConVar("cl_enable_luckyballs_icon"):GetBool() && LocalPlayer():Team() == TEAM_HUNTERS then
local offset = Vector( 0, 0, 45 )
local ang = LocalPlayer():EyeAngles()
local w = ScrW()
local h = ScrH()
local cX = w/2
local cY = h/2
for _,ent in pairs(ents.FindByClass('ph_luckyball')) do
local pos = ent:GetPos() + offset
local poscr = pos:ToScreen()
if LocalPlayer():IsLineOfSightClear(ent) then
if ((poscr.x > 32 && poscr.x < (w-43)) && (poscr.y > 32 && poscr.y < (h-38))) then
surface.SetDrawColor(255,255,255,255)
surface.SetTexture(surface.GetTextureID(mat))
surface.DrawTexturedRect( poscr.x-32, poscr.y, 64, 64 )
else
local r = math.Round(cX/2)
local rad = math.atan2(poscr.y-cY, poscr.x-cX)
local deg = 0 - math.Round(math.deg(rad))
surface.SetDrawColor(255,255,255,255)
surface.SetTexture(surface.GetTextureID(pointer))
surface.DrawTexturedRectRotated(math.cos(rad)*r+cX, math.sin(rad)*r+cY,64,64,deg+90)
end
end
end
end
-- Draw Devil Ball Icon
if GetConVar("cl_enable_devilballs_icon"):GetBool() && LocalPlayer():Team() == TEAM_PROPS then
local offset = Vector( 0, 0, 35 )
local ang = LocalPlayer():EyeAngles()
local w = ScrW()
local h = ScrH()
local cX = w/2
local cY = h/2
for _,ent in pairs(ents.FindByClass('ph_devilball')) do
local pos = ent:GetPos() + offset
local poscr = pos:ToScreen()
if LocalPlayer():IsLineOfSightClear(ent) then
if ((poscr.x > 32 && poscr.x < (w-43)) && (poscr.y > 32 && poscr.y < (h-38))) then
surface.SetDrawColor(255,255,255,255)
surface.SetTexture(surface.GetTextureID(dmat))
surface.DrawTexturedRect( poscr.x-32, poscr.y, 64, 64 )
else
local r = math.Round(cX/2)
local rad = math.atan2(poscr.y-cY, poscr.x-cX)
local deg = 0 - math.Round(math.deg(rad))
surface.SetDrawColor(255,255,255,255)
surface.SetTexture(surface.GetTextureID(dpointer))
surface.DrawTexturedRectRotated(math.cos(rad)*r+cX, math.sin(rad)*r+cY,64,64,deg+90)
end
end
end
end
-- Prop Crosshair
if GetConVar("ph_show_custom_crosshair"):GetBool() && LocalPlayer():Team() == TEAM_PROPS && LocalPlayer():Alive() then
local color
local trace = {}
if cHullz < 24 then
trace.start = LocalPlayer():EyePos() + Vector(0, 0, cHullz + (24-cHullz))
trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, cHullz + (24-cHullz)) + LocalPlayer():EyeAngles():Forward() * 100
elseif cHullz > 84 then
trace.start = LocalPlayer():EyePos() + Vector(0, 0, cHullz - 84)
trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, cHullz - 84) + LocalPlayer():EyeAngles():Forward() * 300
else
trace.start = LocalPlayer():EyePos() + Vector(0, 0, 8)
trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, 8) + LocalPlayer():EyeAngles():Forward() * 100
end
trace.filter = ents.FindByClass("ph_prop")
local trace2 = util.TraceLine(trace)
if trace2.Entity && trace2.Entity:IsValid() && table.HasValue(PHE.USABLE_PROP_ENTITIES, trace2.Entity:GetClass()) then
color = Color(10,255,10,255)
else
color = Color(255,255,255,255)
end
surface.SetDrawColor( color )
surface.SetMaterial( crosshair )
surface.DrawTexturedRect( ScrW() / 2 - ( 64 / 2 ), ScrH() / 2 - ( 64 / 2 ), 64, 64 )
end
-- The 'You were Killed By' text, or the Freeze Cam text.
if LocalPlayer():GetNWBool("InFreezeCam", false) then
local w1, h1 = surface.GetTextSize("You were killed by "..LocalPlayer():GetNWEntity("PlayerKilledByPlayerEntity", nil):Name() );
local textx = ScrW()/2
local steamx = (ScrW()/2) - 32
draw.SimpleTextOutlined("You were killed by "..LocalPlayer():GetNWEntity("PlayerKilledByPlayerEntity", nil):Name(), "TrebuchetBig", textx, ScrH()*0.75, Color(255, 10, 10, 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER, 1.5, Color(0, 0, 0, 255))
end
end
hook.Add("HUDPaint", "PH_HUDPaint", HUDPaint)
-- After the player has been drawn
function PH_PostPlayerDraw(pl)
-- Draw a line on hunters
if GetConVar("ph_cl_spec_hunter_line"):GetBool() && (!LocalPlayer():Alive() || LocalPlayer():Team() == TEAM_SPECTATOR) then
if IsValid(pl) && pl:Alive() && pl:Team() == TEAM_HUNTERS then
render.DrawLine(pl:GetShootPos(), pl:GetEyeTrace().HitPos, team.GetColor(pl:Team()), true)
render.SetMaterial(MAT_LASERDOT)
render.DrawSprite(pl:GetEyeTrace().HitPos, 8, 8, team.GetColor(pl:Team()))
end
end
end
hook.Add("PostPlayerDraw", "PH_PostPlayerDraw", PH_PostPlayerDraw)
hook.Add("PrePlayerDraw", "PHE.HidePlayer", function(ply)
if ply:Team() == TEAM_PROPS then return true end
end)
-- Draws halos on team members
function PHEDrawPropselectHalos()
if GetConVar("ph_cl_halos"):GetBool() then
-- Something to tell if the prop is selectable
if LocalPlayer():Team() == TEAM_PROPS && LocalPlayer():Alive() then
local trace = {}
-- fix for smaller prop size. They should stay horizontal rather than looking straight down.
if cHullz < 24 then
trace.start = LocalPlayer():EyePos() + Vector(0, 0, cHullz + (24-cHullz))
trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, cHullz + (24-cHullz)) + LocalPlayer():EyeAngles():Forward() * 100
elseif cHullz > 84 then
trace.start = LocalPlayer():EyePos() + Vector(0, 0, cHullz - 84)
trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, cHullz - 84) + LocalPlayer():EyeAngles():Forward() * 300
else
trace.start = LocalPlayer():EyePos() + Vector(0, 0, 8)
trace.endpos = LocalPlayer():EyePos() + Vector(0, 0, 8) + LocalPlayer():EyeAngles():Forward() * 100
end
trace.filter = ents.FindByClass("ph_prop")
local trace2 = util.TraceLine(trace)
if trace2.Entity && trace2.Entity:IsValid() && table.HasValue(PHE.USABLE_PROP_ENTITIES, trace2.Entity:GetClass()) then
local ent_table = {}
table.insert(ent_table, trace2.Entity)
halo.Add(ent_table, Color(20, 250, 0), 1.2, 1.2, 1, true, true)
end
end
end
end
hook.Add("PreDrawHalos", "PHEDrawPropselectHalos", PHEDrawPropselectHalos)
-- Play random taunt
hook.Add("KeyPress", "tracetest.GetPropInfo", function(pl, key)
if ((pl:Team() == TEAM_PROPS && pl:Alive()) && key == IN_ATTACK2) then
LocalPlayer():ConCommand("gm_showspare1")
end
end)
-- Called every client frame
function GM:Think()
-- Prop light
if client_prop_light && LocalPlayer() && LocalPlayer():IsValid() && LocalPlayer():Alive() && LocalPlayer():Team() == TEAM_PROPS then
local prop_light = DynamicLight(LocalPlayer():EntIndex())
if prop_light then
prop_light.pos = LocalPlayer():GetPos()
prop_light.r = 255
prop_light.g = 255
prop_light.b = 255
prop_light.brightness = 0.25
prop_light.decay = 1
prop_light.size = 180
prop_light.dietime = CurTime() + 0.1
end
end
end
-- ///////////////////\\\\\\\\\\\\\\\\\ --
-- Net Receives Hooks --
-- ///////////////////\\\\\\\\\\\\\\\\\ --
local tutormat = "vgui/hud_control_help.png"
local curshow = 0
net.Receive("PH_ShowTutor", function()
if GetConVar("ph_show_tutor_control"):GetBool() && LocalPlayer():Alive() then
if curshow <= 2 then
local xNotify = vgui.Create( "DNotify" )
xNotify:SetPos( ScrW() - 300 , 60 )
xNotify:SetSize( 256, 256 )
xNotify:SetLife(12)
local bg = vgui.Create( "DPanel", xNotify )
bg:Dock( FILL )
bg:SetBackgroundColor( Color( 16, 16, 16, 180 ) )
local image = vgui.Create( "DImage", bg )
image:SetImage(tutormat)
image:Dock(FILL)
xNotify:AddItem(bg)
curshow = curshow + 1
end
end
end)
-- Receive the Winning Notification
net.Receive("PH_RoundDraw_Snd", function(len)
if GetConVar("ph_cl_endround_sound"):GetBool() then
surface.PlaySound(table.Random(PHE.WINNINGSOUNDS["Draw"]))
end
end)
net.Receive("PH_TeamWinning_Snd", function(len)
local snd = net.ReadString()
if GetConVar("ph_cl_endround_sound"):GetBool() then
surface.PlaySound(snd)
end
end)
-- Resets the player hull
net.Receive("ResetHull", function()
if LocalPlayer() && LocalPlayer():IsValid() then
LocalPlayer():ResetHull()
cHullz = 64
end
end)
-- Sets the local blind variable to be used in CalcView
net.Receive("SetBlind", function()
blind = net.ReadBool()
end)
--[[ Here you can add more than 2 additional freeze cam sounds.
You can add more sounds by using table.insert(PHE.FreezeCamSnd, <path file>) repeatedly outside of this code scope.
Example:
table.insert(PHE.FreezeCamSnd, "vo/k_lab/kl_fiddlesticks.wav")
table.insert(PHE.FreezeCamSnd, "vo/k_lab/kl_ohdear.wav")
...more ]]
-- If you wish to use a single sound instead, use ph_fc_use_single_sound 1 & ph_fc_cue_path "<path/sound/file.wav>" convar to override.
PHE.FreezeCamSnd = {
-- do not manually add sounds in here, which this may break the sound list. Use table.insert instead!
"misc/freeze_cam.wav",
"misc/freeze_cam_sad1.wav"
}
-- Plays the Freeze Cam sound
net.Receive("PlayFreezeCamSound", function()
if GetConVar("ph_fc_use_single_sound"):GetBool() then
surface.PlaySound(GetConVar("ph_fc_cue_path"):GetString())
else
surface.PlaySound(table.Random(PHE.FreezeCamSnd))
end
end)
-- Sets the player hull
net.Receive("SetHull", function()
local hullxy = net.ReadInt(32)
local huz = net.ReadInt(32)
local hulldz = net.ReadInt(32)
local new_health = net.ReadInt(9)
cHullz = huz
LocalPlayer():SetHull(Vector(hullxy * -1, hullxy * -1, 0), Vector(hullxy, hullxy, huz))
LocalPlayer():SetHullDuck(Vector(hullxy * -1, hullxy * -1, 0), Vector(hullxy, hullxy, hulldz))
LocalPlayer():SetHealth(new_health)
end)
-- Replaces the flashlight with a client-side dynamic light for props
net.Receive("PlayerSwitchDynamicLight", function()
if client_prop_light then
client_prop_light = false
surface.PlaySound("prop_idbs/light_off1.wav")
CL_GLOBAL_LIGHT_STATE = 0
else
client_prop_light = true
surface.PlaySound("prop_idbs/light_on.wav")
CL_GLOBAL_LIGHT_STATE = 1
end
end)
-- Turns the dynamic light OFF
net.Receive("DisableDynamicLight", function()
if client_prop_light then
client_prop_light = false
end
end)

View File

@@ -0,0 +1,646 @@
local Ph = {}
function ph_BaseMainWindow(ply, cmd, args)
local mdlName = ply:GetInfo("cl_playermodel")
local mdlPath = player_manager.TranslatePlayerModel(mdlName)
local frm = vgui.Create("DFrame")
frm:SetSize(ScrW()-96,ScrH()-64)
frm:SetTitle("Prop Hunt: Enhanced | Help & Settings menu")
frm.Paint = function(self,w,h)
surface.SetDrawColor(30,30,30,180)
surface.DrawRect(0,0,w,h)
end
frm:SetDraggable(false)
frm:Center()
frm:MakePopup()
local tab = vgui.Create("DPropertySheet", frm)
tab:Dock(FILL)
tab:DockMargin(12,12,12,12)
tab.Paint = function(self)
surface.SetDrawColor(50,50,50,255)
surface.DrawRect(0,0,self:GetWide(),self:GetTall())
end
function Ph:GetMutedStateIcon(bool)
if bool then
return "vgui/phehud/voice_off"
end
return "vgui/phehud/voice_on"
end
function Ph:CreateBasicLayout(color,pTab) -- Warning: This one only can be used within this scope! todo: See 'cl_credits.lua' to see some details.
local panel = vgui.Create("DPanel", pTab)
panel:SetBackgroundColor(color)
local scroll = vgui.Create( "DScrollPanel", panel )
scroll:Dock(FILL)
local grid = vgui.Create("DGrid", scroll)
grid:Dock(NODOCK)
grid:SetPos(10,10)
grid:SetCols(1)
grid:SetColWide(800)
grid:SetRowHeight(32)
return panel,grid
end
-- Base Function for Automated-VGUI Creation. I've Spent 8 Hours to do this with laptop keep autoshutdowns... Damn it
-- Usage of Ph:CreateVGUIType(cmd,typ,data,panel,text)
-- typ: check, label, btn, slider
function Ph:CreateVGUIType(cmd,typ,data,panel,text)
-- CheckBox
if typ == "check" then
if type(data) == "string" then
local chk = vgui.Create("DCheckBoxLabel")
chk:SetSize(panel:GetColWide(),panel:GetRowHeight())
chk:SetText(text)
local num = GetConVar(cmd):GetBool()
if num then
chk:SetChecked(true); chk:SetValue(1);
else
chk:SetChecked(false); chk:SetValue(0);
end
function chk:OnChange(bool)
local v = 0
if bool then
v = 1
else
v = 0
end
if data == "SERVER" then
net.Start("SvCommandReq")
net.WriteString(cmd)
net.WriteInt(v,2)
net.SendToServer()
elseif data == "CLIENT" then
RunConsoleCommand(cmd, v)
chat.AddText(Color(200,0,0),"[Settings]", color_white, " Cvar '"..cmd.."' has been changed to "..v)
if v == 1 then
surface.PlaySound("buttons/button9.wav")
else
surface.PlaySound("buttons/button19.wav")
end
end
end
panel:AddItem(chk)
else
print(cmd.." -> Ph:CreateVGUIType FAILED! - 'data' argument must containt string value, Got: "..type(data).." instead!!")
end
end
-- Label
if typ == "label" then
local txt = vgui.Create("DLabel")
txt:SetSize(panel:GetColWide(),panel:GetRowHeight())
txt:SetText(text)
if !data then
txt:SetFont("HudHintTextLarge")
else
txt:SetFont(data)
end
txt:SetTextColor(color_white)
panel:AddItem(txt)
end
-- Spacer/Divider
if typ == "spacer" then
local pnl = vgui.Create("DPanel")
pnl:SetSize(panel:GetColWide(),panel:GetRowHeight())
pnl:SetBackgroundColor(Color(0,0,0,0))
panel:AddItem(pnl)
end
-- Button
if typ == "btn" then
if type(data) == "table" then
-- How many buttons that will be created. Note: maximum are 6 buttons in 1 segment.
local legal = data.max
if data.max < 1 then legal = 1 end
if data.max > 6 then legal = 6 end
local pnl = vgui.Create("DPanel")
pnl:SetSize(panel:GetColWide(),panel:GetRowHeight())
pnl:SetBackgroundColor(Color(0,0,0,0))
local function btncreation(pPanel,pText, f)
local btn = vgui.Create("DButton", pPanel)
btn:SetText(pText)
btn:Dock(LEFT)
btn:DockMargin(8,2,0,2)
-- If this looks stupid, but it working, it ain't stupid!
btn:SizeToContents()
btn:SetSize(btn:GetWide()+8,btn:GetTall())
btn.DoClick = f
end
for i=1,legal do
btncreation(pnl,data.textdata[i][1], data.textdata[i][2])
end
panel:AddItem(pnl)
else
print(cmd.." -> Ph:CreateVGUIType FAILED! - 'data' argument must containt table value, Example:\n\n { max = max_num_button, textdata = {[1] = {text, function}, [2] = {text, function}, etc...}} \n --> Got "..type(data).." instead!!")
end
end
-- Slider
if typ == "slider" then
if type(data) == "table" then
local min = data.min
local max = data.max
local dval = data.init
local dec = data.dec
local kind = data.kind
local float = data.float
local pnl = vgui.Create("DPanel")
pnl:SetSize(panel:GetColWide(),panel:GetRowHeight()-6)
pnl:SetBackgroundColor(Color(120,120,120,200))
local slider = vgui.Create("DNumSlider",pnl)
slider:SetPos(10,0)
slider:SetSize(panel:GetColWide()-30,panel:GetRowHeight()-6)
slider:SetText(text)
slider:SetMin(min)
slider:SetMax(max)
slider:SetValue(dval)
slider:SetDecimals(dec)
slider.OnValueChanged = function(pnl,val)
slider:SetValue(val)
if kind == "SERVER" then
net.Start("SvCommandSliderReq")
net.WriteString(cmd)
net.WriteBool(float)
if float then
net.WriteFloat(val)
else
net.WriteInt(slider:GetValue(), 16)
end
net.SendToServer()
elseif kind == "CLIENT" then
if float then
RunConsoleCommand(cmd, val)
else
RunConsoleCommand(cmd, math.Round(val))
end
end
end
panel:AddItem(pnl)
else
print(cmd.." -> Ph:CreateVGUIType FAILED! - 'data' argument must containt table value, Example:\n\n { min = min value, max = max value, init = initial value, dec = decimal count, kind = SERVER/CLIENT} } \n --> Got "..type(data).." instead!!")
end
end
-- Mute Functions
if typ == "mute" then
if type(data) == "Player" && IsValid(data) then
local ply = data
local pnl = vgui.Create("DPanel")
pnl:SetSize(panel:GetColWide(),panel:GetRowHeight()-6)
pnl:SetBackgroundColor(Color(20,20,20,150))
local ava = vgui.Create("AvatarImage", pnl)
ava:Dock(LEFT)
ava:SetSize(24,24)
ava:SetPlayer(ply,32)
local name = vgui.Create("DLabel", pnl)
name:Dock(LEFT)
name:DockMargin(8,4,8,4)
name:SetSize(panel:GetColWide()/2,0)
name:SetText(ply:Nick())
name:SetFont("HudHintTextLarge")
name:SetTextColor(color_white)
local imagebtn
local button = vgui.Create("DButton", pnl)
button:Dock(RIGHT)
button:DockMargin(4,0,4,0)
button:SetSize(24,0)
button:SetText("")
button.Paint = function(btn)
surface.SetDrawColor(90,90,90,0)
surface.DrawRect(0,0,btn:GetWide(),btn:GetTall())
end
button.DoClick = function()
if not IsValid(ply) then return end
local mute = ply:IsMuted()
ply:SetMuted(not mute)
imagebtn:SetImage(Ph:GetMutedStateIcon(not mute))
end
if ply == LocalPlayer() then
button:SetVisible(false)
else
button:SetVisible(true)
end
imagebtn = vgui.Create("DImage",button)
imagebtn:Dock(FILL)
imagebtn:SetImage(Ph:GetMutedStateIcon(ply:IsMuted()))
panel:AddItem(pnl)
else
print(cmd.." -> Ph:CreateVGUIType FAILED! - 'data' argument must containt Entity userdata value \n --> Got "..type(data).." instead!!")
end
end
end
function Ph:HelpSelections()
local panel = vgui.Create("DPanel", tab)
panel:SetBackgroundColor(Color(100,100,100,255))
local helpImage = vgui.Create("DImage", panel)
helpImage.Count = 1
helpImage:Dock(FILL)
helpImage:SetImage("vgui/phhelp1.vmt")
local pBottom = vgui.Create("DPanel", panel)
pBottom:Dock(BOTTOM)
pBottom:SetSize(0,40)
pBottom:SetBackgroundColor(Color(0,0,0,0))
local motd = vgui.Create("DButton", pBottom)
motd:Dock(FILL)
motd:SetSize(0,40)
motd:SetText("SERVER INFORMATION & RULES [MOTD]")
motd:SetFont("PHE.ArmorFont")
motd:SetTextColor(color_white)
motd.hover = {r=55,g=55,b=55}
motd.Paint = function(pnl)
if pnl:IsHovered() then
pnl.hover = {r=70,g=70,b=70}
else
pnl.hover = {r=55,g=55,b=55}
end
surface.SetDrawColor(pnl.hover.r,pnl.hover.g,pnl.hover.b,255)
surface.DrawRect(0,0,motd:GetWide(),motd:GetTall())
end
motd.DoClick = function() ply:ConCommand("ulx motd"); frm:Close() end
local bnext = vgui.Create("DButton", pBottom)
bnext:Dock(RIGHT)
bnext:SetSize(128,40)
bnext:SetText("NEXT >")
bnext:SetFont("HudHintTextLarge")
bnext:SetTextColor(color_white)
bnext.hover = {r=100,g=100,b=100}
bnext.Paint = function(pnl)
if pnl:IsHovered() then
pnl.hover = {r=130,g=130,b=130}
pnl:SetTextColor(color_white)
elseif pnl:GetDisabled() then
pnl.hover = {r=20,g=20,b=20}
pnl:SetTextColor(Color(40,40,40))
else
pnl.hover = {r=100,g=100,b=100}
pnl:SetTextColor(color_white)
end
surface.SetDrawColor(pnl.hover.r,pnl.hover.g,pnl.hover.b,255)
surface.DrawRect(0,0,motd:GetWide(),motd:GetTall())
end
bnext.DoClick = function(pnl)
helpImage.Count = helpImage.Count + 1
if helpImage.Count >= 6 then
helpImage.Count = 6
end
helpImage:SetImage("vgui/phhelp"..helpImage.Count..".vmt")
end
local bprev = vgui.Create("DButton", pBottom)
bprev:Dock(LEFT)
bprev:SetSize(128,40)
bprev:SetText("< PREVIOUS")
bprev:SetFont("HudHintTextLarge")
bprev:SetTextColor(color_white)
bprev.hover = {r=100,g=100,b=100}
bprev.Paint = function(pnl)
if pnl:IsHovered() then
pnl.hover = {r=130,g=130,b=130}
pnl:SetTextColor(color_white)
elseif pnl:GetDisabled() then
pnl.hover = {r=20,g=20,b=20}
pnl:SetTextColor(Color(40,40,40))
else
pnl.hover = {r=100,g=100,b=100}
pnl:SetTextColor(color_white)
end
surface.SetDrawColor(pnl.hover.r,pnl.hover.g,pnl.hover.b,255)
surface.DrawRect(0,0,motd:GetWide(),motd:GetTall())
end
bprev.DoClick = function(pnl)
helpImage.Count = helpImage.Count - 1
if helpImage.Count <= 1 then
helpImage.Count = 1
end
helpImage:SetImage("vgui/phhelp"..helpImage.Count..".vmt")
end
tab:AddSheet("Help", panel, "icon16/help.png")
end
function Ph:PlayerModelSelections()
local panel = vgui.Create("DPanel", tab)
panel:SetBackgroundColor(Color(40,40,40,120))
-- Prefer had to do this instead doing all over and over.
function Ph:PlayerModelAdditions()
-- the Model's DPanel preview. The Pos & Size must be similar as the ModelPreview.
local panelpreview = vgui.Create( "DPanel", panel )
panelpreview:Dock(FILL)
panelpreview:SetBackgroundColor(Color(120,120,120,100))
-- Model Preview.
local modelPreview = vgui.Create( "DModelPanel", panelpreview )
modelPreview:Dock(FILL)
modelPreview:SetFOV ( 50 )
modelPreview:SetModel ( mdlPath )
local slider = vgui.Create("DNumSlider", panelpreview)
slider:Dock(BOTTOM)
slider:SetSize(0,32)
slider:SetText(" Set Model FOV")
slider:SetMin(50)
slider:SetMax(90)
slider:SetValue(40)
slider:SetDecimals(0)
slider.OnValueChanged = function(pnl,val)
slider:SetValue(val)
modelPreview:SetFOV(val)
end
local scroll = vgui.Create( "DScrollPanel", panel )
scroll:Dock(LEFT)
scroll:SetSize( 720, 0 )
-- ^dito, grid dimensions 66x66 w/ Coloumn 7.
local pnl = vgui.Create( "DGrid", scroll )
pnl:Dock(FILL)
pnl:SetCols( 10 )
pnl:SetColWide( 68 )
pnl:SetRowHeight( 68 )
local plMode = GetConVar("ph_use_playermodeltype"):GetInt()
local plWhich = {
[0] = player_manager.AllValidModels(),
[1] = list.Get("PlayerOptionsModel")
}
if plMode == nil then plWhich = 0 end
-- Get All Valid Paired Models and sort 'em out.
for name, model in SortedPairs( plWhich[plMode] ) do
-- dont forget to cache.
util.PrecacheModel(model)
local icon = vgui.Create( "SpawnIcon" )
-- Click functions
icon.DoClick = function()
surface.PlaySound( "buttons/combine_button3.wav" )
RunConsoleCommand( "cl_playermodel", name )
modelPreview:SetModel(model)
Derma_Query("Model " .. name.. " has been selected and it will be applied after respawn!", "Model Applied",
"OK", function() end)
end
-- Right click functions
icon.DoRightClick = function()
-- Same as above, but they has custom menus once user tries to right click on the models.
local menu = DermaMenu()
-- if user caught it says 'ERROR' but the model present, refresh it (:RebuildSpawnIcon)
menu:AddOption( "Apply Model", function()
surface.PlaySound( "buttons/combine_button3.wav" )
RunConsoleCommand( "cl_playermodel", name )
modelPreview:SetModel(model)
Derma_Query("Model " .. name.. " has been selected and it will be applied after respawn!", "Model Applied", "OK", function() end)
end):SetIcon("icon16/tick.png")
menu:AddSpacer()
menu:AddOption( "Refresh Icon", function() icon:RebuildSpawnIcon() end):SetIcon("icon16/arrow_refresh.png")
menu:AddOption( "Preview", function() modelPreview:SetModel(model) end):SetIcon("icon16/magnifier.png")
menu:AddOption( "Model Information", function()
Derma_Message( "Model's name is: " .. name .. "\n \nUsable by: Everyone.", "Model Info", "Close" )
end ):SetIcon("icon16/information.png")
menu:AddSpacer()
menu:AddOption( "Close" ):SetIcon("icon16/cross.png")
menu:Open()
end
-- Make sure the user has noticed after choosing a model by indicating from "Borders".
icon.PaintOver = function()
if ( GetConVarString( "cl_playermodel" ) == name ) then
surface.SetDrawColor( Color( 255, 210 + math.sin(RealTime()*10)*40, 0 ) )
surface.DrawOutlinedRect( 4, 4, icon:GetWide()-8, icon:GetTall()-8 )
surface.DrawOutlinedRect( 3, 3, icon:GetWide()-6, icon:GetTall()-6 )
end
end
-- Set set etc...
icon:SetModel(model)
icon:SetSize(64,64)
icon:SetTooltip(name)
pnl:AddItem(icon)
end
return pnl
end
-- Self Explanationary.
if GetConVar("ph_use_custom_plmodel"):GetBool() then
-- Call the VGUI Properties of PlayerModelAdditions().
Ph:PlayerModelAdditions()
tab:AddSheet("Player Model", panel, "icon16/brick.png")
else
-- Show small message instead
local scroll = vgui.Create( "DScrollPanel", panel )
scroll:Dock(FILL)
local gridmdl = vgui.Create("DGrid", scroll)
gridmdl:Dock(NODOCK)
gridmdl:SetPos(10,10)
gridmdl:SetCols(1)
gridmdl:SetColWide(800)
gridmdl:SetRowHeight(32)
Ph:CreateVGUIType("", "label", false, gridmdl, "Sorry, Custom Player Model is disabled on this server!")
-- this hook is intended to use for custom player model outside from PH:E Menu. (like Custom Donator Model window or something).
hook.Call("PH_CustomPlayermdlButton", nil, panel, gridmdl, function(cmd,typ,data,panel,text) Ph:CreateVGUIType(cmd,typ,data,panel,text) end)
tab:AddSheet("Player Model", panel, "icon16/brick.png")
end
end
function Ph:PlayerOption()
local panel,gridpl = Ph:CreateBasicLayout(Color(40,40,40,180),tab)
Ph:CreateVGUIType("", "label", false, gridpl, "Player Options:")
Ph:CreateVGUIType("ph_cl_halos", "check", "CLIENT", gridpl, "Toggle Halo effect when choosing a prop" )
Ph:CreateVGUIType("ph_cl_pltext", "check", "CLIENT", gridpl, "Show Team player names above their heads instead (and appear through wall too)")
Ph:CreateVGUIType("ph_cl_endround_sound", "check", "CLIENT", gridpl, "Play End round sound cue")
Ph:CreateVGUIType("ph_cl_autoclose_taunt", "check", "CLIENT", gridpl, "Option for Auto closing for Taunt window when double-clicking them")
Ph:CreateVGUIType("ph_cl_spec_hunter_line", "check", "CLIENT", gridpl, "Draw a line on hunters so we can see their aim in spectator mode.")
Ph:CreateVGUIType("cl_enable_luckyballs_icon", "check", "CLIENT", gridpl, "Enable 'Lucky ball' icon to be displayed once they are spawned")
Ph:CreateVGUIType("cl_enable_devilballs_icon", "check", "CLIENT", gridpl, "Enable 'Devil ball' icon to be displayed once they are spawned")
Ph:CreateVGUIType("hudspacer","spacer",nil,gridpl,"" )
Ph:CreateVGUIType("", "label", false, gridpl, "HUD Settings")
Ph:CreateVGUIType("ph_hud_use_new", "check", "CLIENT", gridpl, "Use New PH: Enhanced HUD")
Ph:CreateVGUIType("ph_show_tutor_control", "check", "CLIENT", gridpl, "Show Tutorial Pop-up (Shown only 2x on each prop spawns)")
Ph:CreateVGUIType("ph_show_custom_crosshair", "check", "CLIENT", gridpl, "Enable Custom Crosshair")
Ph:CreateVGUIType("ph_show_team_topbar", "check", "CLIENT", gridpl, "Show total alive team players bar on the top left (At least 4 Players will be shown)")
tab:AddSheet("Player", panel, "icon16/user_orange.png")
end
function Ph:PlayerMute()
local panel,gridmute = Ph:CreateBasicLayout(Color(40,40,40,180),tab)
Ph:CreateVGUIType("","label",false,gridmute,"Select one player that you wish to mute.")
for _,Plys in pairs(player.GetAll()) do
Ph:CreateVGUIType("","mute",Plys,gridmute,"")
end
tab:AddSheet("Mute", panel, "icon16/sound_delete.png")
end
-- Call All Functions, but Admin (must check by serverside user rights from sv_admin.lua)
Ph:HelpSelections()
Ph:PlayerMute()
Ph:PlayerOption()
Ph:PlayerModelSelections()
-- Custom Hook Menu here. Give 1 second for better safe-calling...
timer.Simple(1, function()
hook.Call("PH_CustomTabMenu", nil, tab, function(cmd,typ,data,panel,text) Ph:CreateVGUIType(cmd,typ,data,panel,text) end)
end)
function Ph:ShowAdminMenu()
local panel,grid = Ph:CreateBasicLayout(Color(40,40,40,180),tab)
Ph:CreateVGUIType("", "label", false, grid, "Serverside gamemode Options (Only visible for Admins/Owner)")
Ph:CreateVGUIType("ph_use_custom_plmodel", "check", "SERVER", grid, "Enable custom models for Hunters")
Ph:CreateVGUIType("ph_use_custom_plmodel_for_prop", "check", "SERVER", grid, "Enable custom models for Props - Make sure to enable for Hunter too.")
Ph:CreateVGUIType("ph_customtaunts_delay", "slider", {min = 2, max = 120, init = GetConVar("ph_customtaunts_delay"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Custom Taunts Delay (Seconds)")
Ph:CreateVGUIType("ph_normal_taunt_delay", "slider", {min = 2, max = 120, init = GetConVar("ph_normal_taunt_delay"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Normal Taunts Delay (Seconds)")
Ph:CreateVGUIType("ph_autotaunt_enabled", "check", "SERVER", grid, "Enable Auto Taunt Features")
Ph:CreateVGUIType("ph_autotaunt_delay", "slider", {min = 30, max = 180, init = GetConVar("ph_autotaunt_delay"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Auto Taunts Delay (Seconds)")
Ph:CreateVGUIType("devspacer","spacer",nil,grid,"" )
Ph:CreateVGUIType("ph_notice_prop_rotation", "check", "SERVER", grid, "Display 'Prop Rotation' notification on every Prop Spawns")
Ph:CreateVGUIType("ph_prop_camera_collisions", "check", "SERVER", grid, "Enable Prop Camera collision to the wall")
Ph:CreateVGUIType("ph_freezecam", "check", "SERVER", grid, "Enable Freecam features for team props")
Ph:CreateVGUIType("ph_prop_collision", "check", "SERVER", grid, "Enable Prop collide on each other prop players")
Ph:CreateVGUIType("ph_swap_teams_every_round", "check", "SERVER", grid, "Swap team every round - Disabling means team will stay forever")
Ph:CreateVGUIType("ph_hunter_fire_penalty", "slider", {min = 2, max = 80, init = GetConVar("ph_hunter_fire_penalty"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Hunter points penalty")
Ph:CreateVGUIType("ph_hunter_kill_bonus", "slider", {min = 5, max = 100, init = GetConVar("ph_hunter_kill_bonus"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Hunter kill bonus")
Ph:CreateVGUIType("ph_game_time", "slider", {min = 20, max = 300, init = GetConVar("ph_game_time"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Total Game time (Minutes)")
Ph:CreateVGUIType("ph_hunter_blindlock_time", "slider", {min = 15, max = 60, init = GetConVar("ph_hunter_blindlock_time"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Hunter blindlock time (Seconds)")
Ph:CreateVGUIType("ph_round_time", "slider", {min = 120, max = 600, init = GetConVar("ph_round_time"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Game round time (Seconds)")
Ph:CreateVGUIType("ph_rounds_per_map", "slider", {min = 5, max = 30, init = GetConVar("ph_rounds_per_map"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Total game Rounds per Map")
Ph:CreateVGUIType("ph_enable_lucky_balls", "check", "SERVER", grid, "Allow Lucky Balls Features to be spawned on breakable props (Chance is 8%)")
Ph:CreateVGUIType("ph_enable_devil_balls", "check", "SERVER", grid, "Allow Devil Balls Features to be spawned when hunter dies (Chance is 70%)")
Ph:CreateVGUIType("ph_waitforplayers", "check", "SERVER", grid, "Wait for Players to begin the gameplay")
Ph:CreateVGUIType("ph_min_waitforplayers", "slider", { min = 1, max = game.MaxPlayers(), init = GetConVar("ph_min_waitforplayers"):GetInt(), dec = 0, kind = "SERVER" }, grid, "Mininum Players to Wait before the game starts (default: 1)")
Ph:CreateVGUIType("", "label", false, grid, "Enable Custom Taunt. Mode: 0 = Random, 1 = Custom, 2 Both mode)")
Ph:CreateVGUIType("", "btn", {max = 2, textdata = {
[1] = {"--[ Current Mode is Mode: "..GetConVar('ph_enable_custom_taunts'):GetInt().." ] --",
function(self)
local CusTauntConvar = {
[0] = "Mode [0/F3]: Random Taunt",
[1] = "Mode [1/C]: Custom Taunt",
[2] = "Mode [2]: Both Modes"
}
local function SendTauntCommandState(state)
net.Start("SendTauntStateCmd")
net.WriteString(tostring(state))
net.SendToServer()
end
self:SetText(CusTauntConvar[GetConVar("ph_enable_custom_taunts"):GetInt()])
local state = 0
if GetConVar("ph_enable_custom_taunts"):GetInt() == 0 then
state = 1
SendTauntCommandState(1)
self:SetText(CusTauntConvar[state])
elseif GetConVar("ph_enable_custom_taunts"):GetInt() == 1 then
state = 2
SendTauntCommandState(2)
self:SetText(CusTauntConvar[state])
elseif GetConVar("ph_enable_custom_taunts"):GetInt() == 2 then
state = 0
SendTauntCommandState(0)
self:SetText(CusTauntConvar[state])
end
end},
[2] = {"Open Taunt Window", function(self)
if !LocalPlayer():Alive() then
print("You must do this action when you are alive!")
frm:Close()
else
LocalPlayer():ConCommand("ph_showtaunts")
end
end}
}
}, grid ,"")
Ph:CreateVGUIType("devspacer","spacer",nil,grid,"" )
Ph:CreateVGUIType("", "label", false, grid, "Developer Options/Experimentals Features")
Ph:CreateVGUIType("phe_check_props_boundaries", "check", "SERVER", grid, "[WORK IN PROGRESS] Enable Boundaries Check? This prevents you to get stuck with objects/walls.")
Ph:CreateVGUIType("ph_mkbren_use_new_mdl","check","SERVER",grid, "Developer: Use new model for Bren MK II Bonus Weapon (Require Map Restart!)")
Ph:CreateVGUIType("ph_print_verbose", "check", "SERVER", grid, "Developer: Enable verbose information of PH:E events in the console")
Ph:CreateVGUIType("ph_enable_plnames", "check", "SERVER", grid, "Enable Player team names to be appear on their screen.")
Ph:CreateVGUIType("ph_fc_use_single_sound", "check", "SERVER", grid, "Use single Freezecam sound instead of sound list (Use 'ph_fc_cue_path' to determine Freezecam sound path)")
Ph:CreateVGUIType("ph_use_playermodeltype", "check", "SERVER", grid, "Use Legacy Model List : 0 = All Playermodels (AddValidModel), 1 = Use Legacy: list.Get('PlayerOptionsModel')")
Ph:CreateVGUIType("ph_prop_jumppower", "slider", {min = 1, max = 3, init = GetConVar("ph_prop_jumppower"):GetFloat(), dec = 2, float = true, kind = "SERVER"}, grid, "Additional Jump Power multiplier for Props")
Ph:CreateVGUIType("ph_sv_enable_obb_modifier","check","SERVER",grid, "Developer: Enable Customized Prop Entity OBB Model Data Modifier")
Ph:CreateVGUIType("ph_reload_obb_setting_everyround","check","SERVER",grid, "Developer: Reload Customized Prop Entity OBB Model Data Modifier every round restarts")
tab:AddSheet("Admins", panel, "icon16/user_gray.png")
end
function Ph:MapVoteMenu()
local panel,grid = Ph:CreateBasicLayout(Color(40,40,40,180),tab)
Ph:CreateVGUIType("", "label", false, grid, "MapVote Settings")
Ph:CreateVGUIType("mv_allowcurmap","check","SERVER",grid,"Allow Current map to be Voted")
Ph:CreateVGUIType("mv_cooldown","check","SERVER",grid,"Enable map Cooldown for voting")
Ph:CreateVGUIType("mv_use_ulx_votemaps","check","SERVER",grid,"Use map listing from ULX Mapvote? 1 = use from ULX mapvote list (which you can whitelist them), 0 = use default maps/*.bsp directory listing.")
Ph:CreateVGUIType("mv_maplimit", "slider", {min = 2, max = 80, init = GetConVar("mv_maplimit"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Number of Maps to be shown in MapVote.")
Ph:CreateVGUIType("mv_timelimit", "slider", {min = 15, max = 90, init = GetConVar("mv_timelimit"):GetInt(), dec = 0, kind = "SERVER"}, grid, "Time in Seconds for default mapvote when voting.")
Ph:CreateVGUIType("mv_mapbeforerevote", "slider", {min = 1, max = 10, init = GetConVar("mv_mapbeforerevote"):GetInt(), dec = 0, kind = "SERVER"}, grid, "How many times cooldown map to be appear again?")
Ph:CreateVGUIType("mv_rtvcount", "slider", {min = 2, max = game.MaxPlayers(), init = GetConVar("mv_rtvcount"):GetInt(), dec = 0, kind = "SERVER"}, grid, "How many players required to use RTV (Rock the Vote)")
Ph:CreateVGUIType("s1","spacer",nil,grid,"" )
Ph:CreateVGUIType("", "label", false, grid, "To Setup which map should be listed, use (for example) [ mv_mapprefix 'ph_,cs_,de_' ] in the console.")
Ph:CreateVGUIType("", "label", false, grid, "If you are unable to do a MapVote, you NEED to install ULX Admin Mod!")
Ph:CreateVGUIType("s2","spacer",nil,grid,"" )
Ph:CreateVGUIType("", "label", false, grid, "MapVote Action (To cancel, simply type !unmap_vote in the chat or type 'unmap_vote' in console)")
Ph:CreateVGUIType("", "btn", {max = 2, textdata = {
[1] = {"Start MapVote", function(self)
LocalPlayer():ConCommand("map_vote")
end
},
[2] = {"Stop MapVote", function(self)
LocalPlayer():ConCommand("unmap_vote")
end}
}
},grid,"")
tab:AddSheet("MapVote", panel, "icon16/map.png")
end
-- if Current User is Admin then check their user as security measure in the server.
if ply:IsAdmin() then
net.Start("CheckAdminFirst")
net.SendToServer()
end
-- if Current User Passes the admin check, shows the admin tab.
net.Receive("CheckAdminResult", function(len, pln)
Ph:ShowAdminMenu()
Ph:MapVoteMenu()
end)
end
concommand.Add("ph_enhanced_show_help", ph_BaseMainWindow, nil, "Show Prop Hunt: Enhanced Main and Help menus." )

View File

@@ -0,0 +1,51 @@
function GM:HUDDrawTargetID()
local tr = util.GetPlayerTrace(LocalPlayer())
local trace = util.TraceLine(tr)
-- Don't show if 'Player Names above their head' is enabled.
if GetConVar("ph_enable_plnames"):GetBool() && GetConVar("ph_cl_pltext"):GetBool() then return end
if (!trace.Hit) then return end
if (!trace.HitNonWorld) then return end
local text = "ERROR"
local font = "TargetID"
if (trace.Entity:IsPlayer() && trace.Entity:Team() == LocalPlayer():Team()) then
text = trace.Entity:Nick()
else
return
end
surface.SetFont(font)
local w, h = surface.GetTextSize(text)
local MouseX, MouseY = gui.MousePos()
if (MouseX == 0 && MouseY == 0) then
MouseX = ScrW() / 2
MouseY = ScrH() / 2
end
local x = MouseX
local y = MouseY
x = x - w / 2
y = y + 30
draw.SimpleText(text, font, x + 1, y + 1, Color(0, 0, 0, 120))
draw.SimpleText(text, font, x + 2, y + 2, Color(0, 0, 0, 50))
draw.SimpleText(text, font, x, y, self:GetTeamColor(trace.Entity))
y = y + h + 5
local text = trace.Entity:Health().."%"
local font = "TargetIDSmall"
surface.SetFont(font)
local w, h = surface.GetTextSize(text)
local x = MouseX - w / 2
draw.SimpleText(text, font, x + 1, y + 1, Color(0, 0, 0, 120))
draw.SimpleText(text, font, x + 2, y + 2, Color(0, 0, 0, 50))
draw.SimpleText(text, font, x, y, self:GetTeamColor(trace.Entity))
end

View File

@@ -0,0 +1,278 @@
surface.CreateFont("PHE.TauntFont",
{
font = "Roboto",
size = 16,
weight = 500,
antialias = true,
shadow = false
})
local isplayed = false
local isopened = false
local isforcedclose = false
local hastaunt = false
net.Receive("PH_ForceCloseTauntWindow", function()
isforcedclose = true
end)
net.Receive("PH_AllowTauntWindow", function()
isforcedclose = false
end)
local function MainFrame()
if GetConVar("ph_enable_custom_taunts"):GetInt() < 1 then
chat.AddText(Color(220,0,0),"[PH:E - Taunts] Warning: This server has custom taunts disabled.")
return
end
isopened = true
local frame = vgui.Create("DFrame")
frame:SetSize(400,600)
frame:SetTitle("Prop Hunt | Taunt Menu")
frame:Center()
frame:SetVisible(true)
frame:ShowCloseButton(true)
-- Make sure they have Mouse & Keyboard interactions.
frame:SetMouseInputEnabled(true)
frame:SetKeyboardInputEnabled(true)
frame.Paint = function(self,w,h)
surface.SetDrawColor(Color(40,40,40,180))
surface.DrawRect(0,0,w,h)
end
frame.OnClose = function()
isopened = false
hastaunt = false
end
local function frame_Think_Force()
if isforcedclose == true && isopened == true then
isopened = false
hastaunt = false
frame:Close()
end
end
hook.Add("Think", "CloseWindowFrame_Force", frame_Think_Force)
local list = vgui.Create("DListView", frame)
list:SetMultiSelect(false)
list:AddColumn("soundlist") -- because header is gone.
list.m_bHideHeaders = true
list:SetPos(10,52)
list:SetSize(0,450)
list:Dock(BOTTOM)
local TEAM_TAUNTS = {}
local WHOLE_TEAM_TAUNTS = {}
-- Determine if prop or hunter taunt list to be used
if (LocalPlayer():Team() == TEAM_HUNTERS) then
TEAM_TAUNTS = PHE:GetTeamTaunt(TEAM_HUNTERS,false)
WHOLE_TEAM_TAUNTS = PHE:GetAllTeamTaunt(TEAM_HUNTERS)
else
TEAM_TAUNTS = PHE:GetTeamTaunt(TEAM_PROPS,false)
WHOLE_TEAM_TAUNTS = PHE:GetAllTeamTaunt(TEAM_PROPS)
end
for name,_ in pairs(TEAM_TAUNTS) do
list:AddLine(name)
end
local comb = vgui.Create("DComboBox", frame)
comb:Dock(TOP)
comb:SetSize(0, 20)
comb:SetValue("Original Taunts")
comb:AddChoice("Original Taunts")
comb:AddChoice("PH:E/Custom Taunts")
function comb:SortAndStyle(pnl)
pnl:SortByColumn(1,false)
pnl.Paint = function(self,w,h)
surface.SetDrawColor(Color(50,50,50,180))
surface.DrawRect(0,0,w,h)
end
local color =
{
hover = Color(80,80,80,200),
select = Color(120,120,120,255),
alt = Color(60,60,60,180),
normal = Color(50,50,50,180)
}
for _,line in pairs( pnl:GetLines() ) do
function line:Paint( w, h )
if ( self:IsHovered() ) then
surface.SetDrawColor(color.hover)
elseif ( self:IsSelected() ) then
surface.SetDrawColor(color.select)
elseif ( self:GetAltLine() ) then
surface.SetDrawColor(color.alt)
else
surface.SetDrawColor(color.normal)
end
surface.DrawRect(0,0,w,h)
end
for _,col in pairs(line["Columns"]) do
col:SetFont("PHE.TauntFont")
col:SetTextColor(color_white)
end
end
end
comb.OnSelect = function(pnl, idx, val)
if val == "Original Taunts" then
list:Clear()
hastaunt = false
if TEAM_TAUNTS then
for name,val in pairs(TEAM_TAUNTS) do
list:AddLine(name)
end
end
pnl:SortAndStyle(list)
elseif val == "PH:E/Custom Taunts" then
list:Clear()
hastaunt = false
if LocalPlayer():Team() == TEAM_PROPS then
if PHE:GetTeamTaunt(TEAM_PROPS,true) != false then
for name,val in pairs(PHE:GetTeamTaunt(TEAM_PROPS,true)) do
list:AddLine(name)
end
else
list:AddLine("<< WARNING: NO TAUNTS DETECTED! >>")
end
else
if PHE:GetTeamTaunt(TEAM_HUNTERS,true) != false then
for name,val in pairs(PHE:GetTeamTaunt(TEAM_HUNTERS,true)) do
list:AddLine(name)
end
else
list:AddLine("<< WARNING: NO TAUNTS DETECTED! >>")
end
end
pnl:SortAndStyle(list)
end
end
comb:SortAndStyle(list)
-- I know, this one is fixed style.
local btnpanel = vgui.Create("DPanel", frame)
btnpanel:Dock(FILL)
btnpanel:SetBackgroundColor(Color(20,20,20,200))
local function CreateStyledButton(dock,size,ttip,margin,texture,imagedock, btnfunction)
local left,top,right,bottom = margin[1],margin[2],margin[3],margin[4]
local button = vgui.Create("DButton", btnpanel)
button:Dock(dock)
button:SetSize(size,0)
button:DockMargin(left,top,right,bottom)
button:SetText("")
button:SetTooltip(ttip)
button.Paint = function(self,w,h)
if self:IsHovered() then
surface.SetDrawColor(Color(90,90,90,200))
else
surface.SetDrawColor(Color(0,0,0,0))
end
surface.DrawRect(0,0,w,h)
end
button.DoClick = btnfunction
local image = vgui.Create("DImage", button)
image:SetImage(texture)
image:Dock(imagedock)
end
local function TranslateTaunt(linename)
return WHOLE_TEAM_TAUNTS[linename]
end
local function SendToServer(snd)
if !isplayed then
net.Start("CL2SV_PlayThisTaunt"); net.WriteString(tostring(snd)); net.SendToServer();
isplayed = true
timer.Simple(GetConVar("ph_customtaunts_delay"):GetInt(), function() isplayed = false; end)
else
chat.AddText(Color(220,40,0),"[PH:E - Taunts] Warning: ",Color(220,220,220),"Please wait in " .. GetConVar("ph_customtaunts_delay"):GetInt() .. " seconds...!")
end
end
CreateStyledButton(LEFT,86,"Play Taunt Locally",{5,5,5,5},"vgui/phehud/btn_play.vmt",FILL, function()
if hastaunt then
local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1))
surface.PlaySound(getline)
end
end)
CreateStyledButton(LEFT,86,"Play Taunt Globally",{5,5,5,5}, "vgui/phehud/btn_playpub.vmt",FILL, function()
if hastaunt then
local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1))
SendToServer(getline)
end
end)
CreateStyledButton(LEFT,86,"Play Taunt Globally and Close",{5,5,5,5},"vgui/phehud/btn_playx.vmt",FILL, function()
if hastaunt then
local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1))
SendToServer(getline)
frame:Close()
end
end)
CreateStyledButton(FILL,86,"Close the Window",{5,5,5,5},"vgui/phehud/btn_close.vmt",FILL, function()
frame:Close()
end)
list.OnRowRightClick = function(panel,line)
hastaunt = true
local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1))
local menu = DermaMenu()
menu:AddOption("Play (Local)", function() surface.PlaySound(getline); print("Playing: "..getline); end):SetIcon("icon16/control_play.png")
menu:AddOption("Play (Global)", function() SendToServer(getline); end):SetIcon("icon16/sound.png")
menu:AddOption("Play and Close (Global)", function() SendToServer(getline); frame:Close(); end):SetIcon("icon16/sound_delete.png")
menu:AddSpacer()
menu:AddOption("Close Menu", function() frame:Close(); end):SetIcon("icon16/cross.png")
menu:Open()
end
list.OnRowSelected = function()
hastaunt = true
end
list.DoDoubleClick = function(id,line)
hastaunt = true
local getline = TranslateTaunt(list:GetLine(list:GetSelectedLine()):GetValue(1))
SendToServer(getline)
if GetConVar("ph_cl_autoclose_taunt"):GetBool() then frame:Close(); end
end
frame:MakePopup()
frame:SetKeyboardInputEnabled(false)
end
concommand.Add("ph_showtaunts", function()
if LocalPlayer():Alive() && isforcedclose != true && LocalPlayer():GetObserverMode() == OBS_MODE_NONE then
if isopened != true then
MainFrame()
end
else
chat.AddText(Color(220,40,0),"[PH:E Taunts] Notice: ",Color(220,220,220), "You can only play custom taunts when you\'re alive as prop/hunter!")
end
end, nil, "Show Prop Hunt taunt list, so you can select and play for self or play as a taunt.")
local function BindPress(ply, bind, pressed)
if string.find(bind, "+menu_context") and pressed then
RunConsoleCommand("ph_showtaunts")
end
end
hook.Add("PlayerBindPress", "PlayerBindPress_menuContext", BindPress)

View File

@@ -0,0 +1,23 @@
-- This is a template of Devil Balls Additions which will adds a new events for Devil balls entity.
-- Note: Key name (the "UniqueName") must be different and cannot be similar with other name's addition. This is purposely used for printVerbose and preventing
-- Duplicated addition and table reading errors.
-- To add something, Remove "--[[" and "]]" to make them available again.
--[[
list.Set("DevilBallsAddition", "UniqueName", function(pl)
-- give something to the player or modify something to pl.ph_prop. for example:
pl:ChatPrint("Hello! Let me change the prop color and revert in 5 seconds!")
if IsValid(pl.ph_prop) then
pl.ph_prop:SetMaterials("models/shiny")
pl.ph_prop:SetColor(255,0,0)
pl.RevertColor = timer.Simple(5, function()
pl.ph_prop:SetMaterials("")
pl.ph_prop:SetColor(255,255,255)
end)
end
end)
]]

View File

@@ -0,0 +1,16 @@
-- This is a template of Lucky Balls Additions which will adds a new events for luck balls entity.
-- Note: Key name (the "UniqueName") must be different and cannot be similar with other name's addition. This is purposely used for printVerbose and preventing
-- Duplicated addition and table reading errors.
-- To add something, Remove "--[[" and "]]" to make them available again.
--[[
list.Set("LuckyBallsAddition", "UniqueName", function(pl)
-- give something to the player. for example: Stunstick
pl:ChatPrint("Hello! Here is your free Stunstick! :D")
pl:Give("weapon_stunstick")
end)
]]

View File

@@ -0,0 +1,50 @@
-- ph_kleiner Configuration.
-- Add some Invisible Wall to prevent Exploit. Additionaly, Force all player props become Kleiner model after 0.5 seconds of respawn.
function PH_Create_PlayerClip(min, max)
local pc = ents.Create("brush_playerclip")
pc.min = min
pc.max = max
pc.pos = pc.max - ((pc.max - pc.min) / 2)
pc:SetPos(pc.pos)
pc:Spawn()
end
local function RemoveClipBrush()
for _,pc in pairs(ents.FindByClass("brush_playerclip")) do
if !IsValid(pc) then return end
printVerbose("[PH_Kleiner_v2.Config] Removing Anti Exploit Brush -> #"..pc:EntIndex())
pc:Remove()
end
end
hook.Add("PreCleanupMap", "PH_RemoveClip", RemoveClipBrush)
local function PostCreatePlayerClip()
if game.GetMap() == "ph_kliener_v2" && engine.ActiveGamemode() == "prop_hunt" then
printVerbose("Creating Anti Exploit walls...")
PH_Create_PlayerClip(Vector(1040, -273, 1000), Vector(-1159, -156, 1500))
PH_Create_PlayerClip(Vector(-1020, 639, -50), Vector(-1306, 669, 850))
PH_Create_PlayerClip(Vector(-1299, 659, -50), Vector(-1312, -1440, 1510))
PH_Create_PlayerClip(Vector(-1302, -1434, -371), Vector(1042, -3500, 1500))
PH_Create_PlayerClip(Vector(1049, -1432, -50), Vector(1058, -217, 1400))
-- Force all players become Kleiner on respawn!
timer.Simple(5, function()
for k,v in pairs(ents.FindByClass("ph_prop")) do
v:SetModel("models/player/kleiner.mdl")
v:DrawShadow(false)
end
end)
-- Disable all shadows
local ShadowControl = ents.Create( "shadow_control" )
ShadowControl:SetPos( Vector( 0, 0, 0 ) )
ShadowControl:SetKeyValue( "disableallshadows", "1" )
ShadowControl:Spawn()
ShadowControl:Activate()
end
end
hook.Add("PostCleanupMap", "PH_AddClipBrush", PostCreatePlayerClip)

View File

@@ -0,0 +1,16 @@
-- We will initialize the config stuff here
-- Shared includes
AddCSLuaFile("sh_phe_additional_taunts.lua")
include("sh_phe_additional_taunts.lua")
-- Server includes
if SERVER then
include("server/sv_phkleiner_config.lua")
include("server/sv_devilball_additions.lua")
include("server/sv_luckyball_additions.lua")
end

View File

@@ -0,0 +1,23 @@
-- In here you can add two team taunts without seperating them.
local taunts = {}
-- Begin Table: Hunters
taunts.Hunter = {
["Guuuh!"] = "vo/k_lab/ba_guh.wav",
["If you See Dr. Breen"] = "vo/streetwar/rubble/ba_tellbreen.wav"
-- Add more Hunters Taunt here...
}
-- Begin Table: Props
taunts.Props = {
["Windows XP Shutdown"] = "taunts/ph_enhanced/ext_xp_off.wav",
["Windows XP Startup"] = "taunts/ph_enhanced/ext_xp_start.wav"
-- Add more Props Taunt here...
}
-- if everything's done with above, let's add them as the list.
-- They will be automatically added as soon as the game loads!
for propTaunt,propPath in pairs(taunts.Props) do list.Set("PHE.CustomPropTaunts", propTaunt, propPath) end
for hunterTaunt,hunterPath in pairs(taunts.Hunter) do list.Set("PHE.CustomHunterTaunts", hunterTaunt, hunterPath) end
-- You can also add your custom taunts outside from this scope with your own [ list.Set("PHE.Custom<Prop/Hunter>Taunts", "Taunt Name", "Your Taunt Path") ]

View File

@@ -0,0 +1,791 @@
-- Ship
resource.AddWorkshop("417565863")
-- Send required file to clients
AddCSLuaFile("sh_init.lua")
AddCSLuaFile("sh_player.lua")
AddCSLuaFile("cl_tauntwindow.lua")
AddCSLuaFile("cl_init.lua")
AddCSLuaFile("cl_hud_mask.lua")
AddCSLuaFile("cl_hud.lua")
AddCSLuaFile("cl_menu.lua")
AddCSLuaFile("cl_targetid.lua")
AddCSLuaFile("cl_autotaunt.lua")
AddCSLuaFile("cl_credits.lua")
-- Include the required lua files
include("sv_networkfunctions.lua")
include("sh_init.lua")
include("sh_config.lua")
include("sv_admin.lua")
include("sv_autotaunt.lua")
include("sv_tauntwindow.lua")
include("sv_bbox_addition.lua")
-- Server only constants
PHE.EXPLOITABLE_DOORS = {
"func_door",
"prop_door_rotating",
"func_door_rotating"
}
-- Voice Control Constant init
PHE.VOICE_IS_END_ROUND = 0
-- Update cvar to variables changes every so seconds
PHE.UPDATE_CVAR_TO_VARIABLE = 0
-- Spectator check
PHE.SPECTATOR_CHECK = 0
-- Player Join/Leave message
gameevent.Listen( "player_connect" )
hook.Add( "player_connect", "AnnouncePLJoin", function( data )
for k, v in pairs( player.GetAll() ) do
v:PrintMessage( HUD_PRINTTALK, data.name .. " has connected to the server." )
end
end )
gameevent.Listen( "player_disconnect" )
hook.Add( "player_disconnect", "AnnouncePLLeave", function( data )
for k,v in pairs( player.GetAll() ) do
v:PrintMessage( HUD_PRINTTALK, data.name .. " has left the server (Reason: " .. data.reason ..")" )
end
end )
-- Force Close taunt window function, determined whenever the round ends, or team winning.
local function ForceCloseTauntWindow(num)
if num == 1 then
net.Start("PH_ForceCloseTauntWindow")
net.Broadcast()
elseif num == 0 then
net.Start("PH_AllowTauntWindow")
net.Broadcast()
end
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!")
PHE.VOICE_IS_END_ROUND = 1
ForceCloseTauntWindow(1)
net.Start("PH_RoundDraw_Snd")
net.Broadcast()
hook.Call("PH_OnRoundDraw", nil)
return
end
if table.Count(Teams) == 1 then
local TeamID = table.GetFirstKey(Teams)
-- debug
MsgAll("Round Result: "..team.GetName(TeamID).." ("..TeamID..") Wins!\n")
-- End Round
GAMEMODE:RoundEndWithResult(TeamID, team.GetName(TeamID).." win!")
PHE.VOICE_IS_END_ROUND = 1
ForceCloseTauntWindow(1)
-- send the win notification
if TeamID == TEAM_HUNTERS then
net.Start("PH_TeamWinning_Snd")
net.WriteString(PHE.WINNINGSOUNDS[TEAM_HUNTERS])
net.Broadcast()
elseif TeamID == TEAM_PROPS then
net.Start("PH_TeamWinning_Snd")
net.WriteString(PHE.WINNINGSOUNDS[TEAM_PROPS])
net.Broadcast()
end
hook.Call("PH_OnRoundWinTeam", nil, TeamID)
return
end
end
-- Player Voice & Chat Control to prevent Metagaming. (As requested by some server owners/suggestors.)
-- You can disable this feature by typing 'sv_alltalk 1' in console to make everyone can hear.
-- Control Player Voice
function GM:PlayerCanHearPlayersVoice(listen, speaker)
local alltalk_cvar = GetConVar("sv_alltalk"):GetInt()
if (alltalk_cvar > 0) then return true, false end
-- prevent Loopback check.
if (listen == speaker) then return false, false end
-- Only alive players can listen other living players.
if listen:Alive() && speaker:Alive() then return true, false end
-- Event: On Round Start. Living Players don't listen to dead players.
if PHE.VOICE_IS_END_ROUND == 0 && listen:Alive() && !speaker:Alive() then return false, false end
-- Listen to all dead players while you dead.
if !listen:Alive() && !speaker:Alive() then return true, false end
-- However, Living players can be heard from dead players.
if !listen:Alive() && speaker:Alive() then return true, false end
-- Event: On Round End/Time End. Listen to everyone.
if PHE.VOICE_IS_END_ROUND == 1 && listen:Alive() && !speaker:Alive() then return true, false end
-- Spectator can only read from themselves.
if listen:Team() == TEAM_SPECTATOR && listen:Alive() && speaker:Alive() then return false, false end
-- This is for ULX "Permanent Gag". Uncomment this if you have some issues.
-- if speaker:GetPData( "permgagged" ) == "true" then return false, false end
-- does return true, true required here?
end
-- Control Players Chat
function GM:PlayerCanSeePlayersChat(txt, onteam, listen, speaker)
if ( onteam ) then
-- Generic Specific OnTeam chats
if ( !IsValid( speaker ) || !IsValid( listen ) ) then return false end
if ( listen:Team() != speaker:Team() ) then return false end
-- ditto, this is same as below.
if listen:Alive() && speaker:Alive() then return true end
if PHE.VOICE_IS_END_ROUND == 0 && listen:Alive() && !speaker:Alive() then return false end
if !listen:Alive() && !speaker:Alive() then return true end
if !listen:Alive() && speaker:Alive() then return true end
if PHE.VOICE_IS_END_ROUND == 1 && listen:Alive() && !speaker:Alive() then return true end
if listen:Team() == TEAM_SPECTATOR && listen:Alive() && speaker:Alive() then return false end
end
local alltalk_cvar = GetConVar("sv_alltalk"):GetInt()
if (alltalk_cvar > 0) then return true end
-- Generic Checks
if ( !IsValid( speaker ) || !IsValid( listen ) ) then return false end
-- Only alive players can see other living players.
if listen:Alive() && speaker:Alive() then return true end
-- Event: On Round Start. Living Players don't see dead players' chat.
if PHE.VOICE_IS_END_ROUND == 0 && listen:Alive() && !speaker:Alive() then return false end
-- See Chat to all dead players while you dead.
if !listen:Alive() && !speaker:Alive() then return true end
-- However, Living players' chat can be seen from dead players.
if !listen:Alive() && speaker:Alive() then return true end
-- Event: On Round End/Time End. See Chat to everyone.
if PHE.VOICE_IS_END_ROUND == 1 && listen:Alive() && !speaker:Alive() then return true end
-- Spectator can only read from themselves.
if listen:Team() == TEAM_SPECTATOR && listen:Alive() && speaker:Alive() then return false end
return true
end
-- Called when an entity takes damage
function EntityTakeDamage(ent, dmginfo)
local att = dmginfo:GetAttacker()
-- Code from: https://facepunch.com/showthread.php?t=1500179 , Special thanks from AlcoholicoDrogadicto(http://steamcommunity.com/profiles/76561198082241865/) for suggesting this.
if GAMEMODE:InRound() && ent && ent:IsPlayer() && ent:Alive() && ent:Team() == TEAM_PROPS && ent.ph_prop then
-- Prevent Prop 'Friendly Fire'
if ( dmginfo:GetAttacker():IsPlayer() && dmginfo:GetAttacker():Team() == ent:Team() )
then printVerbose("DMGINFO::ATTACKED!!-> "..tostring(dmginfo:GetAttacker())..", DMGTYPE: "..dmginfo:GetDamageType())
return
end
--Debug purpose.
printVerbose("!! " .. ent:Name() .. "'s PLAYER entity appears to have taken damage, we can redirect it to the prop! (Model is: " .. ent.ph_prop:GetModel() .. ")")
ent.ph_prop:TakeDamageInfo(dmginfo)
return
end
if GAMEMODE:InRound() && ent && (ent:GetClass() != "ph_prop" && ent:GetClass() != "func_breakable" && ent:GetClass() != "prop_door_rotating" && ent:GetClass() != "prop_dynamic*") && !ent:IsPlayer() && att && att:IsPlayer() && att:Team() == TEAM_HUNTERS && att:Alive() then
if att:Armor() >= 5 && GetConVar("ph_hunter_fire_penalty"):GetInt() >= 5 then
att:SetHealth(att:Health() - (math.Round(GetConVar("ph_hunter_fire_penalty"):GetInt()/2)))
att:SetArmor(att:Armor() - 15)
if att:Armor() < 0 then att:SetArmor(0) end
else
att:SetHealth(att:Health() - GetConVar("ph_hunter_fire_penalty"):GetInt())
end
if att:Health() <= 0 then
MsgAll(att:Name() .. " felt guilty for hurting so many innocent props and committed suicide\n")
att:Kill()
hook.Call("PH_HunterDeathPenalty", nil, att)
end
end
end
hook.Add("EntityTakeDamage", "PH_EntityTakeDamage", EntityTakeDamage)
-- Called when player tries to pickup a weapon
function GM:PlayerCanPickupWeapon(pl, ent)
if pl:Team() != TEAM_HUNTERS then
return false
end
return true
end
function PH_ResetCustomTauntWindowState()
-- Force close any taunt menu windows
ForceCloseTauntWindow(0)
-- Extra additional
PHE.VOICE_IS_END_ROUND = 0
-- Reset Player's Height
end
hook.Add("PostCleanupMap", "PH_ResetCustomTauntWindow", PH_ResetCustomTauntWindowState)
-- Make a variable for 4 unique combines.
-- Clean up, sorry btw.
local playerModels = {
"combine",
"combineprison",
"combineelite",
"police"
-- you may add more here.
}
function GM:PlayerSetModel(pl)
-- player actual model to prevent multi-damage hitbox.
local player_model = "models/props_idbs/phenhanced/box.mdl"
if GetConVar("ph_use_custom_plmodel"):GetBool() then
-- Use a delivered player model info from cl_playermodel ConVar.
-- This however will use a custom player selection. It'll immediately apply once it is selected.
local mdlinfo = pl:GetInfo("cl_playermodel")
local mdlname = player_manager.TranslatePlayerModel(mdlinfo)
if pl:Team() == TEAM_HUNTERS then
player_model = mdlname
end
else
-- Otherwise, Use Random one based from a table above.
local customModel = table.Random(playerModels)
local customMdlName = player_manager.TranslatePlayerModel(customModel)
if pl:Team() == TEAM_HUNTERS then
player_model = customMdlName
end
end
-- precache and Set the model.
util.PrecacheModel(player_model)
pl:SetModel(player_model)
end
-- The [E] & Mouse Click 1 behaviour is now moved in here!
function GM:PlayerExchangeProp(pl, ent)
if !IsValid(pl) then return; end
if !IsValid(ent) then return; end
if pl:Team() == TEAM_PROPS && pl:IsOnGround() && !pl:Crouching() && table.HasValue(PHE.USABLE_PROP_ENTITIES, ent:GetClass()) && ent:GetModel() then
if table.HasValue(PHE.BANNED_PROP_MODELS, ent:GetModel()) then
pl:ChatPrint("[PH: Enhanced] Notice: That prop has been banned from the server.")
elseif IsValid(ent:GetPhysicsObject()) && (pl.ph_prop:GetModel() != ent:GetModel() || pl.ph_prop:GetSkin() != ent:GetSkin()) then
local ent_health = math.Clamp(ent:GetPhysicsObject():GetVolume() / 250, 1, 200)
local new_health = math.Clamp((pl.ph_prop.health / pl.ph_prop.max_health) * ent_health, 1, 200)
pl.ph_prop.health = new_health
pl.ph_prop.max_health = ent_health
pl.ph_prop:SetModel(ent:GetModel())
pl.ph_prop:SetSkin(ent:GetSkin())
pl.ph_prop:SetSolid(SOLID_VPHYSICS)
pl.ph_prop:SetPos(pl:GetPos() - Vector(0, 0, ent:OBBMins().z))
pl.ph_prop:SetAngles(pl:GetAngles())
pl:SetHealth(new_health)
if GetConVar("ph_sv_enable_obb_modifier"):GetBool() && ent:GetNWBool("hasCustomHull",false) then
local hmin = ent.m_Hull[1]
local hmax = ent.m_Hull[2]
local dmin = ent.m_dHull[1]
local dmax = ent.m_dHull[2]
if hmax.z < 24 || dmax.z < 24 then
pl:SetViewOffset(Vector(0,0,24))
pl:SetViewOffsetDucked(Vector(0,0,24))
elseif hmax.z > 84 || dmax.z > 84 then --what the heck Duck Size is 84? BigMomma.mdl?
pl:SetViewOffset(Vector(0,0,84))
pl:SetViewOffsetDucked(Vector(0,0,84))
else
pl:SetViewOffset(Vector(0,0,hmax.z))
pl:SetViewOffsetDucked(Vector(0,0,dmax.z))
end
pl:SetHull(hmin,hmax)
pl:SetHullDuck(dmin,dmax)
net.Start("SetHull")
net.WriteInt(math.Round(math.Max(hmax.x,hmax.y)),32)
net.WriteInt(hmax.z,32)
net.WriteInt(dmax.z,32)
net.WriteInt(new_health,9)
net.Send(pl)
else
local hullxymax = math.Round(math.Max(ent:OBBMaxs().x, ent:OBBMaxs().y))
local hullxymin = hullxymax * -1
local hullz = math.Round(ent:OBBMaxs().z - ent:OBBMins().z)
local dhullz = hullz
if hullz > 10 && hullz <= 30 then
dhullz = hullz-(hullz*0.5)
elseif hullz > 30 && hullz <= 40 then
dhullz = hullz-(hullz*0.2)
elseif hullz > 40 && hullz <= 50 then
dhullz = hullz-(hullz*0.1)
else
dhullz = hullz
end
if hullz < 24 then
pl:SetViewOffset(Vector(0,0,24))
pl:SetViewOffsetDucked(Vector(0,0,24))
elseif hullz > 84 then
pl:SetViewOffset(Vector(0,0,84))
pl:SetViewOffsetDucked(Vector(0,0,84))
else
pl:SetViewOffset(Vector(0,0,hullz))
pl:SetViewOffsetDucked(Vector(0,0,dhullz))
end
pl:SetHull(Vector(hullxymin, hullxymin, 0), Vector(hullxymax, hullxymax, hullz))
pl:SetHullDuck(Vector(hullxymin, hullxymin, 0), Vector(hullxymax, hullxymax, dhullz))
net.Start("SetHull")
net.WriteInt(hullxymax, 32)
net.WriteInt(hullz, 32)
net.WriteInt(dhullz, 32)
net.WriteInt(new_health, 9)
net.Send(pl)
end
end
hook.Call("PH_OnChangeProp", nil, pl, ent)
end
end
-- Called when a player tries to use an object. By default this pressed ['E'] button. MouseClick 1 will be mentioned below at line @351
function GM:PlayerUse(pl, ent)
if !pl:Alive() || pl:Team() == TEAM_SPECTATOR || pl:Team() == TEAM_UNASSIGNED then return false; end
-- Prevent Execution Spam by holding ['E'] button too long.
if pl.UseTime <= CurTime() then
local hmx, hz = ent:GetPropSize()
if GetConVar("phe_check_props_boundaries"):GetBool() && !pl:CheckHull(hmx, hmx, hz) then
pl:SendLua("chat.AddText(Color(235, 10, 15), \"[PH: Enhanced]\", Color(220, 220, 220), \" There is no room to change that prop!\")")
else
self:PlayerExchangeProp(pl, ent)
end
pl.UseTime = CurTime() + 1
end
-- Prevent the door exploit
if table.HasValue(PHE.EXPLOITABLE_DOORS, ent:GetClass()) && pl.last_door_time && pl.last_door_time + 1 > CurTime() then
return false
end
pl.last_door_time = CurTime()
return true
end
net.Receive("CL2SV_ExchangeProp", function(len, ply)
local Prop = net.ReadEntity()
ply:PrintMessage(HUD_PRINTCONSOLE, "-=* NOTICE *=-")
ply:PrintMessage(HUD_PRINTCONSOLE, "Hello! We've noticed you tried using the \"CL2SV_ExchangeProp\" net message.")
ply:PrintMessage(HUD_PRINTCONSOLE, "Sad news is that this net message is no longer used (due to exploits). Shame, isn't it?")
ply:PrintMessage(HUD_PRINTCONSOLE, "")
ply:PrintMessage(HUD_PRINTCONSOLE, "This net message will still respond, but you will receive this message instead.")
ply:PrintMessage(HUD_PRINTCONSOLE, "-=* NOTICE *=-")
--[[
if ply.UseTime <= CurTime() then
if !ply:IsHoldingEntity() then
local hmx,hz = Prop:GetPropSize()
if (GetConVar("phe_check_props_boundaries"):GetBool() && !ply:CheckHull(hmx,hmx,hz)) then
ply:SendLua("chat.AddText(Color(235,10,15), \"[PH: Enhanced]\", Color(220,220,220), \" There is no room to change that prop!\")")
else
GAMEMODE:PlayerExchangeProp(ply, Prop)
end
end
ply.UseTime = CurTime() + 1
end
]]
-- OBSOLETE : THIS IS COMMENTED OUT BECAUSE THIS METHOD IS SILLY AND SHOULD NOT BE USED. --yeah kind of my fault! >.<
end)
-- Called when player presses [F3]. Plays a taunt for their team
function GM:ShowSpare1(pl)
if (GetConVar("ph_enable_custom_taunts"):GetInt() == 1) && GAMEMODE:InRound() then
pl:ConCommand("ph_showtaunts")
end
if ((GetConVar("ph_enable_custom_taunts"):GetInt() == 0) or (GetConVar("ph_enable_custom_taunts"):GetInt() == 2)) && GAMEMODE:InRound() && pl:Alive() && (pl:Team() == TEAM_HUNTERS || pl:Team() == TEAM_PROPS) && pl.last_taunt_time + GetConVar("ph_normal_taunt_delay"):GetInt() <= CurTime() && (table.Count(PHE.PROP_TAUNTS) > 1 && table.Count(PHE.HUNTER_TAUNTS) > 1) then
local curTeamTaunt = {
hunter = PHE:GetAllTeamTaunt(TEAM_HUNTERS),
prop = PHE:GetAllTeamTaunt(TEAM_PROPS)
}
-- play the taunts based on listed curCustTaunt available.
repeat
if pl:Team() == TEAM_HUNTERS then
rand_taunt = table.Random(curTeamTaunt.hunter)
else
rand_taunt = table.Random(curTeamTaunt.prop)
end
until rand_taunt != pl.last_taunt
pl.last_taunt_time = CurTime() + GetConVar("ph_normal_taunt_delay"):GetInt()
pl.last_taunt = rand_taunt
pl:EmitSound(rand_taunt, 100)
pl:SetNWFloat("LastTauntTime", CurTime())
end
end
-- Called when a player leaves
function PlayerDisconnected(pl)
pl:RemoveProp()
end
hook.Add("PlayerDisconnected", "PH_PlayerDisconnected", PlayerDisconnected)
-- Set specific variable for checking in player initial spawn, then use Player:IsHoldingEntity()
hook.Add("PlayerInitialSpawn", "PHE.SetupInitData", function(ply)
ply.LastPickupEnt = NULL
ply.UseTime = 0
end)
hook.Add("AllowPlayerPickup", "PHE.IsHoldingEntity", function(ply,ent)
ply.LastPickupEnt = ent
ent.LastPickupPly = ply
end)
-- Spray Controls
hook.Add( "PlayerSpray", "PH.GeneralSprayFunc", function( ply )
if ( ( !ply:Alive() ) || ( ply:Team() == TEAM_SPECTATOR ) ) then
return true
end
end )
-- Called when the players spawns
function PlayerSpawn(pl)
pl:SetNWBool("PlayerLockedRotation", false)
pl:SetNWBool("InFreezeCam", false)
pl:SetNWEntity("PlayerKilledByPlayerEntity", nil)
pl:Blind(false)
pl:RemoveProp()
pl:SetColor(Color(255,255,255,255))
pl:SetRenderMode(RENDERMODE_TRANSALPHA)
pl:UnLock()
pl:ResetHull()
pl:SetNWFloat("LastTauntTime", CurTime())
pl.last_taunt_time = 0
net.Start("ResetHull")
net.Send(pl)
net.Start("DisableDynamicLight")
net.Send(pl)
pl:SetCollisionGroup(COLLISION_GROUP_PASSABLE_DOOR)
pl:CollisionRulesChanged()
if pl:Team() == TEAM_HUNTERS then
pl:SetJumpPower(160)
elseif pl:Team() == TEAM_PROPS then
pl:SetJumpPower(160 * GetConVar("ph_prop_jumppower"):GetFloat())
end
-- Listen server host
if !game.IsDedicated() then
pl:SetNWBool("ListenServerHost", pl:IsListenServerHost())
end
end
hook.Add("PlayerSpawn", "PH_PlayerSpawn", PlayerSpawn)
-- Called when round ends
function RoundEnd()
-- Unblind the hunters
for _, pl in pairs(team.GetPlayers(TEAM_HUNTERS)) do
pl:Blind(false)
pl:UnLock()
end
-- Stop autotaunting
net.Start("AutoTauntRoundEnd")
net.Broadcast()
end
hook.Add("PH_RoundEnd", "PH.ForceHuntersUnblind", RoundEnd)
-- This is called when the round time ends (props win)
function GM:RoundTimerEnd()
if !GAMEMODE:InRound() then
return
end
GAMEMODE:RoundEndWithResult(TEAM_PROPS, "Props win!")
PHE.VOICE_IS_END_ROUND = 1
ForceCloseTauntWindow(1)
net.Start("PH_TeamWinning_Snd")
net.WriteString(PHE.WINNINGSOUNDS[TEAM_PROPS])
net.Broadcast()
hook.Call("PH_OnTimerEnd", nil)
end
-- Called before start of round
function GM:OnPreRoundStart(num)
game.CleanUpMap()
if GetGlobalInt("RoundNumber") != 1 && (GetConVar("ph_swap_teams_every_round"):GetInt() == 1 || ((team.GetScore(TEAM_PROPS) + team.GetScore(TEAM_HUNTERS)) > 0)) then
for _, pl in pairs(player.GetAll()) do
if pl:Team() == TEAM_PROPS || pl:Team() == TEAM_HUNTERS then
if pl:Team() == TEAM_PROPS then
pl:SetTeam(TEAM_HUNTERS)
else
pl:SetTeam(TEAM_PROPS)
if GetConVar("ph_notice_prop_rotation"):GetBool() then
timer.Simple(0.5, function() pl:SendLua( [[notification.AddLegacy("You are in Prop Team with Rotate support! You can rotate the prop around by moving your mouse.", NOTIFY_UNDO, 20 )]] ) end)
pl:SendLua( [[notification.AddLegacy("Additionally you can toggle lock rotation by pressing R key!", NOTIFY_GENERIC, 18 )]] )
pl:SendLua( [[surface.PlaySound("garrysmod/content_downloaded.wav")]] )
end
end
pl:ChatPrint("Teams have been swapped!")
end
end
-- Props will gain a Bonus Armor points Hunter teams has more than 4 players in it. The more player, the more armor they get.
timer.Simple(1, function()
local NumHunter = table.Count(team.GetPlayers(TEAM_HUNTERS))
if NumHunter >= 4 && NumHunter <= 8 then
for _,prop in pairs(team.GetPlayers(TEAM_PROPS)) do
if IsValid(prop) then prop:SetArmor(math.random(1,3) * 15) end
end
elseif NumHunter > 8 then
for _,prop in pairs(team.GetPlayers(TEAM_PROPS)) do
if IsValid(prop) then prop:SetArmor(math.random(3,7) * 15) end
end
end
end)
hook.Call("PH_OnPreRoundStart", nil, GetConVar("ph_swap_teams_every_round"):GetInt())
end
UTIL_StripAllPlayers()
UTIL_SpawnAllPlayers()
UTIL_FreezeAllPlayers()
end
-- Called every server tick.
function GM:Think()
-- Prop spectating is a bit messy so let us clean it up a bit
if PHE.SPECTATOR_CHECK < CurTime() then
for _, pl in pairs(team.GetPlayers(TEAM_PROPS)) do
if IsValid(pl) && !pl:Alive() && pl:GetObserverMode() == OBS_MODE_IN_EYE then
hook.Call("ChangeObserverMode", GAMEMODE, pl, OBS_MODE_ROAMING)
end
end
PHE.SPECTATOR_CHECK = CurTime() + PHE.SPECTATOR_CHECK_ADD
end
end
-- Bonus Drop :D
function PH_Props_OnBreak(ply, ent)
if GetConVar("ph_enable_lucky_balls"):GetBool() then
local pos = ent:GetPos()
if math.random() < 0.08 then -- 8% Chance of drops.
local dropent = ents.Create("ph_luckyball")
dropent:SetPos(Vector(pos.x, pos.y, pos.z + 32)) -- to make sure the Lucky Ball didn't fall underground.
dropent:SetAngles(Angle(0,0,0))
dropent:SetColor(Color(math.Round(math.random(0,255)),math.Round(math.random(0,255)),math.Round(math.random(0,255)),255))
dropent:Spawn()
end
end
end
hook.Add("PropBreak", "Props_OnBreak_WithDrops", PH_Props_OnBreak)
-- Force Close the Taunt Menu whenever the prop is being killed.
function close_PlayerKilledSilently(ply)
if ply:Team() == TEAM_PROPS then
net.Start( "PH_ForceCloseTauntWindow" )
net.Send(ply)
end
end
hook.Add("PlayerSilentDeath", "SilentDed_ForceClose", close_PlayerKilledSilently)
-- Flashlight toggling
function GM:PlayerSwitchFlashlight(pl, on)
if pl:Alive() && pl:Team() == TEAM_HUNTERS then
return true
end
if pl:Alive() && pl:Team() == TEAM_PROPS then
net.Start("PlayerSwitchDynamicLight")
net.Send(pl)
end
return false
end
-- Round Control
cvars.AddChangeCallback("ph_min_waitforplayers", function(cvar, old, new)
if tonumber(new) < 1 then
RunConsoleCommand("ph_min_waitforplayers", "1")
print("[PH:E] Warning: Value must not be 0! Use ph_waitforplayers 0 to disable.")
end
end)
local bAlreadyStarted = false
function GM:OnRoundEnd( num )
-- Check if GetConVar("ph_waitforplayers"):GetBool() is true
-- This is a fast implementation for a waiting system
-- Make optimisations if needed
if ( GetConVar("ph_waitforplayers"):GetBool() ) then
-- Take away a round number quickly before it adds another when there are not enough players
-- Set to false
if ( ( team.NumPlayers( TEAM_HUNTERS ) < GetConVar("ph_min_waitforplayers"):GetInt() ) || ( team.NumPlayers( TEAM_PROPS ) < GetConVar("ph_min_waitforplayers"):GetInt() ) ) then
bAlreadyStarted = false
end
-- Set to true
if ( ( team.NumPlayers( TEAM_HUNTERS ) >= GetConVar("ph_min_waitforplayers"):GetInt() ) && ( team.NumPlayers( TEAM_PROPS ) >= GetConVar("ph_min_waitforplayers"):GetInt() ) ) then
bAlreadyStarted = true
end
-- Check if the round was already started before so we count it as a fully played round
if ( !bAlreadyStarted ) then
SetGlobalInt( "RoundNumber", GetGlobalInt("RoundNumber") - 1 )
end
end
hook.Call("PH_OnRoundEnd", nil, num)
end
function GM:RoundStart()
local roundNum = GetGlobalInt( "RoundNumber" );
local roundDuration = GAMEMODE:GetRoundTime( roundNum )
GAMEMODE:OnRoundStart( roundNum )
timer.Create( "RoundEndTimer", roundDuration, 0, function() GAMEMODE:RoundTimerEnd() end )
timer.Create( "CheckRoundEnd", 1, 0, function() GAMEMODE:CheckRoundEnd() end )
SetGlobalFloat( "RoundEndTime", CurTime() + roundDuration );
-- Check if GetConVar("ph_waitforplayers"):GetBool() is true
-- This is a fast implementation for a waiting system
-- Make optimisations if needed
if ( GetConVar("ph_waitforplayers"):GetBool() ) then
-- Pause these timers if there are not enough players on the teams in the server
if ( ( team.NumPlayers( TEAM_HUNTERS ) < GetConVar("ph_min_waitforplayers"):GetInt() ) || ( team.NumPlayers( TEAM_PROPS ) < GetConVar("ph_min_waitforplayers"):GetInt() ) ) then
if ( timer.Exists( "RoundEndTimer" ) && timer.Exists( "CheckRoundEnd" ) ) then
timer.Pause( "RoundEndTimer" )
timer.Pause( "CheckRoundEnd" )
SetGlobalFloat( "RoundEndTime", -1 );
PrintMessage( HUD_PRINTTALK, "There's not enough players to start the game!" )
-- Reset the team score
team.SetScore(TEAM_PROPS, 0)
team.SetScore(TEAM_HUNTERS, 0)
end
end
end
-- Send this as a global boolean
SetGlobalBool( "RoundWaitForPlayers", GetConVar("ph_waitforplayers"):GetBool() )
hook.Call("PH_RoundStart", nil)
end
-- End of Round Control Override
-- Player pressed a key
function PlayerPressedKey(pl, key)
-- Use traces to select a prop
local min,max = pl:GetHull()
if pl && pl:IsValid() && pl:Alive() && pl:Team() == TEAM_PROPS then
plhullz = max.z
if key == IN_ATTACK then
local trace = {}
if plhullz < 24 then
trace.start = pl:EyePos() + Vector(0, 0, plhullz + (24- plhullz))
trace.endpos = pl:EyePos() + Vector(0, 0, plhullz + (24 - plhullz)) + pl:EyeAngles():Forward() * 100
elseif plhullz > 84 then
trace.start = pl:EyePos() + Vector(0, 0, plhullz - 84)
trace.endpos = pl:EyePos() + Vector(0, 0, plhullz - 84) + pl:EyeAngles():Forward() * 300
else
trace.start = pl:EyePos() + Vector(0, 0, 8)
trace.endpos = pl:EyePos() + Vector(0, 0, 8) + pl:EyeAngles():Forward() * 100
end
trace.filter = ents.FindByClass("ph_prop")
local trace2 = util.TraceLine(trace)
if trace2.Entity && trace2.Entity:IsValid() && table.HasValue(PHE.USABLE_PROP_ENTITIES, trace2.Entity:GetClass()) then
if pl.UseTime <= CurTime() then
if !pl:IsHoldingEntity() then
local hmx, hz = trace2.Entity:GetPropSize()
if GetConVar("phe_check_props_boundaries"):GetBool() && !pl:CheckHull(hmx, hmx, hz) then
pl:SendLua("chat.AddText(Color(235, 10, 15), \"[PH: Enhanced]\", Color(220, 220, 220), \" There is no room to change that prop!\")")
else
GAMEMODE:PlayerExchangeProp(pl, trace2.Entity)
end
end
pl.UseTime = CurTime() + 1
end
end
end
end
-- Prop rotation lock key
if pl && pl:IsValid() && pl:Alive() && pl:Team() == TEAM_PROPS then
if key == IN_RELOAD then
if pl:GetPlayerLockedRot() then
pl:SetNWBool("PlayerLockedRotation", false)
pl:PrintMessage(HUD_PRINTCENTER, "Prop Rotation Lock: Disabled")
net.Start("PHE.rotateState")
net.WriteInt(0, 2)
net.Send(pl)
else
pl:SetNWBool("PlayerLockedRotation", true)
pl:PrintMessage(HUD_PRINTCENTER, "Prop Rotation Lock: Enabled")
net.Start("PHE.rotateState")
net.WriteInt(1, 2)
net.Send(pl)
end
end
end
end
hook.Add("KeyPress", "PlayerPressedKey", PlayerPressedKey)

View File

@@ -0,0 +1,329 @@
surface.CreateFont("RAM_VoteFont", {
font = "Trebuchet MS",
size = 19,
weight = 700,
antialias = true,
shadow = true
})
surface.CreateFont("RAM_VoteFontCountdown", {
font = "Tahoma",
size = 32,
weight = 700,
antialias = true,
shadow = true
})
surface.CreateFont("RAM_VoteSysButton",
{ font = "Marlett",
size = 13,
weight = 0,
symbol = true,
})
MapVote.EndTime = 0
MapVote.Panel = false
net.Receive("RAM_MapVoteStart", function()
MapVote.CurrentMaps = {}
MapVote.Allow = true
MapVote.Votes = {}
local amt = net.ReadUInt(32)
for i = 1, amt do
local map = net.ReadString()
MapVote.CurrentMaps[#MapVote.CurrentMaps + 1] = map
end
MapVote.EndTime = CurTime() + net.ReadUInt(32)
if(IsValid(MapVote.Panel)) then
MapVote.Panel:Remove()
end
MapVote.Panel = vgui.Create("VoteScreen")
MapVote.Panel:SetMaps(MapVote.CurrentMaps)
end)
net.Receive("RAM_MapVoteUpdate", function()
local update_type = net.ReadUInt(3)
if(update_type == MapVote.UPDATE_VOTE) then
local ply = net.ReadEntity()
if(IsValid(ply)) then
local map_id = net.ReadUInt(32)
MapVote.Votes[ply:SteamID()] = map_id
if(IsValid(MapVote.Panel)) then
MapVote.Panel:AddVoter(ply)
end
end
elseif(update_type == MapVote.UPDATE_WIN) then
if(IsValid(MapVote.Panel)) then
MapVote.Panel:Flash(net.ReadUInt(32))
end
end
end)
net.Receive("RAM_MapVoteCancel", function()
if IsValid(MapVote.Panel) then
MapVote.Panel:Remove()
end
end)
net.Receive("RTV_Delay", function()
chat.AddText(Color( 102,255,51 ), "[RTV]", Color( 255,255,255 ), " The vote has been rocked, map vote will begin on round end")
end)
local PANEL = {}
function PANEL:Init()
self:ParentToHUD()
self.Canvas = vgui.Create("Panel", self)
self.Canvas:MakePopup()
self.Canvas:SetKeyboardInputEnabled(false)
self.countDown = vgui.Create("DLabel", self.Canvas)
self.countDown:SetTextColor(color_white)
self.countDown:SetFont("RAM_VoteFontCountdown")
self.countDown:SetText("")
self.countDown:SetPos(0, 14)
self.mapList = vgui.Create("DPanelList", self.Canvas)
self.mapList:SetDrawBackground(false)
self.mapList:SetSpacing(4)
self.mapList:SetPadding(4)
self.mapList:EnableHorizontal(true)
self.mapList:EnableVerticalScrollbar()
self.closeButton = vgui.Create("DButton", self.Canvas)
self.closeButton:SetText("")
self.closeButton.Paint = function(panel, w, h)
derma.SkinHook("Paint", "WindowCloseButton", panel, w, h)
end
self.closeButton.DoClick = function()
print("MapVote has started...")
self:SetVisible(false)
end
self.maximButton = vgui.Create("DButton", self.Canvas)
self.maximButton:SetText("")
self.maximButton:SetDisabled(true)
self.maximButton.Paint = function(panel, w, h)
derma.SkinHook("Paint", "WindowMaximizeButton", panel, w, h)
end
self.minimButton = vgui.Create("DButton", self.Canvas)
self.minimButton:SetText("")
self.minimButton:SetDisabled(true)
self.minimButton.Paint = function(panel, w, h)
derma.SkinHook("Paint", "WindowMinimizeButton", panel, w, h)
end
self.Voters = {}
end
function PANEL:PerformLayout()
local cx, cy = chat.GetChatBoxPos()
self:SetPos(0, 0)
self:SetSize(ScrW(), ScrH())
local extra = math.Clamp(300, 0, ScrW() - 640)
self.Canvas:StretchToParent(0, 0, 0, 0)
self.Canvas:SetWide(640 + extra)
// self.Canvas:SetTall(cy -60)
self.Canvas:SetTall(640)
self.Canvas:SetPos(0, 0)
self.Canvas:CenterHorizontal()
self.Canvas:SetZPos(0)
self.mapList:StretchToParent(0, 90, 0, 0)
local buttonPos = 640 + extra - 31 * 3
self.closeButton:SetPos(buttonPos - 31 * 0, 4)
self.closeButton:SetSize(31, 31)
self.closeButton:SetVisible(true)
self.maximButton:SetPos(buttonPos - 31 * 1, 4)
self.maximButton:SetSize(31, 31)
self.maximButton:SetVisible(true)
self.minimButton:SetPos(buttonPos - 31 * 2, 4)
self.minimButton:SetSize(31, 31)
self.minimButton:SetVisible(true)
end
local heart_mat = Material("icon16/heart.png")
local star_mat = Material("icon16/star.png")
local shield_mat = Material("icon16/shield.png")
function PANEL:AddVoter(voter)
for k, v in pairs(self.Voters) do
if(v.Player and v.Player == voter) then
return false
end
end
local icon_container = vgui.Create("Panel", self.mapList:GetCanvas())
local icon = vgui.Create("AvatarImage", icon_container)
icon:SetSize(16, 16)
icon:SetZPos(1000)
icon:SetTooltip(voter:Name())
icon_container.Player = voter
icon_container:SetTooltip(voter:Name())
icon:SetPlayer(voter, 16)
if MapVote.HasExtraVotePower(voter) then
icon_container:SetSize(40, 20)
icon:SetPos(21, 2)
icon_container.img = star_mat
else
icon_container:SetSize(20, 20)
icon:SetPos(2, 2)
end
icon_container.Paint = function(s, w, h)
draw.RoundedBox(4, 0, 0, w, h, Color(255, 0, 0, 80))
if(icon_container.img) then
surface.SetMaterial(icon_container.img)
surface.SetDrawColor(Color(255, 255, 255))
surface.DrawTexturedRect(2, 2, 16, 16)
end
end
table.insert(self.Voters, icon_container)
end
function PANEL:Think()
for k, v in pairs(self.mapList:GetItems()) do
v.NumVotes = 0
end
for k, v in pairs(self.Voters) do
if(not IsValid(v.Player)) then
v:Remove()
else
if(not MapVote.Votes[v.Player:SteamID()]) then
v:Remove()
else
local bar = self:GetMapButton(MapVote.Votes[v.Player:SteamID()])
if(MapVote.HasExtraVotePower(v.Player)) then
bar.NumVotes = bar.NumVotes + 2
else
bar.NumVotes = bar.NumVotes + 1
end
if(IsValid(bar)) then
local CurrentPos = Vector(v.x, v.y, 0)
local NewPos = Vector((bar.x + bar:GetWide()) - 21 * bar.NumVotes - 2, bar.y + (bar:GetTall() * 0.5 - 10), 0)
if(not v.CurPos or v.CurPos ~= NewPos) then
v:MoveTo(NewPos.x, NewPos.y, 0.3)
v.CurPos = NewPos
end
end
end
end
end
local timeLeft = math.Round(math.Clamp(MapVote.EndTime - CurTime(), 0, math.huge))
self.countDown:SetText(tostring(timeLeft or 0).." seconds")
self.countDown:SizeToContents()
self.countDown:CenterHorizontal()
end
function PANEL:SetMaps(maps)
self.mapList:Clear()
for k, v in RandomPairs(maps) do
local button = vgui.Create("DButton", self.mapList)
button.ID = k
button:SetText(v)
button.DoClick = function()
net.Start("RAM_MapVoteUpdate")
net.WriteUInt(MapVote.UPDATE_VOTE, 3)
net.WriteUInt(button.ID, 32)
net.SendToServer()
end
do
local Paint = button.Paint
button.Paint = function(s, w, h)
local col = Color(255, 255, 255, 10)
if(button.bgColor) then
col = button.bgColor
end
draw.RoundedBox(4, 0, 0, w, h, col)
Paint(s, w, h)
end
end
button:SetTextColor(color_white)
button:SetContentAlignment(4)
button:SetTextInset(8, 0)
button:SetFont("RAM_VoteFont")
local extra = math.Clamp(300, 0, ScrW() - 640)
button:SetDrawBackground(false)
button:SetTall(24)
button:SetWide(285 + (extra / 2))
button.NumVotes = 0
self.mapList:AddItem(button)
end
end
function PANEL:GetMapButton(id)
for k, v in pairs(self.mapList:GetItems()) do
if(v.ID == id) then return v end
end
return false
end
function PANEL:Paint()
--Derma_DrawBackgroundBlur(self)
local CenterY = ScrH() / 2
local CenterX = ScrW() / 2
surface.SetDrawColor(0, 0, 0, 200)
surface.DrawRect(0, 0, ScrW(), ScrH())
end
function PANEL:Flash(id)
self:SetVisible(true)
local bar = self:GetMapButton(id)
if(IsValid(bar)) then
timer.Simple( 0.0, function() bar.bgColor = Color( 0, 255, 255 ) surface.PlaySound( "hl1/fvox/blip.wav" ) end )
timer.Simple( 0.2, function() bar.bgColor = nil end )
timer.Simple( 0.4, function() bar.bgColor = Color( 0, 255, 255 ) surface.PlaySound( "hl1/fvox/blip.wav" ) end )
timer.Simple( 0.6, function() bar.bgColor = nil end )
timer.Simple( 0.8, function() bar.bgColor = Color( 0, 255, 255 ) surface.PlaySound( "hl1/fvox/blip.wav" ) end )
timer.Simple( 1.0, function() bar.bgColor = Color( 100, 100, 100 ) end )
end
end
derma.DefineControl("VoteScreen", "", PANEL, "DPanel")

View File

@@ -0,0 +1,114 @@
RTV = RTV or {}
RTV.ChatCommands = {
"!rtv",
"/rtv",
"rtv"
}
RTV.TotalVotes = 0
RTV.Wait = 60 -- The wait time in seconds. This is how long a player has to wait before voting when the map changes.
RTV._ActualWait = CurTime() + RTV.Wait
RTV.PlayerCount = MapVote.Config.RTVPlayerCount or 3
function RTV.ShouldChange()
return RTV.TotalVotes >= math.Round(#player.GetAll()*0.66)
end
function RTV.RemoveVote()
RTV.TotalVotes = math.Clamp( RTV.TotalVotes - 1, 0, math.huge )
end
function RTV.Start()
PrintMessage( HUD_PRINTTALK, "The vote has been rocked, map vote imminent")
timer.Simple(4, function()
MapVote.Start(nil, nil, nil, nil)
end)
end
function RTV.AddVote( ply )
if RTV.CanVote( ply ) then
RTV.TotalVotes = RTV.TotalVotes + 1
ply.RTVoted = true
MsgN( ply:Nick().." has voted to Rock the Vote." )
PrintMessage( HUD_PRINTTALK, ply:Nick().." has voted to Rock the Vote. ("..RTV.TotalVotes.."/"..math.Round(#player.GetAll()*0.66)..")" )
if RTV.ShouldChange() then
RTV.Start()
end
end
end
hook.Add( "PlayerDisconnected", "Remove RTV", function( ply )
if ply.RTVoted then
RTV.RemoveVote()
end
timer.Simple( 0.1, function()
if (#player.GetAll() < 1 && !GetConVar("mv_change_when_no_player"):GetBool()) then
print("MapVote: There is no player to force change map...")
else
if RTV.ShouldChange() then
RTV.Start()
end
end
end )
end )
function RTV.CanVote( ply )
local plyCount = table.Count(player.GetAll())
if RTV._ActualWait >= CurTime() then
return false, "You must wait a bit before voting!"
end
if GetGlobalBool( "In_Voting" ) then
return false, "There is currently a vote in progress!"
end
if ply.RTVoted then
return false, "You have already voted to Rock the Vote!"
end
if RTV.ChangingMaps then
return false, "There has already been a vote, the map is going to change!"
end
if plyCount < RTV.PlayerCount then
return false, "You need more players before you can rock the vote!"
end
return true
end
function RTV.StartVote( ply )
local can, err = RTV.CanVote(ply)
if not can then
ply:PrintMessage( HUD_PRINTTALK, err )
return
end
RTV.AddVote( ply )
end
concommand.Add( "rtv_start", RTV.StartVote )
hook.Add( "PlayerSay", "RTV Chat Commands", function( ply, text )
if table.HasValue( RTV.ChatCommands, string.lower(text) ) then
RTV.StartVote( ply )
return ""
end
end )

View File

@@ -0,0 +1,257 @@
util.AddNetworkString("RAM_MapVoteStart")
util.AddNetworkString("RAM_MapVoteUpdate")
util.AddNetworkString("RAM_MapVoteCancel")
util.AddNetworkString("RTV_Delay")
MapVote.Continued = false
net.Receive("RAM_MapVoteUpdate", function(len, ply)
if(MapVote.Allow) then
if(IsValid(ply)) then
local update_type = net.ReadUInt(3)
if(update_type == MapVote.UPDATE_VOTE) then
local map_id = net.ReadUInt(32)
if(MapVote.CurrentMaps[map_id]) then
MapVote.Votes[ply:SteamID()] = map_id
net.Start("RAM_MapVoteUpdate")
net.WriteUInt(MapVote.UPDATE_VOTE, 3)
net.WriteEntity(ply)
net.WriteUInt(map_id, 32)
net.Broadcast()
end
end
end
end
end)
if file.Exists( "mapvote/recentmaps.txt", "DATA" ) then
recentmaps = util.JSONToTable(file.Read("mapvote/recentmaps.txt", "DATA"))
else
recentmaps = {}
end
if ConVarExists("mv_maplimit") then
printVerbose("[MapVote] Loading ConVars...")
MapVote.Config = {
MapLimit = GetConVar("mv_maplimit"):GetInt(),
TimeLimit = GetConVar("mv_timelimit"):GetInt(),
AllowCurrentMap = GetConVar("mv_allowcurmap"):GetBool(),
EnableCooldown = GetConVar("mv_cooldown"):GetBool(),
MapsBeforeRevote = GetConVar("mv_mapbeforerevote"):GetBool(),
RTVPlayerCount = GetConVar("mv_rtvcount"):GetInt(),
MapPrefixes = string.Explode(",", GetConVar("mv_mapprefix"):GetString():lower())
}
else
MapVote.Config = {}
end
local conv = {
["mv_maplimit"] = function(cvar,old,new)
if new && (new != nil || new != "") then
MapVote.Config.MapLimit = tonumber(new)
end
end,
["mv_timelimit"] = function(cvar,old,new)
if new && (new != nil || new != "") then
MapVote.Config.TimeLimit = tonumber(new)
end
end,
["mv_allowcurmap"] = function(cvar,old,new)
if new && (new != nil || new != "") then
MapVote.Config.AllowCurrentMap = tobool(new)
end
end,
["mv_cooldown"] = function(cvar,old,new)
if new && (new != nil || new != "") then
MapVote.Config.EnableCooldown = tobool(new)
end
end,
["mv_mapbeforerevote"] = function(cvar,old,new)
if new && (new != nil || new != "") then
MapVote.Config.MapsBeforeRevote = tobool(new)
end
end,
["mv_rtvcount"] = function(cvar,old,new)
if new && (new != nil || new != "") then
MapVote.Config.RTVPlayerCount = tonumber(new)
end
end,
["mv_mapprefix"] = function(cvar,old,new)
if new && (new != nil || new != "") then
MapVote.Config.MapPrefixes = string.Explode(",", new:lower())
end
end
}
-- Precheck when the convar is changed
for cvar,func in pairs(conv) do
printVerbose("[MapVote] Adding ConVar Callbacks for: "..cvar)
cvars.AddChangeCallback(cvar, func)
end
function CoolDownDoStuff()
cooldownnum = MapVote.Config.MapsBeforeRevote or 3
if table.getn(recentmaps) == cooldownnum then
table.remove(recentmaps)
end
local curmap = game.GetMap():lower()..".bsp"
if not table.HasValue(recentmaps, curmap) then
table.insert(recentmaps, 1, curmap)
end
file.Write("mapvote/recentmaps.txt", util.TableToJSON(recentmaps))
end
function MapVote.GetFromULX()
if (ulx == nil) then
print("[!PH: Enhanced] Warning: ULX is not installed!")
return false
end
if (ulx.votemaps) then
return ulx.votemaps
end
end
function MapVote.Start(length, current, limit, prefix)
current = current or MapVote.Config.AllowCurrentMap or false
length = length or MapVote.Config.TimeLimit or 28
limit = limit or MapVote.Config.MapLimit or 24
cooldown = MapVote.Config.EnableCooldown or true
prefix = prefix or MapVote.Config.MapPrefixes
local is_expression = false
local ulxmap = MapVote.GetFromULX()
if not prefix then
local info = file.Read(GAMEMODE.Folder.."/"..GAMEMODE.FolderName..".txt", "GAME")
if(info) then
local info = util.KeyValuesToTable(info)
prefix = info.maps
else
error("MapVote Prefix can not be loaded from gamemode")
end
is_expression = true
else
if prefix and type(prefix) ~= "table" then
prefix = {prefix}
end
end
local maps = {}
if GetConVar("mv_use_ulx_votemaps"):GetBool() && ulxmap ~= false then
for _,map in pairs(ulxmap) do
table.insert(maps, map..".bsp")
end
else
maps = file.Find("maps/*.bsp", "GAME")
end
local vote_maps = {}
local amt = 0
for k, map in RandomPairs(maps) do
local mapstr = map:sub(1, -5):lower()
if(not current and game.GetMap():lower()..".bsp" == map) then continue end
if(cooldown and table.HasValue(recentmaps, map)) then continue end
if is_expression then
if(string.find(map, prefix)) then -- This might work (from gamemode.txt)
vote_maps[#vote_maps + 1] = map:sub(1, -5)
amt = amt + 1
end
else
for k, v in pairs(prefix) do
if string.find(map, "^"..v) then
vote_maps[#vote_maps + 1] = map:sub(1, -5)
amt = amt + 1
break
end
end
end
if(limit and amt >= limit) then break end
end
net.Start("RAM_MapVoteStart")
net.WriteUInt(#vote_maps, 32)
for i = 1, #vote_maps do
net.WriteString(vote_maps[i])
end
net.WriteUInt(length, 32)
net.Broadcast()
MapVote.Allow = true
MapVote.CurrentMaps = vote_maps
MapVote.Votes = {}
timer.Create("RAM_MapVote", length, 1, function()
MapVote.Allow = false
local map_results = {}
for k, v in pairs(MapVote.Votes) do
if(not map_results[v]) then
map_results[v] = 0
end
for k2, v2 in pairs(player.GetAll()) do
if(v2:SteamID() == k) then
if(MapVote.HasExtraVotePower(v2)) then
map_results[v] = map_results[v] + 2
else
map_results[v] = map_results[v] + 1
end
end
end
end
CoolDownDoStuff()
local winner = table.GetWinningKey(map_results) or 1
net.Start("RAM_MapVoteUpdate")
net.WriteUInt(MapVote.UPDATE_WIN, 3)
net.WriteUInt(winner, 32)
net.Broadcast()
local map = MapVote.CurrentMaps[winner]
timer.Simple(4, function()
hook.Run("MapVoteChange", map)
RunConsoleCommand("changelevel", map)
end)
end)
end
hook.Add( "Shutdown", "RemoveRecentMaps", function()
if file.Exists( "mapvote/recentmaps.txt", "DATA" ) then
file.Delete( "mapvote/recentmaps.txt" )
end
end )
function MapVote.Cancel()
if MapVote.Allow then
MapVote.Allow = false
net.Start("RAM_MapVoteCancel")
net.Broadcast()
timer.Destroy("RAM_MapVote")
end
end

View File

@@ -0,0 +1,106 @@
-- Create new class
local CLASS = {}
-- Some settings for the class
CLASS.DisplayName = "Hunter"
CLASS.WalkSpeed = 230
CLASS.CrouchedWalkSpeed = 0.4
CLASS.RunSpeed = 290
CLASS.DuckSpeed = 0.2
CLASS.DrawTeamRing = false
-- Called by spawn and sets loadout
function CLASS:Loadout(pl)
pl:GiveAmmo(32, "Buckshot")
pl:GiveAmmo(255, "SMG1")
pl:GiveAmmo(12, "357")
pl:Give("weapon_crowbar")
pl:Give("weapon_shotgun")
pl:Give("weapon_smg1")
pl:Give("item_ar2_grenade")
pl:Give("weapon_357")
local cl_defaultweapon = pl:GetInfo("cl_defaultweapon")
if pl:HasWeapon(cl_defaultweapon) then
pl:SelectWeapon(cl_defaultweapon)
end
end
-- Called when player spawns with this class
function CLASS:OnSpawn(pl)
if !pl:IsValid() then return end
pl:SetupHands()
pl:SetCustomCollisionCheck(true)
pl:SetAvoidPlayers(false)
pl:CrosshairEnable()
pl:SetViewOffset(Vector(0,0,64))
pl:SetViewOffsetDucked(Vector(0,0,28))
local unlock_time = math.Clamp(GetConVar("ph_hunter_blindlock_time"):GetInt() - (CurTime() - GetGlobalFloat("RoundStartTime", 0)), 0, GetConVar("ph_hunter_blindlock_time"):GetInt())
local unblindfunc = function()
if pl:IsValid() then
pl:Blind(false)
end
end
local lockfunc = function()
if pl:IsValid() then
pl.Lock(pl)
end
end
local unlockfunc = function()
if pl:IsValid() then
pl.UnLock(pl)
end
end
if unlock_time > 2 then
pl:Blind(true)
timer.Simple(unlock_time, unblindfunc)
timer.Simple(2, lockfunc)
timer.Simple(unlock_time, unlockfunc)
end
end
-- Hands
function CLASS:GetHandsModel()
if !GetConVar("ph_use_custom_plmodel"):GetBool() then
return { model = "models/weapons/c_arms_combine.mdl", skin = 1, body = "0100000" }
end
end
-- Called when a player dies with this class
function CLASS:OnDeath(pl, attacker, dmginfo)
pl:CreateRagdoll()
pl:UnLock()
-- Always Reset the ViewOffset
pl:SetViewOffset(Vector(0,0,64))
pl:SetViewOffsetDucked(Vector(0,0,28))
-- Spawn Devil Ball
local pos = pl:GetPos()
if GetConVar("ph_enable_devil_balls"):GetBool() then
if math.random() < 0.7 then --70% chance.
local dropent = ents.Create("ph_devilball")
dropent:SetPos(Vector(pos.x, pos.y, pos.z + 16)) -- to make sure the Devil Ball didn't fall underground.
dropent:SetAngles(Angle(0,0,0))
dropent:Spawn()
end
end
end
-- Register
player_class.Register("Hunter", CLASS)

View File

@@ -0,0 +1,93 @@
-- Create new class
local CLASS = {}
-- Some settings for the class
CLASS.DisplayName = "Prop"
CLASS.WalkSpeed = 250
CLASS.CrouchedWalkSpeed = 0.2
CLASS.RunSpeed = 275
CLASS.DuckSpeed = 0.2
CLASS.DrawTeamRing = false
-- Prevent 'mod_studio: MOVETYPE_FOLLOW with No Models error.'
CLASS.DrawViewModel = false
-- Called by spawn and sets loadout
function CLASS:Loadout(pl)
-- Props don't get anything
end
-- Called when player spawns with this class
function CLASS:OnSpawn(pl)
pl:SetColor(Color(0,0,0,0))
pl:SetCustomCollisionCheck(true)
pl:SetupHands()
pl:SetAvoidPlayers(true)
pl:CrosshairEnable()
-- Initial Setup during Prop choosing a props. Jump-Duck may still required somehow.
pl:SetViewOffset(Vector(0,0,64))
pl:SetViewOffsetDucked(Vector(0,0,28))
-- Prevent 'mod_studio: MOVETYPE_FOLLOW with No Models error.'
pl:DrawViewModel(false)
pl.ph_prop = ents.Create("ph_prop")
pl.ph_prop:SetPos(pl:GetPos())
pl.ph_prop:SetAngles(pl:GetAngles())
pl.ph_prop:Spawn()
if GetConVar("ph_use_custom_plmodel_for_prop"):GetBool() then
if table.HasValue(PHE.PROP_PLMODEL_BANS, string.lower(player_manager.TranslatePlayerModel(pl:GetInfo("cl_playermodel")))) then
pl.ph_prop:SetModel("models/player/kleiner.mdl")
pl:ChatPrint("Your custom playermodel was banned from Props.")
elseif table.HasValue(PHE.PROP_PLMODEL_BANS, string.lower(pl:GetInfo("cl_playermodel"))) then
pl.ph_prop:SetModel("models/player/kleiner.mdl")
pl:ChatPrint("Your custom playermodel was banned from Props.")
else
pl.ph_prop:SetModel(player_manager.TranslatePlayerModel(pl:GetInfo("cl_playermodel")))
end
end
pl.ph_prop:SetSolid(SOLID_BBOX)
pl.ph_prop:SetOwner(pl)
pl:SetNWEntity("PlayerPropEntity", pl.ph_prop)
-- Delay start the AutoTaunt stuff and Control Tutorial
timer.Simple(1, function()
if IsValid(pl) then
net.Start("AutoTauntSpawn")
net.Send(pl)
net.Start("PH_ShowTutor")
net.Send(pl)
end
end)
pl.ph_prop.max_health = 100
end
-- Hands
function CLASS:GetHandsModel()
return
end
-- Called when a player dies with this class
function CLASS:OnDeath(pl, attacker, dmginfo)
pl:RemoveProp()
-- reset the Prop Rotating State.
net.Start("PHE.rotateState")
net.WriteInt(0, 2)
net.Send(pl)
pl:SetViewOffset(Vector(0,0,64))
pl:SetViewOffsetDucked(Vector(0,0,28))
end
-- Register
player_class.Register("Prop", CLASS)

View File

@@ -0,0 +1,421 @@
-- Global Var for custom taunt, delivering from taunts/prop -or- hunter_taunts.lua
PHE.PH_TAUNT_CUSTOM = {}
PHE.PH_TAUNT_CUSTOM.PROP = {}
PHE.PH_TAUNT_CUSTOM.HUNTER = {}
-- Time (in seconds) for spectator check (Default: 0.1)
PHE.SPECTATOR_CHECK_ADD = 0.1
PHE.USABLE_PROP_ENTITIES = {
"prop_physics",
"prop_physics_multiplayer"
}
-- Configure your staff admin/mod or donator rank (vip/donator) to the ignore mute list so they cannot be muted for a reason.
PHE.IgnoreMutedUserGroup = {
-- admin
"superadmin",
"admin",
"Owner",
"Co-owner",
-- Misc users
"Developer",
"Moderator",
"Donator",
"VIP"
}
-- Admin Staffs table for sv_admin.lua, which enables to modify gamemode settings under F1 > Prop Hunt Menu > Admin menu.
PHE.SVAdmins = {
"admin",
"superadmin",
"owner"
}
-- Banned Props models
PHE.BANNED_PROP_MODELS = {}
--[[ // DO NOT MODIFY! use from taunts/prop_taunts.lua or hunter_taunts.lua instead! \\ ]]--
PHE.HUNTER_TAUNTS = {
["Come to Papa"] = "taunts/hunters/come_to_papa.wav",
["I am your Father"] = "taunts/hunters/father.wav",
["Need Fire Assistance!"] = "taunts/hunters/fireassis.wav",
["(GlaDOS) President"] = "taunts/hunters/glados-president.wav",
["I am Hit!"] = "taunts/hunters/hitassist.wav",
["How Rude"] = "taunts/hunters/how_rude.wav",
["I will Find You"] = "taunts/hunters/ill_find_you.wav",
["Radio Laugh"] = "taunts/hunters/laugh.wav",
["Now What?"] = "taunts/hunters/now_what.wav",
["You dont have the Soul"] = "taunts/hunters/you_dont_have_the_soul.wav",
["You dont know the Power"] = "taunts/hunters/you_dont_know_the_power.wav",
["You are underestimating"] = "taunts/hunters/you_underestimate_the_power.wav",
["Threat Neutralized"] = "taunts/hunters/threat_neutralized.wav",
["DX: My Vision is Augmented"] = "taunts/ph_enhanced/dx_augmented.wav",
["DX: Im gonna Whoop your Ass"] = "taunts/ph_enhanced/dx_imgonnawoopyourass.wav",
["DX: Dont worry we are cops"] = "taunts/ph_enhanced/dx_dontworrywurcops.wav",
["DX: Heheh"] = "taunts/ph_enhanced/dx_hehe.wav",
["Enough of Mambo Jumbo"] = "vo/npc/male01/vanswer13.wav",
["HACKS"] = "vo/npc/male01/thehacks01.wav",
["Over Here"] = "vo/npc/male01/overhere01.wav",
["Over There"] = "vo/npc/male01/overthere01.wav",
["Over There!!"] = "vo/npc/male01/overthere02.wav"
}
--[[ // DO NOT MODIFY! use from taunts/props_taunts.lua or hunters_taunts.lua instead! \\ ]]--
PHE.PROP_TAUNTS = {
["Run for your Life!"] = "vo/npc/male01/runforyourlife02.wav",
["Bad Boys"] = "taunts/props/bad_boys.wav",
["Not the Bees"] = "taunts/props/bees_fix.wav",
["BillyMays - Are you on the Balls"] = "taunts/props/billymays_areyouontheballs.wav",
["BillyMays - Get on the Balls"] = "taunts/props/billymays_getontheballs.wav",
["BillyMays - I Guarantee It"] = "taunts/props/billymays_iguaranteeit.wav",
["BillyMays - Its so Easy"] = "taunts/props/billymays_itsoeasy.wav",
["BillyMays - Laundry made Easy"] = "taunts/props/billymays_laundrymadeeasy.wav",
["BillyMays - New OxyClean"] = "taunts/props/billymays_newoxyclean.wav",
["BillyMays - No more Detergent"] = "taunts/props/billymays_nomoredetergent.wav",
["BillyMays - Only $9.99"] = "taunts/props/billymays_only9_99.wav",
["BillyMays - OxyClean"] = "taunts/props/billymays_oxyclean.wav",
["BillyMays - So Get on the Balls!"] = "taunts/props/billymays_sogetontheballs.wav",
["Boom, Headshot!"] = "taunts/props/boom_hs.wav",
["Car Horn"] = "taunts/props/car_horn.wav",
["Chicken Hammer"] = "taunts/props/chicken_hammer.wav",
["DOH"] = "taunts/props/doh.wav",
["Force Eliminated"] = "taunts/props/forces_eliminated.wav",
["Go Away or I Shall"] = "taunts/props/go_away_or_i_shall.wav",
["H A R D B A S S"] = "taunts/props/hardbass.wav",
["T R I P O L O S K I"] = "taunts/props/tri_poloski1.wav",
["Poloski Beats"] = "taunts/props/tri_poloski2.wav",
["Nein Nein Nein"] = "taunts/props/nein.wav",
["Ill be back"] = "taunts/props/ill_be_back.wav",
["I am Corn Holio"] = "taunts/props/i_am_cornholio.wav",
["I Am the one and only"] = "taunts/props/i_am_the_one_and_only.wav",
["LEROY JENKINS"] = "taunts/props/leroy_jenkins.wav",
["Oh yeah he will pay"] = "taunts/props/oh_yea_he_will_pay.wav",
["Muffin Man"] = "taunts/props/ok_i_will_tell_you.wav",
["ON ME"] = "taunts/props/on_me.wav",
["Its over 9000"] = "taunts/props/over9000.wav",
["PINGAS"] = "taunts/props/pingas.wav",
["Please Come Again"] = "taunts/props/pls_come_again.wav",
["Pokemon"] = "taunts/props/pokemon.wav",
["Very Retarded Laugh"] = "taunts/props/retarted_laugh.wav",
["Shams Wow"] = "taunts/props/sham_wow.wav",
["This is SPARTA"] = "taunts/props/sparta.wav",
["WATATATATA"] = "taunts/props/watatata.wav",
["What is wrong with you"] = "taunts/props/wrong.wav",
["WROOOONG"] = "taunts/props/wroooong.wav",
["wololo"] = "taunts/props/wololo.wav",
["WooHoo"] = "taunts/props/woohoo.wav",
["DX: Easy Bruh"] = "taunts/ph_enhanced/dx_easy_bruh.wav",
["DX: Hehe"] = "taunts/ph_enhanced/dx_heh.wav",
["DX: I dont Move Out"] = "taunts/ph_enhanced/dx_idonotmoveout.wav",
["DX: You Killed my Friend"] = "taunts/ph_enhanced/dx_iloominarty.wav",
["DX: Leave me alone"] = "taunts/ph_enhanced/dx_leaveme.wav",
["DX: LOOK AT ME"] = "taunts/ph_enhanced/dx_lookatme.wav",
["DX: AAAAAAARGGHHHHHH"] = "taunts/ph_enhanced/dx_molepeople.wav",
["DX: A BOMB"] = "taunts/ph_enhanced/dx_thebomb.wav",
["DX: THE BOMB JC"] = "taunts/ph_enhanced/dx_thebomb2.wav",
["DX: What a Shame"] = "taunts/ph_enhanced/dx_whatashame.wav",
["DX: Whoa #1"] = "taunts/ph_enhanced/dx_whoawhoawhoa_1.wav",
["DX: Whoa #2"] = "taunts/ph_enhanced/dx_whoawhoawhoa_2.wav",
["SPAGHET"] = "taunts/ph_enhanced/ext_spaghet.wav",
["WHO TOUCHA MY SPAGHET"] = "taunts/ph_enhanced/ext_touch_ma_spaghet.wav",
["Do you know the way"] = "taunts/ph_enhanced/ext_do_you_kno_de_wei.wav",
["U have ebola to kno the wei"] = "taunts/ph_enhanced/ext_uhaveebolatoknodewei.wav",
["Angry German Kid"] = "taunts/ph_enhanced/ext_angry_german_kid.wav",
["Vitas: 7th Elements"] = "taunts/ph_enhanced/ext_blablaahah.wav",
["I hate you"] = "taunts/ph_enhanced/ext_crackmod_ihateyou.wav",
["I watch your rear"] = "taunts/ph_enhanced/ext_crackmod_watchyourrear.wav",
["You damn Ugly"] = "taunts/ph_enhanced/ext_crackmod_youareugly.wav",
["Dance Music"] = "taunts/ph_enhanced/ext_dance_music.wav",
["MLG: GET NO SCOPE"] = "taunts/ph_enhanced/ext_get_no_scope.wav",
["MLG: GET THE CAMERA"] = "taunts/ph_enhanced/ext_getcamera.wav",
["MLG: OH ITS TRIPLE"] = "taunts/ph_enhanced/ext_mlg_triple.wav",
["Bicycle Bell"] = "taunts/ph_enhanced/ext_bicycle_bell.wav",
["Ding"] = "taunts/ph_enhanced/ext_cling.wav",
["AND III ALWAYS LOVE YOU"] = "taunts/ph_enhanced/ext_and_iiiiiiiiiiiiiiiiiiii.wav",
["The Rude of Storming Sand"] = "taunts/ph_enhanced/ext_darude.wav",
["deaugh"] = "taunts/ph_enhanced/ext_deaugh.wav",
["CDI Die"] = "taunts/ph_enhanced/ext_die.wav",
["CDI Oah"] = "taunts/ph_enhanced/ext_oah.wav",
["Heres some cash goys"] = "taunts/ph_enhanced/ext_dosh1.wav",
["Loadsam money"] = "taunts/ph_enhanced/ext_dosh2.wav",
["Who needed money"] = "taunts/ph_enhanced/ext_dosh3.wav",
["Money money money"] = "taunts/ph_enhanced/ext_dosh4.wav",
["Dosh grab it while you can"] = "taunts/ph_enhanced/ext_dosh5.wav",
["Dun dun duuuun"] = "taunts/ph_enhanced/ext_dundundun.wav",
["derpy fart"] = "taunts/ph_enhanced/ext_fart1.wav",
["nice fart"] = "taunts/ph_enhanced/ext_fart2.wav",
["auffwauffderp"] = "taunts/ph_enhanced/ext_fdsa.wav",
["Game Over"] = "taunts/ph_enhanced/ext_gameover.wav",
["Game Over mario"] = "taunts/ph_enhanced/ext_gameover_mario.wav",
["Get out of Here stalker"] = "taunts/ph_enhanced/ext_getoutofhere_stalker.wav",
["GET TO THE CHOPPA"] = "taunts/ph_enhanced/ext_get_to_the_choppa.wav",
["Idiots #1"] = "taunts/ph_enhanced/ext_idiots_1.wav",
["Idiots #2"] = "taunts/ph_enhanced/ext_idiots_2.wav",
["This is Illegal"] = "taunts/ph_enhanced/ext_illegal.wav",
["JASONNN"] = "taunts/ph_enhanced/ext_jason1.wav",
["JASON!"] = "taunts/ph_enhanced/ext_jason2.wav",
["JASON"] = "taunts/ph_enhanced/ext_jason3.wav",
["Jim Carrey REMIX"] = "taunts/ph_enhanced/ext_jim_carrey.wav",
["AND HIS NAME IS JOHN CENA"] = "taunts/ph_enhanced/ext_johncena.wav",
["AND HIS NAME IS JOHN CENA REMIX"] = "taunts/ph_enhanced/ext_johncena_remix.wav",
["no way"] = "taunts/ph_enhanced/ext_nowai.wav",
["Remove Freeman"] = "taunts/ph_enhanced/ext_remove_kebab.wav",
["SHUT UP"] = "taunts/ph_enhanced/ext_shutuuuuuuup.wav",
["JC2: No no no"] = "taunts/ph_enhanced/jc2_nonono.wav",
["JC2: no way"] = "taunts/ph_enhanced/jc2_nowai.wav",
["JC2: You Son of a Bee"] = "taunts/ph_enhanced/jc2_usonova_bee.wav",
["Shia Labeouf: JUST DO IT"] = "taunts/ph_enhanced/just_doit1.wav",
["Shia Labeouf: DO IT"] = "taunts/ph_enhanced/just_doit2.wav",
["Hula Dance"] = "taunts/ph_enhanced/ext_huladance.wav",
["X Files"] = "taunts/ph_enhanced/ext_illuminaty.wav",
["Lovely hehe"] = "taunts/ph_enhanced/ext_lovely_hehe_mp4.wav",
["Yeah Boy"] = "taunts/ph_enhanced/ext_yeahboy_mp4.wav",
["MY LEG"] = "taunts/ph_enhanced/ext_my_leg.wav",
["JOHN FREEMANS WEPON"] = "taunts/ph_enhanced/ext_wepon.wav",
["OOOOOOOOH"] = "taunts/ph_enhanced/ext_woo.wav",
["Uuf"] = "taunts/ph_enhanced/ext_oof_minecraft.wav",
["Oof"] = "taunts/ph_enhanced/ext_oof_roblox.wav",
["Cloaker"] = "taunts/ph_enhanced/ext_pd2_cloaker.wav",
["WOOOOH"] = "taunts/ph_enhanced/ext_pyrocynical_woo.wav"
}
-- Custom Player Model bans for props
PHE.PROP_PLMODEL_BANS = {
"models/player.mdl"
}
PHE.WINNINGSOUNDS = {
[1] = "misc/ph_hunterwin.mp3", -- hunter
[2] = "misc/ph_propwin.mp3", -- props
["Draw"] = {"misc/ph_rounddraw_1.mp3", "misc/ph_rounddraw_2.mp3"}
}
local function AddDemTaunt()
printVerbose("[PH:E Taunts] Initializing Custom Taunts...")
for propName,propTaunt in pairs(list.Get("PHE.CustomPropTaunts")) do
printVerbose("[PH:E Taunts] Adding Custom PROP taunts -> "..propName)
PHE.PH_TAUNT_CUSTOM.PROP[propName] = propTaunt
if (SERVER) then
resource.AddSingleFile("sound/"..propTaunt)
end
end
for huntName,huntTaunt in pairs(list.Get("PHE.CustomHunterTaunts")) do
printVerbose("[PH:E Taunts] Adding Custom HUNTER taunts -> "..huntName)
PHE.PH_TAUNT_CUSTOM.HUNTER[huntName] = huntTaunt
if (SERVER) then
resource.AddSingleFile("sound/"..huntTaunt)
end
end
end
hook.Add("Initialize", "PHE.AddTauntTables", AddDemTaunt)
-- External Use only, such as Taunt Collection and stuff.
-- MAKE SURE TO CALL 'PHE:RefreshTauntList()' AFTER ADDING YOUR CUSTOM TAUNTS!
function PHE:AddCustomTaunt(idTeam,strName,strTaunt)
if idTeam == TEAM_PROPS then
PHE.PH_TAUNT_CUSTOM.PROP[strName] = strTaunt
end
if idTeam == TEAM_HUNTERS then
PHE.PH_TAUNT_CUSTOM.HUNTER[strName] = strTaunt
end
end
-- External Use only, such as Taunt Collection or other.
-- MAKE SURE TO CALL 'PHE:RefreshTauntList()' AFTER REMOVING THE SPECIFIED TAUNTS!
function PHE:RemoveCustomTauntByPath(idTeam,strTaunt)
if idTeam == TEAM_PROPS then
if table.HasValue(PHE.PH_TAUNT_CUSTOM.PROP, strTaunt) then table.RemoveByValue(strTaunt) end
end
if idTeam == TEAM_HUNTERS then
if table.HasValue(PHE.PH_TAUNT_CUSTOM.HUNTER, strTaunt) then table.RemoveByValue(strTaunt) end
end
end
function PHE:GetAllTeamTaunt(teamid)
if teamid == TEAM_PROPS then
local taunt = table.Copy(PHE.PROP_TAUNTS)
if table.Count(PHE.PH_TAUNT_CUSTOM.PROP) > 0 then
for name,tprop in pairs(PHE.PH_TAUNT_CUSTOM.PROP) do
taunt[name] = tprop
end
end
return taunt
end
if teamid == TEAM_HUNTERS then
local taunt = table.Copy(PHE.HUNTER_TAUNTS)
if table.Count(PHE.PH_TAUNT_CUSTOM.HUNTER) > 0 then
for name,thunter in pairs(PHE.PH_TAUNT_CUSTOM.HUNTER) do
taunt[name] = thunter
end
end
return taunt
end
return false
end
function PHE:GetTeamTaunt(teamid,bCustom)
if teamid == TEAM_PROPS then
if bCustom then
if table.Count(PHE.PH_TAUNT_CUSTOM.PROP) > 0 then
return PHE.PH_TAUNT_CUSTOM.PROP
else
return false
end
else
return PHE.PROP_TAUNTS
end
end
if teamid == TEAM_HUNTERS then
if bCustom then
if table.Count(PHE.PH_TAUNT_CUSTOM.HUNTER) > 0 then
return PHE.PH_TAUNT_CUSTOM.HUNTER
else
return false
end
else
return PHE.HUNTER_TAUNTS
end
end
return false
end
function PHE:RefreshTauntList()
local proptaunt = {
normal = table.Copy(PHE.PROP_TAUNTS),
custom = table.Copy(PHE.PH_TAUNT_CUSTOM.PROP)
}
table.Empty(PHE.PROP_TAUNTS)
table.Empty(PHE.PH_TAUNT_CUSTOM.PROP)
local huntertaunt = {
normal = table.Copy(PHE.HUNTER_TAUNTS),
custom = table.Copy(PHE.PH_TAUNT_CUSTOM.HUNTER)
}
table.Empty(PHE.HUNTER_TAUNTS)
table.Empty(PHE.PH_TAUNT_CUSTOM.HUNTER)
-- Sort Prop Taunts
for name,taunt in pairs(proptaunt.normal) do
PHE.PROP_TAUNTS[name] = taunt
end
for name,taunt in pairs(proptaunt.custom) do
PHE.PH_TAUNT_CUSTOM.PROP[name] = taunt
end
table.sort(PHE.PROP_TAUNTS)
table.sort(PHE.PH_TAUNT_CUSTOM.PROP)
-- Sort Hunter Taunts
for name,taunt in pairs(huntertaunt.normal) do
PHE.HUNTER_TAUNTS[name] = taunt
end
for name,taunt in pairs(huntertaunt.custom) do
PHE.PH_TAUNT_CUSTOM.HUNTER[name] = taunt
end
table.sort(PHE.HUNTER_TAUNTS)
table.sort(PHE.PH_TAUNT_CUSTOM.HUNTER)
end
hook.Add("InitPostEntity","PHE.RefreshTaunts",function()
PHE:RefreshTauntList()
end)
concommand.Add("phe_refresh_taunt_list", function() PHE:RefreshTauntList() end, nil, "(EXPERIMENTAL) Force Refresh the Taunt List. This may cause some taunts are missing. Restart map is Required!")
-- Add the custom player model bans for props AND prop banned models
if SERVER then
if ( !file.Exists( "phe_config", "DATA" ) ) then
printVerbose("[PH: Enhanced] Warning: ./data/phe_config/ does not exist. Creating New One...")
file.CreateDir( "phe_config" )
end
local function AddBadPLModels()
local dir = "phe_config/prop_plymodel_bans"
-- Create base config area
if ( !file.Exists( dir, "DATA" ) ) then
file.CreateDir( dir )
end
-- Create actual config
if ( !file.Exists( dir.."/bans.txt", "DATA" ) ) then
file.Write( dir.."/bans.txt", util.TableToJSON({"models/player.mdl"}, true) )
end
if ( file.Exists( dir.."/bans.txt", "DATA" ) ) then
local PROP_PLMODEL_BANS_READ = util.JSONToTable( file.Read( dir.."/bans.txt", "DATA" ) )
-- empty the table instead
table.Empty(PHE.PROP_PLMODEL_BANS)
for _, v in pairs(PROP_PLMODEL_BANS_READ) do
printVerbose("[PH:E PlayerModels] Adding custom prop player model ban --> "..string.lower(v))
table.insert(PHE.PROP_PLMODEL_BANS, string.lower(v))
end
else
printVerbose("[PH: Enhanced] Cannot read "..dir.."/bans.txt: Error - did not exist. Did you just delete it or what?")
end
end
hook.Add("Initialize", "PHE.AddBadPlayerModels", AddBadPLModels)
local function AddBannedPropModels()
local dir = "phe_config/prop_model_bans"
local mdlpermabans = {
"models/props/cs_assault/dollar.mdl",
"models/props/cs_assault/money.mdl",
"models/props/cs_office/snowman_arm.mdl",
"models/props/cs_office/computer_mouse.mdl",
"models/props/cs_office/projector_remote.mdl",
"models/foodnhouseholditems/egg.mdl",
"models/props/cs_militia/reload_bullet_tray.mdl"
}
if ( !file.Exists(dir, "DATA") ) then
file.CreateDir(dir)
end
if ( !file.Exists(dir.."/model_bans.txt","DATA") ) then
file.Write( dir.."/model_bans.txt", util.TableToJSON( mdlpermabans, true ))
end
if ( file.Exists ( dir.."/model_bans.txt","DATA" ) ) then
local PROP_MODEL_BANS_READ = util.JSONToTable(file.Read(dir.."/model_bans.txt"))
-- empty the tables anyway.
table.Empty(PHE.BANNED_PROP_MODELS)
for _,v in pairs(PROP_MODEL_BANS_READ) do
printVerbose("[PH:E Model Bans] Adding entry of restricted model to be used --> "..string.lower(v))
table.insert(PHE.BANNED_PROP_MODELS, string.lower(v))
end
else
printVerbose("[PH: Enhanced] Cannot read "..dir.."/model_bans.txt: Error - did not exist. Did you just delete it or what?")
end
end
hook.Add("Initialize", "PHE.AddBannedPropModels", AddBannedPropModels)
-- Add ConCommands.
concommand.Add("phe_refresh_plmodel_ban", AddBadPLModels, nil, "Refresh Server Playermodel Ban Lists, read from prop_plymodel_bans/bans.txt data.", FCVAR_SERVER_CAN_EXECUTE)
concommand.Add("phe_refresh_propmodel_ban", AddBannedPropModels, nil, "Refresh Server Prop Models Ban Lists, read from prop_model_bans/model_bans.txt data.", FCVAR_SERVER_CAN_EXECUTE)
end
-- AAAAAAARGGHHHHHH
function PHE:AAAAAAARGGHHHHHH()
print("oh no, it\'s the AAAAAAARGGHHHHHH AAAHHHHHHHHHHHHHHHH!")
if CLIENT then
surface.PlaySound(PHE.PROP_TAUNTS["DX: AAAAAAARGGHHHHHH"])
end
end
concommand.Add("aaaaaaargghhhhhh", function() PHE:AAAAAAARGGHHHHHH() end, nil, "The classic AAAAAAARGGHHHHHH from Deus Ex.",0x10)

View File

@@ -0,0 +1,73 @@
-- PROP HUNT: ENHANCED CONVARS
-- Playermodels controls convars
local mdlprop = CreateConVar("ph_use_custom_plmodel_for_prop", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should use a custom Player's Model for Props when the round begins?")
local mdlenable = CreateConVar("ph_use_custom_plmodel", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should use a custom player model available for Hunters?\nPlease note that you must have to activate \'ph_use_custom_plmodel_for_prop\' too!")
-- Tutorial for ph_use_playermodeltype can be found under FAQ.
local mdltype = CreateConVar("ph_use_playermodeltype", "0", {FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Which model list that should deliver from? 0 = All Playermodels availale, 1 = Use Legacy method: list.Get('PlayerOptionsModel') (Recommended if you want to custom your model list)")
-- Enhanced Prop Hunt specify convars
local cmcoll = CreateConVar("ph_prop_camera_collisions", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Attempts to stop props from viewing inside walls.")
local fcam = CreateConVar("ph_freezecam", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Freeze Camera.")
local propcoll = CreateConVar("ph_prop_collision", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should Team Props collide with each other?")
-- Custom Taunts ConVars
local ct_delay = CreateConVar("ph_customtaunts_delay", "6", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "How many in seconds delay for props to play custom taunt again? (Default is 6)")
local ct_enable = CreateConVar("ph_enable_custom_taunts", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Enable custom taunts for prop teams by pressing C? (Default 0)\n You must have a list of custom taunts to enable this.")
local nt_delay = CreateConVar("ph_normal_taunt_delay", "2", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "How many in seconds delay for props to play normal [F3] taunt again? (Default is 2)")
-- The Prop Jump Multiplier (count by float)
local pjumpx = CreateConVar("ph_prop_jumppower", "1.4", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Multipliers for Prop Jump Power (Do not confused with Prop's Gravity!). Default is 1.4. Min. 1.")
-- The 'Prop Rotation' Notification
local rotation_notify = CreateConVar("ph_notice_prop_rotation", "1", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Enable Prop Rotation notification on every time Prop Spawns.")
-- Freezecam Sound Overrides & Cue Path checks (make sure they don't use '\' but instead '/')
local fc_sound = CreateConVar("ph_fc_use_single_sound", "0", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Use single Freezecam sound instead of sound list?")
local fc_cue = CreateConVar("ph_fc_cue_path", "misc/freeze_cam.wav", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY}, "Path for single Freezecam sound.")
if SERVER then
cvars.AddChangeCallback("ph_fc_cue_path", function(cvar,old,new) PHE.LegalCuePath = string.Replace(new, "\\", "/") end, "fc_path_modify")
end
-- Lucky Ball ConVars
local lball = CreateConVar("ph_enable_lucky_balls", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_NOTIFY }, "Spawn Lucky balls on breakable props?")
local dball = CreateConVar("ph_enable_devil_balls", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_NOTIFY }, "Spawn Devil balls when hunter dies?")
-- PlayerID on Team Specific
local plnames = CreateConVar("ph_enable_plnames", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Serverside control for if a clients see client\'s team player names through walls.")
-- Generic Prop Hunt ConVars
local h_penalty = CreateConVar("ph_hunter_fire_penalty", "5", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Health points removed from hunters when they shoot.")
local h_killbns = CreateConVar("ph_hunter_kill_bonus", "100", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "How much health to give back to the Hunter after killing a prop.")
local h_swap = CreateConVar("ph_swap_teams_every_round", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should teams swapped on every round?")
local game_time = CreateConVar("ph_game_time", "30", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Maximum Time Left (in minutes) - Default is 30 minutes.")
local blind_time = CreateConVar("ph_hunter_blindlock_time", "30", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "How long hunters are blinded (in seconds)")
local round_time = CreateConVar("ph_round_time", "300", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Time (in seconds) for each rounds.")
local round_map = CreateConVar("ph_rounds_per_map", "10", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Numbers played on a map (Default: 10)")
-- Round Control
local wait_pl = CreateConVar( "ph_waitforplayers", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "Should we wait for players for proper round?" )
local wait_pl_min = CreateConVar( "ph_min_waitforplayers", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Numbers of mininum players that we should wait for round start. Value must not contain less than 1." )
-- Verbose mode & Function
local verbose = CreateConVar("ph_print_verbose", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Developer Verbose. Some printed messages will only appear if this is enabled.")
function printVerbose(text)
if GetConVar("ph_print_verbose"):GetBool() && text then
print(tostring(text))
end
end
-- Autotaunt delay (in seconds)
local at_delay = CreateConVar("ph_autotaunt_delay", "45", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "The delay for the auto taunt")
-- Is autotaunt enabled
local at_enable = CreateConVar("ph_autotaunt_enabled", "1",{ FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Should auto taunting be enabled")
-- Use newer model for Bren MK
local mkbren_new = CreateConVar("ph_mkbren_use_new_mdl", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Use new model for Bren MK II Bonus Weapon (Require Map Restart!!)")
-- OBB Model Data Modifier, specified on map.
local obb_mod = CreateConVar("ph_sv_enable_obb_modifier", "1",{ FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Developer: Enable OBB Model Data Modifier")
local obb_every = CreateConVar("ph_reload_obb_setting_everyround", "1",{ FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Developer: Reload OBB Model Data Modifier Every round Restarts")
-- This is for a temporary.
local check_boundaries = CreateConVar("phe_check_props_boundaries", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "[EXPERIMENTAL] This feature is under Work-in-Progress! Enable prop boundaries Check? This will prevent you to stuck with other objects/Wall.")

View File

@@ -0,0 +1,24 @@
hook.Add("Move", "moveProp", function(ply,move)
if SERVER then
if ply:Alive() && ply:Team() == TEAM_PROPS then
-- Local variables
local ent = ply.ph_prop
-- Set position and angles
if IsValid(ent) && IsValid(ply) && ply:Alive() then
-- Set position
if (ent:GetModel() == "models/player/kleiner.mdl" || ent:GetModel() == player_manager.TranslatePlayerModel(ply:GetInfo("cl_playermodel"))) then
ent:SetPos(move:GetOrigin())
else
ent:SetPos(move:GetOrigin() - Vector(0, 0, ent:OBBMins().z))
end
-- Set angles
if !ply:GetPlayerLockedRot() then
local ang = move:GetAngles()
ent:SetAngles(Angle(0,ang.y,0))
end
end
end
end
end)

View File

@@ -0,0 +1,105 @@
PHE.RESULT = false
local function UPDATE_SET_RESULT(result)
PHE.RESULT = result
end
local function UPDATE_GET_RESULT()
return PHE.RESULT
end
local function UPDATE_DO_FETCH()
http.Fetch(
GAMEMODE.UPDATEURL,
function(body,len,head,code)
if tonumber(code) >= 300 then
return false
elseif body == "" then
return false
else
UPDATE_SET_RESULT(body)
return body
end
end,
function(err) print("[!PH: Enhanced Update] Error retreiving update. Reason: "..err) end
)
end
function PHE:CheckUpdate(bool)
local result = ""
local httpcode = 0
result = UPDATE_DO_FETCH() or UPDATE_GET_RESULT() or PHE.RESULT or false
if (!result || result == "") then
print("[!PH: Enhanced Update] Unknown Error retreiving update.")
return false,false,false
end
printVerbose("[*PH: Enhanced Update] Incoming update result data:\n ===\n"..tostring(result).."\n ===\n")
local data = util.JSONToTable(result)
local ver = tonumber(data.version)
local rev = data.revision
local log = data.notice
local text
if tonumber(GAMEMODE._VERSION) > ver then
text = "[!PH: Enhanced Update] New version of "..ver.." is available. To update, please procceed to this link: \n --> https://prophunt.wolvindra.net/?go=download \n --> Changelog: "..log
MsgC(Color(0,160,230), text.."\n")
elseif string.lower(GAMEMODE.REVISION) != rev then
text = "[!PH: Enhanced Update] New Revision of "..rev.." is available. To update, please procceed with this revision, visit this link: \n --> https://prophunt.wolvindra.net/?go=download&rev="..rev.." \n --> Changelog: "..log
MsgC(Color(0,160,230), text.."\n")
elseif tonumber(GAMEMODE._VERSION) == ver && string.lower(GAMEMODE.REVISION) == rev then
text = "[*PH: Enhanced Update] Your gamemode is up to date. (Version "..ver.." - Revision "..string.upper(rev)..")"
MsgC(Color(0,200,40), text.."\n")
end
if bool then
return ver,rev,log
end
end
local function CheckUpdate()
print("[PH: Enhanced] - Retreiving Update Info... Please Wait!")
UPDATE_DO_FETCH()
timer.Simple(4, function()
print( "~[ Prop Hunt : Enhanced Update & Info ]~" )
local version,rev,changelog = PHE:CheckUpdate(true)
if (!version || !rev || !changelog) then
MsgC(Color(230,20,20), "[!!] Error Retreiving updates info")
return
end
MsgC(Color(181,230,30),"[+] Current Version : "..version.."\n")
MsgC(Color(175,245,15),"[+] Current Revision: "..rev.."\n")
MsgC(Color(247,211,13),"[!] See ChangeLog : "..changelog.."\n\n")
end)
end
concommand.Add("ph_check_update", CheckUpdate ,nil, "Force Check Update Prop Hunt: Enhanced.")
local cooldown = 86400
hook.Add("Initialize", "PHE.CheckUpdateInit", function()
local nextUpdate = cookie.GetNumber("nextUpdate",0)
local time = os.time()
if time < nextUpdate then
print("[PH: Enhanced] - Update has been checked. Will Re-check the update on "..os.date("%Y/%m/%d - %H:%M:%S",nextUpdate))
else
print("[PH: Enhanced] - Initialize for Checking Update...")
UPDATE_DO_FETCH()
print("[PH: Enhanced] - Retreiving Update Info...")
cookie.Set("nextUpdate", time + cooldown)
timer.Simple(5, function()
PHE:CheckUpdate(false)
print("[PH: Enhanced] - Update has been checked. Your next update notice will be displayed on "..os.date("%Y/%m/%d - %H:%M:%S",nextUpdate))
end)
end
end)

View File

@@ -0,0 +1,129 @@
-- Initialize the shared variable
PHE = {}
PHE.__index = PHE
-- Some config stuff
AddCSLuaFile("config/sh_init.lua")
include("config/sh_init.lua")
AddCSLuaFile("sh_drive_prop.lua")
include("sh_drive_prop.lua")
-- ULX Mapvote
AddCSLuaFile("ulx/modules/sh/sh_phe_mapvote.lua")
include("ulx/modules/sh/sh_phe_mapvote.lua")
-- Initialize and Add ConVar Blocks.
AddCSLuaFile("sh_convars.lua")
include("sh_convars.lua")
-- Include the required lua files
AddCSLuaFile("sh_config.lua")
include("sh_config.lua")
include("sh_player.lua")
-- Add Sound Precaching Functions
AddCSLuaFile("sh_precache.lua")
include("sh_precache.lua")
-- Plugins! :D
PHE.PLUGINS = {}
AddCSLuaFile("sh_plugins.lua")
include("sh_plugins.lua")
-- MapVote
if SERVER then
AddCSLuaFile("sh_mapvote.lua")
AddCSLuaFile("mapvote/cl_mapvote.lua")
include("sh_mapvote.lua")
include("mapvote/sv_mapvote.lua")
include("mapvote/rtv.lua")
else
include("sh_mapvote.lua")
include("mapvote/cl_mapvote.lua")
end
-- Updates!
AddCSLuaFile("sh_httpupdates.lua")
include("sh_httpupdates.lua")
-- Fretta!
DeriveGamemode("fretta")
IncludePlayerClasses()
-- Information about the gamemode
GM.Name = "Prop Hunt: ENHANCED"
GM.Author = "Wolvindra-Vinzuerio & D4UNKN0WNM4N2010"
GM._VERSION = "15"
GM.REVISION = "I"
GM.DONATEURL = "https://prophunt.wolvindra.net/go/donate_go.php?gamemodeonly=true"
GM.UPDATEURL = "https://raw.githubusercontent.com/Vinzuerio/ph-enhanced/master/updates/version.json"
-- Help info
GM.Help = [[An Enhanced Classic Prop Hunt Gamemode.
To See More Help, Click 'Prop Hunt Menu' for more!
Version: ]].. GM._VERSION ..[[ Revision: ]].. GM.REVISION ..[[
What's New:
- Optimised gamemode and more reliable
- New Prop Hunt Enhanced HUD
- New Hunter 'Armor' Method
- New gamemode settings in PH Menu
- New gamemode Plugins
- New UI for Menu & Taunt Window
- Smoother prop movements
- and many more..!]]
-- Fretta configuration
GM.GameLength = GetConVarNumber("ph_game_time")
GM.AddFragsToTeamScore = true
GM.CanOnlySpectateOwnTeam = true
GM.ValidSpectatorModes = { OBS_MODE_CHASE, OBS_MODE_IN_EYE, OBS_MODE_ROAMING }
GM.Data = {}
GM.EnableFreezeCam = true
GM.NoAutomaticSpawning = true
GM.NoNonPlayerPlayerDamage = true
GM.NoPlayerPlayerDamage = true
GM.RoundBased = true
GM.RoundLimit = GetConVar("ph_rounds_per_map"):GetInt()
GM.RoundLength = GetConVar("ph_round_time"):GetInt()
GM.RoundPreStartTime = 0
GM.SuicideString = "was dead or died mysteriously." -- i think this one is pretty obsolete.
GM.TeamBased = true
GM.AutomaticTeamBalance = false
GM.ForceJoinBalancedTeams = true
-- Called on gamemdoe initialization to create teams
function GM:CreateTeams()
if !GAMEMODE.TeamBased then
return
end
TEAM_HUNTERS = 1
team.SetUp(TEAM_HUNTERS, "Hunters", Color(150, 205, 255, 255))
team.SetSpawnPoint(TEAM_HUNTERS, {"info_player_counterterrorist", "info_player_combine", "info_player_deathmatch", "info_player_axis"})
team.SetClass(TEAM_HUNTERS, {"Hunter"})
TEAM_PROPS = 2
team.SetUp(TEAM_PROPS, "Props", Color(255, 60, 60, 255))
team.SetSpawnPoint(TEAM_PROPS, {"info_player_terrorist", "info_player_rebel", "info_player_deathmatch", "info_player_allies"})
team.SetClass(TEAM_PROPS, {"Prop"})
end
-- Check collisions
function CheckPropCollision(entA, entB)
-- Disable prop on prop collisions
if !GetConVar("ph_prop_collision"):GetBool() && (entA && entB && ((entA:IsPlayer() && entA:Team() == TEAM_PROPS && entB:IsValid() && entB:GetClass() == "ph_prop") || (entB:IsPlayer() && entB:Team() == TEAM_PROPS && entA:IsValid() && entA:GetClass() == "ph_prop"))) then
return false
end
-- Disable hunter on hunter collisions so we can allow bullets through them
if (IsValid(entA) && IsValid(entB) && (entA:IsPlayer() && entA:Team() == TEAM_HUNTERS && entB:IsPlayer() && entB:Team() == TEAM_HUNTERS)) then
return false
end
end
hook.Add("ShouldCollide", "CheckPropCollision", CheckPropCollision)

View File

@@ -0,0 +1,48 @@
-- Credits & Original code: https://github.com/tyrantelf/gmod-mapvote
-- This is modified as for ease use of MapVote in Prop Hunt Enhanced, to avoid users having difficulties to edit their mapvote config file instead through ConVars.
MapVote = {}
MapVote.Config = {}
--Default Config
MapVoteConfigDefault = {
MapLimit = 24,
TimeLimit = 28,
AllowCurrentMap = false,
EnableCooldown = true,
MapsBeforeRevote = 2,
RTVPlayerCount = 3,
MapPrefixes = {"ph_"}
}
--Default Config
local convarlist = {
{"mv_maplimit", "24", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "numbers of map that shown on mapvote." },
{"mv_timelimit", "28", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "time in second for default mapvotes time." },
{"mv_change_when_no_player", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "change the map after no players in the server?" },
{"mv_allowcurmap", "0", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "allow current map to be voted (1/0)" },
{"mv_use_ulx_votemaps", "0", {FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Use map listing from ULX Mapvote? 1 = use from ULX mapvote list (which you can whitelist them), 0 = use default maps/*.bsp directory listing."},
{"mv_cooldown", "1", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "enable cooldown for voting a map" },
{"mv_mapbeforerevote", "2", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "how many times that the map which cooldown can be shown again?" },
{"mv_rtvcount", "3", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE, FCVAR_NOTIFY }, "number of required players to use rtv mapvote." },
{"mv_mapprefix", "ph_,cs_,de_", { FCVAR_SERVER_CAN_EXECUTE, FCVAR_REPLICATED, FCVAR_ARCHIVE }, "Map Prefixes that will be shown under mapvote. Use the following example:\n \"ph_,cs_,de_\" (Dont forget to use quotation marks!)." }
}
if !ConVarExists("mv_maplimit") then
printVerbose("[MapVote] ConVars initialized!")
for _,convars in pairs(convarlist) do
CreateConVar(convars[1], convars[2], convars[3], convars[4])
end
end
function MapVote.HasExtraVotePower(ply)
return false
end
MapVote.CurrentMaps = {}
MapVote.Votes = {}
MapVote.Allow = false
MapVote.UPDATE_VOTE = 1
MapVote.UPDATE_WIN = 3

View File

@@ -0,0 +1,96 @@
-- Finds the player Player/Entities table
local Player = FindMetaTable("Player")
local Entity = FindMetaTable("Entity")
if !Player then return end
if !Entity then return end
-- Checks player hull to make sure it does not even stuck with the world/other objects.
function Entity:GetPropSize()
local hullxymax = math.Round(math.Max(self:OBBMaxs().x-self:OBBMins().x, self:OBBMaxs().y-self:OBBMins().y))
local hullz = math.Round(self:OBBMaxs().z - self:OBBMins().z)
return hullxymax,hullz
end
function Player:CheckHull(hx,hy,hz)
local tr = {}
tr.start = self:GetPos()
tr.endpos = self:GetPos()
tr.filter = {self, self.ph_prop}
tr.maxs = Vector(hx,hy,hz)
tr.mins = Vector(-hx,-hy,0)
local trx = util.TraceHull(tr)
if trx.Hit then return false end
return true
end
-- Blinds the player by setting view out into the void
function Player:Blind(bool)
if !self:IsValid() then return end
if SERVER then
net.Start("SetBlind")
if bool then
net.WriteBool(true)
self:SetNWBool("isBlind", true)
else
net.WriteBool(false)
self:SetNWBool("isBlind", false)
end
net.Send(self)
elseif CLIENT then
blind = bool
end
end
-- Player has locked prop rotation?
function Player:GetPlayerLockedRot()
return self:GetNWBool("PlayerLockedRotation", false)
end
-- Player's prop entity
function Player:GetPlayerPropEntity()
return self:GetNWEntity("PlayerPropEntity", nil)
end
-- Removes the prop given to the player
function Player:RemoveProp()
if CLIENT || !self:IsValid() then return end
if self.ph_prop && self.ph_prop:IsValid() then
self.ph_prop:Remove()
self.ph_prop = nil
end
end
-- Returns ping for the scoreboard
function Player:ScoreboardPing()
-- If this is not a dedicated server and player is the host
if self:GetNWBool("ListenServerHost") then
return "SV"
elseif self:IsBot() then
return "BOT" -- otherwise this will act very strange.
end
-- Return normal ping value otherwise
return self:Ping()
end
if SERVER then
function Player:IsHoldingEntity()
if !self.LastPickupEnt then
return false
end
if !IsValid(self.LastPickupEnt) then
return false
end
local ent = self.LastPickupEnt
if ent.LastPickupPly != self then
return false
end
return self.LastPickupEnt:IsPlayerHolding()
end
end

View File

@@ -0,0 +1,102 @@
function PHE:InitializePlugin()
for name,plugin in pairs(list.Get("PHE.Plugins")) do
printVerbose("------------------------------------------\n[PHE Plugin] :: Adding Plugin: "..name)
PHE.PLUGINS[name] = plugin
end
if table.Count(PHE.PLUGINS) > 0 then
for pName,pData in pairs(PHE.PLUGINS) do
printVerbose("[PHE Plugin] Loading Plugin "..pName)
printVerbose("--> Loaded Plugins: "..pData.name.."\n--> Version: "..pData.version.."\n--> Info: "..pData.info.."\n------------------------------------------")
end
end
end
hook.Add("Initialize", "PHE.InitPlugins", function()
PHE:InitializePlugin()
end)
if CLIENT then
hook.Add("PH_CustomTabMenu", "PHE.NewPlugins", function(tab, pVgui)
local main = {}
main.panel = vgui.Create("DPanel", tab)
main.panel:SetSize(tab:GetWide(),tab:GetTall())
main.panel:SetBackgroundColor(Color(40,40,40,120))
main.scroll = vgui.Create( "DScrollPanel", main.panel )
main.scroll:Dock(FILL)
main.grid = vgui.Create("DGrid", main.scroll)
main.grid:SetPos(10,10)
main.grid:SetSize(tab:GetWide()-20,280)
main.grid:SetCols(1)
main.grid:SetColWide(tab:GetWide()-100)
main.grid:SetRowHeight(300)
if table.Count(PHE.PLUGINS) < 1 then
if LocalPlayer():IsSuperAdmin() then
local lbl = vgui.Create("DLabel",main.panel)
lbl:SetPos(40,60)
lbl:SetText("No Plugins are available. Find more Prop Hunt: Enhanced Exclusive Plugins here!")
lbl:SetFont("Trebuchet24")
lbl:SetTextColor(color_white)
lbl:SizeToContents()
local but = vgui.Create("DButton",main.panel)
but:SetPos(40,96)
but:SetSize(256,40)
but:SetText("Find PH:E Plugins")
but.DoClick = function() gui.OpenURL("https://project.wolvindra.net/phe/?go=plugins") end
but:SetIcon("icon16/bricks.png")
else
local lbl = vgui.Create("DLabel",main.panel)
lbl:SetPos(40,60)
lbl:SetText("This server has no custom addons/plugins installed.")
lbl:SetFont("Trebuchet24")
lbl:SetTextColor(color_white)
lbl:SizeToContents()
end
else
for plName,Data in pairs(PHE.PLUGINS) do
local section = {}
section.main = vgui.Create("DPanel",main.grid)
section.main:SetSize(main.grid:GetWide()-100,main.grid:GetTall())
section.main:SetBackgroundColor(Color(20,20,20,150))
section.roll = vgui.Create("DScrollPanel",section.main)
section.roll:SetSize(section.main:GetWide(),section.main:GetTall())
section.grid = vgui.Create("DGrid",section.roll)
section.grid:SetPos(20,20)
section.grid:SetSize(section.roll:GetWide()-20,section.roll:GetTall())
section.grid:SetCols(1)
section.grid:SetColWide(800)
section.grid:SetRowHeight(40)
pVgui("","label","Trebuchet24",section.grid, Data.name.."| v."..Data.version )
pVgui("","label",false,section.grid, "Description: "..Data.info )
if (LocalPlayer():IsSuperAdmin() || table.HasValue(PHE.SVAdmins, LocalPlayer():GetUserGroup())) then
if table.Count(Data.settings) > 0 then
pVgui("","label",false,section.grid, "-- Server Settings --" )
for _,val in pairs(Data.settings) do
pVgui(val[1],val[2],val[3],section.grid,val[4])
end
end
end
if table.Count(Data.client) > 0 then
pVgui("","label",false,section.grid, "-- Client Settings --" )
for _,val in pairs(Data.client) do
pVgui(val[1],val[2],val[3],section.grid,val[4])
end
end
main.grid:AddItem(section.main)
end
end
tab:AddSheet("Plugins [BETA]", main.panel, "icon16/bricks.png")
end)
end

View File

@@ -0,0 +1,41 @@
-- Generic Sound Precache function
CreateConVar("ph_precache_phe_core", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Precache Prop Hunt: Enhanced core sounds during player initial spawn.")
CreateConVar("ph_precache_taunts", "0", {FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_NOTIFY}, "Precache Prop Hunt: Enhanced core taunts during player's initial spawn.")
hook.Add("PlayerInitialSpawn", "PHE.PrecacheSoundCore", function()
-- WARNING: THESE ARE FIXED FOR OPTIMISATION PURPOSE.
-- If you want to modify the gamemode, remove this function as well as the ConVars above.
local path = {
misc = "misc/",
core = "prop_idbs/",
swep = "weapons/mkbren/",
swepb = "weapons/brenmk3/",
generic = "gamemode/prop_hunt/content/sound/"
}
local function PrecacheThis(path)
if file.Exists(path, "GAME") then
wav = file.Find(path.."*.wav", "GAME")
mp3 = file.Find(path.."*.mp3", "GAME")
printVerbose("[PH:E] Precaching Sound Core...")
for _,snd in pairs(wav) do util.PrecacheSound(snd) end
for _,sndm in pairs(mp3) do util.PrecacheSound(sndm) end
end
end
if GetConVar("ph_precache_phe_core"):GetBool() then
PrecacheThis(path.generic..path.misc)
PrecacheThis(path.generic..path.core)
PrecacheThis(path.generic..path.swep)
PrecacheThis(path.generic..path.swepb)
end
if GetConVar("ph_precache_taunts"):GetBool() then
timer.Simple(3, function()
for _,ptaunts in pairs(PHE.PROP_TAUNTS) do util.PrecacheSound(ptaunts) end
for _,htaunts in pairs(PHE.HUNTER_TAUNTS) do util.PrecacheSound(htaunts) end
end)
end
end)

View File

@@ -0,0 +1,48 @@
net.Receive("CheckAdminFirst", function(len, ply)
if ply:IsAdmin() or table.HasValue(PHE.SVAdmins, ply:GetUserGroup()) then
net.Start("CheckAdminResult")
net.Send(ply)
end
end)
net.Receive("SvCommandReq", function(len, ply)
local cmd = net.ReadString()
local valbool = net.ReadInt(2)
if ply:IsAdmin() or table.HasValue(PHE.SVAdmins, ply:GetUserGroup()) then
RunConsoleCommand(cmd, math.Round(valbool))
printVerbose("[ADMIN CVAR NOTIFY] Commands: "..cmd.." has been changed (Player: "..ply:Nick().." ("..ply:SteamID()..")")
else
game.KickID(ply:SteamID(), "Illegal command access found by: "..ply:Nick())
printVerbose("[ADMIN CVAR NOTIFY] An user "..ply:Nick().."(".. ply:SteamID() ..") is attempting to access "..cmd..", kicked!")
end
end)
net.Receive("SvCommandSliderReq", function(len, ply)
local cmd = net.ReadString()
local bool = net.ReadBool()
local val
if bool then
val = net.ReadFloat()
else
val = net.ReadInt(16)
end
if ply:IsAdmin() or table.HasValue(PHE.SVAdmins, ply:GetUserGroup()) then
RunConsoleCommand(cmd, val)
printVerbose("[ADMIN CVAR SLIDER NOTIFY] Commands: "..cmd.." has been changed (Player: "..ply:Nick().." ("..ply:SteamID()..")")
else
game.KickID(ply:SteamID(), "Illegal command access found by: "..ply:Nick())
printVerbose("[ADMIN CVAR NOTIFY] An user "..ply:Nick().."(".. ply:SteamID() ..") is attempting to access "..cmd..", kicked!")
end
end)
net.Receive("SendTauntStateCmd", function(len, ply)
local cmdval = net.ReadString()
if ply:IsAdmin() or table.HasValue(PHE.SVAdmins, ply:GetUserGroup()) then
RunConsoleCommand("ph_enable_custom_taunts", cmdval)
printVerbose("[ADMIN CVAR TAUNT NOTIFY] Commands: "..cmdval.." has been changed (Player: "..ply:Nick().." ("..ply:SteamID()..")")
else
game.KickID(ply:SteamID(), "Illegal command access found by: "..ply:Nick())
printVerbose("[ADMIN CVAR NOTIFY] An user "..ply:Nick().."(".. ply:SteamID() ..") is attempting to access "..cmdval..", kicked!")
end
end)

View File

@@ -0,0 +1,30 @@
-- Props will autotaunt at specified intervals (put this crap on the server because the old way was all on the client and that's silly)
local function TauntTimeLeft(ply)
-- Always return 1 when the conditions are not met
if !IsValid(ply) || !ply:Alive() || ply:Team() != TEAM_PROPS then return 1; end
local lastTauntTime = ply:GetNWFloat("LastTauntTime")
local nextTauntTime = lastTauntTime + GetConVar("ph_autotaunt_delay"):GetInt()
local currentTime = CurTime()
return nextTauntTime - currentTime
end
local function AutoTauntThink()
if GetConVar("ph_autotaunt_enabled"):GetBool() then
local WHOLE_TAUNTS = PHE:GetAllTeamTaunt(TEAM_PROPS)
for _, ply in ipairs(team.GetPlayers(TEAM_PROPS)) do
local timeLeft = TauntTimeLeft(ply)
if IsValid(ply) && ply:Alive() && ply:Team() == TEAM_PROPS && timeLeft <= 0 then
local rand_taunt = table.Random(WHOLE_TAUNTS)
if !isstring(rand_taunt) then rand_taunt = tostring(rand_taunt); end
ply:EmitSound(rand_taunt, 100)
ply:SetNWFloat("LastTauntTime", CurTime())
end
end
end
end
timer.Create("AutoTauntThinkTimer", 1, 0, AutoTauntThink)

View File

@@ -0,0 +1,100 @@
local CUR_MAP_DATA = {}
local function LoadOBBConfig()
local map = game.GetMap()
local GetData = "phe-config/obb/"..map..".txt"
if !file.Exists(GetData, "DATA") then
printVerbose("[PH: Enhanced] No OBB Configuration found for map: "..map)
return false
end
if file.Exists(GetData, "DATA") then
local data = file.Read(GetData,"DATA")
local ParsedData = util.JSONToTable(data)
return ParsedData
end
end
local function DoConfig()
local data = CUR_MAP_DATA
if !data then return end
--[[
JSON structure:
[
[
"model/path/b.mdl",
{
"min": [0, 0, 0],
"max": [16, 16, 72],
"dmin": [0, 0, 0],
"dmax": [16, 16, 28]
}
]
]
LUA structure:
1:
1: "model/path/b.mdl"
2:
min = {-0,-0,-0}
max = {16,16,72}
dmin = {-0,-0,-0}
dmax = {16,16,28}
]]
local function SetEntityData(ent, tab1, tab2)
ent:SetNWBool("hasCustomHull",true)
ent.m_Hull = tab1
ent.m_dHull = tab2
end
for i=1,#data do
local tent = ents.FindByModel(data[i][1])
local min = Vector(data[i][2]["min"][1],data[i][2]["min"][2],data[i][2]["min"][3])
local max = Vector(data[i][2]["max"][1],data[i][2]["max"][2],data[i][2]["max"][3])
local dmin = Vector(data[i][2]["dmin"][1],data[i][2]["dmin"][2],data[i][2]["dmin"][3])
local dmax = Vector(data[i][2]["dmax"][1],data[i][2]["dmax"][2],data[i][2]["dmax"][3])
for _,found in pairs(tent) do
if IsValid(found) then
printVerbose("[PH: Enhanced] OBB MODIFIER: Setting up Vector Value for Entity ["..found:EntIndex().."]["..found:GetModel().."] =\n >Hull-Vector: min "..tostring(min).." max "..tostring(max).."\n >Duck-Hull Vector: dmin "..tostring(dmin).." dmax "..tostring(dmax))
SetEntityData(found,{min,max},{dmin,dmax})
end
end
end
end
hook.Add("Initialize", "PHE.InitOBBModelData", function()
if !file.Exists("phe-config/obb","DATA") then
file.CreateDir("phe-config/obb")
end
timer.Simple(1.5, function()
printVerbose("[PH: Enhanced] Initializing OBB ModelData Config...")
CUR_MAP_DATA = LoadOBBConfig()
DoConfig()
end)
end)
hook.Add("PostCleanupMap", "PHE.PostOBBModelData", function()
if GetConVar("ph_reload_obb_setting_everyround"):GetBool() then
printVerbose("[PH: Enhanced] PostCleanup OBB ModelData Config...")
DoConfig()
end
end)
concommand.Add("refresh_obb_map_setting", function(ply)
printVerbose("[PH: Enhanced] Refreshing OBB Model Data Modifier...")
CUR_MAP_DATA = LoadOBBConfig()
DoConfig()
end, nil, "Reload PH: Enhanced OBB/Collission Bound Model Data Modifier on this map.", FCVAR_SERVER_CAN_EXECUTE)

View File

@@ -0,0 +1,29 @@
-- initial for props functions
util.AddNetworkString("ResetHull")
util.AddNetworkString("SetBlind")
util.AddNetworkString("SetHull")
util.AddNetworkString("PlayFreezeCamSound")
util.AddNetworkString("PlayerSwitchDynamicLight")
util.AddNetworkString("DisableDynamicLight")
util.AddNetworkString("PH_ShowTutor")
util.AddNetworkString("CheckAdminFirst")
util.AddNetworkString("CheckAdminResult")
util.AddNetworkString("SvCommandReq")
util.AddNetworkString("SvCommandSliderReq")
util.AddNetworkString("SendTauntStateCmd")
util.AddNetworkString("CL2SV_PlayThisTaunt")
util.AddNetworkString("CL2SV_ExchangeProp")
util.AddNetworkString("utilWLVShowMessage")
util.AddNetworkString("ServerUsablePropsToClient")
util.AddNetworkString("PH_ForceCloseTauntWindow")
util.AddNetworkString("PH_AllowTauntWindow")
util.AddNetworkString("PH_RoundDraw_Snd")
util.AddNetworkString("PH_TeamWinning_Snd")
util.AddNetworkString("AutoTauntSpawn")
util.AddNetworkString("AutoTauntRoundEnd")
-- some stupid checks
util.AddNetworkString("PHE.rotateState")

View File

@@ -0,0 +1,22 @@
-- Validity check to prevent some sort of spam
local function IsDelayed(ply)
local lastTauntTime = ply:GetNWFloat("LastTauntTime")
local delayedTauntTime = lastTauntTime + GetConVar("ph_customtaunts_delay"):GetInt()
local currentTime = CurTime()
return delayedTauntTime > currentTime
end
net.Receive("CL2SV_PlayThisTaunt", function(len, ply)
local snd = net.ReadString()
if IsValid(ply) && !IsDelayed(ply) then
if file.Exists("sound/"..snd, "GAME") then
ply:EmitSound(snd, 100)
ply:SetNWFloat("LastTauntTime", CurTime())
else
ply:ChatPrint("[PH: Enhanced] - Warning: That taunt you selected does not exists on server!")
end
else
ply:ChatPrint("[PH: Enhanced] - Please wait in few seconds...!")
end
end)

View File

@@ -0,0 +1,32 @@
local CATEGORY_NAME = "PH:E MapVote"
------------------------------ VoteMap ------------------------------
function PHE_MapVote( calling_ply, votetime, should_cancel )
if MapVote != nil then
if not should_cancel then
MapVote.Start(votetime, nil, nil, nil)
ulx.fancyLogAdmin( calling_ply, "#A called a votemap!" )
else
MapVote.Cancel()
ulx.fancyLogAdmin( calling_ply, "#A canceled the votemap!" )
end
else
if SERVER then
if game.IsDedicated() then
print("[ULX MapVote] WARNING: You need at least few players to get this work!")
else
print("[ULX MapVote] ERROR: MapVote is Unavailable.")
end
end
end
end
if !ulx then
print("MapVote Error: ULX is not installed!")
else
local mapvotecmd = ulx.command( CATEGORY_NAME, "map_vote", PHE_MapVote, "!map_vote" )
mapvotecmd:addParam{ type=ULib.cmds.NumArg, min=15, default=25, hint="time", ULib.cmds.optional, ULib.cmds.round }
mapvotecmd:addParam{ type=ULib.cmds.BoolArg, invisible=true }
mapvotecmd:defaultAccess( ULib.ACCESS_ADMIN )
mapvotecmd:help( "Invokes the map vote logic" )
mapvotecmd:setOpposite( "unmap_vote", {_, _, true}, "!unmap_vote" )
end