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

Getting the player number of owning player

Status
Not open for further replies.
Level 8
Joined
Jul 29, 2010
Messages
319
I'm making a TD, I have 14 lanes, 1 per player, there is a region for each lane which covers the entirety of said lane, there is a region at the end of each lane which is the final stop for the creeps that will be running through the lanes, I'm trying to develop a trigger which when a unit enters the final region of a lane, it will get the player number of the player who has units in that lane. I also need that trigger to check if there are multiple players units in that lane at the time and check which player has the most units in that lane, this is just a failsafe in case for whatever reason a players builder just happens to wander into another players lane, so far I've tried all sorts of triggers such as
  • Unit enters portal
    • Events
      • Unit - A unit enters Lane 1 Portal <gen>
      • Unit - A unit enters Lane 2 Portal <gen>
      • Unit - A unit enters Lane 3 Portal <gen>
      • Unit - A unit enters Lane 4 Portal <gen>
      • Unit - A unit enters Lane 5 Portal <gen>
      • Unit - A unit enters Lane 6 Portal <gen>
      • Unit - A unit enters Lane 7 Portal <gen>
      • Unit - A unit enters Lane 8 Portal <gen>
      • Unit - A unit enters Lane 9 Portal <gen>
      • Unit - A unit enters Lane 10 Portal <gen>
      • Unit - A unit enters Lane 11 Portal <gen>
      • Unit - A unit enters Lane 12 Portal <gen>
      • Unit - A unit enters Lane 13 Portal <gen>
      • Unit - A unit enters Lane 14 Portal <gen>
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of (Triggering unit)) Equal to Player 21 (Coal)
        • Then - Actions
          • -------- Player --------
          • For each (Integer A) from 1 to 14, do (Actions)
            • Loop - Actions
              • -------- Region --------
              • For each (Integer B) from 1 to 14, do (Actions)
                • Loop - Actions
                  • Unit Group - Pick every unit in (Units in (Load (Integer B) of 7 in CONSTANT_Hashtable) owned by (Player((Integer A)))) and do (Actions)
                    • Loop - Actions
                      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                        • If - Conditions
                          • And - All (Conditions) are true
                            • Conditions
                              • ((Load (Integer B) of 8 in CONSTANT_Hashtable) contains (Triggering unit)) Equal to True
                              • ((Load (Integer B) of 7 in CONSTANT_Hashtable) contains (Picked unit)) Equal to True
                        • Then - Actions
                          • Set NumberOfLives[(Integer A)] = (NumberOfLives[(Integer A)] - 1)
                          • Game - Display to (Player group((Player((Integer A))))) for 0.25 seconds the text: (|c00FFFF00You have + ((String(NumberOfLives[(Integer A)])) + lives left.|r))
                        • Else - Actions
        • Else - Actions
 
Level 39
Joined
Feb 27, 2007
Messages
5,019
You could do this with a hashtable if you want, or with 2 parallel arrays. There is no need to worry about builders in other lanes with either method. For the hashtable method whenever you create a runner unit you would save into the hashtable the player that should lose lives if that unit makes it to the 'end':
  • -------- on unit create --------
  • Hashtable - Save YourPlayerVariableHoweverYouKnowWhichPlayerItShouldBe as "lifeloser" of Key(last created unit) in CONSTANT_Hashtable
  • -------- on unit death --------
  • Hashtable - Clear all child hashtables of child (Key (Triggering Unit)) in CONSTANT_Hashtable
  • -------- on unit enters region --------
  • Set LosingPlayer = Load "lifeloser" of Key(Triggering Unit)) in CONSTANT_Hashtable
  • Hashtable - Clear all child hashtables of child (Key (Triggering Unit)) in CONSTANT_Hashtable
With parallel arrays you would need to check the region the unit is in against some pre-stored variables:
  • -------- on map init set these --------
  • Set LifePlayers[1] = Player 1 (Red)
  • Set LifeRegion[1] = Lane 1 Portal <gen>
  • Set LifePlayers[2] = Player 2 (Blue)
  • Set LifeRegion[2] = Lane 2 Portal <gen>
  • ..
  • Set LifePlayers[14] = Player 14 (idk the color)
  • Set LifeRegion[14] = Lane 14 Portal <gen>
  • -------- On entering a region like you have above --------
  • For each (Integer A) from 1 to 14 do (Actions)
    • Loop - Actions
      • If (All conditions are true) then do (Then actions) else do (Else actions)
        • If - Conditions
          • LifeRegion[(Integer A)] contains (Triggering Unit) equal to true
        • Then - Actions
          • Set LosingPlayer = LifePlayers[(Integer A)]
          • Custom script: exitwhen true //not necessary to have this, just more efficient
        • Else - Actions
 
