Results 1 to 4 of 4

Thread: [Confirmed] Beastmaster's Wild Axes spread way too wide

  1. #1
    Basic Member ThoAppelsin's Avatar
    Join Date
    Jan 2012

    [Confirmed] Beastmaster's Wild Axes spread way too wide

    590 - (-90) > 680 > -48 for the collision of both Svens > 632 > -140 twice for the currently faulty Axe searching range > 352... > +1 for zero? pff nevermind

    They spread 353 units wide at max, as stated in the npc_abilities.txt
    they should be spreading about 255 units wide at max

    - Wild Axes possibly can miss a unit in between
    - Wild Axes possibly can miss a tree in between
    - Wild Axes hit/damage a wider area than it should

    A superficial explanation of DotA behaviour can be found in the next post

  2. #2
    Basic Member ThoAppelsin's Avatar
    Join Date
    Jan 2012
    Well, this time, I won't really explain the JASS. I will lay it down there, so that the ones who wonder how it is can see how it is. It can be found over there >>> yeah, just scroll over there >>>
    What that code over there does is basically this:

    x(Axe#1)  =  x(Beast) * t^2  +  600 * cos(angle + 45) * t * (1-t)  +  x(Target) * (1-t)^2
    y(Axe#1)  =  y(Beast) * t^2  +  600 * sin(angle + 45) * t * (1-t)  +  y(Target) * (1-t)^2
    x(Axe#2)  =  x(Beast) * t^2  +  600 * cos(angle - 45) * t * (1-t)  +  x(Target) * (1-t)^2
    y(Axe#2)  =  y(Beast) * t^2  +  600 * sin(angle - 45) * t * (1-t)  +  y(Target) * (1-t)^2
    t is initially 1, and with each cycle, it gets reduced by [0.02 / max(d/1300; 0.4)] where d is the distance between the target and the Beast
    this reduction rate is only changes the speed of the events

    anyway, the key thing here that you should know is that the cos() and sin() here are calculated with radians and not degrees
    well, I don't like saying this, but I think the original intention here was to make those +45 and -45s in degrees, not radians. I mean, who the hell uses +45 for radians?
    Anyway, 45 radians is about 58 degrees, so if it was 45 degrees instead the axes would spread even less than 255.
    I think they may have seen their mistake there, but then decided to keep it like this instead of changing it.

    well... even when you know all these it is not really easy to see how wide axes spread. Their spread reaches to a maximum when the t is 0.5.
    Here, I have made a graph with Excel to visualise the path Wild Axes travel in DotA, along with the AoE it damages:

    And a view only link to the excel file itself, I think it probably is possible to save it though, so you may play around as you wish if you want:
    Graph should be able to draw any Wild Axe path that is not greater than 1300 units, but it will draw more than it should if you input a smaller path. Also, coordinates shall better be within -1500 and 1500

    As you may see in the data sheet of the file linked above, the deviation is 127.64 at max for a single axe. You can also calculate this yourself through the formulae given above:
    - assume that the axes were thrown along the X-axis
    - both the y(Beast) and y(Target) values become zero, making the first and last component of the addition zero for every t value
    - t = 0.5
    - 600 * sin(0 +/- 45) * 0.5 * 0.5

    ... yeah
    It took me a while to remember that cos() and sin() use radians by default... Seeing that 45 there made me think that it should be in degrees, so it took longer than it should.

    01  function Func1560 takes nothing returns nothing
    02    local integer loc_integer01=GetHandleId(GetExpiredTimer())
    03    local unit loc_unit01=(LoadUnitHandle(hashtable001,(loc_integer01),(290)))
    04    local unit loc_unit02=(LoadUnitHandle(hashtable001,(loc_integer01),(14)))
    05    local real loc_real01=(LoadReal(hashtable001,(loc_integer01),(284)))
    06    local real loc_real02=(LoadReal(hashtable001,(loc_integer01),(285)))
    07    local real loc_real03=(LoadReal(hashtable001,(loc_integer01),(286)))
    08    local real loc_real04=(LoadReal(hashtable001,(loc_integer01),(287)))
    09    local real loc_real05=(LoadReal(hashtable001,(loc_integer01),(288)))
    10    local real loc_real06=(LoadReal(hashtable001,(loc_integer01),(289)))
    11    local real loc_real07=(LoadReal(hashtable001,(loc_integer01),(137)))
    12    local real loc_real08=1-loc_real07
    13    local boolean loc_boolean01=(LoadBoolean(hashtable001,(loc_integer01),(291)))
    14    local group loc_group01=(LoadGroupHandle(hashtable001,(loc_integer01),(133)))
    15    local real loc_real09=RMaxBJ(Func0141(loc_real01,loc_real02,loc_real03,loc_real04)/1300,0.4)
    16    call SetUnitX(loc_unit01,Func0120(loc_real01*loc_real07*loc_real07+loc_real05*2*loc_real07*loc_real08+loc_real03*loc_real08*loc_real08))
    17    call SetUnitY(loc_unit01,Func0122(loc_real02*loc_real07*loc_real07+loc_real06*2*loc_real07*loc_real08+loc_real04*loc_real08*loc_real08))
    18    call Func1559(loc_unit02,GetUnitX(loc_unit01),GetUnitY(loc_unit01),loc_group01)
    19    if(loc_boolean01)then
    20      call SaveReal(hashtable001,(loc_integer01),(137),((loc_real07-.02/loc_real09)*1.0))
    21    else
    22      call SaveReal(hashtable001,(loc_integer01),(137),((loc_real07+.02/loc_real09)*1.0))
    23      call SaveReal(hashtable001,(loc_integer01),(284),((GetUnitX(loc_unit02))*1.0))
    24      call SaveReal(hashtable001,(loc_integer01),(285),((GetUnitY(loc_unit02))*1.0))
    25    endif
    26    if(loc_real07<0 and loc_boolean01)then
    27      call SaveBoolean(hashtable001,(loc_integer01),(291),(false))
    28      call SaveReal(hashtable001,(loc_integer01),(288),((loc_real01+300*Cos(Atan2(loc_real04-loc_real02,loc_real03-loc_real01)+(LoadReal(hashtable001,(loc_integer01),(292)))))*1.0))
    29      call SaveReal(hashtable001,(loc_integer01),(289),((loc_real02+300*Sin(Atan2(loc_real04-loc_real02,loc_real03-loc_real01)+(LoadReal(hashtable001,(loc_integer01),(292)))))*1.0))
    30    endif
    31    if(loc_real07>1 and loc_boolean01==false)then
    32      call PauseTimer(GetExpiredTimer())
    33      call Func0029(loc_group01)
    34      call FlushChildHashtable(hashtable001,(loc_integer01))
    35      call RemoveUnit(loc_unit01)
    36      call DestroyTimer(GetExpiredTimer())
    37    endif
    38  endfunction
    41  function Func1561 takes nothing returns nothing
    42    local unit loc_unit01=GetTriggerUnit()
    43    local real loc_real01=GetUnitX(loc_unit01)
    44    local real loc_real02=GetUnitY(loc_unit01)
    45    local real loc_real03=GetLocationX(GetSpellTargetLoc())
    46    local real loc_real04=GetLocationY(GetSpellTargetLoc())
    47    local unit loc_unit02=CreateUnit(GetOwningPlayer(loc_unit01),'e01T',loc_real01,loc_real02,270.0)
    48    local unit loc_unit03=CreateUnit(GetOwningPlayer(loc_unit01),'e01T',loc_real01,loc_real02,270.0)
    49    local integer loc_integer01
    50    local integer loc_integer02
    51    local timer loc_timer01=CreateTimer()
    52    local timer loc_timer02=CreateTimer()
    53    if GetSpellTargetUnit()!=null then
    54      set loc_real03=GetUnitX(GetSpellTargetUnit())
    55      set loc_real04=GetUnitY(GetSpellTargetUnit())
    56    endif
    57    call Func0181(loc_unit02,'Amrf')
    58    call UnitRemoveAbility(loc_unit02,'Amrf')
    59    call SetUnitFlyHeight(loc_unit02,150,0)
    60    call Func0181(loc_unit03,'Amrf')
    61    call UnitRemoveAbility(loc_unit03,'Amrf')
    62    call SetUnitFlyHeight(loc_unit03,150,0)
    63    set loc_integer01=GetHandleId(loc_timer01)
    64    call SaveUnitHandle(hashtable001,(loc_integer01),(14),(loc_unit01))
    65    call SaveUnitHandle(hashtable001,(loc_integer01),(290),(loc_unit02))
    66    call SaveGroupHandle(hashtable001,(loc_integer01),(133),(Func0030()))
    67    call SaveReal(hashtable001,(loc_integer01),(284),((loc_real01)*1.0))
    68    call SaveReal(hashtable001,(loc_integer01),(285),((loc_real02)*1.0))
    69    call SaveReal(hashtable001,(loc_integer01),(286),((loc_real03)*1.0))
    70    call SaveReal(hashtable001,(loc_integer01),(287),((loc_real04)*1.0))
    71    call SaveReal(hashtable001,(loc_integer01),(288),((loc_real01+300*Cos(Atan2(loc_real04-loc_real02,loc_real03-loc_real01)+45))*1.0))
    72    call SaveReal(hashtable001,(loc_integer01),(289),((loc_real02+300*Sin(Atan2(loc_real04-loc_real02,loc_real03-loc_real01)+45))*1.0))
    73    call SaveReal(hashtable001,(loc_integer01),(137),((1)*1.0))
    74    call SaveReal(hashtable001,(loc_integer01),(292),((-45)*1.0))
    75    call SaveBoolean(hashtable001,(loc_integer01),(291),(true))
    76    set loc_integer02=GetHandleId(loc_timer02)
    77    call SaveUnitHandle(hashtable001,(loc_integer02),(14),(loc_unit01))
    78    call SaveUnitHandle(hashtable001,(loc_integer02),(290),(loc_unit03))
    79    call SaveGroupHandle(hashtable001,(loc_integer02),(133),(Func0030()))
    80    call SaveReal(hashtable001,(loc_integer02),(284),((loc_real01)*1.0))
    81    call SaveReal(hashtable001,(loc_integer02),(285),((loc_real02)*1.0))
    82    call SaveReal(hashtable001,(loc_integer02),(286),((loc_real03)*1.0))
    83    call SaveReal(hashtable001,(loc_integer02),(287),((loc_real04)*1.0))
    84    call SaveReal(hashtable001,(loc_integer02),(288),((loc_real01+300*Cos(Atan2(loc_real04-loc_real02,loc_real03-loc_real01)-45))*1.0))
    85    call SaveReal(hashtable001,(loc_integer02),(289),((loc_real02+300*Sin(Atan2(loc_real04-loc_real02,loc_real03-loc_real01)-45))*1.0))
    86    call SaveReal(hashtable001,(loc_integer02),(137),((1)*1.0))
    87    call SaveReal(hashtable001,(loc_integer02),(292),((45)*1.0))
    88    call SaveBoolean(hashtable001,(loc_integer02),(291),(true))
    89    call TimerStart(loc_timer01,.025,true,function Func1560)
    90    call TimerStart(loc_timer02,.025,true,function Func1560)
    91  endfunction

    e01T is a Wild Axe
    Func0141 is a distance calculator
    Func0120 and Func0122 are functions that just ensure that a point isn't outside the map boundaries

  3. #3
    Basic Member
    Join Date
    Dec 2011
    added to sticky.

    does this affect their speed?
    Make sure to read the Forum Rules as well as the stickied Threads of the Forum Section you are posting in.

    Contributions i'd like to highlight:
    My Suggestion: Coaching System
    My Sticky: Intended Changes List
    My Challenge: Completely Fixed Hero Challenge: Skywrath Mage

  4. #4
    Basic Member ThoAppelsin's Avatar
    Join Date
    Jan 2012
    don't really know, but I don't think so. This is not the real world, spreading probably is issued through a seperate formula.

    Also, I cannot see the speed of the Wild Axes in the data files, so... Well, I can say that Wild Axes in DotA have:
    - 1040 units/sec average speed (movement is done with a quadratic formula therefore not a constant speed) if they are cast for a range longer than 520
    - 2xthrownRange units/sec average speed if they are cast for a range shorter than 520; eg. 800 ms if thrown at 400 range

    no idea what happens in Dota 2

Posting Permissions

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