Advertisement
Guest User

Untitled

a guest
Nov 7th, 2018
213
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.53 KB | None | 0 0
  1. function gadget:GetInfo()
  2.   return {
  3.     name      = "Damage Handler",
  4.     desc      = "Reroutes chain damages as damages made by initial attacker",
  5.     author    = "Doo",
  6.     date      = "05/11/18",
  7.     license   = "GPL",
  8.     layer     = 0,
  9.     enabled   = true
  10.   }
  11. end
  12.  
  13. if gadgetHandler:IsSyncedCode() then
  14.  
  15. local lastAttacker = {} -- lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
  16. local valid = Spring.ValidUnitID
  17. local getTeam = Spring.GetUnitTeam
  18. local alliedt = Spring.AreTeamsAllied
  19. local ec = Spring.Echo
  20. local isdead = Spring.GetUnitIsDead
  21. local getDefID = Spring.GetUnitDefID
  22. local uSphere = Spring.GetUnitsInSphere
  23. local addDamages = Spring.AddUnitDamage
  24.  
  25. local function live(unitID)
  26.     return (isdead(unitID) == false)
  27. end
  28.  
  29. local function alliedu(unitID1, unitID2)
  30.     local teamID1 = getTeam(unitID1)
  31.     local teamID2 = getTeam(unitID1)
  32.     return alliedt(teamID1, teamID2)
  33. end
  34.  
  35. function gadget:GameFrame(f)
  36.     for unitID, tab in pairs(lastAttacker) do
  37.         if unitID%300 == f%300 then
  38.             if (not valid(unitID)) and (not valid(tab.id)) then
  39.                 lastAttacker[unitID] = nil
  40.             end
  41.         end
  42.     end
  43. end
  44.  
  45. function gadget:UnitPreDamaged(unitID, unitDefID, unitTeam, damage, paralyzer, weaponDefID, projectileID, attackerID, attackerDefID, attackerTeam, forceReroute)
  46.     if not unitID then -- unlikely to happen
  47.         return damage
  48.     end
  49.    
  50.     ---- 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.
  51.     local defs = attackerID and UnitDefs[getDefID(attackerID)]
  52.     local wdefs = WeaponDefs[weaponDefID]
  53.     local explosion = (defs and wdefs and (defs.deathExplosion == wdefs.name)) or true
  54.     -----
  55.    
  56.     if attackerID and valid(attackerID) and live(attackerID) then -- live, valid attackerID: there is nothing to do besides registering lastAttacker[unitID]
  57.         lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
  58.     elseif attackerID and valid(attackerID) and (not live(attackerID)) then  -- dead, valid attackerID
  59.         if not explosion then -- from a "conventional" weapon ( == known source, not a death explosion), nothing to do beside registering lastAttacker
  60.             lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
  61.         else -- Explosion damages
  62.             if alliedu(unitID, attackerID) then -- from an allied unit (== chain damages?)
  63.                 if lastAttacker[attackerID] then -- lastAttacker[attackerID] is the unit that killed attackerID, therefor causing the chain damages to unitID
  64.                     lastAttacker[unitID] = lastAttacker[attackerID]
  65.                 else -- there is no lastAttacker[attackerID] known (rare cases: it is possible attackerID simply self-ded)
  66.                     lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
  67.                 end
  68.             else -- enemy units: nothing to do as attackerID is dead anyway (no experience to give), simply register it as lastAttacker[unitID]
  69.                 lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
  70.             end
  71.         end
  72.     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
  73.         if not explosion then -- from a "conventional" weapon ( == known source, not a death explosion), nothing to do beside registering lastAttacker
  74.             lastAttacker[unitID] = {id = attackerID, team = attackerTeam} -- nothing to do
  75.         else -- Explosion damages
  76.             if alliedt(unitTeam, attackerTeam) then -- from an allied unit (== chain damages?)
  77.                 if lastAttacker[attackerID] then -- lastAttacker[attackerID] is the unit that killed attackerID, therefor causing the chain damages to unitID
  78.                     lastAttacker[unitID] = lastAttacker[attackerID]
  79.                 else -- there is no lastAttacker[attackerID] known (rare cases: it is possible attackerID simply self-ded)
  80.                     lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
  81.                 end
  82.             else -- enemy units: nothing to do as attackerID is dead anyway (no experience to give), simply register it as lastAttacker[unitID]
  83.                 lastAttacker[unitID] = {id = attackerID, team = attackerTeam}
  84.             end
  85.         end
  86.     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)
  87.         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.
  88.             attackerID = lastAttacker[unitID].id
  89.             attackerTeam = lastAttacker[unitID].team
  90.             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.
  91.         else -- we really have no idea what damaged unitID and do nothing
  92.         end
  93.     end
  94.     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()
  95.         attackerID = lastAttacker[unitID].id
  96.         return RerouteDamages(unitID, attackerID, damage, paralyzer, weaponDefID)
  97.     else -- if source == attackerID and forceReroute == nil then we just return the damages
  98.         return damage
  99.     end
  100. end
  101.  
  102. function gadget:Explosion(weaponDefID, px, py, pz, attackerID, projectileID)
  103.     if not attackerID then -- unlikely to happen
  104.         return
  105.     else
  106.         local defs = UnitDefs[getDefID(attackerID)]
  107.         local wdefs = WeaponDefs[weaponDefID]
  108.         if defs.deathExplosion == wdefs.name then -- It is a death explosion
  109.             for i, unitID in pairs(uSphere(px, py, pz, wdefs.damageAreaOfEffect)) do -- All the units that can be affected
  110.                 if not (unitID == attackerID) then
  111.                     lastAttacker[unitID] = {id = attackerID, team = getTeam(attackerID)} -- mark them as last attacked by attackerID for the upcoming death explosion damages
  112.                 end
  113.             end
  114.         end
  115.     end
  116. end
  117.  
  118. function RerouteDamages(unitID, attackerID, damage, paralyzer, weaponDefID)
  119.     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)
  120.         if paralyzer == true then
  121.             paralyzer = damage
  122.             damage = 0
  123.         else
  124.             paralyzer = 0
  125.             damage = damage
  126.         end
  127.         addDamages(unitID, damage, paralyzer, attackerID, weaponDefID)
  128.         return 0
  129.     else -- attackerID is invalid, we cannot reroute the damages
  130.         return damage
  131.     end
  132. end
  133. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement