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
|
||||
21
gamemodes/darkrp/LICENSE
Normal file
21
gamemodes/darkrp/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 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.
|
||||
45
gamemodes/darkrp/README.md
Normal file
45
gamemodes/darkrp/README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
Willard Networks - WN:IX
|
||||
A unique HL2RP schema built by the WN team
|
||||
|
||||
Copyright Atko 2023
|
||||
All Rights Reserved
|
||||
|
||||
# Code Style
|
||||
* General coding style
|
||||
* Use tab-indentation with tab-width set to 4 spaces!
|
||||
* Use 'and' and 'or', rather than '&&' or '||'. For negation the '!' is used over 'not'
|
||||
* We use 'if (condition) then' for spacing, as well as 'func(arg1, arg2, arg3, ...)'. Arrays use array[index], except for double indexing in which case spaces get added array1[ array2[index] ] (to prevent [[ and ]] from forming long strings or comments)
|
||||
* String concatenation is done without spacing like.."this".."."
|
||||
* " " has the preference for strings, although ' ' can be used if your string contains a ". [[ ]] can be used for multiline strings, or strings that contain both " and '
|
||||
* Unused loop variables or return variables are assigned to '\_' to indicate they are unused
|
||||
* Variable and data fields
|
||||
* Local vars use lower camel case (lowerCamelCase)
|
||||
* Functions are upper camel case (UpperCamelCase). Local function vars use lower camel case (as per local var casing)
|
||||
* Enums are in all caps, with underscores for spacing. This also counts if you make enum fields on a table (e.g. PLUGIN.MAX_VAR)
|
||||
* Strings for internal use should be UpperCamelCase (data fields, net messages, ...). If some sort of identifiying prefix is used, lower camel casing is used (e.g. ixSendData, cmdCharSetHealth, ...)
|
||||
* Try to give loop variables sensible names over k, v. E.g. 'for character, data in pairs(list) do', which creates much more readable code than 'for k, v in pairs(list) do'
|
||||
* Avoid using variable names that overwrite library names.
|
||||
* 'player' is generally replaced with 'client'
|
||||
* 'table' should use something more descriptive, or 'tbl' if you really got nothing
|
||||
* 'string' can use 'text' or 'str'
|
||||
* Optimization
|
||||
* Avoid creating and using global variables, the access time on them is extremely slow. The easiest workaround is to localize the variable at the top of the file (if it is a table, the variable will still update as tables are stored by reference rather than by value). Libraries (e.g. ix, math, string, ...) can also be localized like this, and is typically done if you absolutely need to squeeze out performance from some bit of code that will run a lot.
|
||||
* Avoid using Think, Tick, etc. server-side. Basically any hook that gets called every frame (or even worse: every frame for every player) unless there is absolutely no way around it. A lot of stuff doesn't need to check every frame, but is fine if it checks every 0.5/1/2/... seconds. Use timers for this!
|
||||
* If you must use Think-like hooks or have another performance critical bit of code:
|
||||
* Keep it short, shorter code usually is more optimized
|
||||
* Localize everything in it
|
||||
* Avoid loops, make loops as small as possible. If you need to loop over a table to search one entry, you may need to rethink your table structure. E.g. looping over a table of all players is slower than looking up a player by SteamID (table[client:SteamID64()]).
|
||||
* 'for i = 1, x do' is faster than 'for k, v in ipairs', which is faster than 'for k, v in pairs'
|
||||
* Making tables is expensive compared to clearing out a small table. Array indexing (table[1]) is faster than hashmap lookups (table.x)
|
||||
* Square roots (sqrt, Distance) and geometry functions (cos, acos, sin, asin, tan, ...) are SLOOOOW (compared to e.g. multiplication)! Avoid them in performance-critical code. Distance can often be replaced by DistToSqr (squared distance) when the goal is simple comparisons to avoid taking a square root (don't forget to square the other side of the comparison). E.g. 'x:Distance(y) > 100' becomes 'x:DistToSqr(y) > 100 * 100'
|
||||
* Creating functions during runtime is SLOOOOOOOOOOOOOOW, but sometimes needed. Just avoid this happening in code that runs often/regularly. Try to limit it to e.g. character load, or when a player does a certain action. If possible, use a function created during compile and pass the needed arguments via varargs.
|
||||
* Helix-specific stuff
|
||||
* Use ix.log.AddType and ix.log.Add rather than ix.log.AddRaw. This creates a category that can be used with our log searching tool, and stores some extra searchable meta-data as well (client, arguments passed, location, ...)
|
||||
* Categorize your logtypes by proceeding the type with the plugin name or some other descriptive prefix. This facilitates selecting it from the giant dropdown menu in the logsearch tool. E.g. medicalBleedout, itemPickup, ...
|
||||
* Try to use localized text (via e.g. L(), NotifyLocalized, ...) and define a translation table in your plugin via ix.lang.AddTable. This makes life for our Russian friends a lot easier.
|
||||
* Server-side only code always should be in an sv_file! This counts double for net hooks, security checks, etc. Any half-decent hacker will read your cl_ and sh_ files to find exploits, do not make their life easier. It is also harder to steal our code if they do not have the server-side code.
|
||||
|
||||
## Using the Linter in your IDE
|
||||
See instructions [here](https://github.com/mpeterv/luacheck#editor-support).
|
||||
|
||||
For visual studio, simply downloading the vscode-luacheck plugin should be enough with no additional configuration required.
|
||||
8
gamemodes/darkrp/darkrp.txt
Normal file
8
gamemodes/darkrp/darkrp.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
"ixhl2rp"
|
||||
{
|
||||
"base" "helix"
|
||||
"title" "darkrp"
|
||||
"author" "willard.network"
|
||||
"category" "rp"
|
||||
"menusystem" "1"
|
||||
}
|
||||
245
gamemodes/darkrp/entities/entities/ix_combinelock.lua
Normal file
245
gamemodes/darkrp/entities/entities/ix_combinelock.lua
Normal file
@@ -0,0 +1,245 @@
|
||||
--[[
|
||||
| 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 = "Combine Lock"
|
||||
ENT.Category = "HL2 RP"
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminOnly = true
|
||||
ENT.PhysgunDisable = true
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "Locked")
|
||||
self:NetworkVar("Bool", 1, "DisplayError")
|
||||
self:NetworkVar("Bool", 2, "Disabled")
|
||||
|
||||
if (SERVER) then
|
||||
self:NetworkVarNotify("Locked", self.OnLockChanged)
|
||||
end
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
function ENT:GetLockPosition(door, normal)
|
||||
local index = door:LookupBone("handle")
|
||||
local position = door:GetPos()
|
||||
normal = normal or door:GetForward():Angle()
|
||||
|
||||
if (index and index >= 1) then
|
||||
position = door:GetBonePosition(index)
|
||||
end
|
||||
|
||||
position = position + normal:Forward() * 7.2 + normal:Up() * 10 + normal:Right() * 2
|
||||
|
||||
normal:RotateAroundAxis(normal:Up(), 90)
|
||||
normal:RotateAroundAxis(normal:Forward(), 180)
|
||||
normal:RotateAroundAxis(normal:Right(), 180)
|
||||
|
||||
return position, normal
|
||||
end
|
||||
|
||||
function ENT:SetDoor(door, position, angles)
|
||||
if (!IsValid(door) or !door:IsDoor()) then
|
||||
return
|
||||
end
|
||||
|
||||
local doorPartner = door:GetDoorPartner()
|
||||
|
||||
self.door = door
|
||||
self.door:DeleteOnRemove(self)
|
||||
door.ixLock = self
|
||||
|
||||
if (IsValid(doorPartner)) then
|
||||
self.doorPartner = doorPartner
|
||||
self.doorPartner:DeleteOnRemove(self)
|
||||
doorPartner.ixLock = self
|
||||
end
|
||||
|
||||
self:SetPos(position)
|
||||
self:SetAngles(angles)
|
||||
self:SetParent(door)
|
||||
end
|
||||
|
||||
function ENT:SpawnFunction(client, trace)
|
||||
local door = trace.Entity
|
||||
|
||||
if (!IsValid(door) or !door:IsDoor() or IsValid(door.ixLock)) then
|
||||
return client:NotifyLocalized("dNotValid")
|
||||
end
|
||||
|
||||
local normal = client:GetEyeTrace().HitNormal:Angle()
|
||||
local position, angles = self:GetLockPosition(door, normal)
|
||||
|
||||
local entity = ents.Create("ix_combinelock")
|
||||
entity:SetPos(trace.HitPos)
|
||||
entity:Spawn()
|
||||
entity:Activate()
|
||||
entity:SetDoor(door, position, angles)
|
||||
|
||||
ix.saveEnts:SaveEntity(entity)
|
||||
Schema:SaveCombineLocks()
|
||||
return entity
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/willardnetworks/props_combine/wn_combine_lock.mdl")
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:SetHealth(300)
|
||||
|
||||
self.nextUseTime = 0
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (IsValid(self)) then
|
||||
self:SetParent(nil)
|
||||
end
|
||||
|
||||
if (IsValid(self.door)) then
|
||||
self.door:Fire("unlock")
|
||||
self.door.ixLock = nil
|
||||
end
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
self.doorPartner.ixLock = nil
|
||||
end
|
||||
|
||||
if (!ix.shuttingDown) then
|
||||
Schema:SaveCombineLocks()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnLockChanged(name, bWasLocked, bLocked)
|
||||
if (!IsValid(self.door) or self:GetDisabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
ix.saveEnts:SaveEntity(self)
|
||||
if (bLocked) then
|
||||
self:EmitSound("buttons/combine_button2.wav")
|
||||
self.door:Fire("lock")
|
||||
self.door:Fire("close")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("lock")
|
||||
self.doorPartner:Fire("close")
|
||||
end
|
||||
else
|
||||
self:EmitSound("buttons/combine_button7.wav")
|
||||
self.door:Fire("unlock")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DisplayError()
|
||||
self:EmitSound("buttons/combine_button_locked.wav")
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:DisplayDamage()
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:Toggle(client)
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
if (self.nextUseTime > CurTime()) then
|
||||
return
|
||||
end
|
||||
|
||||
if (!Schema:CanPlayerOpenCombineLock(client, self)) then
|
||||
self:DisplayError()
|
||||
self.nextUseTime = CurTime() + 2
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
self:SetLocked(!self:GetLocked())
|
||||
self.nextUseTime = CurTime() + 2
|
||||
end
|
||||
|
||||
function ENT:Use(client)
|
||||
self:Toggle(client)
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmgInfo)
|
||||
self:SetHealth(self:Health() - dmgInfo:GetDamage())
|
||||
self:EmitSound("physics/metal/metal_sheet_impact_hard"..math.random(6, 8)..".wav")
|
||||
self:DisplayDamage()
|
||||
|
||||
if (self:Health() <= 0) then
|
||||
local pos = self:GetPos()
|
||||
local curTime = CurTime()
|
||||
|
||||
if (!self.nextSpark or self.nextSpark <= curTime) then
|
||||
local effect = EffectData()
|
||||
effect:SetStart(pos)
|
||||
effect:SetOrigin(pos)
|
||||
effect:SetScale(2)
|
||||
util.Effect("cball_explode", effect)
|
||||
|
||||
self.nextSpark = curTime + 0.1
|
||||
end
|
||||
|
||||
local attacker = dmgInfo:GetAttacker()
|
||||
|
||||
self:EmitSound("npc/manhack/gib.wav")
|
||||
ix.combineNotify:AddImportantNotification("WRN:// Bio-Restrictor failure", nil, attacker:IsPlayer() and attacker, self:GetPos())
|
||||
ix.item.Spawn("trash_biolock", Vector(self:GetPos().x, self:GetPos().y, self:GetPos().z))
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
else
|
||||
local glowMaterial = ix.util.GetMaterial("sprites/glow04_noz")
|
||||
local color_green = Color(0, 255, 0, 255)
|
||||
local color_blue = Color(52, 73, 94, 255)
|
||||
local color_red = Color(255, 50, 50, 255)
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
local color = color_green
|
||||
|
||||
if (self:GetDisplayError()) then
|
||||
color = color_red
|
||||
elseif (self:GetLocked()) then
|
||||
color = color_blue
|
||||
end
|
||||
|
||||
local position = self:GetPos() + self:GetUp() * -8.7 + self:GetForward() * -3.85 + self:GetRight() * -6
|
||||
|
||||
render.SetMaterial(glowMaterial)
|
||||
render.DrawSprite(position, 10, 10, color)
|
||||
end
|
||||
end
|
||||
295
gamemodes/darkrp/entities/entities/ix_combinelock_cmru.lua
Normal file
295
gamemodes/darkrp/entities/entities/ix_combinelock_cmru.lua
Normal file
@@ -0,0 +1,295 @@
|
||||
--[[
|
||||
| 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 = "Combine Lock (CMRU)"
|
||||
ENT.Category = "HL2 RP"
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminOnly = true
|
||||
ENT.PhysgunDisable = true
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "Locked")
|
||||
self:NetworkVar("Bool", 1, "DisplayError")
|
||||
self:NetworkVar("Bool", 2, "Disabled")
|
||||
|
||||
if (SERVER) then
|
||||
self:NetworkVarNotify("Locked", self.OnLockChanged)
|
||||
end
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
function ENT:GetLockPosition(door, normal)
|
||||
local index = door:LookupBone("handle")
|
||||
local position = door:GetPos()
|
||||
normal = normal or door:GetForward():Angle()
|
||||
|
||||
if (index and index >= 1) then
|
||||
position = door:GetBonePosition(index)
|
||||
end
|
||||
|
||||
position = position + normal:Forward() * 7.2 + normal:Up() * 10 + normal:Right() * 2
|
||||
|
||||
normal:RotateAroundAxis(normal:Up(), 90)
|
||||
normal:RotateAroundAxis(normal:Forward(), 180)
|
||||
normal:RotateAroundAxis(normal:Right(), 180)
|
||||
|
||||
return position, normal
|
||||
end
|
||||
|
||||
function ENT:SetDoor(door, position, angles)
|
||||
if (!IsValid(door) or !door:IsDoor()) then
|
||||
return
|
||||
end
|
||||
|
||||
local doorPartner = door:GetDoorPartner()
|
||||
|
||||
self.door = door
|
||||
self.door:DeleteOnRemove(self)
|
||||
door.ixLock = self
|
||||
|
||||
if (IsValid(doorPartner)) then
|
||||
self.doorPartner = doorPartner
|
||||
self.doorPartner:DeleteOnRemove(self)
|
||||
doorPartner.ixLock = self
|
||||
end
|
||||
|
||||
self:SetPos(position)
|
||||
self:SetAngles(angles)
|
||||
self:SetParent(door)
|
||||
end
|
||||
|
||||
function ENT:SpawnFunction(client, trace)
|
||||
local door = trace.Entity
|
||||
|
||||
if (!IsValid(door) or !door:IsDoor() or IsValid(door.ixLock)) then
|
||||
return client:NotifyLocalized("dNotValid")
|
||||
end
|
||||
|
||||
local normal = client:GetEyeTrace().HitNormal:Angle()
|
||||
local position, angles = self:GetLockPosition(door, normal)
|
||||
|
||||
local entity = ents.Create("ix_combinelock_cmru")
|
||||
entity:SetPos(trace.HitPos)
|
||||
entity:Spawn()
|
||||
entity:Activate()
|
||||
entity:SetDoor(door, position, angles)
|
||||
|
||||
ix.saveEnts:SaveEntity(entity)
|
||||
Schema:SaveCombineLocks()
|
||||
return entity
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/willardnetworks/props_combine/wn_combine_lock.mdl")
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:SetHealth(300)
|
||||
|
||||
self.accessLevel = 1
|
||||
self.nextUseTime = 0
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (IsValid(self)) then
|
||||
self:SetParent(nil)
|
||||
end
|
||||
|
||||
if (IsValid(self.door)) then
|
||||
self.door:Fire("unlock")
|
||||
self.door.ixLock = nil
|
||||
end
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
self.doorPartner.ixLock = nil
|
||||
end
|
||||
|
||||
if (!ix.shuttingDown) then
|
||||
Schema:SaveCombineLocks()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnLockChanged(name, bWasLocked, bLocked)
|
||||
if (!IsValid(self.door) or self:GetDisabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
ix.saveEnts:SaveEntity(self)
|
||||
if (bLocked) then
|
||||
self:EmitSound("buttons/combine_button2.wav")
|
||||
self.door:Fire("lock")
|
||||
self.door:Fire("close")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("lock")
|
||||
self.doorPartner:Fire("close")
|
||||
end
|
||||
else
|
||||
self:EmitSound("buttons/combine_button7.wav")
|
||||
self.door:Fire("unlock")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DisplayError()
|
||||
self:EmitSound("buttons/combine_button_locked.wav")
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:DisplayDamage()
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:Toggle(client)
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
if (self.nextUseTime > CurTime()) then
|
||||
return
|
||||
end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
local items = character:GetInventory():GetItems()
|
||||
local cmruCards = {}
|
||||
|
||||
for _, item in pairs(items) do
|
||||
if (item.uniqueID == "cmru_card" and item:GetData("cardID")) then
|
||||
cmruCards[#cmruCards + 1] = item
|
||||
end
|
||||
end
|
||||
|
||||
local canOpen = false
|
||||
for _, card in pairs(cmruCards) do
|
||||
-- access level 5 should open all doors. access level 3 should open only 3, 2, and 1 doors, etc
|
||||
if (items[card:GetData("cardID")] and (card:GetData("accessLevel", 1) >= self.accessLevel)) then
|
||||
canOpen = true
|
||||
end
|
||||
end
|
||||
|
||||
if (!Schema:CanPlayerOpenCombineLock(client, self) and !canOpen) then
|
||||
self:DisplayError()
|
||||
self.nextUseTime = CurTime() + 2
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
self:SetLocked(!self:GetLocked())
|
||||
|
||||
self.nextUseTime = CurTime() + 2
|
||||
end
|
||||
|
||||
function ENT:Use(client)
|
||||
if (client:KeyDown(IN_SPEED) and (client:Team() == FACTION_ADMIN or client:Team() == FACTION_SERVERADMIN or client:IsCombine() or client:GetCharacter():HasFlags("M"))) then
|
||||
net.Start("changeLockAccessCmru")
|
||||
net.WriteEntity(self)
|
||||
net.Send(client)
|
||||
else
|
||||
self:Toggle(client)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnOptionSelected(client, option, data)
|
||||
if (option == "Set Level 1 Access") then
|
||||
self.accessLevel = 1
|
||||
|
||||
client:Notify("You have set Level 1 Access to this lock.")
|
||||
elseif (option == "Set Level 2 Access") then
|
||||
self.accessLevel = 2
|
||||
|
||||
client:Notify("You have set Level 2 Access to this lock.")
|
||||
elseif (option == "Set Level 3 Access") then
|
||||
self.accessLevel = 3
|
||||
|
||||
client:Notify("You have set Level 3 Access to this lock.")
|
||||
elseif (option == "Set Level 4 Access") then
|
||||
self.accessLevel = 4
|
||||
|
||||
client:Notify("You have set Level 4 Access to this lock.")
|
||||
elseif (option == "Set Level 5 Access") then
|
||||
self.accessLevel = 5
|
||||
|
||||
client:Notify("You have set Level 5 Access to this lock.")
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmgInfo)
|
||||
self:SetHealth(self:Health() - dmgInfo:GetDamage())
|
||||
self:EmitSound("physics/metal/metal_sheet_impact_hard"..math.random(6, 8)..".wav")
|
||||
self:DisplayDamage()
|
||||
|
||||
if (self:Health() <= 0) then
|
||||
local pos = self:GetPos()
|
||||
local curTime = CurTime()
|
||||
|
||||
if (!self.nextSpark or self.nextSpark <= curTime) then
|
||||
local effect = EffectData()
|
||||
effect:SetStart(pos)
|
||||
effect:SetOrigin(pos)
|
||||
effect:SetScale(2)
|
||||
util.Effect("cball_explode", effect)
|
||||
|
||||
self.nextSpark = curTime + 0.1
|
||||
end
|
||||
|
||||
local attacker = dmgInfo:GetAttacker()
|
||||
|
||||
self:EmitSound("npc/manhack/gib.wav")
|
||||
ix.combineNotify:AddImportantNotification("WRN:// Bio-Restrictor failure", nil, attacker:IsPlayer() and attacker, self:GetPos())
|
||||
ix.item.Spawn("trash_biolock", Vector(self:GetPos().x, self:GetPos().y, self:GetPos().z))
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
else
|
||||
local glowMaterial = ix.util.GetMaterial("sprites/glow04_noz")
|
||||
local color_green = Color(0, 255, 0, 255)
|
||||
local color_magenta = Color(214, 55, 229, 255)
|
||||
local color_red = Color(255, 50, 50, 255)
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
local color = color_green
|
||||
|
||||
if (self:GetDisplayError()) then
|
||||
color = color_red
|
||||
elseif (self:GetLocked()) then
|
||||
color = color_magenta
|
||||
end
|
||||
|
||||
local position = self:GetPos() + self:GetUp() * -8.7 + self:GetForward() * -3.85 + self:GetRight() * -6
|
||||
|
||||
render.SetMaterial(glowMaterial)
|
||||
render.DrawSprite(position, 10, 10, color)
|
||||
end
|
||||
end
|
||||
284
gamemodes/darkrp/entities/entities/ix_combinelock_cwu.lua
Normal file
284
gamemodes/darkrp/entities/entities/ix_combinelock_cwu.lua
Normal file
@@ -0,0 +1,284 @@
|
||||
--[[
|
||||
| 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 = "Combine Lock (CWU)"
|
||||
ENT.Category = "HL2 RP"
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminOnly = true
|
||||
ENT.PhysgunDisable = true
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "Locked")
|
||||
self:NetworkVar("Bool", 1, "DisplayError")
|
||||
self:NetworkVar("Bool", 2, "Disabled")
|
||||
|
||||
if (SERVER) then
|
||||
self:NetworkVarNotify("Locked", self.OnLockChanged)
|
||||
end
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
function ENT:GetLockPosition(door, normal)
|
||||
local index = door:LookupBone("handle")
|
||||
local position = door:GetPos()
|
||||
normal = normal or door:GetForward():Angle()
|
||||
|
||||
if (index and index >= 1) then
|
||||
position = door:GetBonePosition(index)
|
||||
end
|
||||
|
||||
position = position + normal:Forward() * 7.2 + normal:Up() * 10 + normal:Right() * 2
|
||||
|
||||
normal:RotateAroundAxis(normal:Up(), 90)
|
||||
normal:RotateAroundAxis(normal:Forward(), 180)
|
||||
normal:RotateAroundAxis(normal:Right(), 180)
|
||||
|
||||
return position, normal
|
||||
end
|
||||
|
||||
function ENT:SetDoor(door, position, angles)
|
||||
if (!IsValid(door) or !door:IsDoor()) then
|
||||
return
|
||||
end
|
||||
|
||||
local doorPartner = door:GetDoorPartner()
|
||||
|
||||
self.door = door
|
||||
self.door:DeleteOnRemove(self)
|
||||
door.ixLock = self
|
||||
|
||||
if (IsValid(doorPartner)) then
|
||||
self.doorPartner = doorPartner
|
||||
self.doorPartner:DeleteOnRemove(self)
|
||||
doorPartner.ixLock = self
|
||||
end
|
||||
|
||||
self:SetPos(position)
|
||||
self:SetAngles(angles)
|
||||
self:SetParent(door)
|
||||
end
|
||||
|
||||
function ENT:SpawnFunction(client, trace)
|
||||
local door = trace.Entity
|
||||
|
||||
if (!IsValid(door) or !door:IsDoor() or IsValid(door.ixLock)) then
|
||||
return client:NotifyLocalized("dNotValid")
|
||||
end
|
||||
|
||||
local normal = client:GetEyeTrace().HitNormal:Angle()
|
||||
local position, angles = self:GetLockPosition(door, normal)
|
||||
|
||||
local entity = ents.Create("ix_combinelock_cwu")
|
||||
entity:SetPos(trace.HitPos)
|
||||
entity:Spawn()
|
||||
entity:Activate()
|
||||
entity:SetDoor(door, position, angles)
|
||||
|
||||
ix.saveEnts:SaveEntity(entity)
|
||||
Schema:SaveCombineLocks()
|
||||
return entity
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/willardnetworks/props_combine/wn_combine_lock.mdl")
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:SetHealth(300)
|
||||
|
||||
self.accessLevel = "Member Access"
|
||||
self.nextUseTime = 0
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (IsValid(self)) then
|
||||
self:SetParent(nil)
|
||||
end
|
||||
|
||||
if (IsValid(self.door)) then
|
||||
self.door:Fire("unlock")
|
||||
self.door.ixLock = nil
|
||||
end
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
self.doorPartner.ixLock = nil
|
||||
end
|
||||
|
||||
if (!ix.shuttingDown) then
|
||||
Schema:SaveCombineLocks()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnLockChanged(name, bWasLocked, bLocked)
|
||||
if (!IsValid(self.door) or self:GetDisabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
ix.saveEnts:SaveEntity(self)
|
||||
if (bLocked) then
|
||||
self:EmitSound("buttons/combine_button2.wav")
|
||||
self.door:Fire("lock")
|
||||
self.door:Fire("close")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("lock")
|
||||
self.doorPartner:Fire("close")
|
||||
end
|
||||
else
|
||||
self:EmitSound("buttons/combine_button7.wav")
|
||||
self.door:Fire("unlock")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DisplayError()
|
||||
self:EmitSound("buttons/combine_button_locked.wav")
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:DisplayDamage()
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:Toggle(client)
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
if (self.nextUseTime > CurTime()) then
|
||||
return
|
||||
end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
local items = character:GetInventory():GetItems()
|
||||
local cwuCards = {}
|
||||
|
||||
for _, item in pairs(items) do
|
||||
if (item.uniqueID == "cwu_card" and item:GetData("cardID")) then
|
||||
cwuCards[#cwuCards + 1] = item
|
||||
end
|
||||
end
|
||||
|
||||
local canOpen = false
|
||||
for _, cards in pairs(cwuCards) do
|
||||
local accessLevel = cards:GetData("accessLevel", "Member Access")
|
||||
|
||||
if (items[cards:GetData("cardID")] and (accessLevel == "Management Access" or (accessLevel == "Member Access" and self.accessLevel == "Member Access"))) then
|
||||
canOpen = true
|
||||
end
|
||||
end
|
||||
|
||||
if (!Schema:CanPlayerOpenCombineLock(client, self) and !canOpen) then
|
||||
self:DisplayError()
|
||||
self.nextUseTime = CurTime() + 2
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
self:SetLocked(!self:GetLocked())
|
||||
|
||||
self.nextUseTime = CurTime() + 2
|
||||
end
|
||||
|
||||
function ENT:Use(client)
|
||||
if (client:KeyDown(IN_SPEED) and (client:Team() == FACTION_ADMIN or client:Team() == FACTION_SERVERADMIN or client:IsCombine() or client:GetCharacter():HasFlags("M"))) then
|
||||
net.Start("changeLockAccess")
|
||||
net.WriteEntity(self)
|
||||
net.Send(client)
|
||||
else
|
||||
self:Toggle(client)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnOptionSelected(client, option, data)
|
||||
if (option == "Set Member Access") then
|
||||
self.accessLevel = "Member Access"
|
||||
|
||||
client:Notify("You have set Member Access to this lock.")
|
||||
elseif (option == "Set Management Access") then
|
||||
self.accessLevel = "Management Access"
|
||||
|
||||
client:Notify("You have set Management Access to this lock.")
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmgInfo)
|
||||
self:SetHealth(self:Health() - dmgInfo:GetDamage())
|
||||
self:EmitSound("physics/metal/metal_sheet_impact_hard"..math.random(6, 8)..".wav")
|
||||
self:DisplayDamage()
|
||||
|
||||
if (self:Health() <= 0) then
|
||||
local pos = self:GetPos()
|
||||
local curTime = CurTime()
|
||||
|
||||
if (!self.nextSpark or self.nextSpark <= curTime) then
|
||||
local effect = EffectData()
|
||||
effect:SetStart(pos)
|
||||
effect:SetOrigin(pos)
|
||||
effect:SetScale(2)
|
||||
util.Effect("cball_explode", effect)
|
||||
|
||||
self.nextSpark = curTime + 0.1
|
||||
end
|
||||
|
||||
local attacker = dmgInfo:GetAttacker()
|
||||
|
||||
self:EmitSound("npc/manhack/gib.wav")
|
||||
ix.combineNotify:AddImportantNotification("WRN:// Bio-Restrictor failure", nil, attacker:IsPlayer() and attacker, self:GetPos())
|
||||
ix.item.Spawn("trash_biolock", Vector(self:GetPos().x, self:GetPos().y, self:GetPos().z))
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
else
|
||||
local glowMaterial = ix.util.GetMaterial("sprites/glow04_noz")
|
||||
local color_green = Color(0, 255, 0, 255)
|
||||
local color_blue = Color(37, 64, 213, 255)
|
||||
local color_red = Color(255, 50, 50, 255)
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
local color = color_green
|
||||
|
||||
if (self:GetDisplayError()) then
|
||||
color = color_red
|
||||
elseif (self:GetLocked()) then
|
||||
color = color_blue
|
||||
end
|
||||
|
||||
local position = self:GetPos() + self:GetUp() * -8.7 + self:GetForward() * -3.85 + self:GetRight() * -6
|
||||
|
||||
render.SetMaterial(glowMaterial)
|
||||
render.DrawSprite(position, 10, 10, color)
|
||||
end
|
||||
end
|
||||
284
gamemodes/darkrp/entities/entities/ix_combinelock_dob.lua
Normal file
284
gamemodes/darkrp/entities/entities/ix_combinelock_dob.lua
Normal file
@@ -0,0 +1,284 @@
|
||||
--[[
|
||||
| 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 = "Combine Lock (DOB)"
|
||||
ENT.Category = "HL2 RP"
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminOnly = true
|
||||
ENT.PhysgunDisable = true
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "Locked")
|
||||
self:NetworkVar("Bool", 1, "DisplayError")
|
||||
self:NetworkVar("Bool", 2, "Disabled")
|
||||
|
||||
if (SERVER) then
|
||||
self:NetworkVarNotify("Locked", self.OnLockChanged)
|
||||
end
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
function ENT:GetLockPosition(door, normal)
|
||||
local index = door:LookupBone("handle")
|
||||
local position = door:GetPos()
|
||||
normal = normal or door:GetForward():Angle()
|
||||
|
||||
if (index and index >= 1) then
|
||||
position = door:GetBonePosition(index)
|
||||
end
|
||||
|
||||
position = position + normal:Forward() * 7.2 + normal:Up() * 10 + normal:Right() * 2
|
||||
|
||||
normal:RotateAroundAxis(normal:Up(), 90)
|
||||
normal:RotateAroundAxis(normal:Forward(), 180)
|
||||
normal:RotateAroundAxis(normal:Right(), 180)
|
||||
|
||||
return position, normal
|
||||
end
|
||||
|
||||
function ENT:SetDoor(door, position, angles)
|
||||
if (!IsValid(door) or !door:IsDoor()) then
|
||||
return
|
||||
end
|
||||
|
||||
local doorPartner = door:GetDoorPartner()
|
||||
|
||||
self.door = door
|
||||
self.door:DeleteOnRemove(self)
|
||||
door.ixLock = self
|
||||
|
||||
if (IsValid(doorPartner)) then
|
||||
self.doorPartner = doorPartner
|
||||
self.doorPartner:DeleteOnRemove(self)
|
||||
doorPartner.ixLock = self
|
||||
end
|
||||
|
||||
self:SetPos(position)
|
||||
self:SetAngles(angles)
|
||||
self:SetParent(door)
|
||||
end
|
||||
|
||||
function ENT:SpawnFunction(client, trace)
|
||||
local door = trace.Entity
|
||||
|
||||
if (!IsValid(door) or !door:IsDoor() or IsValid(door.ixLock)) then
|
||||
return client:NotifyLocalized("dNotValid")
|
||||
end
|
||||
|
||||
local normal = client:GetEyeTrace().HitNormal:Angle()
|
||||
local position, angles = self:GetLockPosition(door, normal)
|
||||
|
||||
local entity = ents.Create("ix_combinelock_dob")
|
||||
entity:SetPos(trace.HitPos)
|
||||
entity:Spawn()
|
||||
entity:Activate()
|
||||
entity:SetDoor(door, position, angles)
|
||||
|
||||
ix.saveEnts:SaveEntity(entity)
|
||||
Schema:SaveCombineLocks()
|
||||
return entity
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/willardnetworks/props_combine/wn_combine_lock.mdl")
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:SetHealth(300)
|
||||
|
||||
self.accessLevel = "Member Access"
|
||||
self.nextUseTime = 0
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (IsValid(self)) then
|
||||
self:SetParent(nil)
|
||||
end
|
||||
|
||||
if (IsValid(self.door)) then
|
||||
self.door:Fire("unlock")
|
||||
self.door.ixLock = nil
|
||||
end
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
self.doorPartner.ixLock = nil
|
||||
end
|
||||
|
||||
if (!ix.shuttingDown) then
|
||||
Schema:SaveCombineLocks()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnLockChanged(name, bWasLocked, bLocked)
|
||||
if (!IsValid(self.door) or self:GetDisabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
ix.saveEnts:SaveEntity(self)
|
||||
if (bLocked) then
|
||||
self:EmitSound("buttons/combine_button2.wav")
|
||||
self.door:Fire("lock")
|
||||
self.door:Fire("close")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("lock")
|
||||
self.doorPartner:Fire("close")
|
||||
end
|
||||
else
|
||||
self:EmitSound("buttons/combine_button7.wav")
|
||||
self.door:Fire("unlock")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DisplayError()
|
||||
self:EmitSound("buttons/combine_button_locked.wav")
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:DisplayDamage()
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:Toggle(client)
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
if (self.nextUseTime > CurTime()) then
|
||||
return
|
||||
end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
local items = character:GetInventory():GetItems()
|
||||
local dobCards = {}
|
||||
|
||||
for _, item in pairs(items) do
|
||||
if (item.uniqueID == "dob_card" and item:GetData("cardID")) then
|
||||
dobCards[#dobCards + 1] = item
|
||||
end
|
||||
end
|
||||
|
||||
local canOpen = false
|
||||
for _, cards in pairs(dobCards) do
|
||||
local accessLevel = cards:GetData("accessLevel", "Member Access")
|
||||
|
||||
if (items[cards:GetData("cardID")] and (accessLevel == "Management Access" or (accessLevel == "Member Access" and self.accessLevel == "Member Access"))) then
|
||||
canOpen = true
|
||||
end
|
||||
end
|
||||
|
||||
if (!Schema:CanPlayerOpenCombineLock(client, self) and !canOpen) then
|
||||
self:DisplayError()
|
||||
self.nextUseTime = CurTime() + 2
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
self:SetLocked(!self:GetLocked())
|
||||
|
||||
self.nextUseTime = CurTime() + 2
|
||||
end
|
||||
|
||||
function ENT:Use(client)
|
||||
if (client:KeyDown(IN_SPEED) and (client:Team() == FACTION_ADMIN or client:Team() == FACTION_SERVERADMIN or client:IsCombine() or client:GetCharacter():HasFlags("M"))) then
|
||||
net.Start("changeLockAccess")
|
||||
net.WriteEntity(self)
|
||||
net.Send(client)
|
||||
else
|
||||
self:Toggle(client)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnOptionSelected(client, option, data)
|
||||
if (option == "Set Member Access") then
|
||||
self.accessLevel = "Member Access"
|
||||
|
||||
client:Notify("You have set Member Access to this lock.")
|
||||
elseif (option == "Set Management Access") then
|
||||
self.accessLevel = "Management Access"
|
||||
|
||||
client:Notify("You have set Management Access to this lock.")
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmgInfo)
|
||||
self:SetHealth(self:Health() - dmgInfo:GetDamage())
|
||||
self:EmitSound("physics/metal/metal_sheet_impact_hard"..math.random(6, 8)..".wav")
|
||||
self:DisplayDamage()
|
||||
|
||||
if (self:Health() <= 0) then
|
||||
local pos = self:GetPos()
|
||||
local curTime = CurTime()
|
||||
|
||||
if (!self.nextSpark or self.nextSpark <= curTime) then
|
||||
local effect = EffectData()
|
||||
effect:SetStart(pos)
|
||||
effect:SetOrigin(pos)
|
||||
effect:SetScale(2)
|
||||
util.Effect("cball_explode", effect)
|
||||
|
||||
self.nextSpark = curTime + 0.1
|
||||
end
|
||||
|
||||
local attacker = dmgInfo:GetAttacker()
|
||||
|
||||
self:EmitSound("npc/manhack/gib.wav")
|
||||
ix.combineNotify:AddImportantNotification("WRN:// Bio-Restrictor failure", nil, attacker:IsPlayer() and attacker, self:GetPos())
|
||||
ix.item.Spawn("trash_biolock", Vector(self:GetPos().x, self:GetPos().y, self:GetPos().z))
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
else
|
||||
local glowMaterial = ix.util.GetMaterial("sprites/glow04_noz")
|
||||
local color_green = Color(0, 255, 0, 255)
|
||||
local color_orange = Color(235, 125, 52, 255)
|
||||
local color_red = Color(255, 50, 50, 255)
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
local color = color_green
|
||||
|
||||
if (self:GetDisplayError()) then
|
||||
color = color_red
|
||||
elseif (self:GetLocked()) then
|
||||
color = color_orange
|
||||
end
|
||||
|
||||
local position = self:GetPos() + self:GetUp() * -8.7 + self:GetForward() * -3.85 + self:GetRight() * -6
|
||||
|
||||
render.SetMaterial(glowMaterial)
|
||||
render.DrawSprite(position, 10, 10, color)
|
||||
end
|
||||
end
|
||||
284
gamemodes/darkrp/entities/entities/ix_combinelock_moe.lua
Normal file
284
gamemodes/darkrp/entities/entities/ix_combinelock_moe.lua
Normal file
@@ -0,0 +1,284 @@
|
||||
--[[
|
||||
| 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 = "Combine Lock (MOE)"
|
||||
ENT.Category = "HL2 RP"
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminOnly = true
|
||||
ENT.PhysgunDisable = true
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "Locked")
|
||||
self:NetworkVar("Bool", 1, "DisplayError")
|
||||
self:NetworkVar("Bool", 2, "Disabled")
|
||||
|
||||
if (SERVER) then
|
||||
self:NetworkVarNotify("Locked", self.OnLockChanged)
|
||||
end
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
function ENT:GetLockPosition(door, normal)
|
||||
local index = door:LookupBone("handle")
|
||||
local position = door:GetPos()
|
||||
normal = normal or door:GetForward():Angle()
|
||||
|
||||
if (index and index >= 1) then
|
||||
position = door:GetBonePosition(index)
|
||||
end
|
||||
|
||||
position = position + normal:Forward() * 7.2 + normal:Up() * 10 + normal:Right() * 2
|
||||
|
||||
normal:RotateAroundAxis(normal:Up(), 90)
|
||||
normal:RotateAroundAxis(normal:Forward(), 180)
|
||||
normal:RotateAroundAxis(normal:Right(), 180)
|
||||
|
||||
return position, normal
|
||||
end
|
||||
|
||||
function ENT:SetDoor(door, position, angles)
|
||||
if (!IsValid(door) or !door:IsDoor()) then
|
||||
return
|
||||
end
|
||||
|
||||
local doorPartner = door:GetDoorPartner()
|
||||
|
||||
self.door = door
|
||||
self.door:DeleteOnRemove(self)
|
||||
door.ixLock = self
|
||||
|
||||
if (IsValid(doorPartner)) then
|
||||
self.doorPartner = doorPartner
|
||||
self.doorPartner:DeleteOnRemove(self)
|
||||
doorPartner.ixLock = self
|
||||
end
|
||||
|
||||
self:SetPos(position)
|
||||
self:SetAngles(angles)
|
||||
self:SetParent(door)
|
||||
end
|
||||
|
||||
function ENT:SpawnFunction(client, trace)
|
||||
local door = trace.Entity
|
||||
|
||||
if (!IsValid(door) or !door:IsDoor() or IsValid(door.ixLock)) then
|
||||
return client:NotifyLocalized("dNotValid")
|
||||
end
|
||||
|
||||
local normal = client:GetEyeTrace().HitNormal:Angle()
|
||||
local position, angles = self:GetLockPosition(door, normal)
|
||||
|
||||
local entity = ents.Create("ix_combinelock_moe")
|
||||
entity:SetPos(trace.HitPos)
|
||||
entity:Spawn()
|
||||
entity:Activate()
|
||||
entity:SetDoor(door, position, angles)
|
||||
|
||||
ix.saveEnts:SaveEntity(entity)
|
||||
Schema:SaveCombineLocks()
|
||||
return entity
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/willardnetworks/props_combine/wn_combine_lock.mdl")
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:SetHealth(300)
|
||||
|
||||
self.accessLevel = "Member Access"
|
||||
self.nextUseTime = 0
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (IsValid(self)) then
|
||||
self:SetParent(nil)
|
||||
end
|
||||
|
||||
if (IsValid(self.door)) then
|
||||
self.door:Fire("unlock")
|
||||
self.door.ixLock = nil
|
||||
end
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
self.doorPartner.ixLock = nil
|
||||
end
|
||||
|
||||
if (!ix.shuttingDown) then
|
||||
Schema:SaveCombineLocks()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnLockChanged(name, bWasLocked, bLocked)
|
||||
if (!IsValid(self.door) or self:GetDisabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
ix.saveEnts:SaveEntity(self)
|
||||
if (bLocked) then
|
||||
self:EmitSound("buttons/combine_button2.wav")
|
||||
self.door:Fire("lock")
|
||||
self.door:Fire("close")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("lock")
|
||||
self.doorPartner:Fire("close")
|
||||
end
|
||||
else
|
||||
self:EmitSound("buttons/combine_button7.wav")
|
||||
self.door:Fire("unlock")
|
||||
|
||||
if (IsValid(self.doorPartner)) then
|
||||
self.doorPartner:Fire("unlock")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DisplayError()
|
||||
self:EmitSound("buttons/combine_button_locked.wav")
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:DisplayDamage()
|
||||
self:SetDisplayError(true)
|
||||
|
||||
timer.Simple(1.2, function()
|
||||
if (IsValid(self)) then
|
||||
self:SetDisplayError(false)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:Toggle(client)
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
if (self.nextUseTime > CurTime()) then
|
||||
return
|
||||
end
|
||||
|
||||
local character = client:GetCharacter()
|
||||
local items = character:GetInventory():GetItems()
|
||||
local moeCards = {}
|
||||
|
||||
for _, item in pairs(items) do
|
||||
if (item.uniqueID == "moe_card" and item:GetData("cardID")) then
|
||||
moeCards[#moeCards + 1] = item
|
||||
end
|
||||
end
|
||||
|
||||
local canOpen = false
|
||||
for _, cards in pairs(moeCards) do
|
||||
local accessLevel = cards:GetData("accessLevel", "Member Access")
|
||||
|
||||
if (items[cards:GetData("cardID")] and (accessLevel == "Management Access" or (accessLevel == "Member Access" and self.accessLevel == "Member Access"))) then
|
||||
canOpen = true
|
||||
end
|
||||
end
|
||||
|
||||
if (!Schema:CanPlayerOpenCombineLock(client, self) and !canOpen) then
|
||||
self:DisplayError()
|
||||
self.nextUseTime = CurTime() + 2
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
self:SetLocked(!self:GetLocked())
|
||||
|
||||
self.nextUseTime = CurTime() + 2
|
||||
end
|
||||
|
||||
function ENT:Use(client)
|
||||
if (client:KeyDown(IN_SPEED) and (client:Team() == FACTION_ADMIN or client:Team() == FACTION_SERVERADMIN or client:IsCombine() or client:GetCharacter():HasFlags("M"))) then
|
||||
net.Start("changeLockAccess")
|
||||
net.WriteEntity(self)
|
||||
net.Send(client)
|
||||
else
|
||||
self:Toggle(client)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnOptionSelected(client, option, data)
|
||||
if (option == "Set Member Access") then
|
||||
self.accessLevel = "Member Access"
|
||||
|
||||
client:Notify("You have set Member Access to this lock.")
|
||||
elseif (option == "Set Management Access") then
|
||||
self.accessLevel = "Management Access"
|
||||
|
||||
client:Notify("You have set Management Access to this lock.")
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmgInfo)
|
||||
self:SetHealth(self:Health() - dmgInfo:GetDamage())
|
||||
self:EmitSound("physics/metal/metal_sheet_impact_hard"..math.random(6, 8)..".wav")
|
||||
self:DisplayDamage()
|
||||
|
||||
if (self:Health() <= 0) then
|
||||
local pos = self:GetPos()
|
||||
local curTime = CurTime()
|
||||
|
||||
if (!self.nextSpark or self.nextSpark <= curTime) then
|
||||
local effect = EffectData()
|
||||
effect:SetStart(pos)
|
||||
effect:SetOrigin(pos)
|
||||
effect:SetScale(2)
|
||||
util.Effect("cball_explode", effect)
|
||||
|
||||
self.nextSpark = curTime + 0.1
|
||||
end
|
||||
|
||||
local attacker = dmgInfo:GetAttacker()
|
||||
|
||||
self:EmitSound("npc/manhack/gib.wav")
|
||||
ix.combineNotify:AddImportantNotification("WRN:// Bio-Restrictor failure", nil, attacker:IsPlayer() and attacker, self:GetPos())
|
||||
ix.item.Spawn("trash_biolock", Vector(self:GetPos().x, self:GetPos().y, self:GetPos().z))
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
else
|
||||
local glowMaterial = ix.util.GetMaterial("sprites/glow04_noz")
|
||||
local color_green = Color(0, 255, 0, 255)
|
||||
local color_magenta = Color(214, 55, 229, 255)
|
||||
local color_red = Color(255, 50, 50, 255)
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetDisabled()) then return end
|
||||
|
||||
local color = color_green
|
||||
|
||||
if (self:GetDisplayError()) then
|
||||
color = color_red
|
||||
elseif (self:GetLocked()) then
|
||||
color = color_magenta
|
||||
end
|
||||
|
||||
local position = self:GetPos() + self:GetUp() * -8.7 + self:GetForward() * -3.85 + self:GetRight() * -6
|
||||
|
||||
render.SetMaterial(glowMaterial)
|
||||
render.DrawSprite(position, 10, 10, color)
|
||||
end
|
||||
end
|
||||
445
gamemodes/darkrp/entities/entities/ix_forcefield.lua
Normal file
445
gamemodes/darkrp/entities/entities/ix_forcefield.lua
Normal file
@@ -0,0 +1,445 @@
|
||||
--[[
|
||||
| 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 = "Forcefield"
|
||||
ENT.Category = "HL2 RP"
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminOnly = true
|
||||
ENT.RenderGroup = RENDERGROUP_BOTH
|
||||
ENT.PhysgunDisabled = true
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Int", 0, "Mode")
|
||||
self:NetworkVar("Entity", 0, "Dummy")
|
||||
self:NetworkVar("Bool", 0, "Malfunctioning")
|
||||
end
|
||||
|
||||
local MODE_OFFLINE = 1
|
||||
local MODE_ALLOW_ALL = 2
|
||||
local MODE_ALLOW_COMBINE = 3
|
||||
local MODE_ALLOW_COMBINE_INF = 4
|
||||
|
||||
if (SERVER) then
|
||||
function ENT:SpawnFunction(client, trace)
|
||||
local angles = (client:GetPos() - trace.HitPos):Angle()
|
||||
angles.p = 0
|
||||
angles.r = 0
|
||||
angles:RotateAroundAxis(angles:Up(), 270)
|
||||
|
||||
local entity = ents.Create("ix_forcefield")
|
||||
entity:SetPos(trace.HitPos + Vector(0, 0, 40))
|
||||
entity:SetAngles(angles:SnapTo("y", 90))
|
||||
entity:Spawn()
|
||||
entity:Activate()
|
||||
|
||||
Schema:SaveForceFields()
|
||||
return entity
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/willardnetworks/props/forcefield_left.mdl")
|
||||
self:SetSkin(3)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
|
||||
local data = {}
|
||||
data.start = self:GetPos() + self:GetRight() * -16
|
||||
data.endpos = self:GetPos() + self:GetRight() * -480
|
||||
data.filter = self
|
||||
local trace = util.TraceLine(data)
|
||||
|
||||
local angles = self:GetAngles()
|
||||
angles:RotateAroundAxis(angles:Up(), 90)
|
||||
|
||||
self.dummy = ents.Create("prop_physics")
|
||||
self.dummy:SetModel("models/willardnetworks/props/forcefield_right.mdl")
|
||||
self.dummy:SetSkin(3)
|
||||
self.dummy:SetPos(trace.HitPos)
|
||||
self.dummy:SetAngles(self:GetAngles())
|
||||
self.dummy:Spawn()
|
||||
self.dummy.PhysgunDisabled = true
|
||||
self.dummy:SetCollisionGroup(COLLISION_GROUP_WORLD)
|
||||
self:DeleteOnRemove(self.dummy)
|
||||
|
||||
local verts = {
|
||||
{pos = Vector(0, 0, -25)},
|
||||
{pos = Vector(0, 0, 150)},
|
||||
{pos = self:WorldToLocal(self.dummy:GetPos()) + Vector(0, 0, 150)},
|
||||
{pos = self:WorldToLocal(self.dummy:GetPos()) + Vector(0, 0, 150)},
|
||||
{pos = self:WorldToLocal(self.dummy:GetPos()) - Vector(0, 0, 25)},
|
||||
{pos = Vector(0, 0, -25)}
|
||||
}
|
||||
|
||||
self:PhysicsFromMesh(verts)
|
||||
|
||||
local physObj = self:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physObj)) then
|
||||
physObj:EnableMotion(false)
|
||||
physObj:Sleep()
|
||||
end
|
||||
|
||||
self:AddSolidFlags(FSOLID_CUSTOMBOXTEST)
|
||||
self:SetCustomCollisionCheck(true)
|
||||
self:SetDummy(self.dummy)
|
||||
|
||||
physObj = self.dummy:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physObj)) then
|
||||
physObj:EnableMotion(false)
|
||||
physObj:Sleep()
|
||||
end
|
||||
|
||||
self:SetMoveType(MOVETYPE_NOCLIP)
|
||||
self:SetMoveType(MOVETYPE_PUSH)
|
||||
self:MakePhysicsObjectAShadow()
|
||||
self:SetMode(MODE_OFFLINE)
|
||||
end
|
||||
|
||||
function ENT:StartTouch(entity)
|
||||
if (!self.buzzer) then
|
||||
self.buzzer = CreateSound(entity, "ambient/machines/combine_shield_touch_loop1.wav")
|
||||
self.buzzer:Play()
|
||||
self.buzzer:ChangeVolume(0.8, 0)
|
||||
self.buzzer:SetSoundLevel(60)
|
||||
else
|
||||
self.buzzer:ChangeVolume(0.8, 0.5)
|
||||
self.buzzer:Play()
|
||||
end
|
||||
|
||||
self.entities = (self.entities or 0) + 1
|
||||
end
|
||||
|
||||
function ENT:EndTouch(entity)
|
||||
self.entities = math.max((self.entities or 0) - 1, 0)
|
||||
|
||||
if (self.buzzer and self.entities == 0) then
|
||||
self.buzzer:FadeOut(0.5)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (self.buzzer) then
|
||||
self.buzzer:Stop()
|
||||
self.buzzer = nil
|
||||
end
|
||||
|
||||
if (!ix.shuttingDown and !self.ixIsSafe) then
|
||||
Schema:SaveForceFields()
|
||||
end
|
||||
end
|
||||
|
||||
ENT.MODES = {
|
||||
{
|
||||
function(entity)
|
||||
return false
|
||||
end,
|
||||
"field disengaged.",
|
||||
"disengaged",
|
||||
3
|
||||
},
|
||||
{
|
||||
function(entity)
|
||||
if (!entity:IsPlayer()) then return true end
|
||||
|
||||
local character = entity:GetCharacter()
|
||||
if (!character or !character:GetInventory()) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (!character:GetInventory():HasItem("id_card", {active = true})) then
|
||||
if character:GetInventory():HasItem("fake_id_card") then
|
||||
return false
|
||||
end
|
||||
if character:IsVortigaunt() and
|
||||
character:GetCollarItemID() and
|
||||
ix.item.instances[character:GetCollarItemID()] and
|
||||
-ix.config.Get("blacklistSCAmount", 40) <= ix.item.instances[character:GetCollarItemID()]:GetData("sterilizedCredits", 0) then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end,
|
||||
"allow only registered individuals with active ID Card.",
|
||||
"engaged",
|
||||
0
|
||||
},
|
||||
{
|
||||
function(entity)
|
||||
return true
|
||||
end,
|
||||
"disallow non-functionary units.",
|
||||
"restricted",
|
||||
1
|
||||
},
|
||||
{
|
||||
function(entity)
|
||||
return true
|
||||
end,
|
||||
"disallow non-functionary units (infestation control specific)",
|
||||
"restricted",
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
function ENT:Use(activator)
|
||||
if ((self.nextUse or 0) < CurTime()) then
|
||||
self.nextUse = CurTime() + 1.5
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
local bForced = CAMI.PlayerHasAccess(activator, "Helix - Basic Admin Commands", nil) and activator:GetMoveType() == MOVETYPE_NOCLIP
|
||||
|
||||
if (activator:HasActiveCombineSuit() or ix.faction.Get(activator:Team()).allowForcefieldControl or bForced) then
|
||||
self:SetMode(self:GetMode() + 1)
|
||||
local action = "modified"
|
||||
|
||||
if (self:GetMode() > #self.MODES) then
|
||||
self:SetMode(MODE_OFFLINE)
|
||||
self:CollisionRulesChanged()
|
||||
|
||||
self:SetSkin(self.MODES[1][4])
|
||||
self.dummy:SetSkin(self.MODES[1][4])
|
||||
self:EmitSound("npc/turret_floor/die.wav")
|
||||
else
|
||||
self:CollisionRulesChanged()
|
||||
|
||||
self:SetSkin(self.MODES[self:GetMode()][4])
|
||||
self.dummy:SetSkin(self.MODES[self:GetMode()][4])
|
||||
end
|
||||
|
||||
self:EmitSound("buttons/combine_button5.wav", 140, 100 + (self:GetMode() - 1) * 15)
|
||||
activator:ChatPrint("Changed barrier mode to: " .. self.MODES[self:GetMode()][2])
|
||||
|
||||
Schema:SaveForceFields()
|
||||
if (bForced) then return end
|
||||
|
||||
ix.combineNotify:AddNotification("NTC:// Containment Field " .. self.MODES[self:GetMode()][3] .. " by " .. activator:GetCombineTag(), nil, activator)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Malfunction()
|
||||
local bMalfunctioning = self:GetMalfunctioning()
|
||||
if (!bMalfunctioning) then return end
|
||||
|
||||
timer.Simple(math.random(0.2, 1), function()
|
||||
if (!self:IsValid()) then return end
|
||||
|
||||
self:SetMode(MODE_OFFLINE)
|
||||
self:CollisionRulesChanged()
|
||||
|
||||
self:SetSkin(self.MODES[1][4])
|
||||
self.dummy:SetSkin(self.MODES[1][4])
|
||||
self:EmitSound("buttons/combine_button5.wav", 65, 100 + (self:GetMode() - 1) * 15)
|
||||
self:EmitSound("npc/turret_floor/die.wav", 55)
|
||||
|
||||
local target = math.random(2) == 1 and self or self:GetDummy()
|
||||
local vPoint = target:GetPos() + Vector(0, 0, math.random(-10, 100)) + target:GetRight() * (target == self and -10 or 10)
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin(vPoint)
|
||||
util.Effect("ManhackSparks", effectdata)
|
||||
|
||||
if (math.random(2) == 1) then
|
||||
target = math.random(2) == 1 and self or self:GetDummy()
|
||||
vPoint = target:GetPos() + Vector(0, 0, math.random(-10, 100)) + target:GetRight() * (target == self and -10 or 10)
|
||||
effectdata = EffectData()
|
||||
effectdata:SetOrigin(vPoint)
|
||||
util.Effect("ManhackSparks", effectdata)
|
||||
end
|
||||
|
||||
self:EmitSound("ambient/energy/zap" .. math.random(1, 9) .. ".wav", 65)
|
||||
|
||||
timer.Simple(math.random(1, 5), function()
|
||||
if (!self:IsValid()) then return end
|
||||
|
||||
self:SetMode(math.random(2, 4))
|
||||
self:CollisionRulesChanged()
|
||||
|
||||
self:SetSkin(self.MODES[self:GetMode()][4])
|
||||
self.dummy:SetSkin(self.MODES[self:GetMode()][4])
|
||||
|
||||
self:EmitSound("buttons/combine_button5.wav", 65, 100 + (self:GetMode() - 1) * 15)
|
||||
|
||||
self:Malfunction()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
hook.Add("ShouldCollide", "ix_forcefields", function(a, b)
|
||||
local entity
|
||||
local forcefield
|
||||
|
||||
if (a:GetClass() == "ix_forcefield") then
|
||||
entity = b
|
||||
forcefield = a
|
||||
elseif (b:GetClass() == "ix_forcefield") then
|
||||
entity = a
|
||||
forcefield = b
|
||||
end
|
||||
|
||||
if (IsValid(forcefield)) then
|
||||
if (IsValid(entity)) then
|
||||
if (entity:IsPlayer() and (entity:HasActiveCombineSuit() or ix.faction.Get(entity:Team()).allowForcefieldPassage) or entity:GetClass() == "ix_scanner") then
|
||||
return false
|
||||
end
|
||||
|
||||
if (entity:IsPlayer() and forcefield:GetMode() == MODE_ALLOW_COMBINE_INF and ix.faction.Get(entity:Team()).allowForcefieldInfestationPassage) then
|
||||
return false
|
||||
end
|
||||
|
||||
local mode = forcefield:GetMode() or MODE_OFFLINE
|
||||
|
||||
return istable(forcefield.MODES[mode]) and forcefield.MODES[mode][1](entity)
|
||||
else
|
||||
return forcefield:GetMode() != 5
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
SHIELD_MATERIALS = {
|
||||
nil,
|
||||
ix.util.GetMaterial("models/effects/shield_blue"),
|
||||
ix.util.GetMaterial("models/effects/shield_red"),
|
||||
ix.util.GetMaterial("models/effects/shield_yellow")
|
||||
}
|
||||
|
||||
function ENT:Initialize()
|
||||
local data = {}
|
||||
data.start = self:GetPos() + self:GetRight()*-16
|
||||
data.endpos = self:GetPos() + self:GetRight()*-480
|
||||
data.filter = self
|
||||
local trace = util.TraceLine(data)
|
||||
|
||||
self:SetCustomCollisionCheck(true)
|
||||
self:PhysicsInitConvex({
|
||||
vector_origin,
|
||||
Vector(0, 0, 150),
|
||||
trace.HitPos + Vector(0, 0, 150),
|
||||
trace.HitPos
|
||||
})
|
||||
|
||||
self.distance = self:GetPos():Distance(trace.HitPos)
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetMode() == MODE_OFFLINE) then
|
||||
return
|
||||
end
|
||||
|
||||
local pos = self:GetPos()
|
||||
local angles = self:GetAngles()
|
||||
local matrix = Matrix()
|
||||
matrix:Translate(pos + self:GetUp() * -40)
|
||||
matrix:Rotate(angles)
|
||||
|
||||
render.SetMaterial(SHIELD_MATERIALS[self:GetMode()])
|
||||
|
||||
local dummy = self:GetDummy()
|
||||
|
||||
if (IsValid(dummy)) then
|
||||
local dummyPos = dummy:GetPos()
|
||||
local vertex = self:WorldToLocal(dummyPos)
|
||||
self:SetRenderBounds(vector_origin, vertex + self:GetUp() * 150)
|
||||
|
||||
cam.PushModelMatrix(matrix)
|
||||
self:DrawShield(vertex)
|
||||
cam.PopModelMatrix()
|
||||
|
||||
matrix:Translate(vertex)
|
||||
matrix:Rotate(Angle(0, 180, 0))
|
||||
|
||||
cam.PushModelMatrix(matrix)
|
||||
self:DrawShield(vertex)
|
||||
cam.PopModelMatrix()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DrawShield(vertex)
|
||||
mesh.Begin(MATERIAL_QUADS, 1)
|
||||
mesh.Position(vector_origin)
|
||||
mesh.TexCoord(0, 0, 0)
|
||||
mesh.AdvanceVertex()
|
||||
|
||||
mesh.Position(self:GetUp() * 190)
|
||||
mesh.TexCoord(0, 0, 3)
|
||||
mesh.AdvanceVertex()
|
||||
|
||||
mesh.Position(vertex + self:GetUp() * 190)
|
||||
mesh.TexCoord(0, 3, 3)
|
||||
mesh.AdvanceVertex()
|
||||
|
||||
mesh.Position(vertex)
|
||||
mesh.TexCoord(0, 3, 0)
|
||||
mesh.AdvanceVertex()
|
||||
mesh.End()
|
||||
end
|
||||
end
|
||||
|
||||
properties.Add("ixForcefieldStartMalfunction", {
|
||||
MenuLabel = "Start Malfunctioning",
|
||||
Order = 500,
|
||||
MenuIcon = "icon16/lightning_add.png",
|
||||
|
||||
Filter = function(self, entity, client)
|
||||
if (entity:GetClass() == "ix_forcefield" and !entity:GetMalfunctioning() and CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands", nil)) then return true end
|
||||
end,
|
||||
|
||||
Action = function(self, entity)
|
||||
self:MsgStart()
|
||||
net.WriteEntity(entity)
|
||||
self:MsgEnd()
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
local entity = net.ReadEntity()
|
||||
|
||||
if (!IsValid(entity)) then return end
|
||||
if (!self:Filter(entity, client)) then return end
|
||||
|
||||
entity:SetMalfunctioning(true)
|
||||
entity:Malfunction()
|
||||
end
|
||||
})
|
||||
|
||||
properties.Add("ixForcefieldStopMalfunction", {
|
||||
MenuLabel = "Stop Malfunctioning",
|
||||
Order = 500,
|
||||
MenuIcon = "icon16/lightning_delete.png",
|
||||
|
||||
Filter = function(self, entity, client)
|
||||
if (entity:GetClass() == "ix_forcefield" and entity:GetMalfunctioning() and CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands", nil)) then return true end
|
||||
end,
|
||||
|
||||
Action = function(self, entity)
|
||||
self:MsgStart()
|
||||
net.WriteEntity(entity)
|
||||
self:MsgEnd()
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
local entity = net.ReadEntity()
|
||||
|
||||
if (!IsValid(entity)) then return end
|
||||
if (!self:Filter(entity, client)) then return end
|
||||
|
||||
entity:SetMalfunctioning(false)
|
||||
end
|
||||
})
|
||||
437
gamemodes/darkrp/entities/entities/ix_rebelfield.lua
Normal file
437
gamemodes/darkrp/entities/entities/ix_rebelfield.lua
Normal file
@@ -0,0 +1,437 @@
|
||||
--[[
|
||||
| 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 = "Hacked Forcefield"
|
||||
ENT.Category = "HL2 RP"
|
||||
ENT.Spawnable = true
|
||||
ENT.AdminOnly = true
|
||||
ENT.RenderGroup = RENDERGROUP_BOTH
|
||||
ENT.PhysgunDisabled = true
|
||||
ENT.bNoPersist = true
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Int", 0, "Mode")
|
||||
self:NetworkVar("Entity", 0, "Dummy")
|
||||
self:NetworkVar("Bool", 0, "Malfunctioning")
|
||||
end
|
||||
|
||||
local MODE_OFFLINE = 1
|
||||
local MODE_ALLOW_ALL = 2
|
||||
local MODE_ALLOW_COMBINE = 3
|
||||
local MODE_ALLOW_COMBINE_INF = 4
|
||||
|
||||
if (SERVER) then
|
||||
function ENT:SpawnFunction(client, trace)
|
||||
local angles = (client:GetPos() - trace.HitPos):Angle()
|
||||
angles.p = 0
|
||||
angles.r = 0
|
||||
angles:RotateAroundAxis(angles:Up(), 270)
|
||||
|
||||
local entity = ents.Create("ix_rebelfield")
|
||||
entity:SetPos(trace.HitPos + Vector(0, 0, 40))
|
||||
entity:SetAngles(angles:SnapTo("y", 90))
|
||||
entity:Spawn()
|
||||
entity:Activate()
|
||||
|
||||
Schema:SaveRebelForceFields()
|
||||
return entity
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/willardnetworks/props/forcefield_left.mdl")
|
||||
self:SetSkin(3)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
|
||||
local data = {}
|
||||
data.start = self:GetPos() + self:GetRight() * -16
|
||||
data.endpos = self:GetPos() + self:GetRight() * -480
|
||||
data.filter = self
|
||||
local trace = util.TraceLine(data)
|
||||
|
||||
local angles = self:GetAngles()
|
||||
angles:RotateAroundAxis(angles:Up(), 90)
|
||||
|
||||
self.dummy = ents.Create("prop_physics")
|
||||
self.dummy:SetModel("models/willardnetworks/props/forcefield_right.mdl")
|
||||
self.dummy:SetSkin(3)
|
||||
self.dummy:SetPos(trace.HitPos)
|
||||
self.dummy:SetAngles(self:GetAngles())
|
||||
self.dummy:Spawn()
|
||||
self.dummy.PhysgunDisabled = true
|
||||
self.dummy:SetCollisionGroup(COLLISION_GROUP_WORLD)
|
||||
self:DeleteOnRemove(self.dummy)
|
||||
|
||||
local verts = {
|
||||
{pos = Vector(0, 0, -25)},
|
||||
{pos = Vector(0, 0, 150)},
|
||||
{pos = self:WorldToLocal(self.dummy:GetPos()) + Vector(0, 0, 150)},
|
||||
{pos = self:WorldToLocal(self.dummy:GetPos()) + Vector(0, 0, 150)},
|
||||
{pos = self:WorldToLocal(self.dummy:GetPos()) - Vector(0, 0, 25)},
|
||||
{pos = Vector(0, 0, -25)}
|
||||
}
|
||||
|
||||
self:PhysicsFromMesh(verts)
|
||||
|
||||
local physObj = self:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physObj)) then
|
||||
physObj:EnableMotion(false)
|
||||
physObj:Sleep()
|
||||
end
|
||||
|
||||
self:AddSolidFlags(FSOLID_CUSTOMBOXTEST)
|
||||
self:SetCustomCollisionCheck(true)
|
||||
self:SetDummy(self.dummy)
|
||||
|
||||
physObj = self.dummy:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physObj)) then
|
||||
physObj:EnableMotion(false)
|
||||
physObj:Sleep()
|
||||
end
|
||||
|
||||
self:SetMoveType(MOVETYPE_NOCLIP)
|
||||
self:SetMoveType(MOVETYPE_PUSH)
|
||||
self:MakePhysicsObjectAShadow()
|
||||
self:SetMode(MODE_OFFLINE)
|
||||
end
|
||||
|
||||
function ENT:StartTouch(entity)
|
||||
if (!self.buzzer) then
|
||||
self.buzzer = CreateSound(entity, "ambient/machines/combine_shield_touch_loop1.wav")
|
||||
self.buzzer:Play()
|
||||
self.buzzer:ChangeVolume(0.8, 0)
|
||||
self.buzzer:SetSoundLevel(60)
|
||||
else
|
||||
self.buzzer:ChangeVolume(0.8, 0.5)
|
||||
self.buzzer:Play()
|
||||
end
|
||||
|
||||
self.entities = (self.entities or 0) + 1
|
||||
end
|
||||
|
||||
function ENT:EndTouch(entity)
|
||||
self.entities = math.max((self.entities or 0) - 1, 0)
|
||||
|
||||
if (self.buzzer and self.entities == 0) then
|
||||
self.buzzer:FadeOut(0.5)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (self.buzzer) then
|
||||
self.buzzer:Stop()
|
||||
self.buzzer = nil
|
||||
end
|
||||
|
||||
if (!ix.shuttingDown and !self.ixIsSafe) then
|
||||
Schema:SaveRebelForceFields()
|
||||
end
|
||||
end
|
||||
|
||||
ENT.MODES = {
|
||||
{
|
||||
function(entity)
|
||||
return false
|
||||
end,
|
||||
"field disengaged.",
|
||||
"disengaged",
|
||||
3
|
||||
},
|
||||
{
|
||||
function(entity)
|
||||
if (!entity:IsPlayer()) then return true end
|
||||
|
||||
local character = entity:GetCharacter()
|
||||
if (!character or !character:GetInventory()) then
|
||||
return true
|
||||
end
|
||||
|
||||
if (!character:GetInventory():HasItem("id_card", {active = true})) then
|
||||
if character:IsVortigaunt() and
|
||||
character:GetCollarItemID() and
|
||||
ix.item.instances[character:GetCollarItemID()] and
|
||||
-ix.config.Get("blacklistSCAmount", 40) <= ix.item.instances[character:GetCollarItemID()]:GetData("sterilizedCredits", 0) then
|
||||
return false
|
||||
end
|
||||
return false
|
||||
else
|
||||
return false
|
||||
end
|
||||
end,
|
||||
"allow all individuals",
|
||||
"engaged",
|
||||
0
|
||||
},
|
||||
{
|
||||
function(entity)
|
||||
return true
|
||||
end,
|
||||
"disallow combine forces.",
|
||||
"restricted",
|
||||
1
|
||||
},
|
||||
{
|
||||
function(entity)
|
||||
return true
|
||||
end,
|
||||
"disallow non-functionary units (Unused Variant... ignore and change!!!)",
|
||||
"restricted",
|
||||
2
|
||||
}
|
||||
}
|
||||
|
||||
function ENT:Use(activator)
|
||||
if ((self.nextUse or 0) < CurTime()) then
|
||||
self.nextUse = CurTime() + 1.5
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
local bForced = CAMI.PlayerHasAccess(activator, "Helix - Basic Admin Commands", nil) and activator:GetMoveType() == MOVETYPE_NOCLIP
|
||||
|
||||
if (activator:GetCharacter():HasFlags("F") or bForced) then
|
||||
self:SetMode(self:GetMode() + 1)
|
||||
local action = "modified"
|
||||
|
||||
if (self:GetMode() > #self.MODES) then
|
||||
self:SetMode(MODE_OFFLINE)
|
||||
self:CollisionRulesChanged()
|
||||
|
||||
self:SetSkin(self.MODES[1][4])
|
||||
self.dummy:SetSkin(self.MODES[1][4])
|
||||
self:EmitSound("npc/turret_floor/die.wav")
|
||||
else
|
||||
self:CollisionRulesChanged()
|
||||
|
||||
self:SetSkin(self.MODES[self:GetMode()][4])
|
||||
self.dummy:SetSkin(self.MODES[self:GetMode()][4])
|
||||
end
|
||||
|
||||
self:EmitSound("buttons/combine_button5.wav", 140, 100 + (self:GetMode() - 1) * 15)
|
||||
activator:ChatPrint("Changed barrier mode to: " .. self.MODES[self:GetMode()][2])
|
||||
|
||||
Schema:SaveRebelForceFields()
|
||||
if (bForced) then return end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Malfunction()
|
||||
local bMalfunctioning = self:GetMalfunctioning()
|
||||
if (!bMalfunctioning) then return end
|
||||
|
||||
timer.Simple(math.random(0.2, 1), function()
|
||||
if (!self:IsValid()) then return end
|
||||
|
||||
self:SetMode(MODE_OFFLINE)
|
||||
self:CollisionRulesChanged()
|
||||
|
||||
self:SetSkin(self.MODES[1][4])
|
||||
self.dummy:SetSkin(self.MODES[1][4])
|
||||
self:EmitSound("buttons/combine_button5.wav", 65, 100 + (self:GetMode() - 1) * 15)
|
||||
self:EmitSound("npc/turret_floor/die.wav", 55)
|
||||
|
||||
local target = math.random(2) == 1 and self or self:GetDummy()
|
||||
local vPoint = target:GetPos() + Vector(0, 0, math.random(-10, 100)) + target:GetRight() * (target == self and -10 or 10)
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin(vPoint)
|
||||
util.Effect("ManhackSparks", effectdata)
|
||||
|
||||
if (math.random(2) == 1) then
|
||||
target = math.random(2) == 1 and self or self:GetDummy()
|
||||
vPoint = target:GetPos() + Vector(0, 0, math.random(-10, 100)) + target:GetRight() * (target == self and -10 or 10)
|
||||
effectdata = EffectData()
|
||||
effectdata:SetOrigin(vPoint)
|
||||
util.Effect("ManhackSparks", effectdata)
|
||||
end
|
||||
|
||||
self:EmitSound("ambient/energy/zap" .. math.random(1, 9) .. ".wav", 65)
|
||||
|
||||
timer.Simple(math.random(1, 5), function()
|
||||
if (!self:IsValid()) then return end
|
||||
|
||||
self:SetMode(math.random(2, 4))
|
||||
self:CollisionRulesChanged()
|
||||
|
||||
self:SetSkin(self.MODES[self:GetMode()][4])
|
||||
self.dummy:SetSkin(self.MODES[self:GetMode()][4])
|
||||
|
||||
self:EmitSound("buttons/combine_button5.wav", 65, 100 + (self:GetMode() - 1) * 15)
|
||||
|
||||
self:Malfunction()
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
hook.Add("ShouldCollide", "ix_rebelfields", function(a, b)
|
||||
local entity
|
||||
local forcefield
|
||||
|
||||
if (a:GetClass() == "ix_rebelfield") then
|
||||
entity = b
|
||||
forcefield = a
|
||||
elseif (b:GetClass() == "ix_rebelfield") then
|
||||
entity = a
|
||||
forcefield = b
|
||||
end
|
||||
|
||||
if (IsValid(forcefield)) then
|
||||
if (IsValid(entity)) then
|
||||
if (entity:IsPlayer() and ix.faction.Get(entity:Team()).allowRebelForcefieldPassage) then
|
||||
return false
|
||||
end
|
||||
|
||||
local mode = forcefield:GetMode() or MODE_OFFLINE
|
||||
|
||||
return istable(forcefield.MODES[mode]) and forcefield.MODES[mode][1](entity)
|
||||
else
|
||||
return forcefield:GetMode() != 5
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
SHIELD_MATERIALS = {
|
||||
nil,
|
||||
ix.util.GetMaterial("models/effects/shield_blue"),
|
||||
ix.util.GetMaterial("models/effects/shield_red"),
|
||||
ix.util.GetMaterial("models/effects/shield_yellow")
|
||||
}
|
||||
|
||||
function ENT:Initialize()
|
||||
local data = {}
|
||||
data.start = self:GetPos() + self:GetRight()*-16
|
||||
data.endpos = self:GetPos() + self:GetRight()*-480
|
||||
data.filter = self
|
||||
local trace = util.TraceLine(data)
|
||||
|
||||
self:SetCustomCollisionCheck(true)
|
||||
self:PhysicsInitConvex({
|
||||
vector_origin,
|
||||
Vector(0, 0, 150),
|
||||
trace.HitPos + Vector(0, 0, 150),
|
||||
trace.HitPos
|
||||
})
|
||||
|
||||
self.distance = self:GetPos():Distance(trace.HitPos)
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetMode() == MODE_OFFLINE) then
|
||||
return
|
||||
end
|
||||
|
||||
local pos = self:GetPos()
|
||||
local angles = self:GetAngles()
|
||||
local matrix = Matrix()
|
||||
matrix:Translate(pos + self:GetUp() * -40)
|
||||
matrix:Rotate(angles)
|
||||
|
||||
render.SetMaterial(SHIELD_MATERIALS[self:GetMode()])
|
||||
|
||||
local dummy = self:GetDummy()
|
||||
|
||||
if (IsValid(dummy)) then
|
||||
local dummyPos = dummy:GetPos()
|
||||
local vertex = self:WorldToLocal(dummyPos)
|
||||
self:SetRenderBounds(vector_origin, vertex + self:GetUp() * 150)
|
||||
|
||||
cam.PushModelMatrix(matrix)
|
||||
self:DrawShield(vertex)
|
||||
cam.PopModelMatrix()
|
||||
|
||||
matrix:Translate(vertex)
|
||||
matrix:Rotate(Angle(0, 180, 0))
|
||||
|
||||
cam.PushModelMatrix(matrix)
|
||||
self:DrawShield(vertex)
|
||||
cam.PopModelMatrix()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DrawShield(vertex)
|
||||
mesh.Begin(MATERIAL_QUADS, 1)
|
||||
mesh.Position(vector_origin)
|
||||
mesh.TexCoord(0, 0, 0)
|
||||
mesh.AdvanceVertex()
|
||||
|
||||
mesh.Position(self:GetUp() * 190)
|
||||
mesh.TexCoord(0, 0, 3)
|
||||
mesh.AdvanceVertex()
|
||||
|
||||
mesh.Position(vertex + self:GetUp() * 190)
|
||||
mesh.TexCoord(0, 3, 3)
|
||||
mesh.AdvanceVertex()
|
||||
|
||||
mesh.Position(vertex)
|
||||
mesh.TexCoord(0, 3, 0)
|
||||
mesh.AdvanceVertex()
|
||||
mesh.End()
|
||||
end
|
||||
end
|
||||
|
||||
properties.Add("ixRebelfieldStartMalfunction", {
|
||||
MenuLabel = "Start Malfunctioning",
|
||||
Order = 500,
|
||||
MenuIcon = "icon16/lightning_add.png",
|
||||
|
||||
Filter = function(self, entity, client)
|
||||
if (entity:GetClass() == "ix_rebelfield" and !entity:GetMalfunctioning() and CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands", nil)) then return true end
|
||||
end,
|
||||
|
||||
Action = function(self, entity)
|
||||
self:MsgStart()
|
||||
net.WriteEntity(entity)
|
||||
self:MsgEnd()
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
local entity = net.ReadEntity()
|
||||
|
||||
if (!IsValid(entity)) then return end
|
||||
if (!self:Filter(entity, client)) then return end
|
||||
|
||||
entity:SetMalfunctioning(true)
|
||||
entity:Malfunction()
|
||||
end
|
||||
})
|
||||
|
||||
properties.Add("ixRebelfieldStopMalfunction", {
|
||||
MenuLabel = "Stop Malfunctioning",
|
||||
Order = 500,
|
||||
MenuIcon = "icon16/lightning_delete.png",
|
||||
|
||||
Filter = function(self, entity, client)
|
||||
if (entity:GetClass() == "ix_rebelfield" and entity:GetMalfunctioning() and CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands", nil)) then return true end
|
||||
end,
|
||||
|
||||
Action = function(self, entity)
|
||||
self:MsgStart()
|
||||
net.WriteEntity(entity)
|
||||
self:MsgEnd()
|
||||
end,
|
||||
|
||||
Receive = function(self, length, client)
|
||||
local entity = net.ReadEntity()
|
||||
|
||||
if (!IsValid(entity)) then return end
|
||||
if (!self:Filter(entity, client)) then return end
|
||||
|
||||
entity:SetMalfunctioning(false)
|
||||
end
|
||||
})
|
||||
346
gamemodes/darkrp/entities/weapons/gmod_tool/shared.lua
Normal file
346
gamemodes/darkrp/entities/weapons/gmod_tool/shared.lua
Normal file
@@ -0,0 +1,346 @@
|
||||
--[[
|
||||
| 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 = "Tool Gun"
|
||||
SWEP.Author = ""
|
||||
SWEP.Contact = ""
|
||||
SWEP.Purpose = ""
|
||||
SWEP.Instructions = ""
|
||||
|
||||
SWEP.ViewModel = "models/weapons/c_toolgun.mdl"
|
||||
SWEP.WorldModel = "models/weapons/w_toolgun.mdl"
|
||||
|
||||
SWEP.UseHands = true
|
||||
SWEP.Spawnable = true
|
||||
|
||||
-- Be nice, precache the models
|
||||
util.PrecacheModel( SWEP.ViewModel )
|
||||
util.PrecacheModel( SWEP.WorldModel )
|
||||
|
||||
-- Todo, make/find a better sound.
|
||||
-- SWEP.ShootSound = Sound( "Airboat.FireGunRevDown" )
|
||||
SWEP.ShootSound = Sound( "" )
|
||||
|
||||
SWEP.Tool = {}
|
||||
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Automatic = false
|
||||
SWEP.Primary.Ammo = "none"
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.DefaultClip = -1
|
||||
SWEP.Secondary.Automatic = false
|
||||
SWEP.Secondary.Ammo = "none"
|
||||
|
||||
SWEP.CanHolster = true
|
||||
SWEP.CanDeploy = true
|
||||
|
||||
function SWEP:InitializeTools()
|
||||
|
||||
local temp = {}
|
||||
|
||||
for k,v in pairs( self.Tool ) do
|
||||
|
||||
temp[k] = table.Copy( v )
|
||||
temp[k].SWEP = self
|
||||
temp[k].Owner = self.Owner
|
||||
temp[k].Weapon = self.Weapon
|
||||
temp[k]:Init()
|
||||
|
||||
end
|
||||
|
||||
self.Tool = temp
|
||||
|
||||
end
|
||||
|
||||
function SWEP:SetupDataTables()
|
||||
|
||||
self:NetworkVar( "Entity", 0, "TargetEntity1" )
|
||||
self:NetworkVar( "Entity", 1, "TargetEntity2" )
|
||||
self:NetworkVar( "Entity", 2, "TargetEntity3" )
|
||||
self:NetworkVar( "Entity", 3, "TargetEntity4" )
|
||||
|
||||
end
|
||||
|
||||
-- Convenience function to check object limits
|
||||
function SWEP:CheckLimit( str )
|
||||
return self:GetOwner():CheckLimit( str )
|
||||
end
|
||||
|
||||
function SWEP:Initialize()
|
||||
|
||||
self:SetHoldType( "revolver" )
|
||||
|
||||
self:InitializeTools()
|
||||
|
||||
-- We create these here. The problem is that these are meant to be constant values.
|
||||
-- in the toolmode they're not because some tools can be automatic while some tools aren't.
|
||||
-- Since this is a global table it's shared between all instances of the gun.
|
||||
-- By creating new tables here we're making it so each tool has its own instance of the table
|
||||
-- So changing it won't affect the other tools.
|
||||
|
||||
self.Primary = {
|
||||
ClipSize = -1,
|
||||
DefaultClip = -1,
|
||||
Automatic = false,
|
||||
Ammo = "none"
|
||||
}
|
||||
|
||||
self.Secondary = {
|
||||
ClipSize = -1,
|
||||
DefaultClip = -1,
|
||||
Automatic = false,
|
||||
Ammo = "none"
|
||||
}
|
||||
|
||||
end
|
||||
|
||||
function SWEP:OnRestore()
|
||||
|
||||
self:InitializeTools()
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Precache()
|
||||
|
||||
util.PrecacheSound( self.ShootSound )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Reload()
|
||||
|
||||
-- This makes the reload a semi-automatic thing rather than a continuous thing
|
||||
if ( !self.Owner:KeyPressed( IN_RELOAD ) ) then return end
|
||||
|
||||
local mode = self:GetMode()
|
||||
local trace = self.Owner:GetEyeTrace()
|
||||
if ( !trace.Hit ) then return end
|
||||
|
||||
local tool = self:GetToolObject()
|
||||
if ( !tool ) then return end
|
||||
|
||||
tool:CheckObjects()
|
||||
|
||||
-- Does the server setting say it's ok?
|
||||
if ( !tool:Allowed() ) then return end
|
||||
|
||||
-- Ask the gamemode if it's ok to do this
|
||||
if ( !gamemode.Call( "CanTool", self.Owner, trace, mode ) ) then return end
|
||||
|
||||
if ( !tool:Reload( trace ) ) then return end
|
||||
|
||||
self:DoShootEffect( trace.HitPos, trace.HitNormal, trace.Entity, trace.PhysicsBone, IsFirstTimePredicted() )
|
||||
|
||||
end
|
||||
|
||||
-- Returns the mode we're in
|
||||
function SWEP:GetMode()
|
||||
|
||||
return self.Mode
|
||||
|
||||
end
|
||||
|
||||
-- Think does stuff every frame
|
||||
function SWEP:Think()
|
||||
|
||||
self.Mode = self.Owner:GetInfo( "gmod_toolmode" )
|
||||
|
||||
local tool = self:GetToolObject()
|
||||
if ( !tool ) then return end
|
||||
|
||||
tool:CheckObjects()
|
||||
|
||||
self.last_mode = self.current_mode
|
||||
self.current_mode = self.Mode
|
||||
|
||||
-- Release ghost entities if we're not allowed to use this new mode?
|
||||
if ( !tool:Allowed() ) then
|
||||
self:GetToolObject( self.last_mode ):ReleaseGhostEntity()
|
||||
return
|
||||
end
|
||||
|
||||
if ( self.last_mode != self.current_mode ) then
|
||||
|
||||
if ( !self:GetToolObject( self.last_mode ) ) then return end
|
||||
|
||||
-- We want to release the ghost entity just in case
|
||||
self:GetToolObject( self.last_mode ):Holster()
|
||||
|
||||
end
|
||||
|
||||
self.Primary.Automatic = tool.LeftClickAutomatic or false
|
||||
self.Secondary.Automatic = tool.RightClickAutomatic or false
|
||||
self.RequiresTraceHit = tool.RequiresTraceHit or true
|
||||
|
||||
tool:Think()
|
||||
|
||||
end
|
||||
|
||||
-- The shoot effect
|
||||
function SWEP:DoShootEffect( hitpos, hitnormal, entity, physbone, bFirstTimePredicted )
|
||||
|
||||
self:EmitSound( self.ShootSound )
|
||||
self:SendWeaponAnim( ACT_VM_PRIMARYATTACK ) -- View model animation
|
||||
|
||||
-- There's a bug with the model that's causing a muzzle to
|
||||
-- appear on everyone's screen when we fire this animation.
|
||||
self.Owner:SetAnimation( PLAYER_ATTACK1 ) -- 3rd Person Animation
|
||||
|
||||
if ( !bFirstTimePredicted ) then return end
|
||||
|
||||
--[[
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( hitpos )
|
||||
effectdata:SetNormal( hitnormal )
|
||||
effectdata:SetEntity( entity )
|
||||
effectdata:SetAttachment( physbone )
|
||||
util.Effect( "selection_indicator", effectdata )
|
||||
|
||||
|
||||
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin( hitpos )
|
||||
effectdata:SetStart( self.Owner:GetShootPos() )
|
||||
effectdata:SetAttachment( 1 )
|
||||
effectdata:SetEntity( self )
|
||||
util.Effect( "ToolTracer", effectdata )
|
||||
|
||||
--]]
|
||||
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
ix.log.AddType("toolgunFired", function(client, name)
|
||||
return string.format("%s has fired a toolgun with the name: %s", client:GetName(), name)
|
||||
end)
|
||||
end
|
||||
|
||||
-- Trace a line then send the result to a mode function
|
||||
function SWEP:PrimaryAttack()
|
||||
|
||||
local mode = self:GetMode()
|
||||
local tr = util.GetPlayerTrace( self.Owner )
|
||||
tr.mask = bit.bor( CONTENTS_SOLID, CONTENTS_MOVEABLE, CONTENTS_MONSTER, CONTENTS_WINDOW, CONTENTS_DEBRIS, CONTENTS_GRATE, CONTENTS_AUX )
|
||||
local trace = util.TraceLine( tr )
|
||||
if ( !trace.Hit ) then return end
|
||||
|
||||
local tool = self:GetToolObject()
|
||||
if ( !tool ) then return end
|
||||
|
||||
tool:CheckObjects()
|
||||
|
||||
-- Does the server setting say it's ok?
|
||||
if ( !tool:Allowed() ) then return end
|
||||
|
||||
-- Ask the gamemode if it's ok to do this
|
||||
if ( !gamemode.Call( "CanTool", self.Owner, trace, mode ) ) then return end
|
||||
if (SERVER) then
|
||||
ix.log.Add(self:GetOwner(), "toolgunFired", self:GetMode())
|
||||
end
|
||||
|
||||
if ( !tool:LeftClick( trace ) ) then return end
|
||||
|
||||
self:DoShootEffect( trace.HitPos, trace.HitNormal, trace.Entity, trace.PhysicsBone, IsFirstTimePredicted() )
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
|
||||
local mode = self:GetMode()
|
||||
local tr = util.GetPlayerTrace( self.Owner )
|
||||
tr.mask = bit.bor( CONTENTS_SOLID, CONTENTS_MOVEABLE, CONTENTS_MONSTER, CONTENTS_WINDOW, CONTENTS_DEBRIS, CONTENTS_GRATE, CONTENTS_AUX )
|
||||
local trace = util.TraceLine( tr )
|
||||
if ( !trace.Hit ) then return end
|
||||
|
||||
local tool = self:GetToolObject()
|
||||
if ( !tool ) then return end
|
||||
|
||||
tool:CheckObjects()
|
||||
|
||||
-- Ask the gamemode if it's ok to do this
|
||||
if ( !tool:Allowed() ) then return end
|
||||
if ( !gamemode.Call( "CanTool", self.Owner, trace, mode ) ) then return end
|
||||
|
||||
if ( !tool:RightClick( trace ) ) then return end
|
||||
|
||||
self:DoShootEffect( trace.HitPos, trace.HitNormal, trace.Entity, trace.PhysicsBone, IsFirstTimePredicted() )
|
||||
|
||||
end
|
||||
|
||||
function SWEP:Holster()
|
||||
|
||||
-- Just do what the SWEP wants to do if there's no tool
|
||||
if ( !self:GetToolObject() ) then return self.CanHolster end
|
||||
|
||||
local CanHolster = self:GetToolObject():Holster()
|
||||
if ( CanHolster ~= nil ) then return CanHolster end
|
||||
|
||||
return self.CanHolster
|
||||
|
||||
end
|
||||
|
||||
-- Delete ghosts here in case the weapon gets deleted all of a sudden somehow
|
||||
function SWEP:OnRemove()
|
||||
|
||||
if ( !self:GetToolObject() ) then return end
|
||||
|
||||
self:GetToolObject():ReleaseGhostEntity()
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- This will remove any ghosts when a player dies and drops the weapon
|
||||
function SWEP:OwnerChanged()
|
||||
|
||||
if ( !self:GetToolObject() ) then return end
|
||||
|
||||
self:GetToolObject():ReleaseGhostEntity()
|
||||
|
||||
end
|
||||
|
||||
-- Deploy
|
||||
function SWEP:Deploy()
|
||||
|
||||
-- Just do what the SWEP wants to do if there is no tool
|
||||
if ( !self:GetToolObject() ) then return self.CanDeploy end
|
||||
|
||||
self:GetToolObject():UpdateData()
|
||||
|
||||
local CanDeploy = self:GetToolObject():Deploy()
|
||||
if ( CanDeploy ~= nil ) then return CanDeploy end
|
||||
|
||||
return self.CanDeploy
|
||||
|
||||
end
|
||||
|
||||
function SWEP:GetToolObject( tool )
|
||||
|
||||
local mode = tool or self:GetMode()
|
||||
|
||||
if ( !self.Tool[ mode ] ) then return false end
|
||||
|
||||
return self.Tool[ mode ]
|
||||
|
||||
end
|
||||
|
||||
function SWEP:FireAnimationEvent( pos, ang, event, options )
|
||||
|
||||
-- Disables animation based muzzle event
|
||||
if ( event == 21 ) then return true end
|
||||
-- Disable thirdperson muzzle flash
|
||||
if ( event == 5003 ) then return true end
|
||||
|
||||
end
|
||||
|
||||
include( "stool.lua" )
|
||||
162
gamemodes/darkrp/entities/weapons/gmod_tool/stools/paint.lua
Normal file
162
gamemodes/darkrp/entities/weapons/gmod_tool/stools/paint.lua
Normal file
@@ -0,0 +1,162 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
TOOL.Category = "Render"
|
||||
TOOL.Name = "#tool.paint.name"
|
||||
|
||||
TOOL.LeftClickAutomatic = true
|
||||
TOOL.RightClickAutomatic = true
|
||||
TOOL.RequiresTraceHit = true
|
||||
|
||||
TOOL.ClientConVar[ "decal" ] = "Blood"
|
||||
|
||||
TOOL.Information = {
|
||||
{ name = "left" },
|
||||
{ name = "right" },
|
||||
{ name = "reload" }
|
||||
}
|
||||
|
||||
local function PlaceDecal( ply, ent, data )
|
||||
|
||||
if ( !IsValid( ent ) && !ent:IsWorld() ) then return end
|
||||
|
||||
local bone = ent:GetPhysicsObjectNum( data.bone or 0 )
|
||||
if ( !IsValid( bone ) ) then bone = ent end
|
||||
|
||||
if ( SERVER ) then
|
||||
util.Decal( data.decal, bone:LocalToWorld( data.Pos1 ), bone:LocalToWorld( data.Pos2 ), ply )
|
||||
|
||||
local i = ent.DecalCount or 0
|
||||
i = i + 1
|
||||
duplicator.StoreEntityModifier( ent, "decal" .. i, data )
|
||||
ent.DecalCount = i
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--
|
||||
-- Register decal duplicator
|
||||
--
|
||||
for i = 1, 32 do
|
||||
|
||||
duplicator.RegisterEntityModifier( "decal" .. i, function( ply, ent, data )
|
||||
timer.Simple( i * 0.05, function() PlaceDecal( ply, ent, data ) end )
|
||||
end )
|
||||
|
||||
end
|
||||
|
||||
function TOOL:Reload( trace )
|
||||
if ( !IsValid( trace.Entity ) ) then return false end
|
||||
|
||||
trace.Entity:RemoveAllDecals()
|
||||
|
||||
if ( SERVER ) then
|
||||
for i = 1, 32 do
|
||||
duplicator.ClearEntityModifier( trace.Entity, "decal" .. i )
|
||||
end
|
||||
trace.Entity.DecalCount = nil
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function TOOL:LeftClick( trace )
|
||||
|
||||
return self:RightClick( trace, true )
|
||||
|
||||
end
|
||||
|
||||
function TOOL:RightClick( trace, bNoDelay )
|
||||
|
||||
local decal = self:GetClientInfo( "decal" )
|
||||
|
||||
local Pos1 = trace.HitPos + trace.HitNormal
|
||||
local Pos2 = trace.HitPos - trace.HitNormal
|
||||
|
||||
local Bone = trace.Entity:GetPhysicsObjectNum( trace.PhysicsBone or 0 )
|
||||
if ( !IsValid( Bone ) ) then Bone = trace.Entity end
|
||||
|
||||
Pos1 = Bone:WorldToLocal( Pos1 )
|
||||
Pos2 = Bone:WorldToLocal( Pos2 )
|
||||
|
||||
PlaceDecal( self:GetOwner(), trace.Entity, { Pos1 = Pos1, Pos2 = Pos2, bone = trace.PhysicsBone, decal = decal } )
|
||||
|
||||
if ( bNoDelay ) then
|
||||
self:GetWeapon():SetNextPrimaryFire( CurTime() + 0.05 )
|
||||
self:GetWeapon():SetNextSecondaryFire( CurTime() + 0.05 )
|
||||
else
|
||||
self:GetWeapon():SetNextPrimaryFire( CurTime() + 0.2 )
|
||||
self:GetWeapon():SetNextSecondaryFire( CurTime() + 0.2 )
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
game.AddDecal( "Eye", "decals/eye" )
|
||||
game.AddDecal( "Dark", "decals/dark" )
|
||||
game.AddDecal( "Smile", "decals/smile" )
|
||||
game.AddDecal( "Light", "decals/light" )
|
||||
game.AddDecal( "Cross", "decals/cross" )
|
||||
game.AddDecal( "Nought", "decals/nought" )
|
||||
game.AddDecal( "Noughtsncrosses", "decals/noughtsncrosses" )
|
||||
|
||||
list.Add( "PaintMaterials", "Eye" )
|
||||
list.Add( "PaintMaterials", "Smile" )
|
||||
list.Add( "PaintMaterials", "Light" )
|
||||
list.Add( "PaintMaterials", "Dark" )
|
||||
list.Add( "PaintMaterials", "Blood" )
|
||||
list.Add( "PaintMaterials", "YellowBlood" )
|
||||
list.Add( "PaintMaterials", "Impact.Metal" )
|
||||
list.Add( "PaintMaterials", "Scorch" )
|
||||
list.Add( "PaintMaterials", "BeerSplash" )
|
||||
list.Add( "PaintMaterials", "ExplosiveGunshot" )
|
||||
list.Add( "PaintMaterials", "BirdPoop" )
|
||||
list.Add( "PaintMaterials", "PaintSplatPink" )
|
||||
list.Add( "PaintMaterials", "PaintSplatGreen" )
|
||||
list.Add( "PaintMaterials", "PaintSplatBlue" )
|
||||
list.Add( "PaintMaterials", "ManhackCut" )
|
||||
list.Add( "PaintMaterials", "FadingScorch" )
|
||||
list.Add( "PaintMaterials", "Antlion.Splat" )
|
||||
list.Add( "PaintMaterials", "Splash.Large" )
|
||||
list.Add( "PaintMaterials", "BulletProof" )
|
||||
list.Add( "PaintMaterials", "GlassBreak" )
|
||||
list.Add( "PaintMaterials", "Impact.Sand" )
|
||||
list.Add( "PaintMaterials", "Impact.BloodyFlesh" )
|
||||
list.Add( "PaintMaterials", "Impact.Antlion" )
|
||||
list.Add( "PaintMaterials", "Impact.Glass" )
|
||||
list.Add( "PaintMaterials", "Impact.Wood" )
|
||||
list.Add( "PaintMaterials", "Impact.Concrete" )
|
||||
list.Add( "PaintMaterials", "Noughtsncrosses" )
|
||||
list.Add( "PaintMaterials", "Nought" )
|
||||
list.Add( "PaintMaterials", "Cross" )
|
||||
|
||||
function TOOL.BuildCPanel( CPanel )
|
||||
|
||||
-- Remove duplicates.
|
||||
local Options = {}
|
||||
for id, str in pairs( list.Get( "PaintMaterials" ) ) do
|
||||
if ( !table.HasValue( Options, str ) ) then
|
||||
table.insert( Options, str )
|
||||
end
|
||||
end
|
||||
|
||||
table.sort( Options )
|
||||
|
||||
local listbox = CPanel:AddControl( "ListBox", { Label = "#tool.paint.texture", Height = 17 + table.Count( Options ) * 17 } )
|
||||
for k, decal in pairs( Options ) do
|
||||
local line = listbox:AddLine( decal )
|
||||
line.data = { paint_decal = decal }
|
||||
|
||||
if ( GetConVarString( "paint_decal" ) == tostring( decal ) ) then line:SetSelected( true ) end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,105 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
TOOL.Category = "HL2RP Staff QoL"
|
||||
TOOL.Name = "NPC Spawner Editor"
|
||||
TOOL.RequiresTraceHit = true
|
||||
|
||||
TOOL.Information = {
|
||||
{ name = "left" },
|
||||
{ name = "right" },
|
||||
{ name = "reload" }
|
||||
}
|
||||
function TOOL:GetPlayerBoundsTrace()
|
||||
local client = self:GetOwner()
|
||||
|
||||
return util.TraceLine({
|
||||
start = client:GetShootPos(),
|
||||
endpos = client:GetShootPos() + client:GetForward() * 96,
|
||||
filter = client
|
||||
})
|
||||
end
|
||||
function TOOL:LeftClick( trace )
|
||||
|
||||
|
||||
if (SERVER) then
|
||||
if !CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands") then return false end
|
||||
|
||||
local entity = trace.Entity
|
||||
if !entity or entity and !IsValid(entity) then return end
|
||||
if !self.GetOwner then return end
|
||||
if !self:GetOwner() then return end
|
||||
if !IsValid(self:GetOwner()) then return end
|
||||
if entity:GetClass() != "ix_npcspawner" then return end
|
||||
entity:Use(self:GetOwner())
|
||||
end
|
||||
end
|
||||
function TOOL:RightClick( trace )
|
||||
local entity = trace.Entity
|
||||
local client = self:GetOwner()
|
||||
if !entity or entity and !IsValid(entity) then
|
||||
client.npcEditStart = nil
|
||||
client.npcEnt = nil
|
||||
return
|
||||
end
|
||||
if !self.GetOwner then return end
|
||||
if !self:GetOwner() then return end
|
||||
if !IsValid(self:GetOwner()) then return end
|
||||
if entity:GetClass() != "ix_npcspawner" then return end
|
||||
if client.npcEditStart then
|
||||
client.npcEditStart = nil
|
||||
client.npcEnt = nil
|
||||
else
|
||||
client.npcEditStart = entity:GetPos() + (entity:GetForward() * -60 + entity:GetRight()*-40 + entity:GetUp()*128)
|
||||
client.npcEnt = entity
|
||||
end
|
||||
end
|
||||
function TOOL:Reload(trace)
|
||||
local client = self:GetOwner()
|
||||
if !CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands") then return false end
|
||||
if !self.GetOwner then return end
|
||||
if !self:GetOwner() then return end
|
||||
if !IsValid(self:GetOwner()) then return end
|
||||
if !client.npcEditStart or !client.npcEnt then return end
|
||||
local tr = util.TraceLine({
|
||||
start = client:GetShootPos(),
|
||||
endpos = client:GetShootPos() + client:GetForward() * 96,
|
||||
filter = client
|
||||
})
|
||||
client.npcEnt:SetSpawnPosStart(client.npcEditStart)
|
||||
client.npcEnt:SetSpawnPosEnd(tr.HitPos)
|
||||
|
||||
client.npcEditStart = nil
|
||||
client.npcEnt = nil
|
||||
end
|
||||
if CLIENT then
|
||||
hook.Add("PostDrawTranslucentRenderables", "NPCSpawnEdit", function(bDepth, bSkybox)
|
||||
if ( bSkybox ) then return end
|
||||
if LocalPlayer().npcEditStart then
|
||||
local tr = util.TraceLine({
|
||||
start = LocalPlayer():GetShootPos(),
|
||||
endpos = LocalPlayer():GetShootPos() + LocalPlayer():GetForward() * 96,
|
||||
filter = LocalPlayer()
|
||||
})
|
||||
local center, min, max = LocalPlayer().npcEnt:SpawnAreaPosition(LocalPlayer().npcEditStart, tr.HitPos)
|
||||
local color = Color(255, 255, 255, 255)
|
||||
|
||||
render.DrawWireframeBox(center, angle_zero, min, max, color)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
language.Add( "Tool.sh_npcspawnedit.name", "NPC Spawner Configurator" )
|
||||
language.Add( "Tool.sh_npcspawnedit.desc", "You can edit NPC spawner entities with it." )
|
||||
language.Add( "Tool.sh_npcspawnedit.left", "Open spawner menu" )
|
||||
language.Add( "Tool.sh_npcspawnedit.right", "Edit spawner area bounds. Click again to stop changing bounds." )
|
||||
language.Add( "Tool.sh_npcspawnedit.reload", "Save your area bound changes." )
|
||||
end
|
||||
@@ -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/
|
||||
--]]
|
||||
|
||||
|
||||
TOOL.Category = "HL2RP Staff QoL"
|
||||
TOOL.Name = "Panel Add"
|
||||
TOOL.RequiresTraceHit = true
|
||||
|
||||
TOOL.ClientConVar[ "url" ] = ""
|
||||
TOOL.ClientConVar[ "scale" ] = 1
|
||||
TOOL.ClientConVar[ "brightness" ] = 100
|
||||
|
||||
TOOL.Information = {
|
||||
{ name = "left" },
|
||||
{ name = "right" },
|
||||
{ name = "reload" }
|
||||
}
|
||||
|
||||
function TOOL:LeftClick( trace )
|
||||
if (SERVER) then
|
||||
if !CAMI.PlayerHasAccess(self:GetOwner(), "Helix - Basic Admin Commands") then return false end
|
||||
|
||||
local position = trace.HitPos
|
||||
local angles = trace.HitNormal:Angle()
|
||||
angles:RotateAroundAxis(angles:Up(), 90)
|
||||
angles:RotateAroundAxis(angles:Forward(), 90)
|
||||
|
||||
if !ix.plugin.list then return end
|
||||
if !ix.plugin.list["3dpanel"] then return end
|
||||
if !ix.plugin.list["3dpanel"].AddPanel then return end
|
||||
|
||||
local url = self:GetClientInfo( "url", "" )
|
||||
local scale = self:GetClientNumber( "scale", 0 )
|
||||
local brightness = self:GetClientNumber( "brightness", 0 )
|
||||
|
||||
ix.plugin.list["3dpanel"]:AddPanel(position + angles:Up() * 0.1, angles, url, scale, brightness)
|
||||
|
||||
return "@panelAdded"
|
||||
end
|
||||
end
|
||||
|
||||
function TOOL:RightClick( trace )
|
||||
if !ix.plugin.list then return end
|
||||
if !ix.plugin.list["3dpanel"] then return end
|
||||
if !ix.plugin.list["3dpanel"].RemovePanel then return end
|
||||
|
||||
local position = trace.HitPos
|
||||
-- Remove the panel(s) and get the amount removed.
|
||||
local amount = ix.plugin.list["3dpanel"]:RemovePanel(position, false)
|
||||
|
||||
return "@panelRemoved", amount
|
||||
end
|
||||
|
||||
function TOOL.BuildCPanel( CPanel )
|
||||
CPanel:AddControl( "Header", { Description = "Enter URL!" } )
|
||||
CPanel:AddControl( "textbox", { Label = "URL", Command = "sh_paneladd_url", Help = false } )
|
||||
CPanel:AddControl( "Slider", { Label = "Scale", Command = "sh_paneladd_scale", Type = "Float", Min = 0.001, Max = 5, Help = false } )
|
||||
CPanel:AddControl( "Slider", { Label = "Brightness", Command = "sh_paneladd_brightness", Type = "Float", Min = 0, Max = 255, Help = false } )
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
language.Add( "Tool.sh_paneladd.name", "Panel Add" )
|
||||
language.Add( "Tool.sh_paneladd.desc", "Same as /paneladd" )
|
||||
language.Add( "Tool.sh_paneladd.left", "Primary: Add Panel" )
|
||||
language.Add( "Tool.sh_paneladd.right", "Right Click: Remove Panel" )
|
||||
language.Add( "Tool.sh_paneladd.reload", "Nothing." )
|
||||
end
|
||||
@@ -0,0 +1,84 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
TOOL.Category = "HL2RP Staff QoL"
|
||||
TOOL.Name = "Persist"
|
||||
TOOL.RequiresTraceHit = true
|
||||
|
||||
TOOL.Information = {
|
||||
{ name = "left" },
|
||||
{ name = "right" },
|
||||
{ name = "reload" }
|
||||
}
|
||||
|
||||
local function GetRealModel(entity)
|
||||
return entity:GetClass() == "prop_effect" and entity.AttachedEntity:GetModel() or entity:GetModel()
|
||||
end
|
||||
|
||||
function TOOL:LeftClick( trace )
|
||||
if (SERVER) then
|
||||
if !CAMI.PlayerHasAccess(client, "Helix - Basic Admin Commands") then return false end
|
||||
|
||||
local entity = trace.Entity
|
||||
if !entity or entity and !IsValid(entity) then return end
|
||||
if entity:IsPlayer() or entity:IsVehicle() or entity.bNoPersist then return end
|
||||
if !self.GetOwner then return end
|
||||
if !self:GetOwner() then return end
|
||||
if !IsValid(self:GetOwner()) then return end
|
||||
if !ix.plugin.list then return end
|
||||
if !ix.plugin.list["persistence"] then return end
|
||||
if !ix.plugin.list["persistence"].stored then return end
|
||||
|
||||
local lampCount = 0
|
||||
|
||||
for _, v in pairs(ix.plugin.list["persistence"].stored) do
|
||||
if IsValid(v) and v:GetClass() == "gmod_lamp" then
|
||||
lampCount = lampCount + 1
|
||||
end
|
||||
end
|
||||
|
||||
if !entity:GetNetVar("Persistent") then
|
||||
if entity:GetClass() == "gmod_lamp" and lampCount >= ix.config.Get("maxLamps", 1) then
|
||||
return self:GetOwner():Notify("Max persisted lamps reached.")
|
||||
end
|
||||
|
||||
ix.plugin.list["persistence"].stored[#ix.plugin.list["persistence"].stored + 1] = entity
|
||||
|
||||
entity:SetNetVar("Persistent", true)
|
||||
ix.saveEnts:SaveEntity(entity)
|
||||
|
||||
ix.log.Add(self:GetOwner(), "persist", GetRealModel(entity), true)
|
||||
self:GetOwner():Notify("You persisted this entity.")
|
||||
else
|
||||
for k, v in ipairs(ix.plugin.list["persistence"].stored) do
|
||||
if (v == entity) then
|
||||
table.remove(ix.plugin.list["persistence"].stored, k)
|
||||
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
entity:SetNetVar("Persistent", false)
|
||||
ix.saveEnts:DeleteEntity(entity)
|
||||
|
||||
ix.log.Add(self:GetOwner(), "persist", GetRealModel(entity), false)
|
||||
self:GetOwner():Notify("You unpersisted this entity.")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
language.Add( "Tool.sh_persist.name", "Persist" )
|
||||
language.Add( "Tool.sh_persist.desc", "Same as persist in context menu" )
|
||||
language.Add( "Tool.sh_persist.left", "Primary: Persist/Unpersist" )
|
||||
language.Add( "Tool.sh_persist.right", "Nothing." )
|
||||
language.Add( "Tool.sh_persist.reload", "Nothing." )
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
TOOL.Category = "HL2RP Staff QoL"
|
||||
TOOL.Name = "Text Add"
|
||||
TOOL.RequiresTraceHit = true
|
||||
|
||||
TOOL.ClientConVar[ "text" ] = ""
|
||||
TOOL.ClientConVar[ "scale" ] = 1
|
||||
|
||||
TOOL.Information = {
|
||||
{ name = "left" },
|
||||
{ name = "right" },
|
||||
{ name = "reload" }
|
||||
}
|
||||
|
||||
function TOOL:LeftClick( trace )
|
||||
if (SERVER) then
|
||||
if !CAMI.PlayerHasAccess(self:GetOwner(), "Helix - Basic Admin Commands") then return false end
|
||||
|
||||
local position = trace.HitPos
|
||||
local angles = trace.HitNormal:Angle()
|
||||
angles:RotateAroundAxis(angles:Up(), 90)
|
||||
angles:RotateAroundAxis(angles:Forward(), 90)
|
||||
|
||||
if !ix.plugin.list then return end
|
||||
if !ix.plugin.list["3dtext"] then return end
|
||||
if !ix.plugin.list["3dtext"].AddText then return end
|
||||
|
||||
local text = self:GetClientInfo( "text", "" )
|
||||
local scale = self:GetClientNumber( "scale", 0 )
|
||||
|
||||
local index = ix.plugin.list["3dtext"]:AddText(position + angles:Up() * 0.1, angles, text, scale)
|
||||
|
||||
undo.Create("ix3dText")
|
||||
undo.SetPlayer(self:GetOwner())
|
||||
undo.AddFunction(function()
|
||||
if (ix.plugin.list["3dtext"]:RemoveTextByID(index)) then
|
||||
ix.log.Add(self:GetOwner(), "undo3dText")
|
||||
end
|
||||
end)
|
||||
undo.Finish()
|
||||
|
||||
return "@textAdded"
|
||||
end
|
||||
end
|
||||
|
||||
function TOOL:RightClick( trace )
|
||||
if !ix.plugin.list then return end
|
||||
if !ix.plugin.list["3dtext"] then return end
|
||||
if !ix.plugin.list["3dtext"].RemoveText then return end
|
||||
|
||||
local position = trace.HitPos + trace.HitNormal * 2
|
||||
local amount = ix.plugin.list["3dtext"]:RemoveText(position, false)
|
||||
|
||||
return "@textRemoved", amount
|
||||
end
|
||||
|
||||
function TOOL.BuildCPanel( CPanel )
|
||||
CPanel:AddControl( "Header", { Description = "Enter Text!" } )
|
||||
CPanel:AddControl( "textbox", { Label = "Text", Command = "sh_textadd_text", Help = false } )
|
||||
CPanel:AddControl( "Slider", { Label = "Scale", Command = "sh_textadd_scale", Type = "Float", Min = 0.001, Max = 5, Help = false } )
|
||||
end
|
||||
|
||||
if CLIENT then
|
||||
language.Add( "Tool.sh_textadd.name", "Text Add" )
|
||||
language.Add( "Tool.sh_textadd.desc", "Same as /textadd" )
|
||||
language.Add( "Tool.sh_textadd.left", "Primary: Add Text" )
|
||||
language.Add( "Tool.sh_textadd.right", "Right Click: Remove Text." )
|
||||
language.Add( "Tool.sh_textadd.reload", "Nothing." )
|
||||
end
|
||||
313
gamemodes/darkrp/entities/weapons/ix_stunstick.lua
Normal file
313
gamemodes/darkrp/entities/weapons/ix_stunstick.lua
Normal file
@@ -0,0 +1,313 @@
|
||||
--[[
|
||||
| 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 = "CV-2000 Stun Baton"
|
||||
SWEP.Slot = 0
|
||||
SWEP.SlotPos = 5
|
||||
SWEP.DrawAmmo = false
|
||||
SWEP.DrawCrosshair = false
|
||||
end
|
||||
|
||||
SWEP.Category = "HL2 RP"
|
||||
SWEP.Author = "Chessnut"
|
||||
SWEP.Instructions = "Primary Fire: Stun.\nALT + Primary Fire: Toggle stun.\nSecondary Fire: Push/Knock."
|
||||
SWEP.Purpose = "Hitting things and knocking on doors."
|
||||
SWEP.Drop = false
|
||||
|
||||
SWEP.HoldType = "melee"
|
||||
|
||||
SWEP.Spawnable = true
|
||||
SWEP.AdminOnly = true
|
||||
|
||||
SWEP.ViewModelFOV = 47
|
||||
SWEP.ViewModelFlip = false
|
||||
SWEP.AnimPrefix = "melee"
|
||||
|
||||
SWEP.ViewTranslation = 4
|
||||
|
||||
SWEP.Primary.ClipSize = -1
|
||||
SWEP.Primary.DefaultClip = -1
|
||||
SWEP.Primary.Automatic = false
|
||||
SWEP.Primary.Ammo = ""
|
||||
SWEP.Primary.Damage = 15
|
||||
SWEP.Primary.Delay = 0.7
|
||||
|
||||
SWEP.Secondary.ClipSize = -1
|
||||
SWEP.Secondary.DefaultClip = 0
|
||||
SWEP.Secondary.Automatic = false
|
||||
SWEP.Secondary.Ammo = ""
|
||||
|
||||
SWEP.ViewModel = Model("models/weapons/c_stunstick.mdl")
|
||||
SWEP.WorldModel = Model("models/weapons/w_stunbaton.mdl")
|
||||
|
||||
SWEP.UseHands = true
|
||||
SWEP.LowerAngles = Angle(15, -10, -20)
|
||||
|
||||
SWEP.FireWhenLowered = true
|
||||
|
||||
function SWEP:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "Activated")
|
||||
end
|
||||
|
||||
function SWEP:Precache()
|
||||
util.PrecacheSound("physics/wood/wood_crate_impact_hard3.wav")
|
||||
end
|
||||
|
||||
function SWEP:Initialize()
|
||||
self:SetHoldType(self.HoldType)
|
||||
end
|
||||
|
||||
function SWEP:OnRaised()
|
||||
self.lastRaiseTime = CurTime()
|
||||
end
|
||||
|
||||
function SWEP:OnLowered()
|
||||
self:SetActivated(false)
|
||||
end
|
||||
|
||||
function SWEP:Holster(nextWep)
|
||||
self:OnLowered()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local STUNSTICK_GLOW_MATERIAL2 = Material("effects/blueflare1")
|
||||
local STUNSTICK_GLOW_MATERIAL_NOZ = Material("sprites/light_glow02_add_noz")
|
||||
|
||||
function SWEP:DrawWorldModel()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetActivated()) then
|
||||
local size = math.Rand(4.0, 6.0)
|
||||
local glow = math.Rand(0.6, 0.8) * 255
|
||||
local color = Color(glow / 2, glow / 1.5, glow / 1.1)
|
||||
local attachment = self:GetAttachment(1)
|
||||
|
||||
if (attachment) then
|
||||
local position = attachment.Pos
|
||||
|
||||
render.SetMaterial(STUNSTICK_GLOW_MATERIAL2)
|
||||
render.DrawSprite(position, size * 2, size * 2, color)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local NUM_BEAM_ATTACHEMENTS = 9
|
||||
local BEAM_ATTACH_CORE_NAME = "sparkrear"
|
||||
|
||||
function SWEP:PostDrawViewModel()
|
||||
if (!self:GetActivated()) then
|
||||
return
|
||||
end
|
||||
|
||||
local viewModel = LocalPlayer():GetViewModel()
|
||||
|
||||
if (!IsValid(viewModel)) then
|
||||
return
|
||||
end
|
||||
|
||||
cam.Start3D(EyePos(), EyeAngles())
|
||||
local size = math.Rand(3.0, 4.0)
|
||||
local color = Color(75, 100, 150, 50 + math.sin(RealTime() * 2)*20)
|
||||
|
||||
STUNSTICK_GLOW_MATERIAL_NOZ:SetFloat("$alpha", color.a / 255)
|
||||
|
||||
render.SetMaterial(STUNSTICK_GLOW_MATERIAL_NOZ)
|
||||
|
||||
local attachment = viewModel:GetAttachment(viewModel:LookupAttachment(BEAM_ATTACH_CORE_NAME))
|
||||
|
||||
if (attachment) then
|
||||
render.DrawSprite(attachment.Pos, size * 10, size * 15, color)
|
||||
end
|
||||
|
||||
for i = 1, NUM_BEAM_ATTACHEMENTS do
|
||||
attachment = viewModel:GetAttachment(viewModel:LookupAttachment("spark"..i.."a"))
|
||||
size = math.Rand(2.5, 5.0)
|
||||
|
||||
if (attachment and attachment.Pos) then
|
||||
render.DrawSprite(attachment.Pos, size, size, color)
|
||||
end
|
||||
|
||||
attachment = viewModel:GetAttachment(viewModel:LookupAttachment("spark"..i.."b"))
|
||||
size = math.Rand(2.5, 5.0)
|
||||
|
||||
if (attachment and attachment.Pos) then
|
||||
render.DrawSprite(attachment.Pos, size, size, color)
|
||||
end
|
||||
end
|
||||
cam.End3D()
|
||||
end
|
||||
|
||||
function SWEP:PrimaryAttack()
|
||||
self:SetNextPrimaryFire(CurTime() + self.Primary.Delay)
|
||||
|
||||
if (!self:GetOwner():IsWepRaised()) then
|
||||
return
|
||||
end
|
||||
|
||||
if (self:GetOwner():KeyDown(IN_WALK)) then
|
||||
if (SERVER) then
|
||||
self:SetActivated(!self:GetActivated())
|
||||
|
||||
local state = self:GetActivated()
|
||||
|
||||
if (state) then
|
||||
self:GetOwner():EmitSound("Weapon_StunStick.Activate")
|
||||
else
|
||||
self:GetOwner():EmitSound("Weapon_StunStick.Deactivate")
|
||||
end
|
||||
|
||||
local model = string.lower(self:GetOwner():GetModel())
|
||||
|
||||
if (ix.anim.GetModelClass(model) == "metrocop") then
|
||||
self:GetOwner():ForceSequence(state and "activatebaton" or "deactivatebaton", nil, nil, true)
|
||||
end
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
local result = hook.Run("CanDoMeleeAttack", self)
|
||||
if (result == false) then
|
||||
return
|
||||
end
|
||||
|
||||
self:EmitSound("Weapon_StunStick.Swing")
|
||||
self:SendWeaponAnim(ACT_VM_HITCENTER)
|
||||
|
||||
local damage = self.Primary.Damage
|
||||
|
||||
if (self:GetActivated()) then
|
||||
damage = 10
|
||||
end
|
||||
|
||||
self:GetOwner():SetAnimation(PLAYER_ATTACK1)
|
||||
self:GetOwner():ViewPunch(Angle(1, 0, 0.125))
|
||||
|
||||
self:GetOwner():LagCompensation(true)
|
||||
local data = {}
|
||||
data.start = self:GetOwner():GetShootPos()
|
||||
data.endpos = data.start + self:GetOwner():GetAimVector()*72
|
||||
data.filter = self:GetOwner()
|
||||
local trace = util.TraceLine(data)
|
||||
self:GetOwner():LagCompensation(false)
|
||||
|
||||
if (SERVER and trace.Hit) then
|
||||
if (self:GetActivated()) then
|
||||
local effect = EffectData()
|
||||
effect:SetStart(trace.HitPos)
|
||||
effect:SetNormal(trace.HitNormal)
|
||||
effect:SetOrigin(trace.HitPos)
|
||||
util.Effect("StunstickImpact", effect, true, true)
|
||||
end
|
||||
|
||||
self:GetOwner():EmitSound("Weapon_StunStick.Melee_HitWorld")
|
||||
|
||||
local entity = trace.Entity
|
||||
|
||||
if (IsValid(entity)) then
|
||||
if (entity:IsPlayer()) then
|
||||
if (self:GetActivated()) then
|
||||
entity.ixStuns = (entity.ixStuns or 0) + 1
|
||||
|
||||
timer.Simple(10, function()
|
||||
if (!entity.ixStuns) then return end
|
||||
entity.ixStuns = math.max(entity.ixStuns - 1, 0)
|
||||
end)
|
||||
end
|
||||
|
||||
entity:ViewPunch(Angle(-20, math.random(-15, 15), math.random(-10, 10)))
|
||||
|
||||
if (self:GetActivated() and entity.ixStuns > 2) then
|
||||
entity:SetRagdolled(true, 60)
|
||||
ix.log.Add(entity, "knockedOut", "hit by stunstick owned by "..self:GetOwner():GetName())
|
||||
entity.ixStuns = 0
|
||||
|
||||
return
|
||||
end
|
||||
elseif (entity:IsRagdoll()) then
|
||||
damage = self:GetActivated() and 2 or 10
|
||||
end
|
||||
|
||||
local damageInfo = DamageInfo()
|
||||
damageInfo:SetAttacker(self:GetOwner())
|
||||
damageInfo:SetInflictor(self)
|
||||
damageInfo:SetDamage(damage)
|
||||
damageInfo:SetDamageType(DMG_CLUB)
|
||||
damageInfo:SetDamagePosition(trace.HitPos)
|
||||
damageInfo:SetDamageForce(self:GetOwner():GetAimVector() * 10000)
|
||||
entity:DispatchTraceAttack(damageInfo, data.start, data.endpos)
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function SWEP:SecondaryAttack()
|
||||
self:GetOwner():LagCompensation(true)
|
||||
local data = {}
|
||||
data.start = self:GetOwner():GetShootPos()
|
||||
data.endpos = data.start + self:GetOwner():GetAimVector()*72
|
||||
data.filter = self:GetOwner()
|
||||
data.mins = Vector(-8, -8, -30)
|
||||
data.maxs = Vector(8, 8, 10)
|
||||
local trace = util.TraceHull(data)
|
||||
local entity = trace.Entity
|
||||
self:GetOwner():LagCompensation(false)
|
||||
|
||||
if (SERVER and IsValid(entity)) then
|
||||
local bPushed = false
|
||||
|
||||
if (entity:IsDoor()) then
|
||||
if (hook.Run("PlayerCanKnockOnDoor", self:GetOwner(), entity) == false) then
|
||||
return
|
||||
end
|
||||
|
||||
self:GetOwner():ViewPunch(Angle(-1.3, 1.8, 0))
|
||||
self:GetOwner():EmitSound("physics/wood/wood_crate_impact_hard3.wav")
|
||||
self:GetOwner():SetAnimation(PLAYER_ATTACK1)
|
||||
|
||||
self:SetNextSecondaryFire(CurTime() + 0.4)
|
||||
self:SetNextPrimaryFire(CurTime() + 1)
|
||||
elseif (entity:IsPlayer()) then
|
||||
local direction = self:GetOwner():GetAimVector() * (300 + (self:GetOwner():GetCharacter():GetAttribute("str", 0) * 3))
|
||||
direction.z = 0
|
||||
entity:SetVelocity(direction)
|
||||
|
||||
hook.Run("PlayerPushedPlayer", self:GetOwner(), entity)
|
||||
|
||||
bPushed = true
|
||||
else
|
||||
local physObj = entity:GetPhysicsObject()
|
||||
|
||||
if (IsValid(physObj)) then
|
||||
physObj:SetVelocity(self:GetOwner():GetAimVector() * 180)
|
||||
end
|
||||
|
||||
bPushed = true
|
||||
end
|
||||
|
||||
if (bPushed) then
|
||||
self:SetNextSecondaryFire(CurTime() + 1.5)
|
||||
self:SetNextPrimaryFire(CurTime() + 1.5)
|
||||
self:GetOwner():EmitSound("Weapon_Crossbow.BoltHitBody")
|
||||
|
||||
local model = string.lower(self:GetOwner():GetModel())
|
||||
|
||||
if (ix.anim.GetModelClass(model) == "metrocop") then
|
||||
self:GetOwner():ForceSequence("pushplayer")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
12
gamemodes/darkrp/gamemode/cl_init.lua
Normal file
12
gamemodes/darkrp/gamemode/cl_init.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
--[[
|
||||
| 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/
|
||||
--]]
|
||||
|
||||
|
||||
DeriveGamemode("helix")
|
||||
13
gamemodes/darkrp/gamemode/init.lua
Normal file
13
gamemodes/darkrp/gamemode/init.lua
Normal file
@@ -0,0 +1,13 @@
|
||||
--[[
|
||||
| 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")
|
||||
DeriveGamemode("helix")
|
||||
35
gamemodes/darkrp/glualint.json
Normal file
35
gamemodes/darkrp/glualint.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"lint_maxScopeDepth": 20,
|
||||
"lint_syntaxErrors": true,
|
||||
"lint_syntaxInconsistencies": true,
|
||||
"lint_deprecated": true,
|
||||
"lint_trailingWhitespace": true,
|
||||
"lint_whitespaceStyle": false,
|
||||
"lint_beginnerMistakes": true,
|
||||
"lint_emptyBlocks": true,
|
||||
"lint_shadowing": true,
|
||||
"lint_gotos": true,
|
||||
"lint_doubleNegations": true,
|
||||
"lint_redundantIfStatements": false,
|
||||
"lint_redundantParentheses": true,
|
||||
"lint_duplicateTableKeys": true,
|
||||
"lint_profanity": true,
|
||||
"lint_unusedVars": true,
|
||||
"lint_unusedParameters": false,
|
||||
"lint_unusedLoopVars": false,
|
||||
"lint_inconsistentVariableStyle": false,
|
||||
"lint_ignoreFiles": [],
|
||||
|
||||
"prettyprint_spaceAfterParens": false,
|
||||
"prettyprint_spaceAfterBrackets": false,
|
||||
"prettyprint_spaceAfterBraces": false,
|
||||
"prettyprint_spaceEmptyBrackets": true,
|
||||
"prettyprint_spaceAfterLabel": false,
|
||||
"prettyprint_spaceBeforeComma": false,
|
||||
"prettyprint_spaceAfterComma": true,
|
||||
"prettyprint_semicolons": false,
|
||||
"prettyprint_cStyle": false,
|
||||
"prettyprint_rejectInvalidCode": false,
|
||||
"prettyprint_indentation": " ",
|
||||
"log_format": "auto"
|
||||
}
|
||||
138
gamemodes/darkrp/plugins/ambient.lua
Normal file
138
gamemodes/darkrp/plugins/ambient.lua
Normal file
@@ -0,0 +1,138 @@
|
||||
--[[
|
||||
| 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 PLUGIN = PLUGIN
|
||||
|
||||
PLUGIN.name = "Ambient"
|
||||
PLUGIN.description = "Ambient Sounds"
|
||||
PLUGIN.author = "DrodA"
|
||||
PLUGIN.version = 1.0
|
||||
|
||||
ix.option.Add("enableAmbient", ix.type.bool, true, {
|
||||
category = "Musique de fond",
|
||||
OnChanged = function(old_value, new_value)
|
||||
if (!new_value) then
|
||||
PLUGIN:StopSound()
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
PLUGIN:PlaySound(PLUGIN.ambients[math.random(1, #PLUGIN.ambients)])
|
||||
end
|
||||
})
|
||||
|
||||
ix.option.Add("ambientVolume", ix.type.number, 0.7, {
|
||||
category = "Musique de fond",
|
||||
min = 0.1, max = 1, decimals = 1,
|
||||
OnChanged = function(old_value, new_value)
|
||||
PLUGIN:SetVolume(new_value)
|
||||
end
|
||||
})
|
||||
|
||||
ix.lang.AddTable("english", {
|
||||
optAmbientVolume = "Volume de la musique d'ambiance",
|
||||
optdAmbientVolume = "Comment le volume de la musique ambiante doit être fort",
|
||||
optEnableAmbient = "Activer la musique ambiante",
|
||||
optdEnableAmbient = "Si la musique ambiante doit être activée ou non."
|
||||
})
|
||||
|
||||
ix.lang.AddTable("french", {
|
||||
optAmbientVolume = "Volume de la musique d'ambiance",
|
||||
optdAmbientVolume = "Comment le volume de la musique ambiante doit être fort",
|
||||
optEnableAmbient = "Activer la musique ambiante",
|
||||
optdEnableAmbient = "Si la musique ambiante doit être activée ou non."
|
||||
})
|
||||
|
||||
if (SERVER) then return end
|
||||
|
||||
local timer_id = "ix_ambient_track"
|
||||
|
||||
PLUGIN.ambients = {
|
||||
{path = "music/passive/passivemusic_01.ogg", length = 85},
|
||||
{path = "music/passive/passivemusic_02.ogg", length = 130},
|
||||
{path = "music/passive/passivemusic_03.ogg", length = 95},
|
||||
{path = "music/passive/passivemusic_04.ogg", length = 125},
|
||||
{path = "music/passive/passivemusic_05.ogg", length = 215},
|
||||
{path = "music/passive/passivemusic_06.ogg", length = 210},
|
||||
{path = "music/passive/passivemusic_07.ogg", length = 245},
|
||||
{path = "music/passive/passivemusic_08.ogg", length = 268},
|
||||
{path = "music/passive/passivemusic_09.ogg", length = 150},
|
||||
{path = "music/passive/passivemusic_10.ogg", length = 260},
|
||||
{path = "music/passive/passivemusic_11.ogg", length = 340},
|
||||
{path = "music/passive/passivemusic_12.ogg", length = 260},
|
||||
{path = "music/passive/passivemusic_13.ogg", length = 440},
|
||||
{path = "music/passive/passivemusic_14.ogg", length = 130},
|
||||
{path = "music/passive/passivemusic_15.ogg", length = 130},
|
||||
{path = "music/passive/passivemusic_16.ogg", length = 250},
|
||||
{path = "music/passive/passivemusic_17.ogg", length = 270},
|
||||
{path = "music/passive/passivemusic_18.ogg", length = 320},
|
||||
{path = "music/passive/passivemusic_19.ogg", length = 100},
|
||||
{path = "music/passive/passivemusic_20.ogg", length = 210}
|
||||
}
|
||||
|
||||
for _, v in pairs(PLUGIN.ambients) do
|
||||
util.PrecacheSound(v.path)
|
||||
end
|
||||
|
||||
function PLUGIN:StopSound()
|
||||
if (timer.Exists(timer_id)) then
|
||||
timer.Remove(timer_id)
|
||||
end
|
||||
|
||||
if (self.ambient) then
|
||||
self.ambient:Stop()
|
||||
self.ambient = nil
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:SetVolume(volume)
|
||||
if !self.ambient then return end
|
||||
|
||||
self.ambient:ChangeVolume(volume)
|
||||
end
|
||||
|
||||
function PLUGIN:PlaySound(data)
|
||||
if (!ix.option.Get("enableAmbient")) then
|
||||
self:StopSound()
|
||||
return
|
||||
end
|
||||
|
||||
if (timer.Exists(timer_id)) then
|
||||
self:StopSound()
|
||||
end
|
||||
|
||||
self.ambient = CreateSound(LocalPlayer(), data.path)
|
||||
self.ambient:Play()
|
||||
self.ambient:ChangeVolume(ix.option.Get("ambientVolume"), 0)
|
||||
|
||||
timer.Create(timer_id, data.length, 1, function()
|
||||
PLUGIN:StopSound()
|
||||
|
||||
timer.Simple(math.random(30, 60), function()
|
||||
PLUGIN:PlaySound(PLUGIN.ambients[math.random(1, #PLUGIN.ambients)])
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
function PLUGIN:CharacterLoaded(character)
|
||||
if (!timer.Exists(timer_id) and ix.option.Get("enableAmbient")) then
|
||||
self:PlaySound(PLUGIN.ambients[math.random(1, #PLUGIN.ambients)])
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:PostPlaySound(sound, isGlobal)
|
||||
if (isGlobal) then
|
||||
self:StopSound()
|
||||
|
||||
timer.Simple(SoundDuration(sound) + math.random(30, 60), function()
|
||||
PLUGIN:PlaySound(PLUGIN.ambients[math.random(1, #PLUGIN.ambients)])
|
||||
end)
|
||||
end
|
||||
end
|
||||
43
gamemodes/darkrp/plugins/ammolimit.lua
Normal file
43
gamemodes/darkrp/plugins/ammolimit.lua
Normal file
@@ -0,0 +1,43 @@
|
||||
--[[
|
||||
| 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 PLUGIN = PLUGIN
|
||||
|
||||
PLUGIN.name = "Ammo Limit"
|
||||
PLUGIN.author = "Gr4Ss"
|
||||
PLUGIN.description = "Limit how much ammo can be loaded from ammo boxes."
|
||||
|
||||
ix.lang.AddTable("english", {
|
||||
ammoLimitReached = "You have reached the equipped ammo limit!"
|
||||
})
|
||||
|
||||
ix.config.Add("ammoBoxLimit", 4, "The maximum amount of ammo boxes someone is allowed to equip", nil, {
|
||||
data = {min = 0, max = 10, decimals = 1},
|
||||
category = "Other"
|
||||
})
|
||||
|
||||
function PLUGIN:CanPlayerInteractItem(client, action, item, data)
|
||||
if (isentity(item)) then
|
||||
if (IsValid(item)) then
|
||||
item = ix.item.instances[item.ixItemID]
|
||||
else
|
||||
return
|
||||
end
|
||||
elseif (isnumber(item)) then
|
||||
item = ix.item.instances[item]
|
||||
end
|
||||
|
||||
if (!item) then return end
|
||||
if (action == "use" and item.ammo and item.ammoAmount and client:GetAmmoCount(item.ammo) >= item.ammoAmount * ix.config.Get("ammoBoxLimit")) then
|
||||
client:NotifyLocalized("ammoLimitReached")
|
||||
return false
|
||||
end
|
||||
end
|
||||
55
gamemodes/darkrp/plugins/anoncombine/cl_hooks.lua
Normal file
55
gamemodes/darkrp/plugins/anoncombine/cl_hooks.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/
|
||||
--]]
|
||||
|
||||
|
||||
local chatTypeWhitelist = {
|
||||
["scoreboard"] = true,
|
||||
["radio"] = true
|
||||
}
|
||||
|
||||
function PLUGIN:GetHookCallPriority(hook)
|
||||
if (hook == "GetCharacterName" or hook == "PopulateCharacterInfo") then
|
||||
return 1500
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:GetCharacterName(client, chatType)
|
||||
if (!IsValid(client)) then return end
|
||||
if (LocalPlayer():IsCombine() or chatTypeWhitelist[chatType]) then return end
|
||||
|
||||
if (LocalPlayer():GetMoveType() == MOVETYPE_NOCLIP and !LocalPlayer():InVehicle()) then return end
|
||||
if (ix.faction.Get(LocalPlayer():Team()).recogniseAll) then return end
|
||||
|
||||
if (client:Team() == FACTION_OTA) then
|
||||
return client:GetCharacter():GetClass() == CLASS_EOW and "Soldat d'Élite de l'Overwatch" or "Soldat de l'Overwatch"
|
||||
elseif (client:GetNetVar("combineMaskEquipped")) then
|
||||
return "Officier de la Protection Civile"
|
||||
end
|
||||
end
|
||||
|
||||
function PLUGIN:PopulateCharacterInfo(client, character, container)
|
||||
if (LocalPlayer():IsCombine() or !client:GetNetVar("combineMaskEquipped") and client:Team() != FACTION_OTA) then return end
|
||||
|
||||
timer.Simple(0.1, function()
|
||||
local description = container:GetRow("description")
|
||||
|
||||
if (IsValid(description)) then
|
||||
description:Remove()
|
||||
end
|
||||
|
||||
local geneticDesc = container:GetRow("geneticDesc")
|
||||
|
||||
if (IsValid(geneticDesc)) then
|
||||
local height = character:GetHeight()
|
||||
|
||||
geneticDesc:SetText(height .. " ")
|
||||
end
|
||||
end)
|
||||
end
|
||||
16
gamemodes/darkrp/plugins/anoncombine/sh_plugin.lua
Normal file
16
gamemodes/darkrp/plugins/anoncombine/sh_plugin.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/
|
||||
--]]
|
||||
|
||||
|
||||
PLUGIN.name = "Anonymous Combine"
|
||||
PLUGIN.author = "Aspect™"
|
||||
PLUGIN.description = "Makes the Combine more anonymous."
|
||||
|
||||
ix.util.Include("cl_hooks.lua")
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user