Level 8
Joined
Jul 29, 2010
Messages
319
You could do this with a hashtable if you want, or with 2 parallel arrays. There is no need to worry about builders in other lanes with either method. For the hashtable method whenever you create a runner unit you would save into the hashtable the player that should lose lives if that unit makes it to the 'end':
  • -------- on unit create --------
  • Hashtable - Save YourPlayerVariableHoweverYouKnowWhichPlayerItShouldBe as "lifeloser" of Key(last created unit) in CONSTANT_Hashtable
  • -------- on unit death --------
  • Hashtable - Clear all child hashtables of child (Key (Triggering Unit)) in CONSTANT_Hashtable
  • -------- on unit enters region --------
  • Set LosingPlayer = Load "lifeloser" of Key(Triggering Unit)) in CONSTANT_Hashtable
  • Hashtable - Clear all child hashtables of child (Key (Triggering Unit)) in CONSTANT_Hashtable
With parallel arrays you would need to check the region the unit is in against some pre-stored variables:
  • -------- on map init set these --------
  • Set LifePlayers[1] = Player 1 (Red)
  • Set LifeRegion[1] = Lane 1 Portal <gen>
  • Set LifePlayers[2] = Player 2 (Blue)
  • Set LifeRegion[2] = Lane 2 Portal <gen>
  • ..
  • Set LifePlayers[14] = Player 14 (idk the color)
  • Set LifeRegion[14] = Lane 14 Portal <gen>
  • -------- On entering a region like you have above --------
  • For each (Integer A) from 1 to 14 do (Actions)
    • Loop - Actions
      • If (All conditions are true) then do (Then actions) else do (Else actions)
        • If - Conditions
          • LifeRegion[(Integer A)] contains (Triggering Unit) equal to true
        • Then - Actions
          • Set LosingPlayer = LifePlayers[(Integer A)]
          • Custom script: exitwhen true //not necessary to have this, just more efficient
        • Else - Actions
Thank you for the quick reply :D I quite like the hashtable idea, however my issue is with trying to determine which player is in the lane of the running unit
  • Hashtable - Save PlayerVariable as "lifeloser" of Key(last created unit) in CONSTANT_Hashtable
I need to determine which player will be saved as PlayerVariable, Players do not have fixed positions in this which makes it even more difficult since I don't know which players will be spawning in which lanes.

EDIT: Myimage.PNG Here is an image of the lanes, when a running unit is created, it has no predetermined lane to run to, it runs to a region which then uses a series of trigger such as this one below to determine whether one or both lanes are active and then randomly chooses a lane for that unit to enter, another trigger then changes CONSTANT_LaneActive[Chosenlane] to False when a certain number of units have been sent to that region so that when a unit enters a "relay" region, it can now no longer be sent to that region.
  • Relay1
    • Events
      • Unit - A unit enters Relay 1 <gen>
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Owner of (Triggering unit)) Equal to Player 21 (Coal)
        • Then - Actions
          • Set INDEPENDANT_RandomLaneInteger[1] = (Random integer number between 1 and 2)
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • INDEPENDANT_RandomLaneInteger[1] Equal to 1
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CONSTANT_LaneActive[1] Equal to True
                • Then - Actions
                  • Unit - Order (Triggering unit) to Move To (Load 1 of 5 in CONSTANT_Hashtable)
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • CONSTANT_LaneActive[8] Equal to True
                    • Then - Actions
                      • Unit - Order (Triggering unit) to Move To (Load 8 of 5 in CONSTANT_Hashtable)
                    • Else - Actions
                      • Unit - Order (Triggering unit) to Move To (Load 2 of 2 in CONSTANT_Hashtable)
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • CONSTANT_LaneActive[8] Equal to True
                • Then - Actions
                  • Unit - Order (Triggering unit) to Move To (Load 8 of 5 in CONSTANT_Hashtable)
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • CONSTANT_LaneActive[1] Equal to True
                    • Then - Actions
                      • Unit - Order (Triggering unit) to Move To (Load 1 of 5 in CONSTANT_Hashtable)
                    • Else - Actions
                      • Unit - Order (Triggering unit) to Move To (Load 2 of 2 in CONSTANT_Hashtable)
        • Else - Actions
