It's back bitches!

This commit is contained in:
Michael Fabain Dirks
2016-06-14 07:28:36 +02:00
parent 2d3360ab82
commit d625658c71
48 changed files with 2682 additions and 1760 deletions
+12
View File
@@ -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 -1
View File
@@ -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
--]]
@@ -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,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
@@ -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
@@ -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

@@ -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 -1
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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%