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

Who is controlling the unit?

Status
Not open for further replies.
Level 2
Joined
Apr 24, 2015
Messages
19
Hey!
Is there any way, through triggers or any means, to be able to tell which player is giving a shared unit commands?

For example:
A player in a team of 10 players leaves and thus their control is shared to all 9 remaining allies. Then one of these people commands the units to attack each other or other allies. Is there any way through triggers to tell who is giving the units these commands?
 
Level 39
Joined
Feb 27, 2007
Messages
4,994
Not explicitly, no. There are, however, new mouseclick natives in 1.30 that could probably be used for this purpose, but I have 0 experience using those. The only other partial solution is that you can check which players have that particular unit selected at the instant it is issued the order, but if multiple people have it selected that method is inconclusive.
 
Had a quick go at this. Mouse click events seem to have priority over unit orders, so something like this should work for all click-based orders:
JASS:
//! zinc
library ClickOrderTest {

    // =============================================================================================

    // Unit order trigger actions.
    private function OrderTrigAction() {
        player p;
     
        // If we're currently listening to unit orders, fetch the clicking player.
        if (Listen) {
            p = ListenPlayer;
         
            // ***********************
            // Ordering player is p
            // Do whatever with p here
            // ***********************
         
            // Debug
            BJDebugMsg("[|cFF50FF50" + I2S(GetTriggerExecCount(GetTriggeringTrigger())) + "|r] |cFFFF0000" + GetPlayerName(p) + "|r (|cFF5050FF" + OrderId2String(GetIssuedOrderId()) + "|r)");
            p = null;
        }
    }
 
    // =============================================================================================
 
    // Trigger variables. Useless comments.
    private trigger MouseTrig = CreateTrigger();
    private trigger OrderTrig = CreateTrigger();
 
    // Unit order listen variables.
    private boolean Listen       = false;
    private player  ListenPlayer = null;
    private timer   ListenTimer  = CreateTimer();
 
    // =============================================================================================
 
    // Timer handler.
    // Stops listening for unit orders.
    private function ListenHandler() {
        Listen = false;
        ListenPlayer = null;
    }
 
    // Mouse click trigger actions.
    // Starts listening for unit orders on the current frame.
    private function MouseTrigAction() {
        ListenPlayer = GetTriggerPlayer();
        Listen = true;
        TimerStart(ListenTimer, 0, false, function ListenHandler);
    }
 
    // Initializer function.
    private function onInit() {
        // Set up mouse click trigger.
        TriggerRegisterPlayerEvent(MouseTrig, Player(0), EVENT_PLAYER_MOUSE_DOWN);
        TriggerAddAction(MouseTrig, function MouseTrigAction);
     
        // Set up unit order trigger.
        TriggerRegisterAnyUnitEventBJ(OrderTrig, EVENT_PLAYER_UNIT_ISSUED_ORDER);
        TriggerRegisterAnyUnitEventBJ(OrderTrig, EVENT_PLAYER_UNIT_ISSUED_POINT_ORDER);
        TriggerRegisterAnyUnitEventBJ(OrderTrig, EVENT_PLAYER_UNIT_ISSUED_TARGET_ORDER);
        TriggerAddAction(OrderTrig, function OrderTrigAction);
    }
}
//! endzinc
If you'd prefer, a GUI version based on this should be pretty straight forward.

EDIT: Added triggers

Variables:
COT_Player (Player)
COT_Listen (Boolean)
COT_Timer (Timer)


  • Unit Order
    • Events
      • Unit - A unit Is issued an order targeting an object
      • Unit - A unit Is issued an order targeting a point
      • Unit - A unit Is issued an order with no target
    • Conditions
      • COT_Listen Equal to True
    • Actions
      • -------- The variable COT_Player holds the ordering player --------
      • Game - Display to (All players) the text: (|cFFFF0000 + ((Name of COT_Player) + |r is the ordering player!))
  • Mouse Click
    • Events
      • Player - Player 1 (Red) issues Mouse Down event
    • Conditions
    • Actions
      • Set COT_Player = (Triggering player)
      • Set COT_Listen = True
      • Countdown Timer - Start COT_Timer as a One-shot timer that will expire in 0.00 seconds
  • Timer Handler
    • Events
      • Time - COT_Timer expires
    • Conditions
    • Actions
      • Set COT_Listen = False
 

Attachments

  • ClickOrderTest.w3x
    30.7 KB · Views: 44
Last edited:
Level 15
Joined
Aug 14, 2007
Messages
936
@nicolas97p Alternatively, however, you are able to use unit selection trigger to check for selected unit.

If (Unit currently selected by player 1 and player priority is player 1[assuming this is an integer]) then
do actions
Player 1 gains control of unit (Change owner to Player 1)
Change priority of player shared control to player 2 (Set integer variable priorityplayer to 2)
else if (player 2)
...
else if (player 3)
.....

else if (Unit currently selected by player 12 and player priority is player 12) then
do actions
Player 12 gains control of unit (Change owner to Player 12)
Change priority of player shared control to player 1 (Set integer variable priorityplayer to 1, it goes in a loop, you can use periodic event to limit this as well, managing event for this loop action is important)

With this system you get a fair player share and also accurately know which players are currently selecting that unit. This is also very lag-free as order triggers tend to use a lot of codes in the trigger.
 
Level 2
Joined
Apr 24, 2015
Messages
19
It's a good idea @Acutesharpness but unfortunately it doens't work for the maps I'm gonna use it for. Due to limits of units you can own of a specific type. This limit would then be able to bypassed in that case. Thanks for the tip though! This is how I ended up doing it if it would help anyone.
 

Attachments

  • Who_is_controlling.w3x
    43.2 KB · Views: 22
Level 39
Joined
Feb 27, 2007
Messages
4,994
I found some emergent problems you need to address
I guess you never got the memo that saying things without providing an example or test map or detailed description really doesn't help anyone. What "emergent problems"?
don't use melee initialization event, instead use time elapse 0.01 second
You are correct that it is generally better to run at elapsed time > 0 rather than map init. However, this is really only relevant for libraries and scopes with initializers that may rely on other libraries/scopes to do something before their init section runs, since you only have rudimentary control with the requires keyword and all initializers are run in new threads via ExecuteFunc(). From the JASSHelper manual: "it will make it be executed with priority using ExecuteFunc , ExecuteFunc is forced so it uses another thread, most libraries require heavy operations on init so we better prevent the init thread from crashing." GUI trigger init event is called dead last in the entire order of things and doesn't use ExecuteFunc() so they don't have this problem. The only real issue with GUI using MapInit events is if there are too many operations and you reach the op limit causing a thread crash.
 
Status
Not open for further replies.
Top