So my trouble is determining which lane is occupied by which players.

EDIT2: So I've even tried this system to no avail.
This trigger is one i've got setup for choosing difficulty
Using the action down the bottom of this trigger to save a handle of the region containing the player's builder.
  • Response
    • Events
      • Dialog - A dialog button is clicked for CONSTANT_DifficultySelection
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Clicked dialog button) Equal to DIALOG_DialogButton[1]
        • Then - Actions
          • Set DEPENDANT_HardMode = (DEPENDANT_HardMode + 1)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Clicked dialog button) Equal to DIALOG_DialogButton[2]
        • Then - Actions
          • Set DEPENDANT_HardMode = (DEPENDANT_HardMode - 1)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DEPENDANT_HardMode Greater than 0
        • Then - Actions
          • Set NumberOfLives[(Player number of (Triggering player))] = 40
          • Set DEPENDANT_GoldPerWave = 200
          • Set DEPENDANT_GoldPerKill = 5
          • Set DEPENDANTUnitsPerWaveIncrease = 8
          • Set UnitSpawnIntervals = 1.00
          • Set DEPENDANT_UnitsPerWave = (45 x (Number of players in Players))
        • Else - Actions
          • Set NumberOfLives[(Player number of (Triggering player))] = 60
          • Set DEPENDANTUnitsPerWaveIncrease = 3
          • Set DEPENDANT_GoldPerWave = 100
          • Set DEPENDANT_GoldPerKill = 3
          • Set UnitSpawnIntervals = 1.75
          • Set DEPENDANT_UnitsPerWave = (25 x (Number of players in Players))
      • Dialog - Hide CONSTANT_DifficultySelection for (Triggering player)
      • Set TempPoint = ((Triggering player) start location)
      • Unit - Create 1 Eredar Warlock for (Triggering player) at TempPoint facing 90.00 degrees
      • Custom script: call RemoveLocation(udg_TempPoint)
      • Unit Group - Add (Last created unit) to Builders
      • For each (Integer A) from 1 to 14, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Load (Integer A) of 3 in CONSTANT_Hashtable) contains (Last created unit)) Equal to True
            • Then - Actions
              • Set CONSTANT_LaneActive[(Integer A)] = True
              • Hashtable - Save Handle Of(Load (Integer A) of 3 in CONSTANT_Hashtable) as (Player number of (Triggering player)) of 1 in CONSTANT_UnitHashtable
            • Else - Actions
  • Unit enters portal
    • Events
      • Unit - A unit enters Lane 1 Portal <gen>
      • Unit - A unit enters Lane 2 Portal <gen>
      • Unit - A unit enters Lane 3 Portal <gen>
      • Unit - A unit enters Lane 4 Portal <gen>
      • Unit - A unit enters Lane 5 Portal <gen>
      • Unit - A unit enters Lane 6 Portal <gen>
      • Unit - A unit enters Lane 7 Portal <gen>
      • Unit - A unit enters Lane 8 Portal <gen>
      • Unit - A unit enters Lane 9 Portal <gen>
      • Unit - A unit enters Lane 10 Portal <gen>
      • Unit - A unit enters Lane 11 Portal <gen>
      • Unit - A unit enters Lane 12 Portal <gen>
      • Unit - A unit enters Lane 13 Portal <gen>
      • Unit - A unit enters Lane 14 Portal <gen>
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 14, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Load (Integer A) of 1 in CONSTANT_UnitHashtable) contains (Triggering unit)) Equal to True
            • Then - Actions
              • Unit - Remove (Triggering unit) from the game
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • NumberOfLives[(Integer A)] Greater than 0
                • Then - Actions
                  • Set NumberOfLives[(Integer A)] = (NumberOfLives[(Integer A)] - 1)
                  • Game - Display to (Player group((Player((Integer A))))) the text: (|c00FFFF00You have + ((String(NumberOfLives[(Integer A)])) + lives left.|r))
                • Else - Actions
                  • Unit Group - Pick every unit in (Units owned by (Player((Integer A)))) and do (Actions)
                    • Loop - Actions
                      • Unit - Explode (Picked unit)
            • Else - Actions
  • But the issue here is it doesn't seem to even get past the condition since the triggering unit is never removed from the game, the units just stand in the ending region piling up.
