How to issue orders to unit with Jass without timers?

Level 5
Joined
May 10, 2024
Messages
57
Hi,

I'm issuing holylight order using Jass. Table below is a timeline of that action.

StepTimeWhat's happeningComment
1.0.00secIssue order "holylight".
2.0.00secUnit starts smoking.If unit is not stunned, then in most situations his order changes instantly. Sometimes his order changes after some delay. I have no idea what is going on inside the engine. I called this period "smoking".
3.0.10secOrder of the unit has changed to "holylight".
4.0.10secUnit starts turning towards the target.
5.0.20secUnit starts moving towards the target until it is within the cast range.The turn towards the target took 0.10 seconds.
6.1.20secUnit starts smoking.It took 1.00 sec to get into the cast range.
7.1.30secUnit starts channeling an ability.

I have simple function which control my unit. Function should work correctly regardless of call frequency. I must be able to call it multiple times per tick and it should work well.

JASS:
function controlUnit takes unit whichUnit returns nothing
    local targetUnit = SomeFuncToFindTargetUnit()
    call IssueTargetOrder(whichUnit, "holylight", targetUnit)
endfunction

If controlUnit in current state is firing more then once in 0.10 sec, then caster will never cast Holy Light because he does not have enough time for smoking on Step 2. It means that caster should not be interrupted before step 3.
To solve this, I could create global boolean IsIssuingOrder and set it to true before issuing an order to caster. Then I subscribe for issue order events: EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, EVENT_PLAYER_UNIT_ISSUED_ORDER to change global variable back to false once order is issued.

JASS:
function IssuedOrderEvent takes nothing returns nothing
    local integer issuedOrderId = GetIssuedOrderId()
    local integer curentOrderId = GetUnitCurrentOrder(GetTriggerUnit())
    if (issuedOrderId == curentOrderId) then
        set IsIssuingOrder = false
    endif
endfunction

It's time to update controlUnit function.

JASS:
function controlUnit takes unit whichUnit returns nothing
    local targetUnit = SomeFuncToFindTargetUnit()
    if (IsIssuingOrder == false) then
        set IsIssuingOrder = true
        call IssueTargetOrder(whichUnit, "holylight", targetUnit)
    endif
endfunction

Now I must be able call controlUnit more then once per 0.10 sec and it should not stuck on step 2 because of the timer. But if my unit is picked up by zeppelin on step 2, then unit will stuck in IsIssuingOrder state forever or until I add some code to handle this situation. But there may be other situations. What about PauseUnit, DisableUnit? There can be a lot of them!

Next situation. I issue HolyLight on my footman. Before unit started casting ability, invulnerability potion has ended on enemy undead hero with 50 hp. It's obvious that would be better to kill enemy hero instead of healing my footman. It means that between step 3 and 7 caster must be able change his target. In other words I can interrupt holylight order after step 3 and before step 7, before caster starts channeling. I need global boolean IsChanneling to indicate that unit start channeling an ability.
I subscribe for "start channeling" event and "end casting" event EVENT_PLAYER_UNIT_SPELL_CHANNEL, EVENT_PLAYER_UNIT_SPELL_ENDCAST to change my global variable.

JASS:
function SpellChannel takes nothing returns nothing
    set IsChanneling = true
endfunction
JASS:
function SpellEndcast takes nothing returns nothing
    set IsChanneling = false
endfunction

It's time to update controlUnit function.

JASS:
function controlUnit takes unit whichUnit returns nothing
    local targetUnit = SomeFuncToFindTargetUnit()
    if (IsIssuingOrder == false and IsChanneling == false) then
        set IsIssuingOrder = true
        call IssueTargetOrder(whichUnit, "holylight", targetUnit)
    endif
endfunction

Now I have another problem. Caster will stuck if controlUnit is firing more often then time needed for step 4+5+6.

How you issue orders to units with Jass avoiding problems listed above?
Do you have suggestions, ideas how to solve this problems without expiration timers?
 
Level 29
Joined
Sep 26, 2009
Messages
2,594
Warcraft uses event-based system, so trying this via timer is just you trying to circumvent the engine. So of course you will encounter issues :D
The "smoke" time is most definitely unit's cast point or spell's cast time, see Casting Events Guide

So the solution is to use multiple triggers, each with different event (i.e. issued order, starts casting, stops casting, etc.) and handle unit's state in them.
Can't really be more specific as I don't understand what you are trying to achieve except for re-issuing holy light order every 0.1 seconds.
 
Top