mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
228 lines
5.2 KiB
Lua
228 lines
5.2 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
local CurTime = CurTime
|
|
local ParticleEffect = ParticleEffect
|
|
|
|
local BUILDER, PART = pac.PartTemplate("base_drawable")
|
|
|
|
PART.ClassName = "effect"
|
|
PART.Groups = {'effects', 'model', 'entity'}
|
|
PART.Icon = 'icon16/wand.png'
|
|
|
|
BUILDER:StartStorableVars()
|
|
BUILDER:GetSet("Effect", "default", {enums = function() return pac.particle_list end})
|
|
BUILDER:GetSet("Loop", true)
|
|
BUILDER:GetSet("Follow", true)
|
|
BUILDER:GetSet("Rate", 1, {editor_sensitivity = 0.1})
|
|
BUILDER:GetSet("UseParticleTracer", false)
|
|
|
|
BUILDER:GetSetPart("PointA")
|
|
BUILDER:GetSetPart("PointB")
|
|
BUILDER:GetSetPart("PointC")
|
|
BUILDER:GetSetPart("PointD")
|
|
|
|
BUILDER:EndStorableVars()
|
|
|
|
BUILDER:RemoveProperty("Translucent")
|
|
PART.Translucent = false -- otherwise OnDraw won't be called
|
|
|
|
local BaseClass_GetOwner = PART.GetOwner
|
|
|
|
function PART:GetNiceName()
|
|
return pac.PrettifyName(self:GetEffect())
|
|
end
|
|
|
|
function PART:Initialize()
|
|
self:SetEffect(self.Effect)
|
|
|
|
if not pac.particle_list then
|
|
local found = {}
|
|
|
|
for file_name in pairs(pac_loaded_particle_effects) do
|
|
local ok, err = pcall(function()
|
|
local data = file.Read("particles/"..file_name, "GAME", "b")
|
|
if data then
|
|
for str in data:gmatch("\3%c([%a_]+)%c") do
|
|
if #str > 1 then
|
|
found[str] = str
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
if not ok then
|
|
local msg = "unable to parse particle file " .. file_name .. ": " .. err
|
|
self:SetError(msg)
|
|
pac.Message(Color(255, 50, 50), msg)
|
|
end
|
|
end
|
|
|
|
pac.particle_list = found
|
|
end
|
|
end
|
|
|
|
PART.last_spew = 0
|
|
|
|
if not pac_loaded_particle_effects then
|
|
pac_loaded_particle_effects = {}
|
|
|
|
for _, file_name in pairs(file.Find("particles/*.pcf", "GAME")) do
|
|
if not pac_loaded_particle_effects[file_name] and not pac.BlacklistedParticleSystems[file_name:lower()] then
|
|
game.AddParticles("particles/" .. file_name)
|
|
end
|
|
|
|
pac_loaded_particle_effects[file_name] = true
|
|
end
|
|
end
|
|
|
|
local already = {}
|
|
local alreadyServer = {}
|
|
local function pac_request_precache(name)
|
|
if already[name] then return end
|
|
already[name] = true
|
|
PrecacheParticleSystem(name)
|
|
net.Start("pac_request_precache")
|
|
net.WriteString(name)
|
|
net.SendToServer()
|
|
end
|
|
|
|
function PART:SetEffect(name)
|
|
self.waitingForServer = true
|
|
self.Effect = name
|
|
self.Ready = alreadyServer[name] or false
|
|
|
|
if not alreadyServer[name] then
|
|
pac_request_precache(name)
|
|
else
|
|
self.waitingForServer = false
|
|
end
|
|
end
|
|
|
|
pac.AddHook("pac_EffectPrecached", "pac_Effects", function(name)
|
|
if alreadyServer[name] then return end
|
|
alreadyServer[name] = true
|
|
pac.dprint("effect %q precached!", name)
|
|
pac.CallRecursiveOnAllParts("OnEffectPrecached", name)
|
|
end)
|
|
|
|
function PART:OnEffectPrecached(name)
|
|
if self.Effect == name then
|
|
self.Ready = true
|
|
self.waitingForServer = false
|
|
end
|
|
end
|
|
|
|
function PART:OnDraw()
|
|
if not self.Ready then
|
|
if not self.waitingForServer then
|
|
self:SetEffect(self.Effect)
|
|
end
|
|
return
|
|
end
|
|
|
|
local ent = self:GetOwner()
|
|
|
|
if ent:IsValid() and self.Loop then
|
|
local time = CurTime()
|
|
if self.last_spew < time then
|
|
local pos, ang = self:GetDrawPosition()
|
|
|
|
ent:StopParticles()
|
|
ent:StopParticleEmission()
|
|
self:Emit(pos, ang)
|
|
self.last_spew = time + math.max(self.Rate, 0.1)
|
|
end
|
|
end
|
|
end
|
|
|
|
function PART:OnHide()
|
|
local ent = self:GetOwner()
|
|
|
|
if ent:IsValid() then
|
|
ent:StopParticles()
|
|
ent:StopParticleEmission()
|
|
end
|
|
end
|
|
|
|
function PART:OnShow(from_rendering)
|
|
if from_rendering then
|
|
self:Emit(self:GetDrawPosition())
|
|
end
|
|
end
|
|
|
|
function PART:Emit(pos, ang)
|
|
local ent = self:GetOwner()
|
|
|
|
if ent:IsValid() then
|
|
if not self.Effect then
|
|
ent:StopParticles()
|
|
ent:StopParticleEmission()
|
|
return
|
|
end
|
|
|
|
if self.UseParticleTracer and self.PointA:IsValid() then
|
|
local ent2 = self.PointA.Entity and self.PointA.Entity or self.PointA:GetOwner()
|
|
|
|
util.ParticleTracerEx(
|
|
self.Effect,
|
|
ent:GetPos(),
|
|
ent2:GetPos(),
|
|
true,
|
|
ent:EntIndex(),
|
|
0
|
|
)
|
|
return
|
|
end
|
|
|
|
if self.PointA:IsValid() then
|
|
local points = {}
|
|
|
|
table.insert(points, {
|
|
entity = self.PointA.Entity and self.PointA.Entity or self.PointA:GetOwner(),
|
|
attachtype = PATTACH_ABSORIGIN_FOLLOW,
|
|
})
|
|
|
|
if self.PointB:IsValid() then
|
|
table.insert(points, {
|
|
entity = self.PointB.Entity and self.PointB.Entity or self.PointB:GetOwner(),
|
|
attachtype = PATTACH_ABSORIGIN_FOLLOW,
|
|
})
|
|
end
|
|
|
|
if self.PointC:IsValid() then
|
|
table.insert(points, {
|
|
entity = self.PointC.Entity and self.PointC.Entity or self.PointC:GetOwner(),
|
|
attachtype = PATTACH_ABSORIGIN_FOLLOW,
|
|
})
|
|
end
|
|
|
|
if self.PointD:IsValid() then
|
|
table.insert(points, {
|
|
entity = self.PointD.Entity and self.PointD.Entity or self.PointD:GetOwner(),
|
|
attachtype = PATTACH_ABSORIGIN_FOLLOW,
|
|
})
|
|
end
|
|
|
|
ent:CreateParticleEffect(self.Effect, points)
|
|
elseif self.Follow then
|
|
ent:StopParticles()
|
|
ent:StopParticleEmission()
|
|
CreateParticleSystem(ent, self.Effect, PATTACH_ABSORIGIN_FOLLOW, 0)
|
|
else
|
|
ent:StopParticles()
|
|
ent:StopParticleEmission()
|
|
ParticleEffect(self.Effect, pos, ang, ent)
|
|
end
|
|
end
|
|
end
|
|
|
|
BUILDER:Register()
|