Life Break/Charge of Darkness

Discussion in 'Advanced Mechanics' started by Yago, Apr 16, 2012.

  1. EebstertheGreat

    EebstertheGreat Forum Manager

    No. Here's the code though. As always, read the last function first (it gets called from main when Huskar is picked).[jass]function Func1811 takes unit loc_unit01,unit loc_unit02 returns nothing
    local unit loc_unit03=CreateUnit(GetOwningPlayer(loc_unit01),'e00E',GetUnitX(loc_unit02),GetUnitY(loc_unit02),0)
    local integer loc_integer01=GetUnitAbilityLevel(loc_unit01,'A0QR')
    local real loc_real01
    local real loc_real02=0.5
    if loc_integer01==0 then
    set loc_integer01=GetUnitAbilityLevel(loc_unit01,'A1B3')
    set loc_real02=0.65
    endif
    call Func0179(loc_unit03,'A0QU') // Func0179 adds the ability to the unit and makes it permanent
    call SetUnitAbilityLevel(loc_unit03,'A0QU',loc_integer01)
    call IssueTargetOrder(loc_unit03,"slow",loc_unit02)
    if loc_integer01==1 then
    set loc_real01=0.35
    elseif loc_integer01==2 then
    set loc_real01=0.30
    else
    set loc_real01=0.25
    endif
    call Func0107(loc_unit01,loc_unit01,1,GetUnitState(loc_unit01,UNIT_STATE_LIFE)*loc_real01) // Func0107 has the first unit damage the second for the real damage of type determined by the integer (for 1, it's ATTACK_TYPE_HERO,DAMAGE_TYPE_FIRE,WEAPON_TYPE_WHOKNOWS)
    call Func0107(loc_unit01,loc_unit02,1,GetUnitState(loc_unit02,UNIT_STATE_LIFE)*loc_real02)
    call DestroyEffect(AddSpecialEffectTarget("Objects\\Spawnmodels\\Human\\HumanBlood\\BloodElfSpellThiefBlood.mdl",loc_unit01,"chest"))
    call DestroyEffect(AddSpecialEffectTarget("effects\\LifeBreak.mdx",loc_unit02,"chest"))
    set loc_unit01=null
    set loc_unit02=null
    set loc_unit03=null
    endfunction

    function Func1812 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 real loc_real01=(LoadReal(hashtable001,(loc_integer01),(23)))
    local real loc_real02=(LoadReal(hashtable001,(loc_integer01),(24)))
    local real loc_real03
    local real loc_real04
    local real loc_real05=GetUnitX(loc_unit01)
    local real loc_real06=GetUnitY(loc_unit01)
    local real loc_real07=GetUnitX(loc_unit02)
    local real loc_real08=GetUnitY(loc_unit02)
    local real loc_real09=Atan2(loc_real08-loc_real06,loc_real07-loc_real05)
    if GetUnitTypeId(loc_unit01)=='E02X' then // E02X is Rubick
    call SetUnitAnimationByIndex(loc_unit01,1)
    else
    call SetUnitAnimationByIndex(loc_unit01,17)
    endif
    if GetTriggerEventId()==EVENT_WIDGET_DEATH or Func0139(loc_real01,loc_real02,loc_real07,loc_real08)>1400 or Func0250(loc_unit01)then // Func0139 calculates distance, Func0250 checks if the unit is disabled
    call SetUnitPathing(loc_unit01,true)
    call DestroyEffect((LoadEffectHandle(hashtable001,(loc_integer01),(175))))
    call DestroyEffect((LoadEffectHandle(hashtable001,(loc_integer01),(176))))
    call UnitRemoveAbility(loc_unit01,'A0ST')
    call SetUnitTimeScale(loc_unit01,1.0)
    call FlushChildHashtable(hashtable001,(loc_integer01))
    call Func0035(loc_trigger01)
    elseif Func0139(loc_real05,loc_real06,loc_real07,loc_real08)<125 then
    call SetUnitPathing(loc_unit01,true)
    call DestroyEffect((LoadEffectHandle(hashtable001,(loc_integer01),(175))))
    call DestroyEffect((LoadEffectHandle(hashtable001,(loc_integer01),(176))))
    call UnitRemoveAbility(loc_unit01,'A0ST')
    call FlushChildHashtable(hashtable001,(loc_integer01))
    call Func0035(loc_trigger01)
    call SetUnitTimeScale(loc_unit01,1.0)
    if loc_unit02!=null and Func0180(loc_unit02)==false then // Func0180 checks if the unit is dead or null
    call IssueTargetOrder(loc_unit01,"attack",loc_unit02)
    call Func1811(loc_unit01,loc_unit02)
    endif
    else
    call SetUnitPathing(loc_unit01,false)
    set loc_real01=loc_real07
    set loc_real02=loc_real08
    call SaveReal(hashtable001,(loc_integer01),(23),((loc_real01)*1.0))
    call SaveReal(hashtable001,(loc_integer01),(24),((loc_real02)*1.0))
    set loc_real03=loc_real05+15*Cos(loc_real09)
    set loc_real04=loc_real06+15*Sin(loc_real09)
    call SetUnitPosition(loc_unit01,loc_real03,loc_real04)
    call SetUnitFacing(loc_unit01,loc_real09*bj_RADTODEG)
    endif
    set loc_trigger01=null
    set loc_unit01=null
    set loc_unit02=null
    return false
    endfunction

    function Func1813 takes nothing returns nothing
    local unit loc_unit01=GetTriggerUnit()
    local unit loc_unit02=GetSpellTargetUnit()
    local trigger loc_trigger01=CreateTrigger()
    local integer loc_integer01=GetHandleId(loc_trigger01)
    call TriggerRegisterTimerEvent(loc_trigger01,0.015,true)
    call TriggerRegisterDeathEvent(loc_trigger01,loc_unit01)
    call TriggerAddCondition(loc_trigger01,Condition(function Func1812))
    call SaveUnitHandle(hashtable001,(loc_integer01),(2),(loc_unit01))
    call SaveUnitHandle(hashtable001,(loc_integer01),(17),(loc_unit02))
    call SaveReal(hashtable001,(loc_integer01),(23),((GetUnitX(loc_unit02))*1.0))
    call SaveReal(hashtable001,(loc_integer01),(24),((GetUnitY(loc_unit02))*1.0))
    call SaveEffectHandle(hashtable001,(loc_integer01),(175),(AddSpecialEffectTarget("war3mapImported\\LifeBreakCharge.mdx",loc_unit01,"hand right alternate")))
    call SaveEffectHandle(hashtable001,(loc_integer01),(176),(AddSpecialEffectTarget("war3mapImported\\LifeBreakCharge.mdx",loc_unit01,"hand left alternate")))
    call SetUnitPathing(loc_unit01,false)
    call Func0179(loc_unit01,'A0ST') // A0ST is the magic immunity ability
    call SetPlayerAbilityAvailable(GetOwningPlayer(loc_unit01),'A0ST',false)
    call SetUnitAnimationByIndex(loc_unit01,17)
    call SetUnitTimeScale(loc_unit01,3.0)
    set loc_unit01=null
    set loc_unit02=null
    set loc_trigger01=null
    endfunction

    function Func1814 takes nothing returns boolean
    if(GetSpellAbilityId()=='A0QR' or GetSpellAbilityId()=='A1B3')and Func0028(GetSpellTargetUnit())==false then // A0QR = Life Break, A1B3 = Life Break (Aghanim's), and Func0028 checks for Linken's or Rosh spell block
    call Func1813()
    endif
    return false
    endfunction

    function Func1815 takes nothing returns nothing
    local trigger loc_trigger01=CreateTrigger()
    call Func0164(loc_trigger01,EVENT_PLAYER_UNIT_SPELL_EFFECT)
    call TriggerAddCondition(loc_trigger01,Condition(function Func1814))
    set loc_trigger01=null
    call Func0122('A0QU') // preloads the slow ability A0QU
    endfunction[/jass]
     
  2. Heraklinos

    Heraklinos Well-Known Member

    ^thanks a lot :)
     
  3. Yago

    Yago Well-Known Member

    Wow. So I must have been really lucky that game it stun dodged. As I've said, I've had it work only once I know of, maybe more, but when I tested it failed. Thanks for clarifying.
     
  4. Clogon

    Clogon Well-Known Member

    @EebstertheGreat and Steric:
    Thanks for the numbers and analysis.
     
  5. Heraklinos

    Heraklinos Well-Known Member

    one more questions:
    What would happen first if both Life Break's check for the magic immunity removal and Charge of Darkness's check for the stun is done in the same 0.005 update interval (they both get in range of each other)? The stun or the removal of magic immunity?
     
  6. Steric

    Steric Well-Known Member

    Everything happens in an order. Two things cannot simultaneously happen. One check will happen before the other.
     
  7. Heraklinos

    Heraklinos Well-Known Member

    You clearly didn't get my point...
    I didn't say "same time", I said "same update interval". My question is which check would go first.

    Note: what you said don't apply well in a quantum computer, if it would be successfully built :)
     
  8. EebstertheGreat

    EebstertheGreat Forum Manager

    The one that happens first will happen first . . . the general assumption is that the engine processes new orders in the order they are received. So if it receives the Life Break order before the Charge of Darkness order, it will be checked first.

    That might not really be the case of course; the logic might work quite differently for timers. But I don't know how to check this nor do I really care to. The deep inner workings of the WC3 engine tend to be confusing, hard to probe, and nearly irrelevant.
     
  9. Heraklinos

    Heraklinos Well-Known Member

    ^That's sad to hear :(
    Actually it's quite relevant to my calculation (though not so much, but relevant anyway). At first my assumption was the one casted first will be checked first but I wasn't sure, if anyone actually know the algorithm WC3 engine uses would be nice, sadly that the old-school mechfags aren't around here anymore.
     
  10. MauranKilom

    MauranKilom Well-Known Member

    Do you really think the "old-school mechfags" knew the code of wc3?
    They didn't. They gained knowledge from tests in wc3 (without knowing anything about the inner workings) and drew conclusions.

    One might call this procedure "science".
     
  11. EebstertheGreat

    EebstertheGreat Forum Manager

    I think he means they would have been more willing to actually make a map to test it, while I'm much too lazy.
     
  12. Steric

    Steric Well-Known Member

    There is no "same update interval" as far as I know. One timer was started at some time and will run every 0.020 seconds. The other timer started at some other time and runs every 0.015 seconds. Unless 0.005 seconds is the shortest time interval that can exist in the warcraft III system (which for all I know, could be), one timer will expire an instant before the other.

    If the triggers were somehow triggered simultaneously (which I don't even think is possible), then I believe that the one that was created last will run first.

    Even if there was a successfully built Quantum Computer, the warcraft III program runs things one at a time, so that's irrelevant.
     
  13. Heraklinos

    Heraklinos Well-Known Member

    ^Eebster got my question anyway, it doesn't matter if you don't. Maybe this might help Multi-players RTS.

    I know that reverse engineering is illegal, but however they seem to know so much that might be able to answer my question, or even bothered to make a test map for the sake of knowledge, like the old "research group" from DA or people from wc3c.net
    every thing changes :(

    exactly my point
    I can't make a test map myself cause I don't have WC3 installed on my computer over a year ago, I lost the damn Frozen Throne CD.