• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Removing the stopping while using an Ability?

Status
Not open for further replies.
Level 6
Joined
Feb 16, 2014
Messages
193
Everytime i will make a unit use an ability the unit will stop and i have to order the unit to move again,but in the map i'm making u need to be always moving(evading) and shooting,so how do i make a unit just keep moving even if i'm using an ability from that unit?
 
Level 14
Joined
Oct 18, 2013
Messages
724
Some abilities do not cancel your last issued order. There may be more, but Berserk and Defend are two prime examples of this. Other abilites that might are: Magic Defense, Immolation, Taunt (Pretty sure it doesn't though)
 
Level 6
Joined
Feb 16, 2014
Messages
193
Wait i have another question,is there any way i can set the unit speed to 1000 or more? because i'm gonna use a unit as a projectile(guided missile)
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
^
In addition, the trade-off between MoveUnit and SetUnitX/Y is that MoveUnit will interrupt (cancel) current order of a unit while SetUnitX/Y does not.

My suggestion is that, if you are ordering your unit to cast an ability (provided it is moving at that time), switch your "movement" method to SetUnitX/Y.
This allows your unit to cast abilities without stopping its movement, but to prevent the awkwardness of seeing your unit "gliding" on the field, you can also use the SetUnitAnimationByIndex to simulate the walking animation of the unit.

But, this will contradict, because Spell Casting of a unit has its own animation.
So you want your unit to do the Spell Cast Animation or the Walking Animation, or both ?
By doing both, your system will be more difficult tasks to keep track when your unit has finished casting the spell animation, and resume its walking animation.
 
Level 6
Joined
Feb 16, 2014
Messages
193
^
In addition, the trade-off between MoveUnit and SetUnitX/Y is that MoveUnit will interrupt (cancel) current order of a unit while SetUnitX/Y does not.

My suggestion is that, if you are ordering your unit to cast an ability (provided it is moving at that time), switch your "movement" method to SetUnitX/Y.
This allows your unit to cast abilities without stopping its movement, but to prevent the awkwardness of seeing your unit "gliding" on the field, you can also use the SetUnitAnimationByIndex to simulate the walking animation of the unit.

But, this will contradict, because Spell Casting of a unit has its own animation.
So you want your unit to do the Spell Cast Animation or the Walking Animation, or both ?
By doing both, your system will be more difficult tasks to keep track when your unit has finished casting the spell animation, and resume its walking animation.
Well i'm creating a trigger so that when that unit(the Missile) gets close to an air unit then that unit will explode dealing damage to any units(air units) near the explosion,so i would only want the walking animation.
 
Level 6
Joined
Feb 16, 2014
Messages
193
But wouldn't SetUnitX/Y and MoveUnitInstantly almost be the same? it will instantly move the unit to a point but I like to make a Homing Missile,the missile will follow the selected air unit and when it gets close enough then it will explode,so wouldn't SetUnitX/Y and MoveUnitInstanly like ruin the missile by making it instantly go to the target unit? :(
 
Level 26
Joined
Aug 18, 2009
Messages
4,099
JASS:
globals
    location dummyLoc = Location(0, 0)
endglobals

function GetUnitZ takes unit u returns real
    call MoveLocation(dummyLoc, GetUnitX(u), GetUnitY(u))
    
    return (GetLocationZ(dummyLoc) + GetUnitFlyHeight(u))
endfunction

function SetUnitXYZ takes unit u, real x, real y, real z returns nothing    
    call SetUnitX(u, x)
    call SetUnitY(u, y)
    
    call MoveLocation(dummyLoc, x, y)
    
    call SetUnitFlyHeight(u, z - GetLocationZ(dummyLoc), 0)
endfunction

struct Missile
    static hashtable ht=InitHashtable()
    static constant real INTERVAL=0.03125
    
    unit dummy
    timer moveTimer
    
    real x
    real y
    real z
    
    real moveLen
    real moveLenSqr
    
    unit target
    
    method destroy takes nothing returns nothing
        call RemoveSavedInteger(ht, GetHandleId(this.moveTimer), 0)
        call PauseTimer(this.moveTimer)
        call DestroyTimer(this.moveTimer)
        
        call RemoveUnit(this.dummy)
        
        call this.deallocate()
    endmethod
    
    method move takes nothing returns nothing
        local real targetX = GetUnitX(this.target)
        local real targetY = GetUnitY(this.target)
        local real targetZ = GetUnitZ(this.target)

        local real dX = targetX - this.x
        local real dY = targetY - this.y
        local real dZ = targetZ - this.z
        
        local real dSqr = dX*dX+dY*dY+dZ*dZ
        local real d
        
        if (dSqr < this.moveLenSqr) then
            call this.destroy()
        else
            set d = SquareRoot(dSqr)
        
            set this.x = this.x + dX / d * this.moveLen
            set this.y = this.y + dY / d * this.moveLen
            set this.z = this.z + dZ / d * this.moveLen
            
            call SetUnitXYZ(this.dummy, this.x, this.y, this.z)
        endif
    endmethod
    
    static method moveByTimer takes nothing returns nothing
        call thistype(LoadInteger(ht, GetHandleId(GetExpiredTimer()), 0)).move()
    endmethod
    
    static method create takes integer id, real x, real y, real z, unit target, real speed returns thistype
        local thistype this = thistype.allocate()
        
        set this.dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), id, 0, 0, 0)
        
        set this.x = x
        set this.y = y
        set this.z = z
        
        set this.moveLen = speed*INTERVAL
        set this.moveLenSqr = speed*speed*INTERVAL*INTERVAL
        set this.target = target
        set this.moveTimer = CreateTimer()
        
        call SaveInteger(ht, GetHandleId(this.moveTimer), 0, this)
        
        call UnitAddAbility(this.dummy, 'Amrf')
        call UnitRemoveAbility(this.dummy, 'Amrf')
        call UnitAddAbility(this.dummy, 'Aloc')
        
        call SetUnitXYZ(this.dummy, x, y, z)
        
        call TimerStart(this.moveTimer, INTERVAL, true, function thistype.moveByTimer)
        
        return this
    endmethod
