Detecting Hero that killed even though the hero was not last to hit the enemy

edited January 2017 in Questions

So the issue I am having right now is how do I find the hero that got the kill since my current code only grabs the unit that got the last hit when the kill took place and as a result the expected outcome is off

function GameMode:OnEntityKilled( keys )
  DebugPrint( '[BAREBONES] OnEntityKilled Called' )
  DebugPrintTable( keys )
   -- The Unit that was Killed
  local killedUnit = EntIndexToHScript( keys.entindex_killed )
  -- The Killing entity
  local killerEntity = nil
  if keys.entindex_attacker ~= nil then
    killerEntity = EntIndexToHScript( keys.entindex_attacker )
  end
 -- The ability/item used to kill, or nil if not killed by an item/ability
  local killerAbility = nil
  if keys.entindex_inflictor ~= nil then
    killerAbility = EntIndexToHScript( keys.entindex_inflictor )
  end
 -- Put code here to handle when an entity gets killed
if  killerEntity:IsHero() and killedUnit:IsHero() then
    if killedUnit:GetBaseStrength() > 1 and killedUnit:GetBaseIntellect() > 1 and   killedUnit:GetBaseAgility() > 1 then
     killedUnit:SetBaseStrength(killedUnit:GetBaseStrength()  - 1)
     killedUnit:SetBaseIntellect(killedUnit:GetBaseIntellect()  - 1)
     killedUnit:SetBaseAgility(killedUnit:GetBaseAgility()  - 1)
 end

    killerEntity:SetBaseStrength(killerEntity:GetBaseStrength()  + 1)
    killerEntity:SetBaseIntellect(killerEntity:GetBaseIntellect()  + 1)
    killerEntity:SetBaseAgility(killerEntity:GetBaseAgility()  + 1)

 end
end

Comments

  • edited January 2017 Posts: 96

    Instead of listening to just entity_killed event, listen to both entity_hurt and entity_killed event and attach hero to the entity. For example:

    ListenToGameEvent( "entity_hurt", Dynamic_Wrap( GameMode, "OnUnitHurt" ), self )
    ListenToGameEvent( "entity_killed", Dynamic_Wrap( GameMode, "OnUnitKilled" ), self )
    
    function GameMode:OnUnitHurt( keys )
      local hurt_unit = EntIndexToHScript( keys.entindex_killed )
      local attacker = EntIndexToHScript( keys.entindex_attacker )
    
      if attacker and attacker:IsRealHero() then -- or attacker:IsHero() up to you
        hurt_unit.last_hero_hit = attacker
      end
    end
    
    function GameMode:OnUnitKilled( keys )
      local hurt_unit = EntIndexToHScript( keys.entindex_killed )
      --[[
        Set whatever you want
      ]]
    
      if hurt_unit.last_hero_hit then
        --[[
          Do whatever you want
        ]]
      end
    end
    

    Though i'm not sure if there is quick API to handle this case.

  • edited January 2017 Posts: 273

    @Tanner

    You need to check if the unit that did the last hit is a lane creep or player-controlled creep. Maybe with this: IsControllableByAnyPlayer(). If yes check if its a hero, if not then find the owner and player. Then find the hero assigned to the player. If a unit is a lane creep, make a code that finds the nearest allied hero. So something like this:

    if killerEntity:IsControllableByAnyPlayer() then
       if killerEntity:IsRealHero() then
          -- your code with attributes
       else
          local killer_owner = killerEntity:GetOwner()
          local killer_playerID = killer_owner:GetPlayerID()
          local killer_player = PlayerResource:GetPlayer(killer_playerID)
          local killer_hero = killer_player:GetAssignedHero()
          -- your code with attributes
       end
    else
    -- code about finding the neareast allied hero
    -- when you find the nearest allied hero to the unit that did the last hit, apply your code with attributes
    end
    

    Note that this is not entirely precise when a lane creep do the last hit, but its better than nothing.

    Use IsRealHero() instead of IsHero(), unless you want your code to be applied on illusions too. I suggest you use :CalculateStatBonus() after changing attributes.

  • Posts: 14

    Thank you everyone I will try each of these and some variations to see which works best