• 🏆 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!

[JASS] Problem with units interruption (movement)

Status
Not open for further replies.
Level 26
Joined
Mar 19, 2008
Messages
3,140
Hey guys. This time it's me who require help :S

I have problem with simple loop, it picks unit every short time period and orders it to move to given direction. Problem is that in Jass those orders interrupt unit's movement. And don't tell me (I guess so) that it's all about just interval because my GUI version works pretty fine. Both uses Bride's IsUnitMoving and Unit Indexer (yes GUI ones).
JASS:
globals
    group HOWL_FEAR_GROUP = CreateGroup()
    constant integer HOWL_ID = 'A001'
    constant real HOWL_MIN_RADIUS = 400.
    constant real HOWL_MAX_RADIUS = 800.
    constant real HOWL_INTERVAL = 0.03125
    unit HOWL_CASTER = null
    real array HOWL_X
    real array HOWL_Y
    real array HOWL_STOPTIME
    real array HOWL_DURATION
endglobals

function HowlAreaOfEffect takes integer level returns real
    return 350 + (level * 50.)
endfunction

function GetHowlDuration takes integer level returns real
    return 5. + (level * 1.)
endfunction

function GetHowlStopTime takes nothing returns real
    return 1.5
endfunction

function Howl_Filter takes nothing returns boolean
    local unit u = GetFilterUnit()
    local integer key = GetUnitUserData(u)
    local integer level = GetUnitAbilityLevel(HOWL_CASTER, HOWL_ID)
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real r = GetRandomReal(HOWL_MIN_RADIUS, HOWL_MAX_RADIUS)
    local real angle = GetRandomReal(0, 360)
    if IsUnitEnemy(u, GetOwningPlayer(HOWL_CASTER)) and (not (GetWidgetLife(u) < 0.405)) and not IsUnitType(u, UNIT_TYPE_STRUCTURE) and not IsUnitType(u, UNIT_TYPE_MECHANICAL) then
        set HOWL_X[key] = x + r * Cos(angle * bj_DEGTORAD)
        set HOWL_Y[key] = y + r * Sin(angle * bj_DEGTORAD)
        set HOWL_DURATION[key] = GetHowlDuration(level)
        set HOWL_STOPTIME[key] = GetHowlStopTime()
        call GroupAddUnit(HOWL_FEAR_GROUP , u)
    endif
    set u = null
    return false
endfunction

function HowlOfFear_Conditions takes nothing returns boolean
    return GetSpellAbilityId() == HOWL_ID
endfunction

function HowlOfFear_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local group g = CreateGroup()
    local integer level = GetUnitAbilityLevel(u, HOWL_ID)
    local real x = GetUnitX(u)
    local real y = GetUnitY(u)
    local real radius = HowlAreaOfEffect(level)
    set HOWL_CASTER = u
    call GroupEnumUnitsInRange(g, x, y, radius, function Howl_Filter)
    call DestroyGroup(g)
    set g = null
    set HOWL_CASTER = null
    set u = null
endfunction

function Fear_Group_Loop takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer key = GetUnitUserData(u)
    local real angle = GetRandomReal(0, 360)
    local real r = GetRandomReal(HOWL_MIN_RADIUS, HOWL_MAX_RADIUS)
    local real dx
    local real dy
    if HOWL_DURATION[key] > 0.00 then
        call IssuePointOrder(u, "move", HOWL_X[key], HOWL_Y[key])
        if udg_UnitMoving[key] == false then
            set HOWL_STOPTIME[key] = HOWL_STOPTIME[key] - HOWL_INTERVAL
            if HOWL_STOPTIME[key] <= 0.00 then
                set dx = HOWL_X[key] + r * Cos(angle * bj_DEGTORAD)
                set dy = HOWL_Y[key] + r * Sin(angle * bj_DEGTORAD)
                set HOWL_STOPTIME[key] = GetHowlStopTime()
                set HOWL_X[key] = dx
                set HOWL_Y[key] = dy
            endif
        endif
        set HOWL_DURATION[key] = HOWL_DURATION[key] - HOWL_INTERVAL
    else
        call GroupRemoveUnit(HOWL_FEAR_GROUP, u)
        call IssueImmediateOrder(u, "stop")
    endif
    set u = null
endfunction

function Fear_Group takes nothing returns nothing
    call ForGroup(HOWL_FEAR_GROUP, function Fear_Group_Loop)
endfunction

function Howl_Of_Fear_Actions takes nothing returns nothing
    local trigger t1 = CreateTrigger()
    local trigger t2 = CreateTrigger()
    call TriggerRegisterAnyUnitEventBJ(t1, EVENT_PLAYER_UNIT_SPELL_EFFECT )
    call TriggerAddCondition(t1, Condition(function HowlOfFear_Conditions))
    call TriggerAddAction(t1, function HowlOfFear_Actions)
    call TriggerRegisterTimerEvent(t2, HOWL_INTERVAL, true)
    call TriggerAddAction(t2, function Fear_Group)
    set t1 = null
    set t2 = null
