• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Help with Variable for Player Group

In need of help!

The goal is to make that any of the desired players (1 to 4) when nearby, be able to rescue the following units:

1735934120575.png


So I have tried to create a variable group for the 4 players, but only PLAYER 1 is able to rescue the units, for the rest (2, 3 and 4) it dnst work..

1735933986395.png



Can someone give me a hint on how to fix it?
 
Level 30
Joined
Aug 29, 2012
Messages
1,382
Nevermind, I think I see what's wrong. Make your player group variable as an array, and try like this

  • Actions
    • Player Group - Add Player 1 (Red) to PlayerGroup[1]
    • Player Group - Add Player 2 (Blue) to PlayerGroup[2]
    • Player Group - Add Player 3 (Teal) to PlayerGroup[3]
    • Player Group - Add Player 4 (Purple) to PlayerGroup[4] // Define those at map init
And then

  • For each (Integer A) from 1 to 4, do (Actions)
    • Loop - Actions
      • Unit - Make Footman 0000 <gen> Rescuable by PlayerGroup[(Integer A)]
      • Unit - Make Rifleman 0001 <gen> Rescuable by PlayerGroup[(Integer A)]
      • // etc.
Because you're using a loop with integer A but the integer A isn't used for anything. Besides, I suspect a player group can only contain 1 player (this is some 300 IQ logic) hence store each player separately with the array
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
Are you perhaps checking the Heavy Infantry 1206 specifically? In the code I see above that particular unit is only rescuable by Player 1, but the others would be rescuable by all 4 players. My other thought is that you could be doing this all in the wrong order? The player group likely needs to be set before the units are made rescuable.
 
Are you perhaps checking the Heavy Infantry 1206 specifically? In the code I see above that particular unit is only rescuable by Player 1, but the others would be rescuable by all 4 players. My other thought is that you could be doing this all in the wrong order? The player group likely needs to be set before the units are made rescuable.
I have tried with all 3 units, 1207, 1145 and 1206;

And the order is correct, MIni for player groups and elapsed game time for rescuable units.

I'm 100% lost here
 
Just glossed over this, but the Player Group arrays may need to be initialized. Set their Size to a high enough number in the Variable editor, 24 should cover every Player. Same holds true for any Unit Group arrays (assuming they use Player Numbers as the [index].
Trying to fix this the entire day, no sucess.... If you have some time avaliable @Uncle, could you try to make a trigger that make this works?
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
Trying to fix this the entire day, no sucess.... If you have some time avaliable @Uncle, could you try to make a trigger that make this works?
Are you testing this in the editor? I think it only works with actual Users in a match.

You can launch multiple clients of Warcraft 3 through the BNET app and play LAN against yourself to find out.

Edit: Actually, I just remembered that I helped someone with this problem somewhat recently. I think it's bugged, here's a workaround:
 
Level 24
Joined
Feb 27, 2019
Messages
833
Trying to fix this the entire day, no sucess.... If you have some time avaliable @Uncle, could you try to make a trigger that make this works?
Bit of advice from a link from Uncles signature: How To Post Your Trigger

This works to add players to a player group:
  • For each (Integer A) from 1 to 4, do (Actions)
    • Loop - Actions
      • Player Group - Add (Player((Integer A))) to PlayerGroup
You really hit all the mines on minesweeper. What didnt work was set playergroup in conjunction with add/remove and as fore mentioned arrays need to be initialized which was after going down that rabbit hole with arrays. Hopefully there isnt another mine that im missing here, that would be really... unfortunate.
 
Level 45
Joined
Feb 27, 2007
Messages
5,578
Duck I have no idea what the heck you are saying (aside from arrays obviously not helping at all here). Look back at the screenshots in the first post. That's not an array so the force can't be uninitialized (and we see it being assigned a value directly), and then players 1-4 are added to it (player 1 already was in it). That should work if it's happening before the rescue actions.

The only thing that makes sense is the force being destroyed or the variable being assigned a new value in another trigger.
 
Level 24
Joined
Feb 27, 2019
Messages
833
Yeah Pyro, that was a bit of a scrambled text I wrote. I was trying to respond to two different issues with both the first screenshot, non array, and the mentioned array.

My point should have only been that these actions cant be used in conjunction with each other.
  • Set VariableSet FORCExFourCities = Player Group - Player 1 (Red)
  • Player Group - Add Player 1 (Red) to FORCExFourCities
Either or must be used, not both. If its set, players cant be added. It appears it should work and I dont know the specifics of why it doesnt.
 
Level 29
Joined
Sep 26, 2009
Messages
2,595
You guys mistakenly think the issue is with player group(s) and their initialization, but the real issue is that rescue behavior only works for player 1 red.
I've been testing this now in empty map and that is the conclusion I've reached.

What I've tried:
  • I created 4 footmen who will be the rescuable units
  • I created 4 Paladins, each for different player (red, blue, teal, purple) and checked who can rescue those footmen
then I ran following two tests:

I've set up a player group with players 1-4 and then used the gui action to make each footmen rescuable by that player group. I've double checked that the player group does indeed contain those 4 players via debug triggers.
  • Actions
    • Player Group - Add Player 1 (Red) to PG
    • Player Group - Add Player 2 (Blue) to PG
    • Player Group - Add Player 3 (Teal) to PG
    • Player Group - Add Player 4 (Purple) to PG
    • Set VariableSet RescuableUnits[1] = Footman 0000 <gen>
    • Set VariableSet RescuableUnits[2] = Footman 0001 <gen>
    • Set VariableSet RescuableUnits[3] = Footman 0002 <gen>
    • Set VariableSet RescuableUnits[4] = Footman 0003 <gen>
    • For each (Integer A) from 1 to 4, do (Actions)
      • Loop - Actions
        • Unit - Make RescuableUnits[(Integer A)] Rescuable by PG

The action
  • Unit - Make some_unit Rescuable by player_group
is a function from Blizzard.j file so I've checked its implementation here Doc - MakeUnitRescuableToForceBJ and recreated those triggers in more explicit manner without using any player groups.
The rescue trigger:
  • Rescue
    • Events
      • Unit - A unit Is rescued
    • Conditions
    • Actions
      • Custom script: set udg_RescuingPlayer = GetOwningPlayer(GetRescuer())
      • Unit - Rescue (Triggering unit) for RescuingPlayer and Change color
and Map init trigger:
  • Actions
    • Set VariableSet RescuableUnits[1] = Footman 0000 <gen>
    • Set VariableSet RescuableUnits[2] = Footman 0001 <gen>
    • Set VariableSet RescuableUnits[3] = Footman 0002 <gen>
    • Set VariableSet RescuableUnits[4] = Footman 0003 <gen>
    • For each (Integer A) from 1 to 4, do (Actions)
      • Loop - Actions
        • For each (Integer B) from 0 to 3, do (Actions)
          • Loop - Actions
            • Custom script: call SetUnitRescuable(udg_RescuableUnits[GetForLoopIndexA()], Player(GetForLoopIndexB()), bj_makeUnitRescuableFlag)


Both of these tests were working only for player 1 red.
  • Note that I've tried to run setup/init triggers using both "Map initialization" event as well as "Time - Elapsed game time is 1.00 seconds" event and there was no difference in results.
  • I configured player slots so that there are 4 User-controlled slots for players 1-4. Only player 1 was able to rescue no matter which player slot I was using
  • I configured player slots so that only player 2 blue is user-controlled slot, while player 1, 3 and 4 are computer controlled slots. Only player 1 was able to rescue
  • I configured player slots so that only player 2 blue is user-controlled slot, all remaining slots are set to None. Again, only player 1 was able to rescue.
  • I tried these configurations while setting footmen as Neutral Passive as well as Player 6 Orange and there was no difference in results.

The only way I got this to work was to use 'Unit within range' event like so:
  • Rescue Unit 0000
    • Events
      • Unit - A unit comes within 384.00 of Footman 0000 <gen>
    • Conditions
    • Actions
      • Trigger - Turn off (This trigger)
      • Unit - Rescue Footman 0000 <gen> for (Owner of (Triggering unit)) and Change color
This circumvents the "Unit - Make some_unit Rescuable by player_group" action since I check distance manually and then manually rescue unit via 'Unit - Rescue unit' action.
The annoying thing is that each rescuable unit needs its own such trigger. Doing that via GUI for many units will be a nightmare. But doing it via JASS and dynamically generating those triggers could be a good solution.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
You guys mistakenly think the issue is with player group(s) and their initialization, but the real issue is that rescue behavior only works for player 1 red.
I've been testing this now in empty map and that is the conclusion I've reached.

The only way I got this to work was to use 'Unit within range' event like so:
  • Rescue Unit 0000
    • Events
      • Unit - A unit comes within 384.00 of Footman 0000 <gen>
    • Conditions
    • Actions
      • Trigger - Turn off (This trigger)
      • Unit - Rescue Footman 0000 <gen> for (Owner of (Triggering unit)) and Change color
This circumvents the "Unit - Make some_unit Rescuable by player_group" action since I check distance manually and then manually rescue unit via 'Unit - Rescue unit' action.
The annoying thing is that each rescuable unit needs its own such trigger. Doing that via GUI for many units will be a nightmare. But doing it via JASS and dynamically generating those triggers could be a good solution.
I linked a solution in my last post that relies on unit groups and periodic distance checks. Should be better than having to rely on 1 trigger per unit.
 

Uncle

Warcraft Moderator
Level 73
Joined
Aug 10, 2018
Messages
7,866
I've been using rescuable units by player 15 in my map without issue, the issue has to be somewhere else
But what do you mean exactly? The goal is to allow multiple players (assumedly Users) be able to rescue Player 15's units.

Getting Player 1 to do it works fine, it's getting the other Users to do it as well that's the problem.
 
Level 30
Joined
Aug 29, 2012
Messages
1,382
Welp after a few tests I'd say that an unit can only be rescued by one player at a time (unless having shared unit control somehow causes problems), this works only for red

  • Unit - Make Rifleman 0003 <gen> Rescuable by Player Group - Player 1 (Red)
  • Unit - Make Rifleman 0003 <gen> Rescuable by Player Group - Player 2 (Blue)
But this works for blue

  • Unit - Make Rifleman 0003 <gen> Rescuable by Player Group - Player 2 (Blue)
  • Unit - Make Rifleman 0003 <gen> Rescuable by Player Group - Player 1 (Red)
And this works for red only :'D

  • Unit - Make Rifleman 0003 <gen> Rescuable by (All players)
Figures >_< You learn something everyday I guess
 
Level 29
Joined
Sep 26, 2009
Messages
2,595
@Chaosium that's nice find. I did not try to change the order of players when registering those units as rescuable.
I thought that perhaps the issue could be that if for example two players could rescue same unit, and both players would be within rescue range of that unit, then it would change the ownership between the two over and over, since "Unit - Rescue Unit" action checks only if rescue player != owning player.
But that does not seem to be the case: I rescued unit, via trigger I changed its ownership back to Neutral Passive and then got back again within rescue range and it no longer changed the owner.

Seems like this is simply bug in wc3 engine :)

Anyway, I also tried the option of using multiple "Unit within range" triggers created dynamically via jass. I've put 100 footmen in the map and noticed a drop of about 2-3 fps. I didn't check how it fares against Uncle's solution where he periodically checks each rescuable unit.
The script is here for anyone interested:

vJASS:
library RescueUnits

    globals
        private constant hashtable DataTable = InitHashtable()
        private constant integer KeyTrigger = 1
        private constant integer KeyUnit = 2
        private constant integer KeyPlayers = 3
        private constant real RescueRange = 284.00

        private force Allowed = null
    endglobals

    private function ClearUnitRescueData takes unit whichUnit returns nothing
        local integer handleId = GetHandleId(whichUnit)
        local trigger trg = LoadTriggerHandle(DataTable, handleId, KeyTrigger)
        local integer trgId = GetHandleId(trg)
        local force players = LoadForceHandle(DataTable, trgId, KeyPlayers)

        call FlushChildHashtable(DataTable, handleId)
        call FlushChildHashtable(DataTable, trgId)

        call DestroyForce(players)
        call DestroyTrigger(trg)

        set trg = null
        set players = null
    endfunction

    private function RescueTriggerActions takes nothing returns nothing
        local integer handleId = GetHandleId(GetTriggeringTrigger())
        local player rescuer = GetOwningPlayer(GetTriggerUnit())
        local unit rescuableUnit

        if IsPlayerInForce(rescuer, LoadForceHandle(DataTable, handleId, KeyPlayers)) then
            set rescuableUnit = LoadUnitHandle(DataTable, handleId, KeyUnit)
            call RescueUnitBJ(rescuableUnit, rescuer, true)
            call ClearUnitRescueData(rescuableUnit)
        endif

        set rescuer = null
        set rescuableUnit = null
    endfunction

    private function AddRescueForce takes nothing returns nothing
        call ForceAddPlayer(Allowed, GetEnumPlayer())
    endfunction

    private function AddRescuePlayers takes trigger t, force allowedPlayers returns nothing
        set Allowed = LoadForceHandle(DataTable, GetHandleId(t), KeyPlayers)
        call ForForce(allowedPlayers, function AddRescueForce)
        set Allowed = null
    endfunction
  
    private function CreateRescuableUnitTrigger takes unit rescuableUnit, force allowedPlayers returns nothing
        local trigger trg = CreateTrigger()
        local integer trgId = GetHandleId(trg)

        set Allowed = CreateForce()
        call ForForce(allowedPlayers, function AddRescueForce)

        call TriggerRegisterUnitInRangeSimple(trg, RescueRange, rescuableUnit)
        call TriggerAddAction(trg, function RescueTriggerActions)

        call SaveUnitHandle(DataTable, trgId, KeyUnit, rescuableUnit)
        call SaveForceHandle(DataTable, trgId, KeyPlayers, Allowed)
        call SaveTriggerHandle(DataTable, GetHandleId(rescuableUnit), KeyTrigger, trg)

        set trg = null
        set Allowed = null
    endfunction

    function MakeUnitRescueable takes unit rescuableUnit, force allowedPlayers returns nothing
        local trigger t = LoadTriggerHandle(DataTable, GetHandleId(rescuableUnit), KeyTrigger)
        if t == null then
            call CreateRescuableUnitTrigger(rescuableUnit, allowedPlayers)
        else
            call AddRescuePlayers(t, allowedPlayers)
        endif
        set t = null
    endfunction

    function ClearRescueData takes unit whichUnit returns nothing
        call ClearUnitRescueData(whichUnit)
    endfunction
endlibrary

Usage looked like this:
  • Map Init
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Player Group - Add Player 1 (Red) to rescuePlayers
      • Player Group - Add Player 2 (Blue) to rescuePlayers
      • Player Group - Add Player 3 (Teal) to rescuePlayers
      • Unit Group - Pick every unit in (Units of type Footman) and do (Actions)
        • Loop - Actions
          • Custom script: call MakeUnitRescueable( GetEnumUnit(), udg_rescuePlayers )
  • Unit Dies
    • Events
      • Unit - A unit Dies
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Footman
    • Actions
      • Custom script: call ClearRescueData( GetTriggerUnit() )
 
Top