• 🏆 Texturing Contest #33 is OPEN! Contestants must re-texture a SD unit model found in-game (Warcraft 3 Classic), recreating the unit into a peaceful NPC version. 🔗Click here to enter!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[Spell] Wandering Tornado wanders too strangely

Status
Not open for further replies.
Level 17
Joined
Feb 11, 2011
Messages
1,860
Hello guys,

I have a boss that creates an invulnerable tornado that wanders around the arena, tossing enemies in the air if they get too close. One problem, the tornado seems to follow enemy heroes. Is this part of the "Wander (tornado)" ability? I have set it to ignore its guard position.
:vw_wtf:

Thanks for any help!
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
@defskull Wander ability is hardcoded. If there are enemy units around it will follow them.

There are only two fields that have meaning in that ability:
Area of Effect - it's area in which tornado lives
Casting Range - determinates the area in which tornado moves

Note: If Casting Range >= Area of Effect tornado dies instantly

Points and targets are choosen in random (wasn't checking the prority well enought).

If it comes to Object Editor stuff, I've tested practicaly every ability ;)
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
I have an arena. You teleport in with your hero and you have to fight creeps. Level 20 is a boss which summons a tornado which is meant to wander around the arena and put nearby enemies into a mini tornado. It works fine except the tornado follows enemies instead of moving to random points.
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
give the tornado the wander (critter) ability.

Thanks, I will try that when I get a chance :thumbs_up:

EDIT: I tried giving the tornado the "Wander (neurtal)" ability. It works, but it only wanders like a distance of 150 every 5 seconds. This still happens when I give it the same data as the "Wander (tornado)" (e.g. cast range) and it makes no difference. Is there a way to make it continuously wander around a region?
 
Level 8
Joined
Jan 8, 2010
Messages
493
why not? the tornado is wandering, and making it move randomly from point to point (even if it doesn't reach that point and start moving to another point) it will look like it is wandering. or maybe create a one-shot timer that has a random time and when it expires the tornado will move to a new target location.
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
Thanks for the timer idea! This is what I have done:

  • Tornado Wander
    • Events
      • Time - Wander expires
    • Conditions
    • Actions
      • Custom script: call Tornado_Wander(udg_Tornado)
JASS:
function Tornado_Wander takes unit u returns nothing
    local location loc1 = GetUnitLoc(u)
    local location loc2 = GetRandomLocInRect(gg_rct_WholeArena)
    local real dist = DistanceBetweenPoints(loc1, loc2)
    call IssuePointOrderLoc(u, "move", loc2)
    call RemoveLocation(loc1)
    call RemoveLocation(loc2)
    set loc1 = null
    set loc2 = null
    set u = null
    call DisplayTextToPlayer(Player(0), 0, 0, "Waiting " + I2S(R2I(dist / 100)) + " seconds.")
    call StartTimerBJ(udg_Wander, false, (dist / 100))
endfunction

Also, how do I get rid of the red writing on GetRandomLocInRect and DistanceBetweenPoints? I.e. what can I substitute for them?
 

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
Replace both script and GUI trigger with:
JASS:
function TWCallback takes unit u returns nothing
    if udg_UnitMoving[GetUnitUserData(udg_Tornado)] then
        local real x = GetRandomReal(GetRectMinX(gg_rct_WholeArena), GetRectMaxX(gg_rct_WholeArena))
        local real y = GetRandomReal(GetRectMinY(gg_rct_WholeArena), GetRectMaxY(gg_rct_WholeArena))
        call IssuePointOrderById(udg_Tornado, 851986, x, y)
    endif
    if udg_TornadoEnd then
        call PauseTimer(GetExpiredTimer())
        call DestroyTimer(GetExpiredTimer())
    endif
endfunction

function InitTrig_Tornado_Wander takes nothing returns nothing
    call TimerStart(CreateTimer(), 0.5, true, function TWCallback)
endfunction
Used your Tornado & WholeArena globals. Script requires IsUnitMoving.
Added condition for disabling trigger once you decide that tornado should move no more / event with tornado ends / boss dies.
Just create boolean variable TornadoEnd and set it to true whenever you what to turn off the trigger.
 
Last edited:

Bannar

Code Reviewer
Level 26
Joined
Mar 19, 2008
Messages
3,140
No it's not, but you should have used coordinates instead of locations + replace the bjs.
Additionaly: remove the DisableTrigger() function - I've forgotten that there is no trigger at all ^^ - destroying timer is enough.

EDIT: Distance between points looks like:
JASS:
function DistanceBetweenPoints takes location locA, location locB returns real
    local real dx = GetLocationX(locB) - GetLocationX(locA)
    local real dy = GetLocationY(locB) - GetLocationY(locA)
    return SquareRoot(dx * dx + dy * dy)
endfunctionp
So to get distance in more efficient way you should use reals. If you want to calculate distance between lets say two random points in your region you have to do the following:
JASS:
        local real x1 = GetRandomReal(GetRectMinX(gg_rct_WholeArena), GetRectMaxX(gg_rct_WholeArena))
        local real y1 = GetRandomReal(GetRectMinY(gg_rct_WholeArena), GetRectMaxY(gg_rct_WholeArena))
        local real x2 = GetRandomReal(GetRectMinX(gg_rct_WholeArena), GetRectMaxX(gg_rct_WholeArena))
        local real y2 = GetRandomReal(GetRectMinY(gg_rct_WholeArena), GetRectMaxY(gg_rct_WholeArena))
        local real distance = SquareRoot(x1 * x1 + dy * dy)
 
Level 17
Joined
Feb 11, 2011
Messages
1,860
Okay, thanks. Would this be correct then:

  • Tornado Wander
    • Events
      • Time - Wander expires
    • Conditions
    • Actions
      • Custom script: call Tornado_Wander(udg_Tornado)
JASS:
function Tornado_Wander takes unit u returns nothing
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real x2 = GetRandomReal(GetRectMinX(gg_rct_WholeArena), GetRectMaxX(gg_rct_WholeArena))
    local real y2 = GetRandomReal(GetRectMinY(gg_rct_WholeArena), GetRectMaxY(gg_rct_WholeArena))
    local real dx = x - x2
    local real dy = y - y2
    local real dist = SquareRoot(dx * dx + dy * dy)
    call IssuePointOrder(u, "move", x2, y2)
    call DisplayTextToPlayer(Player(0), 0, 0, "Waiting " + I2S(R2I(dist / 100)) + " seconds.")
    call TimerStart(udg_Wander, dist / 100, false, null)
    set u = null
endfunction

EDIT: Tested it quickly and seems to be working perfectly! Thanks! :smile:
 
Status
Not open for further replies.
Top