local BASE_DAMAGE = 90 local WEAPON_STICKY_GRENADE = 3 local VALID_WEAPON_CLASSES = {"tf_weapon_rocketlauncher", "tf_weapon_rocketlauncher_directhit", "tf_weapon_rocketlauncher_airstrike", "tf_weapon_flaregun_revenge", "tf_weapon_flaregun", "tf_weapon_cleaver"} local function weaponMimic(properties) local mimic = ents.CreateWithKeys("tf_point_weapon_mimic", properties) return mimic end local function addGlobalDamageCallback(player) -- Weird hack to fix conch not healing with penetration (thanks Orin xoxo) player:AddCallback(ON_DAMAGE_RECEIVED_PRE, function(_, damageinfo) -- Ugly way to check for rocket penetrations if damageinfo.Inflictor == nil then return end if damageinfo.Inflictor:GetClassname() ~= "tf_projectile_pipe" then return end if damageinfo.Weapon ~= nil then return end damageinfo.Weapon = damageinfo.Attacker:GetPlayerItemBySlot(LOADOUT_POSITION_PRIMARY) return true end) end function OnPlayerConnected(player) addGlobalDamageCallback(player) end local function addPenetration(projectile, useDamageTable, useDamageTableAlt) timer.Simple(0, function() if not IsValid(projectile) then return end local owner = projectile.m_hOwnerEntity --print(owner) if not owner then local originalLauncher = projectile.m_hOriginalLauncher owner = originalLauncher.m_hOwner end --combat tanks, and weapon mimics if not owner:IsPlayer() then return end local primary --print(owner) if not useDamageTable then primary = owner:GetPlayerItemBySlot(LOADOUT_POSITION_PRIMARY) else primary = owner:GetPlayerItemBySlot(1) end local classMatch = false local decidedClass for _, className in pairs(VALID_WEAPON_CLASSES) do if primary:GetClassname() == className then classMatch = true decidedClass = className end end if classMatch == false then return end local maxPenetrationCount = primary:GetAttributeValue("projectile penetration") if not maxPenetrationCount then --print("No penetration attribute") return end local callback; local isCrit = projectile.m_bCritical local penetrated = {} local penetrations = 0 callback = projectile:AddCallback(ON_SHOULD_COLLIDE, function(_, collided) -- CTFPlayer, then NextBotCombatCharacter, then CTFBaseObject --print(collided:GetClassname()) if not collided:IsPlayer() and not collided:IsNPC() and not collided:IsObject() and not collided:GetClassname() == "entity_medigun_shield" then return end if collided.m_iTeamNum == owner.m_iTeamNum then return false end if collided:GetClassname() == "entity_medigun_shield" then --print("That was a shield, we don't care.") return false end -- Make sure it hasn't been penetrated already local index = collided:GetHandleIndex() if penetrated[index] then --print("Already Penetrated") return false end -- Boring shit if penetrations >= maxPenetrationCount then --print("Hit our cap") projectile:RemoveCallback(callback) return end penetrations = penetrations + 1 penetrated[index] = true -- Good shit local damageBonusMult = primary:GetAttributeValueByClass("mult_dmg", 1) local damage = BASE_DAMAGE * damageBonusMult if decidedClass ~= "tf_weapon_cleaver" and decidedClass ~= "tf_weapon_flaregun_revenge" and decidedClass ~= "tf_weapon_flaregun" then local blastRadisuMult = primary:GetAttributeValueByClass("mult_explosion_radius", 1) local blastRadius = 146 * blastRadisuMult if collided:IsPlayer() and primary:GetAttributeValue("rocket specialist", true) ~= nil then blastRadius = blastRadius * ( 1 + ( primary:GetAttributeValue("rocket specialist", true) * 0.15 ) ) --rocket spec scales blast radius if not tobool(collided.m_bIsMiniBoss ) then collided:StunPlayer(1, 1, TF_STUNFLAG_SLOWDOWN, owner) else collided:StunPlayer(1, 0.85, TF_STUNFLAG_SLOWDOWN, owner) end local damageTable = { Attacker = owner, Inflictor = projectile, Weapon = primary, Damage = damage, DamageType = DMG_BLAST, DamageCustom = TF_DMG_CUSTOM_NONE, CritType = isCrit, DamagePosition = projectile:GetAbsOrigin(), ReportedPosition = projectile:GetAbsOrigin(), } collided:TakeDamage(damageTable) --damage = damage * 0.3 --dumb end local mimic = weaponMimic({ TeamNum = owner.m_iTeamNum, WeaponType = WEAPON_STICKY_GRENADE, -- sticky Damage = damage, Crits = isCrit, SplashRadius = blastRadius, SpeedMax = 0, SpeedMin = 0, ["$dmgtype"] = 69420, ["$killicon"] = "player_penetration", origin = tostring(projectile:GetAbsOrigin()), angles = tostring(Vector(0, 0, 0)), }) mimic["$SetOwner"](mimic, owner) mimic:FireOnce() mimic:DetonateStickies() timer.Simple(0.1, function() --print("Removed mimic") mimic:Remove() end) return false elseif decidedClass == "tf_weapon_flaregun_revenge" then local base_damage = 30 local baseDamageTypes = DMG_BURN|DMG_IGNITE if isCrit ~= 0 then baseDamageTypes = DMG_BURN|DMG_CRITICAL|DMG_IGNITE end local damageTable = { Attacker = owner, Inflictor = projectile, Weapon = primary, Damage = base_damage * damageBonusMult, DamageType = baseDamageTypes, DamageCustom = TF_DMG_CUSTOM_BURNING, CritType = isCrit, DamagePosition = projectile:GetAbsOrigin(), ReportedPosition = projectile:GetAbsOrigin(), } collided:TakeDamage(damageTable) return false elseif decidedClass == "tf_weapon_flaregun" then local base_damage = 30 local baseDamageTypes = DMG_BURN|DMG_IGNITE if isCrit ~= 0 then baseDamageTypes = DMG_BURN|DMG_CRITICAL|DMG_IGNITE end if collided:InCond( TF_COND_BURNING ) then if isCrit == 0 then isCrit = 1 end end local damageTable = { Attacker = owner, Inflictor = projectile, Weapon = primary, Damage = base_damage * damageBonusMult, DamageType = baseDamageTypes, DamageCustom = TF_DMG_CUSTOM_BURNING, CritType = isCrit, DamagePosition = projectile:GetAbsOrigin(), ReportedPosition = projectile:GetAbsOrigin(), } projectile.m_vecAbsVelocity = projectile.m_vecAbsVelocity / 2 collided:TakeDamage(damageTable) collided:StunPlayer( 1, 0.85, TF_STUNFLAG_SLOWDOWN, owner ) return false elseif decidedClass == "tf_weapon_cleaver" then local base_damage = 50 local baseDamageTypes = DMG_MELEE damageBonusMult = primary:GetAttributeValueByClass("mult_dmg_vs_players", 1) if isCrit ~= 0 then baseDamageTypes = DMG_MELEE|DMG_CRITICAL end local damageTable = { Attacker = owner, Inflictor = projectile, Weapon = primary, Damage = base_damage * damageBonusMult, DamageType = baseDamageTypes, DamageCustom = TF_DMG_CUSTOM_BLEEDING, CritType = isCrit, DamagePosition = projectile:GetAbsOrigin(), ReportedPosition = projectile:GetAbsOrigin(), } collided:TakeDamage(damageTable) --collided:BleedPlayer(10) return false end return false end) end) end ents.AddCreateCallback("tf_projectile_flare", function(projectile) addPenetration(projectile, true) --print("That was a flare.") end) ents.AddCreateCallback("tf_projectile_rocket", function(projectile) addPenetration(projectile) end) ents.AddCreateCallback("tf_projectile_cleaver", function(projectile) addPenetration(projectile, true) end) local function checkLineOfSight(activator, caller) local activatorAngles = activator:GetAbsAngles() --thanks mince local callerHead = caller:GetAbsOrigin() + Vector(0, 0, caller["m_vecViewOffset[2]"]); local traceAngles = (callerHead - (activator:GetAbsOrigin() + Vector( 0, 0, activatorAngles[3] ))):ToAngles() traceAngles = Vector(traceAngles[1], traceAngles[2], 0) local TraceLineOfSight = { start = activator, -- Start position vector. Can also be set to entity, in this case the trace will start from entity eyes position distance = 10000, -- Used if endpos is nil angles = traceAngles, -- Used if endpos is nil mask = MASK_SOLID, -- Solid type mask, see MASK_* globals collisiongroup = COLLISION_GROUP_PLAYER, -- Pretend the trace to be fired by an entity belonging to this group. See COLLISION_GROUP_* globals } local lineOfSightTraceTable = util.Trace(TraceLineOfSight) --PrintTable(lineOfSightTraceTable) --print(lineOfSightTraceTable.HitPos) if lineOfSightTraceTable.Hit == true and lineOfSightTraceTable.HitWorld == false then --print("Enemy is in our line of sight") return true else --print("Enemy is not in our line of sight") return false end end function pipePenetrateOnKill(damage, activator, caller) local primary = activator:GetPlayerItemBySlot(0) local primaryHealOnKill = primary:GetAttributeValue("heal on kill", true) or 0 local primaryDamage = ( primary:GetAttributeValue("damage bonus", true) or 1 ) local activatorTeamNum = activator.m_iTeamNum local activatorOrigin = activator:GetAbsOrigin() local callerOriginAdjusted = caller:GetAbsOrigin() + Vector(0, 0, 21.4) local targetAngles local listOfTargetsUnsorted = {} local selectedTarget = activator --in case nobody else is picked. local selectedTargetDistance = 800 local BASE_DAMAGE = 100 if damage < BASE_DAMAGE * primaryDamage then return end local mimic = weaponMimic({ TeamNum = activator.m_iTeamNum, ["$weaponname"] = primary:GetItemName(), origin = tostring(callerOriginAdjusted), angles = tostring(Vector(0,0,0)), }) for _, player in pairs(ents.GetAllPlayers()) do if player.m_iTeamNum ~= activatorTeamNum and player:IsAlive() and ( player:GetAbsOrigin():Distance(callerOriginAdjusted) <= 800 ) then if checkLineOfSight(mimic, player) then table.insert(listOfTargetsUnsorted, player) end end end if type(next(listOfTargetsUnsorted)) ~= "nil" then local listOfTargetsSortedHealth = {} for _, player in pairs(listOfTargetsUnsorted) do if player.m_iHealth < (100 * primaryDamage) then table.insert(listOfTargetsSortedHealth, player) end end local lowestTargetDistance = 9999 if type(next(listOfTargetsSortedHealth)) ~= "nil" then for _, player in pairs(listOfTargetsSortedHealth) do local targetDistance = player:GetAbsOrigin():Distance(callerOriginAdjusted) if targetDistance < lowestTargetDistance then lowestTargetDistance = targetDistance selectedTarget = player selectedTargetDistance = targetDistance end end else for _, player in pairs(listOfTargetsUnsorted) do local targetDistance = player:GetAbsOrigin():Distance(callerOriginAdjusted) if targetDistance < lowestTargetDistance then lowestTargetDistance = targetDistance selectedTarget = player selectedTargetDistance = targetDistance end end end end --targetAngles = (selectedTarget:GetAbsOrigin() - mimic:GetAbsOrigin()):ToAngles() targetAngles = mimic:GetAbsOrigin():FaceVector( selectedTarget:GetEyePos() ) -- -0.00132 is a manually calibrated constant based on the stock loch n load. --targetAngles = Vector((targetAngles[1] - (selectedTargetDistance * -0.00132)), targetAngles[2], 0):ToAngles() --activator:SetAbsOrigin(callerOriginAdjusted) --activator:SnapEyeAngles(targetAngles) mimic:SetAbsAngles(targetAngles) mimic["$SetOwner"](mimic, activator) mimic["$AddWeaponAttribute"](mimic, "heal on kill|" .. primaryHealOnKill) mimic["$AddWeaponAttribute"](mimic, "damage bonus|" .. primaryDamage) --mimic["$AddWeaponAttribute"](mimic, "blast radius decreased|" .. 0.3) --mimic["$AddWeaponAttribute"](mimic, "fire input on kill|popscript^$pipePenetrateOnKill^") --funny, but OP as fuck mimic:FireOnce() timer.Simple(0.1, function() --print("Removed mimic") mimic:Remove() end) end