Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function gadget:GetInfo()
- return {
- name = "Damage Handler",
- desc = "Reroutes chain damages as damages made by initial attacker",
- author = "Doo",
- date = "05/11/18",
- license = "GPL",
- layer = 0,
- enabled = true
- }
- end
- if gadgetHandler:IsSyncedCode() then
- local lastAttacker = {} -- lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
- local valid = Spring.ValidUnitID
- local getTeam = Spring.GetUnitTeam
- local alliedt = Spring.AreTeamsAllied
- local ec = Spring.Echo
- local isdead = Spring.GetUnitIsDead
- local getDefID = Spring.GetUnitDefID
- local uSphere = Spring.GetUnitsInSphere
- local addDamages = Spring.AddUnitDamage
- local function live(unitID)
- return (isdead(unitID) == false)
- end
- local function alliedu(unitID1, unitID2)
- local teamID1 = getTeam(unitID1)
- local teamID2 = getTeam(unitID1)
- return alliedt(teamID1, teamID2)
- end
- function gadget:GameFrame(f)
- for unitID, tab in pairs(lastAttacker) do
- if unitID%300 == f%300 then
- if (not valid(unitID)) and (not valid(tab.id)) then
- lastAttacker[unitID] = nil
- end
- end
- end
- end
- function gadget:UnitPreDamaged(unitID, unitDefID, unitTeam, damage, paralyzer, weaponDefID, projectileID, attackerID, attackerDefID, attackerTeam, forceReroute)
- if not unitID then -- unlikely to happen
- return damage
- end
- ---- Any damage that can't be traced back to a proper source (waterDamages, explosion damages after attackerID is rendered invalid, debris damages....) are considered as explosion damages.
- local defs = attackerID and UnitDefs[getDefID(attackerID)]
- local wdefs = WeaponDefs[weaponDefID]
- local explosion = (defs and wdefs and (defs.deathExplosion == wdefs.name)) or true
- -----
- if attackerID and valid(attackerID) and live(attackerID) then -- live, valid attackerID: there is nothing to do besides registering lastAttacker[unitID]
- lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
- elseif attackerID and valid(attackerID) and (not live(attackerID)) then -- dead, valid attackerID
- if not explosion then -- from a "conventional" weapon ( == known source, not a death explosion), nothing to do beside registering lastAttacker
- lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
- else -- Explosion damages
- if alliedu(unitID, attackerID) then -- from an allied unit (== chain damages?)
- if lastAttacker[attackerID] then -- lastAttacker[attackerID] is the unit that killed attackerID, therefor causing the chain damages to unitID
- lastAttacker[unitID] = lastAttacker[attackerID]
- else -- there is no lastAttacker[attackerID] known (rare cases: it is possible attackerID simply self-ded)
- lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
- end
- else -- enemy units: nothing to do as attackerID is dead anyway (no experience to give), simply register it as lastAttacker[unitID]
- lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
- end
- end
- elseif attackerID and (not valid(attackerID)) then -- dead, invalid attackerID: supposedly a rare case but here we sometimes call gadget:UnitPreDamaged again with different IDs and attackerID can be invalid so it still has to be handled
- if not explosion then -- from a "conventional" weapon ( == known source, not a death explosion), nothing to do beside registering lastAttacker
- lastAttacker[unitID] = {id = attackerID, team = attackerTeam} -- nothing to do
- else -- Explosion damages
- if alliedt(unitTeam, attackerTeam) then -- from an allied unit (== chain damages?)
- if lastAttacker[attackerID] then -- lastAttacker[attackerID] is the unit that killed attackerID, therefor causing the chain damages to unitID
- lastAttacker[unitID] = lastAttacker[attackerID]
- else -- there is no lastAttacker[attackerID] known (rare cases: it is possible attackerID simply self-ded)
- lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
- end
- else -- enemy units: nothing to do as attackerID is dead anyway (no experience to give), simply register it as lastAttacker[unitID]
- lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
- end
- end
- elseif not attackerID then -- dead, invalid, no known attackerID: This happens very often in the case of death explosions (can also happen with some conventional weapons)
- if lastAttacker[unitID] then -- If we have a known lastAttacker we will consider it as the source of the damages here. This is an approximation but is rather effective.
- attackerID = lastAttacker[unitID].id
- attackerTeam = lastAttacker[unitID].team
- return gadget:UnitPreDamaged(unitID, unitDefID, unitTeam, damage, paralyzer, weaponDefID, nil, attackerID, attackerDefID, attackerTeam, true) -- we rerun UnitPreDamaged with the new attackerID and attackerTeam, while forcing reroute at the end of this new call.
- else -- we really have no idea what damaged unitID and do nothing
- end
- end
- if forceReroute or (lastAttacker[unitID] and attackerID and lastAttacker[unitID].id ~= attackerID) then -- if the source of the last damages (= the ones we're processing now) isn't attackerID, or if we forced a reroute, we return RerouteDamages()
- attackerID = lastAttacker[unitID].id
- return RerouteDamages(unitID, attackerID, damage, paralyzer, weaponDefID)
- else -- if source == attackerID and forceReroute == nil then we just return the damages
- return damage
- end
- end
- function gadget:Explosion(weaponDefID, px, py, pz, attackerID, projectileID)
- if not attackerID then -- unlikely to happen
- return
- else
- local defs = UnitDefs[getDefID(attackerID)]
- local wdefs = WeaponDefs[weaponDefID]
- if defs.deathExplosion == wdefs.name then -- It is a death explosion
- for i, unitID in pairs(uSphere(px, py, pz, wdefs.damageAreaOfEffect)) do -- All the units that can be affected
- if not (unitID == attackerID) then
- lastAttacker[unitID] = {id = attackerID, team = getTeam(attackerID)} -- mark them as last attacked by attackerID for the upcoming death explosion damages
- end
- end
- end
- end
- end
- function RerouteDamages(unitID, attackerID, damage, paralyzer, weaponDefID)
- if valid(attackerID) then -- our attackerID is valid and we can reroute the damages, we return 0 and AddUnitDamage from the right source (keep same damages, paralyze and weaponDefID)
- if paralyzer == true then
- paralyzer = damage
- damage = 0
- else
- paralyzer = 0
- damage = damage
- end
- addDamages(unitID, damage, paralyzer, attackerID, weaponDefID)
- return 0
- else -- attackerID is invalid, we cannot reroute the damages
- return damage
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement