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

[System] [Needs work] CargoEvent

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
CargoEvent was inspired by the methods in Jesus4Lyf's Transport and grim001's AutoEvents. Originally, this was just meant to be an efficient, UnitIndexer-compatible build, but during testing I found everything having to do with the unload-detection had to be redone to compensate for some crazy errors that abound in the other two transport libraries.

JASS:
library CargoEvent requires UnitIndexer
/*
    CargoEvent by Bribe, v1.1.0.0
    
    Working on this library has been quite educational. During the process,
    I found the existing detection in Jesus4Lyf's "Transport" and grim001's
    "AutoEvents" needed to be remade.
    
    Those libraries move the unit to the edge of the map. What about Bound-
    Sentinel, which knocks them back into bounds? This fires the unload event
    prematurely. Don't use BoundSentinel? What about a unit that is loaded
    while in the process of being knocked-back? That screws it up as well.
    
    I've tried debugging this by setting the unit's position out of bounds a
    second time, but it strangely won't re-fire the event. And BoundSentinel
    would cause an infinite loop even if it worked. Time for a new method.
    
    On top of that, A recursion bug in the other systems that can cause big
    problems - a load order at the same time a unit is unloaded.
    
    This library fixes those bugs but factors in other considerations:
    
        1. Units must be indexed by UnitIndexer (have a unique ID)
        
        2. Units paused while loaded on a transport will not be issued a stop
           order when they are unloaded, so I have implemented a safety catch
           that unpauses units when they are paused in-transit. If you do not
           want this check (or don't have any risk of this happening in your
           map), set PAUSE_SAFETY to false.
    
    API
    
        struct CargoEvent extends array
            
            Event LOAD
                > Fires when a passenger is loaded into a transport.
    
            Event UNLOAD
                > Fires when a passenger is unloaded from a transport.
            
            readonly integer transport
                > The unit-id of this unit's transport.
    
        function GetUnitTransport takes unit passenger returns unit
            > returns the unit carrying the passenger.
    
        function GetEventLoadedUnit
            > returns the passenger that was loaded/unloaded.
    
        function GetEventTransportUnit takes nothing returns unit
            > returns the transport loading/unloading the passenger.
*/
    
native UnitAlive takes unit id returns boolean
    
globals
    private boolean array block
    private constant boolean PAUSE_SAFETY = true
endglobals
    
private module Init
    private static method onInit takes nothing returns nothing
        local boolexpr l = Filter(function thistype.unload)
        static if PAUSE_SAFETY then
            local boolexpr p = Filter(function thistype.unpause)
        endif
        local integer i = 15
        local trigger t = CreateTrigger()
        loop
            call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_LOADED, null)
            call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_ISSUED_ORDER, l)
            static if PAUSE_SAFETY then
                call TriggerRegisterPlayerUnitEvent(t, Player(i), EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER, p)
            endif
            exitwhen i == 0
            set i = i - 1
        endloop
        call TriggerAddCondition(t, Filter(function thistype.load))
        set LOAD = Event.create()
        set UNLOAD = Event.create()
        set t = null
        set l = null
        static if PAUSE_SAFETY then
            set p = null
        endif
    endmethod
endmodule
    
struct CargoEvent extends array
    
    readonly    static      Event       LOAD    = 0
    readonly    static      Event       UNLOAD  = 0
    readonly    integer     transport
    
    private static method unload takes nothing returns boolean
        local thistype this = GetUnitId(GetFilterUnit())
        if this.transport != 0 and not block[this] and not (IsUnitLoaded(GetUnitById(this)) and UnitAlive(GetUnitById(this))) then
            /*
              How this works:
              
                1. Ignore units that aren't currently loaded.
                2. Check for recursion so as to not double-fire the event (if
                   a unit is loaded at the same time it was unloaded)
                3. A stop order is issued by a unit when it's unloaded.
                4. Ensure the unit was not ordered to stop while loaded.
                5. A unit fires the unload event when it dies in-transit.
            */
            set block[this] = true
            call UNLOAD.fireData(this)
            set block[this] = false
            if not (IsUnitLoaded(GetUnitById(this)) and UnitAlive(GetUnitById(this.transport))) then
                // Also recursion-safe
                set this.transport = 0
            endif
        endif
        return false
    endmethod
    
    private static method load takes nothing returns boolean
        local thistype this = GetUnitId(GetTriggerUnit())
        set this.transport = GetUnitId(GetTransportUnit())
        call LOAD.fireData(this)
        return false
    endmethod
    
    static if PAUSE_SAFETY then
        private static method unpause takes nothing returns boolean
            if IsUnitLoaded(GetFilterUnit()) and IsUnitPaused(GetFilterUnit()) then
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 99, "CargoEvent Safety: A passenger was paused in-transit and is now being un-paused to ensure proper unload-detection.")
                call PauseUnit(GetFilterUnit(), false)
            endif
            return false
        endmethod
    endif
    
    implement Init
endstruct
    
function GetUnitTransport takes unit passenger returns unit
    return GetUnitById(CargoEvent(GetUnitId(passenger)).transport)
endfunction
    
function GetEventLoadedUnit takes nothing returns unit
    return GetUnitById(GetEventData())
endfunction
    
function GetEventTransportUnit takes nothing returns unit
    return GetUnitById(CargoEvent(GetEventData()).transport)
endfunction
    
endlibrary


  • 1.1.0.0 - Added optional PAUSE_SAFETY to protect against bugs.
  • 1.0.1.0 - Optimized the boolean checks, merged the "order" and "load" triggers into one.
  • 1.0.0.0 - Public release
 
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
I've tested it with heroes & units and the event fired when I killed it over water. I will test it again to be sure when I'm home.

At home I also have the pause-safety. It's pretty simple and done without hooks - the "pause" order is a point order??? Anyway, I just added a "pause safety" in static if's which I'll be updating in what would be the morning in the USA.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Ok, for pause safety, that should always be enabled. You should be able to infer how many times a unit was paused, store a count of those pauses, and decrease the count every time the unit is unpaused. This will ensure that the unit is properly unpaused when it is unloaded. Make sense? ; ).

The pausing thing would be its own resource.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Well, I guess that you could argue that if you are only passing 1 value of type integer, then the EventData version is fine.

But another argument would be passing multiple values, or passing values of different types.

A method that is only useful for a select few things just doesn't make too much sense to me, which is why I'm against the Event Data version : P.

See, I could argue then that if a library needed an eventUnit and 2 event integers, then it'd be the exact same overhead to put it into Event as it would be to keep it in the library, and then I could just keep expanding on that claiming that it'd be less overhead for all of these libs :\.

That's where I'm coming from ; p. Sure, it may make sense right now, but I don't think it's a good practice =)
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Yeah currently I just have the part in where it unpauses units in a transport. The problem is with unpausing units when dropped is that I don't know if the user will still want it paused at that point :-/

I don't know if stuns have the same effect, however. A stunned/paused unit cannot be loaded into a transport and I don't think that a unit can cast a stun spell on a transported unit. Eh.

It's a tough ballgame. I don't want to limit users to say they can't pause a unit in a transport, but at the same time the "unload" event does need to fire, that's why I have the PAUSE_SAFETY static if.

I think what I will do is add a periodic timer in the rare case a unit is paused while in a transport. The timer will just cycle until the appropriate conditions are met, every 0.03125 seconds would be reasonable here. I'd rather have the event fire at an innaccurate time rather than take away a user's ability to pause a unit while in a transport.
 
Last edited:
Level 7
Joined
Dec 3, 2006
Messages
339
This could be pretty useful for me but for some reason I can't force the unload order for a specific unit loaded or an complete unload order I'm wondering what may be the issue causing this. Is an unload ability required?

I used the order id from here: http://www.hiveworkshop.com/forums/jass-functions-413/repo-order-ids-197002/

But had no luck. : /

Maybe it's like cancel where theres an order id for it but you can't really detect/use it?
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Well the unit you have to order is the transport, not the unit being transported.

I'm not sure what's not working about it. Was it working before you imported this system into your map?

If it's not working either way, I recommend posting about it in the Triggers / Scripts forum, because more people will be able to see your help request there and decrease the latency time in getting a proper response.
 
Level 7
Joined
Dec 3, 2006
Messages
339
I am ordering the transport. I was just thinking its kind of odd. I mean even using ForceUIKey i cannot get it to unload. Here take a look if you want. Test the map type -load to load up several units that are created on spot(I intend to use for a spell like bar). And then try unloading the cancel icon(footman) which should unload everything so you can see the unit's stats display again.

