Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- --[[
- When an object has a different entrance and exit surface material, the damage lost is calculated using the average resistance of the two.
- penmod: How easy it is for a bullet to go through the material (0.001 to 1.0).
- dmgmod: How much of the damaging power of the bullet is preserved while going through the material (0.001 to 1.0).
- ]]
- local mat_translation = {
- [MAT_CONCRETE] = {
- name = "concrete",
- penmod = 0.5,
- dmgmod = 0.25
- },
- [MAT_DIRT] = {
- name = "dirt",
- penmod = 0.6,
- dmgmod = 0.3
- },
- [MAT_EGGSHELL] = "The egg sacs in the antlion tunnels in HL2: EP2",
- [MAT_FLESH] = {
- name = "flesh",
- penmod = 0.9,
- dmgmod = 0.5
- },
- [MAT_GRATE] = {
- name = "grate",
- penmod = 0.95,
- dmgmod = 0.99
- },
- [MAT_CLIP] = "Unused",
- [MAT_SNOW] = {
- name = "snow",
- penmod = 0.85,
- dmgmod = 0.5
- },
- [MAT_PLASTIC] = {
- name = "plastic",
- penmod = 0.3,
- dmgmod = 0.25
- },
- [MAT_METAL] = {
- name = "metal",
- penmod = 0.4,
- dmgmod = 0.3
- },
- [MAT_SAND] = {
- name = "sand",
- penmod = 0.3,
- dmgmod = 0.25
- },
- [MAT_FOLIAGE] = {
- name = "foliage",
- penmod = 0.95,
- dmgmod = 0.5
- },
- [MAT_COMPUTER] = {
- name = "computer",
- penmod = 0.4,
- dmgmod = 0.45
- },
- [MAT_SLOSH] = {
- name = "Water, slime",
- penmod = 0.3
- },
- [MAT_TILE] = {
- name = "tile",
- penmod = 0.7,
- dmgmod = 0.3
- },
- [MAT_VENT] = {
- name = "vent",
- penmod = 0.6,
- dmgmod = 0.45
- },
- [MAT_WOOD] = {
- name = "wood",
- penmod = 0.9,
- dmgmod = 0.6
- },
- [MAT_DEFAULT] = {
- name = "default",
- penmod = 1.0,
- dmgmod = 0.5
- },
- [MAT_GLASS] = {
- name = "glass",
- penmod = 0.99,
- dmgmod = 0.5
- },
- [MAT_WARPSHIELD] = "\"wierd-looking jello effect for advisor shield.\"",
- }
- mat_translation[MAT_GRASS] = table.Copy(mat_translation[MAT_DIRT])
- mat_translation[MAT_GRASS].name = "grass"
- mat_translation[MAT_ALIENFLESH] = table.Copy(mat_translation[MAT_FLESH])
- mat_translation[MAT_ALIENFLESH].name = "alien flesh"
- mat_translation[MAT_BLOODYFLESH] = table.Copy(mat_translation[MAT_FLESH])
- mat_translation[MAT_BLOODYFLESH].name = "bloody flesh"
- mat_translation[MAT_ANTLION] = table.Copy(mat_translation[MAT_FLESH])
- mat_translation[MAT_ANTLION].name = "antlion"
- local function calc_lost_damage(wep, enter_trace, exit_trace, currentDamage)
- local enter_data = mat_translation[enter_trace.MatType] or mat_translation[MAT_DEFAULT]
- local exit_data = mat_translation[exit_trace.MatType] or mat_translation[MAT_DEFAULT]
- local is_solid_surf = bit.band(bit.rshift(enter_trace.Contents, 3), CONTENTS_SOLID) ~= 0
- local is_light_surf = bit.band(bit.rshift(enter_trace.SurfaceFlags, 7), SURF_LIGHT) ~= 0
- local thickness, modifier, lostDamage, finalDamageModifier, combinedPenetrationModifier
- if enter_trace.MatType == MAT_GLASS or enter_trace.MatType == MAT_GRATE then
- combinedPenetrationModifier = 3
- finalDamageModifier = .05
- elseif is_solid_surf or is_light_surf then
- combinedPenetrationModifier = 1
- finalDamageModifier = .16
- else
- combinedPenetrationModifier = (enter_data.penmod + exit_data.penmod) / 2
- finalDamageModifier = .16
- end
- if enter_trace.MatType == exit_trace.MatType then
- if enter_trace.MatType == MAT_DIRT or enter_trace.MatType == MAT_WOOD then
- combinedPenetrationModifier = 3
- elseif enter_trace.MatType == MAT_PLASTIC then
- combinedPenetrationModifier = 2
- end
- end
- thickness = (exit_trace.HitPos - enter_trace.HitPos):LengthSqr()
- modifier = math.max(1 / combinedPenetrationModifier, 0)
- local penetrationPower = wep.PenetrationPower or 1
- lostDamage = math.max(
- ((modifier * thickness) / 24)
- + ((currentDamage * finalDamageModifier)
- + (math.max(3.75 / penetrationPower, 0) * 3 * modifier)), 0)
- if lostDamage > currentDamage then
- return currentDamage
- end
- return lostDamage
- end
- function SWEP:BulletCallback(atk, tr, dmg, pens)
- if CLIENT and not IsFirstTimePredicted() then return end
- local impacts = sv_showimpacts:GetInt()
- local penetrations = sv_showimpacts_penetration:GetInt()
- pens = pens or 0
- if impacts == 1 or (CLIENT and impacts == 2) or (SERVER and impacts == 3) then
- debugoverlay.Box(tr.HitPos, Vector(1,1,1), -Vector(1,1,1), sv_showimpacts_time:GetFloat(), CLIENT and Color(255,0,0,128) or Color(0,0,255,128))
- end
- local mat = mat_translation[tr.MatType] or mat_translation[MAT_DEFAULT]
- if SERVER and penetrations ~= 0 then
- local nice_dist = util.NiceMetric(util.HUtoCM(tr.HitPos:Distance(tr.StartPos)))
- debugoverlay.EntityTextAtPosition(tr.HitPos, -2, mat.name, sv_showimpacts_time:GetFloat(), Color(0,255,0, 64))
- debugoverlay.EntityTextAtPosition(tr.HitPos, 0, "^", sv_showimpacts_time:GetFloat(), Color(255, 154, 0, 64))
- if penetrations == 2 then
- debugoverlay.EntityTextAtPosition(tr.HitPos, 1, dmg:GetDamage(), sv_showimpacts_time:GetFloat(), Color(255,0,0))
- debugoverlay.EntityTextAtPosition(tr.HitPos, 2, nice_dist, sv_showimpacts_time:GetFloat(), Color(255, 129, 62))
- else
- debugoverlay.EntityTextAtPosition(tr.HitPos, 1, string.format("DAMAGE APPLIED: %d", dmg:GetDamage()), sv_showimpacts_time:GetFloat(), Color(255,0,0))
- debugoverlay.EntityTextAtPosition(tr.HitPos, 2, string.format("TOTAL DISTANCE: %s", nice_dist), sv_showimpacts_time:GetFloat(), Color(255, 129, 62))
- end
- end
- if pens > 3 then return end
- if tr.HitSky then return end
- -- Bullet Penetration
- local dir = tr.Normal
- local back_tr
- local filter = not tr.Entity:IsWorld() and tr.Entity or nil
- for i = 1, 1000 do
- local new_tr = util.TraceLine({
- endpos = tr.HitPos,
- start = tr.HitPos + dir * i,
- --filter = filter
- })
- --print(new_tr.Entity, new_tr.HitNoDraw, new_tr.StartSolid, not (new_tr.HitNoDraw or new_tr.StartSolid))
- if not (new_tr.HitNoDraw or new_tr.StartSolid) then
- --print("found back_tr", new_tr.Entity)
- back_tr = new_tr
- break
- end
- end
- if not back_tr then return end
- local back_mat = mat_translation[back_tr.MatType] or mat_translation[MAT_DEFAULT]
- local original_damage = dmg:GetDamage()
- local dmg_lost = calc_lost_damage(self, tr, back_tr, original_damage)
- dmg:SetDamage(original_damage - dmg_lost)
- if dmg:GetDamage() <= 0 then
- --print("STOPPED!")
- return
- end
- if SERVER and penetrations ~= 0 then
- local nice_dist = util.NiceMetric(util.HUtoCM(tr.HitPos:Distance(back_tr.StartPos)))
- debugoverlay.Line(tr.HitPos, back_tr.StartPos, sv_showimpacts_time:GetFloat(), Color(16,192,192), true)
- if penetrations == 2 then
- debugoverlay.EntityTextAtPosition(back_tr.HitPos, -3, nice_dist, sv_showimpacts_time:GetFloat(), Color(255,128,128))
- debugoverlay.EntityTextAtPosition(back_tr.HitPos, -2, string.format("%d", dmg:GetDamage() - original_damage), sv_showimpacts_time:GetFloat(), Color(255,0,0, 64))
- debugoverlay.EntityTextAtPosition(back_tr.HitPos, -1, back_mat.name, sv_showimpacts_time:GetFloat(), Color(32,128,196, 64))
- else
- debugoverlay.EntityTextAtPosition(back_tr.HitPos, -3, string.format("THICKNESS: %s", nice_dist), sv_showimpacts_time:GetFloat(), Color(255,128,128))
- debugoverlay.EntityTextAtPosition(back_tr.HitPos, -2, string.format("LOST DAMAGE: %d", original_damage - dmg:GetDamage()), sv_showimpacts_time:GetFloat(), Color(255,0,0, 64))
- debugoverlay.EntityTextAtPosition(back_tr.HitPos, -1, back_mat.name, sv_showimpacts_time:GetFloat(), Color(32,128,196, 64))
- end
- end
- local data = EffectData()
- data:SetOrigin(back_tr.HitPos)
- data:SetStart(back_tr.StartPos)
- data:SetSurfaceProp(back_tr.SurfaceProps)
- data:SetDamageType(dmg:GetDamageType())
- data:SetHitBox(back_tr.HitBox)
- data:SetEntity(back_tr.Entity)
- if SERVER or (CLIENT and IsFirstTimePredicted()) then
- util.Effect("Impact", data, not game.SinglePlayer())
- end
- self:FireBullets({
- Src = back_tr.HitPos,
- Dir = dir,
- Num = 1,
- AmmoType = self.Primary.Ammo,
- Tracer = 0,
- Attacker = self:GetOwner(),
- Spread = vector_origin,
- Damage = dmg:GetDamage(),
- Distance = self.BulletDistance,
- Callback = function(atk, tr, dmg) self:BulletCallback(atk, tr, dmg, pens + 1) end
- })
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement