Team Voting System

Level 7
Joined
May 30, 2018
Messages
290
Dear Hive,

I tried to produce a simple button-votting system for choosing a race in my map. There are 2 Teams a 5 Players. The first player of each team is the player who gets the starting units of the chosen race (so player 1 red and 6 orange). Now I need to know how to seperate the votes into the two teams, so that the trigger detects when a player of team 1 or team 2 casts a vote and adds this vote to the votes of the corresponding team and finally spawns the units of the voted race for the first player of each team (red and orange). I know its kinda convoluted, but maybe it gets clearer when I post the triggers down below. I had an first idea: Making a player group for each team and detecting in which of these groups the voting player is, tho I don't know if I did it the right way. Another question is, if I did the counting right. So if more than half of the team pick one race it gets picked and else a random race is chosen. (+ how could I add a timer to the voting process)

The Team Set Up:

  • Set Up Teams
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet Team1[1] = Player Group - Player 1 (Red)
      • Set VariableSet Team1[2] = Player Group - Player 2 (Blue)
      • Set VariableSet Team1[3] = Player Group - Player 3 (Teal)
      • Set VariableSet Team1[4] = Player Group - Player 4 (Purple)
      • Set VariableSet Team1[5] = Player Group - Player 5 (Yellow)
      • Set VariableSet Team2[1] = Player Group - Player 6 (Orange)
      • Set VariableSet Team2[2] = Player Group - Player 7 (Green)
      • Set VariableSet Team2[3] = Player Group - Player 8 (Pink)
      • Set VariableSet Team2[4] = Player Group - Player 9 (Gray)
      • Set VariableSet Team2[5] = Player Group - Player 10 (Light Blue)
The Race set up:

  • Set Up Races
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet RaceSpawn[1] = Peasant
      • Set VariableSet RaceSpawn[2] = Peon
      • Set VariableSet RaceSpawn[3] = Acolyte
The vote set up:

  • Set Up Vote
    • Events
      • Time - Elapsed game time is 2.00 seconds
    • Conditions
    • Actions
      • Dialog - Clear VoteOptions
      • Dialog - Change the title of VoteOptions to Choose your Race
      • Dialog - Create a dialog button for VoteOptions labelled Humans
      • Set VariableSet RaceOptions[1] = (Last created dialog Button)
      • Dialog - Create a dialog button for VoteOptions labelled Orcs
      • Set VariableSet RaceOptions[2] = (Last created dialog Button)
      • Dialog - Create a dialog button for VoteOptions labelled Undead
      • Set VariableSet RaceOptions[3] = (Last created dialog Button)
      • Player Group - Pick every player in (All players) and do (Actions)
        • Loop - Actions
          • Dialog - Show VoteOptions for (Picked player)
The votes per team

  • Do Vote Team 1
    • Events
      • Dialog - A dialog button is clicked for VoteOptions
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 3, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Triggering player) is in Team1[(Integer A)].) Equal to True
              • (Clicked dialog button) Equal to RaceOptions[(Integer A)]
            • Then - Actions
              • Set VariableSet VoteCount_Team1[(Integer A)] = (VoteCount_Team1[(Integer A)] + 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • VoteCount_Team1[(Integer A)] Greater than 2
                • Then - Actions
                  • Unit - Create 5 RaceSpawn[(Integer A)] for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
                • Else - Actions
                  • Unit - Create 5 RaceSpawn[(Random integer number between 1 and 3)] for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
            • Else - Actions
  • Do Vote Team 2
    • Events
      • Dialog - A dialog button is clicked for VoteOptions
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 3, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Triggering player) is in Team2[(Integer A)].) Equal to True
              • (Clicked dialog button) Equal to RaceOptions[(Integer A)]
            • Then - Actions
              • Set VariableSet VoteCount_Team2[(Integer A)] = (VoteCount_Team2[(Integer A)] + 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • VoteCount_Team2[(Integer A)] Greater than 2
                • Then - Actions
                  • Unit - Create 5 RaceSpawn[(Integer A)] for Player 6 (Orange) at (Center of (Playable map area)) facing Default building facing degrees
                • Else - Actions
                  • Unit - Create 5 RaceSpawn[(Random integer number between 1 and 3)] for Player 6 (Orange) at (Center of (Playable map area)) facing Default building facing degrees
            • Else - Actions
I know it leaks locations and that integer A is suboptimal, I will deal with these issues later ;)
 
Last edited:

Uncle

Warcraft Moderator
Level 48
Joined
Aug 10, 2018
Messages
4,651
Your Team variables don't make any sense. Just create two Player Groups, Team1 and Team2:
  • ((Triggering player) is in Team2 Equal to True

The Else - Actions for creating random units is wrong.
  • Unit - Create 5 RaceSpawn[(Random integer number between 1 and 3)] for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
This will always happen during the first and second vote since the VoteCount will be <= 2.

You want to reserve the random option for after all voting has been completed. This could be done using an Integer to compare if VotesCounted is >= VotesNeeded. VotesNeeded would be determined by counting the numbre of active Users in Team1/Team2 at the start of the voting process.

Additionally, you want to use a Timer that after let's say 30 seconds expires and counts up the votes and determines a winner. This way if VotesCounted never reaches VotesNeeded the game will move on anyway. Also, remember to Pause this timer if players finish voting before it expires.

Other things to note:
Players can leave the game messing up the voting process. If VotesNeeded is equal to the number of active players on a given Team, then you need to account for what happens when one of those players leaves. Does their vote still count? Should you check to see if they voted or not, and if not, give them a random vote? These are all things to take into account.

You probably don't want to Create units until the entire voting process for both teams is completed.
 
Level 7
Joined
May 30, 2018
Messages
290
Your Team variables don't make any sense. Just create two Player Groups, Team1 and Team2:
  • ((Triggering player) is in Team2 Equal to True

The Else - Actions for creating random units is wrong.
  • Unit - Create 5 RaceSpawn[(Random integer number between 1 and 3)] for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
This will always happen during the first and second vote since the VoteCount will be <= 2.

You want to reserve the random option for after all voting has been completed. This could be done using an Integer to compare if VotesCounted is >= VotesNeeded. VotesNeeded would be determined by counting the numbre of active Users in Team1/Team2 at the start of the voting process.

Additionally, you want to use a Timer that after let's say 30 seconds expires and counts up the votes and determines a winner. This way if VotesCounted never reaches VotesNeeded the game will move on anyway. Also, remember to Pause this timer if players finish voting before it expires.

Other things to note:
Players can leave the game messing up the voting process. If VotesNeeded is equal to the number of active players on a given Team, then you need to account for what happens when one of those players leaves. Does their vote still count? Should you check to see if they voted or not, and if not, give them a random vote? These are all things to take into account.

You probably don't want to Create units until the entire voting process for both teams is completed.
I can't really wrap my head around how to implement the integer comparison you mentioned. I tried these 2 approaches, but in my mind they dont seem to alter the probelm with the detection of already cast votes. I tried to make 2 versions I though of:

Version 1
  • Set Up Count
    • Events
      • Map initialization
    • Conditions
    • Actions
      • Set VariableSet VotesNeeded = (Number of players in Team1)
  • Do Vote Team 1
    • Events
      • Dialog - A dialog button is clicked for VoteOptions
    • Conditions
    • Actions
      • For each (Integer A) from 1 to 3, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Triggering player) is in Team1.) Equal to True
              • (Clicked dialog button) Equal to RaceOptions[(Integer A)]
            • Then - Actions
              • Set VariableSet VoteCount_Team1[(Integer A)] = (VoteCount_Team1[(Integer A)] + 1)
              • Set VariableSet VotesNeeded = (VotesNeeded - 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • VotesNeeded Equal to 0
                  • VoteCount_Team1[(Integer A)] Greater than 2
                • Then - Actions
                  • Unit - Create 5 RaceSpawn[(Integer A)] for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
                  • Countdown Timer - Pause VoteTimer
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • VotesNeeded Not equal to 0
                      • VoteCount_Team1[(Integer A)] Less than or equal to 2
                    • Then - Actions
                      • Unit - Create 5 RaceSpawn[(Random integer number between 1 and 3)] for Player 1 (Red) at (Center of (Playable map area)) facing Default building facing degrees
                      • Countdown Timer - Pause VoteTimer
                    • Else - Actions
            • Else - Actions

Version 2
  • Do Vote Team 2
    • Events
      • Dialog - A dialog button is clicked for VoteOptions
    • Conditions
    • Actions
      • Set VariableSet VotesNeeded = (Number of players in Team2)
      • For each (Integer A) from 1 to 3, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • ((Triggering player) is in Team2.) Equal to True
              • (Clicked dialog button) Equal to RaceOptions[(Integer A)]
            • Then - Actions
              • Set VariableSet VoteCount_Team2[(Integer A)] = (VoteCount_Team2[(Integer A)] + 1)
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • VoteCount_Team2[(Integer A)] Greater than or equal to VotesNeeded
                • Then - Actions
                  • Unit - Create 5 RaceSpawn[(Integer A)] for Player 6 (Orange) at (Center of (Playable map area)) facing Default building facing degrees
                  • Countdown Timer - Pause VoteTimer
                • Else - Actions
                  • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                    • If - Conditions
                      • VoteCount_Team2[(Integer A)] Less than VotesNeeded
                    • Then - Actions
                      • Unit - Create 5 RaceSpawn[(Random integer number between 1 and 3)] for Player 6 (Orange) at (Center of (Playable map area)) facing Default building facing degrees
                      • Countdown Timer - Pause VoteTimer
                    • Else - Actions
            • Else - Actions
+ How do I manage to only spawn units after the whole voting process is finished, as u mentioned above.
 

Uncle

Warcraft Moderator
Level 48
Joined
Aug 10, 2018
Messages
4,651
(I'm writing these triggers from memory so they'll look weird)

After each vote you check to see if VoteCount[team number] is >= VotesNeeded[team number]. Or you can subtract from it and check if it's Equal to 0 like you did, either way can work.
Once a team has reached this needed amount you'll know that they're finished voting.

From there you determine which Race has won for that given team by comparing their votes (this probably isn't the best way of doing it):

  • If VoteCount_Team1[1] > VoteCount_Team1[2] and VoteCount_Team1[1] > VoteCount_Team1[3] then Set TeamWorker[1] = Peasant
  • Else If VoteCount_Team1[2] > VoteCount_Team1[1] and VoteCount_Team1[2] > VoteCount_Team1[3] then Set TeamWorker[1] = Peon
  • Else If VoteCount_Team1[3] > VoteCount_Team1[1] and VoteCount_Team1[3] > VoteCount_Team1[2] then Set TeamWorker[1] = Acolyte

TeamWorker would be a Unit-type Array. It's Index represents the Team #, so [1] = Team 1, [2] = Team 2.

You could also use (or add in addition to TeamWorker) an Integer variable to store the Team's race like:
TeamRace[1] = 1, TeamRace[1] = 2, TeamRace[1] = 3. 1 = Human, 2 = Orc, 3 = Undead.
This may serve useful in the future like if you wanted to do something depending on a team's race.

Now that we've stored this information we can reference it when it comes time to create the starting units.

This would happen after both teams have finished voting (so VotesNeeded[1] and VotesNeeded[2] are both <= 0) OR after the Timer has expired:
  • If TeamWorker[1] Equal to No Unit then Create 5 RaceSpawn[Random number from 1 to 3] Else Create 5 TeamWorker[1]
  • If TeamWorker[2] Equal to No Unit then Create 5 RaceSpawn[Random number from 1 to 3] Else Create 5 TeamWorker[2]

You could put the above Create unit Actions in an entirely new Trigger and Run this trigger in response to one of the 2 Events:
  • /// Voting finished OR Vote timer expired ///
  • Trigger - Run CreateStartingUnits (ignoring conditions)

Also, remember, you only want to Pause the voting timer when BOTH teams have FINISHED voting.

Another important thing:
  • ((Triggering player) is in Team2.) Equal to True
This Condition should be in the main Condition block. NONE of the Actions should run unless this condition is met.
 
Last edited:

Uncle

Warcraft Moderator
Level 48
Joined
Aug 10, 2018
Messages
4,651
I created a working system based on what you wanted and attached the map. Requires the latest patch to open.
 

Attachments

  • Voting System.w3m
    22.1 KB · Views: 11
Level 7
Joined
May 30, 2018
Messages
290
I created a working system based on what you wanted and attached the map. Requires the latest patch to open.
I took a look at the triggers and understand them for the most part. However a few variables and how they interact are not clear to me:

Set VariableSet HasVoted[(Player number of (Triggering player))] = True
(whats the purpose of this line, since it never gets referenced somewhere else)


Set VariableSet RaceWorkers[1] = Peasant
and later
Set VariableSet TeamWorker[1] = Peasant
(Where is the difference, why are we setting up the same thing twice?)

Set VariableSet TeamRace[1] = 2
(what does this refere to? Where is Team Race defined?)

Set VariableSet TeamWorker[1] = RaceWorkers[TeamRace[1]]
(What does this line do in general?)


Thank you.
 

Uncle

Warcraft Moderator
Level 48
Joined
Aug 10, 2018
Messages
4,651
TeamWorker is Set when a race is chosen from the vote in order to keep track of a team's winning race. So if Team 1 voted for Human then Peasant is their TeamWorker. RaceWorkers is used when it comes time to determine a random worker to be chosen in case a team fails to vote for a specific race:
  • /// A team failed to vote for race options 1, 2, or 3:
  • Set Variable TeamRace[1] = Random integer between 1 and 3
  • Set Variable TeamWorker[1] = RaceWorkers[TeamRace[1]] <--- TeamRace[1] was just set to a random integer between 1 and 3 so this chooses a random worker from RaceWorkers

TeamRace[1] is Set to whichever Race wins the vote for Team 1. TeamRace[2] is Set to whichever Race wins the vote for Team 2.

HasVoted[] is referenced in the "Player Leaves During Voting" trigger. It checks to see whether or not a leaving player has voted. If they have already voted then they get ignored, otherwise their team's VoteCast is increased by 1 potentially triggering the end of the voting phase. In other words, if Player 3 were to be the last person that needs to vote and they leave the game then this variable is used to detect this and end the voting phase.

Understand that the "Leaving Player" stuff isn't necessary, I added it in there to make sure that the system work well. You don't want to wait 20+ seconds because someone left the game during the voting phase, instead the triggers should take this into consideration and the voting should end when all ACTIVE players are finished voting.

Don't overcomplicate it. Team 1 has X players, Team 2 has Y players. Both teams need to cast ALL of their votes in order for the voting phase to end. This means that Team 1 has to reach X votes and Team 2 has to reach Y votes. Once both X and Y are reached then the voting ends. Alternatively, if some players go afk and don't vote then there is a timer to make sure that things proceed regardless. Also, if a player leaves during this voting period and they never get around to voting then simply count their vote towards their team's Votes Needed (potentially Random).
 
Last edited:
Top