I can't seem to wrap my head around any of this or why the triggers aren't working, each time I feel like i've worked it out it turns out to just be another dead end.
 
Last edited:
Level 39
Joined
Feb 27, 2007
Messages
5,019
Hmm, that does complicate things. Can all players can build in all lanes at all times, or do you sort of 'pick' your lane at a certain point and get locked into it?

Imo the method I see in your triggers is pretty whack and my intuition is that it could be significantly optimized. I'll think about this and post again probably tomorrow, but for now the best method I see is to count up the number of player units in each region right before the wave spawns and assign each exit portal to the player with the most units in that portal's lane. I would probably also specify that if a particular player has already been chosen for a lane, that player's units are ignored in subsequent lanes until all other players have been assigned a lane or there are no other player's units present in the lane. Repeat for each wave so the players get properly updated. No matter what logic you use to determine who should lose lives for a lane, by virtue of not locking each player 100% into their own lane there will always be a way to cheat the system with a coordinated group of people playing the map.

Regarding your use of hashtables, using integers for your parent and child keys makes it really difficult to understand what exactly the relevance of the things you're saving and loading are. I would suggest you use strings for your keys instead to add readability and ease of understanding to your triggers. Not just for the sake of anyone who may help you, but for your sake as well. It may well help you avoid making stupid mistakes. The function for this is called "Hashtable - Get String ID" instead of just typing an integer for the key.
 
Level 8
Joined
Jul 29, 2010
Messages
319
Hmm, that does complicate things. Can all players can build in all lanes at all times, or do you sort of 'pick' your lane at a certain point and get locked into it?

Imo the method I see in your triggers is pretty whack and my intuition is that it could be significantly optimized. I'll think about this and post again probably tomorrow, but for now the best method I see is to count up the number of player units in each region right before the wave spawns and assign each exit portal to the player with the most units in that portal's lane. I would probably also specify that if a particular player has already been chosen for a lane, that player's units are ignored in subsequent lanes until all other players have been assigned a lane or there are no other player's units present in the lane. Repeat for each wave so the players get properly updated. No matter what logic you use to determine who should lose lives for a lane, by virtue of not locking each player 100% into their own lane there will always be a way to cheat the system with a coordinated group of people playing the map.

Regarding your use of hashtables, using integers for your parent and child keys makes it really difficult to understand what exactly the relevance of the things you're saving and loading are. I would suggest you use strings for your keys instead to add readability and ease of understanding to your triggers. Not just for the sake of anyone who may help you, but for your sake as well. It may well help you avoid making stupid mistakes. The function for this is called "Hashtable - Get String ID" instead of just typing an integer for the key.
I managed to solve it, after a stupidly long session of painstaking hours of just scouring my triggers I realised a bunch of mistakes I had made, I've been working on this map for quite a while now and recently I was often staying up for 2 or even 3 days in a row without sleep just to work on it, one of those times just so happen to also be the time I set up my hashtables and I now realise that my hashtables were an absolute mess and that fixing those mistakes made everything run smooth, this is now my system.

At the start of every game when each player votes on the difficulty they wish the map to be set to is when most of the maps values and variables are set, this also happens to be when the voting players building unit is created, so using this I created this trigger as shown before.
  • Response
    • Events
      • Dialog - A dialog button is clicked for CONSTANT_DifficultySelection
    • Conditions
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Clicked dialog button) Equal to DIALOG_DialogButton[1]
        • Then - Actions
          • Set DEPENDANT_HardMode = (DEPENDANT_HardMode + 1)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Clicked dialog button) Equal to DIALOG_DialogButton[2]
        • Then - Actions
          • Set DEPENDANT_HardMode = (DEPENDANT_HardMode - 1)
        • Else - Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • DEPENDANT_HardMode Greater than 0
        • Then - Actions
          • Set NumberOfLives[(Player number of (Triggering player))] = 40
          • Set DEPENDANT_GoldPerWave = 200
          • Set DEPENDANT_GoldPerKill = 5
          • Set DEPENDANTUnitsPerWaveIncrease = 8
          • Set UnitSpawnIntervals = 1.00
          • Set DEPENDANT_UnitsPerWave = (45 x (Number of players in Players))
        • Else - Actions
          • Set NumberOfLives[(Player number of (Triggering player))] = 60
          • Set DEPENDANTUnitsPerWaveIncrease = 3
          • Set DEPENDANT_GoldPerWave = 100
          • Set DEPENDANT_GoldPerKill = 3
          • Set UnitSpawnIntervals = 1.75
          • Set DEPENDANT_UnitsPerWave = (25 x (Number of players in Players))
      • Dialog - Hide CONSTANT_DifficultySelection for (Triggering player)
      • Set TempPoint = ((Triggering player) start location)
      • Unit - Create 1 Eredar Warlock for (Triggering player) at TempPoint facing 90.00 degrees
      • Custom script: call RemoveLocation(udg_TempPoint)
      • Unit Group - Add (Last created unit) to Builders
      • For each (Integer A) from 1 to 14, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Load (Integer A) of 3 in CONSTANT_Hashtable) contains (Last created unit)) Equal to True
            • Then - Actions
              • Set CONSTANT_LaneActive[(Integer A)] = True
              • Hashtable - Save Handle Of(Load (Integer A) of 7 in CONSTANT_Hashtable) as (Player number of (Owner of (Last created unit))) of 1 in CONSTANT_UnitHashtable
            • Else - Actions
