Page 1 of 2 1 2 LastLast
Results 1 to 10 of 20

Thread: [Intended?] Slark's Essence Shift lacks an Attack Speed threshold check

  1. #1
    Basic Member ThoAppelsin's Avatar
    Join Date
    Jan 2012
    Posts
    2,892

    [Intended?] Slark's Essence Shift lacks an Attack Speed threshold check

    Slark is able to shift essence with an Attack Speed lower than 50
    he shouldn't be able to shift essence when his Attack Speed is below 50


    One may call this as an intended change, but I would say no and defend otherwise.
    I may provide a jass explanation for this if requested

  2. #2
    I considered this an intended change, i do hope it stays the way it is now.

  3. #3
    Volunteer Moderator
    Join Date
    Mar 2012
    Location
    Australia
    Posts
    2,671
    Surely this was protection to stop him essence shifting when he kept failing attacks at low attack speed? This doesn't happen anymore and works when the attack lands instead so surely this is a fix? But I'd love to hear your reasoning.

    And reading your playdota thread this is the EXACT reason it doesn't work in dota 1... This isn't an issue in dota 2, and it can be checked properly, just like all the other on-attack modifiers... So... Yeah... Why the hell isn't this intended?
    Last edited by Wyn-Ryder; 04-05-2013 at 06:31 PM.

  4. #4
    Basic Member Kaneomanie's Avatar
    Join Date
    Oct 2012
    Posts
    694
    Being reluctant with intended changes is alright but in this case I don't see the point in copying a dota 1 workaround for a problem that is nonexistent in dota 2, am I missing something here?

  5. #5
    Basic Member ThoAppelsin's Avatar
    Join Date
    Jan 2012
    Posts
    2,892
    No such thing

    Essence Shift in DotA takes its effect after passing through numereous checks.
    I will try to explain it simple but complete, without making it sound too complicated; and I will add the full function chain for the Essence Shift at the end of this post:

    1 - Leveling up this skill A1HR (Essence Shift) activates everything
    2 - ATTACKED event triggers the next function
    3 - Check if the attacker has the ability A1HR over level zero and is Slark
    4 - Check if the attacked unit is a hero and not a structure and not Roshan and an enemy of the attacker
    5 - Check if the triggered cooldown is off the cooldown
    6 - Put the triggered cooldown on cooldown (0.45 - 0.05*lvl)
    7 - Either DAMAGED event, or the 1 sec countdown timer triggers the next function
    8 - If the trigger was the DAMAGED event and the damage source was the Slark; disable the trigger, and shift essence after 0.01 second
    8 - If the trigger was the 1 sec countdown timer, disable the trigger


    Wow, went better than I thought. I think this is really simple now. It only needs these two extra info:
    ATTACKED event: it is when an attacker begins its attacking animation against the ATTACKED unit, the t = 0
    DAMAGED event: it is when a unit receives a damage, the t = attackPoint(oftheAttacker)


    If a Slark fails to land the attack he started; Essence Shift simply won't shift anything, not because of the timer, but because of the DAMAGED event is not fulfilled.
    Whether there be a timer or not, Slark may not shift essence until he starts an ATTACK, and then deals DAMAGE to the target.

    The timer effectively prevents Slark from shifting essence if it takes him longer than 1 second for him to fulfill DAMAGED event after breaching the ATTACKED event.
    Slark has the attack point 0.5. With -50 IAS, his attack point increases to 1 sec. -50 IAS and anything lower than that makes him unable to shift essence.


    Setting that timer to be anything higher than 2.5 would allow Slark to shift essence at any IAS, yet it is set to 1, which achieves almost nothing else than an IAS threshold.
    Promised JASS:


    Code:
    function Func3542 takes nothing returns boolean
      local trigger loc_trigger01=GetTriggeringTrigger()
      local integer loc_integer01=GetHandleId(loc_trigger01)
      local unit loc_unit01=(LoadUnitHandle(hashtable001,(loc_integer01),(2)))
      local unit loc_unit02=GetDyingUnit()
      if GetOwningPlayer(GetKillingUnit())==GetOwningPlayer(loc_unit01)and IsUnitType(loc_unit02,UNIT_TYPE_HERO)==true and IsUnitIllusion(loc_unit02)==false then
      endif
      set loc_trigger01=null
      set loc_unit01=null
      set loc_unit02=null
      return false
    endfunction
    
    function Func3543 takes nothing returns boolean
      local trigger loc_trigger01=GetTriggeringTrigger()
      local integer loc_integer01=GetHandleId(loc_trigger01)
      local unit loc_unit01=(LoadUnitHandle(hashtable001,(loc_integer01),(2)))
      local unit loc_unit02=(LoadUnitHandle(hashtable001,(loc_integer01),(17)))
      local integer loc_integer02=(LoadInteger(hashtable001,(loc_integer01),(422)))
      local integer loc_integer03=(LoadInteger(hashtable001,(loc_integer01),(423)))
      local integer loc_integer04=(LoadInteger(hashtable001,(loc_integer01),(424)))
      if GetTriggerEventId()==EVENT_UNIT_DEATH then
        if(LoadBoolean(hashtable001,(loc_integer01),(276)))==false and GetTriggerUnit()==loc_unit01 then
          call SaveBoolean(hashtable001,(loc_integer01),(276),(true))
          call SetHeroAgi(loc_unit01,GetHeroAgi(loc_unit01,false)-loc_integer02-loc_integer03-loc_integer04,true)
        elseif(LoadBoolean(hashtable001,(loc_integer01),(277)))==false and GetTriggerUnit()==loc_unit02 then
          call SaveBoolean(hashtable001,(loc_integer01),(277),(true))
          call SetHeroAgi(loc_unit02,GetHeroAgi(loc_unit02,false)+loc_integer02,true)
          call SetHeroStr(loc_unit02,GetHeroStr(loc_unit02,false)+loc_integer03,true)
          call SetHeroInt(loc_unit02,GetHeroInt(loc_unit02,false)+loc_integer04,true)
        endif
      else
        if(LoadBoolean(hashtable001,(loc_integer01),(276)))==false then
          call SaveBoolean(hashtable001,(loc_integer01),(276),(true))
          call SetHeroAgi(loc_unit01,GetHeroAgi(loc_unit01,false)-loc_integer02-loc_integer03-loc_integer04,true)
        endif
        if(LoadBoolean(hashtable001,(loc_integer01),(277)))==false then
          call SaveBoolean(hashtable001,(loc_integer01),(277),(true))
          call SetHeroAgi(loc_unit02,GetHeroAgi(loc_unit02,false)+loc_integer02,true)
          call SetHeroStr(loc_unit02,GetHeroStr(loc_unit02,false)+loc_integer03,true)
          call SetHeroInt(loc_unit02,GetHeroInt(loc_unit02,false)+loc_integer04,true)
        endif
        call FlushChildHashtable(hashtable001,(loc_integer01))
        call Func0035(loc_trigger01)
      endif
      set loc_trigger01=null
      set loc_unit01=null
      set loc_unit02=null
      return false
    endfunction
    
    function Func3544 takes unit loc_unit01,unit loc_unit02 returns nothing
      local integer loc_integer01=GetUnitAbilityLevel(loc_unit01,'A1HR')
      local integer loc_integer02=Func0045(loc_unit02)
      local trigger loc_trigger01=CreateTrigger()
      local integer loc_integer03=GetHandleId(loc_trigger01)
      local integer loc_integer04
      local integer loc_integer05
      local integer loc_integer06
      local real loc_real01
      if loc_integer02==2 then
        set loc_integer04=IMinBJ(GetHeroAgi(loc_unit02,false)-1,1)
        set loc_integer05=IMinBJ(GetHeroStr(loc_unit02,false)-1,1)
        set loc_integer06=IMinBJ(GetHeroInt(loc_unit02,false)-1,1)
      elseif loc_integer02==3 then
        set loc_integer04=IMinBJ(GetHeroAgi(loc_unit02,false)-1,1)
        set loc_integer05=IMinBJ(GetHeroStr(loc_unit02,false)-1,1)
        set loc_integer06=IMinBJ(GetHeroInt(loc_unit02,false)-1,1)
      elseif loc_integer02==1 then
        set loc_integer04=IMinBJ(GetHeroAgi(loc_unit02,false)-1,1)
        set loc_integer05=IMinBJ(GetHeroStr(loc_unit02,false)-1,1)
        set loc_integer06=IMinBJ(GetHeroInt(loc_unit02,false)-1,1)
      endif
      call SetHeroAgi(loc_unit01,GetHeroAgi(loc_unit01,false)+loc_integer04+loc_integer06+loc_integer05,true)
      call SetHeroAgi(loc_unit02,GetHeroAgi(loc_unit02,false)-loc_integer04,true)
      call SetHeroStr(loc_unit02,GetHeroStr(loc_unit02,false)-loc_integer05,true)
      call SetHeroInt(loc_unit02,GetHeroInt(loc_unit02,false)-loc_integer06,true)
      call SaveInteger(hashtable001,(loc_integer03),(422),(loc_integer04))
      call SaveInteger(hashtable001,(loc_integer03),(424),(loc_integer06))
      call SaveInteger(hashtable001,(loc_integer03),(423),(loc_integer05))
      call SaveUnitHandle(hashtable001,(loc_integer03),(2),(loc_unit01))
      call SaveUnitHandle(hashtable001,(loc_integer03),(17),(loc_unit02))
      call SaveBoolean(hashtable001,(loc_integer03),(276),(false))
      call SaveBoolean(hashtable001,(loc_integer03),(277),(false))
      if loc_integer01==1 then
        set loc_real01=15
      elseif loc_integer01==2 then
        set loc_real01=30
      elseif loc_integer01==3 then
        set loc_real01=60
      elseif loc_integer01==4 then
        set loc_real01=120
      endif
      call TriggerRegisterTimerEvent(loc_trigger01,loc_real01,false)
      call TriggerRegisterUnitEvent(loc_trigger01,loc_unit01,EVENT_UNIT_DEATH)
      call TriggerRegisterUnitEvent(loc_trigger01,loc_unit02,EVENT_UNIT_DEATH)
      call TriggerAddCondition(loc_trigger01,Condition(function Func3543))
      set loc_trigger01=null
    endfunction
    
    function Func3545 takes nothing returns boolean
      local trigger loc_trigger01=GetTriggeringTrigger()
      local integer loc_integer01=GetHandleId(loc_trigger01)
      local unit loc_unit01=(LoadUnitHandle(hashtable001,(loc_integer01),(2)))
      local unit loc_unit02=(LoadUnitHandle(hashtable001,(loc_integer01),(17)))
      if GetTriggerEventId()!=EVENT_UNIT_DEATH then
        call Func3544(loc_unit01,loc_unit02)
      endif
      call FlushChildHashtable(hashtable001,(loc_integer01))
      call Func0035(loc_trigger01)
      set loc_trigger01=null
      set loc_unit01=null
      set loc_unit02=null
      return false
    endfunction
    
    function Func3546 takes nothing returns boolean
      local trigger loc_trigger01=GetTriggeringTrigger()
      local integer loc_integer01=GetHandleId(loc_trigger01)
      local integer loc_integer02=(LoadInteger(hashtable001,(loc_integer01),(30)))
      local unit loc_unit01=Func0022(loc_integer02)
      local unit loc_unit02=(LoadUnitHandle(hashtable001,(loc_integer01),(2)))
      if GetTriggerEventId()==EVENT_UNIT_DAMAGED then
        if GetEventDamageSource()==loc_unit02 then
          call DisableTrigger(loc_trigger01)
          call Func0021(loc_integer02)
          call FlushChildHashtable(hashtable001,(loc_integer01))
          call Func0035(loc_trigger01)
          set loc_trigger01=CreateTrigger()
          set loc_integer01=GetHandleId(loc_trigger01)
          call TriggerRegisterTimerEvent(loc_trigger01,0.01,false)
          call TriggerAddCondition(loc_trigger01,Condition(function Func3545))
          call TriggerRegisterUnitEvent(loc_trigger01,loc_unit02,EVENT_UNIT_DEATH)
          call TriggerRegisterUnitEvent(loc_trigger01,loc_unit01,EVENT_UNIT_DEATH)
          call SaveUnitHandle(hashtable001,(loc_integer01),(2),(loc_unit02))
          call SaveUnitHandle(hashtable001,(loc_integer01),(17),(loc_unit01))
        endif
      else
        call Func0021(loc_integer02)
        call FlushChildHashtable(hashtable001,(loc_integer01))
        call Func0035(loc_trigger01)
      endif
      set loc_trigger01=null
      set loc_unit02=null
      set loc_unit01=null
      return false
    endfunction
    
    function Func3547 takes nothing returns nothing
      local trigger loc_trigger01=CreateTrigger()
      local unit loc_unit01=GetTriggerUnit()
      local unit loc_unit02=GetAttacker()
      local integer loc_integer01=GetHandleId(loc_trigger01)
      call TriggerRegisterUnitEvent(loc_trigger01,loc_unit01,EVENT_UNIT_DAMAGED)
      call TriggerRegisterTimerEvent(loc_trigger01,1,false)
      call TriggerAddCondition(loc_trigger01,Condition(function Func3546))
      call SaveInteger(hashtable001,(loc_integer01),(30),(Func0024(loc_unit01)))
      call SaveUnitHandle(hashtable001,(loc_integer01),(2),(loc_unit02))
      set loc_unit01=null
      set loc_unit02=null
      set loc_trigger01=null
    endfunction
    
    function Func3548 takes nothing returns nothing
      local unit loc_unit01=GetAttacker()
      if((LoadInteger(hashtable001,(GetHandleId((loc_unit01))),((4274))))==1)==false then
        call Func0044(loc_unit01,4274,0.45-GetUnitAbilityLevel(GetAttacker(),'A1HR')*0.05)
        call Func3547()
      endif
    endfunction
    
    function Func3549 takes nothing returns boolean
      if GetUnitAbilityLevel(GetAttacker(),'A1HR')>0 and IsUnitType(GetTriggerUnit(),UNIT_TYPE_HERO)==true and IsUnitType(GetTriggerUnit(),UNIT_TYPE_STRUCTURE)==false and GetAttacker()==(LoadUnitHandle(hashtable001,(GetHandleId(GetTriggeringTrigger())),(14)))and GetUnitTypeId(GetTriggerUnit())!='n00L' and IsUnitEnemy(GetTriggerUnit(),GetOwningPlayer(GetAttacker()))then
        call Func3548()
      endif
      return false
    endfunction
    
    function Func3550 takes nothing returns nothing
      local trigger loc_trigger01=CreateTrigger()
      local integer loc_integer01
      call Func0166(loc_trigger01,EVENT_PLAYER_UNIT_ATTACKED)
      call TriggerAddCondition(loc_trigger01,Condition(function Func3549))
      call SaveUnitHandle(hashtable001,(GetHandleId(loc_trigger01)),(14),(GetTriggerUnit()))
      set loc_trigger01=CreateTrigger()
      set loc_integer01=GetHandleId(loc_trigger01)
      call Func0166(loc_trigger01,EVENT_PLAYER_UNIT_DEATH)
      call TriggerAddCondition(loc_trigger01,Condition(function Func3542))
      call SaveUnitHandle(hashtable001,(loc_integer01),(2),(GetTriggerUnit()))
      set loc_trigger01=null
    endfunction
    
    function Func3551 takes nothing returns boolean
      if GetLearnedSkill()=='A1HR' and IsUnitIllusion(GetTriggerUnit())==false and GetUnitAbilityLevel(GetTriggerUnit(),'A1HR')==1 then
        call Func3550()
      endif
      return false
    endfunction
    
    function Func3552 takes nothing returns nothing
      local trigger loc_trigger01=CreateTrigger()
      call Func0166(loc_trigger01,EVENT_PLAYER_HERO_SKILL)
      call TriggerAddCondition(loc_trigger01,Condition(function Func3551))
      set loc_trigger01=null
    endfunction

  6. #6
    Volunteer Moderator
    Join Date
    Mar 2012
    Location
    Australia
    Posts
    2,671
    So basically. It's just there for the reason I pointed out in #3. Obsolete piece of code now.

  7. #7
    Basic Member ThoAppelsin's Avatar
    Join Date
    Jan 2012
    Posts
    2,892
    There is no point in post #3

  8. #8
    Basic Member
    Join Date
    Dec 2011
    Posts
    1,903
    This is really obsolete indeed.
    I mean the way it used to work is if he had begun an attack in the past second, he could trigger the Essence Shift effect with -anything-. Dark Pact, Pounce, Radiance, whatever.

    This is really the same as Riki's backstab and god knows how many other abilities that were smooth lined due to WC3 limitations in regards to on-hit events requiring awkward work arounds.

  9. #9
    Basic Member hoveringmover's Avatar
    Join Date
    Feb 2013
    Posts
    2,509
    If it is true that Slark needs to deal damage for Essence Shift to work in DOTA 2, then this seemingly minor bug is going to potentially turn into a very big bug when Abaddon comes out, don't you think? And how about now with Omniknight? Or is this something that is mostly going to be relevant when Slark is missing a Monkey King Bar and can't hit his targets due to Evasion or Curse? I personally haven't noticed any issues with this, but I can keep my eyes open.
    Last edited by hoveringmover; 04-05-2013 at 07:59 PM.

  10. #10
    Basic Member
    Join Date
    Dec 2011
    Posts
    1,903
    Quote Originally Posted by hoveringmover View Post
    If it is true that Slark needs to deal damage for Essence Shift to work in DOTA 2, then this seemingly minor bug is going to potentially turn into a very big bug when Abaddon comes out, don't you think? And how about now with Omniknight? Or is this something that is mostly going to be relevant when Slark is missing a Monkey King Bar and can't hit his targets due to Evasion or Curse?
    Essence Shift doesn't trigger on missed attacks.
    Triggered healing spells still trigger on-damage effects, as they take damage before they are healed back, so it's no different.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •