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

Is GetUnitsSelectedAll(<player>) asynchronous ?

Status
Not open for further replies.
Level 12
Joined
Feb 27, 2019
Messages
399
Hello,

I made the following trigger (I use damage engine, the final purpose is to use healing potion automatically to save the hero under some conditions).

  • AutoPotionOfGreaterHealing
    • Events
      • Game - DamageEvent becomes Equal to 1.00
    • Conditions
      • ((Owner of DamageEventTarget) is in ConnectedPlayers.) Equal to True
      • (DamageEventTarget is A Hero) Equal to True
      • (DamageEventTarget is paused) Equal to False
      • (DamageEventTarget has an item of type Potion of Greater Healing) Equal to True
      • DamageEventAmount Greater than or equal to (Life of DamageEventTarget)
    • Actions
      • Custom script: local unit udg_LocalTempUnit = udg_DamageEventTarget
      • Custom script: local player udg_LocalTempPlayer = GetOwningPlayer(udg_LocalTempUnit)
      • Custom script: local group udg_LocalTempGroup
      • -------- Check if player selection is shop(s) --------
      • // Set VariableSet LocalTempGroup = (Units currently selected by LocalTempPlayer) // Would execute right and save from death
      • Set VariableSet LocalTempGroup = (Units currently selected by LocalTempPlayer)
      • Hero - Order LocalTempUnit to use (Item carried by LocalTempUnit of type Potion of Greater Healing) // Would not save the unit from death ???
      • [...] // Other unrelevant code for this post
      • Custom script: call DestroyGroup(udg_LocalTempGroup)
      • Custom script: set udg_LocalTempGroup = null
      • Custom script: set udg_LocalTempPlayer = null
      • Custom script: set udg_LocalTempUnit = null
What is akward is that:
- "Hero - Order Hero <> to use item <>" works fine and saves the unit from dying if I place it before the line "Set VariableSet LocalTempGroup = (Units currently selected by LocalTempPlayer)".
- In the opposite, if I place it after this line, the unit dies.

WTF ???
Is GetUnitsSelectedAll primitive actually asynchronous, with a hidden wait somewhere in its code ??
 
Level 13
Joined
May 10, 2009
Messages
868
(Units currently selected by X) is slow af and, IIRC, hangs the thread until it synchronizes selection among players. You'd better off creating a constant unit group for each possible player and add/remove units with the selection events.
 
Level 12
Joined
Feb 27, 2019
Messages
399
(Units currently selected by X) is slow af and, IIRC, hangs the thread until it synchronizes selection among players. You'd better off creating a constant unit group for each possible player and add/remove units with the selection events.

Oh it is the "syncselections()" thing ?
It pauses the thread, synchronize over network, then resume the thread ?

If I listen select/unselect events & register 1 unit-group per player for selected units, theoretically I won't have desync issues in multi-player games ?


Tracking myself selected/unselected units would be a bit bothersome, since I've to track all those events: player X selects a unit, player X unselects a unit, unit is removed (deindexed) ?

And maybe (if they don't fire a unselect event): unit dies, unit acquires ability Aloc, unit is hidden..
 
Last edited:
Level 13
Joined
May 10, 2009
Messages
868
Oh it is the "syncselections()" thing ?
It pauses the thread, synchronize over network, then resume the thread ?
Yes.

If I listen select/unselect events & register 1 unit-group per player for selected units, theoretically I won't have desync issues in multi-player games ?
Correct, as those events are already synchronized.

Tracking myself selected/unselected units would be a bit bothersome, since I've to track all those events: player X selects a unit, player X unselects a unit, unit is removed (deindexed) ?
I don't think this part is difficult at all because once a unit is removed/dies/hides, the events fire as they should.
 
Level 12
Joined
Feb 27, 2019
Messages
399
Mhh with Bribe's "Unit Event" system (including "Unit in Action") I can do this vjass system then:

JASS:
library UnitSelection

    globals
        private trigger playerSelectUnitTrigger
        private trigger playerDeselectUnitTrigger
        private trigger unitInactionTrigger
    endglobals

    function onPlayerSelectUnit takes nothing returns boolean
        local player p = GetTriggerPlayer()
        local integer pIndex = GetConvertedPlayerId(p)
        local unit u = GetTriggerUnit()
        local boolean b = IsUnitInGroup(u, udg_Selections[pIndex])
        if (not b) then
            call GroupAddUnitSimple(u, udg_Selections[pIndex])

            // Fire a unit selection event
            set udg_UnitSelectionPlayerId = pIndex
            set udg_UnitSelectionEvent = 0.00
            set udg_UnitSelectionEvent = 1.00
            set udg_UnitSelectionEvent = 0.00
            set udg_UnitSelectionPlayerId = 0
        endif
        set u = null
        set p = null
        return false
    endfunction

    function onPlayerDeselectUnit takes nothing returns boolean
        local player p = GetTriggerPlayer()
        local integer pIndex = GetConvertedPlayerId(p)
        local unit u = GetTriggerUnit()
        local boolean b = IsUnitInGroup(u, udg_Selections[pIndex])
        if (b) then
            call GroupRemoveUnitSimple(u, udg_Selections[pIndex])

            // Fire a unit deselection event
            set udg_UnitSelectionPlayerId = pIndex
            set udg_UnitSelectionEvent = 0.00
            set udg_UnitSelectionEvent = 2.00
            set udg_UnitSelectionEvent = 0.00
            set udg_UnitSelectionPlayerId = 0
        endif
        set u = null
        set p = null
        return false
    endfunction

    function onUnitInaction takes nothing returns boolean
        local integer pIndex
        local integer pCount = GetPlayers()
        local unit u = udg_UDexUnits[udg_UDex]
        local boolean b
        set pIndex = 1
        loop
            set b = IsUnitInGroup(u, udg_Selections[pIndex])
            if (b) then
                call GroupRemoveUnitSimple(u, udg_Selections[pIndex])
                // Fire a unit deselection event
                set udg_UnitSelectionPlayerId = pIndex
                set udg_UnitSelectionEvent = 0.00
                set udg_UnitSelectionEvent = 2.00
                set udg_UnitSelectionEvent = 0.00
                set udg_UnitSelectionPlayerId = 0
            endif
            set pIndex = pIndex + 1
            exitwhen pIndex > pCount
        endloop
        set u = null
        return false
    endfunction

    // ----------------------------------------------------------------------------
    // onInit: system initializer
    // ----------------------------------------------------------------------------
    private module M
        private static method onInit takes nothing returns nothing
            local integer index
            local integer playerCount = GetPlayers()
            set playerSelectUnitTrigger = CreateTrigger()
            set playerDeselectUnitTrigger = CreateTrigger()
            set unitInactionTrigger = CreateTrigger()

            set index = 1
            loop
                set udg_Selections[index] = CreateGroup()
                call TriggerRegisterPlayerSelectionEventBJ( playerSelectUnitTrigger, ConvertedPlayer(index), true )
                call TriggerRegisterPlayerSelectionEventBJ( playerDeselectUnitTrigger, ConvertedPlayer(index), false )
                set index = index + 1
                exitwhen index > playerCount
            endloop
            call TriggerRegisterVariableEvent( unitInactionTrigger, "udg_UnitInActionEvent", EQUAL, 2.00 )

            call TriggerAddCondition(playerSelectUnitTrigger, Condition(function onPlayerSelectUnit))
            call TriggerAddCondition(playerDeselectUnitTrigger, Condition(function onPlayerDeselectUnit))
            call TriggerAddCondition(unitInactionTrigger, Condition(function onUnitInaction))
        endmethod
    endmodule
    private struct S extends array
        implement M
    endstruct

endlibrary
 
Status
Not open for further replies.
Top