Initial Reupload
This commit is contained in:
135
gamemodes/prop_hunt/gamemode/cl_autotaunt.lua
Normal file
135
gamemodes/prop_hunt/gamemode/cl_autotaunt.lua
Normal 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)
|
||||
66
gamemodes/prop_hunt/gamemode/cl_credits.lua
Normal file
66
gamemodes/prop_hunt/gamemode/cl_credits.lua
Normal 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)
|
||||
265
gamemodes/prop_hunt/gamemode/cl_hud.lua
Normal file
265
gamemodes/prop_hunt/gamemode/cl_hud.lua
Normal 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)
|
||||
83
gamemodes/prop_hunt/gamemode/cl_hud_mask.lua
Normal file
83
gamemodes/prop_hunt/gamemode/cl_hud_mask.lua
Normal 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)
|
||||
461
gamemodes/prop_hunt/gamemode/cl_init.lua
Normal file
461
gamemodes/prop_hunt/gamemode/cl_init.lua
Normal 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)
|
||||
646
gamemodes/prop_hunt/gamemode/cl_menu.lua
Normal file
646
gamemodes/prop_hunt/gamemode/cl_menu.lua
Normal 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." )
|
||||
51
gamemodes/prop_hunt/gamemode/cl_targetid.lua
Normal file
51
gamemodes/prop_hunt/gamemode/cl_targetid.lua
Normal 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
|
||||
278
gamemodes/prop_hunt/gamemode/cl_tauntwindow.lua
Normal file
278
gamemodes/prop_hunt/gamemode/cl_tauntwindow.lua
Normal 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)
|
||||
@@ -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)
|
||||
]]
|
||||
@@ -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)
|
||||
]]
|
||||
@@ -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)
|
||||
16
gamemodes/prop_hunt/gamemode/config/sh_init.lua
Normal file
16
gamemodes/prop_hunt/gamemode/config/sh_init.lua
Normal 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
|
||||
@@ -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") ]
|
||||
791
gamemodes/prop_hunt/gamemode/init.lua
Normal file
791
gamemodes/prop_hunt/gamemode/init.lua
Normal 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)
|
||||
329
gamemodes/prop_hunt/gamemode/mapvote/cl_mapvote.lua
Normal file
329
gamemodes/prop_hunt/gamemode/mapvote/cl_mapvote.lua
Normal 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")
|
||||
114
gamemodes/prop_hunt/gamemode/mapvote/rtv.lua
Normal file
114
gamemodes/prop_hunt/gamemode/mapvote/rtv.lua
Normal 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 )
|
||||
257
gamemodes/prop_hunt/gamemode/mapvote/sv_mapvote.lua
Normal file
257
gamemodes/prop_hunt/gamemode/mapvote/sv_mapvote.lua
Normal 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
|
||||
106
gamemodes/prop_hunt/gamemode/player_class/class_hunter.lua
Normal file
106
gamemodes/prop_hunt/gamemode/player_class/class_hunter.lua
Normal 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)
|
||||
93
gamemodes/prop_hunt/gamemode/player_class/class_prop.lua
Normal file
93
gamemodes/prop_hunt/gamemode/player_class/class_prop.lua
Normal 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)
|
||||
421
gamemodes/prop_hunt/gamemode/sh_config.lua
Normal file
421
gamemodes/prop_hunt/gamemode/sh_config.lua
Normal 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)
|
||||
73
gamemodes/prop_hunt/gamemode/sh_convars.lua
Normal file
73
gamemodes/prop_hunt/gamemode/sh_convars.lua
Normal 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.")
|
||||
24
gamemodes/prop_hunt/gamemode/sh_drive_prop.lua
Normal file
24
gamemodes/prop_hunt/gamemode/sh_drive_prop.lua
Normal 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)
|
||||
105
gamemodes/prop_hunt/gamemode/sh_httpupdates.lua
Normal file
105
gamemodes/prop_hunt/gamemode/sh_httpupdates.lua
Normal 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)
|
||||
129
gamemodes/prop_hunt/gamemode/sh_init.lua
Normal file
129
gamemodes/prop_hunt/gamemode/sh_init.lua
Normal 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)
|
||||
48
gamemodes/prop_hunt/gamemode/sh_mapvote.lua
Normal file
48
gamemodes/prop_hunt/gamemode/sh_mapvote.lua
Normal 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
|
||||
96
gamemodes/prop_hunt/gamemode/sh_player.lua
Normal file
96
gamemodes/prop_hunt/gamemode/sh_player.lua
Normal 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
|
||||
102
gamemodes/prop_hunt/gamemode/sh_plugins.lua
Normal file
102
gamemodes/prop_hunt/gamemode/sh_plugins.lua
Normal 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
|
||||
41
gamemodes/prop_hunt/gamemode/sh_precache.lua
Normal file
41
gamemodes/prop_hunt/gamemode/sh_precache.lua
Normal 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)
|
||||
48
gamemodes/prop_hunt/gamemode/sv_admin.lua
Normal file
48
gamemodes/prop_hunt/gamemode/sv_admin.lua
Normal 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)
|
||||
30
gamemodes/prop_hunt/gamemode/sv_autotaunt.lua
Normal file
30
gamemodes/prop_hunt/gamemode/sv_autotaunt.lua
Normal 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)
|
||||
100
gamemodes/prop_hunt/gamemode/sv_bbox_addition.lua
Normal file
100
gamemodes/prop_hunt/gamemode/sv_bbox_addition.lua
Normal 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)
|
||||
29
gamemodes/prop_hunt/gamemode/sv_networkfunctions.lua
Normal file
29
gamemodes/prop_hunt/gamemode/sv_networkfunctions.lua
Normal 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")
|
||||
22
gamemodes/prop_hunt/gamemode/sv_tauntwindow.lua
Normal file
22
gamemodes/prop_hunt/gamemode/sv_tauntwindow.lua
Normal 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)
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user