First, don't screenshot triggers; do this:
How To Post Your Trigger
Second your objective is not clear to me from your description or the error you have encountered. Are you trying to make every player fight every other player in sequence (like a round-robin pattern) or do you just want to randomize pairs of players to battle until all players have been given a pair or a bye? Why are even numbers involved; what is their purpose? Are there teams and you should only fight players from other teams (that's not usually how Autobattlers work but I'm trying to understand the even player numbers thing)? What happens if there are an odd number of players so one player gets a bye?
Overall you're doing a bunch of things here that don't make sense and are actively preventing the solution you've written from 'working'. Consider the logic of looping over the players, randomizing a player each time, and then only doing something if the random player matches the player that you're currently using for iteration. What if they don't match? Nothing happens and the process moves on to the next player in the iteration. Your placement trigger doesn't make pairs of players fight but instead either creates 2 battles for each player-player pair (one at each home location) or actually moves everyone's army to their opponent's location while moving the opponent too so there's no actual fighting happening. Rather than try to fix your logic, truly I think it's better just to start over with a clearer understanding of your goals and the process you will use to achieve them.
One more important thing to mention before I show how I would approach this problem:
the first line where you set fakePlayergroup = activePlayers does not create a copy of the unit group at all! It simply assigns a second variable (with a different name, yes) to point to the
same group that already existed. You know intuitively know that it works this way with units, and the logic applies the same with all other handle type variables. Consider this scenario:
-
Unit - Create 1 Footman for Player 1 (Red) at SomePoint facing SomeDegrees
-
Set UnitVar = (Last created unit)
-
Set OtherUnitVar = UnitVar
-
-------- how many units are there now? one or two? one! two variables point to the same unit, but the unit is not duplicated by the existence of the variables --------
-
-------- later: -------
-
Unit - Kill OtherUnitVar
-
-------- so is UnitVar dead now? Yes, because the variable OtherUnitVar also pointed to it and then the unit that it pointed to was killed. which was the same unit --------
What this means in your scenario is that the
activePlayers group is slowly depleted of all the players in it over time as various
randomPlayers are removed from
fakePlayerGroup... which is really the same group! While it's not too difficult to clone many objects in wc3, it can be a little annoying with Player and Unit groups because they're kind of a meta-object that holds other objects as a collective: you have to
rebuild the new group by re-adding all the correct players. In GUI there does exist a command to do this with unit groups:
-
Unit Group - Add all units of SOURCE to DESTINATION
...but an equivalent command does not exist for player groups. In order to make a 'copy' of a player group that some variable points to, you'll have to loop over it and add all players manually to a different group. Usually you'll want to clear the destination group first:
-
Player Group - Remove all players from DESTINATION //this is NOT the same as destroying the player group with DestroyForce
-
Player Group - Pick every player in SOURCE and do (Actions)
-

Loop - Actions
-


Player Group - Add (Picked Player) to DESTINATION
Okay so how would I do this? I assume you want to randomize pairs of players within activePlayers, if there's one left over there's a bye, and then to do something with those pairs. Strategic use of variables and indexing information by player-number will help you significantly here.
-
Player Group - Remove all players from battleGroup
-
Player Group - Pick every player in activePlayers and do (Actions)
-

Loop - Actions
-


Player Group - Add (Picked Player) to battleGroup //you could exclude a specific player from battling at this stage if you know there are an odd number and you want to give the bye to someone intentionally instead of random
-
Set battleCount = ((Number of players in battleGroup) / 2) //you want this to stay as integer division so it truncates: if there are 5 people there should be 5/2 = 2 battles)
-
For each (Integer A) from 1 to battleCount do (Actions)
-

Loop - Actions
-


Set battleP1[(Integer A)] = (Random player from battleGroup)
-


Player Group - Remove battleP1[(Integer A)] from battleGroup
-


Set battleP2[(Integer A)] = (Random player from battleGroup)
-


Player Group - Remove battleP2[(Integer A)] from battleGroup
-
Set battleBye = (Random player from battleGroup) //this either returns the one remaining player who should get a bye or returns null because there is no bye player, so we can check later if it's null or not to see if a bye should happen
After this trigger runs, the arrays are populated with the pairs of battles (not including the bye player if it should occur). You will still then have to translate this information into actually doing something. Based on what I can see above you have precached an enemy teleport point and a home point for each player, so I would do something like this:
-
For each (Integer A) from 1 to battleCount do (Actions)
-

Loop - Actions
-


Set PID1 = (Player Number of (battleP1[(Integer A)]))
-


Set PID2 = (Player Number of (battleP2[(Integer A)]))
-


Custom script: set bj_wantDestroyGroup = true
-


Unit Group - Pick every unit in (Units in playerZone[PID2]) and do (Actions)
-



Loop - Actions
-




Set TempPoint = (enemyTeleportPoint[PID1] offset by (diffCalculatorToUnitPosX[(Custom value of (Picked Unit))], diffCalculatorToUnitPosY[(Custom value of (Picked Unit))])) //this is "point with offset" which does occasionally have a use as seen here
-




Unit - Move (Picked Unit) instantly to TempPoint
-




Custom script: call RemoveLocation(udg_TempPoint) //change name to match your variable but keep the udg_ prefix; capitalization matters
-
If (All conditions are true) then do (Then actions) else do (Else actions)
-

If - Conditions
-


battleBye not equal to (Picked Player) //THIS IS A NONSTANDARD USE OF PICKED PLAYER HERE, SO PLEASE UNDERSTAND WHAT IT IS DOING. GUI doesn't have the ability to put "null" or "no player" in a condition like this, so the best thing you can do is to pick a function/expression that will evaluate to null instead. That is why I have used Picked Player here: specifically BECAUSE it does not work in this context (outside a player group block it returns null)
-

Then - Actions
-


-------- if we get here there was a bye that was supposed to happen --------
-

Else - Actions
-


-------- if we get here there was no bye --------