As for the preventorders thing i was trying to fuddle around with it to see if i could get it to work so that it would save and continue move orders etc. I'm not exactly using it completely right though i guess. The triggering is kind of poor cause i'm just setting up some tests to see if this is really a workable idea.

JASS:
scope b initializer INIT
private function actionz takes nothing returns nothing
local unit transport = GetEventTransportUnit()
local unit loaded = GetEventLoadedUnit()
local string s = GetUnitName(transport)
local string s2 = OrderId2String(852047) // <-- this is the unload order id check'd from the [Repo] Order Ids
                                                      //  also tried 852048, 852049
call BJDebugMsg(s+ "unloaded")
call GroupRemoveUnit(transportGroup, loaded)
if GetUnitTypeId(loaded)== 'hfoo' then
    //call AllowNextOrder(udg_transporty)  <- was just something to make sure the order wasn't interrupted didn't help   
    
    //call IssueImmediateOrder(udg_transporty, s2) //<-- should order to unload all
    //call ForceUIKey("U") //<-- even hotkeys don't work?
   call IssueImmediateOrderById(udg_transporty, 0xD004F) //<-- also doesn't work even though this id that printed when i used the ability
endif
//this below is trying the other way where the unit inside is ordered to unload
//and this doesn't work either.
  //  if GetUnitTypeId(loaded)== 'hfoo' then
      //  loop
     //   exitwhen CountUnitsInGroup(transportGroup) == 0
     //   call AllowNextOrder(GroupPickRandomUnit(transportGroup))
     //   call IssueImmediateOrder(GroupPickRandomUnit(transportGroup), s2)
     //   endloop
 //  endif
endfunction

private function INIT takes nothing returns nothing
local trigger t = CreateTrigger()
call TriggerRegisterEvent(t,CargoEvent.UNLOAD)
call TriggerAddAction(t, function actionz)
endfunction

endscope

Edit:
I'm also using the Entangle GoldMine Instant Unload ability; cause it has no target point requirement.
And i've also just tried 852048, and 852049 as an order id : /

Edit: Reuploaded tried both Bribe's and Waterknight's suggestions still nothing.

Edit: SOLVED it was 852049 and ForceUIKey("u") also worked; it was a matter of code being halted by an unitgroup undefined. Thread is here:http://www.hiveworkshop.com/forums/world-editor-help-zone-98/possible-even-issue-unload-204324/
 

Attachments

  • CargoStufdf.w3x
    35.1 KB · Views: 57
Last edited:
Level 7
Joined
Dec 3, 2006
Messages
339
Well, print orders gave me this: OxD004F

Any way of converting that order to an integer id? Or is that the same as the [repo] order id for it?
 
Level 7
Joined
Dec 3, 2006
Messages
339
Hmm, still doesn't work. To further prevent spamming this submission thread with slightly off-topicness i created a new thread:
http://www.hiveworkshop.com/forums/world-editor-help-zone-98/possible-even-issue-unload-204324/

The allownextorder doesn't prevent anything it's from a custom version of preventorders:

JASS:
/***********************************************************
*                           PreventOrders                   
*                       by Element of Water                 
************************************************************
* Requirements:                                             
* - AutoIndex by grim001                                    
* - JassHelper by Vexorian (for vJass)                      
************************************************************
* What is it?                                               
*                                                           
* PreventOrders is a simple library which provides a few    
* useful functions to do with the preventing and
* cancelling of certain orders. Whenever an order is
* "prevented", the unit will carry on with its previous
* order as usual (but if it has multiple orders queued
* up, it will not continue with those).                     
*                                                           
* CancelOrders immediately cancels a unit's orders. It      
* is different to simply issuing a "stop" order, because    
* it works even in response to SpellCast or IssuedOrder     
* events. It takes just a  single unit parameter. Call      
* it like this:                                             
*                                                           
* call CancelOrders(myUnit)                                 
*                                                           
* It's that simple!                                         
*
* PreventCurrentOrder immediately stops the unit from
* performing its current order and returns it to its
* previous order. The syntax for calling it is as follows:
*
* call PreventCurrentOrder(myUnit)
*
* Simplez!
*                                                           
* PreventOrders permanently stops a unit from responding    
* to immediate, point and/or target orders. Call it like    
* this:                                                     
*                                                           
* call PreventOrders(myUnit, immediate, point, target)      
*                                                           
* immediate, point and target are booleans. These should    
* be true if you want to disable immediate, point or        
* target orders respectively. If you want to re-enable      
* a type of order, simply call the function again with      
* the desired parameters as false, and the unit will be     
* able to recieve orders again                              
*                                                           
* PreventSpecificOrder permanently stops a unit from        
* responding to a specific order, such as "move", "smart",  
* "channel", "acidbomb", etc. Call it like this:            
*                                                           
* call PreventSpecificOrder(myUnit, order, prevent)         
*                                                           
* order is the order string which determines which order    
* is prevented, and prevent is a boolean. prevent should    
* be true if you want to disable the order, and false if    
* you want to re-enable it. Also, if it is false it will    
* bypass the blocking of all orders just for this order.    
* You can call ClearSpecificOrderPrevention(myUnit, order)  
* to reset for one specific order, or call                  
* ClearAllSpecificOrderPrevention(myUnit) to reset all      
* orders for that unit.
*                                                           
* There is a variation of this function,                    
* PreventSpecificOrderById, which takes an integer instead  
* of a string for if you prefer to work with order ids.     
* You may also use ClearSpecificOrderPreventionById.        
*                                                           
* AllowNextOrder allows a unit to respond to the next order 
* it is issued, whatever that may be. Even if the order     
* would not be blocked anyway, this is cleared immediately  
* after the next order issued to the unit. The syntax to    
* call it is as follows:                                    
*                                                           
* call AllowNextOrder(myUnit)                               
*                                                           
* This function is useful for when you want to control the  
* unit through triggers, but make it unresponsive to        
* player control. The PreventOrdersHooks add-on utilises    
* this function to allow all triggered orders via hooks.    
***********************************************************/
library PreventOrders initializer Init requires UnitIndexer
    private keyword Data
    
    globals
        private timer       Tim         = CreateTimer()
        private Data array  CancelStack
        private integer     CancelCount = 0
        private hashtable   Hash        = InitHashtable()
        
        private constant integer ORDER_STOP = 851972
        
        // Purely for debugging purposes, this displays when an order is prevented
        private constant boolean DISPLAY_PREVENTED_ORDERS = false
        // Set this to true to make units keep their old orders rather than simply stopping when an order is prevented
        private constant boolean RETAIN_PREVIOUS_ORDERS   = true //false
    endglobals
    
    private function DebugMsg takes string unitName, string orderType, string orderString returns nothing
        debug static if DISPLAY_PREVENTED_ORDERS then
        debug     call BJDebugMsg("PreventOrders: Prevented " + unitName + " from being issued a" + orderType + " " + orderString + " order")
        debug endif
    endfunction
    
    struct Data extends array
        static constant integer IMMEDIATE = 1
        static constant integer POINT     = 2
        static constant integer TARGET    = 3
        
        
        unit u
        boolean i
        boolean p
        boolean t
        
        boolean doNext
        
        integer lastOrderType
        integer lastOrderId
        widget  lastOrderTargetW
        real    lastOrderTargetX
        real    lastOrderTargetY
        boolean cancel
        
      method lastImmediateOrder takes integer id returns nothing
            set lastOrderType = IMMEDIATE
            set lastOrderId   = id
        endmethod
        
       method lastPointOrder takes integer id, real x, real y returns nothing
            set lastOrderType    = POINT
            set lastOrderId      = id
            set lastOrderTargetX = x
            set lastOrderTargetY = y
        endmethod
        
       method lastTargetOrder takes integer id, widget target returns nothing
            set lastOrderType    = TARGET
            set lastOrderId      = id
            set lastOrderTargetW = target
        endmethod
        
       method doLastOrder takes nothing returns nothing
            if cancel then
                set doNext = true
                call IssueImmediateOrderById(u, ORDER_STOP)
            else
                if     lastOrderType == IMMEDIATE then
                    set doNext = true
                    call IssueImmediateOrderById(u, lastOrderId)
                elseif lastOrderType == POINT then
                    set doNext = true
                    call IssuePointOrderById(u, lastOrderId, lastOrderTargetX, lastOrderTargetY)
                elseif lastOrderType == TARGET then
                    set doNext = true
                    call IssueTargetOrderById(u, lastOrderId, lastOrderTargetW)
                else
                    set doNext = true
                    call IssueImmediateOrderById(u, ORDER_STOP)
                endif
            endif
        endmethod
        
       method assign takes unit whichUnit returns nothing
            set u = whichUnit
        endmethod
        
       method destroy takes nothing returns nothing
            call FlushChildHashtable(Hash, this)

            set u = null
            set i = false
            set p = false
            set t = false
            
            set doNext = false
            
            set lastOrderType = 0
            set cancel        = false
        endmethod
    endstruct
    
    private function Cancel takes nothing returns nothing
        loop
            set CancelCount = CancelCount - 1
            static if RETAIN_PREVIOUS_ORDERS then
                call CancelStack[CancelCount].doLastOrder()
            else
                set CancelStack[CancelCount].doNext = true
                call IssueImmediateOrderById(CancelStack[CancelCount].u, ORDER_STOP)
            endif
            exitwhen CancelCount == 0
        endloop
    endfunction
    
    private function PreventCurrentOrderFromData takes Data d returns nothing
        if CancelCount == 0 then
            call TimerStart(Tim, 0., false, function Cancel)
        endif
        set CancelStack[CancelCount] = d
        set CancelCount = CancelCount + 1
    endfunction
    
    function PreventCurrentOrder takes unit u returns nothing
        call PreventCurrentOrderFromData(Data[GetUnitId(u)])
    endfunction
    
    function CancelOrders takes unit u returns nothing
        local Data d = Data[GetUnitId(u)]
        static if RETAIN_PREVIOUS_ORDERS then
            set d.cancel = true
        endif
        call PreventCurrentOrderFromData(d)
    endfunction
    
    function PreventOrders takes unit u, boolean i, boolean p, boolean t returns nothing
        local Data d = Data[GetUnitId(u)]
        
        if i or p or t then
            set d.i = i
            set d.p = p
            set d.t = t
        endif
    endfunction
    
    function PreventSpecificOrderById takes unit u, integer orderId, boolean prevent returns nothing
        local Data d = Data[GetUnitId(u)]
        
        if orderId != 0 then
            if prevent then
                call SaveBoolean(Hash, d, orderId, true)
            elseif d != 0 then
                call SaveBoolean(Hash, d, orderId, false)
            endif
        endif
    endfunction
    
    function PreventSpecificOrder takes unit u, string order, boolean prevent returns nothing
        call PreventSpecificOrderById(u, OrderId(order), prevent)
    endfunction
    
    function ClearSpecificOrderPreventionById takes unit u, integer orderId returns nothing
        local Data d = Data[GetUnitId(u)]
        
        if orderId != 0 and orderId != ORDER_STOP then
            call RemoveSavedBoolean(Hash, d, orderId)
        endif
    endfunction
    
    function ClearSpecificOrderPrevention takes unit u, string order returns nothing
        call ClearSpecificOrderPreventionById(u, OrderId(order))
    endfunction
    
    function ClearAllSpecificOrderPrevention takes unit u returns nothing
        local Data d = Data[GetUnitId(u)]
        call FlushChildHashtable(Hash, d)
    endfunction
    
    function AllowNextOrder takes unit u returns nothing 
        local Data d = Data[GetUnitId(u)]
        set d.doNext = true
    endfunction
    
    private function ImmediateOrder takes nothing returns boolean
        local unit u = GetTriggerUnit()
        local Data d = Data[GetUnitId(u)]
        local integer i = GetIssuedOrderId()
        
        if d.doNext then
            set d.doNext = false
            call d.lastImmediateOrder(i)
        else
            if d.i then
                if (not HaveSavedBoolean(Hash, d, i)) or (LoadBoolean(Hash, d, i)) then
                    call PreventCurrentOrderFromData(d)
                    debug call DebugMsg(GetUnitName(u), "n immediate", OrderId2String(i))
                else
                    static if RETAIN_PREVIOUS_ORDERS then
                        call d.lastImmediateOrder(i)
                    endif
                endif
            elseif LoadBoolean(Hash, d, i) then
                call PreventCurrentOrderFromData(d)
                debug call DebugMsg(GetUnitName(u), "n immediate", OrderId2String(i))
            else
                static if RETAIN_PREVIOUS_ORDERS then
                    call d.lastImmediateOrder(i)
                endif
            endif
        endif
        
        set u = null
        
        return false
    endfunction
    
    private function PointOrder takes nothing returns boolean
        local unit u    = GetTriggerUnit()
        local Data d    = Data[GetUnitId(u)]
        local integer i = GetIssuedOrderId()
        
        if d.doNext then
            set d.doNext = false
            call d.lastPointOrder(i, GetOrderPointX(), GetOrderPointY())
        else
            if d.p then
                if (not HaveSavedBoolean(Hash, d, i)) or (LoadBoolean(Hash, d, i)) then
                    
                    call PreventCurrentOrderFromData(d)
                    debug call DebugMsg(GetUnitName(u), " point", OrderId2String(i))
                else
                    static if RETAIN_PREVIOUS_ORDERS then
                        call d.lastPointOrder(i, GetOrderPointX(), GetOrderPointY())
                    endif
                endif
            elseif LoadBoolean(Hash, d, i) then
                call PreventCurrentOrderFromData(d)
                debug call DebugMsg(GetUnitName(u), " point", OrderId2String(i))
            else
                static if RETAIN_PREVIOUS_ORDERS then
                    call d.lastPointOrder(i, GetOrderPointX(), GetOrderPointY())
                endif
            endif
        endif
        
        set u = null
        
        return false
    endfunction
    
    private function TargetOrder takes nothing returns boolean
        local unit u    = GetTriggerUnit()
        local Data d    = Data[GetUnitId(u)]
        local integer i = GetIssuedOrderId()
        
        if d.doNext then
            set d.doNext = false
            call d.lastTargetOrder(i, GetOrderTarget())
        else
            if d.t then
                if (not HaveSavedBoolean(Hash, d, i)) or (LoadBoolean(Hash, d, i)) then
                    call PreventCurrentOrderFromData(d)
                    debug call DebugMsg(GetUnitName(u), " target", OrderId2String(i))
                else
                    static if RETAIN_PREVIOUS_ORDERS then
                        call d.lastTargetOrder(i, GetOrderTarget())
                    endif
                endif
            elseif LoadBoolean(Hash, d, i) then
                call PreventCurrentOrderFromData(d)
                debug call DebugMsg(GetUnitName(u), " target", OrderId2String(i))
            else
                static if RETAIN_PREVIOUS_ORDERS then
                    call d.lastTargetOrder(i, GetOrderTarget())
                endif
            endif
        endif
        
        set u = null
        
        return false
    endfunction
    
    private function UnitIndexed takes nothing returns boolean
        local integer i = GetIndexedUnitId()
        local unit u = GetUnitById(i)
        local Data d = Data[i]
        call d.assign(u)
        set u = null
        return false
    endfunction
    
    private function UnitLeavesMap takes nothing returns boolean
        local integer i = GetIndexedUnitId()
        local unit u = GetUnitById(i)
        local Data d = Data[i]
        call d.destroy()
        set u = null
        return false
    endfunction
    
    private function Init takes nothing returns nothing
        local trigger t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_ORDER)
        call TriggerAddCondition(t, Condition(function ImmediateOrder))
        
        set t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER)
        call TriggerAddCondition(t, Condition(function PointOrder))
        
        set t = CreateTrigger()
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER)
        call TriggerAddCondition(t, Condition(function TargetOrder))
        
        call RegisterUnitIndexEvent(Condition(function UnitIndexed), UnitIndexer.INDEX)
        call RegisterUnitIndexEvent(Condition(function UnitLeavesMap), UnitIndexer.DEINDEX)
        //call OnUnitIndexed(UnitIndexed)
        
        //call OnUnitDeindexed(UnitDeindexed)
    endfunction
