Залив
This commit is contained in:
44
lua/entities/mg_40mm/cl_init.lua
Normal file
44
lua/entities/mg_40mm/cl_init.lua
Normal file
@@ -0,0 +1,44 @@
|
||||
include("shared.lua")
|
||||
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
ENT.bTracerOn = false
|
||||
|
||||
ENT.OuterFlairColor = Color(236,153,17,255)
|
||||
ENT.InnerFlairColor = Color(255,255,255,255)
|
||||
|
||||
ENT.OuterFlairScale = 1
|
||||
ENT.InnerFlairScale = 0.3
|
||||
|
||||
local flair = Material("shadowdark/flairs/grenade_flair.vmt")
|
||||
|
||||
function ENT:DrawTranslucent(flags)
|
||||
if (self:GetVelocity():LengthSqr() > 0 || self:GetNailed()) then
|
||||
self:DrawModel()
|
||||
|
||||
local ang = LocalPlayer():EyeAngles()
|
||||
local angle = Angle( 0, LocalPlayer():EyeAngles()[2], 0 )
|
||||
|
||||
angle = Angle(LocalPlayer():EyeAngles()[1], angle.y, 0 )
|
||||
|
||||
angle:RotateAroundAxis( angle:Up(), -90 )
|
||||
angle:RotateAroundAxis( angle:Forward(), 90 )
|
||||
|
||||
|
||||
cam.Start3D2D( self:GetPos() - self:GetForward() * 5, angle, 0.2 )
|
||||
|
||||
local OuterScale = 512 * self.OuterFlairScale
|
||||
local InnerScale = 512 * self.InnerFlairScale
|
||||
|
||||
surface.SetMaterial(flair)
|
||||
surface.SetDrawColor(self.OuterFlairColor)
|
||||
surface.DrawTexturedRect(-OuterScale/2, -OuterScale/2, OuterScale, OuterScale)
|
||||
|
||||
surface.SetDrawColor(self.InnerFlairColor)
|
||||
surface.DrawTexturedRect(-InnerScale/2, -InnerScale/2, InnerScale, InnerScale)
|
||||
cam.End3D2D()
|
||||
|
||||
if (!self.bTracerOn) then
|
||||
self.bTracerOn = true
|
||||
end
|
||||
end
|
||||
end
|
||||
134
lua/entities/mg_40mm/init.lua
Normal file
134
lua/entities/mg_40mm/init.lua
Normal file
@@ -0,0 +1,134 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.bCollided = false
|
||||
ENT.Projectile = {
|
||||
Class = "mg_bullet",
|
||||
Speed = 4000,
|
||||
Gravity = 1
|
||||
}
|
||||
ENT.Maxs = Vector(1, 1, 1)
|
||||
ENT.Model = Model("models/items/ar2_grenade.mdl")
|
||||
ENT.AoeEntity = nil
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel(self.Model)
|
||||
self:PhysicsInitBox(Vector(-10, -1, -1), Vector(10, 1, 1))
|
||||
self:GetPhysicsObject():Wake()
|
||||
self:GetPhysicsObject():SetMaterial("default_silent")
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_PLAYER_PICKUP)
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_IMPACT_DMG)
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_HEAVY_OBJECT)
|
||||
self:GetPhysicsObject():EnableMotion(true)
|
||||
self:GetPhysicsObject():EnableDrag(false)
|
||||
self:GetPhysicsObject():SetMass(1000)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_IN_VEHICLE) --doesn't collide with anything, no traces
|
||||
self:AddEFlags(EFL_NO_DAMAGE_FORCES)
|
||||
self:AddEFlags(EFL_DONTWALKON)
|
||||
self:AddEFlags(EFL_DONTBLOCKLOS)
|
||||
self:AddEFlags(EFL_NO_PHYSCANNON_INTERACTION)
|
||||
|
||||
self.Projectile = table.Copy(self.Weapon.Projectile)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(self:GetAngles():Forward() * self.Projectile.Speed)
|
||||
self.LastPos = self:GetOwner():EyePos()
|
||||
self.Bullet = self.Weapon.Bullet
|
||||
self.ImpactDamage = self.Weapon.Explosive.ImpactBlastRatio
|
||||
self.BlastRadius = self.Weapon.Explosive.BlastRadius
|
||||
end
|
||||
|
||||
ENT.m_gravity = 0
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if (!phys:IsMotionEnabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
self.m_gravity = math.Clamp(self.m_gravity + (self.Projectile.Gravity), -90, 90)
|
||||
|
||||
phys:SetAngles(phys:GetAngles() + Angle(self.m_gravity, 0, 0) * FrameTime())
|
||||
phys:SetPos(self.LastPos + phys:GetAngles():Forward() * (self.Projectile.Speed * FrameTime()))
|
||||
|
||||
--Aim assist
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Box(phys:GetPos(), -self.Maxs, self.Maxs, 0, Color(0, 200, 50, 10))
|
||||
end
|
||||
|
||||
local trData = {
|
||||
start = self.LastPos,
|
||||
endpos = phys:GetPos(),
|
||||
filter = {self:GetOwner(), self},
|
||||
mask = MASK_SHOT_PORTAL,
|
||||
collisiongroup = COLLISION_GROUP_NONE,
|
||||
mins = -self.Maxs,
|
||||
maxs = self.Maxs
|
||||
}
|
||||
|
||||
local tr = util.TraceHull(trData)
|
||||
|
||||
if (tr.Hit && (tr.Entity:IsPlayer() || tr.Entity:IsNPC())) then
|
||||
self:Impact(tr, phys, true)
|
||||
return
|
||||
end
|
||||
|
||||
--Normal hitscan
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Line(self.LastPos, phys:GetPos(), 1, Color(255, 0, 0, 1))
|
||||
end
|
||||
|
||||
tr = util.TraceLine(trData)
|
||||
|
||||
if (tr.Hit) then
|
||||
self:Impact(tr, phys, false)
|
||||
return
|
||||
end
|
||||
|
||||
self.LastPos = phys:GetPos()
|
||||
end
|
||||
|
||||
function ENT:Impact(tr1, phys, bHull)
|
||||
phys:EnableMotion(false)
|
||||
|
||||
self:SetPos(tr1.HitPos)
|
||||
|
||||
self:FireBullets({
|
||||
Attacker = self:GetOwner(),
|
||||
Num = 1,
|
||||
Tracer = 0,
|
||||
Src = self.LastPos,
|
||||
Dir = (phys:GetPos() - self.LastPos):GetNormalized(),
|
||||
HullSize = bHull && self.Maxs:Length() * 2 || 1,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(attacker, tr, dmgInfo)
|
||||
dmgInfo:SetInflictor(IsValid(self.Weapon) && self.Weapon || self)
|
||||
dmgInfo:SetDamageType(dmgInfo:GetDamageType() + DMG_DIRECT + self:GetDamageType())
|
||||
|
||||
if (IsValid(self.Weapon)) then
|
||||
self.Weapon:BulletCallback(attacker, tr, dmgInfo)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
local dmg = DamageInfo()
|
||||
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamage(self.Bullet.Damage[1])
|
||||
dmg:SetDamageType(DMG_BLAST + DMG_AIRBOAT)
|
||||
dmg:SetReportedPosition(self:GetPos())
|
||||
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.BlastRadius)
|
||||
util.ScreenShake(self:GetPos(), 3500, 1111, 1, 124 * 4)
|
||||
|
||||
ParticleEffect("Generic_explo_high", self:GetPos(), self:GetAngles())
|
||||
self:EmitSound("^viper/shared/frag_expl.ogg", 0, 100, 1, CHAN_WEAPON)
|
||||
util.Decal("Scorch", self:GetPos(), self:GetPos() + self:GetUp() * -100, {self})
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:GetDamageType()
|
||||
return DMG_BLAST + DMG_DIRECT
|
||||
end
|
||||
39
lua/entities/mg_40mm/shared.lua
Normal file
39
lua/entities/mg_40mm/shared.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_trail")
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.Hit",
|
||||
channel = CHAN_BODY,
|
||||
volume = 1,
|
||||
level = 85,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/bullet_small_crossbow_bolt_swt_01.ogg", "viper/shared/bullet_small_crossbow_bolt_swt_02.ogg", "viper/shared/bullet_small_crossbow_bolt_swt_03.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.HitBody",
|
||||
channel = CHAN_BODY,
|
||||
volume = 1,
|
||||
level = 85,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/bullet_flesh_plr_head_01.ogg", "viper/shared/bullet_flesh_plr_head_02.ogg", "viper/shared/bullet_flesh_plr_head_03.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.Skewer",
|
||||
channel = CHAN_ITEM,
|
||||
volume = 1,
|
||||
level = 85,
|
||||
pitch = {95, 105},
|
||||
sound = {"weapons/crossbow/bolt_skewer1.wav"}
|
||||
})
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "Nailed")
|
||||
end
|
||||
52
lua/entities/mg_aoe_arrow_explosion/cl_init.lua
Normal file
52
lua/entities/mg_aoe_arrow_explosion/cl_init.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_aoe_arrow_explosion", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
|
||||
local BaseClass = baseclass.Get(ENT.Base)
|
||||
|
||||
function ENT:Beep()
|
||||
local dlight = DynamicLight(self:EntIndex())
|
||||
dlight.pos = self:GetPos()
|
||||
dlight.r = 15
|
||||
dlight.g = 255
|
||||
dlight.b = 15
|
||||
dlight.brightness = -1
|
||||
dlight.Decay = 1000
|
||||
dlight.Size = 256
|
||||
dlight.DieTime = CurTime() + 0.1
|
||||
|
||||
sound.Play("MW19_Crossbow.ExploBeep", self:GetPos())
|
||||
ParticleEffectAttach("arrow_beep_flare", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
end
|
||||
|
||||
function ENT:Draw(flags)
|
||||
self:DrawShadow(false)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
ParticleEffect("Generic_explo_high", self:GetPos(), self:GetAngles())
|
||||
self:EmitSound("^viper/shared/frag_expl.ogg", 0, 100, 1, CHAN_BODY) --snd scripts dont work lol!
|
||||
|
||||
local dlight = DynamicLight(self:EntIndex())
|
||||
if (dlight) then
|
||||
dlight.pos = self:GetPos()
|
||||
dlight.r = 255
|
||||
dlight.g = 75
|
||||
dlight.b = 0
|
||||
dlight.brightness = 5
|
||||
dlight.Decay = 500
|
||||
dlight.Size = 512
|
||||
dlight.DieTime = CurTime() + 6
|
||||
end
|
||||
|
||||
util.Decal("Scorch", self:GetPos(), self:GetPos() + self:GetUp() * -100, {self, self.arrow})
|
||||
|
||||
local ed = EffectData()
|
||||
ed:SetScale(5000)
|
||||
ed:SetOrigin(self:GetPos())
|
||||
ed:SetRadius(512)
|
||||
ed:SetMagnitude(1000)
|
||||
ed:SetScale(1000)
|
||||
ed:SetEntity(self)
|
||||
util.Effect("ShakeRopes", ed)
|
||||
end
|
||||
59
lua/entities/mg_aoe_arrow_explosion/init.lua
Normal file
59
lua/entities/mg_aoe_arrow_explosion/init.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.ExplosionRadius = 256
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/dav0r/hoverball.mdl")
|
||||
--[[self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:GetPhysicsObject():EnableMotion(false)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)]]
|
||||
self:SetLifeTime(1.5)
|
||||
self:AddFlags(FL_GRENADE)
|
||||
self:AddFlags(FL_ONFIRE)
|
||||
self.nextBeep = self:GetLifeTime()
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if (IsValid(self:GetParent()) && self:GetParent():Health() <= 0 && self:GetParent():GetMaxHealth() > 1) then
|
||||
self:Explode()
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
self:SetLifeTime(self:GetLifeTime() - FrameTime())
|
||||
|
||||
if (self:GetLifeTime() > 0.1 && self:GetLifeTime() <= self.nextBeep) then
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), self.ExplosionRadius * 2, 1, nil) --make shit run away (nil owner so even rebels run)
|
||||
self.nextBeep = self:GetLifeTime() * 0.75
|
||||
BroadcastLua("Entity("..self:EntIndex().."):Beep()")
|
||||
end
|
||||
|
||||
if (self:GetLifeTime() <= 0) then
|
||||
self:Explode()
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
self:NextThink(CurTime())
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Explode()
|
||||
local dmgInfo = DamageInfo()
|
||||
dmgInfo:SetAttacker(self:GetOwner())
|
||||
dmgInfo:SetDamage(150)
|
||||
dmgInfo:SetDamageType(DMG_BLAST + DMG_AIRBOAT)
|
||||
dmgInfo:SetInflictor(self)
|
||||
util.BlastDamageInfo(dmgInfo, self:GetPos(), self.ExplosionRadius)
|
||||
util.ScreenShake(self:GetPos(), 3500, 1111, 1, self.ExplosionRadius * 4)
|
||||
|
||||
if (IsValid(self.arrow)) then
|
||||
self.arrow:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
self:Explode()
|
||||
end
|
||||
23
lua/entities/mg_aoe_arrow_explosion/shared.lua
Normal file
23
lua/entities/mg_aoe_arrow_explosion/shared.lua
Normal file
@@ -0,0 +1,23 @@
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_beep_flare")
|
||||
|
||||
game.AddParticles("particles/generic_explosions_pak.pcf")
|
||||
PrecacheParticleSystem("Generic_explo_high")
|
||||
PrecacheParticleSystem("Generic_explo_mid")
|
||||
PrecacheParticleSystem("Generic_explo_tiny")
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Float", 0, "LifeTime")
|
||||
end
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.ExploBeep",
|
||||
channel = CHAN_ITEM,
|
||||
volume = 1,
|
||||
level = 85,
|
||||
pitch = 100,
|
||||
sound = "viper/shared/weap_semtex_beep.ogg"
|
||||
})
|
||||
44
lua/entities/mg_aoe_arrow_gas/cl_init.lua
Normal file
44
lua/entities/mg_aoe_arrow_gas/cl_init.lua
Normal file
@@ -0,0 +1,44 @@
|
||||
include("shared.lua")
|
||||
killicon.Add("mg_aoe_arrow_gas", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
|
||||
local gasEntities = {}
|
||||
|
||||
function ENT:Initialize()
|
||||
table.insert(gasEntities, self)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
table.RemoveByValue(gasEntities, self)
|
||||
end
|
||||
|
||||
function ENT:Draw(flags)
|
||||
self:DrawShadow(false)
|
||||
end
|
||||
|
||||
function ENT:DrawPukeVision()
|
||||
if (!IsValid(GetViewEntity())) then
|
||||
return
|
||||
end
|
||||
|
||||
local dist = GetViewEntity():NearestPoint(self:GetPos()):DistToSqr(self:GetPos()) - (64 * 64)
|
||||
|
||||
if (dist > self.GasRadius * self.GasRadius) then
|
||||
return
|
||||
end
|
||||
|
||||
local delta = 1 - (dist / (self.GasRadius * self.GasRadius))
|
||||
local time = self:GetCreationTime() + self.LifeTime
|
||||
local fadeout = math.Clamp(time - CurTime(), 0, 0.5) * 2
|
||||
local fadein = math.Clamp(math.abs(CurTime() - self:GetCreationTime()), 0, 1)
|
||||
|
||||
delta = delta * fadein
|
||||
delta = delta * fadeout
|
||||
|
||||
surface.SetDrawColor(117, 143, 53, 200 * delta)
|
||||
surface.DrawRect(0, 0, ScrW(), ScrH())
|
||||
end
|
||||
hook.Add("HUDPaintBackground", "HUDPaint_MW19_GasVision", function()
|
||||
for _, e in pairs(gasEntities) do
|
||||
e:DrawPukeVision()
|
||||
end
|
||||
end)
|
||||
83
lua/entities/mg_aoe_arrow_gas/init.lua
Normal file
83
lua/entities/mg_aoe_arrow_gas/init.lua
Normal file
@@ -0,0 +1,83 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.smokeSound = nil
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/dav0r/hoverball.mdl")
|
||||
--[[self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:GetPhysicsObject():EnableMotion(false)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)]]
|
||||
self:AddFlags(FL_GRENADE)
|
||||
self:AddFlags(FL_ONFIRE)
|
||||
|
||||
local repFil = RecipientFilter()
|
||||
repFil:AddAllPlayers()
|
||||
|
||||
self.smokeSound = CreateSound(self, "MW19_Crossbow.GasOn", repFil)
|
||||
self.smokeSound:Play()
|
||||
|
||||
self:EmitSound("MW19_Crossbow.GasExplode")
|
||||
|
||||
ParticleEffectAttach("arrow_gas_dust", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
ParticleEffect("arrow_gas_explode", self:GetPos(), self:GetAngles(), self, 0)
|
||||
|
||||
self:SetParent(NULL) --detaching from whatever we nailed on
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), self.GasRadius * 2, self.LifeTime, nil) --make shit run away (nil owner so even rebels run)
|
||||
end
|
||||
|
||||
local function doesEntityBreathe(ent)
|
||||
return ent:GetBloodColor() != BLOOD_COLOR_MECH && ent:GetBloodColor() != DONT_BLEED
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if (CurTime() > self:GetCreationTime() + (self.LifeTime - 2)) then
|
||||
self:StopGas()
|
||||
end
|
||||
|
||||
if (CurTime() - self:GetCreationTime() > self.LifeTime) then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
for _, e in pairs(ents.FindInSphere(self:GetPos(), self.GasRadius)) do
|
||||
if (e:IsPlayer() || e:IsNPC() || e:IsNextBot()) then
|
||||
if (!doesEntityBreathe(e) || !e:IsLineOfSightClear(self:GetPos())) then
|
||||
continue
|
||||
end
|
||||
|
||||
local dmgInfo = DamageInfo()
|
||||
dmgInfo:SetAttacker(self:GetOwner())
|
||||
dmgInfo:SetDamage(8)
|
||||
dmgInfo:SetDamageType(DMG_NERVEGAS)
|
||||
dmgInfo:SetInflictor(self)
|
||||
e:TakeDamageInfo(dmgInfo)
|
||||
end
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 0.25)
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
self:StopGas()
|
||||
end
|
||||
|
||||
ENT.bStoppedGas = false
|
||||
|
||||
function ENT:StopGas()
|
||||
if (self.bStoppedGas) then
|
||||
return
|
||||
end
|
||||
|
||||
self.bStoppedGas = true
|
||||
|
||||
if (self.smokeSound != nil) then
|
||||
self.smokeSound:Stop()
|
||||
end
|
||||
|
||||
self:StopParticles()
|
||||
sound.Play("MW19_Crossbow.GasOff", self:GetPos())
|
||||
end
|
||||
36
lua/entities/mg_aoe_arrow_gas/shared.lua
Normal file
36
lua/entities/mg_aoe_arrow_gas/shared.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.GasRadius = 164
|
||||
ENT.LifeTime = 8
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_gas_dust")
|
||||
PrecacheParticleSystem("arrow_gas_explode")
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.GasOn",
|
||||
channel = CHAN_BODY,
|
||||
volume = 0.25,
|
||||
level = 75,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/smoke_grenade_smoke_loop.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.GasOff",
|
||||
channel = CHAN_BODY,
|
||||
volume = 0.25,
|
||||
level = 75,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/smoke_grenade_smoke_loop_end.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.GasExplode",
|
||||
channel = CHAN_ITEM,
|
||||
volume = 1,
|
||||
level = 100,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/smoke_expl_body_01.ogg"}
|
||||
})
|
||||
45
lua/entities/mg_aoe_arrow_smoke/cl_init.lua
Normal file
45
lua/entities/mg_aoe_arrow_smoke/cl_init.lua
Normal file
@@ -0,0 +1,45 @@
|
||||
include("shared.lua")
|
||||
killicon.Add("mg_aoe_arrow_gas", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
|
||||
local smokeEntities = {}
|
||||
|
||||
function ENT:Initialize()
|
||||
table.insert(smokeEntities, self)
|
||||
self:SetCollisionGroup(self.CollisionGroup)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
table.RemoveByValue(smokeEntities, self)
|
||||
end
|
||||
|
||||
function ENT:Draw(flags)
|
||||
self:DrawShadow(false)
|
||||
end
|
||||
|
||||
function ENT:DrawSmokeVision()
|
||||
if (!IsValid(GetViewEntity())) then
|
||||
return
|
||||
end
|
||||
|
||||
local dist = GetViewEntity():NearestPoint(self:GetPos()):DistToSqr(self:GetPos()) - (64 * 64)
|
||||
|
||||
if (dist > self.SmokeRadius * self.SmokeRadius) then
|
||||
return
|
||||
end
|
||||
|
||||
local delta = 1 - (dist / (self.SmokeRadius * self.SmokeRadius))
|
||||
local time = self:GetCreationTime() + self.LifeTime
|
||||
local fadeout = math.Clamp(time - CurTime(), 0, 0.5) * 2
|
||||
local fadein = math.Clamp(math.abs(CurTime() - self:GetCreationTime()), 0, 1)
|
||||
|
||||
delta = delta * fadein
|
||||
delta = delta * fadeout
|
||||
|
||||
surface.SetDrawColor(150, 150, 150, 255 * delta)
|
||||
surface.DrawRect(0, 0, ScrW(), ScrH())
|
||||
end
|
||||
hook.Add("HUDPaintBackground", "HUDPaint_MW19_SmokeVision", function()
|
||||
for _, e in pairs(smokeEntities) do
|
||||
e:DrawSmokeVision()
|
||||
end
|
||||
end)
|
||||
69
lua/entities/mg_aoe_arrow_smoke/init.lua
Normal file
69
lua/entities/mg_aoe_arrow_smoke/init.lua
Normal file
@@ -0,0 +1,69 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.smokeSound = nil
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetParent(NULL) --detaching from whatever we nailed on
|
||||
|
||||
self:SetModel("models/dav0r/hoverball.mdl")
|
||||
self:SetOwner(NULL)
|
||||
self:EnableCustomCollisions(true)
|
||||
|
||||
local p = self:GetPos() --+ self:GetAngles():Up() * -self.SmokeRadius
|
||||
local b = Vector(0.66, 0.66, 0.66) * self.SmokeRadius
|
||||
self:PhysicsInitBox(-b, b)
|
||||
self:SetCollisionBoundsWS(p - b, p + b)
|
||||
self:GetPhysicsObject():EnableMotion(false)
|
||||
self:SetCollisionGroup(self.CollisionGroup)
|
||||
|
||||
local repFil = RecipientFilter()
|
||||
repFil:AddAllPlayers()
|
||||
|
||||
self.smokeSound = CreateSound(self, "MW19_Crossbow.SmokeOn", repFil)
|
||||
self.smokeSound:Play()
|
||||
self.smokeSound:ChangePitch(75)
|
||||
|
||||
self:EmitSound("MW19_Crossbow.SmokeExplode")
|
||||
|
||||
ParticleEffectAttach("arrow_smoke", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
ParticleEffect("arrow_smoke_explode", self:GetPos(), self:GetAngles(), self, 0)
|
||||
end
|
||||
|
||||
function ENT:GetRelationship(e)
|
||||
return self:GetOwner()
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if (CurTime() > self:GetCreationTime() + (self.LifeTime - 2)) then
|
||||
self:StopSmoke()
|
||||
end
|
||||
|
||||
if (CurTime() - self:GetCreationTime() > self.LifeTime) then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
self:StopSmoke()
|
||||
end
|
||||
|
||||
ENT.bStoppedSmoke = false
|
||||
|
||||
function ENT:StopSmoke()
|
||||
if (self.bStoppedSmoke) then
|
||||
return
|
||||
end
|
||||
|
||||
self.bStoppedSmoke = true
|
||||
|
||||
if (self.smokeSound != nil) then
|
||||
self.smokeSound:Stop()
|
||||
end
|
||||
|
||||
self:StopParticles()
|
||||
sound.Play("MW19_Crossbow.SmokeOff", self:GetPos())
|
||||
end
|
||||
57
lua/entities/mg_aoe_arrow_smoke/shared.lua
Normal file
57
lua/entities/mg_aoe_arrow_smoke/shared.lua
Normal file
@@ -0,0 +1,57 @@
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.SmokeRadius = 256
|
||||
ENT.LifeTime = 11
|
||||
ENT.CollisionGroup = COLLISION_GROUP_DEBRIS_TRIGGER
|
||||
|
||||
function ENT:TestCollision(startpos, delta, isbox, extents, mask)
|
||||
--[[if (bit.band(mask, MASK_SHOT) == MASK_SHOT && SERVER) then
|
||||
--workaround for strider
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = startpos,
|
||||
filter = self,
|
||||
mask = MASK_SHOT
|
||||
})
|
||||
|
||||
if (IsValid(tr.Entity)) then
|
||||
tr.Entity:Fire("SetCannonTarget", "") --strider
|
||||
tr.Entity:Fire("SetMinigunTarget", "") --strider
|
||||
--can't do shit to helicopter _shrug_
|
||||
end
|
||||
end]] --causes an infinite loop when shooting more arrows into the smoke
|
||||
|
||||
return bit.band(mask, MASK_BLOCKLOS) == MASK_BLOCKLOS
|
||||
end
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_smoke")
|
||||
PrecacheParticleSystem("arrow_smoke_explode")
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.SmokeOn",
|
||||
channel = CHAN_BODY,
|
||||
volume = 0.25,
|
||||
level = 75,
|
||||
pitch = {75, 85},
|
||||
sound = {"viper/shared/smoke_grenade_smoke_loop.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.SmokeOff",
|
||||
channel = CHAN_BODY,
|
||||
volume = 0.25,
|
||||
level = 75,
|
||||
pitch = {75, 85},
|
||||
sound = {"viper/shared/smoke_grenade_smoke_loop_end.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.SmokeExplode",
|
||||
channel = CHAN_ITEM,
|
||||
volume = 1,
|
||||
level = 100,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/smoke_expl_body_01.ogg"}
|
||||
})
|
||||
27
lua/entities/mg_aoe_arrow_thermite/cl_init.lua
Normal file
27
lua/entities/mg_aoe_arrow_thermite/cl_init.lua
Normal file
@@ -0,0 +1,27 @@
|
||||
include("shared.lua")
|
||||
killicon.Add("mg_aoe_arrow_thermite", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
|
||||
function ENT:Initialize()
|
||||
self:EmitSound("MW19_Crossbow.FireOn")
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
self:StopSound("MW19_Crossbow.FireOn")
|
||||
sound.Play("MW19_Crossbow.FireOff", self:GetPos())
|
||||
end
|
||||
|
||||
function ENT:Draw(flags)
|
||||
self:DrawShadow(false)
|
||||
|
||||
local dlight = DynamicLight(self:EntIndex())
|
||||
if (dlight) then
|
||||
dlight.pos = self:GetPos()
|
||||
dlight.r = 255
|
||||
dlight.g = 75
|
||||
dlight.b = 0
|
||||
dlight.brightness = 5
|
||||
dlight.Decay = 500
|
||||
dlight.Size = math.random(50, 64)
|
||||
dlight.DieTime = CurTime() + 0.25
|
||||
end
|
||||
end
|
||||
105
lua/entities/mg_aoe_arrow_thermite/init.lua
Normal file
105
lua/entities/mg_aoe_arrow_thermite/init.lua
Normal file
@@ -0,0 +1,105 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.smokeSound = nil
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/dav0r/hoverball.mdl")
|
||||
--[[self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:GetPhysicsObject():EnableMotion(false)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)]]
|
||||
self:AddFlags(FL_GRENADE)
|
||||
self:AddFlags(FL_ONFIRE)
|
||||
|
||||
self:EmitSound("MW19_Crossbow.FireExplode")
|
||||
|
||||
ParticleEffectAttach("arrow_thermite", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
util.Decal("Dark", self:GetPos(), self:GetPos() + self:GetUp() * -100, {self, self.arrow})
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), self.FireRadius * 2, self.LifeTime, nil) --make shit run away (nil owner so even rebels run)
|
||||
|
||||
if (IsValid(self:GetParent())) then
|
||||
self:GetParent():CallOnRemove("mw19_dontremovemyarrowffs", function(ent)
|
||||
if (!IsValid(ent)) then
|
||||
return
|
||||
end
|
||||
|
||||
for _, c in pairs(ent:GetChildren()) do
|
||||
if (IsValid(c) && c:GetClass() == self:GetClass()) then
|
||||
c:SetParent(NULL)
|
||||
c:TeleportOnGround()
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:TeleportOnGround()
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() - Vector(0, 0, 32000),
|
||||
filter = {self, self.arrow}
|
||||
})
|
||||
|
||||
self:SetPos(tr.HitPos)
|
||||
|
||||
local angle = tr.HitNormal:Angle()
|
||||
angle:RotateAroundAxis(angle:Right(), 270)
|
||||
self:SetAngles(angle)
|
||||
|
||||
if (!tr.Entity:IsWorld()) then
|
||||
self:SetParent(tr.Entity)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if (IsValid(self:GetParent()) && self:GetParent():Health() <= 0 && self:GetParent():GetMaxHealth() > 1) then
|
||||
self:SetParent(NULL)
|
||||
self:TeleportOnGround()
|
||||
end
|
||||
|
||||
if (CurTime() - self:GetCreationTime() > self.LifeTime) then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
for _, e in pairs(ents.FindInSphere(self:GetPos(), self.FireRadius)) do
|
||||
if (e == self.arrow || e == self) then
|
||||
continue
|
||||
end
|
||||
|
||||
if ((e:IsPlayer() || e:IsNPC() || e:IsNextBot()) && !e:IsLineOfSightClear(self:GetPos())) then
|
||||
continue
|
||||
end
|
||||
|
||||
if (e:Health() <= 0 && e:GetMaxHealth() > 1) then
|
||||
continue
|
||||
end
|
||||
|
||||
e:Ignite(0.25)
|
||||
|
||||
local dmgInfo = DamageInfo()
|
||||
dmgInfo:SetAttacker(self:GetOwner())
|
||||
dmgInfo:SetDamage(10)
|
||||
dmgInfo:SetDamageType(DMG_BURN)
|
||||
dmgInfo:SetInflictor(self)
|
||||
e:TakeDamageInfo(dmgInfo)
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 0.25)
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
self:StopFire()
|
||||
end
|
||||
|
||||
function ENT:StopFire()
|
||||
self:StopParticles()
|
||||
sound.Play("MW19_Crossbow.FireOff", self:GetPos())
|
||||
|
||||
if (IsValid(self.arrow)) then
|
||||
ParticleEffectAttach("arrow_thermite_smokeleft", PATTACH_ABSORIGIN_FOLLOW, self.arrow, 0)
|
||||
end
|
||||
end
|
||||
36
lua/entities/mg_aoe_arrow_thermite/shared.lua
Normal file
36
lua/entities/mg_aoe_arrow_thermite/shared.lua
Normal file
@@ -0,0 +1,36 @@
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.FireRadius = 42
|
||||
ENT.LifeTime = 6
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_thermite")
|
||||
PrecacheParticleSystem("arrow_thermite_smokeleft")
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.FireOn",
|
||||
channel = CHAN_BODY,
|
||||
volume = 0.75,
|
||||
level = 75,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/weap_thermite_loop.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.FireOff",
|
||||
channel = CHAN_BODY,
|
||||
volume = 0.75,
|
||||
level = 75,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/weap_thermite_loop_end_01.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.FireExplode",
|
||||
channel = CHAN_ITEM,
|
||||
volume = 1,
|
||||
level = 100,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/weap_thermite_impact_01.ogg", "viper/shared/weap_thermite_impact_02.ogg", "viper/shared/weap_thermite_impact_03.ogg"}
|
||||
})
|
||||
17
lua/entities/mg_arrow/cl_init.lua
Normal file
17
lua/entities/mg_arrow/cl_init.lua
Normal file
@@ -0,0 +1,17 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
ENT.bTracerOn = false
|
||||
|
||||
function ENT:DrawTranslucent(flags)
|
||||
if (self:GetVelocity():LengthSqr() > 0 || self:GetNailed()) then
|
||||
self:DrawModel()
|
||||
|
||||
if (!self.bTracerOn) then
|
||||
ParticleEffectAttach("arrow_trail", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
self.bTracerOn = true
|
||||
end
|
||||
end
|
||||
end
|
||||
229
lua/entities/mg_arrow/init.lua
Normal file
229
lua/entities/mg_arrow/init.lua
Normal file
@@ -0,0 +1,229 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.bCollided = false
|
||||
ENT.Projectile = {
|
||||
Class = "mg_bullet",
|
||||
Speed = 4000,
|
||||
Gravity = 1
|
||||
}
|
||||
ENT.Maxs = Vector(1, 1, 1)
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_mag.mdl")
|
||||
ENT.AoeEntity = nil
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel(self.Model)
|
||||
self:PhysicsInitBox(Vector(-10, -1, -1), Vector(10, 1, 1))
|
||||
self:GetPhysicsObject():Wake()
|
||||
self:GetPhysicsObject():SetMaterial("default_silent")
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_PLAYER_PICKUP)
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_IMPACT_DMG)
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_HEAVY_OBJECT)
|
||||
self:GetPhysicsObject():EnableMotion(true)
|
||||
self:GetPhysicsObject():EnableDrag(false)
|
||||
self:GetPhysicsObject():SetMass(1000)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_IN_VEHICLE) --doesn't collide with anything, no traces
|
||||
self:AddEFlags(EFL_NO_DAMAGE_FORCES)
|
||||
self:AddEFlags(EFL_DONTWALKON)
|
||||
self:AddEFlags(EFL_DONTBLOCKLOS)
|
||||
self:AddEFlags(EFL_NO_PHYSCANNON_INTERACTION)
|
||||
|
||||
self.Projectile = table.Copy(self.Weapon.Projectile)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(self:GetAngles():Forward() * self.Projectile.Speed)
|
||||
self.LastPos = self:GetOwner():EyePos()
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
--[[if (IsValid(self:GetParent()) && self:GetParent():Health() <= 0 && self:GetParent():GetMaxHealth() > 1) then
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
self:GetPhysicsObject():EnableMotion(true)
|
||||
self:GetPhysicsObject():Wake()
|
||||
self:SetParent(NULL)
|
||||
end]]
|
||||
end
|
||||
|
||||
ENT.m_gravity = 0
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if (!phys:IsMotionEnabled()) then
|
||||
return
|
||||
end
|
||||
|
||||
self.m_gravity = math.Clamp(self.m_gravity + (self.Projectile.Gravity), -90, 90)
|
||||
|
||||
phys:SetAngles(phys:GetAngles() + Angle(self.m_gravity, 0, 0) * FrameTime())
|
||||
phys:SetPos(self.LastPos + phys:GetAngles():Forward() * (self.Projectile.Speed * FrameTime()))
|
||||
|
||||
--Aim assist
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Box(phys:GetPos(), -self.Maxs, self.Maxs, 0, Color(0, 200, 50, 10))
|
||||
end
|
||||
|
||||
local trData = {
|
||||
start = self.LastPos,
|
||||
endpos = phys:GetPos(),
|
||||
filter = {self:GetOwner(), self},
|
||||
mask = MASK_SHOT_PORTAL,
|
||||
collisiongroup = COLLISION_GROUP_PROJECTILE,
|
||||
mins = -self.Maxs,
|
||||
maxs = self.Maxs
|
||||
}
|
||||
|
||||
local tr = util.TraceHull(trData)
|
||||
|
||||
if (tr.Hit && (tr.Entity:IsPlayer() || tr.Entity:IsNPC())) then
|
||||
self:Impact(tr, phys, true)
|
||||
return
|
||||
end
|
||||
|
||||
--Normal hitscan
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Line(self.LastPos, phys:GetPos(), 1, Color(255, 0, 0, 1))
|
||||
end
|
||||
|
||||
tr = util.TraceLine(trData)
|
||||
|
||||
if (tr.Hit) then
|
||||
self:Impact(tr, phys, false)
|
||||
return
|
||||
end
|
||||
|
||||
self.LastPos = phys:GetPos()
|
||||
end
|
||||
|
||||
local function parentEntity(tr, ent)
|
||||
local arrowHitAng = tr.Normal:Angle()
|
||||
local arrowHitPos = tr.HitPos + arrowHitAng:Forward() * -3 + arrowHitAng:Up() * -1.5
|
||||
local boneId = tr.Entity:GetHitboxBone(tr.HitBox, 0)
|
||||
|
||||
if (boneId != nil) then
|
||||
if (tr.Entity:IsRagdoll()) then
|
||||
boneId = tr.Entity:TranslatePhysBoneToBone(tr.PhysicsBone)
|
||||
end
|
||||
|
||||
ent:FollowBone(tr.Entity, boneId)
|
||||
debugoverlay.Text(tr.HitPos, tr.Entity:GetBoneName(boneId), 1)
|
||||
else
|
||||
if (!tr.Entity:IsWorld()) then
|
||||
ent:SetParent(tr.Entity)
|
||||
end
|
||||
end
|
||||
|
||||
ent:SetAngles(arrowHitAng)
|
||||
ent:SetPos(arrowHitPos)
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if (!self:GetNailed()) then
|
||||
return
|
||||
end
|
||||
|
||||
if (self.Projectile.PickUp) then
|
||||
local dist = self:GetOwner():NearestPoint(self:GetPos()):DistToSqr(self:GetPos())
|
||||
|
||||
if (dist < 32 * 32) then
|
||||
self:GetOwner():EmitSound("viper/shared/iw8_mp_scavenger_pack_pickup.wav")
|
||||
self:GetOwner():SetAmmo(self:GetOwner():GetAmmoCount("XBowBolt") + 1, "XBowBolt")
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(tr1, phys, bHull)
|
||||
SafeRemoveEntityDelayed(self, 20)
|
||||
|
||||
phys:EnableMotion(false)
|
||||
|
||||
if (self.Projectile.PickUp) then
|
||||
self:AddEffects(EF_ITEM_BLINK)
|
||||
end
|
||||
|
||||
self:SetMoveType(MOVETYPE_NONE)
|
||||
self:SetNailed(true)
|
||||
|
||||
self:StopParticles()
|
||||
|
||||
self:FireBullets({
|
||||
Attacker = self:GetOwner(),
|
||||
Num = 1,
|
||||
Tracer = 0,
|
||||
Src = self.LastPos,
|
||||
Dir = (phys:GetPos() - self.LastPos):GetNormalized(),
|
||||
HullSize = bHull && self.Maxs:Length() * 2 || 1,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(attacker, tr, dmgInfo)
|
||||
dmgInfo:SetInflictor(IsValid(self.Weapon) && self.Weapon || self)
|
||||
dmgInfo:SetDamageType(dmgInfo:GetDamageType() + DMG_DIRECT + self:GetDamageType())
|
||||
|
||||
if (IsValid(self.Weapon)) then
|
||||
self.Weapon:BulletCallback(attacker, tr, dmgInfo)
|
||||
end
|
||||
|
||||
if (tr.HitSky) then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
if (self.AoeEntity != nil) then
|
||||
local aoe = ents.Create(self.AoeEntity)
|
||||
aoe:SetOwner(self:GetOwner())
|
||||
parentEntity(tr, aoe)
|
||||
aoe:SetPos(tr.HitPos + tr.HitNormal * 3)
|
||||
|
||||
local angle = tr.HitNormal:Angle()
|
||||
angle:RotateAroundAxis(angle:Right(), 270)
|
||||
|
||||
aoe:SetAngles(angle)
|
||||
aoe:Spawn()
|
||||
aoe.arrow = self
|
||||
self.aoe = aoe
|
||||
end
|
||||
|
||||
if (tr.Entity:IsPlayer() || tr.Entity:IsNPC() || tr.Entity:IsNextBot() || tr.Entity:IsRagdoll()) then
|
||||
sound.Play("MW19_Crossbow.HitBody", tr.HitPos + tr.HitNormal * 5)
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
sound.Play("MW19_Crossbow.Hit", tr.HitPos)
|
||||
|
||||
parentEntity(tr, self)
|
||||
|
||||
self:FireBullets({
|
||||
Attacker = self:GetOwner(),
|
||||
Num = 1,
|
||||
Tracer = 0,
|
||||
Src = tr.HitPos + self:GetAngles():Forward() * 11,
|
||||
Dir = tr.Normal * -1,
|
||||
IgnoreEntity = self.aoe,
|
||||
Damage = 0,
|
||||
Callback = function(attacker, trBack, dmgInfo)
|
||||
if (trBack.Entity != tr.Entity) then
|
||||
--constraint.Weld(tr.Entity, trBack.Entity, tr.PhysicsBone, trBack.PhysicsBone, 0, false)
|
||||
local lPos1 = LocalToWorld(tr.HitPos, tr.HitNormal:Angle(), tr.Entity:GetPos(), tr.Entity:GetAngles())
|
||||
lPos1 = tr.Entity:GetPhysicsObject():WorldToLocal(tr.HitPos + tr.HitNormal)
|
||||
|
||||
local lPos2 = LocalToWorld(tr.HitPos, tr.HitNormal:Angle(), trBack.Entity:GetPos(), trBack.Entity:GetAngles())
|
||||
|
||||
self.constraint = constraint.Axis(tr.Entity, trBack.Entity, tr.PhysicsBone, trBack.PhysicsBone, lPos1, lPos2, 0, 0, 0, false)
|
||||
self:EmitSound("MW19_Crossbow.Skewer")
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
function ENT:GetDamageType()
|
||||
return DMG_SNIPER + DMG_SLASH
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (IsValid(self.constraint)) then
|
||||
self.constraint:Remove()
|
||||
end
|
||||
end
|
||||
39
lua/entities/mg_arrow/shared.lua
Normal file
39
lua/entities/mg_arrow/shared.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_trail")
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.Hit",
|
||||
channel = CHAN_BODY,
|
||||
volume = 1,
|
||||
level = 85,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/bullet_small_crossbow_bolt_swt_01.ogg", "viper/shared/bullet_small_crossbow_bolt_swt_02.ogg", "viper/shared/bullet_small_crossbow_bolt_swt_03.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.HitBody",
|
||||
channel = CHAN_BODY,
|
||||
volume = 1,
|
||||
level = 85,
|
||||
pitch = {95, 105},
|
||||
sound = {"viper/shared/bullet_flesh_plr_head_01.ogg", "viper/shared/bullet_flesh_plr_head_02.ogg", "viper/shared/bullet_flesh_plr_head_03.ogg"}
|
||||
})
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.Skewer",
|
||||
channel = CHAN_ITEM,
|
||||
volume = 1,
|
||||
level = 85,
|
||||
pitch = {95, 105},
|
||||
sound = {"weapons/crossbow/bolt_skewer1.wav"}
|
||||
})
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "Nailed")
|
||||
end
|
||||
10
lua/entities/mg_arrow_bone/cl_init.lua
Normal file
10
lua/entities/mg_arrow_bone/cl_init.lua
Normal file
@@ -0,0 +1,10 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow_bone", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
|
||||
local BaseClass = baseclass.Get(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
self:EmitSound("MW19_Crossbow.Bone")
|
||||
end
|
||||
6
lua/entities/mg_arrow_bone/init.lua
Normal file
6
lua/entities/mg_arrow_bone/init.lua
Normal file
@@ -0,0 +1,6 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_magskull.mdl")
|
||||
16
lua/entities/mg_arrow_bone/shared.lua
Normal file
16
lua/entities/mg_arrow_bone/shared.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
ENT.Base = "mg_arrow"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.EMPRadius = 600
|
||||
|
||||
game.AddParticles("particles/generic_explosions_pak.pcf")
|
||||
PrecacheParticleSystem("Generic_explo_emp")
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.Bone",
|
||||
channel = CHAN_BODY,
|
||||
volume = 1,
|
||||
level = 80,
|
||||
pitch = {95, 105},
|
||||
sound = {"@viper/shared/bone.wav"}
|
||||
})
|
||||
11
lua/entities/mg_arrow_emp/cl_init.lua
Normal file
11
lua/entities/mg_arrow_emp/cl_init.lua
Normal file
@@ -0,0 +1,11 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow_emp", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
|
||||
hook.Add("HUDShouldDraw", "MW19_HUDShouldDraw_EMP", function(name)
|
||||
if (IsValid(GetViewEntity())) then
|
||||
if (CurTime() < GetViewEntity():GetNWFloat("MW19_EMPEffect", CurTime())) then
|
||||
return name != "CHudAmmo" && name != "CHudBattery" && name != "CHudHealth" && name != "CHudSecondaryAmmo"
|
||||
end
|
||||
end
|
||||
end)
|
||||
81
lua/entities/mg_arrow_emp/init.lua
Normal file
81
lua/entities/mg_arrow_emp/init.lua
Normal file
@@ -0,0 +1,81 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_mag_empbolt.mdl")
|
||||
ENT.AoeEntity = nil
|
||||
|
||||
local BaseClass = baseclass.Get(ENT.Base)
|
||||
|
||||
local customInputs = {
|
||||
["npc_turret_floor"] = function(npc) npc:Fire("SelfDestruct") end,
|
||||
["npc_rollermine"] = function(npc) npc:Fire("PowerDown") end,
|
||||
["npc_cscanner"] = function(npc) npc:SetHealth(0) npc:ClearSchedule() end,--SCHED_SCANNER_ATTACK_DIVEBOMB,
|
||||
["npc_clawscanner"] = function(npc) npc:SetHealth(0) npc:ClearSchedule() end,--SCHED_SCANNER_ATTACK_DIVEBOMB,
|
||||
["npc_manhack"] = function(npc) npc:MoveStop() npc:SetHealth(0) npc:MoveStart() end,
|
||||
["npc_turret_ceiling"] = function(npc) npc:SetHealth(0) npc:TakeDamage(1000, npc, npc) end,
|
||||
["npc_combine_camera"] = function(npc) npc:SetHealth(0) npc:TakeDamage(1000, npc, npc) end,
|
||||
["npc_dog"] = function(npc) npc:TakeDamage(10000, npc, npc) end,
|
||||
["npc_hunter"] = function(npc) npc:Fire("Dodge") end,
|
||||
["combine_mine"] = function(npc) npc:SetSaveValue("m_iMineState", "3") npc:Fire("Disarm") npc:EmitSound("npc/roller/mine/rmine_tossed1.wav", 75, math.random(95, 105), 1, CHAN_BODY) end,
|
||||
["item_healthcharger"] = function(npc) npc:SetSaveValue("m_iJuice", "0") npc:Use(Entity(1)) npc:EmitSound("items/medshotno1.wav", 75, math.random(95, 105), 1, CHAN_BODY) end,
|
||||
["item_suitcharger"] = function(npc) npc:SetSaveValue("m_iJuice", "0") npc:Use(Entity(1)) npc:EmitSound("items/suitchargeno1.wav", 75, math.random(95, 105), 1, CHAN_BODY) end,
|
||||
["prop_thumper"] = function(npc) npc:Fire("Disable") end,
|
||||
["grenade_helicopter"] = function(npc) npc:SetSaveValue("m_flLifeTime", "10000000") Entity(1):SimulateGravGunPickup(npc)
|
||||
--npc:SetSaveValue("spawnflags", ""..bit.bor(npc:GetSpawnFlags(), 16)) end --dud, doesn't get read runtime?
|
||||
end,
|
||||
["item_battery"] = function(npc) npc:AddFlags(FL_DONTTOUCH) end,
|
||||
["weapon_striderbuster"] = function(npc) npc:Fire("Break") end, --the amount of effort required to make this thing detonate... nah
|
||||
["npc_grenade_frag"] = function(npc)
|
||||
for _, c in pairs(npc:GetChildren()) do
|
||||
c:Fire("Disable")
|
||||
end
|
||||
npc:Fire("SetTimer", "9999")
|
||||
npc:SetSaveValue("m_flNextBlipTime", "9999") end --aware that if you pick it up it's gonna restart
|
||||
--wanted to give player satisfaction of disabling it and then using it to fuck em up
|
||||
}
|
||||
|
||||
function ENT:Impact(tr, phys, bHull)
|
||||
BaseClass.Impact(self, tr, phys, bHull)
|
||||
|
||||
if (tr.HitSky) then
|
||||
return
|
||||
end
|
||||
|
||||
sound.Play("^viper/shared/emp_expl.ogg", tr.HitPos, 0, 150, 1, CHAN_BODY) --snd scripts dont work lol!
|
||||
|
||||
local angle = tr.HitNormal:Angle()
|
||||
angle:RotateAroundAxis(angle:Right(), 270)
|
||||
ParticleEffect("Generic_explo_emp", tr.HitPos, angle, nil, 0)
|
||||
util.ScreenShake(self:GetPos(), 3500, 1111, 1, self.EMPRadius * 2)
|
||||
util.Decal("Scorch", tr.HitPos, tr.HitPos - tr.HitNormal * 10, self)
|
||||
|
||||
for _, e in pairs(ents.FindInSphere(tr.HitPos, self.EMPRadius)) do
|
||||
if (e:IsPlayer()) then
|
||||
e:SetNWFloat("MW19_EMPEffect", CurTime() + 4)
|
||||
e:SetArmor(0)
|
||||
continue
|
||||
end
|
||||
|
||||
if (customInputs[e:GetClass()] != nil) then
|
||||
timer.Simple(math.Rand(0, 0.2), function()
|
||||
if (!IsValid(e)) then
|
||||
return
|
||||
end
|
||||
customInputs[e:GetClass()](e)
|
||||
end)
|
||||
|
||||
local ef = EffectData()
|
||||
ef:SetEntity(e)
|
||||
ef:SetMagnitude(30)
|
||||
ef:SetScale(20)
|
||||
util.Effect("TeslaHitboxes", ef)
|
||||
else
|
||||
--if someone wants to latch onto this functionality
|
||||
if (e.OnModernWarfareEMP != nil) then
|
||||
e.OnModernWarfareEMP(self, tr)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
16
lua/entities/mg_arrow_emp/shared.lua
Normal file
16
lua/entities/mg_arrow_emp/shared.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
ENT.Base = "mg_arrow"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.EMPRadius = 600
|
||||
|
||||
game.AddParticles("particles/generic_explosions_pak.pcf")
|
||||
PrecacheParticleSystem("Generic_explo_emp")
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.EMP",
|
||||
channel = CHAN_BODY,
|
||||
volume = 1,
|
||||
level = 150,
|
||||
pitch = {95, 105},
|
||||
sound = {"^viper/shared/emp_expl.ogg"}
|
||||
})
|
||||
3
lua/entities/mg_arrow_explosive/cl_init.lua
Normal file
3
lua/entities/mg_arrow_explosive/cl_init.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow_explosive", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
7
lua/entities/mg_arrow_explosive/init.lua
Normal file
7
lua/entities/mg_arrow_explosive/init.lua
Normal file
@@ -0,0 +1,7 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_mag_expbolt.mdl")
|
||||
ENT.AoeEntity = "mg_aoe_arrow_explosion"
|
||||
2
lua/entities/mg_arrow_explosive/shared.lua
Normal file
2
lua/entities/mg_arrow_explosive/shared.lua
Normal file
@@ -0,0 +1,2 @@
|
||||
ENT.Base = "mg_arrow"
|
||||
ENT.Type = "anim"
|
||||
3
lua/entities/mg_arrow_flashbang/cl_init.lua
Normal file
3
lua/entities/mg_arrow_flashbang/cl_init.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow_flashbang", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
83
lua/entities/mg_arrow_flashbang/init.lua
Normal file
83
lua/entities/mg_arrow_flashbang/init.lua
Normal file
@@ -0,0 +1,83 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_mag_flashbolt.mdl")
|
||||
ENT.AoeEntity = nil
|
||||
|
||||
local BaseClass = baseclass.Get(ENT.Base)
|
||||
|
||||
local function isCowerSupportedForNPC(npc)
|
||||
for _, a in pairs(npc:GetSequenceList()) do
|
||||
if (npc:GetSequenceActivity(npc:LookupSequence(a)) == ACT_COWER) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
--[[local supportedNpcs = {
|
||||
["npc_antlion"] = "Flip1",
|
||||
["npc_antlionguard"] = "Stunned01",
|
||||
["npc_antlionguardian"] = "Stunned01",
|
||||
["npc_hunter"] = "Shakeoff",
|
||||
["npc_antlion_worker"] = "Flip1"
|
||||
}]] --couldn't make these work
|
||||
|
||||
local lethalToNpcs = {"npc_barnacle", "npc_crow", "npc_pigeon", "npc_seagull"}
|
||||
|
||||
function ENT:Impact(tr, phys, bHull)
|
||||
BaseClass.Impact(self, tr, phys, bHull)
|
||||
|
||||
if (tr.HitSky) then
|
||||
return
|
||||
end
|
||||
|
||||
self:EmitSound("MW19_Crossbow.Flashbang")
|
||||
|
||||
local radius = self.FlashRadius
|
||||
local owner = self:GetOwner()
|
||||
ParticleEffect("arrow_flashbang", tr.HitPos, Angle(), nil, 0)
|
||||
util.Decal("Scorch", tr.HitPos, tr.HitPos - tr.HitNormal * 10, self)
|
||||
|
||||
timer.Simple(0.3, function() --ohshit moment
|
||||
for _, e in pairs(ents.FindInSphere(tr.HitPos, radius)) do
|
||||
if ((e:IsPlayer() || e:IsNPC()) && !e:IsLineOfSightClear(tr.HitPos + tr.HitNormal * 10)) then
|
||||
continue
|
||||
end
|
||||
|
||||
if (e:IsPlayer()) then
|
||||
local dist = e:GetPos():DistToSqr(tr.HitPos)
|
||||
local distDelta = 1 - math.Clamp(dist / (radius * radius), 0, 1)
|
||||
local strength = Lerp(distDelta, 0, 2)
|
||||
|
||||
e:SendLua("LocalPlayer():EmitSound('MW19_Crossbow.Flashbang')")
|
||||
local dot = e:EyeAngles():Forward():Dot((e:GetPos() - tr.HitPos):GetNormalized())
|
||||
strength = strength * math.max(-dot, 0.1)
|
||||
|
||||
e:ScreenFade(SCREENFADE.IN, color_white, strength, strength * 0.5)
|
||||
e:SetDSP(35)
|
||||
|
||||
continue
|
||||
end
|
||||
|
||||
if (e:IsNPC()) then
|
||||
e:StartEngineTask(89, 0) --task_sound_pain
|
||||
|
||||
if (isCowerSupportedForNPC(e)) then
|
||||
e:SetSchedule(SCHED_COWER)
|
||||
else
|
||||
if (table.HasValue(lethalToNpcs, e:GetClass())) then
|
||||
e:TakeDamage(e:Health(), self:GetOwner(), self || nil)
|
||||
end
|
||||
end
|
||||
|
||||
continue
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), self.FlashRadius, 6, nil) --needed for task (make them blinded for a little longer)
|
||||
end
|
||||
16
lua/entities/mg_arrow_flashbang/shared.lua
Normal file
16
lua/entities/mg_arrow_flashbang/shared.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
ENT.Base = "mg_arrow"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.FlashRadius = 1200
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_flashbang")
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.Flashbang",
|
||||
channel = CHAN_BODY,
|
||||
volume = 1,
|
||||
level = 100,
|
||||
pitch = {95, 105},
|
||||
sound = {"@viper/shared/smoke_expl_body_01.ogg"}
|
||||
})
|
||||
3
lua/entities/mg_arrow_gas/cl_init.lua
Normal file
3
lua/entities/mg_arrow_gas/cl_init.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow_gas", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
14
lua/entities/mg_arrow_gas/init.lua
Normal file
14
lua/entities/mg_arrow_gas/init.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_mag_stunbolt.mdl")
|
||||
ENT.AoeEntity = "mg_aoe_arrow_gas"
|
||||
|
||||
local BaseClass = baseclass.Get(ENT.Base)
|
||||
|
||||
function ENT:Impact(tr, phys, bHull)
|
||||
BaseClass.Impact(self, tr, phys, bHull)
|
||||
ParticleEffectAttach("arrow_gas_ejection", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
end
|
||||
5
lua/entities/mg_arrow_gas/shared.lua
Normal file
5
lua/entities/mg_arrow_gas/shared.lua
Normal file
@@ -0,0 +1,5 @@
|
||||
ENT.Base = "mg_arrow"
|
||||
ENT.Type = "anim"
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_gas_ejection")
|
||||
3
lua/entities/mg_arrow_knockback/cl_init.lua
Normal file
3
lua/entities/mg_arrow_knockback/cl_init.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow_knockback", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
33
lua/entities/mg_arrow_knockback/init.lua
Normal file
33
lua/entities/mg_arrow_knockback/init.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_mag_firebolt.mdl")
|
||||
ENT.AoeEntity = nil
|
||||
|
||||
local BaseClass = baseclass.Get(ENT.Base)
|
||||
|
||||
function ENT:Impact(tr, phys, bHull)
|
||||
BaseClass.Impact(self, tr, phys, bHull)
|
||||
|
||||
if (tr.HitSky) then
|
||||
return
|
||||
end
|
||||
|
||||
self:EmitSound("MW19_Crossbow.Knockback")
|
||||
|
||||
local radius = self.KnockbackRadius
|
||||
|
||||
for _, e in pairs(ents.FindInSphere(tr.HitPos, radius)) do
|
||||
if ((e:IsPlayer() || e:IsNPC()) && !e:IsLineOfSightClear(tr.HitPos + tr.HitNormal * 10)) then
|
||||
continue
|
||||
end
|
||||
|
||||
local force = self.KnockbackForce * (e:IsNPC() && 1.5 || 1)
|
||||
|
||||
local dir = (e:WorldSpaceCenter() - tr.HitPos):GetNormalized()
|
||||
local curVel = e:GetVelocity()
|
||||
e:SetVelocity(Vector(curVel.x, curVel.y, 200) + dir * force)
|
||||
end
|
||||
end
|
||||
14
lua/entities/mg_arrow_knockback/shared.lua
Normal file
14
lua/entities/mg_arrow_knockback/shared.lua
Normal file
@@ -0,0 +1,14 @@
|
||||
ENT.Base = "mg_arrow"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.KnockbackRadius = 320
|
||||
ENT.KnockbackForce = 300
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.Knockback",
|
||||
channel = CHAN_BODY,
|
||||
volume = 1,
|
||||
level = 100,
|
||||
pitch = {95, 105},
|
||||
sound = {"@viper/shared/smoke_expl_body_01.ogg"}
|
||||
})
|
||||
3
lua/entities/mg_arrow_smoke/cl_init.lua
Normal file
3
lua/entities/mg_arrow_smoke/cl_init.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow_gas", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
7
lua/entities/mg_arrow_smoke/init.lua
Normal file
7
lua/entities/mg_arrow_smoke/init.lua
Normal file
@@ -0,0 +1,7 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_mag_smokebolt.mdl")
|
||||
ENT.AoeEntity = "mg_aoe_arrow_smoke"
|
||||
5
lua/entities/mg_arrow_smoke/shared.lua
Normal file
5
lua/entities/mg_arrow_smoke/shared.lua
Normal file
@@ -0,0 +1,5 @@
|
||||
ENT.Base = "mg_arrow"
|
||||
ENT.Type = "anim"
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_gas_ejection")
|
||||
3
lua/entities/mg_arrow_stim/cl_init.lua
Normal file
3
lua/entities/mg_arrow_stim/cl_init.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow_stim", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
49
lua/entities/mg_arrow_stim/init.lua
Normal file
49
lua/entities/mg_arrow_stim/init.lua
Normal file
@@ -0,0 +1,49 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_mag_stimbolt.mdl")
|
||||
ENT.AoeEntity = nil
|
||||
|
||||
local BaseClass = baseclass.Get(ENT.Base)
|
||||
|
||||
local function isCowerSupportedForNPC(npc)
|
||||
for _, a in pairs(npc:GetSequenceList()) do
|
||||
if (npc:GetSequenceActivity(npc:LookupSequence(a)) == ACT_COWER) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
local function determineHealRelationship(ent, owner)
|
||||
if (ent:IsNPC()) then
|
||||
return ent:Disposition(owner) == D_LI
|
||||
end
|
||||
|
||||
if (ent:IsPlayer()) then
|
||||
return ent:Team() == owner:Team()
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:Impact(tr, phys, bHull)
|
||||
BaseClass.Impact(self, tr, phys, bHull)
|
||||
|
||||
if (tr.HitSky) then
|
||||
return
|
||||
end
|
||||
|
||||
if (!IsValid(tr.Entity)) then
|
||||
return
|
||||
end
|
||||
|
||||
if (determineHealRelationship(tr.Entity, self:GetOwner())) then
|
||||
tr.Entity:SetHealth(math.Clamp(tr.Entity:Health() + self.HealAmount, 0, tr.Entity:GetMaxHealth()))
|
||||
tr.Entity:EmitSound("MW19_Crossbow.Heal")
|
||||
ParticleEffect("arrow_heal", tr.HitPos, Angle(), nil, 0)
|
||||
end
|
||||
end
|
||||
16
lua/entities/mg_arrow_stim/shared.lua
Normal file
16
lua/entities/mg_arrow_stim/shared.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
ENT.Base = "mg_arrow"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.HealAmount = 40
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("arrow_heal")
|
||||
|
||||
sound.Add({
|
||||
name = "MW19_Crossbow.Heal",
|
||||
channel = CHAN_BODY,
|
||||
volume = 1,
|
||||
level = 100,
|
||||
pitch = {95, 105},
|
||||
sound = {"@viper/shared/heal.wav"}
|
||||
})
|
||||
3
lua/entities/mg_arrow_thermite/cl_init.lua
Normal file
3
lua/entities/mg_arrow_thermite/cl_init.lua
Normal file
@@ -0,0 +1,3 @@
|
||||
include("shared.lua")
|
||||
|
||||
killicon.Add("mg_arrow_thermite", "VGUI/entities/mg_crossbow", Color(255, 0, 0, 255))
|
||||
7
lua/entities/mg_arrow_thermite/init.lua
Normal file
7
lua/entities/mg_arrow_thermite/init.lua
Normal file
@@ -0,0 +1,7 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.Model = Model("models/viper/mw/attachments/crossbow/attachment_vm_sn_crossbow_mag_firebolt.mdl")
|
||||
ENT.AoeEntity = "mg_aoe_arrow_thermite"
|
||||
4
lua/entities/mg_arrow_thermite/shared.lua
Normal file
4
lua/entities/mg_arrow_thermite/shared.lua
Normal file
@@ -0,0 +1,4 @@
|
||||
ENT.Base = "mg_arrow"
|
||||
ENT.Type = "anim"
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
74
lua/entities/mg_attachment.lua
Normal file
74
lua/entities/mg_attachment.lua
Normal file
@@ -0,0 +1,74 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.RenderGroup = RENDERGROUP_OTHER
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Int", 0, "Slot")
|
||||
self:NetworkVar("Int", 1, "Index")
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
if (!IsValid(self:GetOwner())) then
|
||||
error("Invalid weapon for attachment!")
|
||||
end
|
||||
|
||||
self:AddEFlags(EFL_KEEP_ON_RECREATE_ENTITIES)
|
||||
self:AddEFlags(EFL_FORCE_CHECK_TRANSMIT)
|
||||
self:AddEFlags(EFL_NO_THINK_FUNCTION)
|
||||
self:AddEFlags(EFL_NO_GAME_PHYSICS_SIMULATION)
|
||||
self:AddEFlags(EFL_DONTBLOCKLOS)
|
||||
self:AddEFlags(EFL_DONTWALKON)
|
||||
self:AddEFlags(EFL_NO_DISSOLVE)
|
||||
self:AddEFlags(EFL_NO_PHYSCANNON_INTERACTION)
|
||||
self:AddEFlags(EFL_NO_DAMAGE_FORCES)
|
||||
|
||||
self:AddFlags(FL_NOTARGET)
|
||||
self:AddFlags(FL_DONTTOUCH)
|
||||
self:AddFlags(FL_STEPMOVEMENT)
|
||||
self:SetNoDraw(true)
|
||||
|
||||
self:SetMoveType(MOVETYPE_NONE)
|
||||
self:SetSolid(SOLID_NONE)
|
||||
|
||||
self:Attach()
|
||||
end
|
||||
|
||||
function ENT:Attach()
|
||||
local weapon = self:GetOwner()
|
||||
|
||||
if (SERVER) then
|
||||
for _, child in pairs(weapon:GetChildren()) do
|
||||
if (child:GetClass() == "mg_attachment" && child:GetSlot() == self:GetSlot() && child != self) then
|
||||
child:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
weapon:Attach(self:GetSlot(), self:GetIndex())
|
||||
return
|
||||
end
|
||||
|
||||
--on client we do this gibberish
|
||||
local identifier = "mg_attachment_fixup"..self:EntIndex()
|
||||
|
||||
timer.Create(identifier, 0, 0, function()
|
||||
if (!IsValid(weapon)) then
|
||||
timer.Destroy(identifier)
|
||||
return
|
||||
end
|
||||
|
||||
if (weapon.Attach != nil && self.GetSlot != nil) then
|
||||
weapon:Attach(self:GetSlot(), self:GetIndex())
|
||||
timer.Destroy(identifier)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
--sorryyyyy garrysmod-issues/issues/5344
|
||||
local oldCleanup = game.CleanUpMap
|
||||
function game.CleanUpMap(dontSendToClients, ExtraFilters)
|
||||
dontSendToClients = dontSendToClients || false
|
||||
ExtraFilters = ExtraFilters || {}
|
||||
table.insert(ExtraFilters, "mg_attachment")
|
||||
oldCleanup(dontSendToClients, ExtraFilters)
|
||||
end
|
||||
69
lua/entities/mg_bullet/cl_init.lua
Normal file
69
lua/entities/mg_bullet/cl_init.lua
Normal file
@@ -0,0 +1,69 @@
|
||||
include("shared.lua")
|
||||
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
ENT.bWhizz = false
|
||||
|
||||
local flareMaterial = Material("sprites/orangecore1_gmod")
|
||||
|
||||
function ENT:DrawTranslucent(flags)
|
||||
self:DestroyShadow()
|
||||
|
||||
if (self:GetVelocity():Length() <= 1) then
|
||||
return
|
||||
end
|
||||
|
||||
self:DrawLight()
|
||||
self:DrawTracer()
|
||||
self:DrawBullet()
|
||||
end
|
||||
|
||||
function ENT:DrawLight()
|
||||
local dlight = DynamicLight(self:EntIndex())
|
||||
if (dlight) then
|
||||
dlight.pos = self:GetPos()
|
||||
dlight.r = 255
|
||||
dlight.g = 155
|
||||
dlight.b = 0
|
||||
dlight.brightness = 2
|
||||
dlight.Decay = 500
|
||||
dlight.Size = 128
|
||||
dlight.DieTime = CurTime() + 0.1
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DrawBullet()
|
||||
local angle = (self:GetPos() - EyePos()):Angle()
|
||||
angle:RotateAroundAxis(EyeAngles():Right(), 90)
|
||||
|
||||
local dist = math.min(self:GetPos():Distance(EyePos()), 300)
|
||||
|
||||
cam.Start3D2D(self:GetPos(), angle, dist * 0.0004)
|
||||
surface.SetDrawColor(255, 255, 255, 255)
|
||||
surface.SetMaterial(flareMaterial)
|
||||
surface.DrawTexturedRectRotated(0, 0, 32, 32, 0)
|
||||
cam.End3D2D()
|
||||
end
|
||||
|
||||
function ENT:DrawTracer()
|
||||
local angle = self:GetAngles()
|
||||
angle:RotateAroundAxis(self:GetAngles():Forward(), 90)
|
||||
|
||||
cam.Start3D2D(self:GetPos(), angle, 0.15)
|
||||
surface.SetDrawColor(255, 255, 255, 255)
|
||||
surface.SetMaterial(flareMaterial)
|
||||
surface.DrawTexturedRectUV(-512, -3, 512, 6, 0, 0, 0.5, 1)
|
||||
cam.End3D2D()
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if (!IsValid(GetViewEntity())) then
|
||||
return
|
||||
end
|
||||
|
||||
local bInRadius = EyePos():DistToSqr(self:GetPos()) < 128 * 128
|
||||
|
||||
if (bInRadius && !self.bWhizz && self:GetOwner() != GetViewEntity()) then
|
||||
GetViewEntity():EmitSound("Bullets.DefaultNearmiss")
|
||||
self.bWhizz = true
|
||||
end
|
||||
end
|
||||
112
lua/entities/mg_bullet/init.lua
Normal file
112
lua/entities/mg_bullet/init.lua
Normal file
@@ -0,0 +1,112 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
ENT.bCollided = false
|
||||
ENT.Projectile = {
|
||||
Class = "mg_bullet",
|
||||
Speed = 4000,
|
||||
Gravity = 1
|
||||
}
|
||||
ENT.Maxs = Vector(6, 6, 6)
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/weapons/ar2_grenade.mdl")
|
||||
self:PhysicsInitBox(Vector(-1, -1, -1), Vector(1, 1, 1))
|
||||
self:GetPhysicsObject():Wake()
|
||||
self:GetPhysicsObject():SetMaterial("default_silent")
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_PLAYER_PICKUP)
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_IMPACT_DMG)
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_HEAVY_OBJECT)
|
||||
self:GetPhysicsObject():EnableMotion(true)
|
||||
self:GetPhysicsObject():EnableDrag(false)
|
||||
self:GetPhysicsObject():SetMass(1000)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_IN_VEHICLE) --doesn't collide with anything, no traces
|
||||
self:AddEFlags(EFL_NO_DAMAGE_FORCES)
|
||||
self:AddEFlags(EFL_DONTWALKON)
|
||||
self:AddEFlags(EFL_DONTBLOCKLOS)
|
||||
self:AddEFlags(EFL_NO_PHYSCANNON_INTERACTION)
|
||||
|
||||
self.Projectile = table.Copy(self.Weapon.Projectile)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(self:GetAngles():Forward() * self.Projectile.Speed)
|
||||
self.LastPos = self:GetOwner():EyePos()
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if (self.bCollided && IsValid(self)) then
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
phys:AddVelocity(Vector(0, 0, self.Projectile.Gravity))
|
||||
|
||||
if (!self.bCollided) then
|
||||
--Aim assist
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Box(phys:GetPos(), -self.Maxs, self.Maxs, 0, Color(0, 200, 50, 10))
|
||||
end
|
||||
|
||||
local trData = {
|
||||
start = self.LastPos,
|
||||
endpos = phys:GetPos(),
|
||||
filter = {self:GetOwner(), self},
|
||||
mask = MASK_SHOT_PORTAL,
|
||||
collisiongroup = COLLISION_GROUP_PROJECTILE,
|
||||
mins = -self.Maxs,
|
||||
maxs = self.Maxs
|
||||
}
|
||||
|
||||
local tr = util.TraceHull(trData)
|
||||
if (tr.Hit && (tr.Entity:IsPlayer() || tr.Entity:IsNPC())) then
|
||||
self:Impact(tr, phys, true)
|
||||
return
|
||||
end
|
||||
|
||||
--Normal hitscan
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Line(self.LastPos, phys:GetPos(), 1, Color(255, 0, 0, 1))
|
||||
end
|
||||
|
||||
tr = util.TraceLine(trData)
|
||||
if (tr.Hit) then
|
||||
self:Impact(tr, phys, false)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self.LastPos = phys:GetPos()
|
||||
end
|
||||
|
||||
function ENT:Impact(tr, phys, bHull)
|
||||
if (IsValid(self.Weapon)) then
|
||||
self:FireBullets({
|
||||
Attacker = self:GetOwner(),
|
||||
Num = 1,
|
||||
Tracer = 0,
|
||||
Src = self.LastPos,
|
||||
Dir = (phys:GetPos() - self.LastPos):GetNormalized(),
|
||||
HullSize = bHull && self.Maxs:Length() * 2 || 1,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(attacker, tr, dmgInfo)
|
||||
dmgInfo:SetInflictor(self.Weapon)
|
||||
dmgInfo:SetDamageType(DMG_DIRECT + self:GetDamageType())
|
||||
self.Weapon:BulletCallback(attacker, tr, dmgInfo)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
self:Kill()
|
||||
end
|
||||
|
||||
function ENT:Kill()
|
||||
self.bCollided = true
|
||||
self:SetNoDraw(true)
|
||||
self:GetPhysicsObject():EnableMotion(false)
|
||||
end
|
||||
|
||||
function ENT:GetDamageType()
|
||||
return DMG_BULLET
|
||||
end
|
||||
5
lua/entities/mg_bullet/shared.lua
Normal file
5
lua/entities/mg_bullet/shared.lua
Normal file
@@ -0,0 +1,5 @@
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
7
lua/entities/mg_frag_grenade/cl_init.lua
Normal file
7
lua/entities/mg_frag_grenade/cl_init.lua
Normal file
@@ -0,0 +1,7 @@
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:Draw()
|
||||
|
||||
self:DrawModel()
|
||||
|
||||
end
|
||||
55
lua/entities/mg_frag_grenade/init.lua
Normal file
55
lua/entities/mg_frag_grenade/init.lua
Normal file
@@ -0,0 +1,55 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/items/grenadeammo.mdl")
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetColor(Color(0,0,0))
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
|
||||
if phys:IsValid() then
|
||||
|
||||
phys:Wake()
|
||||
|
||||
end
|
||||
|
||||
self.DetonationTime = self.FuseTime + CurTime()
|
||||
|
||||
self:Throw()
|
||||
|
||||
end
|
||||
|
||||
|
||||
function ENT:PhysicsCollide( data, phys )
|
||||
if data.Speed > 40 then
|
||||
self:EmitSound("equipment/mike67/phy_frag_bounce_concrete_med_0"..math.random(1,8).."_ext.ogg",75, 100, math.Remap(data.Speed, 40, 80, 0, 1), CHAN_AUTO)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
if self.DetonationTime <= CurTime() then
|
||||
self:Explode()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:Explode()
|
||||
ParticleEffect( "Generic_explo_high", self:GetPos(), Angle(0,0,0))
|
||||
util.BlastDamage(self, self:GetOwner(), self:GetPos(), 475, 640)
|
||||
util.ScreenShake(self:GetPos(), 8, 3, 1, 700)
|
||||
self:EmitSound("^viper/shared/frag_expl.ogg", 0, 100, 1, CHAN_WEAPON)
|
||||
util.Decal( "Scorch", self:GetPos(), self:GetPos() + Vector(0, 0, -10), {self})
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:Throw()
|
||||
local phys = self:GetPhysicsObject()
|
||||
phys:SetVelocity(self:GetOwner():GetAimVector() * 3000)
|
||||
phys:ApplyTorqueCenter( VectorRand( -3, 3) )
|
||||
end
|
||||
6
lua/entities/mg_frag_grenade/shared.lua
Normal file
6
lua/entities/mg_frag_grenade/shared.lua
Normal file
@@ -0,0 +1,6 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_gmodentity"
|
||||
|
||||
ENT.PrintName = "Frag Grenade"
|
||||
ENT.Spawnable = false
|
||||
ENT.FuseTime = 5
|
||||
84
lua/entities/mg_javelin_airstrike_warhead/cl_init.lua
Normal file
84
lua/entities/mg_javelin_airstrike_warhead/cl_init.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
include("shared.lua")
|
||||
|
||||
ENT.AutomaticFrameAdvance = true
|
||||
|
||||
|
||||
local flair = Material("shadowdark/flairs/grenade_flair.vmt")
|
||||
ENT.OuterFlairColor = Color(236,153,17,255)
|
||||
ENT.InnerFlairColor = Color(255,255,255,255)
|
||||
|
||||
ENT.OuterFlairScale = 1
|
||||
ENT.InnerFlairScale = 0.3
|
||||
|
||||
function ENT:Draw(flags)
|
||||
self:DrawModel(flags)
|
||||
|
||||
if (self.m_SpawnPos != nil && self:GetPos():Distance(self.m_SpawnPos) > 64) then
|
||||
ParticleEffectAttach("rockettrail", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
self.m_SpawnPos = nil
|
||||
end
|
||||
|
||||
local ang = LocalPlayer():EyeAngles()
|
||||
local angle = Angle( 0, LocalPlayer():EyeAngles()[2], 0 )
|
||||
|
||||
angle = Angle(LocalPlayer():EyeAngles()[1], angle.y, 0 )
|
||||
|
||||
angle:RotateAroundAxis( angle:Up(), -90 )
|
||||
angle:RotateAroundAxis( angle:Forward(), 90 )
|
||||
|
||||
cam.Start3D2D( self:GetPos() - self:GetForward() * 20, angle, 0.2 )
|
||||
|
||||
local OuterScale = 512 * self.OuterFlairScale
|
||||
local InnerScale = 512 * self.InnerFlairScale
|
||||
|
||||
surface.SetMaterial(flair)
|
||||
surface.SetDrawColor(self.OuterFlairColor)
|
||||
surface.DrawTexturedRect(-OuterScale/2, -OuterScale/2, OuterScale, OuterScale)
|
||||
|
||||
surface.SetDrawColor(self.InnerFlairColor)
|
||||
surface.DrawTexturedRect(-InnerScale/2, -InnerScale/2, InnerScale, InnerScale)
|
||||
cam.End3D2D()
|
||||
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent(flags)
|
||||
self:Draw(flags)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (self:WaterLevel() <= 0) then
|
||||
self:EmitSound("^viper/shared/rocket_expl_body_01.wav", 0, 100, 1, CHAN_WEAPON) --snd scripts dont work lol!
|
||||
|
||||
local dlight = DynamicLight(self:EntIndex())
|
||||
if (dlight) then
|
||||
dlight.pos = self:GetPos()
|
||||
dlight.r = 255
|
||||
dlight.g = 75
|
||||
dlight.b = 0
|
||||
dlight.brightness = 5
|
||||
dlight.Decay = 2000
|
||||
dlight.Size = 1024
|
||||
dlight.DieTime = CurTime() + 5
|
||||
end
|
||||
end
|
||||
|
||||
self:StopParticles()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Client Think - called every frame
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
if (self:WaterLevel() > 0) then
|
||||
self:EmitSound("viper/shared/melee/melee_world_fist_soft_plr_01.ogg", 75, 100, 0.001, CHAN_WEAPON)
|
||||
self:StopParticles()
|
||||
end
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: Called immediately after a "load"
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
239
lua/entities/mg_javelin_airstrike_warhead/init.lua
Normal file
239
lua/entities/mg_javelin_airstrike_warhead/init.lua
Normal file
@@ -0,0 +1,239 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: KeyValue
|
||||
Desc: Called when a keyvalue is added to us
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:KeyValue( key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: The game has just been reloaded. This is usually the right place
|
||||
to call the GetNW* functions to restore the script's values.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AcceptInput
|
||||
Desc: Accepts input, return true to override/accept input
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:AcceptInput( name, activator, caller, data )
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: UpdateTransmitState
|
||||
Desc: Set the transmit state
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:UpdateTransmitState()
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Entity's think function.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(colData, collider)
|
||||
if (self.m_Water && self:GetVelocity():Length() < 250) then
|
||||
timer.Simple(0, function()
|
||||
self:Remove()
|
||||
end)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local bHasExploded = false
|
||||
|
||||
for i, e in pairs(ents.FindInSphere(self:GetPos(), 16)) do
|
||||
if (e:IsNPC()) then
|
||||
self:Explode({
|
||||
HitEntity = e,
|
||||
HitNormal = (e:NearestPoint(self:GetPos()) - self:GetPos()):GetNormalized(),
|
||||
HitPos = e:NearestPoint(self:GetPos())
|
||||
})
|
||||
|
||||
if (e:GetClass() == "npc_strider") then
|
||||
e:Fire("Explode")
|
||||
end
|
||||
|
||||
bHasExploded = true
|
||||
end
|
||||
end
|
||||
|
||||
if (!bHasExploded) then
|
||||
self:Explode(colData)
|
||||
end
|
||||
end
|
||||
|
||||
local function WithinRange(num,min,max)
|
||||
return num < max && num > min
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
|
||||
self.Target:SetPos(phys:GetPos())
|
||||
|
||||
debugoverlay.Cross( self.TrackedPosition, 30, 1, Color( 255, 255, 255 ), true )
|
||||
|
||||
self.m_Fuel = self.m_Fuel - 100 * FrameTime()
|
||||
|
||||
if (self.m_Propel && self.m_Fuel <= 0) then
|
||||
self.m_Propel = false
|
||||
phys:EnableDrag(true)
|
||||
phys:EnableGravity(true)
|
||||
phys:AddVelocity(phys:GetAngles():Forward() * self.Projectile.Speed)
|
||||
end
|
||||
|
||||
if (self.m_Propel) then
|
||||
|
||||
if self.TrackedEntity && self.TrackedEntity:IsValid() then
|
||||
self.TargetPos = self.TrackedEntity:GetPos()
|
||||
else
|
||||
--self.TrackedPosition = self.WeaponData.TrackedPosition
|
||||
end
|
||||
|
||||
phys:SetPos(self.LastPos + phys:GetAngles():Forward() * (self.Projectile.Speed * FrameTime()) - (Vector(0, 0, self.m_gravity) * FrameTime()))
|
||||
|
||||
if (self.m_State == "Ascent") then
|
||||
local angle = phys:GetAngles()
|
||||
angle.p = math.Clamp(angle.p - 6, -89, 89)
|
||||
phys:SetAngles(angle)
|
||||
if self:GetPos().z >= self.CruiseHeight then
|
||||
self.m_State = "Cruise"
|
||||
end
|
||||
elseif (self.m_State == "Cruise") then
|
||||
local range = 1100
|
||||
local angle = phys:GetAngles()
|
||||
angle.p = math.Clamp(angle.p + 2, -90,-0)
|
||||
phys:SetAngles(angle)
|
||||
if WithinRange(phys:GetPos().x,self.TrackedPosition.x - range,self.TrackedPosition.x + range) && WithinRange(phys:GetPos().y,self.TrackedPosition.y - range,self.TrackedPosition.y + range) then
|
||||
self:Explode()
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
local vel = phys:GetVelocity()
|
||||
phys:SetAngles(vel:Angle() + Angle(self.Projectile.Gravity,math.Rand(self.m_Stability / -self.Projectile.Stability, self.m_Stability / self.Projectile.Stability),self.m_gravity))
|
||||
phys:SetVelocity(vel)
|
||||
end
|
||||
|
||||
if (!self.bCollided) then
|
||||
--Aim assist
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Box(phys:GetPos(), -self.Maxs, self.Maxs, 0, Color(0, 200, 50, 10))
|
||||
end
|
||||
|
||||
local trData = {
|
||||
start = self.LastPos,
|
||||
endpos = phys:GetPos(),
|
||||
filter = {self:GetOwner(), self},
|
||||
mask = MASK_SHOT_PORTAL,
|
||||
collisiongroup = COLLISION_GROUP_NONE,
|
||||
mins = -self:OBBMaxs(),
|
||||
maxs = self:OBBMins()
|
||||
}
|
||||
|
||||
local tr = util.TraceHull(trData)
|
||||
|
||||
if (tr.Hit && (tr.Entity:IsPlayer() || tr.Entity:IsNPC())) then
|
||||
self:SetPos(tr.HitPos)
|
||||
self:Explode(tr)
|
||||
|
||||
if (tr.Entity:GetClass() == "npc_strider") then
|
||||
tr.Entity:Fire("Explode")
|
||||
elseif tr.Entity:GetClass() != self:GetClass() && tr.Entity:GetClass() != "mg_javelin_airstrike_warhead" then
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamage(1)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
dmg:SetInflictor(self)
|
||||
tr.Entity:TakeDamageInfo(dmg)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
--Normal hitscan
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Line(self.LastPos, phys:GetPos(), 1, Color(255, 0, 0, 1))
|
||||
end
|
||||
|
||||
tr = util.TraceLine(trData)
|
||||
|
||||
if (tr.Hit) then
|
||||
self:SetPos(tr.HitPos)
|
||||
self:Explode(tr)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self.LastPos = phys:GetPos()
|
||||
end
|
||||
|
||||
function ENT:Explode()
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if (self:WaterLevel() <= 0) then
|
||||
ParticleEffect("Generic_explo_high", phys:GetPos(),Angle(0,0,0))
|
||||
else
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin(phys:GetPos())
|
||||
util.Effect("WaterSurfaceExplosion", effectdata)
|
||||
end
|
||||
|
||||
local dmgInfo = DamageInfo()
|
||||
dmgInfo:SetDamage(50)
|
||||
dmgInfo:SetAttacker(IsValid(self:GetOwner()) && self:GetOwner() || self)
|
||||
dmgInfo:SetInflictor(self)
|
||||
dmgInfo:SetDamageType(self:GetDamageType())
|
||||
util.BlastDamageInfo(dmgInfo, phys:GetPos(), self.WeaponData.Explosive.BlastRadius)
|
||||
|
||||
util.ScreenShake(phys:GetPos(), 3500, 1111, 1, self.WeaponData.Explosive.BlastRadius * 4)
|
||||
|
||||
|
||||
--release submunitions
|
||||
|
||||
for i = 1,12,1 do
|
||||
local ent = ents.Create("mg_submunition")
|
||||
ent:SetPos(self:GetPos())
|
||||
ent:SetAngles(AngleRand())
|
||||
ent.LastPos = self:GetPos()
|
||||
ent:SetOwner(self:GetOwner())
|
||||
ent.Damage = self.Weapon.Bullet.Damage[1] / 12
|
||||
|
||||
if self.TrackedEntity then
|
||||
ent.TrackedEntity = self.TrackedEntity
|
||||
else
|
||||
local ents = ents.FindInSphere(self.TrackedPosition, 1000)
|
||||
local targets = {}
|
||||
for k,v in pairs(ents) do
|
||||
if v:IsNPC() || v:IsPlayer() || v:IsVehicle() then
|
||||
table.insert(targets, v)
|
||||
end
|
||||
end
|
||||
PrintTable(targets)
|
||||
if targets[1] then
|
||||
ent.TrackedEntity = targets[math.random(1, #targets)]
|
||||
end
|
||||
end
|
||||
|
||||
timer.Simple(i/50, function()
|
||||
ent:Spawn()
|
||||
end)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:GetDamageType()
|
||||
return DMG_BLAST + DMG_AIRBOAT
|
||||
end
|
||||
79
lua/entities/mg_javelin_airstrike_warhead/shared.lua
Normal file
79
lua/entities/mg_javelin_airstrike_warhead/shared.lua
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
|
||||
ENT.ExplosionRadius = 430
|
||||
ENT.ExplosionDamage = 700
|
||||
|
||||
game.AddParticles("particles/explosion_fx_ins.pcf")
|
||||
game.AddParticles("particles/ins_rockettrail.pcf")
|
||||
PrecacheParticleSystem("ins_C4_explosion")
|
||||
PrecacheParticleSystem("ins_grenade_explosion")
|
||||
PrecacheParticleSystem("ins_m203_explosion")
|
||||
PrecacheParticleSystem("ins_rpg_explosion")
|
||||
PrecacheParticleSystem("rockettrail")
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Initialize
|
||||
Desc: First function called. Use to set up your entity
|
||||
-----------------------------------------------------------]]
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/viper/mw/weapons/w_juliet_rocket.mdl")
|
||||
self:AddEFlags(EFL_FORCE_CHECK_TRANSMIT)
|
||||
self:SetCustomCollisionCheck(true)
|
||||
|
||||
if (SERVER) then
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:GetPhysicsObject():SetMaterial("metal")
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_PLAYER_PICKUP)
|
||||
self:GetPhysicsObject():EnableDrag(false)
|
||||
self:GetPhysicsObject():EnableGravity(false)
|
||||
self:GetPhysicsObject():Wake()
|
||||
|
||||
self.Projectile = table.Copy(self.Weapon.Projectile)
|
||||
self.WeaponData = self.Weapon:GetTable()
|
||||
|
||||
self.m_Propel = true
|
||||
self.m_Fuel = self.Projectile.Fuel
|
||||
self.m_Stability = 0
|
||||
self.m_Water = false
|
||||
self.m_State = "Ascent"
|
||||
self.LastPos = self:GetOwner():EyePos()
|
||||
self.Target = ents.Create("info_target")
|
||||
self.Target:Spawn()
|
||||
|
||||
local up = self:GetPos()
|
||||
up.z = up.z + 2000
|
||||
|
||||
local tr = util.TraceLine( {
|
||||
start = self:GetPos(),
|
||||
endpos = up,
|
||||
filter = {self,self:GetOwner()}
|
||||
} )
|
||||
|
||||
self.CruiseHeight = tr.HitPos.z - 900
|
||||
|
||||
if self.WeaponData.TrackedEntity then
|
||||
self.m_Tracking = self.Projectile.Tracking
|
||||
self.TrackedEntity = self.WeaponData.TrackedEntity
|
||||
self.TrackedPosition = self.WeaponData.TrackedEntity:GetPos()
|
||||
else
|
||||
local tr = self.Weapon:GetOwner():GetEyeTrace()
|
||||
self.TrackedPosition = tr.HitPos
|
||||
self.TargetPos = tr.HitPos
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
self.m_SpawnPos = self:GetPos()
|
||||
self:EmitSound("^weapons/juliet/weap_juliet_proj_lp_01.wav", SNDLVL_180db, 100, 1, CHAN_WEAPON)
|
||||
end
|
||||
end
|
||||
84
lua/entities/mg_javelin_warhead/cl_init.lua
Normal file
84
lua/entities/mg_javelin_warhead/cl_init.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
include("shared.lua")
|
||||
|
||||
ENT.AutomaticFrameAdvance = true
|
||||
|
||||
|
||||
local flair = Material("shadowdark/flairs/grenade_flair.vmt")
|
||||
ENT.OuterFlairColor = Color(236,153,17,255)
|
||||
ENT.InnerFlairColor = Color(255,255,255,255)
|
||||
|
||||
ENT.OuterFlairScale = 1
|
||||
ENT.InnerFlairScale = 0.3
|
||||
|
||||
function ENT:Draw(flags)
|
||||
self:DrawModel(flags)
|
||||
|
||||
if (self.m_SpawnPos != nil && self:GetPos():Distance(self.m_SpawnPos) > 64) then
|
||||
ParticleEffectAttach("rockettrail", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
self.m_SpawnPos = nil
|
||||
end
|
||||
|
||||
local ang = LocalPlayer():EyeAngles()
|
||||
local angle = Angle( 0, LocalPlayer():EyeAngles()[2], 0 )
|
||||
|
||||
angle = Angle(LocalPlayer():EyeAngles()[1], angle.y, 0 )
|
||||
|
||||
angle:RotateAroundAxis( angle:Up(), -90 )
|
||||
angle:RotateAroundAxis( angle:Forward(), 90 )
|
||||
|
||||
cam.Start3D2D( self:GetPos() - self:GetForward() * 20, angle, 0.2 )
|
||||
|
||||
local OuterScale = 512 * self.OuterFlairScale
|
||||
local InnerScale = 512 * self.InnerFlairScale
|
||||
|
||||
surface.SetMaterial(flair)
|
||||
surface.SetDrawColor(self.OuterFlairColor)
|
||||
surface.DrawTexturedRect(-OuterScale/2, -OuterScale/2, OuterScale, OuterScale)
|
||||
|
||||
surface.SetDrawColor(self.InnerFlairColor)
|
||||
surface.DrawTexturedRect(-InnerScale/2, -InnerScale/2, InnerScale, InnerScale)
|
||||
cam.End3D2D()
|
||||
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent(flags)
|
||||
self:Draw(flags)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (self:WaterLevel() <= 0) then
|
||||
self:EmitSound("^viper/shared/rocket_expl_env_0"..math.random(1, 3)..".wav", 150, 100, 1, CHAN_WEAPON) --snd scripts dont work lol!
|
||||
|
||||
local dlight = DynamicLight(self:EntIndex())
|
||||
if (dlight) then
|
||||
dlight.pos = self:GetPos()
|
||||
dlight.r = 255
|
||||
dlight.g = 75
|
||||
dlight.b = 0
|
||||
dlight.brightness = 5
|
||||
dlight.Decay = 2000
|
||||
dlight.Size = 1024
|
||||
dlight.DieTime = CurTime() + 5
|
||||
end
|
||||
end
|
||||
|
||||
self:StopParticles()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Client Think - called every frame
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
if (self:WaterLevel() > 0) then
|
||||
self:EmitSound("viper/shared/melee/melee_world_fist_soft_plr_01.ogg", 75, 100, 0.001, CHAN_WEAPON)
|
||||
self:StopParticles()
|
||||
end
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: Called immediately after a "load"
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
224
lua/entities/mg_javelin_warhead/init.lua
Normal file
224
lua/entities/mg_javelin_warhead/init.lua
Normal file
@@ -0,0 +1,224 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: KeyValue
|
||||
Desc: Called when a keyvalue is added to us
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:KeyValue( key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: The game has just been reloaded. This is usually the right place
|
||||
to call the GetNW* functions to restore the script's values.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AcceptInput
|
||||
Desc: Accepts input, return true to override/accept input
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:AcceptInput( name, activator, caller, data )
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: UpdateTransmitState
|
||||
Desc: Set the transmit state
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:UpdateTransmitState()
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Entity's think function.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(colData, collider)
|
||||
if (self.m_Water && self:GetVelocity():Length() < 250) then
|
||||
timer.Simple(0, function()
|
||||
self:Remove()
|
||||
end)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local bHasExploded = false
|
||||
|
||||
for i, e in pairs(ents.FindInSphere(self:GetPos(), 16)) do
|
||||
if (e:IsNPC()) then
|
||||
self:Explode({
|
||||
HitEntity = e,
|
||||
HitNormal = (e:NearestPoint(self:GetPos()) - self:GetPos()):GetNormalized(),
|
||||
HitPos = e:NearestPoint(self:GetPos())
|
||||
})
|
||||
|
||||
if (e:GetClass() == "npc_strider") then
|
||||
e:Fire("Explode")
|
||||
end
|
||||
|
||||
bHasExploded = true
|
||||
end
|
||||
end
|
||||
|
||||
if (!bHasExploded) then
|
||||
self:Explode(colData)
|
||||
end
|
||||
end
|
||||
|
||||
local function WithinRange(num,min,max)
|
||||
return num < max && num > min
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
|
||||
self.Target:SetPos(phys:GetPos())
|
||||
|
||||
debugoverlay.Cross( self.TrackedPosition, 30, 1, Color( 255, 255, 255 ), true )
|
||||
|
||||
self.m_Fuel = self.m_Fuel - 100 * FrameTime()
|
||||
|
||||
if (self.m_Propel && self.m_Fuel <= 0) then
|
||||
self.m_Propel = false
|
||||
phys:EnableDrag(true)
|
||||
phys:EnableGravity(true)
|
||||
phys:AddVelocity(phys:GetAngles():Forward() * self.Projectile.Speed)
|
||||
end
|
||||
|
||||
if (self.m_Propel) then
|
||||
|
||||
if self.TrackedEntity && self.TrackedEntity:IsValid() then
|
||||
self.TargetPos = self.TrackedEntity:GetPos()
|
||||
else
|
||||
--self.TrackedPosition = self.WeaponData.TrackedPosition
|
||||
end
|
||||
|
||||
phys:SetPos(self.LastPos + phys:GetAngles():Forward() * (self.Projectile.Speed * FrameTime()) - (Vector(0, 0, self.m_gravity) * FrameTime()))
|
||||
|
||||
if (self.m_State == "Ascent") then
|
||||
local angle = phys:GetAngles()
|
||||
angle.p = math.Clamp(angle.p - 6, -89, 89)
|
||||
phys:SetAngles(angle)
|
||||
if self:GetPos().z >= self.CruiseHeight then
|
||||
self.m_State = "Cruise"
|
||||
end
|
||||
elseif (self.m_State == "Cruise") then
|
||||
local range = 1100
|
||||
local angle = phys:GetAngles()
|
||||
angle.p = math.Clamp(angle.p + 2, -90,-0)
|
||||
phys:SetAngles(angle)
|
||||
if WithinRange(phys:GetPos().x,self.TrackedPosition.x - range,self.TrackedPosition.x + range) && WithinRange(phys:GetPos().y,self.TrackedPosition.y - range,self.TrackedPosition.y + range) then
|
||||
self.m_State = "Seek"
|
||||
end
|
||||
elseif (self.m_State == "Seek") then
|
||||
local dir = self.TargetPos - phys:GetPos()
|
||||
phys:SetAngles(LerpAngle(0.09, phys:GetAngles(), dir:Angle()))
|
||||
end
|
||||
|
||||
else
|
||||
local vel = phys:GetVelocity()
|
||||
phys:SetAngles(vel:Angle() + Angle(self.Projectile.Gravity,math.Rand(self.m_Stability / -self.Projectile.Stability, self.m_Stability / self.Projectile.Stability),self.m_gravity))
|
||||
phys:SetVelocity(vel)
|
||||
end
|
||||
|
||||
if (!self.bCollided) then
|
||||
--Aim assist
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Box(phys:GetPos(), -self.Maxs, self.Maxs, 0, Color(0, 200, 50, 10))
|
||||
end
|
||||
|
||||
local trData = {
|
||||
start = self.LastPos,
|
||||
endpos = phys:GetPos(),
|
||||
filter = {self:GetOwner(), self},
|
||||
mask = MASK_SHOT_PORTAL,
|
||||
collisiongroup = COLLISION_GROUP_NONE,
|
||||
mins = -self:OBBMaxs(),
|
||||
maxs = self:OBBMins()
|
||||
}
|
||||
|
||||
local tr = util.TraceHull(trData)
|
||||
|
||||
if (tr.Hit && (tr.Entity:IsPlayer() || tr.Entity:IsNPC())) then
|
||||
self:SetPos(tr.HitPos)
|
||||
self:ImpactDamage(tr.Entity)
|
||||
self:Explode(tr)
|
||||
|
||||
if (tr.Entity:GetClass() == "npc_strider") then
|
||||
tr.Entity:Fire("Explode")
|
||||
elseif (tr.Entity:GetClass() == "npc_combinegunship") then
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamage(1)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
dmg:SetInflictor(self)
|
||||
tr.Entity:TakeDamageInfo(dmg)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
--Normal hitscan
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Line(self.LastPos, phys:GetPos(), 1, Color(255, 0, 0, 1))
|
||||
end
|
||||
|
||||
tr = util.TraceLine(trData)
|
||||
|
||||
if (tr.Hit) then
|
||||
self:SetPos(tr.HitPos)
|
||||
self:ImpactDamage(tr.Entity)
|
||||
self:Explode(tr)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self.LastPos = phys:GetPos()
|
||||
end
|
||||
|
||||
function ENT:Explode(trData)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if (self:WaterLevel() <= 0) then
|
||||
ParticleEffect("Generic_explo_vhigh", phys:GetPos() + trData.HitNormal,Angle(0,0,0))
|
||||
else
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin(phys:GetPos())
|
||||
util.Effect("WaterSurfaceExplosion", effectdata)
|
||||
end
|
||||
|
||||
local dmgInfo = DamageInfo()
|
||||
dmgInfo:SetDamage(self.WeaponData.Bullet.Damage[1])
|
||||
dmgInfo:SetAttacker(IsValid(self:GetOwner()) && self:GetOwner() || self)
|
||||
dmgInfo:SetInflictor(self)
|
||||
dmgInfo:SetDamageType(self:GetDamageType())
|
||||
util.BlastDamageInfo(dmgInfo, phys:GetPos(), self.WeaponData.Explosive.BlastRadius)
|
||||
|
||||
util.ScreenShake(phys:GetPos(), 3500, 1111, 1, self.WeaponData.Explosive.BlastRadius * 4)
|
||||
|
||||
util.Decal("Scorch", trData.HitPos - trData.HitNormal, trData.HitPos + trData.HitNormal, self)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:ImpactDamage(ent)
|
||||
local dmgInfo = DamageInfo()
|
||||
dmgInfo:SetDamage(self.WeaponData.Bullet.Damage[1] / self.WeaponData.Explosive.ImpactBlastRatio)
|
||||
dmgInfo:SetAttacker(IsValid(self:GetOwner()) && self:GetOwner() || self)
|
||||
dmgInfo:SetInflictor(self)
|
||||
dmgInfo:SetDamageType(self:GetDamageType())
|
||||
dmgInfo:SetDamagePosition(self:GetPos())
|
||||
ent:TakeDamageInfo(dmgInfo)
|
||||
end
|
||||
|
||||
function ENT:GetDamageType()
|
||||
return DMG_BLAST + DMG_AIRBOAT
|
||||
end
|
||||
79
lua/entities/mg_javelin_warhead/shared.lua
Normal file
79
lua/entities/mg_javelin_warhead/shared.lua
Normal file
@@ -0,0 +1,79 @@
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
|
||||
ENT.ExplosionRadius = 430
|
||||
ENT.ExplosionDamage = 700
|
||||
|
||||
game.AddParticles("particles/explosion_fx_ins.pcf")
|
||||
game.AddParticles("particles/ins_rockettrail.pcf")
|
||||
PrecacheParticleSystem("ins_C4_explosion")
|
||||
PrecacheParticleSystem("ins_grenade_explosion")
|
||||
PrecacheParticleSystem("ins_m203_explosion")
|
||||
PrecacheParticleSystem("ins_rpg_explosion")
|
||||
PrecacheParticleSystem("rockettrail")
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Initialize
|
||||
Desc: First function called. Use to set up your entity
|
||||
-----------------------------------------------------------]]
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/viper/mw/weapons/w_juliet_rocket.mdl")
|
||||
self:AddEFlags(EFL_FORCE_CHECK_TRANSMIT)
|
||||
self:SetCustomCollisionCheck(true)
|
||||
|
||||
if (SERVER) then
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:GetPhysicsObject():SetMaterial("metal")
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_PLAYER_PICKUP)
|
||||
self:GetPhysicsObject():EnableDrag(false)
|
||||
self:GetPhysicsObject():EnableGravity(false)
|
||||
self:GetPhysicsObject():Wake()
|
||||
|
||||
self.Projectile = table.Copy(self.Weapon.Projectile)
|
||||
self.WeaponData = self.Weapon:GetTable()
|
||||
|
||||
self.m_Propel = true
|
||||
self.m_Fuel = self.Projectile.Fuel
|
||||
self.m_Stability = 0
|
||||
self.m_Water = false
|
||||
self.m_State = "Ascent"
|
||||
self.LastPos = self:GetOwner():EyePos()
|
||||
self.Target = ents.Create("info_target")
|
||||
self.Target:Spawn()
|
||||
|
||||
local up = self:GetPos()
|
||||
up.z = up.z + 2000
|
||||
|
||||
local tr = util.TraceLine( {
|
||||
start = self:GetPos(),
|
||||
endpos = up,
|
||||
filter = {self,self:GetOwner()}
|
||||
} )
|
||||
|
||||
self.CruiseHeight = tr.HitPos.z - 900
|
||||
|
||||
if self.WeaponData.TrackedEntity then
|
||||
self.m_Tracking = self.Projectile.Tracking
|
||||
self.TrackedEntity = self.WeaponData.TrackedEntity
|
||||
self.TrackedPosition = self.WeaponData.TrackedEntity:GetPos()
|
||||
else
|
||||
local tr = self.Weapon:GetOwner():GetEyeTrace()
|
||||
self.TrackedPosition = tr.HitPos
|
||||
self.TargetPos = tr.HitPos
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
self.m_SpawnPos = self:GetPos()
|
||||
self:EmitSound("^weapons/juliet/weap_juliet_proj_lp_01.wav", SNDLVL_180db, 100, 1, CHAN_WEAPON)
|
||||
end
|
||||
end
|
||||
9
lua/entities/mg_slug/cl_init.lua
Normal file
9
lua/entities/mg_slug/cl_init.lua
Normal file
@@ -0,0 +1,9 @@
|
||||
include("shared.lua")
|
||||
|
||||
local base = baseclass.Get(ENT.Base)
|
||||
|
||||
function ENT:DrawTracer()
|
||||
if (GetViewEntity() == self:GetOwner()) then
|
||||
base.DrawTracer(self)
|
||||
end
|
||||
end
|
||||
8
lua/entities/mg_slug/init.lua
Normal file
8
lua/entities/mg_slug/init.lua
Normal file
@@ -0,0 +1,8 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:GetDamageType()
|
||||
return DMG_BUCKSHOT
|
||||
end
|
||||
1
lua/entities/mg_slug/shared.lua
Normal file
1
lua/entities/mg_slug/shared.lua
Normal file
@@ -0,0 +1 @@
|
||||
ENT.Base = "mg_bullet"
|
||||
29
lua/entities/mg_sniper_bullet/cl_init.lua
Normal file
29
lua/entities/mg_sniper_bullet/cl_init.lua
Normal file
@@ -0,0 +1,29 @@
|
||||
include("shared.lua")
|
||||
|
||||
local BaseClass = baseclass.Get(ENT.Base)
|
||||
local flareMaterial = Material("sprites/orangecore1_gmod")
|
||||
|
||||
ENT.bTracerOn = false
|
||||
|
||||
function ENT:DrawTracer()
|
||||
end
|
||||
|
||||
function ENT:DrawBullet()
|
||||
if (!self.bTracerOn) then
|
||||
ParticleEffectAttach("bullet_sniper_smoke", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
self.bTracerOn = true
|
||||
end
|
||||
|
||||
if (GetViewEntity() == self:GetOwner()) then
|
||||
local angle = (self:GetPos() - EyePos()):Angle()
|
||||
angle:RotateAroundAxis(EyeAngles():Right(), 90)
|
||||
|
||||
local dist = math.min(self:GetPos():Distance(EyePos()), 2300)
|
||||
|
||||
cam.Start3D2D(self:GetPos(), angle, dist * 0.0001)
|
||||
surface.SetDrawColor(255, 255, 255, 255)
|
||||
surface.SetMaterial(flareMaterial)
|
||||
surface.DrawTexturedRectRotated(0, 0, 32, 32, 0)
|
||||
cam.End3D2D()
|
||||
end
|
||||
end
|
||||
55
lua/entities/mg_sniper_bullet/init.lua
Normal file
55
lua/entities/mg_sniper_bullet/init.lua
Normal file
@@ -0,0 +1,55 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
function ENT:GetDamageType()
|
||||
return DMG_SNIPER
|
||||
end
|
||||
|
||||
ENT.m_gravity = 0
|
||||
ENT.Maxs = Vector(3, 3, 3)
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
self.m_gravity = self.m_gravity + (self.Projectile.Gravity)
|
||||
|
||||
phys:SetPos(self.LastPos + phys:GetAngles():Forward() * (self.Projectile.Speed * FrameTime()) - (Vector(0, 0, self.m_gravity) * FrameTime()))
|
||||
|
||||
if (!self.bCollided) then
|
||||
--Aim assist
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Box(phys:GetPos(), -self.Maxs, self.Maxs, 0, Color(0, 200, 50, 10))
|
||||
end
|
||||
|
||||
local trData = {
|
||||
start = self.LastPos,
|
||||
endpos = phys:GetPos(),
|
||||
filter = {self:GetOwner(), self},
|
||||
mask = MASK_SHOT_PORTAL,
|
||||
collisiongroup = COLLISION_GROUP_PROJECTILE,
|
||||
mins = -self.Maxs,
|
||||
maxs = self.Maxs
|
||||
}
|
||||
|
||||
local tr = util.TraceHull(trData)
|
||||
|
||||
if (tr.Hit && (tr.Entity:IsPlayer() || tr.Entity:IsNPC())) then
|
||||
self:Impact(tr, phys, true)
|
||||
return
|
||||
end
|
||||
|
||||
--Normal hitscan
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Line(self.LastPos, phys:GetPos(), 1, Color(255, 0, 0, 1))
|
||||
end
|
||||
|
||||
tr = util.TraceLine(trData)
|
||||
|
||||
if (tr.Hit) then
|
||||
self:Impact(tr, phys, false)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
self.LastPos = phys:GetPos()
|
||||
end
|
||||
5
lua/entities/mg_sniper_bullet/shared.lua
Normal file
5
lua/entities/mg_sniper_bullet/shared.lua
Normal file
@@ -0,0 +1,5 @@
|
||||
ENT.Base = "mg_bullet"
|
||||
|
||||
game.AddParticles("particles/mw19_attachments.pcf")
|
||||
PrecacheParticleSystem("bullet_sniper_smoke")
|
||||
PrecacheParticleSystem("bullet_sniper_tracer")
|
||||
84
lua/entities/mg_submunition/cl_init.lua
Normal file
84
lua/entities/mg_submunition/cl_init.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
include("shared.lua")
|
||||
|
||||
ENT.AutomaticFrameAdvance = true
|
||||
|
||||
|
||||
local flair = Material("shadowdark/flairs/grenade_flair.vmt")
|
||||
ENT.OuterFlairColor = Color(236,153,17,255)
|
||||
ENT.InnerFlairColor = Color(255,255,255,255)
|
||||
|
||||
ENT.OuterFlairScale = 1
|
||||
ENT.InnerFlairScale = 0.3
|
||||
|
||||
function ENT:Draw(flags)
|
||||
self:DrawModel(flags)
|
||||
|
||||
if (self.m_SpawnPos != nil && self:GetPos():Distance(self.m_SpawnPos) > 64) then
|
||||
ParticleEffectAttach("rockettrail", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
self.m_SpawnPos = nil
|
||||
end
|
||||
|
||||
local ang = LocalPlayer():EyeAngles()
|
||||
local angle = Angle( 0, LocalPlayer():EyeAngles()[2], 0 )
|
||||
|
||||
angle = Angle(LocalPlayer():EyeAngles()[1], angle.y, 0 )
|
||||
|
||||
angle:RotateAroundAxis( angle:Up(), -90 )
|
||||
angle:RotateAroundAxis( angle:Forward(), 90 )
|
||||
|
||||
cam.Start3D2D( self:GetPos() - self:GetForward() * -5, angle, 0.2 )
|
||||
|
||||
local OuterScale = 512 * self.OuterFlairScale
|
||||
local InnerScale = 512 * self.InnerFlairScale
|
||||
|
||||
surface.SetMaterial(flair)
|
||||
surface.SetDrawColor(self.OuterFlairColor)
|
||||
surface.DrawTexturedRect(-OuterScale/2, -OuterScale/2, OuterScale, OuterScale)
|
||||
|
||||
surface.SetDrawColor(self.InnerFlairColor)
|
||||
surface.DrawTexturedRect(-InnerScale/2, -InnerScale/2, InnerScale, InnerScale)
|
||||
cam.End3D2D()
|
||||
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent(flags)
|
||||
self:Draw(flags)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (self:WaterLevel() <= 0) then
|
||||
self:EmitSound("^viper/shared/rocket_expl_body_01.wav", 150, 100, 1, CHAN_WEAPON) --snd scripts dont work lol!
|
||||
|
||||
local dlight = DynamicLight(self:EntIndex())
|
||||
if (dlight) then
|
||||
dlight.pos = self:GetPos()
|
||||
dlight.r = 255
|
||||
dlight.g = 75
|
||||
dlight.b = 0
|
||||
dlight.brightness = 5
|
||||
dlight.Decay = 2000
|
||||
dlight.Size = 1024
|
||||
dlight.DieTime = CurTime() + 5
|
||||
end
|
||||
end
|
||||
|
||||
self:StopParticles()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Client Think - called every frame
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
if (self:WaterLevel() > 0) then
|
||||
self:EmitSound("viper/shared/melee/melee_world_fist_soft_plr_01.ogg", 75, 100, 0.001, CHAN_WEAPON)
|
||||
self:StopParticles()
|
||||
end
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: Called immediately after a "load"
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
175
lua/entities/mg_submunition/init.lua
Normal file
175
lua/entities/mg_submunition/init.lua
Normal file
@@ -0,0 +1,175 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: KeyValue
|
||||
Desc: Called when a keyvalue is added to us
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:KeyValue( key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: The game has just been reloaded. This is usually the right place
|
||||
to call the GetNW* functions to restore the script's values.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AcceptInput
|
||||
Desc: Accepts input, return true to override/accept input
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:AcceptInput( name, activator, caller, data )
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: UpdateTransmitState
|
||||
Desc: Set the transmit state
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:UpdateTransmitState()
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(colData, collider)
|
||||
if (self.m_Water && self:GetVelocity():Length() < 250) then
|
||||
timer.Simple(0, function()
|
||||
self:Remove()
|
||||
end)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local bHasExploded = false
|
||||
|
||||
for i, e in pairs(ents.FindInSphere(self:GetPos(), 16)) do
|
||||
if (e:IsNPC()) then
|
||||
self:Explode({
|
||||
HitEntity = e,
|
||||
HitNormal = (e:NearestPoint(self:GetPos()) - self:GetPos()):GetNormalized(),
|
||||
HitPos = e:NearestPoint(self:GetPos())
|
||||
})
|
||||
|
||||
bHasExploded = true
|
||||
end
|
||||
end
|
||||
|
||||
if (!bHasExploded) then
|
||||
self:Explode(colData)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
|
||||
self.m_Fuel = self.m_Fuel - 100 * FrameTime()
|
||||
self.m_Stability = self.m_Stability + 700 * FrameTime()
|
||||
|
||||
if (self.m_Propel && self.m_Fuel <= 0) then
|
||||
self.m_Propel = false
|
||||
phys:EnableDrag(true)
|
||||
phys:EnableGravity(true)
|
||||
phys:AddVelocity(phys:GetAngles():Forward() * self.Speed)
|
||||
end
|
||||
|
||||
if (self.m_Propel) then
|
||||
|
||||
phys:SetPos(self.LastPos + phys:GetAngles():Forward() * (self.Speed * FrameTime()))
|
||||
|
||||
if self.TrackedEntity && self.TrackedEntity:IsValid() then
|
||||
local dir = self.TrackedEntity:WorldSpaceCenter() - phys:GetPos()
|
||||
phys:SetAngles(LerpAngle(0.1, phys:GetAngles(), dir:Angle()))
|
||||
else
|
||||
self.m_Fuel = 0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if (!self.bCollided) then
|
||||
--Aim assist
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Box(phys:GetPos(), -self.Maxs, self.Maxs, 0, Color(0, 200, 50, 10))
|
||||
end
|
||||
|
||||
local trData = {
|
||||
start = self.LastPos,
|
||||
endpos = phys:GetPos(),
|
||||
filter = {self:GetOwner(), self},
|
||||
mask = MASK_SHOT_PORTAL,
|
||||
collisiongroup = COLLISION_GROUP_NONE,
|
||||
mins = -self:OBBMaxs(),
|
||||
maxs = self:OBBMins()
|
||||
}
|
||||
|
||||
local tr = util.TraceHull(trData)
|
||||
|
||||
if (tr.Hit && (tr.Entity:IsPlayer() || tr.Entity:IsNPC())) then
|
||||
self:SetPos(tr.HitPos)
|
||||
self:Explode(tr)
|
||||
return
|
||||
end
|
||||
|
||||
--Normal hitscan
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Line(self.LastPos, phys:GetPos(), 1, Color(255, 0, 0, 1))
|
||||
end
|
||||
|
||||
tr = util.TraceLine(trData)
|
||||
|
||||
if (tr.Hit) then
|
||||
if tr.Entity:GetClass() == "func_breakable_surf" then
|
||||
--shatter glass windows and other weak surfaces
|
||||
util.BlastDamage(self, self, tr.HitPos, 1, 1)
|
||||
elseif tr.Entity:GetClass() != self:GetClass() && tr.Entity:GetClass() != "mg_javelin_airstrike_warhead" then
|
||||
self:SetPos(tr.HitPos)
|
||||
self:Explode(tr)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.LastPos = phys:GetPos()
|
||||
end
|
||||
|
||||
function ENT:Explode(trData)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if (self:WaterLevel() <= 0) then
|
||||
ParticleEffect("Generic_explo_mid", phys:GetPos() + trData.HitNormal,Angle(0,0,0))
|
||||
else
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin(phys:GetPos())
|
||||
util.Effect("WaterSurfaceExplosion", effectdata)
|
||||
end
|
||||
|
||||
local dmgInfo = DamageInfo()
|
||||
dmgInfo:SetDamage(self.Damage)
|
||||
dmgInfo:SetAttacker(IsValid(self:GetOwner()) && self:GetOwner() || self)
|
||||
dmgInfo:SetInflictor(self)
|
||||
dmgInfo:SetDamageType(self:GetDamageType())
|
||||
util.BlastDamageInfo(dmgInfo, phys:GetPos(), 190)
|
||||
|
||||
util.ScreenShake(phys:GetPos(), 3500, 1111, 1, 300)
|
||||
|
||||
util.Decal("Scorch", trData.HitPos - trData.HitNormal, trData.HitPos + trData.HitNormal, self)
|
||||
|
||||
for i, e in pairs(ents.FindInSphere(self:GetPos(), 32)) do
|
||||
if (e:GetClass() == "npc_strider") then
|
||||
e:Fire("Explode")
|
||||
end
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:ImpactDamage(ent)
|
||||
|
||||
end
|
||||
|
||||
function ENT:GetDamageType()
|
||||
return DMG_BLAST + DMG_AIRBOAT
|
||||
end
|
||||
56
lua/entities/mg_submunition/shared.lua
Normal file
56
lua/entities/mg_submunition/shared.lua
Normal file
@@ -0,0 +1,56 @@
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
|
||||
ENT.ExplosionRadius = 430
|
||||
ENT.ExplosionDamage = 700
|
||||
|
||||
game.AddParticles("particles/explosion_fx_ins.pcf")
|
||||
game.AddParticles("particles/ins_rockettrail.pcf")
|
||||
PrecacheParticleSystem("ins_C4_explosion")
|
||||
PrecacheParticleSystem("ins_grenade_explosion")
|
||||
PrecacheParticleSystem("ins_m203_explosion")
|
||||
PrecacheParticleSystem("ins_rpg_explosion")
|
||||
PrecacheParticleSystem("rockettrail")
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Initialize
|
||||
Desc: First function called. Use to set up your entity
|
||||
-----------------------------------------------------------]]
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/items/ar2_grenade.mdl")
|
||||
self:AddEFlags(EFL_FORCE_CHECK_TRANSMIT)
|
||||
self:SetCustomCollisionCheck(true)
|
||||
|
||||
if (SERVER) then
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:GetPhysicsObject():SetMaterial("metal")
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_PLAYER_PICKUP)
|
||||
self:GetPhysicsObject():EnableDrag(false)
|
||||
self:GetPhysicsObject():EnableGravity(false)
|
||||
self:GetPhysicsObject():Wake()
|
||||
|
||||
self.m_Propel = true
|
||||
self.m_Fuel = 300
|
||||
self.m_Stability = 0
|
||||
self.m_Water = false
|
||||
self.Target = ents.Create("info_target")
|
||||
self.Target:Spawn()
|
||||
|
||||
self.m_Tracking = true
|
||||
|
||||
self.Speed = math.random(1000, 1700)
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
self.m_SpawnPos = self:GetPos()
|
||||
self:EmitSound("^viper/shared/move_rpapa7_proj_flame_cls.wav", SNDLVL_180db, 100, 1, CHAN_WEAPON)
|
||||
end
|
||||
end
|
||||
216
lua/entities/mg_viewmodel/cl_init.lua
Normal file
216
lua/entities/mg_viewmodel/cl_init.lua
Normal file
@@ -0,0 +1,216 @@
|
||||
include("client/cl_animation.lua")
|
||||
include("client/cl_calcview.lua")
|
||||
include("client/cl_render.lua")
|
||||
include("client/cl_events.lua")
|
||||
include("shared.lua")
|
||||
require("mw_utils")
|
||||
|
||||
ENT.m_Particles = {}
|
||||
ENT.m_Shells = {}
|
||||
|
||||
function ENT:CreateRig()
|
||||
if (table.IsEmpty(MW_RIGS)) then
|
||||
return
|
||||
end
|
||||
|
||||
local k, v = next(MW_RIGS)
|
||||
|
||||
if (v == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
self.m_Rig = ClientsideModel(v.Model, self.RenderGroup)
|
||||
self.m_Rig:SetRenderMode(self.RenderMode)
|
||||
self.m_Rig:AddEffects(EF_BONEMERGE)
|
||||
self.m_Rig:AddEffects(EF_BONEMERGE_FASTCULL)
|
||||
self.m_Rig:AddEffects(EF_PARENT_ANIMATES)
|
||||
self.m_Rig:SetParent(self)
|
||||
|
||||
function self.m_Rig:CanDraw()
|
||||
if (self:GetNoDraw()) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (gmod.GetGamemode().ForcePlayerHands) then
|
||||
return false
|
||||
end
|
||||
|
||||
local rig = MW_RIGS[GetConVar("mgbase_rig"):GetString()]
|
||||
|
||||
if (rig == nil) then
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function self.m_Rig:RenderOverride(flags)
|
||||
if (!self:CanDraw()) then
|
||||
return
|
||||
end
|
||||
|
||||
self:SetModel(MW_RIGS[GetConVar("mgbase_rig"):GetString()].Model)
|
||||
self:SetSkin(GetConVar("mgbase_rig_skin"):GetInt())
|
||||
--self:DrawModel(flags)
|
||||
--gloves draw the arms as well
|
||||
end
|
||||
|
||||
mw_utils.DealWithFullUpdate(self.m_Rig)
|
||||
end
|
||||
|
||||
function ENT:CreateGloves()
|
||||
if (table.IsEmpty(MW_GLOVES)) then
|
||||
return
|
||||
end
|
||||
|
||||
local k, v = next(MW_GLOVES)
|
||||
|
||||
if (v == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
self.m_Gloves = ClientsideModel(v.Model, self.RenderGroup)
|
||||
self.m_Gloves:SetRenderMode(self.RenderMode)
|
||||
self.m_Gloves:AddEffects(EF_BONEMERGE)
|
||||
self.m_Gloves:AddEffects(EF_BONEMERGE_FASTCULL)
|
||||
self.m_Gloves:AddEffects(EF_PARENT_ANIMATES)
|
||||
self.m_Gloves:SetParent(self.m_Rig)
|
||||
|
||||
function self.m_Gloves:CanDraw()
|
||||
if (self:GetNoDraw()) then
|
||||
return false
|
||||
end
|
||||
|
||||
if (gmod.GetGamemode().ForcePlayerHands) then
|
||||
return false
|
||||
end
|
||||
|
||||
local rig = MW_RIGS[GetConVar("mgbase_rig"):GetString()]
|
||||
local gloves = MW_GLOVES[GetConVar("mgbase_gloves"):GetString()]
|
||||
|
||||
if (gloves == nil || rig == nil) then
|
||||
--checks rig as well since it draws it
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function self.m_Gloves:RenderOverride(flags)
|
||||
if (!self:CanDraw()) then
|
||||
return
|
||||
end
|
||||
|
||||
self:SetModel(MW_GLOVES[GetConVar("mgbase_gloves"):GetString()].Model)
|
||||
self:SetSkin(GetConVar("mgbase_gloves_skin"):GetInt())
|
||||
self:DrawModel(flags)
|
||||
end
|
||||
|
||||
mw_utils.DealWithFullUpdate(self.m_Gloves)
|
||||
end
|
||||
|
||||
function ENT:CreateCHands()
|
||||
self.m_CHands = ClientsideModel(Model("models/weapons/c_arms_hev.mdl"), self.RenderGroup)
|
||||
self.m_CHands:SetRenderMode(self.RenderMode)
|
||||
self.m_CHands:AddEffects(EF_BONEMERGE)
|
||||
self.m_CHands:AddEffects(EF_BONEMERGE_FASTCULL)
|
||||
self.m_CHands:AddEffects(EF_PARENT_ANIMATES)
|
||||
self.m_CHands:SetParent(self)
|
||||
|
||||
function self.m_CHands:CanDraw()
|
||||
if (self:GetNoDraw()) then
|
||||
return false
|
||||
end
|
||||
|
||||
local rig = GetConVar("mgbase_rig"):GetString()
|
||||
|
||||
if (rig != "chands" && !gmod.GetGamemode().ForcePlayerHands) then
|
||||
return false
|
||||
end
|
||||
|
||||
return IsValid(LocalPlayer():GetHands())
|
||||
end
|
||||
|
||||
function self.m_CHands:GetPlayerColor()
|
||||
return LocalPlayer():GetPlayerColor()
|
||||
end
|
||||
|
||||
function self.m_CHands:RenderOverride(flags)
|
||||
if (!self:CanDraw()) then
|
||||
return
|
||||
end
|
||||
|
||||
local p = LocalPlayer()
|
||||
|
||||
if (VManip != nil) then
|
||||
p:GetHands():SetParent(self:GetParent())
|
||||
p:GetHands():DrawModel(flags) --for thermals
|
||||
--its a useless call outside of thermals but i dont care
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
self:SetModel(p:GetHands():GetModel())
|
||||
self:SetSkin(p:GetHands():GetSkin())
|
||||
|
||||
for b = 0, p:GetHands():GetNumBodyGroups() do
|
||||
self:SetBodygroup(b, p:GetHands():GetBodygroup(b))
|
||||
end
|
||||
|
||||
self:DrawModel(flags)
|
||||
end
|
||||
|
||||
mw_utils.DealWithFullUpdate(self.m_CHands)
|
||||
end
|
||||
|
||||
ENT.m_LastAnim = -1
|
||||
|
||||
function ENT:PlaySequence(anim, rate, cycle)
|
||||
rate = rate || 1
|
||||
cycle = cycle || 0
|
||||
|
||||
if (self.m_LastAnim != anim) then
|
||||
self.m_RightHandGripTarget = 1
|
||||
self.m_LeftHandGripTarget = 1
|
||||
end
|
||||
|
||||
self.m_LastAnim = anim
|
||||
self:ResetSequence(anim)
|
||||
self:SetPlaybackRate(rate)
|
||||
self:SetCycle(cycle)
|
||||
end
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
net.Receive("mgbase_viewmodelanim", function(len)
|
||||
local ent = net.ReadEntity()
|
||||
local rate = net.ReadFloat()
|
||||
local animId = net.ReadUInt(16)
|
||||
local tick = net.ReadUInt(16)
|
||||
|
||||
if (!IsValid(ent)) then
|
||||
return
|
||||
end
|
||||
|
||||
ent.m_AnimFromServer = {
|
||||
Rate = rate,
|
||||
Tick = tick,
|
||||
AnimID = animId,
|
||||
TimeDifference = ent:GetOwner():IsCarriedByLocalPlayer() && LocalPlayer():Ping() / 1000 || 0
|
||||
}
|
||||
end)
|
||||
|
||||
hook.Add("VManipPrePlayAnim", "MW19_VManipStopActions", function()
|
||||
local ply = LocalPlayer()
|
||||
local w = ply:GetActiveWeapon()
|
||||
|
||||
if (IsValid(w) && weapons.IsBasedOn(w:GetClass(), "mg_base")) then
|
||||
return !w:HasFlag("Reloading")
|
||||
&& !w:HasFlag("Drawing")
|
||||
&& w:HasFlag("Rechambered")
|
||||
&& CurTime() >= w:GetNextMeleeTime()
|
||||
&& CurTime() >= w:GetNextAimModeTime()
|
||||
&& !w:HasFlag("Holstering")
|
||||
&& w:GetViewModel().m_LastSequenceIndex != "Inspect" && w:GetViewModel().m_LastSequenceIndex != "Inspect_Empty"
|
||||
end
|
||||
end)
|
||||
275
lua/entities/mg_viewmodel/client/cl_animation.lua
Normal file
275
lua/entities/mg_viewmodel/client/cl_animation.lua
Normal file
@@ -0,0 +1,275 @@
|
||||
require("mw_math")
|
||||
|
||||
ENT.m_AimDeltaLerp = 0
|
||||
ENT.m_LocomotionDeltaLerp = 0
|
||||
ENT.m_CustomizationRateLerp = 0
|
||||
ENT.m_bMoveStopped = true
|
||||
ENT.m_bMoveStarted = false
|
||||
ENT.m_bOnGround = true
|
||||
ENT.m_LeftHandGripPoseParameter = nil
|
||||
ENT.m_LeftHandGripTarget = 0
|
||||
ENT.m_LeftHandGripLerp = 0
|
||||
ENT.m_RightHandGripPoseParameter = nil
|
||||
ENT.m_RightHandGripTarget = 0
|
||||
ENT.m_RightHandGripLerp = 0
|
||||
ENT.m_LastSprayRounds = 0
|
||||
|
||||
local idleIndices = {
|
||||
["Idle"] = true,
|
||||
["Jump"] = true,
|
||||
["Jog_Out"] = true,
|
||||
["Land"] = true
|
||||
}
|
||||
local uncancellableIndices = {
|
||||
["Sprint_In"] = true,
|
||||
["Holster"] = true
|
||||
}
|
||||
local allowAim = {
|
||||
["Ads_In"] = true,
|
||||
["Fire_Last"] = true,
|
||||
["Fire"] = true
|
||||
}
|
||||
|
||||
local function playIdleAnimation(vm, seqIndex)
|
||||
local ind = vm.m_LastSequenceIndex
|
||||
|
||||
if ((idleIndices[ind] || (!uncancellableIndices[ind] && vm:GetCycle() >= 0.98)) && (allowAim[ind] != nil || vm:GetOwner():GetAimDelta() <= 0)) then
|
||||
vm:PlayAnimation(seqIndex, true)
|
||||
end
|
||||
end
|
||||
|
||||
local function locomotion(vm)
|
||||
local w = vm:GetOwner()
|
||||
local p = w:GetOwner()
|
||||
|
||||
if (!IsValid(p) || !p:IsPlayer()) then
|
||||
return
|
||||
end
|
||||
|
||||
local vel = p:GetVelocity()
|
||||
vel = Vector(vel.x, vel.y, 0)
|
||||
|
||||
local len = math.max(vel:Length(), 0.01)
|
||||
|
||||
if (!p:IsOnGround() || (p.GetSliding != nil && p:GetSliding())) then
|
||||
vm.m_LocomotionDeltaLerp = mw_math.SafeLerp(6 * RealFrameTime(), vm.m_LocomotionDeltaLerp, 0)
|
||||
else
|
||||
vm.m_LocomotionDeltaLerp = mw_math.SafeLerp(4 * RealFrameTime(), vm.m_LocomotionDeltaLerp, len / p:GetWalkSpeed())
|
||||
end
|
||||
|
||||
--jogging and walking
|
||||
local slowWalkPoint = p:GetSlowWalkSpeed() / p:GetWalkSpeed()
|
||||
local slowWalkDelta = 1 - math.abs(slowWalkPoint - vm.m_LocomotionDeltaLerp) / slowWalkPoint
|
||||
local jogDelta = vm.m_LocomotionDeltaLerp - slowWalkDelta
|
||||
|
||||
--when we stop jogging
|
||||
if (jogDelta <= 0.5 && !vm.m_bMoveStopped) then
|
||||
if (p:IsOnGround()) then
|
||||
playIdleAnimation(vm, "Jog_Out")
|
||||
end
|
||||
|
||||
vm.m_bMoveStopped = true
|
||||
elseif (jogDelta > 0.5) then
|
||||
vm.m_bMoveStopped = false
|
||||
end
|
||||
|
||||
--when we start moving
|
||||
if (vm.m_LocomotionDeltaLerp > 0.1 && !vm.m_bMoveStarted) then
|
||||
if (p:IsOnGround()) then
|
||||
playIdleAnimation(vm, "Land")
|
||||
end
|
||||
|
||||
vm.m_bMoveStarted = true
|
||||
elseif (vm.m_LocomotionDeltaLerp <= 0.1) then
|
||||
vm.m_bMoveStarted = false
|
||||
end
|
||||
|
||||
vm:SetPoseParameter("jog_loop", jogDelta * Lerp(vm.m_AimDeltaLerp, 1, 0.1 * (w.Zoom.MovementMultiplier || 1)))
|
||||
vm:SetPoseParameter("walk_loop", slowWalkDelta * Lerp(vm.m_AimDeltaLerp, 1, 0.2 * (w.Zoom.PoseParameterMultiplier || 1)))
|
||||
|
||||
--freefall loop
|
||||
local z = math.min(p:GetVelocity().z, 0)
|
||||
local delta = math.min(math.min(z + 500, 0) / -1100, 1)
|
||||
vm:SetPoseParameter("freefall_loop", delta * Lerp(vm.m_AimDeltaLerp, 1, 0.1))
|
||||
|
||||
--jumping and landing
|
||||
if (vm.m_bOnGround != p:IsOnGround()) then
|
||||
if (!p:IsOnGround()) then
|
||||
playIdleAnimation(vm, "Jump")
|
||||
else
|
||||
playIdleAnimation(vm, "Land")
|
||||
end
|
||||
|
||||
vm.m_bOnGround = p:IsOnGround()
|
||||
end
|
||||
|
||||
--sprint
|
||||
local sprintPoint = p:GetRunSpeed() / p:GetWalkSpeed()
|
||||
local sprintDelta = (vm.m_LocomotionDeltaLerp - 1) / (sprintPoint - 1)
|
||||
vm:SetPoseParameter("sprint_loop", math.min(sprintDelta, math.Clamp((CurTime() - w:GetNextReloadTime()) * 10, 0, 1)) * Lerp(vm.m_AimDeltaLerp, 1, 0.1))
|
||||
-- not so efficient but very effective sprinting reload bodge
|
||||
|
||||
--the offset when moving in general
|
||||
local offsetDelta = mw_math.CosineInterp(vm.m_LocomotionDeltaLerp * math.Clamp(1 - sprintDelta, 0, 1), 0, 1)
|
||||
offsetDelta = offsetDelta * (1 - math.Clamp(vm.m_AimDeltaLerp * 2, 0, 1))
|
||||
vm:SetPoseParameter("jog_offset", offsetDelta)
|
||||
|
||||
--after fire reshoulder
|
||||
if (vm.m_LastSprayRounds != w:GetSprayRounds() && !w:HasFlag("BipodDeployed")) then
|
||||
if (w:GetSprayRounds() == 0 && vm.m_LastSprayRounds >= 5) then
|
||||
if (!string.find(string.lower(vm.m_LastSequenceIndex), "fire")) then
|
||||
local anim = math.random(1, 2) == 1 && "Land" || "Jog_Out"
|
||||
|
||||
if (w.Animations.SprayEnd != nil) then
|
||||
anim = "SprayEnd"
|
||||
end
|
||||
|
||||
playIdleAnimation(vm, anim)
|
||||
vm.m_LastSprayRounds = w:GetSprayRounds()
|
||||
end
|
||||
else
|
||||
vm.m_LastSprayRounds = w:GetSprayRounds()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ENT.m_InspectSpeed = 1
|
||||
|
||||
local function inspection(vm)
|
||||
local w = vm:GetOwner()
|
||||
|
||||
local randomness = math.sin(CurTime() * 2) * 0.05 + math.sin(CurTime() * 3) * 0.05
|
||||
local inspectDelta = w.FreezeInspectDelta || 0.15
|
||||
|
||||
if (w:Clip1() <= 0 && w.EmptyFreezeInspectDelta) then
|
||||
inspectDelta = w.EmptyFreezeInspectDelta
|
||||
end
|
||||
|
||||
local bStop = w:HasFlag("StoppedInspectAnimation") || (w:HasFlag("Customizing") && vm:GetCycle() > inspectDelta)
|
||||
vm.m_InspectSpeed = mw_math.SafeLerp(5 * RealFrameTime(), vm.m_InspectSpeed, Lerp(mw_math.btn(bStop), 1, randomness))
|
||||
|
||||
if (string.find(string.lower(vm.m_LastSequenceIndex), "inspect")) then
|
||||
vm:SetPlaybackRate(vm.m_InspectSpeed)
|
||||
end
|
||||
end
|
||||
|
||||
local function grips(vm)
|
||||
local w = vm:GetOwner()
|
||||
|
||||
if (w.GripPoseParameters != nil) then
|
||||
for i, pp in pairs(w.GripPoseParameters) do
|
||||
vm:SetPoseParameter(pp, 0)
|
||||
end
|
||||
|
||||
vm.m_LeftHandGripLerp = math.Approach(vm.m_LeftHandGripLerp, vm.m_LeftHandGripTarget, 10 * RealFrameTime())
|
||||
|
||||
if (vm.m_LeftHandGripPoseParameter != nil) then
|
||||
vm:SetPoseParameter(vm.m_LeftHandGripPoseParameter, vm.m_LeftHandGripLerp)
|
||||
end
|
||||
end
|
||||
|
||||
if (w.GripPoseParameters2 != nil) then
|
||||
for i, pp in pairs(w.GripPoseParameters2) do
|
||||
vm:SetPoseParameter(pp, 0)
|
||||
end
|
||||
|
||||
vm.m_RightHandGripLerp = math.Approach(vm.m_RightHandGripLerp, vm.m_RightHandGripTarget, 10 * RealFrameTime())
|
||||
|
||||
if (vm.m_RightHandGripPoseParameter != nil) then
|
||||
vm:SetPoseParameter(vm.m_RightHandGripPoseParameter, vm.m_RightHandGripLerp)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:SetPoseParameters()
|
||||
local w = self:GetOwner()
|
||||
|
||||
self:SetPoseParameter("aim_offset", self.m_AimDeltaLerp)
|
||||
self:SetPoseParameter("hybrid_offset", w:GetAimMode())
|
||||
self:SetPoseParameter("firemode_offset", w:GetFiremode() - 1)
|
||||
self:SetPoseParameter("empty_offset", mw_math.btn(w:Clip1() <= 0 || !w:HasFlag("Rechambered")))
|
||||
self:SetPoseParameter("bipod", mw_math.btn(w:HasFlag("BipodDeployed")))
|
||||
end
|
||||
|
||||
ENT.m_UpdateDelta = 0
|
||||
|
||||
function ENT:Think()
|
||||
local w = self:GetOwner()
|
||||
|
||||
if (!IsValid(w)) then
|
||||
return
|
||||
end
|
||||
|
||||
self:ReconcileServerAnims()
|
||||
|
||||
if (!w:IsCarriedByLocalPlayer() || !IsValid(w:GetOwner()) || w != w:GetOwner():GetActiveWeapon()) then
|
||||
return
|
||||
end
|
||||
|
||||
if (self.m_UpdateDelta <= 0.2) then
|
||||
self:UpdateAnimation(self.m_LastSequenceIndex)
|
||||
self.m_UpdateDelta = self.m_UpdateDelta + FrameTime()
|
||||
--WAKE UP GODDAMN IT
|
||||
end
|
||||
|
||||
if (self.m_LastSequenceIndex != "INIT") then
|
||||
self.m_AimDeltaLerp = mw_math.SafeLerp(30 * RealFrameTime(), self.m_AimDeltaLerp, w:GetAimDelta())
|
||||
|
||||
self:SetPoseParameters()
|
||||
|
||||
--we play idle a bit earlier if ads in
|
||||
local targetCycle = self.m_LastSequenceIndex == "Ads_In" && 0.5 || 0.98
|
||||
|
||||
if (self:GetCycle() >= targetCycle) then
|
||||
playIdleAnimation(self, "Idle")
|
||||
end
|
||||
|
||||
--states
|
||||
locomotion(self)
|
||||
inspection(self)
|
||||
grips(self)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:ReconcileServerAnims()
|
||||
if (self.m_AnimFromServer == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
local tick = self.m_AnimFromServer.Tick
|
||||
local animId = self.m_AnimFromServer.AnimID
|
||||
local rate = self.m_AnimFromServer.Rate
|
||||
local timeDifference = self.m_AnimFromServer.TimeDifference
|
||||
self.m_AnimFromServer = nil
|
||||
|
||||
local seqIndex = self:GetSequenceIndexByID(animId)
|
||||
|
||||
if (tick < self.m_Tick || (tick == self.m_Tick && self.m_LastSequenceIndex == seqIndex)) then
|
||||
return
|
||||
end
|
||||
|
||||
local sequences = self:GetOwner().Animations[seqIndex].Sequences
|
||||
|
||||
local seqId = self:LookupSequence(sequences[1])
|
||||
local length = self:SequenceDuration(seqId)
|
||||
|
||||
local cycle = timeDifference / length
|
||||
cycle = cycle * rate
|
||||
|
||||
self:PlaySequence(sequences[math.random(1, #sequences)], rate, cycle)
|
||||
|
||||
self.m_LastSequenceIndex = seqIndex
|
||||
self.m_Tick = tick
|
||||
end
|
||||
|
||||
function ENT:VManipPostPlayAnim(name)
|
||||
playIdleAnimation(self, "Jog_Out")
|
||||
end
|
||||
|
||||
function ENT:VManipHoldQuit()
|
||||
playIdleAnimation(self, "Land")
|
||||
end
|
||||
|
||||
function ENT:VManipRemove()
|
||||
playIdleAnimation(self, "Jog_Out")
|
||||
end
|
||||
461
lua/entities/mg_viewmodel/client/cl_calcview.lua
Normal file
461
lua/entities/mg_viewmodel/client/cl_calcview.lua
Normal file
@@ -0,0 +1,461 @@
|
||||
require("mw_math")
|
||||
require("mw_utils")
|
||||
|
||||
ENT.m_AimDelta = 0
|
||||
ENT.m_AimModeDelta = 0
|
||||
ENT.m_CameraAttachment = nil
|
||||
function ENT:CalcView(origin, angles)
|
||||
if (self:GetRenderOrigin() == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
--local camera = self:GetAttachment(mw_utils.LookupAttachmentCached(self, "camera"))
|
||||
|
||||
if (self.m_CameraAttachment == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
local camera = self.m_CameraAttachment
|
||||
local cameraPos, cameraAng = camera:GetTranslation(), camera:GetAngles()
|
||||
|
||||
angles:RotateAroundAxis(angles:Forward(), cameraAng.r)
|
||||
angles:RotateAroundAxis(angles:Up(), -cameraAng.y)
|
||||
angles:RotateAroundAxis(angles:Right(), cameraAng.p)
|
||||
|
||||
mw_math.VectorAddAndMul(origin, angles:Forward(), -cameraPos.x)
|
||||
mw_math.VectorAddAndMul(origin, angles:Up(), -cameraPos.z)
|
||||
mw_math.VectorAddAndMul(origin, angles:Right(), cameraPos.y)
|
||||
end
|
||||
|
||||
ENT.m_Movement = {
|
||||
p = mw_math.CreateSpring(150, 0.75),
|
||||
x = mw_math.CreateSpring(80, 1),
|
||||
y = mw_math.CreateSpring(100, 1)
|
||||
}
|
||||
|
||||
ENT.m_LastZVel = 0
|
||||
ENT.m_LandTarget = 0
|
||||
|
||||
local function movementInertia(vm, pos, ang)
|
||||
local w = vm:GetWeaponOwner()
|
||||
local p = vm:GetPlayerOwner()
|
||||
|
||||
if (!IsValid(vm:GetPlayerOwner())) then
|
||||
return
|
||||
end
|
||||
|
||||
local vel = p:GetVelocity()
|
||||
|
||||
--vertical
|
||||
if (!p:IsOnGround()) then
|
||||
vm.m_LastZVel = vel.z
|
||||
vm.m_LandTarget = 0
|
||||
else
|
||||
if (vm.m_LastZVel != 0) then
|
||||
vm.m_LandTarget = -math.Clamp(vm.m_LastZVel, -1000, 1000) * 0.02
|
||||
vm.m_LastZVel = 0
|
||||
end
|
||||
|
||||
vm.m_LandTarget = mw_math.SafeLerp(5 * FrameTime(), vm.m_LandTarget, 0)
|
||||
end
|
||||
|
||||
vm.m_Movement.p:SetTarget(math.Clamp(math.Clamp(vel.z, -200, 200) * 0.025, -10, 10) + vm.m_LandTarget)
|
||||
vm.m_Movement.p:Decay()
|
||||
|
||||
local pi = vm.m_Movement.p:GetValue() * mw_math.SafeLerp(vm.m_AimDelta, 1, 0.1)
|
||||
|
||||
ang:SetUnpacked(ang.p - pi, ang.y, ang.r)
|
||||
|
||||
--horizontal
|
||||
vel:Div(p:GetWalkSpeed())
|
||||
|
||||
local dotY = 0
|
||||
local dotX = 0
|
||||
|
||||
if (!w:HasFlag("Sprinting")) then
|
||||
local movementAngles = Angle(0, p:EyeAngles().y, 0)
|
||||
dotY = movementAngles:Forward():Dot(vel)
|
||||
dotY = dotY * -1
|
||||
dotY = math.Clamp(dotY, -2, 2)
|
||||
|
||||
dotX = movementAngles:Right():Dot(vel)
|
||||
dotX = dotX * -1
|
||||
dotX = math.Clamp(dotX, -1.25, 1.25)
|
||||
end
|
||||
|
||||
vm.m_Movement.y:SetTarget(dotY)
|
||||
vm.m_Movement.y:Decay()
|
||||
|
||||
vm.m_Movement.x:SetTarget(dotX)
|
||||
vm.m_Movement.x:Decay()
|
||||
|
||||
local y = vm.m_Movement.y:GetValue() * mw_math.SafeLerp(vm.m_AimDelta, 1, 0.3)
|
||||
local x = vm.m_Movement.x:GetValue() * mw_math.SafeLerp(vm.m_AimDelta, 1, 0.075)
|
||||
|
||||
pos:SetUnpacked(pos.x + x, pos.y + y, pos.z)
|
||||
end
|
||||
|
||||
ENT.m_SwayAngle = nil
|
||||
ENT.m_Sway = {
|
||||
p = mw_math.CreateSpring(150, 0.75),
|
||||
ya = mw_math.CreateSpring(120, 1),
|
||||
r = mw_math.CreateSpring(60, 0.85),
|
||||
x = mw_math.CreateSpring(145, 1),
|
||||
y = mw_math.CreateSpring(100, 1),
|
||||
z = mw_math.CreateSpring(150, 0.75)
|
||||
}
|
||||
|
||||
local function sway(vm, pos, ang, originalAng)
|
||||
if (vm.m_SwayAngle == nil) then
|
||||
vm.m_SwayAngle = Angle(originalAng)
|
||||
end
|
||||
|
||||
local diffY = math.AngleDifference(vm.m_SwayAngle.y, originalAng.y)
|
||||
diffY = diffY / RealFrameTime()
|
||||
diffY = diffY * 0.015
|
||||
|
||||
local diffP = math.AngleDifference(vm.m_SwayAngle.p, originalAng.p)
|
||||
diffP = diffP / RealFrameTime()
|
||||
diffP = diffP * 0.01
|
||||
|
||||
vm.m_Sway.p:SetTarget(diffP + diffY * mw_math.SafeLerp(vm.m_AimDelta, 0.1, 0))
|
||||
vm.m_Sway.ya:SetTarget(diffY)
|
||||
vm.m_Sway.r:SetTarget(diffY * 0.75)
|
||||
|
||||
vm.m_Sway.z:SetTarget(diffP * 0.125 + diffY * mw_math.SafeLerp(vm.m_AimDelta, 0.01, 0))
|
||||
vm.m_Sway.x:SetTarget(diffY * 0.15)
|
||||
vm.m_Sway.y:SetTarget(diffY * 0.1)
|
||||
|
||||
vm.m_Sway.p:Decay()
|
||||
vm.m_Sway.ya:Decay()
|
||||
vm.m_Sway.r:Decay()
|
||||
vm.m_Sway.x:Decay()
|
||||
vm.m_Sway.y:Decay()
|
||||
vm.m_Sway.z:Decay()
|
||||
|
||||
vm.m_SwayAngle:Set(originalAng)
|
||||
|
||||
--
|
||||
|
||||
local p = vm.m_Sway.p:GetValue() * mw_math.SafeLerp(vm.m_AimDelta, 1, -0.1)
|
||||
local y = vm.m_Sway.ya:GetValue() * mw_math.SafeLerp(vm.m_AimDelta, 1, -0.1)
|
||||
local r = vm.m_Sway.r:GetValue() * mw_math.SafeLerp(vm.m_AimDelta, 1, -0.1)
|
||||
|
||||
ang:SetUnpacked(ang.p - p, ang.y + y, ang.r - r)
|
||||
|
||||
local x = vm.m_Sway.x:GetValue() * mw_math.SafeLerp(vm.m_AimDelta, 1, -0.1)
|
||||
x = x - mw_math.SafeLerp(vm.m_AimDelta, r * 0.05, 0)
|
||||
|
||||
local y = vm.m_Sway.y:GetValue() * mw_math.SafeLerp(vm.m_AimDelta, 1, -0.1)
|
||||
local z = vm.m_Sway.z:GetValue() * mw_math.SafeLerp(vm.m_AimDelta, 1, -0.1)
|
||||
z = z - mw_math.SafeLerp(vm.m_AimDelta, r * 0.035, 0)
|
||||
|
||||
pos:SetUnpacked(pos.x + x, pos.y + y, pos.z + z)
|
||||
end
|
||||
|
||||
local defaultSprintAngle = Angle(0, 0, 25)
|
||||
local defaultSprintPos = Vector(1, 0, -1)
|
||||
local defaultVManipAngle = Angle(0, 2, -10)
|
||||
local defaultVManipPos = Vector(1.5, 3, -1.5)
|
||||
local defaultCrouchAngle = Angle(0, 0, -5)
|
||||
local defaultCrouchPos = Vector(-1, -0.5, -1)
|
||||
local defaultBipodAngle = Angle()
|
||||
local defaultBipodPos = Vector(-1.5, 0, -1.5)
|
||||
|
||||
ENT.m_OffsetAng = {
|
||||
p = mw_math.CreateSpring(150, 0.75),
|
||||
ya = mw_math.CreateSpring(120, 1),
|
||||
r = mw_math.CreateSpring(100, 1.5)
|
||||
}
|
||||
|
||||
ENT.m_OffsetPos = mw_math.CreateVectorSpring(150, 1.5)
|
||||
|
||||
local offsetsPos = Vector()
|
||||
local offsetsAng = Angle()
|
||||
local sprintAng = Angle()
|
||||
local sprintPos = Vector()
|
||||
local alternateAimPos = Vector()
|
||||
local alternateAimAng = Angle()
|
||||
local aimPos = Vector()
|
||||
local aimAng = Angle()
|
||||
local vManipAng = Angle()
|
||||
local vManipPos = Vector()
|
||||
local bipodAng = Angle()
|
||||
local bipodPos = Vector()
|
||||
local crouchAng = Angle()
|
||||
local crouchPos = Vector()
|
||||
|
||||
local function offsets(vm, pos, ang)
|
||||
local w = vm:GetOwner()
|
||||
local p = w:GetOwner()
|
||||
|
||||
offsetsPos:SetUnpacked(0, 0, 0)
|
||||
offsetsAng:SetUnpacked(0, 0, 0)
|
||||
|
||||
--aim offsets
|
||||
aimPos:Set(w.ViewModelOffsets.Aim.Pos)
|
||||
aimAng:Set(w.ViewModelOffsets.Aim.Angles)
|
||||
|
||||
if (w:GetSight() != nil) then
|
||||
aimPos:Add(w:GetSight().AimPos || mw_math.ZeroVector)
|
||||
aimAng:Add(w:GetSight().AimAng || mw_math.ZeroAngle)
|
||||
end
|
||||
|
||||
aimPos:Mul(mw_math.btn(w:HasFlag("Aiming") && w:GetAimMode() == 0))
|
||||
aimAng:Mul(mw_math.btn(w:HasFlag("Aiming") && w:GetAimMode() == 0))
|
||||
|
||||
offsetsPos:Add(aimPos)
|
||||
offsetsAng:Add(aimAng)
|
||||
|
||||
--canted aim offsets
|
||||
alternateAimPos:Set(w.ViewModelOffsets.Aim.Pos)
|
||||
alternateAimAng:Set(w.ViewModelOffsets.Aim.Angles)
|
||||
|
||||
if (w:GetSight() != nil && w:GetSight().ReticleHybrid != nil) then
|
||||
alternateAimPos:Add(w:GetSight().HybridAimPos || w.HybridAimPos || mw_math.ZeroVector)
|
||||
alternateAimAng:Add(w:GetSight().HybridAimAng || w.HybridAimAngles || mw_math.ZeroAngle)
|
||||
else
|
||||
if (w.LaserAimPos != nil && w.LaserAimAngles != nil && w:GetLaser() != nil) then
|
||||
alternateAimPos:Set(w.LaserAimPos)
|
||||
alternateAimAng:Set(w.LaserAimAngles)
|
||||
|
||||
local reloadDelta = Lerp(mw_math.btn(CurTime() >= Lerp(0.5, w:GetNextMagTime(), w:GetNextReloadTime())), 0.5, 1)
|
||||
alternateAimAng:Mul(reloadDelta)
|
||||
alternateAimPos:Mul(reloadDelta)
|
||||
end
|
||||
end
|
||||
|
||||
--alternateAimPos:Mul(vm.m_AimModeDelta)
|
||||
alternateAimPos:Mul(mw_math.btn(!(w.DisableCantedReload && w:HasFlag("Reloading")) && w:HasFlag("Aiming") && w:GetAimMode() > 0))
|
||||
|
||||
--alternateAimAng:Mul(vm.m_AimModeDelta)
|
||||
alternateAimAng:Mul(mw_math.btn(!(w.DisableCantedReload && w:HasFlag("Reloading")) && w:HasFlag("Aiming") && w:GetAimMode() > 0))
|
||||
|
||||
offsetsPos:Add(alternateAimPos)
|
||||
offsetsAng:Add(alternateAimAng)
|
||||
|
||||
--sprinting
|
||||
sprintAng:Set(defaultSprintAngle)
|
||||
sprintPos:Set(defaultSprintPos)
|
||||
|
||||
if (w.ViewModelOffsets.Sprint != nil) then
|
||||
sprintAng:Set(w.ViewModelOffsets.Sprint.Angles || sprintAng)
|
||||
sprintPos:Set(w.ViewModelOffsets.Sprint.Pos || sprintPos)
|
||||
end
|
||||
|
||||
sprintPos:Mul(mw_math.btn(w:HasFlag("Sprinting")))
|
||||
sprintAng:Mul(mw_math.btn(w:HasFlag("Sprinting")))
|
||||
|
||||
offsetsAng:Add(sprintAng)
|
||||
offsetsPos:Add(sprintPos)
|
||||
|
||||
--idle
|
||||
local eyePitch = Lerp(mw_math.btn(w:HasFlag("Aiming")), p:EyeAngles().p / 90, 0)
|
||||
offsetsAng:Add(w.ViewModelOffsets.Idle.Angles * mw_math.btn(!w:HasFlag("Aiming")))
|
||||
offsetsAng.r = offsetsAng.r + (eyePitch * 5)
|
||||
|
||||
offsetsPos:Add(w.ViewModelOffsets.Idle.Pos * mw_math.btn(!w:HasFlag("Aiming")))
|
||||
offsetsPos.y = offsetsPos.y + eyePitch
|
||||
offsetsPos.z = offsetsPos.z + (math.min(eyePitch, 0.5) * 5 * mw_math.btn(w:HasFlag("BipodDeployed")))
|
||||
|
||||
--vmanip
|
||||
vManipAng:Set(defaultVManipAngle)
|
||||
vManipPos:Set(defaultVManipPos)
|
||||
|
||||
if (w.ViewModelOffsets.VManip != nil) then
|
||||
vManipAng:Set(w.ViewModelOffsets.VManip.Angles || vManipAng)
|
||||
vManipPos:Set(w.ViewModelOffsets.VManip.Pos || vManipPos)
|
||||
end
|
||||
|
||||
vManipPos:Mul(mw_math.btn(VManip != nil && !w:HasFlag("Aiming") && VManip:IsActive()))
|
||||
vManipAng:Mul(mw_math.btn(VManip != nil && !w:HasFlag("Aiming") && VManip:IsActive()))
|
||||
|
||||
offsetsAng:Add(vManipAng)
|
||||
offsetsPos:Add(vManipPos)
|
||||
|
||||
--bipod
|
||||
bipodAng:Set(defaultBipodAngle)
|
||||
bipodPos:Set(defaultBipodPos)
|
||||
|
||||
if (w.ViewModelOffsets.Bipod != nil) then
|
||||
bipodAng:Set(w.ViewModelOffsets.Bipod.Angles || bipodAng)
|
||||
bipodPos:Set(w.ViewModelOffsets.Bipod.Pos || bipodPos)
|
||||
end
|
||||
|
||||
bipodPos:Mul(mw_math.btn(w:HasFlag("BipodDeployed") && !w:HasFlag("Aiming")))
|
||||
bipodAng:Mul(mw_math.btn(w:HasFlag("BipodDeployed") && !w:HasFlag("Aiming")))
|
||||
|
||||
offsetsAng:Add(bipodAng)
|
||||
offsetsPos:Add(bipodPos)
|
||||
|
||||
--crouching
|
||||
crouchAng:Set(defaultCrouchAngle)
|
||||
crouchPos:Set(defaultCrouchPos)
|
||||
|
||||
if (w.ViewModelOffsets.Crouch != nil) then
|
||||
crouchAng:Set(w.ViewModelOffsets.Crouch.Angles || crouchAng)
|
||||
crouchPos:Set(w.ViewModelOffsets.Crouch.Pos || crouchPos)
|
||||
end
|
||||
|
||||
local crouchDelta = mw_math.btn(p:IsFlagSet(4) && !w:HasFlag("BipodDeployed") && !w:HasFlag("Aiming"))
|
||||
crouchPos:Mul(crouchDelta)
|
||||
crouchAng.p = crouchAng.p * crouchDelta
|
||||
crouchAng.y = crouchAng.y * crouchDelta
|
||||
crouchAng.r = Lerp(mw_math.btn(p:IsFlagSet(4) && !w:HasFlag("BipodDeployed")), 0, Lerp(mw_math.btn(w:HasFlag("Aiming")), crouchAng.r, crouchAng.r * 0.5))
|
||||
|
||||
offsetsAng:Add(crouchAng)
|
||||
offsetsPos:Add(crouchPos)
|
||||
|
||||
--final result
|
||||
vm.m_OffsetAng.p:SetTarget(offsetsAng.p)
|
||||
vm.m_OffsetAng.ya:SetTarget(offsetsAng.y)
|
||||
vm.m_OffsetAng.r:SetTarget(offsetsAng.r)
|
||||
|
||||
vm.m_OffsetPos:SetTarget(offsetsPos)
|
||||
mw_math.DecaySprings(vm.m_OffsetAng.p, vm.m_OffsetAng.ya, vm.m_OffsetAng.r, vm.m_OffsetPos)
|
||||
|
||||
local x, y, z = vm.m_OffsetPos:GetValue().x, vm.m_OffsetPos:GetValue().y, vm.m_OffsetPos:GetValue().z
|
||||
pos:SetUnpacked(pos.x + x, pos.y + y, pos.z + z)
|
||||
|
||||
local pi, ya, r = vm.m_OffsetAng.p:GetValue(), vm.m_OffsetAng.ya:GetValue(), vm.m_OffsetAng.r:GetValue()
|
||||
ang:SetUnpacked(ang.p - pi, ang.y + ya, ang.r + r)
|
||||
end
|
||||
|
||||
ENT.m_RecoilResetSpeed = 100
|
||||
ENT.m_RecoilAngleTarget = Angle()
|
||||
ENT.m_RecoilPosTarget = Vector()
|
||||
ENT.m_RecoilShakeLerp = 0
|
||||
ENT.m_RecoilRollLerp = 0
|
||||
ENT.m_RecoilRoll = 0
|
||||
|
||||
local recoilFuncs = {
|
||||
[true] = function(w, name) return w.Recoil.ViewModel[name] || 1 end,
|
||||
[false] = function() return 1 end
|
||||
}
|
||||
|
||||
local function getRecoilValue(w, name)
|
||||
return recoilFuncs[w.Recoil.ViewModel != nil](w, name)
|
||||
end
|
||||
|
||||
ENT.m_RecoilAng = mw_math.CreateAngleSpring(80, 1)
|
||||
ENT.m_RecoilPos = mw_math.CreateVectorSpring(40, 1)
|
||||
|
||||
function ENT:SetRecoilTargets(pos, ang)
|
||||
self.m_RecoilAngleTarget:Set(ang)
|
||||
self.m_RecoilPosTarget:Set(pos)
|
||||
self.m_RecoilResetSpeed = -1
|
||||
end
|
||||
|
||||
local lerp = Lerp
|
||||
local clamp = math.Clamp
|
||||
local safeLerp = mw_math.SafeLerp
|
||||
local realFrameTime = RealFrameTime
|
||||
local approach = mw_math.Approach
|
||||
local approachAngle = mw_math.ApproachAngle
|
||||
local function recoil(vm, pos, ang)
|
||||
local w = vm:GetOwner()
|
||||
|
||||
vm.m_RecoilShakeLerp = safeLerp(10 * realFrameTime(), vm.m_RecoilShakeLerp, w.Camera.Shake)
|
||||
vm.m_RecoilRoll = safeLerp(10 * realFrameTime(), vm.m_RecoilRoll, 0)
|
||||
vm.m_RecoilRollLerp = safeLerp(10 * realFrameTime(), vm.m_RecoilRollLerp, vm.m_RecoilRoll)
|
||||
|
||||
vm.m_RecoilAng.sc = lerp(vm.m_AimDelta, 80, 240) * getRecoilValue(w, "SnapMultiplier")
|
||||
vm.m_RecoilAng.wc = lerp(vm.m_AimDelta, 1.25, 0.85) / getRecoilValue(w, "LoosenessMultiplier")
|
||||
vm.m_RecoilPos.sc = lerp(vm.m_AimDelta, 80, 120) * getRecoilValue(w, "SnapMultiplier")
|
||||
vm.m_RecoilPos.wc = lerp(vm.m_AimDelta, 1, 1.2) / getRecoilValue(w, "LoosenessMultiplier")
|
||||
|
||||
vm.m_RecoilResetSpeed = safeLerp(10 * realFrameTime(), vm.m_RecoilResetSpeed, 1)
|
||||
local resetSpeed = clamp(vm.m_RecoilResetSpeed, 0, 1) * 100
|
||||
|
||||
vm.m_RecoilAngleTarget.pitch = approachAngle(vm.m_RecoilAngleTarget.pitch, 0, resetSpeed * realFrameTime())
|
||||
vm.m_RecoilAngleTarget.yaw = approachAngle(vm.m_RecoilAngleTarget.yaw, 0, resetSpeed * realFrameTime())
|
||||
vm.m_RecoilAngleTarget.roll = approachAngle(vm.m_RecoilAngleTarget.roll, 0, resetSpeed * realFrameTime())
|
||||
|
||||
vm.m_RecoilAng:SetTarget(vm.m_RecoilAngleTarget * 10)
|
||||
vm.m_RecoilAng:Decay()
|
||||
|
||||
vm.m_RecoilPosTarget.x = approach(vm.m_RecoilPosTarget.x, 0, resetSpeed * realFrameTime())
|
||||
vm.m_RecoilPosTarget.y = approach(vm.m_RecoilPosTarget.y, 0, resetSpeed * realFrameTime())
|
||||
vm.m_RecoilPosTarget.z = approach(vm.m_RecoilPosTarget.z, 0, resetSpeed * realFrameTime())
|
||||
|
||||
vm.m_RecoilPos:SetTarget(vm.m_RecoilPosTarget)
|
||||
vm.m_RecoilPos:Decay()
|
||||
|
||||
local p = vm.m_RecoilAng:GetValue().p * lerp(vm.m_AimDelta, 1, 0.065)
|
||||
local ya = vm.m_RecoilAng:GetValue().y * lerp(vm.m_AimDelta, 1, 0.08)
|
||||
local r = vm.m_RecoilAng:GetValue().r * lerp(vm.m_AimDelta, 1, 0.1)
|
||||
|
||||
ang.p = ang.p - p
|
||||
ang.y = ang.y - ya
|
||||
ang.r = ang.r + r + lerp(vm.m_AimDelta, 0, vm.m_RecoilRollLerp)
|
||||
|
||||
local x = vm.m_RecoilPos:GetValue().x * lerp(vm.m_AimDelta, 1, 0.35)
|
||||
local y = vm.m_RecoilPos:GetValue().y * lerp(vm.m_AimDelta, 1, 0.35)
|
||||
local z = vm.m_RecoilPos:GetValue().z * lerp(vm.m_AimDelta, 1, 0.35)
|
||||
|
||||
pos.x = pos.x - x
|
||||
pos.y = pos.y - y - lerp(vm.m_AimDelta, 0, vm.m_RecoilShakeLerp * 1.5)
|
||||
pos.z = pos.z + z
|
||||
end
|
||||
|
||||
function ENT:CalcViewModelView(pos, ang)
|
||||
if (game.SinglePlayer() && gui.IsGameUIVisible()) then
|
||||
return
|
||||
end
|
||||
|
||||
local w = self:GetOwner()
|
||||
local lpos, lang = hook.Run("CalcViewModelView", w, self, pos, ang, Vector(pos), Angle(ang))
|
||||
|
||||
pos:Set(lpos)
|
||||
ang:Set(lang)
|
||||
|
||||
local cPos, cAng = Vector(), Angle()
|
||||
|
||||
self.m_AimDelta = mw_math.SafeLerp(18 * RealFrameTime(), self.m_AimDelta, w:GetAimDelta())
|
||||
self.m_AimModeDelta = mw_math.SafeLerp(18 * RealFrameTime(), self.m_AimModeDelta, w:GetAimModeDelta())
|
||||
|
||||
movementInertia(self, cPos, cAng)
|
||||
sway(self, cPos, cAng, ang)
|
||||
recoil(self, cPos, cAng)
|
||||
|
||||
cPos:Mul(mw_math.btn(1 / RealFrameTime() >= 14))
|
||||
cAng:Mul(mw_math.btn(1 / RealFrameTime() >= 14))
|
||||
|
||||
ang:RotateAroundAxis(ang:Forward(), cAng.r)
|
||||
ang:RotateAroundAxis(ang:Right(), cAng.p)
|
||||
ang:RotateAroundAxis(ang:Up(), cAng.y)
|
||||
|
||||
pos:Add(ang:Forward() * cPos.y)
|
||||
pos:Add(ang:Right() * cPos.x)
|
||||
pos:Add(ang:Up() * cPos.z)
|
||||
|
||||
--we calculate offsets at the end so movements are aligned to original axis
|
||||
--regardless of offset
|
||||
cPos:SetUnpacked(0, 0, 0)
|
||||
cAng:SetUnpacked(0, 0, 0)
|
||||
offsets(self, cPos, cAng)
|
||||
|
||||
ang:RotateAroundAxis(ang:Forward(), cAng.r)
|
||||
ang:RotateAroundAxis(ang:Right(), cAng.p)
|
||||
ang:RotateAroundAxis(ang:Up(), cAng.y)
|
||||
|
||||
pos:Add(ang:Forward() * cPos.y)
|
||||
pos:Add(ang:Right() * cPos.x)
|
||||
pos:Add(ang:Up() * cPos.z)
|
||||
|
||||
local originalFov = weapons.GetStored("mg_base").ViewModelFOV
|
||||
local hipFovMul = GetConVar("mgbase_fx_vmfov"):GetFloat()
|
||||
local adsFovMul = GetConVar("mgbase_fx_vmfov_ads"):GetFloat()
|
||||
|
||||
if (w:GetSight() != nil && w:GetSight().Optic != nil) then
|
||||
adsFovMul = math.max(adsFovMul, Lerp(self.m_AimModeDelta, 1, adsFovMul))
|
||||
end
|
||||
|
||||
w.ViewModelFOV = mw_math.SafeLerp(self.m_AimDelta, originalFov, originalFov * Lerp(self.m_AimModeDelta, w.Zoom.ViewModelFovMultiplier, 0.9))
|
||||
w.ViewModelFOV = w.ViewModelFOV * Lerp(self.m_AimDelta, hipFovMul, adsFovMul)
|
||||
|
||||
if (GetViewEntity():IsPlayer()) then
|
||||
local curFov = GetViewEntity():GetFOV()
|
||||
w.ViewModelFOV = w.ViewModelFOV / Lerp(self.m_AimDelta, 1, (90 / curFov))
|
||||
end
|
||||
end
|
||||
298
lua/entities/mg_viewmodel/client/cl_events.lua
Normal file
298
lua/entities/mg_viewmodel/client/cl_events.lua
Normal file
@@ -0,0 +1,298 @@
|
||||
require("mw_utils")
|
||||
|
||||
--Events we can use:
|
||||
-- CL_EVENT_SOUND [sound, vector for spatial] (5004) -> sound (eg: "event 5004 mw19.sound 0,10,10")
|
||||
-- CL_EJECT_BRASS1 [attachment name] (6001) -> ejection (eg: event 6001 tag_ejection)
|
||||
-- CL_EVENT_DISPATCHEFFECT0 [particle name, attachment name] (9001) -> particles (eg: event 9001 mw_muzzleflash tag_flash)
|
||||
-- CL_EVENT_DISPATCHEFFECT1 [0/1] (9011) -> left hand grip pose toggle (eg: event 9011 0 -> event 9011 1)
|
||||
-- CL_EVENT_DISPATCHEFFECT2 [0/1] (9021) -> right hand grip pose toggle (eg: event 9021 0 -> event 9021 1)
|
||||
-- CL_EVENT_DISPATCHEFFECT3 [name] (9031) -> run attachment function (eg: event 9031 FillBullets)
|
||||
|
||||
--Animation event codes
|
||||
local CL_EVENT_MUZZLEFLASH0 = 5001 -- Muzzleflash on attachment 0
|
||||
local CL_EVENT_MUZZLEFLASH1 = 5011 -- Muzzleflash on attachment 1
|
||||
local CL_EVENT_MUZZLEFLASH2 = 5021 -- Muzzleflash on attachment 2
|
||||
local CL_EVENT_MUZZLEFLASH3 = 5031 -- Muzzleflash on attachment 3
|
||||
local CL_EVENT_SPARK0 = 5002 -- Spark on attachment 0
|
||||
local CL_EVENT_NPC_MUZZLEFLASH0 = 5003 -- Muzzleflash on attachment 0 for third person views
|
||||
local CL_EVENT_NPC_MUZZLEFLASH1 = 5013 -- Muzzleflash on attachment 1 for third person views
|
||||
local CL_EVENT_NPC_MUZZLEFLASH2 = 5023 -- Muzzleflash on attachment 2 for third person views
|
||||
local CL_EVENT_NPC_MUZZLEFLASH3 = 5033 -- Muzzleflash on attachment 3 for third person views
|
||||
local CL_EVENT_SOUND = 5004 -- Emit a sound // NOTE THIS MUST MATCH THE DEFINE AT CBaseEntity::PrecacheModel on the server!!!!!
|
||||
local CL_EVENT_EJECTBRASS1 = 6001 -- Eject a brass shell from attachment 1
|
||||
local CL_EVENT_DISPATCHEFFECT0 = 9001 -- Hook into a DispatchEffect on attachment 0
|
||||
local CL_EVENT_DISPATCHEFFECT1 = 9011 -- Hook into a DispatchEffect on attachment 1
|
||||
local CL_EVENT_DISPATCHEFFECT2 = 9021 -- Hook into a DispatchEffect on attachment 2
|
||||
local CL_EVENT_DISPATCHEFFECT3 = 9031 -- Hook into a DispatchEffect on attachment 3
|
||||
local CL_EVENT_DISPATCHEFFECT4 = 9041 -- Hook into a DispatchEffect on attachment 4
|
||||
local CL_EVENT_DISPATCHEFFECT5 = 9051 -- Hook into a DispatchEffect on attachment 5
|
||||
local CL_EVENT_DISPATCHEFFECT6 = 9061 -- Hook into a DispatchEffect on attachment 6
|
||||
local CL_EVENT_DISPATCHEFFECT7 = 9071 -- Hook into a DispatchEffect on attachment 7
|
||||
local CL_EVENT_DISPATCHEFFECT8 = 9081 -- Hook into a DispatchEffect on attachment 8
|
||||
local CL_EVENT_DISPATCHEFFECT9 = 9091 -- Hook into a DispatchEffect on attachment 9
|
||||
local utilef = util.Effect
|
||||
local pef = ParticleEffectAttach
|
||||
|
||||
local function invalidateBoneCacheForParticles(ent)
|
||||
while (IsValid(ent)) do
|
||||
if (ent:IsEffectActive(EF_BONEMERGE) || !IsValid(ent:GetParent())) then
|
||||
ent:InvalidateBoneCache()
|
||||
end
|
||||
ent = ent:GetParent()
|
||||
end
|
||||
end
|
||||
|
||||
local function findAttachmentInChildren(ent, attName)
|
||||
local attId = mw_utils.LookupAttachmentCached(ent, attName)
|
||||
|
||||
for _, c in pairs(ent:GetChildren()) do
|
||||
if (c:GetClass() != "class C_BaseFlex") then
|
||||
continue
|
||||
end
|
||||
|
||||
local ce, ca = findAttachmentInChildren(c, attName)
|
||||
|
||||
if (ca != nil) then
|
||||
attId = ca
|
||||
ent = ce
|
||||
end
|
||||
end
|
||||
|
||||
return ent, attId
|
||||
end
|
||||
|
||||
function ENT:FindAttachment(attName)
|
||||
return findAttachmentInChildren(self, attName)
|
||||
end
|
||||
|
||||
local function createEffectDataForShell(owner, attName)
|
||||
local data = EffectData()
|
||||
data:SetEntity(owner)
|
||||
|
||||
local attEnt, attId = findAttachmentInChildren(owner, attName)
|
||||
|
||||
if (attId == nil) then
|
||||
mw_utils.ErrorPrint("createEffectDataForShell: "..attName.." does not exist on model!")
|
||||
return data
|
||||
end
|
||||
|
||||
local att = attEnt:GetAttachment(attId)
|
||||
data:SetOrigin(att.Pos)
|
||||
data:SetAngles(att.Ang)
|
||||
|
||||
owner = owner:GetOwner()
|
||||
|
||||
while (IsValid(owner) && !owner:IsPlayer()) do
|
||||
owner = owner:GetOwner()
|
||||
end
|
||||
|
||||
if (IsValid(owner)) then
|
||||
data:SetNormal(owner:GetVelocity():GetNormalized())
|
||||
data:SetMagnitude(owner:GetVelocity():Length())
|
||||
end
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
function ENT:IsFirstPerson()
|
||||
local w = self:GetOwner()
|
||||
return IsValid(w:GetOwner()) && w:GetOwner():IsPlayer() && !w:GetOwner():ShouldDrawLocalPlayer() && w:IsCarriedByLocalPlayer()
|
||||
end
|
||||
|
||||
function ENT:HandleEjection(attName)
|
||||
local w = self:GetOwner()
|
||||
|
||||
if (w.Shell == "mwb_shelleject" || w.Shell == "mwb_shelleject_comp") then
|
||||
mw_utils.ErrorPrint("DoEjection: do not use mwb_shelleject! Use an existing caliber or make your own.")
|
||||
return true
|
||||
elseif (istable(w.Shell)) then
|
||||
mw_utils.DevPrint("DoEjection: still using legacy way! Consider switching to new method.")
|
||||
end
|
||||
|
||||
local eff = isstring(w.Shell) && w.Shell || "mwb_shelleject_comp"
|
||||
|
||||
if (self:IsFirstPerson()) then
|
||||
local data = createEffectDataForShell(self, attName)
|
||||
data:SetFlags(1)
|
||||
utilef(eff, data)
|
||||
else
|
||||
local data = createEffectDataForShell(w, attName)
|
||||
data:SetFlags(0)
|
||||
utilef(eff, data)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:HandleParticle(partName, attName)
|
||||
local w = self:GetOwner()
|
||||
|
||||
if (w.ParticleEffects != nil && w.ParticleEffects[partName] != nil) then
|
||||
partName = w.ParticleEffects[partName]
|
||||
end
|
||||
|
||||
if (self:IsFirstPerson()) then
|
||||
local ent, attId = findAttachmentInChildren(self, attName)
|
||||
|
||||
if (attId == nil) then
|
||||
mw_utils.ErrorPrint("HandleParticle: "..attName.." does not exist on viewmodel!")
|
||||
return true
|
||||
end
|
||||
|
||||
if (self.m_Particles[partName] != nil) then
|
||||
self.m_Particles[partName]:StopEmissionAndDestroyImmediately()
|
||||
end
|
||||
|
||||
local particleSystem = CreateParticleSystem(ent, partName, PATTACH_POINT_FOLLOW, attId)
|
||||
particleSystem:SetIsViewModelEffect(true)
|
||||
particleSystem:SetShouldDraw(false)
|
||||
self.m_Particles[partName] = particleSystem
|
||||
else
|
||||
local ent, attId = findAttachmentInChildren(w, attName)
|
||||
|
||||
if (attId == nil) then
|
||||
mw_utils.ErrorPrint("HandleParticle: "..attName.." does not exist on worldmodel!")
|
||||
return true
|
||||
end
|
||||
|
||||
ent:StopParticlesNamed(partName)
|
||||
pef(partName, PATTACH_POINT_FOLLOW, ent, attId)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:HandleSound(soundName, spatialVector)
|
||||
local w = self:GetOwner()
|
||||
|
||||
if (IsValid(w) && w.SoundOverrides != nil) then
|
||||
soundName = w.SoundOverrides[soundName] || soundName
|
||||
end
|
||||
|
||||
if (spatialVector != nil && !spatialVector:IsZero()) then
|
||||
if (IsValid(w:GetOwner()) && !w:GetOwner():IsOnGround()) then
|
||||
return true
|
||||
end
|
||||
|
||||
local ang = self:GetAngles()
|
||||
local pos = self:GetPos()
|
||||
pos:Add(ang:Forward() * spatialVector.y)
|
||||
pos:Add(ang:Right() * spatialVector.x)
|
||||
pos:Add(ang:Up() * spatialVector.z)
|
||||
|
||||
sound.Play(soundName, pos)
|
||||
return true
|
||||
end
|
||||
|
||||
--if (self:GetPlaybackRate() != 1) then
|
||||
-- self:EmitSound(soundName, 100, math.Clamp(self:GetPlaybackRate(), 0.95, 1.15) * 100, 1, CHAN_AUTO, SND_CHANGE_PITCH)
|
||||
--else
|
||||
self:EmitSound(soundName, 0, math.Clamp(self:GetPlaybackRate(), 1, 1.1) * 100, 0, 0, SND_SHOULDPAUSE + SND_CHANGE_PITCH)
|
||||
--end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:HandleLeftHandGrip(val)
|
||||
self.m_LeftHandGripTarget = tonumber(val)
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:HandleRightHandGrip(val)
|
||||
self.m_RightHandGripTarget = tonumber(val)
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:HandleAttFunction(name)
|
||||
self:GetOwner():AttachmentFunction(name)
|
||||
return true
|
||||
end
|
||||
|
||||
local function eventError(event, msg)
|
||||
mw_utils.ErrorPrint("FireAnimationEvent ("..event.."): "..msg)
|
||||
end
|
||||
|
||||
function ENT:FireAnimationEvent(pos, ang, event, name)
|
||||
if (event == CL_EVENT_DISPATCHEFFECT3) then
|
||||
return self:HandleAttFunction(name)
|
||||
end
|
||||
|
||||
if (event == CL_EVENT_DISPATCHEFFECT1) then
|
||||
return self:HandleLeftHandGrip(name || 0)
|
||||
end
|
||||
|
||||
if (event == CL_EVENT_DISPATCHEFFECT2) then
|
||||
return self:HandleRightHandGrip(name || 0)
|
||||
end
|
||||
|
||||
if (event == CL_EVENT_SOUND) then
|
||||
if (name == nil) then
|
||||
eventError(event, "Missing sound name!")
|
||||
return true
|
||||
end
|
||||
|
||||
local args = string.Explode(" ", name)
|
||||
|
||||
if (#args <= 0) then
|
||||
eventError(event, "Missing arguments!")
|
||||
return true
|
||||
end
|
||||
|
||||
local soundName = args[1]
|
||||
local spatialVector = Vector()
|
||||
|
||||
if (args[2] != nil) then
|
||||
local components = string.Explode(",", args[2])
|
||||
|
||||
if (#components <= 1) then
|
||||
--jake used spaces like a dumbass
|
||||
spatialVector.x = args[2]
|
||||
spatialVector.y = args[3]
|
||||
spatialVector.z = args[4]
|
||||
else
|
||||
spatialVector.x = tonumber(components[1]) || 0
|
||||
spatialVector.y = tonumber(components[2]) || 0
|
||||
spatialVector.z = tonumber(components[3]) || 0
|
||||
end
|
||||
end
|
||||
|
||||
return self:HandleSound(soundName, spatialVector)
|
||||
end
|
||||
|
||||
if (event == CL_EVENT_EJECTBRASS1) then
|
||||
if (name == nil) then
|
||||
eventError(event, "Missing attachment name!")
|
||||
return true
|
||||
end
|
||||
|
||||
if (self:GetOwner().HandleEjection != nil) then
|
||||
return self:GetOwner():HandleEjection(name)
|
||||
end
|
||||
|
||||
return self:HandleEjection(name)
|
||||
end
|
||||
|
||||
if (event == CL_EVENT_DISPATCHEFFECT0) then
|
||||
if (name == nil) then
|
||||
eventError(event, "Missing arguments!")
|
||||
return true
|
||||
end
|
||||
|
||||
local args = string.Explode(" ", name)
|
||||
|
||||
if (#args <= 0) then
|
||||
eventError(event, "Missing arguments!")
|
||||
return true
|
||||
end
|
||||
|
||||
local partName = args[1]
|
||||
local attName = args[2]
|
||||
|
||||
if (attName == nil) then
|
||||
eventError(event, "Missing attachment name!")
|
||||
return true
|
||||
end
|
||||
|
||||
return self:HandleParticle(partName, attName)
|
||||
end
|
||||
end
|
||||
273
lua/entities/mg_viewmodel/client/cl_render.lua
Normal file
273
lua/entities/mg_viewmodel/client/cl_render.lua
Normal file
@@ -0,0 +1,273 @@
|
||||
local function drawModels(vm, ent, flags)
|
||||
--https://github.com/Facepunch/garrysmod-issues/issues/4821
|
||||
--i didn't need this before, but now i do :shrug:
|
||||
ent:RemoveEFlags(EFL_USE_PARTITION_WHEN_NOT_SOLID)
|
||||
|
||||
local children = ent:GetChildren()
|
||||
local numChildren = #children
|
||||
|
||||
if (ent:IsEffectActive(EF_BONEMERGE)) then
|
||||
if (ent == vm.m_CHands) then
|
||||
ent:SetRenderOrigin(LocalToWorld(-ent:OBBCenter(), mw_math.ZeroAngle, vm:GetRenderOrigin(), vm:GetRenderAngles()))
|
||||
else
|
||||
if (ent:EntIndex() < 0) then
|
||||
ent:SetRenderOrigin(vm:GetRenderOrigin())
|
||||
end
|
||||
|
||||
if (numChildren > 0) then
|
||||
--some weird issue on windowed needs this
|
||||
ent:SetupBones()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if ((numChildren <= 0 || ent:EntIndex() > 0) && !ent.bAttachmentRenderOverride) then
|
||||
ent:DrawModel(flags)
|
||||
end
|
||||
|
||||
ent.CustomizationAnimationDelta = 0
|
||||
|
||||
for c = 1, numChildren do
|
||||
drawModels(vm, children[c], flags)
|
||||
end
|
||||
end
|
||||
|
||||
local function isCustomizing()
|
||||
return IsValid(MW_CUSTOMIZEMENU)
|
||||
end
|
||||
|
||||
local function drawCustomizationBackground()
|
||||
if (!isCustomizing()) then
|
||||
return
|
||||
end
|
||||
|
||||
cam.Start2D()
|
||||
surface.SetDrawColor(0, 0, 0, MW_CUSTOMIZEMENU.AlphaDelta * 200)
|
||||
surface.DrawRect(0, 0, ScrW(), ScrH())
|
||||
cam.End2D()
|
||||
end
|
||||
|
||||
local function shouldDrawModel(model, children)
|
||||
for _, c in pairs(children) do
|
||||
if (!c:IsEffectActive(EF_BONEMERGE)) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
return #children <= 0 || model:EntIndex() > 0
|
||||
end
|
||||
|
||||
local function drawCustomizationHighlights(model, flags, refvalue)
|
||||
model.CustomizationAnimationDelta = (model.CustomizationAnimationDelta || 0) - (math.min(FrameTime(), 0.1) * 3)
|
||||
|
||||
local children = model:GetChildren()
|
||||
|
||||
if (shouldDrawModel(model, children)) then
|
||||
model:RemoveEFlags(EFL_USE_PARTITION_WHEN_NOT_SOLID)
|
||||
|
||||
if (#children > 0) then
|
||||
--some weird issue on windowed needs this
|
||||
model:SetupBones()
|
||||
end
|
||||
|
||||
render.SetStencilWriteMask(0xFF)
|
||||
render.SetStencilTestMask(0xFF)
|
||||
render.SetStencilReferenceValue(0)
|
||||
|
||||
render.SetStencilCompareFunction(STENCIL_ALWAYS)
|
||||
render.SetStencilPassOperation(STENCIL_REPLACE)
|
||||
render.SetStencilFailOperation(STENCIL_KEEP)
|
||||
render.SetStencilZFailOperation(STENCIL_KEEP)
|
||||
|
||||
render.SetStencilEnable(true)
|
||||
render.SetStencilReferenceValue(refvalue + 1)
|
||||
model:RemoveEFlags(EFL_USE_PARTITION_WHEN_NOT_SOLID)
|
||||
model:DrawModel(flags)
|
||||
render.SetStencilCompareFunction(STENCIL_EQUAL)
|
||||
|
||||
if (model.CustomizationAnimationDelta > 0) then
|
||||
cam.Start2D()
|
||||
surface.SetDrawColor(model.CustomizationAnimationColor.r, model.CustomizationAnimationColor.g, model.CustomizationAnimationColor.b, model.CustomizationAnimationDelta * 200)
|
||||
surface.DrawRect(0, 0, ScrW(), ScrH())
|
||||
cam.End2D()
|
||||
end
|
||||
|
||||
render.SetStencilEnable(false)
|
||||
end
|
||||
|
||||
for i, c in pairs(children) do
|
||||
drawCustomizationHighlights(c, flags, refvalue + i + #c:GetChildren()) --this is gonna get out of hand eventually
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Draw(flags)
|
||||
if (GetConVar("mgbase_debug_vmrender"):GetInt() <= 0) then
|
||||
return
|
||||
end
|
||||
|
||||
if (self.m_LastSequenceIndex == "INIT" || self:GetRenderOrigin() == nil) then
|
||||
--calcview / no anim called
|
||||
return
|
||||
end
|
||||
|
||||
local w = self:GetOwner()
|
||||
|
||||
if (!IsValid(w) || !w:IsCarriedByLocalPlayer()) then
|
||||
return
|
||||
end
|
||||
|
||||
if (IsValid(w:GetOwner())) then
|
||||
w:GetOwner():DrawViewModel(false)
|
||||
end
|
||||
|
||||
render.SetColorModulation(1, 1, 1)
|
||||
drawCustomizationBackground()
|
||||
|
||||
self:DrawShadow(false)
|
||||
|
||||
self.bRendering = true
|
||||
self:SetupBones() --makes velements and vmanip work
|
||||
self.bRendering = false
|
||||
|
||||
if (!isCustomizing()) then
|
||||
if (!w:HasFlag("Holstering") || CurTime() <= w:GetNextHolsterTime()) then
|
||||
self:SetNoDraw(false)
|
||||
drawModels(self, self, flags)
|
||||
|
||||
for name, particleSystem in pairs(self.m_Particles) do
|
||||
if (!particleSystem:IsValid() || particleSystem:IsFinished()) then
|
||||
self.m_Particles[name] = nil
|
||||
continue
|
||||
end
|
||||
|
||||
particleSystem:Render()
|
||||
end
|
||||
|
||||
--attachments
|
||||
local atts = w:GetAllAttachmentsInUse()
|
||||
|
||||
for slot = #atts, 1, -1 do
|
||||
if (IsValid(atts[slot].m_Model)) then
|
||||
atts[slot]:Render(w, atts[slot].m_Model)
|
||||
end
|
||||
end
|
||||
end
|
||||
self:SetNoDraw(true)
|
||||
else
|
||||
--self.m_CHands:SetNoDraw(false)
|
||||
self.m_CHands:DrawModel(flags)
|
||||
--self.m_CHands:SetNoDraw(true)
|
||||
drawCustomizationHighlights(self, flags, MWBASE_STENCIL_REFVALUE + 17)
|
||||
end
|
||||
|
||||
for shell, _ in pairs(self.m_Shells) do
|
||||
if (!IsValid(shell)) then
|
||||
self.m_Shells[shell] = nil
|
||||
continue
|
||||
end
|
||||
|
||||
shell:DrawModel(flags)
|
||||
end
|
||||
|
||||
self:ViewBlur()
|
||||
|
||||
if (IsValid(w:GetOwner())) then
|
||||
w:GetOwner():DrawViewModel(true)
|
||||
end
|
||||
end
|
||||
|
||||
local function drawBlurModels(model, flags)
|
||||
local children = model:GetChildren()
|
||||
|
||||
--if (shouldDrawModel(model, children)) then
|
||||
model:RemoveEFlags(EFL_USE_PARTITION_WHEN_NOT_SOLID)
|
||||
model:DrawModel(flags)
|
||||
--end
|
||||
|
||||
for i, c in pairs(children) do
|
||||
drawBlurModels(c, flags) --this is gonna get out of hand eventually
|
||||
end
|
||||
end
|
||||
|
||||
local blurMaterial = Material("mg/blur.vmt")
|
||||
ENT.LerpBlur = 0
|
||||
function ENT:ViewBlur()
|
||||
local w = self:GetOwner()
|
||||
|
||||
if (!IsValid(w)) then
|
||||
return
|
||||
end
|
||||
|
||||
local bPixelShaders2 = render.SupportsPixelShaders_2_0()
|
||||
|
||||
if (!bPixelShaders2) then
|
||||
return
|
||||
end
|
||||
|
||||
if (GetConVar("mgbase_fx_blur"):GetInt() != 1) then return end
|
||||
|
||||
if (w.DisableReloadBlur && w:HasFlag("Reloading")) then return end
|
||||
|
||||
local bOpticAim = (w:GetAimDelta() > 0 && w:GetSight() != nil && w:GetSight().Optic != nil && w:GetAimModeDelta() <= w.m_hybridSwitchThreshold)
|
||||
local bCanBlur = w:HasFlag("Reloading") || w:HasFlag("Customizing") || bOpticAim || (CurTime() < w:GetNextInspectTime() && w.m_seqIndex == "Inspect")
|
||||
|
||||
if (bCanBlur) then
|
||||
local delta = 1 - w:GetAimDelta()
|
||||
|
||||
if (bOpticAim) then
|
||||
delta = w:GetAimDelta()
|
||||
end
|
||||
|
||||
if (CurTime() < w:GetNextInspectTime() && w.m_seqIndex == "Inspect") then
|
||||
delta = self:GetCycle() > 0.8 && 0 || 1
|
||||
end
|
||||
|
||||
self.LerpBlur = Lerp(5 * FrameTime(), self.LerpBlur, 5 * delta)
|
||||
|
||||
render.SetStencilWriteMask(0xFF)
|
||||
render.SetStencilTestMask(0xFF)
|
||||
render.SetStencilReferenceValue(0)
|
||||
render.SetStencilPassOperation(STENCIL_KEEP)
|
||||
render.SetStencilZFailOperation(STENCIL_KEEP)
|
||||
render.ClearStencil()
|
||||
render.SetStencilEnable(true)
|
||||
render.SetStencilReferenceValue(MWBASE_STENCIL_REFVALUE + 13)
|
||||
render.SetStencilCompareFunction(STENCIL_NEVER)
|
||||
render.SetStencilFailOperation(STENCIL_REPLACE)
|
||||
render.SetBlend(0)
|
||||
|
||||
if (w:GetAimDelta() < 1) then
|
||||
drawBlurModels(self, flags)
|
||||
elseif (w:GetSight() != nil && IsValid(w:GetSight().hideModel)) then
|
||||
w:GetSight().m_Model:SetupBones()
|
||||
w:GetSight().m_Model:InvalidateBoneCache()
|
||||
local matrix = w:GetSight().m_Model:GetBoneMatrix(0)
|
||||
|
||||
w:GetSight().hideModel:SetPos(matrix:GetTranslation())
|
||||
w:GetSight().hideModel:SetAngles(matrix:GetAngles())
|
||||
|
||||
w:GetSight().hideModel:DrawModel()
|
||||
end
|
||||
render.SetBlend(1)
|
||||
render.SetStencilCompareFunction(STENCIL_NOTEQUAL)
|
||||
cam.Start2D()
|
||||
for i = 1, self.LerpBlur, 1 do
|
||||
render.UpdateScreenEffectTexture()
|
||||
surface.SetMaterial(blurMaterial)
|
||||
surface.SetDrawColor(255, 255, 255, 255)
|
||||
surface.DrawTexturedRect(0, 0, ScrW(), ScrH())
|
||||
end
|
||||
cam.End2D()
|
||||
render.SetStencilEnable(false)
|
||||
render.ClearStencil()
|
||||
else
|
||||
self.LerpBlur = 0
|
||||
end
|
||||
end
|
||||
|
||||
--[[hook.Add("VManipVMEntity", "MW19_VManipEntity", function(ply, weapon)
|
||||
--this is probably not necessary since vmanip already looks for m_ViewModel
|
||||
if (weapons.IsBasedOn(weapon:GetClass(), "mg_base")) then
|
||||
return weapon:GetViewModel()
|
||||
end
|
||||
end)]]
|
||||
9
lua/entities/mg_viewmodel/init.lua
Normal file
9
lua/entities/mg_viewmodel/init.lua
Normal file
@@ -0,0 +1,9 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("client/cl_animation.lua")
|
||||
AddCSLuaFile("client/cl_calcview.lua")
|
||||
AddCSLuaFile("client/cl_render.lua")
|
||||
AddCSLuaFile("client/cl_events.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
include("shared.lua")
|
||||
|
||||
util.AddNetworkString("mgbase_viewmodelanim")
|
||||
186
lua/entities/mg_viewmodel/shared.lua
Normal file
186
lua/entities/mg_viewmodel/shared.lua
Normal file
@@ -0,0 +1,186 @@
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
ENT.RenderGroup = RENDERGROUP_VIEWMODEL
|
||||
ENT.RenderMode = RENDERMODE_ENVIROMENTAL
|
||||
--ENT.AutomaticFrameAdvance = true
|
||||
|
||||
function ENT:Initialize()
|
||||
if (!IsValid(self:GetOwner())) then
|
||||
error("Invalid weapon for viewmodel!")
|
||||
end
|
||||
|
||||
self:AddEFlags(EFL_KEEP_ON_RECREATE_ENTITIES)
|
||||
self:AddEFlags(EFL_FORCE_CHECK_TRANSMIT)
|
||||
self:AddEFlags(EFL_NO_THINK_FUNCTION)
|
||||
self:AddEFlags(EFL_NO_GAME_PHYSICS_SIMULATION)
|
||||
self:AddEFlags(EFL_DONTBLOCKLOS)
|
||||
self:AddEFlags(EFL_DONTWALKON)
|
||||
self:AddEFlags(EFL_NO_DISSOLVE)
|
||||
self:AddEFlags(EFL_NO_PHYSCANNON_INTERACTION)
|
||||
self:AddEFlags(EFL_NO_DAMAGE_FORCES)
|
||||
self:AddEffects(EF_NOINTERP)
|
||||
self:AddFlags(FL_NOTARGET)
|
||||
self:AddFlags(FL_DONTTOUCH)
|
||||
self:AddFlags(FL_STEPMOVEMENT)
|
||||
|
||||
self:SetMoveType(MOVETYPE_NONE)
|
||||
self:SetSolid(SOLID_NONE)
|
||||
self:SetNotSolid(true)
|
||||
self:SetRenderMode(self.RenderMode)
|
||||
self:DrawShadow(false)
|
||||
--self:SetNoDraw(true)
|
||||
self:UseClientSideAnimation()
|
||||
|
||||
local weapon = self:GetOwner()
|
||||
|
||||
if (CLIENT) then
|
||||
self:DestroyShadow()
|
||||
self:InvalidateBoneCache()
|
||||
self:SetupBones()
|
||||
|
||||
self:ResetSequence(0)
|
||||
self:SetCycle(0)
|
||||
self:SetPlaybackRate(1)
|
||||
|
||||
self:CreateRig()
|
||||
self:CreateGloves()
|
||||
self:CreateCHands()
|
||||
|
||||
self:AddCallback("BuildBonePositions", function(vm, numbones)
|
||||
if (!vm.bRendering) then
|
||||
return
|
||||
end
|
||||
|
||||
--vm:GetAttachment(vm:LookupAttachment("camera"))
|
||||
local matrix = vm:GetBoneMatrix(mw_utils.LookupBoneCached(vm, "tag_camera"))
|
||||
|
||||
if (matrix != nil) then
|
||||
local worldMatrix = vm:GetBoneMatrix(0)
|
||||
self.m_CameraAttachment = matrix:GetInverse() * worldMatrix
|
||||
end
|
||||
|
||||
if (VManip != nil) then
|
||||
hook.GetTable()["PostDrawViewModel"]["VManip"](vm, vm:GetOwner():GetOwner(), vm:GetOwner())
|
||||
end
|
||||
end)
|
||||
|
||||
if (VManip != nil) then
|
||||
hook.Add("VManipPostPlayAnim", self, function(self, name)
|
||||
self:VManipPostPlayAnim(name)
|
||||
end)
|
||||
|
||||
hook.Add("VManipHoldQuit", self, function(self)
|
||||
self:VManipHoldQuit()
|
||||
end)
|
||||
|
||||
hook.Add("VManipRemove", self, function(self)
|
||||
self:VManipRemove()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
self.m_LastSequenceIndex = "INIT"
|
||||
self.m_Tick = 0
|
||||
|
||||
--old compatibility
|
||||
--weapon.m_ViewModel = self
|
||||
end
|
||||
|
||||
function ENT:GetAnimID(weaponSequenceIndex)
|
||||
local id = 0
|
||||
|
||||
for index, _ in SortedPairs(self:GetOwner().Animations) do
|
||||
id = id + 1
|
||||
|
||||
if (string.lower(index) == string.lower(weaponSequenceIndex)) then
|
||||
return id
|
||||
end
|
||||
end
|
||||
|
||||
return -1
|
||||
end
|
||||
|
||||
function ENT:GetSequenceIndexByID(animId)
|
||||
local id = 0
|
||||
|
||||
for index, _ in SortedPairs(self:GetOwner().Animations) do
|
||||
id = id + 1
|
||||
|
||||
if (id == animId) then
|
||||
return index
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function ENT:GetPlayerOwner()
|
||||
if (IsValid(self:GetOwner())) then
|
||||
return self:GetOwner():GetOwner()
|
||||
end
|
||||
|
||||
return NULL
|
||||
end
|
||||
|
||||
function ENT:GetWeaponOwner()
|
||||
return self:GetOwner()
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (IsValid(self.m_Rig)) then self.m_Rig:Remove() end
|
||||
if (IsValid(self.m_Gloves)) then self.m_Gloves:Remove() end
|
||||
if (IsValid(self.m_CHands)) then self.m_CHands:Remove() end
|
||||
end
|
||||
|
||||
function ENT:PlayAnimation(weaponSequenceIndex, bNoTick) --"Holster", "Draw", ...
|
||||
self.m_LastSequenceIndex = weaponSequenceIndex
|
||||
|
||||
if (!bNoTick) then
|
||||
self.m_Tick = self.m_Tick + 1
|
||||
end
|
||||
|
||||
local weaponSequence = nil--self:GetOwner().Animations[weaponSequenceIndex]
|
||||
|
||||
for index, seq in pairs(self:GetOwner().Animations) do
|
||||
if (string.lower(index) == string.lower(weaponSequenceIndex)) then
|
||||
weaponSequence = seq
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if (weaponSequence == nil) then
|
||||
return
|
||||
end
|
||||
|
||||
local animId = self:GetAnimID(weaponSequenceIndex)
|
||||
local rate = weaponSequence.Fps / 30
|
||||
|
||||
if (CLIENT) then
|
||||
local anims = weaponSequence.Sequences
|
||||
self:PlaySequence(anims[math.random(1, #anims)], rate)
|
||||
end
|
||||
|
||||
if (SERVER) then
|
||||
net.Start("mgbase_viewmodelanim", true)
|
||||
net.WriteEntity(self)
|
||||
net.WriteFloat(rate)
|
||||
net.WriteUInt(animId, 16)
|
||||
net.WriteUInt(self.m_Tick, 16)
|
||||
net.Broadcast()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:UpdateAnimation()
|
||||
local cycle = self:GetCycle()
|
||||
self:PlayAnimation(self.m_LastSequenceIndex, true)
|
||||
self:SetCycle(cycle)
|
||||
end
|
||||
|
||||
--sorryyyyy garrysmod-issues/issues/5344
|
||||
local oldCleanup = game.CleanUpMap
|
||||
function game.CleanUpMap(dontSendToClients, ExtraFilters)
|
||||
dontSendToClients = dontSendToClients || false
|
||||
ExtraFilters = ExtraFilters || {}
|
||||
table.insert(ExtraFilters, "mg_viewmodel")
|
||||
oldCleanup(dontSendToClients, ExtraFilters)
|
||||
end
|
||||
84
lua/entities/mg_warhead/cl_init.lua
Normal file
84
lua/entities/mg_warhead/cl_init.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
include("shared.lua")
|
||||
|
||||
ENT.AutomaticFrameAdvance = true
|
||||
|
||||
|
||||
local flair = Material("shadowdark/flairs/grenade_flair.vmt")
|
||||
ENT.OuterFlairColor = Color(236,153,17,255)
|
||||
ENT.InnerFlairColor = Color(255,255,255,255)
|
||||
|
||||
ENT.OuterFlairScale = 1
|
||||
ENT.InnerFlairScale = 0.3
|
||||
|
||||
function ENT:Draw(flags)
|
||||
self:DrawModel(flags)
|
||||
|
||||
if (self.m_SpawnPos != nil && self:GetPos():Distance(self.m_SpawnPos) > 64) then
|
||||
ParticleEffectAttach("rockettrail", PATTACH_ABSORIGIN_FOLLOW, self, 0)
|
||||
self.m_SpawnPos = nil
|
||||
end
|
||||
|
||||
local ang = LocalPlayer():EyeAngles()
|
||||
local angle = Angle( 0, LocalPlayer():EyeAngles()[2], 0 )
|
||||
|
||||
angle = Angle(LocalPlayer():EyeAngles()[1], angle.y, 0 )
|
||||
|
||||
angle:RotateAroundAxis( angle:Up(), -90 )
|
||||
angle:RotateAroundAxis( angle:Forward(), 90 )
|
||||
|
||||
cam.Start3D2D( self:GetPos() - self:GetForward() * -5, angle, 0.2 )
|
||||
|
||||
local OuterScale = 512 * self.OuterFlairScale
|
||||
local InnerScale = 512 * self.InnerFlairScale
|
||||
|
||||
surface.SetMaterial(flair)
|
||||
surface.SetDrawColor(self.OuterFlairColor)
|
||||
surface.DrawTexturedRect(-OuterScale/2, -OuterScale/2, OuterScale, OuterScale)
|
||||
|
||||
surface.SetDrawColor(self.InnerFlairColor)
|
||||
surface.DrawTexturedRect(-InnerScale/2, -InnerScale/2, InnerScale, InnerScale)
|
||||
cam.End3D2D()
|
||||
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent(flags)
|
||||
self:Draw(flags)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if (self:WaterLevel() <= 0) then
|
||||
self:EmitSound("^viper/shared/rocket_expl_env_0"..math.random(1, 3)..".wav", 150, 100, 1, CHAN_WEAPON) --snd scripts dont work lol!
|
||||
|
||||
local dlight = DynamicLight(self:EntIndex())
|
||||
if (dlight) then
|
||||
dlight.pos = self:GetPos()
|
||||
dlight.r = 255
|
||||
dlight.g = 75
|
||||
dlight.b = 0
|
||||
dlight.brightness = 5
|
||||
dlight.Decay = 2000
|
||||
dlight.Size = 1024
|
||||
dlight.DieTime = CurTime() + 5
|
||||
end
|
||||
end
|
||||
|
||||
self:StopParticles()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Client Think - called every frame
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
if (self:WaterLevel() > 0) then
|
||||
self:EmitSound("viper/shared/melee/melee_world_fist_soft_plr_01.ogg", 75, 100, 0.001, CHAN_WEAPON)
|
||||
self:StopParticles()
|
||||
end
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: Called immediately after a "load"
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
278
lua/entities/mg_warhead/init.lua
Normal file
278
lua/entities/mg_warhead/init.lua
Normal file
@@ -0,0 +1,278 @@
|
||||
AddCSLuaFile("cl_init.lua")
|
||||
AddCSLuaFile("shared.lua")
|
||||
|
||||
include("shared.lua")
|
||||
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: KeyValue
|
||||
Desc: Called when a keyvalue is added to us
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:KeyValue( key, value )
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: OnRestore
|
||||
Desc: The game has just been reloaded. This is usually the right place
|
||||
to call the GetNW* functions to restore the script's values.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:OnRestore()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AcceptInput
|
||||
Desc: Accepts input, return true to override/accept input
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:AcceptInput( name, activator, caller, data )
|
||||
return false
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: UpdateTransmitState
|
||||
Desc: Set the transmit state
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:UpdateTransmitState()
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Think
|
||||
Desc: Entity's think function.
|
||||
-----------------------------------------------------------]]
|
||||
function ENT:Think()
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(colData, collider)
|
||||
if (self.m_Water && self:GetVelocity():Length() < 250) then
|
||||
timer.Simple(0, function()
|
||||
self:Remove()
|
||||
end)
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
local bHasExploded = false
|
||||
|
||||
for i, e in pairs(ents.FindInSphere(self:GetPos(), 16)) do
|
||||
if (e:IsNPC()) then
|
||||
self:Explode({
|
||||
HitEntity = e,
|
||||
HitNormal = (e:NearestPoint(self:GetPos()) - self:GetPos()):GetNormalized(),
|
||||
HitPos = e:NearestPoint(self:GetPos())
|
||||
})
|
||||
|
||||
if (e:GetClass() == "npc_strider") then
|
||||
e:Fire("Explode")
|
||||
end
|
||||
|
||||
bHasExploded = true
|
||||
end
|
||||
end
|
||||
|
||||
if (!bHasExploded) then
|
||||
self:Explode(colData)
|
||||
end
|
||||
end
|
||||
|
||||
-- function ENT:PhysicsUpdate(phys)
|
||||
-- if (self:WaterLevel() > 0) then
|
||||
-- self.m_Water = true
|
||||
-- end
|
||||
|
||||
-- if (self.m_Water) then
|
||||
-- phys:EnableDrag(true)
|
||||
-- phys:EnableGravity(true)
|
||||
-- return
|
||||
-- end
|
||||
|
||||
-- self.m_Fuel = self.m_Fuel - 100 * FrameTime()
|
||||
-- self.m_Stability = self.m_Stability + 700 * FrameTime()
|
||||
|
||||
-- if (self.m_Propel && self.m_Fuel <= 0) then
|
||||
-- self.m_Propel = false
|
||||
-- phys:EnableDrag(true)
|
||||
-- phys:EnableGravity(true)
|
||||
-- end
|
||||
|
||||
-- if (self.m_Propel) then
|
||||
-- phys:AddVelocity(phys:GetAngles():Forward() * self.Projectile.Speed)
|
||||
-- self.m_gravity = self.m_gravity + (self.Projectile.Gravity)
|
||||
|
||||
-- phys:SetPos(self.LastPos + phys:GetAngles():Forward() * (self.Projectile.Speed * FrameTime()) - (Vector(0, 0, self.m_gravity) * FrameTime()))
|
||||
-- end
|
||||
|
||||
-- local vel = phys:GetVelocity()
|
||||
-- phys:SetAngles(vel:Angle() + Angle(self.Projectile.Gravity,math.Rand(self.m_Stability / -self.Projectile.Stability, self.m_Stability / self.Projectile.Stability),self.m_gravity))
|
||||
-- phys:SetVelocity(vel)
|
||||
|
||||
|
||||
|
||||
|
||||
-- if (self:WaterLevel() > 0) then
|
||||
-- self.m_Propel = false
|
||||
-- end
|
||||
|
||||
-- for i, e in pairs(ents.FindInSphere(phys:GetPos(), 16)) do
|
||||
-- if (e:IsNPC()) then
|
||||
-- self:Explode({
|
||||
-- HitEntity = e,
|
||||
-- HitNormal = (e:NearestPoint(phys:GetPos()) - phys:GetPos()):GetNormalized(),
|
||||
-- HitPos = e:NearestPoint(phys:GetPos())
|
||||
-- })
|
||||
|
||||
-- if (e:GetClass() == "npc_strider") then
|
||||
-- e:Fire("Explode")
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
|
||||
self.Target:SetPos(phys:GetPos())
|
||||
|
||||
self.m_Fuel = self.m_Fuel - 100 * FrameTime()
|
||||
self.m_Stability = self.m_Stability + 700 * FrameTime()
|
||||
|
||||
if (self.m_Propel && self.m_Fuel <= 0) then
|
||||
self.m_Propel = false
|
||||
phys:EnableDrag(true)
|
||||
phys:EnableGravity(true)
|
||||
phys:AddVelocity(phys:GetAngles():Forward() * self.Projectile.Speed)
|
||||
end
|
||||
|
||||
if (self.m_Propel) then
|
||||
|
||||
phys:SetPos(self.LastPos + phys:GetAngles():Forward() * (self.Projectile.Speed * FrameTime()) - (Vector(0, 0, self.m_gravity) * FrameTime()))
|
||||
|
||||
if (self.m_Tracking && self.TrackedEntity:IsValid()) then
|
||||
local dir = self.TrackedEntity:WorldSpaceCenter() - phys:GetPos()
|
||||
phys:SetAngles(LerpAngle(self.Projectile.TrackingFraction, phys:GetAngles(), dir:Angle()))
|
||||
elseif self.Projectile.Stability != 0 then
|
||||
phys:SetAngles(phys:GetAngles() + Angle(0,math.Rand(self.m_Stability / -self.Projectile.Stability, self.m_Stability / self.Projectile.Stability),0))
|
||||
end
|
||||
|
||||
else
|
||||
local vel = phys:GetVelocity()
|
||||
phys:SetAngles(vel:Angle() + Angle(self.Projectile.Gravity,math.Rand(self.m_Stability / -self.Projectile.Stability, self.m_Stability / self.Projectile.Stability),self.m_gravity))
|
||||
phys:SetVelocity(vel)
|
||||
end
|
||||
|
||||
if (!self.bCollided) then
|
||||
--Aim assist
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Box(phys:GetPos(), -self.Maxs, self.Maxs, 0, Color(0, 200, 50, 10))
|
||||
end
|
||||
|
||||
local trData = {
|
||||
start = self.LastPos,
|
||||
endpos = phys:GetPos(),
|
||||
filter = {self:GetOwner(), self},
|
||||
mask = MASK_SHOT_PORTAL,
|
||||
collisiongroup = COLLISION_GROUP_NONE,
|
||||
mins = -self:OBBMaxs(),
|
||||
maxs = self:OBBMins()
|
||||
}
|
||||
|
||||
local tr = util.TraceHull(trData)
|
||||
|
||||
if (tr.Hit && (tr.Entity:IsPlayer() || tr.Entity:IsNPC())) then
|
||||
self:SetPos(tr.HitPos)
|
||||
self:Impact(tr,phys,true)
|
||||
self:ImpactDamage(tr.Entity)
|
||||
self:Explode(tr)
|
||||
return
|
||||
end
|
||||
|
||||
--Normal hitscan
|
||||
if (GetConVar("mgbase_debug_projectiles"):GetInt() > 0) then
|
||||
debugoverlay.Line(self.LastPos, phys:GetPos(), 1, Color(255, 0, 0, 1))
|
||||
end
|
||||
|
||||
tr = util.TraceLine(trData)
|
||||
|
||||
if (tr.Hit) then
|
||||
if tr.Entity:GetClass() == "func_breakable_surf" then
|
||||
--shatter glass windows and other weak surfaces
|
||||
util.BlastDamage(self, self, tr.HitPos, 1, 1)
|
||||
else
|
||||
self:SetPos(tr.HitPos)
|
||||
self:Impact(tr,phys,false)
|
||||
self:ImpactDamage(tr.Entity)
|
||||
self:Explode(tr)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self.LastPos = phys:GetPos()
|
||||
end
|
||||
|
||||
function ENT:Explode(trData)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if (self:WaterLevel() <= 0) then
|
||||
if self.WeaponData.Explosive.BlastRadius >= 200 then
|
||||
ParticleEffect("Generic_explo_vhigh", phys:GetPos() + trData.HitNormal,Angle(0,0,0))
|
||||
else
|
||||
ParticleEffect("Generic_explo_high", phys:GetPos() + trData.HitNormal,Angle(0,0,0))
|
||||
end
|
||||
else
|
||||
local effectdata = EffectData()
|
||||
effectdata:SetOrigin(phys:GetPos())
|
||||
util.Effect("WaterSurfaceExplosion", effectdata)
|
||||
end
|
||||
|
||||
local dmgInfo = DamageInfo()
|
||||
dmgInfo:SetDamage(self.WeaponData.Bullet.Damage[1])
|
||||
dmgInfo:SetAttacker(IsValid(self:GetOwner()) && self:GetOwner() || self)
|
||||
dmgInfo:SetInflictor(self)
|
||||
dmgInfo:SetDamageType(self:GetDamageType())
|
||||
util.BlastDamageInfo(dmgInfo, phys:GetPos(), self.WeaponData.Explosive.BlastRadius)
|
||||
|
||||
util.ScreenShake(phys:GetPos(), 3500, 1111, 1, self.WeaponData.Explosive.BlastRadius * 4)
|
||||
|
||||
util.Decal("Scorch", trData.HitPos - trData.HitNormal, trData.HitPos + trData.HitNormal, self)
|
||||
|
||||
for i, e in pairs(ents.FindInSphere(self:GetPos(), 32)) do
|
||||
if (e:GetClass() == "npc_strider") then
|
||||
e:Fire("Explode")
|
||||
end
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:ImpactDamage(ent)
|
||||
-- local dmgInfo = DamageInfo()
|
||||
-- dmgInfo:SetDamage(self.WeaponData.Bullet.Damage[1] / self.WeaponData.Explosive.ImpactBlastRatio)
|
||||
-- dmgInfo:SetAttacker(IsValid(self:GetOwner()) && self:GetOwner() || self)
|
||||
-- dmgInfo:SetInflictor(self)
|
||||
-- dmgInfo:SetDamageType(self:GetDamageType())
|
||||
-- dmgInfo:SetDamagePosition(self:GetPos())
|
||||
-- ent:TakeDamageInfo(dmgInfo)
|
||||
end
|
||||
|
||||
function ENT:GetDamageType()
|
||||
return DMG_BLAST + DMG_AIRBOAT
|
||||
end
|
||||
|
||||
function ENT:Impact(tr, phys, bHull)
|
||||
if (IsValid(self.Weapon)) then
|
||||
self:FireBullets({
|
||||
Attacker = self:GetOwner(),
|
||||
Num = 1,
|
||||
Tracer = 0,
|
||||
Src = self.LastPos,
|
||||
Dir = (phys:GetPos() - self.LastPos):GetNormalized(),
|
||||
HullSize = bHull && 2 || 1,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(attacker, tr, dmgInfo)
|
||||
dmgInfo:SetInflictor(self.Weapon)
|
||||
dmgInfo:SetDamageType(DMG_DIRECT + self:GetDamageType())
|
||||
self.Weapon:BulletCallback(attacker, tr, dmgInfo)
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
62
lua/entities/mg_warhead/shared.lua
Normal file
62
lua/entities/mg_warhead/shared.lua
Normal file
@@ -0,0 +1,62 @@
|
||||
|
||||
ENT.Base = "base_entity"
|
||||
ENT.Type = "anim"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminOnly = false
|
||||
|
||||
ENT.ExplosionRadius = 430
|
||||
ENT.ExplosionDamage = 700
|
||||
|
||||
game.AddParticles("particles/explosion_fx_ins.pcf")
|
||||
game.AddParticles("particles/ins_rockettrail.pcf")
|
||||
PrecacheParticleSystem("ins_C4_explosion")
|
||||
PrecacheParticleSystem("ins_grenade_explosion")
|
||||
PrecacheParticleSystem("ins_m203_explosion")
|
||||
PrecacheParticleSystem("ins_rpg_explosion")
|
||||
PrecacheParticleSystem("rockettrail")
|
||||
PrecacheParticleSystem("Generic_explo_vhigh")
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: Initialize
|
||||
Desc: First function called. Use to set up your entity
|
||||
-----------------------------------------------------------]]
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel("models/viper/mw/weapons/w_rpapa7_rocket.mdl")
|
||||
self:AddEFlags(EFL_FORCE_CHECK_TRANSMIT)
|
||||
self:SetCustomCollisionCheck(true)
|
||||
|
||||
if (SERVER) then
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:GetPhysicsObject():SetMaterial("metal")
|
||||
self:GetPhysicsObject():AddGameFlag(FVPHYSICS_NO_PLAYER_PICKUP)
|
||||
self:GetPhysicsObject():EnableDrag(false)
|
||||
self:GetPhysicsObject():EnableGravity(false)
|
||||
self:GetPhysicsObject():Wake()
|
||||
|
||||
self.Projectile = table.Copy(self.Weapon.Projectile)
|
||||
self.WeaponData = self.Weapon:GetTable()
|
||||
|
||||
self.m_Propel = true
|
||||
self.m_Fuel = self.Projectile.Fuel
|
||||
self.m_Stability = 0
|
||||
self.m_Water = false
|
||||
self.LastPos = self:GetOwner():EyePos()
|
||||
self.Target = ents.Create("info_target")
|
||||
self.Target:Spawn()
|
||||
|
||||
if self.WeaponData.TrackedEntity then
|
||||
self.m_Tracking = self.Projectile.Tracking
|
||||
self.TrackedEntity = self.WeaponData.TrackedEntity
|
||||
end
|
||||
end
|
||||
|
||||
if (CLIENT) then
|
||||
self.m_SpawnPos = self:GetPos()
|
||||
self:EmitSound("^viper/shared/move_rpapa7_proj_flame_cls.wav", SNDLVL_180db, 100, 1, CHAN_WEAPON)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user