Files
wnsrc/addons/pillpack/lua/entities/pill_ent_costume.lua
lifestorm 6a58f406b1 Upload
2024-08-04 23:54:45 +03:00

946 lines
31 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/
--]]
AddCSLuaFile()
ENT.Type = "anim"
ENT.AutomaticFrameAdvance = true
function ENT:SetupDataTables()
self:NetworkVar("String", 0, "PillForm")
self:NetworkVar("Entity", 0, "PillUser")
self:NetworkVar("Entity", 1, "Puppet")
self:NetworkVar("Float", 0, "ChargeTime")
self:NetworkVar("Angle", 0, "ChargeAngs")
self:NetworkVar("Float", 1, "CloakLeft")
end
function ENT:Initialize()
self.formTable = pk_pills.getPillTable(self:GetPillForm())
local ply = self:GetPillUser()
if not self.formTable or not IsValid(ply) then
if SERVER then self:Remove() end
return
end
local hull = self.formTable.hull or Vector(32, 32, 72)
local duckBy = self.formTable.duckBy or (self.formTable.hull and 0 or 36)
ply:SetHull(-Vector(hull.x / 2, hull.y / 2, 0), Vector(hull.x / 2, hull.y / 2, hull.z))
ply:SetHullDuck(-Vector(hull.x / 2, hull.y / 2, 0), Vector(hull.x / 2, hull.y / 2, hull.z - duckBy or 0))
ply:SetRenderMode(RENDERMODE_NONE)
--Do this so weapon equips are not blocked
pk_pills.mapEnt(ply, nil)
if SERVER then
self:SetModel("models/Combine_Helicopter/helicopter_bomb01.mdl")
self:SetPos(ply:GetPos())
self:SetParent(ply)
self:DrawShadow(false)
ply:StripWeapons()
ply:RemoveAllAmmo()
if self.formTable.flies then
ply:SetMoveType(MOVETYPE_FLY)
else
ply:SetMoveType(MOVETYPE_WALK)
end
if ply:FlashlightIsOn() then
ply:Flashlight(false)
end
ply:Freeze(false)
ply:SetNotSolid(false)
ply:DrawViewModel(false)
--ply:DrawWorldModel(false)
local camOffset = self.formTable.camera and self.formTable.camera.offset or Vector(0, 0, 64)
--clside this?
ply:SetStepSize(hull.z / 4)
ply:SetViewOffset(camOffset)
ply:SetViewOffsetDucked(camOffset - Vector(0, 0, duckBy))
local speed = self.formTable.moveSpeed or {}
ply:SetWalkSpeed(speed.walk or 200)
ply:SetRunSpeed(speed.run or speed.walk or 500)
if speed.ducked then
ply:SetCrouchedWalkSpeed(speed.ducked / (speed.walk or 200))
elseif duckBy == 0 then
ply:SetCrouchedWalkSpeed(1)
else
ply:SetCrouchedWalkSpeed(.3)
end
ply:SetJumpPower(self.formTable.jumpPower or 200)
self.loopingSounds = {}
if self.formTable.sounds then
for k, v in pairs(self.formTable.sounds) do
if string.sub(k, 1, 5) == "loop_" then
self.loopingSounds[string.sub(k, 6)] = CreateSound(self, v)
elseif string.sub(k, 1, 5) == "auto_" and isstring(v) then
local func
func = function()
if IsValid(self) then
local f = self.formTable.sounds[k .. "_func"]
if not f then return end
local play, time = f(self:GetPillUser(), self)
if play then
self:PillSound(k)
end
timer.Simple(time, func)
end
end
func()
end
end
if self.loopingSounds.move then
self:PillLoopSound("move")
end
end
if self.formTable.health then
self:GetPillUser():SetHealth(self.formTable.health)
self:GetPillUser():SetMaxHealth(self.formTable.health)
else
self:GetPillUser():GodEnable()
end
ply:SetArmor(0)
if self.formTable.loadout then
for _, v in pairs(self.formTable.loadout) do
ply:Give(v)
end
end
if self.formTable.ammo then
for k, v in pairs(self.formTable.ammo) do
ply:SetAmmo(v, k)
end
end
--[[if self.formTable.seqInit then
self:PillAnim(self.formTable.seqInit,true)
end]]
--[[if self.formTable.bodyGroups then
for _,v in pairs(self.formTable.bodyGroups) do
self:SetBodygroup(v,1)
end
end]]
--self:SetPlaybackRate(1)
pk_pills.setAiTeam(ply, self.formTable.side or "default")
local model = self.formTable.model
local skin = self.formTable.skin
local attachments = self.formTable.attachments
if self.formTable.options then
local options = self.formTable.options()
if self.option and options[self.option] then
local pickedOption = options[self.option]
if pickedOption.model then
model = pickedOption.model
end
if pickedOption.skin then
skin = pickedOption.skin
end
if pickedOption.attachments then
attachments = pickedOption.attachments
end
else
local pickedOption = table.Random(options)
if not model then
model = pickedOption.model
end
if not skin then
skin = pickedOption.skin
end
if not attachments then
attachments = pickedOption.attachments
end
end
end
local puppet = ents.Create("pill_puppet")
puppet:SetModel(model or "models/Humans/corpse1.mdl")
if skin then
puppet:SetSkin(skin)
end
if attachments then
for _, mdl in pairs(attachments) do
local a = ents.Create("pill_attachment")
a:SetParent(puppet)
a:SetModel(mdl)
a:Spawn()
end
end
if self.formTable.visColor then
puppet:SetColor(self.formTable.visColor)
elseif self.formTable.visColorRandom then
puppet:SetColor(HSVToColor(math.Rand(0, 360), 1, 1))
end
if self.formTable.visMat then
puppet:SetMaterial(self.formTable.visMat)
end
if self.formTable.bodyGroups then
for _, v in pairs(self.formTable.bodyGroups) do
if v then
puppet:SetBodygroup(v, 1)
end
end
end
if self.formTable.modelScale then
puppet:SetModelScale(self.formTable.modelScale, .1)
end
if self.formTable.boneMorphs then
for k, v in pairs(self.formTable.boneMorphs) do
local b = puppet:LookupBone(k)
if b then
if v.pos then
puppet:ManipulateBonePosition(b, v.pos)
end
if v.rot then
puppet:ManipulateBoneAngles(b, v.rot)
end
if v.scale then
puppet:ManipulateBoneScale(b, v.scale)
end
end
end
end
if self.formTable.cloak then
self:SetCloakLeft(self.formTable.cloak.max)
end
--puppet:SetParent(self)
puppet:Spawn()
self:DeleteOnRemove(puppet)
self:SetPuppet(puppet)
end
pk_pills.mapEnt(ply, self)
--self:SetPlaybackRate(1)
end
function ENT:OnRemove()
local ply = self:GetPillUser()
if SERVER then
self:PillLoopStopAll()
end
local newType = pk_pills.unmapEnt(self:GetPillUser(), self)
if newType ~= "ply" and IsValid(ply) then
ply:ResetHull()
if SERVER then
ply:SetViewOffset(Vector(0, 0, 64))
ply:SetViewOffsetDucked(Vector(0, 0, 28))
ply:SetStepSize(18)
-- Not sure if this chunk is needed... leaving it for now.
ply:Freeze(false)
if ply:Alive() then
ply:SetMoveType(MOVETYPE_WALK)
end
ply:SetNotSolid(false)
if ply:Alive() then
-- Just respawn the player to reset most stuff.
local angs = ply:EyeAngles()
local pos = ply:GetPos()
local vel = ply:GetVelocity()
local hp = ply:Health()
ply:StripWeapons()
ply:StripAmmo()
ply:Spawn()
ply:SetEyeAngles(angs)
ply:SetPos(pos)
ply:SetVelocity(vel)
ply:SetHealth(hp)
end
if not newType then
ply:SetRenderMode(RENDERMODE_NORMAL)
pk_pills.setAiTeam(ply, "default")
end
elseif not newType then
if ply == LocalPlayer() then
if ply.pk_pill_gmpEnabled then
ply.pk_pill_gmpEnabled = nil
--RunConsoleCommand("gmp_enabled","1")
end
--ply.ShouldDisableLegs=nil
end
end
end
end
function ENT:Think()
local ply = self:GetPillUser()
local puppet = self:GetPuppet()
if not IsValid(puppet) or not IsValid(ply) then return end
local vel = ply:GetVelocity():Length()
if SERVER then
--Anims
local anims = table.Copy(self.formTable.anims.default or {})
table.Merge(anims, (IsValid(ply:GetActiveWeapon()) and self.formTable.anims[ply:GetActiveWeapon():GetHoldType()]) or (self.forceAnimSet and self.formTable.anims[self.forceAnimSet]) or {})
local anim
--local useSeqVel=true
local overrideRate
if (not self.anim or not anims[self.anim]) then
self.animFreeze = nil
self.animStart = nil
end
if self.animFreeze and not self.plyFrozen then
ply:SetWalkSpeed(ply:GetWalkSpeed() / 2)
ply:SetRunSpeed(ply:GetWalkSpeed() / 2)
self.plyFrozen = true
elseif not self.animFreeze and self.plyFrozen then
local speed = self.formTable.moveSpeed or {}
ply:SetWalkSpeed(speed.walk or 200)
ply:SetRunSpeed(speed.run or speed.walk or 500)
self.plyFrozen = nil
end
if self.anim and anims[self.anim] then
anim = anims[self.anim]
overrideRate = anims[self.anim .. "_rate"] or 1
local cycle = puppet:GetCycle()
if not self.animStart then
if cycle == 1 or (self.animCycle and self.animCycle > cycle) or (string.lower(anim) ~= string.lower(puppet:GetSequenceName(puppet:GetSequence()))) then
self.anim = nil
self.animCycle = nil
if self.animFreeze then
self.animFreeze = nil
end
elseif self.animCycle then
self.animCycle = cycle
end
end
elseif self.tickAnim and anims[self.tickAnim] then
anim = anims[self.tickAnim]
overrideRate = anims[self.tickAnim .. "_rate"] or 1
self.tickAnim = nil
elseif self.burrowed then
anim = anims["burrow_loop"]
elseif ply:WaterLevel() > 2 then
anim = anims["swim"] or anims["glide"] or anims["idle"]
elseif ply:IsOnGround() then
if ply:Crouching() then
if vel > ply:GetCrouchedWalkSpeed() / 4 then
anim = anims["crouch_walk"] or anims["crouch"] or anims["walk"] or anims["idle"]
else
anim = anims["crouch"] or anims["idle"]
end
else
if vel > (ply:GetWalkSpeed() + ply:GetRunSpeed()) / 2 then
anim = anims["run"] or anims["walk"] or anims["idle"]
elseif vel > ply:GetWalkSpeed() / 4 then
anim = anims["walk"] or anims["idle"]
else
anim = anims["idle"]
end
end
else
anim = anims["glide"] or anims["idle"]
end
if anim == anims["idle"] or anim == anims["crouch"] then
overrideRate = 1
end
if (anim and puppet:GetSequence() ~= puppet:LookupSequence(anim)) or self.animStart or (self.formTable.autoRestartAnims and puppet:GetCycle() == 1) then
puppet:ResetSequence(puppet:LookupSequence(anim))
puppet:SetCycle(0)
self.animCycle = 0
end
self.animStart = nil
local seq_vel = puppet:GetSequenceGroundSpeed(puppet:GetSequence())
--if true then
if self.formTable.movePoseMode ~= "xy" and self.formTable.movePoseMode ~= "xy-bot" and not overrideRate then
local rate = overrideRate or vel / seq_vel
--goofy limitation (floods console with errors if above 12!)
if rate > 12 then
rate = 12
end
puppet:SetPlaybackRate(rate)
else
--puppet:SetPlaybackRate(1)
end
--print(puppet:GetCycle())
if self.formTable.movePoseMode then
--
if self.formTable.movePoseMode == "yaw" then
local move_dir = puppet:WorldToLocalAngles(ply:GetVelocity():Angle())
puppet:SetPoseParameter("move_yaw", move_dir.y)
elseif self.formTable.movePoseMode == "xy" then
if not overrideRate then
local localvel = ply:WorldToLocal(ply:GetPos() + ply:GetVelocity())
local maxdim = math.Max(math.abs(localvel.x), math.abs(localvel.y))
local clampedvel = maxdim == 0 and Vector(0, 0, 0) or localvel / maxdim
puppet:SetPoseParameter("move_x", clampedvel.x)
puppet:SetPoseParameter("move_y", -clampedvel.y)
seq_vel = puppet:GetSequenceGroundSpeed(puppet:GetSequence())
if seq_vel ~= 0 then
puppet:SetPoseParameter("move_x", math.Clamp(localvel.x / seq_vel, -.99, .99))
puppet:SetPoseParameter("move_y", math.Clamp(-localvel.y / seq_vel, -.99, .99))
end
--print(puppet:GetPlaybackRate())
else
puppet:SetPoseParameter("move_x", 0)
puppet:SetPoseParameter("move_y", 0)
end
elseif self.formTable.movePoseMode == "xy-bot" then
if not overrideRate then
local localvel = ply:WorldToLocal(ply:GetPos() + ply:GetVelocity())
local maxdim = math.Max(math.abs(localvel.x), math.abs(localvel.y))
local clampedvel = maxdim == 0 and Vector(0, 0, 0) or localvel / maxdim
local move_dir = puppet:WorldToLocalAngles(ply:GetVelocity():Angle())
puppet:SetPoseParameter("move_x", clampedvel.x)
puppet:SetPoseParameter("move_y", -clampedvel.y)
puppet:SetPoseParameter("move_yaw", move_dir.y)
puppet:SetPoseParameter("move_scale", 1)
seq_vel = puppet:GetSequenceGroundSpeed(puppet:GetSequence())
if seq_vel ~= 0 then
puppet:SetPoseParameter("move_x", math.Clamp(localvel.x / seq_vel, -.99, .99))
puppet:SetPoseParameter("move_y", math.Clamp(-localvel.y / seq_vel, -.99, .99))
puppet:SetPoseParameter("move_scale", math.Clamp(localvel:Length() / seq_vel, -.99, .99))
end
--print(puppet:GetPlaybackRate())
else
puppet:SetPoseParameter("move_x", 0)
puppet:SetPoseParameter("move_y", 0)
puppet:SetPoseParameter("move_yaw", 0)
puppet:SetPoseParameter("move_scale", 0)
end
end
end
--Aimage
if self.formTable.aim then
if self.formTable.aim.xPose then
local yaw = math.AngleDifference(ply:EyeAngles().y, puppet:GetAngles().y)
if self.formTable.aim.xInvert then
yaw = -yaw
end
puppet:SetPoseParameter(self.formTable.aim.xPose, yaw)
end
if self.formTable.aim.yPose then
local pitch = math.AngleDifference(ply:EyeAngles().p, puppet:GetAngles().p)
if self.formTable.aim.yInvert then
pitch = -pitch
end
puppet:SetPoseParameter(self.formTable.aim.yPose, pitch)
end
end
--gliding and landing
if not ply:IsOnGround() and ply:WaterLevel() == 0 and self.formTable.glideThink then
self.formTable.glideThink(ply, self)
end
if not ply:IsOnGround() and not self.touchingWater and ply:WaterLevel() > 0 and self.formTable.land then
self.formTable.land(ply, self)
end
--water death
self.touchingWater = ply:WaterLevel() > 1
if (self.formTable.damageFromWater and self.touchingWater) then
if self.formTable.damageFromWater == -1 then
--self:PillDie()
ply:Kill()
else
ply:TakeDamage(self.formTable.damageFromWater)
--TODO APPLY DAMAGE
end
end
--tick attack
if ply:KeyDown(IN_ATTACK) and self.formTable.attack and self.formTable.attack.mode == "tick" then
self.formTable.attack.func(ply, self, self.formTable.attack)
end
if ply:KeyDown(IN_ATTACK2) and self.formTable.attack2 and self.formTable.attack2.mode == "tick" then
self.formTable.attack2.func(ply, self, self.formTable.attack2)
end
--auto attack
if ply:KeyDown(IN_ATTACK) and self.formTable.attack and self.formTable.attack.mode == "auto" then
if not self.formTable.aim then
self:PillLoopSound("attack")
else
self:PillLoopStop("attack")
end
if (not self.lastAttack or (self.formTable.attack.interval or self.formTable.attack.delay) < CurTime() - self.lastAttack) then
self.formTable.attack.func(ply, self, self.formTable.attack)
self.lastAttack = CurTime()
end
else
self:PillLoopStop("attack")
end
if ply:KeyDown(IN_ATTACK2) and self.formTable.attack2 and self.formTable.attack2.mode == "auto" then
if not self.formTable.aim then
self:PillLoopSound("attack2")
else
self:PillLoopStop("attack2")
end
if not self.lastAttack2 or (self.formTable.attack2.interval or self.formTable.attack2.delay) < CurTime() - self.lastAttack2 then
self.formTable.attack2.func(ply, self, self.formTable.attack2)
self.lastAttack2 = CurTime()
end
else
self:PillLoopStop("attack2")
end
--charge
if self:GetChargeTime() ~= 0 then
if ply:OnGround() then
local charge = self.formTable.charge
local angs = ply:EyeAngles()
self:PillAnimTick("charge_loop")
local hit_ent = ply:TraceHullAttack(ply:EyePos(), ply:EyePos() + angs:Forward() * 100, Vector(-20, -20, -20), Vector(20, 20, 20), charge.dmg, DMG_CRUSH, 1, true)
if IsValid(hit_ent) then
self:PillAnim("charge_hit", true)
self:PillGesture("charge_hit")
self:PillSound("charge_hit")
self:SetChargeTime(0)
self:PillLoopStop("charge")
end
else
self:SetChargeTime(0)
self:PillLoopStop("charge")
end
end
--Cloak
if self.formTable.cloak then
local cloak = self.formTable.cloak
if self.iscloaked then
local cloakamt = self:GetCloakLeft()
if cloakamt ~= -1 then
cloakamt = cloakamt - FrameTime()
if cloakamt < 0 then
cloakamt = 0
self:ToggleCloak()
end
self:SetCloakLeft(cloakamt)
end
else
local cloakamt = self:GetCloakLeft()
if cloakmt ~= -1 and cloakamt < cloak.max then
cloakamt = cloakamt + FrameTime() * cloak.rechargeRate
if cloakamt > cloak.max then
cloakamt = cloak.max
end
self:SetCloakLeft(cloakamt)
end
end
local color = self:GetPuppet():GetColor()
if self.iscloaked then
if color.a > 0 then
color.a = color.a - 5
self:GetPuppet():SetColor(color)
end
else
if color.a < 255 then
color.a = color.a + 5
self:GetPuppet():SetColor(color)
end
end
--PrintTable(color)
if IsValid(self.wepmdl) and self.wepmdl:GetColor().a ~= color.a then
self.wepmdl:SetColor(color)
end
end
--if !IsValid(ply) then self:NextThink(CurTime()) return true end
--wepon-no longer SO hackey
if not self.formTable.hideWeapons then
local realWep = self:GetPillUser():GetActiveWeapon()
--&&self:GetPillUser()!=ply or pk_pills.var_thirdperson:GetBool()) then
if IsValid(realWep) and realWep:GetModel() ~= "" then
--hiding the real thing [BROKEN]
--[[if realWep:GetRenderMode()!=RENDERMODE_NONE then
realWep:SetRenderMode(RENDERMODE_NONE)
end]]
if realWep.pill_attachment then
if IsValid(self.wepmdl) then
self.wepmdl:Remove()
end
self.wepmdl = ents.Create("pill_attachment_wep")
self.wepmdl:SetParent(self:GetPuppet())
self.wepmdl:SetModel(realWep:GetModel())
self.wepmdl.attachment = realWep.pill_attachment
self.wepmdl:Spawn()
if realWep.pill_offset then
self.wepmdl:SetWepOffset(realWep.pill_offset)
end
if realWep.pill_angle then
self.wepmdl:SetWepAng(realWep.pill_angle)
end
realWep.pill_proxy = self.wepmdl
elseif not IsValid(self.wepmdl) then
self.wepmdl = ents.Create("pill_attachment_wep")
self.wepmdl:SetParent(self:GetPuppet())
self.wepmdl:SetModel(realWep:GetModel())
self.wepmdl:Spawn()
realWep.pill_proxy = self.wepmdl
elseif self.wepmdl:GetModel() ~= realWep:GetModel() then
self.wepmdl:SetModel(realWep:GetModel())
end
elseif IsValid(self.wepmdl) then
self.wepmdl:Remove()
end
end
else
if self:GetPillUser() ~= LocalPlayer() or pk_pills.convars.cl_thirdperson:GetBool() then
puppet:SetNoDraw(false)
else
puppet:SetNoDraw(true)
end
local realWep = self:GetPillUser():GetActiveWeapon()
if IsValid(realWep) and realWep:GetModel() ~= "" and not realWep:GetNoDraw() then
realWep:SetNoDraw(true)
end
end
--Align pos and angles with player
if SERVER then
puppet:SetPos(ply:GetPos())
else
puppet:SetRenderOrigin(ply:GetPos())
end
if vel > 0 or math.abs(math.AngleDifference(puppet:GetAngles().y, ply:EyeAngles().y)) > 60 then
local angs = ply:EyeAngles()
angs.p = 0
if SERVER then
puppet:SetAngles(angs)
else
--puppet:SetAngles(angs)
puppet:SetRenderAngles(angs)
end
end
self:NextThink(CurTime())
return true
end
if SERVER then
function ENT:DoKeyPress(ply, key)
if self.animFreeze then return end
if self:GetChargeTime() ~= 0 then
self:SetChargeTime(0)
self:PillLoopStop("charge")
return
end
if key == IN_ATTACK and self.formTable.attack and self.formTable.attack.mode == "trigger" then
self.formTable.attack.func(ply, self, self.formTable.attack)
end
if key == IN_ATTACK2 and self.formTable.attack2 and self.formTable.attack2.mode == "trigger" then
self.formTable.attack2.func(ply, self, self.formTable.attack2)
end
if key == IN_RELOAD and self.formTable.reload then
self.formTable.reload(ply, self)
end
if key == IN_DUCK then
if self.formTable.canBurrow then
if not self.burrowed then
local trace = util.QuickTrace(ply:GetPos(), Vector(0, 0, -1), ply)
if trace.Hit and (trace.MatType == MAT_DIRT or trace.MatType == MAT_SAND or trace.MatType == MAT_GRASS) then
self:PillAnim("burrow_in")
self:PillSound("burrow_in")
ply:SetLocalVelocity(Vector(0, 0, 0))
ply:SetMoveType(MOVETYPE_NONE)
ply:SetNotSolid(true)
self.burrowed = true
self:GetPuppet():DrawShadow(false)
--local p=ply:GetPos()
--ent:SetPos(Vector(p.x,p.y,trace.HitPos.z-options.burrow))
--ent:SetMoveType(MOVETYPE_NONE)
--if ent.formTable.model then ent:SetModel(ent.formTable.model) end
--ent:PillSound("burrow")
--ent:PillLoopStopAll()
end
else
self:PillAnim("burrow_out")
self:PillSound("burrow_out")
ply:SetMoveType(MOVETYPE_WALK)
ply:SetNotSolid(false)
self.burrowed = nil
self:GetPuppet():DrawShadow(true)
end
end
end
end
function ENT:DoJump()
if self.formTable.jump then
self.formTable.jump(self:GetPillUser(), self)
end
end
function ENT:PillDie()
local ply = self:GetPillUser()
if self.formTable.die then
self.formTable.die(ply, self)
end
self:PillSound("die")
if IsValid(self:GetPuppet()) and not self.formTable.noragdoll then
local r = ents.Create("prop_ragdoll")
r:SetModel(self.subModel or self:GetPuppet():GetModel())
r:SetPos(ply:GetPos())
r:SetAngles(ply:GetAngles())
--r:SetOwner(ply)
r:Spawn()
r:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
r:Fire("FadeAndRemove", nil, 10)
end
self:Remove()
pk_pills.handeDeathCommon(self)
end
--[[function ENT:PillDie()
if self.dead then return end
self:GetPillUser():KillSilent()
if self.formTable.die then
self.formTable.die(self:GetPillUser(),self)
end
self:PillSound("die")
self:Remove()
self.dead=true
end]]
function ENT:PillAnim(name, freeze)
self.anim = name
self.animStart = true
self.animFreeze = true
end
function ENT:PillAnimTick(name)
self.tickAnim = name
end
function ENT:PillGesture(name)
local ply = self:GetPillUser()
local puppet = self:GetPuppet()
if not IsValid(puppet) then return end
local anims = table.Copy(self.formTable.anims.default or {})
table.Merge(anims, IsValid(ply:GetActiveWeapon()) and self.formTable.anims[ply:GetActiveWeapon():GetHoldType()] or {})
local gesture = anims["g_" .. name]
if gesture then
puppet:RestartGesture(puppet:GetSequenceActivity(puppet:LookupSequence(gesture)))
end
end
function ENT:PillChargeAttack()
if not self:GetPillUser():OnGround() or self.burrowed then return end
self:PillAnim("charge_start", true)
self:PillSound("charge_start")
local function doStart()
if not IsValid(self) then return end
self:SetChargeTime(CurTime())
local angs = self:GetPillUser():EyeAngles()
angs.p = 0
self:SetChargeAngs(angs)
self:PillLoopSound("charge")
end
if self.formTable.charge.delay then
timer.Simple(self.formTable.charge.delay, doStart)
else
doStart()
end
end
function ENT:PillFilterCam(ent)
net.Start("pk_pill_filtercam")
net.WriteEntity(self)
net.WriteEntity(ent)
net.Send(self:GetPillUser())
end
else
function ENT:GetPillHealth()
return self:GetPillUser():Health()
end
end
--The "bulk" parameter should only be used if you plan to play a ton of sounds in quick succession.
function ENT:PillSound(name, bulk)
if not self.formTable.sounds then return end
local s = self.formTable.sounds[name]
if (istable(s)) then
s = table.Random(s)
end
if isstring(s) then
if bulk then
sound.Play(s, self:GetPos(), self.formTable.sounds[name .. "_level"] or (name == "step" and 75 or 100), self.formTable.sounds[name .. "_pitch"] or 100, 1)
else
self:EmitSound(s, self.formTable.sounds[name .. "_level"] or (name == "step" and 75 or 100), self.formTable.sounds[name .. "_pitch"] or 100)
end
return true
end
end
function ENT:PillLoopSound(name, volume, pitch)
if not self.loopingSounds[name] then return end
local s = self.loopingSounds[name]
if s:IsPlaying() then
if volume then
s:ChangeVolume(volume)
end
if pitch then
s:ChangePitch(pitch, .1)
end
else
if volume or pitch then
s:PlayEx(volume or 1, pitch or 100)
else
s:Play()
end
end
end
function ENT:PillLoopStop(name)
if not self.loopingSounds[name] then return end
local s = self.loopingSounds[name]
s:FadeOut(.1)
end
function ENT:PillLoopStopAll()
if self.loopingSounds then
for _, v in pairs(self.loopingSounds) do
v:Stop()
end
end
end
function ENT:ToggleCloak()
local ply = self:GetPillUser()
if self.iscloaked then
self.iscloaked = nil
self:PillSound("uncloak")
pk_pills.setAiTeam(ply, self.formTable.side or "default")
else
local cloakleft = self:GetCloakLeft()
if cloakleft > 0 or cloakleft == -1 then
self.iscloaked = true
self:PillSound("cloak")
pk_pills.setAiTeam(ply, "harmless")
end
end
end
function ENT:Draw()
--Align pos and angles with player
--[[local puppet = self:GetPuppet()
local ply = self:GetPillUser()
local vel=ply:GetVelocity():Length()
if IsValid(puppet) then
puppet:SetRenderOrigin(ply:GetPos())
if vel>0||math.abs(math.AngleDifference(puppet:GetAngles().y,ply:EyeAngles().y))>60 then
local angs=ply:EyeAngles()
angs.p=0
puppet:SetRenderAngles(angs)
end
end
puppet:DrawModel()]]
end