endlibrary

I'll test it without though to make sure its not the cause i guess.
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Really BJDebugMsg is cool enough for debug messages ...

GetLocalPlayer "bugs" in replay, for text messages it will be considered as the first human playing slot. (but it seems to affect only visual things not the gameplay or the result of the game)
If you care that much about efficiency in debugs (for wtf reason ?!) you could still use DisplayTextFromPlayer with a valid player (included GetLocalPlayer), since it will display it for each player as long its player argument is valid.
And yes 60 s is enough.
(i supposed it's an other NotYetImplanted feature : display a text as if it was a player chat, or something like that)
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
There is still the chatbox you know (and the game is even be paused, if you launch the game in solo mode).

But because of its string limit, if you have a spam of debug messages i suppose a dedicated system is worth it (the requirement should be optionnal if it's a public resource though, if the user have not this library : the function(s) used should be a wrapper of BJDebugMsg or eventually DisplayTextFromPlayer ).

Each time i see a BJDebugMsg inlined with a DisplayTextForPlayer(GetLocalPlayer()...) for a debug message, it just makes me "sad" ...
 

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,467
Yeah I have been using it more and more lately myself as well. One of the things I like about GUI is it is so easy to make a debug message (BJDebugMsg requires three alternations of the SHIFT key, for example, it is easy to make capitalization mistakes and don't get me started on how easy it is to syntax up string concatenation), and it is also much more efficient than BJDebugMsg :p
 
Level 17
Joined
Apr 27, 2008
Messages
2,455
Yeah I have been using it more and more lately myself as well. One of the things I like about GUI is it is so easy to make a debug message (BJDebugMsg requires three alternations of the SHIFT key, for example, it is easy to make capitalization mistakes and don't get me started on how easy it is to syntax up string concatenation), and it is also much more efficient than BJDebugMsg :p

Mouahahaha, talking about efficiency in GUI, funny.
Even common things like "if/then" have so much overheads comparing to jass. (yeah i realize that is a joke)

Plus, i still prefer three alternations of the shift key against X clicks (copy/paste can't be used all the time)
Also, with Tesh, typing BJ (or maybe BJD i don't remember) + enter is enough.

Finally, even if math/strings concatenation are way more friendly user in jass, i have to admit that string concatenation could be improved in jass.
Write something like that is really boring :

I2S(<integer>) + "message1" + R2S(<real>) + "message2" ...

instead of (or something else, like in C way or whatever) :

"%<integer> message1 %<real> message2"

I just wanted to say it because i said in your luck thread quite the opposite (in some way) but didn't realized the matter of the sugar syntax improvement.

End of off-topic for me (unless you want to continue and don't care about the flood in your resource)
 
Level 7
Joined
Dec 3, 2006
Messages
339
AutoIndex? A crime!
BJDebugMsg? A felony!
Timer Callbacks? Osama Bin Laden!

I changed that script to run on UnitIndexer if you bothered to look just was lazy and didn't change the documentation. And BJDebugMsg isn't all that bad if you just use it for tests only. But why are timer callbacks bad?

JASS:
    private function Cancel takes nothing returns nothing
        loop
            set CancelCount = CancelCount - 1
            static if RETAIN_PREVIOUS_ORDERS then
                call CancelStack[CancelCount].doLastOrder()
            else
                set CancelStack[CancelCount].doNext = true
                call IssueImmediateOrderById(CancelStack[CancelCount].u, ORDER_STOP)
            endif
            exitwhen CancelCount == 0
        endloop
    endfunction
    
    private function PreventCurrentOrderFromData takes Data d returns nothing
        if CancelCount == 0 then
            call TimerStart(Tim, 0., false, function Cancel)
        endif
        set CancelStack[CancelCount] = d
        set CancelCount = CancelCount + 1
    endfunction
Like what would this look like without a callback and fix'd?
 
But why are timer callbacks bad?

Like what would this look like without a callback and fix'd?

IMO it is perfectly fine to have callbacks, especially for 0 second timers. The real duration of 0 second timers is so low that you would have to have multiple calls instantaneously for you to worry at all about efficiency. :)
 
Level 7
Joined
Dec 3, 2006
Messages
339
This should be updated to include unloaded dead units if possible. The meatwagon exhume corpses is the only ability i found finally of all the load abilities that allows me to load an unit in a transport instantly without changing facing or something of the other.
 
Level 7
Joined
Dec 3, 2006
Messages
339
Understandable I guess; but seems silly, i mean technically it is an "unit event" (a unit loading another unit). I guess the only reasonable way would be to code it all into the Extension[UnitEvent]. But if Nes isn't going to do it I guess i'll just make my own version for my map.
 
Top