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

[Snippet] Order Event

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
Like SpellEffectEvent, but this one is for catching orders. Also like SpellEffectEvent, this is pretty much as lightweight as it gets.

Update to version 3.0.0.0 - now requires Table due to some orders having very high indices. Thanks to Spellbound for pointing this out. Also, I improved the initialization by not auto-registering all three events unless the user specifically calls RegisterOrderEvent.

JASS:
//============================================================================
// OrderEvent by Bribe, special thanks to Nestharus and Azlier, version 3.0.1.1
//
// API
// ---
//     RegisterOrderEvent(integer orderId, code eventFunc)
//     RegisterAnyOrderEvent(code eventFunc) //Runs for point/target/instant for any order
//
// Requires
// --------
//     RegisterPlayerUnitEvent: http://www.hiveworkshop.com/threads/snippet-registerevent-pack.250266/
//     Table: http://www.hiveworkshop.com/forums/showthread.php?t=188084
//
library OrderEvent requires RegisterPlayerUnitEvent, Table

globals
    private Table t = 0
endglobals

//============================================================================
function RegisterAnyOrderEvent takes code c returns nothing
    static if RPUE_VERSION_NEW then
        call RegisterAnyPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, c)
        call RegisterAnyPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, c)
        call RegisterAnyPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, c)
    else
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, c)
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER, c)
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, c)
    endif
endfunction

//============================================================================
private function OnOrder takes nothing returns nothing
    call TriggerEvaluate(t.trigger[GetIssuedOrderId()])
endfunction

//============================================================================
function RegisterOrderEvent takes integer orderId, code c returns nothing
    local trigger trig
    if integer(t) == 0 then
        set t = Table.create()
        call RegisterAnyOrderEvent(function OnOrder)
    endif
    set trig = t.trigger[orderId]
    if trig == null then
        set trig = CreateTrigger()
        set t.trigger[orderId] = trig
    endif
    call TriggerAddCondition(trig, Filter(c))
    set trig = null
endfunction

endlibrary
 
Last edited:
Level 14
Joined
Nov 18, 2007
Messages
1,084
I can't think of a situation when I want to have an event detecting a specific order for all three cases of being immediate, point, or target and making me have to manually differentiate between them.
Because of this, I'm not sure when I would want to use this over RegisterPlayerUnitEvent and just filter out specific order ids.

Of course, I would be open to suggestions. :p
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
I had just read what watermelon_1234 had said and what you answered to him.
But now, i've reading your code and it makes sense.
Most of times we only need to check about a specific order, and if we have the need to check all point or all target, or no target orders, then you just don't need this resource.
 
Level 7
Joined
Dec 3, 2006
Messages
339
Small typo. . .

function RegisterAnyOrderEvent takes code order returns nothing
->function RegisterAnyOrderEvent takes code c returns nothing
 
Level 14
Joined
Nov 18, 2007
Messages
1,084
I still don't see how this resource is useful, at least from a spell maker's point of view.

Let's say I have a spell based on Berserk and I want to do spell actions only when the order is issued.
How is your system's way
JASS:
    private function SpellActions takes nothing returns nothing
        local unit c = GetTriggerUnit()
        if GetUnitAbilityLevel(c, SPELL_ID) > 0 then
            // Do spell stuff here
        endif
        set c = null
    endfunction
    
    private function Init takes nothing returns nothing
        call RegisterOrderEvent(ORDER_ID, function SpellActions)
    endfunction
better than
JASS:
    private function SpellActions takes nothing returns nothing
        local unit c = GetTriggerUnit()
        if GetIssuedOrderId() == ORDER_ID and GetUnitAbilityLevel(c, SPELL_ID) > 0 then
            // Do spell stuff here
        endif
        set c = null
    endfunction
    
    private function Init takes nothing returns nothing
        call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_ISSUED_ORDER, function SpellActions)
    endfunction
not to mention that the latter only registers immediate orders since the spell can't be cast differently?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
The reason the first way is better is because the trigger will only evaluate if the correct order has landed. The system efficiently handles orders no matter if it was a point, target or immediate order.

It is the same concept of using SpellEffectEvent or GTrigger to handle a specific cast (GTrigger also handles specific orders like this does).

Take for example a unit is ordered "stop". The system will evaluate all triggers that was registered with the "stop" order ID. With your method, your thing will evaluate no matter which order was issued.
 

Submission:
[Snippet] OrderEvent v2.1.0.0

Date:
18 October 16

Status:
Graveyard
Note:

The resource was previously approved and therefore should work fine.
If you use this script already in your codes, it's okay to keep it there.
But now we have this approved [Snippet] RegisterEvent pack, and so it's time to graveyard these specializations.
 

AGD

AGD

Level 16
Joined
Mar 29, 2016
Messages
688
You can safely use vJass "key" types, though.
Haven't thought of that, thanks for the tip.

Well, you wouldn't want to use "0" for a Table ... ever.
I'm curious though, is it because it's against the standards not a good practice? or is it because it's unsafe like using the index 8191 in an array?
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,456
If you use an unassigned integer as a Table index, you'd run the risk of another system doing the same. However, in the case of Table 0, that is considered "null" and if there are any mishaps in someone's code which leads to the referencing of uninitialized Tables, they would default to 0 and you get a lot of overwrites. So, even if you could be sure that the index of 0 is being used nowhere else, it's not good practice.
 
  • Like
Reactions: AGD
Top