endstruct
 
Level 6
Joined
Feb 16, 2014
Messages
193
JASS:
globals
    location dummyLoc = Location(0, 0)
endglobals

function GetUnitZ takes unit u returns real
    call MoveLocation(dummyLoc, GetUnitX(u), GetUnitY(u))
    
    return (GetLocationZ(dummyLoc) + GetUnitFlyHeight(u))
endfunction

function SetUnitXYZ takes unit u, real x, real y, real z returns nothing    
    call SetUnitX(u, x)
    call SetUnitY(u, y)
    
    call MoveLocation(dummyLoc, x, y)
    
    call SetUnitFlyHeight(u, z - GetLocationZ(dummyLoc), 0)
endfunction

struct Missile
    static hashtable ht=InitHashtable()
    static constant real INTERVAL=0.03125
    
    unit dummy
    timer moveTimer
    
    real x
    real y
    real z
    
    real moveLen
    real moveLenSqr
    
    unit target
    
    method destroy takes nothing returns nothing
        call RemoveSavedInteger(ht, GetHandleId(this.moveTimer), 0)
        call PauseTimer(this.moveTimer)
        call DestroyTimer(this.moveTimer)
        
        call RemoveUnit(this.dummy)
        
        call this.deallocate()
    endmethod
    
    method move takes nothing returns nothing
        local real targetX = GetUnitX(this.target)
        local real targetY = GetUnitY(this.target)
        local real targetZ = GetUnitZ(this.target)

        local real dX = targetX - this.x
        local real dY = targetY - this.y
        local real dZ = targetZ - this.z
        
        local real dSqr = dX*dX+dY*dY+dZ*dZ
        local real d
        
        if (dSqr < this.moveLenSqr) then
            call this.destroy()
        else
            set d = SquareRoot(dSqr)
        
            set this.x = this.x + dX / d * this.moveLen
            set this.y = this.y + dY / d * this.moveLen
            set this.z = this.z + dZ / d * this.moveLen
            
            call SetUnitXYZ(this.dummy, this.x, this.y, this.z)
        endif
    endmethod
    
    static method moveByTimer takes nothing returns nothing
        call thistype(LoadInteger(ht, GetHandleId(GetExpiredTimer()), 0)).move()
    endmethod
    
    static method create takes integer id, real x, real y, real z, unit target, real speed returns thistype
        local thistype this = thistype.allocate()
        
        set this.dummy = CreateUnit(Player(PLAYER_NEUTRAL_PASSIVE), id, 0, 0, 0)
        
        set this.x = x
        set this.y = y
        set this.z = z
        
        set this.moveLen = speed*INTERVAL
        set this.moveLenSqr = speed*speed*INTERVAL*INTERVAL
        set this.target = target
        set this.moveTimer = CreateTimer()
        
        call SaveInteger(ht, GetHandleId(this.moveTimer), 0, this)
        
        call UnitAddAbility(this.dummy, 'Amrf')
        call UnitRemoveAbility(this.dummy, 'Amrf')
        call UnitAddAbility(this.dummy, 'Aloc')
        
        call SetUnitXYZ(this.dummy, x, y, z)
        
        call TimerStart(this.moveTimer, INTERVAL, true, function thistype.moveByTimer)
        
        return this
    endmethod
