mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 05:43:46 +03:00
Upload
This commit is contained in:
1918
lua/weapons/gmod_tool/stools/advdupe2.lua
Normal file
1918
lua/weapons/gmod_tool/stools/advdupe2.lua
Normal file
File diff suppressed because it is too large
Load Diff
312
lua/weapons/gmod_tool/stools/energyball.lua
Normal file
312
lua/weapons/gmod_tool/stools/energyball.lua
Normal 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
|
||||
319
lua/weapons/gmod_tool/stools/env_headcrabcanister.lua
Normal file
319
lua/weapons/gmod_tool/stools/env_headcrabcanister.lua
Normal 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
|
||||
234
lua/weapons/gmod_tool/stools/fire.lua
Normal file
234
lua/weapons/gmod_tool/stools/fire.lua
Normal 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
|
||||
213
lua/weapons/gmod_tool/stools/glow.lua
Normal file
213
lua/weapons/gmod_tool/stools/glow.lua
Normal 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
|
||||
162
lua/weapons/gmod_tool/stools/item_ammo_crate.lua
Normal file
162
lua/weapons/gmod_tool/stools/item_ammo_crate.lua
Normal file
@@ -0,0 +1,162 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
TOOL.Category = "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
|
||||
150
lua/weapons/gmod_tool/stools/item_charger_spawner.lua
Normal file
150
lua/weapons/gmod_tool/stools/item_charger_spawner.lua
Normal 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
|
||||
314
lua/weapons/gmod_tool/stools/item_item_crate.lua
Normal file
314
lua/weapons/gmod_tool/stools/item_item_crate.lua
Normal 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
|
||||
418
lua/weapons/gmod_tool/stools/ladder.lua
Normal file
418
lua/weapons/gmod_tool/stools/ladder.lua
Normal 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;
|
||||
64
lua/weapons/gmod_tool/stools/nocollideworld.lua
Normal file
64
lua/weapons/gmod_tool/stools/nocollideworld.lua
Normal file
@@ -0,0 +1,64 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
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
|
||||
804
lua/weapons/gmod_tool/stools/particlecontrol.lua
Normal file
804
lua/weapons/gmod_tool/stools/particlecontrol.lua
Normal 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
|
||||
893
lua/weapons/gmod_tool/stools/particlecontrol_proj.lua
Normal file
893
lua/weapons/gmod_tool/stools/particlecontrol_proj.lua
Normal 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
|
||||
712
lua/weapons/gmod_tool/stools/particlecontrol_tracer.lua
Normal file
712
lua/weapons/gmod_tool/stools/particlecontrol_tracer.lua
Normal 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
|
||||
1643
lua/weapons/gmod_tool/stools/precision.lua
Normal file
1643
lua/weapons/gmod_tool/stools/precision.lua
Normal file
File diff suppressed because it is too large
Load Diff
619
lua/weapons/gmod_tool/stools/prop_door.lua
Normal file
619
lua/weapons/gmod_tool/stools/prop_door.lua
Normal 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
|
||||
196
lua/weapons/gmod_tool/stools/prop_thumper.lua
Normal file
196
lua/weapons/gmod_tool/stools/prop_thumper.lua
Normal 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
|
||||
480
lua/weapons/gmod_tool/stools/rb655_easy_animation.lua
Normal file
480
lua/weapons/gmod_tool/stools/rb655_easy_animation.lua
Normal 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" )
|
||||
208
lua/weapons/gmod_tool/stools/rb655_easy_bodygroup.lua
Normal file
208
lua/weapons/gmod_tool/stools/rb655_easy_bodygroup.lua
Normal 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
|
||||
108
lua/weapons/gmod_tool/stools/resizer.lua
Normal file
108
lua/weapons/gmod_tool/stools/resizer.lua
Normal 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
|
||||
492
lua/weapons/gmod_tool/stools/smartweld.lua
Normal file
492
lua/weapons/gmod_tool/stools/smartweld.lua
Normal 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
|
||||
317
lua/weapons/gmod_tool/stools/smoke.lua
Normal file
317
lua/weapons/gmod_tool/stools/smoke.lua
Normal file
@@ -0,0 +1,317 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
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
|
||||
218
lua/weapons/gmod_tool/stools/smoke_trail.lua
Normal file
218
lua/weapons/gmod_tool/stools/smoke_trail.lua
Normal 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
|
||||
261
lua/weapons/gmod_tool/stools/sparks.lua
Normal file
261
lua/weapons/gmod_tool/stools/sparks.lua
Normal 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
|
||||
1691
lua/weapons/gmod_tool/stools/stacker_improved.lua
Normal file
1691
lua/weapons/gmod_tool/stools/stacker_improved.lua
Normal file
File diff suppressed because it is too large
Load Diff
104
lua/weapons/gmod_tool/stools/starfield.lua
Normal file
104
lua/weapons/gmod_tool/stools/starfield.lua
Normal 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
|
||||
344
lua/weapons/gmod_tool/stools/steam.lua
Normal file
344
lua/weapons/gmod_tool/stools/steam.lua
Normal 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
|
||||
436
lua/weapons/gmod_tool/stools/submaterial.lua
Normal file
436
lua/weapons/gmod_tool/stools/submaterial.lua
Normal 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
|
||||
291
lua/weapons/gmod_tool/stools/tesla.lua
Normal file
291
lua/weapons/gmod_tool/stools/tesla.lua
Normal 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
|
||||
87
lua/weapons/gmod_tool/stools/test_tool_d2k.lua
Normal file
87
lua/weapons/gmod_tool/stools/test_tool_d2k.lua
Normal file
@@ -0,0 +1,87 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
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
|
||||
160
lua/weapons/gmod_tool/stools/unbreakable.lua
Normal file
160
lua/weapons/gmod_tool/stools/unbreakable.lua
Normal 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
|
||||
115
lua/weapons/gmod_tool/stools/vjstool_bullseye.lua
Normal file
115
lua/weapons/gmod_tool/stools/vjstool_bullseye.lua
Normal 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
|
||||
66
lua/weapons/gmod_tool/stools/vjstool_entityscanner.lua
Normal file
66
lua/weapons/gmod_tool/stools/vjstool_entityscanner.lua
Normal file
@@ -0,0 +1,66 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
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
|
||||
152
lua/weapons/gmod_tool/stools/vjstool_healthmodifier.lua
Normal file
152
lua/weapons/gmod_tool/stools/vjstool_healthmodifier.lua
Normal 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
|
||||
66
lua/weapons/gmod_tool/stools/vjstool_notarget.lua
Normal file
66
lua/weapons/gmod_tool/stools/vjstool_notarget.lua
Normal file
@@ -0,0 +1,66 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
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
|
||||
124
lua/weapons/gmod_tool/stools/vjstool_npcequipment.lua
Normal file
124
lua/weapons/gmod_tool/stools/vjstool_npcequipment.lua
Normal 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
|
||||
144
lua/weapons/gmod_tool/stools/vjstool_npcfollower.lua
Normal file
144
lua/weapons/gmod_tool/stools/vjstool_npcfollower.lua
Normal 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
|
||||
294
lua/weapons/gmod_tool/stools/vjstool_npcmover.lua
Normal file
294
lua/weapons/gmod_tool/stools/vjstool_npcmover.lua
Normal 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
|
||||
290
lua/weapons/gmod_tool/stools/vjstool_npcrelationship.lua
Normal file
290
lua/weapons/gmod_tool/stools/vjstool_npcrelationship.lua
Normal 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
|
||||
334
lua/weapons/gmod_tool/stools/vjstool_npcspawner.lua
Normal file
334
lua/weapons/gmod_tool/stools/vjstool_npcspawner.lua
Normal 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
|
||||
Reference in New Issue
Block a user