mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-16 13:23:46 +03:00
Upload
This commit is contained in:
5
gamemodes/base/base.txt
Normal file
5
gamemodes/base/base.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
"base"
|
||||
{
|
||||
"title" "Base"
|
||||
"base" ""
|
||||
}
|
||||
49
gamemodes/base/entities/effects/base.lua
Normal file
49
gamemodes/base/entities/effects/base.lua
Normal file
@@ -0,0 +1,49 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Returns the right shoot start position for a tracer - based on 'data'.
|
||||
-----------------------------------------------------------]]
|
||||
function EFFECT:GetTracerShootPos( Position, Ent, Attachment )
|
||||
|
||||
self.ViewModelTracer = false
|
||||
|
||||
if ( !IsValid( Ent ) ) then return Position end
|
||||
if ( !Ent:IsWeapon() ) then return Position end
|
||||
|
||||
-- Shoot from the viewmodel
|
||||
if ( Ent:IsCarriedByLocalPlayer() && !LocalPlayer():ShouldDrawLocalPlayer() ) then
|
||||
|
||||
local ViewModel = LocalPlayer():GetViewModel()
|
||||
|
||||
if ( ViewModel:IsValid() ) then
|
||||
|
||||
local att = ViewModel:GetAttachment( Attachment )
|
||||
if ( att ) then
|
||||
Position = att.Pos
|
||||
self.ViewModelTracer = true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Shoot from the world model
|
||||
else
|
||||
|
||||
local att = Ent:GetAttachment( Attachment )
|
||||
if ( att ) then
|
||||
Position = att.Pos
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return Position
|
||||
|
||||
end
|
||||
65
gamemodes/base/entities/effects/dof_node.lua
Normal file
65
gamemodes/base/entities/effects/dof_node.lua
Normal file
@@ -0,0 +1,65 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
EFFECT.Mat = Material( "pp/dof" )
|
||||
|
||||
function EFFECT:Init( data )
|
||||
|
||||
table.insert( DOF_Ents, self )
|
||||
self.Scale = data:GetScale()
|
||||
|
||||
local size = 32
|
||||
self:SetCollisionBounds( Vector( -size, -size, -size ), Vector( size, size, size ) )
|
||||
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
|
||||
-- If the spacing or offset has changed we need to reconfigure our positions
|
||||
local ply = LocalPlayer()
|
||||
|
||||
self.spacing = DOF_SPACING * self.Scale
|
||||
self.offset = DOF_OFFSET
|
||||
|
||||
-- Just return if it hasn't
|
||||
--if ( spacing == self.spacing && offset == self.offset ) then return true end
|
||||
|
||||
local pos = ply:EyePos()
|
||||
local fwd = ply:EyeAngles():Forward()
|
||||
|
||||
if ( ply:GetViewEntity() != ply ) then
|
||||
pos = ply:GetViewEntity():GetPos()
|
||||
fwd = ply:GetViewEntity():GetForward()
|
||||
end
|
||||
|
||||
pos = pos + ( fwd * self.spacing ) + ( fwd * self.offset )
|
||||
|
||||
self:SetParent( nil )
|
||||
self:SetPos( pos )
|
||||
self:SetParent( ply )
|
||||
|
||||
-- We don't kill this, the pp effect should
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
|
||||
-- Note: UpdateScreenEffectTexture fucks up the water, RefractTexture is lower quality
|
||||
render.UpdateRefractTexture()
|
||||
--render.UpdateScreenEffectTexture()
|
||||
|
||||
local SpriteSize = ( self.spacing + self.offset ) * 8
|
||||
|
||||
render.SetMaterial( self.Mat )
|
||||
render.DrawSprite( self:GetPos(), SpriteSize, SpriteSize, color_white )
|
||||
|
||||
end
|
||||
68
gamemodes/base/entities/effects/tooltracer.lua
Normal file
68
gamemodes/base/entities/effects/tooltracer.lua
Normal file
@@ -0,0 +1,68 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
EFFECT.Mat = Material( "effects/tool_tracer" )
|
||||
|
||||
function EFFECT:Init( data )
|
||||
|
||||
self.Position = data:GetStart()
|
||||
self.WeaponEnt = data:GetEntity()
|
||||
self.Attachment = data:GetAttachment()
|
||||
|
||||
-- Keep the start and end pos - we're going to interpolate between them
|
||||
self.StartPos = self:GetTracerShootPos( self.Position, self.WeaponEnt, self.Attachment )
|
||||
self.EndPos = data:GetOrigin()
|
||||
|
||||
self.Alpha = 255
|
||||
self.Life = 0
|
||||
|
||||
self:SetRenderBoundsWS( self.StartPos, self.EndPos )
|
||||
|
||||
end
|
||||
|
||||
function EFFECT:Think()
|
||||
|
||||
self.Life = self.Life + FrameTime() * 4
|
||||
self.Alpha = 255 * ( 1 - self.Life )
|
||||
|
||||
return self.Life < 1
|
||||
|
||||
end
|
||||
|
||||
function EFFECT:Render()
|
||||
|
||||
if ( self.Alpha < 1 ) then return end
|
||||
|
||||
render.SetMaterial( self.Mat )
|
||||
local texcoord = math.Rand( 0, 1 )
|
||||
|
||||
local norm = ( self.StartPos - self.EndPos ) * self.Life
|
||||
|
||||
self.Length = norm:Length()
|
||||
|
||||
for i = 1, 3 do
|
||||
|
||||
render.DrawBeam( self.StartPos - norm, -- Start
|
||||
self.EndPos, -- End
|
||||
8, -- Width
|
||||
texcoord, -- Start tex coord
|
||||
texcoord + self.Length / 128, -- End tex coord
|
||||
color_white ) -- Color (optional)
|
||||
end
|
||||
|
||||
render.DrawBeam( self.StartPos,
|
||||
self.EndPos,
|
||||
8,
|
||||
texcoord,
|
||||
texcoord + ( ( self.StartPos - self.EndPos ):Length() / 128 ),
|
||||
Color( 255, 255, 255, 128 * ( 1 - self.Life ) ) )
|
||||
|
||||
end
|
||||
20
gamemodes/base/entities/entities/aoc_spawnpoint.lua
Normal file
20
gamemodes/base/entities/entities/aoc_spawnpoint.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
33
gamemodes/base/entities/entities/base_ai/cl_init.lua
Normal file
33
gamemodes/base/entities/entities/base_ai/cl_init.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
include( "shared.lua" )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Draw
|
||||
Desc: Draw it!
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: DrawTranslucent
|
||||
Desc: Draw translucent
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:DrawTranslucent()
|
||||
|
||||
-- This is here just to make it backwards compatible.
|
||||
-- You shouldn't really be drawing your model here unless it's translucent
|
||||
|
||||
self:Draw()
|
||||
|
||||
end
|
||||
147
gamemodes/base/entities/entities/base_ai/init.lua
Normal file
147
gamemodes/base/entities/entities/base_ai/init.lua
Normal file
@@ -0,0 +1,147 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile( "cl_init.lua" )
|
||||
AddCSLuaFile( "shared.lua" )
|
||||
|
||||
include( "shared.lua" )
|
||||
include( "schedules.lua" )
|
||||
include( "tasks.lua" )
|
||||
|
||||
-- Variables
|
||||
|
||||
ENT.m_fMaxYawSpeed = 200 -- Max turning speed
|
||||
ENT.m_iClass = CLASS_CITIZEN_REBEL -- NPC Class
|
||||
|
||||
AccessorFunc( ENT, "m_iClass", "NPCClass" )
|
||||
AccessorFunc( ENT, "m_fMaxYawSpeed", "MaxYawSpeed" )
|
||||
|
||||
function ENT:Initialize()
|
||||
|
||||
-- Some default calls to make the NPC function
|
||||
self:SetModel( "models/alyx.mdl" )
|
||||
self:SetHullType( HULL_HUMAN )
|
||||
self:SetHullSizeNormal()
|
||||
self:SetSolid( SOLID_BBOX )
|
||||
self:SetMoveType( MOVETYPE_STEP )
|
||||
self:CapabilitiesAdd( bit.bor( CAP_MOVE_GROUND, CAP_OPEN_DOORS, CAP_ANIMATEDFACE, CAP_SQUAD, CAP_USE_WEAPONS, CAP_DUCK, CAP_MOVE_SHOOT, CAP_TURN_HEAD, CAP_USE_SHOT_REGULATOR, CAP_AIM_GUN ) )
|
||||
|
||||
self:SetHealth( 100 )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnTakeDamage
|
||||
Desc: Called when the NPC takes damage
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnTakeDamage( dmginfo )
|
||||
|
||||
--[[
|
||||
Msg( tostring(dmginfo) .. "\n" )
|
||||
Msg( "Inflictor:\t" .. tostring(dmginfo:GetInflictor()) .. "\n" )
|
||||
Msg( "Attacker:\t" .. tostring(dmginfo:GetAttacker()) .. "\n" )
|
||||
Msg( "Damage:\t" .. tostring(dmginfo:GetDamage()) .. "\n" )
|
||||
Msg( "Base Damage:\t" .. tostring(dmginfo:GetBaseDamage()) .. "\n" )
|
||||
Msg( "Force:\t" .. tostring(dmginfo:GetDamageForce()) .. "\n" )
|
||||
Msg( "Position:\t" .. tostring(dmginfo:GetDamagePosition()) .. "\n" )
|
||||
Msg( "Reported Pos:\t" .. tostring(dmginfo:GetReportedPosition()) .. "\n" ) -- ??
|
||||
--]]
|
||||
|
||||
-- return 1
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Use
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Use( activator, caller, type, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: StartTouch
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:StartTouch( entity )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: EndTouch
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:EndTouch( entity )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Touch
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Touch( entity )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: GetRelationship
|
||||
Return the relationship between this NPC and the
|
||||
passed entity. If you don't return anything then
|
||||
the default disposition will be used.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:GetRelationship( entity )
|
||||
|
||||
--return D_NU
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: ExpressionFinished
|
||||
Called when an expression has finished. Duh.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:ExpressionFinished( strExp )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnChangeActivity
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnChangeActivity( act )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
|
||||
end
|
||||
|
||||
-- Called to update which sounds the NPC should be able to hear
|
||||
function ENT:GetSoundInterests()
|
||||
-- Hear thumper sound hints
|
||||
-- return 256
|
||||
end
|
||||
|
||||
-- Called when NPC's movement fails
|
||||
function ENT:OnMovementFailed()
|
||||
end
|
||||
|
||||
-- Called when NPC's movement succeeds
|
||||
function ENT:OnMovementComplete()
|
||||
end
|
||||
|
||||
-- Called when the NPC's active weapon changes
|
||||
function ENT:OnActiveWeaponChanged( old, new )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: GetAttackSpread
|
||||
How good is the NPC with this weapon? Return the number
|
||||
of degrees of inaccuracy for the NPC to use.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:GetAttackSpread( Weapon, Target )
|
||||
return 0.1
|
||||
end
|
||||
216
gamemodes/base/entities/entities/base_ai/schedules.lua
Normal file
216
gamemodes/base/entities/entities/base_ai/schedules.lua
Normal file
@@ -0,0 +1,216 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: RunAI - Called from the engine every 0.1 seconds
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:RunAI( strExp )
|
||||
|
||||
-- If we're running an Engine Side behaviour
|
||||
-- then return true and let it get on with it.
|
||||
if ( self:IsRunningBehavior() ) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- If we're doing an engine schedule then return true
|
||||
-- This makes it do the normal AI stuff.
|
||||
if ( self:DoingEngineSchedule() ) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- If we're currently running a schedule then run it.
|
||||
if ( self.CurrentSchedule ) then
|
||||
self:DoSchedule( self.CurrentSchedule )
|
||||
end
|
||||
|
||||
-- If we have no schedule (schedule is finished etc)
|
||||
-- Then get the derived NPC to select what we should be doing
|
||||
if ( !self.CurrentSchedule ) then
|
||||
self:SelectSchedule()
|
||||
end
|
||||
|
||||
-- Do animation system
|
||||
self:MaintainActivity()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SelectSchedule - Set the schedule we should be
|
||||
playing right now.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:SelectSchedule( iNPCState )
|
||||
|
||||
self:SetSchedule( SCHED_IDLE_WANDER )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: StartSchedule - Start a Lua schedule. Not to be
|
||||
confused with SetSchedule which starts an Engine based
|
||||
schedule.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:StartSchedule( schedule )
|
||||
|
||||
self.CurrentSchedule = schedule
|
||||
self.CurrentTaskID = 1
|
||||
self:SetTask( schedule:GetTask( 1 ) )
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: DoSchedule - Runs a Lua schedule.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:DoSchedule( schedule )
|
||||
|
||||
if ( self.CurrentTask ) then
|
||||
self:RunTask( self.CurrentTask )
|
||||
end
|
||||
|
||||
if ( self:TaskFinished() ) then
|
||||
self:NextTask( schedule )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: ScheduleFinished
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:ScheduleFinished()
|
||||
|
||||
self.CurrentSchedule = nil
|
||||
self.CurrentTask = nil
|
||||
self.CurrentTaskID = nil
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: DoSchedule - Set the current task.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:SetTask( task )
|
||||
|
||||
self.CurrentTask = task
|
||||
self.bTaskComplete = false
|
||||
self.TaskStartTime = CurTime()
|
||||
|
||||
self:StartTask( self.CurrentTask )
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: NextTask - Start the next task in specific schedule.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:NextTask( schedule )
|
||||
|
||||
-- Increment task id
|
||||
self.CurrentTaskID = self.CurrentTaskID + 1
|
||||
|
||||
-- If this was the last task then finish up.
|
||||
if ( self.CurrentTaskID > schedule:NumTasks() ) then
|
||||
|
||||
self:ScheduleFinished( schedule )
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
-- Switch to next task
|
||||
self:SetTask( schedule:GetTask( self.CurrentTaskID ) )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: StartTask - called once on starting task
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:StartTask( task )
|
||||
task:Start( self )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: RunTask - called every think on running task.
|
||||
The actual task function should tell us when
|
||||
the task is finished.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:RunTask( task )
|
||||
task:Run( self )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: TaskTime - Returns how many seconds we've been
|
||||
doing this current task
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:TaskTime()
|
||||
return CurTime() - self.TaskStartTime
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnTaskComplete - Called from the engine when
|
||||
TaskComplete is called. This allows us to move
|
||||
onto the next task - even when TaskComplete was
|
||||
called from an engine side task.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnTaskComplete()
|
||||
|
||||
self.bTaskComplete = true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: TaskFinished - Returns true if the current
|
||||
running Task is finished.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:TaskFinished()
|
||||
return self.bTaskComplete
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: StartTask
|
||||
Start the task. You can use this to override engine
|
||||
side tasks. Return true to not run default stuff.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:StartEngineTask( iTaskID, TaskData )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: RunTask
|
||||
Run the task. You can use this to override engine
|
||||
side tasks. Return true to not run default stuff.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:RunEngineTask( iTaskID, TaskData )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
These functions handle the engine schedules
|
||||
When an engine schedule is set the engine calls StartEngineSchedule
|
||||
Then when it's finished it calls EngineScheduleFinishHelp me decide
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:StartEngineSchedule( scheduleID ) self:ScheduleFinished() self.bDoingEngineSchedule = true end
|
||||
function ENT:EngineScheduleFinish() self.bDoingEngineSchedule = nil end
|
||||
function ENT:DoingEngineSchedule() return self.bDoingEngineSchedule end
|
||||
|
||||
function ENT:OnCondition( iCondition )
|
||||
|
||||
--Msg( self, " Condition: ", iCondition, " - ", self:ConditionName(iCondition), "\n" )
|
||||
|
||||
end
|
||||
|
||||
function ENT:TranslateActivity( act )
|
||||
|
||||
-- Return a value to translate the activity to a new one
|
||||
-- if ( act == ACT_WALK ) then return ACT_RUN end
|
||||
|
||||
end
|
||||
54
gamemodes/base/entities/entities/base_ai/shared.lua
Normal file
54
gamemodes/base/entities/entities/base_ai/shared.lua
Normal file
@@ -0,0 +1,54 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "ai"
|
||||
|
||||
ENT.PrintName = "Base SNPC"
|
||||
ENT.Author = ""
|
||||
ENT.Contact = ""
|
||||
ENT.Purpose = ""
|
||||
ENT.Instructions = ""
|
||||
|
||||
ENT.AutomaticFrameAdvance = false
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRemove
|
||||
Desc: Called just before entity is deleted
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRemove()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: PhysicsCollide
|
||||
Desc: Called when physics collides. The table contains
|
||||
data on the collision
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:PhysicsCollide( data, physobj )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: PhysicsUpdate
|
||||
Desc: Called to update the physics .. or something.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:PhysicsUpdate( physobj )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SetAutomaticFrameAdvance
|
||||
Desc: If you're not using animation you should turn this
|
||||
off - it will save lots of bandwidth.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:SetAutomaticFrameAdvance( bUsingAnim )
|
||||
|
||||
self.AutomaticFrameAdvance = bUsingAnim
|
||||
|
||||
end
|
||||
90
gamemodes/base/entities/entities/base_ai/tasks.lua
Normal file
90
gamemodes/base/entities/entities/base_ai/tasks.lua
Normal file
@@ -0,0 +1,90 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Task: PlaySequence
|
||||
|
||||
Accepts:
|
||||
|
||||
data.ID - sequence id
|
||||
data.Name - sequence name (Must provide either id or name)
|
||||
data.Wait - Optional. Should we wait for sequence to finish
|
||||
data.Speed - Optional. Playback speed of sequence
|
||||
data.Loop - Optional. Should the sequence be looped
|
||||
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:TaskStart_PlaySequence( data )
|
||||
|
||||
local SequenceID = data.ID
|
||||
|
||||
if ( data.Name ) then SequenceID = self:LookupSequence( data.Name ) end
|
||||
|
||||
self:ResetSequence( SequenceID )
|
||||
self:SetNPCState( NPC_STATE_SCRIPT )
|
||||
|
||||
local Duration = self:SequenceDuration()
|
||||
|
||||
if ( data.Speed && data.Speed > 0 ) then
|
||||
|
||||
SequenceID = self:SetPlaybackRate( data.Speed )
|
||||
Duration = Duration / data.Speed
|
||||
|
||||
end
|
||||
|
||||
self.TaskSequenceEnd = CurTime() + Duration
|
||||
self.Loop = data.Loop or false
|
||||
|
||||
end
|
||||
|
||||
function ENT:Task_PlaySequence( data )
|
||||
|
||||
-- Wait until sequence is finished
|
||||
if ( CurTime() < self.TaskSequenceEnd or self.Loop ) then return end
|
||||
|
||||
self:TaskComplete()
|
||||
self:SetNPCState( NPC_STATE_NONE )
|
||||
|
||||
-- Clean up
|
||||
self.TaskSequenceEnd = nil
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Task: FindEnemy
|
||||
|
||||
Accepts:
|
||||
|
||||
data.ID - sequence id
|
||||
data.Name - sequence name (Must provide either id or name)
|
||||
data.Wait - Optional. Should we wait for sequence to finish
|
||||
data.Speed - Optional. Playback speed of sequence
|
||||
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:TaskStart_FindEnemy( data )
|
||||
|
||||
for k, v in ipairs( ents.FindInSphere( self:GetPos(), data.Radius or 512 ) ) do
|
||||
|
||||
if ( v:IsValid() && v != self && v:GetClass() == data.Class ) then
|
||||
|
||||
self:SetEnemy( v, true )
|
||||
self:UpdateEnemyMemory( v, v:GetPos() )
|
||||
self:TaskComplete()
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self:SetEnemy( NULL )
|
||||
|
||||
end
|
||||
|
||||
function ENT:Task_FindEnemy( data )
|
||||
end
|
||||
114
gamemodes/base/entities/entities/base_anim.lua
Normal file
114
gamemodes/base/entities/entities/base_anim.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.PrintName = ""
|
||||
ENT.Author = ""
|
||||
ENT.Contact = ""
|
||||
ENT.Purpose = ""
|
||||
ENT.Instructions = ""
|
||||
|
||||
-- Defaulting this to OFF. This will automatically save bandwidth
|
||||
-- on stuff that is already out there, but might break a few things
|
||||
-- that are out there. I'm choosing to break those things because
|
||||
-- there are a lot less of them that are actually using the animtime
|
||||
|
||||
ENT.AutomaticFrameAdvance = false
|
||||
|
||||
function ENT:SetAutomaticFrameAdvance( bUsingAnim )
|
||||
self.AutomaticFrameAdvance = bUsingAnim
|
||||
end
|
||||
|
||||
|
||||
function ENT:OnRemove()
|
||||
end
|
||||
|
||||
|
||||
function ENT:PhysicsCollide( data, physobj )
|
||||
end
|
||||
|
||||
|
||||
function ENT:PhysicsUpdate( physobj )
|
||||
end
|
||||
|
||||
if ( CLIENT ) then
|
||||
|
||||
function ENT:Draw( flags )
|
||||
|
||||
self:DrawModel( flags )
|
||||
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent( flags )
|
||||
|
||||
-- This is here just to make it backwards compatible.
|
||||
-- You shouldn't really be drawing your model here unless it's translucent
|
||||
|
||||
self:Draw( flags )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if ( SERVER ) then
|
||||
|
||||
function ENT:OnTakeDamage( dmginfo )
|
||||
|
||||
--[[
|
||||
Msg( tostring(dmginfo) .. "\n" )
|
||||
Msg( "Inflictor:\t" .. tostring(dmginfo:GetInflictor()) .. "\n" )
|
||||
Msg( "Attacker:\t" .. tostring(dmginfo:GetAttacker()) .. "\n" )
|
||||
Msg( "Damage:\t" .. tostring(dmginfo:GetDamage()) .. "\n" )
|
||||
Msg( "Base Damage:\t" .. tostring(dmginfo:GetBaseDamage()) .. "\n" )
|
||||
Msg( "Force:\t" .. tostring(dmginfo:GetDamageForce()) .. "\n" )
|
||||
Msg( "Position:\t" .. tostring(dmginfo:GetDamagePosition()) .. "\n" )
|
||||
Msg( "Reported Pos:\t" .. tostring(dmginfo:GetReportedPosition()) .. "\n" ) -- ??
|
||||
--]]
|
||||
|
||||
end
|
||||
|
||||
|
||||
function ENT:Use( activator, caller, type, value )
|
||||
end
|
||||
|
||||
|
||||
function ENT:StartTouch( entity )
|
||||
end
|
||||
|
||||
|
||||
function ENT:EndTouch( entity )
|
||||
end
|
||||
|
||||
|
||||
function ENT:Touch( entity )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Simulate
|
||||
Desc: Controls/simulates the physics on the entity.
|
||||
Officially the most complicated callback in the whole mod.
|
||||
Returns 3 variables..
|
||||
1. A SIM_ enum
|
||||
2. A vector representing the linear acceleration/force
|
||||
3. A vector represending the angular acceleration/force
|
||||
If you're doing nothing you can return SIM_NOTHING
|
||||
Note that you need to call ent:StartMotionController to tell the entity
|
||||
to start calling this function..
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:PhysicsSimulate( phys, deltatime )
|
||||
return SIM_NOTHING
|
||||
end
|
||||
|
||||
end
|
||||
66
gamemodes/base/entities/entities/base_brush.lua
Normal file
66
gamemodes/base/entities/entities/base_brush.lua
Normal file
@@ -0,0 +1,66 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "brush"
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Initialize
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Initialize()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: StartTouch
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:StartTouch( entity )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: EndTouch
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:EndTouch( entity )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Touch
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Touch( entity )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: PassesTriggerFilters
|
||||
Desc: Return true if this object should trigger us
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:PassesTriggerFilters( entity )
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: KeyValue
|
||||
Desc: Called when a keyvalue is added to us
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:KeyValue( key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Entity's think function.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRemove
|
||||
Desc: Called just before entity is deleted
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRemove()
|
||||
end
|
||||
34
gamemodes/base/entities/entities/base_entity/cl_init.lua
Normal file
34
gamemodes/base/entities/entities/base_entity/cl_init.lua
Normal file
@@ -0,0 +1,34 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
include( "shared.lua" )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Initialize
|
||||
Desc: First function called. Use to set up your entity
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Initialize()
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Client Think - called every frame
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: Called immediately after a "load"
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
87
gamemodes/base/entities/entities/base_entity/init.lua
Normal file
87
gamemodes/base/entities/entities/base_entity/init.lua
Normal file
@@ -0,0 +1,87 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile( "cl_init.lua" )
|
||||
AddCSLuaFile( "shared.lua" )
|
||||
|
||||
include( "shared.lua" )
|
||||
include( "outputs.lua" )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Initialize
|
||||
Desc: First function called. Use to set up your entity
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Initialize()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: KeyValue
|
||||
Desc: Called when a keyvalue is added to us
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:KeyValue( key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: The game has just been reloaded. This is usually the right place
|
||||
to call the GetNW* functions to restore the script's values.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AcceptInput
|
||||
Desc: Accepts input, return true to override/accept input
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:AcceptInput( name, activator, caller, data )
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: UpdateTransmitState
|
||||
Desc: Set the transmit state
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:UpdateTransmitState()
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Entity's think function.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
--
|
||||
-- Default generic spawn function
|
||||
-- So you don't have to add one your entitie unless you want to.
|
||||
--
|
||||
function ENT:SpawnFunction( ply, tr, ClassName )
|
||||
|
||||
if ( !tr.Hit ) then return end
|
||||
|
||||
local SpawnPos = tr.HitPos + tr.HitNormal * 10
|
||||
local SpawnAng = ply:EyeAngles()
|
||||
SpawnAng.p = 0
|
||||
SpawnAng.y = SpawnAng.y + 180
|
||||
|
||||
local ent = ents.Create( ClassName )
|
||||
ent:SetCreator( ply )
|
||||
ent:SetPos( SpawnPos )
|
||||
ent:SetAngles( SpawnAng )
|
||||
ent:Spawn()
|
||||
ent:Activate()
|
||||
|
||||
ent:DropToFloor()
|
||||
|
||||
return ent
|
||||
|
||||
end
|
||||
133
gamemodes/base/entities/entities/base_entity/outputs.lua
Normal file
133
gamemodes/base/entities/entities/base_entity/outputs.lua
Normal file
@@ -0,0 +1,133 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is called from ENT:KeyValue(key,value) to store the output from
|
||||
-- the map, it could also be called from ENT:AcceptInput I think, so if
|
||||
-- ent_fire addoutput is used, we can store that too (that hasn't been
|
||||
-- tested though).
|
||||
-- Usage: self:StoreOutput("<name of output>","<entities to fire>,<input name>,<param>,<delay>,<times to be used>")
|
||||
-- If called from ENT:KeyValue, then the first parameter is the key, and
|
||||
-- the second is value.
|
||||
function ENT:StoreOutput( name, info )
|
||||
|
||||
-- Newer Source Engine games use this symbol as a delimiter
|
||||
local rawData = string.Explode( "\x1B", info )
|
||||
if ( #rawData < 2 ) then
|
||||
rawData = string.Explode( ",", info )
|
||||
end
|
||||
|
||||
local Output = {}
|
||||
Output.entities = rawData[1] or ""
|
||||
Output.input = rawData[2] or ""
|
||||
Output.param = rawData[3] or ""
|
||||
Output.delay = tonumber( rawData[4] ) or 0
|
||||
Output.times = tonumber( rawData[5] ) or -1
|
||||
|
||||
self.m_tOutputs = self.m_tOutputs or {}
|
||||
self.m_tOutputs[ name ] = self.m_tOutputs[ name ] or {}
|
||||
|
||||
table.insert( self.m_tOutputs[ name ], Output )
|
||||
|
||||
end
|
||||
|
||||
-- This works like SetNetworkKeyValue, call it from ENT:KeyValue and it'll
|
||||
-- return true if it successfully added an output from the passed KV pair.
|
||||
function ENT:AddOutputFromKeyValue( key, value )
|
||||
|
||||
if ( key:sub( 1, 2 ) == "On" ) then
|
||||
|
||||
self:StoreOutput( key, value )
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
-- Call from ENT:AcceptInput and it'll return true if the input was AddOutput
|
||||
-- and if it successfully added an output.
|
||||
-- Note that to be strictly compatible with Source entities, AddOutput should
|
||||
-- allow setting arbitrary keyvalues, but this implementation does not.
|
||||
function ENT:AddOutputFromAcceptInput( name, value )
|
||||
|
||||
if ( name ~= "AddOutput" ) then
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
local pos = string.find( value, " ", 1, true )
|
||||
if ( pos == nil ) then
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
name, value = value:sub( 1, pos - 1 ), value:sub( pos + 1 )
|
||||
|
||||
-- This is literally KeyValue but as an input and with ,s as :s.
|
||||
value = value:gsub( ":", "," )
|
||||
|
||||
return self:AddOutputFromKeyValue( name, value )
|
||||
|
||||
end
|
||||
|
||||
-- Nice helper function, this does all the work. Returns false if the
|
||||
-- output should be removed from the list.
|
||||
local function FireSingleOutput( output, this, activator, data )
|
||||
|
||||
if ( output.times == 0 ) then return false end
|
||||
|
||||
local entitiesToFire = {}
|
||||
|
||||
if ( output.entities == "!activator" ) then
|
||||
entitiesToFire = { activator }
|
||||
elseif ( output.entities == "!self" ) then
|
||||
entitiesToFire = { this }
|
||||
elseif ( output.entities == "!player" ) then
|
||||
entitiesToFire = player.GetAll()
|
||||
else
|
||||
entitiesToFire = ents.FindByName( output.entities )
|
||||
end
|
||||
|
||||
for _, ent in ipairs( entitiesToFire ) do
|
||||
ent:Fire( output.input, data or output.param, output.delay, activator, this )
|
||||
end
|
||||
|
||||
if ( output.times ~= -1 ) then
|
||||
output.times = output.times - 1
|
||||
end
|
||||
|
||||
return ( output.times > 0 ) || ( output.times == -1 )
|
||||
|
||||
end
|
||||
|
||||
-- This function is used to trigger an output.
|
||||
function ENT:TriggerOutput( name, activator, data )
|
||||
|
||||
if ( !self.m_tOutputs ) then return end
|
||||
if ( !self.m_tOutputs[ name ] ) then return end
|
||||
|
||||
local OutputList = self.m_tOutputs[ name ]
|
||||
|
||||
for idx = #OutputList, 1, -1 do
|
||||
|
||||
if ( OutputList[ idx ] and !FireSingleOutput( OutputList[ idx ], self, activator, data ) ) then
|
||||
|
||||
-- Shift the indexes so this loop doesn't fail later
|
||||
table.remove( self.m_tOutputs[ name ], idx )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
16
gamemodes/base/entities/entities/base_entity/shared.lua
Normal file
16
gamemodes/base/entities/entities/base_entity/shared.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
54
gamemodes/base/entities/entities/base_filter.lua
Normal file
54
gamemodes/base/entities/entities/base_filter.lua
Normal file
@@ -0,0 +1,54 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "filter"
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Initialize
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Initialize()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: KeyValue
|
||||
Desc: Called when a keyvalue is added to us
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:KeyValue( key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Entity's think function.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRemove
|
||||
Desc: Called just before entity is deleted
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRemove()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: PassesFilter
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:PassesFilter( trigger, ent )
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: PassesDamageFilter
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:PassesDamageFilter( dmg )
|
||||
return true
|
||||
end
|
||||
64
gamemodes/base/entities/entities/base_nextbot/shared.lua
Normal file
64
gamemodes/base/entities/entities/base_nextbot/shared.lua
Normal file
@@ -0,0 +1,64 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = ""
|
||||
ENT.Author = ""
|
||||
ENT.Contact = ""
|
||||
ENT.Purpose = ""
|
||||
ENT.Instructions = ""
|
||||
|
||||
ENT.Type = "nextbot"
|
||||
|
||||
function ENT:Initialize()
|
||||
end
|
||||
|
||||
if ( SERVER ) then
|
||||
|
||||
--
|
||||
-- All of the AI logic is serverside - so we derive it from a
|
||||
-- specialized class on the server.
|
||||
--
|
||||
include( "sv_nextbot.lua" )
|
||||
|
||||
else
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Draw
|
||||
Desc: Draw it!
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: DrawTranslucent
|
||||
Desc: Draw translucent
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:DrawTranslucent()
|
||||
|
||||
-- This is here just to make it backwards compatible.
|
||||
-- You shouldn't really be drawing your model here unless it's translucent
|
||||
|
||||
self:Draw()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: FireAnimationEvent
|
||||
Desc: Called when an animation event is fired. Return true to suppress
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:FireAnimationEvent( pos, ang, event, options )
|
||||
end
|
||||
|
||||
end
|
||||
425
gamemodes/base/entities/entities/base_nextbot/sv_nextbot.lua
Normal file
425
gamemodes/base/entities/entities/base_nextbot/sv_nextbot.lua
Normal file
@@ -0,0 +1,425 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:BehaveStart
|
||||
-- Desc: Called to initialize the behaviour.\n\n You shouldn't override this - it's used to kick off the coroutine that runs the bot's behaviour. \n\nThis is called automatically when the NPC is created, there should be no need to call it manually.
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:BehaveStart()
|
||||
|
||||
self.BehaveThread = coroutine.create( function() self:RunBehaviour() end )
|
||||
|
||||
end
|
||||
|
||||
function ENT:RunBehaviour()
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:BehaveUpdate
|
||||
-- Desc: Called to update the bot's behaviour
|
||||
-- Arg1: number|interval|How long since the last update
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:BehaveUpdate( fInterval )
|
||||
|
||||
if ( !self.BehaveThread ) then return end
|
||||
|
||||
--
|
||||
-- Give a silent warning to developers if RunBehaviour has returned
|
||||
--
|
||||
if ( coroutine.status( self.BehaveThread ) == "dead" ) then
|
||||
|
||||
self.BehaveThread = nil
|
||||
Msg( self, " Warning: ENT:RunBehaviour() has finished executing\n" )
|
||||
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Continue RunBehaviour's execution
|
||||
--
|
||||
local ok, message = coroutine.resume( self.BehaveThread )
|
||||
if ( ok == false ) then
|
||||
|
||||
self.BehaveThread = nil
|
||||
ErrorNoHalt( self, " Error: ", message, "\n" )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:BodyUpdate
|
||||
-- Desc: Called to update the bot's animation
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:BodyUpdate()
|
||||
|
||||
local act = self:GetActivity()
|
||||
|
||||
--
|
||||
-- This helper function does a lot of useful stuff for us.
|
||||
-- It sets the bot's move_x move_y pose parameters, sets their animation speed relative to the ground speed, and calls FrameAdvance.
|
||||
--
|
||||
if ( act == ACT_RUN || act == ACT_WALK ) then
|
||||
|
||||
self:BodyMoveXY()
|
||||
|
||||
-- BodyMoveXY() already calls FrameAdvance, calling it twice will affect animation playback, specifically on layers
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- If we're not walking or running we probably just want to update the anim system
|
||||
--
|
||||
self:FrameAdvance()
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:OnLeaveGround
|
||||
-- Desc: Called when the bot's feet leave the ground - for whatever reason
|
||||
-- Arg1: Entity|ent|Entity that the NextBot "jumped" from
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:OnLeaveGround( ent )
|
||||
|
||||
--MsgN( "OnLeaveGround", ent )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:OnLeaveGround
|
||||
-- Desc: Called when the bot's feet return to the ground
|
||||
-- Arg1: Entity|ent|Entity that the NextBot landed on
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:OnLandOnGround( ent )
|
||||
|
||||
--MsgN( "OnLandOnGround", ent )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:OnStuck
|
||||
-- Desc: Called when the bot thinks it is stuck
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:OnStuck()
|
||||
|
||||
--MsgN( "OnStuck" )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:OnUnStuck
|
||||
-- Desc: Called when the bot thinks it is un-stuck
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:OnUnStuck()
|
||||
|
||||
--MsgN( "OnUnStuck" )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:OnTakeDamage
|
||||
-- Desc: Called when the bot is about to take damage
|
||||
-- Arg1: CTakeDamageInfo|info|damage info
|
||||
-- Ret1: number|how much damage was taken, prevents default damage code from running
|
||||
--
|
||||
function ENT:OnTakeDamage( damageinfo )
|
||||
|
||||
-- return 0
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:OnInjured
|
||||
-- Desc: Called when the bot gets hurt
|
||||
-- Arg1: CTakeDamageInfo|info|damage info
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:OnInjured( damageinfo )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:OnKilled
|
||||
-- Desc: Called when the bot gets killed
|
||||
-- Arg1: CTakeDamageInfo|info|damage info
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:OnKilled( dmginfo )
|
||||
|
||||
hook.Run( "OnNPCKilled", self, dmginfo:GetAttacker(), dmginfo:GetInflictor() )
|
||||
|
||||
self:BecomeRagdoll( dmginfo )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:OnOtherKilled
|
||||
-- Desc: Called when someone else or something else has been killed
|
||||
-- Arg1: Entity|victim|entity that was killed
|
||||
-- Arg2: CTakeDamageInfo|info|damage info
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:OnOtherKilled( victim, info )
|
||||
|
||||
--MsgN( "OnOtherKilled", victim, info )
|
||||
|
||||
end
|
||||
|
||||
function ENT:OnContact( ent )
|
||||
|
||||
--MsgN( "OnContact", ent )
|
||||
|
||||
end
|
||||
|
||||
function ENT:OnIgnite()
|
||||
|
||||
--MsgN( "OnIgnite" )
|
||||
|
||||
end
|
||||
|
||||
function ENT:OnNavAreaChanged( old, new )
|
||||
|
||||
--MsgN( "OnNavAreaChanged", old, new )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NextBot:FindSpots
|
||||
-- Desc: Returns a table of hiding spots.
|
||||
-- Arg1: table|specs|This table should contain the search info.\n\n * 'type' - the type (either 'hiding')\n * 'pos' - the position to search.\n * 'radius' - the radius to search.\n * 'stepup' - the highest step to step up.\n * 'stepdown' - the highest we can step down without being hurt.
|
||||
-- Ret1: table|An unsorted table of tables containing\n * 'vector' - the position of the hiding spot\n * 'distance' - the distance to that position
|
||||
--
|
||||
function ENT:FindSpots( tbl )
|
||||
|
||||
local tbl = tbl or {}
|
||||
|
||||
tbl.pos = tbl.pos or self:WorldSpaceCenter()
|
||||
tbl.radius = tbl.radius or 1000
|
||||
tbl.stepdown = tbl.stepdown or 20
|
||||
tbl.stepup = tbl.stepup or 20
|
||||
tbl.type = tbl.type or 'hiding'
|
||||
|
||||
-- Use a path to find the length
|
||||
local path = Path( "Follow" )
|
||||
|
||||
-- Find a bunch of areas within this distance
|
||||
local areas = navmesh.Find( tbl.pos, tbl.radius, tbl.stepdown, tbl.stepup )
|
||||
|
||||
local found = {}
|
||||
|
||||
-- In each area
|
||||
for _, area in ipairs( areas ) do
|
||||
|
||||
-- get the spots
|
||||
local spots
|
||||
|
||||
if ( tbl.type == 'hiding' ) then spots = area:GetHidingSpots() end
|
||||
|
||||
for k, vec in ipairs( spots ) do
|
||||
|
||||
-- Work out the length, and add them to a table
|
||||
path:Invalidate()
|
||||
|
||||
path:Compute( self, vec ) -- TODO: This is bullshit - it's using 'self.pos' not tbl.pos
|
||||
|
||||
table.insert( found, { vector = vec, distance = path:GetLength() } )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return found
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NextBot:FindSpot
|
||||
-- Desc: Like FindSpots but only returns a vector
|
||||
-- Arg1: string|type|Either "random", "near", "far"
|
||||
-- Arg2: table|options|A table containing a bunch of tweakable options. See the function definition for more details
|
||||
-- Ret1: vector|If it finds a spot it will return a vector. If not it will return nil.
|
||||
--
|
||||
function ENT:FindSpot( type, options )
|
||||
|
||||
local spots = self:FindSpots( options )
|
||||
if ( !spots || #spots == 0 ) then return end
|
||||
|
||||
if ( type == "near" ) then
|
||||
|
||||
table.SortByMember( spots, "distance", true )
|
||||
return spots[1].vector
|
||||
|
||||
end
|
||||
|
||||
if ( type == "far" ) then
|
||||
|
||||
table.SortByMember( spots, "distance", false )
|
||||
return spots[1].vector
|
||||
|
||||
end
|
||||
|
||||
-- random
|
||||
return spots[ math.random( 1, #spots ) ].vector
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NextBot:HandleStuck
|
||||
-- Desc: Called from Lua when the NPC is stuck. This should only be called from the behaviour coroutine - so if you want to override this function and do something special that yields - then go for it.\n\nYou should always call self.loco:ClearStuck() in this function to reset the stuck status - so it knows it's unstuck.
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:HandleStuck()
|
||||
|
||||
--
|
||||
-- Clear the stuck status
|
||||
--
|
||||
self.loco:ClearStuck()
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NextBot:MoveToPos
|
||||
-- Desc: To be called in the behaviour coroutine only! Will yield until the bot has reached the goal or is stuck
|
||||
-- Arg1: Vector|pos|The position we want to get to
|
||||
-- Arg2: table|options|A table containing a bunch of tweakable options. See the function definition for more details
|
||||
-- Ret1: string|Either "failed", "stuck", "timeout" or "ok" - depending on how the NPC got on
|
||||
--
|
||||
function ENT:MoveToPos( pos, options )
|
||||
|
||||
local options = options or {}
|
||||
|
||||
local path = Path( "Follow" )
|
||||
path:SetMinLookAheadDistance( options.lookahead or 300 )
|
||||
path:SetGoalTolerance( options.tolerance or 20 )
|
||||
path:Compute( self, pos )
|
||||
|
||||
if ( !path:IsValid() ) then return "failed" end
|
||||
|
||||
while ( path:IsValid() ) do
|
||||
|
||||
path:Update( self )
|
||||
|
||||
-- Draw the path (only visible on listen servers or single player)
|
||||
if ( options.draw ) then
|
||||
path:Draw()
|
||||
end
|
||||
|
||||
-- If we're stuck then call the HandleStuck function and abandon
|
||||
if ( self.loco:IsStuck() ) then
|
||||
|
||||
self:HandleStuck()
|
||||
|
||||
return "stuck"
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- If they set maxage on options then make sure the path is younger than it
|
||||
--
|
||||
if ( options.maxage ) then
|
||||
if ( path:GetAge() > options.maxage ) then return "timeout" end
|
||||
end
|
||||
|
||||
--
|
||||
-- If they set repath then rebuild the path every x seconds
|
||||
--
|
||||
if ( options.repath ) then
|
||||
if ( path:GetAge() > options.repath ) then path:Compute( self, pos ) end
|
||||
end
|
||||
|
||||
coroutine.yield()
|
||||
|
||||
end
|
||||
|
||||
return "ok"
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NextBot:PlaySequenceAndWait
|
||||
-- Desc: To be called in the behaviour coroutine only! Plays an animation sequence and waits for it to end before returning.
|
||||
-- Arg1: string|name|The sequence name
|
||||
-- Arg2: number|the speed (default 1)
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:PlaySequenceAndWait( name, speed )
|
||||
|
||||
local len = self:SetSequence( name )
|
||||
speed = speed or 1
|
||||
|
||||
self:ResetSequenceInfo()
|
||||
self:SetCycle( 0 )
|
||||
self:SetPlaybackRate( speed )
|
||||
|
||||
-- wait for it to finish
|
||||
coroutine.wait( len / speed )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:Use
|
||||
-- Desc: Called when a player 'uses' the entity
|
||||
-- Arg1: entity|activator|The entity that activated the use
|
||||
-- Arg2: entity|called|The entity that called the use
|
||||
-- Arg3: number|type|The type of use (USE_ON, USE_OFF, USE_TOGGLE, USE_SET)
|
||||
-- Arg4: number|value|Any passed value
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:Use( activator, caller, type, value )
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:Think
|
||||
-- Desc: Called periodically
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:HandleAnimEvent
|
||||
-- Desc: Called for serverside events
|
||||
--
|
||||
function ENT:HandleAnimEvent( event, eventtime, cycle, typee, options )
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: NEXTBOT:OnTraceAttack
|
||||
-- Desc: Called serverside when the nextbot is attacked
|
||||
--
|
||||
function ENT:OnTraceAttack( dmginfo, dir, trace )
|
||||
|
||||
hook.Run( "ScaleNPCDamage", self, trace.HitGroup, dmginfo )
|
||||
|
||||
end
|
||||
|
||||
-- Called when we see a player or another nextbot
|
||||
function ENT:OnEntitySight( subject )
|
||||
end
|
||||
|
||||
-- Called when we see lose sight of a player or a nextbot we saw earlier
|
||||
function ENT:OnEntitySightLost( subject )
|
||||
end
|
||||
55
gamemodes/base/entities/entities/base_point.lua
Normal file
55
gamemodes/base/entities/entities/base_point.lua
Normal file
@@ -0,0 +1,55 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "point"
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Initialize
|
||||
Desc: First function called. Use to set up your entity
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Initialize()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: KeyValue
|
||||
Desc: Called when a keyvalue is added to us
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:KeyValue( key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Entity's think function.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: OnRemove
|
||||
-- Desc: Called just before entity is deleted
|
||||
--
|
||||
function ENT:OnRemove()
|
||||
end
|
||||
|
||||
--
|
||||
-- UpdateTransmitState
|
||||
--
|
||||
function ENT:UpdateTransmitState()
|
||||
|
||||
--
|
||||
-- The default behaviour for point entities is to not be networked.
|
||||
-- If you're deriving an entity and want it to appear clientside, override this
|
||||
-- TRANSMIT_ALWAYS = always send, TRANSMIT_PVS = send if in PVS
|
||||
--
|
||||
return TRANSMIT_NEVER
|
||||
|
||||
end
|
||||
20
gamemodes/base/entities/entities/diprip_start_team_blue.lua
Normal file
20
gamemodes/base/entities/entities/diprip_start_team_blue.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/diprip_start_team_red.lua
Normal file
20
gamemodes/base/entities/entities/diprip_start_team_red.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/dys_spawn_point.lua
Normal file
20
gamemodes/base/entities/entities/dys_spawn_point.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
142
gamemodes/base/entities/entities/env_skypaint.lua
Normal file
142
gamemodes/base/entities/entities/env_skypaint.lua
Normal file
@@ -0,0 +1,142 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "point"
|
||||
ENT.DisableDuplicator = true
|
||||
|
||||
--
|
||||
-- Make this entity always networked
|
||||
--
|
||||
function ENT:UpdateTransmitState() return TRANSMIT_ALWAYS end
|
||||
|
||||
--
|
||||
-- Networked / Saved Data
|
||||
--
|
||||
function ENT:SetupDataTables()
|
||||
|
||||
self:NetworkVar( "Vector", 0, "TopColor", { KeyName = "topcolor", Edit = { type = "VectorColor", category = "Main", order = 1 } } )
|
||||
self:NetworkVar( "Vector", 1, "BottomColor", { KeyName = "bottomcolor", Edit = { type = "VectorColor", category = "Main", title = "Color Bottom", order = 2 } } )
|
||||
self:NetworkVar( "Float", 0, "FadeBias", { KeyName = "fadebias", Edit = { type = "Float", category = "Main", min = 0, max = 1, order = 3 } } )
|
||||
|
||||
self:NetworkVar( "Float", 4, "SunSize", { KeyName = "sunsize", Edit = { type = "Float", min = 0, max = 10, category = "Sun" } } )
|
||||
self:NetworkVar( "Vector", 2, "SunNormal", { KeyName = "sunnormal" } ) -- No editing this - it's for coders only
|
||||
self:NetworkVar( "Vector", 3, "SunColor", { KeyName = "suncolor", Edit = { type = "VectorColor", category = "Sun" } } )
|
||||
|
||||
self:NetworkVar( "Float", 2, "DuskScale", { KeyName = "duskscale", Edit = { type = "Float", min = 0, max = 1, category = "Dusk" } } )
|
||||
self:NetworkVar( "Float", 3, "DuskIntensity", { KeyName = "duskintensity", Edit = { type = "Float", min = 0, max = 10, category = "Dusk" } } )
|
||||
self:NetworkVar( "Vector", 4, "DuskColor", { KeyName = "duskcolor", Edit = { type = "VectorColor", category = "Dusk" } } )
|
||||
|
||||
self:NetworkVar( "Bool", 0, "DrawStars", { KeyName = "drawstars", Edit = { type = "Boolean", category = "Stars", order = 10 } } )
|
||||
self:NetworkVar( "String", 0, "StarTexture", { KeyName = "startexture", Edit = { type = "Texture", group = "Stars", category = "Stars", order = 11 } } )
|
||||
|
||||
self:NetworkVar( "Int", 0, "StarLayers", { KeyName = "starlayers", Edit = { type = "Int", min = 1, max = 3, category = "Stars", order = 12 } } )
|
||||
self:NetworkVarElement( "Angle", 0, 'p', "StarScale", { KeyName = "starscale", Edit = { type = "Float", min = 0, max = 5, category = "Stars", order = 13 } } )
|
||||
self:NetworkVarElement( "Angle", 0, 'y', "StarFade", { KeyName = "starfade", Edit = { type = "Float", min = 0, max = 5, category = "Stars", order = 14 } } )
|
||||
self:NetworkVarElement( "Angle", 0, 'r', "StarSpeed", { KeyName = "starspeed", Edit = { type = "Float", min = 0, max = 2, category = "Stars", order = 15 } } )
|
||||
|
||||
self:NetworkVar( "Float", 1, "HDRScale", { KeyName = "hdrscale", Edit = { type = "Float", category = "Main", min = 0, max = 1, order = 4 } } )
|
||||
|
||||
--
|
||||
-- Entity defaults
|
||||
--
|
||||
if ( SERVER ) then
|
||||
|
||||
self:SetTopColor( Vector( 0.2, 0.5, 1.0 ) )
|
||||
self:SetBottomColor( Vector( 0.8, 1.0, 1.0 ) )
|
||||
self:SetFadeBias( 1 )
|
||||
|
||||
self:SetSunNormal( Vector( 0.4, 0.0, 0.01 ) )
|
||||
self:SetSunColor( Vector( 0.2, 0.1, 0.0 ) )
|
||||
self:SetSunSize( 2.0 )
|
||||
|
||||
self:SetDuskColor( Vector( 1.0, 0.2, 0.0 ) )
|
||||
self:SetDuskScale( 1 )
|
||||
self:SetDuskIntensity( 1 )
|
||||
|
||||
self:SetDrawStars( true )
|
||||
self:SetStarLayers( 1 )
|
||||
self:SetStarSpeed( 0.01 )
|
||||
self:SetStarScale( 0.5 )
|
||||
self:SetStarFade( 1.5 )
|
||||
self:SetStarTexture( "skybox/starfield" )
|
||||
|
||||
self:SetHDRScale( 0.66 )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
end
|
||||
|
||||
function ENT:KeyValue( key, value )
|
||||
|
||||
if ( self:SetNetworkKeyValue( key, value ) ) then
|
||||
return
|
||||
end
|
||||
|
||||
-- TODO: sunposmethod
|
||||
-- 0 : "Custom - Use the Sun Normal to position the sun"
|
||||
-- 1 : "Automatic - Find a env_sun entity and use that"
|
||||
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
--
|
||||
-- Find an env_sun - if we don't already have one.
|
||||
--
|
||||
if ( SERVER && self.EnvSun == nil ) then
|
||||
|
||||
-- so this closure only gets called once - even if it fails
|
||||
self.EnvSun = false
|
||||
|
||||
local sunlist = ents.FindByClass( "env_sun" )
|
||||
if ( #sunlist > 0 ) then
|
||||
self.EnvSun = sunlist[1]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- If we have a sun - force our sun normal to its value
|
||||
--
|
||||
if ( SERVER && IsValid( self.EnvSun ) ) then
|
||||
|
||||
local vec = self.EnvSun:GetInternalVariable( "m_vDirection" )
|
||||
|
||||
if ( isvector( vec ) ) then
|
||||
self:SetSunNormal( vec )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Become the active sky again if we're not already
|
||||
--
|
||||
if ( CLIENT && g_SkyPaint != self && !IsValid( g_SkyPaint ) ) then
|
||||
|
||||
g_SkyPaint = self
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- To prevent server insanity - only let admins edit the sky.
|
||||
--
|
||||
function ENT:CanEditVariables( ply )
|
||||
|
||||
return ply:IsAdmin() || game.SinglePlayer()
|
||||
|
||||
end
|
||||
77
gamemodes/base/entities/entities/gmod_hands.lua
Normal file
77
gamemodes/base/entities/entities/gmod_hands.lua
Normal file
@@ -0,0 +1,77 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.RenderGroup = RENDERGROUP_OTHER
|
||||
|
||||
function ENT:Initialize()
|
||||
|
||||
hook.Add( "OnViewModelChanged", self, self.ViewModelChanged )
|
||||
|
||||
self:SetNotSolid( true )
|
||||
self:DrawShadow( false )
|
||||
self:SetTransmitWithParent( true ) -- Transmit only when the viewmodel does!
|
||||
|
||||
end
|
||||
|
||||
function ENT:DoSetup( ply, spec )
|
||||
|
||||
-- Set these hands to the player
|
||||
ply:SetHands( self )
|
||||
self:SetOwner( ply )
|
||||
|
||||
-- Which hands should we use? Let the gamemode decide
|
||||
hook.Call( "PlayerSetHandsModel", GAMEMODE, spec or ply, self )
|
||||
|
||||
-- Attach them to the viewmodel
|
||||
local vm = ( spec or ply ):GetViewModel( 0 )
|
||||
self:AttachToViewmodel( vm )
|
||||
|
||||
vm:DeleteOnRemove( self )
|
||||
ply:DeleteOnRemove( self )
|
||||
|
||||
end
|
||||
|
||||
function ENT:GetPlayerColor()
|
||||
|
||||
--
|
||||
-- Make sure there's an owner and they have this function
|
||||
-- before trying to call it!
|
||||
--
|
||||
local owner = self:GetOwner()
|
||||
if ( !IsValid( owner ) ) then return end
|
||||
if ( !owner.GetPlayerColor ) then return end
|
||||
|
||||
return owner:GetPlayerColor()
|
||||
|
||||
end
|
||||
|
||||
function ENT:ViewModelChanged( vm, old, new )
|
||||
|
||||
-- Ignore other peoples viewmodel changes!
|
||||
if ( vm:GetOwner() != self:GetOwner() ) then return end
|
||||
|
||||
self:AttachToViewmodel( vm )
|
||||
|
||||
end
|
||||
|
||||
function ENT:AttachToViewmodel( vm )
|
||||
|
||||
self:AddEffects( EF_BONEMERGE )
|
||||
self:SetParent( vm )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
|
||||
self:SetPos( vector_origin )
|
||||
self:SetAngles( angle_zero )
|
||||
|
||||
end
|
||||
91
gamemodes/base/entities/entities/gmod_player_start.lua
Normal file
91
gamemodes/base/entities/entities/gmod_player_start.lua
Normal file
@@ -0,0 +1,91 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
|
||||
function ENT:Initialize()
|
||||
|
||||
if ( self.RedTeam or self.GreenTeam or self.YellowTeam or self.BlueTeam ) then
|
||||
|
||||
-- If any of these are set to true then
|
||||
-- make sure that any that aren't setup are
|
||||
-- set to false.
|
||||
|
||||
self.BlueTeam = self.BlueTeam or false
|
||||
self.GreenTeam = self.GreenTeam or false
|
||||
self.YellowTeam = self.YellowTeam or false
|
||||
self.RedTeam = self.RedTeam or false
|
||||
|
||||
else
|
||||
|
||||
-- If none are set then make it so that they all
|
||||
-- are set to true since any team can spawn here.
|
||||
-- This will also happen if we don't have the "spawnflags"
|
||||
-- keyvalue setup.
|
||||
|
||||
self.BlueTeam = true
|
||||
self.GreenTeam = true
|
||||
self.YellowTeam = true
|
||||
self.RedTeam = true
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:KeyValue( key, value )
|
||||
|
||||
if ( key == "spawnflags" ) then
|
||||
|
||||
local sf = tonumber( value )
|
||||
|
||||
for i = 15, 0, -1 do
|
||||
|
||||
local bit = math.pow( 2, i )
|
||||
|
||||
-- Quick bit if bitwise math to figure out if the spawnflags
|
||||
-- represent red/blue/green or yellow.
|
||||
-- We have to use booleans since the TEAM_ identifiers
|
||||
-- aren't setup at this point.
|
||||
-- (this would be easier if we had bitwise operators in Lua)
|
||||
|
||||
if ( ( sf - bit ) >= 0 ) then
|
||||
|
||||
if ( bit == 8 ) then self.RedTeam = true
|
||||
elseif ( bit == 4 ) then self.GreenTeam = true
|
||||
elseif ( bit == 2 ) then self.YellowTeam = true
|
||||
elseif ( bit == 1 ) then self.BlueTeam = true
|
||||
end
|
||||
|
||||
sf = sf - bit
|
||||
|
||||
else
|
||||
|
||||
if ( bit == 8 ) then self.RedTeam = false
|
||||
elseif ( bit == 4 ) then self.GreenTeam = false
|
||||
elseif ( bit == 2 ) then self.YellowTeam = false
|
||||
elseif ( bit == 1 ) then self.BlueTeam = false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
20
gamemodes/base/entities/entities/info_player_allies.lua
Normal file
20
gamemodes/base/entities/entities/info_player_allies.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_axis.lua
Normal file
20
gamemodes/base/entities/entities/info_player_axis.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_blue.lua
Normal file
20
gamemodes/base/entities/entities/info_player_blue.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_coop.lua
Normal file
20
gamemodes/base/entities/entities/info_player_coop.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_deathmatch.lua
Normal file
20
gamemodes/base/entities/entities/info_player_deathmatch.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_desperado.lua
Normal file
20
gamemodes/base/entities/entities/info_player_desperado.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_fof.lua
Normal file
20
gamemodes/base/entities/entities/info_player_fof.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_human.lua
Normal file
20
gamemodes/base/entities/entities/info_player_human.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_knight.lua
Normal file
20
gamemodes/base/entities/entities/info_player_knight.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_pirate.lua
Normal file
20
gamemodes/base/entities/entities/info_player_pirate.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_red.lua
Normal file
20
gamemodes/base/entities/entities/info_player_red.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_terrorist.lua
Normal file
20
gamemodes/base/entities/entities/info_player_terrorist.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_vigilante.lua
Normal file
20
gamemodes/base/entities/entities/info_player_vigilante.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_viking.lua
Normal file
20
gamemodes/base/entities/entities/info_player_viking.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_player_zombie.lua
Normal file
20
gamemodes/base/entities/entities/info_player_zombie.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_spawnpoint.lua
Normal file
20
gamemodes/base/entities/entities/info_spawnpoint.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_survivor_position.lua
Normal file
20
gamemodes/base/entities/entities/info_survivor_position.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/info_survivor_rescue.lua
Normal file
20
gamemodes/base/entities/entities/info_survivor_rescue.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
20
gamemodes/base/entities/entities/ins_spawnpoint.lua
Normal file
20
gamemodes/base/entities/entities/ins_spawnpoint.lua
Normal file
@@ -0,0 +1,20 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- This is just a simple point entity.
|
||||
|
||||
-- We only use it to represent the position and angle of a spawn point
|
||||
-- So we don't have to do anything here because the baseclass will
|
||||
-- take care of the basics
|
||||
|
||||
-- This file only exists so that the entity is created
|
||||
|
||||
ENT.Type = "point"
|
||||
73
gamemodes/base/entities/entities/lua_run.lua
Normal file
73
gamemodes/base/entities/entities/lua_run.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- A spawnflag constant for addons
|
||||
SF_LUA_RUN_ON_SPAWN = 1
|
||||
|
||||
ENT.Type = "point"
|
||||
ENT.DisableDuplicator = true
|
||||
|
||||
AccessorFunc( ENT, "m_bDefaultCode", "DefaultCode" )
|
||||
|
||||
function ENT:Initialize()
|
||||
|
||||
-- If the entity has its first spawnflag set, run the code automatically
|
||||
if ( self:HasSpawnFlags( SF_LUA_RUN_ON_SPAWN ) ) then
|
||||
self:RunCode( self, self, self:GetDefaultCode() )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:KeyValue( key, value )
|
||||
|
||||
if ( key == "Code" ) then
|
||||
self:SetDefaultCode( value )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:SetupGlobals( activator, caller )
|
||||
|
||||
ACTIVATOR = activator
|
||||
CALLER = caller
|
||||
|
||||
if ( IsValid( activator ) && activator:IsPlayer() ) then
|
||||
TRIGGER_PLAYER = activator
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:KillGlobals()
|
||||
|
||||
ACTIVATOR = nil
|
||||
CALLER = nil
|
||||
TRIGGER_PLAYER = nil
|
||||
|
||||
end
|
||||
|
||||
function ENT:RunCode( activator, caller, code )
|
||||
|
||||
self:SetupGlobals( activator, caller )
|
||||
|
||||
RunString( code, "lua_run#" .. self:EntIndex() )
|
||||
|
||||
self:KillGlobals()
|
||||
|
||||
end
|
||||
|
||||
function ENT:AcceptInput( name, activator, caller, data )
|
||||
|
||||
if ( name == "RunCode" ) then self:RunCode( activator, caller, self:GetDefaultCode() ) return true end
|
||||
if ( name == "RunPassedCode" ) then self:RunCode( activator, caller, data ) return true end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
82
gamemodes/base/entities/entities/npc_tf2_ghost.lua
Normal file
82
gamemodes/base/entities/entities/npc_tf2_ghost.lua
Normal file
@@ -0,0 +1,82 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "base_nextbot"
|
||||
ENT.Spawnable = false
|
||||
|
||||
function ENT:Initialize()
|
||||
|
||||
--self:SetModel( "models/props_halloween/ghost_no_hat.mdl" )
|
||||
--self:SetModel( "models/props_wasteland/controlroom_filecabinet002a.mdl" )
|
||||
self:SetModel( "models/mossman.mdl" )
|
||||
|
||||
end
|
||||
|
||||
function ENT:RunBehaviour()
|
||||
|
||||
while ( true ) do
|
||||
|
||||
self:StartActivity( ACT_WALK ) -- walk anims
|
||||
self.loco:SetDesiredSpeed( 100 ) -- walk speeds
|
||||
|
||||
-- Choose a random location within 400 units of our position
|
||||
local targetPos = self:GetPos() + Vector( math.Rand( -1, 1 ), math.Rand( -1, 1 ), 0 ) * 400
|
||||
|
||||
-- Search for walkable space there, or nearby
|
||||
local area = navmesh.GetNearestNavArea( targetPos )
|
||||
|
||||
-- We found walkable space, get the closest point on that area to where we want to be
|
||||
if ( IsValid( area ) ) then targetPos = area:GetClosestPointOnArea( targetPos ) end
|
||||
|
||||
-- walk to the target place (yielding)
|
||||
self:MoveToPos( targetPos )
|
||||
|
||||
self:StartActivity( ACT_IDLE ) -- revert to idle activity
|
||||
|
||||
self:PlaySequenceAndWait( "idle_to_sit_ground" ) -- Sit on the floor
|
||||
self:SetSequence( "sit_ground" ) -- Stay sitting
|
||||
coroutine.wait( self:PlayScene( "scenes/eli_lab/mo_gowithalyx01.vcd" ) ) -- play a scene and wait for it to finish before progressing
|
||||
self:PlaySequenceAndWait( "sit_ground_to_idle" ) -- Get up
|
||||
|
||||
-- find the furthest away hiding spot
|
||||
local pos = self:FindSpot( "random", { type = "hiding", radius = 5000 } )
|
||||
|
||||
-- if the position is valid
|
||||
if ( pos ) then
|
||||
self:StartActivity( ACT_RUN ) -- run anim
|
||||
self.loco:SetDesiredSpeed( 200 ) -- run speed
|
||||
self:PlayScene( "scenes/npc/female01/watchout.vcd" ) -- shout something while we run just for a laugh
|
||||
self:MoveToPos( pos ) -- move to position (yielding)
|
||||
self:PlaySequenceAndWait( "fear_reaction" ) -- play a fear animation
|
||||
self:StartActivity( ACT_IDLE ) -- when we finished, go into the idle anim
|
||||
else
|
||||
|
||||
-- some activity to signify that we didn't find shit
|
||||
|
||||
end
|
||||
|
||||
coroutine.yield()
|
||||
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- List the NPC as spawnable
|
||||
--
|
||||
list.Set( "NPC", "npc_tf2_ghost", {
|
||||
Name = "Example NPC",
|
||||
Class = "npc_tf2_ghost",
|
||||
Category = "Nextbot"
|
||||
} )
|
||||
188
gamemodes/base/entities/entities/prop_effect.lua
Normal file
188
gamemodes/base/entities/entities/prop_effect.lua
Normal file
@@ -0,0 +1,188 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
if ( CLIENT ) then
|
||||
CreateConVar( "cl_draweffectrings", "1", 0, "Should the green effect rings be visible?" )
|
||||
end
|
||||
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
|
||||
function ENT:Initialize()
|
||||
|
||||
local Radius = 6
|
||||
local mins = Vector( 1, 1, 1 ) * Radius * -0.5
|
||||
local maxs = Vector( 1, 1, 1 ) * Radius * 0.5
|
||||
|
||||
if ( SERVER ) then
|
||||
|
||||
self.AttachedEntity = ents.Create( "prop_dynamic" )
|
||||
self.AttachedEntity:SetModel( self:GetModel() )
|
||||
self.AttachedEntity:SetAngles( self:GetAngles() )
|
||||
self.AttachedEntity:SetPos( self:GetPos() )
|
||||
self.AttachedEntity:SetSkin( self:GetSkin() )
|
||||
self.AttachedEntity:Spawn()
|
||||
self.AttachedEntity:SetParent( self )
|
||||
self.AttachedEntity:DrawShadow( false )
|
||||
|
||||
self:SetModel( "models/props_junk/watermelon01.mdl" )
|
||||
|
||||
self:DeleteOnRemove( self.AttachedEntity )
|
||||
self.AttachedEntity:DeleteOnRemove( self )
|
||||
|
||||
-- Don't use the model's physics - create a box instead
|
||||
self:PhysicsInitBox( mins, maxs )
|
||||
self:SetSolid( SOLID_VPHYSICS )
|
||||
|
||||
-- Set up our physics object here
|
||||
local phys = self:GetPhysicsObject()
|
||||
if ( IsValid( phys ) ) then
|
||||
phys:Wake()
|
||||
phys:EnableGravity( false )
|
||||
phys:EnableDrag( false )
|
||||
end
|
||||
|
||||
self:DrawShadow( false )
|
||||
self:SetCollisionGroup( COLLISION_GROUP_WEAPON )
|
||||
|
||||
else
|
||||
|
||||
-- So addons can override this
|
||||
self.GripMaterial = Material( "sprites/grip" )
|
||||
self.GripMaterialHover = Material( "sprites/grip_hover" )
|
||||
|
||||
-- Get the attached entity so that clientside functions like properties can interact with it
|
||||
local tab = ents.FindByClassAndParent( "prop_dynamic", self )
|
||||
if ( tab && IsValid( tab[ 1 ] ) ) then self.AttachedEntity = tab[ 1 ] end
|
||||
|
||||
end
|
||||
|
||||
-- Set collision bounds exactly
|
||||
self:SetCollisionBounds( mins, maxs )
|
||||
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
|
||||
if ( halo.RenderedEntity() == self ) then
|
||||
self.AttachedEntity:DrawModel()
|
||||
return
|
||||
end
|
||||
|
||||
if ( GetConVarNumber( "cl_draweffectrings" ) == 0 ) then return end
|
||||
|
||||
-- Don't draw the grip if there's no chance of us picking it up
|
||||
local ply = LocalPlayer()
|
||||
local wep = ply:GetActiveWeapon()
|
||||
if ( !IsValid( wep ) ) then return end
|
||||
|
||||
local weapon_name = wep:GetClass()
|
||||
|
||||
if ( weapon_name != "weapon_physgun" && weapon_name != "weapon_physcannon" && weapon_name != "gmod_tool" ) then
|
||||
return
|
||||
end
|
||||
|
||||
if ( self:BeingLookedAtByLocalPlayer() ) then
|
||||
render.SetMaterial( self.GripMaterialHover )
|
||||
else
|
||||
render.SetMaterial( self.GripMaterial )
|
||||
end
|
||||
|
||||
render.DrawSprite( self:GetPos(), 16, 16, color_white )
|
||||
|
||||
end
|
||||
|
||||
-- Copied from base_gmodentity.lua
|
||||
ENT.MaxWorldTipDistance = 256
|
||||
function ENT:BeingLookedAtByLocalPlayer()
|
||||
local ply = LocalPlayer()
|
||||
if ( !IsValid( ply ) ) then return false end
|
||||
|
||||
local view = ply:GetViewEntity()
|
||||
local dist = self.MaxWorldTipDistance
|
||||
dist = dist * dist
|
||||
|
||||
-- If we're spectating a player, perform an eye trace
|
||||
if ( view:IsPlayer() ) then
|
||||
return view:EyePos():DistToSqr( self:GetPos() ) <= dist && view:GetEyeTrace().Entity == self
|
||||
end
|
||||
|
||||
-- If we're not spectating a player, perform a manual trace from the entity's position
|
||||
local pos = view:GetPos()
|
||||
|
||||
if ( pos:DistToSqr( self:GetPos() ) <= dist ) then
|
||||
return util.TraceLine( {
|
||||
start = pos,
|
||||
endpos = pos + ( view:GetAngles():Forward() * dist ),
|
||||
filter = view
|
||||
} ).Entity == self
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate( physobj )
|
||||
|
||||
if ( CLIENT ) then return end
|
||||
|
||||
-- Don't do anything if the player isn't holding us
|
||||
if ( !self:IsPlayerHolding() && !self:IsConstrained() ) then
|
||||
|
||||
physobj:SetVelocity( vector_origin )
|
||||
physobj:Sleep()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:OnEntityCopyTableFinish( tab )
|
||||
|
||||
-- We need to store the model of the attached entity
|
||||
-- Not the one we have here.
|
||||
tab.Model = self.AttachedEntity:GetModel()
|
||||
|
||||
-- Store the attached entity's table so we can restore it after being pasted
|
||||
tab.AttachedEntityInfo = table.Copy( duplicator.CopyEntTable( self.AttachedEntity ) )
|
||||
tab.AttachedEntityInfo.Pos = nil -- Don't even save angles and position, we are a parented entity
|
||||
tab.AttachedEntityInfo.Angle = nil
|
||||
|
||||
-- Do NOT store the attached entity itself in our table!
|
||||
-- Otherwise, if we copy-paste the prop with the duplicator, its AttachedEntity value will point towards the original prop's attached entity instead, and that'll break stuff
|
||||
tab.AttachedEntity = nil
|
||||
|
||||
end
|
||||
|
||||
function ENT:PostEntityPaste( ply )
|
||||
|
||||
-- Restore the attached entity using the information we've saved
|
||||
if ( IsValid( self.AttachedEntity ) && self.AttachedEntityInfo ) then
|
||||
|
||||
-- Apply skin, bodygroups, bone manipulator, etc.
|
||||
duplicator.DoGeneric( self.AttachedEntity, self.AttachedEntityInfo )
|
||||
|
||||
if ( self.AttachedEntityInfo.EntityMods ) then
|
||||
self.AttachedEntity.EntityMods = table.Copy( self.AttachedEntityInfo.EntityMods )
|
||||
duplicator.ApplyEntityModifiers( ply, self.AttachedEntity )
|
||||
end
|
||||
|
||||
if ( self.AttachedEntityInfo.BoneMods ) then
|
||||
self.AttachedEntity.BoneMods = table.Copy( self.AttachedEntityInfo.BoneMods )
|
||||
duplicator.ApplyBoneModifiers( ply, self.AttachedEntity )
|
||||
end
|
||||
|
||||
self.AttachedEntityInfo = nil
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
317
gamemodes/base/entities/entities/ragdoll_motion.lua
Normal file
317
gamemodes/base/entities/entities/ragdoll_motion.lua
Normal file
@@ -0,0 +1,317 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
ENT.Editable = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
|
||||
--
|
||||
-- Scale - how far the ragdoll will move in the game world in relation to how far it moved in the real world
|
||||
--
|
||||
self:NetworkVar( "Float", 0, "Scale", { KeyName = "scale", Edit = { type = "Float", min = 1, max = 512, order = 1 } } )
|
||||
|
||||
--
|
||||
-- Normalize - if enabled the limbs aren't stretched
|
||||
--
|
||||
self:NetworkVar( "Bool", 0, "Normalize", { KeyName = "normalize", Edit = { type = "Boolean", order = 2 } } )
|
||||
|
||||
--
|
||||
-- Debug - Shows some debug info - only available on a listen server
|
||||
--
|
||||
self:NetworkVar( "Bool", 1, "Debug", { KeyName = "debug", Edit = { type = "Boolean", order = 100 } } )
|
||||
|
||||
--
|
||||
-- Controller - the entity that is currently controlling the ragdoll
|
||||
--
|
||||
self:NetworkVar( "Entity", 0, "Controller" )
|
||||
self:NetworkVar( "Entity", 1, "Target" )
|
||||
|
||||
--
|
||||
-- Defaults
|
||||
--
|
||||
if ( SERVER ) then
|
||||
|
||||
self:SetScale( 36 )
|
||||
self:SetDebug( false )
|
||||
self:SetNormalize( true )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
|
||||
if ( SERVER ) then
|
||||
|
||||
self:SetModel( "models/maxofs2d/motion_sensor.mdl" )
|
||||
self:PhysicsInit( SOLID_VPHYSICS )
|
||||
|
||||
-- Don't collide with the player
|
||||
self:SetCollisionGroup( COLLISION_GROUP_WEAPON )
|
||||
|
||||
self:DrawShadow( false )
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if ( IsValid( phys ) ) then
|
||||
phys:Wake()
|
||||
phys:EnableGravity( false )
|
||||
phys:EnableDrag( false )
|
||||
end
|
||||
|
||||
local colors = {
|
||||
Color( 180, 255, 50 ),
|
||||
Color( 0, 150, 255 ),
|
||||
Color( 255, 255, 0 ),
|
||||
Color( 255, 50, 255 )
|
||||
}
|
||||
|
||||
self:SetColor( table.Random( colors ) )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- We don't want to move unless the player moves us or we're constrained to something.
|
||||
--
|
||||
function ENT:PhysicsUpdate( physobj )
|
||||
|
||||
if ( self:IsPlayerHolding() ) then return end
|
||||
if ( self:IsConstrained() ) then return end
|
||||
|
||||
physobj:SetVelocity( vector_origin )
|
||||
physobj:Sleep()
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Clean up on remove
|
||||
--
|
||||
function ENT:OnRemove()
|
||||
|
||||
if ( SERVER ) then
|
||||
|
||||
local ragdoll = self:GetTarget()
|
||||
if ( IsValid( ragdoll ) ) then
|
||||
ragdoll:SetRagdollBuildFunction( nil )
|
||||
|
||||
if ( IsValid( ragdoll.MotionSensorController ) && ragdoll.MotionSensorController == self ) then
|
||||
ragdoll.MotionSensorController = nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
|
||||
--
|
||||
-- Don't draw if we're holding the camera
|
||||
--
|
||||
local ply = LocalPlayer()
|
||||
local wep = ply:GetActiveWeapon()
|
||||
if ( IsValid( wep ) && wep:GetClass() == "gmod_camera" ) then
|
||||
return
|
||||
end
|
||||
|
||||
self:DrawModel()
|
||||
|
||||
end
|
||||
|
||||
function ENT:DrawDebug( ragdoll, controller, pos, ang, rotation, scale, center, changed_sensor )
|
||||
|
||||
local UpdateTime = 0.1
|
||||
local StayTime = 0.15
|
||||
|
||||
if ( self.LastDebugUpdate && CurTime() - self.LastDebugUpdate < UpdateTime ) then return end
|
||||
|
||||
self.LastDebugUpdate = CurTime()
|
||||
|
||||
center = center
|
||||
|
||||
local col_bone = color_white
|
||||
local col_point = Color( 255, 0, 0, 255 )
|
||||
local col_tran_bn = Color( 0, 255, 0, 255 )
|
||||
|
||||
local realbonepos = {}
|
||||
local fixedbonepos = {}
|
||||
local min = Vector( 1, 1, 1 ) * -0.5
|
||||
local max = Vector( 1, 1, 1 ) * 0.5
|
||||
|
||||
--
|
||||
-- Draw Points
|
||||
--
|
||||
for i = 0, 19 do
|
||||
|
||||
realbonepos[i] = controller:MotionSensorPos( i ) * scale
|
||||
realbonepos[i]:Rotate( rotation )
|
||||
realbonepos[i] = realbonepos[i] + center
|
||||
|
||||
fixedbonepos[i] = changed_sensor[ i ] * scale
|
||||
-- (already rotated)
|
||||
fixedbonepos[i] = fixedbonepos[i] + center
|
||||
|
||||
debugoverlay.Box( realbonepos[i], min, max, StayTime, col_point )
|
||||
debugoverlay.Box( fixedbonepos[i], min, max, StayTime, col_tran_bn )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Draw bones
|
||||
--
|
||||
for k, v in ipairs( motionsensor.DebugBones ) do
|
||||
|
||||
debugoverlay.Line( realbonepos[ v[1] ], realbonepos[ v[2] ], StayTime, col_bone, true )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Draw translated sensor bones
|
||||
--
|
||||
for k, v in ipairs( motionsensor.DebugBones ) do
|
||||
|
||||
debugoverlay.Line( fixedbonepos[ v[1] ], fixedbonepos[ v[2] ], StayTime, col_tran_bn, true )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Draw ragdoll physics bones
|
||||
--
|
||||
for i = 0, ragdoll:GetPhysicsObjectCount() - 1 do
|
||||
|
||||
local phys = ragdoll:GetPhysicsObjectNum( i )
|
||||
|
||||
local position = phys:GetPos()
|
||||
local angle = phys:GetAngles()
|
||||
local txt = tostring( i )
|
||||
|
||||
if ( ang[i] == nil ) then
|
||||
txt = i .. " (UNSET)"
|
||||
end
|
||||
|
||||
debugoverlay.Text( position, txt, StayTime )
|
||||
debugoverlay.Axis( position, angle, 5, StayTime, true )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:SetRagdoll( ragdoll )
|
||||
|
||||
ragdoll.MotionSensorController = self
|
||||
|
||||
self:SetTarget( ragdoll )
|
||||
ragdoll:PhysWake()
|
||||
|
||||
local buildername = motionsensor.ChooseBuilderFromEntity( ragdoll )
|
||||
|
||||
--
|
||||
-- Set the ragdoll build function.
|
||||
-- This function is called whenever the ragdoll bones are built.
|
||||
-- in this function is the one place you can successfully call ent:SetRagdollBone
|
||||
--
|
||||
ragdoll:SetRagdollBuildFunction( function( ragdoll )
|
||||
|
||||
local controller = self:GetController()
|
||||
if ( !IsValid( controller ) ) then return end
|
||||
|
||||
local builder = list.Get( "SkeletonConvertor" )[ buildername ]
|
||||
local scale = self:GetScale()
|
||||
local rotation = self:GetAngles()
|
||||
local center = self:GetPos()
|
||||
local normalize = self:GetNormalize()
|
||||
local debug = self:GetDebug()
|
||||
|
||||
--
|
||||
-- Call the build skeleton function.
|
||||
-- This is thrown out to a pseudo class because we want to be
|
||||
-- able to add new skeleton types nice and easily.
|
||||
--
|
||||
local pos, ang, changed_sensor = motionsensor.BuildSkeleton( builder, controller, rotation )
|
||||
|
||||
--
|
||||
-- For development
|
||||
--
|
||||
if ( debug ) then
|
||||
self:DrawDebug( ragdoll, controller, pos, ang, rotation, scale, center, changed_sensor )
|
||||
end
|
||||
|
||||
--
|
||||
-- If we don't have 85% of the points, just drop dead
|
||||
--
|
||||
local iSkipped = 0
|
||||
local iMaxSkip = table.Count( pos ) * 0.25
|
||||
for k, v in pairs( pos ) do
|
||||
|
||||
if ( math.abs( v.x ) > 0.05 ) then continue end
|
||||
if ( math.abs( v.y ) > 0.05 ) then continue end
|
||||
|
||||
pos[k] = nil -- don't use this point to control the ragdoll
|
||||
ang[k] = nil -- (use the ragdoll point)
|
||||
|
||||
iSkipped = iSkipped + 1
|
||||
|
||||
if ( iSkipped > iMaxSkip ) then
|
||||
|
||||
ragdoll:RagdollStopControlling()
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Loop each returned position
|
||||
--
|
||||
for k, v in pairs( pos ) do
|
||||
|
||||
--
|
||||
-- Set the bone angle
|
||||
--
|
||||
if ( ang[ k ] != nil ) then
|
||||
ragdoll:SetRagdollAng( k, ang[ k ] )
|
||||
end
|
||||
|
||||
--
|
||||
-- The root bone, we directly set the position of this one.
|
||||
--
|
||||
if ( k == 0 || !normalize ) then
|
||||
|
||||
local new_position = center + v * scale
|
||||
ragdoll:SetRagdollPos( k, new_position )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Normalize the ragdoll
|
||||
--
|
||||
if ( normalize ) then
|
||||
|
||||
ragdoll:RagdollSolve()
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Makes the physics objects follow the set bone positions
|
||||
--
|
||||
ragdoll:RagdollUpdatePhysics()
|
||||
|
||||
end )
|
||||
|
||||
end
|
||||
202
gamemodes/base/entities/weapons/weapon_base/ai_translations.lua
Normal file
202
gamemodes/base/entities/weapons/weapon_base/ai_translations.lua
Normal file
@@ -0,0 +1,202 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SetupWeaponHoldTypeForAI
|
||||
Desc: Sets up ACT translations from generic activities to NPC specific activies. In a seperate file to clean up the init.lua
|
||||
Not all NPCs have support for all animations (for example Citizens don't have pistol animations)
|
||||
This only supports the holdtypes the default NPC models can support
|
||||
All of these are taken directly from IMPLEMENT_ACTTABLE() macro of the C++ weapons
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:SetupWeaponHoldTypeForAI( t )
|
||||
|
||||
self.ActivityTranslateAI = {}
|
||||
|
||||
-- Default is pistol/revolver for reasons
|
||||
self.ActivityTranslateAI[ ACT_IDLE ] = ACT_IDLE_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_IDLE_ANGRY ] = ACT_IDLE_ANGRY_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_RELOAD ] = ACT_RELOAD_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM ] = ACT_WALK_AIM_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM ] = ACT_RUN_AIM_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_GESTURE_RANGE_ATTACK1 ] = ACT_GESTURE_RANGE_ATTACK_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_RELOAD_LOW ] = ACT_RELOAD_PISTOL_LOW
|
||||
|
||||
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1_LOW ] = ACT_RANGE_ATTACK_PISTOL_LOW
|
||||
self.ActivityTranslateAI[ ACT_COVER_LOW ] = ACT_COVER_PISTOL_LOW
|
||||
self.ActivityTranslateAI[ ACT_RANGE_AIM_LOW ] = ACT_RANGE_AIM_PISTOL_LOW
|
||||
self.ActivityTranslateAI[ ACT_GESTURE_RELOAD ] = ACT_GESTURE_RELOAD_PISTOL
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK ] = ACT_WALK_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_RUN ] = ACT_RUN_PISTOL
|
||||
|
||||
self.ActivityTranslateAI[ ACT_IDLE_RELAXED ] = ACT_IDLE_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_IDLE_STIMULATED ] = ACT_IDLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AGITATED ] = ACT_IDLE_ANGRY_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_IDLE_STEALTH ] = ACT_IDLE_STEALTH_PISTOL
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK_RELAXED ] = ACT_WALK
|
||||
self.ActivityTranslateAI[ ACT_WALK_STIMULATED ] = ACT_WALK_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_WALK_AGITATED ] = ACT_WALK_AIM_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_WALK_STEALTH ] = ACT_WALK_STEALTH_PISTOL
|
||||
|
||||
self.ActivityTranslateAI[ ACT_RUN_RELAXED ] = ACT_RUN
|
||||
self.ActivityTranslateAI[ ACT_RUN_STIMULATED ] = ACT_RUN_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_RUN_AGITATED ] = ACT_RUN_AIM_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_RUN_STEALTH ] = ACT_RUN_STEALTH_PISTOL
|
||||
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_RELAXED ] = ACT_IDLE_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_STIMULATED ] = ACT_IDLE_ANGRY_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_AGITATED ] = ACT_IDLE_ANGRY_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_STEALTH ] = ACT_IDLE_STEALTH_PISTOL
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_RELAXED ] = ACT_WALK
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_STIMULATED ] = ACT_WALK_AIM_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_AGITATED ] = ACT_WALK_AIM_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_STEALTH ] = ACT_WALK_AIM_STEALTH_PISTOL
|
||||
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_RELAXED ] = ACT_RUN
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_STIMULATED ] = ACT_RUN_AIM_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_AGITATED ] = ACT_RUN_AIM_PISTOL
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_STEALTH ] = ACT_RUN_AIM_STEALTH_PISTOL
|
||||
|
||||
self.ActivityTranslateAI[ ACT_CROUCHIDLE_STIMULATED] = ACT_CROUCHIDLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_CROUCHIDLE_AIM_STIMULATED ] = ACT_RANGE_AIM_PISTOL_LOW
|
||||
self.ActivityTranslateAI[ ACT_CROUCHIDLE_AGITATED ] = ACT_RANGE_AIM_PISTOL_LOW
|
||||
|
||||
self.ActivityTranslateAI[ ACT_READINESS_RELAXED_TO_STIMULATED ] = ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_READINESS_RELAXED_TO_STIMULATED_WALK ] = ACT_READINESS_PISTOL_RELAXED_TO_STIMULATED_WALK
|
||||
self.ActivityTranslateAI[ ACT_READINESS_AGITATED_TO_STIMULATED ] = ACT_READINESS_PISTOL_AGITATED_TO_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_READINESS_STIMULATED_TO_RELAXED ] = ACT_READINESS_PISTOL_STIMULATED_TO_RELAXED
|
||||
|
||||
if ( t == "ar2" || t == "smg" ) then
|
||||
|
||||
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_AR2
|
||||
self.ActivityTranslateAI[ ACT_RELOAD ] = ACT_RELOAD_SMG1
|
||||
self.ActivityTranslateAI[ ACT_IDLE ] = ACT_IDLE_SMG1
|
||||
self.ActivityTranslateAI[ ACT_IDLE_ANGRY ] = ACT_IDLE_ANGRY_SMG1
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK ] = ACT_WALK_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM ] = ACT_WALK_AIM_RIFLE
|
||||
|
||||
self.ActivityTranslateAI[ ACT_IDLE_RELAXED ] = ACT_IDLE_SMG1_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_STIMULATED ] = ACT_IDLE_SMG1_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AGITATED ] = ACT_IDLE_ANGRY_SMG1
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK_RELAXED ] = ACT_WALK_RIFLE_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_WALK_STIMULATED ] = ACT_WALK_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_WALK_AGITATED ] = ACT_WALK_AIM_RIFLE
|
||||
|
||||
self.ActivityTranslateAI[ ACT_RUN_RELAXED ] = ACT_RUN_RIFLE_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_RUN_STIMULATED ] = ACT_RUN_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_RUN_AGITATED ] = ACT_RUN_AIM_RIFLE
|
||||
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_RELAXED ] = ACT_IDLE_SMG1_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_STIMULATED ] = ACT_IDLE_AIM_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_AGITATED ] = ACT_IDLE_ANGRY_SMG1
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_RELAXED ] = ACT_WALK_RIFLE_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_STIMULATED ] = ACT_WALK_AIM_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_AGITATED ] = ACT_WALK_AIM_RIFLE
|
||||
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_RELAXED ] = ACT_RUN_RIFLE_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_STIMULATED ] = ACT_RUN_AIM_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_AGITATED ] = ACT_RUN_AIM_RIFLE
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK_CROUCH ] = ACT_WALK_CROUCH_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_WALK_CROUCH_AIM ] = ACT_WALK_CROUCH_AIM_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_RUN ] = ACT_RUN_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM ] = ACT_RUN_AIM_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_RUN_CROUCH ] = ACT_RUN_CROUCH_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_RUN_CROUCH_AIM ] = ACT_RUN_CROUCH_AIM_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_GESTURE_RANGE_ATTACK1 ] = ACT_GESTURE_RANGE_ATTACK_AR2
|
||||
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1_LOW ] = ACT_RANGE_ATTACK_SMG1_LOW
|
||||
self.ActivityTranslateAI[ ACT_COVER_LOW ] = ACT_COVER_SMG1_LOW
|
||||
self.ActivityTranslateAI[ ACT_RANGE_AIM_LOW ] = ACT_RANGE_AIM_AR2_LOW
|
||||
self.ActivityTranslateAI[ ACT_RELOAD_LOW ] = ACT_RELOAD_SMG1_LOW
|
||||
self.ActivityTranslateAI[ ACT_GESTURE_RELOAD ] = ACT_GESTURE_RELOAD_SMG1
|
||||
|
||||
-- Extra overrides for SMG holdtype
|
||||
if ( t == "smg" ) then
|
||||
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_SMG1
|
||||
self.ActivityTranslateAI[ ACT_GESTURE_RANGE_ATTACK1 ] = ACT_GESTURE_RANGE_ATTACK_SMG1
|
||||
self.ActivityTranslateAI[ ACT_RANGE_AIM_LOW ] = ACT_RANGE_AIM_SMG1_LOW
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if ( t == "shotgun" || t == "crossbow" ) then
|
||||
self.ActivityTranslateAI[ ACT_IDLE ] = ACT_IDLE_SMG1
|
||||
|
||||
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_SHOTGUN
|
||||
self.ActivityTranslateAI[ ACT_RELOAD ] = ACT_RELOAD_SHOTGUN
|
||||
self.ActivityTranslateAI[ ACT_WALK ] = ACT_WALK_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_IDLE_ANGRY ] = ACT_IDLE_ANGRY_SHOTGUN
|
||||
|
||||
self.ActivityTranslateAI[ ACT_IDLE_RELAXED ] = ACT_IDLE_SHOTGUN_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_STIMULATED ] = ACT_IDLE_SHOTGUN_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AGITATED ] = ACT_IDLE_SHOTGUN_AGITATED
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK_RELAXED ] = ACT_WALK_RIFLE_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_WALK_STIMULATED ] = ACT_WALK_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_WALK_AGITATED ] = ACT_WALK_AIM_RIFLE
|
||||
|
||||
self.ActivityTranslateAI[ ACT_RUN_RELAXED ] = ACT_RUN_RIFLE_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_RUN_STIMULATED ] = ACT_RUN_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_RUN_AGITATED ] = ACT_RUN_AIM_RIFLE
|
||||
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_RELAXED ] = ACT_IDLE_SMG1_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_STIMULATED ] = ACT_IDLE_AIM_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AIM_AGITATED ] = ACT_IDLE_ANGRY_SMG1
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_RELAXED ] = ACT_WALK_RIFLE_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_STIMULATED ] = ACT_WALK_AIM_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM_AGITATED ] = ACT_WALK_AIM_RIFLE
|
||||
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_RELAXED ] = ACT_RUN_RIFLE_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_STIMULATED ] = ACT_RUN_AIM_RIFLE_STIMULATED
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM_AGITATED ] = ACT_RUN_AIM_RIFLE
|
||||
|
||||
self.ActivityTranslateAI[ ACT_WALK_AIM ] = ACT_WALK_AIM_SHOTGUN
|
||||
self.ActivityTranslateAI[ ACT_WALK_CROUCH ] = ACT_WALK_CROUCH_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_WALK_CROUCH_AIM ] = ACT_WALK_CROUCH_AIM_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_RUN ] = ACT_RUN_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_RUN_AIM ] = ACT_RUN_AIM_SHOTGUN
|
||||
self.ActivityTranslateAI[ ACT_RUN_CROUCH ] = ACT_RUN_CROUCH_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_RUN_CROUCH_AIM ] = ACT_RUN_CROUCH_AIM_RIFLE
|
||||
self.ActivityTranslateAI[ ACT_GESTURE_RANGE_ATTACK1 ] = ACT_GESTURE_RANGE_ATTACK_SHOTGUN
|
||||
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1_LOW ] = ACT_RANGE_ATTACK_SHOTGUN_LOW
|
||||
self.ActivityTranslateAI[ ACT_RELOAD_LOW ] = ACT_RELOAD_SHOTGUN_LOW
|
||||
self.ActivityTranslateAI[ ACT_GESTURE_RELOAD ] = ACT_GESTURE_RELOAD_SHOTGUN
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
if ( t == "rpg" ) then
|
||||
self.ActivityTranslateAI[ ACT_RANGE_ATTACK1 ] = ACT_RANGE_ATTACK_RPG
|
||||
|
||||
self.ActivityTranslateAI[ ACT_IDLE_RELAXED ] = ACT_IDLE_RPG_RELAXED
|
||||
self.ActivityTranslateAI[ ACT_IDLE_STIMULATED ] = ACT_IDLE_ANGRY_RPG
|
||||
self.ActivityTranslateAI[ ACT_IDLE_AGITATED ] = ACT_IDLE_ANGRY_RPG
|
||||
|
||||
self.ActivityTranslateAI[ ACT_IDLE ] = ACT_IDLE_RPG
|
||||
self.ActivityTranslateAI[ ACT_IDLE_ANGRY ] = ACT_IDLE_ANGRY_RPG
|
||||
self.ActivityTranslateAI[ ACT_WALK ] = ACT_WALK_RPG
|
||||
self.ActivityTranslateAI[ ACT_WALK_CROUCH ] = ACT_WALK_CROUCH_RPG
|
||||
self.ActivityTranslateAI[ ACT_RUN ] = ACT_RUN_RPG
|
||||
self.ActivityTranslateAI[ ACT_RUN_CROUCH ] = ACT_RUN_CROUCH_RPG
|
||||
self.ActivityTranslateAI[ ACT_COVER_LOW ] = ACT_COVER_LOW_RPG
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
221
gamemodes/base/entities/weapons/weapon_base/cl_init.lua
Normal file
221
gamemodes/base/entities/weapons/weapon_base/cl_init.lua
Normal file
@@ -0,0 +1,221 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
include( "ai_translations.lua" )
|
||||
include( "sh_anim.lua" )
|
||||
include( "shared.lua" )
|
||||
|
||||
SWEP.Slot = 0 -- Slot in the weapon selection menu
|
||||
SWEP.SlotPos = 10 -- Position in the slot
|
||||
SWEP.DrawAmmo = true -- Should draw the default HL2 ammo counter
|
||||
SWEP.DrawCrosshair = true -- Should draw the default crosshair
|
||||
SWEP.DrawWeaponInfoBox = true -- Should draw the weapon info box
|
||||
SWEP.BounceWeaponIcon = true -- Should the weapon icon bounce?
|
||||
SWEP.SwayScale = 1.0 -- The scale of the viewmodel sway
|
||||
SWEP.BobScale = 1.0 -- The scale of the viewmodel bob
|
||||
|
||||
SWEP.RenderGroup = RENDERGROUP_OPAQUE
|
||||
|
||||
-- Override this in your SWEP to set the icon in the weapon selection
|
||||
SWEP.WepSelectIcon = surface.GetTextureID( "weapons/swep" )
|
||||
|
||||
-- This is the corner of the speech bubble
|
||||
SWEP.SpeechBubbleLid = surface.GetTextureID( "gui/speech_lid" )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
You can draw to the HUD here - it will only draw when
|
||||
the client has the weapon deployed..
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:DrawHUD()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Checks the objects before any action is taken
|
||||
This is to make sure that the entities haven't been removed
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:DrawWeaponSelection( x, y, wide, tall, alpha )
|
||||
|
||||
-- Set us up the texture
|
||||
surface.SetDrawColor( 255, 255, 255, alpha )
|
||||
surface.SetTexture( self.WepSelectIcon )
|
||||
|
||||
-- Lets get a sin wave to make it bounce
|
||||
local fsin = 0
|
||||
|
||||
if ( self.BounceWeaponIcon == true ) then
|
||||
fsin = math.sin( CurTime() * 10 ) * 5
|
||||
end
|
||||
|
||||
-- Borders
|
||||
y = y + 10
|
||||
x = x + 10
|
||||
wide = wide - 20
|
||||
|
||||
-- Draw that mother
|
||||
surface.DrawTexturedRect( x + fsin, y - fsin, wide - fsin * 2 , ( wide / 2 ) + fsin )
|
||||
|
||||
-- Draw weapon info box
|
||||
self:PrintWeaponInfo( x + wide + 20, y + tall * 0.95, alpha )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
This draws the weapon info box
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:PrintWeaponInfo( x, y, alpha )
|
||||
|
||||
if ( self.DrawWeaponInfoBox == false ) then return end
|
||||
|
||||
if ( self.InfoMarkup == nil ) then
|
||||
local title_color = "<color=230,230,230,255>"
|
||||
local text_color = "<color=150,150,150,255>"
|
||||
|
||||
local str = "<font=HudSelectionText>"
|
||||
if ( self.Author != "" ) then str = str .. title_color .. "Author:</color>\t" .. text_color .. self.Author .. "</color>\n" end
|
||||
if ( self.Contact != "" ) then str = str .. title_color .. "Contact:</color>\t" .. text_color .. self.Contact .. "</color>\n\n" end
|
||||
if ( self.Purpose != "" ) then str = str .. title_color .. "Purpose:</color>\n" .. text_color .. self.Purpose .. "</color>\n\n" end
|
||||
if ( self.Instructions != "" ) then str = str .. title_color .. "Instructions:</color>\n" .. text_color .. self.Instructions .. "</color>\n" end
|
||||
str = str .. "</font>"
|
||||
|
||||
self.InfoMarkup = markup.Parse( str, 250 )
|
||||
end
|
||||
|
||||
surface.SetDrawColor( 60, 60, 60, alpha )
|
||||
surface.SetTexture( self.SpeechBubbleLid )
|
||||
|
||||
surface.DrawTexturedRect( x, y - 64 - 5, 128, 64 )
|
||||
draw.RoundedBox( 8, x - 5, y - 6, 260, self.InfoMarkup:GetHeight() + 18, Color( 60, 60, 60, alpha ) )
|
||||
|
||||
self.InfoMarkup:Draw( x + 5, y + 5, nil, nil, alpha )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:FreezeMovement()
|
||||
Desc: Return true to freeze moving the view
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:FreezeMovement()
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:ViewModelDrawn( viewModel )
|
||||
Desc: Called straight after the viewmodel has been drawn
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:ViewModelDrawn( vm )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: Called immediately after a "load"
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:OnRestore()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: CustomAmmoDisplay
|
||||
Desc: Return a table
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:CustomAmmoDisplay()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: GetViewModelPosition
|
||||
Desc: Allows you to re-position the view model
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:GetViewModelPosition( pos, ang )
|
||||
|
||||
return pos, ang
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: TranslateFOV
|
||||
Desc: Allows the weapon to translate the player's FOV (clientside)
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:TranslateFOV( current_fov )
|
||||
|
||||
return current_fov
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: DrawWorldModel
|
||||
Desc: Draws the world model (not the viewmodel)
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:DrawWorldModel()
|
||||
|
||||
self:DrawModel()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: DrawWorldModelTranslucent
|
||||
Desc: Draws the world model (not the viewmodel)
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:DrawWorldModelTranslucent()
|
||||
|
||||
self:DrawModel()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AdjustMouseSensitivity
|
||||
Desc: Allows you to adjust the mouse sensitivity.
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:AdjustMouseSensitivity()
|
||||
|
||||
return nil
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: GetTracerOrigin
|
||||
Desc: Allows you to override where the tracer comes from (in first person view)
|
||||
returning anything but a vector indicates that you want the default action
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:GetTracerOrigin()
|
||||
|
||||
--[[
|
||||
local ply = self:GetOwner()
|
||||
local pos = ply:EyePos() + ply:EyeAngles():Right() * -5
|
||||
return pos
|
||||
--]]
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: FireAnimationEvent
|
||||
Desc: Allows you to override weapon animation events
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:FireAnimationEvent( pos, ang, event, options )
|
||||
|
||||
if ( !self.CSMuzzleFlashes ) then return end
|
||||
|
||||
-- CS Muzzle flashes
|
||||
if ( event == 5001 or event == 5011 or event == 5021 or event == 5031 ) then
|
||||
|
||||
local data = EffectData()
|
||||
data:SetFlags( 0 )
|
||||
data:SetEntity( self:GetOwner():GetViewModel() )
|
||||
data:SetAttachment( math.floor( ( event - 4991 ) / 10 ) )
|
||||
data:SetScale( 1 )
|
||||
|
||||
if ( self.CSMuzzleX ) then
|
||||
util.Effect( "CS_MuzzleFlash_X", data )
|
||||
else
|
||||
util.Effect( "CS_MuzzleFlash", data )
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
114
gamemodes/base/entities/weapons/weapon_base/init.lua
Normal file
114
gamemodes/base/entities/weapons/weapon_base/init.lua
Normal file
@@ -0,0 +1,114 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile( "cl_init.lua" )
|
||||
AddCSLuaFile( "ai_translations.lua" )
|
||||
AddCSLuaFile( "sh_anim.lua" )
|
||||
AddCSLuaFile( "shared.lua" )
|
||||
|
||||
include( "ai_translations.lua" )
|
||||
include( "sh_anim.lua" )
|
||||
include( "shared.lua" )
|
||||
|
||||
SWEP.Weight = 5 -- Decides whether we should switch from/to this
|
||||
SWEP.AutoSwitchTo = true -- Auto switch to if we pick it up
|
||||
SWEP.AutoSwitchFrom = true -- Auto switch from if you pick up a better weapon
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: The game has just been reloaded. This is usually the right place
|
||||
to call the GetNW* functions to restore the script's values.
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:OnRestore()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AcceptInput
|
||||
Desc: Accepts input, return true to override/accept input
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:AcceptInput( name, activator, caller, data )
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: KeyValue
|
||||
Desc: Called when a keyvalue is added to us
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:KeyValue( key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Equip
|
||||
Desc: A player or NPC has picked the weapon up
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:Equip( newOwner )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: EquipAmmo
|
||||
Desc: The player has picked up the weapon and has taken the ammo from it
|
||||
The weapon will be removed immediately after this call.
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:EquipAmmo( newOwner )
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnDrop
|
||||
Desc: Weapon was dropped
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:OnDrop()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: ShouldDropOnDie
|
||||
Desc: Should this weapon be dropped when its owner dies?
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:ShouldDropOnDie()
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: GetCapabilities
|
||||
Desc: For NPCs, returns what they should try to do with it.
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:GetCapabilities()
|
||||
|
||||
return CAP_WEAPON_RANGE_ATTACK1
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: NPCShoot_Secondary
|
||||
Desc: NPC tried to fire secondary attack
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:NPCShoot_Secondary( shootPos, shootDir )
|
||||
|
||||
self:SecondaryAttack()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: NPCShoot_Secondary
|
||||
Desc: NPC tried to fire primary attack
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:NPCShoot_Primary( shootPos, shootDir )
|
||||
|
||||
self:PrimaryAttack()
|
||||
|
||||
end
|
||||
|
||||
-- These tell the NPC how to use the weapon
|
||||
AccessorFunc( SWEP, "fNPCMinBurst", "NPCMinBurst" )
|
||||
AccessorFunc( SWEP, "fNPCMaxBurst", "NPCMaxBurst" )
|
||||
AccessorFunc( SWEP, "fNPCFireRate", "NPCFireRate" )
|
||||
AccessorFunc( SWEP, "fNPCMinRestTime", "NPCMinRest" )
|
||||
AccessorFunc( SWEP, "fNPCMaxRestTime", "NPCMaxRest" )
|
||||
97
gamemodes/base/entities/weapons/weapon_base/sh_anim.lua
Normal file
97
gamemodes/base/entities/weapons/weapon_base/sh_anim.lua
Normal file
@@ -0,0 +1,97 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
local ActIndex = {
|
||||
[ "pistol" ] = ACT_HL2MP_IDLE_PISTOL,
|
||||
[ "smg" ] = ACT_HL2MP_IDLE_SMG1,
|
||||
[ "grenade" ] = ACT_HL2MP_IDLE_GRENADE,
|
||||
[ "ar2" ] = ACT_HL2MP_IDLE_AR2,
|
||||
[ "shotgun" ] = ACT_HL2MP_IDLE_SHOTGUN,
|
||||
[ "rpg" ] = ACT_HL2MP_IDLE_RPG,
|
||||
[ "physgun" ] = ACT_HL2MP_IDLE_PHYSGUN,
|
||||
[ "crossbow" ] = ACT_HL2MP_IDLE_CROSSBOW,
|
||||
[ "melee" ] = ACT_HL2MP_IDLE_MELEE,
|
||||
[ "slam" ] = ACT_HL2MP_IDLE_SLAM,
|
||||
[ "normal" ] = ACT_HL2MP_IDLE,
|
||||
[ "fist" ] = ACT_HL2MP_IDLE_FIST,
|
||||
[ "melee2" ] = ACT_HL2MP_IDLE_MELEE2,
|
||||
[ "passive" ] = ACT_HL2MP_IDLE_PASSIVE,
|
||||
[ "knife" ] = ACT_HL2MP_IDLE_KNIFE,
|
||||
[ "duel" ] = ACT_HL2MP_IDLE_DUEL,
|
||||
[ "camera" ] = ACT_HL2MP_IDLE_CAMERA,
|
||||
[ "magic" ] = ACT_HL2MP_IDLE_MAGIC,
|
||||
[ "revolver" ] = ACT_HL2MP_IDLE_REVOLVER
|
||||
}
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SetWeaponHoldType
|
||||
Desc: Sets up the translation table, to translate from normal
|
||||
standing idle pose, to holding weapon pose.
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:SetWeaponHoldType( t )
|
||||
|
||||
t = string.lower( t )
|
||||
local index = ActIndex[ t ]
|
||||
|
||||
if ( index == nil ) then
|
||||
Msg( "SWEP:SetWeaponHoldType - ActIndex[ \"" .. t .. "\" ] isn't set! (defaulting to normal)\n" )
|
||||
t = "normal"
|
||||
index = ActIndex[ t ]
|
||||
end
|
||||
|
||||
self.ActivityTranslate = {}
|
||||
self.ActivityTranslate[ ACT_MP_STAND_IDLE ] = index
|
||||
self.ActivityTranslate[ ACT_MP_WALK ] = index + 1
|
||||
self.ActivityTranslate[ ACT_MP_RUN ] = index + 2
|
||||
self.ActivityTranslate[ ACT_MP_CROUCH_IDLE ] = index + 3
|
||||
self.ActivityTranslate[ ACT_MP_CROUCHWALK ] = index + 4
|
||||
self.ActivityTranslate[ ACT_MP_ATTACK_STAND_PRIMARYFIRE ] = index + 5
|
||||
self.ActivityTranslate[ ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ] = index + 5
|
||||
self.ActivityTranslate[ ACT_MP_RELOAD_STAND ] = index + 6
|
||||
self.ActivityTranslate[ ACT_MP_RELOAD_CROUCH ] = index + 6
|
||||
self.ActivityTranslate[ ACT_MP_JUMP ] = index + 7
|
||||
self.ActivityTranslate[ ACT_RANGE_ATTACK1 ] = index + 8
|
||||
self.ActivityTranslate[ ACT_MP_SWIM ] = index + 9
|
||||
|
||||
-- "normal" jump animation doesn't exist
|
||||
if ( t == "normal" ) then
|
||||
self.ActivityTranslate[ ACT_MP_JUMP ] = ACT_HL2MP_JUMP_SLAM
|
||||
end
|
||||
|
||||
self:SetupWeaponHoldTypeForAI( t )
|
||||
|
||||
end
|
||||
|
||||
-- Default hold pos is the pistol
|
||||
SWEP:SetWeaponHoldType( "pistol" )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: weapon:TranslateActivity()
|
||||
Desc: Translate a player's Activity into a weapon's activity
|
||||
So for example, ACT_HL2MP_RUN becomes ACT_HL2MP_RUN_PISTOL
|
||||
Depending on how you want the player to be holding the weapon
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:TranslateActivity( act )
|
||||
|
||||
if ( self:GetOwner():IsNPC() ) then
|
||||
if ( self.ActivityTranslateAI[ act ] ) then
|
||||
return self.ActivityTranslateAI[ act ]
|
||||
end
|
||||
return -1
|
||||
end
|
||||
|
||||
if ( self.ActivityTranslate[ act ] != nil ) then
|
||||
return self.ActivityTranslate[ act ]
|
||||
end
|
||||
|
||||
return -1
|
||||
|
||||
end
|
||||
280
gamemodes/base/entities/weapons/weapon_base/shared.lua
Normal file
280
gamemodes/base/entities/weapons/weapon_base/shared.lua
Normal file
@@ -0,0 +1,280 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- Variables that are used on both client and server
|
||||
|
||||
SWEP.PrintName = "Scripted Weapon" -- 'Nice' Weapon name (Shown on HUD)
|
||||
SWEP.Author = ""
|
||||
SWEP.Contact = ""
|
||||
SWEP.Purpose = ""
|
||||
SWEP.Instructions = ""
|
||||
|
||||
SWEP.ViewModelFOV = 62
|
||||
SWEP.ViewModelFlip = false
|
||||
SWEP.ViewModel = "models/weapons/v_pistol.mdl"
|
||||
SWEP.WorldModel = "models/weapons/w_357.mdl"
|
||||
|
||||
SWEP.Spawnable = false
|
||||
SWEP.AdminOnly = false
|
||||
|
||||
SWEP.Primary.ClipSize = 8 -- Size of a clip
|
||||
SWEP.Primary.DefaultClip = 32 -- Default number of bullets in a clip
|
||||
SWEP.Primary.Automatic = false -- Automatic/Semi Auto
|
||||
SWEP.Primary.Ammo = "Pistol"
|
||||
|
||||
SWEP.Secondary.ClipSize = 8 -- Size of a clip
|
||||
SWEP.Secondary.DefaultClip = 32 -- Default number of bullets in a clip
|
||||
SWEP.Secondary.Automatic = false -- Automatic/Semi Auto
|
||||
SWEP.Secondary.Ammo = "Pistol"
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:Initialize()
|
||||
Desc: Called when the weapon is first loaded
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:Initialize()
|
||||
|
||||
self:SetHoldType( "pistol" )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:PrimaryAttack()
|
||||
Desc: +attack1 has been pressed
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:PrimaryAttack()
|
||||
|
||||
-- Make sure we can shoot first
|
||||
if ( !self:CanPrimaryAttack() ) then return end
|
||||
|
||||
-- Play shoot sound
|
||||
self:EmitSound( "Weapon_AR2.Single" )
|
||||
|
||||
-- Shoot 9 bullets, 150 damage, 0.75 aimcone
|
||||
self:ShootBullet( 150, 1, 0.01, self.Primary.Ammo )
|
||||
|
||||
-- Remove 1 bullet from our clip
|
||||
self:TakePrimaryAmmo( 1 )
|
||||
|
||||
-- Punch the player's view
|
||||
local owner = self:GetOwner()
|
||||
if ( !owner:IsNPC() ) then owner:ViewPunch( Angle( -1, 0, 0 ) ) end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:SecondaryAttack()
|
||||
Desc: +attack2 has been pressed
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:SecondaryAttack()
|
||||
|
||||
-- Make sure we can shoot first
|
||||
if ( !self:CanSecondaryAttack() ) then return end
|
||||
|
||||
-- Play shoot sound
|
||||
self:EmitSound("Weapon_Shotgun.Single")
|
||||
|
||||
-- Shoot 9 bullets, 150 damage, 0.75 aimcone
|
||||
self:ShootBullet( 150, 9, 0.2, self.Secondary.Ammo )
|
||||
|
||||
-- Remove 1 bullet from our clip
|
||||
self:TakeSecondaryAmmo( 1 )
|
||||
|
||||
-- Punch the player's view
|
||||
local owner = self:GetOwner()
|
||||
if ( !owner:IsNPC() ) then owner:ViewPunch( Angle( -10, 0, 0 ) ) end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:Reload()
|
||||
Desc: Reload is being pressed
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:Reload()
|
||||
self:DefaultReload( ACT_VM_RELOAD )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:Think()
|
||||
Desc: Called every frame
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:Think()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:Holster( weapon_to_swap_to )
|
||||
Desc: Weapon wants to holster
|
||||
RetV: Return true to allow the weapon to holster
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:Holster( wep )
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:Deploy()
|
||||
Desc: Whip it out
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:Deploy()
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:ShootEffects()
|
||||
Desc: A convenience function to create shoot effects
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:ShootEffects()
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
self:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) -- View model animation
|
||||
owner:MuzzleFlash() -- Crappy muzzle light
|
||||
owner:SetAnimation( PLAYER_ATTACK1 ) -- 3rd Person Animation
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:ShootBullet()
|
||||
Desc: A convenience function to shoot bullets
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:ShootBullet( damage, num_bullets, aimcone, ammo_type, force, tracer )
|
||||
|
||||
local owner = self:GetOwner()
|
||||
|
||||
local bullet = {}
|
||||
bullet.Num = num_bullets
|
||||
bullet.Src = owner:GetShootPos() -- Source
|
||||
bullet.Dir = owner:GetAimVector() -- Dir of bullet
|
||||
bullet.Spread = Vector( aimcone, aimcone, 0 ) -- Aim Cone
|
||||
bullet.Tracer = tracer || 5 -- Show a tracer on every x bullets
|
||||
bullet.Force = force || 1 -- Amount of force to give to phys objects
|
||||
bullet.Damage = damage
|
||||
bullet.AmmoType = ammo_type || self.Primary.Ammo
|
||||
|
||||
owner:FireBullets( bullet )
|
||||
|
||||
self:ShootEffects()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:TakePrimaryAmmo()
|
||||
Desc: A convenience function to remove ammo
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:TakePrimaryAmmo( num )
|
||||
|
||||
-- Doesn't use clips
|
||||
if ( self:Clip1() <= 0 ) then
|
||||
|
||||
if ( self:Ammo1() <= 0 ) then return end
|
||||
|
||||
self:GetOwner():RemoveAmmo( num, self:GetPrimaryAmmoType() )
|
||||
|
||||
return end
|
||||
|
||||
self:SetClip1( self:Clip1() - num )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:TakeSecondaryAmmo()
|
||||
Desc: A convenience function to remove ammo
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:TakeSecondaryAmmo( num )
|
||||
|
||||
-- Doesn't use clips
|
||||
if ( self:Clip2() <= 0 ) then
|
||||
|
||||
if ( self:Ammo2() <= 0 ) then return end
|
||||
|
||||
self:GetOwner():RemoveAmmo( num, self:GetSecondaryAmmoType() )
|
||||
|
||||
return end
|
||||
|
||||
self:SetClip2( self:Clip2() - num )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:CanPrimaryAttack()
|
||||
Desc: Helper function for checking for no ammo
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:CanPrimaryAttack()
|
||||
|
||||
if ( self:Clip1() <= 0 ) then
|
||||
|
||||
self:EmitSound( "Weapon_Pistol.Empty" )
|
||||
self:SetNextPrimaryFire( CurTime() + 0.2 )
|
||||
self:Reload()
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SWEP:CanSecondaryAttack()
|
||||
Desc: Helper function for checking for no ammo
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:CanSecondaryAttack()
|
||||
|
||||
if ( self:Clip2() <= 0 ) then
|
||||
|
||||
self:EmitSound( "Weapon_Pistol.Empty" )
|
||||
self:SetNextSecondaryFire( CurTime() + 0.2 )
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRemove
|
||||
Desc: Called just before entity is deleted
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:OnRemove()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OwnerChanged
|
||||
Desc: When weapon is dropped or picked up by a new player
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:OwnerChanged()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Ammo1
|
||||
Desc: Returns how much of ammo1 the player has
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:Ammo1()
|
||||
return self:GetOwner():GetAmmoCount( self:GetPrimaryAmmoType() )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Ammo2
|
||||
Desc: Returns how much of ammo2 the player has
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:Ammo2()
|
||||
return self:GetOwner():GetAmmoCount( self:GetSecondaryAmmoType() )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: DoImpactEffect
|
||||
Desc: Callback so the weapon can override the impact effects it makes
|
||||
return true to not do the default thing - which is to call UTIL_ImpactTrace in c++
|
||||
-----------------------------------------------------------]]
|
||||
function SWEP:DoImpactEffect( tr, nDamageType )
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
406
gamemodes/base/gamemode/animations.lua
Normal file
406
gamemodes/base/gamemode/animations.lua
Normal file
@@ -0,0 +1,406 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
function GM:HandlePlayerJumping( ply, velocity, plyTable )
|
||||
|
||||
if ( !plyTable ) then plyTable = ply:GetTable() end
|
||||
|
||||
if ( ply:GetMoveType() == MOVETYPE_NOCLIP ) then
|
||||
plyTable.m_bJumping = false
|
||||
return
|
||||
end
|
||||
|
||||
-- airwalk more like hl2mp, we airwalk until we have 0 velocity, then it's the jump animation
|
||||
-- underwater we're alright we airwalking
|
||||
if ( !plyTable.m_bJumping && !ply:OnGround() && ply:WaterLevel() <= 0 ) then
|
||||
|
||||
if ( !plyTable.m_fGroundTime ) then
|
||||
|
||||
plyTable.m_fGroundTime = CurTime()
|
||||
|
||||
elseif ( ( CurTime() - plyTable.m_fGroundTime ) > 0 && velocity:Length2DSqr() < 0.25 ) then
|
||||
|
||||
plyTable.m_bJumping = true
|
||||
plyTable.m_bFirstJumpFrame = false
|
||||
plyTable.m_flJumpStartTime = 0
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
if ( plyTable.m_bJumping ) then
|
||||
|
||||
if ( plyTable.m_bFirstJumpFrame ) then
|
||||
|
||||
plyTable.m_bFirstJumpFrame = false
|
||||
ply:AnimRestartMainSequence()
|
||||
|
||||
end
|
||||
|
||||
if ( ( ply:WaterLevel() >= 2 ) || ( ( CurTime() - plyTable.m_flJumpStartTime ) > 0.2 && ply:OnGround() ) ) then
|
||||
|
||||
plyTable.m_bJumping = false
|
||||
plyTable.m_fGroundTime = nil
|
||||
ply:AnimRestartMainSequence()
|
||||
|
||||
end
|
||||
|
||||
if ( plyTable.m_bJumping ) then
|
||||
plyTable.CalcIdeal = ACT_MP_JUMP
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
function GM:HandlePlayerDucking( ply, velocity, plyTable )
|
||||
|
||||
if ( !plyTable ) then plyTable = ply:GetTable() end
|
||||
|
||||
if ( !ply:IsFlagSet( FL_ANIMDUCKING ) ) then return false end
|
||||
|
||||
if ( velocity:Length2DSqr() > 0.25 ) then
|
||||
plyTable.CalcIdeal = ACT_MP_CROUCHWALK
|
||||
else
|
||||
plyTable.CalcIdeal = ACT_MP_CROUCH_IDLE
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function GM:HandlePlayerNoClipping( ply, velocity, plyTable )
|
||||
|
||||
if ( !plyTable ) then plyTable = ply:GetTable() end
|
||||
|
||||
if ( ply:GetMoveType() != MOVETYPE_NOCLIP || ply:InVehicle() ) then
|
||||
|
||||
if ( plyTable.m_bWasNoclipping ) then
|
||||
|
||||
plyTable.m_bWasNoclipping = nil
|
||||
ply:AnimResetGestureSlot( GESTURE_SLOT_CUSTOM )
|
||||
if ( CLIENT ) then ply:SetIK( true ) end
|
||||
|
||||
end
|
||||
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
if ( !plyTable.m_bWasNoclipping ) then
|
||||
|
||||
ply:AnimRestartGesture( GESTURE_SLOT_CUSTOM, ACT_GMOD_NOCLIP_LAYER, false )
|
||||
if ( CLIENT ) then ply:SetIK( false ) end
|
||||
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function GM:HandlePlayerVaulting( ply, velocity, plyTable )
|
||||
|
||||
if ( !plyTable ) then plyTable = ply:GetTable() end
|
||||
|
||||
if ( velocity:LengthSqr() < 1000000 ) then return end
|
||||
if ( ply:IsOnGround() ) then return end
|
||||
|
||||
plyTable.CalcIdeal = ACT_MP_SWIM
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function GM:HandlePlayerSwimming( ply, velocity, plyTable )
|
||||
|
||||
if ( !plyTable ) then plyTable = ply:GetTable() end
|
||||
|
||||
if ( ply:WaterLevel() < 2 || ply:IsOnGround() ) then
|
||||
plyTable.m_bInSwim = false
|
||||
return false
|
||||
end
|
||||
|
||||
plyTable.CalcIdeal = ACT_MP_SWIM
|
||||
plyTable.m_bInSwim = true
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
function GM:HandlePlayerLanding( ply, velocity, WasOnGround )
|
||||
|
||||
if ( ply:GetMoveType() == MOVETYPE_NOCLIP ) then return end
|
||||
|
||||
if ( ply:IsOnGround() && !WasOnGround ) then
|
||||
ply:AnimRestartGesture( GESTURE_SLOT_JUMP, ACT_LAND, true )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function GM:HandlePlayerDriving( ply, plyTable )
|
||||
|
||||
if ( !plyTable ) then plyTable = ply:GetTable() end
|
||||
|
||||
-- The player must have a parent to be in a vehicle. If there's no parent, we are in the exit anim, so don't do sitting in 3rd person anymore
|
||||
if ( !ply:InVehicle() || !IsValid( ply:GetParent() ) ) then return false end
|
||||
|
||||
local pVehicle = ply:GetVehicle()
|
||||
|
||||
if ( !pVehicle.HandleAnimation && pVehicle.GetVehicleClass ) then
|
||||
local c = pVehicle:GetVehicleClass()
|
||||
local t = list.Get( "Vehicles" )[ c ]
|
||||
if ( t && t.Members && t.Members.HandleAnimation ) then
|
||||
pVehicle.HandleAnimation = t.Members.HandleAnimation
|
||||
else
|
||||
pVehicle.HandleAnimation = true -- Prevent this if block from trying to assign HandleAnimation again.
|
||||
end
|
||||
end
|
||||
|
||||
if ( isfunction( pVehicle.HandleAnimation ) ) then
|
||||
local seq = pVehicle:HandleAnimation( ply )
|
||||
if ( seq != nil ) then
|
||||
plyTable.CalcSeqOverride = seq
|
||||
end
|
||||
end
|
||||
|
||||
if ( plyTable.CalcSeqOverride == -1 ) then -- pVehicle.HandleAnimation did not give us an animation
|
||||
local class = pVehicle:GetClass()
|
||||
if ( class == "prop_vehicle_jeep" ) then
|
||||
plyTable.CalcSeqOverride = ply:LookupSequence( "drive_jeep" )
|
||||
elseif ( class == "prop_vehicle_airboat" ) then
|
||||
plyTable.CalcSeqOverride = ply:LookupSequence( "drive_airboat" )
|
||||
elseif ( class == "prop_vehicle_prisoner_pod" && pVehicle:GetModel() == "models/vehicles/prisoner_pod_inner.mdl" ) then
|
||||
-- HACK!!
|
||||
plyTable.CalcSeqOverride = ply:LookupSequence( "drive_pd" )
|
||||
else
|
||||
plyTable.CalcSeqOverride = ply:LookupSequence( "sit_rollercoaster" )
|
||||
end
|
||||
end
|
||||
|
||||
local use_anims = ( plyTable.CalcSeqOverride == ply:LookupSequence( "sit_rollercoaster" ) || plyTable.CalcSeqOverride == ply:LookupSequence( "sit" ) )
|
||||
if ( use_anims && ply:GetAllowWeaponsInVehicle() && IsValid( ply:GetActiveWeapon() ) ) then
|
||||
local holdtype = ply:GetActiveWeapon():GetHoldType()
|
||||
if ( holdtype == "smg" ) then holdtype = "smg1" end
|
||||
|
||||
local seqid = ply:LookupSequence( "sit_" .. holdtype )
|
||||
if ( seqid != -1 ) then
|
||||
plyTable.CalcSeqOverride = seqid
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:UpdateAnimation()
|
||||
Desc: Animation updates (pose params etc) should be done here
|
||||
-----------------------------------------------------------]]
|
||||
function GM:UpdateAnimation( ply, velocity, maxseqgroundspeed )
|
||||
|
||||
local len = velocity:Length()
|
||||
local movement = 1.0
|
||||
|
||||
if ( len > 0.2 ) then
|
||||
movement = ( len / maxseqgroundspeed )
|
||||
end
|
||||
|
||||
local rate = math.min( movement, 2 )
|
||||
|
||||
-- if we're under water we want to constantly be swimming..
|
||||
if ( ply:WaterLevel() >= 2 ) then
|
||||
rate = math.max( rate, 0.5 )
|
||||
elseif ( !ply:IsOnGround() && len >= 1000 ) then
|
||||
rate = 0.1
|
||||
end
|
||||
|
||||
ply:SetPlaybackRate( rate )
|
||||
|
||||
-- We only need to do this clientside..
|
||||
if ( CLIENT ) then
|
||||
if ( ply:InVehicle() ) then
|
||||
--
|
||||
-- This is used for the 'rollercoaster' arms
|
||||
--
|
||||
local Vehicle = ply:GetVehicle()
|
||||
local Velocity = Vehicle:GetVelocity()
|
||||
local fwd = Vehicle:GetUp()
|
||||
local dp = fwd:Dot( Vector( 0, 0, 1 ) )
|
||||
|
||||
ply:SetPoseParameter( "vertical_velocity", ( dp < 0 && dp || 0 ) + fwd:Dot( Velocity ) * 0.005 )
|
||||
|
||||
-- Pass the vehicles steer param down to the player
|
||||
local steer = Vehicle:GetPoseParameter( "vehicle_steer" )
|
||||
steer = steer * 2 - 1 -- convert from 0..1 to -1..1
|
||||
if ( Vehicle:GetClass() == "prop_vehicle_prisoner_pod" ) then steer = 0 ply:SetPoseParameter( "aim_yaw", math.NormalizeAngle( ply:GetAimVector():Angle().y - Vehicle:GetAngles().y - 90 ) ) end
|
||||
ply:SetPoseParameter( "vehicle_steer", steer )
|
||||
|
||||
end
|
||||
|
||||
GAMEMODE:GrabEarAnimation( ply )
|
||||
GAMEMODE:MouthMoveAnimation( ply )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- If you don't want the player to grab his ear in your gamemode then
|
||||
-- just override this.
|
||||
--
|
||||
function GM:GrabEarAnimation( ply, plyTable )
|
||||
|
||||
if ( !plyTable ) then plyTable = ply:GetTable() end
|
||||
|
||||
plyTable.ChatGestureWeight = plyTable.ChatGestureWeight || 0
|
||||
|
||||
-- Don't show this when we're playing a taunt!
|
||||
if ( ply:IsPlayingTaunt() ) then return end
|
||||
|
||||
if ( ply:IsTyping() ) then
|
||||
plyTable.ChatGestureWeight = math.Approach( plyTable.ChatGestureWeight, 1, FrameTime() * 5.0 )
|
||||
else
|
||||
plyTable.ChatGestureWeight = math.Approach( plyTable.ChatGestureWeight, 0, FrameTime() * 5.0 )
|
||||
end
|
||||
|
||||
if ( plyTable.ChatGestureWeight > 0 ) then
|
||||
|
||||
ply:AnimRestartGesture( GESTURE_SLOT_VCD, ACT_GMOD_IN_CHAT, true )
|
||||
ply:AnimSetGestureWeight( GESTURE_SLOT_VCD, plyTable.ChatGestureWeight )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Moves the mouth when talking on voicecom
|
||||
--
|
||||
function GM:MouthMoveAnimation( ply )
|
||||
|
||||
local flexes = {
|
||||
ply:GetFlexIDByName( "jaw_drop" ),
|
||||
ply:GetFlexIDByName( "left_part" ),
|
||||
ply:GetFlexIDByName( "right_part" ),
|
||||
ply:GetFlexIDByName( "left_mouth_drop" ),
|
||||
ply:GetFlexIDByName( "right_mouth_drop" )
|
||||
}
|
||||
|
||||
local weight = ply:IsSpeaking() && math.Clamp( ply:VoiceVolume() * 2, 0, 2 ) || 0
|
||||
|
||||
for k, v in ipairs( flexes ) do
|
||||
|
||||
ply:SetFlexWeight( v, weight )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function GM:CalcMainActivity( ply, velocity )
|
||||
|
||||
local plyTable = ply:GetTable()
|
||||
plyTable.CalcIdeal = ACT_MP_STAND_IDLE
|
||||
plyTable.CalcSeqOverride = -1
|
||||
|
||||
self:HandlePlayerLanding( ply, velocity, plyTable.m_bWasOnGround )
|
||||
|
||||
if !( self:HandlePlayerNoClipping( ply, velocity, plyTable ) ||
|
||||
self:HandlePlayerDriving( ply, plyTable ) ||
|
||||
self:HandlePlayerVaulting( ply, velocity, plyTable ) ||
|
||||
self:HandlePlayerJumping( ply, velocity, plyTable ) ||
|
||||
self:HandlePlayerSwimming( ply, velocity, plyTable ) ||
|
||||
self:HandlePlayerDucking( ply, velocity, plyTable ) ) then
|
||||
|
||||
local len2d = velocity:Length2DSqr()
|
||||
if ( len2d > 22500 ) then plyTable.CalcIdeal = ACT_MP_RUN elseif ( len2d > 0.25 ) then plyTable.CalcIdeal = ACT_MP_WALK end
|
||||
|
||||
end
|
||||
|
||||
plyTable.m_bWasOnGround = ply:IsOnGround()
|
||||
plyTable.m_bWasNoclipping = ( ply:GetMoveType() == MOVETYPE_NOCLIP && !ply:InVehicle() )
|
||||
|
||||
return plyTable.CalcIdeal, plyTable.CalcSeqOverride
|
||||
|
||||
end
|
||||
|
||||
local IdleActivity = ACT_HL2MP_IDLE
|
||||
local IdleActivityTranslate = {}
|
||||
IdleActivityTranslate[ ACT_MP_STAND_IDLE ] = IdleActivity
|
||||
IdleActivityTranslate[ ACT_MP_WALK ] = IdleActivity + 1
|
||||
IdleActivityTranslate[ ACT_MP_RUN ] = IdleActivity + 2
|
||||
IdleActivityTranslate[ ACT_MP_CROUCH_IDLE ] = IdleActivity + 3
|
||||
IdleActivityTranslate[ ACT_MP_CROUCHWALK ] = IdleActivity + 4
|
||||
IdleActivityTranslate[ ACT_MP_ATTACK_STAND_PRIMARYFIRE ] = IdleActivity + 5
|
||||
IdleActivityTranslate[ ACT_MP_ATTACK_CROUCH_PRIMARYFIRE ] = IdleActivity + 5
|
||||
IdleActivityTranslate[ ACT_MP_RELOAD_STAND ] = IdleActivity + 6
|
||||
IdleActivityTranslate[ ACT_MP_RELOAD_CROUCH ] = IdleActivity + 6
|
||||
IdleActivityTranslate[ ACT_MP_JUMP ] = ACT_HL2MP_JUMP_SLAM
|
||||
IdleActivityTranslate[ ACT_MP_SWIM ] = IdleActivity + 9
|
||||
IdleActivityTranslate[ ACT_LAND ] = ACT_LAND
|
||||
|
||||
-- it is preferred you return ACT_MP_* in CalcMainActivity, and if you have a specific need to not translate through the weapon do it here
|
||||
function GM:TranslateActivity( ply, act )
|
||||
|
||||
local newact = ply:TranslateWeaponActivity( act )
|
||||
|
||||
-- select idle anims if the weapon didn't decide
|
||||
if ( act == newact ) then
|
||||
return IdleActivityTranslate[ act ]
|
||||
end
|
||||
|
||||
return newact
|
||||
|
||||
end
|
||||
|
||||
function GM:DoAnimationEvent( ply, event, data )
|
||||
|
||||
if ( event == PLAYERANIMEVENT_ATTACK_PRIMARY ) then
|
||||
|
||||
if ply:IsFlagSet( FL_ANIMDUCKING ) then
|
||||
ply:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_CROUCH_PRIMARYFIRE, true )
|
||||
else
|
||||
ply:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_ATTACK_STAND_PRIMARYFIRE, true )
|
||||
end
|
||||
|
||||
return ACT_VM_PRIMARYATTACK
|
||||
|
||||
elseif ( event == PLAYERANIMEVENT_ATTACK_SECONDARY ) then
|
||||
|
||||
-- there is no gesture, so just fire off the VM event
|
||||
return ACT_VM_SECONDARYATTACK
|
||||
|
||||
elseif ( event == PLAYERANIMEVENT_RELOAD ) then
|
||||
|
||||
if ply:IsFlagSet( FL_ANIMDUCKING ) then
|
||||
ply:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_CROUCH, true )
|
||||
else
|
||||
ply:AnimRestartGesture( GESTURE_SLOT_ATTACK_AND_RELOAD, ACT_MP_RELOAD_STAND, true )
|
||||
end
|
||||
|
||||
return ACT_INVALID
|
||||
|
||||
elseif ( event == PLAYERANIMEVENT_JUMP ) then
|
||||
|
||||
ply.m_bJumping = true
|
||||
ply.m_bFirstJumpFrame = true
|
||||
ply.m_flJumpStartTime = CurTime()
|
||||
|
||||
ply:AnimRestartMainSequence()
|
||||
|
||||
return ACT_INVALID
|
||||
|
||||
elseif ( event == PLAYERANIMEVENT_CANCEL_RELOAD ) then
|
||||
|
||||
ply:AnimResetGestureSlot( GESTURE_SLOT_ATTACK_AND_RELOAD )
|
||||
|
||||
return ACT_INVALID
|
||||
end
|
||||
|
||||
end
|
||||
302
gamemodes/base/gamemode/cl_deathnotice.lua
Normal file
302
gamemodes/base/gamemode/cl_deathnotice.lua
Normal file
@@ -0,0 +1,302 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
local hud_deathnotice_time = CreateConVar( "hud_deathnotice_time", "6", FCVAR_REPLICATED, "Amount of time to show death notice (kill feed) for" )
|
||||
local cl_drawhud = GetConVar( "cl_drawhud" )
|
||||
|
||||
-- These are our kill icons
|
||||
local Color_Icon = Color( 255, 80, 0, 255 )
|
||||
local NPC_Color_Enemy = Color( 250, 50, 50, 255 )
|
||||
local NPC_Color_Friendly = Color( 50, 200, 50, 255 )
|
||||
|
||||
killicon.AddFont( "prop_physics", "HL2MPTypeDeath", "9", Color_Icon, 0.52 )
|
||||
killicon.AddFont( "weapon_smg1", "HL2MPTypeDeath", "/", Color_Icon, 0.55 )
|
||||
killicon.AddFont( "weapon_357", "HL2MPTypeDeath", ".", Color_Icon, 0.55 )
|
||||
killicon.AddFont( "weapon_ar2", "HL2MPTypeDeath", "2", Color_Icon, 0.6 )
|
||||
killicon.AddFont( "crossbow_bolt", "HL2MPTypeDeath", "1", Color_Icon, 0.5 )
|
||||
killicon.AddFont( "weapon_shotgun", "HL2MPTypeDeath", "0", Color_Icon, 0.45 )
|
||||
killicon.AddFont( "rpg_missile", "HL2MPTypeDeath", "3", Color_Icon, 0.35 )
|
||||
killicon.AddFont( "npc_grenade_frag", "HL2MPTypeDeath", "4", Color_Icon, 0.56 )
|
||||
killicon.AddFont( "weapon_pistol", "HL2MPTypeDeath", "-", Color_Icon, 0.52 )
|
||||
killicon.AddFont( "prop_combine_ball", "HL2MPTypeDeath", "8", Color_Icon, 0.5 )
|
||||
killicon.AddFont( "grenade_ar2", "HL2MPTypeDeath", "7", Color_Icon, 0.35 )
|
||||
killicon.AddFont( "weapon_stunstick", "HL2MPTypeDeath", "!", Color_Icon, 0.6 )
|
||||
killicon.AddFont( "npc_satchel", "HL2MPTypeDeath", "*", Color_Icon, 0.53 )
|
||||
killicon.AddAlias( "npc_tripmine", "npc_satchel" )
|
||||
killicon.AddFont( "weapon_crowbar", "HL2MPTypeDeath", "6", Color_Icon, 0.45 )
|
||||
killicon.AddFont( "weapon_physcannon", "HL2MPTypeDeath", ",", Color_Icon, 0.55 )
|
||||
|
||||
-- Prop like objects get the prop kill icon
|
||||
killicon.AddAlias( "prop_ragdoll", "prop_physics" )
|
||||
killicon.AddAlias( "prop_physics_respawnable", "prop_physics" )
|
||||
killicon.AddAlias( "func_physbox", "prop_physics" )
|
||||
killicon.AddAlias( "func_physbox_multiplayer", "prop_physics" )
|
||||
killicon.AddAlias( "trigger_vphysics_motion", "prop_physics" )
|
||||
killicon.AddAlias( "func_movelinear", "prop_physics" )
|
||||
killicon.AddAlias( "func_plat", "prop_physics" )
|
||||
killicon.AddAlias( "func_platrot", "prop_physics" )
|
||||
killicon.AddAlias( "func_pushable", "prop_physics" )
|
||||
killicon.AddAlias( "func_rotating", "prop_physics" )
|
||||
killicon.AddAlias( "func_rot_button", "prop_physics" )
|
||||
killicon.AddAlias( "func_tracktrain", "prop_physics" )
|
||||
killicon.AddAlias( "func_train", "prop_physics" )
|
||||
|
||||
local function HandleAchievements( victimType )
|
||||
|
||||
-- Try to find by name
|
||||
for id, tab in pairs( list.Get( "NPC" ) ) do
|
||||
if ( tab.Name == victimType ) then
|
||||
victimType = tab.Class
|
||||
end
|
||||
end
|
||||
-- If fails, try to omit the translation system #
|
||||
if ( victimType:StartsWith( "#" ) ) then
|
||||
victimType = victimType:sub( 2 )
|
||||
end
|
||||
|
||||
local bIsEnemy = IsEnemyEntityName( victimType )
|
||||
local bIsFriend = IsFriendEntityName( victimType )
|
||||
|
||||
if ( bIsEnemy ) then
|
||||
achievements.IncBaddies()
|
||||
end
|
||||
|
||||
if ( bIsFriend ) then
|
||||
achievements.IncGoodies()
|
||||
end
|
||||
|
||||
if ( !bIsFriend && !bIsEnemy ) then
|
||||
achievements.IncBystander()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Backwards compatiblity for addons
|
||||
net.Receive( "PlayerKilledByPlayer", function()
|
||||
|
||||
local victim = net.ReadEntity()
|
||||
local inflictor = net.ReadString()
|
||||
local attacker = net.ReadEntity()
|
||||
|
||||
if ( !IsValid( attacker ) ) then return end
|
||||
if ( !IsValid( victim ) ) then return end
|
||||
|
||||
hook.Run( "AddDeathNotice", attacker:Name(), attacker:Team(), inflictor, victim:Name(), victim:Team(), 0 )
|
||||
|
||||
end )
|
||||
|
||||
net.Receive( "PlayerKilledSelf", function()
|
||||
|
||||
local victim = net.ReadEntity()
|
||||
if ( !IsValid( victim ) ) then return end
|
||||
|
||||
hook.Run( "AddDeathNotice", nil, 0, "suicide", victim:Name(), victim:Team(), 0 )
|
||||
|
||||
end )
|
||||
|
||||
net.Receive( "PlayerKilled", function()
|
||||
|
||||
local victim = net.ReadEntity()
|
||||
if ( !IsValid( victim ) ) then return end
|
||||
|
||||
local inflictor = net.ReadString()
|
||||
local attacker = net.ReadString()
|
||||
|
||||
hook.Run( "AddDeathNotice", "#" .. attacker, -1, inflictor, victim:Name(), victim:Team(), 0 )
|
||||
|
||||
end )
|
||||
|
||||
net.Receive( "PlayerKilledNPC", function()
|
||||
|
||||
local victimtype = net.ReadString()
|
||||
local inflictor = net.ReadString()
|
||||
local attacker = net.ReadEntity()
|
||||
|
||||
--
|
||||
-- For some reason the killer isn't known to us, so don't proceed.
|
||||
--
|
||||
if ( !IsValid( attacker ) ) then return end
|
||||
|
||||
hook.Run( "AddDeathNotice", attacker:Name(), attacker:Team(), inflictor, "#" .. victimtype, -1, 0 )
|
||||
|
||||
local bIsLocalPlayer = ( IsValid( attacker ) && attacker == LocalPlayer() )
|
||||
if ( bIsLocalPlayer ) then
|
||||
HandleAchievements( victimtype )
|
||||
end
|
||||
|
||||
end )
|
||||
|
||||
net.Receive( "NPCKilledNPC", function()
|
||||
|
||||
local victim = "#" .. net.ReadString()
|
||||
local inflictor = net.ReadString()
|
||||
local attacker = "#" .. net.ReadString()
|
||||
|
||||
hook.Run( "AddDeathNotice", attacker, -1, inflictor, victim, -1, 0 )
|
||||
|
||||
end )
|
||||
|
||||
-- The new way
|
||||
DEATH_NOTICE_FRIENDLY_VICTIM = 1
|
||||
DEATH_NOTICE_FRIENDLY_ATTACKER = 2
|
||||
--DEATH_NOTICE_HEADSHOT = 4
|
||||
--DEATH_NOTICE_PENETRATION = 8
|
||||
net.Receive( "DeathNoticeEvent", function()
|
||||
|
||||
local attacker = nil
|
||||
local attackerType = net.ReadUInt( 2 )
|
||||
if ( attackerType == 1 ) then
|
||||
attacker = net.ReadString()
|
||||
elseif ( attackerType == 2 ) then
|
||||
attacker = net.ReadEntity()
|
||||
end
|
||||
|
||||
local inflictor = net.ReadString()
|
||||
|
||||
local victim = nil
|
||||
local victimType = net.ReadUInt( 2 )
|
||||
if ( victimType == 1 ) then
|
||||
victim = net.ReadString()
|
||||
elseif ( victimType == 2 ) then
|
||||
victim = net.ReadEntity()
|
||||
end
|
||||
|
||||
local flags = net.ReadUInt( 8 )
|
||||
|
||||
local bIsLocalPlayer = ( isentity( attacker ) && IsValid( attacker ) && attacker == LocalPlayer() )
|
||||
if ( bIsLocalPlayer && isstring( victim ) ) then
|
||||
HandleAchievements( victim )
|
||||
end
|
||||
|
||||
local team_a = -1
|
||||
local team_v = -1
|
||||
if ( bit.band( flags, DEATH_NOTICE_FRIENDLY_VICTIM ) != 0 ) then team_v = -2 end
|
||||
if ( bit.band( flags, DEATH_NOTICE_FRIENDLY_ATTACKER ) != 0 ) then team_a = -2 end
|
||||
|
||||
-- Handle player entities
|
||||
if ( isentity( attacker ) and attacker:IsValid() and attacker:IsPlayer() ) then team_a = attacker:Team() attacker = attacker:Name() end
|
||||
if ( isentity( victim ) and victim:IsValid() and victim:IsPlayer() ) then team_v = victim:Team() victim = victim:Name() end
|
||||
|
||||
-- Handle other entities
|
||||
if ( isentity( attacker ) and attacker:IsValid() ) then attacker = attacker:GetClass() end
|
||||
if ( isentity( victim ) and victim:IsValid() ) then victim = victim:GetClass() end
|
||||
|
||||
hook.Run( "AddDeathNotice", attacker, team_a, inflictor, victim, team_v, flags )
|
||||
|
||||
end )
|
||||
|
||||
local Deaths = {}
|
||||
|
||||
local function getDeathColor( teamID, target )
|
||||
|
||||
if ( teamID == -1 ) then
|
||||
return table.Copy( NPC_Color_Enemy )
|
||||
end
|
||||
|
||||
if ( teamID == -2 ) then
|
||||
return table.Copy( NPC_Color_Friendly )
|
||||
end
|
||||
|
||||
return table.Copy( team.GetColor( teamID ) )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:AddDeathNotice( Attacker, team1, Inflictor, Victim, team2, flags )
|
||||
Desc: Adds an death notice entry
|
||||
-----------------------------------------------------------]]
|
||||
function GM:AddDeathNotice( attacker, team1, inflictor, victim, team2, flags )
|
||||
|
||||
if ( inflictor == "suicide" ) then attacker = nil end
|
||||
|
||||
local Death = {}
|
||||
Death.time = CurTime()
|
||||
|
||||
Death.left = attacker
|
||||
Death.right = victim
|
||||
Death.icon = inflictor
|
||||
Death.flags = flags
|
||||
|
||||
Death.color1 = getDeathColor( team1, Death.left )
|
||||
Death.color2 = getDeathColor( team2, Death.right )
|
||||
|
||||
table.insert( Deaths, Death )
|
||||
|
||||
end
|
||||
|
||||
local function DrawDeath( x, y, death, time )
|
||||
|
||||
local w, h = killicon.GetSize( death.icon )
|
||||
if ( !w or !h ) then return end
|
||||
|
||||
local fadeout = ( death.time + time ) - CurTime()
|
||||
|
||||
local alpha = math.Clamp( fadeout * 255, 0, 255 )
|
||||
death.color1.a = alpha
|
||||
death.color2.a = alpha
|
||||
|
||||
-- Draw Icon
|
||||
killicon.Render( x - w / 2, y, death.icon, alpha )
|
||||
|
||||
-- Draw KILLER
|
||||
if ( death.left ) then
|
||||
draw.SimpleText( death.left, "ChatFont", x - ( w / 2 ) - 16, y + h / 2, death.color1, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER )
|
||||
end
|
||||
|
||||
-- Draw VICTIM
|
||||
draw.SimpleText( death.right, "ChatFont", x + ( w / 2 ) + 16, y + h / 2, death.color2, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER )
|
||||
|
||||
return math.ceil( y + h * 0.75 )
|
||||
|
||||
-- Font killicons are too high when height corrected, and changing that is not backwards compatible
|
||||
--return math.ceil( y + math.max( h, 28 ) )
|
||||
|
||||
end
|
||||
|
||||
function GM:DrawDeathNotice( x, y )
|
||||
|
||||
if ( cl_drawhud:GetInt() == 0 ) then return end
|
||||
|
||||
local time = hud_deathnotice_time:GetFloat()
|
||||
local reset = Deaths[1] != nil -- Don't reset it if there's nothing in it
|
||||
|
||||
x = x * ScrW()
|
||||
y = y * ScrH()
|
||||
|
||||
-- Draw
|
||||
for k, Death in ipairs( Deaths ) do
|
||||
|
||||
if ( Death.time + time > CurTime() ) then
|
||||
|
||||
if ( Death.lerp ) then
|
||||
x = x * 0.3 + Death.lerp.x * 0.7
|
||||
y = y * 0.3 + Death.lerp.y * 0.7
|
||||
end
|
||||
|
||||
Death.lerp = Death.lerp or {}
|
||||
Death.lerp.x = x
|
||||
Death.lerp.y = y
|
||||
|
||||
y = DrawDeath( math.floor( x ), math.floor( y ), Death, time )
|
||||
reset = false
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- We want to maintain the order of the table so instead of removing
|
||||
-- expired entries one by one we will just clear the entire table
|
||||
-- once everything is expired.
|
||||
if ( reset ) then
|
||||
Deaths = {}
|
||||
end
|
||||
|
||||
end
|
||||
183
gamemodes/base/gamemode/cl_hudpickup.lua
Normal file
183
gamemodes/base/gamemode/cl_hudpickup.lua
Normal file
@@ -0,0 +1,183 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
GM.PickupHistory = {}
|
||||
GM.PickupHistoryLast = 0
|
||||
GM.PickupHistoryTop = ScrH() / 2
|
||||
GM.PickupHistoryWide = 300
|
||||
GM.PickupHistoryCorner = surface.GetTextureID( "gui/corner8" )
|
||||
|
||||
local function AddGenericPickup( self, itemname )
|
||||
local pickup = {}
|
||||
pickup.time = CurTime()
|
||||
pickup.name = itemname
|
||||
pickup.holdtime = 5
|
||||
pickup.font = "DermaDefaultBold"
|
||||
pickup.fadein = 0.04
|
||||
pickup.fadeout = 0.3
|
||||
|
||||
surface.SetFont( pickup.font )
|
||||
local w, h = surface.GetTextSize( pickup.name )
|
||||
pickup.height = h
|
||||
pickup.width = w
|
||||
|
||||
--[[if ( self.PickupHistoryLast >= pickup.time ) then
|
||||
pickup.time = self.PickupHistoryLast + 0.05
|
||||
end]]
|
||||
|
||||
table.insert( self.PickupHistory, pickup )
|
||||
self.PickupHistoryLast = pickup.time
|
||||
|
||||
return pickup
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HUDWeaponPickedUp( wep )
|
||||
Desc: The game wants you to draw on the HUD that a weapon has been picked up
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HUDWeaponPickedUp( wep )
|
||||
|
||||
if ( !IsValid( LocalPlayer() ) || !LocalPlayer():Alive() ) then return end
|
||||
if ( !IsValid( wep ) ) then return end
|
||||
if ( !isfunction( wep.GetPrintName ) ) then return end
|
||||
|
||||
local pickup = AddGenericPickup( self, wep:GetPrintName() )
|
||||
pickup.color = Color( 255, 200, 50, 255 )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HUDItemPickedUp( itemname )
|
||||
Desc: An item has been picked up..
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HUDItemPickedUp( itemname )
|
||||
|
||||
if ( !IsValid( LocalPlayer() ) || !LocalPlayer():Alive() ) then return end
|
||||
|
||||
local pickup = AddGenericPickup( self, "#" .. itemname )
|
||||
pickup.color = Color( 180, 255, 180, 255 )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HUDAmmoPickedUp( itemname, amount )
|
||||
Desc: Ammo has been picked up..
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HUDAmmoPickedUp( itemname, amount )
|
||||
|
||||
if ( !IsValid( LocalPlayer() ) || !LocalPlayer():Alive() ) then return end
|
||||
|
||||
-- Try to tack it onto an exisiting ammo pickup
|
||||
if ( self.PickupHistory ) then
|
||||
|
||||
for k, v in pairs( self.PickupHistory ) do
|
||||
|
||||
if ( v.name == "#" .. itemname .. "_ammo" ) then
|
||||
|
||||
v.amount = tostring( tonumber( v.amount ) + amount )
|
||||
v.time = CurTime() - v.fadein
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local pickup = AddGenericPickup( self, "#" .. itemname .. "_ammo" )
|
||||
pickup.color = Color( 180, 200, 255, 255 )
|
||||
pickup.amount = tostring( amount )
|
||||
|
||||
local w, h = surface.GetTextSize( pickup.amount )
|
||||
pickup.width = pickup.width + w + 16
|
||||
|
||||
end
|
||||
|
||||
function GM:HUDDrawPickupHistory()
|
||||
|
||||
if ( self.PickupHistory == nil ) then return end
|
||||
|
||||
local x, y = ScrW() - self.PickupHistoryWide - 20, self.PickupHistoryTop
|
||||
local tall = 0
|
||||
local wide = 0
|
||||
|
||||
for k, v in pairs( self.PickupHistory ) do
|
||||
|
||||
if ( !istable( v ) ) then
|
||||
|
||||
Msg( tostring( v ) .. "\n" )
|
||||
PrintTable( self.PickupHistory )
|
||||
self.PickupHistory[ k ] = nil
|
||||
return
|
||||
end
|
||||
|
||||
if ( v.time < CurTime() ) then
|
||||
|
||||
if ( v.y == nil ) then v.y = y end
|
||||
|
||||
v.y = ( v.y * 5 + y ) / 6
|
||||
|
||||
local delta = ( v.time + v.holdtime ) - CurTime()
|
||||
delta = delta / v.holdtime
|
||||
|
||||
local alpha = 255
|
||||
local colordelta = math.Clamp( delta, 0.6, 0.7 )
|
||||
|
||||
-- Fade in/out
|
||||
if ( delta > 1 - v.fadein ) then
|
||||
alpha = math.Clamp( ( 1.0 - delta ) * ( 255 / v.fadein ), 0, 255 )
|
||||
elseif ( delta < v.fadeout ) then
|
||||
alpha = math.Clamp( delta * ( 255 / v.fadeout ), 0, 255 )
|
||||
end
|
||||
|
||||
v.x = x + self.PickupHistoryWide - ( self.PickupHistoryWide * ( alpha / 255 ) )
|
||||
|
||||
local rx, ry, rw, rh = math.Round( v.x - 4 ), math.Round( v.y - ( v.height / 2 ) - 4 ), math.Round( self.PickupHistoryWide + 9 ), math.Round( v.height + 8 )
|
||||
local bordersize = 8
|
||||
|
||||
surface.SetTexture( self.PickupHistoryCorner )
|
||||
|
||||
surface.SetDrawColor( v.color.r, v.color.g, v.color.b, alpha )
|
||||
surface.DrawTexturedRectRotated( rx + bordersize / 2, ry + bordersize / 2, bordersize, bordersize, 0 )
|
||||
surface.DrawTexturedRectRotated( rx + bordersize / 2, ry + rh -bordersize / 2, bordersize, bordersize, 90 )
|
||||
surface.DrawRect( rx, ry + bordersize, bordersize, rh-bordersize * 2 )
|
||||
surface.DrawRect( rx + bordersize, ry, v.height - 4, rh )
|
||||
|
||||
surface.SetDrawColor( 230 * colordelta, 230 * colordelta, 230 * colordelta, alpha )
|
||||
surface.DrawTexturedRectRotated( rx + rw - bordersize / 2 , ry + rh - bordersize / 2, bordersize, bordersize, 180 )
|
||||
surface.DrawTexturedRectRotated( rx + rw - bordersize / 2 , ry + bordersize / 2, bordersize, bordersize, 270 )
|
||||
surface.DrawRect( rx + rw - bordersize, ry + bordersize, bordersize, rh-bordersize * 2 )
|
||||
surface.DrawRect( rx + bordersize + v.height - 4, ry, rw - ( v.height - 4 ) - bordersize * 2, rh )
|
||||
|
||||
draw.SimpleText( v.name, v.font, v.x + v.height + 9, ry + ( rh / 2 ) + 1, Color( 0, 0, 0, alpha * 0.5 ), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( v.name, v.font, v.x + v.height + 8, ry + ( rh / 2 ), Color( 255, 255, 255, alpha ), TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER )
|
||||
|
||||
if ( v.amount ) then
|
||||
|
||||
draw.SimpleText( v.amount, v.font, v.x + self.PickupHistoryWide + 1, ry + ( rh / 2 ) + 1, Color( 0, 0, 0, alpha * 0.5 ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER )
|
||||
draw.SimpleText( v.amount, v.font, v.x + self.PickupHistoryWide, ry + ( rh / 2 ), Color( 255, 255, 255, alpha ), TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER )
|
||||
|
||||
end
|
||||
|
||||
y = y + ( v.height + 16 )
|
||||
tall = tall + v.height + 18
|
||||
wide = math.max( wide, v.width + v.height + 24 )
|
||||
|
||||
if ( alpha == 0 ) then self.PickupHistory[ k ] = nil end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
self.PickupHistoryTop = ( self.PickupHistoryTop * 5 + ( ScrH() * 0.75 - tall ) / 2 ) / 6
|
||||
self.PickupHistoryWide = ( self.PickupHistoryWide * 5 + wide ) / 6
|
||||
|
||||
end
|
||||
746
gamemodes/base/gamemode/cl_init.lua
Normal file
746
gamemodes/base/gamemode/cl_init.lua
Normal file
@@ -0,0 +1,746 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
include( "shared.lua" )
|
||||
include( "cl_scoreboard.lua" )
|
||||
include( "cl_targetid.lua" )
|
||||
include( "cl_hudpickup.lua" )
|
||||
include( "cl_spawnmenu.lua" )
|
||||
include( "cl_deathnotice.lua" )
|
||||
include( "cl_pickteam.lua" )
|
||||
include( "cl_voice.lua" )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:Initialize()
|
||||
Desc: Called immediately after starting the gamemode
|
||||
-----------------------------------------------------------]]
|
||||
function GM:Initialize()
|
||||
|
||||
GAMEMODE.ShowScoreboard = false
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:InitPostEntity()
|
||||
Desc: Called as soon as all map entities have been spawned
|
||||
-----------------------------------------------------------]]
|
||||
function GM:InitPostEntity()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:Think()
|
||||
Desc: Called every frame
|
||||
-----------------------------------------------------------]]
|
||||
function GM:Think()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerBindPress()
|
||||
Desc: A player pressed a bound key - return true to override action
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerBindPress( pl, bind, down )
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HUDShouldDraw( name )
|
||||
Desc: return true if we should draw the named element
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HUDShouldDraw( name )
|
||||
|
||||
-- Allow the weapon to override this
|
||||
local ply = LocalPlayer()
|
||||
if ( IsValid( ply ) ) then
|
||||
|
||||
local wep = ply:GetActiveWeapon()
|
||||
|
||||
if ( IsValid( wep ) ) then
|
||||
|
||||
local fShouldDraw = wep.HUDShouldDraw
|
||||
|
||||
if ( isfunction( fShouldDraw ) ) then
|
||||
|
||||
local ret = fShouldDraw( wep, name )
|
||||
if ( ret != nil ) then return ret end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HUDPaint()
|
||||
Desc: Use this section to paint your HUD
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HUDPaint()
|
||||
|
||||
hook.Run( "HUDDrawTargetID" )
|
||||
hook.Run( "HUDDrawPickupHistory" )
|
||||
hook.Run( "DrawDeathNotice", 0.85, 0.04 )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HUDPaintBackground()
|
||||
Desc: Same as HUDPaint except drawn before
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HUDPaintBackground()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GUIMouseReleased( mousecode )
|
||||
Desc: The mouse was double clicked
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GUIMouseDoublePressed( mousecode, AimVector )
|
||||
-- We don't capture double clicks by default,
|
||||
-- We just treat them as regular presses
|
||||
GAMEMODE:GUIMousePressed( mousecode, AimVector )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ShutDown( )
|
||||
Desc: Called when the Lua system is about to shut down
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ShutDown()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:RenderScreenspaceEffects( )
|
||||
Desc: Bloom etc should be drawn here (or using this hook)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:RenderScreenspaceEffects()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GetTeamColor( ent )
|
||||
Desc: Return the color for this ent's team
|
||||
This is for chat and deathnotice text
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GetTeamColor( ent )
|
||||
|
||||
local team = TEAM_UNASSIGNED
|
||||
if ( ent.Team ) then team = ent:Team() end
|
||||
return GAMEMODE:GetTeamNumColor( team )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GetTeamNumColor( num )
|
||||
Desc: returns the colour for this team num
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GetTeamNumColor( num )
|
||||
|
||||
return team.GetColor( num )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:OnPlayerChat()
|
||||
Process the player's chat.. return true for no default
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnPlayerChat( player, strText, bTeamOnly, bPlayerIsDead )
|
||||
|
||||
--
|
||||
-- I've made this all look more complicated than it is. Here's the easy version
|
||||
--
|
||||
-- chat.AddText( player, color_white, ": ", strText )
|
||||
--
|
||||
|
||||
local tab = {}
|
||||
|
||||
if ( bPlayerIsDead ) then
|
||||
table.insert( tab, Color( 255, 30, 40 ) )
|
||||
table.insert( tab, "*DEAD* " )
|
||||
end
|
||||
|
||||
if ( bTeamOnly ) then
|
||||
table.insert( tab, Color( 30, 160, 40 ) )
|
||||
table.insert( tab, "(TEAM) " )
|
||||
end
|
||||
|
||||
if ( IsValid( player ) ) then
|
||||
table.insert( tab, player )
|
||||
else
|
||||
table.insert( tab, "Console" )
|
||||
end
|
||||
|
||||
local filter_context = TEXT_FILTER_GAME_CONTENT
|
||||
if ( bit.band( GetConVarNumber( "cl_chatfilters" ), 64 ) != 0 ) then filter_context = TEXT_FILTER_CHAT end
|
||||
|
||||
table.insert( tab, color_white )
|
||||
table.insert( tab, ": " .. util.FilterText( strText, filter_context, IsValid( player ) and player or nil ) )
|
||||
|
||||
chat.AddText( unpack( tab ) )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:OnChatTab( str )
|
||||
Desc: Tab is pressed when typing (Auto-complete names, IRC style)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnChatTab( str )
|
||||
|
||||
str = string.TrimRight(str)
|
||||
|
||||
local LastWord
|
||||
for word in string.gmatch( str, "[^ ]+" ) do
|
||||
LastWord = word
|
||||
end
|
||||
|
||||
if ( LastWord == nil ) then return str end
|
||||
|
||||
for k, v in ipairs( player.GetAll() ) do
|
||||
|
||||
local nickname = v:Nick()
|
||||
|
||||
if ( string.len( LastWord ) < string.len( nickname ) && string.find( string.lower( nickname ), string.lower( LastWord ), 0, true ) == 1 ) then
|
||||
|
||||
str = string.sub( str, 1, ( string.len( LastWord ) * -1 ) - 1 )
|
||||
str = str .. nickname
|
||||
return str
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return str
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:StartChat( teamsay )
|
||||
Desc: Start Chat.
|
||||
|
||||
If you want to display your chat shit different here's what you'd do:
|
||||
In StartChat show your text box and return true to hide the default
|
||||
Update the text in your box with the text passed to ChatTextChanged
|
||||
Close and clear your text box when FinishChat is called.
|
||||
Return true in ChatText to not show the default chat text
|
||||
|
||||
-----------------------------------------------------------]]
|
||||
function GM:StartChat( teamsay )
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:FinishChat()
|
||||
-----------------------------------------------------------]]
|
||||
function GM:FinishChat()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ChatTextChanged( text)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ChatTextChanged( text )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: ChatText
|
||||
Allows override of the chat text
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ChatText( playerindex, playername, text, filter )
|
||||
|
||||
if ( filter == "chat" ) then
|
||||
Msg( playername, ": ", text, "\n" )
|
||||
else
|
||||
Msg( text, "\n" )
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PostProcessPermitted( str )
|
||||
Desc: return true/false depending on whether this post process should be allowed
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PostProcessPermitted( str )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PostRenderVGUI( )
|
||||
Desc: Called after VGUI has been rendered
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PostRenderVGUI()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreRender( )
|
||||
Desc: Called before all rendering
|
||||
Return true to NOT render this frame for some reason (danger!)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PreRender()
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PostRender( )
|
||||
Desc: Called after all rendering
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PostRender()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:RenderScene( )
|
||||
Desc: Render the scene
|
||||
-----------------------------------------------------------]]
|
||||
function GM:RenderScene( origin, angle, fov )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: CalcVehicleView
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CalcVehicleView( Vehicle, ply, view )
|
||||
|
||||
if ( Vehicle.GetThirdPersonMode == nil || ply:GetViewEntity() != ply ) then
|
||||
-- This shouldn't ever happen.
|
||||
return
|
||||
end
|
||||
|
||||
--
|
||||
-- If we're not in third person mode - then get outa here stalker
|
||||
--
|
||||
if ( !Vehicle:GetThirdPersonMode() ) then return view end
|
||||
|
||||
-- Don't roll the camera
|
||||
-- view.angles.roll = 0
|
||||
|
||||
local mn, mx = Vehicle:GetRenderBounds()
|
||||
local radius = ( mn - mx ):Length()
|
||||
local radius = radius + radius * Vehicle:GetCameraDistance()
|
||||
|
||||
-- Trace back from the original eye position, so we don't clip through walls/objects
|
||||
local TargetOrigin = view.origin + ( view.angles:Forward() * -radius )
|
||||
local WallOffset = 4
|
||||
|
||||
local tr = util.TraceHull( {
|
||||
start = view.origin,
|
||||
endpos = TargetOrigin,
|
||||
filter = function( e )
|
||||
local c = e:GetClass() -- Avoid contact with entities that can potentially be attached to the vehicle. Ideally, we should check if "e" is constrained to "Vehicle".
|
||||
return !c:StartsWith( "prop_physics" ) &&!c:StartsWith( "prop_dynamic" ) && !c:StartsWith( "phys_bone_follower" ) && !c:StartsWith( "prop_ragdoll" ) && !e:IsVehicle() && !c:StartsWith( "gmod_" )
|
||||
end,
|
||||
mins = Vector( -WallOffset, -WallOffset, -WallOffset ),
|
||||
maxs = Vector( WallOffset, WallOffset, WallOffset ),
|
||||
} )
|
||||
|
||||
view.origin = tr.HitPos
|
||||
view.drawviewer = true
|
||||
|
||||
--
|
||||
-- If the trace hit something, put the camera there.
|
||||
--
|
||||
if ( tr.Hit && !tr.StartSolid) then
|
||||
view.origin = view.origin + tr.HitNormal * WallOffset
|
||||
end
|
||||
|
||||
return view
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: CalcView
|
||||
Allows override of the default view
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CalcView( ply, origin, angles, fov, znear, zfar )
|
||||
|
||||
local Vehicle = ply:GetVehicle()
|
||||
local Weapon = ply:GetActiveWeapon()
|
||||
|
||||
local view = {
|
||||
["origin"] = origin,
|
||||
["angles"] = angles,
|
||||
["fov"] = fov,
|
||||
["znear"] = znear,
|
||||
["zfar"] = zfar,
|
||||
["drawviewer"] = false,
|
||||
}
|
||||
|
||||
--
|
||||
-- Let the vehicle override the view and allows the vehicle view to be hooked
|
||||
--
|
||||
if ( IsValid( Vehicle ) ) then return hook.Run( "CalcVehicleView", Vehicle, ply, view ) end
|
||||
|
||||
--
|
||||
-- Let drive possibly alter the view
|
||||
--
|
||||
if ( drive.CalcView( ply, view ) ) then return view end
|
||||
|
||||
--
|
||||
-- Give the player manager a turn at altering the view
|
||||
--
|
||||
player_manager.RunClass( ply, "CalcView", view )
|
||||
|
||||
-- Give the active weapon a go at changing the view
|
||||
if ( IsValid( Weapon ) ) then
|
||||
|
||||
local func = Weapon.CalcView
|
||||
if ( func ) then
|
||||
local origin, angles, fov = func( Weapon, ply, Vector( view.origin ), Angle( view.angles ), view.fov ) -- Note: Constructor to copy the object so the child function can't edit it.
|
||||
view.origin, view.angles, view.fov = origin or view.origin, angles or view.angles, fov or view.fov
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return view
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- If return true: Will draw the local player
|
||||
-- If return false: Won't draw the local player
|
||||
-- If return nil: Will carry out default action
|
||||
--
|
||||
function GM:ShouldDrawLocalPlayer( ply )
|
||||
|
||||
return player_manager.RunClass( ply, "ShouldDrawLocal" )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:AdjustMouseSensitivity()
|
||||
Desc: Allows you to adjust the mouse sensitivity.
|
||||
The return is a fraction of the normal sensitivity (0.5 would be half as sensitive)
|
||||
Return -1 to not override.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:AdjustMouseSensitivity( fDefault )
|
||||
|
||||
local ply = LocalPlayer()
|
||||
if ( !IsValid( ply ) ) then return -1 end
|
||||
|
||||
local wep = ply:GetActiveWeapon()
|
||||
if ( wep && wep.AdjustMouseSensitivity ) then
|
||||
return wep:AdjustMouseSensitivity()
|
||||
end
|
||||
|
||||
return -1
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ForceDermaSkin()
|
||||
Desc: Return the name of skin this gamemode should use.
|
||||
If nil is returned the skin will use default
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ForceDermaSkin()
|
||||
|
||||
--return "example"
|
||||
return nil
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PostPlayerDraw()
|
||||
Desc: The player has just been drawn.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PostPlayerDraw( ply )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PrePlayerDraw()
|
||||
Desc: The player is just about to be drawn.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PrePlayerDraw( ply )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GetMotionBlurSettings()
|
||||
Desc: Allows you to edit the motion blur values
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GetMotionBlurValues( x, y, fwd, spin )
|
||||
|
||||
-- fwd = 0.5 + math.sin( CurTime() * 5 ) * 0.5
|
||||
|
||||
return x, y, fwd, spin
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:InputMouseApply()
|
||||
Desc: Allows you to control how moving the mouse affects the view angles
|
||||
-----------------------------------------------------------]]
|
||||
function GM:InputMouseApply( cmd, x, y, angle )
|
||||
|
||||
--angle.roll = angle.roll + 1
|
||||
--cmd:SetViewAngles( Ang )
|
||||
--return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:OnAchievementAchieved()
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnAchievementAchieved( ply, achid )
|
||||
|
||||
chat.AddText( ply, Color( 230, 230, 230 ), " earned the achievement ", Color( 255, 200, 0 ), achievements.GetName( achid ) )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreDrawSkyBox()
|
||||
Desc: Called before drawing the skybox. Return true to not draw the skybox.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PreDrawSkyBox()
|
||||
|
||||
--return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PostDrawSkyBox()
|
||||
Desc: Called after drawing the skybox
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PostDrawSkyBox()
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: GM:PostDraw2DSkyBox
|
||||
-- Desc: Called right after the 2D skybox has been drawn - allowing you to draw over it.
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function GM:PostDraw2DSkyBox()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreDrawOpaqueRenderables()
|
||||
Desc: Called before drawing opaque entities
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PreDrawOpaqueRenderables( bDrawingDepth, bDrawingSkybox )
|
||||
|
||||
-- return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreDrawOpaqueRenderables()
|
||||
Desc: Called before drawing opaque entities
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PostDrawOpaqueRenderables( bDrawingDepth, bDrawingSkybox )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreDrawOpaqueRenderables()
|
||||
Desc: Called before drawing opaque entities
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PreDrawTranslucentRenderables( bDrawingDepth, bDrawingSkybox )
|
||||
|
||||
-- return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreDrawOpaqueRenderables()
|
||||
Desc: Called before drawing opaque entities
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PostDrawTranslucentRenderables( bDrawingDepth, bDrawingSkybox )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:CalcViewModelView()
|
||||
Desc: Called to set the view model's position
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CalcViewModelView( Weapon, ViewModel, OldEyePos, OldEyeAng, EyePos, EyeAng )
|
||||
|
||||
if ( !IsValid( Weapon ) ) then return end
|
||||
|
||||
local vm_origin, vm_angles = EyePos, EyeAng
|
||||
|
||||
-- Controls the position of all viewmodels
|
||||
local func = Weapon.GetViewModelPosition
|
||||
if ( func ) then
|
||||
local pos, ang = func( Weapon, EyePos*1, EyeAng*1 )
|
||||
vm_origin = pos or vm_origin
|
||||
vm_angles = ang or vm_angles
|
||||
end
|
||||
|
||||
-- Controls the position of individual viewmodels
|
||||
func = Weapon.CalcViewModelView
|
||||
if ( func ) then
|
||||
local pos, ang = func( Weapon, ViewModel, OldEyePos*1, OldEyeAng*1, EyePos*1, EyeAng*1 )
|
||||
vm_origin = pos or vm_origin
|
||||
vm_angles = ang or vm_angles
|
||||
end
|
||||
|
||||
return vm_origin, vm_angles
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreDrawViewModel()
|
||||
Desc: Called before drawing the view model
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PreDrawViewModel( ViewModel, Player, Weapon )
|
||||
|
||||
if ( !IsValid( Weapon ) ) then return false end
|
||||
|
||||
player_manager.RunClass( Player, "PreDrawViewModel", ViewModel, Weapon )
|
||||
|
||||
if ( Weapon.PreDrawViewModel == nil ) then return false end
|
||||
return Weapon:PreDrawViewModel( ViewModel, Weapon, Player )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PostDrawViewModel()
|
||||
Desc: Called after drawing the view model
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PostDrawViewModel( ViewModel, Player, Weapon )
|
||||
|
||||
if ( !IsValid( Weapon ) ) then return false end
|
||||
|
||||
if ( Weapon.UseHands || !Weapon:IsScripted() ) then
|
||||
|
||||
local hands = Player:GetHands()
|
||||
if ( IsValid( hands ) && IsValid( hands:GetParent() ) ) then
|
||||
|
||||
if ( not hook.Call( "PreDrawPlayerHands", self, hands, ViewModel, Player, Weapon ) ) then
|
||||
|
||||
if ( Weapon.ViewModelFlip ) then render.CullMode( MATERIAL_CULLMODE_CW ) end
|
||||
hands:DrawModel()
|
||||
render.CullMode( MATERIAL_CULLMODE_CCW )
|
||||
|
||||
end
|
||||
|
||||
hook.Call( "PostDrawPlayerHands", self, hands, ViewModel, Player, Weapon )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
player_manager.RunClass( Player, "PostDrawViewModel", ViewModel, Weapon )
|
||||
|
||||
if ( Weapon.PostDrawViewModel == nil ) then return false end
|
||||
return Weapon:PostDrawViewModel( ViewModel, Weapon, Player )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:DrawPhysgunBeam()
|
||||
Desc: Return false to override completely
|
||||
-----------------------------------------------------------]]
|
||||
function GM:DrawPhysgunBeam( ply, weapon, bOn, target, boneid, pos )
|
||||
|
||||
-- Do nothing
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:NetworkEntityCreated()
|
||||
Desc: Entity is created over the network
|
||||
-----------------------------------------------------------]]
|
||||
function GM:NetworkEntityCreated( ent )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:CreateMove( command )
|
||||
Desc: Allows the client to change the move commands
|
||||
before it's send to the server
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CreateMove( cmd )
|
||||
|
||||
if ( drive.CreateMove( cmd ) ) then return true end
|
||||
|
||||
if ( player_manager.RunClass( LocalPlayer(), "CreateMove", cmd ) ) then return true end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreventScreenClicks()
|
||||
Desc: The player is hovering over a ScreenClickable world
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PreventScreenClicks( cmd )
|
||||
|
||||
--
|
||||
-- Returning true in this hook will prevent screen clicking sending IN_ATTACK
|
||||
-- commands to the weapons. We want to do this in the properties system, so
|
||||
-- that you don't fire guns when opening the properties menu. Holla!
|
||||
--
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GUIMousePressed( mousecode )
|
||||
Desc: The mouse has been pressed on the game screen
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GUIMousePressed( mousecode, AimVector )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GUIMouseReleased( mousecode )
|
||||
Desc: The mouse has been released on the game screen
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GUIMouseReleased( mousecode, AimVector )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Player class has been changed
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerClassChanged( ply, newID )
|
||||
|
||||
-- No class is set
|
||||
if ( newID < 1 ) then return end
|
||||
|
||||
-- Invalid class ID?
|
||||
local classname = util.NetworkIDToString( newID )
|
||||
if ( !classname ) then return end
|
||||
|
||||
-- Initialize the class on client
|
||||
player_manager.SetPlayerClass( ply, classname )
|
||||
|
||||
end
|
||||
|
||||
function GM:PreDrawHUD()
|
||||
end
|
||||
|
||||
function GM:PostDrawHUD()
|
||||
end
|
||||
|
||||
function GM:DrawOverlay()
|
||||
end
|
||||
|
||||
function GM:DrawMonitors()
|
||||
end
|
||||
|
||||
function GM:PreDrawEffects()
|
||||
end
|
||||
|
||||
function GM:PostDrawEffects()
|
||||
end
|
||||
|
||||
function GM:PreDrawHalos()
|
||||
end
|
||||
|
||||
function GM:CloseDermaMenus()
|
||||
end
|
||||
|
||||
function GM:CreateClientsideRagdoll( entity, ragdoll )
|
||||
end
|
||||
|
||||
function GM:VehicleMove( ply, vehicle, mv )
|
||||
end
|
||||
75
gamemodes/base/gamemode/cl_pickteam.lua
Normal file
75
gamemodes/base/gamemode/cl_pickteam.lua
Normal file
@@ -0,0 +1,75 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ShowTeam()
|
||||
Desc:
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ShowTeam()
|
||||
|
||||
if ( IsValid( self.TeamSelectFrame ) ) then return end
|
||||
|
||||
-- Simple team selection box
|
||||
self.TeamSelectFrame = vgui.Create( "DFrame" )
|
||||
self.TeamSelectFrame:SetTitle( "Pick Team" )
|
||||
|
||||
local AllTeams = team.GetAllTeams()
|
||||
local y = 30
|
||||
for ID, TeamInfo in pairs ( AllTeams ) do
|
||||
|
||||
if ( ID != TEAM_CONNECTING && ID != TEAM_UNASSIGNED ) then
|
||||
|
||||
local Team = vgui.Create( "DButton", self.TeamSelectFrame )
|
||||
function Team.DoClick() self:HideTeam() RunConsoleCommand( "changeteam", ID ) end
|
||||
Team:SetPos( 10, y )
|
||||
Team:SetSize( 130, 20 )
|
||||
Team:SetText( TeamInfo.Name )
|
||||
|
||||
if ( IsValid( LocalPlayer() ) && LocalPlayer():Team() == ID ) then
|
||||
Team:SetEnabled( false )
|
||||
end
|
||||
|
||||
y = y + 30
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if ( GAMEMODE.AllowAutoTeam ) then
|
||||
|
||||
local Team = vgui.Create( "DButton", self.TeamSelectFrame )
|
||||
function Team.DoClick() self:HideTeam() RunConsoleCommand( "autoteam" ) end
|
||||
Team:SetPos( 10, y )
|
||||
Team:SetSize( 130, 20 )
|
||||
Team:SetText( "Auto" )
|
||||
y = y + 30
|
||||
|
||||
end
|
||||
|
||||
self.TeamSelectFrame:SetSize( 150, y )
|
||||
self.TeamSelectFrame:Center()
|
||||
self.TeamSelectFrame:MakePopup()
|
||||
self.TeamSelectFrame:SetKeyboardInputEnabled( false )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HideTeam()
|
||||
Desc:
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HideTeam()
|
||||
|
||||
if ( IsValid(self.TeamSelectFrame) ) then
|
||||
self.TeamSelectFrame:Remove()
|
||||
self.TeamSelectFrame = nil
|
||||
end
|
||||
|
||||
end
|
||||
305
gamemodes/base/gamemode/cl_scoreboard.lua
Normal file
305
gamemodes/base/gamemode/cl_scoreboard.lua
Normal file
@@ -0,0 +1,305 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
surface.CreateFont( "ScoreboardDefault", {
|
||||
font = "Helvetica",
|
||||
size = 22,
|
||||
weight = 800
|
||||
} )
|
||||
|
||||
surface.CreateFont( "ScoreboardDefaultTitle", {
|
||||
font = "Helvetica",
|
||||
size = 32,
|
||||
weight = 800
|
||||
} )
|
||||
|
||||
--
|
||||
-- This defines a new panel type for the player row. The player row is given a player
|
||||
-- and then from that point on it pretty much looks after itself. It updates player info
|
||||
-- in the think function, and removes itself when the player leaves the server.
|
||||
--
|
||||
local PLAYER_LINE = {
|
||||
Init = function( self )
|
||||
|
||||
self.AvatarButton = self:Add( "DButton" )
|
||||
self.AvatarButton:Dock( LEFT )
|
||||
self.AvatarButton:SetSize( 32, 32 )
|
||||
self.AvatarButton.DoClick = function() self.Player:ShowProfile() end
|
||||
|
||||
self.Avatar = vgui.Create( "AvatarImage", self.AvatarButton )
|
||||
self.Avatar:SetSize( 32, 32 )
|
||||
self.Avatar:SetMouseInputEnabled( false )
|
||||
|
||||
self.Name = self:Add( "DLabel" )
|
||||
self.Name:Dock( FILL )
|
||||
self.Name:SetFont( "ScoreboardDefault" )
|
||||
self.Name:SetTextColor( Color( 93, 93, 93 ) )
|
||||
self.Name:DockMargin( 8, 0, 0, 0 )
|
||||
|
||||
self.Mute = self:Add( "DImageButton" )
|
||||
self.Mute:SetSize( 32, 32 )
|
||||
self.Mute:Dock( RIGHT )
|
||||
|
||||
self.Ping = self:Add( "DLabel" )
|
||||
self.Ping:Dock( RIGHT )
|
||||
self.Ping:SetWidth( 50 )
|
||||
self.Ping:SetFont( "ScoreboardDefault" )
|
||||
self.Ping:SetTextColor( Color( 93, 93, 93 ) )
|
||||
self.Ping:SetContentAlignment( 5 )
|
||||
|
||||
self.Deaths = self:Add( "DLabel" )
|
||||
self.Deaths:Dock( RIGHT )
|
||||
self.Deaths:SetWidth( 50 )
|
||||
self.Deaths:SetFont( "ScoreboardDefault" )
|
||||
self.Deaths:SetTextColor( Color( 93, 93, 93 ) )
|
||||
self.Deaths:SetContentAlignment( 5 )
|
||||
|
||||
self.Kills = self:Add( "DLabel" )
|
||||
self.Kills:Dock( RIGHT )
|
||||
self.Kills:SetWidth( 50 )
|
||||
self.Kills:SetFont( "ScoreboardDefault" )
|
||||
self.Kills:SetTextColor( Color( 93, 93, 93 ) )
|
||||
self.Kills:SetContentAlignment( 5 )
|
||||
|
||||
self:Dock( TOP )
|
||||
self:DockPadding( 3, 3, 3, 3 )
|
||||
self:SetHeight( 32 + 3 * 2 )
|
||||
self:DockMargin( 2, 0, 2, 2 )
|
||||
|
||||
end,
|
||||
|
||||
Setup = function( self, pl )
|
||||
|
||||
self.Player = pl
|
||||
|
||||
self.Avatar:SetPlayer( pl )
|
||||
|
||||
self:Think( self )
|
||||
|
||||
--local friend = self.Player:GetFriendStatus()
|
||||
--MsgN( pl, " Friend: ", friend )
|
||||
|
||||
end,
|
||||
|
||||
Think = function( self )
|
||||
|
||||
if ( !IsValid( self.Player ) ) then
|
||||
self:SetZPos( 9999 ) -- Causes a rebuild
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
if ( self.PName == nil || self.PName != self.Player:Nick() ) then
|
||||
self.PName = self.Player:Nick()
|
||||
self.Name:SetText( self.PName )
|
||||
end
|
||||
|
||||
if ( self.NumKills == nil || self.NumKills != self.Player:Frags() ) then
|
||||
self.NumKills = self.Player:Frags()
|
||||
self.Kills:SetText( self.NumKills )
|
||||
end
|
||||
|
||||
if ( self.NumDeaths == nil || self.NumDeaths != self.Player:Deaths() ) then
|
||||
self.NumDeaths = self.Player:Deaths()
|
||||
self.Deaths:SetText( self.NumDeaths )
|
||||
end
|
||||
|
||||
if ( self.NumPing == nil || self.NumPing != self.Player:Ping() ) then
|
||||
self.NumPing = self.Player:Ping()
|
||||
self.Ping:SetText( self.NumPing )
|
||||
end
|
||||
|
||||
--
|
||||
-- Change the icon of the mute button based on state
|
||||
--
|
||||
if ( self.Muted == nil || self.Muted != self.Player:IsMuted() ) then
|
||||
|
||||
self.Muted = self.Player:IsMuted()
|
||||
if ( self.Muted ) then
|
||||
self.Mute:SetImage( "icon32/muted.png" )
|
||||
else
|
||||
self.Mute:SetImage( "icon32/unmuted.png" )
|
||||
end
|
||||
|
||||
self.Mute.DoClick = function( s ) self.Player:SetMuted( !self.Muted ) end
|
||||
self.Mute.OnMouseWheeled = function( s, delta )
|
||||
self.Player:SetVoiceVolumeScale( self.Player:GetVoiceVolumeScale() + ( delta / 100 * 5 ) )
|
||||
s.LastTick = CurTime()
|
||||
end
|
||||
|
||||
self.Mute.PaintOver = function( s, w, h )
|
||||
if ( !IsValid( self.Player ) ) then return end
|
||||
|
||||
local a = 255 - math.Clamp( CurTime() - ( s.LastTick or 0 ), 0, 3 ) * 255
|
||||
if ( a <= 0 ) then return end
|
||||
|
||||
draw.RoundedBox( 4, 0, 0, w, h, Color( 0, 0, 0, a * 0.75 ) )
|
||||
draw.SimpleText( math.ceil( self.Player:GetVoiceVolumeScale() * 100 ) .. "%", "DermaDefaultBold", w / 2, h / 2, Color( 255, 255, 255, a ), TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Connecting players go at the very bottom
|
||||
--
|
||||
if ( self.Player:Team() == TEAM_CONNECTING ) then
|
||||
self:SetZPos( 2000 + self.Player:EntIndex() )
|
||||
return
|
||||
end
|
||||
|
||||
--
|
||||
-- This is what sorts the list. The panels are docked in the z order,
|
||||
-- so if we set the z order according to kills they'll be ordered that way!
|
||||
-- Careful though, it's a signed short internally, so needs to range between -32,768k and +32,767
|
||||
--
|
||||
self:SetZPos( ( self.NumKills * -50 ) + self.NumDeaths + self.Player:EntIndex() )
|
||||
|
||||
end,
|
||||
|
||||
Paint = function( self, w, h )
|
||||
|
||||
if ( !IsValid( self.Player ) ) then
|
||||
return
|
||||
end
|
||||
|
||||
--
|
||||
-- We draw our background a different colour based on the status of the player
|
||||
--
|
||||
|
||||
if ( self.Player:Team() == TEAM_CONNECTING ) then
|
||||
draw.RoundedBox( 4, 0, 0, w, h, Color( 200, 200, 200, 200 ) )
|
||||
return
|
||||
end
|
||||
|
||||
if ( !self.Player:Alive() ) then
|
||||
draw.RoundedBox( 4, 0, 0, w, h, Color( 230, 200, 200, 255 ) )
|
||||
return
|
||||
end
|
||||
|
||||
if ( self.Player:IsAdmin() ) then
|
||||
draw.RoundedBox( 4, 0, 0, w, h, Color( 230, 255, 230, 255 ) )
|
||||
return
|
||||
end
|
||||
|
||||
draw.RoundedBox( 4, 0, 0, w, h, Color( 230, 230, 230, 255 ) )
|
||||
|
||||
end
|
||||
}
|
||||
|
||||
--
|
||||
-- Convert it from a normal table into a Panel Table based on DPanel
|
||||
--
|
||||
PLAYER_LINE = vgui.RegisterTable( PLAYER_LINE, "DPanel" )
|
||||
|
||||
--
|
||||
-- Here we define a new panel table for the scoreboard. It basically consists
|
||||
-- of a header and a scrollpanel - into which the player lines are placed.
|
||||
--
|
||||
local SCORE_BOARD = {
|
||||
Init = function( self )
|
||||
|
||||
self.Header = self:Add( "Panel" )
|
||||
self.Header:Dock( TOP )
|
||||
self.Header:SetHeight( 100 )
|
||||
|
||||
self.Name = self.Header:Add( "DLabel" )
|
||||
self.Name:SetFont( "ScoreboardDefaultTitle" )
|
||||
self.Name:SetTextColor( color_white )
|
||||
self.Name:Dock( TOP )
|
||||
self.Name:SetHeight( 40 )
|
||||
self.Name:SetContentAlignment( 5 )
|
||||
self.Name:SetExpensiveShadow( 2, Color( 0, 0, 0, 200 ) )
|
||||
|
||||
--self.NumPlayers = self.Header:Add( "DLabel" )
|
||||
--self.NumPlayers:SetFont( "ScoreboardDefault" )
|
||||
--self.NumPlayers:SetTextColor( color_white )
|
||||
--self.NumPlayers:SetPos( 0, 100 - 30 )
|
||||
--self.NumPlayers:SetSize( 300, 30 )
|
||||
--self.NumPlayers:SetContentAlignment( 4 )
|
||||
|
||||
self.Scores = self:Add( "DScrollPanel" )
|
||||
self.Scores:Dock( FILL )
|
||||
|
||||
end,
|
||||
|
||||
PerformLayout = function( self )
|
||||
|
||||
self:SetSize( 700, ScrH() - 200 )
|
||||
self:SetPos( ScrW() / 2 - 350, 100 )
|
||||
|
||||
end,
|
||||
|
||||
Paint = function( self, w, h )
|
||||
|
||||
--draw.RoundedBox( 4, 0, 0, w, h, Color( 0, 0, 0, 200 ) )
|
||||
|
||||
end,
|
||||
|
||||
Think = function( self, w, h )
|
||||
|
||||
self.Name:SetText( GetHostName() )
|
||||
|
||||
--
|
||||
-- Loop through each player, and if one doesn't have a score entry - create it.
|
||||
--
|
||||
|
||||
for id, pl in ipairs( player.GetAll() ) do
|
||||
|
||||
if ( IsValid( pl.ScoreEntry ) ) then continue end
|
||||
|
||||
pl.ScoreEntry = vgui.CreateFromTable( PLAYER_LINE, pl.ScoreEntry )
|
||||
pl.ScoreEntry:Setup( pl )
|
||||
|
||||
self.Scores:AddItem( pl.ScoreEntry )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
}
|
||||
|
||||
SCORE_BOARD = vgui.RegisterTable( SCORE_BOARD, "EditablePanel" )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ScoreboardShow( )
|
||||
Desc: Sets the scoreboard to visible
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ScoreboardShow()
|
||||
|
||||
if ( !IsValid( g_Scoreboard ) ) then
|
||||
g_Scoreboard = vgui.CreateFromTable( SCORE_BOARD )
|
||||
end
|
||||
|
||||
if ( IsValid( g_Scoreboard ) ) then
|
||||
g_Scoreboard:Show()
|
||||
g_Scoreboard:MakePopup()
|
||||
g_Scoreboard:SetKeyboardInputEnabled( false )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ScoreboardHide( )
|
||||
Desc: Hides the scoreboard
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ScoreboardHide()
|
||||
|
||||
if ( IsValid( g_Scoreboard ) ) then
|
||||
g_Scoreboard:Hide()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HUDDrawScoreBoard( )
|
||||
Desc: If you prefer to draw your scoreboard the stupid way (without vgui)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HUDDrawScoreBoard()
|
||||
end
|
||||
46
gamemodes/base/gamemode/cl_spawnmenu.lua
Normal file
46
gamemodes/base/gamemode/cl_spawnmenu.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Spawn Menu
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnSpawnMenuOpen()
|
||||
end
|
||||
|
||||
function GM:OnSpawnMenuClose()
|
||||
end
|
||||
|
||||
concommand.Add( "+menu", function()
|
||||
hook.Run( "OnSpawnMenuOpen" )
|
||||
end, nil, "Opens the spawnmenu", FCVAR_DONTRECORD )
|
||||
|
||||
concommand.Add( "-menu", function()
|
||||
if ( input.IsKeyTrapping() ) then return end
|
||||
hook.Run( "OnSpawnMenuClose" )
|
||||
end, nil, "Closes the spawnmenu", FCVAR_DONTRECORD )
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Context Menu
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnContextMenuOpen()
|
||||
end
|
||||
|
||||
function GM:OnContextMenuClose()
|
||||
end
|
||||
|
||||
concommand.Add( "+menu_context", function()
|
||||
hook.Run( "OnContextMenuOpen" )
|
||||
end, nil, "Opens the context menu", FCVAR_DONTRECORD )
|
||||
|
||||
concommand.Add( "-menu_context", function()
|
||||
if ( input.IsKeyTrapping() ) then return end
|
||||
hook.Run( "OnContextMenuClose" )
|
||||
end, nil, "Closes the context menu", FCVAR_DONTRECORD )
|
||||
70
gamemodes/base/gamemode/cl_targetid.lua
Normal file
70
gamemodes/base/gamemode/cl_targetid.lua
Normal file
@@ -0,0 +1,70 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HUDDrawTargetID( )
|
||||
Desc: Draw the target id (the name of the player you're currently looking at)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HUDDrawTargetID()
|
||||
|
||||
local tr = util.GetPlayerTrace( LocalPlayer() )
|
||||
local trace = util.TraceLine( tr )
|
||||
if ( !trace.Hit ) then return end
|
||||
if ( !trace.HitNonWorld ) then return end
|
||||
|
||||
local text = "ERROR"
|
||||
local font = "TargetID"
|
||||
|
||||
if ( trace.Entity:IsPlayer() ) then
|
||||
text = trace.Entity:Nick()
|
||||
else
|
||||
--text = trace.Entity:GetClass()
|
||||
return
|
||||
end
|
||||
|
||||
surface.SetFont( font )
|
||||
local w, h = surface.GetTextSize( text )
|
||||
|
||||
local MouseX, MouseY = input.GetCursorPos()
|
||||
|
||||
if ( MouseX == 0 && MouseY == 0 || !vgui.CursorVisible() ) then
|
||||
|
||||
MouseX = ScrW() / 2
|
||||
MouseY = ScrH() / 2
|
||||
|
||||
end
|
||||
|
||||
local x = MouseX
|
||||
local y = MouseY
|
||||
|
||||
x = x - w / 2
|
||||
y = y + 30
|
||||
|
||||
-- The fonts internal drop shadow looks lousy with AA on
|
||||
draw.SimpleText( text, font, x + 1, y + 1, Color( 0, 0, 0, 120 ) )
|
||||
draw.SimpleText( text, font, x + 2, y + 2, Color( 0, 0, 0, 50 ) )
|
||||
draw.SimpleText( text, font, x, y, self:GetTeamColor( trace.Entity ) )
|
||||
|
||||
y = y + h + 5
|
||||
|
||||
-- Draw the health
|
||||
text = trace.Entity:Health() .. "%"
|
||||
font = "TargetIDSmall"
|
||||
|
||||
surface.SetFont( font )
|
||||
w, h = surface.GetTextSize( text )
|
||||
x = MouseX - w / 2
|
||||
|
||||
draw.SimpleText( text, font, x + 1, y + 1, Color( 0, 0, 0, 120 ) )
|
||||
draw.SimpleText( text, font, x + 2, y + 2, Color( 0, 0, 0, 50 ) )
|
||||
draw.SimpleText( text, font, x, y, self:GetTeamColor( trace.Entity ) )
|
||||
|
||||
end
|
||||
154
gamemodes/base/gamemode/cl_voice.lua
Normal file
154
gamemodes/base/gamemode/cl_voice.lua
Normal file
@@ -0,0 +1,154 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
local PANEL = {}
|
||||
local PlayerVoicePanels = {}
|
||||
|
||||
function PANEL:Init()
|
||||
|
||||
self.LabelName = vgui.Create( "DLabel", self )
|
||||
self.LabelName:SetFont( "GModNotify" )
|
||||
self.LabelName:Dock( FILL )
|
||||
self.LabelName:DockMargin( 8, 0, 0, 0 )
|
||||
self.LabelName:SetTextColor( color_white )
|
||||
|
||||
self.Avatar = vgui.Create( "AvatarImage", self )
|
||||
self.Avatar:Dock( LEFT )
|
||||
self.Avatar:SetSize( 32, 32 )
|
||||
|
||||
self.Color = color_transparent
|
||||
|
||||
self:SetSize( 250, 32 + 8 )
|
||||
self:DockPadding( 4, 4, 4, 4 )
|
||||
self:DockMargin( 2, 2, 2, 2 )
|
||||
self:Dock( BOTTOM )
|
||||
|
||||
end
|
||||
|
||||
function PANEL:Setup( ply )
|
||||
|
||||
self.ply = ply
|
||||
self.LabelName:SetText( ply:Nick() )
|
||||
self.Avatar:SetPlayer( ply )
|
||||
|
||||
self.Color = team.GetColor( ply:Team() )
|
||||
|
||||
self:InvalidateLayout()
|
||||
|
||||
end
|
||||
|
||||
function PANEL:Paint( w, h )
|
||||
|
||||
if ( !IsValid( self.ply ) ) then return end
|
||||
draw.RoundedBox( 4, 0, 0, w, h, Color( 0, self.ply:VoiceVolume() * 255, 0, 240 ) )
|
||||
|
||||
end
|
||||
|
||||
function PANEL:Think()
|
||||
|
||||
if ( IsValid( self.ply ) ) then
|
||||
self.LabelName:SetText( self.ply:Nick() )
|
||||
end
|
||||
|
||||
if ( self.fadeAnim ) then
|
||||
self.fadeAnim:Run()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function PANEL:FadeOut( anim, delta, data )
|
||||
|
||||
if ( anim.Finished ) then
|
||||
|
||||
if ( IsValid( PlayerVoicePanels[ self.ply ] ) ) then
|
||||
PlayerVoicePanels[ self.ply ]:Remove()
|
||||
PlayerVoicePanels[ self.ply ] = nil
|
||||
return
|
||||
end
|
||||
|
||||
return end
|
||||
|
||||
self:SetAlpha( 255 - ( 255 * delta ) )
|
||||
|
||||
end
|
||||
|
||||
derma.DefineControl( "VoiceNotify", "", PANEL, "DPanel" )
|
||||
|
||||
|
||||
|
||||
function GM:PlayerStartVoice( ply )
|
||||
|
||||
if ( !IsValid( g_VoicePanelList ) ) then return end
|
||||
|
||||
-- There'd be an exta one if voice_loopback is on, so remove it.
|
||||
GAMEMODE:PlayerEndVoice( ply )
|
||||
|
||||
|
||||
if ( IsValid( PlayerVoicePanels[ ply ] ) ) then
|
||||
|
||||
if ( PlayerVoicePanels[ ply ].fadeAnim ) then
|
||||
PlayerVoicePanels[ ply ].fadeAnim:Stop()
|
||||
PlayerVoicePanels[ ply ].fadeAnim = nil
|
||||
end
|
||||
|
||||
PlayerVoicePanels[ ply ]:SetAlpha( 255 )
|
||||
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
if ( !IsValid( ply ) ) then return end
|
||||
|
||||
local pnl = g_VoicePanelList:Add( "VoiceNotify" )
|
||||
pnl:Setup( ply )
|
||||
|
||||
PlayerVoicePanels[ ply ] = pnl
|
||||
|
||||
end
|
||||
|
||||
local function VoiceClean()
|
||||
|
||||
for k, v in pairs( PlayerVoicePanels ) do
|
||||
|
||||
if ( !IsValid( k ) ) then
|
||||
GAMEMODE:PlayerEndVoice( k )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
timer.Create( "VoiceClean", 10, 0, VoiceClean )
|
||||
|
||||
function GM:PlayerEndVoice( ply )
|
||||
|
||||
if ( IsValid( PlayerVoicePanels[ ply ] ) ) then
|
||||
|
||||
if ( PlayerVoicePanels[ ply ].fadeAnim ) then return end
|
||||
|
||||
PlayerVoicePanels[ ply ].fadeAnim = Derma_Anim( "FadeOut", PlayerVoicePanels[ ply ], PlayerVoicePanels[ ply ].FadeOut )
|
||||
PlayerVoicePanels[ ply ].fadeAnim:Start( 2 )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local function CreateVoiceVGUI()
|
||||
|
||||
g_VoicePanelList = vgui.Create( "DPanel" )
|
||||
|
||||
g_VoicePanelList:ParentToHUD()
|
||||
g_VoicePanelList:SetPos( ScrW() - 300, 100 )
|
||||
g_VoicePanelList:SetSize( 250, ScrH() - 200 )
|
||||
g_VoicePanelList:SetPaintBackground( false )
|
||||
|
||||
end
|
||||
|
||||
hook.Add( "InitPostEntity", "CreateVoiceVGUI", CreateVoiceVGUI )
|
||||
46
gamemodes/base/gamemode/gravitygun.lua
Normal file
46
gamemodes/base/gamemode/gravitygun.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GravGunPunt()
|
||||
Desc: We're about to punt an entity (primary fire).
|
||||
Return true if we're allowed to.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GravGunPunt( ply, ent )
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GravGunPickupAllowed()
|
||||
Desc: Return true if we're allowed to pickup entity
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GravGunPickupAllowed( ply, ent )
|
||||
return true
|
||||
end
|
||||
|
||||
if ( SERVER ) then
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GravGunOnPickedUp()
|
||||
Desc: The entity has been picked up
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GravGunOnPickedUp( ply, ent )
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GravGunOnDropped()
|
||||
Desc: The entity has been dropped
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GravGunOnDropped( ply, ent )
|
||||
end
|
||||
|
||||
end
|
||||
190
gamemodes/base/gamemode/init.lua
Normal file
190
gamemodes/base/gamemode/init.lua
Normal file
@@ -0,0 +1,190 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
include( 'shared.lua' )
|
||||
include( 'player.lua' )
|
||||
include( 'npc.lua' )
|
||||
include( 'variable_edit.lua' )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:Initialize()
|
||||
Desc: Called immediately after starting the gamemode
|
||||
-----------------------------------------------------------]]
|
||||
function GM:Initialize()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:InitPostEntity()
|
||||
Desc: Called as soon as all map entities have been spawned
|
||||
-----------------------------------------------------------]]
|
||||
function GM:InitPostEntity()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:Think()
|
||||
Desc: Called every frame
|
||||
-----------------------------------------------------------]]
|
||||
function GM:Think()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ShutDown()
|
||||
Desc: Called when the Lua system is about to shut down
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ShutDown()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:DoPlayerDeath( )
|
||||
Desc: Carries out actions when the player dies
|
||||
-----------------------------------------------------------]]
|
||||
function GM:DoPlayerDeath( ply, attacker, dmginfo )
|
||||
|
||||
if ( !dmginfo:IsDamageType( DMG_REMOVENORAGDOLL ) ) then
|
||||
ply:CreateRagdoll()
|
||||
end
|
||||
|
||||
ply:AddDeaths( 1 )
|
||||
|
||||
if ( attacker:IsValid() && attacker:IsPlayer() ) then
|
||||
|
||||
if ( attacker == ply ) then
|
||||
attacker:AddFrags( -1 )
|
||||
else
|
||||
attacker:AddFrags( 1 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerShouldTakeDamage
|
||||
Return true if this player should take damage from this attacker
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerShouldTakeDamage( ply, attacker )
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:EntityTakeDamage( ent, info )
|
||||
Desc: The entity has received damage
|
||||
-----------------------------------------------------------]]
|
||||
function GM:EntityTakeDamage( ent, info )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerHurt( )
|
||||
Desc: Called when a player is hurt.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerHurt( player, attacker, healthleft, healthtaken )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:CreateEntityRagdoll( entity, ragdoll )
|
||||
Desc: A ragdoll of an entity has been created
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CreateEntityRagdoll( entity, ragdoll )
|
||||
end
|
||||
|
||||
-- Set the ServerName every 30 seconds in case it changes..
|
||||
-- This is for backwards compatibility only - client can now use GetHostName()
|
||||
local function HostnameThink()
|
||||
|
||||
SetGlobalString( "ServerName", GetHostName() )
|
||||
|
||||
end
|
||||
|
||||
timer.Create( "HostnameThink", 30, 0, HostnameThink )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Show the default team selection screen
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ShowTeam( ply )
|
||||
|
||||
if ( !GAMEMODE.TeamBased ) then return end
|
||||
|
||||
local TimeBetweenSwitches = GAMEMODE.SecondsBetweenTeamSwitches or 10
|
||||
if ( ply.LastTeamSwitch && RealTime() - ply.LastTeamSwitch < TimeBetweenSwitches ) then
|
||||
ply.LastTeamSwitch = ply.LastTeamSwitch + 1
|
||||
ply:ChatPrint( Format( "Please wait %i more seconds before trying to change team again", ( TimeBetweenSwitches - ( RealTime() - ply.LastTeamSwitch ) ) + 1 ) )
|
||||
return
|
||||
end
|
||||
|
||||
-- For clientside see cl_pickteam.lua
|
||||
ply:SendLua( "GAMEMODE:ShowTeam()" )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- CheckPassword( steamid, networkid, server_password, password, name )
|
||||
--
|
||||
-- Called every time a non-localhost player joins the server. steamid is their 64bit
|
||||
-- steamid. Return false and a reason to reject their join. Return true to allow
|
||||
-- them to join.
|
||||
--
|
||||
function GM:CheckPassword( steamid, networkid, server_password, password, name )
|
||||
|
||||
-- The server has sv_password set
|
||||
if ( server_password != "" ) then
|
||||
|
||||
-- The joining clients password doesn't match sv_password
|
||||
if ( server_password != password ) then
|
||||
return false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Returning true means they're allowed to join the server
|
||||
--
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:FinishMove( player, movedata )
|
||||
-----------------------------------------------------------]]
|
||||
function GM:VehicleMove( ply, vehicle, mv )
|
||||
|
||||
--
|
||||
-- On duck toggle third person view
|
||||
--
|
||||
if ( mv:KeyPressed( IN_DUCK ) && vehicle.SetThirdPersonMode ) then
|
||||
vehicle:SetThirdPersonMode( !vehicle:GetThirdPersonMode() )
|
||||
end
|
||||
|
||||
--
|
||||
-- Adjust the camera distance with the mouse wheel
|
||||
--
|
||||
local iWheel = ply:GetCurrentCommand():GetMouseWheel()
|
||||
if ( iWheel != 0 && vehicle.SetCameraDistance ) then
|
||||
-- The distance is a multiplier
|
||||
-- Actual camera distance = ( renderradius + renderradius * dist )
|
||||
-- so -1 will be zero.. clamp it there.
|
||||
local newdist = math.Clamp( vehicle:GetCameraDistance() - iWheel * 0.03 * ( 1.1 + vehicle:GetCameraDistance() ), -1, 10 )
|
||||
vehicle:SetCameraDistance( newdist )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreUndo( undo )
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PreUndo( undo )
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PreUndo( undo )
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PostUndo( undo, count )
|
||||
end
|
||||
211
gamemodes/base/gamemode/npc.lua
Normal file
211
gamemodes/base/gamemode/npc.lua
Normal file
@@ -0,0 +1,211 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- Backwards compatibility with addons
|
||||
util.AddNetworkString( "PlayerKilledNPC" )
|
||||
util.AddNetworkString( "NPCKilledNPC" )
|
||||
util.AddNetworkString( "PlayerKilled" )
|
||||
util.AddNetworkString( "PlayerKilledSelf" )
|
||||
util.AddNetworkString( "PlayerKilledByPlayer" )
|
||||
|
||||
-- New way
|
||||
util.AddNetworkString( "DeathNoticeEvent" )
|
||||
|
||||
DEATH_NOTICE_FRIENDLY_VICTIM = 1
|
||||
DEATH_NOTICE_FRIENDLY_ATTACKER = 2
|
||||
--DEATH_NOTICE_HEADSHOT = 4
|
||||
--DEATH_NOTICE_PENETRATION = 8
|
||||
function GM:SendDeathNotice( attacker, inflictor, victim, flags )
|
||||
|
||||
net.Start( "DeathNoticeEvent" )
|
||||
|
||||
if ( !attacker ) then
|
||||
net.WriteUInt( 0, 2 )
|
||||
elseif ( isstring( attacker ) ) then
|
||||
net.WriteUInt( 1, 2 )
|
||||
net.WriteString( attacker )
|
||||
elseif ( IsValid( attacker ) ) then
|
||||
net.WriteUInt( 2, 2 )
|
||||
net.WriteEntity( attacker )
|
||||
end
|
||||
|
||||
net.WriteString( inflictor )
|
||||
|
||||
if ( !victim ) then
|
||||
net.WriteUInt( 0, 2 )
|
||||
elseif ( isstring( victim ) ) then
|
||||
net.WriteUInt( 1, 2 )
|
||||
net.WriteString( victim )
|
||||
elseif ( IsValid( victim ) ) then
|
||||
net.WriteUInt( 2, 2 )
|
||||
net.WriteEntity( victim )
|
||||
end
|
||||
|
||||
net.WriteUInt( flags, 8 )
|
||||
|
||||
net.Broadcast()
|
||||
|
||||
end
|
||||
|
||||
function GM:GetDeathNoticeEntityName( ent )
|
||||
|
||||
-- Some specific HL2 NPCs, just for fun
|
||||
-- TODO: Localization strings?
|
||||
if ( ent:GetClass() == "npc_citizen" ) then
|
||||
if ( ent:GetName() == "griggs" ) then return "Griggs" end
|
||||
if ( ent:GetName() == "sheckley" ) then return "Sheckley" end
|
||||
if ( ent:GetName() == "tobias" ) then return "Laszlo" end
|
||||
if ( ent:GetName() == "stanley" ) then return "Sandy" end
|
||||
end
|
||||
|
||||
-- Custom vehicle and NPC names from spawnmenu
|
||||
if ( ent:IsVehicle() and ent.VehicleTable and ent.VehicleTable.Name ) then
|
||||
return ent.VehicleTable.Name
|
||||
end
|
||||
if ( ent:IsNPC() and ent.NPCTable and ent.NPCTable.Name ) then
|
||||
return ent.NPCTable.Name
|
||||
end
|
||||
|
||||
-- Map spawned Odessa or Rebels, etc..
|
||||
for unique_class, NPC in pairs( list.Get( "NPC" ) ) do
|
||||
if ( unique_class == NPC.Class or ent:GetClass() != NPC.Class ) then continue end
|
||||
|
||||
local allGood = true
|
||||
if ( NPC.Model and ent:GetModel() != NPC.Model ) then
|
||||
allGood = false
|
||||
end
|
||||
|
||||
if ( NPC.Skin and ent:GetSkin() != NPC.Skin ) then
|
||||
allGood = false
|
||||
end
|
||||
|
||||
-- For Rebels, etc.
|
||||
if ( NPC.KeyValues ) then
|
||||
for k, v in pairs( NPC.KeyValues ) do
|
||||
local kL = k:lower()
|
||||
if ( kL != "squadname" and kL != "numgrenades" and ent:GetInternalVariable( k ) != v ) then
|
||||
allGood = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- They get unset often :(
|
||||
--if ( NPC.SpawnFlags and ent:HasSpawnFlags( NPC.SpawnFlags ) ) then allGood = false end
|
||||
end
|
||||
|
||||
-- Medics, ew..
|
||||
if ( unique_class == "Medic" and !ent:HasSpawnFlags( SF_CITIZEN_MEDIC ) ) then allGood = false end
|
||||
if ( unique_class == "Rebel" and ent:HasSpawnFlags( SF_CITIZEN_MEDIC ) ) then allGood = false end
|
||||
|
||||
if ( allGood ) then return NPC.Name end
|
||||
end
|
||||
|
||||
-- Unfortunately the code above still doesn't work for Antlion Workers, because they change their classname..
|
||||
if ( ent:GetClass() == "npc_antlion" and ent:GetModel() == "models/antlion_worker.mdl" ) then
|
||||
return list.Get( "NPC" )[ "npc_antlion_worker" ].Name
|
||||
end
|
||||
|
||||
-- Fallback to old behavior
|
||||
return "#" .. ent:GetClass()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:OnNPCKilled( entity, attacker, inflictor )
|
||||
Desc: The NPC has died
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnNPCKilled( ent, attacker, inflictor )
|
||||
|
||||
-- Don't spam the killfeed with scripted stuff
|
||||
if ( ent:GetClass() == "npc_bullseye" or ent:GetClass() == "npc_launcher" ) then return end
|
||||
|
||||
-- If killed by trigger_hurt, act as if NPC killed itself
|
||||
if ( IsValid( attacker ) and attacker:GetClass() == "trigger_hurt" ) then attacker = ent end
|
||||
|
||||
-- NPC got run over..
|
||||
if ( IsValid( attacker ) and attacker:IsVehicle() and IsValid( attacker:GetDriver() ) ) then
|
||||
attacker = attacker:GetDriver()
|
||||
end
|
||||
|
||||
if ( !IsValid( inflictor ) and IsValid( attacker ) ) then
|
||||
inflictor = attacker
|
||||
end
|
||||
|
||||
-- Convert the inflictor to the weapon that they're holding if we can.
|
||||
if ( IsValid( inflictor ) and attacker == inflictor and ( inflictor:IsPlayer() or inflictor:IsNPC() ) ) then
|
||||
|
||||
inflictor = inflictor:GetActiveWeapon()
|
||||
if ( !IsValid( attacker ) ) then inflictor = attacker end
|
||||
|
||||
end
|
||||
|
||||
local InflictorClass = "worldspawn"
|
||||
local AttackerClass = game.GetWorld()
|
||||
|
||||
if ( IsValid( inflictor ) ) then InflictorClass = inflictor:GetClass() end
|
||||
if ( IsValid( attacker ) ) then
|
||||
|
||||
AttackerClass = attacker
|
||||
|
||||
-- If there is no valid inflictor, use the attacker (i.e. manhacks)
|
||||
if ( !IsValid( inflictor ) ) then InflictorClass = attacker:GetClass() end
|
||||
|
||||
if ( attacker:IsPlayer() ) then
|
||||
|
||||
local flags = 0
|
||||
if ( ent:IsNPC() and ent:Disposition( attacker ) != D_HT ) then flags = flags + DEATH_NOTICE_FRIENDLY_VICTIM end
|
||||
|
||||
self:SendDeathNotice( attacker, InflictorClass, self:GetDeathNoticeEntityName( ent ), flags )
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Floor turret got knocked over
|
||||
if ( ent:GetClass() == "npc_turret_floor" ) then AttackerClass = ent end
|
||||
|
||||
-- It was NPC suicide..
|
||||
if ( ent == AttackerClass ) then InflictorClass = "suicide" end
|
||||
|
||||
local flags = 0
|
||||
if ( IsValid( Entity( 1 ) ) and ent:IsNPC() and ent:Disposition( Entity( 1 ) ) == D_LI ) then flags = flags + DEATH_NOTICE_FRIENDLY_VICTIM end
|
||||
if ( IsValid( Entity( 1 ) ) and AttackerClass:IsNPC() and AttackerClass:Disposition( Entity( 1 ) ) == D_LI ) then flags = flags + DEATH_NOTICE_FRIENDLY_ATTACKER end
|
||||
|
||||
self:SendDeathNotice( self:GetDeathNoticeEntityName( AttackerClass ), InflictorClass, self:GetDeathNoticeEntityName( ent ), flags )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ScaleNPCDamage( ply, hitgroup, dmginfo )
|
||||
Desc: Scale the damage based on being shot in a hitbox
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ScaleNPCDamage( npc, hitgroup, dmginfo )
|
||||
|
||||
-- More damage if we're shot in the head
|
||||
if ( hitgroup == HITGROUP_HEAD ) then
|
||||
|
||||
dmginfo:ScaleDamage( 2 )
|
||||
|
||||
end
|
||||
|
||||
-- Less damage if we're shot in the arms or legs
|
||||
if ( hitgroup == HITGROUP_LEFTARM or
|
||||
hitgroup == HITGROUP_RIGHTARM or
|
||||
hitgroup == HITGROUP_LEFTLEG or
|
||||
hitgroup == HITGROUP_RIGHTLEG or
|
||||
hitgroup == HITGROUP_GEAR ) then
|
||||
|
||||
dmginfo:ScaleDamage( 0.25 )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
223
gamemodes/base/gamemode/obj_player_extend.lua
Normal file
223
gamemodes/base/gamemode/obj_player_extend.lua
Normal file
@@ -0,0 +1,223 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
local meta = FindMetaTable( "Player" )
|
||||
if ( !meta ) then return end
|
||||
|
||||
-- In this file we're adding functions to the player meta table.
|
||||
-- This means you'll be able to call functions here straight from the player object
|
||||
-- You can even override already existing functions.
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AddFrozenPhysicsObject
|
||||
Desc: For the Physgun, adds a frozen object to the player's list
|
||||
-----------------------------------------------------------]]
|
||||
function meta:AddFrozenPhysicsObject( ent, phys )
|
||||
|
||||
-- Get the player's table
|
||||
local tab = self:GetTable()
|
||||
|
||||
-- Make sure the physics objects table exists
|
||||
tab.FrozenPhysicsObjects = tab.FrozenPhysicsObjects or {}
|
||||
|
||||
-- Make a new table that contains the info
|
||||
local entry = {}
|
||||
entry.ent = ent
|
||||
entry.phys = phys
|
||||
|
||||
table.insert( tab.FrozenPhysicsObjects, entry )
|
||||
|
||||
gamemode.Call( "PlayerFrozeObject", self, ent, phys )
|
||||
|
||||
end
|
||||
|
||||
local function PlayerUnfreezeObject( ply, ent, object )
|
||||
|
||||
-- Not frozen!
|
||||
if ( object:IsMoveable() ) then return 0 end
|
||||
|
||||
-- Unfreezable means it can't be frozen or unfrozen.
|
||||
-- This prevents the player unfreezing the gmod_anchor entity.
|
||||
if ( ent:GetUnFreezable() ) then return 0 end
|
||||
|
||||
-- NOTE: IF YOU'RE MAKING SOME KIND OF PROP PROTECTOR THEN HOOK "CanPlayerUnfreeze"
|
||||
if ( !gamemode.Call( "CanPlayerUnfreeze", ply, ent, object ) ) then return 0 end
|
||||
|
||||
object:EnableMotion( true )
|
||||
object:Wake()
|
||||
|
||||
gamemode.Call( "PlayerUnfrozeObject", ply, ent, object )
|
||||
|
||||
return 1
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: UnfreezePhysicsObjects
|
||||
Desc: For the Physgun, unfreezes all frozen physics objects
|
||||
-----------------------------------------------------------]]
|
||||
function meta:PhysgunUnfreeze()
|
||||
|
||||
-- Get the player's table
|
||||
local tab = self:GetTable()
|
||||
if ( !tab.FrozenPhysicsObjects ) then return 0 end
|
||||
|
||||
-- Detect double click. Unfreeze all objects on double click.
|
||||
if ( tab.LastPhysUnfreeze && CurTime() - tab.LastPhysUnfreeze < 0.25 ) then
|
||||
return self:UnfreezePhysicsObjects()
|
||||
end
|
||||
|
||||
local tr = self:GetEyeTrace()
|
||||
if ( tr.HitNonWorld && IsValid( tr.Entity ) ) then
|
||||
|
||||
local Ents = constraint.GetAllConstrainedEntities( tr.Entity )
|
||||
local UnfrozenObjects = 0
|
||||
|
||||
for k, ent in pairs( Ents ) do
|
||||
|
||||
local objects = ent:GetPhysicsObjectCount()
|
||||
|
||||
for i = 1, objects do
|
||||
|
||||
local physobject = ent:GetPhysicsObjectNum( i - 1 )
|
||||
UnfrozenObjects = UnfrozenObjects + PlayerUnfreezeObject( self, ent, physobject )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
return UnfrozenObjects
|
||||
|
||||
end
|
||||
|
||||
tab.LastPhysUnfreeze = CurTime()
|
||||
return 0
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: UnfreezePhysicsObjects
|
||||
Desc: For the Physgun, unfreezes all frozen physics objects
|
||||
-----------------------------------------------------------]]
|
||||
function meta:UnfreezePhysicsObjects()
|
||||
|
||||
-- Get the player's table
|
||||
local tab = self:GetTable()
|
||||
|
||||
-- If the table doesn't exist then quit here
|
||||
if ( !tab.FrozenPhysicsObjects ) then return 0 end
|
||||
|
||||
local Count = 0
|
||||
|
||||
-- Loop through each table in our table
|
||||
for k, v in pairs( tab.FrozenPhysicsObjects ) do
|
||||
|
||||
-- Make sure the entity to which the physics object
|
||||
-- is attached is still valid (still exists)
|
||||
if ( isentity( v.ent ) && IsValid( v.ent ) ) then
|
||||
|
||||
-- We can't directly test to see if EnableMotion is false right now
|
||||
-- but IsMovable seems to do the job just fine.
|
||||
-- We only test so the count isn't wrong
|
||||
if ( IsValid( v.phys ) && !v.phys:IsMoveable() ) then
|
||||
|
||||
-- We need to freeze/unfreeze all physobj's in jeeps to stop it spazzing
|
||||
if ( v.ent:GetClass() == "prop_vehicle_jeep" ) then
|
||||
|
||||
-- How many physics objects we have
|
||||
local objects = v.ent:GetPhysicsObjectCount()
|
||||
|
||||
-- Loop through each one
|
||||
for i = 0, objects - 1 do
|
||||
|
||||
local physobject = v.ent:GetPhysicsObjectNum( i )
|
||||
PlayerUnfreezeObject( self, v.ent, physobject )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Count = Count + PlayerUnfreezeObject( self, v.ent, v.phys )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- Remove the table
|
||||
tab.FrozenPhysicsObjects = nil
|
||||
|
||||
return Count
|
||||
|
||||
end
|
||||
|
||||
local g_UniqueIDTable = {}
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
This table will persist between client deaths and reconnects
|
||||
-----------------------------------------------------------]]
|
||||
function meta:UniqueIDTable( key )
|
||||
|
||||
local id = 0
|
||||
if ( SERVER ) then id = self:SteamID64() end
|
||||
|
||||
g_UniqueIDTable[ id ] = g_UniqueIDTable[ id ] or {}
|
||||
g_UniqueIDTable[ id ][ key ] = g_UniqueIDTable[ id ][ key ] or {}
|
||||
|
||||
return g_UniqueIDTable[ id ][ key ]
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Player Eye Trace
|
||||
-----------------------------------------------------------]]
|
||||
function meta:GetEyeTrace()
|
||||
if ( CLIENT ) then
|
||||
local framenum = FrameNumber()
|
||||
|
||||
-- Cache the trace results for the current frame, unless we're serverside
|
||||
-- in which case it wouldn't play well with lag compensation at all
|
||||
if ( self.LastPlayerTrace == framenum ) then
|
||||
return self.PlayerTrace
|
||||
end
|
||||
|
||||
self.LastPlayerTrace = framenum
|
||||
end
|
||||
|
||||
local tr = util.TraceLine( util.GetPlayerTrace( self ) )
|
||||
self.PlayerTrace = tr
|
||||
|
||||
return tr
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
GetEyeTraceIgnoreCursor
|
||||
Like GetEyeTrace but doesn't use the cursor aim vector..
|
||||
-----------------------------------------------------------]]
|
||||
function meta:GetEyeTraceNoCursor()
|
||||
if ( CLIENT ) then
|
||||
local framenum = FrameNumber()
|
||||
|
||||
if ( self.LastPlayerAimTrace == framenum ) then
|
||||
return self.PlayerAimTrace
|
||||
end
|
||||
|
||||
self.LastPlayerAimTrace = framenum
|
||||
end
|
||||
|
||||
local tr = util.TraceLine( util.GetPlayerTrace( self, self:EyeAngles():Forward() ) )
|
||||
self.PlayerAimTrace = tr
|
||||
|
||||
return tr
|
||||
end
|
||||
861
gamemodes/base/gamemode/player.lua
Normal file
861
gamemodes/base/gamemode/player.lua
Normal file
@@ -0,0 +1,861 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:OnPhysgunFreeze( weapon, phys, ent, player )
|
||||
Desc: The physgun wants to freeze a prop
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnPhysgunFreeze( weapon, phys, ent, ply )
|
||||
|
||||
-- Non vphysics entity, we don't know how to handle that
|
||||
if ( !IsValid( phys ) ) then return end
|
||||
|
||||
-- Object is already frozen (!?)
|
||||
if ( !phys:IsMoveable() ) then return end
|
||||
if ( ent:GetUnFreezable() ) then return end
|
||||
|
||||
phys:EnableMotion( false )
|
||||
|
||||
-- Add it to the player's frozen props
|
||||
ply:AddFrozenPhysicsObject( ent, phys )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:OnPhysgunReload( weapon, player )
|
||||
Desc: The physgun wants to freeze a prop
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnPhysgunReload( weapon, ply )
|
||||
|
||||
ply:PhysgunUnfreeze()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerAuthed()
|
||||
Desc: Player's STEAMID has been authed
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerAuthed( ply, SteamID, UniqueID )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerCanPickupWeapon()
|
||||
Desc: Called when a player tries to pickup a weapon.
|
||||
return true to allow the pickup.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerCanPickupWeapon( ply, entity )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerCanPickupItem()
|
||||
Desc: Called when a player tries to pickup an item.
|
||||
return true to allow the pickup.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerCanPickupItem( ply, entity )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:CanPlayerUnfreeze()
|
||||
Desc: Can the player unfreeze this entity & physobject
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CanPlayerUnfreeze( ply, entity, physobject )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerDisconnected()
|
||||
Desc: Player has disconnected from the server.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerDisconnected( ply )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSay()
|
||||
Desc: A player (or server) has used say. Return a string
|
||||
for the player to say. Return an empty string if the
|
||||
player should say nothing.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSay( ply, text, teamonly )
|
||||
|
||||
return text
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerDeathThink( player )
|
||||
Desc: Called when the player is waiting to respawn
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerDeathThink( pl )
|
||||
|
||||
if ( pl.NextSpawnTime && pl.NextSpawnTime > CurTime() ) then return end
|
||||
|
||||
if ( pl:IsBot() || pl:KeyPressed( IN_ATTACK ) || pl:KeyPressed( IN_ATTACK2 ) || pl:KeyPressed( IN_JUMP ) ) then
|
||||
|
||||
pl:Spawn()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerUse( player, entity )
|
||||
Desc: A player has attempted to use a specific entity
|
||||
Return true if the player can use it
|
||||
------------------------------------------------------------]]
|
||||
function GM:PlayerUse( ply, entity )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSilentDeath()
|
||||
Desc: Called when a player dies silently
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSilentDeath( Victim )
|
||||
|
||||
Victim.NextSpawnTime = CurTime() + 2
|
||||
Victim.DeathTime = CurTime()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerDeath()
|
||||
Desc: Called when a player dies.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerDeath( ply, inflictor, attacker )
|
||||
|
||||
-- Don't spawn for at least 2 seconds
|
||||
ply.NextSpawnTime = CurTime() + 2
|
||||
ply.DeathTime = CurTime()
|
||||
|
||||
if ( IsValid( attacker ) && attacker:GetClass() == "trigger_hurt" ) then attacker = ply end
|
||||
|
||||
if ( IsValid( attacker ) && attacker:IsVehicle() && IsValid( attacker:GetDriver() ) ) then
|
||||
attacker = attacker:GetDriver()
|
||||
end
|
||||
|
||||
if ( !IsValid( inflictor ) && IsValid( attacker ) ) then
|
||||
inflictor = attacker
|
||||
end
|
||||
|
||||
-- Convert the inflictor to the weapon that they're holding if we can.
|
||||
-- This can be right or wrong with NPCs since combine can be holding a
|
||||
-- pistol but kill you by hitting you with their arm.
|
||||
if ( IsValid( inflictor ) && inflictor == attacker && ( inflictor:IsPlayer() || inflictor:IsNPC() ) ) then
|
||||
|
||||
inflictor = inflictor:GetActiveWeapon()
|
||||
if ( !IsValid( inflictor ) ) then inflictor = attacker end
|
||||
|
||||
end
|
||||
|
||||
player_manager.RunClass( ply, "Death", inflictor, attacker )
|
||||
|
||||
if ( attacker == ply ) then
|
||||
|
||||
self:SendDeathNotice( nil, "suicide", ply, 0 )
|
||||
|
||||
MsgAll( attacker:Nick() .. " suicided!\n" )
|
||||
|
||||
return end
|
||||
|
||||
if ( attacker:IsPlayer() ) then
|
||||
|
||||
self:SendDeathNotice( attacker, inflictor:GetClass(), ply, 0 )
|
||||
|
||||
MsgAll( attacker:Nick() .. " killed " .. ply:Nick() .. " using " .. inflictor:GetClass() .. "\n" )
|
||||
|
||||
return end
|
||||
|
||||
local flags = 0
|
||||
if ( attacker:IsNPC() and attacker:Disposition( ply ) != D_HT ) then flags = flags + DEATH_NOTICE_FRIENDLY_ATTACKER end
|
||||
|
||||
self:SendDeathNotice( self:GetDeathNoticeEntityName( attacker ), inflictor:GetClass(), ply, 0 )
|
||||
|
||||
MsgAll( ply:Nick() .. " was killed by " .. attacker:GetClass() .. "\n" )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerInitialSpawn()
|
||||
Desc: Called just before the player's first spawn
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerInitialSpawn( pl, transiton )
|
||||
|
||||
pl:SetTeam( TEAM_UNASSIGNED )
|
||||
|
||||
if ( GAMEMODE.TeamBased ) then
|
||||
pl:ConCommand( "gm_showteam" )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSpawnAsSpectator()
|
||||
Desc: Player spawns as a spectator
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSpawnAsSpectator( pl )
|
||||
|
||||
pl:StripWeapons()
|
||||
|
||||
if ( pl:Team() == TEAM_UNASSIGNED ) then
|
||||
|
||||
pl:Spectate( OBS_MODE_FIXED )
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
pl:SetTeam( TEAM_SPECTATOR )
|
||||
pl:Spectate( OBS_MODE_ROAMING )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSpawn()
|
||||
Desc: Called when a player spawns
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSpawn( pl, transiton )
|
||||
|
||||
--
|
||||
-- If the player doesn't have a team in a TeamBased game
|
||||
-- then spawn him as a spectator
|
||||
--
|
||||
if ( self.TeamBased && ( pl:Team() == TEAM_SPECTATOR || pl:Team() == TEAM_UNASSIGNED ) ) then
|
||||
|
||||
self:PlayerSpawnAsSpectator( pl )
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
-- Stop observer mode
|
||||
pl:UnSpectate()
|
||||
|
||||
player_manager.OnPlayerSpawn( pl, transiton )
|
||||
player_manager.RunClass( pl, "Spawn" )
|
||||
|
||||
-- If we are in transition, do not touch player's weapons
|
||||
if ( !transiton ) then
|
||||
-- Call item loadout function
|
||||
hook.Call( "PlayerLoadout", GAMEMODE, pl )
|
||||
end
|
||||
|
||||
-- Set player model
|
||||
hook.Call( "PlayerSetModel", GAMEMODE, pl )
|
||||
|
||||
pl:SetupHands()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSetModel()
|
||||
Desc: Set the player's model
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSetModel( pl )
|
||||
|
||||
player_manager.RunClass( pl, "SetModel" )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSetHandsModel()
|
||||
Desc: Sets the player's view model hands model
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSetHandsModel( pl, ent )
|
||||
|
||||
local info = player_manager.RunClass( pl, "GetHandsModel" )
|
||||
if ( !info ) then
|
||||
local playermodel = player_manager.TranslateToPlayerModelName( pl:GetModel() )
|
||||
info = player_manager.TranslatePlayerHands( playermodel )
|
||||
end
|
||||
|
||||
if ( info ) then
|
||||
ent:SetModel( info.model )
|
||||
ent:SetSkin( info.matchBodySkin and pl:GetSkin() or info.skin )
|
||||
ent:SetBodyGroups( info.body )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerLoadout()
|
||||
Desc: Give the player the default spawning weapons/ammo
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerLoadout( pl )
|
||||
|
||||
player_manager.RunClass( pl, "Loadout" )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSelectTeamSpawn( player )
|
||||
Desc: Find a spawn point entity for this player's team
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSelectTeamSpawn( TeamID, pl )
|
||||
|
||||
local SpawnPoints = team.GetSpawnPoints( TeamID )
|
||||
if ( !SpawnPoints || table.IsEmpty( SpawnPoints ) ) then return end
|
||||
|
||||
local ChosenSpawnPoint = nil
|
||||
|
||||
for i = 0, 6 do
|
||||
|
||||
ChosenSpawnPoint = table.Random( SpawnPoints )
|
||||
if ( hook.Call( "IsSpawnpointSuitable", GAMEMODE, pl, ChosenSpawnPoint, i == 6 ) ) then
|
||||
return ChosenSpawnPoint
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return ChosenSpawnPoint
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:IsSpawnpointSuitable( player )
|
||||
Desc: Find out if the spawnpoint is suitable or not
|
||||
-----------------------------------------------------------]]
|
||||
local spawnpointmin = Vector( -16, -16, 0 )
|
||||
local spawnpointmax = Vector( 16, 16, 64 )
|
||||
function GM:IsSpawnpointSuitable( pl, spawnpointent, bMakeSuitable )
|
||||
|
||||
local Pos = spawnpointent:GetPos()
|
||||
|
||||
-- Note that we're searching the default hull size here for a player in the way of our spawning.
|
||||
-- This seems pretty rough, seeing as our player's hull could be different.. but it should do the job
|
||||
-- (HL2DM kills everything within a 128 unit radius)
|
||||
if ( pl:Team() == TEAM_SPECTATOR ) then return true end
|
||||
|
||||
local Blockers = 0
|
||||
for k, v in ipairs( ents.FindInBox( Pos + spawnpointmin, Pos + spawnpointmax ) ) do
|
||||
if ( IsValid( v ) && v != pl && v:GetClass() == "player" && v:Alive() ) then
|
||||
|
||||
Blockers = Blockers + 1
|
||||
|
||||
if ( bMakeSuitable ) then
|
||||
v:Kill()
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
if ( bMakeSuitable ) then return true end
|
||||
if ( Blockers > 0 ) then return false end
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSelectSpawn( player )
|
||||
Desc: Find a spawn point entity for this player
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSelectSpawn( pl, transiton )
|
||||
|
||||
-- If we are in transition, do not reset player's position
|
||||
if ( transiton ) then return end
|
||||
|
||||
if ( self.TeamBased ) then
|
||||
|
||||
local ent = self:PlayerSelectTeamSpawn( pl:Team(), pl )
|
||||
if ( IsValid( ent ) ) then return ent end
|
||||
|
||||
end
|
||||
|
||||
-- Save information about all of the spawn points
|
||||
-- in a team based game you'd split up the spawns
|
||||
if ( !IsTableOfEntitiesValid( self.SpawnPoints ) ) then
|
||||
|
||||
self.LastSpawnPoint = 0
|
||||
self.SpawnPoints = ents.FindByClass( "info_player_start" )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_deathmatch" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_combine" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_rebel" ) )
|
||||
|
||||
-- CS Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_counterterrorist" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_terrorist" ) )
|
||||
|
||||
-- DOD Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_axis" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_allies" ) )
|
||||
|
||||
-- (Old) GMod Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "gmod_player_start" ) )
|
||||
|
||||
-- TF Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_teamspawn" ) )
|
||||
|
||||
-- INS Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "ins_spawnpoint" ) )
|
||||
|
||||
-- AOC Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "aoc_spawnpoint" ) )
|
||||
|
||||
-- Dystopia Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "dys_spawn_point" ) )
|
||||
|
||||
-- PVKII Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_pirate" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_viking" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_knight" ) )
|
||||
|
||||
-- DIPRIP Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "diprip_start_team_blue" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "diprip_start_team_red" ) )
|
||||
|
||||
-- OB Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_red" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_blue" ) )
|
||||
|
||||
-- SYN Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_coop" ) )
|
||||
|
||||
-- ZPS Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_human" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_zombie" ) )
|
||||
|
||||
-- ZM Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_zombiemaster" ) )
|
||||
|
||||
-- FOF Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_fof" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_desperado" ) )
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_player_vigilante" ) )
|
||||
|
||||
-- L4D Maps
|
||||
self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_survivor_rescue" ) )
|
||||
-- Removing this one for the time being, c1m4_atrium has one of these in a box under the map
|
||||
--self.SpawnPoints = table.Add( self.SpawnPoints, ents.FindByClass( "info_survivor_position" ) )
|
||||
|
||||
end
|
||||
|
||||
local Count = table.Count( self.SpawnPoints )
|
||||
|
||||
if ( Count == 0 ) then
|
||||
Msg("[PlayerSelectSpawn] Error! No spawn points!\n")
|
||||
return nil
|
||||
end
|
||||
|
||||
-- If any of the spawnpoints have a MASTER flag then only use that one.
|
||||
-- This is needed for single player maps.
|
||||
for k, v in pairs( self.SpawnPoints ) do
|
||||
|
||||
if ( v:HasSpawnFlags( 1 ) && hook.Call( "IsSpawnpointSuitable", GAMEMODE, pl, v, true ) ) then
|
||||
return v
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local ChosenSpawnPoint = nil
|
||||
|
||||
-- Try to work out the best, random spawnpoint
|
||||
for i = 1, Count do
|
||||
|
||||
ChosenSpawnPoint = table.Random( self.SpawnPoints )
|
||||
|
||||
if ( IsValid( ChosenSpawnPoint ) && ChosenSpawnPoint:IsInWorld() ) then
|
||||
if ( ( ChosenSpawnPoint == pl:GetVar( "LastSpawnpoint" ) || ChosenSpawnPoint == self.LastSpawnPoint ) && Count > 1 ) then continue end
|
||||
|
||||
if ( hook.Call( "IsSpawnpointSuitable", GAMEMODE, pl, ChosenSpawnPoint, i == Count ) ) then
|
||||
|
||||
self.LastSpawnPoint = ChosenSpawnPoint
|
||||
pl:SetVar( "LastSpawnpoint", ChosenSpawnPoint )
|
||||
return ChosenSpawnPoint
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return ChosenSpawnPoint
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:WeaponEquip( weapon )
|
||||
Desc: Player just picked up (or was given) weapon
|
||||
-----------------------------------------------------------]]
|
||||
function GM:WeaponEquip( weapon )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ScalePlayerDamage( ply, hitgroup, dmginfo )
|
||||
Desc: Scale the damage based on being shot in a hitbox
|
||||
Return true to not take damage
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ScalePlayerDamage( ply, hitgroup, dmginfo )
|
||||
|
||||
-- More damage if we're shot in the head
|
||||
if ( hitgroup == HITGROUP_HEAD ) then
|
||||
|
||||
dmginfo:ScaleDamage( 2 )
|
||||
|
||||
end
|
||||
|
||||
-- Less damage if we're shot in the arms or legs
|
||||
if ( hitgroup == HITGROUP_LEFTARM ||
|
||||
hitgroup == HITGROUP_RIGHTARM ||
|
||||
hitgroup == HITGROUP_LEFTLEG ||
|
||||
hitgroup == HITGROUP_RIGHTLEG ||
|
||||
hitgroup == HITGROUP_GEAR ) then
|
||||
|
||||
dmginfo:ScaleDamage( 0.25 )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerDeathSound()
|
||||
Desc: Return true to not play the default sounds
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerDeathSound()
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:SetupPlayerVisibility()
|
||||
Desc: Add extra positions to the player's PVS
|
||||
-----------------------------------------------------------]]
|
||||
function GM:SetupPlayerVisibility( pPlayer, pViewEntity )
|
||||
--AddOriginToPVS( vector_position_here )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:OnDamagedByExplosion( ply, dmginfo)
|
||||
Desc: Player has been hurt by an explosion
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnDamagedByExplosion( ply, dmginfo )
|
||||
ply:SetDSP( 35, false )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:CanPlayerSuicide( ply )
|
||||
Desc: Player typed KILL in the console. Can they kill themselves?
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CanPlayerSuicide( ply )
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:CanPlayerEnterVehicle( player, vehicle, role )
|
||||
Desc: Return true if player can enter vehicle
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CanPlayerEnterVehicle( ply, vehicle, role )
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerEnteredVehicle( player, vehicle, role )
|
||||
Desc: Player entered the vehicle fine
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerEnteredVehicle( ply, vehicle, role )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:CanExitVehicle()
|
||||
Desc: If the player is allowed to leave the vehicle, return true
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CanExitVehicle( vehicle, passenger )
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerLeaveVehicle()
|
||||
Desc: Player left the vehicle
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerLeaveVehicle( ply, vehicle )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSwitchFlashlight()
|
||||
Desc: Return true to allow action
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSwitchFlashlight( ply, SwitchOn )
|
||||
return ply:CanUseFlashlight()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerCanJoinTeam( ply, teamid )
|
||||
Desc: Allow mods/addons to easily determine whether a player
|
||||
can join a team or not
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerCanJoinTeam( ply, teamid )
|
||||
|
||||
local TimeBetweenSwitches = GAMEMODE.SecondsBetweenTeamSwitches or 10
|
||||
if ( ply.LastTeamSwitch && RealTime() - ply.LastTeamSwitch < TimeBetweenSwitches ) then
|
||||
ply.LastTeamSwitch = ply.LastTeamSwitch + 1
|
||||
ply:ChatPrint( Format( "Please wait %i more seconds before trying to change team again", ( TimeBetweenSwitches - ( RealTime() - ply.LastTeamSwitch ) ) + 1 ) )
|
||||
return false
|
||||
end
|
||||
|
||||
-- Already on this team!
|
||||
if ( ply:Team() == teamid ) then
|
||||
ply:ChatPrint( "You're already on that team" )
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerRequestTeam()
|
||||
Desc: Player wants to change team
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerRequestTeam( ply, teamid )
|
||||
|
||||
-- No changing teams if not teambased!
|
||||
if ( !GAMEMODE.TeamBased ) then return end
|
||||
|
||||
-- This team isn't joinable
|
||||
if ( !team.Joinable( teamid ) ) then
|
||||
ply:ChatPrint( "You can't join that team" )
|
||||
return end
|
||||
|
||||
-- This team isn't joinable
|
||||
if ( !GAMEMODE:PlayerCanJoinTeam( ply, teamid ) ) then
|
||||
-- Messages here should be outputted by this function
|
||||
return end
|
||||
|
||||
GAMEMODE:PlayerJoinTeam( ply, teamid )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerJoinTeam()
|
||||
Desc: Make player join this team
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerJoinTeam( ply, teamid )
|
||||
|
||||
local iOldTeam = ply:Team()
|
||||
|
||||
if ( ply:Alive() ) then
|
||||
if ( iOldTeam == TEAM_SPECTATOR || iOldTeam == TEAM_UNASSIGNED ) then
|
||||
ply:KillSilent()
|
||||
else
|
||||
ply:Kill()
|
||||
end
|
||||
end
|
||||
|
||||
ply:SetTeam( teamid )
|
||||
ply.LastTeamSwitch = RealTime()
|
||||
|
||||
GAMEMODE:OnPlayerChangedTeam( ply, iOldTeam, teamid )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:OnPlayerChangedTeam( ply, oldteam, newteam )
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnPlayerChangedTeam( ply, oldteam, newteam )
|
||||
|
||||
-- Here's an immediate respawn thing by default. If you want to
|
||||
-- re-create something more like CS or some shit you could probably
|
||||
-- change to a spectator or something while dead.
|
||||
if ( newteam == TEAM_SPECTATOR ) then
|
||||
|
||||
-- If we changed to spectator mode, respawn where we are
|
||||
local Pos = ply:EyePos()
|
||||
ply:Spawn()
|
||||
ply:SetPos( Pos )
|
||||
|
||||
elseif ( oldteam == TEAM_SPECTATOR ) then
|
||||
|
||||
-- If we're changing from spectator, join the game
|
||||
ply:Spawn()
|
||||
|
||||
else
|
||||
|
||||
-- If we're straight up changing teams just hang
|
||||
-- around until we're ready to respawn onto the
|
||||
-- team that we chose
|
||||
|
||||
end
|
||||
|
||||
PrintMessage( HUD_PRINTTALK, Format( "%s joined '%s'", ply:Nick(), team.GetName( newteam ) ) )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerSpray()
|
||||
Desc: Return true to prevent player spraying
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerSpray( ply )
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:OnPlayerHitGround()
|
||||
Desc: Return true to disable default action
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnPlayerHitGround( ply, bInWater, bOnFloater, flFallSpeed )
|
||||
|
||||
-- Apply damage and play collision sound here
|
||||
-- then return true to disable the default action
|
||||
--MsgN( ply, bInWater, bOnFloater, flFallSpeed )
|
||||
--return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:GetFallDamage()
|
||||
Desc: return amount of damage to do due to fall
|
||||
-----------------------------------------------------------]]
|
||||
local mp_falldamage = GetConVar( "mp_falldamage" )
|
||||
|
||||
function GM:GetFallDamage( ply, flFallSpeed )
|
||||
|
||||
if ( mp_falldamage:GetBool() ) then -- realistic fall damage is on
|
||||
return ( flFallSpeed - 526.5 ) * ( 100 / 396 ) -- the Source SDK value
|
||||
end
|
||||
|
||||
return 10
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerCanSeePlayersChat()
|
||||
Desc: Can this player see the other player's chat?
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerCanSeePlayersChat( strText, bTeamOnly, pListener, pSpeaker )
|
||||
|
||||
if ( bTeamOnly ) then
|
||||
if ( !IsValid( pSpeaker ) || !IsValid( pListener ) ) then return false end
|
||||
if ( pListener:Team() != pSpeaker:Team() ) then return false end
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
local sv_alltalk = GetConVar( "sv_alltalk" )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerCanHearPlayersVoice()
|
||||
Desc: Can this player see the other player's voice?
|
||||
Returns 2 bools.
|
||||
1. Can the player hear the other player
|
||||
2. Can they hear them spacially
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerCanHearPlayersVoice( pListener, pTalker )
|
||||
|
||||
local alltalk = sv_alltalk:GetInt()
|
||||
if ( alltalk >= 1 ) then return true, alltalk == 2 end
|
||||
|
||||
return pListener:Team() == pTalker:Team(), false
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:NetworkIDValidated()
|
||||
Desc: Called when Steam has validated this as a valid player
|
||||
-----------------------------------------------------------]]
|
||||
function GM:NetworkIDValidated( name, steamid )
|
||||
|
||||
-- MsgN( "GM:NetworkIDValidated", name, steamid )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerShouldTaunt( ply, actid )
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerShouldTaunt( ply, actid )
|
||||
|
||||
-- The default behaviour is to always let them act
|
||||
-- Some gamemodes will obviously want to stop this for certain players by returning false
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerStartTaunt( ply, actid, length )
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerStartTaunt( ply, actid, length )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:AllowPlayerPickup( ply, object )
|
||||
-----------------------------------------------------------]]
|
||||
function GM:AllowPlayerPickup( ply, object )
|
||||
|
||||
-- Should the player be allowed to pick this object up (using ENTER)?
|
||||
-- If no then return false. Default is HELL YEAH
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerDroppedWeapon()
|
||||
Desc: Player has dropped a weapon
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerDroppedWeapon( ply, weapon )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
These are buttons that the client is pressing. They're used
|
||||
in Sandbox mode to control things like wheels, thrusters etc.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerButtonDown( ply, btn ) end
|
||||
function GM:PlayerButtonUp( ply, btn ) end
|
||||
|
||||
concommand.Add( "changeteam", function( pl, cmd, args ) hook.Call( "PlayerRequestTeam", GAMEMODE, pl, tonumber( args[ 1 ] ) ) end )
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:HandlePlayerArmorReduction()
|
||||
Desc: Handle player armor reduction
|
||||
-----------------------------------------------------------]]
|
||||
function GM:HandlePlayerArmorReduction( ply, dmginfo )
|
||||
|
||||
-- If no armor, or special damage types, bypass armor
|
||||
if ( ply:Armor() <= 0 || bit.band( dmginfo:GetDamageType(), DMG_FALL + DMG_DROWN + DMG_POISON + DMG_RADIATION ) != 0 ) then return end
|
||||
|
||||
local flBonus = 1.0 -- Each Point of Armor is worth 1/x points of health
|
||||
local flRatio = 0.2 -- Armor Takes 80% of the damage
|
||||
if ( GetConVar( "player_old_armor" ):GetBool() ) then
|
||||
flBonus = 0.5
|
||||
end
|
||||
|
||||
local flNew = dmginfo:GetDamage() * flRatio
|
||||
local flArmor = (dmginfo:GetDamage() - flNew) * flBonus
|
||||
|
||||
if ( !GetConVar( "player_old_armor" ):GetBool() ) then
|
||||
if ( flArmor < 0.1 ) then flArmor = 0 end -- Let's not have tiny amounts of damage reduce a lot of our armor
|
||||
else if ( flArmor < 1.0 ) then flArmor = 1.0 end
|
||||
end
|
||||
|
||||
-- Does this use more armor than we have?
|
||||
if ( flArmor > ply:Armor() ) then
|
||||
|
||||
flArmor = ply:Armor() * ( 1 / flBonus )
|
||||
flNew = dmginfo:GetDamage() - flArmor
|
||||
ply:SetArmor( 0 )
|
||||
|
||||
else
|
||||
ply:SetArmor( ply:Armor() - flArmor )
|
||||
end
|
||||
|
||||
dmginfo:SetDamage( flNew )
|
||||
|
||||
end
|
||||
145
gamemodes/base/gamemode/player_class/player_default.lua
Normal file
145
gamemodes/base/gamemode/player_class/player_default.lua
Normal file
@@ -0,0 +1,145 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
include( "taunt_camera.lua" )
|
||||
|
||||
local PLAYER = {}
|
||||
|
||||
PLAYER.DisplayName = "Default Class"
|
||||
|
||||
PLAYER.SlowWalkSpeed = 200 -- How fast to move when slow-walking (+WALK)
|
||||
PLAYER.WalkSpeed = 400 -- How fast to move when not running
|
||||
PLAYER.RunSpeed = 600 -- How fast to move when running
|
||||
PLAYER.CrouchedWalkSpeed = 0.3 -- Multiply move speed by this when crouching
|
||||
PLAYER.DuckSpeed = 0.3 -- How fast to go from not ducking, to ducking
|
||||
PLAYER.UnDuckSpeed = 0.3 -- How fast to go from ducking, to not ducking
|
||||
PLAYER.JumpPower = 200 -- How powerful our jump should be
|
||||
PLAYER.CanUseFlashlight = true -- Can we use the flashlight
|
||||
PLAYER.MaxHealth = 100 -- Max health we can have
|
||||
PLAYER.MaxArmor = 100 -- Max armor we can have
|
||||
PLAYER.StartHealth = 100 -- How much health we start with
|
||||
PLAYER.StartArmor = 0 -- How much armour we start with
|
||||
PLAYER.DropWeaponOnDie = false -- Do we drop our weapon when we die
|
||||
PLAYER.TeammateNoCollide = true -- Do we collide with teammates or run straight through them
|
||||
PLAYER.AvoidPlayers = true -- Automatically swerves around other players
|
||||
PLAYER.UseVMHands = true -- Uses viewmodel hands
|
||||
|
||||
--
|
||||
-- Name: PLAYER:SetupDataTables
|
||||
-- Desc: Set up the network table accessors
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function PLAYER:SetupDataTables()
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: PLAYER:Init
|
||||
-- Desc: Called when the class object is created (shared)
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function PLAYER:Init()
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: PLAYER:Spawn
|
||||
-- Desc: Called serverside only when the player spawns
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function PLAYER:Spawn()
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: PLAYER:Loadout
|
||||
-- Desc: Called on spawn to give the player their default loadout
|
||||
-- Arg1:
|
||||
-- Ret1:
|
||||
--
|
||||
function PLAYER:Loadout()
|
||||
|
||||
self.Player:Give( "weapon_pistol" )
|
||||
self.Player:GiveAmmo( 255, "Pistol", true )
|
||||
|
||||
end
|
||||
|
||||
function PLAYER:SetModel()
|
||||
|
||||
local cl_playermodel = self.Player:GetInfo( "cl_playermodel" )
|
||||
local modelname = player_manager.TranslatePlayerModel( cl_playermodel )
|
||||
util.PrecacheModel( modelname )
|
||||
self.Player:SetModel( modelname )
|
||||
|
||||
end
|
||||
|
||||
function PLAYER:Death( inflictor, attacker )
|
||||
end
|
||||
|
||||
-- Clientside only
|
||||
function PLAYER:CalcView( view ) end -- Setup the player's view
|
||||
function PLAYER:CreateMove( cmd ) end -- Creates the user command on the client
|
||||
function PLAYER:ShouldDrawLocal() end -- Return true if we should draw the local player
|
||||
|
||||
-- Shared
|
||||
function PLAYER:StartMove( cmd, mv ) end -- Copies from the user command to the move
|
||||
function PLAYER:Move( mv ) end -- Runs the move (can run multiple times for the same client)
|
||||
function PLAYER:FinishMove( mv ) end -- Copy the results of the move back to the Player
|
||||
|
||||
--
|
||||
-- Name: PLAYER:ViewModelChanged
|
||||
-- Desc: Called when the player changes their weapon to another one causing their viewmodel model to change
|
||||
-- Arg1: Entity|viewmodel|The viewmodel that is changing
|
||||
-- Arg2: string|old|The old model
|
||||
-- Arg3: string|new|The new model
|
||||
-- Ret1:
|
||||
--
|
||||
function PLAYER:ViewModelChanged( vm, old, new )
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: PLAYER:PreDrawViewmodel
|
||||
-- Desc: Called before the viewmodel is being drawn (clientside)
|
||||
-- Arg1: Entity|viewmodel|The viewmodel
|
||||
-- Arg2: Entity|weapon|The weapon
|
||||
-- Ret1:
|
||||
--
|
||||
function PLAYER:PreDrawViewModel( vm, weapon )
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: PLAYER:PostDrawViewModel
|
||||
-- Desc: Called after the viewmodel has been drawn (clientside)
|
||||
-- Arg1: Entity|viewmodel|The viewmodel
|
||||
-- Arg2: Entity|weapon|The weapon
|
||||
-- Ret1:
|
||||
--
|
||||
function PLAYER:PostDrawViewModel( vm, weapon )
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: PLAYER:GetHandsModel
|
||||
-- Desc: Called on player spawn to determine which hand model to use
|
||||
-- Arg1:
|
||||
-- Ret1: table|info|A table containing model, skin and body
|
||||
--
|
||||
function PLAYER:GetHandsModel()
|
||||
|
||||
-- return { model = "models/weapons/c_arms_cstrike.mdl", skin = 1, body = "0100000" }
|
||||
|
||||
local playermodel = player_manager.TranslateToPlayerModelName( self.Player:GetModel() )
|
||||
return player_manager.TranslatePlayerHands( playermodel )
|
||||
|
||||
end
|
||||
|
||||
player_manager.RegisterClass( "player_default", PLAYER, nil )
|
||||
133
gamemodes/base/gamemode/player_class/taunt_camera.lua
Normal file
133
gamemodes/base/gamemode/player_class/taunt_camera.lua
Normal file
@@ -0,0 +1,133 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
--
|
||||
-- This is designed so you can call it like
|
||||
--
|
||||
-- tauntcam = TauntCamera()
|
||||
--
|
||||
-- Then you have your own copy.
|
||||
--
|
||||
function TauntCamera()
|
||||
|
||||
local CAM = {}
|
||||
|
||||
local WasOn = false
|
||||
|
||||
local CustomAngles = angle_zero
|
||||
local PlayerLockAngles = nil
|
||||
|
||||
local InLerp = 0
|
||||
local OutLerp = 1
|
||||
|
||||
--
|
||||
-- Draw the local player if we're active in any way
|
||||
--
|
||||
CAM.ShouldDrawLocalPlayer = function( self, ply, on )
|
||||
|
||||
return on || OutLerp < 1
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Implements the third person, rotation view (with lerping in/out)
|
||||
--
|
||||
CAM.CalcView = function( self, view, ply, on )
|
||||
|
||||
if ( !ply:Alive() || !IsValid( ply:GetViewEntity() ) || ply:GetViewEntity() != ply ) then on = false end
|
||||
|
||||
if ( WasOn != on ) then
|
||||
|
||||
if ( on ) then InLerp = 0 end
|
||||
if ( !on ) then OutLerp = 0 end
|
||||
|
||||
WasOn = on
|
||||
|
||||
end
|
||||
|
||||
if ( !on && OutLerp >= 1 ) then
|
||||
|
||||
CustomAngles = view.angles * 1
|
||||
CustomAngles.r = 0
|
||||
PlayerLockAngles = nil
|
||||
InLerp = 0
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
if ( PlayerLockAngles == nil ) then return end
|
||||
|
||||
--
|
||||
-- Simple 3rd person camera
|
||||
--
|
||||
local TargetOrigin = view.origin - CustomAngles:Forward() * 100
|
||||
local tr = util.TraceHull( { start = view.origin, endpos = TargetOrigin, mask = MASK_SHOT, filter = player.GetAll(), mins = Vector( -8, -8, -8 ), maxs = Vector( 8, 8, 8 ) } )
|
||||
TargetOrigin = tr.HitPos + tr.HitNormal
|
||||
|
||||
if ( InLerp < 1 ) then
|
||||
|
||||
InLerp = InLerp + FrameTime() * 5.0
|
||||
view.origin = LerpVector( InLerp, view.origin, TargetOrigin )
|
||||
view.angles = LerpAngle( InLerp, PlayerLockAngles, CustomAngles )
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
if ( OutLerp < 1 ) then
|
||||
|
||||
OutLerp = OutLerp + FrameTime() * 3.0
|
||||
view.origin = LerpVector( 1-OutLerp, view.origin, TargetOrigin )
|
||||
view.angles = LerpAngle( 1-OutLerp, PlayerLockAngles, CustomAngles )
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
view.angles = CustomAngles * 1
|
||||
view.origin = TargetOrigin
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Freezes the player in position and uses the input from the user command to
|
||||
-- rotate the custom third person camera
|
||||
--
|
||||
CAM.CreateMove = function( self, cmd, ply, on )
|
||||
|
||||
if ( !ply:Alive() ) then on = false end
|
||||
if ( !on ) then return end
|
||||
|
||||
if ( PlayerLockAngles == nil ) then
|
||||
PlayerLockAngles = CustomAngles * 1
|
||||
end
|
||||
|
||||
--
|
||||
-- Rotate our view
|
||||
--
|
||||
CustomAngles.pitch = CustomAngles.pitch + cmd:GetMouseY() * 0.01
|
||||
CustomAngles.yaw = CustomAngles.yaw - cmd:GetMouseX() * 0.01
|
||||
|
||||
--
|
||||
-- Lock the player's controls and angles
|
||||
--
|
||||
cmd:SetViewAngles( PlayerLockAngles )
|
||||
cmd:ClearButtons()
|
||||
cmd:ClearMovement()
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
return CAM
|
||||
|
||||
end
|
||||
145
gamemodes/base/gamemode/player_shd.lua
Normal file
145
gamemodes/base/gamemode/player_shd.lua
Normal file
@@ -0,0 +1,145 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerTraceAttack( )
|
||||
Desc: A bullet has been fired and hit this player
|
||||
Return true to completely override internals
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerTraceAttack( ply, dmginfo, dir, trace )
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:SetPlayerSpeed( )
|
||||
Desc: Sets the player's run/walk speed
|
||||
-----------------------------------------------------------]]
|
||||
function GM:SetPlayerSpeed( ply, walk, run )
|
||||
|
||||
ply:SetWalkSpeed( walk )
|
||||
ply:SetRunSpeed( run )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerFootstep( ply, vPos, iFoot, strSoundName, fVolume, pFilter )
|
||||
Desc: Called when a player steps
|
||||
pFilter is the recipient filter to use for effects/sounds
|
||||
and is only valid SERVERSIDE. Clientside needs no filter!
|
||||
Return true to not play normal sound
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerFootstep( ply, vPos, iFoot, strSoundName, fVolume, pFilter )
|
||||
if ( IsValid( ply ) and !ply:Alive() ) then
|
||||
return true
|
||||
end
|
||||
|
||||
--[[
|
||||
-- Draw effect on footdown
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( vPos )
|
||||
util.Effect( "phys_unfreeze", effectdata, true, pFilter )
|
||||
--]]
|
||||
|
||||
--[[
|
||||
-- Don't play left foot
|
||||
if ( iFoot == 0 ) then return true end
|
||||
--]]
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerStepSoundTime( ply, iType, bWalking )
|
||||
Desc: Return the time between footsteps
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerStepSoundTime( ply, iType, bWalking )
|
||||
|
||||
local fStepTime = 350
|
||||
local fMaxSpeed = ply:GetMaxSpeed()
|
||||
|
||||
if ( iType == STEPSOUNDTIME_NORMAL || iType == STEPSOUNDTIME_WATER_FOOT ) then
|
||||
|
||||
if ( fMaxSpeed <= 100 ) then
|
||||
fStepTime = 400
|
||||
elseif ( fMaxSpeed <= 300 ) then
|
||||
fStepTime = 350
|
||||
else
|
||||
fStepTime = 250
|
||||
end
|
||||
|
||||
elseif ( iType == STEPSOUNDTIME_ON_LADDER ) then
|
||||
|
||||
fStepTime = 450
|
||||
|
||||
elseif ( iType == STEPSOUNDTIME_WATER_KNEE ) then
|
||||
|
||||
fStepTime = 600
|
||||
|
||||
end
|
||||
|
||||
-- Step slower if crouching
|
||||
if ( ply:Crouching() ) then
|
||||
fStepTime = fStepTime + 50
|
||||
end
|
||||
|
||||
return fStepTime
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerNoClip( player, bool )
|
||||
Desc: Player pressed the noclip key, return true if
|
||||
the player is allowed to noclip, false to block
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerNoClip( pl, on )
|
||||
if ( !on ) then return true end
|
||||
-- Allow noclip if we're in single player and living
|
||||
return game.SinglePlayer() && IsValid( pl ) && pl:Alive()
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- FindUseEntity
|
||||
--
|
||||
function GM:FindUseEntity( ply, ent )
|
||||
|
||||
-- ent is what the game found to use by default
|
||||
-- return what you REALLY want it to use
|
||||
|
||||
-- Simple fix to allow entities inside playerclip brushes to be used. Necessary for c1a0c map in Half-Life: Source
|
||||
if ( !IsValid( ent ) ) then
|
||||
local traceEnt = util.TraceLine( {
|
||||
start = ply:GetShootPos(),
|
||||
endpos = ply:GetShootPos() + ply:GetAimVector() * 72,
|
||||
filter = ply
|
||||
} ).Entity
|
||||
if ( IsValid( traceEnt ) ) then return traceEnt end
|
||||
end
|
||||
|
||||
return ent
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Player tick
|
||||
--
|
||||
function GM:PlayerTick( ply, mv )
|
||||
end
|
||||
|
||||
--
|
||||
-- Player is switching weapon. Return true to prevent the switch.
|
||||
--
|
||||
function GM:PlayerSwitchWeapon( ply, oldwep, newwep )
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
282
gamemodes/base/gamemode/shared.lua
Normal file
282
gamemodes/base/gamemode/shared.lua
Normal file
@@ -0,0 +1,282 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
|
||||
This file should contain variables and functions that are
|
||||
the same on both client and server.
|
||||
|
||||
This file will get sent to the client - so don't add
|
||||
anything to this file that you don't want them to be
|
||||
able to see.
|
||||
|
||||
-----------------------------------------------------------]]
|
||||
|
||||
include( "obj_player_extend.lua" )
|
||||
|
||||
include( "gravitygun.lua" )
|
||||
include( "player_shd.lua" )
|
||||
include( "animations.lua" )
|
||||
include( "player_class/player_default.lua" )
|
||||
|
||||
GM.Name = "Base Gamemode"
|
||||
GM.Author = "Garry Newman"
|
||||
GM.Email = "garrynewman@gmail.com"
|
||||
GM.Website = "www.garry.tv"
|
||||
GM.TeamBased = false
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:KeyPress( )
|
||||
Desc: Player pressed a key (see IN enums)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:KeyPress( player, key )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:KeyRelease( )
|
||||
Desc: Player released a key (see IN enums)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:KeyRelease( player, key )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PlayerConnect( )
|
||||
Desc: Player has connects to the server (hasn't spawned)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerConnect( name, address )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PropBreak( )
|
||||
Desc: Prop has been broken
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PropBreak( attacker, prop )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PhysgunPickup( )
|
||||
Desc: Return true if player can pickup entity
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PhysgunPickup( ply, ent )
|
||||
|
||||
-- Don't pick up players
|
||||
if ( ent:GetClass() == "player" ) then return false end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:PhysgunDrop( )
|
||||
Desc: Dropped an entity
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PhysgunDrop( ply, ent )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Text to show in the server browser
|
||||
-----------------------------------------------------------]]
|
||||
function GM:GetGameDescription()
|
||||
return self.Name
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Saved
|
||||
-----------------------------------------------------------]]
|
||||
function GM:Saved()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Restored
|
||||
-----------------------------------------------------------]]
|
||||
function GM:Restored()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: EntityRemoved
|
||||
Desc: Called right before an entity is removed. Note that this
|
||||
isn't going to be totally reliable on the client since the client
|
||||
only knows about entities that it has had in its PVS.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:EntityRemoved( ent )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Tick
|
||||
Desc: Like Think except called every tick on both client and server
|
||||
-----------------------------------------------------------]]
|
||||
function GM:Tick()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnEntityCreated
|
||||
Desc: Called right after the Entity has been made visible to Lua
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnEntityCreated( Ent )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:EntityKeyValue( ent, key, value )
|
||||
Desc: Called when an entity has a keyvalue set
|
||||
Returning a string it will override the value
|
||||
-----------------------------------------------------------]]
|
||||
function GM:EntityKeyValue( ent, key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:CreateTeams()
|
||||
Desc: Note - HAS to be shared.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CreateTeams()
|
||||
|
||||
-- Don't do this if not teambased. But if it is teambased we
|
||||
-- create a few teams here as an example. If you're making a teambased
|
||||
-- gamemode you should override this function in your gamemode
|
||||
|
||||
if ( !GAMEMODE.TeamBased ) then return end
|
||||
|
||||
TEAM_BLUE = 1
|
||||
team.SetUp( TEAM_BLUE, "Blue Team", Color( 0, 0, 255 ) )
|
||||
team.SetSpawnPoint( TEAM_BLUE, "ai_hint" ) -- <-- This would be info_terrorist or some entity that is in your map
|
||||
|
||||
TEAM_ORANGE = 2
|
||||
team.SetUp( TEAM_ORANGE, "Orange Team", Color( 255, 150, 0 ) )
|
||||
team.SetSpawnPoint( TEAM_ORANGE, "sky_camera" ) -- <-- This would be info_terrorist or some entity that is in your map
|
||||
|
||||
TEAM_SEXY = 3
|
||||
team.SetUp( TEAM_SEXY, "Sexy Team", Color( 255, 150, 150 ) )
|
||||
team.SetSpawnPoint( TEAM_SEXY, "info_player_start" ) -- <-- This would be info_terrorist or some entity that is in your map
|
||||
|
||||
team.SetSpawnPoint( TEAM_SPECTATOR, "worldspawn" )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:ShouldCollide( Ent1, Ent2 )
|
||||
Desc: This should always return true unless you have
|
||||
a good reason for it not to.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:ShouldCollide( Ent1, Ent2 )
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:Move
|
||||
This basically overrides the NOCLIP, PLAYERMOVE movement stuff.
|
||||
It's what actually performs the move.
|
||||
Return true to not perform any default movement actions. (completely override)
|
||||
-----------------------------------------------------------]]
|
||||
function GM:Move( ply, mv )
|
||||
|
||||
if ( drive.Move( ply, mv ) ) then return true end
|
||||
if ( player_manager.RunClass( ply, "Move", mv ) ) then return true end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
-- Purpose: This is called pre player movement and copies all the data necessary
|
||||
-- from the player for movement. Copy from the usercmd to move.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:SetupMove( ply, mv, cmd )
|
||||
|
||||
if ( drive.StartMove( ply, mv, cmd ) ) then return true end
|
||||
if ( player_manager.RunClass( ply, "StartMove", mv, cmd ) ) then return true end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: gamemode:FinishMove( player, movedata )
|
||||
-----------------------------------------------------------]]
|
||||
function GM:FinishMove( ply, mv )
|
||||
|
||||
if ( drive.FinishMove( ply, mv ) ) then return true end
|
||||
if ( player_manager.RunClass( ply, "FinishMove", mv ) ) then return true end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Called after the player's think.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerPostThink( ply )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
A player has started driving an entity
|
||||
-----------------------------------------------------------]]
|
||||
function GM:StartEntityDriving( ent, ply )
|
||||
|
||||
drive.Start( ply, ent )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
A player has stopped driving an entity
|
||||
-----------------------------------------------------------]]
|
||||
function GM:EndEntityDriving( ent, ply )
|
||||
|
||||
drive.End( ply, ent )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
To update the player's animation during a drive
|
||||
-----------------------------------------------------------]]
|
||||
function GM:PlayerDriveAnimate( ply )
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
The gamemode has been reloaded
|
||||
-----------------------------------------------------------]]
|
||||
function GM:OnReloaded()
|
||||
end
|
||||
|
||||
function GM:PreGamemodeLoaded()
|
||||
end
|
||||
|
||||
function GM:OnGamemodeLoaded()
|
||||
end
|
||||
|
||||
function GM:PostGamemodeLoaded()
|
||||
end
|
||||
|
||||
--
|
||||
-- Name: GM:OnViewModelChanged
|
||||
-- Desc: Called when the player changes their weapon to another one - and their viewmodel model changes
|
||||
-- Arg1: Entity|viewmodel|The viewmodel that is changing
|
||||
-- Arg2: string|old|The old model
|
||||
-- Arg3: string|new|The new model
|
||||
-- Ret1:
|
||||
--
|
||||
function GM:OnViewModelChanged( vm, old, new )
|
||||
|
||||
local ply = vm:GetOwner()
|
||||
if ( IsValid( ply ) ) then
|
||||
player_manager.RunClass( ply, "ViewModelChanged", vm, old, new )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Disable properties serverside for all non-sandbox derived gamemodes.
|
||||
-----------------------------------------------------------]]
|
||||
function GM:CanProperty( pl, property, ent )
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Allow hooks to override bullet without ignoring all other hooks
|
||||
-----------------------------------------------------------]]
|
||||
function GM:EntityFireBullets( ent, bullets )
|
||||
return true
|
||||
end
|
||||
42
gamemodes/base/gamemode/variable_edit.lua
Normal file
42
gamemodes/base/gamemode/variable_edit.lua
Normal file
@@ -0,0 +1,42 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
--
|
||||
-- Called when we've received a call from a client who wants to edit
|
||||
-- a particular entity.
|
||||
--
|
||||
function GM:VariableEdited( ent, ply, key, val, editor )
|
||||
|
||||
if ( !IsValid( ent ) ) then return end
|
||||
if ( !IsValid( ply ) ) then return end
|
||||
|
||||
--
|
||||
-- Check with the gamemode that we can edit the entity
|
||||
--
|
||||
local CanEdit = hook.Run( "CanEditVariable", ent, ply, key, val, editor )
|
||||
if ( !CanEdit ) then return end
|
||||
|
||||
--
|
||||
-- Actually apply the edited value
|
||||
--
|
||||
ent:EditValue( key, val )
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Your gamemode should use this hook to allow/dissallow editing
|
||||
-- By default only admins can edit entities.
|
||||
--
|
||||
function GM:CanEditVariable( ent, ply, key, val, editor )
|
||||
|
||||
return ply:IsAdmin() || game.SinglePlayer()
|
||||
|
||||
end
|
||||
32
gamemodes/base/send.txt
Normal file
32
gamemodes/base/send.txt
Normal file
@@ -0,0 +1,32 @@
|
||||
#
|
||||
# These files aren't fully sent to the client because they
|
||||
# should never change. Instead we send the CRC of this file
|
||||
# so the client can load their version - and we know it's kewl.
|
||||
#
|
||||
gamemodes\base\gamemode\player_class\player_default.lua
|
||||
gamemodes\base\entities\weapons\weapon_base\cl_init.lua
|
||||
gamemodes\base\entities\weapons\weapon_base\shared.lua
|
||||
gamemodes\base\entities\weapons\weapon_base\ai_translations.lua
|
||||
gamemodes\base\entities\weapons\weapon_base\sh_anim.lua
|
||||
gamemodes\base\entities\entities\base_point.lua
|
||||
gamemodes\base\entities\entities\base_ai\cl_init.lua
|
||||
gamemodes\base\entities\entities\base_ai\shared.lua
|
||||
gamemodes\base\entities\entities\base_anim.lua
|
||||
gamemodes\base\entities\entities\base_entity\cl_init.lua
|
||||
gamemodes\base\entities\entities\base_entity\shared.lua
|
||||
gamemodes\base\entities\entities\prop_effect.lua
|
||||
gamemodes\base\entities\effects\base.lua
|
||||
gamemodes\base\entities\effects\dof_node.lua
|
||||
gamemodes\base\gamemode\cl_init.lua
|
||||
gamemodes\base\gamemode\shared.lua
|
||||
gamemodes\base\gamemode\cl_scoreboard.lua
|
||||
gamemodes\base\gamemode\cl_targetid.lua
|
||||
gamemodes\base\gamemode\cl_hudpickup.lua
|
||||
gamemodes\base\gamemode\cl_spawnmenu.lua
|
||||
gamemodes\base\gamemode\cl_deathnotice.lua
|
||||
gamemodes\base\gamemode\cl_pickteam.lua
|
||||
gamemodes\base\gamemode\cl_voice.lua
|
||||
gamemodes\base\gamemode\gravitygun.lua
|
||||
gamemodes\base\gamemode\player_shd.lua
|
||||
gamemodes\base\gamemode\animations.lua
|
||||
gamemodes\base\gamemode\obj_player_extend.lua
|
||||
23
gamemodes/helix/LICENSE.txt
Normal file
23
gamemodes/helix/LICENSE.txt
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Brian Hang, Kyu Yeon Lee
|
||||
Copyright (c) 2018-2021 Alexander Grist-Hucker, Igor Radovanovic
|
||||
|
||||
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.
|
||||
72
gamemodes/helix/README.md
Normal file
72
gamemodes/helix/README.md
Normal file
@@ -0,0 +1,72 @@
|
||||
This is a private branch from the [public helix](https://github.com/nebulousCloud/helix) repository.
|
||||
|
||||
In order to keep this repository up to date with any changes made to the public helix repository, you can pull changes from the public repo to your local PC, and then push those changes to our private repository.
|
||||
|
||||
Setup the public helix repository as another remote called 'public':
|
||||
```
|
||||
git remote add public https://github.com/NebulousCloud/helix.git
|
||||
```
|
||||
|
||||
To pull in changes made on the public repository to your local PC:
|
||||
```
|
||||
git pull public master
|
||||
```
|
||||
|
||||
Fix any merge conflicts after pulling changes from the public repository on your local PC. Once all has been merged (or there were no conflicts), you can:
|
||||
```
|
||||
git push
|
||||
```
|
||||
|
||||
All commits will now have been nicely added to our private branch (including who made the commit, etc.).
|
||||
|
||||
|
||||
<p align="center">
|
||||
<img src="https://raw.githubusercontent.com/NebulousCloud/helix/master/docs/banner.gif" alt="Helix" />
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://discord.gg/2AutUcF">
|
||||
<img src="https://img.shields.io/discord/505957257125691423.svg" alt="Discord" />
|
||||
</a>
|
||||
<a href="https://github.com/NebulousCloud/helix/actions">
|
||||
<img src="https://img.shields.io/github/workflow/status/NebulousCloud/helix/CI" alt="Build Status" />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
Helix is a framework for roleplay gamemodes in [Garry's Mod](https://gmod.facepunch.com/), based off of [NutScript 1.1](https://github.com/rebel1324/NutScript). Helix provides a stable, feature-filled, open-source, and DRM-free base so you can focus more on the things you want: making gameplay.
|
||||
|
||||
## Getting Started
|
||||
Visit the getting started guide in the [documentation](https://docs.gethelix.co/manual/getting-started/) for an in-depth guide.
|
||||
|
||||
If you know what you're doing, a quick start for bootstrapping your own schema is forking/copying the skeleton schema at https://github.com/nebulouscloud/helix-skeleton. The skeleton contains all the important elements you need to have a functioning schema so you can get to coding right away.
|
||||
|
||||
You can also use our HL2 RP schema at https://github.com/nebulouscloud/helix-hl2rp as a base to work off of if you need something more fleshed out.
|
||||
|
||||
## Plugins
|
||||
If you'd like to enhance your gamemode, you can use any of the freely provided plugins available at the [Helix Plugin Center](https://plugins.gethelix.co). It is also encouraged to submit your own plugins for others to find and use at https://github.com/nebulouscloud/helix-plugins
|
||||
|
||||
## Documentation
|
||||
Up-to-date documentation can be found at https://docs.gethelix.co. This is automatically updated when commits are pushed to the master branch.
|
||||
|
||||
If you'd like to ask some questions or integrate with the community, you can always join our [Discord](https://discord.gg/2AutUcF) server. We highly encourage you to search through the documentation before posting a question - the docs contain a good deal of information about how the various systems in Helix work, and it might explain what you're looking for.
|
||||
|
||||
### Building documentation
|
||||
If you're planning on contributing to the documentation, you'll probably want to preview your changes before you commit. The documentation can be built using [LDoc](https://github.com/impulsh/ldoc) - note that we use a forked version to add some functionality. You'll need [LuaRocks](https://luarocks.org/) installed in order to get started.
|
||||
|
||||
```shell
|
||||
# installing ldoc
|
||||
git clone https://github.com/impulsh/ldoc
|
||||
cd ldoc
|
||||
luarocks make
|
||||
|
||||
# navigate to the helix repo folder and run
|
||||
ldoc .
|
||||
```
|
||||
|
||||
You may not see the syntax highlighting work on your local copy - you'll need to copy the files in `docs/js` and `docs/css` over into the `docs/html` folder after it's done building.
|
||||
|
||||
## Contributing
|
||||
Feel free to submit a pull request with any fixes/changes that you might find beneficial. Currently, there are no solid contributing guidelines other than keeping your code consistent with the rest of the framework.
|
||||
|
||||
## Acknowledgements
|
||||
Helix is a fork of NutScript 1.1 by [Chessnut](https://github.com/brianhang) and [rebel1324](https://github.com/rebel1324).
|
||||
77
gamemodes/helix/config.ld
Normal file
77
gamemodes/helix/config.ld
Normal file
@@ -0,0 +1,77 @@
|
||||
|
||||
file = {
|
||||
"gamemode",
|
||||
"plugins",
|
||||
"docs/hooks",
|
||||
exclude = {"gamemode/core/libs/thirdparty"}
|
||||
}
|
||||
|
||||
module_file = {
|
||||
Character = "gamemode/core/meta/sh_character.lua",
|
||||
Entity = "gamemode/core/meta/sh_entity.lua",
|
||||
Inventory = "gamemode/core/meta/sh_inventory.lua",
|
||||
Item = "gamemode/core/meta/sh_item.lua",
|
||||
Player = "gamemode/core/meta/sh_player.lua"
|
||||
}
|
||||
|
||||
dir = "docs/html"
|
||||
project = "Helix"
|
||||
title = "Helix Documentation"
|
||||
|
||||
no_space_before_args = true
|
||||
style = "docs/css"
|
||||
template = "docs/templates"
|
||||
format = "markdown"
|
||||
ignore = true
|
||||
topics = "docs/manual"
|
||||
use_markdown_titles = true
|
||||
kind_names = {module = "Libraries", topic = "Manual"}
|
||||
merge = true
|
||||
sort = true
|
||||
sort_modules = true
|
||||
|
||||
simple_args_string = true -- we show optionals/defaults outside of the display name
|
||||
strip_metamethod_prefix = true -- remove the name of the table when displaying metamethod names
|
||||
no_viewed_topic_at_top = true -- don't put the currently viewed topic at the top
|
||||
use_new_templates = true -- new templating system
|
||||
pretty_urls = true -- avoid showing .html in urls
|
||||
pretty_topic_names = true -- strips extension from manual filenames, this does not check filename collisions
|
||||
|
||||
custom_tags = {
|
||||
{"realm", hidden = true},
|
||||
{"internal", hidden = true}
|
||||
}
|
||||
|
||||
custom_display_name_handler = function(item, default_handler)
|
||||
if (item.type == "function" and item.module) then
|
||||
if (item.module.type == "classmod" or item.module.type == "panel") then
|
||||
return item.module.mod_name .. ":" .. default_handler(item)
|
||||
elseif (item.module.type == "hooks") then
|
||||
return item.module.mod_name:upper() .. ":" .. default_handler(item)
|
||||
end
|
||||
end
|
||||
|
||||
return default_handler(item)
|
||||
end
|
||||
|
||||
new_type("hooks", "Hooks", true)
|
||||
new_type("panel", "Panels", true)
|
||||
|
||||
-- helix types
|
||||
tparam_alias("char", "Character")
|
||||
tparam_alias("inventory", "Inventory")
|
||||
tparam_alias("item", "Item")
|
||||
tparam_alias("ixtype", "ix.type")
|
||||
tparam_alias("date", "date")
|
||||
|
||||
-- standard types
|
||||
tparam_alias("string", "string")
|
||||
tparam_alias("bool", "boolean")
|
||||
tparam_alias("func", "function")
|
||||
tparam_alias("player", "Player")
|
||||
tparam_alias("entity", "Entity")
|
||||
tparam_alias("color", "color")
|
||||
tparam_alias("tab", "table")
|
||||
tparam_alias("material", "material")
|
||||
tparam_alias("vector", "vector")
|
||||
tparam_alias("angle", "angle")
|
||||
1
gamemodes/helix/docs/banner.gif
Normal file
1
gamemodes/helix/docs/banner.gif
Normal file
@@ -0,0 +1 @@
|
||||
GIF89a8h<01>
|
||||
|
After Width: | Height: | Size: 12 B |
96
gamemodes/helix/docs/css/highlight.css
Normal file
96
gamemodes/helix/docs/css/highlight.css
Normal file
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
|
||||
github.com style (c) Vasily Polovnyov <vast@whiteants.net>
|
||||
|
||||
*/
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-quote {
|
||||
color: #535346;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-subst {
|
||||
color: #333;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-number,
|
||||
.hljs-literal,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-tag .hljs-attr {
|
||||
color: #008080;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-doctag {
|
||||
color: #d14;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-section,
|
||||
.hljs-selector-id {
|
||||
color: #900;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-subst {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-type,
|
||||
.hljs-class .hljs-title {
|
||||
color: #458;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-tag,
|
||||
.hljs-name,
|
||||
.hljs-attribute {
|
||||
color: #000080;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.hljs-regexp,
|
||||
.hljs-link {
|
||||
color: #009926;
|
||||
}
|
||||
|
||||
.hljs-symbol,
|
||||
.hljs-bullet {
|
||||
color: #990073;
|
||||
}
|
||||
|
||||
.hljs-built_in,
|
||||
.hljs-builtin-name {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-meta {
|
||||
color: #999;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
background: #fdd;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
background: #dfd;
|
||||
}
|
||||
|
||||
.hljs-emphasis {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.hljs-strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
522
gamemodes/helix/docs/css/ldoc.css
Normal file
522
gamemodes/helix/docs/css/ldoc.css
Normal file
@@ -0,0 +1,522 @@
|
||||
|
||||
:root {
|
||||
--content-width: 1200px;
|
||||
--sidebar-width: 330px;
|
||||
|
||||
--padding-big: 48px;
|
||||
--padding-normal: 24px;
|
||||
--padding-small: 16px;
|
||||
--padding-tiny: 10px;
|
||||
|
||||
--font-massive: 32px;
|
||||
--font-huge: 24px;
|
||||
--font-big: 18px;
|
||||
--font-normal: 16px;
|
||||
--font-tiny: 12px;
|
||||
|
||||
--font-style-normal: Segoe UI, Helvetica, Arial, sans-serif;
|
||||
--font-style-code: Consolas, monospace;
|
||||
|
||||
--color-accent: rgb(115, 53, 142);
|
||||
--color-accent-dark: rgb(85, 39, 105);
|
||||
--color-white: rgb(255, 255, 255);
|
||||
--color-offwhite: rgb(200, 200, 200);
|
||||
--color-white-accent: rgb(203, 190, 209);
|
||||
--color-black: rgb(0, 0, 0);
|
||||
--color-lightgrey: rgb(160, 160, 160);
|
||||
--color-background-light: rgb(240, 240, 240);
|
||||
--color-background-dark: rgb(33, 33, 33);
|
||||
}
|
||||
|
||||
* {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--color-background-light);
|
||||
font-family: var(--font-style-normal);
|
||||
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
a {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
h1, h2, h3, h4 {
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
ul li {
|
||||
margin-left: var(--padding-small);
|
||||
}
|
||||
|
||||
/* landing */
|
||||
.landing {
|
||||
background-color: var(--color-accent);
|
||||
color: var(--color-white);
|
||||
|
||||
padding: 128px 0 128px 0;
|
||||
}
|
||||
|
||||
.landing h1 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
|
||||
font-weight: 100;
|
||||
font-size: var(--font-massive);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
padding: var(--padding-small);
|
||||
}
|
||||
|
||||
details {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
details summary {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: "Source Code Pro", monospace;
|
||||
font-size: 85%;
|
||||
white-space: pre;
|
||||
tab-size: 4;
|
||||
-moz-tab-size: 4;
|
||||
padding: 2px 4px;
|
||||
background-color: rgb(33, 33, 33, 0.1);
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: rgb(33, 33, 33, 0.1);
|
||||
margin-top: var(--padding-small);
|
||||
padding: var(--padding-tiny);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
pre code {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
span.realm {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 3px;
|
||||
display: inline-block;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
span.realm.shared {
|
||||
background: linear-gradient(45deg, #f80 0%, #f80 50%, #08f 51%, #08f 100%);
|
||||
}
|
||||
|
||||
span.realm.client {
|
||||
background-color: #f80;
|
||||
}
|
||||
|
||||
span.realm.server {
|
||||
background-color: #08f;
|
||||
}
|
||||
|
||||
/* wrapper element for sidebar/content */
|
||||
main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
|
||||
width: var(--content-width);
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
/* sidebar */
|
||||
nav {
|
||||
color: var(--color-offwhite);
|
||||
background-color: var(--color-background-dark);
|
||||
|
||||
position: fixed;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
width: var(--sidebar-width);
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* sidebar header */
|
||||
nav header {
|
||||
color: var(--color-white);
|
||||
background-color: var(--color-accent);
|
||||
|
||||
padding: var(--padding-small);
|
||||
}
|
||||
|
||||
nav header h1 {
|
||||
font-size: var(--font-huge);
|
||||
font-weight: 100;
|
||||
text-align: center;
|
||||
|
||||
margin-bottom: var(--padding-small);
|
||||
}
|
||||
|
||||
#search {
|
||||
background-color: var(--color-accent-dark);
|
||||
color: var(--color-white);
|
||||
|
||||
border: none;
|
||||
font-size: var(--font-normal);
|
||||
outline: none;
|
||||
|
||||
width: 100%;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
#search::placeholder {
|
||||
color: var(--color-white-accent);
|
||||
}
|
||||
|
||||
#search::-webkit-search-cancel-button {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* sidebar contents */
|
||||
nav section {
|
||||
padding: var(--padding-small);
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
nav section ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
|
||||
nav section::-webkit-scrollbar,
|
||||
pre::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
nav section::-webkit-scrollbar-track,
|
||||
pre::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
nav section::-webkit-scrollbar-thumb {
|
||||
background-color: var(--color-lightgrey);
|
||||
}
|
||||
|
||||
pre::-webkit-scrollbar-thumb {
|
||||
background-color: var(--color-lightgrey);
|
||||
}
|
||||
|
||||
/* sidebar contents category */
|
||||
nav section details.category {
|
||||
padding-top: var(--padding-tiny);
|
||||
}
|
||||
|
||||
nav section details.category > ul > li {
|
||||
margin: 0;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
nav section details.category > ul > li a {
|
||||
display: inline-block;
|
||||
width: 90%;
|
||||
}
|
||||
|
||||
nav section details.category:first-of-type {
|
||||
padding-top: calc(var(--padding-tiny) * -1);
|
||||
}
|
||||
|
||||
nav section details.category summary::-webkit-details-marker {
|
||||
opacity: 0.5;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
nav section details.category summary h2 {
|
||||
color: var(--color-accent);
|
||||
|
||||
font-size: var(--font-big);
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
|
||||
padding-bottom: var(--padding-tiny);
|
||||
}
|
||||
|
||||
/* content */
|
||||
article {
|
||||
background-color: rgb(255, 255, 255);
|
||||
|
||||
width: calc(100% - var(--sidebar-width));
|
||||
min-height: 100vh;
|
||||
margin-left: var(--sidebar-width);
|
||||
}
|
||||
|
||||
article .wrapper > *:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* header */
|
||||
article header {
|
||||
color: rgb(255, 255, 255);
|
||||
background-color: rgb(115, 53, 142);
|
||||
padding: var(--padding-tiny);
|
||||
}
|
||||
|
||||
article header h1 {
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.25);
|
||||
padding-bottom: 8px;
|
||||
font-family: var(--font-style-code);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
article header h2 {
|
||||
padding-top: var(--padding-tiny);
|
||||
margin: 0;
|
||||
font-size: var(--font-normal);
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
article header.module a {
|
||||
color: white !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
details.category > summary {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
details.category > summary::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
article h1 {
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
|
||||
margin-top: 24px;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
article h2 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
article h3 {
|
||||
color: rgb(115, 53, 142);
|
||||
margin-top: var(--padding-tiny);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
article p {
|
||||
margin-top: var(--padding-small);
|
||||
}
|
||||
|
||||
article p a,
|
||||
article ul li a,
|
||||
article h1 a,
|
||||
article h2 a {
|
||||
color: rgb(115, 53, 142);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
article h1.title {
|
||||
color: rgb(255, 255, 255);
|
||||
background-color: rgb(115, 53, 142);
|
||||
margin-top: var(--padding-small);
|
||||
margin-bottom: 0;
|
||||
padding: var(--padding-tiny);
|
||||
|
||||
font-size: var(--font-big);
|
||||
font-weight: 100;
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
a.reference {
|
||||
color: rgb(115, 53, 142);
|
||||
float: right;
|
||||
margin-top: 8px;
|
||||
padding-left: 8px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.notice {
|
||||
--color-notice-background: var(--color-accent);
|
||||
--color-notice-text: var(--color-notice-background);
|
||||
|
||||
margin-top: var(--padding-tiny);
|
||||
border: 2px solid var(--color-notice-background);
|
||||
}
|
||||
|
||||
.notice.error {
|
||||
--color-notice-background: rgb(194, 52, 130);
|
||||
}
|
||||
|
||||
.notice.warning {
|
||||
--color-notice-background: rgb(224, 169, 112);
|
||||
--color-notice-text: rgb(167, 104, 37);
|
||||
}
|
||||
|
||||
.notice .title {
|
||||
color: var(--color-white);
|
||||
background-color: var(--color-notice-background);
|
||||
|
||||
padding: var(--padding-tiny);
|
||||
font-size: var(--font-normal);
|
||||
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 2px;
|
||||
}
|
||||
|
||||
.notice p {
|
||||
color: var(--color-notice-text);
|
||||
|
||||
margin: 0 !important;
|
||||
padding: var(--padding-tiny);
|
||||
}
|
||||
|
||||
/* function/table */
|
||||
.method {
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
background-color: rgb(230, 230, 230);
|
||||
padding: var(--padding-tiny);
|
||||
margin-top: var(--padding-small);
|
||||
}
|
||||
|
||||
.method header {
|
||||
color: rgb(0, 0, 0);
|
||||
background-color: inherit;
|
||||
padding: 0;
|
||||
order: -1;
|
||||
}
|
||||
|
||||
.method header .anchor {
|
||||
color: inherit;
|
||||
text-decoration: inherit;
|
||||
}
|
||||
|
||||
.method header .anchor:target h1 {
|
||||
background-color: rgba(115, 53, 142, 0.2);
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
.method header h1 {
|
||||
font-family: "Source Code Pro", monospace;
|
||||
padding-bottom: var(--padding-tiny);
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.25);
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.method header p:first-of-type {
|
||||
margin-top: var(--padding-tiny);
|
||||
}
|
||||
|
||||
.method h3 {
|
||||
color: rgb(115, 53, 142);
|
||||
font-size: var(--font-normal);
|
||||
letter-spacing: 2px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.method pre {
|
||||
margin-top: var(--padding-tiny);
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 1100px) {
|
||||
main nav {
|
||||
position: inherit;
|
||||
}
|
||||
|
||||
main article {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.method ul {
|
||||
margin-top: var(--padding-tiny);
|
||||
background-color: inherit;
|
||||
}
|
||||
|
||||
.method ul li {
|
||||
list-style: none;
|
||||
margin: 4px 0 0 var(--padding-normal);
|
||||
}
|
||||
|
||||
.method ul li:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.method ul li p {
|
||||
margin: 4px 0 0 var(--padding-normal);
|
||||
}
|
||||
|
||||
.method ul li pre {
|
||||
margin: 4px 0 0 var(--padding-normal);
|
||||
}
|
||||
|
||||
.method ul li a {
|
||||
color: rgb(115, 53, 142);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* we have to manually specify these instead of making a shared class since you cannot customize the parameter class in ldoc */
|
||||
.parameter, .type, .default {
|
||||
display: inline-block;
|
||||
color: rgb(255, 255, 255) !important;
|
||||
|
||||
padding: 4px;
|
||||
font-size: 14px;
|
||||
font-family: "Source Code Pro", monospace;
|
||||
}
|
||||
|
||||
.parameter {
|
||||
background-color: rgb(115, 53, 142);
|
||||
}
|
||||
|
||||
.type {
|
||||
background-color: rgb(31, 141, 155);
|
||||
}
|
||||
|
||||
a.type {
|
||||
font-weight: 300 !important;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.default {
|
||||
background-color: rgb(193, 114, 11);
|
||||
}
|
||||
|
||||
.type a {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.or {
|
||||
color: rgba(115, 53, 142, 0.5);
|
||||
background-color: inherit;
|
||||
|
||||
width: calc(100% - 32px);
|
||||
height: 8px;
|
||||
margin: 0 0 8px 32px;
|
||||
|
||||
text-align: center;
|
||||
font-weight: 600;
|
||||
border-bottom: 1px solid rgba(115, 53, 142, 0.5);
|
||||
}
|
||||
|
||||
.or span {
|
||||
background-color: inherit;
|
||||
padding: 0 8px 0 8px;
|
||||
}
|
||||
52
gamemodes/helix/docs/hooks/class.lua
Normal file
52
gamemodes/helix/docs/hooks/class.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- luacheck: ignore 111
|
||||
|
||||
--[[--
|
||||
Class setup hooks.
|
||||
|
||||
As with `Faction`s, `Class`es get their own hooks for when players leave/join a class, etc. These hooks are only
|
||||
valid in class tables that are created in `schema/classes/sh_classname.lua`, and cannot be used like regular gamemode hooks.
|
||||
]]
|
||||
-- @hooks Class
|
||||
|
||||
--- Whether or not a player can switch to this class.
|
||||
-- @realm shared
|
||||
-- @player client Client that wants to switch to this class
|
||||
-- @treturn bool True if the player is allowed to switch to this class
|
||||
-- @usage function CLASS:CanSwitchTo(client)
|
||||
-- return client:IsAdmin() -- only admins allowed in this class!
|
||||
-- end
|
||||
function CanSwitchTo(client)
|
||||
end
|
||||
|
||||
--- Called when a character has left this class and has joined a different one. You can get the class the character has
|
||||
-- has joined by calling `character:GetClass()`.
|
||||
-- @realm server
|
||||
-- @player client Player who left this class
|
||||
function OnLeave(client)
|
||||
end
|
||||
|
||||
--- Called when a character has joined this class.
|
||||
-- @realm server
|
||||
-- @player client Player who has joined this class
|
||||
-- @usage function CLASS:OnSet(client)
|
||||
-- client:SetModel("models/police.mdl")
|
||||
-- end
|
||||
function OnSet(client)
|
||||
end
|
||||
|
||||
--- Called when a character in this class has spawned in the world.
|
||||
-- @realm server
|
||||
-- @player client Player that has just spawned
|
||||
function OnSpawn(client)
|
||||
end
|
||||
58
gamemodes/helix/docs/hooks/faction.lua
Normal file
58
gamemodes/helix/docs/hooks/faction.lua
Normal file
@@ -0,0 +1,58 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- luacheck: ignore 111
|
||||
|
||||
--[[--
|
||||
Faction setup hooks.
|
||||
|
||||
Factions get their own hooks that are called for various reasons, but the most common one is to set up a character
|
||||
once it's created and assigned to a certain faction. For example, giving a police faction character a weapon on creation.
|
||||
These hooks are used in faction tables that are created in `schema/factions/sh_factionname.lua` and cannot be used like
|
||||
regular gamemode hooks.
|
||||
]]
|
||||
-- @hooks Faction
|
||||
|
||||
--- Called when the default name for a character needs to be retrieved (i.e upon initial creation).
|
||||
-- @realm shared
|
||||
-- @player client Client to get the default name for
|
||||
-- @treturn string Default name for the newly created character
|
||||
-- @usage function FACTION:GetDefaultName(client)
|
||||
-- return "MPF-RCT." .. tostring(math.random(1, 99999))
|
||||
-- end
|
||||
function GetDefaultName(client)
|
||||
end
|
||||
|
||||
--- Called when a character has been initally created and assigned to this faction.
|
||||
-- @realm server
|
||||
-- @player client Client that owns the character
|
||||
-- @char character Character that has been created
|
||||
-- @usage function FACTION:OnCharacterCreated(client, character)
|
||||
-- local inventory = character:GetInventory()
|
||||
-- inventory:Add("pistol")
|
||||
-- end
|
||||
function OnCharacterCreated(client, character)
|
||||
end
|
||||
|
||||
--- Called when a character in this faction has spawned in the world.
|
||||
-- @realm server
|
||||
-- @player client Player that has just spawned
|
||||
function OnSpawn(client)
|
||||
end
|
||||
|
||||
--- Called when a player's character has been transferred to this faction.
|
||||
-- @realm server
|
||||
-- @char character Character that was transferred
|
||||
-- @usage function FACTION:OnTransferred(character)
|
||||
-- character:SetModel(self.models[1])
|
||||
-- end
|
||||
function OnTransferred(character)
|
||||
end
|
||||
938
gamemodes/helix/docs/hooks/plugin.lua
Normal file
938
gamemodes/helix/docs/hooks/plugin.lua
Normal file
@@ -0,0 +1,938 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- luacheck: ignore 111
|
||||
|
||||
--[[--
|
||||
Global hooks for general use.
|
||||
|
||||
Plugin hooks are regular hooks that can be used in your schema with `Schema:HookName(args)`, in your plugin with
|
||||
`PLUGIN:HookName(args)`, or in your addon with `hook.Add("HookName", function(args) end)`.
|
||||
]]
|
||||
-- @hooks Plugin
|
||||
|
||||
--- Adjusts the data used just before creating a new character.
|
||||
-- @realm server
|
||||
-- @player client Player that is creating the character
|
||||
-- @tab payload Table of data to be used for character creation
|
||||
-- @tab newPayload Table of data be merged with the current payload
|
||||
-- @usage function PLUGIN:AdjustCreationPayload(client, payload, newPayload)
|
||||
-- newPayload.money = payload.attributes["stm"] -- Sets the characters initial money to the stamina attribute value.
|
||||
-- end
|
||||
function AdjustCreationPayload(client, payload, newPayload)
|
||||
end
|
||||
|
||||
--- Adjusts a player's current stamina offset amount. This is called when the player's stamina is about to be changed; every
|
||||
-- `0.25` seconds on the server, and every frame on the client.
|
||||
-- @realm shared
|
||||
-- @player client Player whose stamina is changing
|
||||
-- @number baseOffset Amount the stamina is changing by. This can be a positive or negative number depending if they are
|
||||
-- exhausting or regaining stamina
|
||||
-- @treturn number New offset to use
|
||||
-- @usage function PLUGIN:AdjustStaminaOffset(client, baseOffset)
|
||||
-- return baseOffset * 2 -- Drain/Regain stamina twice as fast.
|
||||
-- end
|
||||
function AdjustStaminaOffset(client, baseOffset)
|
||||
end
|
||||
|
||||
--- Creates the business panel in the tab menu.
|
||||
-- @realm client
|
||||
-- @treturn bool Whether or not to create the business menu
|
||||
-- @usage function PLUGIN:BuildBusinessMenu()
|
||||
-- return LocalPlayer():IsAdmin() -- Only builds the business menu for admins.
|
||||
-- end
|
||||
function BuildBusinessMenu()
|
||||
end
|
||||
|
||||
--- Whether or not a message can be auto formatted with punctuation and capitalization.
|
||||
-- @realm server
|
||||
-- @player speaker Player that sent the message
|
||||
-- @string chatType Chat type of the message. This will be something registered with `ix.chat.Register` - like `ic`, `ooc`, etc.
|
||||
-- @string text Unformatted text of the message
|
||||
-- @treturn bool Whether or not to allow auto formatting on the message
|
||||
-- @usage function PLUGIN:CanAutoFormatMessage(speaker, chatType, text)
|
||||
-- return false -- Disable auto formatting outright.
|
||||
-- end
|
||||
function CanAutoFormatMessage(speaker, chatType, text)
|
||||
end
|
||||
|
||||
--- Whether or not certain information can be displayed in the character info panel in the tab menu.
|
||||
-- @realm client
|
||||
-- @tab suppress Information to **NOT** display in the UI - modify this to change the behaviour. This is a table of the names of
|
||||
-- some panels to avoid displaying. Valid names include:
|
||||
--
|
||||
-- - `time` - current in-game time
|
||||
-- - `name` - name of the character
|
||||
-- - `description` - description of the character
|
||||
-- - `characterInfo` - entire panel showing a list of additional character info
|
||||
-- - `faction` - faction name of the character
|
||||
-- - `class` - name of the character's class if they're in one
|
||||
-- - `money` - current money the character has
|
||||
-- - `attributes` - attributes list for the character
|
||||
--
|
||||
-- Note that schemas/plugins can add additional character info panels.
|
||||
-- @usage function PLUGIN:CanCreateCharacterInfo(suppress)
|
||||
-- suppress.attributes = true -- Hides the attributes panel from the character info tab
|
||||
-- end
|
||||
function CanCreateCharacterInfo(suppress)
|
||||
end
|
||||
|
||||
--- Whether or not the ammo HUD should be drawn.
|
||||
-- @realm client
|
||||
-- @entity weapon Weapon the player currently is holding
|
||||
-- @treturn bool Whether or not to draw the ammo hud
|
||||
-- @usage function PLUGIN:CanDrawAmmoHUD(weapon)
|
||||
-- if (weapon:GetClass() == "weapon_frag") then -- Hides the ammo hud when holding grenades.
|
||||
-- return false
|
||||
-- end
|
||||
-- end
|
||||
function CanDrawAmmoHUD(weapon)
|
||||
end
|
||||
|
||||
--- Called when a player tries to use abilities on the door, such as locking.
|
||||
-- @realm shared
|
||||
-- @player client The client trying something on the door.
|
||||
-- @entity door The door entity itself.
|
||||
-- @number access The access level used when called.
|
||||
-- @treturn bool Whether or not to allow the client access.
|
||||
-- @usage function PLUGIN:CanPlayerAccessDoor(client, door, access)
|
||||
-- return true -- Always allow access.
|
||||
-- end
|
||||
function CanPlayerAccessDoor(client, door, access)
|
||||
end
|
||||
|
||||
--- Whether or not a player is allowed to create a new character with the given payload.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to create a new character
|
||||
-- @tab payload Data that is going to be used for creating the character
|
||||
-- @treturn bool Whether or not the player is allowed to create the character. This function defaults to `true`, so you
|
||||
-- should only ever return `false` if you're disallowing creation. Otherwise, don't return anything as you'll prevent any other
|
||||
-- calls to this hook from running.
|
||||
-- @treturn string Language phrase to use for the error message
|
||||
-- @treturn ... Arguments to use for the language phrase
|
||||
-- @usage function PLUGIN:CanPlayerCreateCharacter(client, payload)
|
||||
-- if (!client:IsAdmin()) then
|
||||
-- return false, "notNow" -- only allow admins to create a character
|
||||
-- end
|
||||
-- end
|
||||
-- -- non-admins will see the message "You are not allowed to do this right now!"
|
||||
function CanPlayerCreateCharacter(client, payload)
|
||||
end
|
||||
|
||||
--- Whether or not a player is allowed to drop the given `item`.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to drop an item
|
||||
-- @number item instance ID of the item being dropped
|
||||
-- @treturn bool Whether or not to allow the player to drop the item
|
||||
-- @usage function PLUGIN:CanPlayerDropItem(client, item)
|
||||
-- return false -- Never allow dropping items.
|
||||
-- end
|
||||
function CanPlayerDropItem(client, item)
|
||||
end
|
||||
|
||||
--- Whether or not a player can earn money at regular intervals. This hook runs only if the player's character faction has
|
||||
-- a salary set - i.e `FACTION.pay` is set to something other than `0` for their faction.
|
||||
-- @realm server
|
||||
-- @player client Player to give money to
|
||||
-- @tab faction Faction of the player's character
|
||||
-- @treturn bool Whether or not to allow the player to earn salary
|
||||
-- @usage function PLUGIN:CanPlayerEarnSalary(client, faction)
|
||||
-- return client:IsAdmin() -- Restricts earning salary to admins only.
|
||||
-- end
|
||||
function CanPlayerEarnSalary(client, faction)
|
||||
end
|
||||
|
||||
--- Whether or not the player is allowed to enter observer mode. This is allowed only for admins by default and can be
|
||||
-- customized by server owners if the server is using a CAMI-compliant admin mod.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to enter observer
|
||||
-- @treturn bool Whether or not to allow the player to enter observer
|
||||
-- @usage function PLUGIN:CanPlayerEnterObserver(client)
|
||||
-- return true -- Always allow observer.
|
||||
-- end
|
||||
function CanPlayerEnterObserver(client)
|
||||
end
|
||||
|
||||
--- Whether or not a player can equip the given `item`. This is called for items with `outfit`, `pacoutfit`, or `weapons` as
|
||||
-- their base. Schemas/plugins can utilize this hook for their items.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to equip the item
|
||||
-- @tab item Item being equipped
|
||||
-- @treturn bool Whether or not to allow the player to equip the item
|
||||
-- @see CanPlayerUnequipItem
|
||||
-- @usage function PLUGIN:CanPlayerEquipItem(client, item)
|
||||
-- return client:IsAdmin() -- Restrict equipping items to admins only.
|
||||
-- end
|
||||
function CanPlayerEquipItem(client, item)
|
||||
end
|
||||
|
||||
--- Whether or not a player is allowed to hold an entity with the hands SWEP.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to hold an entity
|
||||
-- @entity entity Entity being held
|
||||
-- @treturn bool Whether or not to allow the player to hold the entity
|
||||
-- @usage function PLUGIN:CanPlayerHoldObject(client, entity)
|
||||
-- return !(client:GetMoveType() == MOVETYPE_NOCLIP and !client:InVehicle()) -- Disallow players in observer holding objects.
|
||||
-- end
|
||||
function CanPlayerHoldObject(client, entity)
|
||||
end
|
||||
|
||||
--- Whether or not a player is allowed to interact with an entity's interaction menu if it has one.
|
||||
-- @realm server
|
||||
-- @player client Player attempting interaction
|
||||
-- @entity entity Entity being interacted with
|
||||
-- @string option Option selected by the player
|
||||
-- @param data Any data passed with the interaction option
|
||||
-- @treturn bool Whether or not to allow the player to interact with the entity
|
||||
-- @usage function PLUGIN:CanPlayerInteractEntity(client, entity, option, data)
|
||||
-- return false -- Disallow interacting with any entity.
|
||||
-- end
|
||||
function CanPlayerInteractEntity(client, entity, option, data)
|
||||
end
|
||||
|
||||
--- Whether or not a player is allowed to interact with an item via an inventory action (e.g picking up, dropping, transferring
|
||||
-- inventories, etc). Note that this is for an item *table*, not an item *entity*. This is called after `CanPlayerDropItem`
|
||||
-- and `CanPlayerTakeItem`.
|
||||
-- @realm server
|
||||
-- @player client Player attempting interaction
|
||||
-- @string action The action being performed
|
||||
-- @param item Item's instance ID or item table
|
||||
-- @param data Any data passed with the action
|
||||
-- @treturn bool Whether or not to allow the player to interact with the item
|
||||
-- @usage function PLUGIN:CanPlayerInteractItem(client, action, item, data)
|
||||
-- return false -- Disallow interacting with any item.
|
||||
-- end
|
||||
function CanPlayerInteractItem(client, action, item, data)
|
||||
end
|
||||
|
||||
--- Whether or not a plyer is allowed to join a class.
|
||||
-- @realm shared
|
||||
-- @player client Player attempting to join
|
||||
-- @number class ID of the class
|
||||
-- @tab info The class table
|
||||
-- @treturn bool Whether or not to allow the player to join the class
|
||||
-- @usage function PLUGIN:CanPlayerJoinClass(client, class, info)
|
||||
-- return client:IsAdmin() -- Restrict joining classes to admins only.
|
||||
-- end
|
||||
function CanPlayerJoinClass(client, class, info)
|
||||
end
|
||||
|
||||
--- Whether or not a player can knock on the door with the hands SWEP.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to knock
|
||||
-- @entity entity Door being knocked on
|
||||
-- @treturn bool Whether or not to allow the player to knock on the door
|
||||
-- @usage function PLUGIN:CanPlayerKnock(client, entity)
|
||||
-- return false -- Disable knocking on doors outright.
|
||||
-- end
|
||||
function CanPlayerKnock(client, entity)
|
||||
end
|
||||
|
||||
--- Whether or not a player can open a shipment spawned from the business menu.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to open the shipment
|
||||
-- @entity entity Shipment entity
|
||||
-- @treturn bool Whether or not to allow the player to open the shipment
|
||||
-- @usage function PLUGIN:CanPlayerOpenShipment(client, entity)
|
||||
-- return client:Team() == FACTION_BMD -- Restricts opening shipments to FACTION_BMD.
|
||||
-- end
|
||||
function CanPlayerOpenShipment(client, entity)
|
||||
end
|
||||
|
||||
--- Whether or not a player is allowed to spawn a container entity.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to spawn a container
|
||||
-- @string model Model of the container being spawned
|
||||
-- @entity entity Container entity
|
||||
-- @treturn bool Whether or not to allow the player to spawn the container
|
||||
-- @usage function PLUGIN:CanPlayerSpawnContainer(client, model, entity)
|
||||
-- return client:IsAdmin() -- Restrict spawning containers to admins.
|
||||
-- end
|
||||
function CanPlayerSpawnContainer(client, model, entity)
|
||||
end
|
||||
|
||||
--- Whether or not a player is allowed to take an item and put it in their inventory.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to take the item
|
||||
-- @entity item Entity corresponding to the item
|
||||
-- @treturn bool Whether or not to allow the player to take the item
|
||||
-- @usage function PLUGIN:CanPlayerTakeItem(client, item)
|
||||
-- return !(client:GetMoveType() == MOVETYPE_NOCLIP and !client:InVehicle()) -- Disallow players in observer taking items.
|
||||
-- end
|
||||
function CanPlayerTakeItem(client, item)
|
||||
end
|
||||
|
||||
--- Whether or not the player is allowed to punch with the hands SWEP.
|
||||
-- @realm shared
|
||||
-- @player client Player attempting throw a punch
|
||||
-- @treturn bool Whether or not to allow the player to punch
|
||||
-- @usage function PLUGIN:CanPlayerThrowPunch(client)
|
||||
-- return client:GetCharacter():GetAttribute("str", 0) > 0 -- Only allow players with strength to punch.
|
||||
-- end
|
||||
function CanPlayerThrowPunch(client)
|
||||
end
|
||||
|
||||
--- Whether or not a player can trade with a vendor.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to trade
|
||||
-- @entity entity Vendor entity
|
||||
-- @string uniqueID The uniqueID of the item being traded.
|
||||
-- @bool isSellingToVendor If the client is selling to the vendor
|
||||
-- @treturn bool Whether or not to allow the client to trade with the vendor
|
||||
-- @usage function PLUGIN:CanPlayerTradeWithVendor(client, entity, uniqueID, isSellingToVendor)
|
||||
-- return false -- Disallow trading with vendors outright.
|
||||
-- end
|
||||
function CanPlayerTradeWithVendor(client, entity, uniqueID, isSellingToVendor)
|
||||
end
|
||||
|
||||
--- Whether or not a player can unequip an item.
|
||||
-- @realm server
|
||||
-- @player client Player attempting to unequip an item
|
||||
-- @tab item Item being unequipped
|
||||
-- @treturn bool Whether or not to allow the player to unequip the item
|
||||
-- @see CanPlayerEquipItem
|
||||
-- @usage function PLUGIN:CanPlayerUnequipItem(client, item)
|
||||
-- return false -- Disallow unequipping items.
|
||||
-- end
|
||||
function CanPlayerUnequipItem(client, item)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CanPlayerUseBusiness(client, uniqueID)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CanPlayerUseCharacter(client, character)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function CanPlayerUseDoor(client, entity)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function CanPlayerUseVendor(activator)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function CanPlayerViewInventory()
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function CanSaveContainer(entity, inventory)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CanTransferItem(item, currentInv, oldInv)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CharacterAttributeBoosted(client, character, attribID, boostID, boostAmount)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CharacterAttributeUpdated(client, self, key, value)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CharacterDeleted(client, id, isCurrentChar)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CharacterHasFlags(self, flags)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function CharacterLoaded(character)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function CharacterPostSave(character)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CharacterPreSave(character)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CharacterRecognized()
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function CharacterRestored(character)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CharacterVarChanged(character, key, oldVar, value)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function CharacterVendorTraded(client, entity, uniqueID, isSellingToVendor)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ChatboxCreated()
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ChatboxPositionChanged(x, y, width, height)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ColorSchemeChanged(color)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function ContainerRemoved(container, inventory)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function CreateCharacterInfo(panel)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function CreateCharacterInfoCategory(panel)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function CreateItemInteractionMenu(icon, menu, itemTable)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function CreateMenuButtons(tabs)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function CreateShipment(client, entity)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function DatabaseConnected()
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function DatabaseConnectionFailed(error)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function DoPluginIncludes(path, pluginTable)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function DrawCharacterOverview()
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function DrawHelixModelView(panel, entity)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function DrawPlayerRagdoll(entity)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function GetCharacterDescription(client)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function GetCharacterName(speaker, chatType)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function GetChatPrefixInfo(text)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function GetCrosshairAlpha(curAlpha)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function GetDefaultAttributePoints(client, count)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function GetDefaultCharacterName(client, faction)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function GetMaxPlayerCharacter(client)
|
||||
end
|
||||
|
||||
--- Returns the sound to emit from the player upon death. If nothing is returned then it will use the default male/female death
|
||||
-- sounds.
|
||||
-- @realm server
|
||||
-- @player client Player that died
|
||||
-- @treturn[1] string Sound to play
|
||||
-- @treturn[2] bool `false` if a sound shouldn't be played at all
|
||||
-- @usage function PLUGIN:GetPlayerDeathSound(client)
|
||||
-- -- play impact sound every time someone dies
|
||||
-- return "physics/body/body_medium_impact_hard1.wav"
|
||||
-- end
|
||||
-- @usage function PLUGIN:GetPlayerDeathSound(client)
|
||||
-- -- don't play a sound at all
|
||||
-- return false
|
||||
-- end
|
||||
function GetPlayerDeathSound(client)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function GetPlayerEntityMenu(client, options)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function GetPlayerIcon(speaker)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function GetPlayerPainSound(client)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function GetPlayerPunchDamage(client, damage, context)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function GetSalaryAmount(client, faction)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function GetTypingIndicator(character, text)
|
||||
end
|
||||
|
||||
--- Registers chat classes after the core framework chat classes have been registered. You should usually create your chat
|
||||
-- classes in this hook - especially if you want to reference the properties of a framework chat class.
|
||||
-- @realm shared
|
||||
-- @usage function PLUGIN:InitializedChatClasses()
|
||||
-- -- let's say you wanted to reference an existing chat class's color
|
||||
-- ix.chat.Register("myclass", {
|
||||
-- format = "%s says \"%s\"",
|
||||
-- GetColor = function(self, speaker, text)
|
||||
-- -- make the chat class slightly brighter than the "ic" chat class
|
||||
-- local color = ix.chat.classes.ic:GetColor(speaker, text)
|
||||
--
|
||||
-- return Color(color.r + 35, color.g + 35, color.b + 35)
|
||||
-- end,
|
||||
-- -- etc.
|
||||
-- })
|
||||
-- end
|
||||
-- @see ix.chat.Register
|
||||
-- @see ix.chat.classes
|
||||
function InitializedChatClasses()
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function InitializedConfig()
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function InitializedPlugins()
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function InitializedSchema()
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function InventoryItemAdded(oldInv, inventory, item)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function InventoryItemRemoved(inventory, item)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function IsCharacterRecognized(character, id)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function IsPlayerRecognized(client)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function IsRecognizedChatType(chatType)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function LoadData()
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function LoadFonts(font, genericFont)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function LoadIntro()
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function MenuSubpanelCreated(subpanelName, panel)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function MessageReceived(client, info)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function OnAreaChanged(oldID, newID)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function OnCharacterCreated(client, character)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function OnCharacterDisconnect(client, character)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function OnCharacterFallover(client, entity, bFallenOver)
|
||||
end
|
||||
|
||||
--- Called when a character has gotten up from the ground.
|
||||
-- @realm server
|
||||
-- @player client Player that has gotten up
|
||||
-- @entity ragdoll Ragdoll used to represent the player
|
||||
function OnCharacterGetup(client, ragdoll)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function OnCharacterMenuCreated(panel)
|
||||
end
|
||||
|
||||
--- Called whenever an item entity has spawned in the world. You can access the entity's item table with
|
||||
-- `entity:GetItemTable()`.
|
||||
-- @realm server
|
||||
-- @entity entity Spawned item entity
|
||||
-- @usage function PLUGIN:OnItemSpawned(entity)
|
||||
-- local item = entity:GetItemTable()
|
||||
-- -- do something with the item here
|
||||
-- end
|
||||
function OnItemSpawned(entity)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function OnItemTransferred(item, curInv, inventory)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function OnLocalVarSet(key, var)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function OnPAC3PartTransferred(part)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function OnPickupMoney(client, self)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function OnPlayerAreaChanged(client, oldID, newID)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function OnPlayerObserve(client, state)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function OnPlayerOptionSelected(client, callingClient, option)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function OnPlayerPurchaseDoor(client, entity, bBuying, bCallOnDoorChild)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function OnPlayerRestricted(client)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function OnPlayerUnRestricted(client)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function OnSavedItemLoaded(loadedItems)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function OnWipeTables()
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function PlayerEnterSequence(client, sequence, callback, time, bNoFreeze)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerInteractEntity(client, entity, option, data)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerInteractItem(client, action, item)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerJoinedClass(client, class, oldClass)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function PlayerLeaveSequence(entity)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerLoadedCharacter(client, character, currentChar)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerLockedDoor(client, door, partner)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerLockedVehicle(client, vehicle)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerMessageSend(speaker, chatType, text, anonymous, receivers, rawText)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function PlayerModelChanged(client, model)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerStaminaGained(client)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerStaminaLost(client)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function PlayerThrowPunch(client, trace)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerUnlockedDoor(client, door, partner)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerUnlockedVehicle(client, door)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerUse(client, entity)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PlayerUseDoor(client, entity)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function PlayerWeaponChanged(client, weapon)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function PluginLoaded(uniqueID, pluginTable)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function PluginShouldLoad(uniqueID)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function PluginUnloaded(uniqueID)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PopulateCharacterInfo(client, character, tooltip)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PopulateEntityInfo(entity, tooltip)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PopulateHelpMenu(categories)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PopulateImportantCharacterInfo(entity, character, tooltip)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PopulateItemTooltip(tooltip, item)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PopulatePlayerTooltip(client, tooltip)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PopulateScoreboardPlayerMenu(client, menu)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PostChatboxDraw(width, height, alpha)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PostDrawHelixModelView(panel, entity)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function PostDrawInventory(panel)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PostLoadData()
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PostPlayerLoadout(client)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PostPlayerSay(client, chatType, message, anonymous)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function PostSetupActs()
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PreCharacterDeleted(client, character)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function PrePlayerLoadedCharacter(client, character, currentChar)
|
||||
end
|
||||
|
||||
--- Called before a message sent by a player is processed to be sent to other players - i.e this is ran as early as possible
|
||||
-- and before things like the auto chat formatting. Can be used to prevent the message from being sent at all.
|
||||
-- @realm server
|
||||
-- @player client Player sending the message
|
||||
-- @string chatType Chat class of the message
|
||||
-- @string message Contents of the message
|
||||
-- @bool bAnonymous Whether or not the player is sending the message anonymously
|
||||
-- @treturn bool Whether or not to prevent the message from being sent
|
||||
-- @usage function PLUGIN:PrePlayerMessageSend(client, chatType, message, bAnonymous)
|
||||
-- if (!client:IsAdmin()) then
|
||||
-- return false -- only allow admins to talk in chat
|
||||
-- end
|
||||
-- end
|
||||
function PrePlayerMessageSend(client, chatType, message, bAnonymous)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function SaveData()
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ScreenResolutionChanged(width, height)
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function SetupActs()
|
||||
end
|
||||
|
||||
--- @realm shared
|
||||
function SetupAreaProperties()
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function ShipmentItemTaken(client, uniqueID, amount)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ShouldBarDraw(bar)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function ShouldDeleteSavedItems()
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ShouldDisplayArea(newID)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ShouldDrawCrosshair(client, weapon)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ShouldDrawItemSize(item)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ShouldHideBars()
|
||||
end
|
||||
|
||||
--- Whether or not a character should be permakilled upon death. This is only called if the `permakill` server config is
|
||||
-- enabled.
|
||||
-- @realm server
|
||||
-- @player client Player to permakill
|
||||
-- @char character Player's current character
|
||||
-- @entity inflictor Entity that inflicted the killing blow
|
||||
-- @entity attacker Other player or entity that killed the player
|
||||
-- @treturn bool `false` if the player should not be permakilled
|
||||
-- @usage function PLUGIN:ShouldPermakillCharacter(client, character, inflictor, attacker)
|
||||
-- if (client:IsAdmin()) then
|
||||
-- return false -- all non-admin players will have their character permakilled
|
||||
-- end
|
||||
-- end
|
||||
function ShouldPermakillCharacter(client, character, inflictor, attacker)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function ShouldPlayerDrowned(v)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function ShouldRemoveRagdollOnDeath(client)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function ShouldRestoreInventory(characterID, inventoryID, inventoryType)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ShouldShowPlayerOnScoreboard(client)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function ShouldSpawnClientRagdoll(client)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ShowEntityMenu(entity)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function ThirdPersonToggled(oldValue, value)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function UpdateCharacterInfo(panel, character)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function UpdateCharacterInfoCategory(panel, character)
|
||||
end
|
||||
|
||||
--- @realm server
|
||||
function VoiceDistanceChanged(newValue)
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function WeaponCycleSound()
|
||||
end
|
||||
|
||||
--- @realm client
|
||||
function WeaponSelectSound(weapon)
|
||||
end
|
||||
168
gamemodes/helix/docs/js/app.js
Normal file
168
gamemodes/helix/docs/js/app.js
Normal file
@@ -0,0 +1,168 @@
|
||||
|
||||
const skippedCategories = ["manual"];
|
||||
|
||||
class Node
|
||||
{
|
||||
constructor(name, element, expandable, noAutoCollapse, children = [])
|
||||
{
|
||||
this.name = name;
|
||||
this.element = element;
|
||||
this.expandable = expandable;
|
||||
this.noAutoCollapse = noAutoCollapse;
|
||||
this.children = children;
|
||||
}
|
||||
|
||||
AddChild(name, element, expandable, noAutoCollapse, children)
|
||||
{
|
||||
let newNode = new Node(name, element, expandable, noAutoCollapse, children);
|
||||
this.children.push(newNode);
|
||||
|
||||
return newNode;
|
||||
}
|
||||
}
|
||||
|
||||
class SearchManager
|
||||
{
|
||||
constructor(input, contents)
|
||||
{
|
||||
this.input = input;
|
||||
this.input.addEventListener("input", event =>
|
||||
{
|
||||
this.OnInputUpdated(this.input.value.toLowerCase().replace(/:/g, "."));
|
||||
});
|
||||
|
||||
// setup search tree
|
||||
this.tree = new Node("", document.createElement("null"), true, true);
|
||||
this.entries = {};
|
||||
|
||||
const categoryElements = contents.querySelectorAll(".category");
|
||||
|
||||
// iterate each kind (hooks/libraries/classes/etc)
|
||||
for (const category of categoryElements)
|
||||
{
|
||||
const nameElement = category.querySelector(":scope > summary > h2");
|
||||
|
||||
if (!nameElement)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const categoryName = nameElement.textContent.trim().toLowerCase();
|
||||
|
||||
if (skippedCategories.includes(categoryName))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
let categoryNode = this.tree.AddChild(categoryName, category, true, true);
|
||||
const sectionElements = category.querySelectorAll(":scope > ul > li");
|
||||
|
||||
for (const section of sectionElements)
|
||||
{
|
||||
const entryElements = section.querySelectorAll(":scope > details > ul > li > a");
|
||||
const sectionName = section.querySelector(":scope > details > summary > a")
|
||||
.textContent
|
||||
.trim()
|
||||
.toLowerCase();
|
||||
|
||||
let sectionNode = categoryNode.AddChild(sectionName, section.querySelector(":scope > details"), true);
|
||||
|
||||
for (let i = 0; i < entryElements.length; i++)
|
||||
{
|
||||
const entryElement = entryElements[i];
|
||||
const entryName = entryElement.textContent.trim().toLowerCase();
|
||||
|
||||
sectionNode.AddChild(sectionName + "." + entryName, entryElement.parentElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResetVisibility(current)
|
||||
{
|
||||
current.element.style.display = "";
|
||||
|
||||
if (current.noAutoCollapse)
|
||||
{
|
||||
current.element.open = true;
|
||||
}
|
||||
else if (current.expandable)
|
||||
{
|
||||
current.element.open = false;
|
||||
}
|
||||
|
||||
for (let node of current.children)
|
||||
{
|
||||
this.ResetVisibility(node);
|
||||
}
|
||||
}
|
||||
|
||||
Search(input, current)
|
||||
{
|
||||
let matched = false;
|
||||
|
||||
if (current.name.indexOf(input) != -1)
|
||||
{
|
||||
matched = true;
|
||||
}
|
||||
|
||||
for (let node of current.children)
|
||||
{
|
||||
let childMatched = this.Search(input, node);
|
||||
matched = matched || childMatched;
|
||||
}
|
||||
|
||||
if (matched)
|
||||
{
|
||||
current.element.style.display = "";
|
||||
|
||||
if (current.expandable)
|
||||
{
|
||||
current.element.open = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
current.element.style.display = "none";
|
||||
|
||||
if (current.expandable)
|
||||
{
|
||||
current.element.open = false;
|
||||
}
|
||||
}
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
OnInputUpdated(input)
|
||||
{
|
||||
if (input.length <= 1)
|
||||
{
|
||||
this.ResetVisibility(this.tree);
|
||||
return;
|
||||
}
|
||||
|
||||
this.Search(input, this.tree);
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function()
|
||||
{
|
||||
const openDetails = document.querySelector(".category > ul > li > details[open]");
|
||||
|
||||
if (openDetails)
|
||||
{
|
||||
openDetails.scrollIntoView();
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function()
|
||||
{
|
||||
const searchInput = document.getElementById("search");
|
||||
const contents = document.querySelector("body > main > nav > section");
|
||||
|
||||
if (searchInput && contents)
|
||||
{
|
||||
new SearchManager(searchInput, contents);
|
||||
}
|
||||
});
|
||||
2
gamemodes/helix/docs/js/highlight.min.js
vendored
Normal file
2
gamemodes/helix/docs/js/highlight.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
329
gamemodes/helix/docs/manual/converting-from-clockwork.md
Normal file
329
gamemodes/helix/docs/manual/converting-from-clockwork.md
Normal file
@@ -0,0 +1,329 @@
|
||||
# Clockwork to Helix Migration
|
||||
|
||||
If you are here, you probably want to be converting your code from another framework to Helix. Doing so should not be a difficult task. Most of the previous functions are probably within Helix in one form or another! This means all you need to do is match *x* function found in the old framework to *y* function in Helix. Some headings will contain a link - this will bring you to the documentation for Helix's equivalent library or class.
|
||||
|
||||
This tutorial assumes basic to intermediate knowledge and experience with Garry's Mod Lua.
|
||||
|
||||
**Before you start!** You will notice that Helix uses client for the variable that represents a player. Clockwork uses player for the variable instead, but this will conflict with the player library. So if you see `_player` being used in Clockwork, it means the Garry's Mod player library. This is just a preference and does not affect anything besides appear. So keep in mind throughout the tutorial, you may see player being used for Clockwork code and client being used for Helix code. They represent the same thing, just with a different name.
|
||||
|
||||
If you are converting Clockwork code to Helix, keep in mind that `_player` is not defined so you will need to either define `_player` yourself or switch it to player instead and change the variable name to client for player objects.
|
||||
|
||||
# Basics of Conversion
|
||||
|
||||
## Folders
|
||||
Clockwork code and file structure is not too different from Helix. In the schema, the plugins folder and schema folder stay in the same place. There are some minor differences in naming however:
|
||||
|
||||
- The `schema/entities` folder should be moved outside out of the schema folder.
|
||||
- The `libraries` folder needs to be renamed to `libs` to load.
|
||||
- The `commands` tab will not load as each command is now defined in a single shared file, does not matter which one.
|
||||
|
||||
## Deriving from Helix
|
||||
This is pretty important. If you want to use Helix as the base, you need to set it as the base. So, go to your Clockwork schema's `gamemode` folder. Inside should be two files: `init.lua `and `cl_init.lua`. Open both, and you should see something along the lines of `DeriveGamemode("Clockwork")`. Change this to `DeriveGamemode("helix")`.
|
||||
|
||||
# The Schema
|
||||
|
||||
## Introduction
|
||||
Inside of the `schema` folder of the actual schema, you should see a file named `sh_schema.lua`. This is the main schema file in both Clockwork and Helix. Most of your changes may actually be within this file.
|
||||
|
||||
## Including Files
|
||||
Both frameworks come with a utility function to include a file without worrying about sending them to the client and stuff. In Clockwork, this function is `Clockwork.kernel:IncludePrefixed("sh_myfile.lua")`. Change this to `ix.util.Include("sh_myfile.lua") `and save.
|
||||
|
||||
# The Plugin
|
||||
|
||||
## Introduction
|
||||
Plugins serve as a means to add on to a schema or framework without directly modifying either. This allows for easier modifications that can be added/removed with ease. It is recommended that you keep all custom modifications left to plugins rather than editing the framework or the schema if possible.
|
||||
|
||||
## Structure
|
||||
All plugins in Clockwork and Helix go into the `plugins` folder. However, there are many differences with the CW plugin structure. First of all, there are two things you see when you open a plugin folder: `plugin` again and `plugin.ini`.
|
||||
|
||||
Helix only has one file needed: `sh_plugin.lua` which acts like `sh_schema.lua` but for plugins.
|
||||
|
||||
## Conversion
|
||||
The first step is to move all of the contents from the `plugin` folder to the main folder of the plugin folder. The `sh_plugin.lua` file needs to be changed to provide basic information about the plugin.You need to define three things in `sh_plugin.lua` which can be found within the `plugin.ini` file:
|
||||
|
||||
- `PLUGIN.name = "Plugin Name"`
|
||||
- `PLUGIN.author = "Plugin Author"`
|
||||
- `PLUGIN.description = "Plugin Description"`
|
||||
|
||||
If the plugin uses a special variable (e.g. `cwPluginName`) for the plugin, change it to `PLUGIN`.
|
||||
|
||||
- Note that the `PLUGIN` table is removed after the plugin is loaded. So if you want to use `PLUGIN` after the plugin has loaded (such as in console commands, in entities, etc.), add `local PLUGIN = PLUGIN` at the top.
|
||||
- You can see if a global variable is defined for it by looking for `PLUGIN:SetGlobalAlias("cwMyPlugin")`. So, one would change `cwMyPlugin` to `PLUGIN`.
|
||||
|
||||
# The `Character` Object
|
||||
One main thing that is very notable is how the character is referenced using `client:GetCharacter()` which returns a character object. The way the object works is just like an entity you spawn. It has its own properties like the model, color, etc. that makes it unique. You can access all the characters in a table which stores loaded characters with `ix.char.loaded`.
|
||||
|
||||
The character object comes with many predefined methods. You can look at how they are defined [by clicking here](https://github.com/NebulousCloud/helix/blob/master/gamemode/core/meta/sh_character.lua). The character object makes it very simple to manager character information.
|
||||
|
||||
You will notice throughout the framework, the character object is used a lot. The use of the character object makes a large barrier between what belongs to the character and what belongs to the player. For example: flags, models, factions, data, and other things are stored on the character and can be accessed by the character object.
|
||||
|
||||
In Clockwork, there is no use of an object. Instead, the character information is intertwined with the player object. For example:
|
||||
|
||||
```
|
||||
-- in Clockwork
|
||||
player:SetCharacterData("foo", "bar")
|
||||
|
||||
-- in Helix
|
||||
client:GetCharacter():SetData("foo", "bar")
|
||||
```
|
||||
|
||||
The use of the character object allows you to access other characters a player might own without needing to have them be the active character, or even access them when the player is not on the server. Overall, the use of the character object may seem like a complex concept, but will simplify a lot of things once you get the hang of the idea.
|
||||
|
||||
# The Libraries
|
||||
|
||||
## Animations (`ix.anim`)
|
||||
Clockwork features many functions to set up animations for a specific model. Helix too has this functionality. Helix has one function instead that pairs a model to a specific "animation class" (grouping of animation types). So, all one needs to do is find the appropriate animation class to match the model with. Looking at the Clockwork function name should tell you.
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.animation:AddCivilProtectionModel("models/mymodel.mdl")
|
||||
|
||||
-- after
|
||||
ix.anim.SetModelClass("models/mymodel.mdl", "metrocop")
|
||||
```
|
||||
|
||||
## Attributes (`ix.attributes`)
|
||||
Attributes allow the player to boost certain abilities over time. Both frameworks require one to register attributes, but they are done differently. In Clockwork, the `ATTRIBUTE` table needs to be defined and registered manually. In Helix, the `ATTRIBUTE` table is automatically defined and registered for you. All you need to do is have `ATTRIBUTE.value = "value"`. The basic parts of the attribute needed is `ATTRIBUTE.name` and `ATTRIBUTE.description`.
|
||||
|
||||
One extra feature for attributes in Helix is `ATTRIBUTE:OnSetup(client, value)` which is a function that gets called on spawn to apply any effects. For example, the stamina attribute changes the player's run speed by adding the amount of stamina points the player has.
|
||||
|
||||
You can find an example at [https://github.com/NebulousCloud/helix/blob/master/plugins/stamina/attributes/sh_stm.lua](https://github.com/NebulousCloud/helix/blob/master/plugins/stamina/attributes/sh_stm.lua)
|
||||
|
||||
## Classes (`ix.class`)
|
||||
Classes are a part of the factions. They basically are a more specific form of a faction. Factions in Helix and Clockwork work similarly. For instance, all classes are placed in the `classes` folder under the schema folder and use `CLASS` as the main variable inside the file.
|
||||
|
||||
However:
|
||||
|
||||
- You do not need to use `local CLASS = Clockwork.class:New("My Class")`. Instead, `CLASS` is already defined for you and you set the name using `CLASS.name = "My Class"`
|
||||
- `CLASS.factions` is *not* a table, so `CLASS.factions = {FACTION_MYFACTION}` becomes `CLASS.faction = FACTION_MYFACTION`
|
||||
- You do not need to use `CLASS:Register()` as classes are registered for you after the file is done processing.
|
||||
- Classes are *optional* for factions rather than being required.
|
||||
|
||||
## Commands (`ix.command`)
|
||||
Commands no longer need to be in separate files. Instead, they are just placed into one large file. However, if you really wanted you can register multiple commands across multiple files or however you want. One thing you may notice is Clockwork uses a _COMMAND_ table while Helix does not always. It is simply a design preference. You can find examples at [https://github.com/NebulousCloud/helix/blob/master/gamemode/core/sh_commands.lua](https://github.com/NebulousCloud/helix/blob/master/gamemode/core/sh_commands.lua)
|
||||
|
||||
It should be noted that:
|
||||
|
||||
- `COMMAND.tip` is not used.
|
||||
- `COMMAND.text` is not used.
|
||||
- `COMMAND.flags` is not used.
|
||||
- `COMMAND.arguments` does not need to be defined if no arguments are needed but is defined as a table of argument types when needed `arguments = {ix.type.character, ix.type.number}`. See `ix.command.CommandArgumentsStructure` for details.
|
||||
- `COMMAND.access` for checking whether or not a person is a (super)admin can be replaced with `adminOnly = true` or `superAdminOnly = true` in the command table.
|
||||
|
||||
## Configurations (`ix.config`)
|
||||
In Helix, the method of adding configurations that can be changed by server owners is heavily simplified. [See an example here](https://github.com/NebulousCloud/helix/blob/master/gamemode/config/sh_config.lua).
|
||||
|
||||
Adding a configuration is as follows:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.config:Add("run_speed", 225)
|
||||
|
||||
-- after
|
||||
ix.config.Add("runSpeed", 235, ...)
|
||||
```
|
||||
You'll notice that ellipses (...) were added at the end. This is because there are more arguments since adding configuration information has been placed into one function. Additionally:
|
||||
|
||||
- `Clockwork.config:ShareKey()` is not needed.
|
||||
- The 3rd argument for `Clockwork.config:AddToSystem(name, key, description, min, max)` is also the 3rd argument for `ix.config.Add`
|
||||
- The 4th argument for `ix.config.Add` is an optional function that is called when the configuration is changed.
|
||||
- The 5th argument for `ix.config.Add` is a table. You can specify the category for the configuration to group it with other configurations. There is also a data table inside which can be used to determine the minimum value and maximum value for numbers. Check out [an example here](https://github.com/NebulousCloud/helix/blob/master/gamemode/config/sh_config.lua). See also `ix.config`.
|
||||
|
||||
## Currency (`ix.currency`)
|
||||
Updating your currency code is simple:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.config:SetKey("name_cash", "Tokens")
|
||||
Clockwork.config:SetKey("name_cash", "Dollars") -- another example
|
||||
|
||||
-- after
|
||||
ix.currency.Set("", "token", "tokens")
|
||||
ix.currency.Set("$", "dollar", "dollars")
|
||||
```
|
||||
|
||||
Note that you need to provide a symbol for that currency (€ for Euro, £ for Pound, ¥ for Yen, etc.) or just leave it as an empty string (`""`) and then provide the singular form of the name for the currency, then the plural form.
|
||||
|
||||
## Datastream
|
||||
Helix uses the [net library](http://wiki.garrysmod.com/page/Net_Library_Usage) whereas Clockwork uses datastream ([netstream](https://github.com/alexgrist/NetStream/blob/master/netstream2.lua)).
|
||||
|
||||
If you're unfamiliar with the net library, you can include the netstream library to your schema by downloading [netstream](https://github.com/alexgrist/NetStream/blob/master/netstream2.lua) to `schema/libs/thirdparty/sh_netstream2.lua` and adding `ix.util.Include("libs/thirdparty/sh_netstream2.lua")` to your `sh_schema.lua` file.
|
||||
|
||||
Starting a datastream:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.datastream:Start(receiver, "MessageName", {1, 2, 3});
|
||||
|
||||
-- after
|
||||
netstream.Start(receiver, "MessageName", 1, 2, 3)
|
||||
```
|
||||
|
||||
Receiving a datastream:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.datastream:Hook("MessageName", function(player, data)
|
||||
local a = data[1];
|
||||
local b = data[2];
|
||||
local c = data[3];
|
||||
|
||||
print(a, b, c);
|
||||
end);
|
||||
|
||||
-- after
|
||||
netstream.Hook("MessageName", function(client, a, b, c)
|
||||
print(a, b, c)
|
||||
end)
|
||||
```
|
||||
|
||||
## Factions (`ix.faction`)
|
||||
Factions, like classes, are pretty similar too. They share pretty much the same differences as classes in Clockwork and Helix do.
|
||||
|
||||
For instance:
|
||||
|
||||
- You do not need to use `local FACTION = Clockwork.faction:New("Name Here")`, instead `FACTION` is already defined for you and you set the name using `FACTION.name = "Name Here"`
|
||||
- `FACTION.whitelist = true` is changed to `FACTION.isDefault = false`
|
||||
- `FACTION.models` does not need a male and female part. Instead, all the models are combined into one big list.
|
||||
- `function FACTION:GetName(name)` becomes `function FACTION:GetDefaultName(name)`
|
||||
- `FACTION.description = "Describe me"` is added to the faction.
|
||||
- `FACTION_MYFACTION = FACTION:Register()` becomes `FACTION_MYFACTION = FACTION.index`
|
||||
|
||||
## Flags (`ix.flag`)
|
||||
Flags are functionally equivalent in Helix. To add a new flag:
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.flag:Add("x", "Name", "Description")
|
||||
|
||||
-- after
|
||||
ix.flag.Add("x", "Description")
|
||||
```
|
||||
|
||||
To check or manipulate a character's flag(s):
|
||||
|
||||
```
|
||||
-- before
|
||||
Clockwork.player:GiveFlags(player, flags)
|
||||
Clockwork.player:TakeFlags(player, flags)
|
||||
Clockwork.player:HasFlags(player, flags)
|
||||
|
||||
-- after
|
||||
client:GetCharacter():GiveFlags(flags)
|
||||
client:GetCharacter():TakeFlags(flags)
|
||||
client:GetCharacter():HasFlags(flags)
|
||||
```
|
||||
|
||||
## Inventories (`Inventory`)
|
||||
Inventories have also had a change in the way they work that may seem very different than Clockwork. Similar to how characters are their own objects, inventories become their own objects as well. These inventory objects belong to character objects, which belongs to players. So, this creates a chain of objects which is neat. The use of inventories as objects makes it very simple to attach inventories to anything.
|
||||
|
||||
To access a player's inventory, you need to use `client:GetCharacter():GetInventory()` which returns the main inventory object for the player's character. You can also access all loaded inventories with `ix.item.inventories` but that is not important right now.
|
||||
|
||||
## Items (`Item`)
|
||||
As discussed above, inventories contain items. Items are still used in inventories and world entities, use default class data, have callback functions, and can contain unique item data per instance.
|
||||
|
||||
### Setting up items
|
||||
Every time needs to be registered, or have information about it (such as the name, model, what it does, etc.) defined. In Clockwork, you have your items defined in schemas/plugins under the items folder.
|
||||
|
||||
So let's start with the differences in structure in the item file.
|
||||
|
||||
- `local ITEM = Clockwork.item:New();` is removed
|
||||
- `ITEM.uniqueID` is *completely* optional
|
||||
- Replace `ITEM.cost` with `ITEM.price`
|
||||
- `ITEM:Register()` is removed
|
||||
|
||||
### Item Sizes
|
||||
Helix's inventory uses a grid and utilizes width and height instead of weight as a means of inventory capacity. This means you will have to change your item's weight (`ITEM.weight`) to something that might be analagous to the item's size using `ITEM.width` and `ITEM.height`. The item's size must be at least one by one grid cell. It's up to you to balance the sizes of items in your use case - taking into account how many items a character might have at once, the default inventory size set in the config, etc.
|
||||
|
||||
### Item Functions
|
||||
Item functions are defined very differently than they are in Clockwork. For example:
|
||||
|
||||
```
|
||||
-- before
|
||||
function ITEM:OnUse(player, entity)
|
||||
print("My name is: " .. player:Name(), entity)
|
||||
end
|
||||
|
||||
-- after
|
||||
ITEM.functions.Use = {
|
||||
OnRun = function(item)
|
||||
print("My name is: " .. item.player, item.entity)
|
||||
end
|
||||
}
|
||||
```
|
||||
|
||||
All item functions are defined in the `ITEM.functions` table. This allows the drop-down menus when using the item a lot easier and cleaner to generate dynamically. There is also more control of the icons used for the options, whether or not the function should be displayed, etc.
|
||||
|
||||
You can see an example of a water item here: [https://github.com/NebulousCloud/helix-hl2rp/blob/master/schema/items/sh_water.lua](https://github.com/NebulousCloud/helix-hl2rp/blob/master/schema/items/sh_water.lua)
|
||||
|
||||
Here, we can define what happens when the function is run, what the icon is, and what sound it plays when used. It is basically put into one area rather than being scattered among hooks and stuff.
|
||||
|
||||
### Giving/Taking Items
|
||||
So before we can give/take items, we need to understand what the *item instance* is. Using the analogy earlier about how the inventory system is like a forum, and inside the forum are posts (the items in this case), we can think of instancing an item as making a new post on a forum. So when we talk about an *item instance*, it is an item that has been created in the past. The reason we use an item instance (which is its own object too, neat!) is to make each item ever created unique. Each item instance can have its own data unique to itself.
|
||||
|
||||
Clockwork also uses an item instance system where you have to instance an item. So, to instance an item in Clockwork you would use:
|
||||
|
||||
```
|
||||
item = Clockwork.item:CreateInstance("item")
|
||||
```
|
||||
|
||||
And this would create a new instance of an item. Helix's instancing system is slightly different. Instead of having the function return the instance like it does in Clockwork, Helix relies on a callback to pass the instance. The reason for this is the item must be inserted into the database to get a unique number to represent that item. This is not done instantly, otherwise servers would freeze when new items are made. Clockwork uses the time and adds a number to get the numeric ID for an item, which allows the item to be returned which "solves" the issue, but I digress.
|
||||
|
||||
The Helix equivalent would be:
|
||||
|
||||
```
|
||||
ix.item.Instance(0, "item", data, x, y, function(item) end)
|
||||
```
|
||||
|
||||
Let's break down the differences:
|
||||
|
||||
- For Helix's item instance, the 1st argument (`0`) is the inventory that the item belongs to. You can specify 0 so it does not belong to any inventory.
|
||||
- The data argument is *optional* and is just a table for the item data.
|
||||
- *x* and *y* are the position of the items in inventory. You can find an available *x* and *y* with `inventory:FindEmptySlot()`.
|
||||
- The function is an *optional* argument that passes the item instance. This is where you can directly access the new item.
|
||||
|
||||
Keep in mind that Helix will simplify the item system for you when it can. Normally, you would not need to instance an item yourself unless you were doing something advanced.
|
||||
|
||||
So you might be wondering, how do I spawn an item in the map, and how do I give a player an item? In Clockwork, you would do the following:
|
||||
|
||||
```
|
||||
-- spawning an item in the map
|
||||
Clockwork.entity:CreateItem(player, Clockwork.item:CreateInstance("item"), Vector(1, 2, 3));
|
||||
|
||||
-- giving a player an item
|
||||
player:GiveItem(Clockwork.item:CreateInstance("item"));
|
||||
```
|
||||
|
||||
The equivalent in Helix would be:
|
||||
|
||||
```
|
||||
-- spawning an item in the map
|
||||
ix.item.Spawn("item", Vector(1, 2, 3))
|
||||
|
||||
-- giving a player an item
|
||||
client:GetCharacter():GetInventory():Add("test")
|
||||
```
|
||||
|
||||
So in these two examples, the whole deal of instancing items is done for you in Helix!
|
||||
|
||||
# Hooks
|
||||
You will need to modify the function name and arguments for your schema or plugin hooks.
|
||||
|
||||
```
|
||||
-- before
|
||||
function Schema:PlayerPlayPainSound(player, gender, damageInfo, hitGroup)
|
||||
-- ...
|
||||
end
|
||||
|
||||
-- after
|
||||
function Schema:GetPlayerPainSound(client)
|
||||
-- ...
|
||||
end
|
||||
```
|
||||
|
||||
You can see the documented hooks for the schema and plugins in the `Plugin` section.
|
||||
|
||||
# Conclusion
|
||||
Overall, most of the conversion from Clockwork to Helix is simply renaming a certain function and/or switching the order of arguments around. Both are frameworks so they function similarly.
|
||||
|
||||
You may want to use our HL2 RP schema example for reference which can be found at [https://github.com/NebulousCloud/helix-hl2rp](https://github.com/NebulousCloud/helix-hl2rp)
|
||||
75
gamemodes/helix/docs/manual/getting-started.md
Normal file
75
gamemodes/helix/docs/manual/getting-started.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Getting Started
|
||||
It's pretty easy to get started with creating your own schema with Helix. It requires a bit of bootstrapping if you're starting from scratch, but you should quickly be on your way to developing your schema after following one of the below sections in this guide.
|
||||
|
||||
# Installing the framework
|
||||
Before you start working on your schema, you'll need to install Helix onto your server. The exact instructions will vary based on your server provider, or if you're hosting the server yourself.
|
||||
|
||||
You'll need to download the framework from [GitHub](https://github.com/NebulousCloud/helix) into a folder called `helix`. This folder goes into your server's `gamemodes` folder at `garrysmod/gamemodes/helix`. That's it! The framework is now installed onto your server. Of course, you'll need to restart your server after installing the framework and a schema.
|
||||
|
||||
# MySQL usage
|
||||
By default, Helix will use SQLite (which is built into Garry's Mod) to store player/character data. This requires no configuration and will work "out of the box" after installing and will be fine for most server owners. However, you might want to connect your database to your website or use multiple servers with one database - this will require the usage of an external database accessible elsewhere. This will require the use of a MySQL server. Some server providers will provide you with a MySQL database for free to use with your server.
|
||||
|
||||
## Installing
|
||||
Helix uses the [MySQLOO](https://github.com/FredyH/MySQLOO) library to connect to MySQL databases. You'll need to follow the instructions for installing that library onto your server before continuing. In a nutshell, you need to make sure `gmsv_mysqloo_win32.dll` or `gmsv_mysqloo_linux.dll` (depending on your server's operating system) is in the `garrysmod/lua/bin` folder.
|
||||
|
||||
In older versions of MySQLOO, you previously required a .dll called `libmysql.dll` to place in your `root` server folder, where `srcds`/`srcds_linux` was stored. Newer versions of MySQLOO no longer require this.
|
||||
|
||||
## Configuring
|
||||
Now that you've installed MySQLOO, you need to tell Helix that you want to connect to an external MySQL database instead of using SQLite. This requires creating a `helix.yml` configuration file in the `garrysmod/gamemodes/helix` folder. There is an example one already made for you called `helix.example.yml` that you can copy and rename to `helix.yml`.
|
||||
|
||||
The first thing you'll need to change is the `adapter` entry so that it says `mysqloo`. Next is to change the other entries to match your database's connection information. Here is an example of what your `helix.yml` should look like:
|
||||
|
||||
```
|
||||
database:
|
||||
adapter: "mysqloo"
|
||||
hostname: "myexampledatabase.com"
|
||||
username: "myusername"
|
||||
password: "mypassword"
|
||||
database: "helix"
|
||||
port: 3306
|
||||
```
|
||||
|
||||
The `hostname` field can either be a domain name (like `myexampledatabase.com`) or an IP address (`123.123.123.123`). If you don't know what the `port` field should be, simply leave it as the default `3306`; this is the default port for MySQL database connections. The `database` field is the name of the database that you've created for Helix. Note that it does not need to be `helix`, it can be whatever you'd like.
|
||||
|
||||
Another important thing to note about this configuration file is that you **must** indent with **two spaces only**. `database` should not have any spacing before it, and all other entries must have two spaces before them. Failing to ensure this will make the configuration file fail to load.
|
||||
|
||||
# Starting with the HL2 RP schema (Basic)
|
||||
This section is for using the existing HL2 RP schema as a base for your own schema. It contains a good amount of example code if you need a stronger foundation than just a skeleton.
|
||||
|
||||
First, you'll need to download the schema from [GitHub](https://github.com/NebulousCloud/helix-hl2rp). Make sure that you download the contents of the repository into a folder called `ixhl2rp` and place it into your `garrysmod/gamemodes` folder. That's all you'll need to do to get the schema installed, other than setting your gamemode to `ixhl2rp` in the server's command line.
|
||||
|
||||
# Starting with the skeleton (Basic)
|
||||
If you don't want excess code you might not use, or prefer to build from an almost-empty foundation that covers the basic bootstrapping, then the skeleton schema is for you. The skeleton schema contains a lot of comments explaining why code is laid out in a certain way, and some other helpful tips/explanations. Make sure you give it a read!
|
||||
|
||||
You'll need to download the schema from [GitHub](https://github.com/NebulousCloud/helix-skeleton) into the folder name of your choice - just make sure it's all lowercase with no spaces. Our example for the sake of brevity will be `myschema`. Place the folder into `garrysmod/gamemodes`.
|
||||
|
||||
Next up is to modify the gamemode info so that Garry's Mod will properly recognize it. Rename `skeleton.txt` in your schema folder to your folder's name. In our example we would rename `skeleton.txt` to `myschema.txt`. Next, you'll need to modify the contents of `myschema.txt` and replace the existing information with your own - making sure to replace the `"skeleton"` at the top of the file to your folder's name. In our case we would replace it with `"myschema"`. Once you've renamed the file, you're all good to go!
|
||||
|
||||
# Converting from Clockwork (Intermediate)
|
||||
If you are looking to switch to Helix from Clockwork, you can follow the @{converting-from-clockwork|conversion guide}.
|
||||
|
||||
# Starting from scratch (Intermediate)
|
||||
You can always create the gamemode files yourself if you'd like (although we suggest the skeleton schema in general). In general, a schema is a gamemode that is derived from `helix` and automatically loads `schema/sh_schema.lua`. You shouldn't have your schema files outside of the `schema` folder. The files you'll need are as follows:
|
||||
|
||||
`gamemode/init.lua`
|
||||
```
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
DeriveGamemode("helix")
|
||||
```
|
||||
|
||||
`gamemode/cl_init.lua`
|
||||
```
|
||||
DeriveGamemode("helix")
|
||||
```
|
||||
|
||||
`schema/sh_schema.lua`
|
||||
```
|
||||
Schema.name = "My Schema"
|
||||
Schema.author = "me!"
|
||||
Schema.description = "My awesome schema."
|
||||
|
||||
-- include your other schema files
|
||||
ix.util.Include("cl_schema.lua")
|
||||
ix.util.Include("sv_schema.lua")
|
||||
-- etc.
|
||||
```
|
||||
19
gamemodes/helix/docs/templates/landing.ltp
vendored
Normal file
19
gamemodes/helix/docs/templates/landing.ltp
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
|
||||
<div class="landing">
|
||||
<h1>Helix Documentation</h1>
|
||||
</div>
|
||||
|
||||
<div class="wrapper">
|
||||
<p style="text-align: center;">Welcome to the documentation for Helix - the better gamemode framework.</p>
|
||||
<h2>Developers</h2>
|
||||
<p>The sidebar shows the entire contents of the documentation. Libraries, functions, etc are all searchable with the search box at the top of the sidebar. Migrating from Clockwork? Check out the <a href="{* ldoc.url('manual/converting-from-clockwork') *}">conversion guide</a> in the manual.</p>
|
||||
<h2>Server owners</h2>
|
||||
<p>If you're looking to get your Helix server up and running as soon as possible, check out the <a href="{* ldoc.url('manual/getting-started') *}">Getting Started</a> guide in the manual.</p>
|
||||
<h2>Community</h2>
|
||||
<p>Questions? Want to show off your work? Maybe drop a new plugin release? Come join our community <a href="https://discord.gg/2AutUcF" target="_blank">Discord server</a>.</p>
|
||||
<h2>Contributing</h2>
|
||||
<p>Helix is a large project and there are still a few things missing here and there. Contributions to the documentation - from function references, to simple typo fixes - are welcomed! Check out the <code>ix.storage</code> library's <a href="https://github.com/NebulousCloud/helix/blob/master/gamemode/core/libs/sh_storage.lua" target="_blank">source code</a> for a good example on how to write documentation. You'll need a basic understanding of <a href="https://guides.github.com/features/mastering-markdown/" target="_blank">Markdown</a>, since it's used extensively to generate the markup.</p>
|
||||
<p>If you'd like to contribute code, you can visit the <a href="https://github.com/NebulousCloud/helix/" target="_blank">GitHub repository</a> and make a pull request.</p>
|
||||
<h2>Learning</h2>
|
||||
<p>Getting started on developing with the Helix framework requires an intermediate level of Garry's Mod Lua knowledge. You'll want to learn the basics before you get starting making a schema. The <a href="https://wiki.facepunch.com/gmod/" target="_blank">Garry's Mod Wiki</a> is a good place to start.</p>
|
||||
</div>
|
||||
90
gamemodes/helix/docs/templates/ldoc.ltp
vendored
Normal file
90
gamemodes/helix/docs/templates/ldoc.ltp
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
|
||||
{%
|
||||
local baseUrl = ldoc.css:gsub("ldoc.css", "")
|
||||
local repo = "https://github.com/nebulouscloud/helix/"
|
||||
local pageTitle = mod and (ldoc.display_name(mod) .. " - " .. ldoc.title) or ldoc.title
|
||||
|
||||
local oldmarkup = ldoc.markup
|
||||
function ldoc.markup(text, item)
|
||||
return oldmarkup(text, item, ldoc.plain)
|
||||
end
|
||||
|
||||
function ldoc.url(path)
|
||||
return baseUrl .. path
|
||||
end
|
||||
|
||||
function ldoc.realm_icon(realm)
|
||||
return "<span class=\"realm " .. (realm or "") .. "\"></span>";
|
||||
end
|
||||
|
||||
function ldoc.is_kind_classmethod(kind)
|
||||
return kind ~= "libraries"
|
||||
end
|
||||
|
||||
function ldoc.repo_reference(item)
|
||||
return repo .. "tree/master" .. item.file.filename:gsub(item.file.base, "/gamemode") .. "#L" .. item.lineno
|
||||
end
|
||||
|
||||
local function moduleDescription(mod)
|
||||
if (mod.type == "topic") then
|
||||
return mod.body:gsub(mod.display_name, ""):gsub("#", ""):sub(1, 256) .. "..."
|
||||
end
|
||||
|
||||
return mod.summary
|
||||
end
|
||||
%}
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>{{pageTitle}}</title>
|
||||
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="{{pageTitle}}" />
|
||||
<meta property="og:site_name" content="Helix Documentation" />
|
||||
|
||||
{% if (mod) then %}
|
||||
<meta property="og:description" content="{{moduleDescription(mod)}}" />
|
||||
{% else %}
|
||||
<meta property="og:description" content="Documentation and function reference for the Helix framework." />
|
||||
{% end %}
|
||||
|
||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Code+Pro" />
|
||||
<link rel="stylesheet" href="{* ldoc.css *}" />
|
||||
<link rel="stylesheet" href="{* ldoc.url('highlight.css') *}" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<main>
|
||||
{(docs/templates/sidebar.ltp)}
|
||||
|
||||
<article>
|
||||
{% if (ldoc.root) then -- we're rendering the landing page (index.html) %}
|
||||
{(docs/templates/landing.ltp)}
|
||||
{% elseif (ldoc.body) then -- we're rendering non-code elements %}
|
||||
<div class="wrapper">
|
||||
{* ldoc.body *}
|
||||
</div>
|
||||
{% elseif (module) then -- we're rendering libary contents %}
|
||||
<div class="wrapper">
|
||||
{(docs/templates/module.ltp)}
|
||||
</div>
|
||||
{% end %}
|
||||
</article>
|
||||
</main>
|
||||
|
||||
<script type="text/javascript" src="{* ldoc.url('app.js') *}"></script>
|
||||
<script type="text/javascript" src="{* ldoc.url('highlight.min.js') *}"></script>
|
||||
<script type="text/javascript">
|
||||
var elements = document.querySelectorAll("pre code")
|
||||
|
||||
hljs.configure({
|
||||
languages: ["lua"]
|
||||
});
|
||||
|
||||
for (var i = 0; i < elements.length; i++)
|
||||
{
|
||||
hljs.highlightBlock(elements[i]);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
123
gamemodes/helix/docs/templates/module.ltp
vendored
Normal file
123
gamemodes/helix/docs/templates/module.ltp
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
|
||||
<header class="module">
|
||||
<h1>{{mod.name}}</h1>
|
||||
<h2>{* ldoc.markup(mod.summary) *}</h2>
|
||||
</header>
|
||||
|
||||
<p>{* ldoc.markup(mod.description) *}</p>
|
||||
|
||||
{% for kind, items in mod.kinds() do %}
|
||||
<h1 class="title">{{kind}}</h1>
|
||||
|
||||
{% for item in items() do %}
|
||||
<section class="method">
|
||||
<header>
|
||||
<a class="anchor" id="{{item.name}}">
|
||||
<h1>{* ldoc.realm_icon(item.tags.realm[1]) *}</span>{{ldoc.display_name(item)}}</h1>
|
||||
</a>
|
||||
|
||||
{% if (item.tags.internal) then %}
|
||||
<div class="notice error">
|
||||
<div class="title">Internal</div>
|
||||
<p>This is an internal function! You are able to use it, but you risk unintended side effects if used incorrectly.</p>
|
||||
</div>
|
||||
{% end %}
|
||||
|
||||
{% if (item.module and item.module.type ~= "hooks") then %}
|
||||
<a class="reference" href="{* ldoc.repo_reference(item) *}">View source »</a>
|
||||
{% end %}
|
||||
|
||||
{% if (ldoc.descript(item):len() == 0) then %}
|
||||
<div class="notice warning">
|
||||
<div class="title">Incomplete</div>
|
||||
<p>Documentation for this section is incomplete and needs expanding.</p>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>{* ldoc.markup(ldoc.descript(item)) *}</p>
|
||||
{% end %}
|
||||
</header>
|
||||
|
||||
{# function arguments #}
|
||||
{% if (item.params and #item.params > 0) then %}
|
||||
{% local subnames = mod.kinds:type_of(item).subnames %}
|
||||
|
||||
{% if (subnames) then %}
|
||||
<h3>{{subnames}}</h3>
|
||||
{% end %}
|
||||
|
||||
{% for argument in ldoc.modules.iter(item.params) do %}
|
||||
{% local argument, sublist = item:subparam(argument) %}
|
||||
|
||||
<ul>
|
||||
{% for argumentName in ldoc.modules.iter(argument) do %}
|
||||
{% local displayName = item:display_name_of(argumentName) %}
|
||||
{% local type = ldoc.typename(item:type_of_param(argumentName)) %}
|
||||
{% local default = item:default_of_param(argumentName) %}
|
||||
|
||||
<li>
|
||||
<span class="tag parameter">{{displayName}}</span>
|
||||
|
||||
{% if (type ~= "") then %}
|
||||
<span class="tag">{* type *}</span>
|
||||
{% end %}
|
||||
|
||||
{% if (default and default ~= true) then %}
|
||||
<span class="tag default">default: {{default}}</span>
|
||||
{% elseif (default) then %}
|
||||
<span class="tag default">optional</span>
|
||||
{% end %}
|
||||
|
||||
<p>{* ldoc.markup(item.params.map[argumentName]) *}</p>
|
||||
</li>
|
||||
{% end %}
|
||||
</ul>
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
{# function returns #}
|
||||
{% if ((not ldoc.no_return_or_parms) and item.retgroups) then %}
|
||||
{% local groups = item.retgroups %}
|
||||
|
||||
<h3>Returns</h3>
|
||||
<ul>
|
||||
{% for i, group in ldoc.ipairs(groups) do %}
|
||||
{% for returnValue in group:iter() do %}
|
||||
{% local type, ctypes = item:return_type(returnValue) %}
|
||||
{% type = ldoc.typename(type) %}
|
||||
|
||||
<li>
|
||||
{% if (type ~= "") then %}
|
||||
{* type *}
|
||||
{% else -- we'll assume that it will return a variable type if none is set %}
|
||||
<span class="tag type">any</span>
|
||||
{% end %}
|
||||
|
||||
<p>{* ldoc.markup(returnValue.text) *}</p>
|
||||
</li>
|
||||
{% end %}
|
||||
|
||||
{% if (i ~= #groups) then %}
|
||||
<div class="or"><span>OR</span></div>
|
||||
{% end %}
|
||||
{% end %}
|
||||
</ul>
|
||||
{% end %}
|
||||
|
||||
{% if (item.usage) then -- function usage %}
|
||||
<h3>Example Usage</h3>
|
||||
{% for usage in ldoc.modules.iter(item.usage) do %}
|
||||
<pre><code>{* usage *}</code></pre>
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
{% if (item.see) then %}
|
||||
<h3>See Also</h3>
|
||||
<ul>
|
||||
{% for see in ldoc.modules.iter(item.see) do %}
|
||||
<li><a href="{* ldoc.href(see) *}">{{see.label}}</a></li>
|
||||
{% end %}
|
||||
</ul>
|
||||
{% end %}
|
||||
</section>
|
||||
{% end %}
|
||||
{% end %}
|
||||
69
gamemodes/helix/docs/templates/sidebar.ltp
vendored
Normal file
69
gamemodes/helix/docs/templates/sidebar.ltp
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
|
||||
{%
|
||||
local function isKindExpandable(kind)
|
||||
return kind ~= "Manual"
|
||||
end
|
||||
%}
|
||||
|
||||
<nav>
|
||||
<header>
|
||||
{% if (not ldoc.root) then %}
|
||||
<h1><a href="{* ldoc.url('') *}">Helix Documentation</a></h1>
|
||||
{% end %}
|
||||
<input id="search" type="search" autocomplete="off" placeholder="Search..." />
|
||||
</header>
|
||||
|
||||
<section>
|
||||
{% for kind, mods, type in ldoc.kinds() do %}
|
||||
{% if (ldoc.allowed_in_contents(type, mod)) then %}
|
||||
<details class="category" open>
|
||||
<summary>
|
||||
<h2>{{kind}}</h2>
|
||||
</summary>
|
||||
|
||||
<ul>
|
||||
{% for currentMod in mods() do %}
|
||||
{% local name = ldoc.display_name(currentMod) %}
|
||||
<li>
|
||||
{% if (isKindExpandable(kind)) then %}
|
||||
<details {{currentMod.name == (mod or {}).name and "open" or ""}}>
|
||||
<summary><a href="{* ldoc.ref_to_module(currentMod) *}">{{name}}</a></summary>
|
||||
|
||||
<ul>
|
||||
{% else %}
|
||||
<a href="{* ldoc.ref_to_module(currentMod) *}">{{name}}</a>
|
||||
{% end %}
|
||||
|
||||
{% if (isKindExpandable(kind)) then
|
||||
currentMod.items:sort(function(a, b)
|
||||
return a.name < b.name
|
||||
end)
|
||||
end %}
|
||||
|
||||
{% for k, v in pairs(currentMod.items) do %}
|
||||
{% if (v.kind == "functions") then %}
|
||||
<li>
|
||||
{* ldoc.realm_icon(v.tags.realm[1]) *}
|
||||
<a href="{* ldoc.ref_to_module(currentMod) *}#{{v.name}}">
|
||||
{% if (ldoc.is_kind_classmethod(currentMod.kind)) then
|
||||
echo((v.name:gsub(".+:", "")))
|
||||
else
|
||||
echo((v.name:gsub(currentMod.name .. ".", "")))
|
||||
end %}
|
||||
</a>
|
||||
</li>
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
{% if (isKindExpandable(kind)) then %}
|
||||
</ul>
|
||||
</details>
|
||||
{% end %}
|
||||
</li>
|
||||
{% end %}
|
||||
</ul>
|
||||
</details>
|
||||
{% end %}
|
||||
{% end %}
|
||||
</section>
|
||||
</nav>
|
||||
345
gamemodes/helix/entities/entities/ix_item.lua
Normal file
345
gamemodes/helix/entities/entities/ix_item.lua
Normal file
@@ -0,0 +1,345 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
ENT.PrintName = "Item"
|
||||
ENT.Category = "Helix"
|
||||
ENT.Spawnable = false
|
||||
ENT.ShowPlayerInteraction = true
|
||||
ENT.RenderGroup = RENDERGROUP_BOTH
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("String", 0, "ItemID")
|
||||
end
|
||||
|
||||
function ENT:GetProxyColors()
|
||||
local itemTable = self.GetItemTable and self:GetItemTable()
|
||||
return itemTable and itemTable.proxy or false
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
local invalidBoundsMin = Vector(-8, -8, -8)
|
||||
local invalidBoundsMax = Vector(8, 8, 8)
|
||||
|
||||
util.AddNetworkString("ixItemEntityAction")
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/props_junk/watermelon01.mdl")
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:AddEFlags(EFL_FORCE_CHECK_TRANSMIT)
|
||||
self.health = 50
|
||||
|
||||
local physObj = self:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physObj)) then
|
||||
physObj:EnableMotion(true)
|
||||
physObj:Wake()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Use(activator, caller)
|
||||
local itemTable = self:GetItemTable()
|
||||
|
||||
if (IsValid(caller) and caller:IsPlayer() and caller:GetCharacter() and itemTable) then
|
||||
itemTable.player = caller
|
||||
itemTable.entity = self
|
||||
|
||||
if (itemTable.functions.take.OnCanRun(itemTable)) then
|
||||
caller:PerformInteraction(ix.config.Get("itemPickupTime", 0.5), self, function(client)
|
||||
if (!ix.item.PerformInventoryAction(client, "take", self)) then
|
||||
return false -- do not mark dirty if interaction fails
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
itemTable.player = nil
|
||||
itemTable.entity = nil
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:SetItem(itemID)
|
||||
local itemTable = ix.item.instances[itemID]
|
||||
|
||||
if (itemTable) then
|
||||
local material = itemTable:GetMaterial(self)
|
||||
|
||||
self:SetSkin(itemTable:GetSkin())
|
||||
self:SetModel(itemTable:GetModel())
|
||||
self:SetBodyGroups(itemTable:GetModelBodygroups())
|
||||
|
||||
if (material) then
|
||||
self:SetMaterial(material)
|
||||
end
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetItemID(itemTable.uniqueID)
|
||||
self.ixItemID = itemID
|
||||
|
||||
if (!table.IsEmpty(itemTable.data)) then
|
||||
self:SetNetVar("data", itemTable.data)
|
||||
end
|
||||
|
||||
local physObj = self:GetPhysicsObject()
|
||||
|
||||
if (!IsValid(physObj)) then
|
||||
self:PhysicsInitBox(invalidBoundsMin, invalidBoundsMax)
|
||||
self:SetCollisionBounds(invalidBoundsMin, invalidBoundsMax)
|
||||
end
|
||||
|
||||
if (IsValid(physObj)) then
|
||||
physObj:EnableMotion(true)
|
||||
physObj:Wake()
|
||||
end
|
||||
|
||||
if (itemTable.OnEntityCreated) then
|
||||
itemTable:OnEntityCreated(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnDuplicated(entTable)
|
||||
local itemID = entTable.ixItemID
|
||||
local itemTable = ix.item.instances[itemID]
|
||||
|
||||
ix.item.Instance(0, itemTable.uniqueID, itemTable.data, 1, 1, function(item)
|
||||
self:SetItem(item:GetID())
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(damageInfo)
|
||||
local itemTable = ix.item.instances[self.ixItemID]
|
||||
|
||||
if (itemTable.OnEntityTakeDamage
|
||||
and itemTable:OnEntityTakeDamage(self, damageInfo) == false) then
|
||||
return
|
||||
end
|
||||
|
||||
local damage = damageInfo:GetDamage()
|
||||
self:SetHealth(self:Health() - damage)
|
||||
|
||||
if (self:Health() <= 0 and !self.ixIsDestroying) then
|
||||
self.ixIsDestroying = true
|
||||
self.ixDamageInfo = {damageInfo:GetAttacker(), damage, damageInfo:GetInflictor()}
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (!ix.shuttingDown and !self.ixIsSafe and self.ixItemID) then
|
||||
local itemTable = ix.item.instances[self.ixItemID]
|
||||
|
||||
if (itemTable) then
|
||||
if (self.ixIsDestroying) then
|
||||
self:EmitSound("physics/cardboard/cardboard_box_break"..math.random(1, 3)..".wav")
|
||||
local position = self:LocalToWorld(self:OBBCenter())
|
||||
|
||||
local effect = EffectData()
|
||||
effect:SetStart(position)
|
||||
effect:SetOrigin(position)
|
||||
effect:SetScale(3)
|
||||
util.Effect("GlassImpact", effect)
|
||||
|
||||
if (itemTable.OnDestroyed) then
|
||||
itemTable:OnDestroyed(self)
|
||||
end
|
||||
|
||||
ix.log.Add(self.ixDamageInfo[1], "itemDestroy", itemTable:GetName(), itemTable:GetID())
|
||||
end
|
||||
|
||||
if (itemTable.OnRemoved) then
|
||||
itemTable:OnRemoved()
|
||||
end
|
||||
|
||||
local query = mysql:Delete("ix_items")
|
||||
query:Where("item_id", self.ixItemID)
|
||||
query:Execute()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
local itemTable = self:GetItemTable()
|
||||
|
||||
if (!itemTable) then
|
||||
--self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
if (itemTable.Think) then
|
||||
itemTable:Think(self)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
|
||||
net.Receive("ixItemEntityAction", function(length, client)
|
||||
ix.item.PerformInventoryAction(client, net.ReadString(), net.ReadEntity())
|
||||
end)
|
||||
else
|
||||
ENT.PopulateEntityInfo = true
|
||||
|
||||
local shadeColor = Color(0, 0, 0, 200)
|
||||
local blockSize = 4
|
||||
local blockSpacing = 2
|
||||
|
||||
function ENT:OnPopulateEntityInfo(tooltip)
|
||||
local item = self:GetItemTable()
|
||||
|
||||
if (!item) then
|
||||
return
|
||||
end
|
||||
|
||||
local oldData = item.data
|
||||
|
||||
item.data = self:GetNetVar("data", {})
|
||||
item.entity = self
|
||||
|
||||
ix.hud.PopulateItemTooltip(tooltip, item)
|
||||
|
||||
local name = tooltip:GetRow("name")
|
||||
local color = name and name:GetBackgroundColor() or ix.config.Get("color")
|
||||
|
||||
-- set the arrow to be the same colour as the title/name row
|
||||
tooltip:SetArrowColor(color)
|
||||
|
||||
if ((item.width > 1 or item.height > 1) and
|
||||
hook.Run("ShouldDrawItemSize", item) != false) then
|
||||
|
||||
local sizeHeight = item.height * blockSize + item.height * blockSpacing
|
||||
local size = tooltip:Add("Panel")
|
||||
size:SetWide(tooltip:GetWide())
|
||||
|
||||
if (tooltip:IsMinimal()) then
|
||||
size:SetTall(sizeHeight)
|
||||
size:Dock(TOP)
|
||||
size:SetZPos(-999)
|
||||
else
|
||||
size:SetTall(sizeHeight + 8)
|
||||
size:Dock(BOTTOM)
|
||||
end
|
||||
|
||||
size.Paint = function(sizePanel, width, height)
|
||||
if (!tooltip:IsMinimal()) then
|
||||
surface.SetDrawColor(ColorAlpha(shadeColor, 60))
|
||||
surface.DrawRect(0, 0, width, height)
|
||||
end
|
||||
|
||||
local x, y = width * 0.5 - 1, height * 0.5 - 1
|
||||
local itemWidth = item.width - 1
|
||||
local itemHeight = item.height - 1
|
||||
local heightDifference = ((itemHeight + 1) * blockSize + blockSpacing * itemHeight)
|
||||
|
||||
x = x - (itemWidth * blockSize + blockSpacing * itemWidth) * 0.5
|
||||
y = y - heightDifference * 0.5
|
||||
|
||||
for i = 0, itemHeight do
|
||||
for j = 0, itemWidth do
|
||||
local blockX, blockY = x + j * blockSize + j * blockSpacing, y + i * blockSize + i * blockSpacing
|
||||
|
||||
surface.SetDrawColor(shadeColor)
|
||||
surface.DrawRect(blockX + 1, blockY + 1, blockSize, blockSize)
|
||||
|
||||
surface.SetDrawColor(color)
|
||||
surface.DrawRect(blockX, blockY, blockSize, blockSize)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
tooltip:SizeToContents()
|
||||
end
|
||||
|
||||
item.entity = nil
|
||||
item.data = oldData
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
local itemTable = self:GetItemTable()
|
||||
|
||||
if (itemTable and itemTable.DrawEntity) then
|
||||
itemTable:DrawEntity(self)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:GetEntityMenu(client)
|
||||
local itemTable = self:GetItemTable()
|
||||
local options = {}
|
||||
|
||||
if (!itemTable) then
|
||||
return false
|
||||
end
|
||||
|
||||
itemTable.player = client
|
||||
itemTable.entity = self
|
||||
|
||||
for k, v in SortedPairs(itemTable.functions) do
|
||||
if (k == "take" or k == "combine") then
|
||||
continue
|
||||
end
|
||||
|
||||
if (v.OnCanRun and v.OnCanRun(itemTable) == false) then
|
||||
continue
|
||||
end
|
||||
|
||||
-- we keep the localized phrase since we aren't using the callbacks - the name won't matter in this case
|
||||
options[L(v.name or k)] = function()
|
||||
local send = true
|
||||
|
||||
if (v.OnClick) then
|
||||
send = v.OnClick(itemTable)
|
||||
end
|
||||
|
||||
if (v.sound) then
|
||||
surface.PlaySound(v.sound)
|
||||
end
|
||||
|
||||
if (send != false) then
|
||||
net.Start("ixItemEntityAction")
|
||||
net.WriteString(k)
|
||||
net.WriteEntity(self)
|
||||
net.SendToServer()
|
||||
end
|
||||
|
||||
-- don't run callbacks since we're handling it manually
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
itemTable.player = nil
|
||||
itemTable.entity = nil
|
||||
|
||||
return options
|
||||
end
|
||||
|
||||
function ENT:GetItemTable()
|
||||
return ix.item.list[self:GetItemID()]
|
||||
end
|
||||
|
||||
function ENT:GetData(key, default)
|
||||
local data = self:GetNetVar("data", {})
|
||||
|
||||
return data[key] or default
|
||||
end
|
||||
74
gamemodes/helix/entities/entities/ix_money.lua
Normal file
74
gamemodes/helix/entities/entities/ix_money.lua
Normal file
@@ -0,0 +1,74 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.PrintName = "Money"
|
||||
ENT.Category = "Helix"
|
||||
ENT.Spawnable = false
|
||||
ENT.ShowPlayerInteraction = true
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Int", 0, "Amount")
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
local invalidBoundsMin = Vector(-8, -8, -8)
|
||||
local invalidBoundsMax = Vector(8, 8, 8)
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel(ix.currency.model)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
|
||||
local physObj = self:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physObj)) then
|
||||
physObj:EnableMotion(true)
|
||||
physObj:Wake()
|
||||
else
|
||||
self:PhysicsInitBox(invalidBoundsMin, invalidBoundsMax)
|
||||
self:SetCollisionBounds(invalidBoundsMin, invalidBoundsMax)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Use(activator)
|
||||
if (self.ixSteamID and self.ixCharID) then
|
||||
local char = activator:GetCharacter()
|
||||
|
||||
if (char and self.ixCharID != char:GetID() and self.ixSteamID == activator:SteamID()) then
|
||||
activator:NotifyLocalized("itemOwned")
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
activator:PerformInteraction(ix.config.Get("itemPickupTime", 0.5), self, function(client)
|
||||
if (hook.Run("OnPickupMoney", client, self) != false) then
|
||||
self:Remove()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
else
|
||||
ENT.PopulateEntityInfo = true
|
||||
|
||||
function ENT:OnPopulateEntityInfo(container)
|
||||
local text = container:AddRow("name")
|
||||
text:SetImportant()
|
||||
text:SetText(ix.currency.Get(self:GetAmount()))
|
||||
text:SizeToContents()
|
||||
end
|
||||
end
|
||||
147
gamemodes/helix/entities/entities/ix_shipment.lua
Normal file
147
gamemodes/helix/entities/entities/ix_shipment.lua
Normal file
@@ -0,0 +1,147 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.PrintName = "Shipment"
|
||||
ENT.Category = "Helix"
|
||||
ENT.Spawnable = false
|
||||
ENT.ShowPlayerInteraction = true
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Int", 0, "DeliveryTime")
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/Items/item_item_crate.mdl")
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:PrecacheGibs()
|
||||
|
||||
local physObj = self:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physObj)) then
|
||||
physObj:EnableMotion(true)
|
||||
physObj:Wake()
|
||||
end
|
||||
|
||||
self:SetDeliveryTime(CurTime() + 120)
|
||||
|
||||
timer.Simple(120, function()
|
||||
if (IsValid(self)) then
|
||||
self:Remove()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:Use(activator)
|
||||
activator:PerformInteraction(ix.config.Get("itemPickupTime", 0.5), self, function(client)
|
||||
if (client:GetCharacter() and client:GetCharacter():GetID() == self:GetNetVar("owner", 0)
|
||||
and hook.Run("CanPlayerOpenShipment", client, self) != false) then
|
||||
client.ixShipment = self
|
||||
|
||||
net.Start("ixShipmentOpen")
|
||||
net.WriteEntity(self)
|
||||
net.WriteTable(self.items)
|
||||
net.Send(client)
|
||||
end
|
||||
|
||||
-- don't mark dirty since the player could come back and use this shipment again later
|
||||
return false
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:SetItems(items)
|
||||
self.items = items
|
||||
end
|
||||
|
||||
function ENT:GetItemCount()
|
||||
local count = 0
|
||||
|
||||
for _, v in pairs(self.items) do
|
||||
count = count + math.max(v, 0)
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
self:EmitSound("physics/cardboard/cardboard_box_break"..math.random(1, 3)..".wav")
|
||||
|
||||
local position = self:LocalToWorld(self:OBBCenter())
|
||||
|
||||
local effect = EffectData()
|
||||
effect:SetStart(position)
|
||||
effect:SetOrigin(position)
|
||||
effect:SetScale(3)
|
||||
util.Effect("GlassImpact", effect)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
else
|
||||
ENT.PopulateEntityInfo = true
|
||||
|
||||
local size = 150
|
||||
local tempMat = Material("particle/warp1_warp", "alphatest")
|
||||
|
||||
function ENT:Draw()
|
||||
local pos, ang = self:GetPos(), self:GetAngles()
|
||||
|
||||
self:DrawModel()
|
||||
|
||||
pos = pos + self:GetUp() * 25
|
||||
pos = pos + self:GetForward() * 1
|
||||
pos = pos + self:GetRight() * 3
|
||||
|
||||
local delTime = math.max(math.ceil(self:GetDeliveryTime() - CurTime()), 0)
|
||||
|
||||
local func = function()
|
||||
surface.SetMaterial(tempMat)
|
||||
surface.SetDrawColor(0, 0, 0, 200)
|
||||
surface.DrawTexturedRect(-size / 2, -size / 2 - 10, size, size)
|
||||
|
||||
ix.util.DrawText("k", 0, 0, color_white, 1, 4, "ixIconsBig")
|
||||
ix.util.DrawText(delTime, 0, -10, color_white, 1, 5, "ixBigFont")
|
||||
end
|
||||
|
||||
cam.Start3D2D(pos, ang, .15)
|
||||
func()
|
||||
cam.End3D2D()
|
||||
|
||||
ang:RotateAroundAxis(ang:Right(), 180)
|
||||
pos = pos - self:GetUp() * 26
|
||||
|
||||
cam.Start3D2D(pos, ang, .15)
|
||||
func()
|
||||
cam.End3D2D()
|
||||
end
|
||||
|
||||
function ENT:OnPopulateEntityInfo(container)
|
||||
local owner = ix.char.loaded[self:GetNetVar("owner", 0)]
|
||||
|
||||
local name = container:AddRow("name")
|
||||
name:SetImportant()
|
||||
name:SetText(L("shipment"))
|
||||
name:SizeToContents()
|
||||
|
||||
if (owner) then
|
||||
local description = container:AddRow("description")
|
||||
description:SetText(L("shipmentDesc", owner:GetName()))
|
||||
description:SizeToContents()
|
||||
end
|
||||
end
|
||||
end
|
||||
649
gamemodes/helix/entities/weapons/ix_hands.lua
Normal file
649
gamemodes/helix/entities/weapons/ix_hands.lua
Normal file
@@ -0,0 +1,649 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
if (CLIENT) then
|
||||
SWEP.PrintName = "Hands"
|
||||
SWEP.Slot = 0
|
||||
SWEP.SlotPos = 1
|
||||
SWEP.DrawAmmo = false
|
||||
SWEP.DrawCrosshair = true
|
||||
end
|
||||
|
||||
SWEP.Author = "Chessnut"
|
||||
SWEP.Instructions = [[Primary Fire: Throw/Punch
|
||||
Secondary Fire: Knock/Pickup
|
||||
Secondary Fire + Mouse: Rotate Object
|
||||
Reload: Drop]]
|
||||
SWEP.Purpose = "Hitting things and knocking on doors."
|
||||
SWEP.Drop = false
|
||||
|
||||
SWEP.ViewModelFOV = 45
|
||||
SWEP.ViewModelFlip = false
|
||||
SWEP.AnimPrefix = "rpg"
|
||||
|
||||
SWEP.ViewTranslation = 4
|
||||
if CLIENT then
|
||||
SWEP.NextAllowedPlayRateChange = 0
|
||||
end
|
||||
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Automatic = false
|
||||
SWEP.Primary.Ammo = ""
|
||||
SWEP.Primary.Damage = 5
|
||||
SWEP.Primary.Delay = 0.75
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.DefaultClip = 0
|
||||
SWEP.Secondary.Automatic = false
|
||||
SWEP.Secondary.Ammo = ""
|
||||
SWEP.Secondary.Delay = 0.5
|
||||
|
||||
SWEP.ViewModel = Model("models/weapons/c_arms.mdl")
|
||||
SWEP.WorldModel = ""
|
||||
|
||||
SWEP.UseHands = true
|
||||
SWEP.LowerAngles = Angle(0, 5, -14)
|
||||
SWEP.LowerAngles2 = Angle(0, 5, -19)
|
||||
SWEP.KnockViewPunchAngle = Angle(-1.3, 1.8, 0)
|
||||
|
||||
SWEP.FireWhenLowered = true
|
||||
SWEP.HoldType = "fist"
|
||||
|
||||
SWEP.holdDistance = 64
|
||||
SWEP.maxHoldDistance = 96 -- how far away the held object is allowed to travel before forcefully dropping
|
||||
SWEP.maxHoldStress = 4000 -- how much stress the held object can undergo before forcefully dropping
|
||||
|
||||
-- luacheck: globals ACT_VM_FISTS_DRAW ACT_VM_FISTS_HOLSTER
|
||||
ACT_VM_FISTS_DRAW = 2
|
||||
ACT_VM_FISTS_HOLSTER = 1
|
||||
|
||||
function SWEP:Initialize()
|
||||
self:SetHoldType(self.HoldType)
|
||||
|
||||
self.lastHand = 0
|
||||
self.maxHoldDistanceSquared = self.maxHoldDistance ^ 2
|
||||
self.heldObjectAngle = Angle(angle_zero)
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
function SWEP:PreDrawViewModel(viewModel, weapon, client)
|
||||
local hands = player_manager.TranslatePlayerHands(player_manager.TranslateToPlayerModelName(client:GetModel()))
|
||||
|
||||
if client:GetModel() == "models/willardnetworks/vortigaunt.mdl" then
|
||||
self.ViewModelFOV = 60
|
||||
end
|
||||
|
||||
if (hands and hands.model) then
|
||||
viewModel:SetModel(hands.model)
|
||||
if hands.skin and isnumber(hands.skin) then
|
||||
viewModel:SetSkin(hands.skin)
|
||||
end
|
||||
viewModel:SetBodyGroups(hands.body)
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:DoDrawCrosshair(x, y)
|
||||
surface.SetDrawColor(255, 255, 255, 66)
|
||||
surface.DrawRect(x - 2, y - 2, 4, 4)
|
||||
end
|
||||
|
||||
-- Adjust these variables to move the viewmodel's position
|
||||
SWEP.IronSightsPos = Vector(0, 0, 0)
|
||||
SWEP.IronSightsAng = Vector(0, 0, 0)
|
||||
|
||||
function SWEP:GetViewModelPosition(EyePos, EyeAng)
|
||||
if self.Owner:GetModel() == "models/willardnetworks/vortigaunt.mdl" then
|
||||
self.IronSightsPos = Vector(0, -3, -5)
|
||||
local Mul = 1.0
|
||||
|
||||
local Offset = self.IronSightsPos
|
||||
|
||||
if (self.IronSightsAng) then
|
||||
EyeAng = EyeAng * 1
|
||||
|
||||
EyeAng:RotateAroundAxis(EyeAng:Right(), self.IronSightsAng.x * Mul)
|
||||
EyeAng:RotateAroundAxis(EyeAng:Up(), self.IronSightsAng.y * Mul)
|
||||
EyeAng:RotateAroundAxis(EyeAng:Forward(), self.IronSightsAng.z * Mul)
|
||||
end
|
||||
|
||||
local Right = EyeAng:Right()
|
||||
local Up = EyeAng:Up()
|
||||
local Forward = EyeAng:Forward()
|
||||
|
||||
EyePos = EyePos + Offset.x * Right * Mul
|
||||
EyePos = EyePos + Offset.y * Forward * Mul
|
||||
EyePos = EyePos + Offset.z * Up * Mul
|
||||
|
||||
return EyePos, EyeAng
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("CreateMove", "ixHandsCreateMove", function(cmd)
|
||||
if (LocalPlayer():GetLocalVar("bIsHoldingObject", false) and cmd:KeyDown(IN_ATTACK2)) then
|
||||
cmd:ClearMovement()
|
||||
local angle = RenderAngles()
|
||||
angle.z = 0
|
||||
cmd:SetViewAngles(angle)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function SWEP:Deploy()
|
||||
if (!IsValid(self:GetOwner())) then
|
||||
return
|
||||
end
|
||||
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
|
||||
if (IsValid(viewModel)) then
|
||||
viewModel:SetPlaybackRate(1)
|
||||
viewModel:ResetSequence(ACT_VM_FISTS_DRAW)
|
||||
if CLIENT then
|
||||
self.NextAllowedPlayRateChange = CurTime() + viewModel:SequenceDuration()
|
||||
end
|
||||
end
|
||||
|
||||
self:DropObject()
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:Precache()
|
||||
util.PrecacheSound("npc/vort/claw_swing1.wav")
|
||||
util.PrecacheSound("npc/vort/claw_swing2.wav")
|
||||
util.PrecacheSound("physics/plastic/plastic_box_impact_hard1.wav")
|
||||
util.PrecacheSound("physics/plastic/plastic_box_impact_hard2.wav")
|
||||
util.PrecacheSound("physics/plastic/plastic_box_impact_hard3.wav")
|
||||
util.PrecacheSound("physics/plastic/plastic_box_impact_hard4.wav")
|
||||
util.PrecacheSound("physics/wood/wood_crate_impact_hard2.wav")
|
||||
util.PrecacheSound("physics/wood/wood_crate_impact_hard3.wav")
|
||||
end
|
||||
|
||||
function SWEP:OnReloaded()
|
||||
self.maxHoldDistanceSquared = self.maxHoldDistance ^ 2
|
||||
self:DropObject()
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
if (!IsValid(self:GetOwner())) then
|
||||
return
|
||||
end
|
||||
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
|
||||
if (IsValid(viewModel)) then
|
||||
viewModel:SetPlaybackRate(1)
|
||||
viewModel:ResetSequence(ACT_VM_FISTS_HOLSTER)
|
||||
if CLIENT then
|
||||
self.NextAllowedPlayRateChange = CurTime() + viewModel:SequenceDuration()
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:Think()
|
||||
if (!IsValid(self:GetOwner())) then
|
||||
return
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
|
||||
if (IsValid(viewModel) and self.NextAllowedPlayRateChange < CurTime()) then
|
||||
viewModel:SetPlaybackRate(1)
|
||||
end
|
||||
else
|
||||
if (self:IsHoldingObject()) then
|
||||
local physics = self:GetHeldPhysicsObject()
|
||||
local bIsRagdoll = self.heldEntity:IsRagdoll()
|
||||
local holdDistance = bIsRagdoll and self.holdDistance * 0.5 or self.holdDistance
|
||||
local targetLocation = self:GetOwner():GetShootPos() + self:GetOwner():GetForward() * holdDistance
|
||||
|
||||
if (bIsRagdoll) then
|
||||
targetLocation.z = math.min(targetLocation.z, self:GetOwner():GetShootPos().z - 32)
|
||||
end
|
||||
|
||||
if (!IsValid(physics)) then
|
||||
self:DropObject()
|
||||
return
|
||||
end
|
||||
|
||||
if (physics:GetPos():DistToSqr(targetLocation) > self.maxHoldDistanceSquared) then
|
||||
self:DropObject()
|
||||
else
|
||||
local physicsObject = self.holdEntity:GetPhysicsObject()
|
||||
local currentPlayerAngles = self:GetOwner():EyeAngles()
|
||||
local client = self:GetOwner()
|
||||
|
||||
if (client:KeyDown(IN_ATTACK2)) then
|
||||
local cmd = client:GetCurrentCommand()
|
||||
self.heldObjectAngle:RotateAroundAxis(currentPlayerAngles:Forward(), cmd:GetMouseX() / 15)
|
||||
self.heldObjectAngle:RotateAroundAxis(currentPlayerAngles:Right(), cmd:GetMouseY() / 15)
|
||||
end
|
||||
|
||||
self.lastPlayerAngles = self.lastPlayerAngles or currentPlayerAngles
|
||||
self.heldObjectAngle.y = self.heldObjectAngle.y - math.AngleDifference(self.lastPlayerAngles.y, currentPlayerAngles.y)
|
||||
self.lastPlayerAngles = currentPlayerAngles
|
||||
|
||||
physicsObject:Wake()
|
||||
physicsObject:ComputeShadowControl({
|
||||
secondstoarrive = 0.01,
|
||||
pos = targetLocation,
|
||||
angle = self.heldObjectAngle,
|
||||
maxangular = 256,
|
||||
maxangulardamp = 10000,
|
||||
maxspeed = 256,
|
||||
maxspeeddamp = 10000,
|
||||
dampfactor = 0.8,
|
||||
teleportdistance = self.maxHoldDistance * 0.75,
|
||||
deltatime = FrameTime()
|
||||
})
|
||||
|
||||
if (physics:GetStress() > self.maxHoldStress) then
|
||||
self:DropObject()
|
||||
end
|
||||
|
||||
local pos = physics:GetPos()
|
||||
local clientPos = client:GetPos()
|
||||
|
||||
if (clientPos.z > pos.z and math.Distance(clientPos.x, clientPos.y, pos.x, pos.y) <= 50) then
|
||||
self:DropObject()
|
||||
end
|
||||
end
|
||||
end
|
||||
-- Prevents the camera from getting stuck when the object that the client is holding gets deleted.
|
||||
if(!IsValid(self.heldEntity) and self:GetOwner():GetLocalVar("bIsHoldingObject", true)) then
|
||||
self:GetOwner():SetLocalVar("bIsHoldingObject", false)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:GetHeldPhysicsObject()
|
||||
return IsValid(self.heldEntity) and self.heldEntity:GetPhysicsObject() or nil
|
||||
end
|
||||
|
||||
function SWEP:CanHoldObject(entity)
|
||||
if !entity or entity and !IsValid(entity) then return false end
|
||||
|
||||
local physics = entity.GetPhysicsObject and entity:GetPhysicsObject()
|
||||
local client = self:GetOwner()
|
||||
local clientPos = client:GetPos()
|
||||
local pos = physics and IsValid(physics) and physics:GetPos()
|
||||
|
||||
return IsValid(physics) and
|
||||
(physics:GetMass() <= ix.config.Get("maxHoldWeight", 100) and physics:IsMoveable()) and
|
||||
!self:IsHoldingObject() and
|
||||
!IsValid(entity.ixHeldOwner) and
|
||||
hook.Run("CanPlayerHoldObject", client, entity) and
|
||||
!(clientPos.z > entity:GetPos().z and math.Distance(clientPos.x, clientPos.y, pos.x, pos.y) < 50)
|
||||
end
|
||||
|
||||
function SWEP:IsHoldingObject()
|
||||
return IsValid(self.heldEntity) and
|
||||
IsValid(self.heldEntity.ixHeldOwner) and
|
||||
self.heldEntity.ixHeldOwner == self:GetOwner()
|
||||
end
|
||||
|
||||
function SWEP:PickupObject(entity)
|
||||
if (self:IsHoldingObject() or
|
||||
!IsValid(entity) or
|
||||
!IsValid(entity:GetPhysicsObject())) then
|
||||
return
|
||||
end
|
||||
|
||||
local physics = entity:GetPhysicsObject()
|
||||
physics:EnableGravity(false)
|
||||
physics:AddGameFlag(FVPHYSICS_PLAYER_HELD)
|
||||
|
||||
entity.ixHeldOwner = self:GetOwner()
|
||||
entity.ixCollisionGroup = entity:GetCollisionGroup()
|
||||
entity:StartMotionController()
|
||||
entity:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
|
||||
self.heldObjectAngle = entity:GetAngles()
|
||||
self.heldEntity = entity
|
||||
|
||||
self.holdEntity = ents.Create("prop_physics")
|
||||
self.holdEntity:SetPos(self.heldEntity:LocalToWorld(self.heldEntity:OBBCenter()))
|
||||
self.holdEntity:SetAngles(self.heldEntity:GetAngles())
|
||||
self.holdEntity:SetModel("models/weapons/w_bugbait.mdl")
|
||||
self.holdEntity:SetOwner(self:GetOwner())
|
||||
|
||||
self.holdEntity:SetNoDraw(true)
|
||||
self.holdEntity:SetNotSolid(true)
|
||||
self.holdEntity:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
self.holdEntity:DrawShadow(false)
|
||||
|
||||
self.holdEntity:Spawn()
|
||||
|
||||
local trace = self:GetOwner():GetEyeTrace()
|
||||
local physicsObject = self.holdEntity:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physicsObject)) then
|
||||
physicsObject:SetMass(2048)
|
||||
physicsObject:SetDamping(0, 1000)
|
||||
physicsObject:EnableGravity(false)
|
||||
physicsObject:EnableCollisions(false)
|
||||
physicsObject:EnableMotion(false)
|
||||
end
|
||||
|
||||
if (trace.Entity:IsRagdoll()) then
|
||||
local tracedEnt = trace.Entity
|
||||
self.holdEntity:SetPos(tracedEnt:GetBonePosition(tracedEnt:TranslatePhysBoneToBone(trace.PhysicsBone)))
|
||||
end
|
||||
|
||||
self.constraint = constraint.Weld(self.holdEntity, self.heldEntity, 0,
|
||||
trace.Entity:IsRagdoll() and trace.PhysicsBone or 0, 0, true, true)
|
||||
end
|
||||
|
||||
function SWEP:DropObject(bThrow)
|
||||
if (!IsValid(self.heldEntity) or self.heldEntity.ixHeldOwner != self:GetOwner()) then
|
||||
return
|
||||
end
|
||||
|
||||
self.lastPlayerAngles = nil
|
||||
self:GetOwner():SetLocalVar("bIsHoldingObject", false)
|
||||
|
||||
self.constraint:Remove()
|
||||
self.holdEntity:Remove()
|
||||
|
||||
self.heldEntity:StopMotionController()
|
||||
self.heldEntity:SetCollisionGroup(self.heldEntity.ixCollisionGroup or COLLISION_GROUP_NONE)
|
||||
|
||||
local physics = self:GetHeldPhysicsObject()
|
||||
physics:EnableGravity(true)
|
||||
physics:Wake()
|
||||
physics:ClearGameFlag(FVPHYSICS_PLAYER_HELD)
|
||||
|
||||
if (bThrow) then
|
||||
timer.Simple(0, function()
|
||||
if (IsValid(physics) and IsValid(self:GetOwner())) then
|
||||
physics:AddGameFlag(FVPHYSICS_WAS_THROWN)
|
||||
physics:ApplyForceCenter(self:GetOwner():GetAimVector() * ix.config.Get("throwForce", 732))
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
self.heldEntity.ixHeldOwner = nil
|
||||
self.heldEntity.ixCollisionGroup = nil
|
||||
self.heldEntity = nil
|
||||
end
|
||||
|
||||
function SWEP:PlayPickupSound(surfaceProperty)
|
||||
local result = "Flesh.ImpactSoft"
|
||||
|
||||
if (surfaceProperty != nil) then
|
||||
local surfaceName = util.GetSurfacePropName(surfaceProperty)
|
||||
local soundName = surfaceName:gsub("^metal$", "SolidMetal") .. ".ImpactSoft"
|
||||
|
||||
if (sound.GetProperties(soundName)) then
|
||||
result = soundName
|
||||
end
|
||||
end
|
||||
|
||||
self:GetOwner():EmitSound(result, 75, 100, 40)
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
if (!IsFirstTimePredicted() or CLIENT) then
|
||||
return
|
||||
end
|
||||
|
||||
self:DropObject()
|
||||
return true
|
||||
end
|
||||
|
||||
function SWEP:OnRemove()
|
||||
if (SERVER) then
|
||||
self:DropObject()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:OwnerChanged()
|
||||
if (SERVER) then
|
||||
self:DropObject()
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:DoPunchAnimation()
|
||||
self.lastHand = math.abs(1 - self.lastHand)
|
||||
|
||||
local sequence = 3 + self.lastHand
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
|
||||
if (IsValid(viewModel)) then
|
||||
viewModel:SetPlaybackRate(0.5)
|
||||
viewModel:SetSequence(sequence)
|
||||
if CLIENT then
|
||||
self.NextAllowedPlayRateChange = CurTime() + viewModel:SequenceDuration() * 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
if (!IsFirstTimePredicted()) then
|
||||
return
|
||||
end
|
||||
|
||||
if (SERVER and self:IsHoldingObject()) then
|
||||
self:DropObject(true)
|
||||
return
|
||||
end
|
||||
|
||||
self:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
|
||||
|
||||
if (hook.Run("CanPlayerThrowPunch", self:GetOwner()) == false) then
|
||||
return
|
||||
end
|
||||
|
||||
if (ix.plugin.Get("stamina")) then
|
||||
local staminaUse = ix.config.Get("punchStamina")
|
||||
|
||||
if (staminaUse > 0) then
|
||||
local value = self:GetOwner():GetLocalVar("stm", 0) - staminaUse
|
||||
|
||||
if (value < 0) then
|
||||
return
|
||||
elseif (SERVER) then
|
||||
self:GetOwner():ConsumeStamina(staminaUse)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
self:GetOwner():EmitSound("npc/vort/claw_swing"..math.random(1, 2)..".wav")
|
||||
end
|
||||
|
||||
self:DoPunchAnimation()
|
||||
|
||||
self:GetOwner():SetAnimation(PLAYER_ATTACK1)
|
||||
self:GetOwner():ViewPunch(Angle(self.lastHand + 2, self.lastHand + 5, 0.125))
|
||||
|
||||
if ix.plugin.Get("vortigaunts") then
|
||||
if (ix.config.Get("pushOnly")) and !self:GetOwner():IsVortigaunt() then
|
||||
local data = {}
|
||||
data.start = self.Owner:GetShootPos()
|
||||
data.endpos = data.start + self.Owner:GetAimVector() * 84
|
||||
data.filter = {self, self.Owner}
|
||||
local trace = util.TraceLine(data)
|
||||
local entity = trace.Entity
|
||||
|
||||
if (entity:IsPlayer() and ix.config.Get("allowPush", true)) then
|
||||
self:PushEntity(entity)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
else
|
||||
if (ix.config.Get("pushOnly")) then
|
||||
local data = {}
|
||||
data.start = self.Owner:GetShootPos()
|
||||
data.endpos = data.start + self.Owner:GetAimVector() * 84
|
||||
data.filter = {self, self.Owner}
|
||||
local trace = util.TraceLine(data)
|
||||
local entity = trace.Entity
|
||||
|
||||
if (entity:IsPlayer() and ix.config.Get("allowPush", true)) then
|
||||
self:PushEntity(entity)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
timer.Simple(0.055, function()
|
||||
if (IsValid(self) and IsValid(self:GetOwner())) then
|
||||
local damage = self.Primary.Damage
|
||||
if ix.plugin.Get("vortigaunts") then
|
||||
if self:GetOwner():IsVortigaunt() then
|
||||
damage = damage + self:GetOwner():GetCharacter():GetSkillLevel("melee")
|
||||
end
|
||||
if (SERVER and self:GetOwner():IsPlayer() and self:GetOwner().GetCharacter and self:GetOwner():GetCharacter() and self:GetOwner():IsVortigaunt()) then
|
||||
self:GetOwner():GetCharacter():DoAction("melee_slash")
|
||||
end
|
||||
end
|
||||
local context = {damage = damage}
|
||||
local result = hook.Run("GetPlayerPunchDamage", self:GetOwner(), damage, context)
|
||||
if (result != nil) then
|
||||
damage = result
|
||||
else
|
||||
damage = context.damage
|
||||
end
|
||||
|
||||
damage = damage * 1.7 --For some reason, punching only does 60% of the damage. 60% * 1.7 = 102%
|
||||
|
||||
if self:GetOwner():IsVortigaunt() and damage > 25 then
|
||||
damage = 30
|
||||
end
|
||||
|
||||
self:GetOwner():LagCompensation(true)
|
||||
local data = {}
|
||||
data.start = self:GetOwner():GetShootPos()
|
||||
data.endpos = data.start + self:GetOwner():GetAimVector() * 96
|
||||
data.filter = self:GetOwner()
|
||||
local trace = util.TraceLine(data)
|
||||
|
||||
if (SERVER and trace.Hit) then
|
||||
local entity = trace.Entity
|
||||
|
||||
if (IsValid(entity)) then
|
||||
if ix.plugin.Get("vortigaunts") then
|
||||
if (self:GetOwner():IsPlayer() and self:GetOwner().GetCharacter and self:GetOwner():GetCharacter() and self:GetOwner():IsVortigaunt()) then
|
||||
self:GetOwner():GetCharacter():DoAction("melee_hit")
|
||||
end
|
||||
end
|
||||
local damageInfo = DamageInfo()
|
||||
damageInfo:SetAttacker(self:GetOwner())
|
||||
damageInfo:SetInflictor(self)
|
||||
damageInfo:SetDamage(damage)
|
||||
damageInfo:SetDamageType(DMG_GENERIC)
|
||||
damageInfo:SetDamagePosition(trace.HitPos)
|
||||
damageInfo:SetDamageForce(self:GetOwner():GetAimVector() * 1024)
|
||||
entity:DispatchTraceAttack(damageInfo, data.start, data.endpos)
|
||||
|
||||
if (entity:IsPlayer()) then
|
||||
ix.log.AddRaw(self:GetOwner():Name() .." has damaged " .. entity:Name() .. ", dealing " .. damage .. " with ix_hands")
|
||||
end
|
||||
|
||||
if (entity:IsNPC()) then
|
||||
ix.log.AddRaw(self:GetOwner():Name() .." has damaged " .. entity:GetClass() .. ", dealing " .. damage .. " with ix_hands")
|
||||
end
|
||||
|
||||
self:GetOwner():EmitSound("physics/body/body_medium_impact_hard"..math.random(1, 6)..".wav", 80)
|
||||
end
|
||||
end
|
||||
hook.Run("PlayerThrowPunch", self:GetOwner(), trace)
|
||||
self:GetOwner():LagCompensation(false)
|
||||
|
||||
if (CLIENT and trace.Hit) then
|
||||
local entity = trace.Entity
|
||||
--This is kind of redundant
|
||||
--if (entity:IsPlayer() and IsValid(entity)) then
|
||||
-- chat.AddText(Color(217, 83, 83), "You have damaged " .. entity:Name() .. ", dealing " .. damage .. " points of damage.")
|
||||
--end
|
||||
|
||||
--if (entity:IsNPC()) then
|
||||
-- chat.AddText(Color(217, 83, 83), "You have damaged " .. entity:GetClass() .. ", dealing " .. damage .. " points of damage.")
|
||||
--end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
if (!IsFirstTimePredicted()) then
|
||||
return
|
||||
end
|
||||
|
||||
local data = {}
|
||||
data.start = self:GetOwner():GetShootPos()
|
||||
data.endpos = data.start + self:GetOwner():GetAimVector() * 84
|
||||
data.filter = {self, self:GetOwner()}
|
||||
local trace = util.TraceLine(data)
|
||||
local entity = trace.Entity
|
||||
|
||||
if CLIENT then
|
||||
local viewModel = self:GetOwner():GetViewModel()
|
||||
|
||||
if (IsValid(viewModel)) then
|
||||
viewModel:SetPlaybackRate(0.5)
|
||||
if CLIENT then
|
||||
self.NextAllowedPlayRateChange = CurTime() + viewModel:SequenceDuration() * 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (SERVER and IsValid(entity)) then
|
||||
if (entity:IsDoor()) then
|
||||
if (hook.Run("CanPlayerKnock", self:GetOwner(), entity) == false) then
|
||||
return
|
||||
end
|
||||
|
||||
self:GetOwner():ViewPunch(self.KnockViewPunchAngle)
|
||||
self:GetOwner():EmitSound("physics/wood/wood_crate_impact_hard"..math.random(2, 3)..".wav")
|
||||
self:GetOwner():SetAnimation(PLAYER_ATTACK1)
|
||||
|
||||
self:DoPunchAnimation()
|
||||
self:SetNextSecondaryFire(CurTime() + 0.4)
|
||||
self:SetNextPrimaryFire(CurTime() + 1)
|
||||
elseif (entity:IsPlayer() and ix.config.Get("allowPush", true)) then
|
||||
self:PushEntity(entity)
|
||||
elseif (!entity:IsNPC() and self:CanHoldObject(entity)) then
|
||||
self:GetOwner():SetLocalVar("bIsHoldingObject", true)
|
||||
self:PickupObject(entity)
|
||||
self:PlayPickupSound(trace.SurfaceProps)
|
||||
self:SetNextSecondaryFire(CurTime() + self.Secondary.Delay)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:PushEntity(entity)
|
||||
local curTime = CurTime()
|
||||
local direction = self.Owner:GetAimVector() * (300 + (self.Owner:GetCharacter():GetAttribute("str", 0) * 3))
|
||||
direction.z = 0
|
||||
entity:SetVelocity(direction)
|
||||
|
||||
self.Owner:EmitSound("physics/flesh/flesh_impact_hard"..math.random(1, 6)..".wav")
|
||||
self:SetNextSecondaryFire(curTime + 1.5)
|
||||
self:SetNextPrimaryFire(curTime + 1.5)
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
if (!IsFirstTimePredicted()) then
|
||||
return
|
||||
end
|
||||
|
||||
if (SERVER and IsValid(self.heldEntity)) then
|
||||
self:DropObject()
|
||||
end
|
||||
end
|
||||
60
gamemodes/helix/gamemode/cl_init.lua
Normal file
60
gamemodes/helix/gamemode/cl_init.lua
Normal file
@@ -0,0 +1,60 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- unix systems are case-sensitive, are missing fonts, or use different naming conventions
|
||||
if (!system.IsWindows()) then
|
||||
local fontOverrides = {
|
||||
["Roboto"] = "Roboto Regular",
|
||||
["Roboto Th"] = "Roboto Thin",
|
||||
["Roboto Lt"] = "Roboto Light",
|
||||
["Roboto Bk"] = "Roboto Black",
|
||||
["coolvetica"] = "Coolvetica",
|
||||
["tahoma"] = "Tahoma",
|
||||
["Harmonia Sans Pro Cyr"] = "Roboto Regular",
|
||||
["Harmonia Sans Pro Cyr Light"] = "Roboto Light",
|
||||
["Century Gothic"] = "Roboto Regular"
|
||||
}
|
||||
|
||||
if (system.IsOSX()) then
|
||||
fontOverrides["Consolas"] = "Monaco"
|
||||
else
|
||||
fontOverrides["Consolas"] = "Courier New"
|
||||
end
|
||||
|
||||
local ixCreateFont = surface.CreateFont
|
||||
|
||||
function surface.CreateFont(name, info) -- luacheck: globals surface
|
||||
local font = info.font
|
||||
|
||||
if (font and fontOverrides[font]) then
|
||||
info.font = fontOverrides[font]
|
||||
end
|
||||
|
||||
ixCreateFont(name, info)
|
||||
end
|
||||
end
|
||||
|
||||
DeriveGamemode("sandbox")
|
||||
ix = ix or {util = {}, gui = {}, meta = {}}
|
||||
|
||||
-- Include core files.
|
||||
include("core/sh_util.lua")
|
||||
include("core/sh_data.lua")
|
||||
include("shared.lua")
|
||||
|
||||
-- Sandbox stuff
|
||||
CreateConVar("cl_weaponcolor", "0.30 1.80 2.10", {
|
||||
FCVAR_ARCHIVE, FCVAR_USERINFO, FCVAR_DONTRECORD
|
||||
}, "The value is a Vector - so between 0-1 - not between 0-255")
|
||||
|
||||
timer.Remove("HintSystem_OpeningMenu")
|
||||
timer.Remove("HintSystem_Annoy1")
|
||||
timer.Remove("HintSystem_Annoy2")
|
||||
244
gamemodes/helix/gamemode/config/sh_config.lua
Normal file
244
gamemodes/helix/gamemode/config/sh_config.lua
Normal file
@@ -0,0 +1,244 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
-- You can change the default language by setting this in your schema.
|
||||
ix.config.language = "english"
|
||||
|
||||
--[[
|
||||
DO NOT CHANGE ANYTHING BELOW THIS.
|
||||
|
||||
This is the Helix main configuration file.
|
||||
This file DOES NOT set any configurations, instead it just prepares them.
|
||||
To set the configuration, there is a "Config" tab in the F1 menu for super admins and above.
|
||||
Use the menu to change the variables, not this file.
|
||||
--]]
|
||||
|
||||
ix.config.Add("maxCharacters", 5, "The maximum number of characters a player can have.", nil, {
|
||||
data = {min = 1, max = 50},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("color", Color(75, 119, 190, 255), "The main color theme for the framework.", function(oldValue, newValue)
|
||||
if (newValue.a != 255) then
|
||||
ix.config.Set("color", ColorAlpha(newValue, 255))
|
||||
return
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
hook.Run("ColorSchemeChanged", newValue)
|
||||
end
|
||||
end, {category = "appearance"})
|
||||
ix.config.Add("font", "Roboto Th", "The font used to display titles.", function(oldValue, newValue)
|
||||
if (CLIENT) then
|
||||
hook.Run("LoadFonts", newValue, ix.config.Get("genericFont"))
|
||||
end
|
||||
end, {category = "appearance"})
|
||||
|
||||
ix.config.Add("genericFont", "Roboto", "The font used to display generic texts.", function(oldValue, newValue)
|
||||
if (CLIENT) then
|
||||
hook.Run("LoadFonts", ix.config.Get("font"), newValue)
|
||||
end
|
||||
end, {category = "appearance"})
|
||||
|
||||
ix.config.Add("maxAttributes", 100, "The maximum amount each attribute can be.", nil, {
|
||||
data = {min = 0, max = 100},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("chatAutoFormat", true, "Whether or not to automatically capitalize and punctuate in-character text.", nil, {
|
||||
category = "Chat"
|
||||
})
|
||||
ix.config.Add("chatRange", 280, "The maximum distance a person's IC chat message goes to.", nil, {
|
||||
data = {min = 10, max = 5000, decimals = 1},
|
||||
category = "chat"
|
||||
})
|
||||
ix.config.Add("chatMax", 256, "The maximum amount of characters that can be sent in chat.", nil, {
|
||||
data = {min = 32, max = 1024},
|
||||
category = "chat"
|
||||
})
|
||||
ix.config.Add("chatColor", Color(255, 255, 150), "The default color for IC chat.", nil, {category = "chat"})
|
||||
ix.config.Add("chatListenColor", Color(175, 255, 150), "The color for IC chat if you are looking at the speaker.", nil, {
|
||||
category = "chat"
|
||||
})
|
||||
ix.config.Add("oocDelay", 10, "The delay before a player can use OOC chat again in seconds.", nil, {
|
||||
data = {min = 0, max = 10000},
|
||||
category = "chat"
|
||||
})
|
||||
ix.config.Add("allowGlobalOOC", true, "Whether or not Global OOC is enabled.", nil, {
|
||||
category = "chat"
|
||||
})
|
||||
ix.config.Add("loocDelay", 0, "The delay before a player can use LOOC chat again in seconds.", nil, {
|
||||
data = {min = 0, max = 10000},
|
||||
category = "chat"
|
||||
})
|
||||
ix.config.Add("spawnTime", 5, "The time it takes to respawn.", nil, {
|
||||
data = {min = 0, max = 10000},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("inventoryWidth", 6, "How many slots in a row there is in a default inventory.", nil, {
|
||||
data = {min = 0, max = 20},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("inventoryHeight", 4, "How many slots in a column there is in a default inventory.", nil, {
|
||||
data = {min = 0, max = 20},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("minNameLength", 4, "The minimum number of characters in a name.", nil, {
|
||||
data = {min = 4, max = 64},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("maxNameLength", 32, "The maximum number of characters in a name.", nil, {
|
||||
data = {min = 16, max = 128},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("minDescriptionLength", 16, "The minimum number of characters in a description.", nil, {
|
||||
data = {min = 0, max = 300},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("descriptionDisplayLength", 256,
|
||||
"The amount of characters of a description that will be displayed when someone look at the player.", nil, {
|
||||
data = {min = 64, max = 2048},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("saveInterval", 300, "How often characters save in seconds.", nil, {
|
||||
data = {min = 60, max = 3600},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("walkSpeed", 130, "How fast a player normally walks.", function(oldValue, newValue)
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
v:SetWalkSpeed(newValue)
|
||||
end
|
||||
end, {
|
||||
data = {min = 75, max = 500},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("runSpeed", 235, "How fast a player normally runs.", function(oldValue, newValue)
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
v:SetRunSpeed(newValue)
|
||||
end
|
||||
end, {
|
||||
data = {min = 75, max = 500},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("walkRatio", 0.5, "How fast one goes when holding ALT.", nil, {
|
||||
data = {min = 0, max = 1, decimals = 1},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("jumpPower", 200, "How much force is behind ones jump.", function(oldValue, newValue)
|
||||
for _, v in ipairs(player.GetAll()) do
|
||||
v:SetJumpPower(newValue)
|
||||
end
|
||||
end, {
|
||||
data = {min = 100, max = 400},
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("intro", true, "Whether or not the Helix intro is enabled for new players.", nil, {
|
||||
category = "appearance"
|
||||
})
|
||||
ix.config.Add("music", "music/hl2_song2.mp3", "The default music played in the character menu.", nil, {
|
||||
category = "appearance"
|
||||
})
|
||||
ix.config.Add("communityURL",
|
||||
"https://willard.network/forums/",
|
||||
"The URL to navigate to when the community button is clicked.", nil, {
|
||||
category = "appearance"
|
||||
})
|
||||
ix.config.Add("communityText", "@community",
|
||||
"The text to display on the community button. You can use language phrases by prefixing with @", nil, {
|
||||
category = "appearance"
|
||||
})
|
||||
ix.config.Add("vignette", true, "Whether or not the vignette is shown.", nil, {
|
||||
category = "appearance"
|
||||
})
|
||||
ix.config.Add("scoreboardRecognition", false, "Whether or not recognition is used in the scoreboard.", nil, {
|
||||
category = "characters"
|
||||
})
|
||||
ix.config.Add("defaultMoney", 0, "The amount of money that players start with.", nil, {
|
||||
category = "characters",
|
||||
data = {min = 0, max = 1000}
|
||||
})
|
||||
ix.config.Add("allowVoice", false, "Whether or not voice chat is allowed.", function(oldValue, newValue)
|
||||
if (SERVER) then
|
||||
hook.Run("VoiceToggled", newValue)
|
||||
end
|
||||
end, {
|
||||
category = "server"
|
||||
})
|
||||
ix.config.Add("voiceDistance", 600.0, "How far can the voice be heard.", function(oldValue, newValue)
|
||||
if (SERVER) then
|
||||
hook.Run("VoiceDistanceChanged", newValue)
|
||||
end
|
||||
end, {
|
||||
category = "server",
|
||||
data = {min = 0, max = 5000, decimals = 1}
|
||||
})
|
||||
ix.config.Add("weaponAlwaysRaised", false, "Whether or not weapons are always raised.", nil, {
|
||||
category = "server"
|
||||
})
|
||||
ix.config.Add("weaponRaiseTime", 1, "The time it takes for a weapon to raise.", nil, {
|
||||
data = {min = 0.1, max = 60, decimals = 1},
|
||||
category = "server"
|
||||
})
|
||||
ix.config.Add("maxHoldWeight", 100, "The maximum weight that a player can carry in their hands.", nil, {
|
||||
data = {min = 1, max = 500},
|
||||
category = "interaction"
|
||||
})
|
||||
ix.config.Add("throwForce", 732, "How hard a player can throw the item that they're holding.", nil, {
|
||||
data = {min = 0, max = 8192},
|
||||
category = "interaction"
|
||||
})
|
||||
ix.config.Add("allowPush", true, "Whether or not pushing with hands is allowed.", nil, {
|
||||
category = "interaction"
|
||||
})
|
||||
ix.config.Add("pushOnly", false, "Whether or not punch damage is enabled.", nil, {
|
||||
category = "interaction"
|
||||
})
|
||||
ix.config.Add("itemPickupTime", 0.5, "How long it takes to pick up and put an item in your inventory.", nil, {
|
||||
data = {min = 0, max = 5, decimals = 1},
|
||||
category = "interaction"
|
||||
})
|
||||
ix.config.Add("year", 2015, "The current in-game year.", function(oldValue, newValue)
|
||||
if (SERVER and !ix.date.bSaving) then
|
||||
ix.date.ResolveOffset()
|
||||
ix.date.current:setyear(newValue)
|
||||
ix.date.Send()
|
||||
end
|
||||
end, {
|
||||
data = {min = 1, max = 9999},
|
||||
category = "date"
|
||||
})
|
||||
ix.config.Add("month", 1, "The current in-game month.", function(oldValue, newValue)
|
||||
if (SERVER and !ix.date.bSaving) then
|
||||
ix.date.ResolveOffset()
|
||||
ix.date.current:setmonth(newValue)
|
||||
ix.date.Send()
|
||||
end
|
||||
end, {
|
||||
data = {min = 1, max = 12},
|
||||
category = "date"
|
||||
})
|
||||
ix.config.Add("day", 1, "The current in-game day.", function(oldValue, newValue)
|
||||
if (SERVER and !ix.date.bSaving) then
|
||||
ix.date.ResolveOffset()
|
||||
ix.date.current:setday(newValue)
|
||||
ix.date.Send()
|
||||
end
|
||||
end, {
|
||||
data = {min = 1, max = 31},
|
||||
category = "date"
|
||||
})
|
||||
ix.config.Add("secondsPerMinute", 60, "How many seconds it takes for a minute to pass in-game.", function(oldValue, newValue)
|
||||
if (SERVER and !ix.date.bSaving) then
|
||||
ix.date.UpdateTimescale(newValue)
|
||||
ix.date.Send()
|
||||
end
|
||||
end, {
|
||||
data = {min = 0.01, max = 120},
|
||||
category = "date"
|
||||
})
|
||||
75
gamemodes/helix/gamemode/config/sh_options.lua
Normal file
75
gamemodes/helix/gamemode/config/sh_options.lua
Normal file
@@ -0,0 +1,75 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
if (CLIENT) then
|
||||
ix.option.Add("animationScale", ix.type.number, 1, {
|
||||
category = "appearance", min = 0.3, max = 2, decimals = 1
|
||||
})
|
||||
|
||||
ix.option.Add("24hourTime", ix.type.bool, false, {
|
||||
category = "appearance"
|
||||
})
|
||||
|
||||
ix.option.Add("altLower", ix.type.bool, true, {
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.option.Add("alwaysShowBars", ix.type.bool, false, {
|
||||
category = "appearance"
|
||||
})
|
||||
|
||||
ix.option.Add("noticeDuration", ix.type.number, 8, {
|
||||
category = "appearance", min = 0.1, max = 20, decimals = 1
|
||||
})
|
||||
|
||||
ix.option.Add("noticeMax", ix.type.number, 4, {
|
||||
category = "appearance", min = 1, max = 20
|
||||
})
|
||||
|
||||
ix.option.Add("cheapBlur", ix.type.bool, false, {
|
||||
category = "performance"
|
||||
})
|
||||
|
||||
ix.option.Add("disableAnimations", ix.type.bool, false, {
|
||||
category = "performance"
|
||||
})
|
||||
|
||||
ix.option.Add("openBags", ix.type.bool, true, {
|
||||
category = "general"
|
||||
})
|
||||
|
||||
ix.option.Add("showIntro", ix.type.bool, true, {
|
||||
category = "general"
|
||||
})
|
||||
end
|
||||
|
||||
ix.option.Add("language", ix.type.array, ix.config.language or "english", {
|
||||
category = "general",
|
||||
bNetworked = true,
|
||||
populate = function()
|
||||
local entries = {}
|
||||
|
||||
for k, _ in SortedPairs(ix.lang.stored) do
|
||||
local name = ix.lang.names[k]
|
||||
local name2 = k:utf8sub(1, 1):utf8upper() .. k:utf8sub(2)
|
||||
|
||||
if (name) then
|
||||
name = name .. " (" .. name2 .. ")"
|
||||
else
|
||||
name = name2
|
||||
end
|
||||
|
||||
entries[k] = name
|
||||
end
|
||||
|
||||
return entries
|
||||
end
|
||||
})
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user