Files
wnsrc/lua/pac3/core/client/parts/particles.lua
lifestorm 94063e4369 Upload
2024-08-04 22:55:00 +03:00

376 lines
10 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 cam_IgnoreZ = cam.IgnoreZ
local vector_origin = vector_origin
local FrameTime = FrameTime
local angle_origin = Angle(0,0,0)
local WorldToLocal = WorldToLocal
local BUILDER, PART = pac.PartTemplate("base_drawable")
PART.ClassName = "particles"
PART.Group = 'effects'
PART.Icon = 'icon16/water.png'
BUILDER:StartStorableVars()
BUILDER:SetPropertyGroup("generic")
BUILDER:PropertyOrder("Name")
BUILDER:PropertyOrder("Hide")
BUILDER:PropertyOrder("ParentName")
BUILDER:GetSet("Follow", false)
BUILDER:GetSet("Additive", false)
BUILDER:GetSet("FireOnce", false)
BUILDER:GetSet("FireDelay", 0.2)
BUILDER:GetSet("NumberParticles", 1)
BUILDER:GetSet("PositionSpread", 0)
BUILDER:GetSet("PositionSpread2", Vector(0,0,0))
BUILDER:GetSet("DieTime", 3)
BUILDER:GetSet("StartSize", 2)
BUILDER:GetSet("EndSize", 20)
BUILDER:GetSet("StartLength", 0)
BUILDER:GetSet("EndLength", 0)
BUILDER:GetSet("ParticleAngle", Angle(0,0,0))
BUILDER:GetSet("AddFrametimeLife", false)
BUILDER:SetPropertyGroup("stick")
BUILDER:GetSet("AlignToSurface", true)
BUILDER:GetSet("StickToSurface", true)
BUILDER:GetSet("StickLifetime", 2)
BUILDER:GetSet("StickStartSize", 20)
BUILDER:GetSet("StickEndSize", 0)
BUILDER:GetSet("StickStartAlpha", 255)
BUILDER:GetSet("StickEndAlpha", 0)
BUILDER:SetPropertyGroup("appearance")
BUILDER:GetSet("Material", "effects/slime1")
BUILDER:GetSet("StartAlpha", 255)
BUILDER:GetSet("EndAlpha", 0)
BUILDER:GetSet("Translucent", true)
BUILDER:GetSet("Color2", Vector(255, 255, 255), {editor_panel = "color"})
BUILDER:GetSet("Color1", Vector(255, 255, 255), {editor_panel = "color"})
BUILDER:GetSet("RandomColor", false)
BUILDER:GetSet("Lighting", true)
BUILDER:GetSet("3D", false)
BUILDER:GetSet("DoubleSided", true)
BUILDER:GetSet("DrawManual", false)
BUILDER:SetPropertyGroup("rotation")
BUILDER:GetSet("ZeroAngle",true)
BUILDER:GetSet("RandomRollSpeed", 0)
BUILDER:GetSet("RollDelta", 0)
BUILDER:GetSet("ParticleAngleVelocity", Vector(50, 50, 50))
BUILDER:SetPropertyGroup("orientation")
BUILDER:SetPropertyGroup("movement")
BUILDER:GetSet("Velocity", 250)
BUILDER:GetSet("Spread", 0.1)
BUILDER:GetSet("AirResistance", 5)
BUILDER:GetSet("Bounce", 5)
BUILDER:GetSet("Gravity", Vector(0,0, -50))
BUILDER:GetSet("Collide", true)
BUILDER:GetSet("Sliding", true)
--BUILDER:GetSet("AddVelocityFromOwner", false)
BUILDER:GetSet("OwnerVelocityMultiplier", 0)
BUILDER:EndStorableVars()
function PART:GetNiceName()
return pac.PrettifyName(("/".. self:GetMaterial()):match(".+/(.+)")) or "error"
end
local function RemoveCallback(particle)
particle:SetLifeTime(0)
particle:SetDieTime(0)
particle:SetStartSize(0)
particle:SetEndSize(0)
particle:SetStartAlpha(0)
particle:SetEndAlpha(0)
end
local function SlideCallback(particle, hitpos, normal)
particle:SetBounce(1)
local vel = particle:GetVelocity()
vel.z = 0
particle:SetVelocity(vel)
particle:SetPos(hitpos + normal)
end
local function StickCallback(particle, hitpos, normal)
particle:SetAngleVelocity(Angle(0, 0, 0))
if particle.Align then
local ang = normal:Angle()
ang:RotateAroundAxis(normal, particle:GetAngles().y)
particle:SetAngles(ang)
end
if particle.Stick then
particle:SetVelocity(Vector(0, 0, 0))
particle:SetGravity(Vector(0, 0, 0))
end
particle:SetLifeTime(0)
particle:SetDieTime(particle.StickLifeTime or 0)
particle:SetStartSize(particle.StickStartSize or 0)
particle:SetEndSize(particle.StickEndSize or 0)
particle:SetStartAlpha(particle.StickStartAlpha or 0)
particle:SetEndAlpha(particle.StickEndAlpha or 0)
end
function PART:GetEmitter()
if not self.emitter then
self.NextShot = 0
self.Created = pac.RealTime + 0.1
self.emitter = ParticleEmitter(vector_origin, self:Get3D())
end
return self.emitter
end
function PART:SetDrawManual(b)
self.DrawManual = b
self:GetEmitter():SetNoDraw(b)
end
function PART:SetNumberParticles(num)
self.NumberParticles = math.Clamp(num, 0, 100)
end
function PART:Set3D(b)
self["3D"] = b
self.emitter = nil
end
function PART:OnShow(from_rendering)
self.CanKeepFiring = true
self.FirstShot = true
if not from_rendering then
self.NextShot = 0
local pos, ang = self:GetDrawPosition()
self:EmitParticles(self.Follow and vector_origin or pos, self.Follow and angle_origin or ang, ang)
end
end
function PART:OnDraw()
if not self.FireOnce then self.CanKeepFiring = true end
local pos, ang = self:GetDrawPosition()
local emitter = self:GetEmitter()
emitter:SetPos(pos)
if self.DrawManual or self.IgnoreZ or self.Follow or self.BlendMode ~= "" then
if not self.nodraw then
emitter:SetNoDraw(true)
self.nodraw = true
end
if self.Follow then
cam.Start3D(WorldToLocal(EyePos(), EyeAngles(), pos, ang))
if self.IgnoreZ then cam.IgnoreZ(true) end
emitter:Draw()
if self.IgnoreZ then cam.IgnoreZ(false) end
cam.End3D()
else
emitter:Draw()
end
else
if self.nodraw then
self:SetDrawManual(self:GetDrawManual())
self.nodraw = false
end
end
self:EmitParticles(self.Follow and vector_origin or pos, self.Follow and angle_origin or ang, ang)
end
function PART:SetAdditive(b)
self.Additive = b
self:SetMaterial(self:GetMaterial())
end
function PART:SetMaterial(var)
var = var or ""
if not pac.Handleurltex(self, var, function(mat)
mat:SetFloat("$alpha", 0.999)
mat:SetInt("$spriterendermode", self.Additive and 5 or 1)
self.Materialm = mat
self:CallRecursive("OnMaterialChanged")
end, "Sprite") then
if var == "" then
self.Materialm = nil
else
self.Materialm = pac.Material(var, self)
self:CallRecursive("OnMaterialChanged")
end
end
self.Material = var
end
function PART:EmitParticles(pos, ang, real_ang)
if self.FireOnce and not self.FirstShot then self.CanKeepFiring = false end
local emt = self:GetEmitter()
if not emt then return end
if self.NextShot < pac.RealTime and self.CanKeepFiring then
if self.Material == "" then return end
if self.Velocity == 500.01 then return end
local originalAng = ang
ang = ang:Forward()
local double = 1
if self.DoubleSided then
double = 2
end
for _ = 1, self.NumberParticles do
local mats = self.Material:Split(";")
if #mats > 1 then
self.Materialm = pac.Material(table.Random(mats), self)
self:CallRecursive("OnMaterialChanged")
end
local vec = Vector()
if self.Spread ~= 0 then
vec = Vector(
math.sin(math.Rand(0, 360)) * math.Rand(-self.Spread, self.Spread),
math.cos(math.Rand(0, 360)) * math.Rand(-self.Spread, self.Spread),
math.sin(math.random()) * math.Rand(-self.Spread, self.Spread)
)
end
local color
if self.RandomColor then
color =
{
math.random(math.min(self.Color1.r, self.Color2.r), math.max(self.Color1.r, self.Color2.r)),
math.random(math.min(self.Color1.g, self.Color2.g), math.max(self.Color1.g, self.Color2.g)),
math.random(math.min(self.Color1.b, self.Color2.b), math.max(self.Color1.b, self.Color2.b))
}
else
color = {self.Color1.r, self.Color1.g, self.Color1.b}
end
local roll = math.Rand(-self.RollDelta, self.RollDelta)
if self.PositionSpread ~= 0 then
pos = pos + Angle(math.Rand(-180, 180), math.Rand(-180, 180), math.Rand(-180, 180)):Forward() * self.PositionSpread
end
do
local vecAdd = Vector(
math.Rand(-self.PositionSpread2.x, self.PositionSpread2.x),
math.Rand(-self.PositionSpread2.x, self.PositionSpread2.y),
math.Rand(-self.PositionSpread2.z, self.PositionSpread2.z)
)
vecAdd:Rotate(originalAng)
pos = pos + vecAdd
end
for i = 1, double do
local particle = emt:Add(self.Materialm or self.Material, pos)
if double == 2 then
local ang_
if i == 1 then
ang_ = (ang * -1):Angle()
elseif i == 2 then
ang_ = ang:Angle()
end
particle:SetAngles(ang_)
else
particle:SetAngles(ang:Angle())
end
if self.OwnerVelocityMultiplier ~= 0 then
local owner = self:GetRootPart():GetOwner()
if owner:IsValid() then
vec = vec + (owner:GetVelocity() * self.OwnerVelocityMultiplier)
end
end
particle:SetVelocity((vec + ang) * self.Velocity)
particle:SetColor(unpack(color))
particle:SetColor(unpack(color))
local life = math.Clamp(self.DieTime, 0.0001, 50)
if self.AddFrametimeLife then
life = life + FrameTime()
end
particle:SetDieTime(life)
particle:SetStartAlpha(self.StartAlpha)
particle:SetEndAlpha(self.EndAlpha)
particle:SetStartSize(self.StartSize)
particle:SetEndSize(self.EndSize)
particle:SetStartLength(self.StartLength)
particle:SetEndLength(self.EndLength)
if self.RandomRollSpeed ~= 0 then
particle:SetRoll(self.RandomRollSpeed * 36)
end
if self.RollDelta ~= 0 then
particle:SetRollDelta(self.RollDelta + roll)
end
particle:SetAirResistance(self.AirResistance)
particle:SetBounce(self.Bounce)
particle:SetGravity(self.Gravity)
if self.ZeroAngle then particle:SetAngles(Angle(0,0,0))
else particle:SetAngles(particle:GetAngles() + self.ParticleAngle) end
particle:SetLighting(self.Lighting)
if not self.Follow then
particle:SetCollide(self.Collide)
end
if self.Sliding then
particle:SetCollideCallback(SlideCallback)
end
if self["3D"] then
if not self.Sliding then
if i == 1 then
particle:SetCollideCallback(RemoveCallback)
else
particle:SetCollideCallback(StickCallback)
end
end
particle:SetAngleVelocity(Angle(self.ParticleAngleVelocity.x, self.ParticleAngleVelocity.y, self.ParticleAngleVelocity.z))
particle.Align = self.Align
particle.Stick = self.Stick
particle.StickLifeTime = self.StickLifeTime
particle.StickStartSize = self.StickStartSize
particle.StickEndSize = self.StickEndSize
particle.StickStartAlpha = self.StickStartAlpha
particle.StickEndAlpha = self.StickEndAlpha
end
end
end
self.NextShot = pac.RealTime + self.FireDelay
end
self.FirstShot = false
end
BUILDER:Register()