Once the player has voted then the lane that the unit spawns in will be saved in the hashtable using the player's number as a key.
The next trigger is where all the action takes place.
  • Unit enters portal
    • Events
      • Unit - A unit enters Lane 1 Portal <gen>
      • Unit - A unit enters Lane 2 Portal <gen>
      • Unit - A unit enters Lane 3 Portal <gen>
      • Unit - A unit enters Lane 4 Portal <gen>
      • Unit - A unit enters Lane 5 Portal <gen>
      • Unit - A unit enters Lane 6 Portal <gen>
      • Unit - A unit enters Lane 7 Portal <gen>
      • Unit - A unit enters Lane 8 Portal <gen>
      • Unit - A unit enters Lane 9 Portal <gen>
      • Unit - A unit enters Lane 10 Portal <gen>
      • Unit - A unit enters Lane 11 Portal <gen>
      • Unit - A unit enters Lane 12 Portal <gen>
      • Unit - A unit enters Lane 13 Portal <gen>
      • Unit - A unit enters Lane 14 Portal <gen>
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 14, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Load (Integer A) of 1 in CONSTANT_UnitHashtable) contains (Triggering unit)) Equal to True
            • Then - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • NumberOfLives[(Integer A)] Greater than 0
                • Then - Actions
                  • Unit - Remove (Triggering unit) from the game
                  • Set NumberOfLives[(Integer A)] = (NumberOfLives[(Integer A)] - 1)
                  • Game - Display to (Player group((Player((Integer A))))) for 0.25 seconds the text: (|c00FFFF00You have + ((String(NumberOfLives[(Integer A)])) + lives left.|r))
                • Else - Actions
                  • Set CONSTANT_LaneActive[(Integer A)] = False
                  • Unit Group - Pick every unit in (Units owned by (Player((Integer A)))) and do (Actions)
                    • Loop - Actions
                      • Unit - Explode (Picked unit)
            • Else - Actions
 
Level 39
Joined
Feb 27, 2007
Messages
5,019
If that works for you and you like it, cool keep it... but your system isn't dynamic based on where players build. Each portal is assigned to the player whose start location (spinning pointy circle) is in that lane. The reason for that? You create the builder at the player's start location, then immediately check to find which region it's in.

There's an error (unless you want it to be this way) with your bit about setting lives based on difficulty. Every time a player clicks a difficulty box the variables like DEPENDENT_GoldPerKill get updated to either the normal or hard difficulty set of constants. This can flip flop back and forth if players alternate between voting normal, hard, normal, hard, etc. which really doesn't matter much because only the last time the votes are tallied up do the variables 'stay' permanently, and that likely happens before the first wave starts (but maybe not-- see below). However, each player's life total is only set one time (when they click the button) and it's dependent on the number of normal vs. hard votes at the time they click the button. So if you alternate hard, normal, hard, normal votes it will be normal mode but the 1st and 3rd players to vote will only have 40 lives. This can be done the other way around to get 60 lives while hard mode is active. I would wait to set life totals and mode variables after all votes have been cast.

Also if 1 person delays their difficulty vote for a very long time and then activates it at later it can change the difficulty long after the start of the map. This would also reset their lives count if for some reason that player had lost lives at 0 lives total and not been defeated.
 
Status
Not open for further replies.
Top