This commit is contained in:
lifestorm
2024-08-05 18:40:29 +03:00
parent 9f505a0646
commit c6d9b6f580
8044 changed files with 1853472 additions and 21 deletions

View 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

View 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

View 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 (Conscript)"
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_con")
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 conCards = {}
for _, item in pairs(items) do
if (item.uniqueID == "con_card" and item:GetData("cardID")) then
conCards[#conCards + 1] = item
end
end
local canOpen = false
for _, card in pairs(conCards) 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("changeLockAccessCon")
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_orange = Color(255, 180, 0, 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

View 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

View 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

View 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

View 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
})

View 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
})

View 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" )

View 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

View File

@@ -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

View File

@@ -0,0 +1,74 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
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 - Manage Panels") 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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,490 @@
--[[
| 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_wn_stunstick.mdl")
SWEP.WorldModel = Model("models/weapons/w_wn_stunbaton.mdl")
SWEP.UseHands = true
SWEP.LowerAngles = Angle(15, -10, -20)
SWEP.FireWhenLowered = true
function SWEP:SetupDataTables()
self:NetworkVar("Bool", 0, "Activated")
self:NetworkVarNotify( "Activated", self.OnActiveToggle )
end
function SWEP:Precache()
util.PrecacheSound("physics/wood/wood_crate_impact_hard3.wav")
end
function SWEP:StartStunstickSound()
if (SERVER) then
local client = self:GetOwner()
self.patch1 = CreateSound(client, "wn_stunstick/stunstick_idle_"..math.random(1, 4)..".wav")
self.patch1:SetSoundLevel(40)
self.patch1:Play()
self:SoundTimer()
end
end
function SWEP:StopStunstickSound()
if (SERVER) then
local patchToStop
if (self.patch1 and self.patch1:IsPlaying()) then
patchToStop = self.patch1
else
patchToStop = self.patch2
end
if (!patchToStop) then return end
patchToStop:FadeOut(1)
end
end
-- for when someone primary fires or w/e
function SWEP:DuckStunstickSound(vol, delta)
if (SERVER) then
if (!delta) then
delta = 0.5
end
if (!vol) then
vol = 0.25
end
local patchToDuck = self.patch1 and self.patch1:IsPlaying() and self.patch1 or self.patch2
if (!patchToDuck) then return end
patchToDuck:ChangeVolume(vol, delta)
timer.Simple(delta + 0.1, function()
patchToDuck:ChangeVolume(1, delta)
end)
end
end
function SWEP:OnActiveToggle(name, old, new)
if (new) then
self:StartStunstickSound()
else
self:StopStunstickSound()
end
end
function SWEP:SoundTimer()
if (SERVER) then
local client = self:GetOwner()
local tName = "stunstick_idle_"..client:SteamID64().."_timer"
if timer.Exists(tName) then timer.Remove(tName) end
timer.Create(tName, 12, 0, function()
if (!IsValid(client)) then
timer.Remove(tName)
return
end
if (!IsValid(self) or !self:GetActivated()) then
return
end
local patchToStart
local patchToStop
if (self.patch1 and self.patch1:IsPlaying()) then
patchToStart = self.patch2
patchToStop = self.patch1
else
patchToStart = self.patch1
patchToStop = self.patch2
end
if (!patchToStop) then
timer.Remove(tName)
return
end
patchToStop:FadeOut(1)
patchToStart = CreateSound(client, "wn_stunstick/stunstick_idle_"..math.random(1, 4)..".wav")
patchToStart:SetSoundLevel(40) -- maybe make this configurable idk
patchToStart:Play()
patchToStart:ChangeVolume( 0.1, 0 )
patchToStart:ChangeVolume(1, 1)
if (self.patch1 and self.patch1:IsPlaying()) then
self.patch2 = patchToStart
else
self.patch1 = patchToStart
end
end)
end
end
function SWEP:CreateWMParticle()
if self.particle and self.particle:IsValid() then
self.particle:StopEmissionAndDestroyImmediately()
end
self.particle = CreateParticleSystem(self, "wn_stunstick_fx", PATTACH_POINT_FOLLOW, 1, Vector(0, 0, 0))
end
function SWEP:Initialize()
self:SetHoldType(self.HoldType)
end
function SWEP:OnRaised()
self.lastRaiseTime = CurTime()
end
function SWEP:OnLowered()
self:SetActivated(false)
if (CLIENT) then
if (self.particle and IsValid(self.particle)) then
self.particle:StopEmissionAndDestroyImmediately()
end
end
end
function SWEP:Holster(nextWep)
if self.patch1 and self.patch1:IsPlaying() or self.patch2 and self.patch2:IsPlaying() then
self:StopStunstickSound()
end
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.particle or self.particle and !self.particle:IsValid()) then
if self:GetActivated() then
self:CreateWMParticle()
end
elseif (self.particle and self.particle:IsValid()) then
if !self:GetActivated() then
self.particle:StopEmissionAndDestroyImmediately()
end
end
if (self:GetActivated()) then
local size = math.Rand(2.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"
SWEP.nextSpark = 0
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(1)
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()
local sparkAttachment = viewModel:GetAttachment(1)
if self.nextSpark <= CurTime() then
self.nextSpark = CurTime() + math.random(1, 10)
local ef = EffectData()
ef:SetOrigin(sparkAttachment.Pos)
ef:SetMagnitude(math.random(1, 2))
ef:SetScale(0.1)
util.Effect("ElectricSpark", ef)
self:EmitSound("wn_stunstick/spark".. math.random(1, 4) ..".wav", nil, math.random(80, 120))
end
if (self.particle and self.particle:IsValid() and self:GetActivated()) then
self.particle:StopEmissionAndDestroyImmediately()
end
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
if (CLIENT) then
timer.Simple(0, function()
if !(IsValid(self)) then return end
if (self:GetActivated()) then
self:CreateWMParticle()
else
if (self.particle and self.particle:IsValid()) then
self.particle:StopEmissionAndDestroyImmediately()
end
end
end)
end
return
end
local result = hook.Run("CanDoMeleeAttack", self)
if (result == false) then
return
end
if (self:GetActivated()) then
self:DuckStunstickSound()
end
self:EmitSound("wn_stunstick/stunstick_swing".. math.random(1, 3) ..".wav")
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))
timer.Simple(0.1, function()
if !IsValid(self) then return end
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("wn_stunstick/stunstick_fleshhit".. math.random(1, 3) ..".wav")
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)
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