Forum Rules

  • No flaming or derogatory remarks, directly or through insinuation.
  • No discussion, sharing or referencing illegal software such as hacks, keygen, cracks and pirated software.
  • No offensive contents, including but not limited to, racism, gore or pornography.
  • No excessive spam/meme, i.e. copious one liners in a short period of time, typing with all caps or posting meme responses (text/image).
  • No trolling, including but not limited to, flame incitation, user provocation or false information distribution.
  • No link spamming or signature advertisements for content not specific to Dota 2.
  • No Dota 2 key requests, sell, trade etc.
  • You may not create multiple accounts for any purpose, including ban evasion, unless expressly permitted by a moderator.

  • Please search before posting. One thread per issue. Do not create another thread if there is an existing one already.
  • Before posting anything, make sure you check out all sticky threads (e.g., this). Do not create new threads about closed ones.
  • It is extremely important that you post in correct forum section.

  • Balance discussion only in Misc.
  • All art related (such as hero model) feedbacks go to Art Feedback Forum.
  • All matchmaking feedback should go here: Matchmaking Feedback
  • All report/low priority issues should go here: Commend/Report/Ban Feedback
  • No specific workshop item feedback. These should go to workshop page of that item.
  • When posting in non-bugs section (such as this), use [Bugs], [Discussion] or [Suggestion] prefix in your thread name.

In case you object some action by a moderator, please contact him directly through PM and explain your concerns politely. If you are still unable to resolve the issue, contact an administrator. Do not drag these issues in public.

All rules are meant to augment common sense, please use them when not conflicted with aforementioned policies.
See more
See less

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

  • Filter
  • Time
  • Show
Clear All
new posts

  • [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
    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
      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
        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