endstruct
Is this possible to do in just triggers? because im not familiar with JASS :(
 
Level 26
Joined
Aug 18, 2009
Messages
4,099
GUI lacks certain functions like SetUnitX, SetUnitY, GetLocationZ. Instead of using MoveLocation, you could create a new location everytime, but that would leak horribly for such an application, therefore you would need DestroyLocation, which is again jass-only. Similar with the dynamic timer, the alternative is to use a single static one and register all the missiles in a data structure to be able to iterate over all of them. The implementation of both the data structure and the allocation/deallocation is a hassle. You would normally simply call prewritten functions but GUI is not suited for that, either.

Pro-GUIers say they can solve everything with it. From my perspective, they forge a cyborg abomination. Maybe someone should have renewed the GUI extensions at some point, so they can at least get presented functions to solve common problems. Then again, the question is if people would nod at that or shrivel at the thought of going a tad non-vanilla.

  • init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set INTERVAL = (1.00 / 32.00)
      • Set zLoc = (Point(0.00, 0.00))
      • Set SOURCE_Z_OFFSET = 50.00
      • Set TARGET_Z_OFFSET = 50.00
      • Set SPEED = 500.00
  • start
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • Set sourceLoc = (Position of (Triggering unit))
      • Set targetLoc = (Position of (Target unit of ability being cast))
      • -------- <allocation> --------
      • Set this = alloc_F
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • this Equal To 0
        • 'THEN'-Actions
          • Set alloc_I = (alloc_I + 1)
          • Set this = alloc_I
        • 'ELSE'-Actions
          • Set alloc_F = alloc_V[this]
      • -------- </allocation> --------
      • Set angle = (Angle from sourceLoc to targetLoc)
      • Unit - Create 1 Dummy for Neutral passiv at (Point(0.00, 0.00)) facing angle degrees
      • Set dummy[this] = (Last created unit)
      • Set x[this] = (X of sourceLoc)
      • Set y[this] = (Y of sourceLoc)
      • Custom script: set udg_z[udg_this] = GetLocationZ(udg_sourceLoc) + udg_SOURCE_Z_OFFSET
      • Set moveLen[this] = (500.00 x INTERVAL)
      • Set moveLenSqr[this] = (moveLen[this] x moveLen[this])
      • Set target[this] = (Target unit of ability being cast)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • listC Equal To 0
        • 'THEN'-Actions
          • Countdown-Timer - Start moveTimer as a Wiederholt timer that will expire in INTERVAL seconds
        • 'ELSE'-Actions
      • Set listC = (listC + 1)
      • Set list[listC] = this
      • Einheit - Add Raven Form to dummy[this]
      • Einheit - Remove Raven Form from dummy[this]
      • Custom script: call UnitAddAbility(udg_dummy[udg_this], 'Aloc')
      • Custom script: call SetUnitX(udg_dummy[udg_this], udg_x[udg_this])
      • Custom script: call SetUnitY(udg_dummy[udg_this], udg_y[udg_this])
      • Custom script: call MoveLocation(udg_zLoc, udg_x[udg_this], udg_y[udg_this])
      • Custom script: set udg_height = udg_z[udg_this] - GetLocationZ(udg_zLoc)
      • Animation - Change dummy[this] flying height to height at 0.00
      • Custom script: call RemoveLocation(udg_sourceLoc)
      • Custom script: call RemoveLocation(udg_targetLoc)
  • move
    • Events
      • Time - moveTimer expires
    • Conditions
    • Actions
      • For each (Integer A) from 1 to listC, do (Actions)
        • Loop - Actions
          • Set iterList[(Integer A)] = list[(Integer A)]
      • For each (Integer A) from 1 to listC, do (Actions)
        • Loop - Actions
          • Set this = iterList[(Integer A)]
          • Set targetLoc = (Position of target[this])
          • Set dX = ((X of targetLoc) - x[this])
          • Set dY = ((Y of targetLoc) - y[this])
          • Custom script: set udg_dZ = (GetLocationZ(udg_targetLoc) + GetUnitFlyHeight(udg_target[udg_this]) + udg_TARGET_Z_OFFSET) - udg_z[udg_this]
          • Set dSqr = ((dX x dX) + ((dY x dY) + (dZ x dZ)))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • 'IF'-Conditions
              • dSqr Less Than moveLenSqr[this]
            • 'THEN'-Actions
              • Unit - Remove dummy[this] from the game
              • Set list[(Integer A)] = list[listC]
              • Set listC = (listC - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • 'IF'-Conditions
                  • listC Equal To 0
                • 'THEN'-Actions
                  • Countdown-Timer - Pause moveTimer
                • 'ELSE'-Actions
              • -------- <deallocation> --------
              • Set alloc_V[this] = alloc_F
              • Set alloc_F = this
              • -------- </deallocation> --------
            • 'ELSE'-Actions
              • Set d = (Square root(dSqr))
              • Set x[this] = (x[this] + ((dX / d) x moveLen[this]))
              • Set y[this] = (y[this] + ((dY / d) x moveLen[this]))
              • Set z[this] = (z[this] + ((dZ / d) x moveLen[this]))
              • Custom script: call SetUnitX(udg_dummy[udg_this], udg_x[udg_this])
              • Custom script: call SetUnitY(udg_dummy[udg_this], udg_y[udg_this])
              • Custom script: call MoveLocation(udg_zLoc, udg_x[udg_this], udg_y[udg_this])
              • Custom script: set udg_height = udg_z[udg_this] - GetLocationZ(udg_zLoc)
              • Animation - Change dummy[this] flying height to height at 0.00
              • Unit - Make dummy[this] face target[this] over 0.00 seconds
          • Custom script: call RemoveLocation(udg_targetLoc)
That's far from easier than the vjass code I posted above.
 
Level 6
Joined
Feb 16, 2014
Messages
193
GUI lacks certain functions like SetUnitX, SetUnitY, GetLocationZ. Instead of using MoveLocation, you could create a new location everytime, but that would leak horribly for such an application, therefore you would need DestroyLocation, which is again jass-only. Similar with the dynamic timer, the alternative is to use a single static one and register all the missiles in a data structure to be able to iterate over all of them. The implementation of both the data structure and the allocation/deallocation is a hassle. You would normally simply call prewritten functions but GUI is not suited for that, either.

Pro-GUIers say they can solve everything with it. From my perspective, they forge a cyborg abomination. Maybe someone should have renewed the GUI extensions at some point, so they can at least get presented functions to solve common problems. Then again, the question is if people would nod at that or shrivel at the thought of going a tad non-vanilla.

  • init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set INTERVAL = (1.00 / 32.00)
      • Set zLoc = (Point(0.00, 0.00))
      • Set SOURCE_Z_OFFSET = 50.00
      • Set TARGET_Z_OFFSET = 50.00
      • Set SPEED = 500.00
  • start
    • Events
      • Unit - A unit Starts the effect of an ability
    • Conditions
    • Actions
      • Set sourceLoc = (Position of (Triggering unit))
      • Set targetLoc = (Position of (Target unit of ability being cast))
      • -------- <allocation> --------
      • Set this = alloc_F
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • this Equal To 0
        • 'THEN'-Actions
          • Set alloc_I = (alloc_I + 1)
          • Set this = alloc_I
        • 'ELSE'-Actions
          • Set alloc_F = alloc_V[this]
      • -------- </allocation> --------
      • Set angle = (Angle from sourceLoc to targetLoc)
      • Unit - Create 1 Dummy for Neutral passiv at (Point(0.00, 0.00)) facing angle degrees
      • Set dummy[this] = (Last created unit)
      • Set x[this] = (X of sourceLoc)
      • Set y[this] = (Y of sourceLoc)
      • Custom script: set udg_z[udg_this] = GetLocationZ(udg_sourceLoc) + udg_SOURCE_Z_OFFSET
      • Set moveLen[this] = (500.00 x INTERVAL)
      • Set moveLenSqr[this] = (moveLen[this] x moveLen[this])
      • Set target[this] = (Target unit of ability being cast)
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • 'IF'-Conditions
          • listC Equal To 0
        • 'THEN'-Actions
          • Countdown-Timer - Start moveTimer as a Wiederholt timer that will expire in INTERVAL seconds
        • 'ELSE'-Actions
      • Set listC = (listC + 1)
      • Set list[listC] = this
      • Einheit - Add Raven Form to dummy[this]
      • Einheit - Remove Raven Form from dummy[this]
      • Custom script: call UnitAddAbility(udg_dummy[udg_this], 'Aloc')
      • Custom script: call SetUnitX(udg_dummy[udg_this], udg_x[udg_this])
      • Custom script: call SetUnitY(udg_dummy[udg_this], udg_y[udg_this])
      • Custom script: call MoveLocation(udg_zLoc, udg_x[udg_this], udg_y[udg_this])
      • Custom script: set udg_height = udg_z[udg_this] - GetLocationZ(udg_zLoc)
      • Animation - Change dummy[this] flying height to height at 0.00
      • Custom script: call RemoveLocation(udg_sourceLoc)
      • Custom script: call RemoveLocation(udg_targetLoc)
  • move
    • Events
      • Time - moveTimer expires
    • Conditions
    • Actions
      • For each (Integer A) from 1 to listC, do (Actions)
        • Loop - Actions
          • Set iterList[(Integer A)] = list[(Integer A)]
      • For each (Integer A) from 1 to listC, do (Actions)
        • Loop - Actions
          • Set this = iterList[(Integer A)]
          • Set targetLoc = (Position of target[this])
          • Set dX = ((X of targetLoc) - x[this])
          • Set dY = ((Y of targetLoc) - y[this])
          • Custom script: set udg_dZ = (GetLocationZ(udg_targetLoc) + GetUnitFlyHeight(udg_target[udg_this]) + udg_TARGET_Z_OFFSET) - udg_z[udg_this]
          • Set dSqr = ((dX x dX) + ((dY x dY) + (dZ x dZ)))
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • 'IF'-Conditions
              • dSqr Less Than moveLenSqr[this]
            • 'THEN'-Actions
              • Unit - Remove dummy[this] from the game
              • Set list[(Integer A)] = list[listC]
              • Set listC = (listC - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • 'IF'-Conditions
                  • listC Equal To 0
                • 'THEN'-Actions
                  • Countdown-Timer - Pause moveTimer
                • 'ELSE'-Actions
              • -------- <deallocation> --------
              • Set alloc_V[this] = alloc_F
              • Set alloc_F = this
              • -------- </deallocation> --------
            • 'ELSE'-Actions
              • Set d = (Square root(dSqr))
              • Set x[this] = (x[this] + ((dX / d) x moveLen[this]))
              • Set y[this] = (y[this] + ((dY / d) x moveLen[this]))
              • Set z[this] = (z[this] + ((dZ / d) x moveLen[this]))
              • Custom script: call SetUnitX(udg_dummy[udg_this], udg_x[udg_this])
              • Custom script: call SetUnitY(udg_dummy[udg_this], udg_y[udg_this])
              • Custom script: call MoveLocation(udg_zLoc, udg_x[udg_this], udg_y[udg_this])
              • Custom script: set udg_height = udg_z[udg_this] - GetLocationZ(udg_zLoc)
              • Animation - Change dummy[this] flying height to height at 0.00
              • Unit - Make dummy[this] face target[this] over 0.00 seconds
          • Custom script: call RemoveLocation(udg_targetLoc)
That's far from easier than the vjass code I posted above.
Thx dude u helped alot +rep for u :D
 
Status
Not open for further replies.
Top