This commit is contained in:
lifestorm
2024-08-04 23:54:45 +03:00
parent 8064ba84d8
commit 6a58f406b1
7522 changed files with 4011896 additions and 15 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,312 @@
--[[
| 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 = "Effects"
TOOL.Name = "Energy Ball"
TOOL.Command = nil
TOOL.ConfigName = ""
//Default values
TOOL.ClientConVar["scale"] = 2
TOOL.ClientConVar["emitparticles"] = 1
TOOL.ClientConVar["sound"] = 0
TOOL.ClientConVar["key"] = 5
TOOL.ClientConVar["numpadcontrol"] = 0
TOOL.ClientConVar["toggle"] = 0
//List of all spawned energy ball entities
TOOL.EnergyBalls = {}
//Add language descriptions
if (CLIENT) then
language.Add("Tool.energyball.name", "Energy Ball Tool")
language.Add("Tool.energyball.desc", "Creates a customizable ball of energy")
language.Add("Tool.energyball.0", "Left-Click: Create/Charge energy ball Right-Click: Remove energy balls")
language.Add("Cleanup_energyballs", "Energy Balls")
language.Add("Cleaned_energyballs", "Cleaned up all Energy Balls")
language.Add("SBoxLimit_energyballs", "You've hit the Energy Balls limit!")
language.Add("Undone_energyball", "Energy Ball undone")
end
//Sandbox-related stuff
cleanup.Register("energyballs")
CreateConVar("sbox_maxenergyballs", 8, FCVAR_NOTIFY)
//Make an energy ball
function TOOL:LeftClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return true end
//Charge existing balls if there are any
local scale = math.Round(math.Clamp(self:GetClientNumber("scale"), .32, 15)) //Let's just retreive this here
local findenergyballs = ents.FindInSphere( trace.HitPos, scale * scale )
local success = false
for _, energyball in pairs(findenergyballs) do
//Charge or discharge current ball
if energyball && energyball:IsValid() && !energyball:GetPhysicsObject():IsValid() && energyball:GetClass() == "env_citadel_energy_core" && !energyball:IsPlayer() && !energyball:IsNPC() && !energyball:IsWorld() then
local DontRunTwice = false
//Charge
if !energyball.Charged then
energyball:Fire("StartCharge", "4", 0)
energyball.Charged = true
DontRunTwice = true
if energyball.SFX_Sound then
energyball.SFX_Sound:Stop()
sound.Play( "HL1/ambience/port_suckout1.wav", trace.HitPos, 72, 100 )
timer.Simple( 2.62, function() if energyball && energyball.SFX_Sound then energyball.SFX_Sound:Stop() energyball.SFX_Sound = CreateSound(energyball, Sound("npc/combine_gunship/dropship_onground_loop1.wav")) energyball.SFX_Sound:PlayEx(0.72, 100) end end )
end
end
//Discharge
if !DontRunTwice && energyball.Charged then
energyball:Fire("StartDischarge", "2", 0)
energyball.Charged = false
if energyball.SFX_Sound then
energyball.SFX_Sound:Stop()
sound.Play( "HL1/ambience/port_suckin1.wav", trace.HitPos, 72, 100 )
energyball.SFX_Sound = CreateSound(energyball, Sound("npc/combine_gunship/engine_rotor_loop1.wav"))
energyball.SFX_Sound:PlayEx(0.62, 100)
end
end
success = true
end
end
if success then return true end //Don't spawn anything if charging
//Check current spawnlimits
if (!self:GetSWEP():CheckLimit("energyballs")) then return false end
//Retreive settings
local spawnflags = 0
if self:GetClientNumber("numpadcontrol") == 0 then spawnflags = 2 end
if math.Round(math.Clamp(self:GetClientNumber("emitparticles"), 0, 1)) == 0 then spawnflags = spawnflags + 1 end
//Create energy ball and assign settings
local energyball = ents.Create("env_citadel_energy_core")
if !energyball || !energyball:IsValid() then return false end
energyball:SetPos(trace.HitPos)
energyball:SetKeyValue("angles", tostring(trace.HitNormal:Angle()))
energyball:SetKeyValue("scale", tostring(scale))
energyball:SetKeyValue("spawnflags", tostring(spawnflags))
//Spawn energy ball
energyball:Spawn()
energyball:Activate()
energyball.Charged = false
if trace && trace.Entity && trace.Entity:IsValid() && trace.Entity:GetPhysicsObject():IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then energyball:SetParent(trace.Entity) end
//Emit sounds
if math.Round(math.Clamp(self:GetClientNumber("sound"), 0, 1)) == 1 then
if self:GetClientNumber("numpadcontrol") == 0 then sound.Play( "weapons/physcannon/superphys_small_zap" .. math.random(1,4) .. ".wav", trace.HitPos, 52, 100 ) end
energyball.SFX_Sound = CreateSound(energyball, Sound("npc/combine_gunship/engine_rotor_loop1.wav"))
if self:GetClientNumber("numpadcontrol") == 0 then energyball.SFX_Sound:PlayEx(0.62, 100) end
end
//Add to relevant lists
self:GetOwner():AddCount("energyballs", energyball)
table.insert(self.EnergyBalls, energyball)
//Make sure we can undo
undo.Create("energyball")
undo.AddEntity(energyball)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "energyballs", energyball)
//Make sure we can control it with numpad
if self:GetClientNumber("numpadcontrol") == 1 then
self:SetupNumpadControls(energyball)
end
return true
end
//Setup numpad controls
function TOOL:SetupNumpadControls(energyball)
//Safeguards
if !energyball || !energyball:IsValid() || self:GetClientInfo("key") == nil || self:GetClientInfo("key") == -1 then return false end
//If not toggled
if self:GetClientNumber("toggle") == 0 then
//Create KeyDown numpad functions
local function StartEmitPlasma(ply, energyball)
if !energyball || !energyball:IsValid() then return end
//Start energy discharge
if energyball.Charged then energyball:Fire("StartCharge", "1", 0) end
if !energyball.Charged then energyball:Fire("StartDischarge", "1", 0) end
//Start related sounds
if energyball.SFX_Sound then
energyball.SFX_Sound:Stop()
if !energyball.Charged then energyball.SFX_Sound = CreateSound(energyball, Sound("npc/combine_gunship/engine_rotor_loop1.wav")) energyball.SFX_Sound:PlayEx(0.62, 100) end
if energyball.Charged then energyball.SFX_Sound = CreateSound(energyball, Sound("npc/combine_gunship/dropship_onground_loop1.wav")) energyball.SFX_Sound:PlayEx(0.72, 100) end
end
end
//Register KeyDown functions
numpad.Register("StartEmitPlasma", StartEmitPlasma)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "StartEmitPlasma", energyball)
//Create KeyUp numpad functions
local function StopEmitPlasma(ply, energyball)
if !energyball || !energyball:IsValid() then return end
//Stop energy discharge and related sounds
if energyball.SFX_Sound then energyball.SFX_Sound:Stop() end
energyball:Fire("Stop", "0.32", 0)
end
//Register KeyUp functions
numpad.Register("StopEmitPlasma", StopEmitPlasma)
numpad.OnUp(self:GetOwner(), self:GetClientNumber("key"), "StopEmitPlasma", energyball)
end
//If toggled
if self:GetClientNumber("toggle") == 1 then
energyball.Toggle = false
//Create KeyDown numpad functions
local function ToggleEmitPlasma(ply, energyball)
if !energyball || !energyball:IsValid() then return end
//Start energy discharge
if !energyball.Toggle then
//Energy discharge
if energyball.Charged then energyball:Fire("StartCharge", "1", 0) end
if !energyball.Charged then energyball:Fire("StartDischarge", "1", 0) end
//Related sounds
if energyball.SFX_Sound then
energyball.SFX_Sound:Stop()
if !energyball.Charged then energyball.SFX_Sound = CreateSound(energyball, Sound("npc/combine_gunship/engine_rotor_loop1.wav")) energyball.SFX_Sound:PlayEx(0.62, 100) end
if energyball.Charged then energyball.SFX_Sound = CreateSound(energyball, Sound("npc/combine_gunship/dropship_onground_loop1.wav")) energyball.SFX_Sound:PlayEx(0.72, 100) end
end
energyball.Toggle = true
return
end
//Stop energy discharge and related sounds
if energyball.Toggle then
if energyball.SFX_Sound then sound.Play( "HL1/ambience/port_suckin1.wav", energyball:GetPos(), 62, 100 ) energyball.SFX_Sound:Stop() end
energyball:Fire("Stop", "0.32", 0)
energyball.Toggle = false
return
end
end
//Register KeyDown functions
numpad.Register("ToggleEmitPlasma", ToggleEmitPlasma)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "ToggleEmitPlasma", energyball)
end
return true
end
//Remove energy balls in radius
function TOOL:RightClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Find energy balls in radius
local scale = math.Round(math.Clamp(self:GetClientNumber("scale"), .32, 15))
local findenergyballs = ents.FindInSphere(trace.HitPos, scale * scale)
for _, energyball in pairs(findenergyballs) do
//Remove
if energyball && energyball:IsValid() && !energyball:GetPhysicsObject():IsValid() && energyball:GetClass() == "env_citadel_energy_core" && !energyball:IsPlayer() && !energyball:IsNPC() && !energyball:IsWorld() then
if energyball.SFX_Sound then energyball.SFX_Sound:Stop() sound.Play( "HL1/ambience/port_suckin1.wav", energyball:GetPos(), 62, 100 ) end
energyball:Fire("StartCharge", "2", 0)
energyball:Fire("Kill", "", 0.21)
end
end
end
//Remove all energy balls
function TOOL:Reload()
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Get all energy balls
for x = 1, table.getn(self.EnergyBalls) do
local energyball = self.EnergyBalls[x]
//Remove
if energyball && energyball:IsValid() then
if energyball.SFX_Sound then energyball.SFX_Sound:Stop() sound.Play( "HL1/ambience/port_suckin1.wav", energyball:GetPos(), 62, 100 ) end
energyball:Fire("StartCharge", "2", 0)
energyball:Fire("Kill", "", 0.21)
end
end
end
//Precache all sounds
function TOOL:Precache()
util.PrecacheSound("weapons/physcannon/superphys_small_zap1.wav")
util.PrecacheSound("weapons/physcannon/superphys_small_zap2.wav")
util.PrecacheSound("weapons/physcannon/superphys_small_zap3.wav")
util.PrecacheSound("weapons/physcannon/superphys_small_zap4.wav")
util.PrecacheSound("HL1/ambience/port_suckin1.wav")
util.PrecacheSound("npc/combine_gunship/dropship_onground_loop1.wav")
util.PrecacheSound("npc/combine_gunship/engine_rotor_loop1.wav")
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
//Header
panel:AddControl( "Header", { Text = "#Tool.energyball.name", Description = "#Tool.energyball.desc" } )
//Max delay
panel:AddControl( "Slider", { Label = "Scale", Type = "Integer", Min = "1", Max = "15", Command ="energyball_scale" } )
//Emit particles
panel:AddControl( "CheckBox", { Label = "Particles", Description = "", Command = "energyball_emitparticles" } )
//Make sounds
panel:AddControl( "CheckBox", { Label = "Sound", Description = "", Command = "energyball_sound" } )
//-------------
panel:AddControl( "Label", { Text = "________________________________________", Description = "" } )
//Numpad menu
panel:AddControl( "Numpad", { Label = "Activate/Deactive", Command = "energyball_key", ButtonSize = 22 } )
//Use numpad check
panel:AddControl( "CheckBox", { Label = "Use keyboard", Description = "", Command = "energyball_numpadcontrol" } )
//Toggle check
panel:AddControl( "CheckBox", { Label = "Toggle", Description = "", Command = "energyball_toggle" } )
end

View File

@@ -0,0 +1,319 @@
--[[
| 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 = "Half-Life 2"
TOOL.Name = "#tool.env_headcrabcanister"
TOOL.Model = "models/props_combine/headcrabcannister01b.mdl"
TOOL.ClientConVar[ "key_fire" ] = "38"
TOOL.ClientConVar[ "key_open" ] = "39"
TOOL.ClientConVar[ "key_spawn" ] = "40"
TOOL.ClientConVar[ "fire_immediately" ] = "0"
TOOL.ClientConVar[ "headcrab" ] = "0"
TOOL.ClientConVar[ "count" ] = "6"
TOOL.ClientConVar[ "speed" ] = "3000"
TOOL.ClientConVar[ "time" ] = "5"
TOOL.ClientConVar[ "height" ] = "0"
TOOL.ClientConVar[ "damage" ] = "150"
TOOL.ClientConVar[ "radius" ] = "750"
TOOL.ClientConVar[ "duration" ] = "30"
TOOL.ClientConVar[ "smoke" ] = "0"
TOOL.ClientConVar[ "sf1" ] = "0"
TOOL.ClientConVar[ "sf2" ] = "0"
TOOL.ClientConVar[ "sf4096" ] = "0"
TOOL.ClientConVar[ "sf16384" ] = "0"
TOOL.ClientConVar[ "sf32768" ] = "0"
TOOL.ClientConVar[ "sf65536" ] = "0"
TOOL.ClientConVar[ "sf131072" ] = "0"
TOOL.ClientConVar[ "sf262144" ] = "0"
TOOL.ClientConVar[ "sf524288" ] = "0"
cleanup.Register( "env_headcrabcanisters" )
if ( SERVER ) then
CreateConVar( "sbox_maxenv_headcrabcanisters", 4, FCVAR_ARCHIVE )
numpad.Register( "env_headcrabcanister_fire", function( ply, env_headcrabcanister )
if ( !IsValid( env_headcrabcanister ) ) then return false end
env_headcrabcanister:Fire( "FireCanister" )
end )
numpad.Register( "env_headcrabcanister_open", function( ply, env_headcrabcanister )
if ( !IsValid( env_headcrabcanister ) ) then return false end
env_headcrabcanister:Fire( "OpenCanister" )
end )
numpad.Register( "env_headcrabcanister_spawn", function( ply, env_headcrabcanister )
if ( !IsValid( env_headcrabcanister ) ) then return false end
env_headcrabcanister:Fire( "SpawnHeadcrabs" )
end )
function MakeHeadcrabCanister( ply, model, pos, ang, keyFire, keyOpen, keySpawn, fire_immediately, headcrab, count, speed, time, height, damage, radius, duration, spawnflags, smoke, mapCreationID )
if ( IsValid( ply ) and !ply:CheckLimit( "env_headcrabcanisters" ) ) then return false end
if ( tobool( smoke ) ) then duration = -1 end
fire_immediately = fire_immediately or false
headcrab = headcrab or 0
count = count or 6
speed = speed or 3000
time = time or 5
height = height or 0
damage = damage or 150
radius = radius or 750
duration = duration or 30
spawnflags = spawnflags or 0
keyOpen = keyOpen or -1
keyFire = keyFire or -1
keySpawn = keySpawn or -1
if ( !game.SinglePlayer() ) then
headcrab = math.Clamp( headcrab, 0, 2 )
count = math.Clamp( count, 0, 10 )
time = math.Clamp( time, 0, 30 )
height = math.Clamp( height, 0, 10240 )
damage = math.Clamp( damage, 0, 256 )
radius = math.Clamp( radius, 0, 1024 )
duration = math.Clamp( duration, 0, 90 )
end
local env_headcrabcanister = ents.Create( "env_headcrabcanister" )
if ( !IsValid( env_headcrabcanister ) ) then return false end
env_headcrabcanister:SetPos( pos )
env_headcrabcanister:SetAngles( ang )
env_headcrabcanister:SetKeyValue( "HeadcrabType", headcrab )
env_headcrabcanister:SetKeyValue( "HeadcrabCount", count )
env_headcrabcanister:SetKeyValue( "FlightSpeed", speed )
env_headcrabcanister:SetKeyValue( "FlightTime", time )
env_headcrabcanister:SetKeyValue( "StartingHeight", height )
env_headcrabcanister:SetKeyValue( "Damage", damage )
env_headcrabcanister:SetKeyValue( "DamageRadius", radius )
env_headcrabcanister:SetKeyValue( "SmokeLifetime", duration )
env_headcrabcanister:SetKeyValue( "spawnflags", spawnflags )
env_headcrabcanister:Spawn()
env_headcrabcanister:Activate()
env_headcrabcanister.NumpadFire = numpad.OnDown( ply, keyFire, "env_headcrabcanister_fire", env_headcrabcanister )
env_headcrabcanister.NumpadOpen = numpad.OnDown( ply, keyOpen, "env_headcrabcanister_open", env_headcrabcanister )
env_headcrabcanister.NumpadSpawn = numpad.OnDown( ply, keySpawn, "env_headcrabcanister_spawn", env_headcrabcanister )
if ( tobool( fire_immediately ) ) then env_headcrabcanister:Fire( "FireCanister" ) end
table.Merge( env_headcrabcanister:GetTable(), {
ply = ply,
keyFire = keyFire,
keyOpen = keyOpen,
keySpawn = keySpawn,
fire_immediately = fire_immediately,
headcrab = headcrab,
count = count,
speed = speed,
time = time,
height = height,
damage = damage,
radius = radius,
duration = duration,
spawnflags = spawnflags,
smoke = smoke,
MapCreationID = mapCreationID
} )
if ( IsValid( ply ) ) then
ply:AddCount( "env_headcrabcanisters", env_headcrabcanister )
ply:AddCleanup( "env_headcrabcanisters", env_headcrabcanister )
end
DoPropSpawnedEffect( env_headcrabcanister )
if ( Wire_CreateOutputs and !mapCreationID ) then
env_headcrabcanister.Inputs = Wire_CreateInputs( env_headcrabcanister, { "Open", "Spawn" } )
function env_headcrabcanister:TriggerInput( name, value )
if ( name == "Open" and value > 0 ) then self:Fire( "OpenCanister" ) end
if ( name == "Spawn" and value > 0 ) then self:Fire( "SpawnHeadcrabs" ) end
end
rb655_hl2_CopyWireModMethods( env_headcrabcanister )
end
return env_headcrabcanister
end
duplicator.RegisterEntityClass( "env_headcrabcanister", MakeHeadcrabCanister, "model", "pos", "ang", "keyFire", "keyOpen", "keySpawn", "fire_immediately", "headcrab", "count", "speed", "time", "height", "damage", "radius", "duration", "spawnflags", "smoke", "MapCreationID" )
end
function TOOL:IntrnlGetSF( str )
return math.Clamp( self:GetClientNumber( str ), 0, 1 )
end
function TOOL:LeftClick( trace )
if ( trace.HitSky or !trace.HitPos or trace.HitNormal.z < 0 ) then return false end
if ( IsValid( trace.Entity ) and ( trace.Entity:GetClass() == "env_headcrabcanister" or trace.Entity:IsPlayer() or trace.Entity:IsNPC() ) ) then return false end
if ( CLIENT ) then return true end
local ply = self:GetOwner()
local spawnflags = 0
spawnflags = self:IntrnlGetSF( "sf1" ) + self:IntrnlGetSF( "sf2" ) * 2 + self:IntrnlGetSF( "sf4096" ) * 4096 + self:IntrnlGetSF( "sf16384" ) * 16384
spawnflags = spawnflags + self:IntrnlGetSF( "sf32768" ) * 32768 + self:IntrnlGetSF( "sf65536" ) * 65536 + self:IntrnlGetSF( "sf131072" ) * 131072
spawnflags = spawnflags + self:IntrnlGetSF( "sf262144" ) * 262144 + self:IntrnlGetSF( "sf524288" ) * 524288
local ang = Angle( math.sin( CurTime() ) * 16 - 55, trace.HitNormal:Angle().y, 0 )
if ( trace.HitNormal.z > 0.9999 ) then ang.y = ply:GetAngles().y end
local env_headcrabcanister = MakeHeadcrabCanister(
ply,
self.Model,
trace.HitPos,
ang,
self:GetClientNumber( "key_fire" ),
self:GetClientNumber( "key_open" ),
self:GetClientNumber( "key_spawn" ),
self:GetClientNumber( "fire_immediately" ),
self:GetClientNumber( "headcrab" ),
self:GetClientNumber( "count" ),
self:GetClientNumber( "speed" ),
self:GetClientNumber( "time" ),
self:GetClientNumber( "height" ),
self:GetClientNumber( "damage" ),
self:GetClientNumber( "radius" ),
self:GetClientNumber( "duration" ),
spawnflags,
self:GetClientNumber( "smoke" )
)
undo.Create( "env_headcrabcanister" )
undo.AddEntity( env_headcrabcanister )
undo.SetPlayer( ply )
undo.Finish()
return true
end
function TOOL:UpdateGhostEntity( ent, ply )
if ( !IsValid( ent ) ) then return end
local trace = ply:GetEyeTrace()
if ( !trace.Hit or trace.HitNormal.z < 0 ) then ent:SetNoDraw( true ) return end
if ( IsValid( trace.Entity ) and ( trace.Entity:GetClass() == "env_headcrabcanister" or trace.Entity:IsPlayer() or trace.Entity:IsNPC() ) ) then ent:SetNoDraw( true ) return end
local min = ent:OBBMins()
local ang = Angle( math.sin( CurTime() ) * 16 - 55, trace.HitNormal:Angle().y, 0 )
if ( trace.HitNormal.z > 0.9999 ) then
ang.y = ply:GetAngles().y
ent:SetPos( trace.HitPos - trace.HitNormal * min.z - Vector( 0, 0, 16 ) )
else
ent:SetPos( trace.HitPos - trace.HitNormal )
end
ent:SetAngles( ang )
ent:SetNoDraw( false )
end
function TOOL:Think()
if ( !IsValid( self.GhostEntity ) or self.GhostEntity:GetModel() != self.Model ) then
self:MakeGhostEntity( self.Model, Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
end
self:UpdateGhostEntity( self.GhostEntity, self:GetOwner() )
end
list.Set( "HeadcrabModels", "#npc_headcrab", { env_headcrabcanister_headcrab = "0" } )
list.Set( "HeadcrabModels", "#npc_headcrab_fast", { env_headcrabcanister_headcrab = "1" } )
list.Set( "HeadcrabModels", "#npc_headcrab_poison", { env_headcrabcanister_headcrab = "2" } )
if ( SERVER ) then return end
TOOL.Information = { { name = "left" } }
language.Add( "tool.env_headcrabcanister", "Headcrab Canisters" )
language.Add( "tool.env_headcrabcanister.name", "Headcrab Canister Tool" )
language.Add( "tool.env_headcrabcanister.desc", "Spawn headcrab canisters" )
language.Add( "tool.env_headcrabcanister.left", "Spawn a headcrab canister" )
language.Add( "tool.env_headcrabcanister.fire", "Fire Headcrab Canister" )
language.Add( "tool.env_headcrabcanister.fire_immediately", "Fire on spawn" )
language.Add( "tool.env_headcrabcanister.open", "Open The Canister" )
language.Add( "tool.env_headcrabcanister.spawn", "Spawn headcrabs" )
language.Add( "tool.env_headcrabcanister.headcrab", "Headcrab Type" )
language.Add( "tool.env_headcrabcanister.count", "Headcrab count:" )
language.Add( "tool.env_headcrabcanister.speed", "Flight speed:" )
language.Add( "tool.env_headcrabcanister.time", "Flight time:" )
language.Add( "tool.env_headcrabcanister.height", "Starting height:" )
language.Add( "tool.env_headcrabcanister.damage", "Impact damage:" )
language.Add( "tool.env_headcrabcanister.radius", "Damage radius:" )
language.Add( "tool.env_headcrabcanister.duration", "Smoke duration:" )
language.Add( "tool.env_headcrabcanister.smoke", "Always smoke" )
language.Add( "tool.env_headcrabcanister.sf1", "No impact sound" )
language.Add( "tool.env_headcrabcanister.sf2", "No launch sound" )
language.Add( "tool.env_headcrabcanister.sf4096", "Start impacted" )
language.Add( "tool.env_headcrabcanister.sf16384", "Wait for input to open" )
language.Add( "tool.env_headcrabcanister.sf32768", "Wait for input to spawn headcrabs" )
language.Add( "tool.env_headcrabcanister.sf65536", "No smoke" )
language.Add( "tool.env_headcrabcanister.sf131072", "No shake" )
language.Add( "tool.env_headcrabcanister.sf262144", "Remove on impact" )
language.Add( "tool.env_headcrabcanister.sf524288", "No impact effects" )
language.Add( "Cleanup_env_headcrabcanisters", "Headcrab Canisters" )
language.Add( "Cleaned_env_headcrabcanisters", "Cleaned up all Headcrab Canisters" )
language.Add( "SBoxLimit_env_headcrabcanisters", "You've hit the Headcrab Canisters limit!" )
language.Add( "Undone_env_headcrabcanister", "Headcrab Canister undone" )
language.Add( "max_env_headcrabcanisters", "Max Headcrab Canisters:" )
local ConVarsDefault = TOOL:BuildConVarList()
function TOOL.BuildCPanel( panel )
panel:AddControl( "ComboBox", { MenuButton = 1, Folder = "env_headcrabcanister", Options = { [ "#preset.default" ] = ConVarsDefault }, CVars = table.GetKeys( ConVarsDefault ) } )
panel:AddControl( "Numpad", { Label = "#tool.env_headcrabcanister.fire", Command = "env_headcrabcanister_key_fire" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.fire_immediately", Command = "env_headcrabcanister_fire_immediately" } )
panel:AddControl( "Numpad", { Label = "#tool.env_headcrabcanister.open", Command = "env_headcrabcanister_key_open", Label2 = "#tool.env_headcrabcanister.spawn", Command2 = "env_headcrabcanister_key_spawn" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.sf16384", Command = "env_headcrabcanister_sf16384" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.sf32768", Command = "env_headcrabcanister_sf32768" } )
panel:AddControl( "ListBox", { Label = "#tool.env_headcrabcanister.headcrab", Height = 68, Options = list.Get( "HeadcrabModels" ) } )
panel:AddControl( "Slider", { Label = "#tool.env_headcrabcanister.count", Max = 10, Command = "env_headcrabcanister_count" } )
panel:AddControl( "Slider", { Label = "#tool.env_headcrabcanister.speed", Type = "Float", Min = 1, Max = 8192, Command = "env_headcrabcanister_speed" } )
panel:AddControl( "Slider", { Label = "#tool.env_headcrabcanister.time", Type = "Float", Max = 30, Command = "env_headcrabcanister_time" } )
panel:AddControl( "Slider", { Label = "#tool.env_headcrabcanister.height", Type = "Float", Max = 10240, Command = "env_headcrabcanister_height" } )
panel:AddControl( "Slider", { Label = "#tool.env_headcrabcanister.damage", Type = "Float", Max = 256, Command = "env_headcrabcanister_damage" } )
panel:AddControl( "Slider", { Label = "#tool.env_headcrabcanister.radius", Type = "Float", Max = 1024, Command = "env_headcrabcanister_radius" } )
panel:AddControl( "Slider", { Label = "#tool.env_headcrabcanister.duration", Type = "Float", Max = 90, Command = "env_headcrabcanister_duration" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.smoke", Command = "env_headcrabcanister_smoke" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.sf2", Command = "env_headcrabcanister_sf2" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.sf1", Command = "env_headcrabcanister_sf1" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.sf65536", Command = "env_headcrabcanister_sf65536" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.sf131072", Command = "env_headcrabcanister_sf131072" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.sf524288", Command = "env_headcrabcanister_sf524288" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.sf4096", Command = "env_headcrabcanister_sf4096" } )
panel:AddControl( "Checkbox", { Label = "#tool.env_headcrabcanister.sf262144", Command = "env_headcrabcanister_sf262144" } )
end

View File

@@ -0,0 +1,234 @@
--[[
| 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 = "Effects"
TOOL.Name = "Fire"
TOOL.Command = nil
TOOL.ConfigName = ""
//Default values
TOOL.ClientConVar["lifetime"] = 4
TOOL.ClientConVar["infinite"] = 0
TOOL.ClientConVar["size"] = 64
TOOL.ClientConVar["varysize"] = 0
TOOL.ClientConVar["smoke"] = 1
TOOL.ClientConVar["glow"] = 1
TOOL.ClientConVar["makesound"] = 1
TOOL.ClientConVar["drop"] = 1
TOOL.ClientConVar["key"] = 5
TOOL.ClientConVar["numpadcontrol"] = 0
//List of all spawned fire entities
TOOL.Fires = {}
//Add language descriptions
if (CLIENT) then
language.Add("Tool.fire.name", "Fire Tool")
language.Add("Tool.fire.desc", "Creates customizable fire")
language.Add("Tool.fire.0", "Left-Click: Make a fire Right-Click: Extinguish fire")
language.Add("Cleanup_fires", "Fires")
language.Add("Cleaned_fires", "Cleaned up all Fires")
language.Add("SBoxLimit_fires", "You've hit the Fires limit!")
language.Add("Undone_fire", "Fire undone")
end
//Sandbox-related stuff
cleanup.Register("fires")
CreateConVar("sbox_maxfires", 16, FCVAR_NOTIFY)
//Make a fire
function TOOL:LeftClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return true end
//Check current spawnlimits
if (!self:GetSWEP():CheckLimit("fires")) then return false end
//Retreive settings
local spawnflags = 128 //Delete on extinguish
local lifetime = math.Round(math.Clamp(self:GetClientNumber("lifetime"), 1, 512))
local size = math.Round(math.Clamp(self:GetClientNumber("size"), 32, 128))
if math.Round(math.Clamp(self:GetClientNumber("infinite"), 0, 1)) == 1 then spawnflags = spawnflags + 1 end
if math.Round(math.Clamp(self:GetClientNumber("smoke"), 0, 1)) == 0 then spawnflags = spawnflags + 2 end
if math.Round(math.Clamp(self:GetClientNumber("glow"), 0, 1)) == 0 then spawnflags = spawnflags + 32 end
if math.Round(math.Clamp(self:GetClientNumber("drop"), 0, 1)) == 0 then spawnflags = spawnflags + 16 end
//Vary in size if enabled
if math.Round(math.Clamp(self:GetClientNumber("varysize"), 0, 1)) == 1 then
size = math.Round(math.Clamp(size + math.random(-size*0.42,size*0.42), 32, 128))
if size == 32 then size = size + math.random(0,16) end
if size == 128 then size = size - math.random(0,32) end
end
//Create fire and assign settings
local fire = ents.Create("env_fire")
if !fire || !fire:IsValid() then return false end
fire:SetPos(trace.HitPos)
fire:SetKeyValue("health", tostring(lifetime))
fire:SetKeyValue("firesize", tostring(size))
fire:SetKeyValue("fireattack", tostring(math.random(0.72,1.32)))
fire:SetKeyValue("damagescale", "-1")
fire:SetKeyValue("ignitionpoint", "1200") //Don't ignite from nearby fire
fire:SetKeyValue("spawnflags", tostring(spawnflags))
//Spawn fire
fire:Spawn()
fire:Activate()
if math.Round(math.Clamp(self:GetClientNumber("numpadcontrol"), 0, 1)) == 0 then fire:Fire("StartFire","",0) end
if trace && trace.Entity && trace.Entity:IsValid() && trace.Entity:GetPhysicsObject():IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then fire:SetParent(trace.Entity) end
//Make fire emit burning sounds
if math.Round(math.Clamp(self:GetClientNumber("makesound"), 0, 1)) == 1 then
if math.Round(math.Clamp(self:GetClientNumber("numpadcontrol"), 0, 1)) == 0 then sound.Play( "ambient/fire/ignite.wav", trace.HitPos, 72, 100 ) end
fire.SFX_Sound = CreateSound(fire, Sound("ambient/fire/fire_small_loop" .. math.random(1,2) .. ".wav"))
if math.Round(math.Clamp(self:GetClientNumber("numpadcontrol"), 0, 1)) == 0 then fire.SFX_Sound:PlayEx(0.82, 100) end
if math.Round(math.Clamp(self:GetClientNumber("infinite"), 0, 1)) == 0 then timer.Simple( (lifetime+1), function() if fire && fire:IsValid() then fire.SFX_Sound:Stop() end end ) end
end
//Add to relevant lists
self:GetOwner():AddCount("fires", fire)
table.insert(self.Fires, fire)
//Make sure we can undo
undo.Create("fire")
undo.AddEntity(fire)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "fires", fire)
//Make sure we can control it with numpad
if math.Round(math.Clamp(self:GetClientNumber("numpadcontrol"), 0, 1)) == 1 then
self:SetupNumpadControls(fire)
end
return true
end
//Setup numpad controls
function TOOL:SetupNumpadControls(fire)
//Safeguards
if !fire || !fire:IsValid() || self:GetClientInfo("key") == nil || self:GetClientInfo("key") == -1 then return false end
//Retrieve tool settings
local infinite = math.Round(math.Clamp(self:GetClientNumber("infinite"), 0, 1))
local lifetime = math.Round(math.Clamp(self:GetClientNumber("lifetime"), 1, 512))
//Create KeyDown numpad functions
local function StartEmitFire(ply, fire, infinite, lifetime)
if fire.Started || !fire || !fire:IsValid() then return end
//Start fire and related sounds
if fire.SFX_Sound then fire.SFX_Sound:Stop() end
sound.Play( "ambient/fire/ignite.wav", fire:GetPos(), 72, 100 )
fire.SFX_Sound = CreateSound(fire, Sound("ambient/fire/fire_small_loop" .. math.random(1,2) .. ".wav"))
if infinite == 0 then timer.Simple( (lifetime+1), function() if fire && fire:IsValid() then fire.SFX_Sound:Stop() end end ) end
fire.SFX_Sound:PlayEx(0.82, 100)
fire:Fire("StartFire", "", 0)
fire.Started = true
end
//Register KeyDown functions
numpad.Register("StartEmitFire", StartEmitFire)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "StartEmitFire", fire, infinite, lifetime)
return true
end
//Extinguish fire in radius
function TOOL:RightClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Find fire in radius
local findfire = ents.FindInSphere(trace.HitPos, 42)
for _, fire in pairs(findfire) do
//Extinguish
if fire && fire:IsValid() && !fire:GetPhysicsObject():IsValid() && fire:GetClass() == "env_fire" && !fire:IsPlayer() && !fire:IsNPC() && !fire:IsWorld() then
if fire.SFX_Sound then sound.Play( "ambient/levels/canals/toxic_slime_sizzle3.wav", fire:GetPos(), 68, 100 ) fire.SFX_Sound:Stop() end
fire:Fire("Extinguish", "", 0)
end
end
end
//Extinguish all fires
function TOOL:Reload()
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Get all on-going fires
for x = 1, table.getn(self.Fires) do
local fire = self.Fires[x]
//Extinguish
if fire && fire:IsValid() then
if fire.SFX_Sound then sound.Play( "ambient/levels/canals/toxic_slime_sizzle3.wav", fire:GetPos(), 64, 100 ) fire.SFX_Sound:Stop() end
fire:Fire("Extinguish", "", 0)
end
end
end
//Precache all sounds
function TOOL:Precache()
util.PrecacheSound("ambient/fire/ignite.wav")
util.PrecacheSound("ambient/fire/fire_small_loop1.wav")
util.PrecacheSound("ambient/fire/fire_small_loop2.wav")
util.PrecacheSound("ambient/levels/canals/toxic_slime_sizzle3.wav")
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
//Header
panel:AddControl( "Header", { Text = "#Tool.fire.name", Description = "#Tool.fire.desc" } )
//Lifetime
panel:AddControl( "Slider", { Label = "Lifetime", Type = "Integer", Min = "1", Max = "60", Command ="fire_lifetime" } )
//Infite lifetime
panel:AddControl( "CheckBox", { Label = "Infinite", Description = "Burn infinitely", Command = "fire_infinite" } )
//Size
panel:AddControl( "Slider", { Label = "Size", Type = "Integer", Min = "32", Max = "128", Command ="fire_size" } )
//Variable Size
panel:AddControl( "CheckBox", { Label = "Variable Size", Description = "", Command = "fire_varysize" } )
//----
panel:AddControl( "Label", { Text = "", Description = "" } )
//Smoke
panel:AddControl( "CheckBox", { Label = "Smoke", Description = "", Command = "fire_smoke" } )
//Glow
panel:AddControl( "CheckBox", { Label = "Glow", Description = "", Command = "fire_glow" } )
//Sound
panel:AddControl( "CheckBox", { Label = "Sound", Description = "", Command = "fire_makesound" } )
//Drop to ground
panel:AddControl( "CheckBox", { Label = "Drop to ground", Description = "", Command = "fire_drop" } )
//-------------
panel:AddControl( "Label", { Text = "________________________________________", Description = "" } )
//Numpad menu
panel:AddControl( "Numpad", { Label = "Ignite", Command = "fire_key", ButtonSize = 22 } )
//Use numpad check
panel:AddControl( "CheckBox", { Label = "Ignite with keyboard", Description = "", Command = "fire_numpadcontrol" } )
end

View File

@@ -0,0 +1,213 @@
--[[
| 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 = "Effects"
TOOL.Name = "Glow"
TOOL.Command = nil
TOOL.ConfigName = ""
//Default values
TOOL.ClientConVar["color_r"] = 255
TOOL.ClientConVar["color_g"] = 255
TOOL.ClientConVar["color_b"] = 255
TOOL.ClientConVar["verticalsize"] = 32
TOOL.ClientConVar["horizontalsize"] = 32
TOOL.ClientConVar["mindist"] = 16
TOOL.ClientConVar["maxdist"] = 256
TOOL.ClientConVar["outermaxdist"] = 2048
TOOL.ClientConVar["glowthrough"] = 0
TOOL.ClientConVar["toobject"] = 0
//List of all spawned glow entities
TOOL.Glows = {}
//Add language descriptions
if (CLIENT) then
language.Add("Tool.glow.name", "Glow Tool")
language.Add("Tool.glow.desc", "Creates customizable light glow")
language.Add("Tool.glow.0", "Left-Click: Create glow Right-Click: Remove glow")
language.Add("Cleanup_glows", "Glow Effects")
language.Add("Cleaned_glows", "Cleaned up all Glow Effects")
language.Add("SBoxLimit_glows", "You've hit the Glow Effects limit!")
language.Add("Undone_glow", "Glow undone")
end
//Sandbox-related stuff
cleanup.Register("glows")
CreateConVar("sbox_maxglows", 8, FCVAR_NOTIFY)
//Create sparks
function TOOL:LeftClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return true end
//Check current spawnlimits
if (!self:GetSWEP():CheckLimit("glows")) then return false end
//Find and remove attached glows
if math.Round(math.Clamp(self:GetClientNumber("toobject"), 0, 1)) == 1 && trace.Entity && trace.Entity:IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() && trace.Entity.Glow && trace.Entity.Glow:IsValid() then
trace.Entity.Glow:Fire("Kill", "", 0)
end
//Retreive settings
local color_r = math.Round(math.Clamp(self:GetClientNumber("color_r"), 0, 255))
local color_g = math.Round(math.Clamp(self:GetClientNumber("color_g"), 0, 255))
local color_b = math.Round(math.Clamp(self:GetClientNumber("color_b"), 0, 255))
local verticalsize = math.Round(math.Clamp(self:GetClientNumber("verticalsize"), 1, 256))
local horizontalsize = math.Round(math.Clamp(self:GetClientNumber("horizontalsize"), 1, 256))
local mindist = math.Round(math.Clamp(self:GetClientNumber("mindist"), 1, 8192))
local maxdist = math.Round(math.Clamp(self:GetClientNumber("maxdist"), 1, 8192))
local outermaxdist = math.Round(math.Clamp(self:GetClientNumber("outermaxdist"), 1, 8192))
//Original distance formula
//local mindist = maxdist / 16
//local outermaxdist = maxdist * 8
//Create glow and assign settings
local glow = ents.Create("env_lightglow")
if !glow || !glow:IsValid() then return false end
glow:SetPos(trace.HitPos)
//glow:SetAngles(self:GetOwner():GetAngles())
glow:SetKeyValue("HDRColorScale", "1")
glow:SetKeyValue("rendercolor", "" .. tostring(color_r) .. " " .. tostring(color_g) .. " " .. tostring(color_b) .. "")
glow:SetKeyValue("VerticalGlowSize", tostring(verticalsize))
glow:SetKeyValue("HorizontalGlowSize", tostring(horizontalsize))
glow:SetKeyValue("MaxDist", tostring(maxdist))
glow:SetKeyValue("MinDist", tostring(mindist))
glow:SetKeyValue("OuterMaxDist", tostring(outermaxdist))
if math.Round(math.Clamp(self:GetClientNumber("glowthrough"), 0, 1)) == 1 then glow:SetKeyValue("GlowProxySize", tostring( (verticalsize + horizontalsize) / 3 )) else glow:SetKeyValue("GlowProxySize", "0") end
//glow:SetKeyValue("spawnflags", "1")
//Center to object if told to
if math.Round(math.Clamp(self:GetClientNumber("toobject"), 0, 1)) == 1 && trace.Entity && trace.Entity:IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then
glow:SetPos(trace.Entity:LocalToWorld(trace.Entity:OBBCenter()))
glow:SetKeyValue("GlowProxySize", tostring(trace.Entity:BoundingRadius()))
trace.Entity.Glow = glow
end
//Spawn glow
glow:Spawn()
glow:Activate()
if trace && trace.Entity && trace.Entity:IsValid() && trace.Entity:GetPhysicsObject():IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then glow:SetParent(trace.Entity) end
//sound.Play( "weapons/ar2/ar2_reload_push.wav", trace.HitPos, 72, 100 )
//Add to relevant lists
self:GetOwner():AddCount("glows", glow)
table.insert(self.Glows, glow)
//Make sure we can undo
undo.Create("glow")
undo.AddEntity(glow)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "glows", glow)
return true
end
//Remove sparks in radius
function TOOL:RightClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Find and remove attached glows
if trace.Entity && trace.Entity:IsValid() && trace.Entity.Glow && trace.Entity.Glow:IsValid() then
trace.Entity.Glow:Fire("Kill", "", 0)
end
//Find glows in radius
local findglows = ents.FindInSphere( trace.HitPos, ((math.Round(math.Clamp(self:GetClientNumber("verticalsize"), 1, 256)) + math.Round(math.Clamp(self:GetClientNumber("horizontalsize"), 1, 256)))/2) )
for _, glow in pairs(findglows) do
//Remove
if glow && glow:IsValid() && !glow:GetPhysicsObject():IsValid() && glow:GetClass() == "env_lightglow" && !glow:IsPlayer() && !glow:IsNPC() && !glow:IsWorld() then
glow:Fire("Kill", "", 0)
end
end
end
//Remove all sparks
function TOOL:Reload()
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Get all glows
for x = 1, table.getn(self.Glows) do
local glow = self.Glows[x]
//Remove
if glow && glow:IsValid() then
glow:Fire("Kill", "", 0)
end
end
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
//Header
panel:AddControl( "Header", { Text = "#Tool.glow.name", Description = "#Tool.glow.desc" } )
//Build preset menu and declare default preset
local params = { Label = "#Presets", MenuButton = 1, Folder = "glow", Options = {}, CVars = {} }
//Declare default preset
params.Options.default = {
glow_color_r = 255,
glow_color_g = 255,
glow_color_b = 255,
glow_verticalsize = 32,
glow_horizontalsize = 32,
glow_mindist = 16,
glow_maxdist = 256,
glow_outermaxdist = 2048,
}
//Declare console variables
table.insert( params.CVars, "glow_color_r" )
table.insert( params.CVars, "glow_color_g" )
table.insert( params.CVars, "glow_color_b" )
table.insert( params.CVars, "glow_verticalsize" )
table.insert( params.CVars, "glow_horizontalsize" )
table.insert( params.CVars, "glow_mindist" )
table.insert( params.CVars, "glow_maxdist" )
table.insert( params.CVars, "glow_outermaxdist" )
//All done
panel:AddControl( "ComboBox", params )
//Color picker
panel:AddControl( "Color", { Label = "Glow color", Red = "glow_color_r", Green = "glow_color_g", Blue = "glow_color_b", ShowAlpha = "0", ShowHSV = "1", ShowRGB = "1", Multiplier = "255" } )
//Vertical Size
panel:AddControl( "Slider", { Label = "Vertical Size", Type = "Float", Min = "1", Max = "256", Command ="glow_verticalsize" } )
//Horizontal Size
panel:AddControl( "Slider", { Label = "Horizontal Size", Type = "Float", Min = "1", Max = "256", Command ="glow_horizontalsize" } )
//Minimum Distance Scale
panel:AddControl( "Slider", { Label = "Minimum Visibility Distance", Type = "Float", Min = "1", Max = "1024", Command ="glow_mindist" } )
//Visibility Distance Scale
panel:AddControl( "Slider", { Label = "Optimal Visibility Distance", Type = "Float", Min = "1", Max = "1024", Command ="glow_maxdist" } )
//Maximum Distance Scale
panel:AddControl( "Slider", { Label = "Maximum Visibility Distance", Type = "Float", Min = "1", Max = "1024", Command ="glow_outermaxdist" } )
//Glow through object
panel:AddControl( "CheckBox", { Label = "Glow through object", Description = "", Command = "glow_glowthrough" } )
//Center to object
panel:AddControl( "CheckBox", { Label = "Center to object", Description = "", Command = "glow_toobject" } )
end

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 = "Half-Life 2"
TOOL.Name = "#tool.item_ammo_crate"
TOOL.ClientConVar[ "type" ] = "0"
local ToolModels = {}
ToolModels[ 0 ] = "models/items/ammocrate_pistol.mdl"
ToolModels[ 1 ] = "models/items/ammocrate_smg1.mdl"
ToolModels[ 2 ] = "models/items/ammocrate_ar2.mdl"
ToolModels[ 3 ] = "models/items/ammocrate_rockets.mdl"
ToolModels[ 4 ] = "models/items/ammocrate_buckshot.mdl"
ToolModels[ 5 ] = "models/items/ammocrate_grenade.mdl"
ToolModels[ 6 ] = "models/items/ammocrate_357.mdl"
ToolModels[ 7 ] = "models/items/ammocrate_crossbow.mdl"
ToolModels[ 8 ] = "models/items/ammocrate_ar2.mdl"
ToolModels[ 9 ] = "models/items/ammocrate_smg2.mdl"
ToolModels[ 10 ] = "models/items/ammocrate_smg1.mdl"
cleanup.Register( "item_ammo_crates" )
if ( SERVER ) then
local rb655_force_downloads = CreateConVar( "rb655_force_downloads", "0", FCVAR_ARCHIVE )
if ( rb655_force_downloads:GetFloat() > 0 ) then
resource.AddFile( "models/items/ammocrate_357.mdl" )
resource.AddFile( "models/items/ammocrate_crossbow.mdl" )
end
CreateConVar( "sbox_maxitem_ammo_crates", 10, FCVAR_ARCHIVE + FCVAR_REPLICATED + FCVAR_NOTIFY )
function MakeAmmoCrate( ply, model, pos, ang, type )
if ( IsValid( ply ) and !ply:CheckLimit( "item_ammo_crates" ) ) then return nil end
type = tonumber( type ) or 0
local item_ammo_crate = ents.Create( "item_ammo_crate" )
if ( !IsValid( item_ammo_crate ) ) then return nil end
item_ammo_crate:SetPos( pos )
item_ammo_crate:SetAngles( ang )
item_ammo_crate:SetKeyValue( "AmmoType", math.Clamp( type, 0, 9 ) )
item_ammo_crate:Spawn()
item_ammo_crate:Activate()
item_ammo_crate:SetModel( model )
table.Merge( item_ammo_crate:GetTable(), {
ply = ply,
type = type
} )
if ( IsValid( ply ) ) then
ply:AddCount( "item_ammo_crates", item_ammo_crate )
ply:AddCleanup( "item_ammo_crates", item_ammo_crate )
end
DoPropSpawnedEffect( item_ammo_crate )
return item_ammo_crate
end
duplicator.RegisterEntityClass( "item_ammo_crate", MakeAmmoCrate, "model", "pos", "ang", "type" )
end
function TOOL:LeftClick( trace )
if ( trace.HitSky or !trace.HitPos or trace.HitNormal.z < 0.7 ) then return false end
if ( IsValid( trace.Entity ) and ( trace.Entity:GetClass() == "item_ammo_crate" or trace.Entity:IsPlayer() or trace.Entity:IsNPC() ) ) then return false end
if ( CLIENT ) then return true end
local ply = self:GetOwner()
local ang = trace.HitNormal:Angle()
ang.p = ang.p - 270
if ( trace.HitNormal.z > 0.9999 ) then ang.y = ply:GetAngles().y + 180 end
local type = self:GetClientNumber( "type" )
if ( type == 10 ) then type = math.random( 0, 9 ) end
local item_ammo_crate = MakeAmmoCrate( ply, ToolModels[ type ], trace.HitPos + trace.HitNormal * 16, ang, type )
undo.Create( "item_ammo_crate" )
undo.AddEntity( item_ammo_crate )
undo.SetPlayer( ply )
undo.Finish()
return true
end
function TOOL:UpdateGhostEntity( ent, ply )
if ( !IsValid( ent ) ) then return end
local trace = ply:GetEyeTrace()
if ( !trace.Hit or trace.HitNormal.z < 0.7 ) then ent:SetNoDraw( true ) return end
if ( IsValid( trace.Entity ) and ( trace.Entity:GetClass() == "item_ammo_crate" or trace.Entity:IsPlayer() ) ) then ent:SetNoDraw( true ) return end
local ang = trace.HitNormal:Angle()
ang.p = ang.p - 270
if ( trace.HitNormal.z > 0.9999 ) then ang.y = ply:GetAngles().y + 180 end
local min = ent:OBBMins()
ent:SetPos( trace.HitPos - trace.HitNormal * min.z )
ent:SetAngles( ang )
ent:SetNoDraw( false )
end
function TOOL:Think()
if ( !IsValid( self.GhostEntity ) or self.GhostEntity:GetModel() != ToolModels[ self:GetClientNumber( "type" ) ] ) then
self:MakeGhostEntity( ToolModels[ self:GetClientNumber( "type" ) ], Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
end
self:UpdateGhostEntity( self.GhostEntity, self:GetOwner() )
end
list.Set( "AmmoCrateTypes", "#Pistol_ammo", { item_ammo_crate_type = "0" } )
list.Set( "AmmoCrateTypes", "#Buckshot_ammo", { item_ammo_crate_type = "4" } )
list.Set( "AmmoCrateTypes", "#SMG1_grenade_ammo", { item_ammo_crate_type = "9" } )
list.Set( "AmmoCrateTypes", "#SMG1_ammo", { item_ammo_crate_type = "1" } )
list.Set( "AmmoCrateTypes", "#AR2_ammo", { item_ammo_crate_type = "2" } )
list.Set( "AmmoCrateTypes", "#RPG_round_ammo", { item_ammo_crate_type = "3" } )
list.Set( "AmmoCrateTypes", "#Buckshot_ammo", { item_ammo_crate_type = "4" } )
list.Set( "AmmoCrateTypes", "#Grenade_ammo", { item_ammo_crate_type = "5" } )
list.Set( "AmmoCrateTypes", "#357_ammo", { item_ammo_crate_type = "6" } )
list.Set( "AmmoCrateTypes", "#XBowBolt_ammo", { item_ammo_crate_type = "7" } )
list.Set( "AmmoCrateTypes", "#AR2AltFire_ammo", { item_ammo_crate_type = "8" } )
list.Set( "AmmoCrateTypes", "#SMG1_grenade_ammo", { item_ammo_crate_type = "9" } )
list.Set( "AmmoCrateTypes", "#tool.item_ammo_crate.random", { item_ammo_crate_type = "10" } )
if ( SERVER ) then return end
TOOL.Information = { { name = "left" } }
language.Add( "tool.item_ammo_crate", "Ammo Crates" )
language.Add( "tool.item_ammo_crate.name", "Ammo Crate Tool" )
language.Add( "tool.item_ammo_crate.desc", "Spawn crates full of ammo for resupply" )
language.Add( "tool.item_ammo_crate.left", "Spawn an ammo crate" )
language.Add( "tool.item_ammo_crate.type", "Ammo Crate Type" )
language.Add( "tool.item_ammo_crate.random", "Random" )
language.Add( "Cleanup_item_ammo_crates", "Ammo Crates" )
language.Add( "Cleaned_item_ammo_crates", "Cleaned up all Ammo Crates" )
language.Add( "SBoxLimit_item_ammo_crates", "You've hit the Ammo Crate limit!" )
language.Add( "Undone_item_ammo_crate", "Ammo Crate undone" )
language.Add( "max_item_ammo_crates", "Max Ammo Crates:" )
function TOOL.BuildCPanel( panel )
panel:AddControl( "ListBox", { Label = "#tool.item_ammo_crate.type", Options = list.Get( "AmmoCrateTypes" ), Height = 204 } )
end

View File

@@ -0,0 +1,150 @@
--[[
| 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 = "Half-Life 2"
TOOL.Name = "#tool.item_charger_spawner"
TOOL.ClientConVar[ "type" ] = "0"
--TOOL.ClientConVar[ "citadel" ] = "0"
list.Set( "ChargerTypes", "#item_suitcharger", { item_charger_spawner_type = 0, model = "models/props_combine/suit_charger001.mdl", classname = "item_suitcharger" } )
list.Set( "ChargerTypes", "#item_healthcharger", { item_charger_spawner_type = 1, model = "models/props_combine/health_charger001.mdl", classname = "item_healthcharger" } )
if ( SERVER ) then
--[[duplicator.RegisterEntityModifier( "rb655_citadel_charger", function( ply, ent, data )
ent:SetKeyValue( "spawnflags", 8192 )
end )]]
function MakeHalfLifeCharger( ply, entry, pos, ang --[[, isCitadel]] )
-- Ask the gamemode if it's ok to spawn this
if ( !gamemode.Call( "PlayerSpawnSENT", ply, entry.classname ) ) then return end
-- Spawn it!
local item_charger = ents.Create( entry.classname )
if ( !IsValid( item_charger ) ) then return nil end
item_charger:SetPos( pos )
item_charger:SetAngles( ang )
--[[if ( isCitadel ) then
duplicator.StoreEntityModifier( item_charger, "rb655_citadel_charger", {} )
duplicator.ApplyEntityModifiers( ply, item_charger )
end]]
item_charger:Spawn()
item_charger:Activate()
DoPropSpawnedEffect( item_charger )
-- Pretend we are a SENT
if ( IsValid( ply ) ) then
gamemode.Call( "PlayerSpawnedSENT", ply, item_charger )
end
undo.Create( "SENT" )
undo.SetPlayer( ply )
undo.AddEntity( item_charger )
undo.SetCustomUndoText( "Undone " .. entry.classname )
undo.Finish( "Scripted Entity (" .. tostring( entry.classname ) .. ")" )
ply:AddCleanup( "sents", item_charger )
item_charger:SetVar( "Player", ply )
return item_charger
end
end
function TOOL:LeftClick( trace )
if ( trace.HitSky or !trace.HitPos ) then return false end
if ( IsValid( trace.Entity ) and ( trace.Entity:IsPlayer() or trace.Entity:IsNPC() ) ) then return false end
local entry = self:GetSelectedEntry()
if ( !entry ) then return false end
if ( IsValid( trace.Entity ) and trace.Entity:GetClass() == entry.classname ) then return false end
if ( CLIENT ) then return true end
--local isCitadel = self:GetClientNumber( "citadel" ) != 0
local ply = self:GetOwner()
local ang = trace.HitNormal:Angle()
MakeHalfLifeCharger( ply, entry, trace.HitPos, ang --[[, isCitadel]] )
return true
end
function TOOL:GetSelectedEntry()
local t = self:GetClientNumber( "type" )
local options = list.Get( "ChargerTypes" )
for label, tab in pairs( options ) do
if ( tab.item_charger_spawner_type == t ) then return tab end
end
end
function TOOL:Think()
local entry = self:GetSelectedEntry()
if ( !entry ) then
if ( IsValid( self.GhostEntity ) ) then self.GhostEntity:SetNoDraw( true ) end
return
end
if ( !IsValid( self.GhostEntity ) or self.GhostEntity:GetModel() != entry.model ) then
self:MakeGhostEntity( entry.model, Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
end
self:UpdateGhostEntity( self.GhostEntity, self:GetOwner(), entry )
end
function TOOL:UpdateGhostEntity( ent, ply, entry )
if ( !IsValid( ent ) ) then return end
local trace = ply:GetEyeTrace()
if ( !trace.Hit or !entry ) then ent:SetNoDraw( true ) return end
if ( IsValid( trace.Entity ) and ( trace.Entity:GetClass() == entry.classname or trace.Entity:IsPlayer() or trace.Entity:IsNPC() ) ) then ent:SetNoDraw( true ) return end
ent:SetPos( trace.HitPos )
local ang = trace.HitNormal:Angle()
ent:SetAngles( ang )
ent:SetNoDraw( false )
end
if ( SERVER ) then return end
TOOL.Information = { { name = "left" } }
language.Add( "tool.item_charger_spawner", "Charger Spawner" )
language.Add( "tool.item_charger_spawner.name", "Charger Spawner" )
language.Add( "tool.item_charger_spawner.desc", "Allows precision spawning of the suit & health chargers." )
language.Add( "tool.item_charger_spawner.left", "Spawn a charger" )
language.Add( "tool.item_charger_spawner.type", "Charger Spawner Type" )
--language.Add( "tool.item_charger_spawner.citadel", "Citadel Suit Charger" )
function TOOL.BuildCPanel( panel )
panel:AddControl( "ListBox", { Label = "#tool.item_charger_spawner.type", Options = list.Get( "ChargerTypes" ), Height = 128 } )
-- I can't be bothered to get it to work well with duplicator, so fuck it
--panel:CheckBox( "#tool.item_charger_spawner.citadel", "item_charger_spawner_citadel" )
end

View File

@@ -0,0 +1,314 @@
--[[
| 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 = "Half-Life 2"
TOOL.Name = "#tool.item_item_crate"
TOOL.Models = {}
TOOL.Models[ "models/items/item_item_crate.mdl" ] = 0
TOOL.Models[ "models/items/item_beacon_crate.mdl" ] = 1
TOOL.ClientConVar[ "model" ] = "models/items/item_item_crate.mdl"
TOOL.ClientConVar[ "item" ] = "item_healthkit"
TOOL.ClientConVar[ "amount" ] = "3"
TOOL.ClientConVar[ "health" ] = "25"
TOOL.ClientConVar[ "desired_health" ] = "100"
TOOL.ClientConVar[ "desired_armor" ] = "30"
TOOL.ClientConVar[ "desired_pistol" ] = "50"
TOOL.ClientConVar[ "desired_smg1" ] = "50"
TOOL.ClientConVar[ "desired_smg1_alt" ] = "10"
TOOL.ClientConVar[ "desired_ar2" ] = "40"
TOOL.ClientConVar[ "desired_shotgun" ] = "50"
TOOL.ClientConVar[ "desired_rpg" ] = "0"
TOOL.ClientConVar[ "desired_grenade" ] = "10"
TOOL.ClientConVar[ "desired_357" ] = "0"
TOOL.ClientConVar[ "desired_crossbow" ] = "0"
TOOL.ClientConVar[ "desired_ar2_alt" ] = "0"
cleanup.Register( "item_item_crates" )
if ( SERVER ) then
CreateConVar( "sbox_maxitem_item_crates", 8, FCVAR_ARCHIVE + FCVAR_REPLICATED + FCVAR_NOTIFY )
function MakeItemCrate( ply, pos, ang, appearance, class, amount, health, dynamic_values )
if ( IsValid( ply ) and !ply:CheckLimit( "item_item_crates" ) ) then return nil end
local item_item_crate = ents.Create( "item_item_crate" )
if ( !IsValid( item_item_crate ) ) then return false end
item_item_crate:SetPos( pos )
item_item_crate:SetAngles( ang )
-- Map placed entity fix
class = class or "item_dynamic_ressuply"
appearance = appearance or 0
amount = tonumber( amount ) or 1
dynamic_values = dynamic_values or {}
if ( class == "item_dynamic_resupply" ) then
local item_dynamic_resupply = ents.Create( "item_dynamic_resupply" )
item_dynamic_resupply:SetKeyValue( "targetname", "rb655_item_dynamic_resupply" .. item_dynamic_resupply:EntIndex() )
for i, n in pairs( dynamic_values ) do
item_dynamic_resupply:SetKeyValue( i, n )
end
item_item_crate:SetKeyValue( "SpecificResupply", "rb655_item_dynamic_resupply" .. item_dynamic_resupply:EntIndex() )
item_item_crate:DeleteOnRemove( item_dynamic_resupply )
end
item_item_crate:SetKeyValue( "CrateAppearance", appearance )
item_item_crate:SetKeyValue( "ItemClass", class )
item_item_crate:SetKeyValue( "ItemCount", math.Clamp( amount , 1, 25 ) )
item_item_crate:Spawn()
item_item_crate:Activate()
if ( health ) then item_item_crate:Fire( "SetHealth", math.Clamp( health, 1, 100 ) ) end
if ( appearance and appearance == 1 ) then -- Episode 2 Jalopy radar thingy
local t = ents.Create( "info_radar_target" )
t:SetPos( item_item_crate:GetPos() )
t:SetKeyValue( "mode", 0 )
t:SetKeyValue( "type", 0 )
t:SetKeyValue( "radius", 1200 )
t:Spawn()
t:Activate()
t:Fire( "Enable" )
t:SetParent( item_item_crate )
end
table.Merge( item_item_crate:GetTable(), {
ply = ply,
appearance = appearance,
class = class,
amount = amount,
health = health,
dynamic_values = dynamic_values,
} )
if ( IsValid( ply ) ) then
ply:AddCount( "item_item_crates", item_item_crate )
ply:AddCleanup( "item_item_crates", item_item_crate )
end
DoPropSpawnedEffect( item_item_crate )
return item_item_crate
end
duplicator.RegisterEntityClass( "item_item_crate", MakeItemCrate, "pos", "ang", "appearance", "class", "amount", "health", "dynamic_values" )
end
function TOOL:LeftClick( trace )
if ( trace.HitSky or !trace.HitPos or IsValid( trace.Entity ) and ( trace.Entity:IsPlayer() or trace.Entity:IsNPC() ) ) then return false end
if ( CLIENT ) then return true end
local ply = self:GetOwner()
local ang = trace.HitNormal:Angle()
ang.pitch = ang.pitch - 270
if ( trace.HitNormal.z > 0.9999 ) then ang.y = ply:GetAngles().y + 90 end
local item = self:GetClientInfo( "item" )
if ( item == "" ) then
local t = {}
for k, v in pairs( list.Get( "ItemCrateItems" ) ) do
if ( k == "#tool.item_item_crate.random" ) then continue end
table.insert( t, v.item_item_crate_item )
end
item = t[ math.random( 1, #t ) ]
end
local contains = false
for k, v in pairs( list.Get( "ItemCrateItems" ) ) do
if ( !v.item_item_crate_item ) then continue end
if ( item != v.item_item_crate_item ) then continue end
contains = true
end
if ( !contains ) then return end
local dynamic_values = {
DesiredHealth = self:GetClientInfo( "desired_health" ) / 100,
DesiredArmor = self:GetClientInfo( "desired_armor" ) / 100,
DesiredAmmoPistol = self:GetClientInfo( "desired_pistol" ) / 100,
DesiredAmmoSMG1 = self:GetClientInfo( "desired_smg1" ) / 100,
DesiredAmmoSMG1_Grenade = self:GetClientInfo( "desired_smg1_alt" ) / 100,
DesiredAmmoAR2 = self:GetClientInfo( "desired_ar2" ) / 100,
DesiredAmmoBuckshot = self:GetClientInfo( "desired_shotgun" ) / 100,
DesiredAmmoRPG_Round = self:GetClientInfo( "desired_rpg" ) / 100,
DesiredAmmoGrenade = self:GetClientInfo( "desired_grenade" ) / 100,
DesiredAmmo357 = self:GetClientInfo( "desired_357" ) / 100,
DesiredAmmoCrossbow = self:GetClientInfo( "desired_crossbow" ) / 100,
DesiredAmmoAR2_AltFire = self:GetClientInfo( "desired_ar2_alt" ) / 100
}
local item_item_crate = MakeItemCrate( ply, trace.HitPos, ang, self.Models[ self:GetClientInfo( "model" ) ], item, self:GetClientNumber( "amount" ), self:GetClientNumber( "health" ), dynamic_values )
undo.Create( "item_item_crate" )
undo.AddEntity( item_item_crate )
undo.SetPlayer( ply )
undo.Finish()
return true
end
function TOOL:UpdateGhostEntity( ent, ply )
if ( !IsValid( ent ) ) then return end
local trace = ply:GetEyeTrace()
if ( !trace.Hit ) then return end
if ( IsValid( trace.Entity ) and ( trace.Entity:GetClass() == "item_item_crate" or trace.Entity:IsPlayer() ) ) then ent:SetNoDraw( true ) return end
local ang = trace.HitNormal:Angle()
ang.pitch = ang.pitch - 270
if ( trace.HitNormal.z > 0.9999 ) then ang.y = ply:GetAngles().y + 90 end
local min = ent:OBBMins()
ent:SetPos( trace.HitPos - trace.HitNormal * min.z )
ent:SetAngles( ang )
ent:SetNoDraw( false )
end
function TOOL:Think()
if ( !IsValid( self.GhostEntity ) or self.GhostEntity:GetModel() != self:GetClientInfo( "model" ) ) then
self:MakeGhostEntity( self:GetClientInfo( "model" ), Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
end
self:UpdateGhostEntity( self.GhostEntity, self:GetOwner() )
end
list.Set( "ItemCrateModels", "models/items/item_item_crate.mdl", {} )
list.Set( "ItemCrateModels", "models/items/item_beacon_crate.mdl", {} )
list.Set( "ItemCrateItems", "#item_ammo_pistol", { item_item_crate_item = "item_ammo_pistol" } )
list.Set( "ItemCrateItems", "#item_ammo_pistol_large", { item_item_crate_item = "item_ammo_pistol_large" } )
list.Set( "ItemCrateItems", "#item_ammo_smg1", { item_item_crate_item = "item_ammo_smg1" } )
list.Set( "ItemCrateItems", "#item_ammo_smg1_large", { item_item_crate_item = "item_ammo_smg1_large" } )
list.Set( "ItemCrateItems", "#item_ammo_smg1_grenade", { item_item_crate_item = "item_ammo_smg1_grenade" } )
list.Set( "ItemCrateItems", "#item_ammo_ar2", { item_item_crate_item = "item_ammo_ar2" } )
list.Set( "ItemCrateItems", "#item_ammo_ar2_large", { item_item_crate_item = "item_ammo_ar2_large" } )
list.Set( "ItemCrateItems", "#item_ammo_ar2_altfire", { item_item_crate_item = "item_ammo_ar2_altfire" } )
list.Set( "ItemCrateItems", "#item_ammo_357", { item_item_crate_item = "item_ammo_357" } )
list.Set( "ItemCrateItems", "#item_ammo_357_large", { item_item_crate_item = "item_ammo_357_large" } )
list.Set( "ItemCrateItems", "#item_ammo_crossbow", { item_item_crate_item = "item_ammo_crossbow" } )
list.Set( "ItemCrateItems", "#item_rpg_round", { item_item_crate_item = "item_rpg_round" } )
list.Set( "ItemCrateItems", "#item_box_buckshot", { item_item_crate_item = "item_box_buckshot" } )
list.Set( "ItemCrateItems", "#item_battery", { item_item_crate_item = "item_battery" } )
list.Set( "ItemCrateItems", "#item_healthvial", { item_item_crate_item = "item_healthvial" } )
list.Set( "ItemCrateItems", "#item_healthkit", { item_item_crate_item = "item_healthkit" } )
list.Set( "ItemCrateItems", "#item_grubnugget", { item_item_crate_item = "item_grubnugget" } )
list.Set( "ItemCrateItems", "#item_dynamic_resupply", { item_item_crate_item = "item_dynamic_resupply" } )
list.Set( "ItemCrateItems", "#tool.item_item_crate.random", { item_item_crate_item = "" } )
list.Set( "ItemCrateItems", "#weapon_crowbar", { item_item_crate_item = "weapon_crowbar" } )
list.Set( "ItemCrateItems", "#weapon_stunstick", { item_item_crate_item = "weapon_stunstick" } )
list.Set( "ItemCrateItems", "#weapon_physcannon", { item_item_crate_item = "weapon_physcannon" } )
list.Set( "ItemCrateItems", "#weapon_physgun", { item_item_crate_item = "weapon_physgun" } )
list.Set( "ItemCrateItems", "#weapon_pistol", { item_item_crate_item = "weapon_pistol" } )
list.Set( "ItemCrateItems", "#weapon_357", { item_item_crate_item = "weapon_357" } )
list.Set( "ItemCrateItems", "#weapon_smg1", { item_item_crate_item = "weapon_smg1" } )
list.Set( "ItemCrateItems", "#weapon_ar2", { item_item_crate_item = "weapon_ar2" } )
list.Set( "ItemCrateItems", "#weapon_shotgun", { item_item_crate_item = "weapon_shotgun" } )
list.Set( "ItemCrateItems", "#weapon_crossbow", { item_item_crate_item = "weapon_crossbow" } )
list.Set( "ItemCrateItems", "#weapon_rpg", { item_item_crate_item = "weapon_rpg" } )
list.Set( "ItemCrateItems", "#weapon_frag", { item_item_crate_item = "weapon_frag" } )
if ( SERVER ) then return end
TOOL.Information = { { name = "left" } }
concommand.Add( "item_item_crate_reset", function()
RunConsoleCommand( "item_item_crate_desired_health", "100" )
RunConsoleCommand( "item_item_crate_desired_armor", "30" )
RunConsoleCommand( "item_item_crate_desired_pistol", "50" )
RunConsoleCommand( "item_item_crate_desired_smg1", "50" )
RunConsoleCommand( "item_item_crate_desired_smg1_alt", "10" )
RunConsoleCommand( "item_item_crate_desired_ar2", "40" )
RunConsoleCommand( "item_item_crate_desired_shotgun", "50" )
RunConsoleCommand( "item_item_crate_desired_rpg", "0" )
RunConsoleCommand( "item_item_crate_desired_grenade", "10" )
RunConsoleCommand( "item_item_crate_desired_357", "0" )
RunConsoleCommand( "item_item_crate_desired_crossbow", "0" )
RunConsoleCommand( "item_item_crate_desired_ar2_alt", "0" )
end )
local ConVarsDefault = TOOL:BuildConVarList()
language.Add( "tool.item_item_crate", "Item Crates" )
language.Add( "tool.item_item_crate.name", "Item Crate Tool" )
language.Add( "tool.item_item_crate.desc", "Spawn item crates" )
language.Add( "tool.item_item_crate.left", "Spawn an item crate" )
language.Add( "tool.item_item_crate.model", "Crate Model" )
language.Add( "tool.item_item_crate.contents", "Crate Contents" )
language.Add( "tool.item_item_crate.random", "Random Item" )
language.Add( "tool.item_item_crate.amount", "Content Amount:" )
language.Add( "tool.item_item_crate.amount.help", "The amount of items to put into item crate." )
language.Add( "tool.item_item_crate.health", "Crate Health:" )
language.Add( "tool.item_item_crate.health.help", "Amount of damage the item crate can take before it will break." )
language.Add( "tool.item_item_crate.edit", "Edit Dynamic Resupply Item Values" )
language.Add( "tool.item_item_crate.back", "Return back" )
language.Add( "tool.item_item_crate.reset", "Reset to defaults" )
language.Add( "Cleanup_item_item_crates", "Item Crates" )
language.Add( "Cleaned_item_item_crates", "Cleaned up all Item Crates" )
language.Add( "SBoxLimit_item_item_crates", "You've hit the Item Crates limit!" )
language.Add( "Undone_item_item_crate", "Item Crate undone" )
language.Add( "max_item_item_crates", "Max Item Crates:" )
language.Add( "tool.item_item_crate.desired_health", "Health:" )
language.Add( "tool.item_item_crate.desired_armor", "Armor:" )
language.Add( "tool.item_item_crate.desired_pistol", "Pistol ammo:" )
language.Add( "tool.item_item_crate.desired_smg1", "SMG1 ammo:" )
language.Add( "tool.item_item_crate.desired_smg1_alt", "SMG1 Grenades:" )
language.Add( "tool.item_item_crate.desired_ar2", "AR2 ammo:" )
language.Add( "tool.item_item_crate.desired_shotgun", "Shotgun Ammo:" )
language.Add( "tool.item_item_crate.desired_rpg", "RPG Rounds:" )
language.Add( "tool.item_item_crate.desired_grenade", "Grenades:" )
language.Add( "tool.item_item_crate.desired_357", ".357 Ammo:" )
language.Add( "tool.item_item_crate.desired_crossbow", "Crossbow Ammo:" )
language.Add( "tool.item_item_crate.desired_ar2_alt", "AR2 Energy Balls:" )
language.Add( "tool.item_item_crate.desired_ar2_alt.help", "A dynamic ressuply item. When the player enters the PVS of this entity, it will determine the item most needed by the player, spawn one of those items, and remove itself. To determine which item the player most needs, it calculates which of the Desired Health/Armor/Ammo ratios the player is farthest from.\n\nIf the player is above all the desired levels, then no item will be spawned." )
function TOOL.BuildCPanel( panel )
panel:AddControl( "ComboBox", { MenuButton = 1, Folder = "item_item_crate", Options = { [ "#preset.default" ] = ConVarsDefault }, CVars = table.GetKeys( ConVarsDefault ) } )
panel:AddControl( "PropSelect", { Label = "#tool.item_item_crate.model", Height = 1, ConVar = "item_item_crate_model", Models = list.Get( "ItemCrateModels" ) } )
panel:AddControl( "ListBox", { Label = "#tool.item_item_crate.contents", Height = 256, Options = list.Get( "ItemCrateItems" ) } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.amount", Min = 1, Max = 25, Command = "item_item_crate_amount", Help = true } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.health", Min = 1, Max = 100, Command = "item_item_crate_health", Help = true } )
panel:Help( "#tool.item_item_crate.desired_ar2_alt.help" )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_health", Max = 100, Command = "item_item_crate_desired_health" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_armor", Max = 100, Command = "item_item_crate_desired_armor" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_pistol", Max = 100, Command = "item_item_crate_desired_pistol" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_smg1", Max = 100, Command = "item_item_crate_desired_smg1" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_smg1_alt", Max = 100, Command = "item_item_crate_desired_smg1_alt" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_ar2", Max = 100, Command = "item_item_crate_desired_ar2" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_shotgun", Max = 100, Command = "item_item_crate_desired_shotgun" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_rpg", Max = 100, Command = "item_item_crate_desired_rpg" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_grenade", Max = 100, Command = "item_item_crate_desired_grenade" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_357", Max = 100, Command = "item_item_crate_desired_357" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_crossbow", Max = 100, Command = "item_item_crate_desired_crossbow" } )
panel:AddControl( "Slider", { Label = "#tool.item_item_crate.desired_ar2_alt", Max = 100, Command = "item_item_crate_desired_ar2_alt" } )
panel:Button( "#tool.item_item_crate.reset", "item_item_crate_reset" )
end

View File

@@ -0,0 +1,418 @@
--[[
| 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();
TOOL.Category = "Construction"
TOOL.Name = "Ladders"
TOOL.ClientConVar["laddername"] = "";
TOOL.ClientConVar["model"] = "models/props_c17/metalladder001.mdl";
TOOL.Information = {
{name = "left", stage = 0},
{name = "right", stage = 0},
{name = "left_next", stage = 1, icon = "gui/lmb.png"}
};
/*
ladderOptions is a list of approved models that can be used in the tool.
Prevents people from using console to set the model to something that won't work.
Parameters:
- origin: Where is the origin of the ladder in relation to the bottom? If the ladder's :GetPos() is in the center, find the unit distance between the bottom and center.
See the third ladder in the table.
- height: How many units tall is this ladder?
- ladderOffset: How many units away from the wall should the ladder entity be placed?
- propOffset: How many units away from the wall should the ladder props be placed?
*/
local ladderOptions = {
["models/props_c17/metalladder001.mdl"] = {
origin = vector_origin,
height = 127.5,
ladderOffset = 25,
propOffset = 2.5
},
["models/props_c17/metalladder002.mdl"] = {
origin = vector_origin,
height = 127.5,
ladderOffset = 30
},
["models/props/cs_militia/ladderrung.mdl"] = {
origin = Vector(0, 0, 63.75),
height = 127.5,
ladderOffset = 25
},
["models/props/cs_militia/ladderwood.mdl"] = {
origin = Vector(0, 0, 74),
height = 147,
ladderOffset = 20,
propOffset = 1
},
};
cleanup.Register("ladders");
cleanup.Register("ladder_dismounts");
if (SERVER) then
if (!ConVarExists("sbox_maxladders")) then
CreateConVar("sbox_maxladders", 5, {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Maximum number of ladders which can be created by users.");
end;
if (!ConVarExists("sbox_maxladder_dismounts")) then
CreateConVar("sbox_maxladder_dismounts", 10, {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Maximum number of dismount points which can be created by users. Recommended to be double the number of ladders (two for each ladder).");
end;
end;
/*
Helper function to get segments on a line.
*/
local function GetSegments(p1, p2, segLength, bInclusive)
local points = {};
local distance = p1:Distance(p2);
local norm = (p2 - p1):GetNormalized();
local total = math.floor(distance / segLength);
local nextPos = p1;
if (bInclusive) then
table.insert(points, p1);
end;
for i = 1, total do
nextPos = nextPos + norm * segLength;
table.insert(points, nextPos);
end;
if (bInclusive) then
table.insert(points, p2);
end;
return points;
end;
/*
Ladder Creation
*/
do
local dismountHull = {
mins = Vector(-16, -16, 0),
maxs = Vector(16, 16, 4)
};
function TOOL:LeftClick(trace)
if (IsValid(trace.Entity) and trace.Entity:IsPlayer()) then return false; end;
if (CLIENT) then return true; end;
if (!self:GetOwner():CheckLimit("ladders")) then return false; end;
-- If we haven't selected a first point...
if (self:GetStage() == 0) then
-- Retrieve the physics object of any hit entity. Made useless by previous code, but /something/ needs to go into SetObject...
-- As well, retrieve a modified version of the surface normal. This normal is always horizontal and only rotates around the Y axis. Yay straight ladders.
local physObj = trace.Entity:GetPhysicsObjectNum(trace.PhysicsBone);
local normal = Angle(0, trace.HitNormal:Angle().y, 0):Forward();
-- Clear out any junk that could possibly be left over, and store our data.
self:ClearObjects();
self:SetObject(1, trace.Entity, trace.HitPos, physObj, trace.PhysicsBone, normal);
-- Move to the next stage.
self:SetStage(1);
else
-- Same as before, and check how far away the ladder entity needs to be created, based on which model we're using.
local physObj = trace.Entity:GetPhysicsObjectNum(trace.PhysicsBone);
local normal = Angle(0, trace.HitNormal:Angle().y, 0):Forward();
local model = self:GetClientInfo("model");
-- If the user is being maLICIOUS and trying to use a model not on the list, default to the standard ladder.
if (!ladderOptions[model]) then
model = "models/props_c17/metalladder001.mdl";
end;
local options = ladderOptions[model];
local offset = options.ladderOffset;
-- Store the data of our second click.
self:SetObject(2, trace.Entity, trace.HitPos, physObj, trace.PhysicsBone, normal);
-- Define the top and bottom points of our func_useableladder.
local top = self:GetPos(1) + self:GetNormal(1) * offset;
local bottom = Vector(self:GetPos(1).x, self:GetPos(1).y, self:GetPos(2).z + 5) + self:GetNormal(1) * offset;
-- Create a table to hold all of the created prop_physics. This is used later for undo.AddEntity, and for dismount parenting.
-- Then, retrieve all of the segment points in a straight line from top to bottom of the ladder.
local ladderProps = {};
local fixOffset = options.height - options.origin.z;
local topPos = self:GetPos(1) - Vector(0, 0, fixOffset);
local bottomPos = Vector(self:GetPos(1).x, self:GetPos(1).y, self:GetPos(2).z) + options.origin + Vector(0, 0, 1);
local points = GetSegments(topPos, bottomPos, options.height, true);
-- If our bottom point manages to be higher than our top, remove it.
if (topPos.z < bottomPos.z) then
table.remove(points);
end;
-- Start our undo stack.
undo.Create("Ladder");
-- If a point is too close for whatever reason, remove it.
for i = 1, #points do
if (points[i - 1]) then
if (points[i - 1]:Distance(points[i]) < 30) then
table.remove(points, i);
end;
end;
end;
-- For every point in our table of segments, create a prop_physics, destroy its physics object, and add it to the undo stack.
for k, pos in pairs(points) do
local ladder = ents.Create("prop_physics");
ladder:SetPos(pos + self:GetNormal(1) * (options.propOffset or 0));
ladder:SetAngles(self:GetNormal(1):Angle());
ladder:SetModel(model);
ladder:Spawn();
ladder:GetPhysicsObject():EnableMotion(false);
ladder:PhysicsDestroy();
table.insert(ladderProps, ladder);
undo.AddEntity(ladder);
end;
-- Create the actual ladder entity.
local ladderEnt = ents.Create("func_useableladder");
ladderEnt:SetPos(LerpVector(0.5, top, bottom));
ladderEnt:SetKeyValue("point0", tostring(bottom));
ladderEnt:SetKeyValue("point1", tostring(top));
local targetName = self:GetClientInfo("laddername");
if (!targetName or targetName == "") then
targetName = ladderEnt:EntIndex();
end;
ladderEnt:SetKeyValue("targetname", "zladder_" .. targetName);
ladderEnt:SetParent(ladderProps[1]);
ladderEnt:Spawn();
ladderEnt:CallOnRemove("cleanup", function(ladder)
if (!ladder.props) then return; end;
for k, v in pairs(ladder.props) do
SafeRemoveEntity(v);
end;
end);
-- Store all the props on the ladder entity.
ladderEnt.propTable = {};
ladderEnt.props = {};
ladderEnt.model = model;
-- Store our normal on the ladder.
ladderEnt.normal = self:GetNormal(1);
-- Let our hook inside lua/autorun know that the props here have a ladder attached, so disallow +USE on them.
for k, v in pairs(ladderProps) do
v.ladder = ladderEnt;
v:DrawShadow(false);
v:SetCollisionGroup(COLLISION_GROUP_WORLD);
table.insert(ladderEnt.propTable, {
origin = v:GetPos(),
angles = v:GetAngles()
});
table.insert(ladderEnt.props, v);
v:SetNWEntity("ladder", ladderEnt);
end;
local topTrace = util.TraceHull({
start = self:GetPos(1) - self:GetNormal(1) * 17 + Vector(0, 0, 5),
endpos = self:GetPos(1) - self:GetNormal(1) * 17 - Vector(0, 0, 15),
mins = dismountHull.mins,
maxs = dismountHull.maxs,
filter = function(ent) if (ent:IsPlayer() or ent:IsNPC()) then return false; else return true; end; end;
});
if (topTrace.Hit and !topTrace.AllSolid and !topTrace.StartSolid) then
local topDismount = ents.Create("info_ladder_dismount");
topDismount:SetPos(topTrace.HitPos);
topDismount:Spawn();
topDismount:SetParent(ladderEnt);
topDismount:SetName("zdismount_" .. topDismount:EntIndex());
end;
local bottomTrace = util.TraceHull({
start = bottom + self:GetNormal(1) * 34 + Vector(0, 0, 5),
endpos = bottom + self:GetNormal(1) * 34 - Vector(0, 0, 15),
mins = dismountHull.mins,
maxs = dismountHull.maxs,
filter = function(ent) if (ent:IsPlayer() or ent:IsNPC()) then return false; else return true; end; end;
});
if (bottomTrace.Hit and !bottomTrace.AllSolid and !bottomTrace.StartSolid) then
local bottomDismount = ents.Create("info_ladder_dismount");
bottomDismount:SetPos(bottomTrace.HitPos);
bottomDismount:Spawn();
bottomDismount:SetParent(ladderEnt);
bottomDismount:SetName("zdismount_" .. bottomDismount:EntIndex());
end;
-- Push the ladder entity onto our undo stack.
undo.AddEntity(ladderEnt);
-- Set the undo owner, the text, and close the stack.
undo.SetPlayer(self:GetOwner());
undo.SetCustomUndoText("Undone Ladder");
undo.Finish();
-- Calling CFuncLadder::Activate will force the ladder to search for dismount points near the top and bottom.
ladderEnt:Activate();
-- We've finished making our ladder, so go back to stage 0, clear any objects, and add 1 to our cleanup count.
self:SetStage(0);
self:ClearObjects();
self:GetOwner():AddCount("ladders", ladderEnt);
self:GetOwner():AddCleanup("ladders", ladderEnt);
end;
return true;
end;
/*
Dismount Placing
*/
function TOOL:RightClick(trace)
if (IsValid(trace.Entity) and trace.Entity:IsPlayer()) then return false; end;
if (self:GetStage() > 0) then return false; end;
if (CLIENT) then return true; end;
if (!self:GetOwner():CheckLimit("ladder_dismounts")) then return false; end;
-- Perform a hull trace the size of a dismount spot to determine a safe place to put it. If the dismount is intersecting with ANY geometry-
-- the engine will consider it blocked, and the player cannot use it.
local hullTrace = util.TraceHull({
start = trace.HitPos + trace.HitNormal * 16,
endpos = trace.HitPos - trace.HitNormal * 10,
mins = dismountHull.mins,
maxs = dismountHull.maxs
});
if (!hullTrace.Hit) then return false; end;
-- targetName will be the name of the ladder this dismount is going to attach to.
local targetName = self:GetClientInfo("laddername");
local dismount = ents.Create("info_ladder_dismount");
dismount:SetPos(hullTrace.HitPos);
dismount:SetKeyValue("targetname", "zdismount_" .. dismount:EntIndex());
-- If targetName was specified, set the key value. m_target tells the engine that this dismount spot only works for ladders whose names equal this.
if (targetName and targetName != "") then
dismount:SetKeyValue("target", "zladder_" .. targetName);
end;
dismount:Spawn();
-- Loop through all entities on the map. If it's a ladder, and it has our custom prefix, then check if its entity name is equal to our current name.
-- If so, parent it, so that when the ladder is removed, it cleans up the dismount.
for k, v in pairs(ents.GetAll()) do
if (v:GetClass() == "func_useableladder" and v:GetName():find("zladder_")) then
if (targetName and targetName != "") then
if (v:GetName() == "zladder_" .. targetName) then
dismount:SetParent(v);
end;
end;
-- CFuncLadder::Activate, so dismount points for ladders are updated.
v:Activate();
end;
end;
-- Create our undo stack, push the dismount point, assign ownership, then finish.
undo.Create("Ladder Dismount");
undo.AddEntity(dismount);
undo.SetPlayer(self:GetOwner());
undo.SetCustomUndoText("Undone Ladder Dismount");
undo.Finish();
-- Add the dismount point to our cleanup count.
self:GetOwner():AddCount("ladder_dismounts", dismount);
self:GetOwner():AddCleanup("ladder_dismounts", dismount);
return true;
end;
end;
function TOOL:Think()
end
/*
Holster
Clear stored objects and reset state
*/
function TOOL:Holster()
self:ClearObjects();
self:SetStage(0);
end;
/*
Control Panel
*/
function TOOL.BuildCPanel(CPanel)
local modelTable = {};
for k, v in pairs(ladderOptions) do
modelTable[k] = {};
end;
CPanel:AddControl("Header", {
Description = "#tool.ladder.desc"
});
CPanel:AddControl("TextBox", {
Label = "Ladder Name",
Command = "ladder_laddername"
});
CPanel:AddControl("PropSelect", {
Label = "Select a model to use",
ConVar = "ladder_model",
Height = 1,
Width = 3,
Models = modelTable
});
end;
/*
Language strings
*/
if (CLIENT) then
language.Add("tool.ladder.name", "Ladders");
language.Add("tool.ladder.left", "Select the top point for your ladder.");
language.Add("tool.ladder.right", "Place a dismount point.");
language.Add("tool.ladder.left_next", "Now left click anywhere lower than your first point to determine the height.");
language.Add("tool.ladder.desc", "Create ladders, duh.");
language.Add("Cleaned_ladders", "Cleaned up all Ladders");
language.Add("Cleanup_ladders", "Ladders");
language.Add("Cleaned_ladder_dismounts", "Cleaned up all Ladder Dismounts");
language.Add("Cleanup_ladder_dismounts", "Ladder Dismounts");
end;

View File

@@ -0,0 +1,221 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
TOOL.Category = "Jakub Baku Mannables"
TOOL.Name = "#tool.mannable_changemodel.name"
TOOL.ClientConVar[ "model" ] = "models/airboatgun.mdl"
TOOL.ClientConVar[ "hidegun" ] = 0
TOOL.ClientConVar[ "bone" ] = 0
TOOL.ClientConVar[ "posx" ] = 0
TOOL.ClientConVar[ "posy" ] = 0
TOOL.ClientConVar[ "posz" ] = 0
TOOL.ClientConVar[ "scalex" ] = 0
TOOL.ClientConVar[ "scaley" ] = 0
TOOL.ClientConVar[ "scalez" ] = 0
TOOL.ClientConVar[ "rotx" ] = 0
TOOL.ClientConVar[ "roty" ] = 0
TOOL.ClientConVar[ "rotz" ] = 0
if(CLIENT) then
language.Add("tool.mannable_changemodel.name", "Change Emplacement Model" )
language.Add("tool.mannable_changemodel.desc", "Left click to select entity, right click to sample, reload to apply" )
language.Add("tool.mannable_changemodel.0", "REMEMBER TO APPLY (RELOAD)" )
language.Add("tool.mannable_changemodel.help", "Edit the settings" )
local functions = {
["retrieve"] = function()
local ent = net.ReadEntity()
if(!IsValid(ent)) then return end
if(IsValid(ent._CustomGunModel)) then
RunConsoleCommand("mannable_changemodel_model", ent._CustomGunModel:GetModel())
end
local mat = ent._GunModelMatrix
if(mat) then
local pos = mat:GetTranslation()
local scale = mat:GetScale()
local rot = mat:GetAngles()
RunConsoleCommand("mannable_changemodel_posx", tostring(pos.x))
RunConsoleCommand("mannable_changemodel_posy", tostring(pos.y))
RunConsoleCommand("mannable_changemodel_posz", tostring(pos.z))
RunConsoleCommand("mannable_changemodel_scalex", tostring(scale.x))
RunConsoleCommand("mannable_changemodel_scaley", tostring(scale.y))
RunConsoleCommand("mannable_changemodel_scalez", tostring(scale.z))
RunConsoleCommand("mannable_changemodel_rotx", tostring(rot.pitch))
RunConsoleCommand("mannable_changemodel_roty", tostring(rot.yaw))
RunConsoleCommand("mannable_changemodel_rotz", tostring(rot.roll))
end
end,
["updent"] = function()
local ent = net.ReadEntity()
local mdl = net.ReadString()
local mat = net.ReadMatrix()
local bone = net.ReadInt(32)
if(!IsValid(ent) or ent.Base != "ent_mannable_bakubase") then return end
ent:SetupCustomModel(mdl, bone)
ent._GunModelMatrix = mat
end
}
net.Receive("mannable_tool_changemodel", function(len, ply)
local command = net.ReadString()
if(isfunction(functions[command])) then
functions[command]()
end
end)
function TOOL:Think()
local ent = self:GetWeapon():GetNWEntity("ent")
if(!IsValid(ent) or ent.Base != "ent_mannable_bakubase") then return end
local mat = Matrix()
mat:SetTranslation(Vector(
self:GetClientNumber("posx"),
self:GetClientNumber("posy"),
self:GetClientNumber("posz")
))
mat:SetScale(Vector(self:GetClientNumber("scalex"),
self:GetClientNumber("scaley"),
self:GetClientNumber("scalez")))
mat:SetAngles(Angle(self:GetClientNumber("rotx"),
self:GetClientNumber("roty"),
self:GetClientNumber("rotz")))
ent._GunModelMatrix = mat
end
local FacePoser = surface.GetTextureID( "gui/faceposer_indicator" )
function TOOL:DrawHUD()
if ( GetConVarNumber( "gmod_drawtooleffects" ) == 0 ) then return end
local selected = self:GetWeapon():GetNWEntity("ent")
if ( !IsValid( selected ) ) then return end
local pos = selected:GetPos()
local scrpos = pos:ToScreen()
if ( !scrpos.visible ) then return end
-- Work out the side distance to give a rough headsize box..
local player_eyes = LocalPlayer():EyeAngles()
local side = ( pos + player_eyes:Right() * 20 ):ToScreen()
local size = math.abs( side.x - scrpos.x ) * 0.5
surface.SetDrawColor( 255, 255, 255, 255 )
surface.SetTexture( FacePoser )
surface.DrawTexturedRect( scrpos.x - size, scrpos.y - size, size * 2, size * 2 )
end
else
util.AddNetworkString("mannable_tool_changemodel")
function TOOL:ApplySettings()
local ent = self:GetWeapon():GetNWEntity("ent")
if(!IsValid(ent) or ent.Base != "ent_mannable_bakubase") then return end
local mdl = self:GetClientInfo("model")
local mat = Matrix()
mat:SetTranslation(Vector(
self:GetClientNumber("posx"),
self:GetClientNumber("posy"),
self:GetClientNumber("posz")
))
mat:SetScale(Vector(self:GetClientNumber("scalex"),
self:GetClientNumber("scaley"),
self:GetClientNumber("scalez")))
mat:SetAngles(Angle(self:GetClientNumber("rotx"),
self:GetClientNumber("roty"),
self:GetClientNumber("rotz")))
local bone = self:GetClientNumber("bone")
net.Start("mannable_tool_changemodel")
net.WriteString("updent")
net.WriteEntity(ent)
net.WriteString(mdl)
net.WriteMatrix(mat)
net.WriteInt(bone, 32)
net.Broadcast()
ent._HideGunModel = self:GetClientNumber("hidegun") > 0
if(ent._HideGunModel) then
ent:SetModel("models/props_combine/bunker_gun01_nogun.mdl")
end
end
end
function TOOL:LeftClick( trace )
if(!IsValid(trace.Entity) or trace.Entity.Base != "ent_mannable_bakubase") then return false end
if(CLIENT) then return true end
net.Start("mannable_tool_changemodel")
net.WriteString("retrieve")
net.WriteEntity(trace.Entity)
net.Send(self:GetOwner())
self:GetWeapon():SetNWEntity("ent", trace.Entity)
return true
end
function TOOL:RightClick( trace )
if(!IsValid(trace.Entity) or trace.Entity.Base != "ent_mannable_bakubase") then return false end
if(CLIENT) then return true end
net.Start("mannable_tool_changemodel")
net.WriteString("retrieve")
net.WriteEntity(trace.Entity)
net.Send(self:GetOwner())
return true
end
function TOOL:Reload(trace)
if(!IsValid(trace.Entity) or self:GetWeapon():GetNWEntity("ent") != trace.Entity) then return false end
if(CLIENT) then return true end
self:ApplySettings()
return true
end
local ConVarsDefault = TOOL:BuildConVarList()
function TOOL.BuildCPanel( CPanel )
CPanel:AddControl( "Header", { Description = "#tool.mannable_changemodel.help" } )
CPanel:AddControl( "ComboBox", { MenuButton = 1, Folder = "mannable_changemodel", Options = { [ "#preset.default" ] = ConVarsDefault }, CVars = table.GetKeys( ConVarsDefault ) } )
CPanel:AddControl( "CheckBox", { Label = "Hide gun model", Command = "mannable_changemodel_hidegun" } )
CPanel:AddControl( "TextBox", { Label = "Custom gun model", Command = "mannable_changemodel_model" } )
CPanel:AddControl( "Label", { text = "Position, rotation, scale" } )
CPanel:AddControl( "Slider", { Label = "Pos X", Command = "mannable_changemodel_posx", min = -50, max = 50, type = "float" } )
CPanel:AddControl( "Slider", { Label = "Pos Y", Command = "mannable_changemodel_posy", min = -50, max = 50, type = "float" } )
CPanel:AddControl( "Slider", { Label = "Pos Z", Command = "mannable_changemodel_posz", min = -50, max = 50, type = "float" } )
CPanel:AddControl( "Slider", { Label = "Scale X", Command = "mannable_changemodel_scalex", min = -50, max = 50, type = "float" } )
CPanel:AddControl( "Slider", { Label = "Scale Y", Command = "mannable_changemodel_scaley", min = -50, max = 50, type = "float" } )
CPanel:AddControl( "Slider", { Label = "Scale Z", Command = "mannable_changemodel_scalez", min = -50, max = 50, type = "float" } )
CPanel:AddControl( "Slider", { Label = "Rotation X", Command = "mannable_changemodel_rotx", min = 0, max = 360, type = "float" } )
CPanel:AddControl( "Slider", { Label = "Rotation Y", Command = "mannable_changemodel_roty", min = 0, max = 360, type = "float" } )
CPanel:AddControl( "Slider", { Label = "Rotation Z", Command = "mannable_changemodel_rotz", min = 0, max = 360, type = "float" } )
end

View File

@@ -0,0 +1,64 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
TOOL.Category = "Construction"
TOOL.Name = "#No Collide World"
TOOL.Command = nil
TOOL.ConfigName = ""
if CLIENT then
language.Add("Tool.nocollideworld.name", "No Collide World")
language.Add("Tool.nocollideworld.desc", "Make a prop not collide with anything, including the world")
language.Add("Tool.nocollideworld.0", "Left click on an object to make it not collide with anything. Right click to return an object to normal.")
end
function TOOL:LeftClick( trace )
if (!trace.Entity ) then return end
if (!trace.Entity:IsValid()) then return end
if (trace.Entity:IsPlayer()) then return end
local PhysObj = trace.Entity:GetPhysicsObject()
if ( CLIENT ) then return true end
if ( trace.Entity.CollisionGroup != COLLISION_GROUP_WORLD && PhysObj:IsCollisionEnabled() ) then
trace.Entity:SetCollisionGroup( COLLISION_GROUP_WORLD )
trace.Entity.CollisionGroup = COLLISION_GROUP_WORLD
PhysObj:EnableCollisions(false)
end
return true
end
function TOOL:RightClick( trace )
if (!trace.Entity ) then return end
if (!trace.Entity:IsValid()) then return end
if (trace.Entity:IsPlayer()) then return end
local PhysObj = trace.Entity:GetPhysicsObject()
if ( CLIENT ) then return true end
if ( trace.Entity.CollisionGroup == COLLISION_GROUP_WORLD && !PhysObj:IsCollisionEnabled() ) then
trace.Entity:SetCollisionGroup( COLLISION_GROUP_NONE )
trace.Entity.CollisionGroup = COLLISION_GROUP_NONE
PhysObj:EnableCollisions(true)
end
return true
end

View File

@@ -0,0 +1,804 @@
--[[
| 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 = "Particle Controller"
TOOL.Name = "Adv. Particle Control"
TOOL.Command = nil
TOOL.ConfigName = ""
TOOL.HighlightedEnt = nil
TOOL.ClientConVar[ "effectname" ] = "env_fire_large"
TOOL.ClientConVar[ "mode_beam" ] = "0"
TOOL.beamattach1 = 0
TOOL.beamattach2 = 0
TOOL.ClientConVar[ "utileffect_scale" ] = "1"
TOOL.ClientConVar[ "utileffect_magnitude" ] = "1"
TOOL.ClientConVar[ "utileffect_radius" ] = "10"
TOOL.ClientConVar[ "color_enabled" ] = "0"
TOOL.ClientConVar[ "color_r" ] = "255"
TOOL.ClientConVar[ "color_g" ] = "20"
TOOL.ClientConVar[ "color_b" ] = "0"
TOOL.ClientConVar[ "color_outofone" ] = "0"
TOOL.ClientConVar[ "attachnum" ] = "0"
TOOL.ClientConVar[ "repeatrate" ] = "0"
TOOL.ClientConVar[ "repeatsafety" ] = "1"
TOOL.ClientConVar[ "propmodel" ] = "models/hunter/plates/plate.mdl"
TOOL.ClientConVar[ "propangle" ] = "1"
TOOL.ClientConVar[ "propinvis" ] = "0"
TOOL.ClientConVar[ "numpadkey" ] = "52"
TOOL.ClientConVar[ "toggle" ] = "1"
TOOL.ClientConVar[ "starton" ] = "1"
TOOL.Information = {
{ name = "info1", stage = 1, icon = "gui/info.png" },
{ name = "left0", stage = 0, icon = "gui/lmb.png" },
{ name = "left1", stage = 1, icon = "gui/lmb.png" },
{ name = "middle01", icon = "gui/mmb.png" },
{ name = "right0", stage = 0, icon = "gui/rmb.png" },
{ name = "right1", stage = 1, icon = "gui/rmb.png" },
{ name = "reload0", stage = 0, icon = "gui/r.png" },
{ name = "reload1", stage = 1, icon = "gui/r.png" },
}
if ( CLIENT ) then
language.Add( "tool.particlecontrol.name", "Advanced Particle Controller" )
language.Add( "tool.particlecontrol.desc", "Attach particle effects to things" )
language.Add( "tool.particlecontrol.help", "Particles are used for all sorts of different special effects. You can attach them to models and turn them on and off with a key." )
language.Add( "tool.particlecontrol.info1", "BEAM EFFECT: Attaches to two points" )
language.Add( "tool.particlecontrol.left0", "Add an effect to an object" )
language.Add( "tool.particlecontrol.left1", "Add the other end to an object" )
language.Add( "tool.particlecontrol.middle01", "Scroll through an object's attachments" )
language.Add( "tool.particlecontrol.right0", "Attach a new prop with the effect on it" )
language.Add( "tool.particlecontrol.right1", "Attach a new prop and add the other end to it" )
language.Add( "tool.particlecontrol.reload0", "Remove all effects from an object" )
language.Add( "tool.particlecontrol.reload1", "Cancel beam effect" )
end
util.PrecacheSound("weapons/pistol/pistol_empty.wav")
function TOOL:LeftClick( trace )
local effectname = self:GetClientInfo( "effectname", 0 )
local attachnum = self:GetClientNumber( "attachnum", 0 )
local repeatrate = self:GetClientNumber( "repeatrate", 0 )
local repeatsafety = self:GetClientNumber( "repeatsafety", 0 )
local numpadkey = self:GetClientNumber( "numpadkey", 0 )
local toggle = self:GetClientNumber( "toggle", 0 )
local starton = self:GetClientNumber( "starton", 0 )
local utileffectinfo = Vector( self:GetClientNumber( "utileffect_scale", 0 ), self:GetClientNumber( "utileffect_magnitude", 0 ), self:GetClientNumber( "utileffect_radius", 0 ) )
local colorinfo = nil
if self:GetClientNumber( "color_enabled", 0 ) == 1 then
if self:GetClientNumber( "color_outofone", 0 ) == 1 then
colorinfo = Color( self:GetClientNumber( "color_r", 0 ), self:GetClientNumber( "color_g", 0 ), self:GetClientNumber( "color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
colorinfo = Color( self:GetClientNumber( "color_r", 0 ), self:GetClientNumber( "color_g", 0 ), self:GetClientNumber( "color_b", 0 ), 0 )
end
end
local ply = self:GetOwner()
if self:GetClientNumber( "mode_beam", 0 ) == 0 then
//Not a beam, attach the effect to one entity
if ( trace.Entity:IsValid() ) then
if CLIENT then return true end
if trace.Entity:GetClass() == "prop_effect" and trace.Entity.AttachedEntity then trace.Entity = trace.Entity.AttachedEntity end
AttachParticleControllerNormal( ply, trace.Entity, { NewTable = {
EffectName = effectname,
AttachNum = attachnum,
RepeatRate = repeatrate,
RepeatSafety = repeatsafety,
Toggle = toggle,
StartOn = starton,
NumpadKey = numpadkey,
UtilEffectInfo = utileffectinfo,
ColorInfo = colorinfo
} } )
return true
end
else
//It's a beam, attach the effect between two entities
local iNum = self:NumObjects()
if ( trace.Entity:IsValid() ) then
//if CLIENT then return true end
if trace.Entity:GetClass() == "prop_effect" and trace.Entity.AttachedEntity then trace.Entity = trace.Entity.AttachedEntity end
self:SetObject( iNum + 1, trace.Entity, trace.HitPos, nil, nil, trace.HitNormal )
if iNum == 0 then
self.beamattach1 = attachnum
else
self.beamattach2 = attachnum
end
if ( iNum > 0 ) then
if ( CLIENT ) then
self:ClearObjects()
return true
end
local Ent1, Ent2 = self:GetEnt(1), self:GetEnt(2)
local constraint = constraint.AttachParticleControllerBeam( Ent1, Ent2, {
EffectName = effectname,
AttachNum = self.beamattach1,
AttachNum2 = self.beamattach2,
RepeatRate = repeatrate,
RepeatSafety = repeatsafety,
Toggle = toggle,
StartOn = starton,
NumpadKey = numpadkey,
UtilEffectInfo = utileffectinfo,
ColorInfo = colorinfo
}, ply )
self:ClearObjects()
else
self:SetStage( iNum+1 )
end
return true
end
end
end
function TOOL:RightClick( trace )
local effectname = self:GetClientInfo( "effectname", 0 )
local attachnum = self:GetClientNumber( "attachnum", 0 )
local repeatrate = self:GetClientNumber( "repeatrate", 0 )
local repeatsafety = self:GetClientNumber( "repeatsafety", 0 )
local numpadkey = self:GetClientNumber( "numpadkey", 0 )
local toggle = self:GetClientNumber( "toggle", 0 )
local starton = self:GetClientNumber( "starton", 0 )
local utileffectinfo = Vector( self:GetClientNumber( "utileffect_scale", 0 ), self:GetClientNumber( "utileffect_magnitude", 0 ), self:GetClientNumber( "utileffect_radius", 0 ) )
local colorinfo = nil
if self:GetClientNumber( "color_enabled", 0 ) == 1 then
if self:GetClientNumber( "color_outofone", 0 ) == 1 then
colorinfo = Color( self:GetClientNumber( "color_r", 0 ), self:GetClientNumber( "color_g", 0 ), self:GetClientNumber( "color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
colorinfo = Color( self:GetClientNumber( "color_r", 0 ), self:GetClientNumber( "color_g", 0 ), self:GetClientNumber( "color_b", 0 ), 0 )
end
end
local ply = self:GetOwner()
local propmodel = self:GetClientInfo( "propmodel", 0 )
local propangle = self:GetClientNumber( "propangle", 0 )
//propangle 1: spawn upright
//propangle 2: spawn at surface angle
if !util.IsValidModel(propmodel) then return false end
if !util.IsValidProp(propmodel) then return false end
if CLIENT then return true end
prop = ents.Create( "prop_physics" )
prop:SetModel( propmodel )
prop:SetPos( trace.HitPos - trace.HitNormal * prop:OBBMins().z )
if propangle == 1 then prop:SetAngles(Angle(0,trace.HitNormal:Angle().y,0)) else prop:SetAngles(trace.HitNormal:Angle()) end
prop:SetCollisionGroup(20) //COLLISION_GROUP_NONE, nocollide with everything except world
prop:Spawn()
local shouldweweld = true //don't weld if...
if ( !util.IsValidPhysicsObject(prop, 0) ) then shouldweweld = false end //the prop doesn't have a phys object
if ( !trace.Entity:IsValid() ) then shouldweweld = false end //the thing we clicked on doesn't exist/is the world
if ( trace.Entity && trace.Entity:IsPlayer() ) then shouldweweld = false end //the thing we clicked on is a player
if ( !util.IsValidPhysicsObject( trace.Entity, trace.PhysicsBone ) ) then shouldweweld = false end //the thing we clicked on doesn't have a phys object
if shouldweweld == true then
local const = constraint.Weld( prop, trace.Entity, 0, trace.PhysicsBone, 0, true, true )
else
if util.IsValidPhysicsObject(prop, 0) then prop:GetPhysicsObject():EnableMotion(false) end
end
if self:GetClientNumber( "propinvis", 0 ) == 1 then
prop:SetRenderMode(1) //we need to change the render mode so the transparency actually shows up
prop:SetColor( Color(255,255,255,0) )
duplicator.StoreEntityModifier( prop, "colour", { Color = Color(255,255,255,0), RenderMode = 1, RenderFX = 0 } )
end
undo.Create( "prop" )
undo.AddEntity( prop )
undo.SetPlayer( ply )
undo.Finish( "Prop ("..tostring(propmodel)..")" )
if ( !prop:IsValid() ) then return false end
if self:GetClientNumber( "mode_beam", 0 ) == 0 then
//Not a beam, attach the effect to one entity.
AttachParticleControllerNormal( ply, prop, { NewTable = {
EffectName = effectname,
AttachNum = attachnum,
RepeatRate = repeatrate,
RepeatSafety = repeatsafety,
Toggle = toggle,
StartOn = starton,
NumpadKey = numpadkey,
UtilEffectInfo = utileffectinfo,
ColorInfo = colorinfo
} } )
else
//It's a beam, attach the effect between two entities
local iNum = self:NumObjects()
self:SetObject( iNum + 1, prop, trace.HitPos, nil, nil, trace.HitNormal )
if iNum == 0 then
self.beamattach1 = attachnum
else
self.beamattach2 = attachnum
end
if ( iNum > 0 ) then
if ( CLIENT ) then
self:ClearObjects()
return true
end
local Ent1, Ent2 = self:GetEnt(1), self:GetEnt(2)
local constraint = constraint.AttachParticleControllerBeam( Ent1, Ent2, {
EffectName = effectname,
AttachNum = self.beamattach1,
AttachNum2 = self.beamattach2,
RepeatRate = repeatrate,
RepeatSafety = repeatsafety,
Toggle = toggle,
StartOn = starton,
NumpadKey = numpadkey,
UtilEffectInfo = utileffectinfo,
ColorInfo = colorinfo
}, ply )
self:ClearObjects()
else
self:SetStage( iNum+1 )
end
return true
end
return true
end
function TOOL:Reload( trace )
//if we've selected something for a beam effect, then let us deselect it with reload
if self:GetClientNumber( "mode_beam", 0 ) != 0 and self:NumObjects() > 0 then
//self:GetEnt(1)
self:ClearObjects()
self:SetStage(0)
return true
end
if ( trace.Entity:IsValid() ) then
local fx = false
if trace.Entity:GetClass() == "prop_effect" and trace.Entity.AttachedEntity then trace.Entity = trace.Entity.AttachedEntity end
for _, asdf in pairs( ents:GetAll() ) do
if asdf:GetClass() == "particlecontroller_normal" then
if asdf:GetParent() == trace.Entity then
if SERVER then asdf:Remove() end
fx = true
end
if IsValid(asdf:GetTargetEnt2()) then
if asdf:GetTargetEnt2() == trace.Entity or asdf:GetTargetEnt2():GetParent() == trace.Entity then
if SERVER then asdf:Remove() end
fx = true
end
end
end
end
if SERVER then
duplicator.ClearEntityModifier( trace.Entity, "DupeParticleControllerNormal" )
constraint.RemoveConstraints( trace.Entity, "AttachParticleControllerBeam" )
end
return fx
end
end
if CLIENT then
local colorborder = Color(0,0,0,255)
local colorselect = Color(0,255,0,255)
local colorunselect = Color(255,255,255,255)
function TOOL:DrawHUD()
local pl = LocalPlayer()
local tr = pl:GetEyeTrace()
local attachnum = self:GetClientNumber( "attachnum", 0 )
local function DrawHighlightAttachments(ent)
//If there aren't any attachments, then draw the model origin as selected and stop here:
if !ent:GetAttachments() or !ent:GetAttachments()[1] then
local _pos,_ang = ent:GetPos(), ent:GetAngles()
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 3,_pos.y - 3,6,6,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorselect)
draw.SimpleTextOutlined("0: (origin)","Default",textpos.x,textpos.y,colorselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,2,colorborder)
return
end
//Draw the unselected model origin, if applicable:
if ent:GetAttachments()[attachnum] then
local _pos,_ang = ent:GetPos(), ent:GetAngles()
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 2,_pos.y - 2,4,4,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorunselect)
draw.SimpleTextOutlined("0: (origin)","Default",textpos.x,textpos.y,colorunselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,1,colorborder)
end
//Draw the unselected attachment points:
for _, table in pairs(ent:GetAttachments()) do
local _pos,_ang = ent:GetAttachment(table.id).Pos,ent:GetAttachment(table.id).Ang
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
if table.id != attachnum then
draw.RoundedBox(0,_pos.x - 2,_pos.y - 2,4,4,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorunselect)
draw.SimpleTextOutlined(table.id ..": ".. table.name,"Default",textpos.x,textpos.y,colorunselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,1,colorborder)
end
end
//Draw the selected attachment point or model origin last, so it renders above all the others:
if !ent:GetAttachments()[attachnum] then
//Model origin
local _pos,_ang = ent:GetPos(), ent:GetAngles()
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 3,_pos.y - 3,6,6,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorselect)
draw.SimpleTextOutlined("0: (origin)","Default",textpos.x,textpos.y,colorselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,2,colorborder)
else
//Attachment
local _pos,_ang = ent:GetAttachment(attachnum).Pos,ent:GetAttachment(attachnum).Ang
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 3,_pos.y - 3,6,6,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorselect)
draw.SimpleTextOutlined(attachnum ..": ".. ent:GetAttachments()[attachnum].name,"Default",textpos.x,textpos.y,colorselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,2,colorborder)
end
end
if IsValid(tr.Entity) and tr.Entity == self.HighlightedEnt then
DrawHighlightAttachments(self.HighlightedEnt)
return end
if IsValid(tr.Entity) and tr.Entity != self.HighlightedEnt then
//unhighlight the old ent if it exists
if self.HighlightedEnt != nil then
self.HighlightedEnt = nil
end
//highlight the new ent
self.HighlightedEnt = tr.Entity
end
if !IsValid(tr.Entity) and self.HighlightedEnt != nil then
self.HighlightedEnt = nil
end
end
function TOOL:Holster()
if self.HighlightedEnt != nil then
self.HighlightedEnt = nil
end
end
//All credit for the toolgun scroll wheel code goes to the Wiremod devs. You guys are the best.
local function get_active_tool(ply, tool)
-- find toolgun
local activeWep = ply:GetActiveWeapon()
if not IsValid(activeWep) or activeWep:GetClass() ~= "gmod_tool" or activeWep.Mode ~= tool then return end
return activeWep:GetToolObject(tool)
end
local function hookfunc( ply, bind, pressed )
if not pressed then return end
if bind == "invnext" then
local self = get_active_tool(ply, "particlecontrol")
if not self then return end
return self:ScrollDown(ply:GetEyeTraceNoCursor())
elseif bind == "invprev" then
local self = get_active_tool(ply, "particlecontrol")
if not self then return end
return self:ScrollUp(ply:GetEyeTraceNoCursor())
end
end
if game.SinglePlayer() then -- wtfgarry (have to have a delay in single player or the hook won't get added)
timer.Simple(5,function() hook.Add( "PlayerBindPress", "particlecontrol_playerbindpress", hookfunc ) end)
else
hook.Add( "PlayerBindPress", "particlecontrol_playerbindpress", hookfunc )
end
//End shamefully copied code here.
function TOOL:Scroll(trace,dir)
if !IsValid(self.HighlightedEnt) then return end
local attachcount = 0
if self.HighlightedEnt:GetAttachments() then attachcount = table.Count(self.HighlightedEnt:GetAttachments()) end
local oldattachnum = self:GetClientNumber( "attachnum", 0 )
if oldattachnum > attachcount then oldattachnum = 0 end
local attachnum = oldattachnum + dir
if attachnum < 0 then attachnum = attachcount end
if attachnum > attachcount then attachnum = 0 end
RunConsoleCommand("particlecontrol_attachnum", tostring(attachnum))
self:GetOwner():EmitSound("weapons/pistol/pistol_empty.wav")
return true
end
function TOOL:ScrollUp(trace) return self:Scroll(trace,-1) end
function TOOL:ScrollDown(trace) return self:Scroll(trace,1) end
end
if SERVER then
local function SpawnParticleControllerNormal(ply, ent, DataTable)
if DataTable == nil or DataTable == {} or DataTable.EffectName == nil or ent == nil or !IsValid(ent) then return end
local ParticleControlNormal = ents.Create( "particlecontroller_normal" )
ParticleControlNormal:SetPos(ent:GetPos())
ParticleControlNormal:SetAngles(ent:GetAngles())
ParticleControlNormal:SetParent(ent)
ent:DeleteOnRemove(ParticleControlNormal)
ParticleControlNormal:SetTargetEnt(ent)
ParticleControlNormal:SetEffectName(DataTable.EffectName)
ParticleControlNormal:SetAttachNum(DataTable.AttachNum)
ParticleControlNormal:SetUtilEffectInfo(DataTable.UtilEffectInfo)
if DataTable.ColorInfo != nil then ParticleControlNormal:SetColor(DataTable.ColorInfo) else ParticleControlNormal:SetColor( Color(0,0,0,0) ) end
ParticleControlNormal:SetRepeatRate(DataTable.RepeatRate)
if DataTable.RepeatSafety == 1 or DataTable.RepeatSafety == true then ParticleControlNormal:SetRepeatSafety(true) else ParticleControlNormal:SetRepeatSafety(false) end
if DataTable.StartOn == 1 or DataTable.StartOn == true then ParticleControlNormal:SetActive(true) else ParticleControlNormal:SetActive(false) end
if DataTable.Toggle == 1 or DataTable.Toggle == true then ParticleControlNormal:SetToggle(true) else ParticleControlNormal:SetToggle(false) end
ParticleControlNormal:SetNumpadKey(DataTable.NumpadKey)
numpad.OnDown( ply, DataTable.NumpadKey, "Particle_Press", ParticleControlNormal )
numpad.OnUp( ply, DataTable.NumpadKey, "Particle_Release", ParticleControlNormal )
ParticleControlNormal:SetNumpadState("")
ParticleControlNormal:Spawn()
ParticleControlNormal:Activate()
end
function AttachParticleControllerNormal( ply, ent, Data )
if Data.NewTable then
SpawnParticleControllerNormal(ply, ent, Data.NewTable)
local dupetable = {}
if ent.EntityMods and ent.EntityMods.DupeParticleControllerNormal then dupetable = ent.EntityMods.DupeParticleControllerNormal end
table.insert(dupetable, Data.NewTable)
duplicator.StoreEntityModifier( ent, "DupeParticleControllerNormal", dupetable )
return end
end
function DupeParticleControllerNormal( ply, ent, Data )
//due to a problem with the easy bonemerge tool that causes entity modifiers to be applied TWICE, we need to remove the effects that were added the first time
for _, asdf in pairs( ents:GetAll() ) do
if asdf:GetClass() == "particlecontroller_normal" and asdf:GetParent() == ent then
asdf:Remove()
end
end
for _, DataTable in pairs (Data) do
SpawnParticleControllerNormal(ply, ent, DataTable)
end
end
duplicator.RegisterEntityModifier( "DupeParticleControllerNormal", DupeParticleControllerNormal )
//we have to redefine some of the constraint functions here because they're local functions that don't exist outside of constraints.lua
//not sure how well these'll work, one of them is ripped straight from the nocollide world tool which uses the same trick for its custom constraints
local MAX_CONSTRAINTS_PER_SYSTEM = 100
local function CreateConstraintSystem()
local System = ents.Create("phys_constraintsystem")
if !IsValid(System) then return end
System:SetKeyValue("additionaliterations", GetConVarNumber("gmod_physiterations"))
System:Spawn()
System:Activate()
return System
end
local function FindOrCreateConstraintSystem( Ent1, Ent2 )
local System = nil
Ent2 = Ent2 or Ent1
-- Does Ent1 have a constraint system?
if ( !Ent1:IsWorld() && Ent1:GetTable().ConstraintSystem && Ent1:GetTable().ConstraintSystem:IsValid() ) then
System = Ent1:GetTable().ConstraintSystem
end
-- Don't add to this system - we have too many constraints on it already.
if ( System && System:IsValid() && System:GetVar( "constraints", 0 ) > MAX_CONSTRAINTS_PER_SYSTEM ) then System = nil end
-- Does Ent2 have a constraint system?
if ( !System && !Ent2:IsWorld() && Ent2:GetTable().ConstraintSystem && Ent2:GetTable().ConstraintSystem:IsValid() ) then
System = Ent2:GetTable().ConstraintSystem
end
-- Don't add to this system - we have too many constraints on it already.
if ( System && System:IsValid() && System:GetVar( "constraints", 0 ) > MAX_CONSTRAINTS_PER_SYSTEM ) then System = nil end
-- No constraint system yet (Or they're both full) - make a new one
if ( !System || !System:IsValid() ) then
--Msg("New Constrant System\n")
System = CreateConstraintSystem()
end
Ent1.ConstraintSystem = System
Ent2.ConstraintSystem = System
System.UsedEntities = System.UsedEntities or {}
table.insert( System.UsedEntities, Ent1 )
table.insert( System.UsedEntities, Ent2 )
local ConstraintNum = System:GetVar( "constraints", 0 )
System:SetVar( "constraints", ConstraintNum + 1 )
--Msg("System has "..tostring( System:GetVar( "constraints", 0 ) ).." constraints\n")
return System
end
//end ripped constraint functions here.
//multiple-point "beam" effects use a constraint so the duplicator can group the two entities together
function constraint.AttachParticleControllerBeam( Ent1, Ent2, Data, ply )
if !Ent1 or !Ent2 then return end
//onStartConstraint( Ent1, Ent2 )
local system = FindOrCreateConstraintSystem( Ent1, Ent2 )
SetPhysConstraintSystem( system )
//create a dummy ent for the constraint functions to use
local Constraint = ents.Create("logic_collision_pair")
Constraint:Spawn()
Constraint:Activate()
local ParticleControlBeam = ents.Create( "particlecontroller_normal" )
ParticleControlBeam:SetPos(Ent1:GetPos())
ParticleControlBeam:SetAngles(Ent1:GetAngles())
ParticleControlBeam:SetParent(Ent1)
Ent1:DeleteOnRemove(ParticleControlBeam)
Ent2:DeleteOnRemove(ParticleControlBeam)
ParticleControlBeam:SetTargetEnt(Ent1)
ParticleControlBeam:SetTargetEnt2(Ent2)
ParticleControlBeam:SetEffectName(Data.EffectName)
ParticleControlBeam:SetAttachNum(Data.AttachNum)
ParticleControlBeam:SetAttachNum2(Data.AttachNum2)
ParticleControlBeam:SetUtilEffectInfo(Data.UtilEffectInfo)
if Data.ColorInfo != nil then ParticleControlBeam:SetColor(Data.ColorInfo) else ParticleControlBeam:SetColor( Color(0,0,0,0) ) end
ParticleControlBeam:SetRepeatRate(Data.RepeatRate)
if Data.RepeatSafety == 1 or Data.RepeatSafety == true then ParticleControlBeam:SetRepeatSafety(true) else ParticleControlBeam:SetRepeatSafety(false) end
if Data.StartOn == 1 or Data.StartOn == true then ParticleControlBeam:SetActive(true) else ParticleControlBeam:SetActive(false) end
if Data.Toggle == 1 or Data.Toggle == true then ParticleControlBeam:SetToggle(true) else ParticleControlBeam:SetToggle(false) end
ParticleControlBeam:SetNumpadKey(Data.NumpadKey)
numpad.OnDown( ply, Data.NumpadKey, "Particle_Press", ParticleControlBeam )
numpad.OnUp( ply, Data.NumpadKey, "Particle_Release", ParticleControlBeam )
ParticleControlBeam:SetNumpadState("")
ParticleControlBeam:Spawn()
ParticleControlBeam:Activate()
//onFinishConstraint( Ent1, Ent2 )
SetPhysConstraintSystem( NULL )
constraint.AddConstraintTable( Ent1, Constraint, Ent2 )
local ctable =
{
Type = "AttachParticleControllerBeam",
Ent1 = Ent1,
Ent2 = Ent2,
Data = Data,
ply = ply,
}
Constraint:SetTable( ctable )
return Constraint
end
duplicator.RegisterConstraint( "AttachParticleControllerBeam", constraint.AttachParticleControllerBeam, "Ent1", "Ent2", "Data", "ply" )
end
//we're still testing out a lot of stuff with the cpanel, so let's add a way to refresh it by reselecting the tool
--[[
TOOL.ClientConVar[ "refresh" ] = 1
function TOOL:Think()
if SERVER then return end
if self:GetClientNumber("refresh") == 1 then
RunConsoleCommand("particlecontrol_refresh", "0");
//refresh the cpanel
local panel = controlpanel.Get( "particlecontrol" )
if ( !panel ) then return end
panel:ClearControls()
self.BuildCPanel(panel)
end
end
function TOOL:Deploy()
RunConsoleCommand("particlecontrol_refresh", "1");
end
]]
local ConVarsDefault = TOOL:BuildConVarList()
ConVarsDefault["particlecontrol_attachnum"] = nil //don't save the attachnum in presets, it's used by the other tools too
function TOOL.BuildCPanel(panel)
panel:AddControl( "Header", { Description = "#tool.particlecontrol.help" } )
//Presets
panel:AddControl( "ComboBox", {
MenuButton = 1,
Folder = "particlecontrol",
Options = {
[ "#preset.default" ] = ConVarsDefault
},
CVars = table.GetKeys( ConVarsDefault )
} )
AddParticleBrowser(panel, {
name = "Effect",
commands = {
effectname = "particlecontrol_effectname",
mode_beam = "particlecontrol_mode_beam",
color = "particlecontrol_color",
utileffect = "particlecontrol_utileffect",
},
})
//panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl("Slider", {
Label = "Attachment",
Type = "Integer",
Min = "0",
Max = "10",
Command = "particlecontrol_attachnum",
})
panel:ControlHelp( "Attachment point on the model to use. Set to 0 to attach to the model origin or to attach model-covering effects to the entire model." )
panel:AddControl("Slider", {
Label = "Repeat Rate",
Type = "Float",
Min = "0",
Max = "5",
Command = "particlecontrol_repeatrate",
})
panel:ControlHelp( "How often the effect plays. Set to 0 to not repeat." )
panel:AddControl( "CheckBox", { Label = "Repeat Safety", Command = "particlecontrol_repeatsafety" } )
panel:ControlHelp( "If on, effects are removed before being repeated. This stops them from piling up endlessly, but can also cause small problems, like effects being cut off. You should probably keep this on unless you know what you're doing." )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
local modellist = { Label = "Prop", ConVar = "particlecontrol_propmodel", Category = "Prop", Height = 1, Models = {} }
modellist.Models["models/hunter/plates/plate025x025.mdl"] = {}
modellist.Models["models/hunter/plates/plate.mdl"] = {}
modellist.Models["models/weapons/w_smg1.mdl"] = {}
modellist.Models["models/props_junk/popcan01a.mdl"] = {}
panel:AddControl( "PropSelect", modellist )
panel:AddControl( "ComboBox", {
Label = "Prop Angle",
MenuButton = "0",
Options = {
["Spawn upright"] = { particlecontrol_propangle = "1" },
["Spawn at surface angle"] = { particlecontrol_propangle = "2" }
}
})
panel:AddControl( "CheckBox", { Label = "Invisible prop (particles only)", Command = "particlecontrol_propinvis" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Numpad", {
Label = "Effect Key",
Command = "particlecontrol_numpadkey",
})
panel:AddControl( "CheckBox", { Label = "Toggle", Command = "particlecontrol_toggle" } )
panel:AddControl( "CheckBox", { Label = "Start on?", Command = "particlecontrol_starton" } )
end

View File

@@ -0,0 +1,893 @@
--[[
| 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 = "Particle Controller"
TOOL.Name = "ParCtrl - Projectiles"
TOOL.Command = nil
TOOL.ConfigName = ""
TOOL.HighlightedEnt = nil
TOOL.ClientConVar[ "projfx_enabled" ] = "1"
TOOL.ClientConVar[ "projfx_effectname" ] = "Rocket_Smoke"
TOOL.ClientConVar[ "projfx_utileffect_scale" ] = "1"
TOOL.ClientConVar[ "projfx_utileffect_magnitude" ] = "1"
TOOL.ClientConVar[ "projfx_utileffect_radius" ] = "10"
TOOL.ClientConVar[ "projfx_color_enabled" ] = "0"
TOOL.ClientConVar[ "projfx_color_r" ] = "255"
TOOL.ClientConVar[ "projfx_color_g" ] = "20"
TOOL.ClientConVar[ "projfx_color_b" ] = "0"
TOOL.ClientConVar[ "projfx_color_outofone" ] = "0"
TOOL.ClientConVar[ "impactfx_enabled" ] = "1"
TOOL.ClientConVar[ "impactfx_effectname" ] = "!UTILEFFECT!Explosion!FLAG4!"
TOOL.ClientConVar[ "impactfx_utileffect_scale" ] = "1"
TOOL.ClientConVar[ "impactfx_utileffect_magnitude" ] = "1"
TOOL.ClientConVar[ "impactfx_utileffect_radius" ] = "10"
TOOL.ClientConVar[ "impactfx_color_enabled" ] = "0"
TOOL.ClientConVar[ "impactfx_color_r" ] = "255"
TOOL.ClientConVar[ "impactfx_color_g" ] = "20"
TOOL.ClientConVar[ "impactfx_color_b" ] = "0"
TOOL.ClientConVar[ "impactfx_color_outofone" ] = "0"
//TOOL.ClientConVar[ "attachnum" ] = "1" //we're using the standard tool's attachnum var instead so that the selected attachment stays consistent when swapping between tools
TOOL.ClientConVar[ "repeatrate" ] = "0.80"
TOOL.ClientConVar[ "projmodel" ] = "models/weapons/w_missile.mdl"
TOOL.ClientConVar[ "projmodel_skin" ] = "0"
TOOL.ClientConVar[ "projmodel_attachnum" ] = "1"
TOOL.ClientConVar[ "projmodel_material" ] = ""
TOOL.ClientConVar[ "projmodel_invis" ] = "0"
TOOL.ClientConVar[ "impactfx_effectlifetime" ] = "1.0"
TOOL.ClientConVar[ "projent_spread" ] = "0.04"
TOOL.ClientConVar[ "projent_velocity" ] = "1000"
TOOL.ClientConVar[ "projent_gravity" ] = "0"
TOOL.ClientConVar[ "projent_angle" ] = "0"
TOOL.ClientConVar[ "projent_spin" ] = "0"
TOOL.ClientConVar[ "projent_demomanfix" ] = "0"
TOOL.ClientConVar[ "projent_lifetime_prehit" ] = "10"
TOOL.ClientConVar[ "projent_lifetime_posthit" ] = "0"
TOOL.ClientConVar[ "projent_serverside" ] = "0"
TOOL.ClientConVar[ "propmodel" ] = "models/weapons/w_smg1.mdl"
TOOL.ClientConVar[ "propangle" ] = "2"
TOOL.ClientConVar[ "propinvis" ] = "0"
TOOL.ClientConVar[ "numpadkey" ] = "52"
TOOL.ClientConVar[ "toggle" ] = "1"
TOOL.ClientConVar[ "starton" ] = "1"
TOOL.Information = {
{ name = "left0", stage = 0, icon = "gui/lmb.png" },
{ name = "middle0", stage = 0, icon = "gui/mmb.png" },
{ name = "right0", stage = 0, icon = "gui/rmb.png" },
{ name = "reload0", stage = 0, icon = "gui/r.png" },
}
if ( CLIENT ) then
language.Add( "tool.particlecontrol_proj.name", "Adv. Particle Controller - Projectiles" )
language.Add( "tool.particlecontrol_proj.desc", "Attach projectile effects to things" )
language.Add( "tool.particlecontrol_proj.help", "Projectile effects launch props that have one particle attached to them, and another particle that plays once they expire, either on impact or on a timer." )
language.Add( "tool.particlecontrol_proj.left0", "Add a projectile effect to an object" )
language.Add( "tool.particlecontrol_proj.middle0", "Scroll through an object's attachments" )
language.Add( "tool.particlecontrol_proj.right0", "Attach a new prop with the projectile effect on it" )
language.Add( "tool.particlecontrol_proj.reload0", "Remove all projectile effects from an object" )
end
util.PrecacheSound("weapons/pistol/pistol_empty.wav")
function TOOL:LeftClick( trace )
local projinfo = nil
if self:GetClientNumber( "projfx_enabled", 0 ) == 1 then
projinfo = {
effectname = self:GetClientInfo( "projfx_effectname", 0 ),
utileffectinfo = Vector( self:GetClientNumber( "projfx_utileffect_scale", 0 ), self:GetClientNumber( "projfx_utileffect_magnitude", 0 ), self:GetClientNumber( "projfx_utileffect_radius", 0 ) ),
}
if self:GetClientNumber( "projfx_color_enabled", 0 ) == 1 then
if self:GetClientNumber( "projfx_color_outofone", 0 ) == 1 then
projinfo.colorinfo = Color( self:GetClientNumber( "projfx_color_r", 0 ), self:GetClientNumber( "projfx_color_g", 0 ), self:GetClientNumber( "projfx_color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
projinfo.colorinfo = Color( self:GetClientNumber( "projfx_color_r", 0 ), self:GetClientNumber( "projfx_color_g", 0 ), self:GetClientNumber( "projfx_color_b", 0 ), 0 )
end
end
end
local impactinfo = nil
if self:GetClientNumber( "impactfx_enabled", 0 ) == 1 then
impactinfo = {
effectname = self:GetClientInfo( "impactfx_effectname", 0 ),
utileffectinfo = Vector( self:GetClientNumber( "impactfx_utileffect_scale", 0 ), self:GetClientNumber( "impactfx_utileffect_magnitude", 0 ), self:GetClientNumber( "impactfx_utileffect_radius", 0 ) ),
}
if self:GetClientNumber( "impactfx_color_enabled", 0 ) == 1 then
if self:GetClientNumber( "impactfx_color_outofone", 0 ) == 1 then
impactinfo.colorinfo = Color( self:GetClientNumber( "impactfx_color_r", 0 ), self:GetClientNumber( "impactfx_color_g", 0 ), self:GetClientNumber( "impactfx_color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
impactinfo.colorinfo = Color( self:GetClientNumber( "impactfx_color_r", 0 ), self:GetClientNumber( "impactfx_color_g", 0 ), self:GetClientNumber( "impactfx_color_b", 0 ), 0 )
end
end
end
local attachnum = self:GetOwner():GetInfoNum( "particlecontrol_attachnum", 0 ) //use the standard tool's attachnum var
local repeatrate = self:GetClientNumber( "repeatrate", 0 )
local projmodel = self:GetClientInfo( "projmodel", 0 )
local projmodel_skin = self:GetClientNumber( "projmodel_skin", 0 )
local projmodel_attachnum = self:GetClientNumber( "projmodel_attachnum", 0 )
local projmodel_material = self:GetClientInfo( "projmodel_material", 0 )
local projmodel_invis = self:GetClientNumber( "projmodel_invis", 0 )
local impactfx_effectlifetime = self:GetClientNumber( "impactfx_effectlifetime", 0 )
local projent_spread = self:GetClientNumber( "projent_spread", 0 )
local projent_velocity = self:GetClientNumber( "projent_velocity", 0 )
local projent_gravity = self:GetClientNumber( "projent_gravity", 0 )
local projent_angle = self:GetClientNumber( "projent_angle", 0 )
local projent_spin = self:GetClientNumber( "projent_spin", 0 )
local projent_demomanfix = self:GetClientNumber( "projent_demomanfix", 0 )
local projent_lifetime_prehit = self:GetClientNumber( "projent_lifetime_prehit", 0 )
local projent_lifetime_posthit = self:GetClientNumber( "projent_lifetime_posthit", 0 )
local projent_serverside = self:GetClientNumber( "projent_serverside", 0 )
local numpadkey = self:GetClientNumber( "numpadkey", 0 )
local toggle = self:GetClientNumber( "toggle", 0 )
local starton = self:GetClientNumber( "starton", 0 )
local ply = self:GetOwner()
if ( trace.Entity:IsValid() ) then
if CLIENT then return true end
if trace.Entity:GetClass() == "prop_effect" and trace.Entity.AttachedEntity then trace.Entity = trace.Entity.AttachedEntity end
AttachParticleControllerProj( ply, trace.Entity, { NewTable = {
ProjFXInfo = projinfo,
ImpactFXInfo = impactinfo,
AttachNum = attachnum,
RepeatRate = repeatrate,
ProjModel = projmodel,
ProjModel_Skin = projmodel_skin,
ProjModel_AttachNum = projmodel_attachnum,
ProjModel_Material = projmodel_material,
ProjModel_Invis = projmodel_invis,
ImpactFX_EffectLifetime = impactfx_effectlifetime,
ProjEnt_Spread = projent_spread,
ProjEnt_Velocity = projent_velocity,
ProjEnt_Gravity = projent_gravity,
ProjEnt_Angle = projent_angle,
ProjEnt_Spin = projent_spin,
ProjEnt_DemomanFix = projent_demomanfix,
ProjEnt_Lifetime_PreHit = projent_lifetime_prehit,
ProjEnt_Lifetime_PostHit = projent_lifetime_posthit,
ProjEnt_Serverside = projent_serverside,
NumpadKey = numpadkey,
Toggle = toggle,
StartOn = starton,
} } )
return true
end
end
function TOOL:RightClick( trace )
local projinfo = nil
if self:GetClientNumber( "projfx_enabled", 0 ) == 1 then
projinfo = {
effectname = self:GetClientInfo( "projfx_effectname", 0 ),
utileffectinfo = Vector( self:GetClientNumber( "projfx_utileffect_scale", 0 ), self:GetClientNumber( "projfx_utileffect_magnitude", 0 ), self:GetClientNumber( "projfx_utileffect_radius", 0 ) ),
}
if self:GetClientNumber( "projfx_color_enabled", 0 ) == 1 then
if self:GetClientNumber( "projfx_color_outofone", 0 ) == 1 then
projinfo.colorinfo = Color( self:GetClientNumber( "projfx_color_r", 0 ), self:GetClientNumber( "projfx_color_g", 0 ), self:GetClientNumber( "projfx_color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
projinfo.colorinfo = Color( self:GetClientNumber( "projfx_color_r", 0 ), self:GetClientNumber( "projfx_color_g", 0 ), self:GetClientNumber( "projfx_color_b", 0 ), 0 )
end
end
end
local impactinfo = nil
if self:GetClientNumber( "impactfx_enabled", 0 ) == 1 then
impactinfo = {
effectname = self:GetClientInfo( "impactfx_effectname", 0 ),
utileffectinfo = Vector( self:GetClientNumber( "impactfx_utileffect_scale", 0 ), self:GetClientNumber( "impactfx_utileffect_magnitude", 0 ), self:GetClientNumber( "impactfx_utileffect_radius", 0 ) ),
}
if self:GetClientNumber( "impactfx_color_enabled", 0 ) == 1 then
if self:GetClientNumber( "impactfx_color_outofone", 0 ) == 1 then
impactinfo.colorinfo = Color( self:GetClientNumber( "impactfx_color_r", 0 ), self:GetClientNumber( "impactfx_color_g", 0 ), self:GetClientNumber( "impactfx_color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
impactinfo.colorinfo = Color( self:GetClientNumber( "impactfx_color_r", 0 ), self:GetClientNumber( "impactfx_color_g", 0 ), self:GetClientNumber( "impactfx_color_b", 0 ), 0 )
end
end
end
local attachnum = self:GetOwner():GetInfoNum( "particlecontrol_attachnum", 0 ) //use the standard tool's attachnum var
local repeatrate = self:GetClientNumber( "repeatrate", 0 )
local projmodel = self:GetClientInfo( "projmodel", 0 )
local projmodel_skin = self:GetClientNumber( "projmodel_skin", 0 )
local projmodel_attachnum = self:GetClientNumber( "projmodel_attachnum", 0 )
local projmodel_material = self:GetClientInfo( "projmodel_material", 0 )
local projmodel_invis = self:GetClientNumber( "projmodel_invis", 0 )
local impactfx_effectlifetime = self:GetClientNumber( "impactfx_effectlifetime", 0 )
local projent_spread = self:GetClientNumber( "projent_spread", 0 )
local projent_velocity = self:GetClientNumber( "projent_velocity", 0 )
local projent_gravity = self:GetClientNumber( "projent_gravity", 0 )
local projent_angle = self:GetClientNumber( "projent_angle", 0 )
local projent_spin = self:GetClientNumber( "projent_spin", 0 )
local projent_demomanfix = self:GetClientNumber( "projent_demomanfix", 0 )
local projent_lifetime_prehit = self:GetClientNumber( "projent_lifetime_prehit", 0 )
local projent_lifetime_posthit = self:GetClientNumber( "projent_lifetime_posthit", 0 )
local projent_serverside = self:GetClientNumber( "projent_serverside", 0 )
local numpadkey = self:GetClientNumber( "numpadkey", 0 )
local toggle = self:GetClientNumber( "toggle", 0 )
local starton = self:GetClientNumber( "starton", 0 )
local ply = self:GetOwner()
local propmodel = self:GetClientInfo( "propmodel", 0 )
local propangle = self:GetClientNumber( "propangle", 0 )
//propangle 1: spawn upright
//propangle 2: spawn at surface angle
if !util.IsValidModel(propmodel) then return false end
if !util.IsValidProp(propmodel) then return false end
if CLIENT then return true end
prop = ents.Create( "prop_physics" )
prop:SetModel( propmodel )
prop:SetPos( trace.HitPos - trace.HitNormal * prop:OBBMins().z )
if propangle == 1 then prop:SetAngles(Angle(0,trace.HitNormal:Angle().y,0)) else prop:SetAngles(trace.HitNormal:Angle()) end
prop:SetCollisionGroup(COLLISION_GROUP_NONE)
prop:Spawn()
local shouldweweld = true //don't weld if...
if ( !util.IsValidPhysicsObject(prop, 0) ) then shouldweweld = false end //the prop doesn't have a phys object
if ( !trace.Entity:IsValid() ) then shouldweweld = false end //the thing we clicked on doesn't exist/is the world
if ( trace.Entity && trace.Entity:IsPlayer() ) then shouldweweld = false end //the thing we clicked on is a player
if ( !util.IsValidPhysicsObject( trace.Entity, trace.PhysicsBone ) ) then shouldweweld = false end //the thing we clicked on doesn't have a phys object
if shouldweweld == true then
local const = constraint.Weld( prop, trace.Entity, 0, trace.PhysicsBone, 0, true, true )
else
if util.IsValidPhysicsObject(prop, 0) then prop:GetPhysicsObject():EnableMotion(false) end
end
if self:GetClientNumber( "propinvis", 0 ) == 1 then
prop:SetRenderMode(1) //we need to change the render mode so the transparency actually shows up
prop:SetColor( Color(255,255,255,0) )
duplicator.StoreEntityModifier( prop, "colour", { Color = Color(255,255,255,0), RenderMode = 1, RenderFX = 0 } )
end
undo.Create( "prop" )
undo.AddEntity( prop )
undo.SetPlayer( ply )
undo.Finish( "Prop ("..tostring(propmodel)..")" )
if ( prop:IsValid() ) then
AttachParticleControllerProj( ply, prop, { NewTable = {
ProjFXInfo = projinfo,
ImpactFXInfo = impactinfo,
AttachNum = attachnum,
RepeatRate = repeatrate,
ProjModel = projmodel,
ProjModel_Skin = projmodel_skin,
ProjModel_AttachNum = projmodel_attachnum,
ProjModel_Material = projmodel_material,
ProjModel_Invis = projmodel_invis,
ImpactFX_EffectLifetime = impactfx_effectlifetime,
ProjEnt_Spread = projent_spread,
ProjEnt_Velocity = projent_velocity,
ProjEnt_Gravity = projent_gravity,
ProjEnt_Angle = projent_angle,
ProjEnt_Spin = projent_spin,
ProjEnt_DemomanFix = projent_demomanfix,
ProjEnt_Lifetime_PreHit = projent_lifetime_prehit,
ProjEnt_Lifetime_PostHit = projent_lifetime_posthit,
ProjEnt_Serverside = projent_serverside,
NumpadKey = numpadkey,
Toggle = toggle,
StartOn = starton,
} } )
return true
end
end
function TOOL:Reload( trace )
if ( trace.Entity:IsValid() ) then
local fx = false
if trace.Entity:GetClass() == "prop_effect" and trace.Entity.AttachedEntity then trace.Entity = trace.Entity.AttachedEntity end
for _, asdf in pairs( ents:GetAll() ) do
if asdf:GetClass() == "particlecontroller_proj" and asdf:GetParent() == trace.Entity then
if SERVER then asdf:Remove() end
fx = true
end
end
if SERVER then
duplicator.ClearEntityModifier( trace.Entity, "DupeParticleControllerProj" )
end
return fx
end
end
if CLIENT then
local colorborder = Color(0,0,0,255)
local colorselect = Color(0,255,0,255)
local colorunselect = Color(255,255,255,255)
function TOOL:DrawHUD()
local pl = LocalPlayer()
local tr = pl:GetEyeTrace()
local attachnum = self:GetOwner():GetInfoNum( "particlecontrol_attachnum", 0 ) //use the standard tool's attachnum var
local function DrawHighlightAttachments(ent)
//If there aren't any attachments, then draw the model origin as selected and stop here:
if !ent:GetAttachments() or !ent:GetAttachments()[1] then
local _pos,_ang = ent:GetPos(), ent:GetAngles()
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 3,_pos.y - 3,6,6,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorselect)
draw.SimpleTextOutlined("0: (origin)","Default",textpos.x,textpos.y,colorselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,2,colorborder)
return
end
//Draw the unselected model origin, if applicable:
if ent:GetAttachments()[attachnum] then
local _pos,_ang = ent:GetPos(), ent:GetAngles()
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 2,_pos.y - 2,4,4,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorunselect)
draw.SimpleTextOutlined("0: (origin)","Default",textpos.x,textpos.y,colorunselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,1,colorborder)
end
//Draw the unselected attachment points:
for _, table in pairs(ent:GetAttachments()) do
local _pos,_ang = ent:GetAttachment(table.id).Pos,ent:GetAttachment(table.id).Ang
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
if table.id != attachnum then
draw.RoundedBox(0,_pos.x - 2,_pos.y - 2,4,4,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorunselect)
draw.SimpleTextOutlined(table.id ..": ".. table.name,"Default",textpos.x,textpos.y,colorunselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,1,colorborder)
end
end
//Draw the selected attachment point or model origin last, so it renders above all the others:
if !ent:GetAttachments()[attachnum] then
//Model origin
local _pos,_ang = ent:GetPos(), ent:GetAngles()
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 3,_pos.y - 3,6,6,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorselect)
draw.SimpleTextOutlined("0: (origin)","Default",textpos.x,textpos.y,colorselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,2,colorborder)
else
//Attachment
local _pos,_ang = ent:GetAttachment(attachnum).Pos,ent:GetAttachment(attachnum).Ang
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 3,_pos.y - 3,6,6,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorselect)
draw.SimpleTextOutlined(attachnum ..": ".. ent:GetAttachments()[attachnum].name,"Default",textpos.x,textpos.y,colorselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,2,colorborder)
end
end
if IsValid(tr.Entity) and tr.Entity == self.HighlightedEnt then
DrawHighlightAttachments(self.HighlightedEnt)
return end
if IsValid(tr.Entity) and tr.Entity != self.HighlightedEnt then
//unhighlight the old ent if it exists
if self.HighlightedEnt != nil then
self.HighlightedEnt = nil
end
//highlight the new ent
self.HighlightedEnt = tr.Entity
end
if !IsValid(tr.Entity) and self.HighlightedEnt != nil then
self.HighlightedEnt = nil
end
end
function TOOL:Holster()
if self.HighlightedEnt != nil then
self.HighlightedEnt = nil
end
end
//All credit for the toolgun scroll wheel code goes to the Wiremod devs. You guys are the best.
local function get_active_tool(ply, tool)
-- find toolgun
local activeWep = ply:GetActiveWeapon()
if not IsValid(activeWep) or activeWep:GetClass() ~= "gmod_tool" or activeWep.Mode ~= tool then return end
return activeWep:GetToolObject(tool)
end
local function hookfunc( ply, bind, pressed )
if not pressed then return end
if bind == "invnext" then
local self = get_active_tool(ply, "particlecontrol_proj")
if not self then return end
return self:ScrollDown(ply:GetEyeTraceNoCursor())
elseif bind == "invprev" then
local self = get_active_tool(ply, "particlecontrol_proj")
if not self then return end
return self:ScrollUp(ply:GetEyeTraceNoCursor())
end
end
if game.SinglePlayer() then -- wtfgarry (have to have a delay in single player or the hook won't get added)
timer.Simple(5,function() hook.Add( "PlayerBindPress", "particlecontrol_proj_playerbindpress", hookfunc ) end)
else
hook.Add( "PlayerBindPress", "particlecontrol_proj_playerbindpress", hookfunc )
end
//End shamefully copied code here.
function TOOL:Scroll(trace,dir)
if !IsValid(self.HighlightedEnt) then return end
local attachcount = 0
if self.HighlightedEnt:GetAttachments() then attachcount = table.Count(self.HighlightedEnt:GetAttachments()) end
local oldattachnum = self:GetOwner():GetInfoNum( "particlecontrol_attachnum", 0 ) //use the standard tool's attachnum var
if oldattachnum > attachcount then oldattachnum = 0 end
local attachnum = oldattachnum + dir
if attachnum < 0 then attachnum = attachcount end
if attachnum > attachcount then attachnum = 0 end
RunConsoleCommand("particlecontrol_attachnum", tostring(attachnum)) //use the standard tool's attachnum var
self:GetOwner():EmitSound("weapons/pistol/pistol_empty.wav")
return true
end
function TOOL:ScrollUp(trace) return self:Scroll(trace,-1) end
function TOOL:ScrollDown(trace) return self:Scroll(trace,1) end
end
if SERVER then
local function SpawnParticleControllerProj(ply, ent, DataTable)
if DataTable == nil or DataTable == {} or DataTable.ProjModel == nil or ent == nil or !IsValid(ent) then return end
local ParticleControlProj = ents.Create( "particlecontroller_proj" )
ParticleControlProj:SetPos(ent:GetPos())
ParticleControlProj:SetAngles(ent:GetAngles())
ParticleControlProj:SetParent(ent)
ent:DeleteOnRemove(ParticleControlProj)
ParticleControlProj:SetTargetEnt(ent)
if DataTable.ProjFXInfo != nil then
ParticleControlProj:SetProjFX_EffectName(DataTable.ProjFXInfo.effectname)
ParticleControlProj:SetProjFX_UtilEffectInfo(DataTable.ProjFXInfo.utileffectinfo)
if DataTable.ProjFXInfo.colorinfo != nil then
local projfxcolor = Vector(DataTable.ProjFXInfo.colorinfo.r, DataTable.ProjFXInfo.colorinfo.g, DataTable.ProjFXInfo.colorinfo.b)
if DataTable.ProjFXInfo.colorinfo.a then
projfxcolor = projfxcolor / 255
end
ParticleControlProj:SetProjFX_ColorInfo( projfxcolor )
else
ParticleControlProj:SetProjFX_ColorInfo( Vector(0,0,0) )
end
else
ParticleControlProj:SetProjFX_EffectName("")
end
if DataTable.ImpactFXInfo != nil then
ParticleControlProj:SetImpactFX_EffectName(DataTable.ImpactFXInfo.effectname)
ParticleControlProj:SetImpactFX_UtilEffectInfo(DataTable.ImpactFXInfo.utileffectinfo)
if DataTable.ImpactFXInfo.colorinfo != nil then
local impactfxcolor = Vector(DataTable.ImpactFXInfo.colorinfo.r, DataTable.ImpactFXInfo.colorinfo.g, DataTable.ImpactFXInfo.colorinfo.b)
if DataTable.ImpactFXInfo.colorinfo.a then
impactfxcolor = impactfxcolor / 255
end
ParticleControlProj:SetImpactFX_ColorInfo( impactfxcolor )
else
ParticleControlProj:SetImpactFX_ColorInfo( Vector(0,0,0) )
end
else
ParticleControlProj:SetImpactFX_EffectName("")
end
ParticleControlProj:SetAttachNum(DataTable.AttachNum)
ParticleControlProj:SetRepeatRate(DataTable.RepeatRate)
ParticleControlProj:SetProjModel(DataTable.ProjModel)
ParticleControlProj:SetSkin(DataTable.ProjModel_Skin) //also use the controller ent to store the skin
ParticleControlProj:SetProjModel_AttachNum(DataTable.ProjModel_AttachNum)
ParticleControlProj:SetMaterial(DataTable.ProjModel_Material) //and the material
ParticleControlProj:SetProjModel_Invis( tobool(DataTable.ProjModel_Invis) )
ParticleControlProj:SetImpactFX_EffectLifetime(DataTable.ImpactFX_EffectLifetime)
ParticleControlProj:SetProjEnt_Spread(DataTable.ProjEnt_Spread)
ParticleControlProj:SetProjEnt_Velocity(DataTable.ProjEnt_Velocity)
ParticleControlProj:SetProjEnt_Gravity( tobool(DataTable.ProjEnt_Gravity) )
ParticleControlProj:SetProjEnt_Angle(DataTable.ProjEnt_Angle)
ParticleControlProj:SetProjEnt_Spin(DataTable.ProjEnt_Spin)
ParticleControlProj:SetProjEnt_DemomanFix( tobool(DataTable.ProjEnt_DemomanFix) )
ParticleControlProj:SetProjEnt_Lifetime_PreHit(DataTable.ProjEnt_Lifetime_PreHit)
ParticleControlProj:SetProjEnt_Lifetime_PostHit(DataTable.ProjEnt_Lifetime_PostHit)
ParticleControlProj:SetProjEnt_Serverside( tobool(DataTable.ProjEnt_Serverside) )
ParticleControlProj:SetActive( tobool(DataTable.StartOn) )
ParticleControlProj:SetToggle( tobool(DataTable.Toggle) )
ParticleControlProj:SetNumpadKey(DataTable.NumpadKey)
numpad.OnDown( ply, DataTable.NumpadKey, "Particle_Press", ParticleControlProj )
numpad.OnUp( ply, DataTable.NumpadKey, "Particle_Release", ParticleControlProj )
ParticleControlProj:SetNumpadState("")
ParticleControlProj:Spawn()
ParticleControlProj:Activate()
end
function AttachParticleControllerProj( ply, ent, Data )
if Data.NewTable then
SpawnParticleControllerProj(ply, ent, Data.NewTable)
local dupetable = {}
if ent.EntityMods and ent.EntityMods.DupeParticleControllerProj then dupetable = ent.EntityMods.DupeParticleControllerProj end
table.insert(dupetable, Data.NewTable)
duplicator.StoreEntityModifier( ent, "DupeParticleControllerProj", dupetable )
return end
end
function DupeParticleControllerProj( ply, ent, Data )
//due to a problem with the easy bonemerge tool that causes entity modifiers to be applied TWICE, we need to remove the effects that were added the first time
for _, asdf in pairs( ents:GetAll() ) do
if asdf:GetClass() == "particlecontroller_proj" and asdf:GetParent() == ent then
asdf:Remove()
end
end
for _, DataTable in pairs (Data) do
SpawnParticleControllerProj(ply, ent, DataTable)
end
end
duplicator.RegisterEntityModifier( "DupeParticleControllerProj", DupeParticleControllerProj )
end
//we're still testing out a lot of stuff with the cpanel, so let's add a way to refresh it by reselecting the tool
--[[
TOOL.ClientConVar[ "refresh" ] = 1
function TOOL:Think()
if SERVER then return end
if self:GetClientNumber("refresh") == 1 then
RunConsoleCommand("particlecontrol_proj_refresh", "0");
//refresh the cpanel
local panel = controlpanel.Get( "particlecontrol_proj" )
if ( !panel ) then return end
panel:ClearControls()
self.BuildCPanel(panel)
end
end
function TOOL:Deploy()
RunConsoleCommand("particlecontrol_proj_refresh", "1");
end
]]
local ConVarsDefault = TOOL:BuildConVarList()
function TOOL.BuildCPanel(panel)
panel:AddControl( "Header", { Description = "#tool.particlecontrol_proj.help" } )
//Presets
panel:AddControl( "ComboBox", {
MenuButton = 1,
Folder = "particlecontrol_proj",
Options = {
//[ "#preset.default" ] = ConVarsDefault
[ "Example: Generic Rockets" ] = ConVarsDefault,
[ "Example: TF2 Rockets" ] = { particlecontrol_proj_impactfx_color_b = "0", particlecontrol_proj_impactfx_color_enabled = "0", particlecontrol_proj_impactfx_color_g = "20", particlecontrol_proj_impactfx_color_outofone = "0", particlecontrol_proj_impactfx_color_r = "255", particlecontrol_proj_impactfx_effectlifetime = "1.000000", particlecontrol_proj_impactfx_effectname = "ExplosionCore_Wall", particlecontrol_proj_impactfx_enabled = "1", particlecontrol_proj_impactfx_utileffect_magnitude = "1", particlecontrol_proj_impactfx_utileffect_radius = "10", particlecontrol_proj_impactfx_utileffect_scale = "1", particlecontrol_proj_numpadkey = "52", particlecontrol_proj_projent_angle = "0", particlecontrol_proj_projent_demomanfix = "0", particlecontrol_proj_projent_gravity = "0", particlecontrol_proj_projent_lifetime_posthit = "0.000000", particlecontrol_proj_projent_lifetime_prehit = "10.000000", particlecontrol_proj_projent_serverside = "0", particlecontrol_proj_projent_spin = "0",
particlecontrol_proj_projent_spread = "0", particlecontrol_proj_projent_velocity = "1100.000000", particlecontrol_proj_projfx_color_b = "0", particlecontrol_proj_projfx_color_enabled = "0", particlecontrol_proj_projfx_color_g = "20", particlecontrol_proj_projfx_color_outofone = "0", particlecontrol_proj_projfx_color_r = "255", particlecontrol_proj_projfx_effectname = "rockettrail", particlecontrol_proj_projfx_enabled = "1", particlecontrol_proj_projfx_utileffect_magnitude = "1", particlecontrol_proj_projfx_utileffect_radius = "10", particlecontrol_proj_projfx_utileffect_scale = "1", particlecontrol_proj_projmodel = "models/weapons/w_models/w_rocket.mdl", particlecontrol_proj_projmodel_attachnum = "1", particlecontrol_proj_projmodel_invis = "0", particlecontrol_proj_projmodel_skin = "0", particlecontrol_proj_propangle = "2", particlecontrol_proj_propinvis = "0", particlecontrol_proj_propmodel = "models/weapons/w_smg1.mdl", particlecontrol_proj_repeatrate = "0.800000",
particlecontrol_proj_starton = "1", particlecontrol_proj_toggle = "1" },
[ "Example: TF2 Grenades, red" ] = { particlecontrol_proj_impactfx_color_b = "0", particlecontrol_proj_impactfx_color_enabled = "0", particlecontrol_proj_impactfx_color_g = "20", particlecontrol_proj_impactfx_color_outofone = "0", particlecontrol_proj_impactfx_color_r = "255", particlecontrol_proj_impactfx_effectlifetime = "1.000000", particlecontrol_proj_impactfx_effectname = "ExplosionCore_MidAir", particlecontrol_proj_impactfx_enabled = "1", particlecontrol_proj_impactfx_utileffect_magnitude = "1", particlecontrol_proj_impactfx_utileffect_radius = "10", particlecontrol_proj_impactfx_utileffect_scale = "1", particlecontrol_proj_numpadkey = "52", particlecontrol_proj_projent_angle = "0", particlecontrol_proj_projent_demomanfix = "0", particlecontrol_proj_projent_gravity = "1", particlecontrol_proj_projent_lifetime_posthit = "2.300000", particlecontrol_proj_projent_lifetime_prehit = "2.300000", particlecontrol_proj_projent_serverside = "0", particlecontrol_proj_projent_spin = "4",
particlecontrol_proj_projent_spread = "0", particlecontrol_proj_projent_velocity = "1217.000000", particlecontrol_proj_projfx_color_b = "0", particlecontrol_proj_projfx_color_enabled = "0", particlecontrol_proj_projfx_color_g = "20", particlecontrol_proj_projfx_color_outofone = "0", particlecontrol_proj_projfx_color_r = "255", particlecontrol_proj_projfx_effectname = "pipebombtrail_red", particlecontrol_proj_projfx_enabled = "1", particlecontrol_proj_projfx_utileffect_magnitude = "1", particlecontrol_proj_projfx_utileffect_radius = "10", particlecontrol_proj_projfx_utileffect_scale = "1", particlecontrol_proj_projmodel = "models/weapons/w_models/w_grenade_grenadelauncher.mdl", particlecontrol_proj_projmodel_attachnum = "0", particlecontrol_proj_projmodel_invis = "0", particlecontrol_proj_projmodel_skin = "0", particlecontrol_proj_propangle = "2", particlecontrol_proj_propinvis = "0", particlecontrol_proj_propmodel = "models/weapons/w_smg1.mdl", particlecontrol_proj_repeatrate = "0.600000",
particlecontrol_proj_starton = "1", particlecontrol_proj_toggle = "1" },
[ "Example: TF2 Grenades, blue" ] = { particlecontrol_proj_impactfx_color_b = "0", particlecontrol_proj_impactfx_color_enabled = "0", particlecontrol_proj_impactfx_color_g = "20", particlecontrol_proj_impactfx_color_outofone = "0", particlecontrol_proj_impactfx_color_r = "255", particlecontrol_proj_impactfx_effectlifetime = "1.000000", particlecontrol_proj_impactfx_effectname = "ExplosionCore_MidAir", particlecontrol_proj_impactfx_enabled = "1", particlecontrol_proj_impactfx_utileffect_magnitude = "1", particlecontrol_proj_impactfx_utileffect_radius = "10", particlecontrol_proj_impactfx_utileffect_scale = "1", particlecontrol_proj_numpadkey = "52", particlecontrol_proj_projent_angle = "0", particlecontrol_proj_projent_demomanfix = "0", particlecontrol_proj_projent_gravity = "1", particlecontrol_proj_projent_lifetime_posthit = "2.300000", particlecontrol_proj_projent_lifetime_prehit = "2.300000", particlecontrol_proj_projent_serverside = "0", particlecontrol_proj_projent_spin = "4",
particlecontrol_proj_projent_spread = "0", particlecontrol_proj_projent_velocity = "1217.000000", particlecontrol_proj_projfx_color_b = "0", particlecontrol_proj_projfx_color_enabled = "0", particlecontrol_proj_projfx_color_g = "20", particlecontrol_proj_projfx_color_outofone = "0", particlecontrol_proj_projfx_color_r = "255", particlecontrol_proj_projfx_effectname = "pipebombtrail_blue", particlecontrol_proj_projfx_enabled = "1", particlecontrol_proj_projfx_utileffect_magnitude = "1", particlecontrol_proj_projfx_utileffect_radius = "10", particlecontrol_proj_projfx_utileffect_scale = "1", particlecontrol_proj_projmodel = "models/weapons/w_models/w_grenade_grenadelauncher.mdl", particlecontrol_proj_projmodel_attachnum = "0", particlecontrol_proj_projmodel_invis = "0", particlecontrol_proj_projmodel_skin = "1", particlecontrol_proj_propangle = "2", particlecontrol_proj_propinvis = "0", particlecontrol_proj_propmodel = "models/weapons/w_smg1.mdl", particlecontrol_proj_repeatrate = "0.600000",
particlecontrol_proj_starton = "1", particlecontrol_proj_toggle = "1" },
},
CVars = table.GetKeys( ConVarsDefault )
} )
panel:AddControl( "Checkbox", { Label = "Enable projectile effects?", Command = "particlecontrol_proj_projfx_enabled" } )
AddParticleBrowser(panel, {
name = "Projectile Effect",
commands = {
effectname = "particlecontrol_proj_projfx_effectname",
color = "particlecontrol_proj_projfx_color",
utileffect = "particlecontrol_proj_projfx_utileffect",
enabled = "particlecontrol_proj_projfx_enabled",
},
})
panel:AddControl( "Checkbox", { Label = "Enable impact/expire effects?", Command = "particlecontrol_proj_impactfx_enabled" } )
AddParticleBrowser(panel, {
name = "Impact/Expire Effect",
commands = {
effectname = "particlecontrol_proj_impactfx_effectname",
color = "particlecontrol_proj_impactfx_color",
utileffect = "particlecontrol_proj_impactfx_utileffect",
enabled = "particlecontrol_proj_impactfx_enabled",
},
})
//panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl("Slider", {
Label = "Attachment",
Type = "Integer",
Min = "0",
Max = "10",
Command = "particlecontrol_attachnum", //use the standard tool's attachnum var
})
panel:ControlHelp( "Attachment point on the model to fire projectiles from. Set to 0 to fire from the model origin." )
panel:AddControl("Slider", {
Label = "Repeat Rate",
Type = "Float",
Min = "0",
Max = "1",
Command = "particlecontrol_proj_repeatrate"
})
panel:ControlHelp( "How often the projectile fires. Set to 0 to not repeat." )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
local projmodellist = { Label = "Projectile Model:", ConVar = "particlecontrol_proj_projmodel", Category = "Projectile Model", Height = 1, Models = {} }
projmodellist.Models["models/hunter/plates/plate.mdl"] = {}
projmodellist.Models["models/weapons/w_missile.mdl"] = {}
projmodellist.Models["models/weapons/w_models/w_rocket.mdl"] = {}
projmodellist.Models["models/weapons/w_models/w_grenade_grenadelauncher.mdl"] = {}
panel:AddControl( "PropSelect", projmodellist )
local projmodelentry = vgui.Create( "DTextEntry", panel )
projmodelentry:SetConVar( "particlecontrol_proj_projmodel" )
panel:AddItem(projmodelentry)
panel:AddControl("Slider", {
Label = "Projectile Skin",
Type = "Integer",
Min = "0",
Max = "10",
Command = "particlecontrol_proj_projmodel_skin",
})
panel:AddControl("Slider", {
Label = "Projectile Attachment",
Type = "Integer",
Min = "0",
Max = "10",
Command = "particlecontrol_proj_projmodel_attachnum",
})
panel:ControlHelp( "Attachment point on the projectile to attach the effect to. Set to 0 to attach to model origin." )
panel:AddControl("TextBox", {
Label = "Projectile Material",
Description = "",
MaxLength = 255,
Text = "",
Command = "particlecontrol_proj_projmodel_material",
})
panel:AddControl( "Checkbox", { Label = "Invisible projectiles (particles only)", Command = "particlecontrol_proj_projmodel_invis" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl("Slider", {
Label = "Projectile Spread",
Type = "Float",
Min = "0",
Max = "1",
Command = "particlecontrol_proj_projent_spread"
})
panel:ControlHelp( "Each unit is 90 degrees of spread - you can type in 2 for 180 degrees or even 4 for 360 degrees." )
panel:AddControl("Slider", {
Label = "Projectile Velocity",
Type = "Float",
Min = "0",
Max = "3000",
Command = "particlecontrol_proj_projent_velocity"
})
//panel:ControlHelp( "" )
panel:AddControl( "Checkbox", { Label = "Projectile Gravity", Command = "particlecontrol_proj_projent_gravity" } )
panel:AddControl( "ComboBox", {
Label = "Projectile Angle",
MenuButton = "0",
Options = {
["Forward"] = { particlecontrol_proj_projent_angle = 0 },
["Left"] = { particlecontrol_proj_projent_angle = 1 },
["Right"] = { particlecontrol_proj_projent_angle = 2 },
["Up"] = { particlecontrol_proj_projent_angle = 3 },
["Down"] = { particlecontrol_proj_projent_angle = 4 },
["Back"] = { particlecontrol_proj_projent_angle = 5 },
}
})
panel:AddControl( "ComboBox", {
Label = "Projectile Spin",
MenuButton = "0",
Options = {
["Don't spin"] = { particlecontrol_proj_projent_spin = 0 },
["Spin pitch"] = { particlecontrol_proj_projent_spin = 1 },
["Spin yaw"] = { particlecontrol_proj_projent_spin = 2 },
["Spin roll"] = { particlecontrol_proj_projent_spin = 3 },
["Spin random"] = { particlecontrol_proj_projent_spin = 4 },
}
})
panel:AddControl( "Checkbox", { Label = "Demoman Weapon Fix", Command = "particlecontrol_proj_projent_demomanfix" } )
panel:ControlHelp( "Demoman weapon props have their muzzle attachment at an angle for some reason. Use this to fix it." )
panel:AddControl("Slider", {
Label = "Lifetime",
Type = "Float",
Min = "0",
Max = "10",
Command = "particlecontrol_proj_projent_lifetime_prehit"
})
panel:ControlHelp( "How long projectiles last after being launched." )
panel:AddControl("Slider", {
Label = "Lifetime (after impact)",
Type = "Float",
Min = "0",
Max = "10",
Command = "particlecontrol_proj_projent_lifetime_posthit"
})
panel:ControlHelp( "How long projectiles last after hitting something. Set to 0 to expire on impact." ) //TODO: how to explain that lifetime before hit and lifetime after hit are separate timers?
panel:AddControl( "Checkbox", { Label = "Serverside projectiles?", Command = "particlecontrol_proj_projent_serverside" } )
panel:ControlHelp( "Use serverside props for projectiles. These will collide properly with everything instead of passing through, but they'll also put a lot more stress on the game (meaning more lag), and they'll show up in the wrong spot if bonemerged. Only turn this on if you need it." )
panel:AddControl("Slider", {
Label = "Impact Effect Lifetime",
Type = "Float",
Min = "0.5",
Max = "5",
Command = "particlecontrol_proj_impactfx_effectlifetime"
})
//panel:ControlHelp( "Number of seconds before impact effects are removed." )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
local modellist = { Label = "Prop:", ConVar = "particlecontrol_proj_propmodel", Category = "Prop", Height = 1, Models = {} }
modellist.Models["models/hunter/plates/plate025x025.mdl"] = {}
modellist.Models["models/hunter/plates/plate.mdl"] = {}
modellist.Models["models/weapons/w_smg1.mdl"] = {}
modellist.Models["models/weapons/w_models/w_rocketlauncher.mdl"] = {}
panel:AddControl( "PropSelect", modellist )
panel:AddControl( "ComboBox", {
Label = "Prop Angle",
MenuButton = "0",
Options = {
["Spawn upright"] = { particlecontrol_proj_propangle = "1" },
["Spawn at surface angle"] = { particlecontrol_proj_propangle = "2" }
}
})
panel:AddControl( "Checkbox", { Label = "Invisible prop (particles only)", Command = "particlecontrol_proj_propinvis" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Numpad", {
Label = "Effect Key",
Command = "particlecontrol_proj_numpadkey",
ButtonSize = 22
})
panel:AddControl( "Checkbox", { Label = "Toggle", Command = "particlecontrol_proj_toggle" } )
panel:AddControl( "Checkbox", { Label = "Start on?", Command = "particlecontrol_proj_starton" } )
end

View File

@@ -0,0 +1,712 @@
--[[
| 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 = "Particle Controller"
TOOL.Name = "ParCtrl - Tracers"
TOOL.Command = nil
TOOL.ConfigName = ""
TOOL.HighlightedEnt = nil
TOOL.ClientConVar[ "effectname" ] = "!UTILEFFECT!AR2Tracer"
//TOOL.ClientConVar[ "utileffect_scale" ] = "1"
//TOOL.ClientConVar[ "utileffect_magnitude" ] = "1"
//TOOL.ClientConVar[ "utileffect_radius" ] = "10"
TOOL.ClientConVar[ "color_enabled" ] = "0"
TOOL.ClientConVar[ "color_r" ] = "255"
TOOL.ClientConVar[ "color_g" ] = "20"
TOOL.ClientConVar[ "color_b" ] = "0"
TOOL.ClientConVar[ "color_outofone" ] = "0"
TOOL.ClientConVar[ "impactfx_enabled" ] = "1"
TOOL.ClientConVar[ "impactfx_effectname" ] = "!UTILEFFECT!AR2Impact"
TOOL.ClientConVar[ "impactfx_utileffect_scale" ] = "1"
TOOL.ClientConVar[ "impactfx_utileffect_magnitude" ] = "1"
TOOL.ClientConVar[ "impactfx_utileffect_radius" ] = "10"
TOOL.ClientConVar[ "impactfx_color_enabled" ] = "0"
TOOL.ClientConVar[ "impactfx_color_r" ] = "255"
TOOL.ClientConVar[ "impactfx_color_g" ] = "20"
TOOL.ClientConVar[ "impactfx_color_b" ] = "0"
TOOL.ClientConVar[ "impactfx_color_outofone" ] = "0"
//TOOL.ClientConVar[ "attachnum" ] = "1" //we're using the standard tool's attachnum var instead so that the selected attachment stays consistent when swapping between tools
TOOL.ClientConVar[ "repeatrate" ] = "0.1"
TOOL.ClientConVar[ "effectlifetime" ] = "1.0"
TOOL.ClientConVar[ "tracerspread" ] = "0.02"
TOOL.ClientConVar[ "tracercount" ] = "1"
TOOL.ClientConVar[ "leavebulletholes" ] = "1"
TOOL.ClientConVar[ "propmodel" ] = "models/weapons/w_smg1.mdl"
TOOL.ClientConVar[ "propangle" ] = "2"
TOOL.ClientConVar[ "propinvis" ] = "0"
TOOL.ClientConVar[ "numpadkey" ] = "52"
TOOL.ClientConVar[ "toggle" ] = "1"
TOOL.ClientConVar[ "starton" ] = "1"
TOOL.Information = {
{ name = "left0", stage = 0, icon = "gui/lmb.png" },
{ name = "middle0", stage = 0, icon = "gui/mmb.png" },
{ name = "right0", stage = 0, icon = "gui/rmb.png" },
{ name = "reload0", stage = 0, icon = "gui/r.png" },
}
if ( CLIENT ) then
language.Add( "tool.particlecontrol_tracer.name", "Adv. Particle Controller - Tracers" )
language.Add( "tool.particlecontrol_tracer.desc", "Attach tracer effects to things" )
language.Add( "tool.particlecontrol_tracer.help", "Tracer effects are particles that fire out like bullets, with one end at the attachment and the other end where the \"bullet\" hits something." )
language.Add( "tool.particlecontrol_tracer.left0", "Add a tracer effect to an object" )
language.Add( "tool.particlecontrol_tracer.middle0", "Scroll through an object's attachments" )
language.Add( "tool.particlecontrol_tracer.right0", "Attach a new prop with the tracer effect on it" )
language.Add( "tool.particlecontrol_tracer.reload0", "Remove all tracer effects from an object" )
end
util.PrecacheSound("weapons/pistol/pistol_empty.wav")
function TOOL:LeftClick( trace )
local effectname = self:GetClientInfo( "effectname", 0 )
local attachnum = self:GetOwner():GetInfoNum( "particlecontrol_attachnum", 0 ) //use the standard tool's attachnum var
local repeatrate = self:GetClientNumber( "repeatrate", 0 )
local numpadkey = self:GetClientNumber( "numpadkey", 0 )
local toggle = self:GetClientNumber( "toggle", 0 )
local starton = self:GetClientNumber( "starton", 0 )
//local utileffectinfo = Vector( self:GetClientNumber( "utileffect_scale", 0 ), self:GetClientNumber( "utileffect_magnitude", 0 ), self:GetClientNumber( "utileffect_radius", 0 ) )
local colorinfo = nil
if self:GetClientNumber( "color_enabled", 0 ) == 1 then
if self:GetClientNumber( "color_outofone", 0 ) == 1 then
colorinfo = Color( self:GetClientNumber( "color_r", 0 ), self:GetClientNumber( "color_g", 0 ), self:GetClientNumber( "color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
colorinfo = Color( self:GetClientNumber( "color_r", 0 ), self:GetClientNumber( "color_g", 0 ), self:GetClientNumber( "color_b", 0 ), 0 )
end
end
local tracerspread = self:GetClientNumber( "tracerspread", 0 )
local tracercount = self:GetClientNumber( "tracercount", 0 )
local leavebulletholes = self:GetClientNumber( "leavebulletholes", 0 )
local effectlifetime = self:GetClientNumber( "effectlifetime", 0 )
local impactinfo = nil
if self:GetClientNumber( "impactfx_enabled", 0 ) == 1 then
impactinfo = {
effectname = self:GetClientInfo( "impactfx_effectname", 0 ),
utileffectinfo = Vector( self:GetClientNumber( "impactfx_utileffect_scale", 0 ), self:GetClientNumber( "impactfx_utileffect_magnitude", 0 ), self:GetClientNumber( "impactfx_utileffect_radius", 0 ) ),
}
if self:GetClientNumber( "impactfx_color_enabled", 0 ) == 1 then
if self:GetClientNumber( "impactfx_color_outofone", 0 ) == 1 then
impactinfo.colorinfo = Color( self:GetClientNumber( "impactfx_color_r", 0 ), self:GetClientNumber( "impactfx_color_g", 0 ), self:GetClientNumber( "impactfx_color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
impactinfo.colorinfo = Color( self:GetClientNumber( "impactfx_color_r", 0 ), self:GetClientNumber( "impactfx_color_g", 0 ), self:GetClientNumber( "impactfx_color_b", 0 ), 0 )
end
end
end
local ply = self:GetOwner()
if ( trace.Entity:IsValid() ) then
if CLIENT then return true end
if trace.Entity:GetClass() == "prop_effect" and trace.Entity.AttachedEntity then trace.Entity = trace.Entity.AttachedEntity end
AttachParticleControllerTracer( ply, trace.Entity, { NewTable = {
EffectName = effectname,
AttachNum = attachnum,
RepeatRate = repeatrate,
Toggle = toggle,
StartOn = starton,
NumpadKey = numpadkey,
ColorInfo = colorinfo,
TracerSpread = tracerspread,
TracerCount = tracercount,
LeaveBulletHoles = leavebulletholes,
EffectLifetime = effectlifetime,
ImpactInfo = impactinfo,
} } )
return true
end
end
function TOOL:RightClick( trace )
local effectname = self:GetClientInfo( "effectname", 0 )
local attachnum = self:GetOwner():GetInfoNum( "particlecontrol_attachnum", 0 ) //use the standard tool's attachnum var
local repeatrate = self:GetClientNumber( "repeatrate", 0 )
local numpadkey = self:GetClientNumber( "numpadkey", 0 )
local toggle = self:GetClientNumber( "toggle", 0 )
local starton = self:GetClientNumber( "starton", 0 )
//local utileffectinfo = Vector( self:GetClientNumber( "utileffect_scale", 0 ), self:GetClientNumber( "utileffect_magnitude", 0 ), self:GetClientNumber( "utileffect_radius", 0 ) )
local colorinfo = nil
if self:GetClientNumber( "color_enabled", 0 ) == 1 then
if self:GetClientNumber( "color_outofone", 0 ) == 1 then
colorinfo = Color( self:GetClientNumber( "color_r", 0 ), self:GetClientNumber( "color_g", 0 ), self:GetClientNumber( "color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
colorinfo = Color( self:GetClientNumber( "color_r", 0 ), self:GetClientNumber( "color_g", 0 ), self:GetClientNumber( "color_b", 0 ), 0 )
end
end
local tracerspread = self:GetClientNumber( "tracerspread", 0 )
local tracercount = self:GetClientNumber( "tracercount", 0 )
local leavebulletholes = self:GetClientNumber( "leavebulletholes", 0 )
local effectlifetime = self:GetClientNumber( "effectlifetime", 0 )
local impactinfo = nil
if self:GetClientNumber( "impactfx_enabled", 0 ) == 1 then
impactinfo = {
effectname = self:GetClientInfo( "impactfx_effectname", 0 ),
utileffectinfo = Vector( self:GetClientNumber( "impactfx_utileffect_scale", 0 ), self:GetClientNumber( "impactfx_utileffect_magnitude", 0 ), self:GetClientNumber( "impactfx_utileffect_radius", 0 ) ),
}
if self:GetClientNumber( "impactfx_color_enabled", 0 ) == 1 then
if self:GetClientNumber( "impactfx_color_outofone", 0 ) == 1 then
impactinfo.colorinfo = Color( self:GetClientNumber( "impactfx_color_r", 0 ), self:GetClientNumber( "impactfx_color_g", 0 ), self:GetClientNumber( "impactfx_color_b", 0 ), 1 ) //we're using the alpha value to store color_outofone
else
impactinfo.colorinfo = Color( self:GetClientNumber( "impactfx_color_r", 0 ), self:GetClientNumber( "impactfx_color_g", 0 ), self:GetClientNumber( "impactfx_color_b", 0 ), 0 )
end
end
end
local ply = self:GetOwner()
local propmodel = self:GetClientInfo( "propmodel", 0 )
local propangle = self:GetClientNumber( "propangle", 0 )
//propangle 1: spawn upright
//propangle 2: spawn at surface angle
if !util.IsValidModel(propmodel) then return false end
if !util.IsValidProp(propmodel) then return false end
if CLIENT then return true end
prop = ents.Create( "prop_physics" )
prop:SetModel( propmodel )
prop:SetPos( trace.HitPos - trace.HitNormal * prop:OBBMins().z )
if propangle == 1 then prop:SetAngles(Angle(0,trace.HitNormal:Angle().y,0)) else prop:SetAngles(trace.HitNormal:Angle()) end
prop:SetCollisionGroup(20) //COLLISION_GROUP_NONE, nocollide with everything except world
prop:Spawn()
local shouldweweld = true //don't weld if...
if ( !util.IsValidPhysicsObject(prop, 0) ) then shouldweweld = false end //the prop doesn't have a phys object
if ( !trace.Entity:IsValid() ) then shouldweweld = false end //the thing we clicked on doesn't exist/is the world
if ( trace.Entity && trace.Entity:IsPlayer() ) then shouldweweld = false end //the thing we clicked on is a player
if ( !util.IsValidPhysicsObject( trace.Entity, trace.PhysicsBone ) ) then shouldweweld = false end //the thing we clicked on doesn't have a phys object
if shouldweweld == true then
local const = constraint.Weld( prop, trace.Entity, 0, trace.PhysicsBone, 0, true, true )
else
if util.IsValidPhysicsObject(prop, 0) then prop:GetPhysicsObject():EnableMotion(false) end
end
if self:GetClientNumber( "propinvis", 0 ) == 1 then
prop:SetRenderMode(1) //we need to change the render mode so the transparency actually shows up
prop:SetColor( Color(255,255,255,0) )
duplicator.StoreEntityModifier( prop, "colour", { Color = Color(255,255,255,0), RenderMode = 1, RenderFX = 0 } )
end
undo.Create( "prop" )
undo.AddEntity( prop )
undo.SetPlayer( ply )
undo.Finish( "Prop ("..tostring(propmodel)..")" )
if ( prop:IsValid() ) then
AttachParticleControllerTracer( ply, prop, { NewTable = {
EffectName = effectname,
AttachNum = attachnum,
RepeatRate = repeatrate,
Toggle = toggle,
StartOn = starton,
NumpadKey = numpadkey,
ColorInfo = colorinfo,
TracerSpread = tracerspread,
TracerCount = tracercount,
LeaveBulletHoles = leavebulletholes,
EffectLifetime = effectlifetime,
ImpactInfo = impactinfo,
} } )
return true
end
end
function TOOL:Reload( trace )
if ( trace.Entity:IsValid() ) then
local fx = false
if trace.Entity:GetClass() == "prop_effect" and trace.Entity.AttachedEntity then trace.Entity = trace.Entity.AttachedEntity end
for _, asdf in pairs( ents:GetAll() ) do
if asdf:GetClass() == "particlecontroller_tracer" and asdf:GetParent() == trace.Entity then
if SERVER then asdf:Remove() end
fx = true
end
end
if SERVER then
duplicator.ClearEntityModifier( trace.Entity, "DupeParticleControllerTracer" )
end
return fx
end
end
if CLIENT then
local colorborder = Color(0,0,0,255)
local colorselect = Color(0,255,0,255)
local colorunselect = Color(255,255,255,255)
function TOOL:DrawHUD()
local pl = LocalPlayer()
local tr = pl:GetEyeTrace()
local attachnum = self:GetOwner():GetInfoNum( "particlecontrol_attachnum", 0 ) //use the standard tool's attachnum var
local function DrawHighlightAttachments(ent)
//If there aren't any attachments, then draw the model origin as selected and stop here:
if !ent:GetAttachments() or !ent:GetAttachments()[1] then
local _pos,_ang = ent:GetPos(), ent:GetAngles()
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 3,_pos.y - 3,6,6,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorselect)
draw.SimpleTextOutlined("0: (origin)","Default",textpos.x,textpos.y,colorselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,2,colorborder)
return
end
//Draw the unselected model origin, if applicable:
if ent:GetAttachments()[attachnum] then
local _pos,_ang = ent:GetPos(), ent:GetAngles()
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 2,_pos.y - 2,4,4,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorunselect)
draw.SimpleTextOutlined("0: (origin)","Default",textpos.x,textpos.y,colorunselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,1,colorborder)
end
//Draw the unselected attachment points:
for _, table in pairs(ent:GetAttachments()) do
local _pos,_ang = ent:GetAttachment(table.id).Pos,ent:GetAttachment(table.id).Ang
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
if table.id != attachnum then
draw.RoundedBox(0,_pos.x - 2,_pos.y - 2,4,4,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorunselect)
draw.SimpleTextOutlined(table.id ..": ".. table.name,"Default",textpos.x,textpos.y,colorunselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,1,colorborder)
end
end
//Draw the selected attachment point or model origin last, so it renders above all the others:
if !ent:GetAttachments()[attachnum] then
//Model origin
local _pos,_ang = ent:GetPos(), ent:GetAngles()
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 3,_pos.y - 3,6,6,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorselect)
draw.SimpleTextOutlined("0: (origin)","Default",textpos.x,textpos.y,colorselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,2,colorborder)
else
//Attachment
local _pos,_ang = ent:GetAttachment(attachnum).Pos,ent:GetAttachment(attachnum).Ang
local _pos = _pos:ToScreen()
local textpos = {x = _pos.x+5,y = _pos.y-5}
draw.RoundedBox(0,_pos.x - 3,_pos.y - 3,6,6,colorborder)
draw.RoundedBox(0,_pos.x - 1,_pos.y - 1,2,2,colorselect)
draw.SimpleTextOutlined(attachnum ..": ".. ent:GetAttachments()[attachnum].name,"Default",textpos.x,textpos.y,colorselect,TEXT_ALIGN_LEFT,TEXT_ALIGN_BOTTOM,2,colorborder)
end
end
if IsValid(tr.Entity) and tr.Entity == self.HighlightedEnt then
DrawHighlightAttachments(self.HighlightedEnt)
return end
if IsValid(tr.Entity) and tr.Entity != self.HighlightedEnt then
//unhighlight the old ent if it exists
if self.HighlightedEnt != nil then
self.HighlightedEnt = nil
end
//highlight the new ent
self.HighlightedEnt = tr.Entity
end
if !IsValid(tr.Entity) and self.HighlightedEnt != nil then
self.HighlightedEnt = nil
end
end
function TOOL:Holster()
if self.HighlightedEnt != nil then
self.HighlightedEnt = nil
end
end
//All credit for the toolgun scroll wheel code goes to the Wiremod devs. You guys are the best.
local function get_active_tool(ply, tool)
-- find toolgun
local activeWep = ply:GetActiveWeapon()
if not IsValid(activeWep) or activeWep:GetClass() ~= "gmod_tool" or activeWep.Mode ~= tool then return end
return activeWep:GetToolObject(tool)
end
local function hookfunc( ply, bind, pressed )
if not pressed then return end
if bind == "invnext" then
local self = get_active_tool(ply, "particlecontrol_tracer")
if not self then return end
return self:ScrollDown(ply:GetEyeTraceNoCursor())
elseif bind == "invprev" then
local self = get_active_tool(ply, "particlecontrol_tracer")
if not self then return end
return self:ScrollUp(ply:GetEyeTraceNoCursor())
end
end
if game.SinglePlayer() then -- wtfgarry (have to have a delay in single player or the hook won't get added)
timer.Simple(5,function() hook.Add( "PlayerBindPress", "particlecontrol_tracer_playerbindpress", hookfunc ) end)
else
hook.Add( "PlayerBindPress", "particlecontrol_tracer_playerbindpress", hookfunc )
end
//End shamefully copied code here.
function TOOL:Scroll(trace,dir)
if !IsValid(self.HighlightedEnt) then return end
local attachcount = 0
if self.HighlightedEnt:GetAttachments() then attachcount = table.Count(self.HighlightedEnt:GetAttachments()) end
local oldattachnum = self:GetOwner():GetInfoNum( "particlecontrol_attachnum", 0 ) //use the standard tool's attachnum var
if oldattachnum > attachcount then oldattachnum = 0 end
local attachnum = oldattachnum + dir
if attachnum < 0 then attachnum = attachcount end
if attachnum > attachcount then attachnum = 0 end
RunConsoleCommand("particlecontrol_attachnum", tostring(attachnum)) //use the standard tool's attachnum var
self:GetOwner():EmitSound("weapons/pistol/pistol_empty.wav")
return true
end
function TOOL:ScrollUp(trace) return self:Scroll(trace,-1) end
function TOOL:ScrollDown(trace) return self:Scroll(trace,1) end
end
if SERVER then
local function SpawnParticleControllerTracer(ply, ent, DataTable)
if DataTable == nil or DataTable == {} or DataTable.EffectName == nil or ent == nil or !IsValid(ent) then return end
local ParticleControlTracer = ents.Create( "particlecontroller_tracer" )
ParticleControlTracer:SetPos(ent:GetPos())
ParticleControlTracer:SetAngles(ent:GetAngles())
ParticleControlTracer:SetParent(ent)
ent:DeleteOnRemove(ParticleControlTracer)
ParticleControlTracer:SetTargetEnt(ent)
ParticleControlTracer:SetEffectName(DataTable.EffectName)
ParticleControlTracer:SetAttachNum(DataTable.AttachNum)
//ParticleControlTracer:SetUtilEffectInfo(DataTable.UtilEffectInfo)
if DataTable.ColorInfo != nil then ParticleControlTracer:SetColor(DataTable.ColorInfo) else ParticleControlTracer:SetColor( Color(0,0,0,0) ) end
ParticleControlTracer:SetTracerSpread(DataTable.TracerSpread)
ParticleControlTracer:SetTracerCount(DataTable.TracerCount)
if DataTable.LeaveBulletHoles == 1 or DataTable.LeaveBulletHoles == true then ParticleControlTracer:SetLeaveBulletHoles(true) else ParticleControlTracer:SetLeaveBulletHoles(false) end
ParticleControlTracer:SetEffectLifetime(DataTable.EffectLifetime or 1.00) //old dupes will have nil
if DataTable.ImpactInfo != nil then
ParticleControlTracer:SetImpact_EffectName(DataTable.ImpactInfo.effectname)
ParticleControlTracer:SetImpact_UtilEffectInfo(DataTable.ImpactInfo.utileffectinfo)
if DataTable.ImpactInfo.colorinfo != nil then
local impactcolor = Vector(DataTable.ImpactInfo.colorinfo.r, DataTable.ImpactInfo.colorinfo.g, DataTable.ImpactInfo.colorinfo.b)
if DataTable.ImpactInfo.colorinfo.a then
impactcolor = impactcolor / 255
end
ParticleControlTracer:SetImpact_ColorInfo( impactcolor )
else
ParticleControlTracer:SetImpact_ColorInfo( Vector(0,0,0) )
end
else
ParticleControlTracer:SetImpact_EffectName("")
end
ParticleControlTracer:SetRepeatRate(DataTable.RepeatRate)
if DataTable.StartOn == 1 or DataTable.StartOn == true then ParticleControlTracer:SetActive(true) else ParticleControlTracer:SetActive(false) end
if DataTable.Toggle == 1 or DataTable.Toggle == true then ParticleControlTracer:SetToggle(true) else ParticleControlTracer:SetToggle(false) end
ParticleControlTracer:SetNumpadKey(DataTable.NumpadKey)
numpad.OnDown( ply, DataTable.NumpadKey, "Particle_Press", ParticleControlTracer )
numpad.OnUp( ply, DataTable.NumpadKey, "Particle_Release", ParticleControlTracer )
ParticleControlTracer:SetNumpadState("")
ParticleControlTracer:Spawn()
ParticleControlTracer:Activate()
end
function AttachParticleControllerTracer( ply, ent, Data )
if Data.NewTable then
SpawnParticleControllerTracer(ply, ent, Data.NewTable)
local dupetable = {}
if ent.EntityMods and ent.EntityMods.DupeParticleControllerTracer then dupetable = ent.EntityMods.DupeParticleControllerTracer end
table.insert(dupetable, Data.NewTable)
duplicator.StoreEntityModifier( ent, "DupeParticleControllerTracer", dupetable )
return end
end
function DupeParticleControllerTracer( ply, ent, Data )
//due to a problem with the easy bonemerge tool that causes entity modifiers to be applied TWICE, we need to remove the effects that were added the first time
for _, asdf in pairs( ents:GetAll() ) do
if asdf:GetClass() == "particlecontroller_tracer" and asdf:GetParent() == ent then
asdf:Remove()
end
end
for _, DataTable in pairs (Data) do
SpawnParticleControllerTracer(ply, ent, DataTable)
end
end
duplicator.RegisterEntityModifier( "DupeParticleControllerTracer", DupeParticleControllerTracer )
end
//we're still testing out a lot of stuff with the cpanel, so let's add a way to refresh it by reselecting the tool
--[[
TOOL.ClientConVar[ "refresh" ] = 1
function TOOL:Think()
if SERVER then return end
if self:GetClientNumber("refresh") == 1 then
RunConsoleCommand("particlecontrol_tracer_refresh", "0");
//refresh the cpanel
local panel = controlpanel.Get( "particlecontrol_tracer" )
if ( !panel ) then return end
panel:ClearControls()
self.BuildCPanel(panel)
end
end
function TOOL:Deploy()
RunConsoleCommand("particlecontrol_tracer_refresh", "1");
end
]]
local ConVarsDefault = TOOL:BuildConVarList()
function TOOL.BuildCPanel(panel)
panel:AddControl( "Header", { Description = "#tool.particlecontrol_tracer.help" } )
//Presets
panel:AddControl( "ComboBox", {
MenuButton = 1,
Folder = "particlecontrol_tracer",
Options = {
//[ "#preset.default" ] = ConVarsDefault
[ "Example: Pulse Rifle" ] = ConVarsDefault,
[ "Example: Generic Bullets" ] = { particlecontrol_tracer_color_b = "0", particlecontrol_tracer_color_enabled = "0", particlecontrol_tracer_color_g = "20", particlecontrol_tracer_color_outofone = "0", particlecontrol_tracer_color_r = "255", particlecontrol_tracer_effectlifetime = "1.000000", particlecontrol_tracer_effectname = "!UTILEFFECT!Tracer", particlecontrol_tracer_impactfx_color_b = "0", particlecontrol_tracer_impactfx_color_enabled = "0", particlecontrol_tracer_impactfx_color_g = "20", particlecontrol_tracer_impactfx_color_outofone = "0", particlecontrol_tracer_impactfx_color_r = "255", particlecontrol_tracer_impactfx_effectname = "!UTILEFFECT!AR2Impact", particlecontrol_tracer_impactfx_enabled = "0", particlecontrol_tracer_impactfx_utileffect_magnitude = "1", particlecontrol_tracer_impactfx_utileffect_radius = "10", particlecontrol_tracer_impactfx_utileffect_scale = "1", particlecontrol_tracer_leavebulletholes = "1", particlecontrol_tracer_numpadkey = "52",
particlecontrol_tracer_propangle = "2", particlecontrol_tracer_propinvis = "0", particlecontrol_tracer_propmodel = "models/weapons/w_smg1.mdl", particlecontrol_tracer_repeatrate = "0.080000", particlecontrol_tracer_starton = "1", particlecontrol_tracer_toggle = "1", particlecontrol_tracer_tracercount = "1", particlecontrol_tracer_tracerspread = "0.050000" },
[ "Example: Toolgun" ] = { particlecontrol_tracer_color_b = "0", particlecontrol_tracer_color_enabled = "0", particlecontrol_tracer_color_g = "20", particlecontrol_tracer_color_outofone = "0", particlecontrol_tracer_color_r = "255", particlecontrol_tracer_effectlifetime = "1.000000", particlecontrol_tracer_effectname = "!UTILEFFECT!ToolTracer", particlecontrol_tracer_impactfx_color_b = "0", particlecontrol_tracer_impactfx_color_enabled = "0", particlecontrol_tracer_impactfx_color_g = "20", particlecontrol_tracer_impactfx_color_outofone = "0", particlecontrol_tracer_impactfx_color_r = "255", particlecontrol_tracer_impactfx_effectname = "!UTILEFFECT!selection_indicator", particlecontrol_tracer_impactfx_enabled = "1", particlecontrol_tracer_impactfx_utileffect_magnitude = "1", particlecontrol_tracer_impactfx_utileffect_radius = "10", particlecontrol_tracer_impactfx_utileffect_scale = "1", particlecontrol_tracer_leavebulletholes = "0", particlecontrol_tracer_numpadkey = "52",
particlecontrol_tracer_propangle = "2", particlecontrol_tracer_propinvis = "0", particlecontrol_tracer_propmodel = "models/weapons/w_smg1.mdl", particlecontrol_tracer_repeatrate = "1", particlecontrol_tracer_starton = "1", particlecontrol_tracer_toggle = "1", particlecontrol_tracer_tracercount = "1", particlecontrol_tracer_tracerspread = "0" },
},
CVars = table.GetKeys( ConVarsDefault )
} )
AddParticleBrowserTracer(panel, {
name = "Tracer Effect",
commands = {
effectname = "particlecontrol_tracer_effectname",
color = "particlecontrol_tracer_color",
},
})
//panel:AddControl( "Label", { Text = "" } )
//panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Checkbox", { Label = "Enable impact effects?", Command = "particlecontrol_tracer_impactfx_enabled" } )
AddParticleBrowser(panel, {
name = "Impact Effect",
commands = {
effectname = "particlecontrol_tracer_impactfx_effectname",
color = "particlecontrol_tracer_impactfx_color",
utileffect = "particlecontrol_tracer_impactfx_utileffect",
enabled = "particlecontrol_tracer_impactfx_enabled",
},
})
//panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl("Slider", {
Label = "Attachment",
Type = "Integer",
Min = "0",
Max = "10",
Command = "particlecontrol_attachnum", //use the standard tool's attachnum var
})
panel:ControlHelp( "Attachment point on the model to fire tracers from. Set to 0 to fire from the model origin." )
panel:AddControl("Slider", {
Label = "Repeat Rate",
Type = "Float",
Min = "0",
Max = "1",
Command = "particlecontrol_tracer_repeatrate"
})
panel:ControlHelp( "How often the tracer fires. Set to 0 to not repeat." )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl("Slider", {
Label = "Tracer Spread",
Type = "Float",
Min = "0",
Max = "1",
Command = "particlecontrol_tracer_tracerspread"
})
panel:ControlHelp( "Each unit is 90 degrees of spread - you can type in 2 for 180 degrees or even 4 for 360 degrees." )
panel:AddControl("Slider", {
Label = "Tracers per shot",
Type = "Integer",
Min = "1",
Max = "10",
Command = "particlecontrol_tracer_tracercount"
})
panel:AddControl( "Checkbox", { Label = "Leave bullet holes?", Command = "particlecontrol_tracer_leavebulletholes" } )
panel:AddControl("Slider", {
Label = "Effect Lifetime",
Type = "Float",
Min = "0.5",
Max = "5",
Command = "particlecontrol_tracer_effectlifetime"
})
//panel:ControlHelp( "Number of seconds before tracer and impact effects are removed." )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
local modellist = { Label = "Prop:", ConVar = "particlecontrol_tracer_propmodel", Category = "Prop", Height = 1, Models = {} }
modellist.Models["models/hunter/plates/plate025x025.mdl"] = {}
modellist.Models["models/hunter/plates/plate.mdl"] = {}
modellist.Models["models/weapons/w_smg1.mdl"] = {}
modellist.Models["models/weapons/w_models/w_shotgun.mdl"] = {}
panel:AddControl( "PropSelect", modellist )
panel:AddControl( "ComboBox", {
Label = "Prop Angle",
MenuButton = "0",
Options = {
["Spawn upright"] = { particlecontrol_tracer_propangle = "1" },
["Spawn at surface angle"] = { particlecontrol_tracer_propangle = "2" }
}
})
panel:AddControl( "Checkbox", { Label = "Invisible prop (particles only)", Command = "particlecontrol_tracer_propinvis" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Label", { Text = "" } )
panel:AddControl( "Numpad", {
Label = "Effect Key",
Command = "particlecontrol_tracer_numpadkey",
ButtonSize = 22
})
panel:AddControl( "Checkbox", { Label = "Toggle", Command = "particlecontrol_tracer_toggle" } )
panel:AddControl( "Checkbox", { Label = "Start on?", Command = "particlecontrol_tracer_starton" } )
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,619 @@
--[[
| 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/
--]]
-- Original idea by High6
TOOL.Category = "Half-Life 2"
TOOL.Name = "#tool.prop_door"
TOOL.ClientConVar[ "model" ] = "models/props_c17/door01_left.mdl"
TOOL.ClientConVar[ "type" ] = "1"
TOOL.ClientConVar[ "key_open" ] = "38"
TOOL.ClientConVar[ "key_close" ] = "39"
TOOL.ClientConVar[ "key_lock" ] = "40"
TOOL.ClientConVar[ "key_unlock" ] = "41"
TOOL.ClientConVar[ "auto_close" ] = "1"
TOOL.ClientConVar[ "auto_close_delay" ] = "4"
TOOL.ClientConVar[ "skin" ] = "1"
TOOL.ClientConVar[ "r_double" ] = "0"
TOOL.ClientConVar[ "r_hardware" ] = "1"
TOOL.ClientConVar[ "r_distance" ] = "90"
TOOL.ClientConVar[ "r_speed" ] = "100"
TOOL.ClientConVar[ "breakable" ] = "0"
local gDoorUniqueID = 0
cleanup.Register( "prop_doors" )
local minsZ = {}
minsZ[ "models/props/portal_door_combined.mdl" ] = -18.421800613403
minsZ[ "models/props_mining/elevator01_cagedoor.mdl" ] = 0
minsZ[ "models/props_mining/techgate01.mdl" ] = -3.0040739147807e-05
minsZ[ "models/props_combine/combine_door01.mdl" ] = -96.376152038574
minsZ[ "models/combine_gate_vehicle.mdl" ] = -30.216606140137
minsZ[ "models/combine_gate_citizen.mdl" ] = -30.00006103515
minsZ[ "models/props_lab/elevatordoor.mdl" ] = -1
--minsZ[ "models/props_doors/doorklab01.mdl" ] = -5.004433631897
function TOOL:FixDynamicPos( mdl, pos, ang, minz )
-- This is UGLY AF
if ( --[[!minz &&]] minsZ[ mdl ] ) then minz = minsZ[ mdl ] else minz = 0 end
local ent = self:GetOwner()
if ( mdl == "models/props_mining/elevator01_cagedoor.mdl" ) then
ang:RotateAroundAxis( Vector( 0, 0, 1 ), -90 )
else
pos = pos - Vector( 0, 0, minz )
end
if ( mdl == "models/props_combine/combine_door01.mdl" ) then
ang:RotateAroundAxis( Vector( 0, 0, 1 ), -90 )
end
if ( mdl == "models/props_mining/techgate01.mdl" or mdl == "models/props_mining/techgate01_outland03.mdl" ) then
ang:RotateAroundAxis( Vector( 0, 0, 1 ), -90 )
pos = pos - ent:GetRight() * 80
end
if ( mdl == "models/props/portal_door_combined.mdl" ) then
pos = pos - ent:GetUp() * 21
ang:RotateAroundAxis( Vector( 0, 0, 1 ), -180 )
end
return pos, ang
end
function TOOL:FixRotatingPos( ent )
if ( !IsValid( ent ) ) then return end
local e = ent
local min = ent:OBBMins()
local max = ent:OBBMaxs()
local pos = ent:GetPos()
local ang = ent:GetAngles()
local typ = self:GetClientNumber( "type" )
local doubl = self:GetClientNumber( "r_double" ) + 1
if ( typ == 1 or typ == 3 ) then pos = pos + ent:GetRight() * ( max.y / 2.01 ) * doubl end
if ( typ == 2 ) then pos = pos + ent:GetRight() * ( max.y / 3.1 ) * doubl end
-- L4D2 doors
if ( typ == 4 ) then pos = pos + ent:GetRight() * ( max.y / 2.34 ) * doubl end -- This really should be more dynamic!
if ( typ == 5 ) then pos = pos + ent:GetRight() * ( max.y / 2.04 ) * doubl end
if ( typ == 6 ) then pos = pos + ent:GetRight() * ( max.y / 2.21 ) * doubl end
if ( typ == 7 ) then pos = pos + ent:GetRight() * ( max.y / 2.057 ) * doubl end
if ( typ == 8 ) then pos = pos + ent:GetRight() * ( max.y / 2.07 ) * doubl end
if ( typ == 9 ) then pos = pos + ent:GetRight() * ( max.y / 2.067 ) * doubl end
if ( typ == 10 ) then pos = pos + ent:GetRight() * ( max.y / 2.081 ) * doubl end
e:SetPos( pos - Vector( 0, 0, min.z ) )
e:SetAngles( ang )
e:Activate()
end
if ( SERVER ) then
CreateConVar( "sbox_maxprop_doors", 10, FCVAR_ARCHIVE + FCVAR_REPLICATED + FCVAR_NOTIFY )
numpad.Register( "prop_door_open", function( ply, prop_door ) if ( !IsValid( prop_door ) ) then return false end prop_door:Fire( "Open" ) end )
numpad.Register( "prop_door_close", function( ply, prop_door ) if ( !IsValid( prop_door ) ) then return false end prop_door:Fire( "Close" ) end )
numpad.Register( "prop_door_lock", function( ply, prop_door ) if ( !IsValid( prop_door ) ) then return false end prop_door:Fire( "Lock" ) end )
numpad.Register( "prop_door_unlock", function( ply, prop_door ) if ( !IsValid( prop_door ) ) then return false end prop_door:Fire( "Unlock" ) end )
local function ApplyWireModSupport( door, mapCreationID )
if ( Wire_CreateOutputs and !mapCreationID ) then
--door.Outputs = Wire_CreateOutputs( door, { "OnClosed", "OnOpened", "OnLocked", "OnUnlocked" } )
door.Inputs = Wire_CreateInputs( door, { "Open", "Lock" } )
function door:TriggerInput( name, value )
if ( name == "Open" ) then self:Fire( value != 0 and "Open" or "Close" ) end
if ( name == "Lock" ) then self:Fire( value != 0 and "Lock" or "Unlock" ) end
end
rb655_hl2_CopyWireModMethods( door )
end
end
local function EnsureNameIsUnique( input )
local doors = ents.FindByName( input )
if ( #doors > 1 ) then
--ErrorNoHalt( "Map already has 2 doors with name ", input , "\n" )
-- Could probably use a while loop here...
return EnsureNameIsUnique( input .. "_2" )
end
return input
end
local function RotatingDoorPostDupe( door )
function door:PreEntityCopy()
self.rb655_door_opened = self:GetInternalVariable( "m_eDoorState" ) != 0
self.rb655_door_locked = self:GetInternalVariable( "m_bLocked" )
end
function door:OnDuplicated( table )
-- On duplicaton, if was opened, make it open
if ( table.rb655_door_opened ) then self:Fire( "Open" ) end
if ( table.rb655_door_locked ) then self:Fire( "Lock" ) end
end
end
function MakeDoorRotating( ply, model, pos, ang, _oSkin, keyOpen, keyClose, keyLock, keyUnlock, _oHardware, _oDistance, _oSpeed, _oReturnDelay, breakable, _oTargetName, data, mapCreationID )
if ( IsValid( ply ) and !ply:CheckLimit( "prop_doors" ) ) then return nil end
local prop_door_rotating = ents.Create( "prop_door_rotating" )
if ( !IsValid( prop_door_rotating ) ) then return false end
prop_door_rotating:SetModel( model )
prop_door_rotating:SetPos( pos )
if ( data and data.initialAngles ) then ang = data.initialAngles end
prop_door_rotating:SetAngles( ang )
RotatingDoorPostDupe( prop_door_rotating )
ApplyWireModSupport( prop_door_rotating, mapCreationID )
keyOpen = keyOpen or -1
keyClose = keyClose or -1
keyLock = keyLock or -1
keyUnlock = keyUnlock or -1
local targetname = _oTargetName or ""
if ( data and data.targetname ) then targetname = data.targetname end
local hardware = _oHardware or 1
if ( data and data.hardware ) then hardware = data.hardware end
local distance = _oDistance or 90
if ( data and data.distance ) then distance = data.distance end
local speed = _oSpeed or 100
if ( data and data.speed ) then speed = data.speed end
local returndelay = _oReturnDelay or 4
if ( data and data.returndelay ) then returndelay = data.returndelay end
local skin = _oSkin or 0
if ( data and data.skin ) then skin = data.skin end
local spawnflags = 8192
--if ( data and data.spawnflags ) then spawnflags = data.spawnflags end
local ajarangles
if ( data and data.ajarangles ) then ajarangles = data.ajarangles end
local axis
if ( data and data.axis ) then axis = data.axis end
local spawnpos
if ( data and data.spawnpos ) then spawnpos = data.spawnpos end
if ( targetname and targetname:len() > 0 ) then
-- We gotta make sure there are no more than 2 doors with the same name, because only 2 can be linked at a time.
targetname = EnsureNameIsUnique( targetname )
prop_door_rotating:SetKeyValue( "targetname", targetname )
end
prop_door_rotating:SetKeyValue( "hardware", hardware )
prop_door_rotating:SetKeyValue( "distance", distance )
prop_door_rotating:SetKeyValue( "speed", speed )
prop_door_rotating:SetKeyValue( "returndelay", returndelay )
prop_door_rotating:SetKeyValue( "spawnflags", spawnflags )
if ( ajarangles ) then prop_door_rotating:SetKeyValue( "ajarangles", ajarangles ) end
if ( axis ) then prop_door_rotating:SetKeyValue( "axis", axis ) end
if ( spawnpos ) then prop_door_rotating:SetKeyValue( "spawnpos", spawnpos ) end
prop_door_rotating:Spawn()
prop_door_rotating:Activate()
prop_door_rotating:SetSkin( skin )
if ( breakable ) then prop_door_rotating:Fire( "SetBreakable" ) end
numpad.OnDown( ply, keyOpen, "prop_door_open", prop_door_rotating )
numpad.OnDown( ply, keyClose, "prop_door_close", prop_door_rotating )
numpad.OnDown( ply, keyLock, "prop_door_lock", prop_door_rotating )
numpad.OnDown( ply, keyUnlock, "prop_door_unlock", prop_door_rotating )
table.Merge( prop_door_rotating:GetTable(), {
ply = ply,
keyOpen = keyOpen,
keyClose = keyClose,
keyLock = keyLock,
keyUnlock = keyUnlock,
breakable = breakable,
MapCreationID = mapCreationID,
rb655_dupe_data = {
spawnflags = spawnflags,
ajarangles = ajarangles,
skin = skin,
axis = axis,
initialAngles = ang,
spawnpos = spawnpos,
hardware = hardware,
distance = distance,
speed = speed,
returndelay = returndelay,
targetname = targetname,
--[[slavename = slavename,
state = 0,
opendir = opendir,
forceclosed = forceclosed,
soundopenoverride = soundopenoverride,
soundcloseoverride = soundcloseoverride,
soundmoveoverride = soundmoveoverride,
soundlockedoverride = soundlockedoverride,
soundunlockedoverride = soundunlockedoverride,]]
}
} )
if ( IsValid( ply ) ) then
ply:AddCount( "prop_doors", prop_door_rotating )
ply:AddCleanup( "prop_doors", prop_door_rotating )
end
DoPropSpawnedEffect( prop_door_rotating )
return prop_door_rotating
end
duplicator.RegisterEntityClass( "prop_door_rotating", MakeDoorRotating, "model", "pos", "ang", "skin", "keyOpen", "keyClose", "keyLock", "keyUnlock", "rHardware", "rDistance", "rSpeed", "auto_close_delay", "breakable", "targetname", "rb655_dupe_data", "MapCreationID" )
function MakeDoorDynamic( ply, model, pos, ang, keyOpen, keyClose, keyLock, keyUnlock, auto_close_delay, skin, mapCreationID )
if ( IsValid( ply ) and !ply:CheckLimit( "prop_doors" ) ) then return false end
local prop_door_dynamic = ents.Create( "prop_door_dynamic" )
if ( !IsValid( prop_door_dynamic ) ) then return false end
prop_door_dynamic:SetModel( model )
prop_door_dynamic:SetPos( pos )
prop_door_dynamic:SetAngles( ang )
ApplyWireModSupport( prop_door_dynamic, mapCreationID )
prop_door_dynamic:Spawn()
prop_door_dynamic:Activate()
prop_door_dynamic:SetSkin( skin or 0 )
prop_door_dynamic:SetCloseDelay( auto_close_delay )
numpad.OnDown( ply, keyOpen, "prop_door_open", prop_door_dynamic )
numpad.OnDown( ply, keyClose, "prop_door_close", prop_door_dynamic )
numpad.OnDown( ply, keyLock, "prop_door_lock", prop_door_dynamic )
numpad.OnDown( ply, keyUnlock, "prop_door_unlock", prop_door_dynamic )
table.Merge( prop_door_dynamic:GetTable(), {
ply = ply,
keyOpen = keyOpen,
keyClose = keyClose,
keyLock = keyLock,
keyUnlock = keyUnlock,
auto_close_delay = auto_close_delay,
skin = skin,
MapCreationID = mapCreationID
} )
if ( IsValid( ply ) ) then
ply:AddCount( "prop_doors", prop_door_dynamic )
ply:AddCleanup( "prop_doors", prop_door_dynamic )
end
DoPropSpawnedEffect( prop_door_dynamic )
return prop_door_dynamic
end
duplicator.RegisterEntityClass( "prop_door_dynamic", MakeDoorDynamic, "model", "pos", "ang", "keyOpen", "keyClose", "keyLock", "keyUnlock", "auto_close_delay", "skin", "MapCreationID" )
end
function TOOL:LeftClick( trace )
if ( trace.HitSky or !trace.HitPos ) then return false end
if ( IsValid( trace.Entity ) ) then return false end
if ( CLIENT ) then return true end
local ply = self:GetOwner()
local ang = Angle( 0, ply:GetAngles().y, 0 )
local auto_close_delay = self:GetClientNumber( "auto_close_delay" )
if ( self:GetClientNumber( "auto_close" ) <= 0 ) then auto_close_delay = -1 end
local mdl = self:GetClientInfo( "model" )
local kO = self:GetClientNumber( "key_open" )
local kC = self:GetClientNumber( "key_close" )
local kL = self:GetClientNumber( "key_lock" )
local kU = self:GetClientNumber( "key_unlock" )
local doorSkin = self:GetClientNumber( "skin" ) - 1
local rH = math.Clamp( self:GetClientNumber( "r_hardware" ), 1, 3 )
local rD = self:GetClientNumber( "r_distance" )
local rS = self:GetClientNumber( "r_speed" )
local breakable = self:GetClientNumber( "breakable", 0 ) > 0
local prop_door
local prop_door2
if ( self:GetClientNumber( "type" ) == 0 ) then
local pos, angD = self:FixDynamicPos( mdl, trace.HitPos, ang )
prop_door = MakeDoorDynamic( ply, mdl, pos, angD, kO, kC, kL, kU, auto_close_delay, doorSkin )
else
prop_door = MakeDoorRotating( ply, mdl, trace.HitPos, ang, doorSkin, kO, kC, kL, kU, rH, rD, rS, auto_close_delay, breakable )
self:FixRotatingPos( prop_door )
if ( self:GetClientNumber( "r_double" ) == 1 ) then
local ang2 = Angle( ang ) -- Make a copy
ang2:RotateAroundAxis( Vector( 0, 0, 1 ), 180 )
local name = "rb655_door_" .. gDoorUniqueID
gDoorUniqueID = gDoorUniqueID + 1
prop_door2 = MakeDoorRotating( ply, mdl, trace.HitPos, ang2, doorSkin, kO, kC, kL, kU, rH, rD, rS, auto_close_delay, breakable, name )
prop_door:SetKeyValue( "targetname", name )
prop_door.rb655_dupe_data.targetname = name
self:FixRotatingPos( prop_door2 )
end
end
undo.Create( "prop_door" )
undo.AddEntity( prop_door )
undo.AddEntity( prop_door2 )
undo.SetPlayer( ply )
undo.Finish()
return true
end
function TOOL:UpdateGhostEntity( ent, ply )
if ( !IsValid( ent ) or !IsValid( ply ) ) then return end
local trace = ply:GetEyeTrace()
if ( IsValid( trace.Entity ) or !trace.Hit ) then ent:SetNoDraw( true ) return end
ent:SetPos( trace.HitPos )
ent:SetAngles( Angle( 0, ply:GetAngles().y, 0 ) )
ent:SetSkin( self:GetClientNumber( "skin" ) - 1 )
ent:SetBodygroup( 1, self:GetClientNumber( "r_hardware" ) )
if ( self:GetClientNumber( "type" ) == 0 ) then
local pos, angD = self:FixDynamicPos( ent:GetModel(), ent:GetPos(), ent:GetAngles(), ent:OBBMins().z )
ent:SetPos( pos )
ent:SetAngles( angD )
else
self:FixRotatingPos( ent )
end
ent:SetNoDraw( false )
end
function TOOL:MakeGhostEntity( model, pos, angle )
util.PrecacheModel( model )
if ( SERVER and !game.SinglePlayer() ) then return end -- We do ghosting serverside in single player
if ( CLIENT and game.SinglePlayer() ) then return end -- It's done clientside in multiplayer
self:ReleaseGhostEntity() -- Release the old ghost entity
--if ( !util.IsValidProp( model ) ) then return end -- Don't allow ragdolls/effects to be ghosts
if ( CLIENT ) then self.GhostEntity = ents.CreateClientProp( model )
else self.GhostEntity = ents.Create( "prop_dynamic" ) end
if ( !IsValid( self.GhostEntity ) ) then self.GhostEntity = nil return end -- If there's too many entities we might not spawn..
self.GhostEntity:SetModel( model )
self.GhostEntity:SetPos( pos )
self.GhostEntity:SetAngles( angle )
self.GhostEntity:Spawn()
self.GhostEntity:SetSolid( SOLID_VPHYSICS )
self.GhostEntity:SetMoveType( MOVETYPE_NONE )
self.GhostEntity:SetNotSolid( true )
self.GhostEntity:SetRenderMode( RENDERMODE_TRANSALPHA )
self.GhostEntity:SetColor( Color( 255, 255, 255, 150 ) )
end
local OldMDL = GetConVarString( "prop_door_model" )
function TOOL:Think()
if ( CLIENT and OldMDL != GetConVarString( "prop_door_model" ) ) then
OldMDL = GetConVarString( "prop_door_model" )
if ( LocalPlayer():GetTool() and LocalPlayer():GetTool( "prop_door" ) ) then LocalPlayer():GetTool():UpdateControlPanel() end
end
if ( !IsValid( self.GhostEntity ) or self.GhostEntity:GetModel() != self:GetClientInfo( "model" ) ) then
self:MakeGhostEntity( self:GetClientInfo( "model" ), Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
end
self:UpdateGhostEntity( self.GhostEntity, self:GetOwner() )
end
--[[
Types
0 - Dynamic door
1 - Normal door
2 - Normal slim door
3 - Normal door but with a 3rd option for door handle
]]
list.Set( "DoorModels", "models/props_c17/door01_left.mdl", { prop_door_type = 1 } )
list.Set( "DoorModels", "models/props_c17/door02_double.mdl", { prop_door_type = 2 } )
list.Set( "DoorModels", "models/props_doors/door03_slotted_left.mdl", { prop_door_type = 1 } )
list.Set( "DoorModels", "models/props_combine/combine_door01.mdl", { prop_door_type = 0 } )
list.Set( "DoorModels", "models/combine_gate_vehicle.mdl", { prop_door_type = 0 } )
list.Set( "DoorModels", "models/combine_gate_citizen.mdl", { prop_door_type = 0 } )
list.Set( "DoorModels", "models/props_lab/elevatordoor.mdl", { prop_door_type = 0 } )
list.Set( "DoorModels", "models/props_doors/doorklab01.mdl", { prop_door_type = 0 } )
if ( IsMounted( "episodic" ) ) then list.Set( "DoorModels", "models/props_c17/door03_left.mdl", { prop_door_type = 3 } ) end
if ( IsMounted( "zps" ) ) then list.Set( "DoorModels", "models/props_corpsington/doors/swingdoor01.mdl", { prop_door_type = 1 } ) end
--if ( IsMounted( "portal" ) ) then list.Set( "DoorModels", "models/props/round_elevator_doors.mdl", { prop_door_type = 0 } ) end -- Fucked up angles & collisions
if ( IsMounted( "portal2" ) ) then
list.Set( "DoorModels", "models/props/portal_door_combined.mdl", { prop_door_type = 0 } )
end
if ( IsMounted( "left4dead2" ) or IsMounted( "left4dead" ) ) then
list.Set( "DoorModels", "models/props_doors/doormainmetal01.mdl", { prop_door_type = 7 } )
list.Set( "DoorModels", "models/props_doors/doormainmetalsmall01.mdl", { prop_door_type = 1 } )
list.Set( "DoorModels", "models/props_doors/doorfreezer01.mdl", { prop_door_type = 6 } )
list.Set( "DoorModels", "models/props_doors/doormainmetalwindow01.mdl", { prop_door_type = 10 } )
list.Set( "DoorModels", "models/props_doors/doormainmetalwindowsmall01.mdl", { prop_door_type = 1 } )
list.Set( "DoorModels", "models/props_doors/doormain01.mdl", { prop_door_type = 1 } )
list.Set( "DoorModels", "models/props_doors/doormain01_airport.mdl", { prop_door_type = 7 } )
list.Set( "DoorModels", "models/props_doors/doormain01_airport_small.mdl", { prop_door_type = 8 } )
list.Set( "DoorModels", "models/props_doors/doormain01_small.mdl", { prop_door_type = 9 } )
end
if ( IsMounted( "left4dead2" ) ) then
list.Set( "DoorModels", "models/props_downtown/door_interior_128_01.mdl", { prop_door_type = 1 } )
list.Set( "DoorModels", "models/props_downtown/metal_door_112.mdl", { prop_door_type = 1 } )
list.Set( "DoorModels", "models/props_doors/door_rotate_112.mdl", { prop_door_type = 1 } )
list.Set( "DoorModels", "models/props_doors/door_sliding_112.mdl", { prop_door_type = 1 } )
-- Escape doors
list.Set( "DoorModels", "models/props_doors/checkpoint_door_-01.mdl", { prop_door_type = 4 } )
list.Set( "DoorModels", "models/props_doors/checkpoint_door_-02.mdl", { prop_door_type = 5 } )
list.Set( "DoorModels", "models/props_doors/checkpoint_door_01.mdl", { prop_door_type = 6 } )
list.Set( "DoorModels", "models/props_doors/checkpoint_door_02.mdl", { prop_door_type = 5 } )
-- Wood
list.Set( "DoorModels", "models/props_doors/doormain_rural01.mdl", { prop_door_type = 9 } )
list.Set( "DoorModels", "models/props_doors/doormain_rural01_small.mdl", { prop_door_type = 9 } )
end
if ( IsMounted( "left4dead2" ) or IsMounted( "csgo" ) ) then
list.Set( "DoorModels", "models/props_downtown/door_interior_112_01.mdl", { prop_door_type = 1 } )
list.Set( "DoorModels", "models/props_downtown/metal_door_112.mdl", { prop_door_type = 1 } )
end
if ( IsMounted( "left4dead2" ) or IsMounted( "left4dead" ) or IsMounted( "csgo" ) ) then
list.Set( "DoorModels", "models/props_doors/doorglassmain01.mdl", { prop_door_type = 10 } )
list.Set( "DoorModels", "models/props_doors/doorglassmain01_small.mdl", { prop_door_type = 10 } )
end
if ( IsMounted( "ep2" ) ) then
list.Set( "DoorModels", "models/props_mining/elevator01_cagedoor.mdl", { prop_door_type = 0 } )
list.Set( "DoorModels", "models/props_mining/techgate01.mdl", { prop_door_type = 0 } )
-- list.Set( "DoorModels", "models/props_mining/techgate01_outland03.mdl", { prop_door_type = 0 } )
-- list.Set( "DoorModels", "models/props_silo/silo_elevator_door.mdl", { prop_door_type = 0 } ) -- No collisions
end
if ( SERVER ) then return end
TOOL.Information = { { name = "left" } }
language.Add( "tool.prop_door", "Doors" )
language.Add( "tool.prop_door.name", "Door Tool" )
language.Add( "tool.prop_door.desc", "Spawn a variety of doors" )
language.Add( "tool.prop_door.left", "Spawn a door" )
language.Add( "tool.prop_door.model", "Door Model:" )
language.Add( "tool.prop_door.key_open", "Open door" )
language.Add( "tool.prop_door.key_close", "Close door" )
language.Add( "tool.prop_door.key_lock", "Lock door" )
language.Add( "tool.prop_door.key_unlock", "Unlock door" )
language.Add( "tool.prop_door.auto_close", "Auto close" )
language.Add( "tool.prop_door.auto_close_delay", "Auto close delay:" )
language.Add( "tool.prop_door.skin", "Door skin:" )
language.Add( "tool.prop_door.specific", "Door specific options" )
language.Add( "tool.prop_door.r_double", "Make double doors" )
language.Add( "tool.prop_door.breakable", "Make breakable (if model supports it)" )
language.Add( "tool.prop_door.r_hardware", "Hardware Type" )
language.Add( "tool.prop_door.r_distance", "Rotation distance:" )
language.Add( "tool.prop_door.r_speed", "Open speed:" )
language.Add( "tool.prop_door.lever", "Lever" )
language.Add( "tool.prop_door.pushbar", "Push Bar" )
language.Add( "tool.prop_door.keypad", "Lever with Keypad" )
language.Add( "Cleanup_prop_doors", "Doors" )
language.Add( "Cleaned_prop_doors", "Cleaned up all Doors" )
language.Add( "SBoxLimit_prop_doors", "You've hit the Door limit!" )
language.Add( "Undone_prop_door", "Door undone" )
language.Add( "max_prop_doors", "Max Doors:" )
function TOOL:UpdateControlPanel( index )
local panel = controlpanel.Get( "prop_door" )
if ( !panel ) then Msg( "Couldn't find prop_door panel!" ) return end
panel:ClearControls()
self.BuildCPanel( panel )
end
local ConVarsDefault = TOOL:BuildConVarList()
function TOOL.BuildCPanel( panel )
panel:AddControl( "ComboBox", { MenuButton = 1, Folder = "prop_door", Options = { [ "#preset.default" ] = ConVarsDefault }, CVars = table.GetKeys( ConVarsDefault ) } )
panel:AddControl( "PropSelect", { Label = "#tool.prop_door.model", Height = 3, ConVar = "prop_door_model", Models = list.Get( "DoorModels" ) } )
panel:AddControl( "Numpad", { Label = "#tool.prop_door.key_open", Label2 = "#tool.prop_door.key_close", Command = "prop_door_key_open", Command2 = "prop_door_key_close" } )
panel:AddControl( "Numpad", { Label = "#tool.prop_door.key_lock", Label2 = "#tool.prop_door.key_unlock", Command = "prop_door_key_lock", Command2 = "prop_door_key_unlock" } )
panel:AddControl( "Checkbox", { Label = "#tool.prop_door.auto_close", Command = "prop_door_auto_close" } )
panel:AddControl( "Slider", { Label = "#tool.prop_door.auto_close_delay", Type = "Float", Min = 0, Max = 32, Command = "prop_door_auto_close_delay" } )
local typ = GetConVarNumber( "prop_door_type" )
local numSkins = NumModelSkins( GetConVarString( "prop_door_model" ) )
if ( typ == 0 and numSkins <= 1 ) then return end
panel:Help( "#tool.prop_door.specific" )
if ( numSkins > 1 ) then
panel:AddControl( "Slider", { Label = "#tool.prop_door.skin", Min = 1, Max = numSkins, Command = "prop_door_skin" } )
end
if ( typ == 0 ) then return end
panel:AddControl( "Checkbox", { Label = "#tool.prop_door.r_double", Command = "prop_door_r_double" } )
panel:AddControl( "Checkbox", { Label = "#tool.prop_door.breakable", Command = "prop_door_breakable" } )
local r_hard = GetConVarNumber( "prop_door_r_hardware" )
if ( ( typ != 3 and r_hard == 3 ) or ( typ == 2 and r_hard != 1 ) ) then LocalPlayer():ConCommand( "prop_door_r_hardware 1" ) end
local r_hardware = {
["#tool.prop_door.lever"] = { prop_door_r_hardware = "1" },
["#tool.prop_door.pushbar"] = { prop_door_r_hardware = "2" }
}
if ( typ == 3 ) then r_hardware["#tool.prop_door.keypad"] = { prop_door_r_hardware = "3" } end
if ( typ != 2 ) then
panel:AddControl( "ListBox", { Label = "#tool.prop_door.r_hardware", Height = 68, Options = r_hardware } )
end
panel:AddControl( "Slider", { Label = "#tool.prop_door.r_distance", Type = "Float", Min = 72, Max = 128, Command = "prop_door_r_distance" } )
panel:AddControl( "Slider", { Label = "#tool.prop_door.r_speed", Type = "Float", Min = 48, Max = 256, Command = "prop_door_r_speed" } )
end

View File

@@ -0,0 +1,196 @@
--[[
| 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 = "Half-Life 2"
TOOL.Name = "#tool.prop_thumper"
TOOL.ClientConVar["model" ] = "models/props_combine/CombineThumper002.mdl"
TOOL.ClientConVar[ "dustscale" ] = "128"
TOOL.ClientConVar[ "activate" ] = "38"
TOOL.ClientConVar[ "deactivate" ] = "39"
cleanup.Register( "prop_thumpers" )
if ( SERVER ) then
CreateConVar( "sbox_maxprop_thumpers", 10, FCVAR_ARCHIVE + FCVAR_REPLICATED + FCVAR_NOTIFY )
numpad.Register( "prop_thumper_on", function( ply, prop_thumper )
if ( !IsValid( prop_thumper ) ) then return false end
prop_thumper:Fire( "Enable" )
end )
numpad.Register( "prop_thumper_off", function( ply, prop_thumper )
if ( !IsValid( prop_thumper ) ) then return false end
prop_thumper:Fire( "Disable" )
end )
function MakeThumper( ply, model, pos, ang, keyOn, keyOff, dustscale, targetname, mapCreationID )
if ( IsValid( ply ) and !ply:CheckLimit( "prop_thumpers" ) ) then return nil end
local prop_thumper = ents.Create( "prop_thumper" )
if ( !IsValid( prop_thumper ) ) then return false end
prop_thumper:SetPos( pos )
prop_thumper:SetAngles( ang )
keyOn = keyOn or -1
keyOff = keyOff or -1
dustscale = tonumber( dustscale ) or 128
if ( model == "models/props_combine/combinethumper001a.mdl" ) then
local vec1 = Vector( -64, 72, 256 )
vec1:Rotate( ang )
local Lpos = pos + vec1
local ladder = ents.Create("func_useableladder")
ladder:SetPos( Lpos )
ladder:SetAngles( ang )
ladder:SetKeyValue( "targetname", "rb655_ThumperLadder_" .. prop_thumper:EntIndex() )
ladder:SetKeyValue( "point0", Lpos.x .. " " .. Lpos.y .. " " .. Lpos.z )
ladder:SetKeyValue( "point1", Lpos.x .. " " .. Lpos.y .. " " .. ( Lpos.z - 252 ) )
ladder:Spawn()
prop_thumper:DeleteOnRemove( ladder )
ladder:DeleteOnRemove( prop_thumper )
end
if ( targetname ) then prop_thumper:SetKeyValue( "targetname", targetname ) end
if ( dustscale ) then prop_thumper:SetKeyValue( "dustscale", math.Clamp( dustscale, 64, 1024 ) ) end
prop_thumper:SetModel( model )
prop_thumper:Spawn()
prop_thumper:Activate()
prop_thumper.NumpadOn = numpad.OnDown( ply, keyOn, "prop_thumper_on", prop_thumper )
prop_thumper.NumpadOff = numpad.OnDown( ply, keyOff, "prop_thumper_off", prop_thumper )
table.Merge( prop_thumper:GetTable(), {
ply = ply,
keyOn = keyOn,
keyOff = keyOff,
dustscale = dustscale,
targetname = targetname,
MapCreationID = mapCreationID
} )
if ( IsValid( ply ) ) then
ply:AddCount( "prop_thumpers", prop_thumper )
ply:AddCleanup( "prop_thumpers", prop_thumper )
end
DoPropSpawnedEffect( prop_thumper )
if ( Wire_CreateOutputs and !mapCreationID ) then
prop_thumper.Inputs = Wire_CreateInputs( prop_thumper, { "Turn On" } )
function prop_thumper:TriggerInput( name, value )
if ( name == "Turn On" ) then self:Fire( value != 0 and "Enable" or "Disable" ) end
end
rb655_hl2_CopyWireModMethods( prop_thumper )
end
return prop_thumper
end
duplicator.RegisterEntityClass( "prop_thumper", MakeThumper, "model", "pos", "ang", "keyOn", "keyOff", "dustscale", "targetname", "MapCreationID" )
end
function TOOL:LeftClick( trace )
if ( trace.HitSky or !trace.HitPos or trace.HitNormal.z < 0.98 ) then return false end
if ( IsValid( trace.Entity ) and ( trace.Entity:GetClass() == "prop_thumper" or trace.Entity:IsPlayer() or trace.Entity:IsNPC() ) ) then return false end
if ( CLIENT ) then return true end
local ply = self:GetOwner()
local ang = trace.HitNormal:Angle()
ang.pitch = ang.pitch - 270
if ( trace.HitNormal.z > 0.9999 ) then ang.y = ply:GetAngles().y + 90 end
local prop_thumper = MakeThumper( ply, self:GetClientInfo( "model" ),
trace.HitPos, ang,
self:GetClientNumber( "activate" ),
self:GetClientNumber( "deactivate" ),
self:GetClientNumber( "dustscale" ),
self:GetClientNumber( "distance" )
)
undo.Create( "prop_thumper" )
undo.AddEntity( prop_thumper )
undo.SetPlayer( ply )
undo.Finish()
return true
end
function TOOL:UpdateGhostEntity( ent, ply )
if ( !IsValid( ent ) ) then return end
local trace = ply:GetEyeTrace()
if ( !trace.Hit or trace.HitNormal.z < 0.98 or IsValid( trace.Entity ) and ( trace.Entity:GetClass() == "prop_thumper" or trace.Entity:IsPlayer() or trace.Entity:IsNPC() ) ) then
ent:SetNoDraw( true )
return
end
local ang = trace.HitNormal:Angle()
ang.pitch = ang.pitch - 270
if ( trace.HitNormal.z > 0.9999 ) then ang.y = ply:GetAngles().y + 90 end
local min = ent:OBBMins()
ent:SetPos( trace.HitPos - trace.HitNormal * min.z )
ent:SetAngles( ang )
ent:SetNoDraw( false )
end
function TOOL:Think()
if ( !IsValid( self.GhostEntity ) or self.GhostEntity:GetModel() != self:GetClientInfo( "model" ) ) then
self:MakeGhostEntity( self:GetClientInfo( "model" ), Vector( 0, 0, 0 ), Angle( 0, 0, 0 ) )
end
self:UpdateGhostEntity( self.GhostEntity, self:GetOwner() )
end
list.Set( "ThumperModels", "models/props_combine/CombineThumper001a.mdl", {} )
list.Set( "ThumperModels", "models/props_combine/CombineThumper002.mdl", {} )
if ( SERVER ) then return end
TOOL.Information = { { name = "left" } }
language.Add( "tool.prop_thumper", "Thumpers" )
language.Add( "tool.prop_thumper.name", "Thumper Tool" )
language.Add( "tool.prop_thumper.desc", "Spawn thumpers from Half-Life 2" )
language.Add( "tool.prop_thumper.left", "Spawn a thumper" )
language.Add( "tool.prop_thumper.model", "Thumper Model:" )
language.Add( "tool.prop_thumper.dustscale", "Thumper dust size:" )
language.Add( "tool.prop_thumper.dustscale.help", "The scale of dust produced when thumper hits ground." )
language.Add( "tool.prop_thumper.activate", "Activate Thumper" )
language.Add( "tool.prop_thumper.deactivate", "Deactivate Thumper" )
language.Add( "Cleanup_prop_thumpers", "Thumpers" )
language.Add( "Cleaned_prop_thumpers", "Cleaned up all Thumpers" )
language.Add( "SBoxLimit_prop_thumpers", "You've hit the Thumper limit!" )
language.Add( "Undone_prop_thumper", "Thumper undone" )
language.Add( "max_prop_thumpers", "Max Thumpers:" )
local ConVarsDefault = TOOL:BuildConVarList()
function TOOL.BuildCPanel( panel )
panel:AddControl( "ComboBox", { MenuButton = 1, Folder = "prop_thumper", Options = { [ "#preset.default" ] = ConVarsDefault }, CVars = table.GetKeys( ConVarsDefault ) } )
panel:AddControl( "PropSelect", { Label = "#tool.prop_thumper.model", Height = 1, ConVar = "prop_thumper_model", Models = list.Get( "ThumperModels" ) } )
panel:AddControl( "Numpad", { Label = "#tool.prop_thumper.activate", Label2 = "#tool.prop_thumper.deactivate", Command = "prop_thumper_activate", Command2 = "prop_thumper_deactivate" } )
panel:AddControl( "Slider", { Label = "#tool.prop_thumper.dustscale", Min = 64, Max = 1024, Command = "prop_thumper_dustscale", Help = true } )
end

View File

@@ -0,0 +1,480 @@
--[[
| 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 = "Robotboy655"
TOOL.Name = "#tool.rb655_easy_animation.name"
TOOL.AnimationArray = {}
TOOL.ClientConVar[ "anim" ] = ""
TOOL.ClientConVar[ "speed" ] = "1.0"
TOOL.ClientConVar[ "delay" ] = "0"
TOOL.ClientConVar[ "nohide" ] = "0"
TOOL.ClientConVar[ "loop" ] = "0"
TOOL.ClientConVar[ "noglow" ] = "0"
TOOL.ServerConVar[ "nobbox_sv" ] = "0"
CreateConVar( "rb655_easy_animation_nobbox_sv", "0", FCVAR_ARCHIVE )
local function MakeNiceName( str )
local newname = {}
for _, s in pairs( string.Explode( "_", string.Replace( str, " ", "_" ) ) ) do
if ( string.len( s ) == 0 ) then continue end
if ( string.len( s ) == 1 ) then table.insert( newname, string.upper( s ) ) continue end
table.insert( newname, string.upper( string.Left( s, 1 ) ) .. string.Right( s, string.len( s ) - 1 ) ) -- Ugly way to capitalize first letters.
end
return table.concat( newname, " " )
end
local function IsEntValid( ent )
if ( !IsValid( ent ) or ent:IsWorld() ) then return false end
if ( table.Count( ent:GetSequenceList() or {} ) != 0 ) then return true end
return false
end
local function PlayAnimationBase( ent, anim, speed )
if ( !IsValid( ent ) ) then return end
-- HACK: This is not perfect, but it will have to do
if ( ent:GetClass() == "prop_dynamic" ) then
ent:Fire( "SetAnimation", anim )
ent:Fire( "SetPlaybackRate", math.Clamp( tonumber( speed ), 0.05, 3.05 ) )
return
end
ent:ResetSequence( ent:LookupSequence( anim ) )
ent:ResetSequenceInfo()
ent:SetCycle( 0 )
ent:SetPlaybackRate( math.Clamp( tonumber( speed ), 0.05, 3.05 ) )
end
local UniqueID = 0
function PlayAnimation( ply, ent, anim, speed, delay, loop, isPreview )
if ( !IsValid( ent ) ) then return end
delay = tonumber( delay ) or 0
loop = tobool( loop ) or false
UniqueID = UniqueID + 1
local tid = "rb655_animation_loop_" .. ply:UniqueID() .. "-" .. UniqueID
if ( isPreview ) then tid = "rb655_animation_loop_preview" .. ply:UniqueID() end
timer.Create( tid, delay, 1, function()
PlayAnimationBase( ent, anim, speed )
if ( loop == true and IsValid( ent ) ) then
timer.Adjust( tid, ent:SequenceDuration() / speed, 0, function()
if ( !IsValid( ent ) ) then timer.Remove( tid ) return end
PlayAnimationBase( ent, anim, speed )
end )
end
end )
end
function TOOL:GetSelectedEntity()
return self:GetWeapon():GetNWEntity( 1 )
end
function TOOL:SetSelectedEntity( ent )
if ( IsValid( ent ) and ent:GetClass() == "prop_effect" ) then ent = ent.AttachedEntity end
if ( !IsValid( ent ) ) then ent = NULL end
if ( self:GetSelectedEntity() == ent ) then return end
self:GetWeapon():SetNWEntity( 1, ent )
end
local gOldCVar1 = GetConVarNumber( "ai_disabled" )
local gOldCVar2 = GetConVarNumber( "rb655_easy_animation_nohide" )
local gLastSelectedEntity = NULL
function TOOL:Think()
local ent = self:GetSelectedEntity()
if ( !IsValid( ent ) ) then self:SetSelectedEntity( NULL ) end
if ( CLIENT ) then
if ( gOldCVar1 != GetConVarNumber( "ai_disabled" ) or gOldCVar2 != GetConVarNumber( "rb655_easy_animation_nohide" ) ) then
gOldCVar1 = GetConVarNumber( "ai_disabled" )
gOldCVar2 = GetConVarNumber( "rb655_easy_animation_nohide" )
if ( IsEntValid( ent ) and ent:IsNPC() ) then self:UpdateControlPanel() end
end
if ( ent:EntIndex() == gLastSelectedEntity ) then return end
gLastSelectedEntity = ent:EntIndex()
self:UpdateControlPanel()
RunConsoleCommand( "rb655_easy_animation_anim", "" )
end
end
function TOOL:RightClick( trace )
if ( SERVER ) then self:SetSelectedEntity( trace.Entity ) end
return true
end
function TOOL:Reload( trace )
if ( SERVER ) then
if ( #self.AnimationArray <= 0 and IsValid( self:GetSelectedEntity() ) ) then
self:GetSelectedEntity():SetPlaybackRate( 0 )
elseif ( #self.AnimationArray > 0 ) then
for id, t in pairs( self.AnimationArray ) do
if ( IsValid( t.ent ) ) then t.ent:SetPlaybackRate( 0 ) end
end
end
-- Destroy all timers.
for i = 0, UniqueID do timer.Remove( "rb655_animation_loop_" .. self:GetOwner():UniqueID() .. "-" .. i ) UniqueID = 0 end
timer.Remove( "rb655_animation_loop_preview" .. self:GetOwner():UniqueID() )
end
return true
end
if ( SERVER ) then
util.AddNetworkString( "rb655_easy_animation_array" )
function TOOL:LeftClick( trace )
local ent = self:GetSelectedEntity()
local anim = self:GetClientInfo( "anim" )
for i = 0, UniqueID do timer.Remove( "rb655_animation_loop_" .. self:GetOwner():UniqueID() .. "-" .. i ) UniqueID = 0 end
timer.Remove( "rb655_animation_loop_preview" .. self:GetOwner():UniqueID() )
if ( #self.AnimationArray > 0 ) then
for id, t in pairs( self.AnimationArray ) do
if ( !IsEntValid( t.ent ) or string.len( string.Trim( t.anim ) ) == 0 ) then continue end
PlayAnimation( self:GetOwner(), t.ent, t.anim, t.speed, t.delay, t.loop )
end
else
if ( !IsEntValid( ent ) or string.len( string.Trim( anim ) ) == 0 ) then return end
PlayAnimation( self:GetOwner(), ent, anim, self:GetClientInfo( "speed" ), self:GetClientInfo( "delay" ), self:GetClientInfo( "loop" ), true )
end
return true
end
concommand.Add( "rb655_easy_animation_anim_do", function( ply, cmd, args )
local tool = ply:GetTool( "rb655_easy_animation" )
if ( !tool ) then return end
local ent = tool:GetSelectedEntity()
if ( !IsEntValid( ent ) ) then return end
for i = 0, UniqueID do timer.Remove( "rb655_animation_loop_" .. ply:UniqueID() .. "-" .. i ) UniqueID = 0 end
timer.Remove( "rb655_animation_loop_preview" .. ply:UniqueID() )
PlayAnimation( ply, ent, args[ 1 ] or "", ply:GetTool( "rb655_easy_animation" ):GetClientInfo( "speed" ), 0, ply:GetTool():GetClientInfo( "loop" ), true )
end )
concommand.Add( "rb655_easy_animation_set_pp", function( ply, cmd, args )
local tool = ply:GetTool( "rb655_easy_animation" )
if ( !tool ) then return end
local ent = tool:GetSelectedEntity()
if ( !IsEntValid( ent ) ) then return end
local pp_name = ent:GetPoseParameterName( math.floor( tonumber( args[ 1 ] ) ) )
if ( !pp_name ) then return end
ent:SetPoseParameter( pp_name, tonumber( args[ 2 ] ) )
end )
concommand.Add( "rb655_easy_animation_add", function( ply, cmd, args )
local tool = ply:GetTool( "rb655_easy_animation" )
if ( !tool ) then return end
local e = tool:GetSelectedEntity()
local a = tool:GetClientInfo( "anim" )
local s = tool:GetClientInfo( "speed" )
local d = tool:GetClientInfo( "delay" )
local l = tool:GetClientInfo( "loop" )
if ( !IsEntValid( e ) or string.len( string.Trim( a ) ) == 0 ) then return end
table.insert( tool.AnimationArray, {ent = e, anim = a, speed = s, delay = d, loop = l, ei = e:EntIndex()} )
net.Start( "rb655_easy_animation_array" )
net.WriteTable( tool.AnimationArray )
net.Send( ply )
end )
concommand.Add( "rb655_easy_animation_rid", function( ply, cmd, args ) -- rid is for RemoveID
local tool = ply:GetTool( "rb655_easy_animation" )
if ( !tool.AnimationArray[ tonumber( args[ 1 ] ) ] ) then return end
if ( tool.AnimationArray[ tonumber( args[ 1 ] ) ].ei != tonumber( args[ 2 ] ) and tonumber( args[ 2 ] ) != 0 ) then return end
table.remove( tool.AnimationArray, tonumber( args[ 1 ] ) )
net.Start( "rb655_easy_animation_array" )
net.WriteTable( tool.AnimationArray )
net.Send( ply )
end )
end
if ( SERVER ) then return end
TOOL.Information = {
{ name = "info", stage = 1 },
{ name = "left" },
{ name = "right" },
{ name = "reload" },
}
language.Add( "tool.rb655_easy_animation.left", "Play all animations" )
language.Add( "tool.rb655_easy_animation.right", "Select an object to play animations on" )
language.Add( "tool.rb655_easy_animation.reload", "Pause currently playing animation(s)" )
language.Add( "tool.rb655_easy_animation.name", "Easy Animation Tool" )
language.Add( "tool.rb655_easy_animation.desc", "Easy animations for everyone" )
language.Add( "tool.rb655_easy_animation.1", "Use context menu to play animations" )
language.Add( "tool.rb655_easy_animation.animations", "Animations" )
language.Add( "tool.rb655_easy_animation.add", "Add current selection" )
language.Add( "tool.rb655_easy_animation.add.help", "\nIf you want to play animations on multiple entities at one:\n1) Select entity\n2) Select animation from the list, if the entity has any.\n3) Configure sliders to your desire.\n4) Click \"Add current selection\"\n5) Do 1-4 steps as many times as you wish.\n6) Left-click\n\nYou cannot play two animations on the same entity at the same time. The last animation will cut off the first one." )
language.Add( "tool.rb655_easy_animation.speed", "Animation Speed" )
language.Add( "tool.rb655_easy_animation.speed.help", "How fast the animation will play." )
language.Add( "tool.rb655_easy_animation.delay", "Delay" )
language.Add( "tool.rb655_easy_animation.delay.help", "The time between you left-click and the animation is played." )
language.Add( "tool.rb655_easy_animation.loop", "Loop Animation" )
language.Add( "tool.rb655_easy_animation.loop.help", "Play animation again when it ends." )
language.Add( "tool.rb655_easy_animation.nohide", "Do not filter animations" )
language.Add( "tool.rb655_easy_animation.nohide.help", "Enabling this option will show you the full list of animations available for selected entity. Please note, that this list can be so long, that GMod may freeze for a few seconds. For this reason we hide a bunch of animations deemed \"useless\" by default, such as gestures and other delta animations." )
language.Add( "tool.rb655_easy_animation.poseparam.help", "The sliders above are the Pose Parameters. They affect how certain animations look, for example the direction for Team Fortress 2 run animations, etc." )
language.Add( "tool.rb655_easy_animation.poseparam.badent", "Changing Pose Parameters is only supported on Animatable props!" )
language.Add( "tool.rb655_easy_animation.ai", "NPC is selected, but NPC thinking is not disabled! Without that the NPC will reset its animations every frame." )
language.Add( "tool.rb655_easy_animation.ragdoll", "Ragdolls cannot be animated! Open context menu (Hold C) > right click on ragdoll > Make Animatable" )
language.Add( "tool.rb655_easy_animation.prop", "Props cannot be animated properly! Open context menu (Hold C) > right click on entity > Make Animatable" )
language.Add( "tool.rb655_easy_animation.badent", "This entity does not have any animations." )
language.Add( "tool.rb655_easy_animation.noent", "No entity selected." )
language.Add( "tool.rb655_easy_animation.noglow", "Don't render glow/halo around models" )
language.Add( "tool.rb655_easy_animation.noglow.help", "Don't render glow/halo around models when they are selected, and don't draw bounding boxes below animated models. Bounding boxes are a helper for when animations make the ragdolls go outside of their bounding box making them unselectable.\n" )
language.Add( "tool.rb655_easy_animation.property", "Make Animatable" )
language.Add( "tool.rb655_easy_animation.property_bodyxy", "Animate Movement Pose Parameters" )
language.Add( "tool.rb655_easy_animation.property_damageragdoll", "Ragdoll/Gib on Damage" )
language.Add( "tool.rb655_easy_animation.property_ragdoll", "Make Ragdoll" )
language.Add( "prop_animatable", "Animatable Entity" )
function TOOL:GetStage()
if ( IsValid( self:GetSelectedEntity() ) ) then return 1 end
return 0
end
net.Receive( "rb655_easy_animation_array", function( len )
local tool = LocalPlayer():GetTool( "rb655_easy_animation" )
tool.AnimationArray = net.ReadTable()
if ( CLIENT ) then tool:UpdateControlPanel() end
end )
function TOOL:UpdateControlPanel( index )
local panel = controlpanel.Get( "rb655_easy_animation" )
if ( !panel ) then MsgN( "Couldn't find rb655_easy_animation panel!" ) return end
panel:ClearControls()
self.BuildCPanel( panel, self:GetSelectedEntity() )
end
local clr_err = Color( 200, 0, 0 )
function TOOL.BuildCPanel( panel, ent )
local tool = LocalPlayer() and LocalPlayer():GetTool( "rb655_easy_animation" )
local nohide = false
if ( tool ) then
if ( !IsValid( ent ) ) then ent = tool:GetSelectedEntity() end
nohide = tool:GetClientNumber( "nohide" ) != 0
end
if ( !IsValid( ent ) ) then
panel:AddControl( "Label", { Text = "#tool.rb655_easy_animation.noent" } ):SetTextColor( clr_err )
elseif ( IsEntValid( ent ) ) then
local fine = true
if ( GetConVarNumber( "ai_disabled" ) == 0 and ent:IsNPC() ) then panel:AddControl( "Label", {Text = "#tool.rb655_easy_animation.ai"} ):SetTextColor( clr_err ) fine = false end
if ( ent:GetClass() == "prop_ragdoll" ) then panel:AddControl( "Label", { Text = "#tool.rb655_easy_animation.ragdoll" } ):SetTextColor( clr_err ) fine = false end
if ( ent:GetClass() == "prop_physics" or ent:GetClass() == "prop_physics_multiplayer" or ent:GetClass() == "prop_physics_override" ) then panel:AddControl( "Label", { Text = "#tool.rb655_easy_animation.prop" } ):SetTextColor( clr_err ) end
local t = {}
local badBegginings = { "g_", "p_", "e_", "b_", "bg_", "hg_", "tc_", "aim_", "turn", "gest_", "pose_", "pose_", "auto_", "layer_", "posture", "bodyaccent", "a_" }
local badStrings = { "gesture", "posture", "_trans_", "_rot_", "gest", "aim", "bodyflex_", "delta", "ragdoll", "spine", "arms" }
for k, v in SortedPairsByValue( ent:GetSequenceList() ) do
local isbad = false
for i, s in pairs( badStrings ) do if ( string.find( string.lower( v ), s, 1, true ) != nil ) then isbad = true break end end
if ( isbad == true and !nohide ) then continue end
for i, s in pairs( badBegginings ) do if ( s == string.Left( string.lower( v ), string.len( s ) ) ) then isbad = true break end end
if ( isbad == true and !nohide ) then continue end
language.Add( "rb655_anim_" .. v, MakeNiceName( v ) )
t[ "#rb655_anim_" .. v ] = { rb655_easy_animation_anim = v, rb655_easy_animation_anim_do = v }
end
if ( fine ) then
local filter = panel:AddControl( "TextBox", { Label = "#spawnmenu.quick_filter_tool" } )
filter:SetUpdateOnType( true )
local animList = panel:AddControl( "ListBox", { Label = "#tool.rb655_easy_animation.animations", Options = t, Height = 225 } )
-- patch the function to take into account visiblity
function animList:DataLayout()
local y = 0
for k, Line in ipairs( self.Sorted ) do
if ( !Line:IsVisible() ) then continue end
Line:SetPos( 1, y )
Line:SetSize( self:GetWide() - 2, self.m_iDataHeight )
Line:DataLayout( self )
Line:SetAltLine( k % 2 == 1 )
y = y + Line:GetTall()
end
return y
end
filter.OnValueChange = function( s, txt )
for id, pnl in pairs( animList:GetCanvas():GetChildren() ) do
if ( !pnl:GetValue( 1 ):lower():find( txt:lower(), 1, true ) ) then
pnl:SetVisible( false )
else
pnl:SetVisible( true )
end
end
animList:SetDirty( true )
animList:InvalidateLayout()
end
end
elseif ( !IsEntValid( ent ) ) then
panel:AddControl( "Label", { Text = "#tool.rb655_easy_animation.badent" } ):SetTextColor( clr_err )
end
if ( IsValid( ent ) and ent:GetClass() == "prop_animatable" ) then
for k = 0, ent:GetNumPoseParameters() - 1 do
local min, max = ent:GetPoseParameterRange( k )
local name = ent:GetPoseParameterName( k )
local ctrl = panel:NumSlider( name, nil, min, max, 2 )
ctrl:SetHeight( 11 ) -- This makes the controls all bunched up like how we want
ctrl:DockPadding( 0, -6, 0, -4 ) -- Try to make the lower part of the text visible
ctrl:SetValue( math.Remap( ent:GetPoseParameter( name ), 0, 1, min, max ) )
ctrl.OnValueChanged = function( self, value )
RunConsoleCommand( "rb655_easy_animation_set_pp", k, value )
--ent:SetPoseParameter( ent:GetPoseParameterName( k ), math.Remap( value, min, max, 0, 1 ) )
ent:SetPoseParameter( ent:GetPoseParameterName( k ), value )
end
end
if ( ent:GetNumPoseParameters() > 0 ) then
panel:ControlHelp( "#tool.rb655_easy_animation.poseparam.help" ):DockMargin( 32, 8, 32, 8 )
end
elseif ( IsValid( ent ) and ent:GetClass() != "prop_animatable" and ent:GetNumPoseParameters() > 0 ) then
local errlbl = panel:ControlHelp( "#tool.rb655_easy_animation.poseparam.badent" )
errlbl:DockMargin( 32, 8, 32, 8 )
errlbl:SetTextColor( clr_err )
end
local pnl = vgui.Create( "DPanelList" )
pnl:SetHeight( 225 )
pnl:EnableHorizontal( false )
pnl:EnableVerticalScrollbar()
pnl:SetSpacing( 2 )
pnl:SetPadding( 2 )
Derma_Hook( pnl, "Paint", "Paint", "Panel" ) -- Awesome GWEN background
if ( tool and tool.AnimationArray ) then
for i, d in pairs( tool.AnimationArray ) do
local s = vgui.Create( "RAnimEntry" )
s:SetInfo( i, d.ent, d.anim, d.speed, d.delay, d.loop )
pnl:AddItem( s )
end
end
panel:AddPanel( pnl )
panel:AddControl( "Button", { Label = "#tool.rb655_easy_animation.add", Command = "rb655_easy_animation_add" } )
panel:ControlHelp( "#tool.rb655_easy_animation.add.help" )
panel:AddControl( "Slider", { Label = "#tool.rb655_easy_animation.speed", Type = "Float", Min = 0.05, Max = 3.05, Command = "rb655_easy_animation_speed", Help = true } )
panel:AddControl( "Slider", { Label = "#tool.rb655_easy_animation.delay", Type = "Float", Min = 0, Max = 32, Command = "rb655_easy_animation_delay", Help = true } )
panel:AddControl( "Checkbox", { Label = "#tool.rb655_easy_animation.loop", Command = "rb655_easy_animation_loop", Help = true } )
panel:AddControl( "Checkbox", { Label = "#tool.rb655_easy_animation.nohide", Command = "rb655_easy_animation_nohide", Help = true } )
panel:AddControl( "Checkbox", { Label = "#tool.rb655_easy_animation.noglow", Command = "rb655_easy_animation_noglow", Help = true } )
end
function TOOL:DrawHUD()
local ent = self:GetSelectedEntity()
if ( !IsValid( ent ) or tobool( self:GetClientNumber( "noglow" ) ) ) then return end
local t = { ent }
if ( ent.GetActiveWeapon ) then table.insert( t, ent:GetActiveWeapon() ) end
halo.Add( t, HSVToColor( ( CurTime() * 3 ) % 360, math.abs( math.sin( CurTime() / 2 ) ), 1 ), 2, 2, 1 )
end
local PANEL = {}
function PANEL:Init()
self.ent = nil
self.anim = "attack01"
self.id = 0
self.eid = 0
self.speed = 1
self.delay = 0
self.loop = false
self.rem = vgui.Create( "DImageButton", self )
self.rem:SetImage( "icon16/cross.png" )
self.rem:SetSize( 16, 16 )
self.rem:SetPos( 4, 4 )
self.rem.DoClick = function()
self:RemoveFull()
end
end
function PANEL:RemoveFull()
self.rem:Remove()
self:Remove()
RunConsoleCommand( "rb655_easy_animation_rid", self.id, self.eid )
end
function PANEL:Paint( w, h )
draw.RoundedBox( 2, 0, 0, w, h, Color( 50, 50, 50, 225 ) )
if ( !self.ent or !IsValid( self.ent ) ) then self:RemoveFull() return end
surface.SetFont( "DermaDefault" )
draw.SimpleText( "#" .. self.ent:GetClass(), "DermaDefault", 24, 0, Color( 255, 255, 255, 255 ) )
draw.SimpleText( "#rb655_anim_" .. self.anim, "DermaDefault", 24, 10, Color( 255, 255, 255, 255 ) )
local tW = surface.GetTextSize( "#" .. self.ent:GetClass() )
draw.SimpleText( " #" .. self.ent:EntIndex(), "DermaDefault", 24 + tW, 0, Color( 255, 255, 255, 255 ) )
local tW2 = surface.GetTextSize( "#rb655_anim_" .. self.anim )
local t = " [ S: " .. self.speed .. ", D: " .. self.delay
if ( self.loop ) then t = t .. ", Looping" end
draw.SimpleText( t .. " ]", "DermaDefault", 24 + tW2, 10, Color( 255, 255, 255, 255 ) )
end
function PANEL:SetInfo( id, e, a, s, d, l )
self.id = id
self.eid = e:EntIndex()
self.ent = e
self.anim = a
self.speed = s
self.delay = d
self.loop = tobool( l )
end
vgui.Register( "RAnimEntry", PANEL, "Panel" )

View File

@@ -0,0 +1,208 @@
--[[
| 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 = "Robotboy655"
TOOL.Name = "#tool.rb655_easy_bodygroup.name"
local gLastSelecetedEntity = NULL
local MaxBodyGroups = 72
TOOL.ClientConVar[ "noglow" ] = "0"
TOOL.ClientConVar[ "skin" ] = "0"
for i = 0, MaxBodyGroups do TOOL.ClientConVar[ "group" .. i ] = "1" end
local function MakeNiceName( str )
local newname = {}
for _, s in pairs( string.Explode( "_", str ) ) do
if ( string.len( s ) == 1 ) then table.insert( newname, string.upper( s ) ) continue end
table.insert( newname, string.upper( string.Left( s, 1 ) ) .. string.Right( s, string.len( s ) - 1 ) ) -- Ugly way to capitalize first letters.
end
return string.Implode( " ", newname )
end
local function IsEntValid( ent )
if ( !IsValid( ent ) or ent:IsWorld() ) then return false end
if ( ( ent:SkinCount() or 0 ) > 1 ) then return true end
if ( ( ent:GetNumBodyGroups() or 0 ) > 1) then return true end
if ( ( ent:GetBodygroupCount( 0 ) or 0 ) > 1 ) then return true end
return false
end
local function SetBodygroup( _, ent, t )
ent:SetBodygroup( t.group, t.id )
end
for i = 0, MaxBodyGroups do duplicator.RegisterEntityModifier( "bodygroup" .. i, SetBodygroup ) end -- We only have this so old dupes will work
function TOOL:GetSelecetedEntity()
return self:GetWeapon():GetNWEntity( "rb655_bodygroup_entity" )
end
function TOOL:SetSelecetedEntity( ent )
if ( IsValid( ent ) && ent:GetClass() == "prop_effect" ) then ent = ent.AttachedEntity end
if ( !IsValid( ent ) ) then ent = NULL end
if ( self:GetSelecetedEntity() == ent ) then return end
self:GetWeapon():SetNWEntity( "rb655_bodygroup_entity", ent )
end
-- The whole Ready system is to make sure it have time to sync the console vars. Not the best idea, but it does work.
if ( SERVER ) then
TOOL.Ready = 0
util.AddNetworkString( "rb655_easy_bodygroup_ready" )
net.Receive( "rb655_easy_bodygroup_ready", function( len, ply )
local tool = ply:GetTool( "rb655_easy_bodygroup" )
if ( tool && net.ReadEntity() == tool:GetSelecetedEntity() ) then tool.Ready = 1 end
end )
--[[concommand.Add( "rb655_easy_bodygroup_group", function( ply, cmd, args )
local wep = ply:GetWeapon( "gmod_tool" )
if ( !IsValid( wep ) ) then return end
local tool = wep:GetToolObject( "rb655_easy_bodygroup" )
local group = tonumber( args[ 1 ] )
local value = tonumber( args[ 2 ] )
ply.BodygroupToolValues = ply.BodygroupToolValues or {}
ply.BodygroupToolValues[ group ] = value
end )]]
end
function TOOL:Think()
local ent = self:GetSelecetedEntity()
if ( !IsValid( ent ) ) then self:SetSelecetedEntity( NULL ) end
if ( CLIENT ) then
if ( ent:EntIndex() == gLastSelecetedEntity ) then return end
gLastSelecetedEntity = ent:EntIndex()
self:UpdateControlPanel()
return
end
if ( !IsEntValid( ent ) ) then return end
if ( self.Ready == 0 ) then return end
if ( self.Ready > 0 && self.Ready < 50 ) then self.Ready = self.Ready + 1 return end -- Another ugly workaround
if ( ent:SkinCount() > 1 ) then ent:SetSkin( self:GetClientNumber( "skin" ) ) end
for i = 0, ent:GetNumBodyGroups() - 1 do
if ( ent:GetBodygroupCount( i ) <= 1 ) then continue end
if ( ent:GetBodygroup( i ) == self:GetClientNumber( "group" .. i ) ) then continue end
SetBodygroup( nil, ent, { group = i, id = self:GetClientNumber( "group" .. i ) } )
-- if ( ent:GetBodygroup( i ) == self:GetOwner().BodygroupToolValues[ i ] ) then continue end
-- SetBodygroup( nil, ent, { group = i, id = self:GetOwner().BodygroupToolValues[ i ] } )
end
end
function TOOL:LeftClick( trace )
if ( SERVER && trace.Entity != self:GetSelecetedEntity() ) then
self.Ready = 0
self:SetSelecetedEntity( trace.Entity )
end
return true
end
function TOOL:RightClick( trace ) return self:LeftClick( trace ) end
function TOOL:Reload()
if ( SERVER ) then
self.Ready = 0
self:SetSelecetedEntity( self:GetOwner() )
end
return true
end
if ( SERVER ) then return end
TOOL.Information = {
{ name = "info", stage = 1 },
{ name = "left" },
{ name = "reload" },
}
language.Add( "tool.rb655_easy_bodygroup.left", "Select an object to edit" )
language.Add( "tool.rb655_easy_bodygroup.reload", "Select yourself" )
language.Add( "tool.rb655_easy_bodygroup.name", "Easy Bodygroup Tool" )
language.Add( "tool.rb655_easy_bodygroup.desc", "Eases change of bodygroups and skins" )
language.Add( "tool.rb655_easy_bodygroup.1", "Use context menu to edit bodygroups or skins" )
language.Add( "tool.rb655_easy_bodygroup.noglow", "Don't render glow/halo around models" )
language.Add( "tool.rb655_easy_bodygroup.skin", "Skin" )
language.Add( "tool.rb655_easy_bodygroup.badent", "This entity does not have any skins or bodygroups." )
language.Add( "tool.rb655_easy_bodygroup.noent", "No entity selected." )
function TOOL:GetStage()
if ( IsValid( self:GetSelecetedEntity() ) ) then return 1 end
return 0
end
function TOOL:UpdateControlPanel( index )
local panel = controlpanel.Get( "rb655_easy_bodygroup" )
if ( !panel ) then MsgN( "Couldn't find rb655_easy_bodygroup panel!" ) return end
panel:ClearControls()
self.BuildCPanel( panel, self:GetSelecetedEntity() )
end
-- We don't use the normal automatic stuff because we need to leave out the noglow convar
local ConVarsDefault = {}
ConVarsDefault[ "rb655_easy_bodygroup_skin" ] = 0
for i = 0, MaxBodyGroups do ConVarsDefault[ "rb655_easy_bodygroup_group" .. i ] = 0 end
function TOOL.BuildCPanel( panel, ent )
panel:AddControl( "Checkbox", { Label = "#tool.rb655_easy_bodygroup.noglow", Command = "rb655_easy_bodygroup_noglow" } )
if ( !IsValid( ent ) ) then panel:AddControl( "Label", { Text = "#tool.rb655_easy_bodygroup.noent" } ) return end
if ( !IsEntValid( ent ) ) then panel:AddControl( "Label", { Text = "#tool.rb655_easy_bodygroup.badent" } ) return end
panel:AddControl( "ComboBox", {
MenuButton = 1,
Folder = "rb655_ez_bg_" .. ent:GetModel():lower():Replace( "/", "_" ):StripExtension():sub( 8 ), -- Some hacky bussiness
Options = { [ "#preset.default" ] = ConVarsDefault },
CVars = table.GetKeys( ConVarsDefault )
} )
if ( ent:SkinCount() > 1 ) then
LocalPlayer():ConCommand( "rb655_easy_bodygroup_skin " .. ent:GetSkin() )
panel:AddControl( "Slider", { Label = "#tool.rb655_easy_bodygroup.skin", Max = ent:SkinCount() - 1, Command = "rb655_easy_bodygroup_skin" } )
end
for k = 0, ent:GetNumBodyGroups() - 1 do
if ( ent:GetBodygroupCount( k ) <= 1 ) then continue end
LocalPlayer():ConCommand( "rb655_easy_bodygroup_group" .. k .. " " .. ent:GetBodygroup( k ) )
panel:AddControl( "Slider", { Label = MakeNiceName( ent:GetBodygroupName( k ) ), Max = ent:GetBodygroupCount( k ) - 1, Command = "rb655_easy_bodygroup_group" .. k } )
-- LocalPlayer():ConCommand( "rb655_easy_bodygroup_group " .. k .. " " .. ent:GetBodygroup( k ) )
-- local ctrl = panel:NumSlider( MakeNiceName( ent:GetBodygroupName( k ) ), "", 0, ent:GetBodygroupCount( k ) - 1, 0 )
-- function ctrl:OnValueChanged( val ) RunConsoleCommand( "rb655_easy_bodygroup_group", k, self.Scratch:GetTextValue() ) end
end
net.Start( "rb655_easy_bodygroup_ready" )
net.WriteEntity( ent )
net.SendToServer()
end
function TOOL:DrawHUD()
local ent = self:GetSelecetedEntity()
if ( !IsValid( ent ) or tobool( self:GetClientNumber( "noglow" ) ) ) then return end
local t = { ent }
if ( ent.GetActiveWeapon ) then table.insert( t, ent:GetActiveWeapon() ) end
halo.Add( t, HSVToColor( ( CurTime() * 3 ) % 360, math.abs( math.sin( CurTime() / 2 ) ), 1 ), 2, 2, 1 )
end

View File

@@ -0,0 +1,312 @@
--[[
| 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/
--]]
/*
Perma Remove Props
Created by Malboro, July 2015
Ideas:
Remove FUCKING Maps Props
Errors:
Errors on die
*/
TOOL.Category = "Props Tool"
TOOL.Name = "RemoveProps"
TOOL.Command = nil
TOOL.ConfigName = ""
if CLIENT then
language.Add("Tool.removeprops.name", "RemoveProps")
language.Add("Tool.removeprops.desc", "Remove a props permanently")
language.Add("Tool.removeprops.0", "LeftClick: Add RightClick: OpenMenu")
end
if SERVER then
util.AddNetworkString("ContentRmvProps")
util.AddNetworkString("RmvPropsSQL")
sql.Query("CREATE TABLE IF NOT EXISTS removeprops('id' INTEGER NOT NULL, 'map' TEXT NOT NULL, 'content' TEXT NOT NULL, PRIMARY KEY('id'));")
end
if SERVER then
local function RmvPropsSQL( um, ply )
local EntIndex = net.ReadFloat()
if not ply:IsAdmin() then return end
local content = sql.Query( "SELECT * FROM removeprops;" )
if content == nil then return end
for k, v in pairs( content ) do
if game.GetMap() == v.map then
local data = util.JSONToTable(v.content)
if data.ID == EntIndex then
sql.Query("DELETE FROM removeprops WHERE id = ".. v.id ..";")
end
end
end
end
net.Receive("RmvPropsSQL", RmvPropsSQL)
end
local function RemoveProps()
if CLIENT then return end
local content = sql.Query( "SELECT * FROM removeprops;" )
if not content or content == nil then return end
for k, v in pairs( content ) do
if game.GetMap() == v.map then
local data = util.JSONToTable(v.content)
local ent = ents.GetByIndex(data.ID)
for k2, v2 in pairs(ents.FindInSphere( data.Pos, 0.2 )) do
if v2:GetModel() == data.Model and v2:GetClass() == data.Name then
v2:Remove()
end
end
/*if ent:IsValid() then
ent:Remove()
end*/
end
end
end
hook.Add("InitPostEntity", "InitializeRemoveProps", RemoveProps)
hook.Add("PostCleanupMap", "WhenCleanUpRemoveProps", RemoveProps)
timer.Simple(5, function() RemoveProps() end) -- When the hook isn't call ...
function TOOL:LeftClick(trace)
if CLIENT then return end
local ply = self:GetOwner()
local ent = trace.Entity
if not self:GetOwner():IsAdmin() then return false end
if ent:IsWorld() then ply:ChatPrint( "You can't remove the world DUDE !" ) return false end
if not ent then ply:ChatPrint( "That is not a valid entity !" ) return false end
if not ent:IsValid() then ply:ChatPrint( "That is not a valid entity !" ) return false end
if ent:IsPlayer() then ply:ChatPrint( "That is a player !" ) return false end
if ent.OnDieFunctions then ply:ChatPrint( "You can't remove this !" ) return false end
if ent.PermaProps then ply:ChatPrint( "You can't remove this !" ) return false end
local effectdata = EffectData()
effectdata:SetOrigin(ent:GetPos())
effectdata:SetMagnitude(2)
effectdata:SetScale(2)
effectdata:SetRadius(3)
util.Effect("Sparks", effectdata)
local content = {}
content.ID = ent:EntIndex()
content.Name = ent:GetClass()
content.Model = ent:GetModel()
content.Pos = ent:GetPos()
content.Angle = ent:GetAngles()
sql.Query("INSERT INTO removeprops (id, map, content) VALUES(NULL, ".. sql.SQLStr(game.GetMap()) ..", ".. sql.SQLStr(util.TableToJSON(content)) ..");")
ply:ChatPrint("You remove " .. ent:GetClass() .. " permanently in the map !")
ent:Remove()
return true
end
function TOOL:RightClick(trace)
if CLIENT then return end
local SendTable = {}
local content = sql.Query( "SELECT * FROM removeprops;" )
if content == nil then return end
for k, v in pairs( content ) do
if game.GetMap() == v.map then
local data = util.JSONToTable(v.content)
table.insert(SendTable, data)
end
end
net.Start("ContentRmvProps")
net.WriteTable(SendTable)
net.Send(self:GetOwner())
return false
end
function TOOL:Reload(trace)
if CLIENT then return end
return false
end
function TOOL.BuildCPanel(panel)
panel:AddControl("Header",{Text = "Perma Remove Props", Description = "Remove a server props for restarts\nBy Malboro"})
end
local function ContentRmvProps()
local Content = net.ReadTable()
local DermaPanel = vgui.Create( "DFrame" )
DermaPanel:SetSize( 500, 200 )
DermaPanel:SetTitle( "Removed props" )
DermaPanel:Center()
DermaPanel:MakePopup()
local DermaListView = vgui.Create("DListView", DermaPanel)
DermaListView:SetPos(25, 30)
DermaListView:SetSize(450, 125)
DermaListView:SetMultiSelect(false)
local Col1 = DermaListView:AddColumn("ID")
local Col2 = DermaListView:AddColumn("Name")
local Col3 = DermaListView:AddColumn("Model")
Col1:SetMinWidth(50)
Col1:SetMaxWidth(50)
Col2:SetMinWidth(80)
Col2:SetMaxWidth(80)
DermaListView.OnRowRightClick = function(panel, line)
local MenuButtonOptions = DermaMenu()
MenuButtonOptions:AddOption("Draw entity", function()
if not LocalPlayer().DrawRemovedEnt or not istable(LocalPlayer().DrawRemovedEnt) then LocalPlayer().DrawRemovedEnt = {} end
if LocalPlayer().DrawRemovedEnt[Content[DermaListView:GetLine(line):GetValue(1)].ID] and LocalPlayer().DrawRemovedEnt[Content[DermaListView:GetLine(line):GetValue(1)].ID]:IsValid() then return end
local ent = ents.CreateClientProp( Content[DermaListView:GetLine(line):GetValue(1)].Model )
ent:SetPos( Content[DermaListView:GetLine(line):GetValue(1)].Pos )
ent:SetAngles( Content[DermaListView:GetLine(line):GetValue(1)].Angle )
LocalPlayer().DrawRemovedEnt[Content[DermaListView:GetLine(line):GetValue(1)].ID] = ent
end )
if LocalPlayer().DrawRemovedEnt and LocalPlayer().DrawRemovedEnt[Content[DermaListView:GetLine(line):GetValue(1)].ID] != nil then
MenuButtonOptions:AddOption("Stop Drawing", function()
LocalPlayer().DrawRemovedEnt[Content[DermaListView:GetLine(line):GetValue(1)].ID]:Remove()
LocalPlayer().DrawRemovedEnt[Content[DermaListView:GetLine(line):GetValue(1)].ID] = nil
end )
end
MenuButtonOptions:AddOption("Remove", function()
net.Start("RmvPropsSQL")
net.WriteFloat(Content[DermaListView:GetLine(line):GetValue(1)].ID)
net.SendToServer()
if LocalPlayer().DrawRemovedEnt and LocalPlayer().DrawRemovedEnt[Content[DermaListView:GetLine(line):GetValue(1)].ID] != nil then
LocalPlayer().DrawRemovedEnt[Content[DermaListView:GetLine(line):GetValue(1)].ID]:Remove()
LocalPlayer().DrawRemovedEnt[Content[DermaListView:GetLine(line):GetValue(1)].ID] = nil
end
DermaListView:RemoveLine(line)
LocalPlayer():ChatPrint("Removed successfully from the database ! ( Need server restart )")
end )
MenuButtonOptions:Open()
end
for k, v in pairs(Content) do
DermaListView:AddLine(k, v.Name, v.Model)
end
end
net.Receive("ContentRmvProps", ContentRmvProps)
local function RemoverViewer()
if not LocalPlayer().DrawRemovedEnt or not istable(LocalPlayer().DrawRemovedEnt) then return end
local pos = LocalPlayer():EyePos() + LocalPlayer():EyeAngles():Forward() * 10
local ang = LocalPlayer():EyeAngles()
ang = Angle(ang.p + 90, ang.y, 0)
for k, v in pairs(LocalPlayer().DrawRemovedEnt) do
if not v or not v:IsValid() then LocalPlayer().DrawRemovedEnt[k] = nil continue end
render.ClearStencil()
render.SetStencilEnable(true)
render.SetStencilWriteMask(255)
render.SetStencilTestMask(255)
render.SetStencilReferenceValue(15)
render.SetStencilFailOperation(STENCILOPERATION_REPLACE)
render.SetStencilZFailOperation(STENCILOPERATION_REPLACE)
render.SetStencilPassOperation(STENCILOPERATION_KEEP)
render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_ALWAYS)
render.SetBlend(0)
v:DrawModel()
render.SetBlend(1)
render.SetStencilCompareFunction(STENCILCOMPARISONFUNCTION_EQUAL)
cam.Start3D2D(pos, ang, 1)
surface.SetDrawColor(255, 0, 0, 255)
surface.DrawRect(-ScrW(), -ScrH(), ScrW() * 2, ScrH() * 2)
cam.End3D2D()
v:DrawModel()
render.SetStencilEnable(false)
end
end
hook.Add("PostDrawOpaqueRenderables", "RemoverViewer", RemoverViewer)

View File

@@ -0,0 +1,108 @@
--[[
| 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 = "Poser"
TOOL.Name = "#Resizer"
TOOL.Command = nil
TOOL.ConfigName = ""
if (CLIENT) then
language.Add("Tool.resizer.name","Resizer")
language.Add("Tool.resizer.desc","Resizes props/ragdolls/NPCs")
language.Add("Tool.resizer.0","Click on an object to resize it. Right click to reset.")
CreateClientConVar( "resizer_xsize", "2", false, true )
CreateClientConVar( "resizer_ysize", "2", false, true )
CreateClientConVar( "resizer_zsize", "2", false, true )
CreateClientConVar( "resizer_xyzsize", "2", false, false )
CreateClientConVar( "resizer_allbones", "0", false, true )
local function _resizer_xyzcallback(cvar, prevValue, newValue)
RunConsoleCommand("resizer_xsize", newValue);
RunConsoleCommand("resizer_ysize", newValue);
RunConsoleCommand("resizer_zsize", newValue);
end
cvars.AddChangeCallback("resizer_xyzsize", _resizer_xyzcallback)
end --[[ if (CLIENT) then ]]--
local _resizer_double_fix = false
function TOOL:RightClick( trace )
if (trace.HitNonWorld && trace.Entity != nil && trace.Entity != 0) then
if (SERVER) then
//props | ragdolls | npcs
if (trace.Entity:GetClass() == "prop_physics" || trace.Entity:GetClass() == "prop_ragdoll" || trace.Entity:IsNPC()) then
for i=0, trace.Entity:GetBoneCount() do
trace.Entity:ManipulateBoneScale( i, Vector(1, 1, 1) )
end
end
end
return true
end
return false
end
function TOOL:LeftClick( trace )
if (trace.HitNonWorld && trace.Entity != nil && trace.Entity != 0) then
if (SERVER) then
local scale = Vector( tonumber( self:GetOwner():GetInfo("resizer_xsize")),
tonumber( self:GetOwner():GetInfo("resizer_ysize")),
tonumber( self:GetOwner():GetInfo("resizer_zsize")) )
//props
if (trace.Entity:GetClass() == "prop_physics") then
for i=0, trace.Entity:GetBoneCount() do
trace.Entity:ManipulateBoneScale( i, scale )
end
end
//ragdolls and npcs
if (trace.Entity:GetClass() == "prop_ragdoll" || trace.Entity:IsNPC()) then
if ( tonumber(self:GetOwner():GetInfo("resizer_allbones")) > 0 ) then
for i=0, trace.Entity:GetBoneCount() do
trace.Entity:ManipulateBoneScale( i, scale )
end
else
local Bone = trace.Entity:TranslatePhysBoneToBone( trace.PhysicsBone )
trace.Entity:ManipulateBoneScale( Bone, scale )
end
end
end
return true
end
return false
end
function TOOL.BuildCPanel( CPanel )
CPanel:AddControl( "Header", { Text = "Resizer", Description = "Does not resize the hitbox or shadow." } )
CPanel:AddControl( "ComboBox", {
Label = "#tool.presets",
MenuButton = 1,
Folder = "resizer",
Options = { Default = { resizer_xsize = '1', resizer_ysize='1', resizer_zsize='1', resizer_xyzsize='1'} },
CVars = { "resizer_xsize", "resizer_ysize", "resizer_zsize", "resizer_xyzsize"}
})
CPanel:AddControl( "Slider", { Label = "X size", Type = "Float", Command = "resizer_xsize", Min = "0.01", Max = "10" } )
CPanel:AddControl( "Slider", { Label = "Y size", Type = "Float", Command = "resizer_ysize", Min = "0.01", Max = "10" } )
CPanel:AddControl( "Slider", { Label = "Z size", Type = "Float", Command = "resizer_zsize", Min = "0.01", Max = "10" } )
CPanel:AddControl( "Slider", { Label = "XYZ", Type = "Float", Command = "resizer_xyzsize", Min = "0.01", Max = "10" } )
CPanel:AddControl( "Checkbox", { Label = "Resize all bones of ragdolls/NPCs at once", Command = "resizer_allbones" } )
end

View File

@@ -0,0 +1,492 @@
--[[
| 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/
--]]
--[[
Smart Weld
Created by: Stalker (STEAM_0:1:18093014) - Contact for support
Originally by Duncan Stead (Dunk) - Dont contact for support
]]
TOOL.AllowedClasses = {
prop_physics = true,
prop_physics_multiplayer = true,
prop_ragdoll = true,
prop_effect = true,
prop_vehicle = true,
prop_vehicle_jeep = true,
prop_vehicle_airboat = true,
prop_vehicle_apc = true,
prop_vehicle_crane = true,
prop_vehicle_prisoner_pod = true
}
TOOL.AllowedBaseClasses = {
base_anim = true,
base_entity = true,
base_gmodentity = true,
base_wire_entity = true, -- Wiremod
sent_sakarias_scar_base = true, -- SCars
base_rd3_entity = true -- Spacebuild
}
TOOL.Category = "Constraints"
TOOL.Name = "Weld - Smart"
TOOL.ClientConVar["selectradius"] = 100
TOOL.ClientConVar["nocollide"] = 1
TOOL.ClientConVar["freeze"] = 0
TOOL.ClientConVar["clearwelds"] = 1
TOOL.ClientConVar["strength"] = 0
TOOL.ClientConVar["world"] = 0
TOOL.ClientConVar["maxweldsperprop"]= 10 -- Only for when you weld more than 127 props at once
TOOL.ClientConVar["color_r"] = 0
TOOL.ClientConVar["color_g"] = 255
TOOL.ClientConVar["color_b"] = 0
TOOL.ClientConVar["color_a"] = 255
TOOL.SelectedProps = {}
-- These don't exist on the server in singleplayer but we need them there.
if game.SinglePlayer() then
NOTIFY_GENERIC = 0
NOTIFY_ERROR = 1
NOTIFY_UNDO = 2
NOTIFY_HINT = 3
NOTIFY_CLEANUP = 4
end
cleanup.Register("smartweld")
if CLIENT then
TOOL.Information = {
{name = "left"},
{name = "leftuse"},
{name = "right", stage = 2},
{name = "rightuse", stage = 2},
{name = "reload", stage = 2},
}
language.Add("tool.smartweld.name", "Weld - Smart")
language.Add("tool.smartweld.desc", "Automatically welds selected props")
language.Add("tool.smartweld.left", "Select or deselect a prop")
language.Add("tool.smartweld.leftuse", "Auto-Selects the props in a set radius")
language.Add("tool.smartweld.right", "Welds the selected props")
language.Add("tool.smartweld.rightuse", "Welds all the props to the one you\'re looking at")
language.Add("tool.smartweld.reload", "Clears the current selection")
language.Add("tool.smartweld.selectoutsideradius", "Auto-Select Radius:")
language.Add("tool.smartweld.selectoutsideradius.help", "The auto-select radius, anything beyond this value wont be selected.")
language.Add("tool.smartweld.maxweldsperprop", "Max welds per prop")
language.Add("tool.smartweld.maxweldsperprop.help", "The maximum welds per prop. This only works if you are welding more than 127 props at once. Higher than 10 not recommended, 15 maximum.")
language.Add("tool.smartweld.strength", "Force Limit:")
language.Add("tool.smartweld.strength.help", "The strength of the welds created. Use 0 for unbreakable welds.")
language.Add("tool.smartweld.world", "Weld everything to world")
language.Add("tool.smartweld.world.help", "Turning this on will weld everything to the world. Useful for making something totally immovable.")
language.Add("tool.smartweld.nocollide", "No-collide")
language.Add("tool.smartweld.nocollide.help", "Whether all props should no-collide each other when welded.")
language.Add("tool.smartweld.freeze", "Auto-freeze")
language.Add("tool.smartweld.freeze.help", "Whether all selected props should be frozen after the weld.")
language.Add("tool.smartweld.clearwelds", "Remove old welds")
language.Add("tool.smartweld.clearwelds.help", "If a selected prop has any welds already on it this will remove them first.")
language.Add("tool.smartweld.color", "Selection color")
language.Add("tool.smartweld.color.help", "Modify the selection color, it\'s useful for grouping.")
language.Add("Undone_smartweld", "Undone Smart-Weld")
language.Add("Cleanup_smartweld", "Smart Welds")
language.Add("Cleaned_smartweld", "Smart-Welds Cleared")
end
function TOOL.BuildCPanel(panel)
panel:SetName("Smart Weld")
panel:AddControl("Header", {
Text = "",
Description = "Automatically welds selected props."
})
-- Outside Radius
panel:AddControl("Slider", {
Label = "#tool.smartweld.selectoutsideradius",
Help = "#tool.smartweld.selectoutsideradius",
Type = "float",
Min = "0",
Max = "1000",
Command = "smartweld_selectradius"
})
-- Force Limit
panel:AddControl("Slider", {
Label = "#tool.smartweld.strength",
Help = "#tool.smartweld.strength",
Type = "float",
Min = "0",
Max = "10000",
Command = "smartweld_strength"
})
-- Max Welds Per Prop
panel:AddControl("Slider", {
Label = "#tool.smartweld.maxweldsperprop",
Help = "#tool.smartweld.maxweldsperprop",
Type = "Integer",
Min = "1",
Max = "10",
Command = "smartweld_maxweldsperprop"
})
-- Weld to each other or all to world
panel:AddControl("Checkbox", {
Label = "#tool.smartweld.world",
Help = "#tool.smartweld.world",
Command = "smartweld_world"
})
-- No-Collide Props While Welding
panel:AddControl("Checkbox", {
Label = "#tool.smartweld.nocollide",
Help = "#tool.smartweld.nocollide",
Command = "smartweld_nocollide"
})
-- Freeze Props When Welded
panel:AddControl("Checkbox", {
Label = "#tool.smartweld.freeze",
Help = "#tool.smartweld.freeze",
Command = "smartweld_freeze"
})
-- Clear Previous Welds Before Welding
panel:AddControl("Checkbox", {
Label = "#tool.smartweld.clearwelds",
Help = "#tool.smartweld.clearwelds",
Command = "smartweld_clearwelds"
})
-- Color
panel:AddControl("Color", {
Label = "#tool.smartweld.color",
Help = "#tool.smartweld.color",
Red = "smartweld_color_r",
Green = "smartweld_color_g",
Blue = "smartweld_color_b",
Alpha = "smartweld_color_a"
})
end
-- Micro Optimizations!
local ipairs = ipairs
local IsValid = IsValid
local Weld = constraint.Weld
local AddEntity = undo.AddEntity
local Cleanup = cleanup.Add
-- Clears selected props when you die or holster the tool.
function TOOL:Holster()
if CLIENT or game.SinglePlayer() then
for k, v in ipairs(self.SelectedProps) do
if IsValid(v.ent) then
v.ent:SetColor(v.col)
end
end
end
self.SelectedProps = {}
self:SetStage(1)
end
-- Pretty much deselects all
function TOOL:Reload()
if IsFirstTimePredicted() and self.SelectedProps and #self.SelectedProps > 0 then
self:Holster()
self:Notify("Prop Selection Cleared", NOTIFY_CLEANUP)
end
end
-- Does some validity checks then either selects or deselects the prop.
function TOOL:LeftClick(tr)
if IsFirstTimePredicted() and IsValid(tr.Entity) and not tr.Entity:IsPlayer() then
if SERVER and not util.IsValidPhysicsObject(tr.Entity, tr.PhysicsBone) then
return false
end
if self:GetOwner():KeyDown(IN_USE) then
return self:AutoSelect(tr.Entity)
end
return self:HandleProp(tr)
end
return false
end
-- Auto-selects props
function TOOL:AutoSelect(ent)
if not IsValid(ent) then return false end
local preAutoSelect = #self.SelectedProps
local selectRadius = self:GetClientNumber("selectradius")
local radiusProps = ents.FindInSphere(ent:GetPos(), selectRadius)
if #radiusProps < 1 then return false end
local numNearProps = 0
for i = 1, #radiusProps do
if self:IsAllowedEnt(ent) and not self:PropHasBeenSelected(radiusProps[i]) then
self:SelectProp(radiusProps[i])
numNearProps = numNearProps + 1
end
end
self:Notify(#self.SelectedProps-preAutoSelect .." prop(s) have been auto-selected.", NOTIFY_GENERIC)
end
-- Decides if we should select or deselect the specified entity.
function TOOL:HandleProp(tr)
if #self.SelectedProps == 0 then
self:SelectProp(tr.Entity, tr.PhysicsBone)
else
for k, v in ipairs(self.SelectedProps) do
if v.ent == tr.Entity then
self:DeselectProp(tr.Entity)
return true
end
end
self:SelectProp(tr.Entity, tr.PhysicsBone)
end
return true
end
-- Deselects the chosen prop.
function TOOL:DeselectProp(ent)
for k, v in ipairs(self.SelectedProps) do
if v.ent == ent then
if CLIENT or game.SinglePlayer() then
ent:SetColor(v.col)
end
table.remove(self.SelectedProps, k)
end
end
return true
end
-- Adds prop to props table and sets its color.
function TOOL:SelectProp(entity, hitBoneNum)
if self:IsAllowedEnt(entity) then
if #self.SelectedProps == 0 then
self:SetStage(2)
end
local boneNum = entity:IsRagdoll() and hitBoneNum or 0
table.insert(self.SelectedProps, {
ent = entity,
col = entity:GetColor(),
bone = boneNum
})
if CLIENT or game.SinglePlayer() then
entity:SetColor(Color(self:GetClientNumber("color_r", 0), self:GetClientNumber("color_g", 0), self:GetClientNumber("color_b", 0), self:GetClientNumber("color_a", 255)))
end
return true
end
return false
end
-- Handles the welding
function TOOL:RightClick(tr)
if #self.SelectedProps <= 1 then
self:Notify((#self.SelectedProps == 1 and "Select at least one more prop to weld." or "No props selected!"), NOTIFY_GENERIC)
return false
end
if SERVER then
undo.Create("smartweld")
self:PreWeld()
self:PerformWeld(tr)
undo.SetPlayer(self:GetOwner())
undo.Finish()
end
self:FinishWelding(tr.Entity)
return false
end
-- Does stuff that should happen before welding such as clearing old welds or freezing all the props.
function TOOL:PreWeld()
local freezeProps = self:GetClientNumber("freeze")
local removeOldWelds = self:GetClientNumber("clearwelds")
for k, v in ipairs(self.SelectedProps) do
if IsValid(v.ent) then
if removeOldWelds == 1 then
constraint.RemoveConstraints(v.ent, "Weld")
end
if freezeProps == 1 then
local physobj = v.ent:GetPhysicsObject()
if IsValid(physobj) then
physobj:EnableMotion(false)
self:GetOwner():AddFrozenPhysicsObject(v.ent, physobj)
end
end
end
end
end
-- Decides what kind of weld to perform and then does it.
function TOOL:PerformWeld(tr)
local weldToWorld = tobool(self:GetClientNumber("world"))
local nocollide = tobool(self:GetClientNumber("nocollide"))
local weldForceLimit = math.floor(self:GetClientNumber("strength"))
local ply = self:GetOwner()
if #self.SelectedProps < 2 then
return
end
if weldToWorld then
local world = game.GetWorld()
for _, v in ipairs(self.SelectedProps) do
local weld = Weld(v.ent, world, 0, 0, weldForceLimit, nocollide, false)
AddEntity(weld)
Cleanup(ply, "smartweld", weld)
end
elseif self:GetOwner():KeyDown(IN_USE) then -- Weld all to one
for _, v in ipairs(self.SelectedProps) do
local weld = Weld(v.ent, tr.Entity, v.bone, tr.PhysicsBone, weldForceLimit, nocollide, false)
AddEntity(weld)
Cleanup(ply, "smartweld", weld)
end
elseif #self.SelectedProps < 128 then
for i = 1, #self.SelectedProps do
local firstprop = self.SelectedProps[i]
for k = i+1, #self.SelectedProps do
local secondprop = self.SelectedProps[k]
if IsValid(firstprop.ent) and IsValid(secondprop.ent) then
local weld = Weld(firstprop.ent, secondprop.ent, firstprop.bone, secondprop.bone, weldForceLimit, nocollide, false)
AddEntity(weld)
Cleanup(ply, "smartweld", weld)
end
end
end
else -- There is a source engine limit with welding more than 127 props so we have to work around it by welding to the closest props.
local function AreLinked(prop_one, prop_two)
return self.SelectedProps[prop_two][prop_one] == true or self.SelectedProps[prop_one][prop_two] == true
end
local function LinkProps(id_one, prop_one, id_two)
local weld = Weld(prop_one.ent, self.SelectedProps[id_two].ent, 0, 0, weldForceLimit, nocollide, false)
AddEntity(weld)
Cleanup(ply, "smartweld", weld)
-- This kinda makes a mess in the SelectedProps table but we clear it right after this function anyways.
self.SelectedProps[id_one][id_two] = true
self.SelectedProps[id_two][id_one] = true
end
local maxweldsperprop = math.min(self:GetClientNumber("maxweldsperprop"), 15)
for i, v in ipairs(self.SelectedProps) do
self.SelectedProps[i][i] = true
for _ = 1, maxweldsperprop do
local closestdistance = math.huge
local closestprop_id = -1
for j, d in ipairs(self.SelectedProps) do
if not AreLinked(i, j) then
local distance = (v.ent:GetPos() - d.ent:GetPos()):LengthSqr()
if distance < closestdistance then
closestdistance = distance
closestprop_id = j
end
end
end
if closestprop_id ~= -1 then
LinkProps(i, v, closestprop_id)
end
end
end
end
end
function TOOL:FinishWelding(entity)
if CLIENT or game.SinglePlayer() then
local numProps = 0
for k, v in ipairs(self.SelectedProps) do
if IsValid(v.ent) then
v.ent:SetColor(v.col)
numProps = numProps + 1
end
end
if self:GetOwner():KeyDown(IN_USE) then -- If they chose to weld all to one prop this will correct the count.
if not self:PropHasBeenSelected(entity) then
numProps = numProps + 1
end
self:Notify("Weld complete! ".. numProps .." props have been welded to a single prop.", NOTIFY_GENERIC)
elseif tobool(self:GetClientNumber("world")) then
self:Notify("Weld complete! ".. numProps .." props have been welded to the world.", NOTIFY_GENERIC)
else
self:Notify("Weld complete! ".. numProps .." props have been welded to each other.", NOTIFY_GENERIC)
end
end
self.SelectedProps = {}
self:SetStage(1)
end
-- Checks if a prop has already been selected.
function TOOL:PropHasBeenSelected(ent)
for k, v in ipairs(self.SelectedProps) do
if ent == v.ent then
return true
end
end
return false
end
-- Decides if we want to weld the entity or not.
function TOOL:IsAllowedEnt(ent)
if IsValid(ent) then
local ply = SERVER and self:GetOwner() or self.Owner
local class = ent:GetClass()
local tr = ply:GetEyeTrace()
tr.Entity = ent
if (not hook.Run("CanTool", ply, tr, "smartweld")) or ((not self.AllowedBaseClasses[ent.Base]) and (not self.AllowedClasses[class])) then
return false
end
return true
end
return false
end
-- Puts one of those annoying notifications to the lower right of the screen.
function TOOL:Notify(text, notifyType)
if IsFirstTimePredicted() then
if CLIENT and IsValid(self.Owner) then
notification.AddLegacy(text, notifyType, 5)
surface.PlaySound("buttons/button15.wav")
elseif game.SinglePlayer() then
self:GetOwner():SendLua("GAMEMODE:AddNotify(\"".. text .."\", ".. tostring(notifyType) ..", 5)") -- Because singleplayer is doodoo.
self:GetOwner():SendLua("surface.PlaySound(\"buttons/button15.wav\")")
end
end
end

View File

@@ -0,0 +1,317 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
TOOL.Category = "Effects"
TOOL.Name = "Smoke"
TOOL.Command = nil
TOOL.ConfigName = ""
//Default values
TOOL.ClientConVar["color_r"] = 0
TOOL.ClientConVar["color_g"] = 0
TOOL.ClientConVar["color_b"] = 0
TOOL.ClientConVar["color_a"] = 21
TOOL.ClientConVar["material"] = "particle/smokesprites_0001.vmt"
TOOL.ClientConVar["spreadbase"] = 6
TOOL.ClientConVar["spreadspeed"] = 8
TOOL.ClientConVar["speed"] = 32
TOOL.ClientConVar["startsize"] = 32
TOOL.ClientConVar["endsize"] = 32
TOOL.ClientConVar["roll"] = 8
TOOL.ClientConVar["numparticles"] = 32
TOOL.ClientConVar["jetlength"] = 256
TOOL.ClientConVar["twist"] = 6
TOOL.ClientConVar["key"] = 5
TOOL.ClientConVar["numpadcontrol"] = 0
TOOL.ClientConVar["toggle"] = 0
//List of all spawned smoke entities
TOOL.Smokes = {}
//Add language descriptions
if (CLIENT) then
language.Add("Tool.smoke.name", "Smoke Tool")
language.Add("Tool.smoke.desc", "Creates customizable smoke")
language.Add("Tool.smoke.0", "Left-Click: Create smoke Right-Click: Remove smoke")
language.Add("Cleanup_smokes", "Smoke")
language.Add("Cleaned_smokes", "Cleaned up all Smoke")
language.Add("SBoxLimit_smokes", "You've hit the Smoke limit!")
language.Add("Undone_smoke", "Smoke undone")
end
//Sandbox-related stuff
cleanup.Register("smokes")
CreateConVar("sbox_maxsmokes", 6, FCVAR_NOTIFY)
//Create smoke
function TOOL:LeftClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return true end
//Check current spawnlimits
if (!self:GetSWEP():CheckLimit("smokes")) then return false end
//Retreive settings
local color_r = math.Round(math.Clamp(self:GetClientNumber("color_r"), 0, 255))
local color_g = math.Round(math.Clamp(self:GetClientNumber("color_g"), 0, 255))
local color_b = math.Round(math.Clamp(self:GetClientNumber("color_b"), 0, 255))
local color_a = math.Round(math.Clamp(self:GetClientNumber("color_a"), 0, 255))
local basespread = math.Clamp(self:GetClientNumber("spreadbase"), 0, 1024)
local spreadspeed = math.Round(math.Clamp(self:GetClientNumber("spreadspeed"), 0, 1024))
local speed = math.Round(math.Clamp(self:GetClientNumber("speed"), 0, 2048))
local startsize = math.Clamp(self:GetClientNumber("startsize"), 0, 512)
local endsize = math.Clamp(self:GetClientNumber("endsize"), 0, 512)
local roll = math.Clamp(self:GetClientNumber("roll"), 0, 1024)
local rate = math.Round(math.Clamp(self:GetClientNumber("numparticles"), 0, 512))
local jetlength = math.Round(math.Clamp(self:GetClientNumber("jetlength"), 0, 4096))
local twist = math.Clamp(self:GetClientNumber("twist"), 0, 1024)
//Create smoke and assign settings
local smoke = ents.Create("env_smokestack")
if !smoke || !smoke:IsValid() then return false end
smoke:SetPos(trace.HitPos)
if self:GetClientNumber("numpadcontrol") == 0 then smoke:SetKeyValue("InitialState", "1") else smoke:SetKeyValue("InitialState", "0") end
smoke:SetKeyValue("WindAngle", "0 0 0")
smoke:SetKeyValue("WindSpeed", "0")
smoke:SetKeyValue("rendercolor", "" .. tostring(color_r) .. " " .. tostring(color_g) .. " " .. tostring(color_b) .. "")
smoke:SetKeyValue("renderamt", "" .. tostring(color_a) .. "")
smoke:SetKeyValue("SmokeMaterial", self:GetClientInfo("material"))
smoke:SetKeyValue("BaseSpread", tostring(basespread))
smoke:SetKeyValue("SpreadSpeed", tostring(spreadspeed))
smoke:SetKeyValue("Speed", tostring(speed))
smoke:SetKeyValue("StartSize", tostring(startsize))
smoke:SetKeyValue("EndSize", tostring(endsize))
smoke:SetKeyValue("roll", tostring(roll))
smoke:SetKeyValue("Rate", tostring(rate))
smoke:SetKeyValue("JetLength", tostring(jetlength))
smoke:SetKeyValue("twist", tostring(twist))
//Spawn smoke
smoke:Spawn()
smoke:Activate()
if trace && trace.Entity && trace.Entity:IsValid() && trace.Entity:GetPhysicsObject():IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then smoke:SetParent(trace.Entity) end
//Add to relevant lists
self:GetOwner():AddCount("smokes", smoke)
table.insert(self.Smokes, smoke)
//Make sure we can undo
undo.Create("smoke")
undo.AddEntity(smoke)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "smokes", smoke)
//Make sure we can control it with numpad
if self:GetClientNumber("numpadcontrol") == 1 then
self:SetupNumpadControls(smoke)
end
return true
end
//Setup numpad controls
function TOOL:SetupNumpadControls(smoke)
//Safeguards
if !smoke || !smoke:IsValid() || self:GetClientInfo("key") == nil || self:GetClientInfo("key") == -1 then return false end
//If not toggled
if self:GetClientNumber("toggle") == 0 then
//Create KeyDown numpad functions
local function StartEmitSmoke(ply, smoke)
if !smoke || !smoke:IsValid() then return end
//Start smoke
smoke:Fire("TurnOn", "", 0)
end
//Register KeyDown functions
numpad.Register("StartEmitSmoke", StartEmitSmoke)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "StartEmitSmoke", smoke)
//Create KeyUp numpad functions
local function StopEmitSmoke(ply, smoke)
if !smoke || !smoke:IsValid() then return end
//Stop smoke
smoke:Fire("TurnOff", "", 0)
end
//Register KeyUp functions
numpad.Register("StopEmitSmoke", StopEmitSmoke)
numpad.OnUp(self:GetOwner(), self:GetClientNumber("key"), "StopEmitSmoke", smoke)
end
//If toggled
if self:GetClientNumber("toggle") == 1 then
smoke.Toggle = false
//Create KeyDown numpad functions
local function ToggleEmitSmoke(ply, smoke)
if !smoke || !smoke:IsValid() then return end
//Start smoke
if !smoke.Toggle then
smoke:Fire("TurnOn", "", 0)
smoke.Toggle = true
return
end
//Stop smoke
if smoke.Toggle then
smoke:Fire("TurnOff", "", 0)
smoke.Toggle = false
return
end
end
//Register KeyDown functions
numpad.Register("ToggleEmitSmoke", ToggleEmitSmoke)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "ToggleEmitSmoke", smoke)
end
return true
end
//Remove smoke in radius
function TOOL:RightClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Find smoke in radius
local findsmoke = ents.FindInSphere(trace.HitPos, 128)
for _, smoke in pairs(findsmoke) do
//Remove
if smoke && smoke:IsValid() && !smoke:GetPhysicsObject():IsValid() && smoke:GetClass() == "env_smokestack" && !smoke:IsPlayer() && !smoke:IsNPC() && !smoke:IsWorld() then
smoke:Fire("TurnOff", "", 0)
smoke:Fire("Kill", "", 6)
end
end
end
//Remove all smoke
function TOOL:Reload()
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Get all smoke
for x = 1, table.getn(self.Smokes) do
local smoke = self.Smokes[x]
//Remove
if smoke && smoke:IsValid() then
smoke:Fire("TurnOff", "", 0)
smoke:Fire("Kill", "", 6)
end
end
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
//Header
panel:AddControl( "Header", { Text = "#Tool.smoke.name", Description = "#Tool.smoke.desc" } )
//Build preset menu and declare default preset
local params = { Label = "#Presets", MenuButton = 1, Folder = "smoke", Options = {}, CVars = {} }
//Declare default preset
params.Options.default = {
smoke_color_r = 0,
smoke_color_g = 0,
smoke_color_b = 0,
smoke_color_a = 21,
smoke_material = "particle/smokesprites_0001.vmt",
smoke_spreadbase = 6,
smoke_spreadspeed = 8,
smoke_speed = 32,
smoke_startsize = 32,
smoke_endsize = 32,
smoke_roll = 8,
smoke_numparticles = 32,
smoke_jetlength = 256,
smoke_twist = 6,
}
//Declare console variables
table.insert( params.CVars, "smoke_color_r" )
table.insert( params.CVars, "smoke_color_g" )
table.insert( params.CVars, "smoke_color_b" )
table.insert( params.CVars, "smoke_color_a" )
table.insert( params.CVars, "smoke_material" )
table.insert( params.CVars, "smoke_spreadbase" )
table.insert( params.CVars, "smoke_spreadspeed" )
table.insert( params.CVars, "smoke_speed" )
table.insert( params.CVars, "smoke_startsize" )
table.insert( params.CVars, "smoke_endsize" )
table.insert( params.CVars, "smoke_roll" )
table.insert( params.CVars, "smoke_numparticles" )
table.insert( params.CVars, "smoke_jetlength" )
table.insert( params.CVars, "smoke_twist" )
//All done
panel:AddControl( "ComboBox", params )
//Color picker
panel:AddControl( "Color", { Label = "Smoke color", Red = "smoke_color_r", Green = "smoke_color_g", Blue = "smoke_color_b", Alpha = "smoke_color_a", ShowAlpha = "1", ShowHSV = "1", ShowRGB = "1", Multiplier = "255" } )
//Smoke base size
panel:AddControl( "Slider", { Label = "Smoke base size", Type = "Integer", Min = "0", Max = "64", Command ="smoke_spreadbase" } )
//Spread speed
panel:AddControl( "Slider", { Label = "Spread speed", Type = "Integer", Min = "0", Max = "32", Command ="smoke_spreadspeed" } )
//Particle speed
panel:AddControl( "Slider", { Label = "Particle speed", Type = "Integer", Min = "0", Max = "128", Command ="smoke_speed" } )
//Particle start size
panel:AddControl( "Slider", { Label = "Particle start size", Type = "Integer", Min = "0", Max = "64", Command ="smoke_startsize" } )
//Particle end size
panel:AddControl( "Slider", { Label = "Particle end size", Type = "Integer", Min = "0", Max = "64", Command ="smoke_endsize" } )
//Particle roll
panel:AddControl( "Slider", { Label = "Particle roll", Type = "Integer", Min = "0", Max = "256", Command ="smoke_roll" } )
//Number of particles
panel:AddControl( "Slider", { Label = "Number of particles", Type = "Integer", Min = "0", Max = "64", Command ="smoke_numparticles" } )
//Height
panel:AddControl( "Slider", { Label = "Height", Type = "Integer", Min = "0", Max = "512", Command ="smoke_jetlength" } )
//Twist effect
panel:AddControl( "Slider", { Label = "Twist effect", Type = "Integer", Min = "0", Max = "256", Command ="smoke_twist" } )
//Material Picker
local materials = {"particle/smokesprites_0001.vmt", "particle/particle_smokegrenade.vmt", "particle/SmokeStack.vmt"}
panel:MatSelect( "smoke_material", materials, true, 0.33, 0.33 )
//-------------
panel:AddControl( "Label", { Text = "________________________________________", Description = "" } )
//Numpad menu
panel:AddControl( "Numpad", { Label = "Start/Stop", Command = "smoke_key", ButtonSize = 22 } )
//Use numpad check
panel:AddControl( "CheckBox", { Label = "Use keyboard", Description = "", Command = "smoke_numpadcontrol" } )
//Toggle check
panel:AddControl( "CheckBox", { Label = "Toggle", Description = "", Command = "smoke_toggle" } )
end

View File

@@ -0,0 +1,218 @@
--[[
| 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 = "Effects"
TOOL.Name = "Smoke - Trail"
TOOL.Command = nil
TOOL.ConfigName = ""
//Default values
TOOL.ClientConVar["color_r"] = 132
TOOL.ClientConVar["color_g"] = 132
TOOL.ClientConVar["color_b"] = 132
TOOL.ClientConVar["color_a"] = 142
TOOL.ClientConVar["spawnradius"] = 8
TOOL.ClientConVar["lifetime"] = 3
TOOL.ClientConVar["startsize"] = 32
TOOL.ClientConVar["endsize"] = 52
TOOL.ClientConVar["minspeed"] = 4
TOOL.ClientConVar["maxspeed"] = 8
TOOL.ClientConVar["mindirectedspeed"] = 0
TOOL.ClientConVar["maxdirectedspeed"] = 0
TOOL.ClientConVar["spawnrate"] = 16
//List of all spawned smoke trail entities
TOOL.Smokes = {}
//Add language descriptions
if (CLIENT) then
language.Add("Tool.smoke_trail.name", "Smoke Trail Tool")
language.Add("Tool.smoke_trail.desc", "Creates customizable smoke trails")
language.Add("Tool.smoke_trail.0", "Left-Click: Attach smoke trail Right-Click: Remove trail")
language.Add("Cleanup_smoketrails", "Smoke Trails")
language.Add("Cleaned_smoketrail", "Cleaned up all Smoke Trails")
language.Add("SBoxLimit_smoketrails", "You've hit the Smoke Trails limit!")
language.Add("Undone_smoketrail", "Smoke Trail undone")
end
//Sandbox-related stuff
cleanup.Register("smoketrails")
CreateConVar("sbox_maxsmoketrails", 6, FCVAR_NOTIFY)
//Create smoke
function TOOL:LeftClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return true end
//Check current spawnlimits
if (!self:GetSWEP():CheckLimit("smoketrails")) then return false end
//Retreive settings
local color_r = math.Round(math.Clamp(self:GetClientNumber("color_r"), 0, 255))
local color_g = math.Round(math.Clamp(self:GetClientNumber("color_g"), 0, 255))
local color_b = math.Round(math.Clamp(self:GetClientNumber("color_b"), 0, 255))
local color_a = math.Clamp((math.Round(self:GetClientNumber("color_a")) / 255), 0, 255)
local spawnradius = math.Clamp(self:GetClientNumber("spawnradius"), 0, 128)
local lifetime = math.Clamp(self:GetClientNumber("lifetime"), 1, 16)
local startsize = math.Clamp(self:GetClientNumber("startsize"), 0, 128)
local endsize = math.Clamp(self:GetClientNumber("endsize"), 0, 128)
local minspeed = math.Clamp(self:GetClientNumber("minspeed"), 0, 128)
local maxspeed = math.Clamp(self:GetClientNumber("maxspeed"), 0, 128)
local mindirectedspeed = math.Clamp(self:GetClientNumber("mindirectedspeed"), 0, 256)
local maxdirectedspeed = math.Clamp(self:GetClientNumber("maxdirectedspeed"), 0, 256)
local spawnrate = math.Clamp(self:GetClientNumber("spawnrate"), 1, 128)
//Create smoke trail and assign settings
local smoke = ents.Create("env_smoketrail")
if !smoke || !smoke:IsValid() then return false end
smoke:SetPos(trace.HitPos)
smoke:SetKeyValue("angles", tostring(trace.HitNormal:Angle()))
smoke:SetKeyValue("emittime", "16384")
smoke:SetKeyValue("startcolor", "" .. tostring(color_r) .. " " .. tostring(color_g) .. " " .. tostring(color_b) .. "")
smoke:SetKeyValue("endcolor", "" .. tostring(color_r) .. " " .. tostring(color_g) .. " " .. tostring(color_b) .. "")
smoke:SetKeyValue("opacity", tostring(color_a))
smoke:SetKeyValue("spawnradius", tostring(spawnradius))
smoke:SetKeyValue("lifetime", tostring(lifetime))
smoke:SetKeyValue("startsize", tostring(startsize))
smoke:SetKeyValue("endsize", tostring(endsize))
smoke:SetKeyValue("minspeed", tostring(minspeed))
smoke:SetKeyValue("maxspeed", tostring(maxspeed))
smoke:SetKeyValue("mindirectedspeed", tostring(mindirectedspeed))
smoke:SetKeyValue("maxdirectedspeed", tostring(maxdirectedspeed))
smoke:SetKeyValue("spawnrate", tostring(spawnrate))
//Spawn trail
smoke:Spawn()
smoke:Activate()
if trace && trace.Entity && trace.Entity:IsValid() && trace.Entity:GetPhysicsObject():IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then smoke:SetParent(trace.Entity) end
//Add to relevant lists
self:GetOwner():AddCount("smoketrails", smoke)
table.insert(self.Smokes, smoke)
//Make sure we can undo
undo.Create("smoketrail")
undo.AddEntity(smoke)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "smoketrails", smoke)
return true
end
//Remove trails in radius
function TOOL:RightClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Find smoke in radius
local findsmoke = ents.FindInSphere(trace.HitPos, 64)
for _, smoke in pairs(findsmoke) do
//Remove
if smoke && smoke:IsValid() && !smoke:GetPhysicsObject():IsValid() && smoke:GetClass() == "env_smoketrail" && !smoke:IsPlayer() && !smoke:IsNPC() && !smoke:IsWorld() then
smoke:Fire("Kill", "", 0)
end
end
end
//Remove all smoke
function TOOL:Reload()
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Get all smoke
for x = 1, table.getn(self.Smokes) do
local smoke = self.Smokes[x]
//Remove
if smoke && smoke:IsValid() then
smoke:Fire("Kill", "", 0)
end
end
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
//Header
panel:AddControl( "Header", { Text = "#Tool.smoke_trail.name", Description = "#Tool.smoke_trail.desc" } )
//Build preset menu and declare default preset
local params = { Label = "#Presets", MenuButton = 1, Folder = "smoke_trail", Options = {}, CVars = {} }
//Declare default preset
params.Options.default = {
smoke_trail_color_r = 132,
smoke_trail_color_g = 132,
smoke_trail_color_b = 132,
smoke_trail_color_a = 142,
smoke_trail_spawnradius = 8,
smoke_trail_lifetime = 3,
smoke_trail_startsize = 32,
smoke_trail_endsize = 52,
smoke_trail_minspeed = 4,
smoke_trail_maxspeed = 8,
smoke_trail_mindirectedspeed = 0,
smoke_trail_maxdirectedspeed = 0,
smoke_trail_spawnrate = 16,
}
//Declare console variables
table.insert( params.CVars, "smoke_trail_color_r" )
table.insert( params.CVars, "smoke_trail_color_g" )
table.insert( params.CVars, "smoke_trail_color_b" )
table.insert( params.CVars, "smoke_trail_color_a" )
table.insert( params.CVars, "smoke_trail_spawnradius" )
table.insert( params.CVars, "smoke_trail_lifetime" )
table.insert( params.CVars, "smoke_trail_startsize" )
table.insert( params.CVars, "smoke_trail_endsize" )
table.insert( params.CVars, "smoke_trail_minspeed" )
table.insert( params.CVars, "smoke_trail_maxspeed" )
table.insert( params.CVars, "smoke_trail_mindirectedspeed" )
table.insert( params.CVars, "smoke_trail_maxdirectedspeed" )
table.insert( params.CVars, "smoke_trail_spawnrate" )
//All done
panel:AddControl( "ComboBox", params )
//Color picker
panel:AddControl( "Color", { Label = "Smoke color", Red = "smoke_trail_color_r", Green = "smoke_trail_color_g", Blue = "smoke_trail_color_b", Alpha = "smoke_trail_color_a", ShowAlpha = "1", ShowHSV = "1", ShowRGB = "1", Multiplier = "255" } )
//Spread base
panel:AddControl( "Slider", { Label = "Spread base", Type = "Integer", Min = "0", Max = "32", Command ="smoke_trail_spawnradius" } )
//Trail length
panel:AddControl( "Slider", { Label = "Trail length", Type = "Integer", Min = "1", Max = "8", Command ="smoke_trail_lifetime" } )
//Particle start size
panel:AddControl( "Slider", { Label = "Particle start size", Type = "Integer", Min = "0", Max = "128", Command ="smoke_trail_startsize" } )
//Particle end size
panel:AddControl( "Slider", { Label = "Particle end size", Type = "Integer", Min = "0", Max = "128", Command ="smoke_trail_endsize" } )
//Minimum particle spread
panel:AddControl( "Slider", { Label = "Minimum particle spread", Type = "Integer", Min = "0", Max = "64", Command ="smoke_trail_minspeed" } )
//Maximum particle spread
panel:AddControl( "Slider", { Label = "Maximum particle spread", Type = "Integer", Min = "0", Max = "64", Command ="smoke_trail_maxspeed" } )
//Minimum directional speed
panel:AddControl( "Slider", { Label = "Minimum directional speed", Type = "Integer", Min = "0", Max = "256", Command ="smoke_trail_mindirectedspeed" } )
//Maximum directional speed
panel:AddControl( "Slider", { Label = "Maximum directional speed", Type = "Integer", Min = "0", Max = "256", Command ="smoke_trail_maxdirectedspeed" } )
//Number of particles
panel:AddControl( "Slider", { Label = "Number of particles", Type = "Integer", Min = "1", Max = "32", Command ="smoke_trail_spawnrate" } )
end

View File

@@ -0,0 +1,261 @@
--[[
| 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 = "Effects"
TOOL.Name = "Sparks"
TOOL.Command = nil
TOOL.ConfigName = ""
//Default values
TOOL.ClientConVar["maxdelay"] = 2
TOOL.ClientConVar["magnitude"] = 2
TOOL.ClientConVar["traillength"] = 2
TOOL.ClientConVar["glow"] = 1
TOOL.ClientConVar["makesound"] = 1
TOOL.ClientConVar["key"] = 5
TOOL.ClientConVar["numpadcontrol"] = 0
TOOL.ClientConVar["toggle"] = 0
//List of all spawned spark entities
TOOL.Sparks = {}
//Add language descriptions
if (CLIENT) then
language.Add("Tool.sparks.name", "Sparks Tool")
language.Add("Tool.sparks.desc", "Creates customizable sparks")
language.Add("Tool.sparks.0", "Left-Click: Create sparks Right-Click: Remove sparks")
language.Add("Cleanup_sparks", "Sparks")
language.Add("Cleaned_sparks", "Cleaned up all Sparks")
language.Add("SBoxLimit_sparks", "You've hit the Sparks limit!")
language.Add("Undone_sparks", "Sparks undone")
end
//Sandbox-related stuff
cleanup.Register("sparks")
CreateConVar("sbox_maxsparks", 6, FCVAR_NOTIFY)
//Create sparks
function TOOL:LeftClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return true end
//Check current spawnlimits
if (!self:GetSWEP():CheckLimit("sparks")) then return false end
//Retreive settings
local spawnflags = 512 //Directional
if self:GetClientNumber("numpadcontrol") == 0 then spawnflags = spawnflags + 64 end
local maxdelay = math.Round(math.Clamp(self:GetClientNumber("maxdelay"), .12, 120)) //Integer
local magnitude = math.Round(math.Clamp(self:GetClientNumber("magnitude"), .5, 15)) //Integer
local traillength = math.Round(math.Clamp(self:GetClientNumber("traillength"), .12, 15)) //Float or Integer?
if math.Round(math.Clamp(self:GetClientNumber("glow"), 0, 1)) == 1 then spawnflags = spawnflags + 128 end
if math.Round(math.Clamp(self:GetClientNumber("makesound"), 0, 1)) == 0 then spawnflags = spawnflags + 256 end
//Create sparks and assign settings
local sparks = ents.Create("env_spark")
if !sparks || !sparks:IsValid() then return false end
sparks:SetPos(trace.HitPos)
sparks:SetKeyValue("angles", tostring(trace.HitNormal:Angle()))
sparks:SetKeyValue("MaxDelay", tostring(maxdelay))
sparks:SetKeyValue("Magnitude", tostring(magnitude))
sparks:SetKeyValue("TrailLength", tostring(traillength))
sparks:SetKeyValue("spawnflags", tostring(spawnflags))
//Spawn sparks
sparks:Spawn()
sparks:Activate()
if trace && trace.Entity && trace.Entity:IsValid() && trace.Entity:GetPhysicsObject():IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then sparks:SetParent(trace.Entity) end
//Add to relevant lists
self:GetOwner():AddCount("sparks", sparks)
table.insert(self.Sparks, sparks)
//Make sure we can undo
undo.Create("sparks")
undo.AddEntity(sparks)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "sparks", sparks)
//Make sure we can control it with numpad
if self:GetClientNumber("numpadcontrol") == 1 then
self:SetupNumpadControls(sparks)
end
return true
end
//Setup numpad controls
function TOOL:SetupNumpadControls(sparks)
//Safeguards
if !sparks || !sparks:IsValid() || self:GetClientInfo("key") == nil || self:GetClientInfo("key") == -1 then return false end
//If not toggled
if self:GetClientNumber("toggle") == 0 then
//Create KeyDown numpad functions
local function StartEmitSparks(ply, sparks)
if !sparks || !sparks:IsValid() then return end
//Start sparks
sparks:Fire("SparkOnce", "", 0)
sparks:Fire("StartSpark", "", 0)
end
//Register KeyDown functions
numpad.Register("StartEmitSparks", StartEmitSparks)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "StartEmitSparks", sparks)
//Create KeyUp numpad functions
local function StopEmitSparks(ply, sparks)
if !sparks || !sparks:IsValid() then return end
//Stop sparks
sparks:Fire("StopSpark", "", 0)
end
//Register KeyUp functions
numpad.Register("StopEmitSparks", StopEmitSparks)
numpad.OnUp(self:GetOwner(), self:GetClientNumber("key"), "StopEmitSparks", sparks)
end
//If toggled
if self:GetClientNumber("toggle") == 1 then
sparks.Toggle = false
//Create KeyDown numpad functions
local function ToggleEmitSparks(ply, sparks)
if !sparks || !sparks:IsValid() then return end
//Start sparks
if !sparks.Toggle then
sparks:Fire("StartSpark", "", 0)
sparks.Toggle = true
return
end
//Stop sparks
if sparks.Toggle then
sparks:Fire("StopSpark", "", 0)
sparks.Toggle = false
return
end
end
//Register KeyDown functions
numpad.Register("ToggleEmitSparks", ToggleEmitSparks)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "ToggleEmitSparks", sparks)
end
return true
end
//Remove sparks in radius
function TOOL:RightClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Find sparks in radius
local findsparks = ents.FindInSphere(trace.HitPos, 32)
for _, sparks in pairs(findsparks) do
//Remove
if sparks && sparks:IsValid() && !sparks:GetPhysicsObject():IsValid() && sparks:GetClass() == "env_spark" && !sparks:IsPlayer() && !sparks:IsNPC() && !sparks:IsWorld() then
sparks:Fire("SparkOnce","",0)
sparks:Fire("Kill", "", 0)
end
end
end
//Remove all sparks
function TOOL:Reload()
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Get all sparks
for x = 1, table.getn(self.Sparks) do
local sparks = self.Sparks[x]
//Remove
if sparks && sparks:IsValid() then
sparks:Fire("Kill", "", 0)
end
end
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
//Header
panel:AddControl( "Header", { Text = "#Tool.sparks.name", Description = "#Tool.sparks.desc" } )
//Build preset menu and declare default preset
local params = { Label = "#Presets", MenuButton = 1, Folder = "sparks", Options = {}, CVars = {} }
//Declare default preset
params.Options.default = {
sparks_maxdelay = 2,
sparks_magnitude = 2,
sparks_traillength = 2,
sparks_glow = 1,
sparks_makesound = 1,
}
//Declare console variables
table.insert( params.CVars, "sparks_maxdelay" )
table.insert( params.CVars, "sparks_magnitude" )
table.insert( params.CVars, "sparks_traillength" )
table.insert( params.CVars, "sparks_glow" )
table.insert( params.CVars, "sparks_makesound" )
//All done
panel:AddControl( "ComboBox", params )
//Max delay
panel:AddControl( "Slider", { Label = "Max Delay", Type = "Float", Min = "0", Max = "30", Command ="sparks_maxdelay" } )
//Magnitude
panel:AddControl( "Slider", { Label = "Magnitude", Type = "Float", Min = "0", Max = "10", Command ="sparks_magnitude" } )
//Trail length
panel:AddControl( "Slider", { Label = "Trail Length", Type = "Float", Min = "0", Max = "10", Command ="sparks_traillength" } )
//Glow
panel:AddControl( "CheckBox", { Label = "Glow", Description = "", Command = "sparks_glow" } )
//Sound
panel:AddControl( "CheckBox", { Label = "Sound", Description = "", Command = "sparks_makesound" } )
//-------------
panel:AddControl( "Label", { Text = "________________________________________", Description = "" } )
//Numpad menu
panel:AddControl( "Numpad", { Label = "Start/Stop", Command = "sparks_key", ButtonSize = 22 } )
//Use numpad check
panel:AddControl( "CheckBox", { Label = "Use keyboard", Description = "", Command = "sparks_numpadcontrol" } )
//Toggle check
panel:AddControl( "CheckBox", { Label = "Toggle", Description = "", Command = "sparks_toggle" } )
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,104 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
if !game.SinglePlayer() then TOOL.AddToMenu = false return end //Not available in Multiplayer
TOOL.Category = "Effects"
TOOL.Name = "Starfield"
TOOL.Command = nil
TOOL.ConfigName = ""
//Default values
TOOL.ClientConVar["magnitude"] = 4
//Add language descriptions
if (CLIENT) then
language.Add("Tool.starfield.name", "Starfield Tool")
language.Add("Tool.starfield.desc", "Creates a starfield effect")
language.Add("Tool.starfield.0", "Left-Click: Update starfield layer Right-Click: Remove effect")
language.Add("Cleanup_starfields", "Starfield Effects")
language.Add("Cleaned_starfields", "Cleaned up all Starfield Effects")
language.Add("Undone_starfield", "Starfield Effect undone")
end
//Sandbox-related stuff
cleanup.Register("starfields")
//Add starfield layer
function TOOL:LeftClick(trace)
//Only serverside now
if (CLIENT) then return false end
//Get all entities on the level
for _, fire in pairs(ents.GetAll()) do
//Kill all starfields
if fire && fire:IsValid() && !fire:GetPhysicsObject():IsValid() && fire:GetClass() == "env_starfield" && !fire:IsPlayer() && !fire:IsNPC() && !fire:IsWorld() then
fire:Fire("Kill", "", 0)
end
end
//Retreive settings
local magnitude = math.Clamp(self:GetClientNumber("magnitude"), 1, 128)
//Create effect layer and assign settings
local starfield = ents.Create("env_starfield")
if !starfield || !starfield:IsValid() then return false end
starfield:SetPos(self:GetOwner():GetPos())
//starfield:SetParent(self:GetOwner())
//Spawn effect
starfield:Spawn()
starfield:Activate()
starfield:Fire("SetDensity", tostring(magnitude), 0)
starfield:Fire("TurnOn", "", 0)
//Make sure we can undo
undo.Create("starfield")
undo.AddEntity(starfield)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "starfields", starfield)
return false
end
//Extinguish fire in radius
function TOOL:RightClick(trace)
//Only serverside now
if (CLIENT) then return false end
//Get all entities on the level
for _, fire in pairs(ents.GetAll()) do
//Kill all starfields
if fire && fire:IsValid() && !fire:GetPhysicsObject():IsValid() && fire:GetClass() == "env_starfield" && !fire:IsPlayer() && !fire:IsNPC() && !fire:IsWorld() then
fire:Fire("Kill", "", 0)
end
end
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
//Header
panel:AddControl( "Header", { Text = "#Tool.starfield.name", Description = "#Tool.starfield.desc" } )
//Magnitude
panel:AddControl( "Slider", { Label = "Magnitude", Type = "Integer", Min = "1", Max = "128", Command ="starfield_magnitude" } )
end

View File

@@ -0,0 +1,344 @@
--[[
| 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 = "Effects"
TOOL.Name = "Steam"
TOOL.Command = nil
TOOL.ConfigName = ""
//Default values
TOOL.ClientConVar["color_r"] = 150
TOOL.ClientConVar["color_g"] = 150
TOOL.ClientConVar["color_b"] = 150
TOOL.ClientConVar["color_a"] = 200
TOOL.ClientConVar["jetlength"] = 150
TOOL.ClientConVar["spreadspeed"] = 21
TOOL.ClientConVar["speed"] = 200
TOOL.ClientConVar["startsize"] = 16
TOOL.ClientConVar["endsize"] = 32
TOOL.ClientConVar["rate"] = 32
TOOL.ClientConVar["rollspeed"] = 12
TOOL.ClientConVar["emissive"] = 1
TOOL.ClientConVar["heatwave"] = 1
TOOL.ClientConVar["makesound"] = 1
TOOL.ClientConVar["key"] = 5
TOOL.ClientConVar["numpadcontrol"] = 0
TOOL.ClientConVar["toggle"] = 0
//List of all spawned steam entities
TOOL.Steams = {}
//Add language descriptions
if (CLIENT) then
language.Add("Tool.steam.name", "Steam Tool")
language.Add("Tool.steam.desc", "Creates customizable steam")
language.Add("Tool.steam.0", "Left-Click: Create steam Right-Click: Remove steam")
language.Add("Cleanup_steams", "Steam")
language.Add("Cleaned_steams", "Cleaned up all Steam")
language.Add("SBoxLimit_steams", "You've hit the Steam limit!")
language.Add("Undone_steam", "Steam undone")
end
//Sandbox-related stuff
cleanup.Register("steams")
CreateConVar("sbox_maxsteams", 8, FCVAR_NOTIFY)
//Create steam
function TOOL:LeftClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return true end
//Check current spawnlimits
if (!self:GetSWEP():CheckLimit("steams")) then return false end
//Retreive settings
local color_r = math.Round(math.Clamp(self:GetClientNumber("color_r"), 0, 255))
local color_g = math.Round(math.Clamp(self:GetClientNumber("color_g"), 0, 255))
local color_b = math.Round(math.Clamp(self:GetClientNumber("color_b"), 0, 255))
local color_a = math.Round(math.Clamp(self:GetClientNumber("color_a"), 0, 255))
local jetlength = math.Round(math.Clamp(self:GetClientNumber("jetlength"), 8, 1024))
local spreadspeed = math.Round(math.Clamp(self:GetClientNumber("spreadspeed"), 0, 1024))
local speed = math.Round(math.Clamp(self:GetClientNumber("speed"), 0, 4096))
local startsize = math.Round(math.Clamp(self:GetClientNumber("startsize"), 0, 128))
local endsize = math.Round(math.Clamp(self:GetClientNumber("endsize"), 0, 128))
local rate = math.Round(math.Clamp(self:GetClientNumber("rate"), 1, 2048))
local rollspeed = math.Clamp(self:GetClientNumber("rollspeed"), 0, 128)
//Create steam and assign settings
local steam = ents.Create("env_steam")
if !steam || !steam:IsValid() then return false end
steam:SetPos(trace.HitPos)
if self:GetClientNumber("numpadcontrol") == 0 then steam:SetKeyValue("InitialState", "1") else steam:SetKeyValue("InitialState", "0") end
steam:SetKeyValue("angles", tostring(trace.HitNormal:Angle()))
steam:SetKeyValue("rendercolor", "" .. tostring(color_r) .. " " .. tostring(color_g) .. " " .. tostring(color_b) .. "")
steam:SetKeyValue("renderamt", "" .. tostring(color_a) .. "")
steam:SetKeyValue("JetLength", tostring(jetlength))
steam:SetKeyValue("SpreadSpeed", tostring(spreadspeed))
steam:SetKeyValue("Speed", tostring(speed))
steam:SetKeyValue("StartSize", tostring(startsize))
steam:SetKeyValue("EndSize", tostring(endsize))
steam:SetKeyValue("Rate", tostring(rate))
steam:SetKeyValue("rollspeed", tostring(rollspeed))
if math.Round(math.Clamp(self:GetClientNumber("emissive"), 0, 1)) == 1 then steam:SetKeyValue("spawnflags", "1") end
if math.Round(math.Clamp(self:GetClientNumber("heatwave"), 0, 1)) == 1 then steam:SetKeyValue("type", "1") else steam:SetKeyValue("type", "0") end
//Make steam emit hissing sounds
if math.Round(math.Clamp(self:GetClientNumber("makesound"), 0, 1)) == 1 then
steam.MakesSound = true
if math.Round(math.Clamp(self:GetClientNumber("heatwave"), 0, 1)) == 1 then steam.Heatwave = true steam.SFX_Sound = CreateSound(steam, Sound("ambient/gas/cannister_loop.wav")) else steam.SFX_Sound = CreateSound(steam, Sound("ambient/gas/steam2.wav")) end
if self:GetClientNumber("numpadcontrol") == 0 then sound.Play( "HL1/ambience/steamburst1.wav", trace.HitPos, 60, 100 ) steam.SFX_Sound:PlayEx(0.42, 100) end
end
//Spawn steam
steam:Spawn()
steam:Activate()
if trace && trace.Entity && trace.Entity:IsValid() && trace.Entity:GetPhysicsObject():IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then steam:SetParent(trace.Entity) end
//Add to relevant lists
self:GetOwner():AddCount("steams", steam)
table.insert(self.Steams, steam)
//Make sure we can undo
undo.Create("steam")
undo.AddEntity(steam)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "steams", steam)
//Make sure we can control it with numpad
if self:GetClientNumber("numpadcontrol") == 1 then
self:SetupNumpadControls(steam)
end
return true
end
//Setup numpad controls
function TOOL:SetupNumpadControls(steam)
//Safeguards
if !steam || !steam:IsValid() || self:GetClientInfo("key") == nil || self:GetClientInfo("key") == -1 then return false end
//If not toggled
if self:GetClientNumber("toggle") == 0 then
//Create KeyDown numpad functions
local function StartEmitSteam(ply, steam)
if !steam || !steam:IsValid() then return end
//Start steam and related sounds
if steam.MakesSound then
if steam.SFX_Sound then steam.SFX_Sound:Stop() end
if steam.Heatwave then steam.SFX_Sound = CreateSound(steam, Sound("ambient/gas/cannister_loop.wav")) end
if !steam.Heatwave then steam.SFX_Sound = CreateSound(steam, Sound("ambient/gas/steam2.wav")) end
steam.SFX_Sound:PlayEx(0.42, 100)
end
steam:Fire("TurnOn", "", 0)
end
//Register KeyDown functions
numpad.Register("StartEmitSteam", StartEmitSteam)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "StartEmitSteam", steam)
//Create KeyUp numpad functions
local function StopEmitSteam(ply, steam)
if !steam || !steam:IsValid() then return end
//Stop steam and related sounds
if steam.SFX_Sound then steam.SFX_Sound:Stop() end
steam:Fire("TurnOff", "", 0)
end
//Register KeyUp functions
numpad.Register("StopEmitSteam", StopEmitSteam)
numpad.OnUp(self:GetOwner(), self:GetClientNumber("key"), "StopEmitSteam", steam)
end
//If toggled
if self:GetClientNumber("toggle") == 1 then
steam.Toggle = false
//Create KeyDown numpad functions
local function ToggleEmitSteam(ply, steam)
if !steam || !steam:IsValid() then return end
//Start steam and related sounds
if !steam.Toggle then
if steam.MakesSound then
if steam.SFX_Sound then steam.SFX_Sound:Stop() end
if steam.Heatwave then steam.SFX_Sound = CreateSound(steam, Sound("ambient/gas/cannister_loop.wav")) end
if !steam.Heatwave then steam.SFX_Sound = CreateSound(steam, Sound("ambient/gas/steam2.wav")) end
sound.Play( "HL1/ambience/steamburst1.wav", steam:GetPos(), 60, 100 )
steam.SFX_Sound:PlayEx(0.42, 100)
end
steam:Fire("TurnOn", "", 0)
steam.Toggle = true
return
end
//Stop steam and related sounds
if steam.Toggle then
if steam.SFX_Sound then steam.SFX_Sound:Stop() end
steam:Fire("TurnOff", "", 0)
steam.Toggle = false
return
end
end
//Register KeyDown functions
numpad.Register("ToggleEmitSteam", ToggleEmitSteam)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "ToggleEmitSteam", steam)
end
return true
end
//Remove steam in radius
function TOOL:RightClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Find steam in radius
local findsteam = ents.FindInSphere(trace.HitPos, 32)
for _, steam in pairs(findsteam) do
//Remove
if steam && steam:IsValid() && !steam:GetPhysicsObject():IsValid() && steam:GetClass() == "env_steam" && !steam:IsPlayer() && !steam:IsNPC() && !steam:IsWorld() then
if steam.SFX_Sound then steam.SFX_Sound:Stop() end
steam:Fire("TurnOff", "", 0)
steam:Fire("Kill", "", 6)
end
end
end
//Remove all steam
function TOOL:Reload()
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Get all steam objects
for x = 1, table.getn(self.Steams) do
local steam = self.Steams[x]
//Remove
if steam && steam:IsValid() then
if steam.SFX_Sound then steam.SFX_Sound:Stop() end
steam:Fire("TurnOff", "", 0)
steam:Fire("Kill", "", 6)
end
end
end
//Precache all sounds
function TOOL:Precache()
util.PrecacheSound("HL1/ambience/steamburst1.wav")
util.PrecacheSound("ambient/gas/cannister_loop.wav")
util.PrecacheSound("ambient/gas/steam2.wav")
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
//Header
panel:AddControl( "Header", { Text = "#Tool.steam.name", Description = "#Tool.steam.desc" } )
//Build preset menu and declare default preset
local params = { Label = "#Presets", MenuButton = 1, Folder = "steam", Options = {}, CVars = {} }
//Declare default preset
params.Options.default = {
steam_color_r = 150,
steam_color_g = 150,
steam_color_b = 150,
steam_color_a = 200,
steam_jetlength = 150,
steam_spreadspeed = 21,
steam_speed = 200,
steam_startsize = 16,
steam_endsize = 32,
steam_rate = 32,
steam_rollspeed = 12,
steam_emissive = 1,
steam_heatwave = 1,
steam_makesound = 1,
}
//Declare console variables
table.insert( params.CVars, "steam_color_r" )
table.insert( params.CVars, "steam_color_g" )
table.insert( params.CVars, "steam_color_b" )
table.insert( params.CVars, "steam_color_a" )
table.insert( params.CVars, "steam_jetlength" )
table.insert( params.CVars, "steam_spreadspeed" )
table.insert( params.CVars, "steam_speed" )
table.insert( params.CVars, "steam_startsize" )
table.insert( params.CVars, "steam_endsize" )
table.insert( params.CVars, "steam_rate" )
table.insert( params.CVars, "steam_rollspeed" )
table.insert( params.CVars, "steam_emissive" )
table.insert( params.CVars, "steam_heatwave" )
table.insert( params.CVars, "steam_makesound" )
//All done
panel:AddControl( "ComboBox", params )
//Color picker
panel:AddControl( "Color", { Label = "Steam color", Red = "steam_color_r", Green = "steam_color_g", Blue = "steam_color_b", Alpha = "steam_color_a", ShowAlpha = "1", ShowHSV = "1", ShowRGB = "1", Multiplier = "255" } )
//Jet length
panel:AddControl( "Slider", { Label = "Jet length", Type = "Integer", Min = "1", Max = "512", Command ="steam_jetlength" } )
//Spread speed
panel:AddControl( "Slider", { Label = "Spread speed", Type = "Integer", Min = "0", Max = "128", Command ="steam_spreadspeed" } )
//Linear speed
panel:AddControl( "Slider", { Label = "Linear speed", Type = "Integer", Min = "0", Max = "4096", Command ="steam_speed" } )
//Particle start size
panel:AddControl( "Slider", { Label = "Particle start size", Type = "Integer", Min = "0", Max = "128", Command ="steam_startsize" } )
//Particle end size
panel:AddControl( "Slider", { Label = "Particle end size", Type = "Integer", Min = "0", Max = "128", Command ="steam_endsize" } )
//Particle spawn rate
panel:AddControl( "Slider", { Label = "Particle spawn rate", Type = "Integer", Min = "1", Max = "64", Command ="steam_rate" } )
//Particle roll speed
panel:AddControl( "Slider", { Label = "Particle roll speed", Type = "Integer", Min = "0", Max = "32", Command ="steam_rollspeed" } )
//Emissive
panel:AddControl( "CheckBox", { Label = "Emissive", Description = "", Command = "steam_emissive" } )
//Heatwave
panel:AddControl( "CheckBox", { Label = "Heatwave", Description = "", Command = "steam_heatwave" } )
//Sound
panel:AddControl( "CheckBox", { Label = "Sound", Description = "", Command = "steam_makesound" } )
//-------------
panel:AddControl( "Label", { Text = "________________________________________", Description = "" } )
//Numpad menu
panel:AddControl( "Numpad", { Label = "Start/Stop", Command = "steam_key", ButtonSize = 22 } )
//Use numpad check
panel:AddControl( "CheckBox", { Label = "Use keyboard", Description = "", Command = "steam_numpadcontrol" } )
//Toggle check
panel:AddControl( "CheckBox", { Label = "Toggle", Description = "", Command = "steam_toggle" } )
end

View File

@@ -0,0 +1,436 @@
--[[
| 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 = "SubMaterial"--"#tool.material.name"
if CLIENT then
language.Add( "tool.submaterial.name", "SubMaterial Tool" )
language.Add( "tool.submaterial.desc", "Allow to override submaterials of model." )
language.Add( "tool.submaterial.0", "Wheel Up/Down: Select target part, Primary: Apply material, Secondary: Set default material, Reload: Copy material" )
language.Add( "tool.submaterial.help", "Select material here, type known material string or use HUD to copy materials" )
end
TOOL.ClientConVar[ "override" ] = "debug/env_cubemap_model"
TOOL.ClientConVar[ "index" ] = 0
--
-- Duplicator function
--
local function SetSubMaterial( Player, Entity, Data )
if ( SERVER ) then
local Mats=Entity:GetMaterials()
local MatCount=table.Count(Mats)
for i=0,MatCount-1 do
local si="SubMaterialOverride_"..tostring(i)
-- Block exploitable material in multiplayer and remove empty strings
if Data[si] and ((!game.SinglePlayer() && string.lower(Data[si]) == "pp/copy" ) or Data[si] == "" ) then
Data[si]=nil
end
Entity:SetSubMaterial( i, Data[si] or "")
end
duplicator.ClearEntityModifier( Entity, "submaterial")
if (table.Count(Data) > 0) then duplicator.StoreEntityModifier( Entity, "submaterial", Data ) end
end
return true
end
duplicator.RegisterEntityModifier( "submaterial", SetSubMaterial )
local function UpdateSubMat(Player, Entity, Index, Material)
local Mats=Entity:GetMaterials()
local MatCount=table.Count(Mats)
if Index < 0 or Index >= MatCount then return end
local Data={}
for i=0,MatCount-1 do
local mat=Entity:GetSubMaterial(i)
if i==Index then mat=Material end
if mat and mat ~= "" then Data["SubMaterialOverride_"..tostring(i)]=mat end
end
return SetSubMaterial(Player, Entity, Data)
end
-- Original set material funct
local function SetMaterial( Player, Entity, Data )
if ( SERVER ) then
--
-- Make sure this is in the 'allowed' list in multiplayer - to stop people using exploits
--
--if ( !game.SinglePlayer() && !list.Contains( "OverrideMaterials", Data.MaterialOverride ) && Data.MaterialOverride != "" ) then return end
if not Data.MaterialOverride or (Data.MaterialOverride and (!game.SinglePlayer() && string.lower(Data.MaterialOverride) == "pp/copy" )) then
return
end
Entity:SetMaterial( Data.MaterialOverride )
duplicator.StoreEntityModifier( Entity, "material", Data )
end
return true
end
--and we will override it because original function eats most of materials even not exploitable! :(
duplicator.RegisterEntityModifier( "material", SetMaterial )
--
-- Left click applies the current material
--
function TOOL:LeftClick( trace )
if ( !IsValid( trace.Entity ) ) then return end
if ( CLIENT ) then return true end
local ent = trace.Entity
if ( IsValid( ent.AttachedEntity ) ) then ent = ent.AttachedEntity end
local mat = self:GetClientInfo( "override" )
local index = self:GetClientNumber( "index" , 0)
if index < 1 then
SetMaterial( self:GetOwner(), ent, { MaterialOverride = mat } )
else
UpdateSubMat( self:GetOwner(), ent, index-1, mat )
end
return true
end
--
-- Right click reverts the material
--
function TOOL:RightClick( trace )
if ( !IsValid( trace.Entity ) ) then return end
if ( CLIENT ) then return true end
local ent = trace.Entity
if ( IsValid( ent.AttachedEntity ) ) then ent = ent.AttachedEntity end
local index = self:GetClientNumber( "index" , 0)
if index < 1 then
SetMaterial( self:GetOwner(), ent, { MaterialOverride = "" } )
else
UpdateSubMat( self:GetOwner(), ent, index-1, "" )
end
return true
end
----- Damn Dirty fix... Thx for Wire Advanced tool developer
local function get_active_tool(ply, tool)
-- find toolgun
local activeWep = ply:GetActiveWeapon()
if not IsValid(activeWep) or activeWep:GetClass() ~= "gmod_tool" or activeWep.Mode ~= tool then return end
return activeWep:GetToolObject(tool)
end
if game.SinglePlayer() then -- wtfgarry (these functions don't get called clientside in single player so we need this hack to fix it)
if SERVER then
util.AddNetworkString( "submaterial_wtfgarry" )
local function send( ply, funcname )
net.Start( "submaterial_wtfgarry" )
net.WriteString( funcname )
net.Send( ply )
end
--function TOOL:LeftClick() send( self:GetOwner(), "LeftClick" ) end
--function TOOL:RightClick() send( self:GetOwner(), "RightClick" ) end
function TOOL:Reload() send( self:GetOwner(), "Reload" ) end
elseif CLIENT then
net.Receive( "submaterial_wtfgarry", function( len )
local funcname = net.ReadString()
local tool = get_active_tool( LocalPlayer(), "submaterial" )
if not tool then return end
tool[funcname]( tool, LocalPlayer():GetEyeTrace() )
end)
end
end
-----------------------------
if CLIENT then
TOOL.AimEnt = nil
TOOL.HudData = {}
TOOL.SelIndx = 1
TOOL.ToolMatString = ""
function TOOL:Reload( trace )
if ( !IsValid( trace.Entity ) ) then return end
--if ( CLIENT ) then return true end
local ent = trace.Entity
if ( IsValid( ent.AttachedEntity ) ) then ent = ent.AttachedEntity end
--local index = self:GetClientNumber( "index" , 0)
local mat=self.HudData.EntCurMatString--""
if !mat or mat ~= "" then
RunConsoleCommand("submaterial_override",mat)
end
--LocalPlayer():ChatPrint("Material ".. (((self.SelIndx < 1) and "[Global]") or tostring(self.SelIndx)).." copied: "..mat)
--else LocalPlayer():ChatPrint("Empty material!") end
--end
return true
end
function TOOL:Scroll(trace,dir)
if !IsValid(self.AimEnt) then return end
local Mats=self.AimEnt:GetMaterials()
local MatCount=table.Count(Mats)
self.SelIndx = self.SelIndx + dir
if(self.SelIndx<0) then self.SelIndx = MatCount end
if(self.SelIndx>MatCount) then self.SelIndx = 0 end
RunConsoleCommand("submaterial_index",tostring(self.SelIndx))
return true
--self.HudData.EntCurMat=Material(self.AimEnt:GetMaterials()[self.SelIndx])
end
function TOOL:ScrollUp(trace) return self:Scroll(trace,-1) end
function TOOL:ScrollDown(trace) return self:Scroll(trace,1) end
---- Thx wire_adv dev again...
local function hookfunc( ply, bind, pressed )
if not pressed then return end
if bind == "invnext" then
local self = get_active_tool(ply, "submaterial")
if not self then return end
return self:ScrollDown(ply:GetEyeTraceNoCursor())
elseif bind == "invprev" then
local self = get_active_tool(ply, "submaterial")
if not self then return end
return self:ScrollUp(ply:GetEyeTraceNoCursor())
end
end
if game.SinglePlayer() then -- wtfgarry (have to have a delay in single player or the hook won't get added)
timer.Simple(5,function() hook.Add( "PlayerBindPress", "submat_tool_playerbindpress", hookfunc ) end)
else
hook.Add( "PlayerBindPress", "submat_tool_playerbindpress", hookfunc )
end
--------------------------------------------------
local function FixVertexLitMaterial(Mat)
--
-- If it's a vertexlitgeneric material we need to change it to be
-- UnlitGeneric so it doesn't go dark when we enter a dark room
-- and flicker all about
--
if not Mat then return Mat end
local strImage = Mat:GetName()
if ( string.find( Mat:GetShader(), "VertexLitGeneric" ) || string.find( Mat:GetShader(), "Cable" ) ) then
local t = Mat:GetString( "$basetexture" )
if ( t ) then
local params = {}
params[ "$basetexture" ] = t
params[ "$vertexcolor" ] = 1
params[ "$vertexalpha" ] = 1
Mat = CreateMaterial( strImage .. "_hud_fx", "UnlitGeneric", params )
end
end
return Mat
end
function TOOL:Think( )
local ent=LocalPlayer():GetEyeTraceNoCursor().Entity
if ( IsValid( ent.AttachedEntity ) ) then ent = ent.AttachedEntity end
if self.AimEnt ~= ent then
self.AimEnt=ent
if IsValid(self.AimEnt) then
self.SelIndx=0
RunConsoleCommand("submaterial_index",tostring(self.SelIndx))
self.HudData.Mats=self.AimEnt:GetMaterials()
end
--print("ThinkUpdate "..tostring(self.AimEnt))
end
if IsValid(self.AimEnt) then
self.HudData.CurMats=table.Copy(self.HudData.Mats)
self.HudData.OvrMats={}
local MatCount=table.Count(self.HudData.Mats)
for i=1,MatCount do
local mat=self.AimEnt:GetSubMaterial(i-1)
if mat and mat ~= "" then self.HudData.OvrMats[i]=mat end
end
table.Merge(self.HudData.CurMats,self.HudData.OvrMats)
self.HudData.GlobalMat=self.AimEnt:GetMaterial()
local EntCurMatString=self.HudData.GlobalMat
local EntOrigMatString=self.HudData.GlobalMat
if self.SelIndx > 0 then EntCurMatString=self.HudData.CurMats[self.SelIndx]; EntOrigMatString=self.HudData.Mats[self.SelIndx] end
if self.HudData.EntCurMatString~=EntCurMatString then
self.HudData.EntCurMatString=EntCurMatString
self.HudData.EntCurMat=FixVertexLitMaterial(Material(EntCurMatString))
end
if self.HudData.EntOrigMatString~=EntOrigMatString then
self.HudData.EntOrigMatString=EntOrigMatString
self.HudData.EntOrigMat=FixVertexLitMaterial(Material(EntOrigMatString))
end
end
if IsValid(self.AimEnt) and self.ToolMatString~=GetConVarString("submaterial_override") then
self.ToolMatString=GetConVarString("submaterial_override")
self.HudData.ToolMat=FixVertexLitMaterial(Material(self.ToolMatString))
end
end
function TOOL:DrawHUD( )
if IsValid(self.AimEnt) then
---- List
local Rg=ScrW()/2-50
local MaxW = 0
local TextH = 0
surface.SetFont("ChatFont")
local Hdr=tostring(self.AimEnt)..": "..tostring(table.Count(self.HudData.Mats)).." materials"
MaxW,TextH=surface.GetTextSize(Hdr)
local HdrH = TextH+5
for _,s in pairs(self.HudData.CurMats) do
local ts,_=surface.GetTextSize(s)
if MaxW<ts then MaxW=ts end
end
local LH=4*2+HdrH+TextH*(1+table.Count(self.HudData.Mats))
local LW=4*2+MaxW
local LL=Rg-LW
local LT=ScrH()/2-LH/2
surface.SetDrawColor(Color(64,64,95,191))
--surface.SetMaterial(self.HudData.EntCurMat)
surface.DrawRect(LL, LT, LW, LH)
surface.SetTextColor(Color(255,255,255,255))
surface.SetTextPos(LL+4,LT+4)
surface.DrawText(Hdr)
surface.SetDrawColor(Color(255,255,255,255))
surface.DrawLine(LL+3,LT+4+TextH+3,Rg-3,LT+4+TextH+3)
surface.SetDrawColor(Color(0,127,0,191))
surface.DrawRect(LL+3, LT+4+HdrH+TextH*self.SelIndx, LW-3-3, TextH)
local s="<none>"
if not self.HudData.GlobalMat or self.HudData.GlobalMat == "" then
surface.SetTextColor(Color(255,255,255,255))
else surface.SetTextColor(Color(0,0,255,255)); s=self.HudData.GlobalMat end
surface.SetTextPos(LL+4,LT+4+HdrH)
surface.DrawText(s)
for i,s in pairs(self.HudData.CurMats) do
if self.HudData.OvrMats[i] then surface.SetTextColor(Color(255,0,0,255)) else surface.SetTextColor(Color(255,255,255,255)) end
surface.SetTextPos(LL+4,LT+4+HdrH+TextH*i)
surface.DrawText(s)
end
---- Info box
--local MaxW = 0
local StrToolInfo = "Tool material:"
local StrOrigMatInfo = "Model original material:"
local StrCurMatInfo = "Model current material:"
local MaxW,_=surface.GetTextSize(StrToolInfo)
local ts,_=surface.GetTextSize(StrOrigMatInfo)
if MaxW<ts then MaxW=ts end
local ts,_=surface.GetTextSize(StrCurMatInfo)
if MaxW<ts then MaxW=ts end
local ts,_=surface.GetTextSize(self.ToolMatString)
if MaxW<ts then MaxW=ts end
local ts,_=surface.GetTextSize(self.HudData.EntOrigMatString)
if MaxW<ts then MaxW=ts end
local ts,_=surface.GetTextSize(self.HudData.EntCurMatString)
if MaxW<ts then MaxW=ts end
local IL=ScrW()/2+50
local IH=4*4+(64)*3
local IT=ScrH()/2-IH/2
surface.SetDrawColor(Color(64,64,95,191))
surface.DrawRect(IL, IT, 76+MaxW, IH) -- 4+64+4+MaxW+4
surface.SetTextColor(Color(255,255,255,255))
surface.SetDrawColor(Color(255,255,255,255))
if self.HudData.ToolMat then
surface.SetMaterial(self.HudData.ToolMat)
surface.DrawTexturedRect(IL+4, IT+4, 64, 64)
end
surface.SetTextPos(IL+4+64+4,IT+8)
surface.DrawText(StrToolInfo)
surface.SetTextPos(IL+4+64+4,IT+8+TextH)
surface.DrawText(self.ToolMatString)
surface.SetTextPos(IL+4+64+4,IT+8+TextH*2)
surface.DrawText(self.SelIndx==0 and "[Global]" or "Index: "..self.SelIndx-1)
if self.HudData.EntOrigMat then
surface.SetMaterial(self.HudData.EntOrigMat)
surface.DrawTexturedRect(IL+4, IT+4+(64+4), 64, 64)
end
surface.SetTextPos(IL+4+64+4,IT+8+64+4)
surface.DrawText(StrOrigMatInfo)
surface.SetTextPos(IL+4+64+4,IT+8+64+4+TextH)
surface.DrawText(self.HudData.EntOrigMatString)
if self.HudData.EntCurMat then
surface.SetMaterial(self.HudData.EntCurMat)
surface.DrawTexturedRect(IL+4, IT+4+(64+4)*2, 64, 64)
end
surface.SetTextPos(IL+4+64+4,IT+8+(64+4)*2)
surface.DrawText(StrCurMatInfo)
surface.SetTextPos(IL+4+64+4,IT+8+(64+4)*2+TextH)
surface.DrawText(self.HudData.EntCurMatString)
-- surface.SetMaterial(nil)
--draw.RoundedBox( 2, ScrW()/2-50, ScrH()/2-50, 100, 100, Color(255,255,255,255) )
-- print("DrawHUD "..tostring(self.AimEnt))
end
end
end
function TOOL.BuildCPanel( CPanel )
--CPanel:AddControl( "Slider", { Label = "Index", Command = "submaterial_index", Type = "Integer", Min = 0, Max = 15} )
CPanel:AddControl( "Header", { Description = "#tool.submaterial.help" } )
CPanel:AddControl( "TextBox", { Label = "Mat:", Command = "submaterial_override", MaxLength = "48"} )
CPanel:MatSelect( "submaterial_override", list.Get( "OverrideMaterials" ), true, 64, 64 )
end

View File

@@ -0,0 +1,291 @@
--[[
| 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 = "Effects"
TOOL.Name = "Tesla"
TOOL.Command = nil
TOOL.ConfigName = ""
//Default values
TOOL.ClientConVar["dischargeradius"] = 256
TOOL.ClientConVar["dischargeinterval"] = 1.5
TOOL.ClientConVar["beamcount"] = 2
TOOL.ClientConVar["beamthickness"] = 6
TOOL.ClientConVar["beamlifetime"] = 0.052
TOOL.ClientConVar["sound"] = 1
TOOL.ClientConVar["key"] = 5
TOOL.ClientConVar["numpadcontrol"] = 0
TOOL.ClientConVar["toggle"] = 0
//List of all spawned tesla entities
TOOL.Discharges = {}
//Add language descriptions
if (CLIENT) then
language.Add("Tool.tesla.name", "Tesla Discharge Tool")
language.Add("Tool.tesla.desc", "Creates electric discharges")
language.Add("Tool.tesla.0", "Left-Click: Create an electric discharge Right-Click: Remove discharge")
language.Add("Cleanup_discharges", "Tesla Discharges")
language.Add("Cleaned_discharges", "Cleaned up all Discharges")
language.Add("SBoxLimit_discharges", "You've hit the Discharges limit!")
language.Add("Undone_discharge", "Tesla Discharge undone")
end
//Sandbox-related stuff
cleanup.Register("discharges")
CreateConVar("sbox_maxdischarges", 4, FCVAR_NOTIFY)
//Create discharge
function TOOL:LeftClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return true end
//Check current spawnlimits
if (!self:GetSWEP():CheckLimit("discharges")) then return false end
//Retreive settings
local dischargeradius = math.Round(math.Clamp(self:GetClientNumber("dischargeradius"), 1, 2048))
local dischargeinterval = math.Clamp(self:GetClientNumber("dischargeinterval"), 0.012, 8)
local beamcount = math.Clamp(self:GetClientNumber("beamcount"), 1, 32)
local beamthickness = math.Clamp(self:GetClientNumber("beamthickness"), 0.12, 16)
local beamlifetime = math.Clamp(self:GetClientNumber("beamlifetime"), 0.052, 8)
//Create discharge and assign settings
local discharge = ents.Create("point_tesla")
if !discharge || !discharge:IsValid() then return false end
discharge:SetPos(trace.HitPos)
discharge:SetKeyValue("texture", "trails/laser.vmt")
discharge:SetKeyValue("m_Color", "255 255 255")
discharge:SetKeyValue("m_flRadius", tostring(dischargeradius))
discharge:SetKeyValue("interval_min", tostring(dischargeinterval * 0.75))
discharge:SetKeyValue("interval_max", tostring(dischargeinterval * 1.25))
discharge:SetKeyValue("beamcount_min", tostring(math.Round(beamcount * 0.75)))
discharge:SetKeyValue("beamcount_max", tostring(math.Round(beamcount * 1.25)))
discharge:SetKeyValue("thick_min", tostring(beamthickness * 0.75))
discharge:SetKeyValue("thick_max", tostring(beamthickness * 1.25))
discharge:SetKeyValue("lifetime_min", tostring(beamlifetime * 0.75))
discharge:SetKeyValue("lifetime_max", tostring(beamlifetime * 1.25))
//Emit sounds
if math.Round(math.Clamp(self:GetClientNumber("sound"), 0, 1)) == 1 then
discharge:SetKeyValue("m_SoundName", tostring("weapons/physcannon/superphys_small_zap" .. math.random(1,4) .. ".wav"))
if self:GetClientNumber("numpadcontrol") == 0 then
sound.Play( "ambient/energy/weld" .. math.random(1,2) .. ".wav", trace.HitPos, 64, 100 )
discharge:Fire("DoSpark", "", 0)
end
end
//Spawn discharge
discharge:Spawn()
discharge:Activate()
if trace && trace.Entity && trace.Entity:IsValid() && trace.Entity:GetPhysicsObject():IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then discharge:SetParent(trace.Entity) end
if self:GetClientNumber("numpadcontrol") == 0 then discharge:Fire("TurnOn", "", 0) end
//Add to relevant lists
self:GetOwner():AddCount("discharges", discharge)
table.insert(self.Discharges, discharge)
//Make sure we can undo
undo.Create("discharge")
undo.AddEntity(discharge)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "discharges", discharge)
//Make sure we can control it with numpad
if self:GetClientNumber("numpadcontrol") == 1 then
self:SetupNumpadControls(discharge)
end
return true
end
//Setup numpad controls
function TOOL:SetupNumpadControls(discharge)
//Safeguards
if !discharge || !discharge:IsValid() || self:GetClientInfo("key") == nil || self:GetClientInfo("key") == -1 then return false end
//If not toggled
if self:GetClientNumber("toggle") == 0 then
//Create KeyDown numpad functions
local function StartEmitDischarge(ply, discharge)
if !discharge || !discharge:IsValid() then return end
//Start discharge
discharge:Fire("DoSpark", "", 0)
discharge:Fire("TurnOn", "", 0)
end
//Register KeyDown functions
numpad.Register("StartEmitDischarge", StartEmitDischarge)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "StartEmitDischarge", discharge)
//Create KeyUp numpad functions
local function StopEmitDischarge(ply, discharge)
if !discharge || !discharge:IsValid() then return end
//Stop discharge
discharge:Fire("TurnOff", "", 0)
end
//Register KeyUp functions
numpad.Register("StopEmitDischarge", StopEmitDischarge)
numpad.OnUp(self:GetOwner(), self:GetClientNumber("key"), "StopEmitDischarge", discharge)
end
//If toggled
if self:GetClientNumber("toggle") == 1 then
discharge.Toggle = false
//Create KeyDown numpad functions
local function ToggleEmitDischarge(ply, discharge)
if !discharge || !discharge:IsValid() then return end
//Start discharge
if !discharge.Toggle then
discharge:Fire("TurnOn", "", 0)
discharge.Toggle = true
return
end
//Stop discharge
if discharge.Toggle then
discharge:Fire("TurnOff", "", 0)
discharge.Toggle = false
return
end
end
//Register KeyDown functions
numpad.Register("ToggleEmitDischarge", ToggleEmitDischarge)
numpad.OnDown(self:GetOwner(), self:GetClientNumber("key"), "ToggleEmitDischarge", discharge)
end
return true
end
//Remove discharges in radius
function TOOL:RightClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Find discharges in radius
local finddischarges = ents.FindInSphere(trace.HitPos, 16)
for _, discharge in pairs(finddischarges) do
//Remove
if discharge && discharge:IsValid() && !discharge:GetPhysicsObject():IsValid() && discharge:GetClass() == "point_tesla" && !discharge:IsPlayer() && !discharge:IsNPC() && !discharge:IsWorld() then
discharge:Fire("DoSpark", "", 0)
discharge:Fire("Kill", "", 0)
end
end
end
//Remove all discharges
function TOOL:Reload()
//Clients don't need to know about any of this
if (CLIENT) then return false end
//Get all discharges
for x = 1, table.getn(self.Discharges) do
local discharge = self.Discharges[x]
//Remove
if discharge && discharge:IsValid() then
discharge:Fire("Kill", "", 0)
end
end
end
//Precache all sounds
function TOOL:Precache()
util.PrecacheSound("weapons/physcannon/superphys_small_zap1.wav")
util.PrecacheSound("weapons/physcannon/superphys_small_zap2.wav")
util.PrecacheSound("weapons/physcannon/superphys_small_zap3.wav")
util.PrecacheSound("weapons/physcannon/superphys_small_zap4.wav")
util.PrecacheSound("ambient/energy/weld1.wav")
util.PrecacheSound("ambient/energy/weld2.wav")
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
//Header
panel:AddControl( "Header", { Text = "#Tool.tesla.name", Description = "#Tool.tesla.desc" } )
//Build preset menu and declare default preset
local params = { Label = "#Presets", MenuButton = 1, Folder = "tesla", Options = {}, CVars = {} }
//Declare default preset
params.Options.default = {
tesla_dischargeradius = 256,
tesla_dischargeinterval = 1.5,
tesla_beamcount = 2,
tesla_beamthickness = 6,
tesla_beamlifetime = 0.052,
tesla_sound = 1,
}
//Declare console variables
table.insert( params.CVars, "tesla_dischargeradius" )
table.insert( params.CVars, "tesla_dischargeinterval" )
table.insert( params.CVars, "tesla_beamcount" )
table.insert( params.CVars, "tesla_beamthickness" )
table.insert( params.CVars, "tesla_beamlifetime" )
table.insert( params.CVars, "tesla_sound" )
//All done
panel:AddControl( "ComboBox", params )
//Discharge radius
panel:AddControl( "Slider", { Label = "Discharge Radius", Type = "Float", Min = "1", Max = "2048", Command ="tesla_dischargeradius" } )
//Discharge Interval
panel:AddControl( "Slider", { Label = "Discharge Interval", Type = "Float", Min = "0", Max = "8", Command ="tesla_dischargeinterval" } )
//Beam Count
panel:AddControl( "Slider", { Label = "Beam Count", Type = "Float", Min = "1", Max = "32", Command ="tesla_beamcount" } )
//Beam Thickness
panel:AddControl( "Slider", { Label = "Beam Thickness", Type = "Float", Min = "0", Max = "16", Command ="tesla_beamthickness" } )
//Beam Lifetime
panel:AddControl( "Slider", { Label = "Beam Lifetime", Type = "Float", Min = "0", Max = "8", Command ="tesla_beamlifetime" } )
//Sound
panel:AddControl( "CheckBox", { Label = "Sound", Description = "", Command = "tesla_sound" } )
//-------------
panel:AddControl( "Label", { Text = "________________________________________", Description = "" } )
//Numpad menu
panel:AddControl( "Numpad", { Label = "Activate/Deactivate", Command = "tesla_key", ButtonSize = 22 } )
//Use numpad check
panel:AddControl( "CheckBox", { Label = "Use keyboard", Description = "", Command = "tesla_numpadcontrol" } )
//Toggle check
panel:AddControl( "CheckBox", { Label = "Toggle", Description = "", Command = "tesla_toggle" } )
end

View File

@@ -0,0 +1,87 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
if game.SinglePlayer || !game.SinglePlayer() then TOOL.AddToMenu = false return end //Example file, don't run it
//Generic entity spawning script used for testing whether they work or not
TOOL.AddToMenu = false //We're not testing anything right now
TOOL.Category = "Effects"
TOOL.Name = "TESTING"
TOOL.Command = nil
TOOL.ConfigName = ""
//Add language descriptions
if (CLIENT) then
language.Add("Tool.test.name", "Testing Tool")
language.Add("Tool.test.desc", "Creates random stuff")
language.Add("Tool.test.0", "Left-Click: Make something")
language.Add("Cleanup_test", "Test Entities")
language.Add("Cleaned_test", "Cleaned up all Test Entities")
language.Add("Undone_test", "Test Entity undone")
end
//Sandbox-related stuff
cleanup.Register("test")
//Make a test entity
function TOOL:LeftClick(trace)
//Clients don't need to know about any of this
if (CLIENT) then return true end
//Create entity and assign settings
local entity = ents.Create("env_smoketrail")
if !entity || !entity:IsValid() then return false end
entity:SetPos(trace.HitPos)
entity:SetKeyValue("angles", tostring(trace.HitNormal:Angle()))
entity:SetKeyValue("opacity", "0.52") //Float
entity:SetKeyValue("spawnrate", "16") //Float
entity:SetKeyValue("lifetime", "2") //Float
entity:SetKeyValue("startcolor", "255 255 255")
entity:SetKeyValue("endcolor", "255 255 255")
entity:SetKeyValue("emittime", "16384") //Float
entity:SetKeyValue("minspeed", "4") //Float
entity:SetKeyValue("maxspeed", "16") //Float
entity:SetKeyValue("mindirectedspeed", "16") //Float
entity:SetKeyValue("maxdirectedspeed", "64") //Float
entity:SetKeyValue("startsize", "32") //Float
entity:SetKeyValue("endsize", "100") //Float
entity:SetKeyValue("spawnradius", "16") //Float
entity:SetKeyValue("firesprite", "effects/muzzleflash2")
entity:SetKeyValue("smokesprite", "particle/smokesprites_0001.vmt")
//Spawn it
entity:Spawn()
entity:Activate()
//entity:Fire("Start","",0)
//entity:Fire("TurnOn","",0)
//Parent if needed
if trace && trace.Entity && trace.Entity:IsValid() && trace.Entity:GetPhysicsObject():IsValid() && !trace.Entity:IsPlayer() && !trace.Entity:IsWorld() then entity:SetParent(trace.Entity) end
//Make sure we can undo
undo.Create("Test")
undo.AddEntity(entity)
undo.SetPlayer(self:GetOwner())
undo.Finish()
cleanup.Add(self:GetOwner(), "Test", entity)
return true
end
//Build Tool Menu
function TOOL.BuildCPanel(panel)
panel:AddControl( "Header", { Text = "#Tool.test.name", Description = "#Tool.test.desc" } )
end

View File

@@ -0,0 +1,160 @@
--[[
| 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/
--]]
/*******************
*
* Unbreakable STool
*
*
* Date : 28 janvier 2007 Date : 04 December 2013 - 16th June 2015
*
* Auteur : Chaussette Author : XxWestKillzXx + Gui + Sparky
*
*******************************************************************************/
if( SERVER ) then
// Comment this line if you don't want to send this stool to clients
AddCSLuaFile( "weapons/gmod_tool/stools/unbreakable.lua" )
local RemakeFilterDamage
local function MakeFilterDamage()
local FilterDamage = ents.Create( "filter_activator_name" )
FilterDamage:SetKeyValue( "TargetName", "FilterDamage" )
FilterDamage:SetKeyValue( "negated", "1" )
FilterDamage:Spawn()
FilterDamage:CallOnRemove( "RemakeFilter", function () timer.Simple(0, RemakeFilterDamage) end )
end
RemakeFilterDamage = function()
MakeFilterDamage()
for k, v in pairs(ents.GetAll()) do
if v:GetVar( "Unbreakable" ) then
Element:Fire ( "SetDamageFilter", "FilterDamage", 0 )
end
end
end
hook.Add( "InitPostEntity", "MakeFilterDamage", MakeFilterDamage )
local function MakeUnbreakable( Element, Value )
local Filter = ""
if( Value ) then Filter = "FilterDamage" end
if( Element && Element:IsValid() ) then
Element:SetVar( "Unbreakable", Value )
Element:Fire ( "SetDamageFilter", Filter, 0 )
duplicator.StoreEntityModifier( Element, "Unbreakable", {On = Value} )
end
end
function TOOL:Unbreakable( Element, Value )
MakeUnbreakable( Element, Value )
end
local function dupeUnbreakable( Player, Entity, Data )
if Data.On then
MakeUnbreakable( Entity, true )
end
end
duplicator.RegisterEntityModifier( "Unbreakable", dupeUnbreakable )
function TOOL:Run( Element, Value )
if( Element && Element:IsValid() && ( Element:GetVar( "Unbreakable" ) != Value )) then
self:Unbreakable( Element, Value )
if( Element.Constraints ) then
for x, Constraint in pairs( Element.Constraints ) do
for x = 1, 4, 1 do
if( Constraint[ "Ent" .. x ] ) then self:Run( Constraint[ "Ent" .. x ], Value ) end
end
end
end
end
end
end
TOOL.Category = "Constraints"
TOOL.Name = "Unbreakable"
TOOL.Command = nil
TOOL.ConfigName = ""
TOOL.ClientConVar[ "toggle" ] = "1"
if ( CLIENT ) then
language.Add( "tool.unbreakable.name", "Unbreakable" )
language.Add( "tool.unbreakable.desc", "Make a prop unbreakable" )
language.Add( "tool.unbreakable.0", "Left click to make a prop unbreakable. Right click to restore its previous settings" )
language.Add( "tool.unbreakable.toggle", "Extend To Constrained Objects" )
end
function TOOL:Action( Element, Value )
if( Element && Element:IsValid() ) then
if( CLIENT ) then return true end
if( self:GetClientNumber( "toggle" ) == 0 ) then
self:Unbreakable( Element, Value )
else
self:Run( Element, Value )
end
return true
end
return false
end
function TOOL:LeftClick( Target )
return self:Action( Target.Entity, true )
end
function TOOL:RightClick( Target )
return self:Action( Target.Entity, false )
end
function TOOL.BuildCPanel( Panel )
Panel:AddControl( "Header", { Text = "#tool.unbreakable.name", Description = "#tool.unbreakable.desc" } )
Panel:AddControl( "Checkbox", { Label = "#tool.unbreakable.toggle", Command = "unbreakable_toggle" } )
end

View File

@@ -0,0 +1,115 @@
--[[
| 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.Name = "#tool.vjstool_bullseye.name"
TOOL.Tab = "DrVrej"
TOOL.Category = "Tools"
TOOL.Command = nil -- The console command to execute upon being selected in the Q menu.
TOOL.Information = {
{name = "left"},
}
TOOL.ClientConVar["type"] = "Dynamic"
TOOL.ClientConVar["modeldirectory"] = "models/hunter/plates/plate.mdl"
TOOL.ClientConVar["usecolor"] = 1
TOOL.ClientConVar["startactivate"] = 1
-- Just to make it easier to reset everything to default
local DefaultConVars = {}
for k,v in pairs(TOOL.ClientConVar) do
DefaultConVars["vjstool_bullseye_"..k] = v
end
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
local function DoBuildCPanel_VJ_BullseyeSpawner(Panel)
local reset = vgui.Create("DButton")
reset:SetFont("DermaDefaultBold")
reset:SetText("#vjbase.menu.general.reset.everything")
reset:SetSize(150,25)
reset:SetColor(Color(0,0,0,255))
reset.DoClick = function()
for k,v in pairs(DefaultConVars) do
if v == "" then
LocalPlayer():ConCommand(k.." ".."None")
else
LocalPlayer():ConCommand(k.." "..v) end
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_bullseye")
GetPanel:ClearControls()
DoBuildCPanel_VJ_BullseyeSpawner(GetPanel)
end)
end
end
Panel:AddPanel(reset)
local tutorial = vgui.Create("DButton")
tutorial:SetFont("DermaDefaultBold")
tutorial:SetText("#tool.vjstool.menu.tutorialvideo")
tutorial:SetSize(150, 20)
tutorial:SetColor(Color(0,0,255,255))
tutorial.DoClick = function()
gui.OpenURL("http://www.youtube.com/watch?v=Qf-vrE-BAW4")
end
Panel:AddPanel(tutorial)
Panel:AddControl("Label", {Text = "#tool.vjstool.menu.label.recommendation"})
Panel:ControlHelp("- "..language.GetPhrase("#tool.vjstool_bullseye.menu.help1"))
Panel:ControlHelp("- "..language.GetPhrase("#tool.vjstool_bullseye.menu.help2"))
Panel:AddControl("Label", {Text = language.GetPhrase("#tool.vjstool_bullseye.menu.label1")..":"})
local typebox = vgui.Create("DComboBox")
//typebox:SetConVar("vjstool_bullseye_type")
typebox:SetValue(GetConVarString("vjstool_bullseye_type"))
typebox:AddChoice("Dynamic")
typebox:AddChoice("Static")
typebox:AddChoice("Physics")
function typebox:OnSelect(index,value,data)
LocalPlayer():ConCommand("vjstool_bullseye_type "..value)
end
Panel:AddPanel(typebox)
Panel:AddControl("Label", {Text = language.GetPhrase("#tool.vjstool_bullseye.menu.label2")..":"})
local modeldir = vgui.Create("DTextEntry")
modeldir:SetConVar("vjstool_bullseye_modeldirectory")
modeldir:SetMultiline(false)
Panel:AddPanel(modeldir)
Panel:AddControl("Checkbox", {Label = "#tool.vjstool_bullseye.menu.toggleusestatus", Command = "vjstool_bullseye_usecolor"})
Panel:AddControl("Checkbox", {Label = "#tool.vjstool_bullseye.menu.togglestartactivated", Command = "vjstool_bullseye_startactivate"})
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL.BuildCPanel(Panel)
DoBuildCPanel_VJ_BullseyeSpawner(Panel)
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:LeftClick(tr)
if CLIENT then return true end
local spawner = ents.Create("obj_vj_bullseye")
spawner:SetPos(tr.HitPos)
spawner:SetModel(GetConVarString("vjstool_bullseye_modeldirectory"))
spawner.SolidMovementType = GetConVarString("vjstool_bullseye_type")
spawner.UseActivationSystem = true
spawner.UserStatusColors = GetConVar("vjstool_bullseye_usecolor"):GetBool()
spawner.Activated = GetConVar("vjstool_bullseye_startactivate"):GetBool()
spawner:Spawn()
spawner:Activate()
undo.Create("NPC Bullseye")
undo.AddEntity(spawner)
undo.SetPlayer(self:GetOwner())
undo.Finish()
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:RightClick(tr)
if CLIENT then return true end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Reload(tr)
if CLIENT then return true end
end

View File

@@ -0,0 +1,66 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
TOOL.Name = "#tool.vjstool_entityscanner.name"
TOOL.Tab = "DrVrej"
TOOL.Category = "Tools"
TOOL.Command = nil -- The console command to execute upon being selected in the Q menu.
TOOL.Information = {
{name = "left"},
}
-- Just to make it easier to reset everything to default
local DefaultConVars = {}
for k,v in pairs(TOOL.ClientConVar) do
DefaultConVars["vjstool_entityscanner_"..k] = v
end
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
local function DoBuildCPanel_EntityScanner(Panel)
Panel:AddControl("Label", {Text = "#tool.vjstool_entityscanner.label"})
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL.BuildCPanel(Panel)
DoBuildCPanel_EntityScanner(Panel)
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:LeftClick(tr)
if CLIENT then return true end
if !IsValid(tr.Entity) then return false end
local Ent = tr.Entity
local Phys = Ent:GetPhysicsObject()
PrintMessage(HUD_PRINTCONSOLE,"------------------- Name = "..Ent:GetName().." ||| Class = "..Ent:GetClass().." ||| Index = "..Ent:EntIndex().." -------------------")
PrintMessage(HUD_PRINTCONSOLE,"MODEL: File Path = "..Ent:GetModel().." ||| Skin = "..Ent:GetSkin())
PrintMessage(HUD_PRINTCONSOLE,"POSITION: Vector("..Ent:GetPos().x..", "..Ent:GetPos().y..", "..Ent:GetPos().z..") ||| X = "..Ent:GetPos().x.." , Y = "..Ent:GetPos().y.." , Z = "..Ent:GetPos().z)
PrintMessage(HUD_PRINTCONSOLE,"ANGLE: Angle("..Ent:GetAngles().p..", "..Ent:GetAngles().y..", "..Ent:GetAngles().r..") ||| Pitch = "..Ent:GetAngles().p.." , Yaw = "..Ent:GetAngles().y.." , Roll = "..Ent:GetAngles().r)
PrintMessage(HUD_PRINTCONSOLE,"SEQUENCE: ID = "..Ent:GetSequence().." ||| Name = "..Ent:GetSequenceName(Ent:GetSequence()).." ||| Duration = "..VJ_GetSequenceDuration(Ent,Ent:GetSequenceName(Ent:GetSequence())))
if IsValid(Phys) then
PrintMessage(HUD_PRINTCONSOLE,"VELOCITY: Vector("..Phys:GetVelocity().x..", "..Phys:GetVelocity().y..", "..Phys:GetVelocity().z..") ||| X = "..Phys:GetVelocity().x.." , Y = "..Phys:GetVelocity().y.." , Z = "..Phys:GetVelocity().z.." ||| Length = "..Phys:GetVelocity():Length())
PrintMessage(HUD_PRINTCONSOLE,"PHYSICS: Mass = "..Phys:GetMass().." ||| Surface Area = "..Phys:GetSurfaceArea().." ||| Volume = "..Phys:GetVolume())
else
PrintMessage(HUD_PRINTCONSOLE,"VELOCITY: Can't display this information! Reason: Model doesn't have proper physics!")
PrintMessage(HUD_PRINTCONSOLE,"PHYSICS: Can't display this information! Reason: Model doesn't have proper physics!")
end
PrintMessage(HUD_PRINTCONSOLE,"COLOR: Color("..Ent:GetColor().r..", "..Ent:GetColor().g..", "..Ent:GetColor().b..", "..Ent:GetColor().a..") ||| Red = "..Ent:GetColor().r.." , Green = "..Ent:GetColor().g.." , Blue = "..Ent:GetColor().b.." , Alpha = "..Ent:GetColor().a)
PrintMessage(HUD_PRINTCONSOLE,"-----------------------------------------------------------------------------------------------")
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:RightClick(tr)
if CLIENT then return true end
return false
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Reload(tr)
if CLIENT then return true end
return false
end

View File

@@ -0,0 +1,152 @@
--[[
| 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.Name = "#tool.vjstool_healthmodifier.name"
TOOL.Tab = "DrVrej"
TOOL.Category = "Tools"
TOOL.Command = nil -- The console command to execute upon being selected in the Q menu.
TOOL.Information = {
{name = "left"},
{name = "right"},
{name = "reload"},
}
TOOL.ClientConVar["health"] = "100"
TOOL.ClientConVar["godmode"] = 0
TOOL.ClientConVar["healthregen"] = 0
TOOL.ClientConVar["healthregen_amt"] = 4
TOOL.ClientConVar["healthregen_delay"] = 5
-- Just to make it easier to reset everything to default
local DefaultConVars = {}
for k,v in pairs(TOOL.ClientConVar) do
DefaultConVars["vjstool_healthmodifier_"..k] = v
end
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
function DoBuildCPanel_VJ_HealthModifier(Panel)
local reset = vgui.Create("DButton")
reset:SetFont("DermaDefaultBold")
reset:SetText("#vjbase.menu.general.reset.everything")
reset:SetSize(150,25)
reset:SetColor(Color(0,0,0,255))
reset.DoClick = function()
for k,v in pairs(DefaultConVars) do
if v == "" then
LocalPlayer():ConCommand(k.." ".."None")
else
LocalPlayer():ConCommand(k.." "..v) end
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_healthmodifier")
GetPanel:ClearControls()
DoBuildCPanel_VJ_HealthModifier(GetPanel)
end)
end
end
Panel:AddPanel(reset)
local tutorial = vgui.Create("DButton")
tutorial:SetFont("DermaDefaultBold")
tutorial:SetText("#tool.vjstool.menu.tutorialvideo")
tutorial:SetSize(150, 20)
tutorial:SetColor(Color(0,0,255,255))
tutorial.DoClick = function()
gui.OpenURL("http://www.youtube.com/watch?v=kLygPP-vbHY")
end
Panel:AddPanel(tutorial)
Panel:AddControl("Label", {Text = "#tool.vjstool_healthmodifier.adminonly"})
Panel:AddControl("Slider", {Label = "#tool.vjstool_healthmodifier.sliderhealth", min = 0, max = 10000, Command = "vjstool_healthmodifier_health"})
Panel:AddControl("Label", {Text = "#tool.vjstool_healthmodifier.label1"})
Panel:AddControl("Checkbox", {Label = "#tool.vjstool_healthmodifier.togglegodmode", Command = "vjstool_healthmodifier_godmode"})
Panel:AddControl("Checkbox", {Label = "#tool.vjstool_healthmodifier.togglehealthregen", Command = "vjstool_healthmodifier_healthregen"})
Panel:AddControl("Slider", {Label = "#tool.vjstool_healthmodifier.sliderhealthregenamt", min = 0, max = 10000, Command = "vjstool_healthmodifier_healthregen_amt"})
Panel:AddControl("Slider", {Label = "#tool.vjstool_healthmodifier.sliderhealthregendelay", min = 0, max = 10000, Command = "vjstool_healthmodifier_healthregen_delay"})
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL.BuildCPanel(Panel)
DoBuildCPanel_VJ_HealthModifier(Panel)
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:LeftClick(tr)
if CLIENT then return true end
if IsValid(tr.Entity) then
local Ply = self:GetOwner()
local trent = tr.Entity
local canheal = true
if (trent:Health() != 0 or (trent:IsNPC() or trent:IsPlayer())) then
if trent:IsPlayer() && !Ply:IsAdmin() then
canheal = false
end
if canheal == true then
trent:SetHealth(self:GetClientNumber("health"))
Ply:ChatPrint("Set "..trent:GetClass().."'s health to "..self:GetClientNumber("health"))
if trent:IsNPC() then
if self:GetClientNumber("godmode") == 1 then trent.GodMode = true else trent.GodMode = false end
if trent.IsVJBaseSNPC == true && self:GetClientNumber("healthregen") == 1 then
trent.HasHealthRegeneration = true
trent.HealthRegenerationAmount = self:GetClientNumber("healthregen_amt")
trent.HealthRegenerationDelay = VJ_Set(self:GetClientNumber("healthregen_delay"), self:GetClientNumber("healthregen_delay"))
end
end
return true
end
end
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:RightClick(tr)
if CLIENT then return true end
if IsValid(tr.Entity) then
local Ply = self:GetOwner()
local trent = tr.Entity
local canheal = true
if (trent:Health() != 0 or (trent:IsNPC() or trent:IsPlayer())) then
if trent:IsPlayer() && !Ply:IsAdmin() then
canheal = false
end
if canheal == true then
trent:SetHealth(self:GetClientNumber("health"))
trent:SetMaxHealth(self:GetClientNumber("health"))
Ply:ChatPrint("Set "..trent:GetClass().."'s health and max health to "..self:GetClientNumber("health"))
if trent:IsNPC() then
if self:GetClientNumber("godmode") == 1 then trent.GodMode = true else trent.GodMode = false end
if trent.IsVJBaseSNPC == true && self:GetClientNumber("healthregen") == 1 then
trent.HasHealthRegeneration = true
trent.HealthRegenerationAmount = self:GetClientNumber("healthregen_amt")
trent.HealthRegenerationDelay = VJ_Set(self:GetClientNumber("healthregen_delay"), self:GetClientNumber("healthregen_delay"))
end
end
return true
end
end
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Reload(tr)
if CLIENT then return true end
if IsValid(tr.Entity) then
local Ply = self:GetOwner()
local trent = tr.Entity
local canheal = true
if (trent:Health() != 0 or (trent:IsNPC() or trent:IsPlayer())) then
if trent:IsPlayer() && !Ply:IsAdmin() then
canheal = false
end
if canheal == true then
trent:SetHealth(trent:GetMaxHealth())
Ply:ChatPrint("Healed "..trent:GetClass().." to its max health ("..trent:GetMaxHealth()..")")
return true
end
end
end
end

View File

@@ -0,0 +1,66 @@
--[[
| This file was obtained through the combined efforts
| of Madbluntz & Plymouth Antiquarian Society.
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
| Maloy, DrPepper10 @ RIP, Atle!
|
| Visit for more: https://plymouth.thetwilightzone.ru/
--]]
TOOL.Name = "#tool.vjstool_notarget.name"
TOOL.Tab = "DrVrej"
TOOL.Category = "Tools"
TOOL.Command = nil -- The console command to execute upon being selected in the Q menu.
TOOL.Information = {
{name = "left"},
{name = "right"},
}
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
local function DoBuildCPanel_NoTarget(Panel)
Panel:AddControl("Label", {Text = "#tool.vjstool_notarget.label"})
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL.BuildCPanel(Panel)
DoBuildCPanel_NoTarget(Panel)
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:LeftClick(tr)
if CLIENT then return true end
local Ply = self:GetOwner()
if Ply:IsFlagSet(FL_NOTARGET) != true then
Ply:ChatPrint("#tool.vjstool_notarget.print.yourselfon")
Ply:AddFlags(FL_NOTARGET)
return true
else
Ply:ChatPrint("#tool.vjstool_notarget.print.yourselfoff")
Ply:RemoveFlags(FL_NOTARGET)
return true
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:RightClick(tr)
if CLIENT then return true end
if !IsValid(tr.Entity) then return false end
local Ply = self:GetOwner()
local Ent = tr.Entity
local name = Ent:IsPlayer() and Ent:Nick() or Ent:GetClass()
if Ent:IsFlagSet(FL_NOTARGET) != true then
Ply:ChatPrint("Set no target to "..name..": ON")
Ent:AddFlags(FL_NOTARGET)
return true
else
Ply:ChatPrint("Set no target to "..name..": OFF")
Ent:RemoveFlags(FL_NOTARGET)
return true
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Reload(tr)
if CLIENT then return true end
return false
end

View File

@@ -0,0 +1,124 @@
--[[
| 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.Name = "#tool.vjstool_npcequipment.name"
TOOL.Tab = "DrVrej"
TOOL.Category = "Tools"
TOOL.Command = nil -- The console command to execute upon being selected in the Q menu.
TOOL.Information = {
{name = "left"},
{name = "right"},
}
TOOL.ClientConVar["weaponclass"] = "None"
TOOL.ClientConVar["weaponname"] = "Unknown"
-- Just to make it easier to reset everything to default
local DefaultConVars = {}
for k,v in pairs(TOOL.ClientConVar) do
DefaultConVars["vjstool_npcequipment_"..k] = v
end
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
local function DoBuildCPanel_VJ_NPCEquipment(Panel)
local reset = vgui.Create("DButton")
reset:SetFont("DermaDefaultBold")
reset:SetText("#vjbase.menu.general.reset.everything")
reset:SetSize(150,25)
reset:SetColor(Color(0,0,0,255))
reset.DoClick = function()
for k,v in pairs(DefaultConVars) do
if v == "" then
LocalPlayer():ConCommand(k.." ".."None")
else
LocalPlayer():ConCommand(k.." "..v) end
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcequipment")
GetPanel:ClearControls()
DoBuildCPanel_VJ_NPCEquipment(GetPanel)
end)
end
end
Panel:AddPanel(reset)
Panel:AddControl("Label", {Text = "#tool.vjstool.menu.label.recommendation"})
Panel:ControlHelp("#tool.vjstool_npcequipment.label")
local selectwep = vgui.Create("DTextEntry")
selectwep:SetEditable(false)
selectwep:SetText(language.GetPhrase("#tool.vjstool_npcequipment.selectedequipment")..": "..GetConVarString("vjstool_npcequipment_weaponname").." ["..GetConVarString("vjstool_npcequipment_weaponclass").."]")
selectwep.OnGetFocus = function() LocalPlayer():ConCommand("vj_npcequipment_openwepselect") end
Panel:AddItem(selectwep)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL.BuildCPanel(Panel)
DoBuildCPanel_VJ_NPCEquipment(Panel)
end
---------------------------------------------------------------------------------------------------------------------------------------------
concommand.Add("vj_npcequipment_openwepselect",function(pl,cmd,args)
local MenuFrame = vgui.Create('DFrame')
MenuFrame:SetSize(420, 440)
MenuFrame:SetPos(ScrW()*0.6, ScrH()*0.1)
MenuFrame:SetTitle("#tool.vjstool_npcequipment.print.doubleclick")
//MenuFrame:SetBackgroundBlur(true)
MenuFrame:SetFocusTopLevel(true)
MenuFrame:SetSizable(true)
MenuFrame:ShowCloseButton(true)
//MenuFrame:SetDeleteOnClose(false)
MenuFrame:MakePopup()
local CheckList = vgui.Create("DListView")
CheckList:SetTooltip(false)
CheckList:SetParent(MenuFrame)
CheckList:SetPos(10,30)
CheckList:SetSize(400,400) -- Size
CheckList:SetMultiSelect(false)
CheckList:AddColumn("#tool.vjstool_npcequipment.header1")
CheckList:AddColumn("#tool.vjstool_npcequipment.header2")
CheckList.OnRowSelected = function() chat.AddText(Color(0,255,0), "#tool.vjstool_npcequipment.print.doubleclick") end
function CheckList:DoDoubleClick(lineID,line)
chat.AddText(Color(0,255,0), "#tool.vjstool_npcequipment.print.weaponselected1", Color(255,100,0), " "..line:GetValue(1).." ", Color(0,255,0), "#tool.vjstool_npcequipment.print.weaponselected2")
LocalPlayer():ConCommand("vjstool_npcequipment_weaponname "..line:GetValue(1))
LocalPlayer():ConCommand("vjstool_npcequipment_weaponclass "..line:GetValue(2))
MenuFrame:Close()
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcequipment")
GetPanel:ClearControls()
DoBuildCPanel_VJ_NPCEquipment(GetPanel)
end)
end
//MenuFrame:AddItem(CheckList)
//CheckList:SizeToContents()
for _,v in pairs(list.Get("NPCUsableWeapons")) do
CheckList:AddLine(v.title,v.class)
end
CheckList:SortByColumn(1,false)
end)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:LeftClick(tr)
if CLIENT then return true end
if !tr.Entity:IsNPC() then return end
if IsValid(tr.Entity:GetActiveWeapon()) then tr.Entity:GetActiveWeapon():Remove() end
tr.Entity:Give(GetConVarString("vjstool_npcequipment_weaponclass"))
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:RightClick(tr)
if CLIENT then return true end
if !tr.Entity:IsNPC() then return end
if IsValid(tr.Entity:GetActiveWeapon()) then tr.Entity:GetActiveWeapon():Remove() end
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Reload(tr)
if CLIENT then return true end
end

View File

@@ -0,0 +1,144 @@
--[[
| 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.Name = "#tool.vjstool_npcfollower.name"
TOOL.Tab = "DrVrej"
TOOL.Category = "Tools"
TOOL.Command = nil -- The console command to execute upon being selected in the Q menu.
TOOL.Information = {
{name = "left"},
{name = "right"},
{name = "reload"},
}
-- Just to make it easier to reset everything to default
local DefaultConVars = {}
for k,v in pairs(TOOL.ClientConVar) do
DefaultConVars["vjstool_npcfollower_"..k] = v
end
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
NPC_FOLLOWER_ENT_NAME = "None"
local function DoBuildCPanel_NPCFollower(Panel)
local reset = vgui.Create("DButton")
reset:SetFont("DermaDefaultBold")
reset:SetText("#vjbase.menu.general.reset.everything")
reset:SetSize(150, 25)
reset:SetColor(Color(0,0,0,255))
reset.DoClick = function()
for k, v in pairs(DefaultConVars) do
if v == "" then
LocalPlayer():ConCommand(k.." ".."None")
else
LocalPlayer():ConCommand(k.." "..v)
end
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcfollower")
GetPanel:ClearControls()
DoBuildCPanel_NPCFollower(GetPanel)
end)
end
end
Panel:AddPanel(reset)
Panel:AddControl("Label", {Text = "#tool.vjstool.menu.label.recommendation"})
Panel:AddControl("Label", {Text = "Selected NPC: " .. NPC_FOLLOWER_ENT_NAME})
end
---------------------------------------------------------------------------------------------------------------------------------------------
net.Receive("vj_npcfollower_cl_update", function(len, ply)
local wep = LocalPlayer():GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcfollower" then
local entName = net.ReadString()
NPC_FOLLOWER_ENT_NAME = entName
GetPanel = controlpanel.Get("vjstool_npcfollower")
GetPanel:ClearControls()
DoBuildCPanel_NPCFollower(GetPanel)
end
end)
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL.BuildCPanel(Panel)
DoBuildCPanel_NPCFollower(Panel)
end
else -- If SERVER
util.AddNetworkString("vj_npcfollower_cl_update")
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:LeftClick(tr)
if CLIENT then return true end
local ent = tr.Entity
if (!IsValid(ent)) then return end
if !ent:IsNPC() then return end
if !ent.IsVJBaseSNPC then return end
local NPCname = list.Get("NPC")[ent:GetClass()].Name
local ply = self:GetOwner()
self:ClearObjects()
self:SetObject(1, ent, tr.HitPos, Phys, tr.PhysicsBone, tr.HitNormal)
//if CLIENT then return true end
ply:ChatPrint(NPCname .. " Has been selected!")
net.Start("vj_npcfollower_cl_update")
net.WriteString(NPCname)
net.Send(ply)
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:RightClick(tr)
if CLIENT then return true end
local ent = tr.Entity
if (!IsValid(ent)) then return end
local iNum = self:NumObjects()
local ply = self:GetOwner()
if iNum >= 1 then
local selectedEnt = self:GetEnt(1)
if IsValid(selectedEnt) then
if selectedEnt:Follow(ent, false) then
self:ClearObjects()
ply:ChatPrint(list.Get("NPC")[selectedEnt:GetClass()].Name .. " is now following " .. ent:GetClass())
else
ply:ChatPrint(list.Get("NPC")[selectedEnt:GetClass()].Name .. " is currently unable to follow!")
end
else
ply:ChatPrint("#tool.vjstool_npcfollower.print.noselection")
end
else
ply:ChatPrint("#tool.vjstool_npcfollower.print.noselection")
end
//if CLIENT then return true end
net.Start("vj_npcfollower_cl_update")
net.WriteString("None")
net.Send(ply)
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Reload(tr)
if CLIENT then return true end
local ent = tr.Entity
if (!IsValid(ent)) then return end
if !ent:IsNPC() then return end
if !ent.IsVJBaseSNPC then return end
ent:FollowReset()
local ply = self:GetOwner()
ply:ChatPrint("#tool.vjstool_npcfollower.print.reset")
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Holster()
if SERVER then
net.Start("vj_npcfollower_cl_update")
net.WriteString("None")
net.Send(self:GetOwner())
end
self:ClearObjects()
end

View File

@@ -0,0 +1,294 @@
--[[
| 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.Name = "#tool.vjstool_npcmover.name"
TOOL.Tab = "DrVrej"
TOOL.Category = "Tools"
TOOL.Command = nil -- The console command to execute upon being selected in the Q menu.
TOOL.Information = {
{name = "left"},
{name = "right"},
{name = "reload"},
}
-- Just to make it easier to reset everything to default
local DefaultConVars = {}
for k,v in pairs(TOOL.ClientConVar) do
DefaultConVars["vjstool_npcmover_"..k] = v
end
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
local function DoBuildCPanel_Mover(Panel)
VJ_MOVE_TblCurrentValues = VJ_MOVE_TblCurrentValues or {}
VJ_MOVE_TblCurrentLines = VJ_MOVE_TblCurrentLines or {}
local reset = vgui.Create("DButton")
reset:SetFont("DermaDefaultBold")
reset:SetText("#vjbase.menu.general.reset.everything")
reset:SetSize(150,25)
reset:SetColor(Color(0,0,0,255))
reset.DoClick = function()
for k,v in pairs(DefaultConVars) do
if v == "" then
LocalPlayer():ConCommand(k.." ".."None")
else
LocalPlayer():ConCommand(k.." "..v) end
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcmover")
GetPanel:ClearControls()
DoBuildCPanel_Mover(GetPanel)
end)
end
end
Panel:AddPanel(reset)
Panel:AddControl("Label", {Text = "#tool.vjstool.menu.label.recommendation"})
local CheckList = vgui.Create("DListView")
CheckList:SetTooltip(false)
//CheckList:Center() -- No need since Size does it already
CheckList:SetSize(100, 300) -- Size
CheckList:SetMultiSelect(false)
//CheckList.Paint = function()
//draw.RoundedBox(8, 0, 0, CheckList:GetWide(), CheckList:GetTall(), Color(0, 0, 100, 255))
//end
CheckList:AddColumn("#tool.vjstool_npcmover.header1")
CheckList:AddColumn("#tool.vjstool_npcmover.header2")
//CheckList:AddColumn("Index")
CheckList:AddColumn("#tool.vjstool_npcmover.header3")
//CheckList:AddColumn("Position")
//CheckList:AddColumn("Equipment")
for _,v in ipairs(VJ_MOVE_TblCurrentValues) do
if IsValid(v) then
local locname = "Unknown"
for _,lv in pairs(list.Get("NPC")) do
if v:GetClass() == lv.Class then locname = lv.Name end
end
CheckList:AddLine(locname,v:GetClass(),v) //v:EntIndex()
//CheckList:AddLine(v)
end
end
CheckList.OnRowSelected = function(rowIndex,row) chat.AddText(Color(0,255,0),"Double click to ",Color(255,100,0),"unselect ",Color(0,255,0),"a NPC") end
function CheckList:DoDoubleClick(lineID,line)
chat.AddText(Color(0,255,0),"NPC",Color(255,100,0)," "..line:GetValue(1).." ",Color(0,255,0),"unselected!")
net.Start("vj_npcmover_remove")
net.WriteTable({line:GetValue(3)})
net.SendToServer()
CheckList:RemoveLine(lineID)
table.Empty(VJ_MOVE_TblCurrentValues)
for _,vLine in pairs(CheckList:GetLines()) do
table.insert(VJ_MOVE_TblCurrentValues,vLine:GetValue(3))
end
end
Panel:AddItem(CheckList)
//VJ_MOVE_TblCurrentLines = CheckList:GetLines()
local unselectall = vgui.Create("DButton")
unselectall:SetFont("DermaDefaultBold")
unselectall:SetText("#tool.vjstool_npcmover.buttonunselectall")
unselectall:SetSize(150, 25)
unselectall:SetColor(Color(0,0,0,255))
unselectall.DoClick = function()
local brah = VJ_MOVE_TblCurrentValues
if table.Count(brah) > 0 then
chat.AddText(Color(255,100,0), "#tool.vjstool_npcmover.print.unselectedall")
else
chat.AddText(Color(0,255,0), "#tool.vjstool_npcmover.print.unselectedall.error")
end
net.Start("vj_npcmover_remove")
net.WriteTable(brah)
net.SendToServer()
table.Empty(brah)
CheckList:Clear()
end
Panel:AddPanel(unselectall)
//Panel:AddControl("Checkbox", {Label = "Kill The Enemy", Command = "vjstool_npccontroller_killenemy"})
end
---------------------------------------------------------------------------------------------------------------------------------------------
net.Receive("vj_npcmover_cl_create", function(len, ply)
local wep = LocalPlayer():GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcmover" then
local sventity = net.ReadEntity()
local sventname = net.ReadString()
VJ_MOVE_TblCurrentValues = VJ_MOVE_TblCurrentValues or {}
//if svchangetype == "AddNPC" then table.insert(VJ_MOVE_TblCurrentValues,sventity) end
local changetype = 0 -- Check if we are removing or adding an NPC | 0 = Add, 1 = Remove
for k,v in ipairs(VJ_MOVE_TblCurrentValues) do
if !IsValid(v) then table.remove(VJ_MOVE_TblCurrentValues,k) continue end -- Remove any NPCs that no longer exist!
if v == sventity then -- If the selected NPC already exists then unselect it!
chat.AddText(Color(0,255,0),"NPC",Color(255,100,0)," "..sventname.." ",Color(0,255,0),"unselected!")
changetype = 1
table.remove(VJ_MOVE_TblCurrentValues, k)
end
end
if changetype == 0 then -- Only if we are adding
chat.AddText(Color(0,255,0),"NPC",Color(255,100,0)," "..sventname.." ",Color(0,255,0),"selected!")
table.insert(VJ_MOVE_TblCurrentValues,sventity)
end
-- Refresh the tool menu
GetPanel = controlpanel.Get("vjstool_npcmover")
GetPanel:ClearControls()
DoBuildCPanel_Mover(GetPanel)
net.Start("vj_npcmover_sv_create")
net.WriteEntity(sventity)
net.WriteBit(changetype)
net.SendToServer()
//print("Current Entity: ",sventity)
//print("--------------")
//PrintTable(VJ_MOVE_TblCurrentValues)
//print("--------------")
end
end)
---------------------------------------------------------------------------------------------------------------------------------------------
net.Receive("vj_npcmover_cl_startmove", function(len, ply)
local svwalktype = net.ReadBit()
local svvector = net.ReadVector()
local wep = LocalPlayer():GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcmover" then
for k,v in ipairs(VJ_MOVE_TblCurrentValues) do
if !IsValid(v) then -- Remove any NPCs that no longer exist!
table.remove(VJ_MOVE_TblCurrentValues,k)
GetPanel = controlpanel.Get("vjstool_npcmover")
GetPanel:ClearControls()
DoBuildCPanel_Mover(GetPanel)
end
end
net.Start("vj_npcmover_sv_startmove")
net.WriteTable(VJ_MOVE_TblCurrentValues)
net.WriteBit(svwalktype)
net.WriteVector(svvector)
net.SendToServer()
end
end)
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL.BuildCPanel(Panel)
DoBuildCPanel_Mover(Panel)
end
else -- If SERVER
util.AddNetworkString("vj_npcmover_cl_create")
util.AddNetworkString("vj_npcmover_sv_create")
util.AddNetworkString("vj_npcmover_cl_startmove")
util.AddNetworkString("vj_npcmover_sv_startmove")
util.AddNetworkString("vj_npcmover_remove")
---------------------------------------------------------------------------------------------------------------------------------------------
net.Receive("vj_npcmover_sv_create", function(len, ply)
local wep = ply:GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcmover" then
local sventity = net.ReadEntity()
local svchangetype = net.ReadBit()
if svchangetype == 0 then
//print("fully added")
sventity.VJ_IsBeingControlled_Tool = true
sventity:StopMoving()
if sventity.IsVJBaseSNPC == true then
sventity.DisableWandering = true
sventity.DisableChasingEnemy = true
end
elseif svchangetype == 1 then
//print("fully removed")
sventity.VJ_IsBeingControlled_Tool = false
if sventity.IsVJBaseSNPC == true then
sventity.DisableWandering = false
sventity.DisableChasingEnemy = false
sventity:SelectSchedule()
end
end
end
end)
net.Receive("vj_npcmover_remove", function(len, ply)
local wep = ply:GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcmover" then
local brahtbl = net.ReadTable()
for _,v in ipairs(brahtbl) do
v.VJ_IsBeingControlled_Tool = false
if v.IsVJBaseSNPC == true then
v.DisableWandering = false
v.DisableChasingEnemy = false
v:SelectSchedule()
end
end
end
end)
net.Receive("vj_npcmover_sv_startmove", function(len, ply)
local wep = ply:GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcmover" then
local sventtable = net.ReadTable()
local svwalktype = net.ReadBit()
local svvector = net.ReadVector()
local type_task = "TASK_WALK_PATH"
local type_sched = SCHED_FORCED_GO
if svwalktype == 1 then
type_task = "TASK_RUN_PATH"
type_sched = SCHED_FORCED_GO_RUN
end
for k, v in ipairs(sventtable) do
if IsValid(v) then -- Move the NPC if it's valid!
v:StopMoving()
v:SetLastPosition(svvector)
if v.IsVJBaseSNPC == true then
if k == 1 or math.random(1, 5) == 1 then v:PlaySoundSystem("OnReceiveOrder") end
v:VJ_TASK_GOTO_LASTPOS(type_task, function(x)
if IsValid(v:GetEnemy()) && v:Visible(v:GetEnemy()) then
x:EngTask("TASK_FACE_ENEMY", 0)
x.CanShootWhenMoving = true
x.ConstantlyFaceEnemy = true
end
end)
else -- For non-VJ NPCs
v:SetSchedule(type_sched)
end
end
end
//self:MoveNPC(sventity,svvector,svwalktype)
end
end)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:LeftClick(tr)
if CLIENT then return true end
if !tr.Entity:IsNPC() then return end
net.Start("vj_npcmover_cl_create")
net.WriteEntity(tr.Entity)
if tr.Entity:GetName() == "" then
net.WriteString(list.Get("NPC")[tr.Entity:GetClass()].Name)
else
net.WriteString(tr.Entity:GetName())
end
net.Send(self:GetOwner())
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:RightClick(tr)
if CLIENT then return true end
net.Start("vj_npcmover_cl_startmove")
net.WriteBit(1)
net.WriteVector(tr.HitPos)
net.Send(self:GetOwner())
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Reload(tr)
if CLIENT then return true end
net.Start("vj_npcmover_cl_startmove")
net.WriteBit(0)
net.WriteVector(tr.HitPos)
net.Send(self:GetOwner())
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Holster()
/*if CLIENT then return end
self.TblCurrentNPCs = self.TblCurrentNPCs or {}
for k,v in pairs(self.TblCurrentNPCs) do
self:RemoveNPC(v)
end*/
end

View File

@@ -0,0 +1,290 @@
--[[
| 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.Name = "#tool.vjstool_npcrelationship.name"
TOOL.Tab = "DrVrej"
TOOL.Category = "Tools"
TOOL.Command = nil -- The console command to execute upon being selected in the Q menu.
TOOL.Information = {
{name = "left"},
{name = "right"},
{name = "reload"},
}
//TOOL.ClientConVar["playerinteract"] = 1
TOOL.ClientConVar["allytoplyallies"] = 1
-- Just to make it easier to reset everything to default
local DefaultConVars = {}
for k,v in pairs(TOOL.ClientConVar) do
DefaultConVars["vjstool_npcrelationship_"..k] = v
end
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
local function DoBuildCPanel_Relationship(Panel)
local reset = vgui.Create("DButton")
reset:SetFont("DermaDefaultBold")
reset:SetText("#vjbase.menu.general.reset.everything")
reset:SetSize(150,25)
reset:SetColor(Color(0,0,0,255))
reset.DoClick = function()
for k,v in pairs(DefaultConVars) do
if v == "" then
LocalPlayer():ConCommand(k.." ".."None")
else
LocalPlayer():ConCommand(k.." "..v) end
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcrelationship")
GetPanel:ClearControls()
DoBuildCPanel_Relationship(GetPanel)
end)
end
end
Panel:AddPanel(reset)
local tutorial = vgui.Create("DButton")
tutorial:SetFont("DermaDefaultBold")
tutorial:SetText("#tool.vjstool.menu.tutorialvideo")
tutorial:SetSize(150, 20)
tutorial:SetColor(Color(0,0,255,255))
tutorial.DoClick = function()
gui.OpenURL("http://www.youtube.com/watch?v=SnuQU8Sc4cg")
end
Panel:AddPanel(tutorial)
Panel:AddControl("Label", {Text = "#tool.vjstool.menu.label.recommendation"})
Panel:ControlHelp("#tool.vjstool_npcrelationship.label1")
VJ_NPCRELATION_TblCurrentValues = VJ_NPCRELATION_TblCurrentValues or {}
local CheckList = vgui.Create("DListView")
CheckList:SetTooltip(false)
//CheckList:Center() -- No need since Size does it already
CheckList:SetSize( 100, 300 ) -- Size
CheckList:SetMultiSelect(false)
CheckList:AddColumn("#tool.vjstool_npcrelationship.header")
CheckList.OnRowSelected = function(rowIndex,row) chat.AddText(Color(0,255,0),"Double click to ",Color(255,100,0),"remove ",Color(0,255,0),"a class") end
function CheckList:DoDoubleClick(lineID,line)
chat.AddText(Color(255,100,0)," "..line:GetValue(1).." ",Color(0,255,0),"removed!")
CheckList:RemoveLine(lineID)
table.Empty(VJ_NPCRELATION_TblCurrentValues)
for _,vLine in pairs(CheckList:GetLines()) do
table.insert(VJ_NPCRELATION_TblCurrentValues,vLine:GetValue(1))
end
end
Panel:AddItem(CheckList)
for _,v in pairs(VJ_NPCRELATION_TblCurrentValues) do
CheckList:AddLine(v)
end
local function InsertToTable(val)
if string.len(val) > 0 then
val = string.upper(val)
if VJ_HasValue(VJ_NPCRELATION_TblCurrentValues,val) then
chat.AddText(Color(220,20,60),"ERROR! ",Color(255,100,0),val.." ",Color(220,20,60),"already exists in the table!")
else
chat.AddText(Color(0,255,0),"Added",Color(255,100,0)," "..val.." ",Color(0,255,0),"to the class list!")
table.insert(VJ_NPCRELATION_TblCurrentValues,val)
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcrelationship")
GetPanel:ClearControls()
DoBuildCPanel_Relationship(GetPanel)
end)
end
end
end
local TextEntry = vgui.Create("DTextEntry")
//TextEntry:SetText("Press enter to add class...")
TextEntry.OnEnter = function()
InsertToTable(TextEntry:GetValue())
end
Panel:AddItem(TextEntry)
Panel:ControlHelp("#tool.vjstool_npcrelationship.label2")
local button = vgui.Create("DButton")
button:SetFont("DermaDefaultBold")
button:SetText("#tool.vjstool_npcrelationship.button.combine")
button:SetSize(50,20)
button:SetColor(Color(0,0,0,255))
button.DoClick = function()
InsertToTable("CLASS_COMBINE")
end
Panel:AddPanel(button)
button = vgui.Create("DButton")
button:SetFont("DermaDefaultBold")
button:SetText("#tool.vjstool_npcrelationship.button.antlion")
button:SetSize(50,20)
button:SetColor(Color(0,0,0,255))
button.DoClick = function()
InsertToTable("CLASS_ANTLION")
end
Panel:AddPanel(button)
button = vgui.Create("DButton")
button:SetFont("DermaDefaultBold")
button:SetText("#tool.vjstool_npcrelationship.button.zombie")
button:SetSize(50,20)
button:SetColor(Color(0,0,0,255))
button.DoClick = function()
InsertToTable("CLASS_ZOMBIE")
end
Panel:AddPanel(button)
button = vgui.Create("DButton")
button:SetFont("DermaDefaultBold")
button:SetText("#tool.vjstool_npcrelationship.button.player")
button:SetSize(50,20)
button:SetColor(Color(0,0,0,255))
button.DoClick = function()
InsertToTable("CLASS_PLAYER_ALLY")
end
Panel:AddPanel(button)
Panel:AddControl("Checkbox", {Label = "#tool.vjstool_npcrelationship.togglealliedply", Command = "vjstool_npcrelationship_allytoplyallies"})
Panel:ControlHelp(language.GetPhrase("#tool.vjstool_npcrelationship.label3").." CLASS_PLAYER_ALLY")
//Panel:AddControl("Label", {Text = "For PLAYER entities Only:"})
//Panel:AddControl("Checkbox", {Label = "Make NPCs interact with friendly player", Command = "vjstool_npcspawner_playerinteract"})
//Panel:ControlHelp("Make NPCs be able to interact with friendly player, such follow when pressed E or get out of their way")
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL.BuildCPanel(Panel)
DoBuildCPanel_Relationship(Panel)
end
---------------------------------------------------------------------------------------------------------------------------------------------
net.Receive("vj_npcrelationship_cl_select", function(len, ply)
local wep = LocalPlayer():GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcrelationship" then
//local ent = net.ReadEntity()
local entname = net.ReadString()
//local hasclasstbl = net.ReadBool()
local classtbl = net.ReadTable()
chat.AddText(Color(0,255,0),"Obtained",Color(255,100,0)," "..entname.."'s ",Color(0,255,0),"relationship class list!")
//print(ent)
//print(hasclasstbl)
//PrintTable(classtbl)
//print(#classtbl)
VJ_NPCRELATION_TblCurrentValues = classtbl
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcrelationship")
GetPanel:ClearControls()
DoBuildCPanel_Relationship(GetPanel)
end)
end
end)
---------------------------------------------------------------------------------------------------------------------------------------------
net.Receive("vj_npcrelationship_cl_leftclick", function(len, ply)
local wep = LocalPlayer():GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcrelationship" then
local ent = net.ReadEntity()
local entname = net.ReadString()
local clicktype = net.ReadString()
local allynum = net.ReadFloat()
if clicktype == "ReloadClick" then entname = "Yourself" end
chat.AddText(Color(0,255,0),"#tool.vjstool_npcrelationship.print.applied",Color(255,100,0)," "..entname)
net.Start("vj_npcrelationship_sr_leftclick")
net.WriteEntity(ent)
//net.WriteTable(self)
//net.WriteString(clicktype)
net.WriteTable(VJ_NPCRELATION_TblCurrentValues)
net.WriteFloat(allynum)
net.SendToServer()
end
end)
else
util.AddNetworkString("vj_npcrelationship_cl_select")
util.AddNetworkString("vj_npcrelationship_cl_leftclick")
util.AddNetworkString("vj_npcrelationship_sr_leftclick")
---------------------------------------------------------------------------------------------------------------------------------------------
net.Receive("vj_npcrelationship_sr_leftclick", function(len, ply)
local wep = ply:GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcrelationship" then
local ent = net.ReadEntity()
//local clicktype = net.ReadString()
local classtbl = net.ReadTable()
local allynum = net.ReadFloat()
if #classtbl > 0 then
ent.VJ_NPC_Class = classtbl
if ent.IsVJBaseSNPC == true then
if table.HasValue(classtbl,"CLASS_PLAYER_ALLY") then
if allynum == 1 then ent.FriendsWithAllPlayerAllies = true end
ent.PlayerFriendly = true
else
ent.PlayerFriendly = false
end
end
else
ent.VJ_NPC_Class = {nil}
ent.PlayerFriendly = false
end
end
end)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:LeftClick(tr)
if CLIENT then return true end
local ent = tr.Entity
if IsValid(ent) && ent:IsPlayer() or ent:IsNPC() then
local entname = ent:GetName()
if entname == "" then entname = ent:GetClass() end
net.Start("vj_npcrelationship_cl_leftclick")
net.WriteEntity(ent)
net.WriteString(entname)
net.WriteString("LeftClick")
net.WriteFloat(self:GetClientNumber("allytoplyallies"))
net.Send(self:GetOwner())
return true
end
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:RightClick(tr)
if CLIENT then return true end
local ent = tr.Entity
if IsValid(ent) && ent:IsPlayer() or ent:IsNPC() then
//local hasclasstbl = false
local classtbl = {nil}
local entname = ent:GetName()
if entname == "" then entname = ent:GetClass() end
if (ent.VJ_NPC_Class) then
//hasclasstbl = true
//classtbl = ent.VJ_NPC_Class
for _,v in ipairs(ent.VJ_NPC_Class) do
table.insert(classtbl,v)
end
//if (classtbl.BaseClass) then table.remove(classtbl,BaseClass) end
end
//PrintTable(ent.VJ_NPC_Class)
net.Start("vj_npcrelationship_cl_select")
//net.WriteEntity(ent)
net.WriteString(entname)
//net.WriteBool(hasclasstbl)
net.WriteTable(classtbl)
net.Send(self:GetOwner())
return true
end
/* local trent = tr.Entity
trent:SetHealth(self:GetClientNumber("health"))
if tr.Entity:IsNPC() then
if self:GetClientNumber("godmode") == 1 then trent.GodMode = true else trent.GodMode = false end
end
return true
end*/
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Reload(tr)
if CLIENT then return true end
net.Start("vj_npcrelationship_cl_leftclick")
net.WriteEntity(self:GetOwner())
net.WriteString("Me")
net.WriteString("ReloadClick")
net.Send(self:GetOwner())
return true
end

View File

@@ -0,0 +1,334 @@
--[[
| 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.Name = "#tool.vjstool_npcspawner.name"
TOOL.Tab = "DrVrej"
TOOL.Category = "Tools"
TOOL.Command = nil -- The console command to execute upon being selected in the Q menu.
TOOL.Information = {
{name = "left"},
{name = "right"},
}
TOOL.ClientConVar["playsound"] = 1
TOOL.ClientConVar["nextspawntime"] = 1
TOOL.ClientConVar["spawnent"] = "None"
TOOL.ClientConVar["spawnentname"] = "Unknown"
TOOL.ClientConVar["spawnnpclass"] = ""
TOOL.ClientConVar["fritoplyallies"] = 1
TOOL.ClientConVar["spawnpos_forward"] = 0
TOOL.ClientConVar["spawnpos_right"] = 0
TOOL.ClientConVar["spawnpos_up"] = 0
TOOL.ClientConVar["weaponequip"] = "None"
TOOL.ClientConVar["weaponequipname"] = "None"
TOOL.ClientConVar["nextspawntime"] = 3
-- Just to make it easier to reset everything to default
local DefaultConVars = {}
for k,v in pairs(TOOL.ClientConVar) do
DefaultConVars["vjstool_npcspawner_"..k] = v
end
---------------------------------------------------------------------------------------------------------------------------------------------
if CLIENT then
local function DoBuildCPanel_Spawner(Panel)
local reset = vgui.Create("DButton")
reset:SetFont("DermaDefaultBold")
reset:SetText("#vjbase.menu.general.reset.everything")
reset:SetSize(150,25)
reset:SetColor(Color(0,0,0,255))
reset.DoClick = function()
for k,v in pairs(DefaultConVars) do
-- Ignore "vjstool_npcspawner_spawnnpclass" because we don't want it set to "None", we need it to stay ""
if k == "vjstool_npcspawner_spawnnpclass" then
LocalPlayer():ConCommand("vjstool_npcspawner_spawnnpclass \"\"")
elseif v == "" then
LocalPlayer():ConCommand(k.." ".."None")
else
LocalPlayer():ConCommand(k.." "..v)
end
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcspawner")
GetPanel:ClearControls()
DoBuildCPanel_Spawner(GetPanel)
end)
end
end
Panel:AddPanel(reset)
local tutorial = vgui.Create("DButton")
tutorial:SetFont("DermaDefaultBold")
tutorial:SetText("#tool.vjstool.menu.tutorialvideo")
tutorial:SetSize(150, 20)
tutorial:SetColor(Color(0,0,255,255))
tutorial.DoClick = function()
gui.OpenURL("http://www.youtube.com/watch?v=5H_hIz35W90")
end
Panel:AddPanel(tutorial)
VJ_NPCSPAWNER_TblCurrentValues = VJ_NPCSPAWNER_TblCurrentValues or {}
VJ_NPCSPAWNER_TblCurrentLines = VJ_NPCSPAWNER_TblCurrentLines or {}
VJ_NPCSPAWNER_TblCurrentLinesUsable = VJ_NPCSPAWNER_TblCurrentLinesUsable or {}
Panel:AddControl("Label", {Text = "#tool.vjstool.menu.label.recommendation"})
local selectnpc = vgui.Create("DTextEntry")
selectnpc:SetEditable(false)
selectnpc:SetText(language.GetPhrase("#tool.vjstool_npcspawner.selectednpc")..": "..GetConVarString("vjstool_npcspawner_spawnentname").." ["..GetConVarString("vjstool_npcspawner_spawnent").."]")
selectnpc.OnGetFocus = function() LocalPlayer():ConCommand("vj_npcspawner_opennpcselect") end
Panel:AddItem(selectnpc)
Panel:AddControl("TextBox",{Label = "#tool.vjstool_npcspawner.spawnpos.forward",MaxLength = 10,Type = "Float",WaitForEnter = false,Command = "vjstool_npcspawner_spawnpos_forward"})
Panel:AddControl("TextBox",{Label = "#tool.vjstool_npcspawner.spawnpos.right",MaxLength = 10,Type = "Float",WaitForEnter = false,Command = "vjstool_npcspawner_spawnpos_right"})
Panel:AddControl("TextBox",{Label = "#tool.vjstool_npcspawner.spawnpos.up",MaxLength = 10,Type = "Float",WaitForEnter = false,Command = "vjstool_npcspawner_spawnpos_up"})
local selectwep = vgui.Create("DTextEntry")
selectwep:SetEditable(false)
selectwep:SetText(language.GetPhrase("#tool.vjstool_npcspawner.selectweapon")..": "..GetConVarString("vjstool_npcspawner_weaponequipname").." ["..GetConVarString("vjstool_npcspawner_weaponequip").."]")
selectwep.OnGetFocus = function() LocalPlayer():ConCommand("vj_npcspawner_openwepselect") end
Panel:AddItem(selectwep)
Panel:AddControl("TextBox",{Label = "#tool.vjstool_npcspawner.spawnnpclass",WaitForEnter = false,Command = "vjstool_npcspawner_spawnnpclass"})
Panel:AddControl("CheckBox",{Label = "#tool.vjstool_npcspawner.fritoplyallies",Command = "vjstool_npcspawner_fritoplyallies"})
Panel:ControlHelp("#tool.vjstool_npcspawner.label.fritoplyallies")
Panel:AddControl("Button",{Label = "#tool.vjstool_npcspawner.button.updatelist",Command = "vj_npcspawner_updatelist"})
Panel:ControlHelp("#tool.vjstool_npcspawner.label1")
local CheckList = vgui.Create("DListView")
CheckList:SetTooltip(false)
CheckList:SetSize(100, 307) -- Size
CheckList:SetMultiSelect(false)
CheckList:AddColumn("#tool.vjstool_npcspawner.header1")
CheckList:AddColumn("#tool.vjstool_npcspawner.header2")
CheckList:AddColumn("#tool.vjstool_npcspawner.header3")
CheckList.OnRowSelected = function(rowIndex,row) chat.AddText(Color(0,255,0),"Double click to ",Color(255,100,0),"remove ",Color(0,255,0),"a NPC") end
function CheckList:DoDoubleClick(lineID,line)
chat.AddText(Color(0,255,0),"NPC",Color(255,100,0)," "..line:GetValue(1).." ",Color(0,255,0),"removed!")
CheckList:RemoveLine(lineID)
table.Empty(VJ_NPCSPAWNER_TblCurrentLinesUsable)
for _,vLine in pairs(VJ_NPCSPAWNER_TblCurrentLines) do
table.insert(VJ_NPCSPAWNER_TblCurrentLinesUsable,{Entities=vLine:GetValue(4),SpawnPosition=vLine:GetValue(2),WeaponsList=vLine:GetValue(3),EntityName=vLine:GetValue(1),Relationship=vLine:GetValue(5)})
end
end
Panel:AddItem(CheckList)
for k,v in pairs(VJ_NPCSPAWNER_TblCurrentValues) do
if v.Entities == "" or v.Entities == "none" or v.Entities == {} then table.remove(VJ_NPCSPAWNER_TblCurrentValues,k) continue end
if v.Entities != "" && v.Entities != "none" && v.Entities != {} then
CheckList:AddLine(v.EntityName,Vector(v.SpawnPosition.vForward,v.SpawnPosition.vRight,v.SpawnPosition.vUp),v.WeaponsList,v.Entities,v.Relationship)
//CheckList:AddLine(v.Entities,"x:"..v.SpawnPosition.vForward.." y:"..v.SpawnPosition.vRight.." z:"..v.SpawnPosition.vUp)
end
end
table.Empty(VJ_NPCSPAWNER_TblCurrentValues)
for _,vLine in pairs(VJ_NPCSPAWNER_TblCurrentLines) do
CheckList:AddLine(vLine:GetValue(1),vLine:GetValue(2),vLine:GetValue(3),vLine:GetValue(4),vLine:GetValue(5))
end
VJ_NPCSPAWNER_TblCurrentLines = CheckList:GetLines()
table.Empty(VJ_NPCSPAWNER_TblCurrentLinesUsable)
for _,vLine in pairs(VJ_NPCSPAWNER_TblCurrentLines) do
table.insert(VJ_NPCSPAWNER_TblCurrentLinesUsable,{Entities=vLine:GetValue(4),SpawnPosition=vLine:GetValue(2),WeaponsList=vLine:GetValue(3),EntityName=vLine:GetValue(1),Relationship=vLine:GetValue(5)})
end
Panel:AddControl("Label", {Text = language.GetPhrase("#tool.vjstool_npcspawner.label2")..":"})
Panel:AddControl("Checkbox", {Label = "#tool.vjstool_npcspawner.toggle.spawnsound", Command = "vjstool_npcspawner_playsound"})
Panel:AddControl("Slider", {Label = "#tool.vjstool_npcspawner.nextspawntime",min = 0,max = 1000,Command = "vjstool_npcspawner_nextspawntime"})
end
---------------------------------------------------------------------------------------------------------------------------------------------
concommand.Add("vj_npcspawner_opennpcselect",function(ply,cmd,args)
local MenuFrame = vgui.Create('DFrame')
MenuFrame:SetSize(420, 440)
MenuFrame:SetPos(ScrW()*0.6, ScrH()*0.1)
MenuFrame:SetTitle("#tool.vjstool_npcspawner.title1")
//MenuFrame:SetBackgroundBlur(true)
MenuFrame:SetFocusTopLevel(true)
MenuFrame:SetSizable(true)
MenuFrame:ShowCloseButton(true)
//MenuFrame:SetDeleteOnClose(false)
MenuFrame:MakePopup()
local CheckList = vgui.Create("DListView")
CheckList:SetTooltip(false)
//CheckList:Center() -- No need since Size does it already
CheckList:SetParent(MenuFrame)
CheckList:SetPos(10,30)
CheckList:SetSize(400,400) -- Size
CheckList:SetMultiSelect(false)
CheckList:AddColumn("#tool.vjstool_npcspawner.popup.header1")
CheckList:AddColumn("#tool.vjstool_npcspawner.popup.header2")
CheckList:AddColumn("#tool.vjstool_npcspawner.popup.header3")
CheckList.OnRowSelected = function() chat.AddText(Color(0,255,0),"#tool.vjstool_npcspawner.title1") end
function CheckList:DoDoubleClick(lineID,line)
chat.AddText(Color(0,255,0),"NPC",Color(255,100,0)," "..line:GetValue(1).." ",Color(0,255,0),"selected!")
LocalPlayer():ConCommand("vjstool_npcspawner_spawnentname "..line:GetValue(1))
LocalPlayer():ConCommand("vjstool_npcspawner_spawnent "..line:GetValue(2))
MenuFrame:Close()
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcspawner")
GetPanel:ClearControls()
DoBuildCPanel_Spawner(GetPanel)
end)
end
//MenuFrame:AddItem(CheckList)
//CheckList:SizeToContents()
for _,v in pairs(list.Get("NPC")) do
getcat = v.Category
if v.Category == "" then getcat = "Unknown" end
CheckList:AddLine(v.Name,v.Class,getcat)
end
CheckList:SortByColumn(1,false)
end)
---------------------------------------------------------------------------------------------------------------------------------------------
concommand.Add("vj_npcspawner_openwepselect",function(ply,cmd,args)
local MenuFrame = vgui.Create('DFrame')
MenuFrame:SetSize(420, 440)
MenuFrame:SetPos(ScrW()*0.6, ScrH()*0.1)
MenuFrame:SetTitle("#tool.vjstool_npcspawner.title2")
//MenuFrame:SetBackgroundBlur(true)
MenuFrame:SetFocusTopLevel(true)
MenuFrame:SetSizable(true)
MenuFrame:ShowCloseButton(true)
//MenuFrame:SetDeleteOnClose(false)
MenuFrame:MakePopup()
local CheckList = vgui.Create("DListView")
CheckList:SetTooltip(false)
//CheckList:Center() -- No need since Size does it already
CheckList:SetParent(MenuFrame)
CheckList:SetPos(10,30)
CheckList:SetSize(400,400) -- Size
CheckList:SetMultiSelect(false)
CheckList:AddColumn("#tool.vjstool_npcspawner.popup.header1")
CheckList:AddColumn("#tool.vjstool_npcspawner.popup.header2")
CheckList.OnRowSelected = function() chat.AddText(Color(0,255,0),"#tool.vjstool_npcspawner.title2") end
function CheckList:DoDoubleClick(lineID,line)
chat.AddText(Color(0,255,0),"Weapon",Color(255,100,0)," "..line:GetValue(1).." ",Color(0,255,0),"selected!")
LocalPlayer():ConCommand("vjstool_npcspawner_weaponequipname "..line:GetValue(1))
LocalPlayer():ConCommand("vjstool_npcspawner_weaponequip "..line:GetValue(2))
MenuFrame:Close()
timer.Simple(0.05,function()
GetPanel = controlpanel.Get("vjstool_npcspawner")
GetPanel:ClearControls()
DoBuildCPanel_Spawner(GetPanel)
end)
end
//MenuFrame:AddItem(CheckList)
//CheckList:SizeToContents()
for _,v in pairs(list.Get("NPCUsableWeapons")) do
CheckList:AddLine(v.title,v.class)
end
CheckList:SortByColumn(1,false)
CheckList:AddLine("None","None")
CheckList:AddLine("Default","Default")
end)
---------------------------------------------------------------------------------------------------------------------------------------------
concommand.Add("vj_npcspawner_updatelist",function(ply,cmd,args)
local spawnent = string.lower(GetConVarString("vjstool_npcspawner_spawnent"))
local spawnentname = GetConVarString("vjstool_npcspawner_spawnentname")
local spawnposfor = GetConVarString("vjstool_npcspawner_spawnpos_forward")
local spawnposright = GetConVarString("vjstool_npcspawner_spawnpos_right")
local spawnposup = GetConVarString("vjstool_npcspawner_spawnpos_up")
local spawnnpclass = GetConVarString("vjstool_npcspawner_spawnnpclass")
local spawnfritoplyallies = GetConVarString("vjstool_npcspawner_fritoplyallies")
local spawnequip = string.lower(GetConVarString("vjstool_npcspawner_weaponequip"))
table.insert(VJ_NPCSPAWNER_TblCurrentValues,{EntityName=spawnentname, Entities=spawnent, SpawnPosition={vForward=spawnposfor,vRight=spawnposright,vUp=spawnposup}, WeaponsList=spawnequip, Relationship={Class = spawnnpclass, FriToPlyAllies = spawnfritoplyallies}})
GetPanel = controlpanel.Get("vjstool_npcspawner")
GetPanel:ClearControls()
DoBuildCPanel_Spawner(GetPanel)
end)
---------------------------------------------------------------------------------------------------------------------------------------------
net.Receive("vj_npcspawner_cl_create", function(len, ply)
local wep = LocalPlayer():GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcspawner" then
local svpos = net.ReadVector()
local svclicktype = net.ReadString()
local convartbl = {}
for k,_ in pairs(DefaultConVars) do
convartbl[k] = GetConVarNumber(k)
end
net.Start("vj_npcspawner_sv_create")
net.WriteTable(convartbl)
net.WriteVector(svpos)
net.WriteType(VJ_NPCSPAWNER_TblCurrentLinesUsable)
net.WriteString(svclicktype)
net.SendToServer()
end
end)
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL.BuildCPanel(Panel)
DoBuildCPanel_Spawner(Panel)
end
else -- If SERVER
util.AddNetworkString("vj_npcspawner_cl_create")
util.AddNetworkString("vj_npcspawner_sv_create")
---------------------------------------------------------------------------------------------------------------------------------------------
local spawnSounds = {"garrysmod/save_load1.wav","garrysmod/save_load2.wav","garrysmod/save_load3.wav","garrysmod/save_load4.wav"}
--
net.Receive("vj_npcspawner_sv_create", function(len, ply)
local wep = ply:GetActiveWeapon()
if wep:IsValid() && wep:GetClass() == "gmod_tool" && wep:GetMode() == "vjstool_npcspawner" then
local convartbl = net.ReadTable()
local svpos = net.ReadVector()
local svgetlines = net.ReadType()
local svgettype = net.ReadString()
if !IsValid(ply) then return false end
if table.Count(svgetlines) <= 0 then ply:ChatPrint("#tool.vjstool_npcspawner.print.nothingspawn") return false end
local spawner = ents.Create("obj_vj_spawner_base")
spawner.EntitiesToSpawn = {}
spawner:SetPos(svpos)
local angs = Angle(0,0,0)
if IsValid(ply) then
angs = ply:GetAngles()
angs.pitch = 0
angs.roll = 0
angs.yaw = angs.yaw + 180
end
spawner:SetAngles(angs)
for _,v in pairs(svgetlines) do
//if v.IsVJBaseSpawner == true then ply:ChatPrint("Can't be spawned because it's a spawner") end
table.insert(spawner.EntitiesToSpawn,{SpawnPosition={vForward=v.SpawnPosition.x,vRight=v.SpawnPosition.y,vUp=v.SpawnPosition.z}, Entities={v.Entities}, WeaponsList={v.WeaponsList}, NPC_Class = v.Relationship.Class, FriToPlyAllies = tobool(v.Relationship.FriToPlyAllies)})
end
//spawner.EntitiesToSpawn = {entitiestospawntbl}
if convartbl.vjstool_npcspawner_playsound == 1 then
spawner.SoundTbl_SpawnEntity = spawnSounds
end
spawner.TimedSpawn_Time = convartbl.vjstool_npcspawner_nextspawntime //GetConVarNumber("vjstool_npcspawner_nextspawntime")
if svgettype == "RightClick" then spawner.SingleSpawner = true end
spawner:SetCreator(ply)
spawner:Spawn()
spawner:Activate()
undo.Create("NPC Spawner")
undo.AddEntity(spawner)
undo.SetPlayer(ply)
undo.Finish()
for vpk,vpv in pairs(spawner.CurrentEntities) do
if IsValid(vpv.TheEntity) && vpv.TheEntity.IsVJBaseSpawner == true && vpv.TheEntity.SingleSpawner == true then
vpv.TheEntity:SetCreator(ply)
table.remove(spawner.CurrentEntities,vpk)
if table.Count(spawner.CurrentEntities) <= 0 then spawner:Remove() end
end
end
end
end)
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:LeftClick(tr)
if CLIENT then return true end
net.Start("vj_npcspawner_cl_create")
net.WriteVector(tr.HitPos)
net.WriteString("LeftClick")
net.Send(self:GetOwner())
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:RightClick(tr)
if CLIENT then return true end
net.Start("vj_npcspawner_cl_create")
net.WriteVector(tr.HitPos)
net.WriteString("RightClick")
net.Send(self:GetOwner())
return true
end
---------------------------------------------------------------------------------------------------------------------------------------------
function TOOL:Reload(tr)
if CLIENT then return true end
end