endfunction
//===========================================================================
function InitTrig_Howl_of_Fear takes nothing returns nothing
    local trigger t = CreateTrigger()
    call TriggerRegisterTimerEvent(t, 0.00, false)
    call TriggerAddAction(t, function Howl_Of_Fear_Actions)
    set t = null
endfunction

And here is my GUI version that works very well:
  • Howl of FearGUI
    • Events
      • Unit - A unit Starts the effect of ability
    • Conditions
      • (Ability being cast) Eqaul to MYability
    • Action
      • Set Fearpoint = (Position of (Triggering unit))
      • Custom script: set bj_wantDestroyGroup = true
      • Unit Group - Pick every unit in (Units within 512.00 of Fearpoint matching ((((Matching unit) is Building) Not eqaul to True) and ((((Matching unit) is alive) Equal to True) and (((Matching unit) belongs to an enemy of (Triggering player))Equal to True)))) and do (Actions)
        • Loop - Actions
          • Set key = (Custom value of (Picked unit))
          • Set FearDuration[key] = 8.00
          • Set FearDelay[key] = 1.50
          • Set Fearpoint2 = (Fearpoint offset by 400.00 towards (Random angle) degrees)
          • Set x[key] = (X of Fearpoint2)
          • Set y[key] = (Y of Fearpoint2)
          • Custom script: call RemoveLocation(udg_Fearpoint2)
          • Unit Group - Add (Picked unit) to FearGroup
      • Custom script: call RemoveLocation(udg_Fearpoint)
  • HoF Loop
    • Events
      • Time - Every 0.03 seconds of game time
    • Conditions
    • Actions
      • Unit Group - Pick every unit in FearGroup and do (Actions)
        • Loop - Actions
          • Set key = (Custom value of (Picked unit))
          • Set FearDuration[key] = (FearDuration[key] - 0.03)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • FearDuration[key] Greater than 0.00
            • Then - Actions
              • Custom script: call IssuePointOrder(GetEnumUnit(), "move", udg_x[udg_key], udg_y[udg_key])
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • UnitMoving[key] Not eqaul to true
                • Then - Actions
                  • Set FearDelay[key] = (FearDelay[key] - 0.03)
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • FearDelay[key] Mniejsze lub rĂłwne 0.00
                    • Then - Actions
                      • Set Fearangle = (Random angle)
                      • Set Fearpoint = ((Point(x[key], y[key])) offset by 400.00 towards Fearangle degrees)
                      • Set x[key] = (X of Fearpoint)
                      • Set y[key] = (Y of Fearpoint)
                      • Set FearDelay[key] = 1.50
                      • Custom script: call RemoveLocation(udg_Fearpoint)
                    • Else - Actions
                • Else - Actions
            • Else - Actions
              • Unit Group - Remove (Picked unit) from FearGroup
 
Level 37
Joined
Mar 6, 2006
Messages
9,240
I don't think ordering the unit to move every 0.03 seconds is a good solution.

You could do the order once when the spell is cast. Then in the looping function, check whether the unit is moving or not. Also check the current order if needed. Maybe even check that the unit is moving away from the caster or alternatively towards the destination point (distance and/or facing). Only give the unit a new order if needed.

Disabling the unit's attack could also help.
 
Level 26
Joined
Mar 19, 2008
Messages
3,140
Thats a good idea, however it will bug if I add ' issue a point order' to that orders-prevention trigger since point order will trigger function once again and again. How to disable/enable function in jass? In GUI you disable triggers ;/
What do you mean 'save coordinates'? If you mean to save x and y of destination point, I have already done that.

Maker - I'll soon post map, as WiP for hero contest ^^
 
Level 29
Joined
Mar 10, 2009
Messages
5,016
This...
JASS:
function Fear_Group_Loop takes nothing returns nothing
    local unit u = GetEnumUnit()
    local integer key = GetUnitUserData(u)
    local real angle = GetRandomReal(0, 360)
    local real r = GetRandomReal(HOWL_MIN_RADIUS, HOWL_MAX_RADIUS)
    local real dx
    local real dy
    if HOWL_DURATION[key] > 0.00 then
        call IssuePointOrder(u, "move", HOWL_X[key], HOWL_Y[key])
        if udg_UnitMoving[key] == false then
            set HOWL_STOPTIME[key] = HOWL_STOPTIME[key] - HOWL_INTERVAL
            if HOWL_STOPTIME[key] <= 0.00 then

IMO...Ima experiment on this...
JASS:
local unit u = GetEnumUnit()
local integer key = GetUnitUserData(u)
local string o = OrderId2String(GetUnitCurrentOrder(u))
   if o==null and HOWL_DURATION[key] > 0 then
      set HOWL_DURATION[key] =HOWL_DURATION[key] - HOWL_INTERVAL
      //actions...
   else
      call GroupRemoveUnit(HOWL_FEAR_GROUP, u)
      call IssueImmediateOrder(u, "stop")
   endif
 
Status
Not open for further replies.
Top