It's back bitches!
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
Changelist
|
||||
- Made Seeker Weapons & Ammo configurable from console & cfg file.
|
||||
- Updated Gamemode info so that new configuration options are visible on the client.
|
||||
|
||||
ToDo:
|
||||
- Replace all createconvar with getconvar?
|
||||
- Seeker model not existing after unblind?
|
||||
- End round triggers
|
||||
- Other game modes
|
||||
- UI stuff
|
||||
- Scoreboard
|
||||
- Custom Collisions for Hiders? Allows to copy the prop geometry/align with rotation
|
||||
@@ -1,50 +0,0 @@
|
||||
--Thanks to Blasteh for gmod update the fix and nifnat for spectate fix!
|
||||
|
||||
-- Send required files to client
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
|
||||
-- Include needed files
|
||||
include("shared.lua")
|
||||
|
||||
-- Called when we take damge
|
||||
function ENT:OnTakeDamage(dmg)
|
||||
local pl = self.Owner
|
||||
local attacker = dmg:GetAttacker()
|
||||
local inflictor = dmg:GetInflictor()
|
||||
|
||||
-- Health
|
||||
if pl && pl:IsValid() && pl:Alive() && pl:IsPlayer() && attacker:IsPlayer() && dmg:GetDamage() > 0 then
|
||||
pl:SetHealth(pl:Health() - dmg:GetDamage())
|
||||
|
||||
if pl:Health() <= 0 then
|
||||
-- Figure out real attacker.
|
||||
if inflictor && inflictor == attacker && inflictor:IsPlayer() then
|
||||
inflictor = inflictor:GetActiveWeapon()
|
||||
if !inflictor || inflictor == NULL then inflictor = attacker end
|
||||
end
|
||||
|
||||
-- Kill player and remove the prop
|
||||
pl:KillSilent()
|
||||
pl:RemoveProp() -- Needs to be executed before net.Broadcast
|
||||
|
||||
-- Send kill message.
|
||||
net.Start( "PlayerKilledByPlayer" )
|
||||
net.WriteEntity( pl )
|
||||
net.WriteString( inflictor:GetClass() )
|
||||
net.WriteEntity( attacker )
|
||||
net.Broadcast()
|
||||
|
||||
-- Broadcast same message to all players in console.
|
||||
MsgAll(attacker:Name() .. " found and killed " .. pl:Name() .. "\n")
|
||||
|
||||
-- Increment frags and deaths.
|
||||
attacker:AddFrags(1)
|
||||
pl:AddDeaths(1)
|
||||
|
||||
-- Update attacker health
|
||||
attacker:SetHealth(math.Clamp(attacker:Health() + GetConVar("HUNTER_KILL_BONUS"):GetInt(), 1, 100))
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,46 +0,0 @@
|
||||
-- Entity information
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_anim"
|
||||
|
||||
-- Initialize
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/player/Kleiner.mdl")
|
||||
self:DrawShadow(true);
|
||||
|
||||
-- Physical properties
|
||||
self:SetSolid(SOLID_OBB)
|
||||
|
||||
-- Initialize Networked Variables
|
||||
self:SetApplyNewAngles(false)
|
||||
self:SetHealth(100)
|
||||
if SERVER then self:SetMaxHealth(100) end
|
||||
if CLIENT then self.Owner.ph_prop = self.Entity end
|
||||
end
|
||||
|
||||
-- Set up shared Data.
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar( "Bool", 0, "ApplyNewAngles" )
|
||||
end
|
||||
|
||||
-- Update position
|
||||
function ENT:Think()
|
||||
-- Calculate hull size.
|
||||
local hullOBBMin = self:OBBMins()
|
||||
local hullOBBMax = self:OBBMaxs()
|
||||
local hullOBB = hullOBBMax - hullOBBMin
|
||||
|
||||
-- Shared update
|
||||
local pos = -Vector(0, 0, hullOBBMin.z)
|
||||
self:SetPos(self.Owner:GetPos() + pos)
|
||||
self:SetVelocity(self:GetOwner():GetVelocity())
|
||||
|
||||
-- Server only updates
|
||||
if SERVER then
|
||||
-- Prevent confusion by updating angles only on the server.
|
||||
if self:GetApplyNewAngles() then
|
||||
self:SetAngles(Angle(0, self:GetOwner():GetAngles().yaw, 0))
|
||||
end
|
||||
|
||||
self:NextThink( CurTime() )
|
||||
end
|
||||
end
|
||||
@@ -1,178 +0,0 @@
|
||||
-- Include the needed files
|
||||
include("sh_init.lua")
|
||||
--include("cl_hints.lua")
|
||||
|
||||
-- Draw round timeleft and hunter release timeleft
|
||||
function HUDPaint()
|
||||
if GetGlobalBool("InRound", false) then
|
||||
local blindlock_time_left = (GetConVar("HUNTER_BLINDLOCK_TIME"):GetInt() - (CurTime() - GetGlobalFloat("RoundStartTime", 0))) + 1
|
||||
|
||||
if blindlock_time_left < 1 && blindlock_time_left > -6 then
|
||||
blindlock_time_left_msg = "Hunters have been released!"
|
||||
elseif blindlock_time_left > 0 then
|
||||
blindlock_time_left_msg = "Hunters will be unblinded and released in "..string.ToMinutesSeconds(blindlock_time_left)
|
||||
else
|
||||
blindlock_time_left_msg = nil
|
||||
end
|
||||
|
||||
if LocalPlayer():Team() == TEAM_HUNTERS && blindlock_time_left > 1 then
|
||||
draw.RoundedBox(0, 0, 0, surface.ScreenWidth(), surface.ScreenHeight(), Color(20, 20, 20, 255))
|
||||
end
|
||||
|
||||
if blindlock_time_left_msg then
|
||||
surface.SetFont("MyFont")
|
||||
local tw, th = surface.GetTextSize(blindlock_time_left_msg)
|
||||
|
||||
draw.RoundedBox(8, 20, 20, tw + 20, 26, Color(0, 0, 0, 75))
|
||||
draw.DrawText(blindlock_time_left_msg, "MyFont", 31, 26, Color(255, 255, 0, 255), TEXT_ALIGN_LEFT)
|
||||
end
|
||||
end
|
||||
end
|
||||
hook.Add("HUDPaint", "PH_HUDPaint", HUDPaint)
|
||||
|
||||
-- Called immediately after starting the gamemode
|
||||
function Initialize()
|
||||
hullz = 80
|
||||
--surface.CreateFont("Arial", 14, 1200, true, false, "ph_arial")
|
||||
surface.CreateFont( "MyFont",
|
||||
{
|
||||
font = "Arial",
|
||||
size = 14,
|
||||
weight = 1200,
|
||||
antialias = true,
|
||||
underline = false
|
||||
})
|
||||
end
|
||||
hook.Add("Initialize", "PH_Initialize", Initialize)
|
||||
|
||||
|
||||
-- Resets the player hull
|
||||
function ResetHull(um)
|
||||
if LocalPlayer() && LocalPlayer():IsValid() then
|
||||
LocalPlayer():ResetHull()
|
||||
LocalPlayer():SetViewOffset(Vector(0, 0, 64))
|
||||
LocalPlayer():SetViewOffsetDucked(Vector(0, 0, 28))
|
||||
hullz = 80
|
||||
end
|
||||
end
|
||||
usermessage.Hook("ResetHull", ResetHull)
|
||||
|
||||
|
||||
-- Sets the local blind variable to be used in CalcView
|
||||
function SetBlind(um)
|
||||
blind = um:ReadBool()
|
||||
end
|
||||
usermessage.Hook("SetBlind", SetBlind)
|
||||
|
||||
|
||||
function GM:ShouldDrawLocalPlayer()
|
||||
return false
|
||||
end
|
||||
|
||||
function GM:CalcView( ply, pos, ang, fov )
|
||||
local view = {
|
||||
origin = pos,
|
||||
angles = ang,
|
||||
fov = fov
|
||||
}
|
||||
|
||||
if ply:Team() == TEAM_PROPS && ply:Alive() then
|
||||
-- Fix lua errors by doing this instead.
|
||||
if LocalPlayer().ThirdPersonDistance == nil then
|
||||
LocalPlayer().ThirdPersonDistance = 100
|
||||
end
|
||||
|
||||
-- Slowly return ThirdPersonDistance to 100
|
||||
local traceDist = math.Clamp(LocalPlayer().ThirdPersonDistance * 0.98 + 100 * 0.02, 0, 100)
|
||||
|
||||
-- Trace a line to find the correct position for the camera.
|
||||
local tracePos = pos
|
||||
local trace = {
|
||||
-- Start somewhat outside the prop.
|
||||
start = tracePos - (ang:Forward() * 5),
|
||||
endpos = tracePos - (ang:Forward() * (traceDist + 10)),
|
||||
filter = function(ent)
|
||||
if (ent == LocalPlayer() || ent == LocalPlayer().ph_prop || ent == LocalPlayer().ThirdPersonFilter || ent == ThirdPersonFilter) then
|
||||
return false
|
||||
elseif (ent:GetClass() == "ph_prop" || ent:GetClass() == "worldspawn") then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
}
|
||||
local traceResult = util.TraceLine(trace);
|
||||
|
||||
-- Readjust trace hit distance to force camera outside of the hit position.
|
||||
if traceResult.Hit then
|
||||
traceDist = math.max(traceResult.HitPos:Distance(tracePos) - 10, 0)
|
||||
end
|
||||
LocalPlayer().ThirdPersonDistance = traceDist
|
||||
|
||||
-- Correct view position
|
||||
view.origin = tracePos - (ang:Forward() * traceDist)
|
||||
--[[ else
|
||||
local wep = ply:GetActiveWeapon()
|
||||
if wep && wep != NULL then
|
||||
local func = wep.GetViewModelPosition
|
||||
if func then
|
||||
view.vm_origin, view.vm_angles = func(wep, origin*1, angles*1) -- Note: *1 to copy the object so the child function can't edit it.
|
||||
end
|
||||
|
||||
local func = wep.CalcView
|
||||
if func then
|
||||
view.origin, view.angles, view.fov = func(wep, pl, origin*1, angles*1, fov) -- Note: *1 to copy the object so the child function can't edit it.
|
||||
end
|
||||
end--]]
|
||||
end
|
||||
|
||||
return view;
|
||||
end
|
||||
|
||||
-- Render halos and player names.
|
||||
function DrawPlayerNames(bDrawingDepth, bDrawingSkybox)
|
||||
for i,v in ipairs(player.GetAll()) do
|
||||
if v:Alive() && v != LocalPlayer() then
|
||||
local pos = v:GetPos() + v:GetViewOffset() + Vector(0, 0, 5)
|
||||
local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x)
|
||||
local healthPrc = v:Health() / v:GetMaxHealth()
|
||||
local healthCol = HSVToColor(120 * healthPrc, 1.0, 1.0)
|
||||
|
||||
if v:Team() == TEAM_HUNTERS || LocalPlayer():Team() == TEAM_PROPS then
|
||||
cam.Start3D2D(pos, ang, 0.15)
|
||||
draw.DrawText(v:GetName(), "Trebuchet24", 0, -draw.GetFontHeight("Trebuchet24"), healthCol, TEXT_ALIGN_CENTER)
|
||||
cam.End3D2D()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
hook.Add("PostDrawTranslucentRenderables", "PH_DrawPlayerNames", DrawPlayerNames)
|
||||
|
||||
function DrawPlayerHalos(bDrawingDepth, bDrawingSkybox)
|
||||
for i,v in ipairs(player.GetAll()) do
|
||||
if v:Alive() then
|
||||
local pos = v:GetPos() + Vector(0, 0, 1) * (v:OBBMaxs().z - v:OBBMins().z + 5)
|
||||
local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x)
|
||||
local healthPrc = v:Health() / v:GetMaxHealth()
|
||||
local healthCol = HSVToColor(120 * healthPrc, 1.0, 1.0)
|
||||
|
||||
if v:Team() == TEAM_HUNTERS || LocalPlayer():Team() == TEAM_PROPS then
|
||||
local ent = v
|
||||
if v.ph_prop && v.ph_prop:IsValid() then ent = v.ph_prop end
|
||||
|
||||
halo.Add({ent}, healthCol, 2, 2, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--hook.Add("PostDrawEffects", "PH_DrawPlayerHalos", DrawPlayerHalos)
|
||||
|
||||
-- UMSG: Update player Hull and health.
|
||||
function UMSGSetHull(um)
|
||||
local hullOBBMin = um:ReadVector()
|
||||
local hullOBBMax = um:ReadVector()
|
||||
local new_health = um:ReadShort()
|
||||
|
||||
LocalPlayer():NewHull(hullOBBMin, hullOBBMax)
|
||||
LocalPlayer():SetHealth(new_health)
|
||||
end
|
||||
usermessage.Hook("SetHull", UMSGSetHull)
|
||||
@@ -1,93 +0,0 @@
|
||||
|
||||
|
||||
surface.CreateFont( "GModWorldtip",
|
||||
{
|
||||
font = "Helvetica",
|
||||
size = 20,
|
||||
weight = 700
|
||||
})
|
||||
|
||||
local cl_drawworldtooltips = CreateConVar( "cl_drawworldtooltips", "1", { FCVAR_ARCHIVE } )
|
||||
local WorldTip = nil
|
||||
|
||||
local TipColor = Color( 250, 250, 200, 255 )
|
||||
|
||||
--
|
||||
-- Adds a hint to the queue
|
||||
--
|
||||
function AddWorldTip( unused1, text, unused2, pos, ent )
|
||||
|
||||
WorldTip = {}
|
||||
|
||||
WorldTip.dietime = SysTime() + 0.05
|
||||
WorldTip.text = text
|
||||
WorldTip.pos = pos
|
||||
WorldTip.ent = ent
|
||||
|
||||
end
|
||||
|
||||
|
||||
local function DrawWorldTip( tip )
|
||||
|
||||
if ( IsValid( tip.ent ) ) then
|
||||
tip.pos = tip.ent:GetPos()
|
||||
end
|
||||
|
||||
local pos = tip.pos:ToScreen()
|
||||
|
||||
local black = Color( 0, 0, 0, 255 )
|
||||
local tipcol = Color( TipColor.r, TipColor.g, TipColor.b, 255 )
|
||||
|
||||
local x = 0
|
||||
local y = 0
|
||||
local padding = 10
|
||||
local offset = 50
|
||||
|
||||
surface.SetFont( "GModWorldtip" )
|
||||
local w, h = surface.GetTextSize( tip.text )
|
||||
|
||||
x = pos.x - w
|
||||
y = pos.y - h
|
||||
|
||||
x = x - offset
|
||||
y = y - offset
|
||||
|
||||
draw.RoundedBox( 8, x-padding-2, y-padding-2, w+padding*2+4, h+padding*2+4, black )
|
||||
|
||||
|
||||
local verts = {}
|
||||
verts[1] = { x=x+w/1.5-2, y=y+h+2 }
|
||||
verts[2] = { x=x+w+2, y=y+h/2-1 }
|
||||
verts[3] = { x=pos.x-offset/2+2, y=pos.y-offset/2+2 }
|
||||
|
||||
draw.NoTexture()
|
||||
surface.SetDrawColor( 0, 0, 0, tipcol.a )
|
||||
surface.DrawPoly( verts )
|
||||
|
||||
|
||||
draw.RoundedBox( 8, x-padding, y-padding, w+padding*2, h+padding*2, tipcol )
|
||||
|
||||
local verts = {}
|
||||
verts[1] = { x=x+w/1.5, y=y+h }
|
||||
verts[2] = { x=x+w, y=y+h/2 }
|
||||
verts[3] = { x=pos.x-offset/2, y=pos.y-offset/2 }
|
||||
|
||||
draw.NoTexture()
|
||||
surface.SetDrawColor( tipcol.r, tipcol.g, tipcol.b, tipcol.a )
|
||||
surface.DrawPoly( verts )
|
||||
|
||||
|
||||
draw.DrawText( tip.text, "GModWorldtip", x + w/2, y, black, TEXT_ALIGN_CENTER )
|
||||
|
||||
end
|
||||
|
||||
|
||||
function GM:PaintWorldTips()
|
||||
|
||||
if ( !cl_drawworldtooltips:GetBool() ) then return end
|
||||
|
||||
if ( WorldTip && WorldTip.dietime > SysTime() ) then
|
||||
DrawWorldTip( WorldTip )
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,401 +0,0 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Project Kube
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
--! Client Files
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("sh_init.lua")
|
||||
|
||||
--! Include shared lua.
|
||||
include "sh_init.lua"
|
||||
|
||||
--! Include server lua.
|
||||
include "server/config.lua"
|
||||
include "server/console/variables.lua"
|
||||
include "compat/compat_tauntpackloader.lua"
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Gamemode
|
||||
-- ------------------------------------------------------------------------- --
|
||||
|
||||
-- GameStates
|
||||
GM_STATES_SETUP = 0
|
||||
GM_STATES_HIDE = 1
|
||||
GM_STATES_SEEK = 2
|
||||
GM_STATES_SHAMING = 3 -- Do your best, hiders!
|
||||
|
||||
--! Initialize
|
||||
function GM:Initialize()
|
||||
self.State = GM_STATES_SETUP
|
||||
self.StatePrev = self.State
|
||||
|
||||
--! Run any hooked functions that addons have registered for Prop Hunt.
|
||||
hook.Run("OnPropHuntInitialized")
|
||||
end
|
||||
|
||||
--! Check Victory and Loss conditions
|
||||
function GM:Think()
|
||||
if (self.State == GM_STATES_SETUP) then
|
||||
--! GameState: Setup
|
||||
-- Here we do all the stuff that would be ridiculous to do while playing.
|
||||
if (self.StatePrev != self.State) then
|
||||
game.CleanUpMap()
|
||||
|
||||
-- Assign correct teams depending on Sub-Gamemode.
|
||||
if (self.Config.Modes.SwapTeams == 1) then
|
||||
for i,pl in ipairs(player.GetAll()) do
|
||||
if (pl:Team() == TEAM_HIDERS) then
|
||||
pl:SetTeam(TEAM_SEEKERS)
|
||||
elseif (pl:Team() == TEAM_SEEKERS) then
|
||||
pl:SetTeam(TEAM_HIDERS)
|
||||
end
|
||||
end
|
||||
elseif (self.Config.Modes.RandomizeTeams == 1) then
|
||||
local plys = player.GetAll()
|
||||
--local plyCount =
|
||||
|
||||
elseif (self.Config.Modes.TheDeadHunt == 1) then
|
||||
|
||||
end
|
||||
|
||||
-- Respawn players
|
||||
for i,pl in ipairs(player.GetAll()) do
|
||||
pl:Respawn()
|
||||
end
|
||||
end
|
||||
|
||||
-- Advanced to next GameState if we have enough players
|
||||
self.StatePrev = self.State
|
||||
self.State = GM_STATES_HIDE
|
||||
elseif (self.State == GM_STATES_HIDE) then
|
||||
|
||||
elseif (self.State == GM_STATES_SEEK) then
|
||||
|
||||
elseif (self.State == GM_STATES_SHAMING) then
|
||||
|
||||
else
|
||||
-- Invalid State, we have to reset
|
||||
self.StatePrev = self.State
|
||||
self.State = GM_STATES_SETUP
|
||||
end
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! LEGACY CODE - TO BE REPLACED SOON
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function GM:AllowPlayerPickup(player, entity)
|
||||
return true
|
||||
end
|
||||
|
||||
function AnnounceVictory(players, force)
|
||||
for i,pl in ipairs(players) do
|
||||
if pl:Alive() || force || pl:Team() == TEAM_SPECTATOR then
|
||||
announcer = table.Random(VICTORY_SOUNDS);
|
||||
print("Prop Hunt: '"..pl:GetName().."' announcing victory with '"..announcer.."'.")
|
||||
pl:EmitSound(announcer, 200, 100, 0.5, CHAN_VOICE2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AnnounceLoss(players, force)
|
||||
for i,pl in ipairs(players) do
|
||||
if pl:Alive() || force || pl:Team() == TEAM_SPECTATOR then
|
||||
announcer = table.Random(LOSS_SOUNDS);
|
||||
print("Prop Hunt: '"..pl:GetName().."' announcing loss with '"..announcer.."'.")
|
||||
pl:EmitSound(announcer, 100, 100, 0.5, CHAN_VOICE2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If there is a mapfile send it to the client (sometimes servers want to change settings for certain maps)
|
||||
if file.Exists("maps/"..game.GetMap()..".lua", "LUA") then
|
||||
AddCSLuaFile("maps/"..game.GetMap()..".lua")
|
||||
end
|
||||
|
||||
|
||||
-- Server only constants
|
||||
EXPLOITABLE_DOORS = {
|
||||
"func_door",
|
||||
"prop_door_rotating",
|
||||
"func_door_rotating"
|
||||
}
|
||||
USABLE_PROP_ENTITIES = {
|
||||
"prop_physics",
|
||||
"prop_physics_multiplayer"
|
||||
}
|
||||
|
||||
-- Send the required resources to the client
|
||||
for _, announcer in pairs(LOSS_SOUNDS) do resource.AddFile("sound/"..announcer) end
|
||||
for _, announcer in pairs(VICTORY_SOUNDS) do resource.AddFile("source/"..announcer) end
|
||||
for _, taunt in pairs(HUNTER_TAUNTS) do resource.AddFile("sound/"..taunt) end
|
||||
for _, taunt in pairs(PROP_TAUNTS) do resource.AddFile("sound/"..taunt) end
|
||||
|
||||
-- Called alot
|
||||
function GM:CheckPlayerDeathRoundEnd()
|
||||
if !GAMEMODE.RoundBased || !GAMEMODE:InRound() then
|
||||
return
|
||||
end
|
||||
|
||||
local Teams = GAMEMODE:GetTeamAliveCounts()
|
||||
|
||||
if table.Count(Teams) == 0 then
|
||||
GAMEMODE:RoundEndWithResult(1001, "Draw, everyone loses!")
|
||||
AnnounceLoss(player.GetAll(), true)
|
||||
return
|
||||
end
|
||||
|
||||
if table.Count(Teams) == 1 then
|
||||
-- Play victory and loss sounds.
|
||||
if Teams[0] == TEAM_HUNTERS then
|
||||
AnnounceVictory(team.GetPlayers(TEAM_HUNTERS))
|
||||
AnnounceLoss(team.GetPlayers(TEAM_PROPS))
|
||||
elseif Teams[0] == TEAM_PROPS then
|
||||
AnnounceLoss(team.GetPlayers(TEAM_HUNTERS))
|
||||
AnnounceVictory(team.GetPlayers(TEAM_PROPS))
|
||||
end
|
||||
|
||||
local TeamID = table.GetFirstKey(Teams)
|
||||
GAMEMODE:RoundEndWithResult(TeamID, team.GetName(TeamID).." win!")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Called when an entity takes damage
|
||||
function EntityTakeDamage(ent, dmginfo)
|
||||
local att = dmginfo:GetAttacker()
|
||||
if GAMEMODE:InRound() && ent && ent:GetClass() != "ph_prop" && !ent:IsPlayer() && att && att:IsPlayer() && att:Team() == TEAM_HUNTERS && att:Alive() then
|
||||
att:SetHealth(att:Health() - GetConVar("HUNTER_FIRE_PENALTY"):GetInt())
|
||||
if att:Health() <= 0 then
|
||||
MsgAll(att:Name() .. " felt guilty for hurting so many innocent props and committed suicide\n")
|
||||
att:Kill()
|
||||
end
|
||||
end
|
||||
end
|
||||
hook.Add("EntityTakeDamage", "PH_EntityTakeDamage", EntityTakeDamage)
|
||||
|
||||
|
||||
-- Called when player tries to pickup a weapon
|
||||
function GM:PlayerCanPickupWeapon(pl, ent)
|
||||
if pl:Team() != TEAM_HUNTERS then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-- Called when player needs a model
|
||||
function GM:PlayerSetModel(pl)
|
||||
local player_model = pl:GetModel()
|
||||
|
||||
if pl:Team() == TEAM_HUNTERS then
|
||||
player_model = "models/player/combine_super_soldier.mdl"
|
||||
elseif pl:Team() == TEAM_PROPS then
|
||||
player_model = "models/Gibs/Antlion_gib_small_3.mdl"
|
||||
end
|
||||
|
||||
util.PrecacheModel(player_model)
|
||||
pl:SetModel(player_model)
|
||||
end
|
||||
|
||||
|
||||
-- Called when a player tries to use an object
|
||||
function GM:PlayerUse(pl, ent)
|
||||
if !pl:Alive() || pl:Team() == TEAM_SPECTATOR then return false end
|
||||
|
||||
-- if pl:Team() == TEAM_PROPS && pl:IsOnGround() && !pl:Crouching() && table.HasValue(USABLE_PROP_ENTITIES, ent:GetClass()) && ent:GetModel() then
|
||||
if pl:Team() == TEAM_PROPS && table.HasValue(USABLE_PROP_ENTITIES, ent:GetClass()) && ent:GetModel() then
|
||||
if table.HasValue(BANNED_PROP_MODELS, ent:GetModel()) then
|
||||
pl:ChatPrint("That prop has been banned by the server.")
|
||||
elseif ent:GetPhysicsObject():IsValid() then -- && pl.ph_prop:GetModel() != ent:GetModel() then
|
||||
local ent_health = math.Clamp(ent:GetPhysicsObject():GetVolume() / 250, 1, 200)
|
||||
|
||||
-- Prevent props from gaining health by changing.
|
||||
local per = math.min(pl:Health() / pl:GetMaxHealth(), pl.tempHealthPc || 1.0)
|
||||
if (pl.tempHealthPc == nil) || (per <= pl.tempHealthPc) then pl.tempHealthPc = per end
|
||||
local new_health = math.Clamp(per * ent_health, 1, 200)
|
||||
|
||||
pl:SetJumpPower(math.Clamp(ent:GetPhysicsObject():GetVolume() / 333, 200, 600));
|
||||
|
||||
-- Set Prop Data
|
||||
pl.ph_prop:SetHealth(new_health)
|
||||
pl.ph_prop:SetMaxHealth(ent_health)
|
||||
pl.ph_prop:SetModel(ent:GetModel())
|
||||
pl.ph_prop:SetSkin(ent:GetSkin())
|
||||
|
||||
-- Update Hull and Health
|
||||
pl:NewHull(ent:OBBMins(), ent:OBBMaxs())
|
||||
pl:SetHealth(new_health)
|
||||
pl:SetMaxHealth(ent_health)
|
||||
umsg.Start("SetHull", pl)
|
||||
umsg.Vector(ent:OBBMins())
|
||||
umsg.Vector(ent:OBBMaxs())
|
||||
umsg.Short(new_health)
|
||||
umsg.End()
|
||||
end
|
||||
end
|
||||
|
||||
-- Prevent the door exploit
|
||||
if table.HasValue(EXPLOITABLE_DOORS, ent:GetClass()) && pl.last_door_time && pl.last_door_time + 1 > CurTime() then
|
||||
return false
|
||||
end
|
||||
|
||||
pl.last_door_time = CurTime()
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-- Called when player presses [F3]. Plays a taunt for their team
|
||||
function GM:ShowSpare1(pl)
|
||||
if GAMEMODE:InRound() && pl:Alive() && (pl:Team() == TEAM_HUNTERS || pl:Team() == TEAM_PROPS) && pl.last_taunt_time + TAUNT_DELAY <= CurTime() && #PROP_TAUNTS > 1 && #HUNTER_TAUNTS > 1 then
|
||||
-- repeat
|
||||
if pl:Team() == TEAM_HUNTERS then
|
||||
rand_taunt = table.Random(HUNTER_TAUNTS)
|
||||
else
|
||||
rand_taunt = table.Random(PROP_TAUNTS)
|
||||
end
|
||||
-- until rand_taunt != pl.last_taunt
|
||||
|
||||
pl.last_taunt_time = CurTime()
|
||||
pl.last_taunt = rand_taunt
|
||||
|
||||
print("Prop Hunt: '"..pl:GetName().."' taunting with '"..rand_taunt.."'.")
|
||||
local vol = 1.0
|
||||
if pl:Team() == TEAM_HUNTERS then vol = vol * 0.5 end
|
||||
pl:EmitSound(rand_taunt, 100, 100, vol, CHAN_VOICE2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Allow player to rotate the prop. (Either F4 or ducking)
|
||||
function GM:ShowSpare2(pl)
|
||||
if pl:Alive() && (pl:Team() == TEAM_PROPS) then
|
||||
pl.ph_prop:SetApplyNewAngles(!pl.ph_prop:GetApplyNewAngles())
|
||||
-- pl.ph_prop:SetNewAngles(pl:GetAngles())
|
||||
end
|
||||
end
|
||||
|
||||
-- Called when the gamemode is initialized
|
||||
function Initialize()
|
||||
game.ConsoleCommand("mp_flashlight 0\n")
|
||||
end
|
||||
hook.Add("Initialize", "PH_Initialize", Initialize)
|
||||
|
||||
|
||||
-- Called when a player leaves
|
||||
function PlayerDisconnected(pl)
|
||||
pl:RemoveProp()
|
||||
end
|
||||
hook.Add("PlayerDisconnected", "PH_PlayerDisconnected", PlayerDisconnected)
|
||||
|
||||
|
||||
-- Called when the players spawns
|
||||
function PlayerSpawn(pl)
|
||||
pl:Blind(false)
|
||||
pl:RemoveProp()
|
||||
pl:SetColor( Color(255, 255, 255, 255))
|
||||
pl:SetRenderMode( RENDERMODE_TRANSALPHA )
|
||||
pl:UnLock()
|
||||
pl:ResetHull()
|
||||
pl:SetViewOffset(Vector(0, 0, 64))
|
||||
pl:SetViewOffsetDucked(Vector(0, 0, 28))
|
||||
pl.last_taunt_time = 0
|
||||
pl:SetupHands()
|
||||
|
||||
umsg.Start("ResetHull", pl)
|
||||
umsg.End()
|
||||
-- umsg.Start("ThirdPerson", pl)
|
||||
-- umsg.Bool(pl:Team() == TEAM_PROPS)
|
||||
-- umsg.Entity(nil)
|
||||
-- umsg.End()
|
||||
|
||||
pl:SetCollisionGroup(COLLISION_GROUP_PASSABLE_DOOR)
|
||||
end
|
||||
hook.Add("PlayerSpawn", "PH_PlayerSpawn", PlayerSpawn)
|
||||
|
||||
function GM:PlayerSetHandsModel( ply, ent )
|
||||
local simplemodel = player_manager.TranslateToPlayerModelName( ply:GetModel() )
|
||||
local info = player_manager.TranslatePlayerHands( simplemodel )
|
||||
if ( info ) then
|
||||
ent:SetModel( info.model )
|
||||
ent:SetSkin( info.skin )
|
||||
ent:SetBodyGroups( info.body )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Removes all weapons on a map
|
||||
function RemoveWeaponsAndItems()
|
||||
for _, wep in pairs(ents.FindByClass("weapon_*")) do
|
||||
wep:Remove()
|
||||
end
|
||||
|
||||
for _, item in pairs(ents.FindByClass("item_*")) do
|
||||
item:Remove()
|
||||
end
|
||||
end
|
||||
hook.Add("InitPostEntity", "PH_RemoveWeaponsAndItems", RemoveWeaponsAndItems)
|
||||
|
||||
|
||||
-- Called when round ends
|
||||
function RoundEnd()
|
||||
for _, pl in pairs(team.GetPlayers(TEAM_HUNTERS)) do
|
||||
pl:Blind(false)
|
||||
pl:UnLock()
|
||||
end
|
||||
end
|
||||
hook.Add("RoundEnd", "PH_RoundEnd", RoundEnd)
|
||||
|
||||
|
||||
-- This is called when the round time ends (props win)
|
||||
function GM:RoundTimerEnd()
|
||||
if !GAMEMODE:InRound() then
|
||||
return
|
||||
end
|
||||
|
||||
GAMEMODE:RoundEndWithResult(TEAM_PROPS, "Props win!")
|
||||
end
|
||||
|
||||
|
||||
-- Called before start of round
|
||||
function GM:OnPreRoundStart(num)
|
||||
game.CleanUpMap()
|
||||
|
||||
if GetGlobalInt("RoundNumber") != 1 && (SWAP_TEAMS_EVERY_ROUND == 1 || ((team.GetScore(TEAM_PROPS) + team.GetScore(TEAM_HUNTERS)) > 0 || SWAP_TEAMS_POINTS_ZERO==1)) then
|
||||
for _, pl in pairs(player.GetAll()) do
|
||||
if pl:Team() == TEAM_PROPS || pl:Team() == TEAM_HUNTERS then
|
||||
if pl:Team() == TEAM_PROPS then
|
||||
pl:SetTeam(TEAM_HUNTERS)
|
||||
else
|
||||
pl:SetTeam(TEAM_PROPS)
|
||||
end
|
||||
|
||||
pl:ChatPrint("Teams have been swapped!")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
UTIL_StripAllPlayers()
|
||||
UTIL_SpawnAllPlayers()
|
||||
UTIL_FreezeAllPlayers()
|
||||
end
|
||||
@@ -1,52 +0,0 @@
|
||||
-- Create new class
|
||||
DEFINE_BASECLASS( "player_default" )
|
||||
local CLASS = {}
|
||||
|
||||
-- Some settings for the class
|
||||
CLASS.DisplayName = "Hider"
|
||||
CLASS.WalkSpeed = 250
|
||||
CLASS.CrouchedWalkSpeed = 0.2
|
||||
CLASS.RunSpeed = 250
|
||||
CLASS.DuckSpeed = 0.2
|
||||
CLASS.DrawTeamRing = false
|
||||
|
||||
-- Called by spawn and sets loadout
|
||||
function CLASS:Loadout(pl)
|
||||
-- Props don't get anything
|
||||
end
|
||||
|
||||
-- Called when player spawns with this class
|
||||
function CLASS:OnSpawn(pl)
|
||||
pl:SetColor( Color(255, 255, 255, 0))
|
||||
|
||||
pl.ph_prop = ents.Create("ph_prop")
|
||||
pl.ph_prop:SetPos(pl:GetPos())
|
||||
pl.ph_prop:SetAngles(pl:GetAngles())
|
||||
pl.ph_prop:Spawn()
|
||||
pl.ph_prop:SetOwner(pl)
|
||||
|
||||
pl:SetJumpPower(200);
|
||||
|
||||
-- Update Hull and Health
|
||||
pl:SetHealth(100)
|
||||
pl:SetMaxHealth(100)
|
||||
pl.ph_prop:SetHealth(100)
|
||||
pl.ph_prop:SetMaxHealth(100)
|
||||
|
||||
local hullMin = Vector(-20, -20, -10)
|
||||
local hullMax = Vector( 20, 20, 60)
|
||||
pl:NewHull(hullMin, hullMax)
|
||||
umsg.Start("SetHull", pl)
|
||||
umsg.Vector(hullMin)
|
||||
umsg.Vector(hullMax)
|
||||
umsg.Short(100)
|
||||
umsg.End()
|
||||
end
|
||||
|
||||
-- Called when a player dies with this class
|
||||
function CLASS:OnDeath(pl, attacker, dmginfo)
|
||||
pl:RemoveProp()
|
||||
end
|
||||
|
||||
-- Register
|
||||
player_manager.RegisterClass("Hider", CLASS)
|
||||
@@ -1,120 +0,0 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Project Kube
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
--! This file defines the Seeker player class.
|
||||
-- A seeker is someone who is looking for the hiders, using weapons or other
|
||||
-- means of detecting idiots. Also someone who looks like a diaper baby.
|
||||
-- Weapons and Ammo are granted upon spawn and have to be used sparingly or
|
||||
-- they'll be stuck with the crowbar. Bad seeker, bad.
|
||||
-- Gain health upon killing a hider, lose health when attacking non-hiders.
|
||||
-- Death upon health reaching 0.
|
||||
|
||||
DEFINE_BASECLASS( "player_default" )
|
||||
local SEEKER = {}
|
||||
SEEKER.DisplayName = "Seeker"
|
||||
SEEKER.WalkSpeed = 230 -- How fast to move when not running
|
||||
SEEKER.RunSpeed = 460 -- How fast to move when running
|
||||
SEEKER.CrouchedWalkSpeed = 0.2 -- Multiply move speed by this when crouching
|
||||
SEEKER.DuckSpeed = 0.2 -- How fast to go from not ducking, to ducking
|
||||
SEEKER.UnDuckSpeed = 0.2 -- How fast to go from ducking, to not ducking
|
||||
SEEKER.JumpPower = 200 -- How powerful our jump should be
|
||||
SEEKER.CanUseFlashlight = true -- Can we use the flashlight
|
||||
SEEKER.MaxHealth = 100 -- Max health we can have
|
||||
SEEKER.StartHealth = 100 -- How much health we start with
|
||||
SEEKER.StartArmor = 0 -- How much armour we start with
|
||||
SEEKER.DropWeaponOnDie = false -- Do we drop our weapon when we die
|
||||
SEEKER.TeammateNoCollide = true -- Do we collide with teammates or run straight through them
|
||||
SEEKER.AvoidPlayers = true -- Automatically swerves around other players
|
||||
SEEKER.UseVMHands = true -- Uses viewmodel hands
|
||||
|
||||
-- Called by spawn and sets loadout
|
||||
function SEEKER:Loadout(pl)
|
||||
-- Give the weapons the admin told us to.
|
||||
local weapons = string.Split(GM.Config.Seeker.Weapons, ",")
|
||||
for i,weapon in ipairs(weapons) do
|
||||
pl:Give(weapon)
|
||||
end
|
||||
|
||||
-- Give the ammo the admin told us to.
|
||||
local ammos = string.Split(GM.Config.Seeker.Ammo, ",")
|
||||
for i,ammo in ipairs(ammos) do
|
||||
local typeCount = string.Split(ammo, ":")
|
||||
pl:GiveAmmo(typeCount[1], typeCount[0], true)
|
||||
end
|
||||
|
||||
-- Default weapon stuff
|
||||
local cl_defaultweapon = pl:GetInfo("cl_defaultweapon")
|
||||
if pl:HasWeapon(cl_defaultweapon) then
|
||||
pl:SelectWeapon(cl_defaultweapon)
|
||||
end
|
||||
end
|
||||
|
||||
-- Called when player spawns with this class
|
||||
function SEEKER:OnSpawn(pl)
|
||||
local unlock_time = math.Clamp(GetConVar("ph_rounds_blindtime"):GetInt() - (CurTime() - GetGlobalFloat("RoundStartTime", 0)), 0, GetConVar("ph_rounds_blindtime"):GetInt()) - 1
|
||||
-- !TODO! ph_rounds_blindtime
|
||||
|
||||
--function MyLockFunc()
|
||||
--function MyUnlockFunc()
|
||||
|
||||
local unblindfunc = function()
|
||||
if pl:IsValid() == false then return end
|
||||
--MyUnblindFunc(pl.Blind(false))
|
||||
pl:Blind(false)
|
||||
end
|
||||
local lockfunc = function()
|
||||
if pl:IsValid() == false then return end
|
||||
--MyLockFunc(pl.Lock())
|
||||
pl.Lock(pl)
|
||||
end
|
||||
local unlockfunc = function()
|
||||
if pl:IsValid() == false then return end
|
||||
--MyUnlockFunc(pl.UnLock())
|
||||
pl.UnLock(pl)
|
||||
end
|
||||
|
||||
if unlock_time > 2 then
|
||||
pl:Blind(true)
|
||||
|
||||
timer.Simple(unlock_time, unblindfunc)
|
||||
|
||||
timer.Simple(1, lockfunc)
|
||||
timer.Simple(unlock_time, unlockfunc)
|
||||
end
|
||||
|
||||
pl:SetupHands()
|
||||
end
|
||||
|
||||
function SEEKER:GetHandsModel()
|
||||
return { model = "models/weapons/c_arms_combine.mdl", skin = 1, body = "0100000" }
|
||||
end
|
||||
|
||||
-- Called when a player dies with this SEEKER
|
||||
function SEEKER:OnDeath(pl, attacker, dmginfo)
|
||||
pl:CreateRagdoll()
|
||||
pl:UnLock()
|
||||
end
|
||||
|
||||
-- Register
|
||||
player_manager.RegisterClass("Seeker", SEEKER)
|
||||
@@ -1,433 +0,0 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Project Kube
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
--! Initialize configuration table.
|
||||
GM.Config = { }
|
||||
|
||||
--! Basic Settings
|
||||
-- Timelimit in minutes
|
||||
GM.Config.TimeLimit = math.max(GetConVarNumber("mp_timelimit"),0)
|
||||
-- You have to wait x seconds to taunt again.
|
||||
GM.Config.TauntWaitTime = 5
|
||||
-- Is sprinting enabled?
|
||||
GM.Config.Sprinting = 0 --false
|
||||
|
||||
--! Round Settings
|
||||
GM.Config.Rounds = {}
|
||||
-- How many rounds should we attempt to have?
|
||||
GM.Config.Rounds.Amount = 10
|
||||
-- Rounds last x seconds.
|
||||
GM.Config.Rounds.Time = 300
|
||||
-- Time for HIders to hide.
|
||||
GM.Config.Rounds.BlindTime = 30
|
||||
|
||||
--! Game Modes
|
||||
GM.Config.Modes = {}
|
||||
-- Sub-mode: Simple Team Swap
|
||||
GM.Config.Modes.SwapTeams = 1--true
|
||||
-- Sub-mode: Randomize Teams
|
||||
GM.Config.Modes.RandomizeTeams = 0--false
|
||||
-- Sub-mode: The Dead Hunt (Dead Prop becomes Hunter)
|
||||
GM.Config.Modes.TheDeadHunt = 0--false
|
||||
|
||||
--! Seeker Settings
|
||||
GM.Config.Seeker = {}
|
||||
GM.Config.Seeker.HealthStart = 100
|
||||
GM.Config.Seeker.HealthMax = 100
|
||||
GM.Config.Seeker.HealthBonus = 10
|
||||
GM.Config.Seeker.HealthPenalty = 1
|
||||
GM.Config.Seeker.Weapons = "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun"
|
||||
GM.Config.Seeker.Ammo = "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64"
|
||||
|
||||
--! Hider Settings
|
||||
GM.Config.Hider = {}
|
||||
GM.Config.Hider.HealthStart = 100
|
||||
GM.Config.Hider.HealthMax = 100
|
||||
GM.Config.Hider.HealthScaling = 1--true
|
||||
GM.Config.Hider.HealthScalingMax = 200
|
||||
|
||||
--! Taunts
|
||||
GM.Config.Taunts = {
|
||||
Seeker = { },
|
||||
Hider = { },
|
||||
}
|
||||
|
||||
-- Taunts.Clear()
|
||||
--@desc: Clears the current taunt list.
|
||||
GM.Config.Taunts.Clear = function()
|
||||
this.Seeker = {}
|
||||
this.Hider = {}
|
||||
end
|
||||
|
||||
-- Taunts.Load(sTauntListFile)
|
||||
--@desc: Loads the taunt list from disk.
|
||||
--@param:
|
||||
-- sTauntListFile - A string containing the path to the taunt list to load.
|
||||
--@return: true or false depending on success.
|
||||
GM.Config.Taunts.Load = function(sTauntListFile)
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Load: Loading taunt list from file '"..sTauntListFile.."'...") end
|
||||
|
||||
-- Safeguard against idiots.
|
||||
if type(sTauntListFile) != "string" then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Load: <sTauntListFile> is not a string.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Given file must exist for us to continue.
|
||||
if ! file.Exists(sTauntListFile, "GAME") then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Load: File not found.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Read the file and check if it's empty.
|
||||
sTauntListData = file.Read(sTauntListFile, "GAME")
|
||||
if sTauntListData == "" then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Load: File is empty.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Convert JSON to a table for us to use.
|
||||
sTauntList = util.JSONToTable(sTauntListData)
|
||||
|
||||
-- Is it nil? Then it's not valid JSON
|
||||
if sTauntList == nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Load: File contains invalid JSON.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Finally, append the taunt lists.
|
||||
if sTauntList.Seeker != nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Load: Adding Seeker taunts...") end
|
||||
for k,v in pairs(sTauntList.Seeker) do
|
||||
GAMEMODE.Taunts.Seeker[k] = v
|
||||
end
|
||||
end
|
||||
if sTauntList.Hider != nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Load: Adding Hider taunts...") end
|
||||
for k,v in pairs(sTauntList.Hider) do
|
||||
GAMEMODE.Taunts.Hider[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Load: Complete.") end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Taunts.Save(sTauntListFile)
|
||||
--@desc: Saves the current taunt list to disk.
|
||||
--@param:
|
||||
-- sTauntListFile - A string containing the path to the file to save to.
|
||||
--@return: true or false depending on success.
|
||||
GM.Config.Taunts.Save = function(sTauntListFile)
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Save: Saving taunt list to file '"..sTauntListFile.."'...") end
|
||||
|
||||
-- Safeguard against idiots.
|
||||
if type(sTauntListFile) != "string" then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Save: <sTauntListFile> is not a string.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- File must not be nil, otherwise we can't write to it.
|
||||
if sTauntListFile == nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Save: No file given.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Convert our taunt table to JSON.
|
||||
sTauntListData = util.TableToJSON(GAMEMODE.Taunts);
|
||||
if sTauntListData == nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Save: Corrupted GAMEMODE table.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Write out JSON out to file
|
||||
if ! file.Write(sTauntListFile, sTauntListData) then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Save: Failed to write to file.") end
|
||||
return false
|
||||
end
|
||||
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Save: Complete.") end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Taunts.Add(sTauntName, sSoundFile, iTeamID, mPropFilter)
|
||||
--@desc: Registers a new taunt with the given name, file, team and filter.
|
||||
--@param:
|
||||
-- sTauntName - The unique name of the taunt.
|
||||
-- sSoundFile - A sound file to play when this taunt is selected.
|
||||
-- iTeamID - The team that should receive the taunt or nil for all teams.
|
||||
-- mPropFilter - A string or a table containing strings for props that should be able to use this taunt.
|
||||
--@return: true or false depending on success.
|
||||
GM.Config.Taunts.Add = function(sTauntName, sSoundFile, iTeamID, mPropFilter)
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: Adding new taunt '"..sTauntName.."'...") end
|
||||
|
||||
-- Safeguard against idiots.
|
||||
if type(sTauntName) != "string" then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: <sTauntName> is not a string.") end
|
||||
return false
|
||||
end
|
||||
if type(sSoundFile) != "string" then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: <sSoundFile> is not a string.") end
|
||||
return false
|
||||
end
|
||||
if (type(iTeamID) != "number" && iTeamID != nil) then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: <iTeamID> is not a number or nil.") end
|
||||
return false
|
||||
end
|
||||
if (type(mPropFilter) != "string" && type(mPropFilter) != "table" && mPropFilter != nil) then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: <mPropFilter> is not a string, table or nil.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Check if the sound file actually exists
|
||||
if !file.Exists("sound/"..sSoundFile, "GAME") then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: File '"..sSoundFile.."' does not exist.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Make sure that our prop filter is a table listing the props it's supposed to work for.
|
||||
if (mPropFilter == nil) then
|
||||
mPropFilter = { }
|
||||
elseif type(mPropFilter) == "string" then
|
||||
mPropFilter = { mPropFilter }
|
||||
end
|
||||
|
||||
-- Prepare Taunt table
|
||||
Taunt = {
|
||||
File = sSoundFile,
|
||||
Filter = mPropFilter
|
||||
}
|
||||
|
||||
-- If iTeamID is nil, both teams will receive the taunt.
|
||||
if iTeamID == nil then
|
||||
GAMEMODE.Taunts.Seeker[sTauntName] = Taunt
|
||||
GAMEMODE.Taunts.Hider[sTauntName] = Taunt
|
||||
else
|
||||
-- Make sure that the team is valid.
|
||||
if ! team.Valid(iTeamID) then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: Team "..iTeamID.."' does not exist.") end
|
||||
return false
|
||||
end
|
||||
|
||||
if (iTeamID == TEAM_SEEKERS) then
|
||||
GAMEMODE.Taunts.Seeker[sTauntName] = Taunt
|
||||
elseif (iTeamID == TEAM_HIDERS) then
|
||||
GAMEMODE.Taunts.Hider[sTauntName] = Taunt
|
||||
else
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: Team "..iTeamID.."' can't have taunts.") end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Add: Complete.") end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Taunts.Remove(sTauntName, iTeamID)
|
||||
--@desc: Removes a registered taunt with the given name and team.
|
||||
--@param:
|
||||
-- sTauntName - The unique name of the taunt.
|
||||
-- iTeamID - The team that the taunt should be removed from or nil for all teams.
|
||||
--@return: true or false depending on success.
|
||||
GM.Config.Taunts.Remove = function(sTauntName, iTeamID)
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Remove: Removing taunt '"..sTauntName.."'...") end
|
||||
|
||||
-- Safeguard against idiots.
|
||||
if type(sTauntName) != "string" then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Remove: <sTauntName> is not a string.") end
|
||||
return false
|
||||
end
|
||||
if (type(iTeamID) != "number" && iTeamID != nil) then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Remove: <iTeamID> is not a number or nil.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- if iTeamID is nil, both teams will have the taunt removed.
|
||||
if (iTeamID == nil) then
|
||||
GAMEMODE.Taunts.Seeker[sTauntName] = nil
|
||||
GAMEMODE.Taunts.Hider[sTauntName] = nil
|
||||
else
|
||||
-- Make sure we have a valid Team.
|
||||
if ! team.Valid(iTeamID) then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Remove: Team "..iTeamID.."' does not exist.") end
|
||||
return false
|
||||
end
|
||||
|
||||
if iTeamID == TEAM_SEEKERS then
|
||||
GAMEMODE.Taunts.Seeker[sTauntName] = nil
|
||||
elseif iTeamID == TEAM_HIDERS then
|
||||
GAMEMODE.Taunts.Hider[sTauntName] = nil
|
||||
else
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Remove: Team "..iTeamID.."' can't have taunts.") end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Taunts.Remove: Complete.") end
|
||||
return true
|
||||
end
|
||||
|
||||
-- ToDo: Taunts.Get(iTeamID, sPropName)
|
||||
|
||||
--! Announcers (Round Start, Unblind, Win, Loss)
|
||||
GM.Config.Announcers = {
|
||||
Start = { },
|
||||
Unblind = { },
|
||||
Win = { },
|
||||
Loss = { }
|
||||
}
|
||||
|
||||
-- Announcers.Clear()
|
||||
--@desc: Clears the current announcer list.
|
||||
GM.Config.Announcers.Clear = function()
|
||||
Announcers.Start = { }
|
||||
Announcers.Unblind = { }
|
||||
Announcers.Win = { }
|
||||
Announcers.Loss = { }
|
||||
end
|
||||
|
||||
-- Announcers.Load(sAnnouncerListFile)
|
||||
--@desc: Tries to load the given announcer list.
|
||||
--@param:
|
||||
-- sAnnouncerListFile - A string containing the path to the announcer list to load.
|
||||
--@return: true or false depending on success.
|
||||
GM.Config.Announcers.Load = function(sAnnouncerListFile)
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: Loading announcer list from file '"..sAnnouncerListFile.."'...") end
|
||||
|
||||
-- Safeguard against idiots.
|
||||
if type(sAnnouncerListFile) != "string" then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: <sAnnouncerListFile> is not a string.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Given file must exist for us to continue.
|
||||
if ! file.Exists(sAnnouncerListFile, "GAME") then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: File not found.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Read the file and check if it's empty.
|
||||
sAnnouncerListData = file.Read(sAnnouncerListFile, "GAME")
|
||||
if sAnnouncerListData == "" then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: File is empty.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Convert JSON to a table for us to use.
|
||||
sAnnouncerList = util.JSONToTable(sAnnouncerListData)
|
||||
|
||||
-- Is it nil? Then it's not valid JSON
|
||||
if sAnnouncerList == nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: File contains invalid JSON.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Finally, insert the announcer lists.
|
||||
if sAnnouncerList.Start != nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: Adding Start announcers...") end
|
||||
for k,v in pairs(sAnnouncerList.Start) do
|
||||
GAMEMODE.Announcers.Start[k] = v
|
||||
end
|
||||
end
|
||||
if sAnnouncerList.Unblind != nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: Adding Unblind announcers...") end
|
||||
for k,v in pairs(sAnnouncerList.Unblind) do
|
||||
GAMEMODE.Announcers.Unblind[k] = v
|
||||
end
|
||||
end
|
||||
if sAnnouncerList.Win != nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: Adding Win announcers...") end
|
||||
for k,v in pairs(sAnnouncerList.Win) do
|
||||
GAMEMODE.Announcers.Win[k] = v
|
||||
end
|
||||
end
|
||||
if sAnnouncerList.Loss != nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: Adding Loss announcers...") end
|
||||
for k,v in pairs(sAnnouncerList.Loss) do
|
||||
GAMEMODE.Announcers.Loss[k] = v
|
||||
end
|
||||
end
|
||||
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Load: Complete.") end
|
||||
return true
|
||||
end
|
||||
|
||||
-- Announcers.Save(sAnnouncerListFile)
|
||||
--@desc: Saves the current taunt list to disk.
|
||||
--@param:
|
||||
-- sAnnouncerListFile - A string containing the path to the file to save to.
|
||||
--@return: true or false depending on success.
|
||||
GM.Config.Announcers.Save = function(sAnnouncerListFile)
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Save: Saving announcer list to file '"..sAnnouncerListFile.."'...") end
|
||||
|
||||
-- Safeguard against idiots.
|
||||
if type(sAnnouncerListFile) != "string" then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Save: <sAnnouncerListFile> is not a string.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- File must not be nil, otherwise we can't write to it.
|
||||
if sAnnouncerListFile == nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Save: No file given.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Convert our taunt table to JSON.
|
||||
sAnnouncerListData = util.TableToJSON(GAMEMODE.Announcers);
|
||||
if sAnnouncerListData == nil then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Save: Corrupted GAMEMODE table.") end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Write out JSON out to file
|
||||
if ! file.Write(sAnnouncerListFile, sAnnouncerListData) then
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Save: Failed to write to file.") end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
if GAMEMODE.Debug then print("Prop Hunt.Announcers.Save: Complete.") end
|
||||
return true
|
||||
end
|
||||
|
||||
-- ToDo: Announcers.Add
|
||||
-- ToDo: Announcers.Remove
|
||||
-- ToDo: Announcers.Get(iType)
|
||||
|
||||
--! Whitelists and Blacklists
|
||||
-- Hiders: Entity Whitelist (exact match)
|
||||
GM.Config.EntityWhitelist = {
|
||||
"prop_physics",
|
||||
"prop_physics_multiplayer"
|
||||
}
|
||||
|
||||
-- Hiders: Prop Blacklist (exact match)
|
||||
GM.Config.PropBlacklist = {}
|
||||
|
||||
-- Both: Entity Use-abuse Blacklist (exact match)
|
||||
GM.Config.EntityAbuseBlacklist = {
|
||||
"func_door",
|
||||
"func_door_rotating",
|
||||
"prop_door_rotating"
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Project Kube
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
CreateConVar("ph_tauntwaittime", GM.Config.TauntWaitTime)
|
||||
CreateConVar("ph_sprinting", GM.Config.Sprinting)
|
||||
CreateConVar("ph_rounds", GM.Config.Rounds.Amount)
|
||||
CreateConVar("ph_rounds_time", GM.Config.Rounds.Time)
|
||||
CreateConVar("ph_rounds_blindtime", GM.Config.Rounds.BlindTime)
|
||||
|
||||
CreateConVar("ph_modes_swap", GM.Config.Modes.SwapTeams)
|
||||
CreateConVar("ph_modes_randomize", GM.Config.Modes.RandomizeTeams)
|
||||
CreateConVar("ph_modes_thedeadhunt", GM.Config.Modes.TheDeadHunt)
|
||||
|
||||
CreateConVar("ph_seeker_health", GM.Config.Seeker.HealthStart)
|
||||
CreateConVar("ph_seeker_health_max", GM.Config.Seeker.HealthMax)
|
||||
CreateConVar("ph_seeker_health_killbonus", GM.Config.Seeker.HealthBonus)
|
||||
CreateConVar("ph_seeker_health_penalty", GM.Config.Seeker.HealthPenalty)
|
||||
CreateConVar("ph_seeker_weapons", GM.Config.Seeker.Weapons)
|
||||
CreateConVar("ph_seeker_ammo", GM.Config.Seeker.Ammo)
|
||||
|
||||
CreateConVar("ph_hider_health", GM.Config.Hider.HealthStart)
|
||||
CreateConVar("ph_hider_health_max", GM.Config.Hider.HealthMax)
|
||||
CreateConVar("ph_hider_health_scale", GM.Config.Hider.HealthScaling)
|
||||
CreateConVar("ph_hider_health_scaled_max", GM.Config.Hider.HealthScalingMax)
|
||||
@@ -1,93 +0,0 @@
|
||||
-- Gamemode Information
|
||||
GM.Name = "Prop Hunt"
|
||||
GM.Author = "Michael 'Xaymar' Dirks (Based on Kow@lskis Version, Original by AMT)"
|
||||
GM.Email = "michael.fabian.dirks@gmail.com"
|
||||
GM.Website = "http://xaymar.com/"
|
||||
GM.Debug = (cvars.Number("developer") != 0)
|
||||
|
||||
-- ToDo: Remove fretta as a base gamemode (it's outdated and doesn't help us much).
|
||||
DeriveGamemode("fretta13")
|
||||
|
||||
-- Shared Lua Files
|
||||
if SERVER then
|
||||
AddCSLuaFile("sh_config.lua")
|
||||
AddCSLuaFile("sh_player.lua")
|
||||
end
|
||||
|
||||
-- Player Classes
|
||||
if SERVER then
|
||||
AddCSLuaFile("player_class/class_seeker.lua")
|
||||
AddCSLuaFile("player_class/class_hider.lua")
|
||||
end
|
||||
include "player_class/class_seeker.lua"
|
||||
include "player_class/class_hider.lua"
|
||||
|
||||
-- Set up Teams
|
||||
TEAM_SPECTATOR = 0
|
||||
TEAM_SEEKERS = 1
|
||||
TEAM_HIDERS = 2
|
||||
TEAM_HUNTERS = TEAM_SEEKERS -- Deprecated
|
||||
TEAM_PROPS = TEAM_HIDERS -- Deprecated
|
||||
|
||||
function GM:CreateTeams()
|
||||
-- Seekers: "Hunters"
|
||||
team.SetUp(TEAM_SEEKERS, "Seekers", Color(153, 204, 255, 255))
|
||||
team.SetSpawnPoint(TEAM_SEEKERS, {
|
||||
"info_player_deathmatch",
|
||||
"info_player_axis",
|
||||
"info_player_combine",
|
||||
"info_player_counterterrorist"
|
||||
})
|
||||
team.SetClass(TEAM_SEEKERS, { "Seeker" })
|
||||
|
||||
-- Hiders: "Props"
|
||||
team.SetUp(TEAM_HIDERS, "Hiders", Color(255, 204, 153, 255))
|
||||
team.SetSpawnPoint(TEAM_HIDERS, {
|
||||
"info_player_deathmatch",
|
||||
"info_player_allies",
|
||||
"info_player_terrorist"
|
||||
})
|
||||
team.SetClass(TEAM_HIDERS, { "Hider" })
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- Gamemode Player Code & Data
|
||||
include("sh_player.lua")
|
||||
|
||||
-- Gamemode Configuration Code & Data
|
||||
include("sh_config.lua")
|
||||
|
||||
-- Include the configuration for this map
|
||||
if file.Exists("maps/"..game.GetMap()..".lua", "LUA") || file.Exists("maps/"..game.GetMap()..".lua", "LUA") then
|
||||
include("maps/"..game.GetMap()..".lua")
|
||||
end
|
||||
|
||||
-- Help info
|
||||
GM.Help = [[Prop Hunt is a twist on the classic backyard game Hide and Seek.
|
||||
|
||||
As a Prop you have ]]..GetConVar("HUNTER_BLINDLOCK_TIME"):GetInt()..[[ seconds to replicate an existing prop on the map and then find a good hiding spot. Press [E] to replicate the prop you are looking at. Your health is scaled based on the size of the prop you replicate.
|
||||
|
||||
As a Hunter you will be blindfolded for the first ]]..GetConVar("HUNTER_BLINDLOCK_TIME"):GetInt()..[[ seconds of the round while the Props hide. When your blindfold is taken off, you will need to find props controlled by players and kill them. Damaging non-player props will lower your health significantly. However, killing a Prop will increase your health by ]]..GetConVar("HUNTER_KILL_BONUS"):GetInt()..[[ points.
|
||||
|
||||
Both teams can press [F3] to play a taunt sound. Props can press F4 to enable rotation.]]
|
||||
|
||||
|
||||
-- Fretta configuration
|
||||
GM.AddFragsToTeamScore = true
|
||||
GM.CanOnlySpectateOwnTeam = true
|
||||
GM.Data = {}
|
||||
GM.EnableFreezeCam = true
|
||||
GM.GameLength = GAME_TIME
|
||||
GM.NoAutomaticSpawning = true
|
||||
GM.NoNonPlayerPlayerDamage = true
|
||||
GM.NoPlayerPlayerDamage = true
|
||||
GM.RoundBased = true
|
||||
GM.RoundLimit = ROUNDS_PER_MAP
|
||||
GM.RoundLength = ROUND_TIME
|
||||
GM.RoundPreStartTime = 0
|
||||
GM.SelectModel = false
|
||||
GM.SuicideString = "couldn't take the pressure and committed suicide."
|
||||
GM.TeamBased = true
|
||||
@@ -1,50 +0,0 @@
|
||||
<NotepadPlus>
|
||||
<Project name="Prop Hunt">
|
||||
<Folder name="gamemode">
|
||||
<Folder name="compat">
|
||||
<File name="gamemode\compat\compat_tauntpackloader.lua" />
|
||||
</Folder>
|
||||
<Folder name="player_class">
|
||||
<File name="gamemode\player_class\class_seeker.lua" />
|
||||
<File name="gamemode\player_class\class_hider.lua" />
|
||||
</Folder>
|
||||
<Folder name="server">
|
||||
<Folder name="console">
|
||||
<File name="gamemode\server\console\variables.lua" />
|
||||
</Folder>
|
||||
<File name="gamemode\server\config.lua" />
|
||||
</Folder>
|
||||
<File name="gamemode\cl_init.lua" />
|
||||
<File name="gamemode\cl_worldtips.lua" />
|
||||
<File name="gamemode\init.lua" />
|
||||
<File name="gamemode\sh_config.lua" />
|
||||
<File name="gamemode\sh_init.lua" />
|
||||
<File name="gamemode\sh_player.lua" />
|
||||
</Folder>
|
||||
<Folder name="data">
|
||||
<Folder name="prop_hunt">
|
||||
<File name="data\prop_hunt\banned_props.txt" />
|
||||
<File name="data\prop_hunt\config.txt" />
|
||||
<File name="data\prop_hunt\sounds_loss.txt" />
|
||||
<File name="data\prop_hunt\sounds_taunt_hunter.txt" />
|
||||
<File name="data\prop_hunt\sounds_taunt_prop.txt" />
|
||||
<File name="data\prop_hunt\sounds_victory.txt" />
|
||||
</Folder>
|
||||
</Folder>
|
||||
<Folder name="entities">
|
||||
<Folder name="entities">
|
||||
<Folder name="ph_prop">
|
||||
<File name="entities\entities\ph_prop\cl_init.lua" />
|
||||
<File name="entities\entities\ph_prop\init.lua" />
|
||||
<File name="entities\entities\ph_prop\shared.lua" />
|
||||
</Folder>
|
||||
</Folder>
|
||||
<Folder name="weapons">
|
||||
<File name="entities\weapons\weapon_ph_smg.lua" />
|
||||
</Folder>
|
||||
</Folder>
|
||||
<File name="icon24.png" />
|
||||
<File name="logo.png" />
|
||||
<File name="xaymars_prop_hunt.txt" />
|
||||
</Project>
|
||||
</NotepadPlus>
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"title" : "Xaymar's Custom Prop Hunt ",
|
||||
"title" : "Prop Hunt Extended",
|
||||
"type" : "gamemode",
|
||||
"tags" : [ "fun" ],
|
||||
"ignore" : [
|
||||
@@ -0,0 +1,8 @@
|
||||
--Thanks to Blasteh for gmod update the fix and nifnat for spectate fix!
|
||||
|
||||
-- Send required files to client
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
-- Include needed files
|
||||
include("shared.lua")
|
||||
@@ -0,0 +1,24 @@
|
||||
-- Entity information
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_anim"
|
||||
|
||||
-- Initialize
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/Kleiner.mdl")
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PLAYER)
|
||||
self:SetSolid(SOLID_OBB)
|
||||
self:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self:SetColor(Color(255,255,255,255))
|
||||
end
|
||||
|
||||
-- Update position
|
||||
function ENT:Think()
|
||||
local hullOBBMin = self:OBBMins()
|
||||
local hullOBBMax = self:OBBMaxs()
|
||||
local hullOBB = hullOBBMax - hullOBBMin
|
||||
local pos = -Vector(0, 0, hullOBBMin.z)
|
||||
|
||||
self:SetPos(self.Owner:GetPos() + pos)
|
||||
self:SetVelocity(self:GetOwner():GetVelocity())
|
||||
end
|
||||
--]]
|
||||
+9
-1
@@ -193,7 +193,15 @@ end
|
||||
|
||||
-- Reload: Combination of reloading and switching fire type.
|
||||
function SWEP:Reload()
|
||||
if self:DefaultReload(ACT_VM_RELOAD) then self:EmitSound(self.Sound.Reload) end
|
||||
if self:DefaultReload(ACT_VM_RELOAD) then
|
||||
self:EmitSound(self.Sound.Reload)
|
||||
else
|
||||
if (self.LastReload) && ((CurTime() - self.LastReload) > 1) then
|
||||
self:GetOwner():ChatPrint("BurstToggle")
|
||||
self.BurstFire = !self.BurstFire
|
||||
end
|
||||
end
|
||||
self.LastReload = CurTime()
|
||||
return
|
||||
end
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Includes
|
||||
-- ------------------------------------------------------------------------- --
|
||||
include("sh_init.lua")
|
||||
|
||||
include("client/cl_ui_teamselection.lua")
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Code
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function GM:Initialize()
|
||||
print("-------------------------------------------------------------------------")
|
||||
print("Prop Hunt CL: Initializing...")
|
||||
|
||||
print("Prop Hunt CL: Initializing Gamemode Data...")
|
||||
self.Data = {}
|
||||
|
||||
print("Prop Hunt CL: Creating Huge Ass Font...")
|
||||
surface.CreateFont("PHHugeAssFont", {font="Roboto Bold Condensed", extended=true, size=160, weight=800, antialias=true})
|
||||
|
||||
print("Prop Hunt CL: Complete.")
|
||||
print("-------------------------------------------------------------------------")
|
||||
|
||||
end
|
||||
|
||||
function GM:Think() end
|
||||
|
||||
function GM:InitialPlayerSpawn()
|
||||
print("Prop Hunt CL: InitialPlayerSpawn")
|
||||
|
||||
-- Delay execution until LocalPlayer() is valid.
|
||||
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
|
||||
timer.Simple(.1, function() GAMEMODE:InitialPlayerSpawn() end)
|
||||
return
|
||||
end
|
||||
|
||||
print("Prop Hunt CL: InitialPlayerSpawn Valid")
|
||||
|
||||
player_manager.RunClass(LocalPlayer(), "InitialClientSpawn")
|
||||
end
|
||||
|
||||
function GM:PlayerSpawn()
|
||||
print("Prop Hunt CL: PlayerSpawn")
|
||||
|
||||
-- Delay execution until LocalPlayer() is valid.
|
||||
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
|
||||
timer.Simple(.1, function() GAMEMODE:PlayerSpawn() end)
|
||||
return
|
||||
end
|
||||
|
||||
print("Prop Hunt CL: PlayerSpawn Valid")
|
||||
|
||||
if !(LocalPlayer().Data) then
|
||||
LocalPlayer().Data = {}
|
||||
LocalPlayer().Data.ThirdPerson = true
|
||||
end
|
||||
|
||||
player_manager.RunClass(LocalPlayer(), "ClientSpawn")
|
||||
end
|
||||
|
||||
function GM:HUDPaint()
|
||||
local State = GetGlobalInt("RoundState", GAMEMODE.States.PreMatch)
|
||||
|
||||
-- Show Status at the top center
|
||||
local statusX, statusY, statusW, statusH
|
||||
statusW = 192
|
||||
statusH = 64
|
||||
statusX = ScrW() / 2 - statusW / 2
|
||||
statusY = 16
|
||||
|
||||
--! States
|
||||
-- Pre Match
|
||||
if (State == GAMEMODE.States.PreMatch) then
|
||||
-- Show Status at the top center
|
||||
draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204))
|
||||
surface.SetFont( "Trebuchet24" )
|
||||
surface.SetTextColor( 255, 255, 255, 255 )
|
||||
local w,h = surface.GetTextSize("Waiting...")
|
||||
surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/2 - h / 2)
|
||||
surface.DrawText( "Waiting..." )
|
||||
|
||||
-- Pre Round
|
||||
elseif (State == GAMEMODE.States.PreRound) then
|
||||
-- Show Status at the top center
|
||||
draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204))
|
||||
surface.SetFont( "Trebuchet24" )
|
||||
surface.SetTextColor( 255, 255, 255, 255 )
|
||||
local w,h = surface.GetTextSize("Preparing...")
|
||||
surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/2 - h / 2)
|
||||
surface.DrawText( "Preparing..." )
|
||||
|
||||
-- Hide!
|
||||
elseif (State == GAMEMODE.States.Hide) then
|
||||
local strTime = tostring(math.ceil(GetGlobalInt("RoundTime")))
|
||||
|
||||
-- Show Status at the top center
|
||||
draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204))
|
||||
surface.SetTextColor(255,255,255,255)
|
||||
surface.SetFont("Trebuchet18")
|
||||
local w,h = surface.GetTextSize("Seekers unblinded in:")
|
||||
surface.SetTextPos(statusX + statusW/2 - w / 2, statusY + statusH/4 - h / 2)
|
||||
surface.DrawText("Seekers unblinded in:")
|
||||
|
||||
surface.SetFont( "Trebuchet24" )
|
||||
local w,h = surface.GetTextSize(strTime.." Seconds!")
|
||||
surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/1.5 - h / 2)
|
||||
surface.DrawText(strTime.." Seconds!")
|
||||
elseif (State == GAMEMODE.States.Seek) then
|
||||
local intTime = math.ceil(GetGlobalInt("RoundTime"))
|
||||
local strTime = string.format("%d:%02d", math.floor(intTime / 60), math.ceil(intTime % 60))
|
||||
|
||||
-- Show Status at the top center
|
||||
draw.RoundedBox(16, statusX, statusY, statusW, statusH, Color(0, 0, 0, 204))
|
||||
surface.SetTextColor(255,255,255,255)
|
||||
surface.SetFont("Trebuchet18")
|
||||
local w,h = surface.GetTextSize("Hunting Time!")
|
||||
surface.SetTextPos(statusX + statusW/2 - w / 2, statusY + statusH/4 - h / 2)
|
||||
surface.DrawText("Hunting Time!")
|
||||
|
||||
surface.SetFont( "Trebuchet24" )
|
||||
local w,h = surface.GetTextSize(strTime)
|
||||
surface.SetTextPos( statusX + statusW/2 - w / 2, statusY + statusH/1.5 - h / 2)
|
||||
surface.DrawText(strTime)
|
||||
|
||||
elseif (State == GAMEMODE.States.PostRound) then
|
||||
|
||||
elseif (State == GAMEMODE.States.PostMatch) then
|
||||
|
||||
end
|
||||
|
||||
player_manager.RunClass(LocalPlayer(), "HUDPaint")
|
||||
end
|
||||
|
||||
function GM:ShowTeamSelection()
|
||||
TeamSelectionUI:Show()
|
||||
end
|
||||
concommand.Add("ph_select_team", function() GAMEMODE:ShowTeamSelection() end)
|
||||
|
||||
function GM:GetHandsModel()
|
||||
return player_manager.RunClass(LocalPlayer(), "GetHandsModel")
|
||||
end
|
||||
|
||||
function GM:PostDrawViewModel( vm, ply, weapon )
|
||||
if ( weapon.UseHands || !weapon:IsScripted() ) then
|
||||
local hands = LocalPlayer():GetHands()
|
||||
if ( IsValid( hands ) ) then hands:DrawModel() end
|
||||
end
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Player Manager Binding
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function GM:CalcView(ply, pos, ang, fov, nearZ, farZ)
|
||||
return player_manager.RunClass(LocalPlayer(), "CalcView", {origin = pos, angles = ang, fov = fov, znear = nearZ, zfar = farZ})
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Gamemode Functionality
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function GM:PlayerSetViewOffset(vo, voduck)
|
||||
-- Delay execution until LocalPlayer() is valid.
|
||||
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
|
||||
if !(GAMEMODE.TempData) then GAMEMODE.TempData = {} end
|
||||
GAMEMODE.TempData.ViewOffset = vo
|
||||
GAMEMODE.TempData.ViewOffsetDuck = voduck
|
||||
|
||||
timer.Simple(.1, function() GAMEMODE:PlayerSetViewOffset(GAMEMODE.TempData.ViewOffset, GAMEMODE.TempData.ViewOffsetDuck) end)
|
||||
return
|
||||
end
|
||||
|
||||
LocalPlayer():SetViewOffset(vo)
|
||||
LocalPlayer():SetViewOffsetDucked(voduck)
|
||||
if LocalPlayer():Crouching() then
|
||||
LocalPlayer():SetCurrentViewOffset(voduck)
|
||||
else
|
||||
LocalPlayer():SetCurrentViewOffset(vo)
|
||||
end
|
||||
end
|
||||
|
||||
function GM:PlayerSetHull(hullMin, hullMax)
|
||||
-- Delay execution until LocalPlayer() is valid.
|
||||
if (!LocalPlayer()) || (!IsValid(LocalPlayer())) then
|
||||
if !(GAMEMODE.TempData) then GAMEMODE.TempData = {} end
|
||||
GAMEMODE.TempData.HullMin = hullMin
|
||||
GAMEMODE.TempData.HullMax = hullMax
|
||||
|
||||
timer.Simple(.1, function() GAMEMODE:PlayerSetHull(GAMEMODE.TempData.HullMin, GAMEMODE.TempData.HullMax) end)
|
||||
return
|
||||
end
|
||||
|
||||
if (hullMin == hullMax) && (hullMin == nil) then
|
||||
LocalPlayer():ResetHull()
|
||||
else
|
||||
LocalPlayer():SetHull(hullMin, hullMax)
|
||||
LocalPlayer():SetHullDuck(hullMin, hullMax)
|
||||
end
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Commands
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function GM:OnContextMenuOpen()
|
||||
end
|
||||
|
||||
function GM:OnContextMenuClose()
|
||||
print("Prop Hunt CL: Toggled View Mode")
|
||||
LocalPlayer().Data.ThirdPerson = !LocalPlayer().Data.ThirdPerson
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Network Messages
|
||||
-- ------------------------------------------------------------------------- --
|
||||
net.Receive("PlayerManagerInitialClientSpawn", function(len, pl) GAMEMODE:InitialPlayerSpawn() end)
|
||||
net.Receive("PlayerManagerClientSpawn", function(len, pl) GAMEMODE:PlayerSpawn() end)
|
||||
net.Receive( "PlayerSetHull", function(len, pl)
|
||||
local hullMin, hullMax = net.ReadVector(), net.ReadVector();
|
||||
GAMEMODE:PlayerSetHull(hullMin, hullMax)
|
||||
end)
|
||||
net.Receive( "PlayerResetHull", function(len, pl) GAMEMODE:PlayerSetHull(nil, nil) end)
|
||||
net.Receive( "PlayerViewOffset", function(len, pl)
|
||||
local vo, voduck = net.ReadVector(), net.ReadVector()
|
||||
GAMEMODE:PlayerSetViewOffset(vo, voduck)
|
||||
end)
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Old Code
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--[[
|
||||
-- Render halos and player names.
|
||||
function DrawPlayerNames(bDrawingDepth, bDrawingSkybox)
|
||||
for i,v in ipairs(player.GetAll()) do
|
||||
if v:Alive() && v != LocalPlayer() then
|
||||
local pos = v:GetPos() + v:GetViewOffset() + Vector(0, 0, 5)
|
||||
local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x)
|
||||
local healthPrc = v:Health() / v:GetMaxHealth()
|
||||
local healthCol = HSVToColor(120 * healthPrc, 1.0, 1.0)
|
||||
|
||||
if v:Team() == TEAM_HUNTERS || LocalPlayer():Team() == TEAM_PROPS then
|
||||
cam.Start3D2D(pos, ang, 0.15)
|
||||
draw.DrawText(v:GetName(), "Trebuchet24", 0, -draw.GetFontHeight("Trebuchet24"), healthCol, TEXT_ALIGN_CENTER)
|
||||
cam.End3D2D()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
hook.Add("PostDrawTranslucentRenderables", "PH_DrawPlayerNames", DrawPlayerNames)
|
||||
|
||||
function DrawPlayerHalos(bDrawingDepth, bDrawingSkybox)
|
||||
for i,v in ipairs(player.GetAll()) do
|
||||
if v:Alive() then
|
||||
local pos = v:GetPos() + Vector(0, 0, 1) * (v:OBBMaxs().z - v:OBBMins().z + 5)
|
||||
local ang = Angle(0, LocalPlayer():EyeAngles().y - 90, 90 - LocalPlayer():EyeAngles().x)
|
||||
local healthPrc = v:Health() / v:GetMaxHealth()
|
||||
local healthCol = HSVToColor(120 * healthPrc, 1.0, 1.0)
|
||||
|
||||
if v:Team() == TEAM_HUNTERS || LocalPlayer():Team() == TEAM_PROPS then
|
||||
local ent = v
|
||||
if v.ph_prop && v.ph_prop:IsValid() then ent = v.ph_prop end
|
||||
|
||||
halo.Add({ent}, healthCol, 2, 2, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
--hook.Add("PostDrawEffects", "PH_DrawPlayerHalos", DrawPlayerHalos)
|
||||
]]
|
||||
@@ -0,0 +1,75 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
TeamSelectionUI = {}
|
||||
TeamSelectionUI.Frame = vgui.Create("DFrame")
|
||||
TeamSelectionUI.Frame:SetPos(0, 0)
|
||||
TeamSelectionUI.Frame:SetSize(400, 320)
|
||||
TeamSelectionUI.Frame:Center()
|
||||
TeamSelectionUI.Frame:SetTitle("Select a Team")
|
||||
TeamSelectionUI.Frame:SetVisible(false)
|
||||
TeamSelectionUI.Frame:SetDraggable(true)
|
||||
TeamSelectionUI.Frame:SetSizable(false)
|
||||
TeamSelectionUI.Frame:ShowCloseButton(true)
|
||||
TeamSelectionUI.Frame:SetDeleteOnClose(false)
|
||||
function TeamSelectionUI.Frame:Paint(w, h)
|
||||
draw.RoundedBox(0, 0, 0, w, h, Color(0, 0, 0, 225))
|
||||
end
|
||||
|
||||
function TeamSelectionUI:Show()
|
||||
self.Frame:MakePopup()
|
||||
TeamSelectionUI.Frame:SetVisible(true)
|
||||
end
|
||||
|
||||
function TeamSelectionUI:Hide()
|
||||
TeamSelectionUI.Frame:Close()
|
||||
TeamSelectionUI.Frame:SetVisible(false)
|
||||
end
|
||||
|
||||
TeamSelectionUI.SelectSeeker = vgui.Create("DButton", TeamSelectionUI.Frame)
|
||||
TeamSelectionUI.SelectSeeker:SetPos(0, 20)
|
||||
TeamSelectionUI.SelectSeeker:SetSize(200, 200)
|
||||
TeamSelectionUI.SelectSeeker:SetText("Seeker")
|
||||
TeamSelectionUI.SelectSeeker.DoClick = function()
|
||||
TeamSelectionUI:Hide()
|
||||
LocalPlayer():ConCommand("changeteam " .. tostring(GAMEMODE.Teams.Seekers))
|
||||
end
|
||||
|
||||
TeamSelectionUI.SelectHider = vgui.Create("DButton", TeamSelectionUI.Frame)
|
||||
TeamSelectionUI.SelectHider:SetPos(200, 20)
|
||||
TeamSelectionUI.SelectHider:SetSize(200, 200)
|
||||
TeamSelectionUI.SelectHider:SetText("Hiders")
|
||||
TeamSelectionUI.SelectHider.DoClick = function()
|
||||
TeamSelectionUI:Hide()
|
||||
LocalPlayer():ConCommand("changeteam " .. tostring(GAMEMODE.Teams.Hiders))
|
||||
end
|
||||
|
||||
TeamSelectionUI.Spectate = vgui.Create("DButton", TeamSelectionUI.Frame)
|
||||
TeamSelectionUI.Spectate:SetPos(0, 220)
|
||||
TeamSelectionUI.Spectate:SetSize(400, 100)
|
||||
TeamSelectionUI.Spectate:SetText("Spectate")
|
||||
TeamSelectionUI.Spectate.DoClick = function()
|
||||
TeamSelectionUI:Hide()
|
||||
LocalPlayer():ConCommand("changeteam " .. tostring(GAMEMODE.Teams.Spectators))
|
||||
end
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Project Kube
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -0,0 +1,414 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Downloadable Lua
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Shared
|
||||
AddCSLuaFile("sh_init.lua")
|
||||
AddCSLuaFile("sh_config.lua")
|
||||
AddCSLuaFile("sh_player.lua")
|
||||
AddCSLuaFile("player_class/class_default.lua")
|
||||
AddCSLuaFile("player_class/class_spectator.lua")
|
||||
AddCSLuaFile("player_class/class_seeker.lua")
|
||||
AddCSLuaFile("player_class/class_hider.lua")
|
||||
|
||||
-- Client-Only
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("client/cl_ui_teamselection.lua")
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Code
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Shared
|
||||
include "sh_init.lua"
|
||||
|
||||
-- Server Only
|
||||
include "server/config.lua"
|
||||
include "compat/compat_tauntpackloader.lua"
|
||||
include "server/roundmanager.lua"
|
||||
include "server/states/state_prematch.lua"
|
||||
include "server/states/state_preround.lua"
|
||||
include "server/states/state_hide.lua"
|
||||
include "server/states/state_seek.lua"
|
||||
include "server/states/state_postround.lua"
|
||||
|
||||
function GM:Initialize()
|
||||
print("-------------------------------------------------------------------------")
|
||||
print("Prop Hunt: Initializing...")
|
||||
|
||||
print("Prop Hunt: Registering Networked Messages...")
|
||||
util.AddNetworkString("PlayerManagerInitialClientSpawn")
|
||||
util.AddNetworkString("PlayerManagerClientSpawn")
|
||||
|
||||
util.AddNetworkString("PlayerSetHull")
|
||||
util.AddNetworkString("PlayerResetHull")
|
||||
util.AddNetworkString("PlayerViewOffset")
|
||||
util.AddNetworkString("PlayerRegisterPropEntity")
|
||||
|
||||
print("Prop Hunt: Initializing Gamemode Data...")
|
||||
self.Data = {}
|
||||
|
||||
print("Prop Hunt: Setting initial RoundManager State...")
|
||||
self.RoundManager:SetState(StatePreMatch)
|
||||
|
||||
print("Prop Hunt: Complete.")
|
||||
print("-------------------------------------------------------------------------")
|
||||
end
|
||||
|
||||
function GM:Think()
|
||||
self.RoundManager:Tick()
|
||||
end
|
||||
|
||||
-- Player Connected
|
||||
function GM:PlayerConnect(name, ip)
|
||||
print("Prop Hunt: Player '"..name.."' connecting from IP '"..ip.."'.")
|
||||
end
|
||||
|
||||
-- Player Authenticated
|
||||
function GM:PlayerAuthed(ply, steamid, uniqueid)
|
||||
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") authenticated.")
|
||||
end
|
||||
|
||||
-- Player Disconnected
|
||||
function GM:PlayerDisconnected(ply)
|
||||
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") disconnected.")
|
||||
end
|
||||
|
||||
-- Player Spawn (Initial)
|
||||
function GM:PlayerInitialSpawn(ply)
|
||||
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned for the first time, applying defaults...")
|
||||
|
||||
if (!ply.Data) then
|
||||
-- Initialize Data Structure
|
||||
ply.Data = {}
|
||||
ply.Data.Alive = false
|
||||
ply.Data.AliveTime = 0
|
||||
end
|
||||
|
||||
-- Kill Silently
|
||||
ply:KillSilent()
|
||||
|
||||
-- Show Team Selection Menu
|
||||
ply:SetTeam(GAMEMODE.Teams.Spectators)
|
||||
self:ShowTeam(ply)
|
||||
|
||||
-- Bot: Auto Assign to Team
|
||||
if (ply:IsBot()) then
|
||||
if team.NumPlayers(self.Teams.Hiders) > team.NumPlayers(self.Teams.Seekers) then
|
||||
print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Seekers.")
|
||||
ply:SetTeam(self.Teams.Seekers)
|
||||
else
|
||||
print("Prop Hunt: Bot '"..ply:GetName().."' assigned to Hiders.")
|
||||
ply:SetTeam(self.Teams.Hiders)
|
||||
end
|
||||
end
|
||||
|
||||
-- Notify Player Manager
|
||||
player_manager.RunClass(ply, "InitialSpawn")
|
||||
|
||||
-- Signal Client
|
||||
net.Start("PlayerManagerInitialClientSpawn");net.Send(ply)
|
||||
end
|
||||
|
||||
-- Player Spawn
|
||||
function GM:PlayerSpawn(ply)
|
||||
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") spawned in.")
|
||||
|
||||
-- Player Manager: Assign Player Class
|
||||
local class = team.GetClass(ply:Team())
|
||||
if (class) then
|
||||
if (ply.Data.Alive) then -- Alive Class
|
||||
player_manager.SetPlayerClass(ply, class[1])
|
||||
else -- Dead Class (Spectator)
|
||||
player_manager.SetPlayerClass(ply, class[2])
|
||||
end
|
||||
else
|
||||
player_manager.SetPlayerClass(ply, "Spectator")
|
||||
end
|
||||
|
||||
-- Notify Player Manager
|
||||
player_manager.OnPlayerSpawn(ply)
|
||||
player_manager.RunClass(ply, "Spawn")
|
||||
|
||||
-- Some hooks are not called
|
||||
hook.Call("PlayerSetModel", self, ply)
|
||||
hook.Call("PlayerLoadout", self, ply)
|
||||
|
||||
-- Signal Client
|
||||
net.Start("PlayerManagerClientSpawn");net.Send(ply)
|
||||
end
|
||||
|
||||
-- Player requests Team Change
|
||||
function GM:PlayerRequestTeam(ply, teamId)
|
||||
if self:PlayerCanJoinTeam(ply, teamId) then
|
||||
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") requested to join Team "..team.GetName(teamId)..".")
|
||||
|
||||
if (ply:Team() != teamId) then
|
||||
ply:KillSilent()
|
||||
ply:SetTeam(teamId)
|
||||
|
||||
if (GetGlobalInt("RoundState", GAMEMODE.States.PreMatch) <= GAMEMODE.States.PreRound) then
|
||||
ply.Alive = true
|
||||
ply.AliveTime = CurTime()
|
||||
end
|
||||
else
|
||||
print("Prop Hunt: Player '"..ply:GetName().."' (SteamID: "..ply:SteamID()..") attempted to rejoin the Team it is already in.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Player Manager Binding
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function GM:PlayerLoadout(ply) player_manager.RunClass(ply, "Loadout") end
|
||||
function GM:PlayerDeath(ply, inflictor, attacker) player_manager.RunClass(ply, "Death", inflictor, attacker) end
|
||||
function GM:PlayerSilentDeath(ply) player_manager.RunClass(ply, "SilentDeath") end
|
||||
function GM:PostPlayerDeath(ply)
|
||||
player_manager.RunClass(ply, "PostDeath")
|
||||
|
||||
-- Debug Mode: Respawn after Death
|
||||
if (GAMEMODE.Config:Debug()) then
|
||||
ply.Data.Alive = true
|
||||
print("Prop Hunt: Debug Mode active, Player "..ply:GetName().." was respawned.")
|
||||
end
|
||||
end
|
||||
--function GM:DoPlayerDeath(ply, attacker, dmg) player_manager.RunClass(ply, "DoDeath", attacker, dmg) end
|
||||
function GM:PlayerDeathThink(ply) return player_manager.RunClass(ply, "DeathThink") end
|
||||
function GM:CanPlayerSuicide(ply) return player_manager.RunClass(ply, "CanSuicide") end
|
||||
function GM:PlayerCanPickupWeapon(ply, weapon) return player_manager.RunClass(ply, "CanPickupWeapon", weapon) end
|
||||
function GM:PlayerCanPickupItem(ply, item) return player_manager.RunClass(ply, "CanPickupItem", item) end
|
||||
function GM:PlayerUse(ply, ent) return player_manager.RunClass(ply, "Use", ent) end
|
||||
function GM:AllowPlayerPickup(ply, ent) return player_manager.RunClass(ply, "AllowPickup", ent) end
|
||||
function GM:PlayerSetModel(ply) return player_manager.RunClass(ply, "SetModel") end
|
||||
|
||||
-- Called when an entity takes damage
|
||||
function GM:EntityTakeDamage(ent, dmg)
|
||||
local att = dmg:GetAttacker()
|
||||
|
||||
if (att) && (att:IsValid()) && (att:IsPlayer()) then
|
||||
player_manager.RunClass(att, "DamageEntity", ent, att, dmg)
|
||||
end
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Gamemode Functionality
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function GM:SetRoundState(State)
|
||||
SetGlobalInt("RoundState", State)
|
||||
end
|
||||
|
||||
function GM:PlayerHullFromEntity(ply, ent)
|
||||
if (ent) && (ent:IsValid()) then
|
||||
local hmin, hmax = ent:OBBMins(), ent:OBBMaxs()
|
||||
local hull = Vector(hmax.x - hmin.x, hmax.y - hmin.y, hmax.z - hmin.z)
|
||||
if hull.x <= hull.y then
|
||||
hull.y = hull.x
|
||||
else
|
||||
hull.x = hull.y
|
||||
end
|
||||
hull:Mul(0.5)
|
||||
|
||||
local hullmin = Vector(-hull.x, -hull.y, 0)
|
||||
local hullmax = Vector(hull.x, hull.y, hull.z * 2)
|
||||
|
||||
ply:SetHull(hullmin, hullmax)
|
||||
ply:SetHullDuck(hullmin, hullmax)
|
||||
net.Start("PlayerSetHull")
|
||||
net.WriteVector(hullmin)
|
||||
net.WriteVector(hullmax)
|
||||
net.Send(ply)
|
||||
return {hullmin, hullmax}
|
||||
else
|
||||
ply:ResetHull()
|
||||
net.Start("PlayerResetHull")
|
||||
net.Send(ply)
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function GM:PlayerSetViewOffset(ply, vo, voduck)
|
||||
ply:SetViewOffset(vo)
|
||||
ply:SetViewOffsetDucked(voduck)
|
||||
if ply:Crouching() then
|
||||
ply:SetCurrentViewOffset(voduck)
|
||||
else
|
||||
ply:SetCurrentViewOffset(vo)
|
||||
end
|
||||
|
||||
-- Signal Client
|
||||
net.Start("PlayerViewOffset")
|
||||
net.WriteVector(vo)
|
||||
net.WriteVector(voduck)
|
||||
net.Send(ply)
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Commands
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- F1/ShowHelp
|
||||
function GM:ShowHelp(ply) end
|
||||
|
||||
-- F2/ShowTeam - Select Team
|
||||
function GM:ShowTeam(ply)
|
||||
ply:ConCommand("ph_select_team")
|
||||
end
|
||||
|
||||
-- F3/ShowSpare1
|
||||
function GM:ShowSpare1(ply) end
|
||||
|
||||
-- F4/ShowSpare2
|
||||
function GM:ShowSpare2(ply) end
|
||||
|
||||
-- Debug Command: Print All Players
|
||||
concommand.Add("ph_debug_printplayers", function(ply, cmd, args, argStr)
|
||||
print ("All Players:")
|
||||
for i,ply in ipairs(player.GetAll()) do
|
||||
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..") - Team "..team.GetName(ply:Team()).. " - Alive "..tostring(ply.Data.Alive))
|
||||
end
|
||||
|
||||
print ("Spectators:")
|
||||
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Spectators)) do
|
||||
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
|
||||
end
|
||||
|
||||
print ("Seekers:")
|
||||
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do
|
||||
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
|
||||
end
|
||||
|
||||
print ("Hiders:")
|
||||
for i,ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Hiders)) do
|
||||
print(" "..ply:GetName().." (SteamID: "..ply:SteamID()..")")
|
||||
end
|
||||
|
||||
end, nil, nil, FCVAR_CLIENTCMD_CAN_EXECUTE + FCVAR_CHEAT)
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! LEGACY CODE - TO BE REPLACED SOON
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--[[
|
||||
function AnnounceVictory(players, force)
|
||||
for i,pl in ipairs(players) do
|
||||
if pl:Alive() || force || pl:Team() == TEAM_SPECTATOR then
|
||||
announcer = table.Random(VICTORY_SOUNDS);
|
||||
print("Prop Hunt: '"..pl:GetName().."' announcing victory with '"..announcer.."'.")
|
||||
pl:EmitSound(announcer, 200, 100, 0.5, CHAN_VOICE2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function AnnounceLoss(players, force)
|
||||
for i,pl in ipairs(players) do
|
||||
if pl:Alive() || force || pl:Team() == TEAM_SPECTATOR then
|
||||
announcer = table.Random(LOSS_SOUNDS);
|
||||
print("Prop Hunt: '"..pl:GetName().."' announcing loss with '"..announcer.."'.")
|
||||
pl:EmitSound(announcer, 100, 100, 0.5, CHAN_VOICE2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- If there is a mapfile send it to the client (sometimes servers want to change settings for certain maps)
|
||||
if file.Exists("maps/"..game.GetMap()..".lua", "LUA") then
|
||||
AddCSLuaFile("maps/"..game.GetMap()..".lua")
|
||||
end
|
||||
|
||||
-- Send the required resources to the client
|
||||
for _, announcer in pairs(LOSS_SOUNDS) do resource.AddFile("sound/"..announcer) end
|
||||
for _, announcer in pairs(VICTORY_SOUNDS) do resource.AddFile("source/"..announcer) end
|
||||
for _, taunt in pairs(HUNTER_TAUNTS) do resource.AddFile("sound/"..taunt) end
|
||||
for _, taunt in pairs(PROP_TAUNTS) do resource.AddFile("sound/"..taunt) end
|
||||
|
||||
-- Called alot
|
||||
function GM:CheckPlayerDeathRoundEnd()
|
||||
if !GAMEMODE.RoundBased || !GAMEMODE:InRound() then
|
||||
return
|
||||
end
|
||||
|
||||
local Teams = GAMEMODE:GetTeamAliveCounts()
|
||||
|
||||
if table.Count(Teams) == 0 then
|
||||
GAMEMODE:RoundEndWithResult(1001, "Draw, everyone loses!")
|
||||
AnnounceLoss(player.GetAll(), true)
|
||||
return
|
||||
end
|
||||
|
||||
if table.Count(Teams) == 1 then
|
||||
-- Play victory and loss sounds.
|
||||
if Teams[0] == TEAM_HUNTERS then
|
||||
AnnounceVictory(team.GetPlayers(TEAM_HUNTERS))
|
||||
AnnounceLoss(team.GetPlayers(TEAM_PROPS))
|
||||
elseif Teams[0] == TEAM_PROPS then
|
||||
AnnounceLoss(team.GetPlayers(TEAM_HUNTERS))
|
||||
AnnounceVictory(team.GetPlayers(TEAM_PROPS))
|
||||
end
|
||||
|
||||
local TeamID = table.GetFirstKey(Teams)
|
||||
GAMEMODE:RoundEndWithResult(TeamID, team.GetName(TeamID).." win!")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Called when player presses [F3]. Plays a taunt for their team
|
||||
function GM:ShowSpare1(pl)
|
||||
if GAMEMODE:InRound() && pl:Alive() && (pl:Team() == TEAM_HUNTERS || pl:Team() == TEAM_PROPS) && pl.last_taunt_time + TAUNT_DELAY <= CurTime() && #PROP_TAUNTS > 1 && #HUNTER_TAUNTS > 1 then
|
||||
-- repeat
|
||||
if pl:Team() == TEAM_HUNTERS then
|
||||
rand_taunt = table.Random(HUNTER_TAUNTS)
|
||||
else
|
||||
rand_taunt = table.Random(PROP_TAUNTS)
|
||||
end
|
||||
-- until rand_taunt != pl.last_taunt
|
||||
|
||||
pl.last_taunt_time = CurTime()
|
||||
pl.last_taunt = rand_taunt
|
||||
|
||||
print("Prop Hunt: '"..pl:GetName().."' taunting with '"..rand_taunt.."'.")
|
||||
local vol = 1.0
|
||||
if pl:Team() == TEAM_HUNTERS then vol = vol * 0.5 end
|
||||
pl:EmitSound(rand_taunt, 100, 100, vol, CHAN_VOICE2)
|
||||
end
|
||||
end
|
||||
|
||||
-- Allow player to rotate the prop. (Either F4 or ducking)
|
||||
function GM:ShowSpare2(pl)
|
||||
if pl:Alive() && (pl:Team() == TEAM_PROPS) then
|
||||
pl.ph_prop:SetApplyNewAngles(!pl.ph_prop:GetApplyNewAngles())
|
||||
-- pl.ph_prop:SetNewAngles(pl:GetAngles())
|
||||
end
|
||||
end
|
||||
|
||||
-- Removes all weapons on a map
|
||||
function RemoveWeaponsAndItems()
|
||||
for _, wep in pairs(ents.FindByClass("weapon_*")) do
|
||||
wep:Remove()
|
||||
end
|
||||
|
||||
for _, item in pairs(ents.FindByClass("item_*")) do
|
||||
item:Remove()
|
||||
end
|
||||
end
|
||||
hook.Add("InitPostEntity", "PH_RemoveWeaponsAndItems", RemoveWeaponsAndItems)
|
||||
|
||||
]]
|
||||
@@ -0,0 +1,137 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
DEFINE_BASECLASS("player_default")
|
||||
local CLASS = {}
|
||||
CLASS.DisplayName = "Default"
|
||||
CLASS.WalkSpeed = 250 -- How fast to move when not running
|
||||
CLASS.RunSpeed = 500 -- How fast to move when running
|
||||
CLASS.CrouchedWalkSpeed = 0.5 -- Multiply move speed by this when crouching
|
||||
CLASS.DuckSpeed = 0.2 -- How fast to go from not ducking, to ducking
|
||||
CLASS.UnDuckSpeed = 0.2 -- How fast to go from ducking, to not ducking
|
||||
CLASS.JumpPower = 200 -- How powerful our jump should be
|
||||
CLASS.CanUseFlashlight = false -- Can we use the flashlight
|
||||
CLASS.MaxHealth = 100 -- Max health we can have
|
||||
CLASS.StartHealth = 100 -- How much health we start with
|
||||
CLASS.StartArmor = 0 -- How much armour we start with
|
||||
CLASS.DropWeaponOnDie = false -- Do we drop our weapon when we die
|
||||
CLASS.TeammateNoCollide = true -- Do we collide with teammates or run straight through them
|
||||
CLASS.AvoidPlayers = true -- Automatically swerves around other players
|
||||
CLASS.UseVMHands = true -- Uses viewmodel hands
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Server-Side
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Spawn
|
||||
function CLASS:InitialSpawn() end
|
||||
function CLASS:Spawn() end
|
||||
function CLASS:Loadout() end
|
||||
|
||||
-- Damage
|
||||
function CLASS:Hurt(victim, attacker, healthRemaining, damageTaken) end -- Damage Taken
|
||||
function CLASS:Damage(victim, attacker, healthRemaining, damageDealt) end -- Damage Dealt
|
||||
function CLASS:DamageEntity(ent, attacker, dmginfo) end -- Damage Dealt To Entity
|
||||
|
||||
-- Death
|
||||
function CLASS:Death(inflictor, attacker)
|
||||
self.Player.Data.Alive = false
|
||||
self.Player.Data.AliveTime = CurTime()
|
||||
end
|
||||
function CLASS:SilentDeath()
|
||||
self.Player.Data.Alive = false
|
||||
self.Player.Data.AliveTime = CurTime()
|
||||
end
|
||||
function CLASS:PostDeath() end
|
||||
|
||||
function CLASS:DoDeath() end
|
||||
|
||||
function CLASS:DeathThink()
|
||||
if (CurTime() - self.Player.Data.AliveTime) > 2 then
|
||||
self.Player:Spawn()
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function CLASS:CanSuicide() return true end
|
||||
|
||||
-- Visible Stuff
|
||||
function CLASS:SetModel() BaseClass.SetModel( self ) end
|
||||
|
||||
-- Interaction
|
||||
function CLASS:Use(ent)
|
||||
-- Entity must be valid and not a player.
|
||||
if (!ent) || (!ent:IsValid()) || (ent:IsPlayer()) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Cool Down
|
||||
if (self.Player.Data.UseTime) then
|
||||
local timeSinceUse = (CurTime() - self.Player.Data.UseTime)
|
||||
if (0.2 > timeSinceUse) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Abuse Blacklist (Buttons, Doors, etc)
|
||||
if (5 > timeSinceUse) then
|
||||
local abuseBlacklist = GAMEMODE.Config.Lists:AbuseBlacklist()
|
||||
if (table.HasValue(abuseBlacklist, ent:GetClass())) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
self.Player.Data.UseTime = CurTime()
|
||||
|
||||
return true
|
||||
end
|
||||
function CLASS:AllowPickup(ent) return false end
|
||||
function CLASS:CanPickupWeapon(ent) return false end
|
||||
function CLASS:CanPickupItem(ent) return false end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Shared
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function CLASS:PostThink() end
|
||||
function CLASS:Tick(mv) end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Client-Side
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Spawn
|
||||
function CLASS:InitialClientSpawn()
|
||||
self.Player.Data = {}
|
||||
self.Player.Data.ThirdPerson = false -- Default to FirstPerson View
|
||||
end
|
||||
function CLASS:ClientSpawn() end
|
||||
|
||||
-- View & HUD
|
||||
function CLASS:GetHandsModel() return BaseClass.GetHandsModel(self) end
|
||||
function CLASS:ShouldDrawLocal() return false end
|
||||
function CLASS:HUDPaint() end
|
||||
function CLASS:CalcView(camdata) return camdata end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Register
|
||||
-- ------------------------------------------------------------------------- --
|
||||
player_manager.RegisterClass( "Default", CLASS, "player_default")
|
||||
@@ -0,0 +1,234 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
DEFINE_BASECLASS( "Default" )
|
||||
local CLASS = {}
|
||||
CLASS.DisplayName = "Hider"
|
||||
CLASS.DuckSpeed = 0.0 -- How fast to go from not ducking, to ducking
|
||||
CLASS.UnDuckSpeed = 0.0 -- How fast to go from ducking, to not ducking
|
||||
CLASS.CanUseFlashlight = false -- Can we use the flashlight
|
||||
CLASS.UseVMHands = false -- Uses viewmodel hands
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Server-Side
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Spawn
|
||||
function CLASS:Spawn()
|
||||
print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
|
||||
BaseClass.Spawn(self, self.Player)
|
||||
|
||||
-- Sprinting
|
||||
if (!GAMEMODE.Config:Sprinting()) then
|
||||
self.Player:SetRunSpeed(self.WalkSpeed)
|
||||
end
|
||||
|
||||
-- Settings
|
||||
self.Player:SetMaxHealth(GAMEMODE.Config.Hider:HealthMax())
|
||||
self.Player:SetHealth(GAMEMODE.Config.Hider:Health())
|
||||
self.Player:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self.Player:SetColor(Color(0,0,0,0))
|
||||
|
||||
-- Hull & View Offset
|
||||
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
|
||||
GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,72), Vector(0,0,72))
|
||||
|
||||
-- Collision Group
|
||||
self.Player:SetCollisionGroup(COLLISION_GROUP_PLAYER)
|
||||
|
||||
-- Prop Stuff
|
||||
self.Player.Data.Prop = ents.Create("ph_prop")
|
||||
self.Player.Data.Prop:SetOwner(self.Player)
|
||||
self.Player.Data.Prop:Spawn()
|
||||
self.Player:DeleteOnRemove(self.Player.Data.Prop)
|
||||
|
||||
-- Assign Hands (Auto Networked Sync!)
|
||||
local oldhands = self.Player:GetHands()
|
||||
if (IsValid(oldhands)) then oldhands:Remove() end
|
||||
self.Player:SetHands(self.Player.Data.Prop)
|
||||
end
|
||||
|
||||
-- Death
|
||||
function CLASS:PostDeath(attacker, dmginfo)
|
||||
print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.")
|
||||
BaseClass.PostDeath(self, inflictor, attacker)
|
||||
|
||||
-- Delete Hands Model
|
||||
self.Player:GetHands():Remove()
|
||||
|
||||
-- Collision Group
|
||||
self.Player:SetCollisionGroup(COLLISION_GROUP_PLAYER)
|
||||
|
||||
-- Hull
|
||||
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
|
||||
|
||||
-- Rendering
|
||||
self.Player:SetRenderMode(RENDERMODE_NORMAL)
|
||||
self.Player:SetColor(Color(255,255,255,255))
|
||||
end
|
||||
|
||||
function CLASS:CanSuicide()
|
||||
return true
|
||||
end
|
||||
|
||||
function CLASS:DeathThink()
|
||||
if 1 > (CurTime() - self.Player.Data.AliveTime) then
|
||||
return false
|
||||
end
|
||||
|
||||
self.Player:Spawn()
|
||||
return true
|
||||
end
|
||||
|
||||
-- Visible Stuff
|
||||
function CLASS:SetModel() self.Player:SetModel("models/Gibs/Antlion_gib_small_3.mdl") end -- does "" even work?
|
||||
|
||||
-- Interaction
|
||||
function CLASS:Use(ent)
|
||||
if (!(BaseClass.Use(self, ent))) then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Allow interacting while crouched instead of turning into the prop.
|
||||
if (self.Player:Crouching()) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- Check Lists and other Parameters
|
||||
if (!table.HasValue(GAMEMODE.Config.Lists:ClassWhitelist(), ent:GetClass()))-- Class is not Whitelisted
|
||||
|| (GAMEMODE.Config.Lists.ModelBlacklist[ent:GetModel()]) -- Model is Blacklisted
|
||||
|| !((ent:GetPhysicsObject()) && (ent:GetPhysicsObject():IsValid())) -- Entity doesn't have Physics
|
||||
then
|
||||
print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") attempted to turn into "..ent:GetClass().." ("..ent:GetModel()..").")
|
||||
return true -- Use instead of erroring.
|
||||
end
|
||||
|
||||
-- Turn into the prop
|
||||
local eProp = self.Player:GetHands()
|
||||
util.PrecacheModel(ent:GetModel())
|
||||
eProp:SetModel(ent:GetModel())
|
||||
eProp:SetSkin(ent:GetSkin())
|
||||
eProp:SetHealth(100)
|
||||
eProp:SetMaxHealth(100)
|
||||
eProp:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
|
||||
-- Hull (Optimize into single function? Code is repeated often)
|
||||
local hull = GAMEMODE:PlayerHullFromEntity(self.Player, ent)
|
||||
|
||||
-- View Offset
|
||||
local vo = Vector(0, 0, hull[2].z)
|
||||
GAMEMODE:PlayerSetViewOffset(self.Player, vo, vo)
|
||||
|
||||
-- Health Scaling
|
||||
if (GAMEMODE.Config.Hider:HealthScaling()) then
|
||||
local prc = math.Clamp(self.Player:Health() / self.Player:GetMaxHealth(), 0, 1)
|
||||
local maxhealth = math.Clamp(ent:GetPhysicsObject():GetVolume() / 250, 1, GAMEMODE.Config.Hider:HealthScalingMax())
|
||||
local health = math.Clamp(maxhealth * prc, 1, maxhealth)
|
||||
|
||||
-- Set Health
|
||||
self.Player:SetHealth(health)
|
||||
self.Player:SetMaxHealth(maxhealth)
|
||||
end
|
||||
|
||||
print("Prop Hunt: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") turned into "..ent:GetClass().." ("..ent:GetModel()..").")
|
||||
end
|
||||
|
||||
function CLASS:AllowPickup(ent) return true end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Shared
|
||||
-- ------------------------------------------------------------------------- --
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Client-Side
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function CLASS:ClientSpawn()
|
||||
print("Prop Hunt CL: Hider '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
|
||||
BaseClass.ClientSpawn(self, self.Player)
|
||||
|
||||
self.Player:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
end
|
||||
|
||||
function CLASS:ShouldDrawLocal()
|
||||
return false
|
||||
end
|
||||
|
||||
function CLASS:CalcView(camdata)
|
||||
-- ThirdPerson Settings (ToDo: client config maybe?)
|
||||
local maxViewDist = 100
|
||||
local viewDist = self.Player.Data.ViewDistance or 0
|
||||
|
||||
-- First/Third
|
||||
if (self.Player.Data.ThirdPerson) then
|
||||
if (IsValid(self.Player:GetHands())) then
|
||||
self.Player:GetHands():SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self.Player:GetHands():SetColor(Color(255, 255, 255, 127))
|
||||
end
|
||||
|
||||
-- Incremental Distance instead of instant.
|
||||
viewDist = math.Clamp(viewDist * 0.9 + maxViewDist * 0.1, 0, maxViewDist) -- Zoom Out
|
||||
else
|
||||
if (IsValid(self.Player:GetHands())) then
|
||||
self.Player:GetHands():SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self.Player:GetHands():SetColor(Color(255, 255, 255, 0))
|
||||
end
|
||||
|
||||
viewDist = math.Clamp(viewDist * 0.9, 0, maxViewDist) -- Zoom In
|
||||
end
|
||||
|
||||
-- Trace from Player to would-be camera position
|
||||
local trace = {
|
||||
start = camdata.origin,
|
||||
endpos = camdata.origin - (camdata.angles:Forward() * viewDist),
|
||||
--filter = { "worldspawn", "ph_prop" },
|
||||
filter = function(ent)
|
||||
local filter = { "worldspawn", "ph_prop" }
|
||||
|
||||
if (ent:IsPlayer())
|
||||
|| (table.HasValue(filter, ent:GetClass()))
|
||||
|| (ent == LocalPlayer()) || (ent == LocalPlayer():GetHands()) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
}
|
||||
local result = util.TraceLine(trace)
|
||||
|
||||
-- The Camera has a Sphere radius of 10.
|
||||
if (result.Hit) then -- Configurable?
|
||||
viewDist = math.Clamp(result.HitPos:Distance(camdata.origin), 0, maxViewDist)
|
||||
end
|
||||
|
||||
-- Store ViewDistance
|
||||
self.Player.Data.ViewDistance = viewDist
|
||||
|
||||
-- Adjust CamData
|
||||
camdata.origin = camdata.origin - (camdata.angles:Forward() * math.Clamp(viewDist - 10, 0, maxViewDist))
|
||||
camdata.drawviewer = false
|
||||
|
||||
-- Return
|
||||
return camdata
|
||||
end
|
||||
|
||||
-- Register
|
||||
player_manager.RegisterClass("Hider", CLASS, "Default")
|
||||
@@ -0,0 +1,235 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
--! This file defines the Seeker player class.
|
||||
-- A seeker is someone who is looking for the hiders, using weapons or other
|
||||
-- means of detecting idiots. Also someone who looks like a diaper baby.
|
||||
-- Weapons and Ammo are granted upon spawn and have to be used sparingly or
|
||||
-- they'll be stuck with the crowbar. Bad seeker, bad.
|
||||
-- Gain health upon killing a hider, lose health when attacking non-hiders.
|
||||
-- Death upon health reaching 0.
|
||||
|
||||
DEFINE_BASECLASS( "Default" )
|
||||
local CLASS = {}
|
||||
CLASS.DisplayName = "Seeker"
|
||||
CLASS.CanUseFlashlight = true -- Can we use the flashlight
|
||||
CLASS.MaxHealth = 100
|
||||
CLASS.StartHealth = 100
|
||||
CLASS.StartArmor = 0
|
||||
CLASS.DropWeaponOnDie = true
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Server-Side
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Spawn
|
||||
function CLASS:Spawn()
|
||||
print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
|
||||
BaseClass.Spawn(self)
|
||||
|
||||
-- Sprinting
|
||||
if (GAMEMODE.Config:Sprinting()) then
|
||||
self.Player:SetRunSpeed(self.WalkSpeed)
|
||||
end
|
||||
|
||||
-- Settings
|
||||
self.Player:SetMaxHealth(GAMEMODE.Config.Seeker:HealthMax())
|
||||
self.Player:SetHealth(GAMEMODE.Config.Seeker:Health())
|
||||
self.Player:SetRenderMode(RENDERMODE_NORMAL)
|
||||
self.Player:SetColor(Color(255,255,255,255))
|
||||
|
||||
-- Hull & View Offset
|
||||
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
|
||||
GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,64), Vector(0,0,32))
|
||||
end
|
||||
|
||||
function CLASS:Loadout()
|
||||
-- Give the weapons the admin told us to.
|
||||
local weapons = GAMEMODE.Config.Seeker:Weapons()
|
||||
for i,weapon in ipairs(weapons) do
|
||||
self.Player:Give(weapon)
|
||||
end
|
||||
|
||||
-- Give the ammo the admin told us to.
|
||||
local ammos = GAMEMODE.Config.Seeker:Ammo()
|
||||
for i,ammo in ipairs(ammos) do
|
||||
local typeCount = string.Split(ammo, ":")
|
||||
self.Player:GiveAmmo(tonumber(typeCount[2]), typeCount[1], true)
|
||||
end
|
||||
|
||||
-- Default weapon stuff
|
||||
local cl_defaultweapon = self.Player:GetInfo("cl_defaultweapon")
|
||||
if self.Player:HasWeapon(cl_defaultweapon) then
|
||||
self.Player:SelectWeapon(cl_defaultweapon)
|
||||
end
|
||||
end
|
||||
|
||||
-- Damage
|
||||
function CLASS:Damage(victim, attacker, healthRemaining, damageDealt) end
|
||||
function CLASS:DamageEntity(ent, att, dmg)
|
||||
print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") damaged entity "..ent:GetClass()..".")
|
||||
|
||||
-- Only take damage during this phase.
|
||||
if (GAMEMODE:GetRoundState() == GAMEMODE.States.Seek) then
|
||||
if IsValid(ent) && (!(ent:IsPlayer())) then
|
||||
if (ent:GetClass() == "ph_prop") then
|
||||
ent:GetOwner():TakeDamageInfo(dmg)
|
||||
elseif (ent:GetClass() == "func_breakable") then -- ToDo: Make Configurable which entities don't hurt
|
||||
else
|
||||
att:TakeDamage(GAMEMODE.Config.Seeker:HealthPenalty(), ent, ent)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Death
|
||||
function CLASS:Death(inflictor, attacker)
|
||||
BaseClass.Death(self, inflictor, attacker)
|
||||
|
||||
self.Player:CreateRagdoll()
|
||||
end
|
||||
|
||||
function CLASS:PostDeath()
|
||||
print("Prop Hunt: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.")
|
||||
BaseClass.PostDeath(self, inflictor, attacker)
|
||||
|
||||
self.Player:UnLock()
|
||||
end
|
||||
|
||||
function CLASS:CanSuicide()
|
||||
return true
|
||||
end
|
||||
|
||||
function CLASS:DeathThink()
|
||||
if (CurTime() - self.Player.Data.AliveTime) > 1 then
|
||||
self.Player:Spawn()
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- Visible Stuff
|
||||
function CLASS:SetModel()
|
||||
local cl_playermodel = self.Player:GetInfo( "cl_playermodel" )
|
||||
local modelname = player_manager.TranslatePlayerModel( cl_playermodel )
|
||||
if !(util.IsValidModel(modelname)) then
|
||||
modelname = "models/player/combine_super_soldier.mdl"
|
||||
end
|
||||
util.PrecacheModel(modelname)
|
||||
self.Player:SetModel(modelname)
|
||||
|
||||
-- Hands
|
||||
self.Player:SetupHands()
|
||||
end
|
||||
|
||||
-- Interaction
|
||||
function CLASS:AllowPickup(ent) return true end
|
||||
function CLASS:CanPickupItem(ent) return true end
|
||||
function CLASS:CanPickupWeapon(ent) return true end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Client-Side
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function CLASS:ClientSpawn()
|
||||
print("Prop Hunt CL: Seeker '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
|
||||
BaseClass.ClientSpawn(self)
|
||||
end
|
||||
|
||||
function CLASS:HUDPaint()
|
||||
local State = GetGlobalInt("RoundState", GAMEMODE.States.PreMatch)
|
||||
if (State == GAMEMODE.States.Hide) then
|
||||
local intTime = math.ceil(GetGlobalInt("RoundTime"))
|
||||
local strTime = tostring(intTime)
|
||||
|
||||
-- Seekers are blinded in this Phase.
|
||||
draw.RoundedBox(0, 0, 0, surface.ScreenWidth(), surface.ScreenHeight(), Color(0, 0, 0, 255))
|
||||
|
||||
-- Show Status at the center
|
||||
surface.SetTextColor( 255, 255, 255, 255 )
|
||||
if (intTime >= 1) then
|
||||
surface.SetFont("CloseCaption_Bold")
|
||||
local w,h = surface.GetTextSize("Unblinded in "..strTime.." seconds...")
|
||||
surface.SetTextPos( ScrW()/2 - w / 2, ScrH()/2 - h / 2)
|
||||
surface.DrawText("Unblinded in "..strTime.." seconds...")
|
||||
else
|
||||
surface.SetFont("PHHugeAssFont")
|
||||
local w,h = surface.GetTextSize("NOW")
|
||||
surface.SetTextPos( ScrW()/2 - w / 2, ScrH()/2 - h / 2)
|
||||
surface.DrawText("NOW")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function CLASS:ShouldDrawLocal()
|
||||
return self.Player.Data.ThirdPerson
|
||||
end
|
||||
|
||||
function CLASS:CalcView(camdata)
|
||||
-- ThirdPerson Settings (ToDo: client config maybe?)
|
||||
local maxViewDist = 100
|
||||
local viewDist = self.Player.Data.ViewDistance or 0
|
||||
|
||||
-- First/Third
|
||||
if (self.Player.Data.ThirdPerson) then
|
||||
viewDist = math.Clamp(viewDist * 0.9 + maxViewDist * 0.1, 0, maxViewDist) -- Zoom Out
|
||||
else
|
||||
viewDist = math.Clamp(viewDist * 0.9, 0, maxViewDist) -- Zoom In
|
||||
end
|
||||
|
||||
-- Trace from Player to would-be camera position
|
||||
local trace = {
|
||||
start = camdata.origin,
|
||||
endpos = camdata.origin - (camdata.angles:Forward() * viewDist),
|
||||
--filter = { "worldspawn", "ph_prop" },
|
||||
filter = function(ent)
|
||||
local filter = { "worldspawn", "ph_prop" }
|
||||
|
||||
if (ent:IsPlayer())
|
||||
|| (table.HasValue(filter, ent:GetClass()))
|
||||
|| (ent == LocalPlayer()) || (ent == LocalPlayer():GetHands()) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
}
|
||||
local result = util.TraceLine(trace)
|
||||
|
||||
-- The Camera has a Sphere radius of 10.
|
||||
if (result.Hit) then -- Configurable?
|
||||
viewDist = math.Clamp(result.HitPos:Distance(camdata.origin), 0, maxViewDist)
|
||||
end
|
||||
|
||||
-- Store ViewDistance
|
||||
self.Player.Data.ViewDistance = viewDist
|
||||
|
||||
-- Adjust CamData
|
||||
camdata.origin = camdata.origin - (camdata.angles:Forward() * math.Clamp(viewDist - 10, 0, maxViewDist))
|
||||
--camdata.drawviewer = false
|
||||
|
||||
-- Return
|
||||
return camdata
|
||||
end
|
||||
|
||||
-- Register
|
||||
player_manager.RegisterClass("Seeker", CLASS, "Default")
|
||||
@@ -0,0 +1,85 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
DEFINE_BASECLASS("Default")
|
||||
local CLASS = {}
|
||||
CLASS.DisplayName = "Spectator"
|
||||
CLASS.DuckSpeed = 0.0 -- How fast to go from not ducking, to ducking
|
||||
CLASS.UnDuckSpeed = 0.0 -- How fast to go from ducking, to not ducking
|
||||
CLASS.CanUseFlashlight = false -- Can we use the flashlight
|
||||
CLASS.UseVMHands = false -- Uses viewmodel hands
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Server-Side
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Spawn
|
||||
function CLASS:Spawn()
|
||||
print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
|
||||
BaseClass.Spawn(self)
|
||||
|
||||
self.Player:Spectate(OBS_MODE_ROAMING)
|
||||
self.Player:SetRenderMode(RENDERMODE_NONE)
|
||||
|
||||
-- View Offset & Hull
|
||||
GAMEMODE:PlayerSetViewOffset(self.Player, Vector(0,0,0), Vector(0,0,0))
|
||||
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
|
||||
end
|
||||
|
||||
-- Death
|
||||
function CLASS:PostDeath(inflictor, attacker)
|
||||
print("Prop Hunt: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") died.")
|
||||
BaseClass.PostDeath(self, inflictor, attacker)
|
||||
|
||||
self.Player:Spectate(OBS_MODE_NONE)
|
||||
self.Player:UnSpectate()
|
||||
|
||||
-- Hull
|
||||
GAMEMODE:PlayerHullFromEntity(self.Player, nil)
|
||||
|
||||
self.Player:SetRenderMode(RENDERMODE_NORMAL)
|
||||
end
|
||||
|
||||
-- Visible Stuff
|
||||
function CLASS:SetModel()
|
||||
self.Player:SetModel("")
|
||||
|
||||
-- Hands
|
||||
self.Player:SetupHands()
|
||||
end
|
||||
|
||||
-- Interaction
|
||||
function CLASS:Use(ent) return false end
|
||||
function CLASS:AllowPickup(ent) return false end
|
||||
function CLASS:CanPickupWeapon(ent) return false end
|
||||
function CLASS:CanPickupItem(ent) return false end
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Client-Side
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function CLASS:ClientSpawn()
|
||||
print("Prop Hunt CL: Spectator '"..self.Player:GetName().."' (SteamID: "..self.Player:SteamID()..") spawned.")
|
||||
end
|
||||
|
||||
function CLASS:ShouldDrawLocal() return false end
|
||||
|
||||
player_manager.RegisterClass( "Spectator", CLASS, "Default")
|
||||
@@ -0,0 +1,549 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
--! Initialize configuration table.
|
||||
GM.Config = { }
|
||||
GM.Config.ConVars = {}
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Basic Settings
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Debug Mode
|
||||
GM.Config.ConVars.Debug = CreateConVar("ph_debug", 0, FCVAR_CHEAT + FCVAR_REPLICATED)
|
||||
function GM.Config:Debug()
|
||||
return self.ConVars.Debug:GetBool()
|
||||
end
|
||||
|
||||
-- Game Mode (See sh_init.lua)
|
||||
GM.Config.ConVars.GameMode = CreateConVar("ph_gamemode", GM.Modes.Original, FCVAR_REPLICATED)
|
||||
function GM.Config:GameMode()
|
||||
return self.ConVars.GameMode:GetInt()
|
||||
end
|
||||
|
||||
-- Timelimit in minutes
|
||||
GM.Config.ConVars.TimeLimit = GetConVar("mp_timelimit")
|
||||
function GM.Config:TimeLimit()
|
||||
return self.ConVars.TimeLimit:GetFloat()
|
||||
end
|
||||
|
||||
-- Enable Sprinting?
|
||||
GM.Config.ConVars.Sprinting = CreateConVar("ph_sprinting", 0, FCVAR_REPLICATED)
|
||||
function GM.Config:Sprinting()
|
||||
return self.ConVars.Sprinting:GetBool()
|
||||
end
|
||||
|
||||
-- Taunt Cooldown (Seconds)
|
||||
GM.Config.ConVars.TauntCoolDown = CreateConVar("ph_tauntcooldown", 5, FCVAR_REPLICATED)
|
||||
function GM.Config:TauntCoolDown()
|
||||
return self.ConVars.TauntCoolDown:GetFloat()
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Round Settings
|
||||
-- ------------------------------------------------------------------------- --
|
||||
GM.Config.Round = {}
|
||||
GM.Config.Round.ConVars = {}
|
||||
|
||||
-- How many rounds should the gamemode attempt to fit into the map timelimit, if there is any?
|
||||
GM.Config.Round.ConVars.Amount = CreateConVar("ph_round_limit", 10, FCVAR_REPLICATED)
|
||||
function GM.Config.Round:Amount()
|
||||
return self.ConVars.Amount:GetInt()
|
||||
end
|
||||
|
||||
-- Round Time Limit (Seconds, Default 3 minutes)
|
||||
GM.Config.Round.ConVars.Time = CreateConVar("ph_round_timelimit", 180, FCVAR_REPLICATED)
|
||||
function GM.Config.Round:Time()
|
||||
return self.ConVars.Time:GetInt() - GAMEMODE.Config.Round:BlindTime()
|
||||
end
|
||||
|
||||
-- For how many seconds are the Seekers blinded? (Seconds)
|
||||
GM.Config.Round.ConVars.BlindTime = CreateConVar("ph_round_blindtime", 30, FCVAR_REPLICATED, "How long are hunters blinded? (positive values will be inside the round time limit, negative will add to the round time limit)")
|
||||
function GM.Config.Round:BlindTime()
|
||||
return self.ConVars.BlindTime:GetInt()
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Seeker Settings
|
||||
-- ------------------------------------------------------------------------- --
|
||||
GM.Config.Seeker = {}
|
||||
GM.Config.Seeker.ConVars = {}
|
||||
|
||||
GM.Config.Seeker.ConVars.Health = CreateConVar("ph_seeker_health", 100, FCVAR_REPLICATED)
|
||||
function GM.Config.Seeker:Health()
|
||||
return self.ConVars.Health:GetInt()
|
||||
end
|
||||
|
||||
GM.Config.Seeker.ConVars.HealthMax = CreateConVar("ph_seeker_health_max", 100, FCVAR_REPLICATED)
|
||||
function GM.Config.Seeker:HealthMax()
|
||||
return self.ConVars.HealthMax:GetInt()
|
||||
end
|
||||
|
||||
GM.Config.Seeker.ConVars.HealthBonus = CreateConVar("ph_seeker_health_bonus", 20, FCVAR_REPLICATED)
|
||||
function GM.Config.Seeker:HealthBonus()
|
||||
return self.ConVars.HealthBonus:GetInt()
|
||||
end
|
||||
|
||||
GM.Config.Seeker.ConVars.HealthPenalty = CreateConVar("ph_seeker_health_penalty", 5, FCVAR_REPLICATED)
|
||||
function GM.Config.Seeker:HealthPenalty()
|
||||
return self.ConVars.HealthPenalty:GetInt()
|
||||
end
|
||||
|
||||
GM.Config.Seeker.ConVars.Weapons = CreateConVar("ph_seeker_weapons", "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun", FCVAR_REPLICATED)
|
||||
function GM.Config.Seeker:Weapons()
|
||||
return string.Split(self.ConVars.Weapons:GetString(), ",")
|
||||
end
|
||||
|
||||
GM.Config.Seeker.ConVars.Ammo = CreateConVar("ph_seeker_ammo", "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64", FCVAR_REPLICATED)
|
||||
function GM.Config.Seeker:Ammo()
|
||||
return string.Split(self.ConVars.Ammo:GetString(), ",")
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Hider Settings
|
||||
-- ------------------------------------------------------------------------- --
|
||||
GM.Config.Hider = {}
|
||||
GM.Config.Hider.ConVars = {}
|
||||
|
||||
GM.Config.Hider.ConVars.Health = CreateConVar("ph_hider_health", 100, FCVAR_REPLICATED)
|
||||
function GM.Config.Hider:Health()
|
||||
return self.ConVars.Health:GetInt()
|
||||
end
|
||||
|
||||
GM.Config.Hider.ConVars.HealthMax = CreateConVar("ph_hider_health_max", 100, FCVAR_REPLICATED)
|
||||
function GM.Config.Hider:HealthMax()
|
||||
return self.ConVars.HealthMax:GetInt()
|
||||
end
|
||||
|
||||
GM.Config.Hider.ConVars.HealthScaling = CreateConVar("ph_hider_health_scaling", 100, FCVAR_REPLICATED)
|
||||
function GM.Config.Hider:HealthScaling()
|
||||
return self.ConVars.HealthScaling:GetBool()
|
||||
end
|
||||
|
||||
GM.Config.Hider.ConVars.HealthScalingMax = CreateConVar("ph_hider_health_scaling_max", 200, FCVAR_REPLICATED)
|
||||
function GM.Config.Hider:HealthScalingMax()
|
||||
return self.ConVars.HealthScalingMax:GetInt()
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Whitelist & Blacklist
|
||||
-- ------------------------------------------------------------------------- --
|
||||
GM.Config.Lists = {}
|
||||
GM.Config.Lists.ConVars = {}
|
||||
GM.Config.Lists.ConCmds = {}
|
||||
|
||||
GM.Config.Lists.ConVars.ClassWhitelist = CreateConVar("ph_list_class_whitelist", "prop_physics,prop_physics_multiplayer,prop_physics_respawnable", FCVAR_REPLICATED)
|
||||
function GM.Config.Lists:ClassWhitelist()
|
||||
return string.Split(self.ConVars.ClassWhitelist:GetString(), ",")
|
||||
end
|
||||
|
||||
-- Use Abuse Blacklist
|
||||
GM.Config.Lists.ConVars.AbuseBlacklist = CreateConVar("ph_list_abuse_blacklist", "func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable", FCVAR_REPLICATED)
|
||||
function GM.Config.Lists:AbuseBlacklist()
|
||||
return string.Split(self.ConVars.AbuseBlacklist:GetString(), ",")
|
||||
end
|
||||
|
||||
-- Model Blacklist
|
||||
GM.Config.Lists.ModelBlacklist = {}
|
||||
GM.Config.Lists.ModelBlacklist["models/props/cs_assault/dollar.mdl"] = true
|
||||
GM.Config.Lists.ModelBlacklist["models/props/cs_assault/money.mdl"] = true
|
||||
GM.Config.Lists.ModelBlacklist["models/props/cs_office/snowman_arm.mdl"] = true
|
||||
GM.Config.Lists.ModelBlacklist["models/props_junk/garbage_plasticbottle001a.mdl"] = true
|
||||
GM.Config.Lists.ModelBlacklist["models/props/cs_office/projector_remote.mdl"] = true
|
||||
|
||||
GM.Config.Lists.ConCmds.ModelBlacklistList = concommand.Add("ph_list_model_blacklist_list", function(ply, cmd, args, argStr)
|
||||
print("Model Blacklist:")
|
||||
for k,v in pairs(GAMEMODE.Config.Lists.ModelBlacklist) do
|
||||
print(" "..k)
|
||||
end
|
||||
end, "List all blacklisted models.")
|
||||
|
||||
GM.Config.Lists.ConCmds.ModelBlacklistClear = concommand.Add("ph_list_model_blacklist_list", function(ply, cmd, args, argStr)
|
||||
GM.Config.Lists.ModelBlacklist = {}
|
||||
end, "Clear blacklisted models.")
|
||||
|
||||
GM.Config.Lists.ConCmds.ModelBlacklistAdd = concommand.Add("ph_list_model_blacklist_add", function(ply, cmd, args, argStr)
|
||||
if (table.count(args) > 0) then
|
||||
GAMEMODE.Config.Lists.ModelBlacklist[args[1]] = true
|
||||
else
|
||||
print("Missing model name")
|
||||
end
|
||||
end, "Add a new blacklisted model.")
|
||||
|
||||
GM.Config.Lists.ConCmds.ModelBlacklistRemove = concommand.Add("ph_list_model_blacklist_remove", function(ply, cmd, args, argStr)
|
||||
if (table.count(args) > 0) then
|
||||
GAMEMODE.Config.Lists.ModelBlacklist[args[1]] = nil
|
||||
else
|
||||
print("Missing model name")
|
||||
end
|
||||
end, "Removes a blacklisted model.")
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Taunts
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- GM.Config.Taunts = {
|
||||
-- Seeker = { },
|
||||
-- Hider = { },
|
||||
-- }
|
||||
|
||||
-- -- Taunts.Clear()
|
||||
-- --@desc: Clears the current taunt list.
|
||||
-- GM.Config.Taunts.Clear = function()
|
||||
-- this.Seeker = {}
|
||||
-- this.Hider = {}
|
||||
-- end
|
||||
|
||||
-- -- Taunts.Load(sTauntListFile)
|
||||
-- --@desc: Loads the taunt list from disk.
|
||||
-- --@param:
|
||||
-- -- sTauntListFile - A string containing the path to the taunt list to load.
|
||||
-- --@return: true or false depending on success.
|
||||
-- GM.Config.Taunts.Load = function(sTauntListFile)
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Loading taunt list from file '"..sTauntListFile.."'...") end
|
||||
|
||||
-- -- Safeguard against idiots.
|
||||
-- if type(sTauntListFile) != "string" then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: <sTauntListFile> is not a string.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Given file must exist for us to continue.
|
||||
-- if ! file.Exists(sTauntListFile, "GAME") then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: File not found.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Read the file and check if it's empty.
|
||||
-- sTauntListData = file.Read(sTauntListFile, "GAME")
|
||||
-- if sTauntListData == "" then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: File is empty.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Convert JSON to a table for us to use.
|
||||
-- sTauntList = util.JSONToTable(sTauntListData)
|
||||
|
||||
-- -- Is it nil? Then it's not valid JSON
|
||||
-- if sTauntList == nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: File contains invalid JSON.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Finally, append the taunt lists.
|
||||
-- if sTauntList.Seeker != nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Adding Seeker taunts...") end
|
||||
-- for k,v in pairs(sTauntList.Seeker) do
|
||||
-- GAMEMODE.Taunts.Seeker[k] = v
|
||||
-- end
|
||||
-- end
|
||||
-- if sTauntList.Hider != nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Adding Hider taunts...") end
|
||||
-- for k,v in pairs(sTauntList.Hider) do
|
||||
-- GAMEMODE.Taunts.Hider[k] = v
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Load: Complete.") end
|
||||
-- return true
|
||||
-- end
|
||||
|
||||
-- -- Taunts.Save(sTauntListFile)
|
||||
-- --@desc: Saves the current taunt list to disk.
|
||||
-- --@param:
|
||||
-- -- sTauntListFile - A string containing the path to the file to save to.
|
||||
-- --@return: true or false depending on success.
|
||||
-- GM.Config.Taunts.Save = function(sTauntListFile)
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Saving taunt list to file '"..sTauntListFile.."'...") end
|
||||
|
||||
-- -- Safeguard against idiots.
|
||||
-- if type(sTauntListFile) != "string" then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: <sTauntListFile> is not a string.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- File must not be nil, otherwise we can't write to it.
|
||||
-- if sTauntListFile == nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: No file given.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Convert our taunt table to JSON.
|
||||
-- sTauntListData = util.TableToJSON(GAMEMODE.Taunts);
|
||||
-- if sTauntListData == nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Corrupted GAMEMODE table.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Write out JSON out to file
|
||||
-- if ! file.Write(sTauntListFile, sTauntListData) then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Failed to write to file.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Save: Complete.") end
|
||||
-- return true
|
||||
-- end
|
||||
|
||||
-- -- Taunts.Add(sTauntName, sSoundFile, iTeamID, mPropFilter)
|
||||
-- --@desc: Registers a new taunt with the given name, file, team and filter.
|
||||
-- --@param:
|
||||
-- -- sTauntName - The unique name of the taunt.
|
||||
-- -- sSoundFile - A sound file to play when this taunt is selected.
|
||||
-- -- iTeamID - The team that should receive the taunt or nil for all teams.
|
||||
-- -- mPropFilter - A string or a table containing strings for props that should be able to use this taunt.
|
||||
-- --@return: true or false depending on success.
|
||||
-- GM.Config.Taunts.Add = function(sTauntName, sSoundFile, iTeamID, mPropFilter)
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Adding new taunt '"..sTauntName.."'...") end
|
||||
|
||||
-- -- Safeguard against idiots.
|
||||
-- if type(sTauntName) != "string" then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <sTauntName> is not a string.") end
|
||||
-- return false
|
||||
-- end
|
||||
-- if type(sSoundFile) != "string" then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <sSoundFile> is not a string.") end
|
||||
-- return false
|
||||
-- end
|
||||
-- if (type(iTeamID) != "number" && iTeamID != nil) then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <iTeamID> is not a number or nil.") end
|
||||
-- return false
|
||||
-- end
|
||||
-- if (type(mPropFilter) != "string" && type(mPropFilter) != "table" && mPropFilter != nil) then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: <mPropFilter> is not a string, table or nil.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Check if the sound file actually exists
|
||||
-- if !file.Exists("sound/"..sSoundFile, "GAME") then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: File '"..sSoundFile.."' does not exist.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Make sure that our prop filter is a table listing the props it's supposed to work for.
|
||||
-- if (mPropFilter == nil) then
|
||||
-- mPropFilter = { }
|
||||
-- elseif type(mPropFilter) == "string" then
|
||||
-- mPropFilter = { mPropFilter }
|
||||
-- end
|
||||
|
||||
-- -- Prepare Taunt table
|
||||
-- Taunt = {
|
||||
-- File = sSoundFile,
|
||||
-- Filter = mPropFilter
|
||||
-- }
|
||||
|
||||
-- -- If iTeamID is nil, both teams will receive the taunt.
|
||||
-- if iTeamID == nil then
|
||||
-- GAMEMODE.Taunts.Seeker[sTauntName] = Taunt
|
||||
-- GAMEMODE.Taunts.Hider[sTauntName] = Taunt
|
||||
-- else
|
||||
-- -- Make sure that the team is valid.
|
||||
-- if ! team.Valid(iTeamID) then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Team "..iTeamID.."' does not exist.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- if (iTeamID == TEAM_SEEKERS) then
|
||||
-- GAMEMODE.Taunts.Seeker[sTauntName] = Taunt
|
||||
-- elseif (iTeamID == TEAM_HIDERS) then
|
||||
-- GAMEMODE.Taunts.Hider[sTauntName] = Taunt
|
||||
-- else
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Team "..iTeamID.."' can't have taunts.") end
|
||||
-- return false
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Add: Complete.") end
|
||||
-- return true
|
||||
-- end
|
||||
|
||||
-- -- Taunts.Remove(sTauntName, iTeamID)
|
||||
-- --@desc: Removes a registered taunt with the given name and team.
|
||||
-- --@param:
|
||||
-- -- sTauntName - The unique name of the taunt.
|
||||
-- -- iTeamID - The team that the taunt should be removed from or nil for all teams.
|
||||
-- --@return: true or false depending on success.
|
||||
-- GM.Config.Taunts.Remove = function(sTauntName, iTeamID)
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Removing taunt '"..sTauntName.."'...") end
|
||||
|
||||
-- -- Safeguard against idiots.
|
||||
-- if type(sTauntName) != "string" then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: <sTauntName> is not a string.") end
|
||||
-- return false
|
||||
-- end
|
||||
-- if (type(iTeamID) != "number" && iTeamID != nil) then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: <iTeamID> is not a number or nil.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- if iTeamID is nil, both teams will have the taunt removed.
|
||||
-- if (iTeamID == nil) then
|
||||
-- GAMEMODE.Taunts.Seeker[sTauntName] = nil
|
||||
-- GAMEMODE.Taunts.Hider[sTauntName] = nil
|
||||
-- else
|
||||
-- -- Make sure we have a valid Team.
|
||||
-- if ! team.Valid(iTeamID) then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Team "..iTeamID.."' does not exist.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- if iTeamID == TEAM_SEEKERS then
|
||||
-- GAMEMODE.Taunts.Seeker[sTauntName] = nil
|
||||
-- elseif iTeamID == TEAM_HIDERS then
|
||||
-- GAMEMODE.Taunts.Hider[sTauntName] = nil
|
||||
-- else
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Team "..iTeamID.."' can't have taunts.") end
|
||||
-- return false
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Taunts.Remove: Complete.") end
|
||||
-- return true
|
||||
-- end
|
||||
|
||||
-- -- ToDo: Taunts.Get(iTeamID, sPropName)
|
||||
|
||||
-- --! Announcers (Round Start, Unblind, Win, Loss)
|
||||
-- GM.Config.Announcers = {
|
||||
-- Start = { },
|
||||
-- Unblind = { },
|
||||
-- Win = { },
|
||||
-- Loss = { }
|
||||
-- }
|
||||
|
||||
-- -- Announcers.Clear()
|
||||
-- --@desc: Clears the current announcer list.
|
||||
-- GM.Config.Announcers.Clear = function()
|
||||
-- Announcers.Start = { }
|
||||
-- Announcers.Unblind = { }
|
||||
-- Announcers.Win = { }
|
||||
-- Announcers.Loss = { }
|
||||
-- end
|
||||
|
||||
-- -- Announcers.Load(sAnnouncerListFile)
|
||||
-- --@desc: Tries to load the given announcer list.
|
||||
-- --@param:
|
||||
-- -- sAnnouncerListFile - A string containing the path to the announcer list to load.
|
||||
-- --@return: true or false depending on success.
|
||||
-- GM.Config.Announcers.Load = function(sAnnouncerListFile)
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Loading announcer list from file '"..sAnnouncerListFile.."'...") end
|
||||
|
||||
-- -- Safeguard against idiots.
|
||||
-- if type(sAnnouncerListFile) != "string" then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: <sAnnouncerListFile> is not a string.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Given file must exist for us to continue.
|
||||
-- if ! file.Exists(sAnnouncerListFile, "GAME") then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: File not found.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Read the file and check if it's empty.
|
||||
-- sAnnouncerListData = file.Read(sAnnouncerListFile, "GAME")
|
||||
-- if sAnnouncerListData == "" then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: File is empty.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Convert JSON to a table for us to use.
|
||||
-- sAnnouncerList = util.JSONToTable(sAnnouncerListData)
|
||||
|
||||
-- -- Is it nil? Then it's not valid JSON
|
||||
-- if sAnnouncerList == nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: File contains invalid JSON.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Finally, insert the announcer lists.
|
||||
-- if sAnnouncerList.Start != nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Start announcers...") end
|
||||
-- for k,v in pairs(sAnnouncerList.Start) do
|
||||
-- GAMEMODE.Announcers.Start[k] = v
|
||||
-- end
|
||||
-- end
|
||||
-- if sAnnouncerList.Unblind != nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Unblind announcers...") end
|
||||
-- for k,v in pairs(sAnnouncerList.Unblind) do
|
||||
-- GAMEMODE.Announcers.Unblind[k] = v
|
||||
-- end
|
||||
-- end
|
||||
-- if sAnnouncerList.Win != nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Win announcers...") end
|
||||
-- for k,v in pairs(sAnnouncerList.Win) do
|
||||
-- GAMEMODE.Announcers.Win[k] = v
|
||||
-- end
|
||||
-- end
|
||||
-- if sAnnouncerList.Loss != nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Adding Loss announcers...") end
|
||||
-- for k,v in pairs(sAnnouncerList.Loss) do
|
||||
-- GAMEMODE.Announcers.Loss[k] = v
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Load: Complete.") end
|
||||
-- return true
|
||||
-- end
|
||||
|
||||
-- -- Announcers.Save(sAnnouncerListFile)
|
||||
-- --@desc: Saves the current taunt list to disk.
|
||||
-- --@param:
|
||||
-- -- sAnnouncerListFile - A string containing the path to the file to save to.
|
||||
-- --@return: true or false depending on success.
|
||||
-- GM.Config.Announcers.Save = function(sAnnouncerListFile)
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Saving announcer list to file '"..sAnnouncerListFile.."'...") end
|
||||
|
||||
-- -- Safeguard against idiots.
|
||||
-- if type(sAnnouncerListFile) != "string" then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: <sAnnouncerListFile> is not a string.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- File must not be nil, otherwise we can't write to it.
|
||||
-- if sAnnouncerListFile == nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: No file given.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Convert our taunt table to JSON.
|
||||
-- sAnnouncerListData = util.TableToJSON(GAMEMODE.Announcers);
|
||||
-- if sAnnouncerListData == nil then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Corrupted GAMEMODE table.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
-- -- Write out JSON out to file
|
||||
-- if ! file.Write(sAnnouncerListFile, sAnnouncerListData) then
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Failed to write to file.") end
|
||||
-- return false
|
||||
-- end
|
||||
|
||||
|
||||
-- if GAMEMODE.Config:Debug() then print("Prop Hunt.Announcers.Save: Complete.") end
|
||||
-- return true
|
||||
-- end
|
||||
|
||||
-- -- ToDo: Announcers.Add
|
||||
-- -- ToDo: Announcers.Remove
|
||||
-- -- ToDo: Announcers.Get(iType)
|
||||
@@ -0,0 +1,63 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
GM.RoundManager = {}
|
||||
GM.RoundManager.State = nil;
|
||||
GM.RoundManager.NextState = nil;
|
||||
|
||||
function GM.RoundManager:Tick(...)
|
||||
if (self.State != nil) then
|
||||
if (self.State.Tick != nil) then
|
||||
self.State:Tick(...)
|
||||
end
|
||||
end
|
||||
|
||||
-- Advance States
|
||||
if (self.NextState != self.State) then
|
||||
-- Call OnLeave(NewState)
|
||||
if (self.State != nil) then
|
||||
if (self.State.OnLeave != nil) then
|
||||
self.State:OnLeave(self.NextState)
|
||||
end
|
||||
end
|
||||
|
||||
-- Call OnEnter(OldState)
|
||||
if (self.NextState != nil) then
|
||||
if (self.NextState.OnEnter != nil) then
|
||||
self.NextState:OnEnter(self.State)
|
||||
end
|
||||
end
|
||||
|
||||
-- Set State
|
||||
self.State = self.NextState
|
||||
end
|
||||
end
|
||||
|
||||
function GM.RoundManager:GetState()
|
||||
return self.State
|
||||
end
|
||||
|
||||
function GM.RoundManager:SetState(State)
|
||||
self.NextState = State
|
||||
end
|
||||
@@ -0,0 +1,61 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
StateHide = {}
|
||||
|
||||
function StateHide:OnEnter(OldState)
|
||||
if GAMEMODE.Config:Debug() then print("StateHide: OnEnter") end
|
||||
GAMEMODE:SetRoundState(GAMEMODE.States.Hide)
|
||||
|
||||
-- Round Data
|
||||
GAMEMODE.Data.RoundTime = math.abs(GAMEMODE.Config.Round:BlindTime())
|
||||
GAMEMODE.Data.RoundStartTime = CurTime()
|
||||
|
||||
SetGlobalInt("RoundTime", GAMEMODE.Data.RoundTime)
|
||||
|
||||
-- Freeze Seekers
|
||||
for i, ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do
|
||||
ply:Freeze(true)
|
||||
ply:Lock()
|
||||
end
|
||||
end
|
||||
|
||||
function StateHide:Tick()
|
||||
-- Update Game Time
|
||||
GAMEMODE.Data.RoundTime = math.abs(GAMEMODE.Config.Round:BlindTime()) - (CurTime() - GAMEMODE.Data.RoundStartTime)
|
||||
SetGlobalInt("RoundTime", math.ceil(GAMEMODE.Data.RoundTime))
|
||||
|
||||
-- Advance to Seeking State
|
||||
if (GAMEMODE.Data.RoundTime <= 0) then
|
||||
if GAMEMODE.Config:Debug() then print("StateHide: Advancing to Seek stage.") end
|
||||
|
||||
GAMEMODE.RoundManager:SetState(StateSeek)
|
||||
end
|
||||
|
||||
-- ToDo: Logic for more game modes here?
|
||||
end
|
||||
|
||||
function StateHide:OnLeave(NewState)
|
||||
if GAMEMODE.Config:Debug() then print("StateHide: OnLeave") end
|
||||
end
|
||||
+12
-12
@@ -1,7 +1,7 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Project Kube
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -22,18 +22,18 @@
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
--! Our custom RoundManager
|
||||
-- We need to keep track of three states in a round: Hide, Seek and PostRound.
|
||||
|
||||
--! Round States
|
||||
ROUNDSTATE_HIDE = 1
|
||||
ROUNDSTATE_SEEK = 2
|
||||
ROUNDSTATE_POSTROUND = 3
|
||||
|
||||
function RoundManagerInit()
|
||||
StatePostMatch = {}
|
||||
|
||||
function StatePostMatch:OnEnter(OldState)
|
||||
if GAMEMODE.Config:Debug() then print("StatePostMatch: OnEnter") end
|
||||
GAMEMODE:SetRoundState(GAMEMODE.States.PostMatch)
|
||||
end
|
||||
|
||||
function RoundManagerAdvance()
|
||||
|
||||
function StatePostMatch:Tick()
|
||||
-- Advance State
|
||||
GAMEMODE.RoundManager:SetState(StatePreMatch)
|
||||
end
|
||||
|
||||
function StatePostMatch:OnLeave(NewState)
|
||||
if GAMEMODE.Config:Debug() then print("StatePostMatch: OnLeave") end
|
||||
end
|
||||
@@ -0,0 +1,55 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
StatePostRound = {}
|
||||
|
||||
function StatePostRound:OnEnter(OldState)
|
||||
if GAMEMODE.Config:Debug() then print("StatePostRound: OnEnter") end
|
||||
GAMEMODE:SetRoundState(GAMEMODE.States.PostRound)
|
||||
end
|
||||
|
||||
function StatePostRound:Tick()
|
||||
-- Advance State
|
||||
GAMEMODE.RoundManager:SetState(StatePreRound) -- Test: Reset to Hide
|
||||
end
|
||||
|
||||
function StatePostRound:OnLeave(NewState)
|
||||
if GAMEMODE.Config:Debug() then print("StatePostRound: OnLeave") end
|
||||
|
||||
-- Game Mode: Basic
|
||||
if (GAMEMODE.Config:GameMode() == GAMEMODE.Modes.Original) then
|
||||
-- Swap Teams
|
||||
local hiders, seekers = team.GetPlayers(GAMEMODE.Teams.Hiders), team.GetPlayers(GAMEMODE.Teams.Seekers)
|
||||
for i, ply in ipairs(hiders) do
|
||||
ply:SetTeam(GAMEMODE.Teams.Seekers)
|
||||
player_manager.SetPlayerClass(ply, "Seeker")
|
||||
end
|
||||
for i, ply in ipairs(seekers) do
|
||||
ply:SetTeam(GAMEMODE.Teams.Hiders)
|
||||
player_manager.SetPlayerClass(ply, "Hider")
|
||||
end
|
||||
|
||||
-- TODO: Other Gamemodes
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,54 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
-- Precache Network Message
|
||||
StatePreMatch = {}
|
||||
|
||||
function StatePreMatch:OnEnter(OldState)
|
||||
if GAMEMODE.Config:Debug() then print("StatePreMatch: OnEnter") end
|
||||
GAMEMODE:SetRoundState(GAMEMODE.States.PreMatch)
|
||||
|
||||
SetGlobalInt("Round", GetGlobalInt("Round", 0) + 1)
|
||||
end
|
||||
|
||||
function StatePreMatch:Tick()
|
||||
-- Debug: Auto Advance to PreRound State
|
||||
if (GAMEMODE.Config:Debug()) then
|
||||
print("StatePreMatch: Advancing to StatePreRound")
|
||||
GAMEMODE.RoundManager:SetState(StatePreRound)
|
||||
end
|
||||
|
||||
-- Game Mode: Basic
|
||||
if (GAMEMODE.Config:GameMode() == GAMEMODE.Modes.Original) then
|
||||
-- Both Teams must have at least 1 player.
|
||||
if ((team.NumPlayers(GAMEMODE.Teams.Seekers) >= 1) && (team.NumPlayers(GAMEMODE.Teams.Hiders) >= 1)) then
|
||||
GAMEMODE.RoundManager:SetState(StatePreRound)
|
||||
end
|
||||
-- TODO: Other Gamemodes
|
||||
end
|
||||
end
|
||||
|
||||
function StatePreMatch:OnLeave(NewState)
|
||||
if GAMEMODE.Config:Debug() then print("StatePreMatch: OnLeave") end
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
StatePreRound = {}
|
||||
|
||||
function StatePreRound:OnEnter(OldState)
|
||||
if GAMEMODE.Config:Debug() then print("StatePreRound: OnEnter") end
|
||||
GAMEMODE:SetRoundState(GAMEMODE.States.PreRound)
|
||||
|
||||
-- Clean Up the Map
|
||||
game.CleanUpMap()
|
||||
|
||||
end
|
||||
function StatePreRound:Tick()
|
||||
-- Advance State
|
||||
GAMEMODE.RoundManager:SetState(StateHide)
|
||||
end
|
||||
function StatePreRound:OnLeave(NewState)
|
||||
if GAMEMODE.Config:Debug() then print("StatePreRound: OnLeave") end
|
||||
|
||||
-- Game Mode: Basic
|
||||
if (GAMEMODE.Config:GameMode() == GAMEMODE.Modes.Original) then
|
||||
-- Respawn Everyone
|
||||
for i, ply in ipairs(player.GetAll()) do
|
||||
ply:KillSilent()
|
||||
ply.Data.Alive = true
|
||||
ply:Spawn()
|
||||
end
|
||||
-- TODO: Other Gamemodes
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,83 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
StateSeek = {}
|
||||
|
||||
function StateSeek:OnEnter(OldState)
|
||||
if GAMEMODE.Config:Debug() then print("StateSeek: OnEnter") end
|
||||
GAMEMODE:SetRoundState(GAMEMODE.States.Seek)
|
||||
|
||||
-- Round Data
|
||||
GAMEMODE.Data.RoundTime = GAMEMODE.Config.Round:Time()
|
||||
|
||||
-- Unfreeze Seekers
|
||||
for i, ply in ipairs(team.GetPlayers(GAMEMODE.Teams.Seekers)) do
|
||||
ply:Freeze(false)
|
||||
ply:UnLock()
|
||||
end
|
||||
end
|
||||
|
||||
function StateSeek:Tick()
|
||||
-- Update Game Time
|
||||
GAMEMODE.Data.RoundTime = GAMEMODE.Config.Round:Time() - (CurTime() - GAMEMODE.Data.RoundStartTime)
|
||||
SetGlobalInt("RoundTime", math.ceil(GAMEMODE.Data.RoundTime))
|
||||
|
||||
-- Conditions for moving to the next State
|
||||
if (GAMEMODE.Data.RoundTime <= 0) then -- No Time remaining
|
||||
GAMEMODE.Data.Winner = GAMEMODE.Teams.Hiders
|
||||
GAMEMODE.RoundManager:SetState(StatePostRound)
|
||||
end
|
||||
|
||||
-- Condition: No Seekers / Hiders alive.
|
||||
local hiders, seekers = team.GetPlayers(GAMEMODE.Teams.Hiders), team.GetPlayers(GAMEMODE.Teams.Seekers)
|
||||
local hiderAlive, seekerAlive = false, false
|
||||
for i,ply in ipairs(hiders) do
|
||||
if (ply.Data.Alive) then
|
||||
hiderAlive = true
|
||||
end
|
||||
end
|
||||
for i,ply in ipairs(seekers) do
|
||||
if (ply.Data.Alive) then
|
||||
seekerAlive = true
|
||||
end
|
||||
end
|
||||
if (hiderAlive == false) then
|
||||
if (seekerAlive == false) then
|
||||
GAMEMODE.Data.Winner = GAMEMODE.Teams.Spectators -- Shows as Draw
|
||||
GAMEMODE.RoundManager:SetState(StatePostRound)
|
||||
else
|
||||
GAMEMODE.Data.Winner = GAMEMODE.Teams.Seekers
|
||||
GAMEMODE.RoundManager:SetState(StatePostRound)
|
||||
end
|
||||
else
|
||||
if (seekerAlive == false) then
|
||||
GAMEMODE.Data.Winner = GAMEMODE.Teams.Hiders
|
||||
GAMEMODE.RoundManager:SetState(StatePostRound)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function StateSeek:OnLeave(NewState)
|
||||
if GAMEMODE.Config:Debug() then print("StateSeek: OnLeave") end
|
||||
end
|
||||
-72
@@ -1,23 +1,3 @@
|
||||
if !file.IsDir("prop_hunt", "DATA") then file.CreateDir("prop_hunt") end
|
||||
|
||||
-- These are Models that the Prop team can not become.
|
||||
-- Usually you'd put invisible or impossible to hit models in here.
|
||||
BANNED_PROP_MODELS = {
|
||||
"models/props/cs_assault/dollar.mdl",
|
||||
"models/props/cs_assault/money.mdl",
|
||||
"models/props/cs_office/snowman_arm.mdl",
|
||||
"models/props_junk/garbage_plasticbottle001a.mdl",
|
||||
"models/props/cs_office/projector_remote.mdl"
|
||||
}
|
||||
if (! file.Exists("prop_hunt/banned_props.txt", "DATA")) then
|
||||
file.Write("prop_hunt/banned_props.txt", util.TableToKeyValues(BANNED_PROP_MODELS))
|
||||
end
|
||||
local fileContent = file.Read("prop_hunt/banned_props.txt", "DATA");
|
||||
if fileContent then
|
||||
local fileTable = util.KeyValuesToTable(fileContent)
|
||||
if fileTable then BANNED_PROP_MODELS = fileTable end
|
||||
end
|
||||
|
||||
-- Sounds played by members of the losing team at the end of the round.
|
||||
LOSS_SOUNDS = {
|
||||
"bot/aw_hell.wav",
|
||||
@@ -312,55 +292,3 @@ if fileContent then
|
||||
local fileTable = util.KeyValuesToTable(fileContent)
|
||||
if fileTable then PROP_TAUNTS = fileTable end
|
||||
end
|
||||
|
||||
-- Maximum time (in minutes) for this fretta gamemode (Default: 30)
|
||||
GAME_TIME = math.max(GetConVarNumber("mp_timelimit"),1)
|
||||
|
||||
-- Number of seconds hunters are blinded/locked at the beginning of the map (Default: 30)
|
||||
CreateConVar("HUNTER_BLINDLOCK_TIME", "30", FCVAR_REPLICATED)
|
||||
|
||||
--Create the convars here
|
||||
-- Health points removed from hunters when they shoot (Default: 5)
|
||||
CreateConVar( "HUNTER_FIRE_PENALTY", "5", FCVAR_REPLICATED)
|
||||
|
||||
-- How much health to give back to the Hunter after killing a prop (Default: 20)
|
||||
CreateConVar( "HUNTER_KILL_BONUS", "20", FCVAR_REPLICATED)
|
||||
|
||||
--Whether or not we include grenade launcher ammo (default: 1)
|
||||
CreateConVar( "WEAPONS_ALLOW_GRENADE", "1", FCVAR_REPLICATED)
|
||||
|
||||
-- Seconds a player has to wait before they can taunt again (Default: 5)
|
||||
TAUNT_DELAY = 2
|
||||
|
||||
-- Rounds played on a map (Default: 10)
|
||||
ROUNDS_PER_MAP = 60
|
||||
|
||||
-- Time (in seconds) for each round (Default: 300)
|
||||
ROUND_TIME = 300
|
||||
|
||||
-- Determains if players should be team swapped every round [0 = No, 1 = Yes] (Default: 1)
|
||||
SWAP_TEAMS_EVERY_ROUND = 1
|
||||
|
||||
-- Update above values with values from configuration.
|
||||
if (! file.Exists("prop_hunt/config.txt", "DATA")) then
|
||||
file.Write("prop_hunt/config.txt", util.TableToKeyValues({
|
||||
-- GAME_TIME = 30,
|
||||
TAUNT_DELAY = 2,
|
||||
ROUNDS_PER_MAP = 60,
|
||||
ROUND_TIME = 300,
|
||||
SWAP_TEAM_EVERY_ROUND = 1
|
||||
}))
|
||||
end
|
||||
local fileContent = file.Read("prop_hunt/config.txt", "DATA");
|
||||
if fileContent then
|
||||
local fileTable = util.KeyValuesToTable(fileContent)
|
||||
if fileTable then
|
||||
-- if fileTable.GAME_TIME then GAME_TIME = fileTable.GAME_TIME end
|
||||
if fileTable.TAUNT_DELAY then TAUNT_DELAY = fileTable.TAUNT_DELAY end
|
||||
if fileTable.ROUNDS_PER_MAP then ROUNDS_PER_MAP = fileTable.ROUNDS_PER_MAP end
|
||||
if fileTable.ROUND_TIME then ROUND_TIME = fileTable.ROUND_TIME end
|
||||
if fileTable.SWAP_TEAM_EVERY_ROUND then ROUND_TIME = fileTable.SWAP_TEAM_EVERY_ROUND end
|
||||
end
|
||||
end
|
||||
|
||||
GAME_TIME = math.max(GetConVarNumber("mp_timelimit"),1)
|
||||
@@ -0,0 +1,130 @@
|
||||
--[[
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Xaymar
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
--]]
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Gamemode Information
|
||||
-- ------------------------------------------------------------------------- --
|
||||
GM.Name = "Prop Hunt Extended"
|
||||
GM.Author = "Michael 'Xaymar' Dirks (Based on Kow@lskis Version, Original by AMT)"
|
||||
GM.Email = "michael.fabian.dirks@gmail.com"
|
||||
GM.Website = "http://xaymar.com/"
|
||||
|
||||
GM.TeamBased = true
|
||||
GM.AllowAutoTeam = true
|
||||
GM.SecondsBetweenTeamSwitches = 10
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Includes
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Player Classes
|
||||
include "player_class/class_default.lua"
|
||||
include "player_class/class_spectator.lua"
|
||||
include "player_class/class_seeker.lua"
|
||||
include "player_class/class_hider.lua"
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Code
|
||||
-- ------------------------------------------------------------------------- --
|
||||
-- Game States
|
||||
GM.States = {}
|
||||
GM.States.PreMatch = 0
|
||||
GM.States.PreRound = 1
|
||||
GM.States.Hide = 2
|
||||
GM.States.Seek = 3
|
||||
GM.States.PostRound = 4
|
||||
GM.States.PostMatch = 5
|
||||
|
||||
-- Game Modes
|
||||
GM.Modes = {}
|
||||
GM.Modes.Original = 0
|
||||
GM.Modes.SwizzleEffect = 1 -- Randomizes Teams each Round
|
||||
GM.Modes.TheDeadHunt = 2 -- One Hunter, Dead Prop become Hunter, Props can't see each other.
|
||||
|
||||
-- Teams
|
||||
GM.Teams = {}
|
||||
GM.Teams.Spectators = 0
|
||||
GM.Teams.Seekers = 1
|
||||
GM.Teams.Hiders = 2
|
||||
|
||||
function GM:CreateTeams()
|
||||
-- Specators
|
||||
team.SetUp(self.Teams.Spectators, "Spectators", Color(127, 127, 127, 255))
|
||||
team.SetSpawnPoint(self.Teams.Spectators, {
|
||||
"info_player_deathmatch",
|
||||
"info_player_axis",
|
||||
"info_player_combine",
|
||||
"info_player_counterterrorist",
|
||||
"info_player_allies",
|
||||
"info_player_terrorist"
|
||||
})
|
||||
team.SetClass(self.Teams.Spectators, { "Spectator", "Spectator" })
|
||||
|
||||
-- Seekers: "Hunters"
|
||||
team.SetUp(self.Teams.Seekers, "Seekers", Color(0, 128, 255, 255))
|
||||
team.SetSpawnPoint(self.Teams.Seekers, {
|
||||
"info_player_spawn",
|
||||
"info_player_deathmatch",
|
||||
"info_player_axis",
|
||||
"info_player_combine",
|
||||
"info_player_counterterrorist"
|
||||
})
|
||||
team.SetClass(self.Teams.Seekers, { "Seeker", "Spectator" })
|
||||
|
||||
-- Hiders: "Props"
|
||||
team.SetUp(self.Teams.Hiders, "Hiders", Color(255, 128, 0, 255))
|
||||
team.SetSpawnPoint(self.Teams.Hiders, {
|
||||
"info_player_spawn",
|
||||
"info_player_deathmatch",
|
||||
"info_player_allies",
|
||||
"info_player_terrorist"
|
||||
})
|
||||
team.SetClass(self.Teams.Hiders, { "Hider", "Spectator" })
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Player Manager Binding
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function GM:PlayerPostThink(ply)
|
||||
return player_manager.RunClass(ply, "PostThink")
|
||||
end
|
||||
|
||||
function GM:PlayerTick(ply, mv)
|
||||
return player_manager.RunClass(ply, "Tick", mv)
|
||||
end
|
||||
|
||||
function GM:PlayerHurt(victim, attacker, healthRemaining, damageTaken)
|
||||
if (victim != nil && victim:IsPlayer()) then
|
||||
player_manager.RunClass(victim, "Hurt", victim, attacker, healthRemaining, damageTaken)
|
||||
end
|
||||
if (attacker != nil && attacker:IsPlayer()) then
|
||||
player_manager.RunClass(attacker, "Damage", victim, attacker, healthRemaining, damageTaken)
|
||||
end
|
||||
end
|
||||
|
||||
-- ------------------------------------------------------------------------- --
|
||||
--! Gamemode Functionality
|
||||
-- ------------------------------------------------------------------------- --
|
||||
function GM:GetRoundState()
|
||||
return GetGlobalInt("RoundState", self.States.PreMatch)
|
||||
end
|
||||
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
+65
-79
@@ -1,18 +1,8 @@
|
||||
"xaymars_prop_hunt"
|
||||
"prophuntextended"
|
||||
{
|
||||
"base" "base"
|
||||
"title" "Prop Hunt"
|
||||
"title" "Prop Hunt Extended"
|
||||
"maps" "^ph_|^cs_|^de_|^ttt_"
|
||||
|
||||
"fretta_maps"
|
||||
{
|
||||
"1" "ph_"
|
||||
"2" "cs_"
|
||||
"3" "de_"
|
||||
"4" "ttt_"
|
||||
}
|
||||
"selectable" "1"
|
||||
|
||||
"menusystem" "1"
|
||||
"workshopid" "468149739"
|
||||
|
||||
@@ -20,6 +10,15 @@
|
||||
{
|
||||
// Game Settings
|
||||
1
|
||||
{
|
||||
"name" "ph_gamemode"
|
||||
"text" "G: Game Mode"
|
||||
"help" "0: Basic, 1: Swizzle Effect (Random Teams), 2: The Dead Hunt (One Hunter, Dead Props become Hunters)"
|
||||
"type" "Numeric"
|
||||
"default" "0"
|
||||
}
|
||||
|
||||
2
|
||||
{
|
||||
"name" "mp_timelimit"
|
||||
"text" "G: Time Limit"
|
||||
@@ -28,7 +27,7 @@
|
||||
"default" "20"
|
||||
}
|
||||
|
||||
2
|
||||
3
|
||||
{
|
||||
"name" "ph_sprinting"
|
||||
"text" "G: Enable Sprinting"
|
||||
@@ -37,9 +36,9 @@
|
||||
"default" "0"
|
||||
}
|
||||
|
||||
3
|
||||
4
|
||||
{
|
||||
"name" "ph_tauntwaittime"
|
||||
"name" "ph_tauntcooldown"
|
||||
"text" "G: Taunt Cooldown"
|
||||
"help" "How much time must pass before another taunt may be played."
|
||||
"type" "Numeric"
|
||||
@@ -47,53 +46,35 @@
|
||||
}
|
||||
|
||||
// Round Settings
|
||||
4
|
||||
10
|
||||
{
|
||||
"name" "ph_rounds"
|
||||
"name" "ph_round_limit"
|
||||
"text" "R: Rounds per Map"
|
||||
"help" "How many rounds are played per map."
|
||||
"type" "Numeric"
|
||||
"default" "10"
|
||||
}
|
||||
|
||||
5
|
||||
11
|
||||
{
|
||||
"name" "ph_rounds_time"
|
||||
"name" "ph_round_timelimit"
|
||||
"text" "R: Round Duration (Seconds)"
|
||||
"help" "How long is each round going to last?"
|
||||
"type" "Numeric"
|
||||
"default" "300"
|
||||
}
|
||||
|
||||
6
|
||||
12
|
||||
{
|
||||
"name" "ph_rounds_blindtime"
|
||||
"name" "ph_round_blindtime"
|
||||
"text" "R: Hiding Time (Seconds)"
|
||||
"help" "How long are Seekers blinded in seconds?"
|
||||
"help" "How long are hunters blinded? (positive values will be inside the round time limit, negative will add to the round time limit)"
|
||||
"type" "Numeric"
|
||||
"default" "30"
|
||||
}
|
||||
|
||||
7
|
||||
{
|
||||
"name" "ph_rounds_teams_swap"
|
||||
"text" "R: Swap Teams every round?"
|
||||
"help" "Should teams be swapped every round? (Can't be used with Randomize)"
|
||||
"type" "CheckBox"
|
||||
"default" "1"
|
||||
}
|
||||
|
||||
8
|
||||
{
|
||||
"name" "ph_rounds_teams_randomize"
|
||||
"text" "R: Randomize Teams every round?"
|
||||
"help" "Should teams be randomized every round? (Can't be used with Swap)"
|
||||
"type" "CheckBox"
|
||||
"default" "0"
|
||||
}
|
||||
|
||||
// Seeker Settings
|
||||
9
|
||||
20
|
||||
{
|
||||
"name" "ph_seeker_health"
|
||||
"text" "S: Health"
|
||||
@@ -101,7 +82,7 @@
|
||||
"default" "100"
|
||||
}
|
||||
|
||||
10
|
||||
21
|
||||
{
|
||||
"name" "ph_seeker_health_max"
|
||||
"text" "S: Max Health"
|
||||
@@ -109,58 +90,44 @@
|
||||
"default" "100"
|
||||
}
|
||||
|
||||
11
|
||||
22
|
||||
{
|
||||
"name" "ph_seeker_health_killbonus"
|
||||
"name" "ph_seeker_health_bonus"
|
||||
"text" "S: Health Kill-Bonus"
|
||||
"help" "Health gained on kill."
|
||||
"type" "Numeric"
|
||||
"default" "10"
|
||||
"default" "20"
|
||||
}
|
||||
|
||||
11
|
||||
23
|
||||
{
|
||||
"name" "ph_seeker_health_penalty"
|
||||
"text" "S: Health Penalty"
|
||||
"help" "Health lost on wrong shot."
|
||||
"type" "Numeric"
|
||||
"default" "1"
|
||||
"default" "5"
|
||||
}
|
||||
|
||||
12
|
||||
24
|
||||
{
|
||||
"name" "ph_seeker_ammo_pistol"
|
||||
"text" "S: Ammo for Pistol"
|
||||
"type" "Numeric"
|
||||
"default" "40"
|
||||
"name" "ph_seeker_weapons"
|
||||
"text" "S: Weapons to be given to Seekers"
|
||||
"help" "Format: Weapon,Weapon,..."
|
||||
"type" "Text"
|
||||
"default" "weapon_crowbar,weapon_pistol,weapon_ph_smg,weapon_shotgun,weapon_physcannon"
|
||||
}
|
||||
|
||||
13
|
||||
25
|
||||
{
|
||||
"name" "ph_seeker_ammo_smg"
|
||||
"text" "S: Ammo for SMG"
|
||||
"type" "Numeric"
|
||||
"default" "300"
|
||||
}
|
||||
|
||||
14
|
||||
{
|
||||
"name" "ph_seeker_ammo_smggrenade"
|
||||
"text" "S: Ammo for SMG Grenade"
|
||||
"type" "Numeric"
|
||||
"default" "1"
|
||||
}
|
||||
|
||||
15
|
||||
{
|
||||
"name" "ph_seeker_ammo_shotgun"
|
||||
"text" "S: Ammo for Shotgun"
|
||||
"type" "Numeric"
|
||||
"default" "60"
|
||||
"name" "ph_seeker_ammo"
|
||||
"text" "S: Ammo to give to Seekers"
|
||||
"help" "Format: Name:Amount,Name:Amount,..."
|
||||
"type" "Text"
|
||||
"default" "Pistol:100,SMG1:300,SMG1_Grenade:1,Buckshot:64"
|
||||
}
|
||||
|
||||
// Hider Settings
|
||||
16
|
||||
30
|
||||
{
|
||||
"name" "ph_hider_health"
|
||||
"text" "H: Health"
|
||||
@@ -168,7 +135,7 @@
|
||||
"default" "100"
|
||||
}
|
||||
|
||||
17
|
||||
31
|
||||
{
|
||||
"name" "ph_hider_health_max"
|
||||
"text" "H: Max Health"
|
||||
@@ -176,21 +143,40 @@
|
||||
"default" "100"
|
||||
}
|
||||
|
||||
18
|
||||
32
|
||||
{
|
||||
"name" "ph_hider_health_scale"
|
||||
"name" "ph_hider_health_scaling"
|
||||
"text" "H: Enable Health Scaling"
|
||||
"help" "Larger & heavier objects have more health, smaller less."
|
||||
"type" "CheckBox"
|
||||
"default" "1"
|
||||
}
|
||||
|
||||
19
|
||||
33
|
||||
{
|
||||
"name" "ph_hider_health_scaled_max"
|
||||
"name" "ph_hider_health_scaling_max"
|
||||
"text" "H: Scaled Max Health"
|
||||
"type" "Numeric"
|
||||
"default" "200"
|
||||
}
|
||||
|
||||
// Whitelist & Blacklist
|
||||
40
|
||||
{
|
||||
"name" "ph_list_class_whitelist"
|
||||
"text" "L: Allowed Entity Classes"
|
||||
"help" "Hiders can only use these for changing model and skin."
|
||||
"type" "Text"
|
||||
"default" "ph_prop,prop_physics,prop_physics_multiplayer,prop_physics_respawnable"
|
||||
}
|
||||
|
||||
41
|
||||
{
|
||||
"name" "ph_list_abuse_blacklist"
|
||||
"text" "L: Abuse Blacklist"
|
||||
"help" "Fix interact spam with certain entities so that all areas stay accessible."
|
||||
"type" "Text"
|
||||
"default" ""func_button,func_door,func_door_rotation,prop_door_rotation,func_tracktrain,func_tanktrain,func_breakable""
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
@ECHO OFF
|
||||
:: Retrieve Garry's Mod path from Regristry
|
||||
:: FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
|
||||
SET "GARRYSMODPATH=D:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
|
||||
SET "GARRYSMODPATH=C:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
|
||||
|
||||
SET "PATH=%CD%;%GARRYSMODPATH%\bin;%PATH%"
|
||||
CMD
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
@ECHO OFF
|
||||
:: Fallback
|
||||
SET "GARRYSMODPATH=D:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
|
||||
SET "GARRYSMODPATH=C:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
|
||||
|
||||
:: Retrieve Garry's Mod path from Regristry
|
||||
FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
|
||||
|
||||
"%GARRYSMODPATH%\bin\gmad.exe" create -folder "%CD%/Gamemode" -out "%CD%/Pack.gma"
|
||||
"%GARRYSMODPATH%\bin\gmad.exe" create -folder "%CD%\Source" -out "%CD%\Pack.gma"
|
||||
PAUSE
|
||||
+2
-2
@@ -1,9 +1,9 @@
|
||||
@ECHO OFF
|
||||
:: Fallback
|
||||
SET "GARRYSMODPATH=D:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
|
||||
SET "GARRYSMODPATH=C:\Program Files (x86)\Steam\steamapps\common\GarrysMod"
|
||||
|
||||
:: Retrieve Garry's Mod path from Regristry
|
||||
FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
|
||||
::FOR /F "tokens=2* delims= " %%A IN ('REG QUERY "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\Steam App 4000" /v InstallLocation') DO SET "GARRYSMODPATH=%%B"
|
||||
|
||||
SET /P CHANGES=Changes:
|
||||
"%GARRYSMODPATH%\bin\gmpublish.exe" update -id 468149739 -icon "Logo.jpg" -addon "Pack.gma" -changes "%CHANGES%
|
||||
|
||||
Reference in New Issue
Block a user