add sborka
This commit is contained in:
173
garrysmod/addons/tacrp/lua/entities/tacrp_ammo.lua
Normal file
173
garrysmod/addons/tacrp/lua/entities/tacrp_ammo.lua
Normal file
@@ -0,0 +1,173 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Ammo Pickup"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/ammoboxes/ammo_bag-1.mdl"
|
||||
ENT.ModelOptions = nil
|
||||
|
||||
ENT.InfiniteUse = false
|
||||
ENT.OpeningAnim = false
|
||||
ENT.NextUse = 0
|
||||
ENT.Open = false
|
||||
ENT.MaxHealth = 0
|
||||
|
||||
function ENT:Initialize()
|
||||
local model = self.Model
|
||||
|
||||
if self.ModelOptions then
|
||||
model = table.Random(self.ModelOptions)
|
||||
end
|
||||
|
||||
self:SetModel(model)
|
||||
|
||||
if SERVER then
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(CONTINUOUS_USE)
|
||||
self:PhysWake()
|
||||
|
||||
if self.MaxHealth > 0 then
|
||||
self:SetMaxHealth(self.MaxHealth)
|
||||
self:SetHealth(self.MaxHealth)
|
||||
end
|
||||
|
||||
self:SetTrigger(true) -- Enables Touch() to be called even when not colliding
|
||||
self:UseTriggerBounds(true, 24)
|
||||
end
|
||||
end
|
||||
|
||||
local function ClampedGiveAmmo(ply, ammo, amt, clamp)
|
||||
local count = ply:GetAmmoCount(ammo)
|
||||
|
||||
if count >= clamp then
|
||||
return false
|
||||
elseif count + amt > clamp then
|
||||
amt = math.max(clamp - count, 0)
|
||||
end
|
||||
|
||||
ply:GiveAmmo(amt, ammo)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:ApplyAmmo(ply)
|
||||
if self.NextUse > CurTime() then return end
|
||||
|
||||
local wpn = ply:GetActiveWeapon()
|
||||
|
||||
local ammotype = wpn:GetPrimaryAmmoType()
|
||||
local clipsize = wpn:GetMaxClip1()
|
||||
local supplyamount = clipsize * 1
|
||||
local max = clipsize * 6
|
||||
|
||||
local t2
|
||||
|
||||
if wpn.ArcticTacRP then
|
||||
ammotype = wpn:GetAmmoType()
|
||||
clipsize = wpn.ClipSize
|
||||
max = (wpn:GetValue("SupplyAmmoAmount") or (clipsize * 6)) * (wpn:GetValue("SupplyLimit") or 1)
|
||||
|
||||
if max <= 0 then
|
||||
max = 1
|
||||
end
|
||||
|
||||
if TacRP.ConVars["resupply_grenades"]:GetBool() then
|
||||
local nade = wpn:GetGrenade()
|
||||
|
||||
if nade.Ammo then
|
||||
if !nade.AdminOnly or ply:IsAdmin() then
|
||||
t2 = ClampedGiveAmmo(ply, nade.Ammo, 1, 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local t = ClampedGiveAmmo(ply, ammotype, supplyamount, max)
|
||||
|
||||
if t or t2 then
|
||||
if self.OpeningAnim and !self.Open then
|
||||
local seq = self:LookupSequence("open")
|
||||
self:ResetSequence(seq)
|
||||
self:EmitSound("items/ammocrate_open.wav")
|
||||
|
||||
self.Open = true
|
||||
end
|
||||
|
||||
self.NextUse = CurTime() + 1
|
||||
|
||||
if !self.InfiniteUse then
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/cardboard/cardboard_box_impact_hard1.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard2.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard3.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard4.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard5.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard6.wav",
|
||||
"physics/cardboard/cardboard_box_impact_hard7.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/cardboard/cardboard_box_impact_soft1.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft2.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft3.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft4.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft5.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft6.wav",
|
||||
"physics/cardboard/cardboard_box_impact_soft7.wav",
|
||||
}
|
||||
|
||||
function ENT:PhysicsCollide(data)
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
|
||||
if data.Speed > 25 then
|
||||
self:EmitSound(self.CollisionSoundsHard[math.random(#self.CollisionSoundsHard)])
|
||||
else
|
||||
self:EmitSound(self.CollisionSoundsSoft[math.random(#self.CollisionSoundsSoft)])
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !ply:IsPlayer() then return end
|
||||
self:ApplyAmmo(ply)
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if self.Open and (self.NextUse + 0.1) < CurTime() then
|
||||
local seq = self:LookupSequence("close")
|
||||
self:ResetSequence(seq)
|
||||
self:EmitSound("items/ammocrate_close.wav")
|
||||
|
||||
self.Open = false
|
||||
end
|
||||
|
||||
self:NextThink(CurTime())
|
||||
return true
|
||||
end
|
||||
|
||||
elseif CLIENT then
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
end
|
||||
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_c4.lua
Normal file
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_c4.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "C4 Charge (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/c4_charge-1.mdl"
|
||||
|
||||
ENT.Ammo = "ti_c4"
|
||||
ENT.GrenadeProxy = "tacrp_c4_detonator"
|
||||
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_charge.lua
Normal file
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_charge.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Door Charge (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/door_charge-1.mdl"
|
||||
|
||||
ENT.Ammo = "ti_charge"
|
||||
ENT.GrenadeProxy = "tacrp_nade_charge"
|
||||
28
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_crate.lua
Normal file
28
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_crate.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Ammo Crate"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/ammoboxes/ammo_box-2b.mdl"
|
||||
|
||||
ENT.InfiniteUse = true
|
||||
ENT.OpeningAnim = true
|
||||
|
||||
ENT.AutomaticFrameAdvance = true
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/metal_box_impact_soft1.wav",
|
||||
"physics/metal/metal_box_impact_soft2.wav",
|
||||
"physics/metal/metal_box_impact_soft3.wav",
|
||||
}
|
||||
286
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_crate_ttt.lua
Normal file
286
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_crate_ttt.lua
Normal file
@@ -0,0 +1,286 @@
|
||||
if engine.ActiveGamemode() ~= "terrortown" then return end
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_BOTH
|
||||
|
||||
ENT.PrintName = "tacrp_ammocrate_name"
|
||||
|
||||
ENT.Model = "models/weapons/tacint/ammoboxes/ammo_box-2b.mdl"
|
||||
ENT.CanHavePrints = true
|
||||
ENT.CanUseKey = true
|
||||
ENT.MaxHealth = 250
|
||||
|
||||
ENT.MaxStored = 100
|
||||
ENT.RechargeRate = 1
|
||||
ENT.RechargeFreq = 2
|
||||
|
||||
ENT.AutomaticFrameAdvance = true
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/metal_box_impact_soft1.wav",
|
||||
"physics/metal/metal_box_impact_soft2.wav",
|
||||
"physics/metal/metal_box_impact_soft3.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.AmmoInfo = {
|
||||
-- ammo per use, max, cost per use
|
||||
["357"] = {10, nil, 12}, -- 2 to fill
|
||||
["smg1"] = {30, nil, 10}, -- 2 to fill
|
||||
["pistol"] = {20, nil, 5}, -- 3 to fill
|
||||
["alyxgun"] = {12, nil, 6}, -- 3 to fill
|
||||
["buckshot"] = {8, nil, 8}, -- 3 to fill
|
||||
|
||||
["smg1_grenade"] = {1, 3, 34},
|
||||
["rpg_round"] = {1, 2, 50},
|
||||
["ti_sniper"] = {5, 10, 50},
|
||||
}
|
||||
|
||||
if CLIENT then
|
||||
|
||||
ENT.Icon = "entities/tacrp_ammo_crate.png"
|
||||
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_hint", "Press {usekey} to get ammo. Remaining charge: {num}")
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_broken", "Your Ammo Crate has been destroyed!")
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_subtitle", "Press {usekey} to receive ammo.")
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_charge", "Remaining charge: {charge}.")
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_empty", "No charge left")
|
||||
|
||||
LANG.AddToLanguage("english", "tacrp_ammocrate_short_desc", "The ammo crate recharges over time")
|
||||
|
||||
local TryT = LANG.TryTranslation
|
||||
local ParT = LANG.GetParamTranslation
|
||||
|
||||
ENT.TargetIDHint = {
|
||||
name = "tacrp_ammocrate_name",
|
||||
hint = "tacrp_ammocrate_hint",
|
||||
fmt = function(ent, txt)
|
||||
return ParT(txt, {
|
||||
usekey = Key("+use", "USE"),
|
||||
num = ent:GetStoredAmmo() or 0
|
||||
})
|
||||
end
|
||||
}
|
||||
|
||||
local key_params = {
|
||||
usekey = Key("+use", "USE")
|
||||
}
|
||||
|
||||
-- TTT2 does this
|
||||
hook.Add("TTTRenderEntityInfo", "tacrp_ammo_crate", function(tData)
|
||||
local client = LocalPlayer()
|
||||
local ent = tData:GetEntity()
|
||||
|
||||
if not IsValid(client) or not client:IsTerror() or not client:Alive()
|
||||
or not IsValid(ent) or tData:GetEntityDistance() > 100 or ent:GetClass() ~= "tacrp_ammo_crate_ttt" then
|
||||
return
|
||||
end
|
||||
|
||||
-- enable targetID rendering
|
||||
tData:EnableText()
|
||||
tData:EnableOutline()
|
||||
tData:SetOutlineColor(client:GetRoleColor())
|
||||
|
||||
tData:SetTitle(TryT(ent.PrintName))
|
||||
tData:SetSubtitle(ParT("tacrp_ammocrate_subtitle", key_params))
|
||||
tData:SetKeyBinding("+use")
|
||||
|
||||
local charge = ent:GetStoredAmmo() or 0
|
||||
|
||||
tData:AddDescriptionLine(TryT("tacrp_ammocrate_short_desc"))
|
||||
|
||||
tData:AddDescriptionLine(
|
||||
(charge > 0) and ParT("tacrp_ammocrate_charge", {charge = charge}) or TryT("tacrp_ammocrate_empty"),
|
||||
(charge > 0) and roles.DETECTIVE.ltcolor or COLOR_ORANGE
|
||||
)
|
||||
end)
|
||||
end
|
||||
|
||||
AccessorFuncDT(ENT, "StoredAmmo", "StoredAmmo")
|
||||
AccessorFunc(ENT, "Placer", "Placer")
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:DTVar("Int", 0, "StoredAmmo")
|
||||
end
|
||||
|
||||
function ENT:AddToStorage(amount)
|
||||
self:SetStoredAmmo(math.min(self.MaxStored, self:GetStoredAmmo() + amount))
|
||||
end
|
||||
|
||||
function ENT:TakeFromStorage(amount)
|
||||
amount = math.min(amount, self:GetStoredAmmo())
|
||||
self:SetStoredAmmo(math.max(0, self:GetStoredAmmo() - amount))
|
||||
return amount
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel(self.Model)
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(CONTINUOUS_USE)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if IsValid(phys) then
|
||||
phys:SetMass(150)
|
||||
phys:Wake()
|
||||
end
|
||||
|
||||
if self.MaxHealth > 0 then
|
||||
self:SetMaxHealth(self.MaxHealth)
|
||||
self:SetHealth(self.MaxHealth)
|
||||
end
|
||||
|
||||
self:SetStoredAmmo(self.MaxStored)
|
||||
|
||||
self:SetPlacer(nil)
|
||||
|
||||
self.fingerprints = {}
|
||||
end
|
||||
end
|
||||
|
||||
local function ClampedGiveAmmo(ply, ammo, amt, clamp)
|
||||
local count = ply:GetAmmoCount(ammo)
|
||||
|
||||
if count >= clamp then
|
||||
return 0
|
||||
elseif count + amt > clamp then
|
||||
amt = math.max(clamp - count, 0)
|
||||
end
|
||||
|
||||
return amt
|
||||
end
|
||||
|
||||
function ENT:ApplyAmmo(ply)
|
||||
if (self.NextUse or 0) > CurTime() then return end
|
||||
|
||||
local wpn = ply:GetActiveWeapon()
|
||||
|
||||
local ammotype = string.lower(game.GetAmmoName(wpn:GetPrimaryAmmoType()) or "")
|
||||
if !self.AmmoInfo[ammotype] then return end
|
||||
|
||||
local max = self.AmmoInfo[ammotype][2] or wpn.Primary.ClipMax
|
||||
local amt = self.AmmoInfo[ammotype][1]
|
||||
amt = ClampedGiveAmmo(ply, ammotype, amt, max) -- amount we need
|
||||
local cost = self.AmmoInfo[ammotype][3] * (amt / self.AmmoInfo[ammotype][1])
|
||||
local f = math.min(cost, self:GetStoredAmmo()) / cost -- fraction of cost we can afford
|
||||
|
||||
amt = math.floor(amt * f)
|
||||
|
||||
if amt > 0 then
|
||||
self:TakeFromStorage(cost * f)
|
||||
ply:GiveAmmo(amt, ammotype)
|
||||
|
||||
if !self.Open then
|
||||
local seq = self:LookupSequence("open")
|
||||
self:ResetSequence(seq)
|
||||
self:EmitSound("items/ammocrate_open.wav")
|
||||
|
||||
self.Open = true
|
||||
end
|
||||
|
||||
self.NextUse = CurTime() + 1
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(data)
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
|
||||
if data.Speed > 25 then
|
||||
self:EmitSound(self.CollisionSoundsHard[math.random(#self.CollisionSoundsHard)])
|
||||
else
|
||||
self:EmitSound(self.CollisionSoundsSoft[math.random(#self.CollisionSoundsSoft)])
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !ply:IsPlayer() then return end
|
||||
self:ApplyAmmo(ply)
|
||||
end
|
||||
function ENT:Think()
|
||||
if self.Open and (self.NextUse + 0.1) < CurTime() then
|
||||
local seq = self:LookupSequence("close")
|
||||
self:ResetSequence(seq)
|
||||
self:EmitSound("items/ammocrate_close.wav")
|
||||
|
||||
self.Open = false
|
||||
end
|
||||
|
||||
if (self.NextCharge or 0) < CurTime() then
|
||||
self:AddToStorage(self.RechargeRate)
|
||||
self.NextCharge = CurTime() + self.RechargeFreq
|
||||
end
|
||||
|
||||
self:NextThink(CurTime())
|
||||
return true
|
||||
end
|
||||
|
||||
elseif CLIENT then
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmginfo)
|
||||
if self.BOOM then return end
|
||||
|
||||
self:TakePhysicsDamage(dmginfo)
|
||||
self:SetHealth(self:Health() - dmginfo:GetDamage())
|
||||
local att = dmginfo:GetAttacker()
|
||||
local placer = self:GetPlacer()
|
||||
|
||||
if IsPlayer(att) then
|
||||
DamageLog(Format("DMG: \t %s [%s] damaged ammo crate [%s] for %d dmg", att:Nick(), att:GetRoleString(), IsPlayer(placer) and placer:Nick() or "<disconnected>", dmginfo:GetDamage()))
|
||||
end
|
||||
|
||||
if self:Health() < 0 then
|
||||
self:Remove()
|
||||
util.EquipmentDestroyed(self:GetPos())
|
||||
|
||||
if IsValid(self:GetPlacer()) then
|
||||
LANG.Msg(self:GetPlacer(), "tacrp_ammocrate_broken")
|
||||
end
|
||||
|
||||
self.BOOM = true
|
||||
|
||||
local dmg = self:GetStoredAmmo() * 2.25 + 75
|
||||
|
||||
util.BlastDamage(self, dmginfo:GetAttacker(), self:GetPos(), 400, dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125, 90)
|
||||
end
|
||||
end
|
||||
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_fire.lua
Normal file
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_fire.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Thermite Grenade (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Ammo = "ti_thermite"
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/thermite-1"
|
||||
ENT.GrenadeProxy = "tacrp_nade_thermite"
|
||||
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_flashbang.lua
Normal file
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_flashbang.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Flashbang (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/flashbang.mdl"
|
||||
|
||||
ENT.Ammo = "ti_flashbang"
|
||||
ENT.GrenadeProxy = "tacrp_nade_flashbang"
|
||||
85
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_frag.lua
Normal file
85
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_frag.lua
Normal file
@@ -0,0 +1,85 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Frag Grenade (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/frag.mdl"
|
||||
|
||||
ENT.Ammo = "grenade"
|
||||
ENT.GrenadeProxy = "tacrp_nade_frag"
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel(self.Model)
|
||||
|
||||
if SERVER then
|
||||
self:SetMaterial(self.Material or "")
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(CONTINUOUS_USE)
|
||||
self:PhysWake()
|
||||
|
||||
self:SetTrigger(true) -- Enables Touch() to be called even when not colliding
|
||||
self:UseTriggerBounds(true, 24)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:ApplyAmmo(ply)
|
||||
if self.Used then return end
|
||||
|
||||
self.Used = true
|
||||
ply:GiveAmmo(1, self.Ammo)
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/weapon_impact_hard1.wav",
|
||||
"physics/metal/weapon_impact_hard2.wav",
|
||||
"physics/metal/weapon_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/weapon_impact_soft1.wav",
|
||||
"physics/metal/weapon_impact_soft2.wav",
|
||||
"physics/metal/weapon_impact_soft3.wav",
|
||||
}
|
||||
|
||||
function ENT:PhysicsCollide(data)
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
|
||||
if data.Speed > 25 then
|
||||
self:EmitSound(self.CollisionSoundsHard[math.random(#self.CollisionSoundsHard)])
|
||||
else
|
||||
self:EmitSound(self.CollisionSoundsSoft[math.random(#self.CollisionSoundsSoft)])
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !ply:IsPlayer() then return end
|
||||
self:ApplyAmmo(ply)
|
||||
if self.GrenadeProxy then
|
||||
ply:Give(self.GrenadeProxy, true)
|
||||
end
|
||||
end
|
||||
|
||||
elseif CLIENT then
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
|
||||
end
|
||||
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_gas.lua
Normal file
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_gas.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "CS Gas Grenade (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Ammo = "ti_gas"
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/gas-1"
|
||||
ENT.GrenadeProxy = "tacrp_nade_gas"
|
||||
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_heal.lua
Normal file
16
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_heal.lua
Normal file
@@ -0,0 +1,16 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Medi-Smoke Canister (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Ammo = "ti_heal"
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/heal-1"
|
||||
ENT.GrenadeProxy = "tacrp_nade_heal"
|
||||
28
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_nuke.lua
Normal file
28
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_nuke.lua
Normal file
@@ -0,0 +1,28 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Nuclear Device (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = true
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/props_misc/briefcase_bomb-1.mdl"
|
||||
|
||||
ENT.Ammo = "ti_nuke"
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/metal_box_impact_soft1.wav",
|
||||
"physics/metal/metal_box_impact_soft2.wav",
|
||||
"physics/metal/metal_box_impact_soft3.wav",
|
||||
}
|
||||
|
||||
ENT.GrenadeProxy = false
|
||||
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_smoke.lua
Normal file
15
garrysmod/addons/tacrp/lua/entities/tacrp_ammo_smoke.lua
Normal file
@@ -0,0 +1,15 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_ammo_frag"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Smoke Grenade (Ammo)"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.AdminOnly = false
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Ammo = "ti_smoke"
|
||||
ENT.GrenadeProxy = "tacrp_nade_smoke"
|
||||
167
garrysmod/addons/tacrp/lua/entities/tacrp_att.lua
Normal file
167
garrysmod/addons/tacrp/lua/entities/tacrp_att.lua
Normal file
@@ -0,0 +1,167 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Attachment"
|
||||
ENT.Category = "Tactical Intervention - Attachments"
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.Model = "models/tacint/props_containers/supply_case-2.mdl"
|
||||
ENT.AttToGive = nil
|
||||
|
||||
function ENT:Initialize()
|
||||
local model = self.Model
|
||||
|
||||
self:SetModel(model)
|
||||
|
||||
if SERVER then
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:PhysWake()
|
||||
|
||||
self:SetTrigger(true) -- Enables Touch() to be called even when not colliding
|
||||
self:UseTriggerBounds(true, 24)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:GiveAtt(ply)
|
||||
if !self.AttToGive then return end
|
||||
|
||||
if TacRP.ConVars["free_atts"]:GetBool() then
|
||||
ply:PrintMessage(HUD_PRINTTALK, "All attachments are free! This is not necessary!")
|
||||
return
|
||||
end
|
||||
|
||||
if TacRP.ConVars["lock_atts"]:GetBool() and TacRP:PlayerGetAtts(ply, self.AttToGive) > 0 then
|
||||
ply:PrintMessage(HUD_PRINTTALK, "You already have this attachment!")
|
||||
return
|
||||
end
|
||||
|
||||
local given = TacRP:PlayerGiveAtt(ply, self.AttToGive, 1)
|
||||
if given then
|
||||
TacRP:PlayerSendAttInv(ply)
|
||||
self:EmitSound("TacRP/weapons/flashlight_on.wav")
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
ENT.CollisionSoundsHard = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
|
||||
ENT.CollisionSoundsSoft = {
|
||||
"physics/metal/metal_box_impact_soft1.wav",
|
||||
"physics/metal/metal_box_impact_soft2.wav",
|
||||
"physics/metal/metal_box_impact_soft3.wav",
|
||||
}
|
||||
|
||||
function ENT:PhysicsCollide(data)
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
|
||||
if data.Speed > 40 then
|
||||
self:EmitSound(self.CollisionSoundsHard[math.random(#self.CollisionSoundsHard)], 70, 100, data.Speed / 100)
|
||||
else
|
||||
self:EmitSound(self.CollisionSoundsSoft[math.random(#self.CollisionSoundsSoft)], 70, 100, data.Speed / 100)
|
||||
end
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !ply:IsPlayer() then return end
|
||||
self:GiveAtt(ply)
|
||||
end
|
||||
|
||||
elseif CLIENT then
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
local font = "TacRP_Myriad_Pro_48_Unscaled"
|
||||
local iw2 = 128
|
||||
|
||||
local drawit = function(self, p, a, alpha)
|
||||
cam.Start3D2D(p, a, 0.05)
|
||||
-- surface.SetFont("TacRP_LondonBetween_24_Unscaled")
|
||||
|
||||
if !self.PrintLines then
|
||||
self.PrintLines = TacRP.MultiLineText(TacRP:GetAttName(self.AttToGive), 328, font)
|
||||
end
|
||||
for j, text in ipairs(self.PrintLines or {}) do
|
||||
draw.SimpleTextOutlined(text, font, 0, -40 + j * 40, Color(255, 255, 255, alpha * 255), TEXT_ALIGN_CENTER, TEXT_ALIGN_TOP, 2, Color(0, 0, 0, alpha * 75))
|
||||
end
|
||||
|
||||
-- local w2 = surface.GetTextSize(self.PrintName)
|
||||
|
||||
-- surface.SetTextPos(-w2 / 2, 0)
|
||||
-- surface.SetTextColor(255, 255, 255, 255)
|
||||
-- surface.DrawText(self.PrintName)
|
||||
|
||||
surface.SetDrawColor(255, 255, 255, alpha * 255)
|
||||
surface.SetMaterial(self.Icon or defaulticon)
|
||||
surface.DrawTexturedRect(-iw2 / 2, -iw2 - 8, iw2, iw2)
|
||||
cam.End3D2D()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
local distsqr = (EyePos() - self:WorldSpaceCenter()):LengthSqr()
|
||||
if distsqr <= 262144 then -- 512^2
|
||||
local a = math.Clamp(1 - (distsqr - 196608) / 65536, 0, 1)
|
||||
local ang = self:GetAngles()
|
||||
|
||||
ang:RotateAroundAxis(ang:Forward(), 180)
|
||||
ang:RotateAroundAxis(ang:Right(), 90)
|
||||
ang:RotateAroundAxis(ang:Up(), 90)
|
||||
|
||||
local pos = self:GetPos()
|
||||
|
||||
pos = pos + ang:Forward() * 0
|
||||
pos = pos + ang:Up() * 4.1
|
||||
pos = pos + ang:Right() * -8
|
||||
|
||||
drawit(self, pos, ang, a)
|
||||
|
||||
-- cam.Start3D2D(pos, ang, 0.1)
|
||||
-- surface.SetFont("TacRP_LondonBetween_24_Unscaled")
|
||||
|
||||
-- local w = surface.GetTextSize(self.PrintName)
|
||||
|
||||
-- surface.SetTextPos(-w / 2, 0)
|
||||
-- surface.SetTextColor(255, 255, 255, 255)
|
||||
-- surface.DrawText(self.PrintName)
|
||||
|
||||
-- surface.SetDrawColor(255, 255, 255)
|
||||
-- surface.SetMaterial(self.Icon or defaulticon)
|
||||
-- local iw = 64
|
||||
-- surface.DrawTexturedRect(-iw / 2, -iw - 8, iw, iw)
|
||||
-- cam.End3D2D()
|
||||
|
||||
local ang2 = self:GetAngles()
|
||||
|
||||
ang2:RotateAroundAxis(ang2:Forward(), 90)
|
||||
ang2:RotateAroundAxis(ang2:Right(), -90)
|
||||
ang2:RotateAroundAxis(ang2:Up(), 0)
|
||||
|
||||
local pos2 = self:GetPos()
|
||||
|
||||
pos2 = pos2 + ang2:Forward() * 0
|
||||
pos2 = pos2 + ang2:Up() * 4.1
|
||||
pos2 = pos2 + ang2:Right() * -8
|
||||
|
||||
drawit(self, pos2, ang2, a)
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
68
garrysmod/addons/tacrp/lua/entities/tacrp_bench.lua
Normal file
68
garrysmod/addons/tacrp/lua/entities/tacrp_bench.lua
Normal file
@@ -0,0 +1,68 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.RenderGroup = RENDERGROUP_BOTH
|
||||
|
||||
ENT.PrintName = "Customization Bench"
|
||||
ENT.Category = "Tactical RP"
|
||||
|
||||
ENT.Spawnable = true
|
||||
ENT.Model = "models/props_canal/winch02.mdl"
|
||||
|
||||
function ENT:Initialize()
|
||||
local model = self.Model
|
||||
|
||||
self:SetModel(model)
|
||||
|
||||
if SERVER then
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
self:PhysWake()
|
||||
end
|
||||
|
||||
-- removal is handled when checking position
|
||||
table.insert(TacRP.Benches, self)
|
||||
end
|
||||
|
||||
local font = "TacRP_Myriad_Pro_24_Unscaled"
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
|
||||
local distsqr = (EyePos() - self:WorldSpaceCenter()):LengthSqr()
|
||||
if distsqr <= 262144 then -- 512^2
|
||||
local a = 1 --math.Clamp(1 - (distsqr - 196608) / 65536, 0, 1)
|
||||
local ang = self:GetAngles()
|
||||
|
||||
ang:RotateAroundAxis(ang:Forward(), 180)
|
||||
ang:RotateAroundAxis(ang:Right(), 90)
|
||||
ang:RotateAroundAxis(ang:Up(), 90)
|
||||
|
||||
local pos = self:GetPos()
|
||||
|
||||
pos = pos + ang:Forward() * 2.75
|
||||
pos = pos + ang:Up() * 9
|
||||
pos = pos + ang:Right() * -33
|
||||
|
||||
cam.Start3D2D(pos, ang, 0.075)
|
||||
surface.SetFont(font)
|
||||
local w = surface.GetTextSize(self.PrintName)
|
||||
surface.SetTextPos(-w / 2, 0)
|
||||
surface.SetTextColor(255, 255, 255)
|
||||
surface.DrawText(self.PrintName)
|
||||
if distsqr <= 16384 then
|
||||
local t2 = "READY"
|
||||
local w2 = surface.GetTextSize(t2)
|
||||
surface.SetTextPos(-w2 / 2, 30)
|
||||
surface.SetTextColor(100, 255, 100)
|
||||
surface.DrawText(t2)
|
||||
end
|
||||
cam.End3D2D()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
143
garrysmod/addons/tacrp/lua/entities/tacrp_droppedmag.lua
Normal file
143
garrysmod/addons/tacrp/lua/entities/tacrp_droppedmag.lua
Normal file
@@ -0,0 +1,143 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Dropped Magazine"
|
||||
ENT.Category = ""
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.Model = ""
|
||||
ENT.FadeTime = 5
|
||||
ENT.CanHavePrints = true -- TTT
|
||||
|
||||
ENT.ImpactSounds = {
|
||||
["pistol"] = {
|
||||
"TacRP/weapons/drop_magazine_pistol-1.wav",
|
||||
"TacRP/weapons/drop_magazine_pistol-2.wav",
|
||||
"TacRP/weapons/drop_magazine_pistol-3.wav",
|
||||
"TacRP/weapons/drop_magazine_pistol-4.wav",
|
||||
"TacRP/weapons/drop_magazine_pistol-5.wav",
|
||||
},
|
||||
["metal"] = {
|
||||
"TacRP/weapons/drop_magazine_metal-1.wav",
|
||||
"TacRP/weapons/drop_magazine_metal-2.wav",
|
||||
"TacRP/weapons/drop_magazine_metal-3.wav",
|
||||
"TacRP/weapons/drop_magazine_metal-4.wav",
|
||||
},
|
||||
["plastic"] = {
|
||||
"TacRP/weapons/drop_magazine_plastic-1.wav",
|
||||
"TacRP/weapons/drop_magazine_plastic-2.wav"
|
||||
},
|
||||
["bullet"] = {
|
||||
"player/pl_shell1.wav",
|
||||
"player/pl_shell2.wav",
|
||||
"player/pl_shell3.wav"
|
||||
},
|
||||
["shotgun"] = {
|
||||
"weapons/fx/tink/shotgun_shell1.wav",
|
||||
"weapons/fx/tink/shotgun_shell2.wav",
|
||||
"weapons/fx/tink/shotgun_shell3.wav",
|
||||
},
|
||||
["spoon"] = {
|
||||
"TacRP/weapons/grenade/spoon_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/spoon_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/spoon_bounce-3.wav",
|
||||
}
|
||||
}
|
||||
|
||||
ENT.ImpactType = "pistol"
|
||||
|
||||
ENT.AmmoType = nil
|
||||
ENT.AmmoCount = nil
|
||||
|
||||
function ENT:Initialize()
|
||||
self:SetModel(self.Model)
|
||||
|
||||
if SERVER then
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
|
||||
self:PhysWake()
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:PhysicsInitBox(Vector(-1, -1, -1), Vector(1, 1, 1))
|
||||
end
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
if engine.ActiveGamemode() == "terrortown" and TacRP.ConVars["ttt_magazine_dna"]:GetBool() then
|
||||
self.FadeTime = 600
|
||||
if SERVER then
|
||||
self.fingerprints = {}
|
||||
table.insert(self.fingerprints, self:GetOwner())
|
||||
end
|
||||
end
|
||||
|
||||
if self.AmmoType and self.AmmoCount then
|
||||
self.FadeTime = math.max(self.FadeTime, 120)
|
||||
self:SetOwner(NULL) -- Owner can't +USE their own entities
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(colData, collider)
|
||||
if colData.DeltaTime < 0.5 then return end
|
||||
|
||||
local tbl = self.ImpactSounds[self.ImpactType]
|
||||
|
||||
local snd = ""
|
||||
|
||||
if tbl then
|
||||
snd = table.Random(tbl)
|
||||
end
|
||||
|
||||
self:EmitSound(snd)
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if SERVER and (self.SpawnTime + self.FadeTime) <= CurTime() then
|
||||
|
||||
self:SetRenderFX( kRenderFxFadeFast )
|
||||
|
||||
if (self.SpawnTime + self.FadeTime + 1) <= CurTime() then
|
||||
|
||||
if IsValid(self:GetPhysicsObject()) then
|
||||
self:GetPhysicsObject():EnableMotion(false)
|
||||
end
|
||||
|
||||
if SERVER then
|
||||
if (self.SpawnTime + self.FadeTime + 1.5) <= CurTime() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Use(ply)
|
||||
if self.AmmoType and (self.AmmoCount or 0) > 0 and (self.SpawnTime + 0.5 <= CurTime()) then
|
||||
local given = ply:GiveAmmo(self.AmmoCount, self.AmmoType)
|
||||
self.AmmoCount = self.AmmoCount - given
|
||||
if self.AmmoCount <= 0 then
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
end
|
||||
309
garrysmod/addons/tacrp/lua/entities/tacrp_fire_cloud.lua
Normal file
309
garrysmod/addons/tacrp/lua/entities/tacrp_fire_cloud.lua
Normal file
@@ -0,0 +1,309 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Fire Particle"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
ENT.FireTime = 8
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.Ticks = 0
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
if SERVER then
|
||||
self:SetModel( self.Model )
|
||||
self:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
self:SetSolid( SOLID_VPHYSICS )
|
||||
local maxs = Vector(1, 1, 1)
|
||||
local mins = -maxs
|
||||
self:PhysicsInitBox(mins, maxs)
|
||||
self:DrawShadow( false )
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if phys:IsValid() then
|
||||
phys:Wake()
|
||||
phys:SetBuoyancyRatio(0)
|
||||
end
|
||||
|
||||
self:Detonate()
|
||||
|
||||
-- self.FireTime = self.FireTime * math.Rand(0.8, 1.2)
|
||||
-- self:SetNWFloat("FireTime", CurTime() + self.FireTime)
|
||||
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if CLIENT then
|
||||
local d = Lerp((self.SpawnTime + self.FireTime - CurTime()) / 8, 1, 0.000001) ^ 2
|
||||
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex())
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 135
|
||||
self.Light.b = 0
|
||||
self.Light.Brightness = 5
|
||||
self.Light.Size = math.Clamp(TacRP.ConVars["thermite_radius"]:GetFloat(), 128, 512) * 1.5
|
||||
self.Light.DieTime = CurTime() + self.FireTime
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
if !self:IsValid() or self:WaterLevel() > 2 then return end
|
||||
if !IsValid(emitter) then return end
|
||||
|
||||
if self.Ticks % math.ceil(2 + d * 8) == 0 then
|
||||
local fire = emitter:Add("particles/smokey", self:GetPos() + Vector(math.Rand(-32, 32), math.Rand(-32, 32), 0))
|
||||
fire:SetVelocity( (VectorRand() * 500) + (self:GetAngles():Up() * 300) )
|
||||
fire:SetGravity( Vector(0, 0, 1500) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 100 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 10 )
|
||||
fire:SetEndSize( 150 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 250 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.75)
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 135, 0)
|
||||
local col2 = Color(255, 255, 255)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
if self.Ticks % math.ceil(1 + d * 6) == 0 then
|
||||
local fire = emitter:Add("effects/spark", self:GetPos() + Vector(math.Rand(-32, 32), math.Rand(-32, 32), 0))
|
||||
fire:SetVelocity( VectorRand() * 750 )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 5 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
end
|
||||
|
||||
self.NextFlareTime = self.NextFlareTime or CurTime()
|
||||
|
||||
if self.NextFlareTime <= CurTime() then
|
||||
self.NextFlareTime = CurTime() + math.Rand(0.1, 0.5)
|
||||
local fire = emitter:Add("sprites/orangeflare1", self:GetPos())
|
||||
fire:SetVelocity( VectorRand() * 750 )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(1, 2) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 50 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local aemitter = ParticleEmitter(pa:GetPos())
|
||||
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
|
||||
if !IsValid(aemitter) then return end
|
||||
|
||||
if pa.Ticks % 5 == 0 then
|
||||
local afire = aemitter:Add("particles/smokey", pa:GetPos())
|
||||
afire:SetVelocity( VectorRand() * 5 )
|
||||
afire:SetGravity( Vector(0, 0, 1500) )
|
||||
afire:SetDieTime( math.Rand(0.25, 0.5) * d )
|
||||
afire:SetStartAlpha( 255 )
|
||||
afire:SetEndAlpha( 0 )
|
||||
afire:SetStartSize( 5 * d )
|
||||
afire:SetEndSize( 20 )
|
||||
afire:SetRoll( math.Rand(-180, 180) )
|
||||
afire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
afire:SetColor( 255, 255, 255 )
|
||||
afire:SetAirResistance( 150 )
|
||||
afire:SetPos( pa:GetPos() )
|
||||
afire:SetLighting( false )
|
||||
afire:SetCollide(true)
|
||||
afire:SetBounce(0.9)
|
||||
afire:SetNextThink( CurTime() + FrameTime() )
|
||||
afire:SetThinkFunction( function(apa)
|
||||
if !apa then return end
|
||||
local col1 = Color(255, 135, 0)
|
||||
local col2 = Color(255, 255, 255)
|
||||
|
||||
local col3 = col1
|
||||
local d2 = apa:GetLifeTime() / apa:GetDieTime()
|
||||
col3.r = Lerp(d2, col1.r, col2.r)
|
||||
col3.g = Lerp(d2, col1.g, col2.g)
|
||||
col3.b = Lerp(d2, col1.b, col2.b)
|
||||
|
||||
apa:SetColor(col3.r, col3.g, col3.b)
|
||||
apa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
aemitter:Finish()
|
||||
|
||||
pa.Ticks = pa.Ticks + 1
|
||||
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.Ticks = self.Ticks + 1
|
||||
else
|
||||
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
if self:GetVelocity():LengthSqr() <= 32 then
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
end
|
||||
|
||||
if self.NextDamageTick > CurTime() then return end
|
||||
|
||||
if self:WaterLevel() > 2 then self:Remove() return end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(Lerp((self.SpawnTime + self.FireTime - CurTime()) / self.FireTime, TacRP.ConVars["thermite_damage_max"]:GetFloat(), TacRP.ConVars["thermite_damage_min"]:GetFloat()))
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
util.BlastDamageInfo(dmg, IsValid(self:GetParent()) and self:GetParent():GetPos() or self:GetPos(), TacRP.ConVars["thermite_radius"]:GetFloat())
|
||||
|
||||
if self.SpawnTime + self.FireTime <= CurTime() then self:Remove() return end
|
||||
|
||||
self.NextDamageTick = CurTime() + 0.2
|
||||
self:NextThink(self.NextDamageTick)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.dietime = CurTime() + 0.5
|
||||
self.Light.decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
if !self:IsValid() then return end
|
||||
|
||||
self.Armed = true
|
||||
|
||||
if self.Order and self.Order != 1 then return end
|
||||
|
||||
-- self.FireSound = CreateSound(self, "tacrp_extras/grenades/fire_loop_1.wav")
|
||||
self.FireSound = CreateSound(self, "ambient/gas/steam2.wav")
|
||||
self.FireSound:Play()
|
||||
self.FireSound:ChangePitch(120)
|
||||
|
||||
self.FireSound:ChangePitch(100, self.FireTime)
|
||||
|
||||
timer.Simple(self.FireTime - 1, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self.FireSound:ChangeVolume(0, 1)
|
||||
end)
|
||||
|
||||
timer.Simple(self.FireTime, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
-- cam.Start3D() -- Start the 3D function so we can draw onto the screen.
|
||||
-- render.SetMaterial( GetFireParticle() ) -- Tell render what material we want, in this case the flash from the gravgun
|
||||
-- render.DrawSprite( self:GetPos(), math.random(200, 250), math.random(200, 250), Color(255, 255, 255) ) -- Draw the sprite in the middle of the map, at 16x16 in it's original colour with full alpha.
|
||||
-- cam.End3D()
|
||||
end
|
||||
|
||||
local directfiredamage = {
|
||||
["npc_zombie"] = true,
|
||||
["npc_zombie_torso"] = true,
|
||||
["npc_fastzombie"] = true,
|
||||
["npc_fastzombie_torso"] = true,
|
||||
["npc_poisonzombie"] = true,
|
||||
["npc_zombine"] = true,
|
||||
["npc_headcrab"] = true,
|
||||
["npc_headcrab_fast"] = true,
|
||||
["npc_headcrab_black"] = true,
|
||||
["npc_headcrab_poison"] = true,
|
||||
}
|
||||
|
||||
hook.Add("EntityTakeDamage", "tacrp_fire_cloud", function(ent, dmginfo)
|
||||
if IsValid(dmginfo:GetInflictor()) and dmginfo:GetInflictor():GetClass() == "tacrp_fire_cloud" and dmginfo:GetDamageType() == DMG_BURN then
|
||||
if ent:IsNPC() then
|
||||
if directfiredamage[ent:GetClass()] then
|
||||
dmginfo:SetDamageType(DMG_SLOWBURN) -- DMG_BURN does not hurt HL2 zombies and instead turns them black.
|
||||
elseif ent.Immune_Fire then
|
||||
dmginfo:SetDamageType(DMG_DIRECT) -- Bitch
|
||||
end
|
||||
elseif !ent:IsNextBot() and !ent:IsPlayer() then
|
||||
if ent:GetClass() == "prop_physics" then
|
||||
dmginfo:SetDamageType(DMG_DIRECT) -- some props like to burn slowly against DMG_BURN or DMG_SLOWBURN. don't.
|
||||
elseif ent:GetClass() == "tacrp_proj_nade_thermite" then
|
||||
return true -- don't burn other thermite grenades
|
||||
end
|
||||
dmginfo:ScaleDamage(2) -- tremendous damage to props
|
||||
end
|
||||
dmginfo:SetDamageForce(Vector()) -- fire does not push things around. still applies to players, but that can't be helped.
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "tacrp_fire_cloud", function(ent, dmginfo, took)
|
||||
if took and IsValid(dmginfo:GetInflictor()) and dmginfo:GetInflictor():GetClass() == "tacrp_fire_cloud" and !ent:IsPlayer() then
|
||||
ent:Ignite(math.Rand(3, 5))
|
||||
end
|
||||
end)
|
||||
219
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud.lua
Normal file
219
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud.lua
Normal file
@@ -0,0 +1,219 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Flare Particle"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
ENT.FireTime = 15
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.Ticks = 0
|
||||
|
||||
ENT.FlareLength = 1
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
if SERVER then
|
||||
self:SetModel( self.Model )
|
||||
self:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
self:SetSolid( SOLID_VPHYSICS )
|
||||
local maxs = Vector(2, 1, 1)
|
||||
local mins = -maxs
|
||||
self:PhysicsInitBox(mins, maxs)
|
||||
self:DrawShadow( false )
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if phys:IsValid() then
|
||||
phys:Wake()
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:SetDragCoefficient(5)
|
||||
end
|
||||
|
||||
self:Detonate()
|
||||
|
||||
-- self.FireTime = self.FireTime * math.Rand(0.8, 1.2)
|
||||
-- self:SetNWFloat("FireTime", CurTime() + self.FireTime)
|
||||
else
|
||||
local tr = util.TraceHull({
|
||||
start = self:GetPos() + Vector(0, 0, 12),
|
||||
endpos = self:GetPos() + Vector(0, 0, 1024),
|
||||
mask = MASK_SOLID_BRUSHONLY,
|
||||
mins = Vector(-4, -4, -4),
|
||||
maxs = Vector(4, 4, 4),
|
||||
})
|
||||
self.FlareLength = math.Clamp(tr.Fraction ^ 2, 0.2, 1)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if CLIENT then
|
||||
local d = Lerp((self.SpawnTime + self.FireTime - CurTime()) / 12, 1, 0.000001) ^ 2
|
||||
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex())
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 75
|
||||
self.Light.b = 60
|
||||
self.Light.Brightness = 1.5
|
||||
self.Light.Size = 512
|
||||
self.Light.DieTime = CurTime() + self.FireTime
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
if !self:IsValid() or self:WaterLevel() > 2 then return end
|
||||
if !IsValid(emitter) then return end
|
||||
|
||||
if self.Ticks % math.ceil(2 + d * 8) == 0 then
|
||||
local fire = emitter:Add("particles/smokey", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 8))
|
||||
local wind = Vector(math.sin(CurTime() / 60), math.cos(CurTime() / 60), 0) * math.Rand(1000, 1400)
|
||||
fire:SetVelocity( VectorRand() * 75 + self:GetVelocity() )
|
||||
fire:SetGravity( wind + Vector(0, 0, 2500) )
|
||||
fire:SetDieTime( self.FlareLength * math.Rand(2, 3) )
|
||||
fire:SetStartAlpha( 100 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 10 )
|
||||
fire:SetEndSize( Lerp(self.FlareLength, 48, 128) )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 300 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(1)
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 50, 25)
|
||||
local col2 = Color(255, 155, 155)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
if self.Ticks % math.ceil(6 + d * 10) == 0 then
|
||||
local fire = emitter:Add("effects/spark", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 0))
|
||||
fire:SetVelocity( VectorRand() * 300 + Vector(0, 0, 300) )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 5 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.Ticks = self.Ticks + 1
|
||||
else
|
||||
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
if self:GetVelocity():LengthSqr() <= 32 then
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
end
|
||||
|
||||
if self.NextDamageTick > CurTime() then return end
|
||||
|
||||
if self:WaterLevel() > 2 then self:Remove() return end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(15)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
util.BlastDamageInfo(dmg, IsValid(self:GetParent()) and self:GetParent():GetPos() or self:GetPos(), 96)
|
||||
|
||||
if self.SpawnTime + self.FireTime <= CurTime() then self:Remove() return end
|
||||
|
||||
self.NextDamageTick = CurTime() + 0.2
|
||||
self:NextThink(self.NextDamageTick)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.dietime = CurTime() + 0.5
|
||||
self.Light.decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
if !self:IsValid() then return end
|
||||
|
||||
self.Armed = true
|
||||
|
||||
if self.Order and self.Order != 1 then return end
|
||||
|
||||
-- self.FireSound = CreateSound(self, "tacrp_extras/grenades/fire_loop_1.wav")
|
||||
self.FireSound = CreateSound(self, "weapons/flaregun/burn.wav")
|
||||
self.FireSound:SetSoundLevel(70)
|
||||
self.FireSound:Play()
|
||||
self.FireSound:ChangePitch(105)
|
||||
|
||||
self.FireSound:ChangePitch(95, self.FireTime)
|
||||
|
||||
timer.Simple(self.FireTime - 1, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self.FireSound:ChangeVolume(0, 1)
|
||||
end)
|
||||
|
||||
timer.Simple(self.FireTime, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
ENT.FlareColor = Color(255, 200, 200)
|
||||
ENT.FlareSizeMin = 48
|
||||
ENT.FlareSizeMax = 64
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + Vector(0, 0, 4), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
233
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud_para.lua
Normal file
233
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud_para.lua
Normal file
@@ -0,0 +1,233 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Flare Particle"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
ENT.FireTime = 15
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.Ticks = 0
|
||||
|
||||
ENT.FlareLength = 1
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
if SERVER then
|
||||
self:SetModel( self.Model )
|
||||
self:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
self:SetSolid( SOLID_VPHYSICS )
|
||||
local maxs = Vector(2, 2, 2)
|
||||
local mins = -maxs
|
||||
self:PhysicsInitBox(mins, maxs)
|
||||
self:DrawShadow( false )
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if phys:IsValid() then
|
||||
phys:Wake()
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:SetDragCoefficient(4)
|
||||
end
|
||||
|
||||
self:Detonate()
|
||||
end
|
||||
end
|
||||
|
||||
ENT.LastTraceTime = 0
|
||||
ENT.LastTracePos = nil
|
||||
|
||||
function ENT:Think()
|
||||
if CLIENT then
|
||||
local d = Lerp((self.SpawnTime + self.FireTime - CurTime()) / 12, 1, 0.000001) ^ 2
|
||||
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex())
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 200
|
||||
self.Light.b = 140
|
||||
self.Light.Brightness = 1
|
||||
self.Light.Size = 1500
|
||||
self.Light.DieTime = CurTime() + self.FireTime
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
-- fucking expensive
|
||||
--[[]
|
||||
if !self.ProjectedTexture then
|
||||
self.ProjectedTexture = ProjectedTexture()
|
||||
self.ProjectedTexture:SetTexture("effects/flashlight001")
|
||||
self.ProjectedTexture:SetColor(Color(255, 200, 140))
|
||||
self.ProjectedTexture:SetNearZ(728)
|
||||
self.ProjectedTexture:SetFarZ(4096)
|
||||
self.ProjectedTexture:SetAngles(down)
|
||||
self.ProjectedTexture:SetFOV(170)
|
||||
self.ProjectedTexture:SetLightWorld(false)
|
||||
self.ProjectedTexture:SetBrightness(0.75)
|
||||
end
|
||||
self.ProjectedTexture:SetPos(self:GetPos())
|
||||
self.ProjectedTexture:Update()
|
||||
]]
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
if !self:IsValid() or self:WaterLevel() > 2 then return end
|
||||
if !IsValid(emitter) then return end
|
||||
|
||||
if self.Ticks % math.ceil(4 + d * 8) == 0 then
|
||||
local fire = emitter:Add("particles/smokey", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 8))
|
||||
fire:SetVelocity( VectorRand() * 8 )
|
||||
fire:SetGravity( Vector(0, 0, 100) )
|
||||
fire:SetDieTime( self.FlareLength * math.Rand(5, 6) )
|
||||
fire:SetStartAlpha( 20 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 12 )
|
||||
fire:SetEndSize( math.Rand(32, 48) )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 100 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(1)
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 200, 150)
|
||||
local col2 = Color(255, 255, 225)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
if self.Ticks % math.ceil(4 + d * 10) == 0 then
|
||||
local fire = emitter:Add("effects/spark", self:GetPos())
|
||||
fire:SetVelocity( VectorRand() * 300 + Vector(0, 0, 300) )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 5 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.Ticks = self.Ticks + 1
|
||||
else
|
||||
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
if self.NextDamageTick > CurTime() then return end
|
||||
|
||||
if self:WaterLevel() > 2 then self:Remove() return end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(15)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
util.BlastDamageInfo(dmg, IsValid(self:GetParent()) and self:GetParent():GetPos() or self:GetPos(), 96)
|
||||
|
||||
if self.SpawnTime + self.FireTime <= CurTime() then self:Remove() return end
|
||||
|
||||
self.NextDamageTick = CurTime() + 0.2
|
||||
self:NextThink(self.NextDamageTick)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.dietime = CurTime() + 0.5
|
||||
self.Light.decay = 800
|
||||
end
|
||||
if IsValid(self.ProjectedTexture) then
|
||||
self.ProjectedTexture:Remove()
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
if !self:IsValid() then return end
|
||||
|
||||
self.Armed = true
|
||||
|
||||
if self.Order and self.Order != 1 then return end
|
||||
|
||||
-- self.FireSound = CreateSound(self, "tacrp_extras/grenades/fire_loop_1.wav")
|
||||
self.FireSound = CreateSound(self, "weapons/flaregun/burn.wav")
|
||||
self.FireSound:SetSoundLevel(70)
|
||||
self.FireSound:Play()
|
||||
self.FireSound:ChangePitch(105)
|
||||
|
||||
self.FireSound:ChangePitch(95, self.FireTime)
|
||||
|
||||
timer.Simple(self.FireTime - 1, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self.FireSound:ChangeVolume(0, 1)
|
||||
end)
|
||||
|
||||
timer.Simple(self.FireTime, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
ENT.FlareColor = Color(255, 240, 240)
|
||||
ENT.FlareSizeMin = 64
|
||||
ENT.FlareSizeMax = 96
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + Vector(0, 0, 4), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
v.z = math.max(v.z, -70)
|
||||
phys:SetVelocityInstantaneous(v)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
219
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud_signal.lua
Normal file
219
garrysmod/addons/tacrp/lua/entities/tacrp_flare_cloud_signal.lua
Normal file
@@ -0,0 +1,219 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Flare Particle"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
|
||||
ENT.FireTime = 60 -- Duration once landed
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.Ticks = 0
|
||||
|
||||
ENT.FlareLength = 2
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
if SERVER then
|
||||
self:SetModel( self.Model )
|
||||
self:SetMoveType( MOVETYPE_VPHYSICS )
|
||||
self:SetSolid( SOLID_VPHYSICS )
|
||||
local maxs = Vector(2, 1, 1)
|
||||
local mins = -maxs
|
||||
self:PhysicsInitBox(mins, maxs)
|
||||
self:DrawShadow( false )
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if phys:IsValid() then
|
||||
phys:Wake()
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:SetDragCoefficient(5)
|
||||
end
|
||||
|
||||
self:Detonate()
|
||||
|
||||
-- self.FireTime = self.FireTime * math.Rand(0.8, 1.2)
|
||||
-- self:SetNWFloat("FireTime", CurTime() + self.FireTime)
|
||||
else
|
||||
local tr = util.TraceHull({
|
||||
start = self:GetPos() + Vector(0, 0, 12),
|
||||
endpos = self:GetPos() + Vector(0, 0, 1024),
|
||||
mask = MASK_SOLID_BRUSHONLY,
|
||||
mins = Vector(-4, -4, -4),
|
||||
maxs = Vector(4, 4, 4),
|
||||
})
|
||||
self.FlareLength = math.Clamp(tr.Fraction ^ 2, 0.2, 1)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if CLIENT then
|
||||
local d = Lerp((self.SpawnTime + self.FireTime - CurTime()) / 12, 1, 0.000001) ^ 2
|
||||
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex())
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 75
|
||||
self.Light.b = 60
|
||||
self.Light.Brightness = 1.5
|
||||
self.Light.Size = 512
|
||||
self.Light.DieTime = CurTime() + self.FireTime
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
if !self:IsValid() or self:WaterLevel() > 2 then return end
|
||||
if !IsValid(emitter) then return end
|
||||
|
||||
if self.Ticks % math.ceil(2 + d * 8) == 0 then
|
||||
local fire = emitter:Add("particles/smokey", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 8))
|
||||
local wind = Vector(math.sin(CurTime() / 60), math.cos(CurTime() / 60), 0) * math.Rand(1000, 1400)
|
||||
fire:SetVelocity( VectorRand() * 75 + self:GetVelocity() )
|
||||
fire:SetGravity( wind + Vector(0, 0, 2500) )
|
||||
fire:SetDieTime( self.FlareLength * math.Rand(8, 12) ) -- Flare Height
|
||||
fire:SetStartAlpha( 100 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 10 )
|
||||
fire:SetEndSize( Lerp(self.FlareLength, 96, 256) ) -- Particle Size
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 300 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(1)
|
||||
fire:SetNextThink( CurTime() + FrameTime() )
|
||||
fire:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 50, 25)
|
||||
local col2 = Color(255, 155, 155)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
end
|
||||
|
||||
if self.Ticks % math.ceil(6 + d * 10) == 0 then
|
||||
local fire = emitter:Add("effects/spark", self:GetPos() + Vector(math.Rand(-4, 4), math.Rand(-4, 4), 0))
|
||||
fire:SetVelocity( VectorRand() * 300 + Vector(0, 0, 300) )
|
||||
fire:SetGravity( Vector(math.Rand(-5, 5), math.Rand(-5, 5), -2000) )
|
||||
fire:SetDieTime( math.Rand(0.5, 1) )
|
||||
fire:SetStartAlpha( 255 )
|
||||
fire:SetEndAlpha( 0 )
|
||||
fire:SetStartSize( 5 )
|
||||
fire:SetEndSize( 0 )
|
||||
fire:SetRoll( math.Rand(-180, 180) )
|
||||
fire:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
fire:SetColor( 255, 255, 255 )
|
||||
fire:SetAirResistance( 50 )
|
||||
fire:SetPos( self:GetPos() )
|
||||
fire:SetLighting( false )
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
fire.Ticks = 0
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.Ticks = self.Ticks + 1
|
||||
else
|
||||
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
if self:GetVelocity():LengthSqr() <= 32 then
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
end
|
||||
|
||||
if self.NextDamageTick > CurTime() then return end
|
||||
|
||||
if self:WaterLevel() > 2 then self:Remove() return end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(15)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
util.BlastDamageInfo(dmg, IsValid(self:GetParent()) and self:GetParent():GetPos() or self:GetPos(), 96)
|
||||
|
||||
if self.SpawnTime + self.FireTime <= CurTime() then self:Remove() return end
|
||||
|
||||
self.NextDamageTick = CurTime() + 0.2
|
||||
self:NextThink(self.NextDamageTick)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.dietime = CurTime() + 0.5
|
||||
self.Light.decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
if !self:IsValid() then return end
|
||||
|
||||
self.Armed = true
|
||||
|
||||
if self.Order and self.Order != 1 then return end
|
||||
|
||||
-- self.FireSound = CreateSound(self, "tacrp_extras/grenades/fire_loop_1.wav")
|
||||
self.FireSound = CreateSound(self, "weapons/flaregun/burn.wav")
|
||||
self.FireSound:SetSoundLevel(70)
|
||||
self.FireSound:Play()
|
||||
self.FireSound:ChangePitch(105)
|
||||
|
||||
self.FireSound:ChangePitch(95, self.FireTime)
|
||||
|
||||
timer.Simple(self.FireTime - 1, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self.FireSound:ChangeVolume(0, 1)
|
||||
end)
|
||||
|
||||
timer.Simple(self.FireTime, function()
|
||||
if !IsValid(self) then return end
|
||||
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
ENT.FlareColor = Color(255, 200, 200)
|
||||
ENT.FlareSizeMin = 96
|
||||
ENT.FlareSizeMax = 128
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + Vector(0, 0, 4), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
244
garrysmod/addons/tacrp/lua/entities/tacrp_gas_cloud.lua
Normal file
244
garrysmod/addons/tacrp/lua/entities/tacrp_gas_cloud.lua
Normal file
@@ -0,0 +1,244 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Gas Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 256
|
||||
ENT.SmokeColor = Color(125, 150, 50)
|
||||
ENT.BillowTime = 5
|
||||
ENT.Life = 15
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), 328, self.Life, self)
|
||||
else
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 20
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 200) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
return
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
alph = math.Clamp(alph, 0, 1)
|
||||
|
||||
pa:SetStartAlpha(50 * alph)
|
||||
pa:SetEndAlpha(50 * alph)
|
||||
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime
|
||||
end
|
||||
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
local o = self:GetOwner()
|
||||
local origin = self:GetPos() + Vector(0, 0, 16)
|
||||
|
||||
local ttt = TacRP.GetBalanceMode() == TacRP.BALANCE_TTT
|
||||
local threshold = ttt and 50 or 25
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(self:GetOwner())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageType(DMG_NERVEGAS)
|
||||
dmg:SetDamageForce(Vector(0, 0, 0))
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetDamageCustom(1024) -- immersive death
|
||||
for i, k in pairs(ents.FindInSphere(origin, 300)) do
|
||||
if k:IsPlayer() or k:IsNPC() or k:IsNextBot() then
|
||||
|
||||
if k:IsPlayer() then
|
||||
local wep = k:GetActiveWeapon()
|
||||
if IsValid(wep) and wep.ArcticTacRP and wep:GetValue("GasImmunity") then
|
||||
continue
|
||||
end
|
||||
end
|
||||
|
||||
local tr = util.TraceLine({
|
||||
start = origin,
|
||||
endpos = k:EyePos() or k:WorldSpaceCenter(),
|
||||
filter = self,
|
||||
mask = MASK_SOLID_BRUSHONLY
|
||||
})
|
||||
if tr.Fraction < 1 then continue end
|
||||
|
||||
dmg:SetDamage(math.Rand(3, 6))
|
||||
|
||||
if k:IsPlayer() and TacRP.ConVars["gas_affectplayers"]:GetBool() then
|
||||
k:TakeDamageInfo(dmg)
|
||||
|
||||
local timername = "tacrp_gas_" .. k:EntIndex()
|
||||
local reps = 6
|
||||
|
||||
if timer.Exists(timername) then
|
||||
reps = math.Clamp(timer.RepsLeft(timername) + 3, reps, 20)
|
||||
timer.Remove(timername)
|
||||
end
|
||||
timer.Create(timername, ttt and 5 or 1.5, reps, function()
|
||||
if !IsValid(k) or !k:Alive() or (engine.ActiveGamemode() == "terrortown" and (GetRoundState() == ROUND_PREP or GetRoundState() == ROUND_POST)) then
|
||||
timer.Remove(timername)
|
||||
return
|
||||
end
|
||||
k:ScreenFade( SCREENFADE.IN, Color(125, 150, 50, 3), 0.1, 0 )
|
||||
if k:Health() > threshold then
|
||||
local d = DamageInfo()
|
||||
d:SetDamageType(DMG_NERVEGAS)
|
||||
d:SetDamage(1)
|
||||
d:SetInflictor(IsValid(self) and self or o)
|
||||
d:SetAttacker(o)
|
||||
d:SetDamageForce(k:GetForward())
|
||||
d:SetDamagePosition(k:GetPos())
|
||||
d:SetDamageCustom(1024)
|
||||
k:TakeDamageInfo(d)
|
||||
else
|
||||
k:ViewPunch(Angle(math.Rand(-2, 2), 0, 0))
|
||||
end
|
||||
if ttt or math.random() <= 0.333 then
|
||||
k:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
|
||||
end
|
||||
end)
|
||||
elseif k:IsNPC() and TacRP.ConVars["gas_affectnpcs"]:GetBool() and (k:GetHullType() == HULL_HUMAN or k:GetHullType() == HULL_WIDE_HUMAN) then
|
||||
k:SetCurrentWeaponProficiency(WEAPON_PROFICIENCY_POOR)
|
||||
local rng = math.random()
|
||||
if rng <= 0.3 then
|
||||
k:SetSchedule(SCHED_RUN_RANDOM)
|
||||
elseif rng <= 0.8 then
|
||||
k:SetSchedule(SCHED_COWER)
|
||||
end
|
||||
k:TakeDamageInfo(dmg)
|
||||
elseif !k:IsNPC() and !k:IsPlayer() then
|
||||
k:TakeDamageInfo(dmg)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 1)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
|
||||
-- cs gas strips armor and will try not deal lethal damage
|
||||
hook.Add("EntityTakeDamage", "tacrp_gas", function(ent, dmg)
|
||||
if dmg:GetDamageType() == DMG_NERVEGAS and bit.band(dmg:GetDamageCustom(), 1024) == 1024 then
|
||||
if ent:IsPlayer() then
|
||||
local threshold = TacRP.GetBalanceMode() == TacRP.BALANCE_TTT and 50 or 25
|
||||
local wep = ent:GetActiveWeapon()
|
||||
if IsValid(wep) and wep.ArcticTacRP and wep:GetValue("GasImmunity") then
|
||||
dmg:SetDamage(0)
|
||||
elseif ent:Health() - dmg:GetDamage() <= threshold then
|
||||
dmg:SetDamage(math.max(0, ent:Health() - threshold))
|
||||
end
|
||||
if dmg:GetDamage() <= 0 then
|
||||
ent.TacRPGassed = true
|
||||
end
|
||||
elseif ent:IsNPC() then
|
||||
if ent:Health() <= dmg:GetDamage() then
|
||||
ent:SetHealth(1)
|
||||
dmg:SetDamage(0)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "tacrp_gas", function(ent, dmg, took)
|
||||
if ent:IsPlayer() and dmg:GetDamageType() == DMG_NERVEGAS and bit.band(dmg:GetDamageCustom(), 1024) == 1024 then
|
||||
ent:SetArmor(math.max(0, ent:Armor() - dmg:GetDamage()))
|
||||
if ent.TacRPGassed or (dmg:GetDamage() > 0 and IsValid(dmg:GetInflictor()) and (dmg:GetInflictor():GetClass() == "tacrp_gas_cloud" or dmg:GetInflictor():GetClass() == "tacrp_smoke_cloud_ninja")) then
|
||||
local distsqr = dmg:GetInflictor():GetPos():DistToSqr(ent:GetPos())
|
||||
if distsqr <= 350 * 350 then
|
||||
ent:SetNWFloat("TacRPGasEnd", CurTime() + 10)
|
||||
ent.TacRPGassed = nil
|
||||
ent:ScreenFade( SCREENFADE.IN, Color(125, 150, 50, 100), 0.5, 0 )
|
||||
ent:ViewPunch(Angle(math.Rand(-1, 1), math.Rand(-1, 1), math.Rand(-1, 1)))
|
||||
local ttt = TacRP.GetBalanceMode() == TacRP.BALANCE_TTT
|
||||
if ttt or math.random() <= 0.333 then
|
||||
ent:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
216
garrysmod/addons/tacrp/lua/entities/tacrp_heal_cloud.lua
Normal file
216
garrysmod/addons/tacrp/lua/entities/tacrp_heal_cloud.lua
Normal file
@@ -0,0 +1,216 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Healing Gas Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
local SmokeColor = Color(125, 25, 125)
|
||||
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 256
|
||||
ENT.SmokeColor = SmokeColor
|
||||
ENT.BillowTime = 2.5
|
||||
ENT.Life = 15
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 20
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 200) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius / 2
|
||||
smoke.offset_r = math.Rand(0, 100)
|
||||
smoke.offset_g = math.Rand(0, 100)
|
||||
smoke.offset_b = math.Rand(0, 100)
|
||||
smoke.pulsate_time = math.Rand(0.9, 3)
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
if !self then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
return
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetColor(
|
||||
SmokeColor.r + math.sin((CurTime() * pa.pulsate_time) + pa.offset_r) * 20,
|
||||
SmokeColor.g + math.sin((CurTime() * pa.pulsate_time) + pa.offset_g) * 20,
|
||||
SmokeColor.b + math.sin((CurTime() * pa.pulsate_time) + pa.offset_b) * 20
|
||||
)
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
alph = math.Clamp(alph, 0, 1)
|
||||
|
||||
pa:SetStartAlpha(35 * alph)
|
||||
pa:SetEndAlpha(35 * alph)
|
||||
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
local origin = self:GetPos() + Vector(0, 0, 16)
|
||||
|
||||
for i, k in pairs(ents.FindInSphere(origin, self.SmokeRadius)) do
|
||||
if (k:IsPlayer() or k:IsNPC() or k:IsNextBot()) then
|
||||
local tr = util.TraceLine({
|
||||
start = origin,
|
||||
endpos = k:EyePos() or k:WorldSpaceCenter(),
|
||||
filter = self,
|
||||
mask = MASK_SOLID_BRUSHONLY
|
||||
})
|
||||
if tr.Fraction < 1 then continue end
|
||||
if k:IsPlayer() and (k.TacRPNextCanHealthGasTime or 0) <= CurTime() then
|
||||
local ply = k
|
||||
if ply:Health() < ply:GetMaxHealth() then
|
||||
local amt = TacRP.ConVars["healnade_heal"]:GetInt()
|
||||
local ret = {amt}
|
||||
hook.Run("TacRP_MedkitHeal", self, self:GetOwner(), ply, ret)
|
||||
amt = ret and ret[1] or amt
|
||||
ply:SetHealth(math.min(ply:Health() + amt, ply:GetMaxHealth()))
|
||||
elseif ply:Armor() > 0 and ply:Armor() <= ply:GetMaxArmor() and TacRP.ConVars["healnade_armor"]:GetInt() > 0 then
|
||||
ply:SetArmor(math.min(ply:Armor() + TacRP.ConVars["healnade_armor"]:GetInt(), ply:GetMaxArmor()))
|
||||
end
|
||||
k.TacRPNextCanHealthGasTime = CurTime() + 0.19
|
||||
elseif !k:IsPlayer() and (k.TacRPNextCanHealthGasTime or 0) <= CurTime() then
|
||||
if TacRP.EntityIsNecrotic(k) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(self:GetOwner() or self)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_NERVEGAS)
|
||||
dmginfo:SetDamage(TacRP.ConVars["healnade_damage"]:GetInt())
|
||||
k:TakeDamageInfo(dmginfo)
|
||||
elseif k:Health() < k:GetMaxHealth() then
|
||||
local amt = TacRP.ConVars["healnade_heal"]:GetInt()
|
||||
local ret = {amt}
|
||||
hook.Run("TacRP_MedkitHeal", self, self:GetOwner(), k, ret)
|
||||
amt = ret and ret[1] or amt
|
||||
k:SetHealth(math.min(k:Health() + amt, k:GetMaxHealth()))
|
||||
end
|
||||
k.TacRPNextCanHealthGasTime = CurTime() + 0.19
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 0.2)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
else
|
||||
if (self.NextEmitTime or 0) > CurTime() then return end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("effects/spark", self:GetPos())
|
||||
smoke:SetVelocity( Vector(math.Rand(-1, 1), math.Rand(-1, 1), math.Rand(0, 1)) * 300 )
|
||||
smoke:SetStartAlpha( 255 )
|
||||
smoke:SetEndAlpha( 0 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( 0 )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-32, 32) )
|
||||
smoke:SetColor( 255, 255, 255 )
|
||||
smoke:SetAirResistance( 100 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 1 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetDieTime(2)
|
||||
smoke:SetGravity(Vector(0, 0, -100))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.hl2 = CurTime() + 1
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
if pa.hl2 < CurTime() and !pa.alreadyhl then
|
||||
pa:SetStartSize(8)
|
||||
pa:SetEndSize(0)
|
||||
pa:SetLifeTime(0)
|
||||
pa:SetDieTime(math.Rand(0.25, 0.5))
|
||||
pa:SetVelocity(VectorRand() * 300)
|
||||
pa:SetGravity(Vector(0, 0, -200))
|
||||
pa:SetAirResistance( 200 )
|
||||
pa.alreadyhl = true
|
||||
else
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.NextEmitTime = CurTime() + 0.02
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
218
garrysmod/addons/tacrp/lua/entities/tacrp_heal_cloud_p2a1.lua
Normal file
218
garrysmod/addons/tacrp/lua/entities/tacrp_heal_cloud_p2a1.lua
Normal file
@@ -0,0 +1,218 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Healing Gas Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
local SmokeColor = Color(125, 25, 125)
|
||||
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 128
|
||||
ENT.SmokeColor = SmokeColor
|
||||
ENT.BillowTime = 0.5
|
||||
ENT.Life = 5
|
||||
|
||||
ENT.TacRPSmoke = true
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 12
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 120) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius / 2
|
||||
smoke.offset_r = math.Rand(0, 100)
|
||||
smoke.offset_g = math.Rand(0, 100)
|
||||
smoke.offset_b = math.Rand(0, 100)
|
||||
smoke.pulsate_time = math.Rand(0.9, 3)
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
if !self then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
return
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetColor(
|
||||
SmokeColor.r + math.sin((CurTime() * pa.pulsate_time) + pa.offset_r) * 20,
|
||||
SmokeColor.g + math.sin((CurTime() * pa.pulsate_time) + pa.offset_g) * 20,
|
||||
SmokeColor.b + math.sin((CurTime() * pa.pulsate_time) + pa.offset_b) * 20
|
||||
)
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
alph = math.Clamp(alph, 0, 1)
|
||||
|
||||
pa:SetStartAlpha(35 * alph)
|
||||
pa:SetEndAlpha(35 * alph)
|
||||
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
local origin = self:GetPos() + Vector(0, 0, 16)
|
||||
|
||||
for i, k in pairs(ents.FindInSphere(origin, self.SmokeRadius)) do
|
||||
if (k:IsPlayer() or k:IsNPC() or k:IsNextBot()) then
|
||||
local tr = util.TraceLine({
|
||||
start = origin,
|
||||
endpos = k:EyePos() or k:WorldSpaceCenter(),
|
||||
filter = self,
|
||||
mask = MASK_SOLID_BRUSHONLY
|
||||
})
|
||||
if tr.Fraction < 1 then continue end
|
||||
if k:IsPlayer() and (k.TacRPNextCanHealthGasTime or 0) <= CurTime() then
|
||||
local ply = k
|
||||
if ply:Health() < ply:GetMaxHealth() then
|
||||
local amt = TacRP.ConVars["healnade_heal"]:GetInt()
|
||||
local ret = {amt}
|
||||
hook.Run("TacRP_MedkitHeal", self, self:GetOwner(), ply, ret)
|
||||
amt = ret and ret[1] or amt
|
||||
ply:SetHealth(math.min(ply:Health() + amt, ply:GetMaxHealth()))
|
||||
elseif ply:Armor() > 0 and ply:Armor() <= ply:GetMaxArmor() and TacRP.ConVars["healnade_armor"]:GetInt() > 0 then
|
||||
ply:SetArmor(math.min(ply:Armor() + TacRP.ConVars["healnade_armor"]:GetInt(), ply:GetMaxArmor()))
|
||||
end
|
||||
k.TacRPNextCanHealthGasTime = CurTime() + 0.74
|
||||
elseif !k:IsPlayer() and (k.TacRPNextCanHealthGasTime or 0) <= CurTime() then
|
||||
if TacRP.EntityIsNecrotic(k) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(self:GetOwner() or self)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_NERVEGAS)
|
||||
dmginfo:SetDamage(TacRP.ConVars["healnade_damage"]:GetInt())
|
||||
k:TakeDamageInfo(dmginfo)
|
||||
elseif k:Health() < k:GetMaxHealth() then
|
||||
local amt = TacRP.ConVars["healnade_heal"]:GetInt()
|
||||
local ret = {amt}
|
||||
hook.Run("TacRP_MedkitHeal", self, self:GetOwner(), k, ret)
|
||||
amt = ret and ret[1] or amt
|
||||
k:SetHealth(math.min(k:Health() + amt, k:GetMaxHealth()))
|
||||
end
|
||||
k.TacRPNextCanHealthGasTime = CurTime() + 0.74
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 0.75)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
else
|
||||
if (self.NextEmitTime or 0) > CurTime() then return end
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("effects/spark", self:GetPos())
|
||||
smoke:SetVelocity( Vector(math.Rand(-1, 1), math.Rand(-1, 1), math.Rand(0, 1)) * self.SmokeRadius )
|
||||
smoke:SetStartAlpha( 255 )
|
||||
smoke:SetEndAlpha( 0 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( 0 )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-32, 32) )
|
||||
smoke:SetColor( 255, 255, 255 )
|
||||
smoke:SetAirResistance( 100 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 1 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetDieTime(2)
|
||||
smoke:SetGravity(Vector(0, 0, -100))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.hl2 = CurTime() + self.BillowTime
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
if pa.hl2 < CurTime() and !pa.alreadyhl then
|
||||
pa:SetStartSize(4)
|
||||
pa:SetEndSize(0)
|
||||
pa:SetLifeTime(0)
|
||||
pa:SetDieTime(math.Rand(0.25, 0.5))
|
||||
pa:SetVelocity(VectorRand() * 300)
|
||||
pa:SetGravity(Vector(0, 0, -200))
|
||||
pa:SetAirResistance( 200 )
|
||||
pa.alreadyhl = true
|
||||
else
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.NextEmitTime = CurTime() + 0.1
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
83
garrysmod/addons/tacrp/lua/entities/tacrp_nuke_cloud.lua
Normal file
83
garrysmod/addons/tacrp/lua/entities/tacrp_nuke_cloud.lua
Normal file
@@ -0,0 +1,83 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Nuclear Radiation"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
ENT.Life = 10
|
||||
|
||||
ENT.MaxRadius = 7500
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
self.dt = CurTime() + self.Life
|
||||
|
||||
util.ScreenShake(self:GetPos(), 16, 30, self.Life, self.MaxRadius)
|
||||
|
||||
if CLIENT then return end
|
||||
|
||||
for i, k in pairs(ents.FindInSphere(self:GetPos(), self.MaxRadius)) do
|
||||
if k:GetClass() == "func_breakable_surf" then
|
||||
k:Fire("shatter", "", 0)
|
||||
elseif k:GetClass() == "func_breakable" then
|
||||
k:Fire("break", "", 0)
|
||||
end
|
||||
|
||||
local phys = k:GetPhysicsObject()
|
||||
|
||||
if IsValid(phys) then
|
||||
local vec = (k:GetPos() - self:GetPos()) * 500
|
||||
phys:ApplyForceCenter(vec)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:RadiationAttack()
|
||||
local d = (CurTime() - self.SpawnTime) / self.Life
|
||||
local radius = self.MaxRadius * d
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamage((1 - d) * 5000)
|
||||
dmg:SetDamageType(DMG_RADIATION)
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetAttacker(self:GetOwner() or self.Attacker)
|
||||
dmg:SetInflictor(self)
|
||||
|
||||
for i, k in pairs(ents.FindInSphere(self:GetPos(), radius)) do
|
||||
if !IsValid(k) then continue end
|
||||
constraint.RemoveAll(k)
|
||||
k:TakeDamageInfo(dmg)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
self:RadiationAttack()
|
||||
|
||||
self:NextThink(CurTime() + 1)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
84
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_3gl.lua
Normal file
84
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_3gl.lua
Normal file
@@ -0,0 +1,84 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm 3GL"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/40mm_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/40mm_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/40mm_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.5 or 1)
|
||||
local dmg = 55
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 200, dmg * mult)
|
||||
self:ImpactTraceAttack(ent, dmg * mult, 50)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("helicoptermegabomb", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 100, math.Rand(103, 110))
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(20, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 1))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,76 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Baton"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/flare.mdl"
|
||||
ENT.CollisionSphere = 1
|
||||
|
||||
ENT.IsRocket = false
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetDragCoefficient(0)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
if self.Impacted then return end
|
||||
self.Impacted = true
|
||||
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
dmg:SetDamage(500)
|
||||
dmg:SetDamageType(DMG_CLUB)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
dmg:SetDamageForce(d * 5000)
|
||||
|
||||
local atktr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = data.HitPos,
|
||||
filter = self
|
||||
})
|
||||
|
||||
-- TacRP.CancelBodyDamage(tgt, dmg, atktr.HitGroup)
|
||||
tgt:DispatchTraceAttack(dmg, atktr)
|
||||
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 0,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = d,
|
||||
Src = data.HitPos - d,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
end
|
||||
})
|
||||
|
||||
self:Remove()
|
||||
return true
|
||||
end
|
||||
39
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_gas.lua
Normal file
39
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_gas.lua
Normal file
@@ -0,0 +1,39 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm CS Gas"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_gas_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
48
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_he.lua
Normal file
48
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_he.lua
Normal file
@@ -0,0 +1,48 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm HE"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
local dmg = 150
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 300, dmg * mult)
|
||||
self:ImpactTraceAttack(ent, dmg * mult, 100)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
50
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_heal.lua
Normal file
50
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_heal.lua
Normal file
@@ -0,0 +1,50 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Medi-Smoke"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_heal_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
54
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_heat.lua
Normal file
54
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_heat.lua
Normal file
@@ -0,0 +1,54 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm HEAT"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 150, 25 * TacRP.ConVars["mult_damage_explosive"]:GetFloat())
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_fire_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
local ang = self:GetAngles()
|
||||
|
||||
ang:RotateAroundAxis(ang:Right(), 90)
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(ang)
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,52 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Beanbag"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/flashbang_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/flashbang_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/flashbang_bounce-3.wav",
|
||||
}
|
||||
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 90, 115)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamage(Lerp((data.OurOldVelocity:Length() - 1000) / 4000, 0, 100))
|
||||
dmg:SetDamageType(DMG_CRUSH)
|
||||
dmg:SetDamageForce(data.OurOldVelocity:GetNormalized() * 5000)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmg)
|
||||
end
|
||||
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
|
||||
SafeRemoveEntityDelayed(self, 3)
|
||||
return true
|
||||
end
|
||||
63
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_lvg.lua
Normal file
63
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_lvg.lua
Normal file
@@ -0,0 +1,63 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm LVG"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0.3
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageType(DMG_SONIC)
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetDamage(100 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 300)
|
||||
dmg:SetDamage(10)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 512)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetRadius(512)
|
||||
util.Effect("TacRP_flashexplosion", fx)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
TacRP.Flashbang(self, self:GetPos(), 1024, 2.5, 0.25, 1)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125, 110)
|
||||
self:EmitSound("TacRP/weapons/grenade/flashbang_explode-1.wav", 125, 90, 0.8)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:Impact()
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 90, 115)
|
||||
end
|
||||
120
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_ratshot.lua
Normal file
120
garrysmod/addons/tacrp/lua/entities/tacrp_proj_40mm_ratshot.lua
Normal file
@@ -0,0 +1,120 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Ratshot"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:SetTrigger(true)
|
||||
self:UseTriggerBounds(true, 96)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:StartTouch(ent)
|
||||
if SERVER and ent ~= self:GetOwner() and (ent:IsNPC() or ent:IsPlayer() or ent:IsNextBot()) then
|
||||
self:Detonate()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local src = self:GetPos()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(1.5)
|
||||
fx:SetRadius(4)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
local mult = (self.NPCDamage and 0.25 or 1) * TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
util.BlastDamage(self, attacker, src, 328, 90 * mult)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 115, 105)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 100, 190, 0.5)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(20, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 1))
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
local spark = emitter:Add("effects/spark", self:GetPos())
|
||||
|
||||
spark:SetStartAlpha(255)
|
||||
spark:SetEndAlpha(255)
|
||||
|
||||
spark:SetStartSize(4)
|
||||
spark:SetEndSize(0)
|
||||
|
||||
spark:SetRoll(math.Rand(-180, 180))
|
||||
spark:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
spark:SetVelocity(-self:GetAngles():Forward() * 300 + (VectorRand() * 100))
|
||||
|
||||
spark:SetColor(255, 255, 255)
|
||||
spark:SetLighting(false)
|
||||
|
||||
spark:SetDieTime(math.Rand(0.1, 0.3))
|
||||
|
||||
spark:SetGravity(Vector(0, 0, 10))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,48 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "40mm Smoke"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_smoke_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
132
garrysmod/addons/tacrp/lua/entities/tacrp_proj_ball.lua
Normal file
132
garrysmod/addons/tacrp/lua/entities/tacrp_proj_ball.lua
Normal file
@@ -0,0 +1,132 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Thrown Ball"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint_extras/w_baseball.mdl" --"models/weapons/w_models/w_baseball.mdl" -- TODO replace with hexed model
|
||||
|
||||
ENT.IsRocket = false
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
ENT.Damage = 25
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetDragCoefficient(0)
|
||||
self.StartPos = self:GetPos()
|
||||
self.Trail = util.SpriteTrail(self, 0, color_white, true, 4, 0, 0.1, 2, "trails/tube")
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:StartTouch(ent)
|
||||
if self.Impacted and (CurTime() - self.SpawnTime) > 0.05 and IsValid(ent) and ent:IsPlayer() and ent:GetNWFloat("TacRPScoutBall", 0) > CurTime() then
|
||||
ent:SetNWFloat("TacRPScoutBall", 0)
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(data, collider)
|
||||
|
||||
if IsValid(data.HitEntity) and data.HitEntity:GetClass() == "func_breakable_surf" then
|
||||
self:FireBullets({
|
||||
Attacker = self:GetOwner(),
|
||||
Inflictor = self,
|
||||
Damage = 0,
|
||||
Distance = 32,
|
||||
Tracer = 0,
|
||||
Src = self:GetPos(),
|
||||
Dir = data.OurOldVelocity:GetNormalized(),
|
||||
})
|
||||
local pos, ang, vel = self:GetPos(), self:GetAngles(), data.OurOldVelocity
|
||||
self:SetAngles(ang)
|
||||
self:SetPos(pos)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(vel * 0.5)
|
||||
return
|
||||
end
|
||||
|
||||
if self.Impacted then return end
|
||||
self.Impacted = true
|
||||
self:SetTrigger(true)
|
||||
self:UseTriggerBounds(true, 8)
|
||||
if IsValid(self.Trail) then
|
||||
self.Trail:Remove()
|
||||
end
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
if IsValid(data.HitEntity) then
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
|
||||
local tgtpos = data.HitPos
|
||||
local dist = (tgtpos - self.StartPos):Length()
|
||||
self.Damage = Lerp(math.Clamp(dist / 1500, 0, 1) ^ 1.5, 15, 50) * (data.HitEntity:IsPlayer() and 1 or 1.5)
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
dmg:SetDamage(self.Damage)
|
||||
dmg:SetDamageType(DMG_SLASH)
|
||||
dmg:SetDamageForce(d * 10000)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
|
||||
if dist > 200 then
|
||||
data.HitEntity.TacRPBashSlow = true
|
||||
end
|
||||
|
||||
if data.HitEntity:IsPlayer() then
|
||||
local wep = data.HitEntity:GetActiveWeapon()
|
||||
if IsValid(wep) and wep.ArcticTacRP then
|
||||
wep:SetBreath(0)
|
||||
wep:SetOutOfBreath(true)
|
||||
end
|
||||
end
|
||||
|
||||
if data.HitEntity:IsPlayer() or data.HitEntity:IsNPC() or data.HitEntity:IsNextBot() then
|
||||
if dist >= 1500 then
|
||||
data.HitEntity:EmitSound("tacrp/sandman/pl_impact_stun_range.wav", 100)
|
||||
else
|
||||
data.HitEntity:EmitSound("tacrp/sandman/pl_impact_stun.wav", 90)
|
||||
end
|
||||
else
|
||||
data.HitEntity:EmitSound("tacrp/sandman/baseball_hitworld" .. math.random(1, 3) .. ".wav", 90)
|
||||
end
|
||||
|
||||
if data.HitEntity:IsNPC() or data.HitEntity:IsNextBot() then
|
||||
data.HitEntity:SetVelocity(Vector(0, 0, 200))
|
||||
if data.HitEntity:IsNPC() then
|
||||
data.HitEntity:SetSchedule(SCHED_FLINCH_PHYSICS)
|
||||
end
|
||||
end
|
||||
|
||||
local atktr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = tgtpos,
|
||||
filter = self
|
||||
})
|
||||
|
||||
TacRP.CancelBodyDamage(data.HitEntity, dmg, atktr.HitGroup)
|
||||
data.HitEntity:SetPhysicsAttacker(attacker, 3)
|
||||
data.HitEntity:DispatchTraceAttack(dmg, atktr)
|
||||
|
||||
self:SetOwner(nil)
|
||||
else
|
||||
data.HitEntity:EmitSound("tacrp/sandman/baseball_hitworld" .. math.random(1, 3) .. ".wav", 90)
|
||||
end
|
||||
|
||||
SafeRemoveEntityDelayed(self, 5)
|
||||
-- self:GetPhysicsObject():SetVelocity(-data.HitNormal * data.OurNewVelocity:Length())
|
||||
end
|
||||
618
garrysmod/addons/tacrp/lua/entities/tacrp_proj_base.lua
Normal file
618
garrysmod/addons/tacrp/lua/entities/tacrp_proj_base.lua
Normal file
@@ -0,0 +1,618 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.RenderGroup = RENDERGROUP_TRANSLUCENT
|
||||
|
||||
ENT.PrintName = "Base Projectile"
|
||||
ENT.Category = ""
|
||||
|
||||
ENT.Spawnable = false
|
||||
ENT.Model = ""
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.Material = false // custom material
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.Sticky = false // projectile sticks on impact
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.TimeFuse = false // projectile will arm after this amount of time
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
ENT.StickyFuse = false // projectile becomes timed after sticking.
|
||||
|
||||
ENT.SafetyFuse = 0 // impact fuse hitting too early will not detonate
|
||||
|
||||
ENT.RemoveOnImpact = false
|
||||
ENT.ExplodeOnImpact = false
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false // projectile explodes when it enters water
|
||||
|
||||
ENT.Defusable = false // press E on the projectile to defuse it
|
||||
ENT.DefuseOnDamage = false
|
||||
|
||||
ENT.ImpactDamage = 50
|
||||
ENT.ImpactDamageType = DMG_CRUSH + DMG_CLUB
|
||||
|
||||
ENT.Delay = 0 // after being triggered and this amount of time has passed, the projectile will explode.
|
||||
|
||||
ENT.SoundHint = false // Emit a sound hint so NPCs can react
|
||||
ENT.SoundHintDelay = 0 // Delay after spawn
|
||||
ENT.SoundHintRadius = 328
|
||||
ENT.SoundHintDuration = 1
|
||||
|
||||
ENT.Armed = false
|
||||
|
||||
ENT.SmokeTrail = false // leaves trail of smoke
|
||||
ENT.FlareColor = nil
|
||||
ENT.FlareSizeMin = 200
|
||||
ENT.FlareSizeMax = 250
|
||||
|
||||
|
||||
// Guided projectile related
|
||||
ENT.SteerDelay = 0 // Delay before steering logic kicks in
|
||||
ENT.SteerSpeed = 60 // Turn rate in degrees per second
|
||||
ENT.SteerBrake = 0 // Amount of speed to slow down by when turning
|
||||
ENT.SeekerAngle = 180 // Angle difference (degrees) above which projectile loses target
|
||||
ENT.SeekerExplodeRange = 256 // Distance to the target below which the missile will immediately explode
|
||||
ENT.SeekerExplodeSnapPosition = true // When exploding on a seeked target, teleport to the entity's position for more damage
|
||||
ENT.SeekerExplodeAngle = 180 // Angle tolerance (degrees) below which detonation can happen
|
||||
|
||||
ENT.TopAttack = false // This missile will attack from the top
|
||||
ENT.TopAttackHeight = 512 // Distance above target to top attack
|
||||
ENT.TopAttackDistance = 128 // Distance from target to stop top attacking
|
||||
|
||||
ENT.RocketLifetime = 30 // Rocket will cut after this time
|
||||
|
||||
ENT.MinSpeed = 0
|
||||
ENT.MaxSpeed = 0
|
||||
ENT.Acceleration = 0
|
||||
|
||||
ENT.LeadTarget = false // account for target's velocity and distance
|
||||
ENT.SuperSteerTime = 0 // Amount of time where turn rate is boosted
|
||||
ENT.SuperSteerSpeed = 100 // Boosted turn rate in degrees per seconds
|
||||
|
||||
ENT.NoReacquire = true // If target is lost, it cannot be tracked anymore
|
||||
ENT.FlareRedirectChance = 0
|
||||
|
||||
ENT.LockOnEntity = NULL
|
||||
ENT.TargetPos = nil
|
||||
|
||||
ENT.AudioLoop = nil
|
||||
ENT.BounceSounds = nil
|
||||
ENT.CollisionSphere = nil
|
||||
ENT.GunshipWorkaround = true
|
||||
|
||||
// Tell LVS to not ricochet us
|
||||
ENT.DisableBallistics = true
|
||||
|
||||
ENT.TopAttacking = false
|
||||
ENT.StartSuperSteerTime = 0
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Entity", 0, "Weapon")
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel(self.Model)
|
||||
self:SetMaterial(self.Material or "")
|
||||
if self.CollisionSphere then
|
||||
self:PhysicsInitSphere(self.CollisionSphere)
|
||||
else
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
end
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
if self.Defusable then
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
end
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
phys:EnableDrag(false)
|
||||
phys:SetDragCoefficient(0)
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:Wake()
|
||||
|
||||
if self.IsRocket then
|
||||
phys:EnableGravity(false)
|
||||
end
|
||||
|
||||
if self.TopAttack then
|
||||
self.TopAttacking = true
|
||||
end
|
||||
|
||||
self:SwitchTarget(self.LockOnEntity)
|
||||
end
|
||||
|
||||
self.StartSuperSteerTime = CurTime()
|
||||
self.SpawnTime = CurTime()
|
||||
self.NextFlareRedirectTime = 0
|
||||
|
||||
self.NPCDamage = IsValid(self:GetOwner()) and self:GetOwner():IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool()
|
||||
|
||||
if self.AudioLoop then
|
||||
self.LoopSound = CreateSound(self, self.AudioLoop)
|
||||
self.LoopSound:Play()
|
||||
end
|
||||
|
||||
if self.InstantFuse then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
self:OnInitialize()
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.LoopSound then
|
||||
self.LoopSound:Stop()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnTakeDamage(dmg)
|
||||
if self.Detonated then return end
|
||||
|
||||
// self:TakePhysicsDamage(dmg)
|
||||
|
||||
if self.ExplodeOnDamage then
|
||||
if IsValid(self:GetOwner()) and IsValid(dmg:GetAttacker()) then self:SetOwner(dmg:GetAttacker())
|
||||
else self.Attacker = dmg:GetAttacker() or self.Attacker end
|
||||
self:PreDetonate()
|
||||
elseif self.DefuseOnDamage and dmg:GetDamageType() != DMG_BLAST then
|
||||
self:EmitSound("physics/plastic/plastic_box_break" .. math.random(1, 2) .. ".wav", 70, math.Rand(95, 105))
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetNormal(self:GetAngles():Forward())
|
||||
fx:SetAngles(self:GetAngles())
|
||||
util.Effect("ManhackSparks", fx)
|
||||
self.Detonated = true
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsCollide(data, collider)
|
||||
if IsValid(data.HitEntity) and data.HitEntity:GetClass() == "func_breakable_surf" then
|
||||
self:FireBullets({
|
||||
Attacker = self:GetOwner(),
|
||||
Inflictor = self,
|
||||
Damage = 0,
|
||||
Distance = 32,
|
||||
Tracer = 0,
|
||||
Src = self:GetPos(),
|
||||
Dir = data.OurOldVelocity:GetNormalized(),
|
||||
})
|
||||
local pos, ang, vel = self:GetPos(), self:GetAngles(), data.OurOldVelocity
|
||||
self:SetAngles(ang)
|
||||
self:SetPos(pos)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(vel * 0.5)
|
||||
return
|
||||
end
|
||||
|
||||
if (self.SafetyFuse or 0) > 0 and self.SpawnTime + self.SafetyFuse > CurTime() then
|
||||
self:SafetyImpact(data, collider)
|
||||
self:Remove()
|
||||
return
|
||||
elseif self.ImpactFuse then
|
||||
if !self.Armed then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
|
||||
if self:Impact(data, collider) then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if self.Delay == 0 or self.ExplodeOnImpact then
|
||||
self:PreDetonate(data.HitEntity)
|
||||
end
|
||||
elseif self.ImpactDamage > 0 and (self.NextImpactDamage or 0) < CurTime() and data.Speed >= 10 and IsValid(data.HitEntity) and (engine.ActiveGamemode() != "terrortown" or !data.HitEntity:IsPlayer()) then
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(IsValid(self:GetOwner()) and self:GetOwner() or self.Attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamage(self.ImpactDamage)
|
||||
dmg:SetDamageType(self.ImpactDamageType)
|
||||
dmg:SetDamageForce(data.OurOldVelocity)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmg)
|
||||
self.NextImpactDamage = CurTime() + 0.05
|
||||
elseif !self.ImpactFuse then
|
||||
self:Impact(data, collider)
|
||||
end
|
||||
|
||||
if self.Sticky then
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
self:SetPos(data.HitPos)
|
||||
|
||||
self:SetAngles((-data.HitNormal):Angle())
|
||||
|
||||
if data.HitEntity:IsWorld() or data.HitEntity:GetSolid() == SOLID_BSP then
|
||||
self:SetMoveType(MOVETYPE_NONE)
|
||||
self:SetPos(data.HitPos)
|
||||
else
|
||||
self:SetPos(data.HitPos)
|
||||
self:SetParent(data.HitEntity)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/plant_bomb.wav", 65)
|
||||
|
||||
self.Attacker = self:GetOwner()
|
||||
self:SetOwner(NULL)
|
||||
|
||||
if self.StickyFuse and !self.Armed then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
self:Stuck()
|
||||
else
|
||||
if !self.Bounced then
|
||||
self.Bounced = true
|
||||
local dot = data.HitNormal:Dot(Vector(0, 0, 1))
|
||||
if dot < 0 then
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(data.OurNewVelocity * (1 + dot * 0.5))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if data.DeltaTime < 0.1 then return end
|
||||
if !self.BounceSounds then return end
|
||||
|
||||
local s = table.Random(self.BounceSounds)
|
||||
|
||||
self:EmitSound(s)
|
||||
end
|
||||
|
||||
function ENT:OnThink()
|
||||
end
|
||||
|
||||
function ENT:OnInitialize()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(50, 75))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.25))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if self.SpawnTime + self.RocketLifetime < CurTime() then return end
|
||||
|
||||
if self.TargetPos and (self.SteerDelay + self.SpawnTime) <= CurTime() then
|
||||
local v = phys:GetVelocity()
|
||||
|
||||
local steer_amount = self.SteerSpeed * FrameTime()
|
||||
if self.SuperSteerTime + self.StartSuperSteerTime > CurTime() then
|
||||
steer_amount = self.SuperSteerSpeed * FrameTime()
|
||||
end
|
||||
|
||||
local dir = (self.TargetPos - self:GetPos()):GetNormalized()
|
||||
local diff = math.deg(math.acos(dir:Dot(self:GetForward())))
|
||||
local turn_deg = math.min(diff, steer_amount)
|
||||
|
||||
local newang = self:GetAngles()
|
||||
newang:RotateAroundAxis(dir:Cross(self:GetForward()), -turn_deg)
|
||||
|
||||
local brake = turn_deg / steer_amount * self.SteerBrake
|
||||
|
||||
self:SetAngles(Angle(newang.p, newang.y, 0))
|
||||
phys:SetVelocityInstantaneous(self:GetForward() * math.Clamp(v:Length() + (self.Acceleration - brake) * FrameTime(), self.MinSpeed, self.MaxSpeed))
|
||||
elseif self.Acceleration > 0 then
|
||||
phys:SetVelocityInstantaneous(self:GetForward() * math.Clamp(phys:GetVelocity():Length() + self.Acceleration * FrameTime(), self.MinSpeed, self.MaxSpeed))
|
||||
end
|
||||
end
|
||||
|
||||
local gunship = {["npc_combinegunship"] = true, ["npc_combinedropship"] = true, ["npc_helicopter"] = true}
|
||||
|
||||
function ENT:DoTracking()
|
||||
local target = self.LockOnEntity
|
||||
if IsValid(target) then
|
||||
if self.TopAttack and self.TopAttacking then
|
||||
local xyvector = (target:WorldSpaceCenter() - self:GetPos())
|
||||
xyvector.z = 0
|
||||
local dist = xyvector:Length()
|
||||
|
||||
self.TargetPos = target:WorldSpaceCenter() + Vector(0, 0, self.TopAttackHeight)
|
||||
if self.LeadTarget then
|
||||
local dist2 = (self.TargetPos - self:GetPos()):Length()
|
||||
|
||||
local time = dist2 / self:GetVelocity():Length()
|
||||
self.TargetPos = self.TargetPos + (target:GetVelocity() * time)
|
||||
end
|
||||
|
||||
if dist <= self.TopAttackDistance then
|
||||
self.TopAttacking = false
|
||||
self.StartSuperSteerTime = CurTime()
|
||||
end
|
||||
else
|
||||
local dir = (target:WorldSpaceCenter() - self:GetPos()):GetNormalized()
|
||||
local diff = math.deg(math.acos(dir:Dot(self:GetForward())))
|
||||
if diff <= self.SeekerAngle or self.SuperSteerTime + self.StartSuperSteerTime > CurTime() then
|
||||
self.TargetPos = target:WorldSpaceCenter()
|
||||
local dist = (self.TargetPos - self:GetPos()):Length()
|
||||
if self.LeadTarget then
|
||||
local time = dist / self:GetVelocity():Length()
|
||||
self.TargetPos = self.TargetPos + (target:GetVelocity() * time)
|
||||
end
|
||||
|
||||
if self.FlareRedirectChance > 0 and self.NextFlareRedirectTime <= CurTime() and !TacRP.FlareEntities[target:GetClass()] then
|
||||
local flares = ents.FindInSphere(self:GetPos(), 2048)
|
||||
for k, v in pairs(flares) do
|
||||
if (TacRP.FlareEntities[v:GetClass()] or v.IsTacRPFlare) and math.Rand(0, 1) <= self.FlareRedirectChance then
|
||||
self:SwitchTarget(v)
|
||||
break
|
||||
end
|
||||
end
|
||||
self.NextFlareRedirectTime = CurTime() + 0.5
|
||||
end
|
||||
|
||||
if self.SeekerExplodeRange > 0 and diff <= self.SeekerExplodeAngle
|
||||
and self.SteerDelay + self.SpawnTime <= CurTime()
|
||||
and dist < self.SeekerExplodeRange then
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = target:GetPos(),
|
||||
filter = self,
|
||||
mask = MASK_SOLID,
|
||||
})
|
||||
if self.SeekerExplodeSnapPosition then
|
||||
self:SetPos(tr.HitPos)
|
||||
end
|
||||
self:PreDetonate(target)
|
||||
end
|
||||
elseif self.NoReacquire then
|
||||
self.LockOnEntity = nil
|
||||
self.TargetPos = nil
|
||||
end
|
||||
end
|
||||
elseif (!IsValid(target) and self.NoReacquire) or target.UnTrackable then
|
||||
self.LockOnEntity = nil
|
||||
self.TargetPos = nil
|
||||
end
|
||||
|
||||
if self.GunshipWorkaround and (self.GunshipCheck or 0 < CurTime()) then
|
||||
self.GunshipCheck = CurTime() + 0.33
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + (self:GetVelocity() * 6 * engine.TickInterval()),
|
||||
filter = self,
|
||||
mask = MASK_SHOT
|
||||
})
|
||||
if IsValid(tr.Entity) and gunship[tr.Entity:GetClass()] then
|
||||
self:SetPos(tr.HitPos)
|
||||
self:PreDetonate(tr.Entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !IsValid(self) or self:GetNoDraw() then return end
|
||||
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if SERVER and self.SoundHint and CurTime() >= self.SpawnTime + self.SoundHintDelay then
|
||||
self.SoundHint = false // only once
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), self.SoundHintRadius, self.SoundHintDuration, self)
|
||||
end
|
||||
|
||||
if !self.Armed and isnumber(self.TimeFuse) and self.SpawnTime + self.TimeFuse < CurTime() then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
if self.Armed and self.ArmTime + self.Delay < CurTime() then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if self.ExplodeUnderwater and self:WaterLevel() > 0 then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if SERVER and self.SpawnTime + self.RocketLifetime > CurTime() then
|
||||
self:DoTracking()
|
||||
end
|
||||
|
||||
self:DoSmokeTrail()
|
||||
|
||||
self:OnThink()
|
||||
|
||||
self:NextThink(CurTime())
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Use(ply)
|
||||
if !self.Defusable then return end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rifle_jingle-1.wav")
|
||||
|
||||
if self.PickupAmmo then
|
||||
ply:GiveAmmo(1, self.PickupAmmo, true)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:RemoteDetonate()
|
||||
self:EmitSound("TacRP/weapons/c4/relay_switch-1.wav")
|
||||
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
function ENT:PreDetonate(ent)
|
||||
if CLIENT then return end
|
||||
|
||||
if !self.Detonated then
|
||||
self.Detonated = true
|
||||
|
||||
if !IsValid(self.Attacker) and !IsValid(self:GetOwner()) then self.Attacker = game.GetWorld() end
|
||||
|
||||
self:Detonate(ent)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
// fill this in :)
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
end
|
||||
|
||||
function ENT:SafetyImpact(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(self.ImpactDamageType)
|
||||
dmginfo:SetDamage(self.ImpactDamage * (self.NPCDamage and 0.25 or 1))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity * 20)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 80)
|
||||
|
||||
if self:GetModel() == "models/weapons/tacint/rocket_deployed.mdl" then
|
||||
for i = 1, 4 do
|
||||
local prop = ents.Create("prop_physics")
|
||||
prop:SetPos(self:GetPos())
|
||||
prop:SetAngles(self:GetAngles())
|
||||
prop:SetModel("models/weapons/tacint/rpg7_shrapnel_p" .. i .. ".mdl")
|
||||
prop:Spawn()
|
||||
prop:GetPhysicsObject():SetVelocityInstantaneous(data.OurNewVelocity * 0.5 + VectorRand() * 75)
|
||||
prop:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
SafeRemoveEntityDelayed(prop, 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:ImpactTraceAttack(ent, damage, pen)
|
||||
if !IsValid(ent) then return end
|
||||
if ent.LVS then
|
||||
// LVS only does its penetration logic on FireBullets, so we must fire a bullet to trigger it
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS) // The projectile blocks the penetration decal?!
|
||||
self:FireBullets({
|
||||
Attacker = self.Attacker or self:GetOwner(),
|
||||
Damage = damage,
|
||||
Tracer = 0,
|
||||
Src = self:GetPos(),
|
||||
Dir = self:GetForward(),
|
||||
HullSize = 16,
|
||||
Distance = 128,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, btr, dmginfo)
|
||||
dmginfo:SetDamageType(DMG_AIRBOAT + DMG_SNIPER) // LVS wants this
|
||||
dmginfo:SetDamageForce(self:GetForward() * pen) // penetration strength
|
||||
end,
|
||||
})
|
||||
else
|
||||
// This is way more consistent because the damage always lands
|
||||
local tr = util.TraceHull({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + self:GetForward() * 256,
|
||||
filter = ent,
|
||||
whitelist = true,
|
||||
ignoreworld = true,
|
||||
mask = MASK_ALL,
|
||||
mins = Vector( -8, -8, -8 ),
|
||||
maxs = Vector( 8, 8, 8 ),
|
||||
})
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(self.Attacker or self:GetOwner())
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamagePosition(self:GetPos())
|
||||
dmginfo:SetDamageForce(self:GetForward() * pen)
|
||||
dmginfo:SetDamageType(DMG_AIRBOAT + DMG_SNIPER)
|
||||
dmginfo:SetDamage(damage)
|
||||
ent:DispatchTraceAttack(dmginfo, tr, self:GetForward())
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Stuck()
|
||||
end
|
||||
|
||||
function ENT:DrawTranslucent()
|
||||
self:Draw()
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
|
||||
function ENT:Draw()
|
||||
if self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.05) > CurTime() then return end
|
||||
|
||||
self:DrawModel()
|
||||
|
||||
if self.FlareColor then
|
||||
local mult = self.SafetyFuse and math.Clamp((CurTime() - (self.SpawnTime + self.SafetyFuse)) / self.SafetyFuse, 0.1, 1) or 1
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + (self:GetAngles():Forward() * -16), mult * math.Rand(self.FlareSizeMin, self.FlareSizeMax), mult * math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:SwitchTarget(target)
|
||||
if IsValid(self.LockOnEntity) then
|
||||
if isfunction(self.LockOnEntity.OnLaserLock) then
|
||||
self.LockOnEntity:OnLaserLock(false)
|
||||
end
|
||||
end
|
||||
|
||||
self.LockOnEntity = target
|
||||
|
||||
if IsValid(self.LockOnEntity) then
|
||||
if isfunction(self.LockOnEntity.OnLaserLock) then
|
||||
self.LockOnEntity:OnLaserLock(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("EntityTakeDamage", "tacrp_proj_collision", function(ent, dmginfo)
|
||||
if IsValid(dmginfo:GetInflictor())
|
||||
and scripted_ents.IsBasedOn(dmginfo:GetInflictor():GetClass(), "tacrp_proj_base")
|
||||
and dmginfo:GetDamageType() == DMG_CRUSH then dmginfo:SetDamage(0) return true end
|
||||
end)
|
||||
@@ -0,0 +1,98 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Breaching Slug"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/flare.mdl"
|
||||
ENT.CollisionSphere = 1
|
||||
|
||||
ENT.IsRocket = false
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetDragCoefficient(5)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
if self.Impacted then return end
|
||||
self.Impacted = true
|
||||
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
if IsValid(tgt) and string.find(tgt:GetClass(), "door") then
|
||||
-- if slug spent too much time in the air, it can only open doors, not breach them
|
||||
local vel = d * math.max(0, (self.SpawnTime + 0.25 - CurTime()) / 0.25) ^ 0.75 * 3000
|
||||
for _, otherDoor in pairs(ents.FindInSphere(tgt:GetPos(), 72)) do
|
||||
if tgt != otherDoor and otherDoor:GetClass() == tgt:GetClass() then
|
||||
TacRP.DoorBust(otherDoor, vel, attacker)
|
||||
break
|
||||
end
|
||||
end
|
||||
TacRP.DoorBust(tgt, vel, attacker)
|
||||
elseif IsValid(tgt) and tgt:GetClass() == "func_button" then
|
||||
-- press buttons remotely :3
|
||||
tgt:Use(attacker, self)
|
||||
end
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
dmg:SetDamage(50)
|
||||
dmg:SetDamageType(DMG_CLUB)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
dmg:SetDamageForce(d * 30000)
|
||||
|
||||
local atktr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = data.HitPos,
|
||||
filter = self
|
||||
})
|
||||
|
||||
-- TacRP.CancelBodyDamage(tgt, dmg, atktr.HitGroup)
|
||||
tgt:DispatchTraceAttack(dmg, atktr)
|
||||
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 0,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = d,
|
||||
Src = data.HitPos - d,
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
end
|
||||
})
|
||||
|
||||
self:Remove()
|
||||
return true
|
||||
end
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "tacrp_proj_breach_slug", function(ent, dmg, took)
|
||||
if took and IsValid(dmg:GetInflictor()) and ent:IsPlayer()
|
||||
and dmg:GetInflictor():GetClass() == "tacrp_proj_breach_slug"
|
||||
and (!IsValid(ent:GetActiveWeapon()) or !ent:GetActiveWeapon().ArcticTacRP or !ent:GetActiveWeapon():GetValue("StunResist")) then
|
||||
ent:SetNWFloat("TacRPLastBashed", CurTime() + 3)
|
||||
end
|
||||
end)
|
||||
165
garrysmod/addons/tacrp/lua/entities/tacrp_proj_gyrojet.lua
Normal file
165
garrysmod/addons/tacrp/lua/entities/tacrp_proj_gyrojet.lua
Normal file
@@ -0,0 +1,165 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Gyrojet Round"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint_shark/projectiles/gyrojet_rocket.mdl"
|
||||
ENT.CollisionSphere = 2
|
||||
|
||||
ENT.IsRocket = true
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 128, 0, 100)
|
||||
ENT.FlareLife = 0.5
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/40mm_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/40mm_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/40mm_explode-3.wav",
|
||||
}
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:MakeSmoke()
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(55)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 200 + (VectorRand() * 5)
|
||||
+ self:GetAngles():Right() * math.sin(CurTime() * math.pi * 16) * 32
|
||||
+ self:GetAngles():Up() * math.cos(CurTime() * math.pi * 16) * 32)
|
||||
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.4, 0.6))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !IsValid(self) or self:GetNoDraw() then return end
|
||||
|
||||
if CurTime() - self.SpawnTime >= self.FlareLife then
|
||||
self.FlareColor = false
|
||||
end
|
||||
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if !self.Armed and isnumber(self.TimeFuse) and self.SpawnTime + self.TimeFuse < CurTime() then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
if self.Armed and self.ArmTime + self.Delay < CurTime() then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if self.ExplodeUnderwater and self:WaterLevel() > 0 then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if CLIENT and self.SmokeTrail and CurTime() - self.SpawnTime >= 0.1 then
|
||||
self:MakeSmoke()
|
||||
end
|
||||
|
||||
self:OnThink()
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("MetalSpark", fx)
|
||||
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local inflictor = attacker.GetWeapon and attacker:GetWeapon("tacrp_sd_gyrojet")
|
||||
local dmg = inflictor and inflictor.GetValue and inflictor:GetValue("Damage_Max") or 75
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Inflictor = inflictor or self,
|
||||
Force = 5,
|
||||
Num = 1,
|
||||
Tracer = 0,
|
||||
Dir = data.OurOldVelocity:GetNormalized(),
|
||||
Src = data.HitPos,
|
||||
Damage = dmg,
|
||||
HullSize = 2,
|
||||
Callback = function(att, btr, dmginfo)
|
||||
if IsValid(btr.Entity) then
|
||||
if IsValid(inflictor) and inflictor.GetValue then
|
||||
local range = (btr.HitPos - btr.StartPos):Length()
|
||||
inflictor:AfterShotFunction(btr, dmginfo, range, inflictor:GetValue("Penetration"), {})
|
||||
end
|
||||
else
|
||||
-- Even though bullet did not hit, projectile did; just apply damage
|
||||
if attacker:IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool() then
|
||||
dmginfo:ScaleDamage(0.25)
|
||||
end
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
end
|
||||
})
|
||||
|
||||
self:Remove()
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
local len = phys:GetVelocity():Length()
|
||||
local f = math.Clamp(len / 4000, 0, 1)
|
||||
phys:AddVelocity(self:GetForward() * Lerp(f, 10, 1))
|
||||
end
|
||||
|
||||
local mat = Material("sprites/light_glow02_add")
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if self.FlareColor then
|
||||
local s = Lerp(((CurTime() - self.SpawnTime) / self.FlareLife) ^ 0.5, 1, 0)
|
||||
local s1, s2 = 32 * s, 64 * s
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + (self:GetAngles():Forward() * -4), math.Rand(s1, s2), math.Rand(s1, s2), self.FlareColor)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_gyrojet"
|
||||
ENT.PrintName = "HE Gyrojet Round"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 128, 100)
|
||||
ENT.FlareLife = 0.5
|
||||
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
return false
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local inflictor = attacker.GetWeapon and attacker:GetWeapon("tacrp_sd_gyrojet")
|
||||
local dmg = inflictor and inflictor:GetValue("Damage_Max") or 50
|
||||
if attacker:IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool() then
|
||||
dmg = dmg * 0.25
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 128, dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetNormal(self:GetForward())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 80, 110, 0.75)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,41 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_gyrojet"
|
||||
ENT.PrintName = "LV Gyrojet Round"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 255, 200, 100)
|
||||
ENT.FlareLife = 0.2
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:MakeSmoke()
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(45)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(8, 16))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 150 + (VectorRand() * 5))
|
||||
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.2, 0.4))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_gyrojet"
|
||||
ENT.PrintName = "Gyrojet Pipe Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/Items/AR2_Grenade.mdl"
|
||||
ENT.CollisionSphere = false
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 128, 100)
|
||||
ENT.FlareLife = 0.1
|
||||
|
||||
ENT.IsRocket = false
|
||||
ENT.InstantFuse = true
|
||||
ENT.ImpactFuse = false
|
||||
ENT.Delay = 1.5
|
||||
|
||||
ENT.AudioLoop = false
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
if IsValid(data.HitEntity) and (data.HitEntity:IsPlayer() or data.HitEntity:IsNPC() or data.HitEntity:IsNextBot()) then
|
||||
self:Detonate()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local inflictor = attacker.GetWeapon and attacker:GetWeapon("tacrp_sd_gyrojet")
|
||||
local dmg = inflictor and inflictor.GetValue and inflictor:GetValue("Damage_Max") or 75
|
||||
if attacker:IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool() then
|
||||
dmg = dmg * 0.25
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 150, dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetNormal(self:GetForward())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 80, 110, 0.75)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
end
|
||||
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:MakeSmoke()
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(2)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(10, 12))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 25)
|
||||
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.6, 0.8))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 256))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
@@ -0,0 +1,56 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_gyrojet"
|
||||
ENT.PrintName = "Ratshot Gyrojet Round"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(155, 155, 255, 255)
|
||||
ENT.FlareLife = 0.4
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:SetTrigger(true)
|
||||
self:UseTriggerBounds(true, 48)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:StartTouch(ent)
|
||||
if SERVER and ent ~= self:GetOwner() and (ent:IsNPC() or ent:IsPlayer() or ent:IsNextBot()) then
|
||||
self:Detonate()
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local inflictor = attacker.GetWeapon and attacker:GetWeapon("tacrp_sd_gyrojet")
|
||||
local damage = inflictor and inflictor:GetValue("Damage_Max") or 50
|
||||
if attacker:IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool() then
|
||||
damage = damage * 0.25
|
||||
end
|
||||
local src = self:GetPos() -- + dir * 32
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(4)
|
||||
fx:SetRadius(8)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, src, 200, damage)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 90, 110, 0.75)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 90, 175)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
257
garrysmod/addons/tacrp/lua/entities/tacrp_proj_knife.lua
Normal file
257
garrysmod/addons/tacrp/lua/entities/tacrp_proj_knife.lua
Normal file
@@ -0,0 +1,257 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Thrown Knife"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/w_knife.mdl"
|
||||
|
||||
ENT.IsRocket = false
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
local path = "tacrp/weapons/knife/"
|
||||
ENT.Sound_MeleeHit = {
|
||||
path .. "/scrape_metal-1.wav",
|
||||
path .. "/scrape_metal-2.wav",
|
||||
path .. "/scrape_metal-3.wav",
|
||||
}
|
||||
ENT.Sound_MeleeHitBody = {
|
||||
path .. "/flesh_hit-1.wav",
|
||||
path .. "/flesh_hit-2.wav",
|
||||
path .. "/flesh_hit-3.wav",
|
||||
path .. "/flesh_hit-4.wav",
|
||||
path .. "/flesh_hit-5.wav",
|
||||
}
|
||||
|
||||
ENT.Damage = 35
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetDragCoefficient(2)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
if self.Impacted then return end
|
||||
self.Impacted = true
|
||||
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
if IsValid(tgt) then
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
dmg:SetDamage(self.Damage)
|
||||
dmg:SetDamageType(self.DamageType or DMG_SLASH)
|
||||
dmg:SetDamageForce(d * 10000)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
|
||||
local tgtpos = data.HitPos
|
||||
if (tgt:IsPlayer() or tgt:IsNPC() or tgt:IsNextBot()) then
|
||||
if (tgt:GetNWFloat("TacRPLastBashed", 0) + 3 >= CurTime()
|
||||
or (tgt:GetNWFloat("TacRPStunStart", 0) + tgt:GetNWFloat("TacRPStunDur", 0) >= CurTime())) then
|
||||
dmg:ScaleDamage(1.5)
|
||||
tgt:EmitSound("weapons/crossbow/bolt_skewer1.wav", 80, 110)
|
||||
end
|
||||
|
||||
-- Check if the knife is a headshot
|
||||
-- Either the head is the closest bodygroup, or the direction is quite on point
|
||||
local headpos = nil
|
||||
local pos = data.HitPos + d * 8
|
||||
local hset = tgt:GetHitboxSet()
|
||||
local hdot, bhg, bdist, hdist = 0, 0, math.huge, math.huge
|
||||
for i = 0, tgt:GetHitBoxCount(hset) or 0 do
|
||||
|
||||
local bone = tgt:GetHitBoxBone(i, hset)
|
||||
local mtx = bone and tgt:GetBoneMatrix(bone)
|
||||
if !mtx then continue end
|
||||
local hpos = mtx:GetTranslation()
|
||||
local dot = (hpos - data.HitPos):GetNormalized():Dot(d)
|
||||
local dist = (hpos - pos):LengthSqr()
|
||||
|
||||
if tgt:GetHitBoxHitGroup(i, hset) == HITGROUP_HEAD then
|
||||
hdot = dot
|
||||
hdist = dist
|
||||
headpos = hpos
|
||||
end
|
||||
if dist < bdist then
|
||||
bdist = dist
|
||||
bhg = tgt:GetHitBoxHitGroup(i, hset)
|
||||
tgtpos = hpos
|
||||
end
|
||||
end
|
||||
|
||||
if bhg == HITGROUP_HEAD or (hdot >= 0.85 and hdist < 2500) then
|
||||
dmg:ScaleDamage(2)
|
||||
tgt:EmitSound("player/headshot" .. math.random(1, 2) .. ".wav", 80, 105)
|
||||
tgtpos = headpos
|
||||
end
|
||||
|
||||
self:EmitSound(istable(self.Sound_MeleeHitBody) and self.Sound_MeleeHitBody[math.random(1, #self.Sound_MeleeHitBody)] or self.Sound_MeleeHitBody, 80, 110, 1)
|
||||
-- self:EmitSound("tacrp/weapons/knife/flesh_hit-" .. math.random(1, 5) .. ".wav", 80, 110, 1)
|
||||
|
||||
-- local ang = data.OurOldVelocity:Angle()
|
||||
-- local fx = EffectData()
|
||||
-- fx:SetStart(data.HitPos - d * 4)
|
||||
-- fx:SetOrigin(data.HitPos)
|
||||
-- fx:SetNormal(d)
|
||||
-- fx:SetAngles(-ang)
|
||||
-- fx:SetEntity(tgt)
|
||||
-- fx:SetDamageType(DMG_SLASH)
|
||||
-- fx:SetSurfaceProp(data.TheirSurfaceProps)
|
||||
-- util.Effect("Impact", fx)
|
||||
|
||||
else
|
||||
dmg:SetDamageForce(d * 30000)
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
if SERVER then
|
||||
self:EmitSound(istable(self.Sound_MeleeHit) and self.Sound_MeleeHit[math.random(1, #self.Sound_MeleeHit)] or self.Sound_MeleeHit, 80, 110, 1)
|
||||
end
|
||||
end
|
||||
|
||||
-- tgt:TakeDamageInfo(dmg)
|
||||
|
||||
local atktr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = tgtpos,
|
||||
filter = self
|
||||
})
|
||||
|
||||
TacRP.CancelBodyDamage(tgt, dmg, atktr.HitGroup)
|
||||
tgt:DispatchTraceAttack(dmg, atktr)
|
||||
else
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = self.Damage,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = ang:Forward(),
|
||||
Src = data.HitPos - ang:Forward(),
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetInflictor(IsValid(self.Inflictor) and self.Inflictor or self)
|
||||
if tr.HitSky then
|
||||
SafeRemoveEntity(self)
|
||||
else
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
if SERVER then
|
||||
self:EmitSound(istable(self.Sound_MeleeHit) and self.Sound_MeleeHit[math.random(1, #self.Sound_MeleeHit)] or self.Sound_MeleeHit, 80, 110, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
-- self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
|
||||
if self.DamageType == DMG_SLASH and (tgt:IsWorld() or (IsValid(tgt) and tgt:GetPhysicsObject():IsValid())) then
|
||||
local angles = data.OurOldVelocity:Angle()
|
||||
angles:RotateAroundAxis(self:GetRight(), -90)
|
||||
self:GetPhysicsObject():Sleep()
|
||||
|
||||
timer.Simple(0.01, function()
|
||||
if IsValid(self) and tgt:IsWorld() or (IsValid(tgt) and (!(tgt:IsNPC() or tgt:IsPlayer()) or tgt:Health() > 0)) then
|
||||
if !tgt:IsWorld() then
|
||||
self:SetSolid(SOLID_NONE)
|
||||
end
|
||||
self:SetMoveType(MOVETYPE_NONE)
|
||||
|
||||
local f = {self, self:GetOwner()}
|
||||
table.Add(f, tgt:GetChildren())
|
||||
local tr = util.TraceLine({
|
||||
start = data.HitPos - data.OurOldVelocity,
|
||||
endpos = data.HitPos + data.OurOldVelocity,
|
||||
filter = f,
|
||||
mask = MASK_SOLID,
|
||||
ignoreworld = true,
|
||||
})
|
||||
|
||||
local bone = (tr.Entity == tgt) and tr.PhysicsBone == 0
|
||||
and tr.Entity:GetHitBoxBone(tr.HitBox, tr.Entity:GetHitboxSet())
|
||||
or tr.PhysicsBone or -1
|
||||
local matrix = tgt:GetBoneMatrix(bone)
|
||||
if tr.Entity == tgt and matrix then
|
||||
local bpos = matrix:GetTranslation()
|
||||
local bang = matrix:GetAngles()
|
||||
self:SetPos(data.HitPos)
|
||||
self:FollowBone(tgt, bone)
|
||||
local n_pos, n_ang = WorldToLocal(tr.HitPos + tr.HitNormal * self:GetModelRadius() * 0.5, angles, bpos, bang)
|
||||
self:SetLocalPos(n_pos)
|
||||
self:SetLocalAngles(n_ang)
|
||||
debugoverlay.Cross(pos, 8, 5, Color(255, 0, 255), true)
|
||||
else
|
||||
self:SetAngles(angles)
|
||||
self:SetPos(data.HitPos - data.OurOldVelocity:GetNormalized() * self:GetModelRadius() * 0.5)
|
||||
if !tgt:IsWorld() then
|
||||
self:SetParent(tgt)
|
||||
end
|
||||
end
|
||||
elseif IsValid(self) then
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(data.OurNewVelocity * 0.5)
|
||||
self:GetPhysicsObject():SetAngleVelocityInstantaneous(data.OurOldAngularVelocity * 0.5)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
timer.Simple(0.01, function()
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
if self.HasAmmo then
|
||||
self:SetTrigger(true)
|
||||
self:SetOwner(NULL)
|
||||
end
|
||||
end)
|
||||
|
||||
timer.Simple(5, function()
|
||||
if IsValid(self) then
|
||||
self:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self:SetRenderFX(kRenderFxFadeFast)
|
||||
end
|
||||
end)
|
||||
SafeRemoveEntityDelayed(self, 7)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function ENT:Touch(ent)
|
||||
if self.HasAmmo and ent:IsPlayer() and (IsValid(self.Inflictor) and ent == self.Inflictor:GetOwner()) then
|
||||
self.HasAmmo = false
|
||||
ent:GiveAmmo(1, "xbowbolt")
|
||||
self:Remove()
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "TacRP_KnifeProj", function(ent)
|
||||
if (ent:IsPlayer() or ent:IsNPC()) and ent:Health() < 0 then
|
||||
for _, proj in pairs(ent:GetChildren()) do
|
||||
if proj:GetClass() == "tacrp_proj_knife" then proj:Remove() end
|
||||
end
|
||||
end
|
||||
end)
|
||||
@@ -0,0 +1,49 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "KS-23 Flashbang"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
ENT.ExplodeOnImpact = true
|
||||
|
||||
ENT.Delay = 0.2
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/flashbang_explode-1.wav",
|
||||
}
|
||||
|
||||
ENT.AudioLoop = ""
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
function ENT:Detonate()
|
||||
// util.BlastDamage(self, self:GetOwner(), self:GetPos(), 150, 25)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
self:Remove()
|
||||
return
|
||||
else
|
||||
fx:SetRadius(328)
|
||||
util.Effect("TacRP_flashexplosion", fx)
|
||||
end
|
||||
|
||||
TacRP.Flashbang(self, self:GetPos(), 328, 1, 0.1, 0.3)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
85
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202.lua
Normal file
85
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202.lua
Normal file
@@ -0,0 +1,85 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Rocket"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 200, 150)
|
||||
|
||||
ENT.Radius = 400
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(attacker)
|
||||
|
||||
// Apply a small instance of damage to ignite first, before doing the real damage
|
||||
// This will ensure if the target dies it is on fire first (so it can ignite its ragdolls etc.)
|
||||
dmg:SetDamageType(DMG_SLOWBURN)
|
||||
dmg:SetDamage(5)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
dmg:SetDamageType(DMG_BLAST + DMG_BURN)
|
||||
dmg:SetDamage(250 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
self:ImpactTraceAttack(ent, 100 * mult, 100)
|
||||
|
||||
local decaltr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + self:GetForward() * 128,
|
||||
filter = self,
|
||||
mask = MASK_SOLID,
|
||||
})
|
||||
util.Decal("Scorch", decaltr.StartPos, decaltr.HitPos - (decaltr.HitNormal * 16), self)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("tacrp_m202_explode", fx)
|
||||
self:EmitSound("^weapons/explode5.wav", 100, 110)
|
||||
self:EmitSound("^ambient/fire/ignite.wav", 110, 110)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
local burn = {
|
||||
tacrp_proj_m202 = 12,
|
||||
tacrp_proj_p2a1_flare = 4,
|
||||
tacrp_proj_p2a1_paraflare = 4,
|
||||
tacrp_proj_p2a1_incendiary = 8,
|
||||
}
|
||||
|
||||
hook.Add("PostEntityTakeDamage", "tacrp_pa_m202", function(ent, dmginfo, took)
|
||||
local infl = dmginfo:GetInflictor()
|
||||
if took and IsValid(infl) and burn[infl:GetClass()] and dmginfo:IsDamageType(DMG_SLOWBURN) then
|
||||
local fr = Lerp(1 - (ent:GetPos():Distance(infl:GetPos())) / infl.Radius, 0.25, 1)
|
||||
ent:Ignite(fr * burn[infl:GetClass()] * (ent:IsPlayer() and 1 or 2.5))
|
||||
end
|
||||
end)
|
||||
134
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_apers.lua
Normal file
134
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_apers.lua
Normal file
@@ -0,0 +1,134 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Rocket (APERS)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(200, 200, 255)
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:PhysicsCollide(data, collider)
|
||||
if self:Impact(data, collider) then
|
||||
return
|
||||
end
|
||||
|
||||
BaseClass.PhysicsCollide(self, data, collider)
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if self.SpawnTime + self.SafetyFuse < CurTime() and (self.NextTraceTime or 0) < CurTime() then
|
||||
self.NextTraceTime = CurTime() + 0.1
|
||||
|
||||
local dir = self:GetVelocity():GetNormalized()
|
||||
local deg = 1 //math.Clamp(1.5 - dir:Cross(Vector(0, 0, -1)):Length(), 0.5, 1)
|
||||
|
||||
local tr = util.TraceHull({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + dir * (1024 * deg),
|
||||
filter = self,
|
||||
mins = Vector(-32, -32, -32),
|
||||
maxs = Vector(32, 32, 32)
|
||||
})
|
||||
if tr.Hit then
|
||||
self:PreDetonate()
|
||||
end
|
||||
end
|
||||
|
||||
BaseClass.Think(self)
|
||||
end
|
||||
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local src = self:GetPos() - dir * 64
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(8)
|
||||
fx:SetScale(2)
|
||||
fx:SetRadius(8)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
|
||||
local tr = util.TraceHull({
|
||||
start = src,
|
||||
endpos = src + dir * 1024,
|
||||
filter = self,
|
||||
mins = Vector(-16, -16, -8),
|
||||
maxs = Vector(16, 16, 8)
|
||||
})
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(1)
|
||||
fx:SetRadius(2)
|
||||
fx:SetNormal(dir)
|
||||
for i = 1, math.floor(tr.Fraction * 6) do
|
||||
fx:SetOrigin(tr.StartPos + tr.Normal * (i / 6) * 1024)
|
||||
util.Effect("Sparks", fx)
|
||||
end
|
||||
end
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 5,
|
||||
Force = 1,
|
||||
Distance = 1024,
|
||||
HullSize = 16,
|
||||
Num = 48,
|
||||
Tracer = 1,
|
||||
Src = src,
|
||||
Dir = dir,
|
||||
Spread = Vector(1, 1, 0),
|
||||
IgnoreEntity = self,
|
||||
})
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BULLET + DMG_BLAST)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
for _, ent in pairs(ents.FindInCone(src, dir, 1024, 0.707)) do
|
||||
local tr = util.QuickTrace(src, ent:GetPos() - src, {self, ent})
|
||||
if tr.Fraction == 1 then
|
||||
dmg:SetDamage(mult * 60 * math.Rand(0.75, 1) * Lerp((ent:GetPos():DistToSqr(src) / 1048576) ^ 0.5, 1, 0.25) * (self.NPCDamage and 0.5 or 1) * mult)
|
||||
if !ent:IsOnGround() then dmg:ScaleDamage(1.5) end
|
||||
ent:TakeDamageInfo(dmg)
|
||||
end
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, src, 256, 50 * mult)
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125, 100)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 100, 200)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
205
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_harpoon.lua
Normal file
205
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_harpoon.lua
Normal file
@@ -0,0 +1,205 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Harpoon"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/props_junk/harpoon002a.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
local path = "tacrp/weapons/knife/"
|
||||
ENT.Sound_MeleeHit = {
|
||||
path .. "/scrape_metal-1.wav",
|
||||
path .. "/scrape_metal-2.wav",
|
||||
path .. "/scrape_metal-3.wav",
|
||||
}
|
||||
ENT.Sound_MeleeHitBody = {
|
||||
path .. "/flesh_hit-1.wav",
|
||||
path .. "/flesh_hit-2.wav",
|
||||
path .. "/flesh_hit-3.wav",
|
||||
path .. "/flesh_hit-4.wav",
|
||||
path .. "/flesh_hit-5.wav",
|
||||
}
|
||||
|
||||
function ENT:OnInitialize()
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetMass(25)
|
||||
self:GetPhysicsObject():SetDragCoefficient(10)
|
||||
self:Ignite(30)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
local forward = data.OurOldVelocity:Dot(self:GetAngles():Forward())
|
||||
if forward <= 100 then return true end
|
||||
if IsValid(tgt) then
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
data.HitEntity:Ignite(math.Rand(5, 10), 128)
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_CLUB)
|
||||
dmginfo:SetDamage(self.NPCDamage and 25 or math.Clamp(forward / 70, 10, 200))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
else
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
if SERVER then
|
||||
self:EmitSound(istable(self.Sound_MeleeHit) and self.Sound_MeleeHit[math.random(1, #self.Sound_MeleeHit)] or self.Sound_MeleeHit, 80, 110, 1)
|
||||
end
|
||||
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = self.Damage,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = ang:Forward(),
|
||||
Src = data.HitPos - ang:Forward(),
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetDamageType(DMG_SLASH)
|
||||
dmginfo:SetInflictor(attacker)
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
if tgt:IsWorld() or (IsValid(tgt) and tgt:GetPhysicsObject():IsValid()) then
|
||||
local angles = data.OurOldVelocity:Angle()
|
||||
self:GetPhysicsObject():Sleep()
|
||||
|
||||
timer.Simple(0, function()
|
||||
if tgt:IsWorld() or (IsValid(tgt) and (!(tgt:IsNPC() or tgt:IsPlayer()) or tgt:Health() > 0)) then
|
||||
self:SetSolid(SOLID_NONE)
|
||||
self:SetMoveType(MOVETYPE_NONE)
|
||||
|
||||
local f = {self, self:GetOwner()}
|
||||
table.Add(f, tgt:GetChildren())
|
||||
local tr = util.TraceLine({
|
||||
start = data.HitPos - data.OurOldVelocity,
|
||||
endpos = data.HitPos + data.OurOldVelocity,
|
||||
filter = f,
|
||||
mask = MASK_SOLID,
|
||||
ignoreworld = true,
|
||||
})
|
||||
|
||||
local bone = (tr.Entity == tgt) and tr.PhysicsBone == 0
|
||||
and tr.Entity:GetHitBoxBone(tr.HitBox, tr.Entity:GetHitboxSet())
|
||||
or tr.PhysicsBone or -1
|
||||
local matrix = tgt:GetBoneMatrix(bone)
|
||||
if tr.Entity == tgt and matrix then
|
||||
local bpos = matrix:GetTranslation()
|
||||
local bang = matrix:GetAngles()
|
||||
self:SetPos(data.HitPos)
|
||||
self:FollowBone(tgt, bone)
|
||||
local n_pos, n_ang = WorldToLocal(tr.HitPos + tr.HitNormal * self:GetModelRadius() * 0.5, angles, bpos, bang)
|
||||
self:SetLocalPos(n_pos)
|
||||
self:SetLocalAngles(n_ang)
|
||||
debugoverlay.Cross(pos, 8, 5, Color(255, 0, 255), true)
|
||||
else
|
||||
self:SetAngles(angles)
|
||||
self:SetPos(data.HitPos - data.OurOldVelocity:GetNormalized() * self:GetModelRadius() * 0.5)
|
||||
if !tgt:IsWorld() then
|
||||
self:SetParent(tgt)
|
||||
end
|
||||
end
|
||||
else
|
||||
self:GetPhysicsObject():SetVelocity(data.OurOldVelocity * 0.75)
|
||||
self:GetPhysicsObject():SetAngleVelocity(data.OurOldAngularVelocity)
|
||||
self.Armed = false
|
||||
end
|
||||
end)
|
||||
end
|
||||
timer.Simple(5, function()
|
||||
if IsValid(self) then
|
||||
self:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self:SetRenderFX(kRenderFxFadeFast)
|
||||
end
|
||||
end)
|
||||
SafeRemoveEntityDelayed(self, 7)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local g = Vector(0, 0, -9.81)
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if !self.Armed and phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
self:SetAngles(v:Angle())
|
||||
phys:SetVelocityInstantaneous(v * 0.985 + g)
|
||||
end
|
||||
|
||||
-- local v = phys:GetVelocity()
|
||||
-- self:SetAngles(v:Angle() + Angle(2, 0, 0))
|
||||
-- phys:SetVelocityInstantaneous(self:GetForward() * v:Length())
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and self:GetVelocity():Length() >= 100 then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(100)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 16)
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 0.75))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 15))
|
||||
|
||||
local fire = emitter:Add("effects/fire_cloud" .. math.random(1, 2), pos)
|
||||
fire:SetStartAlpha(150)
|
||||
fire:SetEndAlpha(0)
|
||||
fire:SetStartSize(math.Rand(2, 4))
|
||||
fire:SetEndSize(math.Rand(8, 16))
|
||||
fire:SetRoll(math.Rand(-180, 180))
|
||||
fire:SetRollDelta(math.Rand(-1, 1))
|
||||
fire:SetVelocity(VectorRand() * 16 + self:GetUp() * 16)
|
||||
fire:SetLighting(false)
|
||||
fire:SetDieTime(math.Rand(0.1, 0.3))
|
||||
fire:SetGravity(Vector(0, 0, 50))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
47
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_he.lua
Normal file
47
garrysmod/addons/tacrp/lua/entities/tacrp_proj_m202_he.lua
Normal file
@@ -0,0 +1,47 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Rocket (HE)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 200)
|
||||
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 350, 150 * mult)
|
||||
self:ImpactTraceAttack(ent, 800 * mult, 13000)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,44 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "M202 Rocket (Smoke)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_smoke_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
91
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_c4.lua
Normal file
91
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_c4.lua
Normal file
@@ -0,0 +1,91 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "C4"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/c4_charge-1.mdl"
|
||||
|
||||
ENT.Sticky = true
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = true // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.Defusable = true
|
||||
ENT.DefuseOnDamage = true
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.Delay = 0.5
|
||||
|
||||
ENT.PickupAmmo = "ti_c4"
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/breaching_charge-1.wav"
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
local dmg = TacRP.ConVars["c4_damage"]:GetFloat()
|
||||
local rad = TacRP.ConVars["c4_radius"]:GetFloat()
|
||||
local p = self:GetPos() + self:GetForward() * 8
|
||||
|
||||
util.BlastDamage(self, attacker, p, rad / 2, dmg)
|
||||
util.BlastDamage(self, attacker, p, rad, dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(p)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
|
||||
if rad >= 400 then
|
||||
local count = 8
|
||||
for i = 1, count do
|
||||
local tr = util.TraceLine({
|
||||
start = p,
|
||||
endpos = p + Angle(0, i / count * 360, 0):Forward() * (rad - 200) * math.Rand(0.9, 1.1),
|
||||
mask = MASK_SHOT,
|
||||
filter = self,
|
||||
})
|
||||
fx:SetOrigin(tr.HitPos)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:SetParent(NULL)
|
||||
for _, door in pairs(ents.FindInSphere(self:GetPos(), 256)) do
|
||||
if IsValid(door) and string.find(door:GetClass(), "door") and !door.TacRP_DoorBusted then
|
||||
local vel = (door:GetPos() - self:GetPos()):GetNormalized() * 200000
|
||||
for _, otherDoor in pairs(ents.FindInSphere(door:GetPos(), 72)) do
|
||||
if door != otherDoor and otherDoor:GetClass() == door:GetClass() then
|
||||
TacRP.DoorBust(otherDoor, vel, attacker)
|
||||
break
|
||||
end
|
||||
end
|
||||
TacRP.DoorBust(door, vel, attacker)
|
||||
end
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:Stuck()
|
||||
// you are already dead
|
||||
if IsValid(self:GetParent()) and self:GetParent():IsPlayer() and !IsValid(self:GetParent().nadescream) then
|
||||
self:GetParent().nadescream = self
|
||||
self:GetParent():EmitSound("vo/npc/male01/ohno.wav")
|
||||
end
|
||||
end
|
||||
149
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_charge.lua
Normal file
149
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_charge.lua
Normal file
@@ -0,0 +1,149 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "C4"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/door_charge-1.mdl"
|
||||
|
||||
ENT.Sticky = true
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
ENT.StickyFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.Defusable = false
|
||||
ENT.DefuseOnDamage = true
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.PickupAmmo = "ti_charge"
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/breaching_charge-1.wav"
|
||||
}
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Entity", 0, "Weapon")
|
||||
self:NetworkVar("Bool", 0, "Remote")
|
||||
self:NetworkVar("Float", 0, "ArmTime")
|
||||
end
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Initialize()
|
||||
if IsValid(self:GetOwner()) and self:GetOwner():IsPlayer() and IsValid(self:GetOwner():GetActiveWeapon()) and self:GetOwner():GetActiveWeapon():GetClass() == "tacrp_c4_detonator" then
|
||||
self.StickyFuse = false
|
||||
self.RemoteFuse = true
|
||||
self.Delay = 0.5
|
||||
self.Defusable = true
|
||||
self:SetRemote(true)
|
||||
end
|
||||
|
||||
BaseClass.Initialize(self)
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = IsValid(self.Attacker) and self.Attacker or self:GetOwner()
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), TacRP.ConVars["charge_radius"]:GetFloat(), TacRP.ConVars["charge_damage"]:GetFloat())
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetNormal(self:GetForward())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 110)
|
||||
|
||||
local door = self:GetParent()
|
||||
self:SetParent(NULL)
|
||||
|
||||
if IsValid(door) and string.find(door:GetClass(), "door") then
|
||||
local vel = self:GetForward() * -50000
|
||||
for _, otherDoor in pairs(ents.FindInSphere(door:GetPos(), 72)) do
|
||||
if door != otherDoor and otherDoor:GetClass() == door:GetClass() then
|
||||
TacRP.DoorBust(otherDoor, vel, attacker)
|
||||
break
|
||||
end
|
||||
end
|
||||
TacRP.DoorBust(door, vel, attacker)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:Stuck()
|
||||
|
||||
sound.EmitHint(SOUND_DANGER, self:GetPos(), 256, 2, self)
|
||||
|
||||
self:SetArmTime(CurTime())
|
||||
if !self:GetRemote() then
|
||||
local ttt = TacRP.GetBalanceMode() == TacRP.BALANCE_TTT
|
||||
self:EmitSound("weapons/c4/c4_beep1.wav", ttt and 60 or 80, 110)
|
||||
timer.Create("breachbeep_" .. self:EntIndex(), 0.25, 7, function()
|
||||
if !IsValid(self) then return end
|
||||
self:EmitSound("weapons/c4/c4_beep1.wav", ttt and 60 or 80, 110)
|
||||
end)
|
||||
end
|
||||
|
||||
// you are already dead
|
||||
if IsValid(self:GetParent()) and self:GetParent():IsPlayer() and !IsValid(self:GetParent().nadescream) then
|
||||
self:GetParent().nadescream = self
|
||||
if self:GetRemote() then
|
||||
self:GetParent():EmitSound("vo/npc/male01/ohno.wav")
|
||||
else
|
||||
self:GetParent():EmitSound("vo/npc/male01/no0" .. math.random(1, 2) .. ".wav")
|
||||
end
|
||||
end
|
||||
|
||||
if VJ then
|
||||
self.Zombies = {}
|
||||
for _, x in ipairs(ents.FindInSphere(self:GetPos(), 512)) do
|
||||
if x:IsNPC() and string.find(x:GetClass(),"npc_vj_l4d_com_") and x.Zombie_CanHearPipe == true and x.Zombie_NextPipBombT < CurTime() then
|
||||
x.Zombie_NextPipBombT = CurTime() + 3
|
||||
table.insert(x.VJ_AddCertainEntityAsEnemy,self)
|
||||
x:AddEntityRelationship(self, D_HT, 99)
|
||||
x.MyEnemy = self
|
||||
x:SetEnemy(self)
|
||||
table.insert(self.Zombies, x)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnThink()
|
||||
if VJ and self.Zombies then
|
||||
for _, v in ipairs(self.Zombies) do
|
||||
if IsValid(v) then
|
||||
v:SetLastPosition(self:GetPos())
|
||||
v:VJ_TASK_GOTO_LASTPOS()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local clr_timed = Color(255, 0, 0)
|
||||
local clr_remote = Color(0, 255, 0)
|
||||
|
||||
local mat = Material("sprites/light_glow02_add")
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if (self:GetRemote() or self:GetArmTime() > 0) and math.ceil((CurTime() - self:GetArmTime()) * (self:GetRemote() and 2 or 8)) % 2 == 1 then
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + self:GetAngles():Up() * 7.5 + self:GetAngles():Right() * -4.5 + self:GetAngles():Forward() * 2, 8, 8, self:GetRemote() and clr_remote or clr_timed)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,94 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Flash Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/flashbang.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 1.5
|
||||
|
||||
ENT.SoundHint = true
|
||||
ENT.SoundHintDelay = 0.5
|
||||
ENT.SoundHintRadius = 728
|
||||
ENT.SoundHintDuration = 1
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/flashbang_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/flashbang_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/flashbang_bounce-3.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/flashbang_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageType(engine.ActiveGamemode() == "terrortown" and DMG_DIRECT or DMG_SONIC)
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetDamage(3)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 728)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
self:Remove()
|
||||
return
|
||||
else
|
||||
fx:SetRadius(728)
|
||||
util.Effect("TacRP_flashexplosion", fx)
|
||||
end
|
||||
|
||||
TacRP.Flashbang(self, self:GetPos(), 728, 3, 0.25, 0.5)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and (self.Tick or 0) % 5 == 0 then
|
||||
local pos = self:GetPos() + VectorRand() * 2
|
||||
local emitter = ParticleEmitter(pos)
|
||||
|
||||
local smoke = emitter:Add("effects/spark", pos)
|
||||
|
||||
smoke:SetVelocity( VectorRand() * 32 )
|
||||
smoke:SetStartAlpha( 255 )
|
||||
smoke:SetEndAlpha( 0 )
|
||||
smoke:SetStartSize( 2 )
|
||||
smoke:SetEndSize( 0 )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-32, 32) )
|
||||
smoke:SetColor( 255, 255, 255 )
|
||||
smoke:SetAirResistance( 125 )
|
||||
smoke:SetPos( pos )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 1 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetDieTime(math.Rand(2, 3))
|
||||
smoke:SetGravity(Vector(0, 0, 4))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
self.Tick = (self.Tick or 0) + 1
|
||||
end
|
||||
59
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_frag.lua
Normal file
59
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_frag.lua
Normal file
@@ -0,0 +1,59 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Frag Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/frag.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.SoundHint = true
|
||||
ENT.SoundHintDelay = 1
|
||||
ENT.SoundHintRadius = 512
|
||||
ENT.SoundHintDuration = 1
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/frag_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/frag_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/frag_bounce-3.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
local dmg = TacRP.ConVars["frag_damage"]:GetFloat()
|
||||
if self.ImpactFuse then dmg = dmg * 0.5 end
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), TacRP.ConVars["frag_radius"]:GetFloat(), dmg)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
90
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_gas.lua
Normal file
90
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_gas.lua
Normal file
@@ -0,0 +1,90 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Gas Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/gas-1"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.SoundHint = true
|
||||
ENT.SoundHintDelay = 1
|
||||
ENT.SoundHintRadius = 512
|
||||
ENT.SoundHintDuration = 1
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
// util.BlastDamage(self, attacker, self:GetPos(), 300, 10)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_gas_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 16)
|
||||
smoke:SetColor(125, 150, 50)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 0.75))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 15))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
88
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_heal.lua
Normal file
88
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_heal.lua
Normal file
@@ -0,0 +1,88 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Medi-Gas Canister"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/heal-1"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 5
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
// util.BlastDamage(self, attacker, self:GetPos(), 300, 10)
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_heal_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
ENT.NextSmokeTime = 0
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and self.NextSmokeTime < CurTime() then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(75)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(16, 32))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 42)
|
||||
|
||||
smoke:SetColor(125, 25, 125)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(1, 1.5))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 15))
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.NextSmokeTime = CurTime() + 0.025
|
||||
end
|
||||
end
|
||||
55
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_nuke.lua
Normal file
55
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_nuke.lua
Normal file
@@ -0,0 +1,55 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Nuke"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/props_misc/briefcase_bomb-1.mdl"
|
||||
|
||||
ENT.Sticky = false
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = true // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.Defusable = true
|
||||
ENT.PickupAmmo = "ti_nuke"
|
||||
|
||||
ENT.Delay = 0.5
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"ambient/explosions/explode_6.wav"
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
self:Remove()
|
||||
return
|
||||
else
|
||||
util.Effect("TacRP_nukeexplosion", fx)
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 1024, 100000)
|
||||
|
||||
local cloud = ents.Create( "TacRP_nuke_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 149)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
324
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_rock.lua
Normal file
324
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_rock.lua
Normal file
@@ -0,0 +1,324 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Rock"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/props_debris/concrete_chunk05g.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.Delay = 0
|
||||
|
||||
ENT.AllowFunny = true
|
||||
|
||||
ENT.ExtraModels = {
|
||||
"models/props_junk/PopCan01a.mdl",
|
||||
"models/Gibs/HGIBS.mdl",
|
||||
"models/props_junk/garbage_glassbottle003a.mdl",
|
||||
"models/props_junk/garbage_glassbottle001a.mdl",
|
||||
"models/props_junk/garbage_glassbottle002a.mdl",
|
||||
"models/props_junk/garbage_metalcan001a.mdl",
|
||||
"models/props_junk/garbage_metalcan002a.mdl",
|
||||
"models/props_junk/GlassBottle01a.mdl",
|
||||
"models/props_junk/garbage_coffeemug001a.mdl",
|
||||
"models/props_junk/glassjug01.mdl",
|
||||
"models/props_lab/jar01b.mdl",
|
||||
"models/props_junk/watermelon01.mdl",
|
||||
"models/props_junk/CinderBlock01a.mdl",
|
||||
"models/props_junk/MetalBucket01a.mdl",
|
||||
"models/props_junk/metal_paintcan001a.mdl",
|
||||
"models/Gibs/Antlion_gib_Large_2.mdl",
|
||||
"models/props_junk/garbage_plasticbottle003a.mdl",
|
||||
"models/props_junk/garbage_plasticbottle002a.mdl",
|
||||
"models/props_junk/garbage_plasticbottle001a.mdl",
|
||||
"models/props_junk/terracotta01.mdl",
|
||||
"models/props_junk/Shoe001a.mdl",
|
||||
"models/props_lab/frame002a.mdl",
|
||||
"models/props_lab/reciever01c.mdl",
|
||||
"models/props_lab/box01a.mdl",
|
||||
"models/props_junk/garbage_milkcarton001a.mdl",
|
||||
"models/props_lab/cactus.mdl",
|
||||
"models/props_lab/desklamp01.mdl",
|
||||
"models/Gibs/HGIBS_spine.mdl",
|
||||
"models/Gibs/wood_gib01a.mdl",
|
||||
"models/Gibs/wood_gib01b.mdl",
|
||||
"models/Gibs/wood_gib01c.mdl",
|
||||
"models/Gibs/wood_gib01d.mdl",
|
||||
"models/Gibs/wood_gib01e.mdl",
|
||||
"models/props_c17/oildrum001_explosive.mdl", // won't actually explode :trolleg:
|
||||
"models/props_interiors/SinkKitchen01a.mdl",
|
||||
"models/props_borealis/door_wheel001a.mdl",
|
||||
"models/hunter/blocks/cube025x025x025.mdl",
|
||||
"models/food/burger.mdl",
|
||||
"models/food/hotdog.mdl",
|
||||
"models/lamps/torch.mdl",
|
||||
"models/player/items/humans/top_hat.mdl",
|
||||
"models/dav0r/camera.mdl",
|
||||
"models/dav0r/tnt/tnt.mdl",
|
||||
"models/maxofs2d/camera.mdl",
|
||||
"models/maxofs2d/companion_doll.mdl",
|
||||
"models/maxofs2d/cube_tool.mdl",
|
||||
"models/maxofs2d/light_tubular.mdl",
|
||||
"models/maxofs2d/lamp_flashlight.mdl",
|
||||
"models/mechanics/gears/gear12x12.mdl",
|
||||
"models/mechanics/various/211.mdl",
|
||||
"models/props_phx/games/chess/white_rook.mdl",
|
||||
"models/props_phx/games/chess/white_queen.mdl",
|
||||
"models/props_phx/games/chess/white_pawn.mdl",
|
||||
"models/props_phx/games/chess/white_knight.mdl",
|
||||
"models/props_phx/games/chess/white_king.mdl",
|
||||
"models/props_phx/games/chess/white_dama.mdl",
|
||||
"models/props_phx/games/chess/black_rook.mdl",
|
||||
"models/props_phx/games/chess/black_queen.mdl",
|
||||
"models/props_phx/games/chess/black_pawn.mdl",
|
||||
"models/props_phx/games/chess/black_knight.mdl",
|
||||
"models/props_phx/games/chess/black_king.mdl",
|
||||
"models/props_phx/games/chess/black_dama.mdl",
|
||||
"models/props_phx/games/chess/black_bishop.mdl",
|
||||
"models/props_phx/misc/egg.mdl",
|
||||
"models/props_phx/misc/potato.mdl",
|
||||
"models/props_phx/misc/potato_launcher_explosive.mdl",
|
||||
"models/props_phx/misc/smallcannonball.mdl",
|
||||
"models/props_phx/misc/soccerball.mdl",
|
||||
"models/props_phx/misc/fender.mdl",
|
||||
"models/props_combine/breenbust.mdl",
|
||||
"models/props_combine/breenglobe.mdl",
|
||||
"models/props_combine/combinebutton.mdl",
|
||||
"models/props_combine/breenclock.mdl",
|
||||
"models/props_interiors/pot01a.mdl",
|
||||
"models/props_junk/garbage_bag001a.mdl",
|
||||
"models/props_lab/harddrive02.mdl",
|
||||
"models/props_lab/monitor02.mdl", // HAAAAAAX
|
||||
"models/props_lab/clipboard.mdl",
|
||||
"models/props_lab/tpplug.mdl",
|
||||
"models/props_pipes/valvewheel002a.mdl",
|
||||
"models/props_pipes/valve003.mdl",
|
||||
"models/props_rooftop/sign_letter_m001.mdl",
|
||||
"models/props_rooftop/sign_letter_f001b.mdl",
|
||||
"models/props_rooftop/sign_letter_u001b.mdl",
|
||||
"models/props_wasteland/speakercluster01a.mdl",
|
||||
"models/props_wasteland/prison_toilet01.mdl",
|
||||
"models/props_c17/streetsign001c.mdl",
|
||||
"models/props_c17/streetsign002b.mdl",
|
||||
"models/props_c17/streetsign003b.mdl",
|
||||
"models/props_c17/streetsign004e.mdl",
|
||||
"models/props_c17/streetsign004f.mdl",
|
||||
"models/props_c17/streetsign005b.mdl",
|
||||
"models/props_c17/streetsign005c.mdl",
|
||||
"models/props_c17/streetsign005d.mdl",
|
||||
"models/props_c17/playgroundTick-tack-toe_block01a.mdl",
|
||||
"models/props_c17/doll01.mdl",
|
||||
"models/props_c17/BriefCase001a.mdl",
|
||||
"models/props_c17/metalPot001a.mdl",
|
||||
"models/props_c17/metalPot002a.mdl",
|
||||
"models/props_canal/mattpipe.mdl",
|
||||
"models/extras/info_speech.mdl",
|
||||
"models/items/grenadeammo.mdl", // not a live one
|
||||
"models/props_c17/light_cagelight02_on.mdl",
|
||||
"models/props_c17/suitcase_passenger_physics.mdl",
|
||||
"models/props_citizen_tech/guillotine001a_wheel01.mdl",
|
||||
"models/props_interiors/bathtub01a.mdl", // now this is just absurd
|
||||
"models/props_junk/garbage_takeoutcarton001a.mdl",
|
||||
"models/props_junk/garbage_newspaper001a.mdl",
|
||||
"models/props_junk/sawblade001a.mdl",
|
||||
"models/props_lab/bewaredog.mdl",
|
||||
"models/props_lab/huladoll.mdl",
|
||||
"models/props_lab/powerbox02d.mdl",
|
||||
"models/props_lab/powerbox02b.mdl",
|
||||
"models/props_lab/powerbox02a.mdl",
|
||||
"models/weapons/w_bugbait.mdl",
|
||||
"models/weapons/w_alyx_gun.mdl",
|
||||
"models/weapons/w_crowbar.mdl",
|
||||
"models/weapons/w_smg1.mdl",
|
||||
"models/weapons/w_shotgun.mdl",
|
||||
"models/weapons/w_rocket_launcher.mdl",
|
||||
"models/weapons/w_pistol.mdl",
|
||||
"models/weapons/w_physics.mdl",
|
||||
"models/weapons/w_irifle.mdl",
|
||||
"models/weapons/w_357.mdl",
|
||||
"models/weapons/w_package.mdl",
|
||||
"models/weapons/w_pist_deagle.mdl",
|
||||
"models/weapons/w_pist_elite_single.mdl",
|
||||
"models/weapons/w_pist_glock18.mdl",
|
||||
"models/weapons/w_rif_ak47.mdl",
|
||||
"models/weapons/w_rif_m4a1.mdl",
|
||||
"models/weapons/w_shot_m3super90.mdl",
|
||||
"models/weapons/w_smg_mp5.mdl",
|
||||
"models/weapons/w_snip_awp.mdl",
|
||||
"models/weapons/w_crossbow.mdl",
|
||||
"models/weapons/w_eq_defuser.mdl",
|
||||
"models/weapons/w_toolgun.mdl",
|
||||
"models/weapons/w_missile_closed.mdl",
|
||||
"models/weapons/w_stunbaton.mdl",
|
||||
"models/weapons/w_annabelle.mdl",
|
||||
"models/roller.mdl",
|
||||
"models/pigeon.mdl",
|
||||
"models/headcrabclassic.mdl",
|
||||
"models/headcrab.mdl",
|
||||
"models/headcrabblack.mdl",
|
||||
"models/crow.mdl",
|
||||
"models/seagull.mdl",
|
||||
"models/kleiner.mdl",
|
||||
"models/gman.mdl",
|
||||
"models/manhack.mdl",
|
||||
|
||||
// CSS
|
||||
"models/props/cs_militia/bottle01.mdl",
|
||||
"models/props/cs_office/coffee_mug.mdl",
|
||||
"models/props/cs_office/computer_keyboard.mdl",
|
||||
"models/props/cs_office/water_bottle.mdl",
|
||||
"models/props/cs_office/projector_remote.mdl",
|
||||
"models/props/cs_office/phone.mdl",
|
||||
"models/props/cs_italy/bananna_bunch.mdl",
|
||||
"models/props/cs_italy/bananna.mdl",
|
||||
"models/props/cs_italy/orange.mdl",
|
||||
"models/props/de_tides/vending_turtle.mdl",
|
||||
}
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
if util.IsValidModel(TacRP.ConVars["rock_funny"]:GetString()) then
|
||||
self:SetModel(TacRP.ConVars["rock_funny"]:GetString())
|
||||
elseif self.AllowFunny and math.random() <= TacRP.ConVars["rock_funny"]:GetFloat() then
|
||||
local i = math.min(TacRP.ConVars["rock_funny"]:GetFloat() > 1 and TacRP.ConVars["rock_funny"]:GetInt() - 1 or math.random(1, #self.ExtraModels), #self.ExtraModels)
|
||||
local mdl = self.ExtraModels[i]
|
||||
self:SetModel(util.IsValidModel(mdl) and mdl or self.Model)
|
||||
else
|
||||
self:SetModel(self.Model)
|
||||
end
|
||||
|
||||
self:SetSkin(math.random(1, self:SkinCount()))
|
||||
|
||||
self:PhysicsInit(SOLID_VPHYSICS)
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
if self.Defusable then
|
||||
self:SetUseType(SIMPLE_USE)
|
||||
end
|
||||
self:PhysWake()
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:Remove()
|
||||
else
|
||||
phys:SetDragCoefficient(0)
|
||||
phys:SetMass(2)
|
||||
end
|
||||
|
||||
if self.IsRocket then
|
||||
phys:EnableGravity(false)
|
||||
end
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
|
||||
self.NPCDamage = IsValid(self:GetOwner()) and self:GetOwner():IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool()
|
||||
|
||||
if self.AudioLoop then
|
||||
self.LoopSound = CreateSound(self, self.AudioLoop)
|
||||
self.LoopSound:Play()
|
||||
end
|
||||
|
||||
if self.InstantFuse then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function ENT:PhysicsCollide(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
if IsValid(data.HitEntity) and data.HitEntity:GetClass() == "func_breakable_surf" then
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Inflictor = self,
|
||||
Damage = 0,
|
||||
Distance = 32,
|
||||
Tracer = 0,
|
||||
Src = self:GetPos(),
|
||||
Dir = data.OurOldVelocity:GetNormalized(),
|
||||
})
|
||||
local pos, ang, vel = self:GetPos(), self:GetAngles(), data.OurOldVelocity
|
||||
self:SetAngles(ang)
|
||||
self:SetPos(pos)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(vel * 0.5)
|
||||
return
|
||||
end
|
||||
|
||||
local prop1 = util.GetSurfaceData(data.OurSurfaceProps)
|
||||
local prop2 = util.GetSurfaceData(data.TheirSurfaceProps)
|
||||
|
||||
|
||||
if IsValid(data.HitEntity) and (self.LastDamage or 0) + 0.25 < CurTime() then
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamage(Lerp((data.OurOldVelocity:Length() - 500) / 2500, 4, 35))
|
||||
if self:GetModel() != self.Model then
|
||||
dmg:ScaleDamage(2)
|
||||
end
|
||||
dmg:SetDamageType(DMG_CRUSH + DMG_CLUB)
|
||||
dmg:SetDamageForce(data.OurOldVelocity)
|
||||
dmg:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmg)
|
||||
self.LastDamage = CurTime()
|
||||
self:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
elseif data.Speed >= 75 and (self.LastImpact or 0) + 0.1 < CurTime() then
|
||||
self.LastImpact = CurTime()
|
||||
self:EmitSound(self:GetModel() == self.Model and "physics/concrete/rock_impact_hard" .. math.random(1, 6) .. ".wav" or prop1.impactHardSound)
|
||||
elseif data.Speed >= 25 and (self.LastImpact or 0) + 0.1 < CurTime() then
|
||||
self.LastImpact = CurTime()
|
||||
self:EmitSound(self:GetModel() == self.Model and "physics/concrete/rock_impact_soft" .. math.random(1, 3) .. ".wav" or prop1.impactSoftSound)
|
||||
end
|
||||
|
||||
if !self.FirstHit then
|
||||
self.FirstHit = true
|
||||
self:EmitSound(prop2.bulletImpactSound)
|
||||
|
||||
if self:GetModel() == self.Model then
|
||||
self:EmitSound("physics/concrete/concrete_break" .. math.random(2, 3) .. ".wav", 75, math.Rand(105, 110), 0.5)
|
||||
SafeRemoveEntityDelayed(self, 3)
|
||||
else
|
||||
self:EmitSound(prop1.impactHardSound)
|
||||
if util.IsValidRagdoll(self:GetModel()) then
|
||||
local rag = ents.Create("prop_ragdoll")
|
||||
rag:SetModel(self:GetModel())
|
||||
rag:SetPos(self:GetPos())
|
||||
rag:SetAngles(self:GetAngles())
|
||||
rag:Spawn()
|
||||
rag:SetCollisionGroup(COLLISION_GROUP_WEAPON)
|
||||
if IsValid(rag:GetPhysicsObject()) then
|
||||
rag:GetPhysicsObject():ApplyForceOffset(data.HitPos, data.OurOldVelocity)
|
||||
end
|
||||
|
||||
SafeRemoveEntityDelayed(rag, 5)
|
||||
self:Remove()
|
||||
else
|
||||
local gibs = self:PrecacheGibs()
|
||||
if gibs > 0 then
|
||||
self:GibBreakClient(data.OurNewVelocity * math.Rand(0.8, 1.2))
|
||||
// self:GibBreakServer( data.OurOldVelocity * 2 )
|
||||
self:Remove()
|
||||
else
|
||||
SafeRemoveEntityDelayed(self, 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,79 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Smoke Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = false
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.BounceSounds = {
|
||||
"TacRP/weapons/grenade/smoke_bounce-1.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-2.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-3.wav",
|
||||
"TacRP/weapons/grenade/smoke_bounce-4.wav",
|
||||
}
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"TacRP/weapons/grenade/smoke_explode-1.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
|
||||
self:EmitSound(table.Random(self.ExplodeSounds), 75)
|
||||
|
||||
local cloud = ents.Create( "TacRP_smoke_cloud" )
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:Spawn()
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 16)
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.25, 0.5))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 25))
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
113
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_thermite.lua
Normal file
113
garrysmod/addons/tacrp/lua/entities/tacrp_proj_nade_thermite.lua
Normal file
@@ -0,0 +1,113 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "Thermite Grenade"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/smoke.mdl"
|
||||
|
||||
ENT.Material = "models/tacint/weapons/w_models/smoke/thermite-1"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = false // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
ENT.DefuseOnDamage = true
|
||||
|
||||
ENT.ImpactDamage = 1
|
||||
|
||||
ENT.Delay = 3
|
||||
|
||||
|
||||
ENT.SoundHint = true
|
||||
ENT.SoundHintDelay = 1.5
|
||||
ENT.SoundHintRadius = 328
|
||||
ENT.SoundHintDuration = 1.5
|
||||
|
||||
ENT.Sticky = true
|
||||
|
||||
ENT.ExplodeSounds = {
|
||||
"^TacRP/weapons/grenade/frag_explode-1.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-2.wav",
|
||||
"^TacRP/weapons/grenade/frag_explode-3.wav",
|
||||
}
|
||||
|
||||
function ENT:Detonate()
|
||||
if self:WaterLevel() > 0 then self:Remove() return end
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
|
||||
-- local dmg = 50
|
||||
-- if self.ImpactFuse then dmg = dmg * 0.5 end
|
||||
-- util.BlastDamage(self, attacker, self:GetPos(), 350, dmg)
|
||||
|
||||
self:EmitSound("ambient/fire/gascan_ignite1.wav", 80, 110)
|
||||
|
||||
local cloud = ents.Create( "TacRP_fire_cloud" )
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
local t = 8
|
||||
if self.ImpactFuse then t = t * 0.5 end
|
||||
|
||||
cloud.FireTime = t
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(self:GetAngles())
|
||||
cloud:SetOwner(attacker)
|
||||
cloud:Spawn()
|
||||
if IsValid(self:GetParent()) then
|
||||
cloud:SetParent(self:GetParent())
|
||||
elseif self:GetMoveType() == MOVETYPE_NONE then
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
ENT.NextDamageTick = 0
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail then
|
||||
local pos = self:GetPos() + self:GetUp() * 4
|
||||
local emitter = ParticleEmitter(pos)
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", pos)
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 16 + Vector(0, 0, 64))
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(false)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.5, 1))
|
||||
smoke:SetGravity(Vector(0, 0, -100))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 135, 0)
|
||||
local col2 = Color(255, 255, 255)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
232
garrysmod/addons/tacrp/lua/entities/tacrp_proj_p2a1_flare.lua
Normal file
232
garrysmod/addons/tacrp/lua/entities/tacrp_proj_p2a1_flare.lua
Normal file
@@ -0,0 +1,232 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "P2A1 Signal Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnImpact = true
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 8
|
||||
ENT.SafetyFuse = 0
|
||||
|
||||
ENT.ImpactDamage = 50
|
||||
ENT.ImpactDamageType = DMG_BURN + DMG_SLOWBURN
|
||||
|
||||
ENT.AudioLoop = false
|
||||
|
||||
ENT.Radius = 200
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 200)
|
||||
ENT.FlareSizeMin = 16
|
||||
ENT.FlareSizeMax = 32
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.333333)
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel(self.Model)
|
||||
self:PhysicsInitBox(-Vector(3, 3, 3), Vector(3, 3, 3) )
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
phys:EnableDrag(false)
|
||||
phys:SetDragCoefficient(0)
|
||||
phys:SetMass(1)
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:Wake()
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
self.NextFlareRedirectTime = 0
|
||||
|
||||
self.NPCDamage = IsValid(self:GetOwner()) and self:GetOwner():IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool()
|
||||
|
||||
if self.AudioLoop then
|
||||
self.LoopSound = CreateSound(self, self.AudioLoop)
|
||||
self.LoopSound:Play()
|
||||
end
|
||||
|
||||
if self.InstantFuse then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
phys:SetVelocityInstantaneous(v + self.Gravity)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(attacker)
|
||||
|
||||
// Apply a small instance of damage to ignite first, before doing the real damage
|
||||
// This will ensure if the target dies it is on fire first (so it can ignite its ragdolls etc.)
|
||||
dmg:SetDamageType(DMG_SLOWBURN)
|
||||
dmg:SetDamage(5)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(60 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
// TacRP.Flashbang(self, self:GetPos(), 512, 0.5, 0.1, 0)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("tacrp_flare_explode", fx)
|
||||
self:EmitSound("^ambient/fire/ignite.wav", 80, 112)
|
||||
end
|
||||
|
||||
local cloud = ents.Create("tacrp_flare_cloud")
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(self:GetAngles())
|
||||
cloud:SetOwner(attacker)
|
||||
timer.Simple(0, function()
|
||||
cloud:Spawn()
|
||||
if IsValid(self:GetParent()) then
|
||||
cloud:SetParent(self:GetParent())
|
||||
elseif self:GetMoveType() == MOVETYPE_NONE then
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
else
|
||||
cloud:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 0.5)
|
||||
end
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex() + 1)
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 75
|
||||
self.Light.b = 60
|
||||
self.Light.Brightness = 1
|
||||
self.Light.Size = 1024
|
||||
self.Light.DieTime = CurTime() + 8
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.Size = 1200
|
||||
self.Light.Brightness = 1.5
|
||||
self.Light.DieTime = CurTime() + 1
|
||||
self.Light.Decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(30, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 4)
|
||||
|
||||
smoke:SetColor(255, 50, 25)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(3.5, 4.5))
|
||||
smoke:SetGravity(Vector(0, 0, -7))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 50, 25)
|
||||
local col2 = Color(255, 155, 155)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function ENT:SafetyImpact(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("StunstickImpact", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_CRUSH + DMG_SLOWBURN)
|
||||
dmginfo:SetDamage(self.ImpactDamage * (self.NPCDamage and 0.25 or 1))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity * 20)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
self:EmitSound("physics/plastic/plastic_barrel_impact_hard2.wav", 70, 110)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
@@ -0,0 +1,232 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "P2A1 Signal Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/grenade_40mm.mdl"
|
||||
|
||||
ENT.IsRocket = false // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnImpact = true
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 10
|
||||
ENT.SafetyFuse = 0
|
||||
|
||||
ENT.ImpactDamage = 50
|
||||
ENT.ImpactDamageType = DMG_BURN + DMG_SLOWBURN
|
||||
|
||||
ENT.AudioLoop = false
|
||||
|
||||
ENT.Radius = 200
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 200)
|
||||
ENT.FlareSizeMin = 320
|
||||
ENT.FlareSizeMax = 640
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.333333)
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel(self.Model)
|
||||
self:PhysicsInitBox(-Vector(3, 3, 3), Vector(3, 3, 3) )
|
||||
self:SetMoveType(MOVETYPE_VPHYSICS)
|
||||
self:SetSolid(SOLID_VPHYSICS)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_PROJECTILE)
|
||||
|
||||
local phys = self:GetPhysicsObject()
|
||||
if !phys:IsValid() then
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
phys:EnableDrag(false)
|
||||
phys:SetDragCoefficient(0)
|
||||
phys:SetMass(1)
|
||||
phys:SetBuoyancyRatio(0)
|
||||
phys:Wake()
|
||||
end
|
||||
|
||||
self.SpawnTime = CurTime()
|
||||
self.NextFlareRedirectTime = 0
|
||||
|
||||
self.NPCDamage = IsValid(self:GetOwner()) and self:GetOwner():IsNPC() and !TacRP.ConVars["npc_equality"]:GetBool()
|
||||
|
||||
if self.AudioLoop then
|
||||
self.LoopSound = CreateSound(self, self.AudioLoop)
|
||||
self.LoopSound:Play()
|
||||
end
|
||||
|
||||
if self.InstantFuse then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
phys:SetVelocityInstantaneous(v + self.Gravity)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(attacker)
|
||||
|
||||
// Apply a small instance of damage to ignite first, before doing the real damage
|
||||
// This will ensure if the target dies it is on fire first (so it can ignite its ragdolls etc.)
|
||||
dmg:SetDamageType(DMG_SLOWBURN)
|
||||
dmg:SetDamage(5)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(60 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
// TacRP.Flashbang(self, self:GetPos(), 512, 0.5, 0.1, 0)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("tacrp_flare_explode", fx)
|
||||
self:EmitSound("^ambient/fire/ignite.wav", 80, 112)
|
||||
end
|
||||
|
||||
local cloud = ents.Create("tacrp_flare_cloud_signal")
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(self:GetAngles())
|
||||
cloud:SetOwner(attacker)
|
||||
timer.Simple(0, function()
|
||||
cloud:Spawn()
|
||||
if IsValid(self:GetParent()) then
|
||||
cloud:SetParent(self:GetParent())
|
||||
elseif self:GetMoveType() == MOVETYPE_NONE then
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
else
|
||||
cloud:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 0.5)
|
||||
end
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex() + 1)
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 75
|
||||
self.Light.b = 60
|
||||
self.Light.Brightness = 1
|
||||
self.Light.Size = 1024
|
||||
self.Light.DieTime = CurTime() + 8
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.Size = 1200
|
||||
self.Light.Brightness = 1.5
|
||||
self.Light.DieTime = CurTime() + 1
|
||||
self.Light.Decay = 2000
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(30, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 4)
|
||||
|
||||
smoke:SetColor(255, 50, 25)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(3.5, 4.5))
|
||||
smoke:SetGravity(Vector(0, 0, -7))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 50, 25)
|
||||
local col2 = Color(255, 155, 155)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function ENT:SafetyImpact(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("StunstickImpact", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_CRUSH + DMG_SLOWBURN)
|
||||
dmginfo:SetDamage(self.ImpactDamage * (self.NPCDamage and 0.25 or 1))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity * 20)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
self:EmitSound("physics/plastic/plastic_barrel_impact_hard2.wav", 70, 110)
|
||||
end
|
||||
|
||||
function ENT:UpdateTransmitState()
|
||||
if TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
return TRANSMIT_ALWAYS
|
||||
end
|
||||
return TRANSMIT_PVS
|
||||
end
|
||||
58
garrysmod/addons/tacrp/lua/entities/tacrp_proj_p2a1_heal.lua
Normal file
58
garrysmod/addons/tacrp/lua/entities/tacrp_proj_p2a1_heal.lua
Normal file
@@ -0,0 +1,58 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_p2a1_flare"
|
||||
ENT.PrintName = "P2A1 Medi-Smoke Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(100, 50, 255)
|
||||
ENT.FlareSizeMin = 16
|
||||
ENT.FlareSizeMax = 32
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.3333)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
|
||||
self:EmitSound("TacRP/weapons/grenade/smoke_explode-1.wav", 80, 108)
|
||||
timer.Simple(0, function()
|
||||
local cloud = ents.Create( "tacrp_heal_cloud_p2a1" )
|
||||
if !IsValid(cloud) then return end
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(self:GetOwner())
|
||||
cloud:Spawn()
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(25, 35))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 32)
|
||||
smoke:SetColor(125, 25, 255)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(0.3, 0.5))
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,148 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_p2a1_flare"
|
||||
ENT.PrintName = "P2A1 Incendiary Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Radius = 328
|
||||
|
||||
ENT.SafetyFuse = 0.3
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 200, 100)
|
||||
ENT.FlareSizeMin = 16
|
||||
ENT.FlareSizeMax = 32
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.3)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetDamagePosition(self:GetPos())
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetAttacker(attacker)
|
||||
|
||||
// Apply a small instance of damage to ignite first, before doing the real damage
|
||||
// This will ensure if the target dies it is on fire first (so it can ignite its ragdolls etc.)
|
||||
dmg:SetDamageType(DMG_SLOWBURN)
|
||||
dmg:SetDamage(5)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
dmg:SetDamageType(DMG_BURN)
|
||||
dmg:SetDamage(60 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), self.Radius)
|
||||
|
||||
// TacRP.Flashbang(self, self:GetPos(), 512, 0.5, 0.1, 0)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("tacrp_m202_explode", fx)
|
||||
self:EmitSound("^ambient/fire/ignite.wav", 80, 108)
|
||||
self:EmitSound("^weapons/explode5.wav", 80, 115, 0.8)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex() + 1)
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 128
|
||||
self.Light.b = 50
|
||||
self.Light.Brightness = 1
|
||||
self.Light.Size = 328
|
||||
self.Light.DieTime = CurTime() + 30
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if self.Light then
|
||||
self.Light.Size = 728
|
||||
self.Light.Brightness = 1
|
||||
self.Light.DieTime = CurTime() + 4
|
||||
self.Light.Decay = 250
|
||||
end
|
||||
if !self.FireSound then return end
|
||||
self.FireSound:Stop()
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(25, 35))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 32)
|
||||
|
||||
smoke:SetColor(255, 200, 25)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(0.3, 0.5))
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 128, 50)
|
||||
local col2 = Color(220, 200, 180)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function ENT:SafetyImpact(data, collider)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("StunstickImpact", fx)
|
||||
|
||||
if IsValid(data.HitEntity) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(self.ImpactDamageType)
|
||||
dmginfo:SetDamage(self.ImpactDamage * (self.NPCDamage and 0.25 or 1))
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity * 20)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
data.HitEntity:TakeDamageInfo(dmginfo)
|
||||
end
|
||||
|
||||
self:EmitSound("physics/plastic/plastic_barrel_impact_hard2.wav", 70, 110)
|
||||
end
|
||||
@@ -0,0 +1,113 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_p2a1_flare"
|
||||
ENT.PrintName = "P2A1 Parachute Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.InstantFuse = true
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = false
|
||||
|
||||
ENT.ExplodeOnDamage = false // projectile explodes when it takes damage.
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 2
|
||||
|
||||
ENT.Radius = 328
|
||||
|
||||
ENT.FlareColor = Color(255, 240, 240)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
self:EmitSound("tacint_extras/p2a1/confetti.wav", 80, 80)
|
||||
end
|
||||
|
||||
local cloud = ents.Create("tacrp_flare_cloud_para")
|
||||
|
||||
if !IsValid(cloud) then return end
|
||||
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetAngles(self:GetAngles())
|
||||
cloud:SetOwner(attacker)
|
||||
timer.Simple(0, function()
|
||||
cloud:Spawn()
|
||||
if IsValid(self:GetParent()) then
|
||||
cloud:SetParent(self:GetParent())
|
||||
elseif self:GetMoveType() == MOVETYPE_NONE then
|
||||
cloud:SetMoveType(MOVETYPE_NONE)
|
||||
else
|
||||
cloud:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 1 + Vector(math.Rand(-64, 64), math.Rand(-64, 64), 256))
|
||||
end
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
if !self.Light and TacRP.ConVars["dynamiclight"]:GetBool() then
|
||||
self.Light = DynamicLight(self:EntIndex() + 1)
|
||||
if (self.Light) then
|
||||
self.Light.Pos = self:GetPos()
|
||||
self.Light.r = 255
|
||||
self.Light.g = 200
|
||||
self.Light.b = 100
|
||||
self.Light.Brightness = 0.5
|
||||
self.Light.Size = 728
|
||||
self.Light.DieTime = CurTime() + 2
|
||||
end
|
||||
elseif self.Light then
|
||||
self.Light.Pos = self:GetPos()
|
||||
end
|
||||
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(30, 40))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 4)
|
||||
|
||||
smoke:SetColor(255, 50, 25)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(3.5, 4.5))
|
||||
smoke:SetGravity(Vector(0, 0, -7))
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
local col1 = Color(255, 200, 150)
|
||||
local col2 = Color(255, 255, 225)
|
||||
|
||||
local col3 = col1
|
||||
local d = pa:GetLifeTime() / pa:GetDieTime()
|
||||
col3.r = Lerp(d, col1.r, col2.r)
|
||||
col3.g = Lerp(d, col1.g, col2.g)
|
||||
col3.b = Lerp(d, col1.b, col2.b)
|
||||
|
||||
pa:SetColor(col3.r, col3.g, col3.b)
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,59 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_p2a1_flare"
|
||||
ENT.PrintName = "P2A1 Smoke Flare"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
ENT.FlareSizeMin = 16
|
||||
ENT.FlareSizeMax = 32
|
||||
ENT.Gravity = Vector(0, 0, 9.81 * 0.3333)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
|
||||
self:EmitSound("TacRP/weapons/grenade/smoke_explode-1.wav", 80, 108)
|
||||
timer.Simple(0, function()
|
||||
local cloud = ents.Create( "tacrp_smoke_cloud_p2a1" )
|
||||
if !IsValid(cloud) then return end
|
||||
cloud:SetPos(self:GetPos())
|
||||
cloud:SetOwner(self:GetOwner())
|
||||
cloud:Spawn()
|
||||
self:Remove()
|
||||
end)
|
||||
end
|
||||
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
function ENT:Draw()
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos(), math.Rand(self.FlareSizeMin, self.FlareSizeMax), math.Rand(self.FlareSizeMin, self.FlareSizeMax), self.FlareColor)
|
||||
end
|
||||
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and !(self:GetOwner() == LocalPlayer() and (self.SpawnTime + 0.1) > CurTime()) then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
local smoke = emitter:Add("particles/smokey", self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(4)
|
||||
smoke:SetEndSize(math.Rand(25, 35))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 32)
|
||||
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(false)
|
||||
smoke:SetDieTime(math.Rand(0.3, 0.5))
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
46
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7.lua
Normal file
46
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7.lua
Normal file
@@ -0,0 +1,46 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG-7 Rocket"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.SafetyFuse = 0.075
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 350, 200 * mult)
|
||||
self:ImpactTraceAttack(ent, 1000 * mult, 15000)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
155
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7_harpoon.lua
Normal file
155
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7_harpoon.lua
Normal file
@@ -0,0 +1,155 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG7 Shovel" -- not actually a harpoon lol
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/props_junk/Shovel01a.mdl"
|
||||
|
||||
ENT.ImpactDamage = 0
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
|
||||
local path = "tacrp/weapons/knife/"
|
||||
ENT.Sound_MeleeHit = {
|
||||
"physics/metal/metal_box_impact_hard1.wav",
|
||||
"physics/metal/metal_box_impact_hard2.wav",
|
||||
"physics/metal/metal_box_impact_hard3.wav",
|
||||
}
|
||||
ENT.Sound_MeleeHitBody = {
|
||||
path .. "/flesh_hit-1.wav",
|
||||
path .. "/flesh_hit-2.wav",
|
||||
path .. "/flesh_hit-3.wav",
|
||||
path .. "/flesh_hit-4.wav",
|
||||
path .. "/flesh_hit-5.wav",
|
||||
}
|
||||
|
||||
function ENT:OnInitialize()
|
||||
if SERVER then
|
||||
self:GetPhysicsObject():SetMass(50)
|
||||
self:GetPhysicsObject():SetDragCoefficient(5)
|
||||
end
|
||||
self.Attacker = self.Attacker or self:GetOwner()
|
||||
end
|
||||
|
||||
function ENT:Impact(data, collider)
|
||||
local tgt = data.HitEntity
|
||||
local attacker = self.Attacker or (IsValid(self:GetOwner()) and self:GetOwner()) or self
|
||||
local d = data.OurOldVelocity:GetNormalized()
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
|
||||
local speed = data.Speed
|
||||
if speed <= 50 then return true end
|
||||
|
||||
local dmg = self.NPCDamage and 75 or math.Clamp(speed / 15, 50, 200)
|
||||
|
||||
if IsValid(tgt) then
|
||||
local dmginfo = DamageInfo()
|
||||
dmginfo:SetAttacker(attacker)
|
||||
dmginfo:SetInflictor(self)
|
||||
dmginfo:SetDamageType(DMG_CLUB)
|
||||
dmginfo:SetDamage(dmg)
|
||||
dmginfo:SetDamageForce(data.OurOldVelocity)
|
||||
dmginfo:SetDamagePosition(data.HitPos)
|
||||
tgt:TakeDamageInfo(dmginfo)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
else
|
||||
local ang = data.OurOldVelocity:Angle()
|
||||
|
||||
-- leave a bullet hole. Also may be able to hit things it can't collide with (like stuck C4)
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = dmg,
|
||||
Force = 1,
|
||||
Distance = 4,
|
||||
HullSize = 4,
|
||||
Tracer = 0,
|
||||
Dir = ang:Forward(),
|
||||
Src = data.HitPos - ang:Forward(),
|
||||
IgnoreEntity = self,
|
||||
Callback = function(atk, tr, dmginfo)
|
||||
dmginfo:SetDamageType(DMG_CLUB)
|
||||
dmginfo:SetInflictor(attacker)
|
||||
if tr.HitSky then
|
||||
SafeRemoveEntity(self)
|
||||
else
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(data.HitPos)
|
||||
fx:SetNormal(-ang:Forward())
|
||||
fx:SetAngles(-ang)
|
||||
util.Effect("ManhackSparks", fx)
|
||||
if SERVER then
|
||||
self:EmitSound(istable(self.Sound_MeleeHit) and self.Sound_MeleeHit[math.random(1, #self.Sound_MeleeHit)] or self.Sound_MeleeHit, 80, 110, 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
||||
end
|
||||
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(data.OurNewVelocity * 0.5)
|
||||
|
||||
timer.Simple(0.01, function()
|
||||
if IsValid(self) then
|
||||
self:SetOwner(NULL) -- lol
|
||||
self:SetCollisionGroup(COLLISION_GROUP_INTERACTIVE)
|
||||
end
|
||||
end)
|
||||
timer.Simple(5, function()
|
||||
if IsValid(self) then
|
||||
self:SetRenderMode(RENDERMODE_TRANSALPHA)
|
||||
self:SetRenderFX(kRenderFxFadeFast)
|
||||
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
end
|
||||
end)
|
||||
SafeRemoveEntityDelayed(self, 7)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local g = Vector(0, 0, -9.81)
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if !self.Armed and phys:IsGravityEnabled() and self:WaterLevel() <= 2 then
|
||||
local v = phys:GetVelocity()
|
||||
local a = v:Angle()
|
||||
a.p = a.p - 90
|
||||
self:SetAngles(a)
|
||||
phys:SetVelocityInstantaneous(v * 0.985 + g)
|
||||
end
|
||||
end
|
||||
|
||||
ENT.SmokeTrail = false
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
function ENT:DoSmokeTrail()
|
||||
if CLIENT and self.SmokeTrail and self:GetVelocity():Length() >= 100 then
|
||||
local pos = self:GetPos()
|
||||
local emitter = ParticleEmitter(pos)
|
||||
local smoke = emitter:Add(GetSmokeImage(), pos)
|
||||
|
||||
smoke:SetStartAlpha(25)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(2)
|
||||
smoke:SetEndSize(math.Rand(16, 24))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetVelocity(VectorRand() * 8 + self:GetUp() * 16)
|
||||
smoke:SetColor(255, 255, 255)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(math.Rand(0.5, 0.75))
|
||||
smoke:SetGravity(Vector(0, 0, 15))
|
||||
emitter:Finish()
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,253 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG-7 Improvised Rocket"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0
|
||||
ENT.BoostTime = 5
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 75)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Bool", 0, "NoBooster")
|
||||
self:NetworkVar("Entity", 0, "Weapon")
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
|
||||
if SERVER then
|
||||
local phys = self:GetPhysicsObject()
|
||||
local rng = math.random()
|
||||
if rng <= 0.01 then
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 80, 95)
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos() + self:GetForward() * 32)
|
||||
fx:SetStart(Vector(math.Rand(0, 255), math.Rand(0, 255), math.Rand(0, 255)))
|
||||
util.Effect("balloon_pop", fx)
|
||||
self:GetOwner():EmitSound("tacrp/kids_cheering.mp3", 100, 100, 1)
|
||||
SafeRemoveEntity(self)
|
||||
elseif rng <= 0.25 then
|
||||
self.BoostTime = math.Rand(0.5, 5)
|
||||
|
||||
self:EmitSound("weapons/rpg/shotdown.wav", 80, 95)
|
||||
|
||||
self:SetNoBooster(math.random() <= 0.2)
|
||||
phys:EnableGravity(true)
|
||||
|
||||
if self:GetNoBooster() then
|
||||
phys:SetVelocityInstantaneous(self:GetOwner():GetVelocity() + self:GetForward() * math.Rand(25, 75) + self:GetUp() * math.Rand(75, 150))
|
||||
else
|
||||
phys:SetVelocityInstantaneous(self:GetOwner():GetVelocity() + self:GetForward() * math.Rand(100, 500) + self:GetUp() * math.Rand(50, 200))
|
||||
end
|
||||
phys:AddAngleVelocity(VectorRand() * 180)
|
||||
else
|
||||
self.BoostTime = math.Rand(1, 3)
|
||||
phys:SetVelocityInstantaneous(self:GetForward() * math.Rand(3000, 6000))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
if math.random() <= 0.05 then
|
||||
self:EmitSound("physics/metal/metal_barrel_impact_hard3.wav", 125, 115)
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(4)
|
||||
fx:SetRadius(4)
|
||||
fx:SetNormal(self:GetVelocity():GetNormalized())
|
||||
util.Effect("Sparks", fx)
|
||||
|
||||
for i = 1, 4 do
|
||||
local prop = ents.Create("prop_physics")
|
||||
prop:SetPos(self:GetPos())
|
||||
prop:SetAngles(self:GetAngles())
|
||||
prop:SetModel("models/weapons/tacint/rpg7_shrapnel_p" .. i .. ".mdl")
|
||||
prop:Spawn()
|
||||
prop:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 0.5 + VectorRand() * 75)
|
||||
prop:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
|
||||
|
||||
SafeRemoveEntityDelayed(prop, 3)
|
||||
end
|
||||
|
||||
self:Remove()
|
||||
return
|
||||
end
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
if self.NPCDamage then
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 350, 100)
|
||||
else
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 350, math.Rand(150, 250) * mult)
|
||||
self:ImpactTraceAttack(ent, math.Rand(750, 1500) * mult, math.Rand(7500, 20000))
|
||||
end
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if self:GetNoBooster() then return end
|
||||
local len = phys:GetVelocity():Length()
|
||||
local f = math.Clamp(len / 5000, 0, 1)
|
||||
if phys:IsGravityEnabled() then
|
||||
phys:AddVelocity(self:GetForward() * math.Rand(0, Lerp(f, 100, 10)))
|
||||
phys:AddAngleVelocity(VectorRand() * Lerp(f, 8, 2))
|
||||
elseif self.SpawnTime < CurTime() and len < 500 then
|
||||
phys:EnableGravity(true)
|
||||
else
|
||||
phys:AddVelocity(VectorRand() * Lerp(f, 5, 50) + self:GetForward() * Lerp(f, 10, 0))
|
||||
end
|
||||
end
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !IsValid(self) or self:GetNoDraw() then return end
|
||||
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if !self.Armed and isnumber(self.TimeFuse) and self.SpawnTime + self.TimeFuse < CurTime() then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
if self.Armed and self.ArmTime + self.Delay < CurTime() then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if SERVER and !self:GetNoBooster() and self.SpawnTime + self.BoostTime < CurTime() then
|
||||
self:SetNoBooster(true)
|
||||
self:GetPhysicsObject():EnableGravity(true)
|
||||
end
|
||||
|
||||
if self.LoopSound and self:GetNoBooster() then
|
||||
self.LoopSound:Stop()
|
||||
end
|
||||
|
||||
if self.ExplodeUnderwater and self:WaterLevel() > 0 then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if self.SmokeTrail and CLIENT then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
if !self:GetNoBooster() then
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(50, 75))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.25))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
elseif !self.LastNoBooster then
|
||||
|
||||
for i = 1, 10 do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(25)
|
||||
smoke:SetEndSize(math.Rand(100, 150))
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 200)
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.75))
|
||||
smoke:SetGravity(Vector(0, 0, -200))
|
||||
end
|
||||
else
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(25, 50))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 10)
|
||||
|
||||
smoke:SetColor(150, 150, 150)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.2, 0.3))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
end
|
||||
emitter:Finish()
|
||||
|
||||
self.LastNoBooster = self:GetNoBooster()
|
||||
|
||||
end
|
||||
|
||||
|
||||
self:OnThink()
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if self.FlareColor and !self:GetNoBooster() then
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + (self:GetAngles():Forward() * -16), math.Rand(100, 150), math.Rand(100, 150), self.FlareColor)
|
||||
end
|
||||
end
|
||||
250
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7_mortar.lua
Normal file
250
garrysmod/addons/tacrp/lua/entities/tacrp_proj_rpg7_mortar.lua
Normal file
@@ -0,0 +1,250 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG-7 Mortar Rocket"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true
|
||||
|
||||
ENT.InstantFuse = false
|
||||
ENT.RemoteFuse = false
|
||||
ENT.ImpactFuse = true
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.7
|
||||
ENT.BoostTime = 0.3
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 50, 0)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:SetupDataTables()
|
||||
self:NetworkVar("Entity", 0, "Weapon")
|
||||
self:NetworkVar("Bool", 0, "NoBooster")
|
||||
end
|
||||
|
||||
function ENT:Initialize()
|
||||
BaseClass.Initialize(self)
|
||||
|
||||
if SERVER then
|
||||
-- self:SetAngles(self:GetAngles() + Angle(-5, 0, 0))
|
||||
local phys = self:GetPhysicsObject()
|
||||
phys:SetMass(30)
|
||||
phys:SetDragCoefficient(1)
|
||||
phys:SetVelocity(self:GetForward() * 4000)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
|
||||
if self.NPCDamage then
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 512, 150 * mult)
|
||||
else
|
||||
if self.SpawnTime + self.SafetyFuse >= CurTime() then
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 256, 100 * mult)
|
||||
else
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
self:EmitSound("^ambient/explosions/explode_3.wav", 100, 90, 0.75, CHAN_AUTO)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 128, 500 * mult)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 328, 120 * mult)
|
||||
util.BlastDamage(self, attacker, self:GetPos(), 768, 80 * mult)
|
||||
local count = 8
|
||||
for i = 1, count do
|
||||
local tr = util.TraceLine({
|
||||
start = self:GetPos(),
|
||||
endpos = self:GetPos() + Angle(0, i / count * 360, 0):Forward() * 328 * math.Rand(0.75, 1),
|
||||
mask = MASK_SHOT,
|
||||
filter = self,
|
||||
})
|
||||
fx:SetOrigin(tr.HitPos)
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
end
|
||||
end
|
||||
end
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125, 95)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
if !IsValid(self) or self:GetNoDraw() then return end
|
||||
|
||||
if !self.SpawnTime then
|
||||
self.SpawnTime = CurTime()
|
||||
end
|
||||
|
||||
if !self.Armed and isnumber(self.TimeFuse) and self.SpawnTime + self.TimeFuse < CurTime() then
|
||||
self.ArmTime = CurTime()
|
||||
self.Armed = true
|
||||
end
|
||||
|
||||
if self.Armed and self.ArmTime + self.Delay < CurTime() then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if SERVER and !self:GetNoBooster() and self.SpawnTime + self.BoostTime < CurTime() then
|
||||
self:SetNoBooster(true)
|
||||
self:GetPhysicsObject():EnableGravity(true)
|
||||
self:GetPhysicsObject():SetVelocityInstantaneous(self:GetVelocity() * 0.5)
|
||||
end
|
||||
|
||||
if self.LoopSound and self:GetNoBooster() then
|
||||
self.LoopSound:Stop()
|
||||
end
|
||||
|
||||
if self.ExplodeUnderwater and self:WaterLevel() > 0 then
|
||||
self:PreDetonate()
|
||||
end
|
||||
|
||||
if self.SmokeTrail and CLIENT then
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
if !self:GetNoBooster() then
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(50, 75))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(-self:GetAngles():Forward() * 400 + (VectorRand() * 10))
|
||||
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.25))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
|
||||
elseif !self.LastNoBooster then
|
||||
|
||||
for i = 1, 10 do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetStartAlpha(50)
|
||||
smoke:SetEndAlpha(0)
|
||||
smoke:SetStartSize(25)
|
||||
smoke:SetEndSize(math.Rand(100, 150))
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 200)
|
||||
smoke:SetColor(200, 200, 200)
|
||||
smoke:SetLighting(true)
|
||||
smoke:SetDieTime(math.Rand(0.75, 1.75))
|
||||
smoke:SetGravity(Vector(0, 0, -200))
|
||||
end
|
||||
else
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
|
||||
smoke:SetStartAlpha(30)
|
||||
smoke:SetEndAlpha(0)
|
||||
|
||||
smoke:SetStartSize(10)
|
||||
smoke:SetEndSize(math.Rand(25, 50))
|
||||
|
||||
smoke:SetRoll(math.Rand(-180, 180))
|
||||
smoke:SetRollDelta(math.Rand(-1, 1))
|
||||
|
||||
smoke:SetPos(self:GetPos())
|
||||
smoke:SetVelocity(VectorRand() * 10)
|
||||
|
||||
smoke:SetColor(150, 150, 150)
|
||||
smoke:SetLighting(true)
|
||||
|
||||
smoke:SetDieTime(math.Rand(0.2, 0.3))
|
||||
|
||||
smoke:SetGravity(Vector(0, 0, 0))
|
||||
end
|
||||
|
||||
if CurTime() >= (self.SpawnTime + self.SafetyFuse) and !self.Sparked then
|
||||
self.Sparked = true
|
||||
for i = 1, 15 do
|
||||
local fire = emitter:Add("effects/spark", self:GetPos())
|
||||
fire:SetVelocity(VectorRand() * 512 + self:GetVelocity() * 0.25)
|
||||
fire:SetGravity(Vector(math.Rand(-5, 5), math.Rand(-5, 5), -1000))
|
||||
fire:SetDieTime(math.Rand(0.2, 0.4))
|
||||
fire:SetStartAlpha(255)
|
||||
fire:SetEndAlpha(0)
|
||||
fire:SetStartSize(8)
|
||||
fire:SetEndSize(0)
|
||||
fire:SetRoll(math.Rand(-180, 180))
|
||||
fire:SetRollDelta(math.Rand(-0.2, 0.2))
|
||||
fire:SetColor(255, 255, 255)
|
||||
fire:SetAirResistance(50)
|
||||
fire:SetLighting(false)
|
||||
fire:SetCollide(true)
|
||||
fire:SetBounce(0.8)
|
||||
end
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
|
||||
self.LastNoBooster = self:GetNoBooster()
|
||||
end
|
||||
|
||||
self:OnThink()
|
||||
end
|
||||
|
||||
local g = Vector(0, 0, -9.81)
|
||||
function ENT:PhysicsUpdate(phys)
|
||||
if phys:IsGravityEnabled() then
|
||||
local v = phys:GetVelocity()
|
||||
self:SetAngles(v:Angle())
|
||||
phys:SetVelocityInstantaneous(v + g)
|
||||
end
|
||||
|
||||
-- local v = phys:GetVelocity()
|
||||
-- self:SetAngles(v:Angle() + Angle(2, 0, 0))
|
||||
-- phys:SetVelocityInstantaneous(self:GetForward() * v:Length())
|
||||
end
|
||||
|
||||
local mat = Material("effects/ar2_altfire1b")
|
||||
|
||||
function ENT:Draw()
|
||||
self:DrawModel()
|
||||
|
||||
if self.FlareColor and !self:GetNoBooster() then
|
||||
render.SetMaterial(mat)
|
||||
render.DrawSprite(self:GetPos() + (self:GetAngles():Forward() * -16), math.Rand(100, 150), math.Rand(100, 150), self.FlareColor)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,98 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "RPG-7 Ratshot"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = true // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
ENT.TimeFuse = false
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.Delay = 0.3
|
||||
ENT.SafetyFuse = 0.3
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(75, 175, 255)
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local src = self:GetPos() - dir * 64
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(8)
|
||||
fx:SetScale(2)
|
||||
fx:SetRadius(8)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
|
||||
local tr = util.TraceHull({
|
||||
start = src,
|
||||
endpos = src + dir * 2048,
|
||||
filter = self,
|
||||
mins = Vector(-16, -16, -8),
|
||||
maxs = Vector(16, 16, 8)
|
||||
})
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(1)
|
||||
fx:SetRadius(2)
|
||||
fx:SetNormal(dir)
|
||||
for i = 1, math.floor(tr.Fraction * 6) do
|
||||
fx:SetOrigin(tr.StartPos + tr.Normal * (i / 6) * 2048)
|
||||
util.Effect("Sparks", fx)
|
||||
end
|
||||
end
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat() * (self.NPCDamage and 0.25 or 1)
|
||||
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 5,
|
||||
Force = 1,
|
||||
Distance = 2048,
|
||||
HullSize = 16,
|
||||
Num = 48,
|
||||
Tracer = 1,
|
||||
Src = src,
|
||||
Dir = dir,
|
||||
Spread = Vector(1, 1, 0),
|
||||
IgnoreEntity = self,
|
||||
})
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BULLET + DMG_BLAST)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
for _, ent in pairs(ents.FindInCone(src, dir, 2048, 0.707)) do
|
||||
local tr = util.QuickTrace(src, ent:GetPos() - src, {self, ent})
|
||||
if tr.Fraction == 1 then
|
||||
dmg:SetDamage(130 * math.Rand(0.75, 1) * Lerp((ent:GetPos():DistToSqr(src) / 4194304) ^ 0.5, 1, 0.25) * mult)
|
||||
if !ent:IsOnGround() then dmg:ScaleDamage(1.5) end
|
||||
ent:TakeDamageInfo(dmg)
|
||||
end
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, src, 256, 50 * mult)
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125, 100)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 100, 200)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
73
garrysmod/addons/tacrp/lua/entities/tacrp_proj_stinger.lua
Normal file
73
garrysmod/addons/tacrp/lua/entities/tacrp_proj_stinger.lua
Normal file
@@ -0,0 +1,73 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_base"
|
||||
ENT.PrintName = "FIM-92 Missile"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.Delay = 0
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 120
|
||||
ENT.SeekerAngle = 55
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 1
|
||||
ENT.SuperSteerSpeed = 240
|
||||
|
||||
ENT.MaxSpeed = 5000
|
||||
ENT.Acceleration = 4000
|
||||
|
||||
ENT.SteerDelay = 0.5
|
||||
ENT.FlareRedirectChance = 0.2
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local dir = self:GetForward()
|
||||
local src = self:GetPos() - dir * 64
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BLAST + DMG_AIRBOAT)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
dmg:SetDamage(100 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 256)
|
||||
self:ImpactTraceAttack(ent, 500 * mult, 100)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,71 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_stinger"
|
||||
ENT.PrintName = "FIM-92 Missile (4AAM)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = false
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.FlareSizeMin = 150
|
||||
ENT.FlareSizeMax = 200
|
||||
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 200
|
||||
ENT.SeekerAngle = 90
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 0.5
|
||||
ENT.SuperSteerSpeed = -90 // yes this is intentionally negative
|
||||
|
||||
ENT.MaxSpeed = 6000
|
||||
ENT.Acceleration = 2000
|
||||
|
||||
ENT.SteerDelay = 0
|
||||
ENT.FlareRedirectChance = 0.4
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 230, 200)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local dir = self:GetForward()
|
||||
local src = self:GetPos() - dir * 64
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BLAST + DMG_AIRBOAT)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
dmg:SetDamage(75 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 200)
|
||||
self:ImpactTraceAttack(ent, 100 * mult, 100)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
util.Effect("HelicopterMegaBomb", fx)
|
||||
|
||||
self:EmitSound("^tacrp/weapons/grenade/40mm_explode-" .. math.random(1, 3) .. ".wav", 115)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
123
garrysmod/addons/tacrp/lua/entities/tacrp_proj_stinger_apers.lua
Normal file
123
garrysmod/addons/tacrp/lua/entities/tacrp_proj_stinger_apers.lua
Normal file
@@ -0,0 +1,123 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_stinger"
|
||||
ENT.PrintName = "FIM-92 Missile (APERS)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
ENT.TimeFuse = false
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 30
|
||||
ENT.SeekerAngle = 180
|
||||
ENT.SeekerExplodeRange = 728
|
||||
ENT.SeekerExplodeSnapPosition = false
|
||||
ENT.SeekerExplodeAngle = 20
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 1.5
|
||||
ENT.SuperSteerSpeed = 400
|
||||
|
||||
ENT.MaxSpeed = 2000
|
||||
ENT.Acceleration = 5000
|
||||
|
||||
ENT.SteerDelay = 0.5
|
||||
ENT.FlareRedirectChance = 0.5
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
function ENT:OnInitialize()
|
||||
if SERVER and IsValid(self.LockOnEntity) then
|
||||
local dist = self.LockOnEntity:WorldSpaceCenter():Distance(self:GetPos())
|
||||
self.SteerDelay = math.Clamp(dist / 2000, 0.75, 3)
|
||||
self.SuperSteerTime = self.SteerDelay + 0.5
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Detonate()
|
||||
local dir = self:GetForward()
|
||||
local attacker = self.Attacker or self:GetOwner() or self
|
||||
local src = self:GetPos() - dir * 64
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(src)
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
fx:SetMagnitude(8)
|
||||
fx:SetScale(2)
|
||||
fx:SetRadius(8)
|
||||
fx:SetNormal(dir)
|
||||
util.Effect("Sparks", fx)
|
||||
|
||||
local tr = util.TraceHull({
|
||||
start = src,
|
||||
endpos = src + dir * 2048,
|
||||
filter = self,
|
||||
mins = Vector(-16, -16, -8),
|
||||
maxs = Vector(16, 16, 8)
|
||||
})
|
||||
fx:SetMagnitude(4)
|
||||
fx:SetScale(1)
|
||||
fx:SetRadius(2)
|
||||
fx:SetNormal(dir)
|
||||
for i = 1, math.floor(tr.Fraction * 6) do
|
||||
fx:SetOrigin(tr.StartPos + tr.Normal * (i / 6) * 2048)
|
||||
util.Effect("Sparks", fx)
|
||||
end
|
||||
end
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
|
||||
self:FireBullets({
|
||||
Attacker = attacker,
|
||||
Damage = 5,
|
||||
Force = 1,
|
||||
Distance = 1024,
|
||||
HullSize = 16,
|
||||
Num = 48,
|
||||
Tracer = 1,
|
||||
Src = src,
|
||||
Dir = dir,
|
||||
Spread = Vector(0.5, 0.5, 0),
|
||||
IgnoreEntity = self,
|
||||
})
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BUCKSHOT + DMG_BLAST)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity() * 100)
|
||||
dmg:SetDamagePosition(src)
|
||||
for _, ent in pairs(ents.FindInCone(src, dir, 1024, 0.707)) do
|
||||
local tr = util.QuickTrace(src, ent:GetPos() - src, {self, ent})
|
||||
if tr.Fraction == 1 then
|
||||
dmg:SetDamage(100 * math.Rand(0.75, 1) * Lerp((ent:GetPos():DistToSqr(src) / 1048576) ^ 0.5, 1, 0.25) * (self.NPCDamage and 0.5 or 1) * mult)
|
||||
if !ent:IsOnGround() then dmg:ScaleDamage(1.5) end
|
||||
ent:TakeDamageInfo(dmg)
|
||||
end
|
||||
end
|
||||
|
||||
util.BlastDamage(self, attacker, src, 256, 50 * mult)
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125, 100)
|
||||
self:EmitSound("physics/metal/metal_box_break1.wav", 100, 200)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_stinger"
|
||||
ENT.PrintName = "FIM-92 Missile (QAAM)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 30
|
||||
ENT.SeekerAngle = 75
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 3
|
||||
ENT.SuperSteerSpeed = 120
|
||||
|
||||
ENT.MaxSpeed = 8000
|
||||
ENT.Acceleration = 8000
|
||||
|
||||
ENT.SteerDelay = 0.3
|
||||
ENT.FlareRedirectChance = 0.35
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(175, 175, 255)
|
||||
@@ -0,0 +1,81 @@
|
||||
AddCSLuaFile()
|
||||
|
||||
ENT.Base = "tacrp_proj_stinger"
|
||||
ENT.PrintName = "FIM-92 Missile (SAAM)"
|
||||
ENT.Spawnable = false
|
||||
|
||||
ENT.Model = "models/weapons/tacint/rocket_deployed.mdl"
|
||||
|
||||
ENT.IsRocket = true // projectile has a booster and will not drop.
|
||||
|
||||
ENT.InstantFuse = false // projectile is armed immediately after firing.
|
||||
ENT.RemoteFuse = false // allow this projectile to be triggered by remote detonator.
|
||||
ENT.ImpactFuse = true // projectile explodes on impact.
|
||||
|
||||
ENT.ExplodeOnDamage = true
|
||||
ENT.ExplodeUnderwater = true
|
||||
|
||||
ENT.GunshipWorkaround = false
|
||||
|
||||
ENT.SafetyFuse = 0.1
|
||||
ENT.ImpactDamage = 150
|
||||
|
||||
ENT.SteerSpeed = 60
|
||||
ENT.SeekerAngle = 55
|
||||
|
||||
ENT.LeadTarget = true
|
||||
ENT.SuperSteerTime = 1
|
||||
ENT.SuperSteerSpeed = 150
|
||||
|
||||
ENT.MaxSpeed = 4500
|
||||
ENT.Acceleration = 2000
|
||||
|
||||
ENT.SteerDelay = 0.5
|
||||
ENT.FlareRedirectChance = 0.05
|
||||
|
||||
ENT.AudioLoop = "TacRP/weapons/rpg7/rocket_flight-1.wav"
|
||||
|
||||
ENT.SmokeTrail = true
|
||||
|
||||
ENT.FlareColor = Color(255, 255, 255)
|
||||
|
||||
DEFINE_BASECLASS(ENT.Base)
|
||||
|
||||
function ENT:Detonate(ent)
|
||||
local attacker = self.Attacker or self:GetOwner()
|
||||
local dir = self:GetForward()
|
||||
local src = self:GetPos() - dir * 64
|
||||
|
||||
local mult = TacRP.ConVars["mult_damage_explosive"]:GetFloat()
|
||||
local dmg = DamageInfo()
|
||||
dmg:SetAttacker(attacker)
|
||||
dmg:SetDamageType(DMG_BLAST + DMG_AIRBOAT)
|
||||
dmg:SetInflictor(self)
|
||||
dmg:SetDamageForce(self:GetVelocity())
|
||||
dmg:SetDamagePosition(src)
|
||||
dmg:SetDamage(150 * mult)
|
||||
util.BlastDamageInfo(dmg, self:GetPos(), 256)
|
||||
self:ImpactTraceAttack(ent, 700 * mult, 100)
|
||||
|
||||
local fx = EffectData()
|
||||
fx:SetOrigin(self:GetPos())
|
||||
|
||||
if self:WaterLevel() > 0 then
|
||||
util.Effect("WaterSurfaceExplosion", fx)
|
||||
else
|
||||
util.Effect("Explosion", fx)
|
||||
end
|
||||
|
||||
self:EmitSound("TacRP/weapons/rpg7/explode.wav", 125)
|
||||
|
||||
self:Remove()
|
||||
end
|
||||
|
||||
function ENT:OnThink()
|
||||
if IsValid(self:GetOwner()) and IsValid(self:GetOwner():GetActiveWeapon())
|
||||
and self:GetOwner():GetActiveWeapon().ArcticTacRP then
|
||||
self.LockOnEntity = self:GetOwner():GetActiveWeapon():GetLockOnEntity()
|
||||
else
|
||||
self:SwitchTarget(nil)
|
||||
end
|
||||
end
|
||||
193
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud.lua
Normal file
193
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud.lua
Normal file
@@ -0,0 +1,193 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Smoke Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.TacRPSmoke = true
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 300
|
||||
ENT.SmokeColor = Color(150, 150, 150)
|
||||
ENT.BillowTime = 1
|
||||
ENT.Life = 20
|
||||
|
||||
-- Cheap maths
|
||||
ENT.SmokeRadiusSqr = ENT.SmokeRadius * ENT.SmokeRadius
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
local mins, maxs = Vector(-self.SmokeRadius / 2, -self.SmokeRadius / 2, -self.SmokeRadius / 2), Vector(self.SmokeRadius / 2, self.SmokeRadius / 2, self.SmokeRadius / 2)
|
||||
if SERVER then
|
||||
self:PhysicsInitSphere(self.SmokeRadius / 2)
|
||||
self:SetCollisionBounds(mins, maxs)
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
|
||||
table.insert(TacRP.ClientSmokeCache, self)
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 20
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 250) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
// pass
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
pa:SetStartAlpha(255 * alph)
|
||||
pa:SetEndAlpha(255 * alph)
|
||||
|
||||
-- pa:SetLifeTime(pa:GetLifeTime() + FrameTime())
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
if TacRP.ConVars["smoke_affectnpcs"]:GetBool() then
|
||||
self:EnableCustomCollisions()
|
||||
self:SetCustomCollisionCheck(true)
|
||||
self:CollisionRulesChanged()
|
||||
else
|
||||
self:SetSolid(SOLID_NONE)
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime
|
||||
end
|
||||
|
||||
function ENT:TestCollision( startpos, delta, isbox, extents, mask )
|
||||
if (mask == MASK_BLOCKLOS or mask == MASK_BLOCKLOS_AND_NPCS) then
|
||||
local len = delta:Length()
|
||||
if len <= 200 then return false end -- NPCs can see very close
|
||||
|
||||
local rad = self.SmokeRadiusSqr
|
||||
local pos = self:GetPos()
|
||||
local dir = delta:GetNormalized()
|
||||
|
||||
-- Trace started within the smoke
|
||||
if startpos:DistToSqr(pos) <= rad then
|
||||
return {
|
||||
HitPos = startpos,
|
||||
Fraction = 0,
|
||||
Normal = -dir,
|
||||
}
|
||||
end
|
||||
|
||||
-- Find the closest point on the original trace to the smoke's origin point
|
||||
local t = (pos - startpos):Dot(dir)
|
||||
local p = startpos + t * dir
|
||||
|
||||
-- If the point is within smoke radius, the trace is intersecting the smoke
|
||||
if p:DistToSqr(pos) <= rad then
|
||||
return {
|
||||
HitPos = p,
|
||||
Fraction = math.Clamp(t / len, 0, 0.95),
|
||||
Normal = -dir,
|
||||
}
|
||||
end
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
hook.Add("ShouldCollide", "tacrp_smoke_cloud", function(ent1, ent2)
|
||||
if ent1.TacRPSmoke and !ent2:IsNPC() then return false end
|
||||
if ent2.TacRPSmoke and !ent1:IsNPC() then return false end
|
||||
end)
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
if SERVER then
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
return
|
||||
end
|
||||
|
||||
--[[]
|
||||
if !TacRP.ConVars["smoke_affectnpcs"]:GetBool() then return end
|
||||
local targets = ents.FindInSphere(self:GetPos(), self.SmokeRadius)
|
||||
for _, k in pairs(targets) do
|
||||
if k:IsNPC() then
|
||||
local ret = hook.Run("TacRP_StunNPC", k, self)
|
||||
if ret then continue end
|
||||
k:SetSchedule(SCHED_STANDOFF)
|
||||
end
|
||||
end
|
||||
|
||||
self:NextThink(CurTime() + 0.5)
|
||||
]]
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if CLIENT then
|
||||
timer.Simple(0, function()
|
||||
if !IsValid(self) then
|
||||
table.RemoveByValue(TacRP.ClientSmokeCache, self)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
207
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud_ninja.lua
Normal file
207
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud_ninja.lua
Normal file
@@ -0,0 +1,207 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "base_entity"
|
||||
ENT.PrintName = "Smoke Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.TacRPSmoke = true
|
||||
ENT.Particles = nil
|
||||
ENT.SmokeRadius = 256
|
||||
ENT.SmokeColor = Color(220, 220, 220)
|
||||
ENT.BillowTime = 0.5
|
||||
ENT.Life = 8
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
|
||||
table.insert(TacRP.ClientSmokeCache, self)
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 20
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 220) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(1, 3)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
// pass
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
pa:SetStartAlpha(255 * alph)
|
||||
pa:SetEndAlpha(255 * alph)
|
||||
|
||||
-- pa:SetLifeTime(pa:GetLifeTime() + FrameTime())
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime + 2
|
||||
end
|
||||
|
||||
function ENT:Think()
|
||||
|
||||
|
||||
if SERVER then
|
||||
if !self:GetOwner():IsValid() then self:Remove() return end
|
||||
|
||||
-- local o = self:GetOwner()
|
||||
-- local origin = self:GetPos() + Vector(0, 0, 16)
|
||||
|
||||
-- local dmg = DamageInfo()
|
||||
-- dmg:SetAttacker(self:GetOwner())
|
||||
-- dmg:SetInflictor(self)
|
||||
-- dmg:SetDamageType(DMG_NERVEGAS)
|
||||
-- dmg:SetDamageForce(Vector(0, 0, 0))
|
||||
-- dmg:SetDamagePosition(self:GetPos())
|
||||
-- dmg:SetDamageCustom(1024) -- immersive death
|
||||
|
||||
-- util.BlastDamageInfo(dmg, self:GetPos(), 300)
|
||||
|
||||
-- for i, k in pairs(ents.FindInSphere(origin, 300)) do
|
||||
-- if k == self:GetOwner() then continue end
|
||||
|
||||
-- if k:IsPlayer() or k:IsNPC() or k:IsNextBot() then
|
||||
-- local tr = util.TraceLine({
|
||||
-- start = origin,
|
||||
-- endpos = k:EyePos() or k:WorldSpaceCenter(),
|
||||
-- filter = self,
|
||||
-- mask = MASK_SOLID_BRUSHONLY
|
||||
-- })
|
||||
-- if tr.Fraction < 1 then continue end
|
||||
-- local dist = (tr.HitPos - tr.StartPos):Length()
|
||||
-- local delta = dist / 320
|
||||
|
||||
-- dmg:SetDamage(k:IsPlayer() and math.Rand(1, 3) or math.Rand(5, 15))
|
||||
|
||||
-- k:TakeDamageInfo(dmg)
|
||||
|
||||
-- if k:IsPlayer() then
|
||||
-- k:ScreenFade( SCREENFADE.IN, Color(150, 150, 50, 100), 2 * delta, 0 )
|
||||
|
||||
-- local timername = "tacrp_ninja_gas_" .. k:EntIndex()
|
||||
-- local reps = 3
|
||||
|
||||
-- if timer.Exists(timername) then
|
||||
-- reps = math.Clamp(timer.RepsLeft(timername) + 3, reps, 10)
|
||||
-- timer.Remove(timername)
|
||||
-- end
|
||||
-- timer.Create(timername, 2, reps, function()
|
||||
-- if !IsValid(k) or !k:Alive() then
|
||||
-- timer.Remove(timername)
|
||||
-- return
|
||||
-- end
|
||||
-- k:ScreenFade( SCREENFADE.IN, Color(150, 150, 50, 5), 0.1, 0 )
|
||||
-- if k:Health() > 1 then
|
||||
-- local d = DamageInfo()
|
||||
-- d:SetDamageType(DMG_NERVEGAS)
|
||||
-- d:SetDamage(math.random(1, 2))
|
||||
-- d:SetInflictor(IsValid(self) and self or o)
|
||||
-- d:SetAttacker(o)
|
||||
-- d:SetDamageForce(k:GetForward())
|
||||
-- d:SetDamagePosition(k:GetPos())
|
||||
-- d:SetDamageCustom(1024)
|
||||
-- k:TakeDamageInfo(d)
|
||||
-- else
|
||||
-- k:ViewPunch(Angle(math.Rand(-2, 2), 0, 0))
|
||||
-- end
|
||||
-- if math.random() <= 0.3 then
|
||||
-- k:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
|
||||
-- end
|
||||
-- end)
|
||||
|
||||
-- if math.random() <= 0.3 then
|
||||
-- k:EmitSound("ambient/voices/cough" .. math.random(1, 4) .. ".wav", 80, math.Rand(95, 105))
|
||||
-- end
|
||||
-- elseif k:IsNPC() then
|
||||
-- k:SetSchedule(SCHED_STANDOFF)
|
||||
-- end
|
||||
-- end
|
||||
-- end
|
||||
|
||||
-- self:NextThink(CurTime() + 1)
|
||||
|
||||
if self.dt < CurTime() then
|
||||
SafeRemoveEntity(self)
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:OnRemove()
|
||||
if CLIENT then
|
||||
timer.Simple(0, function()
|
||||
if !IsValid(self) then
|
||||
table.RemoveByValue(TacRP.ClientSmokeCache, self)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function ENT:Draw()
|
||||
return false
|
||||
end
|
||||
100
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud_p2a1.lua
Normal file
100
garrysmod/addons/tacrp/lua/entities/tacrp_smoke_cloud_p2a1.lua
Normal file
@@ -0,0 +1,100 @@
|
||||
ENT.Type = "anim"
|
||||
ENT.Base = "tacrp_smoke_cloud"
|
||||
ENT.PrintName = "Smoke Cloud"
|
||||
ENT.Author = ""
|
||||
ENT.Information = ""
|
||||
ENT.Spawnable = false
|
||||
ENT.AdminSpawnable = false
|
||||
|
||||
local smokeimages = {"particle/smokesprites_0001", "particle/smokesprites_0002", "particle/smokesprites_0003", "particle/smokesprites_0004", "particle/smokesprites_0005", "particle/smokesprites_0006", "particle/smokesprites_0007", "particle/smokesprites_0008", "particle/smokesprites_0009", "particle/smokesprites_0010", "particle/smokesprites_0011", "particle/smokesprites_0012", "particle/smokesprites_0013", "particle/smokesprites_0014", "particle/smokesprites_0015", "particle/smokesprites_0016"}
|
||||
|
||||
local function GetSmokeImage()
|
||||
return smokeimages[math.random(#smokeimages)]
|
||||
end
|
||||
|
||||
ENT.SmokeRadius = 150
|
||||
ENT.SmokeColor = Color(150, 150, 150)
|
||||
ENT.BillowTime = 1
|
||||
ENT.Life = 12
|
||||
|
||||
AddCSLuaFile()
|
||||
|
||||
function ENT:Initialize()
|
||||
if SERVER then
|
||||
self:SetModel( "models/weapons/w_eq_smokegrenade_thrown.mdl" )
|
||||
self:SetMoveType( MOVETYPE_NONE )
|
||||
self:SetSolid( SOLID_NONE )
|
||||
self:DrawShadow( false )
|
||||
else
|
||||
|
||||
table.insert(TacRP.ClientSmokeCache, self)
|
||||
|
||||
local emitter = ParticleEmitter(self:GetPos())
|
||||
|
||||
self.Particles = {}
|
||||
|
||||
local amt = 15
|
||||
|
||||
for i = 1, amt do
|
||||
local smoke = emitter:Add(GetSmokeImage(), self:GetPos())
|
||||
smoke:SetVelocity( VectorRand() * 8 + (Angle(0, i * (360 / amt), 0):Forward() * 100) )
|
||||
smoke:SetStartAlpha( 0 )
|
||||
smoke:SetEndAlpha( 255 )
|
||||
smoke:SetStartSize( 0 )
|
||||
smoke:SetEndSize( self.SmokeRadius )
|
||||
smoke:SetRoll( math.Rand(-180, 180) )
|
||||
smoke:SetRollDelta( math.Rand(-0.2,0.2) )
|
||||
smoke:SetColor( self.SmokeColor.r, self.SmokeColor.g, self.SmokeColor.b )
|
||||
smoke:SetAirResistance( 75 )
|
||||
smoke:SetPos( self:GetPos() )
|
||||
smoke:SetCollide( true )
|
||||
smoke:SetBounce( 0.2 )
|
||||
smoke:SetLighting( false )
|
||||
smoke:SetNextThink( CurTime() + FrameTime() )
|
||||
smoke.bt = CurTime() + self.BillowTime
|
||||
smoke.dt = CurTime() + self.BillowTime + self.Life
|
||||
smoke.ft = CurTime() + self.BillowTime + self.Life + math.Rand(2.5, 5)
|
||||
smoke:SetDieTime(smoke.ft)
|
||||
smoke.life = self.Life
|
||||
smoke.billowed = false
|
||||
smoke.radius = self.SmokeRadius
|
||||
smoke:SetThinkFunction( function(pa)
|
||||
if !pa then return end
|
||||
|
||||
local prog = 1
|
||||
local alph = 0
|
||||
|
||||
if pa.ft < CurTime() then
|
||||
// pass
|
||||
elseif pa.dt < CurTime() then
|
||||
local d = (CurTime() - pa.dt) / (pa.ft - pa.dt)
|
||||
|
||||
alph = 1 - d
|
||||
elseif pa.bt < CurTime() then
|
||||
alph = 1
|
||||
else
|
||||
local d = math.Clamp(pa:GetLifeTime() / (pa.bt - CurTime()), 0, 1)
|
||||
|
||||
prog = (-d ^ 2) + (2 * d)
|
||||
|
||||
alph = d
|
||||
end
|
||||
|
||||
pa:SetEndSize( pa.radius * prog )
|
||||
pa:SetStartSize( pa.radius * prog )
|
||||
|
||||
pa:SetStartAlpha(255 * alph)
|
||||
pa:SetEndAlpha(255 * alph)
|
||||
|
||||
-- pa:SetLifeTime(pa:GetLifeTime() + FrameTime())
|
||||
pa:SetNextThink( CurTime() + FrameTime() )
|
||||
end )
|
||||
|
||||
table.insert(self.Particles, smoke)
|
||||
end
|
||||
|
||||
emitter:Finish()
|
||||
end
|
||||
|
||||
self.dt = CurTime() + self.Life + self.BillowTime + 2
|
||||
end
|
||||
Reference in New Issue
Block a user