- Joined
- Nov 1, 2006
- Messages
- 1,612
Creating a Votekick System
Using Dialogs and Multiboards
by 1)ark_NiTe
Using Dialogs and Multiboards
by 1)ark_NiTe
Note: This is an Advanced Tutorial. It is not recommended for those who have yet to learn the basics of the World Editor.
In this tutorial I will teach you how to create a system that allows any player to kick someone that they think deserves to be removed from the game. There will be only one votekick attempt allowed against any single player and the process will be Timed. I will also give you the option to make the game's host incapable of being kicked. This particular system will be created using Variables, Dialogs, Countdown Timers, and Multiboards. If you are not familiar with the basics of any of them, I would advise you to check out the Variables, Basics of a Dialog, and Multiboards tutorials first. To better follow along with this tutorial, you should download the attached example WC3 map and follow along as you create your triggers. You will not be able to use this on Computer players unless you remove the conditions that reflect "(Player # (Color) controller) Equal to User"
Step 1: Creating Your Variables and Triggers
We need to have several variables in order to properly create this type of system. In your map, create the following variables.
- VotesNeeded (Integer)
- VotesYes (Integer)
- VotesNo (Integer)
- NoOfPlayers (Integer)
- VotesMultiboard (Multiboard)
- VotekickDialog (Dialog)
- VoteYesDialogButton (Dialog Button)
- VoteNoDialogButton (Dialog Button)
- VoteTimer (Countdown Timer)
- VoteTimerWindow (Timer Window)
- KickPlayer (Player)
Create 3 blank triggers:
- Create Vote Timer
- Vote Timer Expires
- ClickButton
Then create 2 more blank triggers per Player in your map:
- Kick[Player] (ex. KickRed, KickBlue, etc.)
- [Player]Attempted (ex. RedAttempted, BlueAttempted, etc.)
Step 2: Setting up the Minor Triggers
Countdown Timer and Dialog Buttons Clicked
Countdown Timer and Dialog Buttons Clicked
Before we create the main triggers, we will create the triggers that will be run by them. The Countdown Timer will contain two triggers. The first trigger, Create Vote Timer, will actually create the timer and will contain No Events, since it will be run from another trigger.
-
Create Vote Timer
- Events
- Conditions
-
Actions
- Trigger - Turn on Vote Timer Expires <gen>
- Countdown Timer - Start VoteTimer as a One-shot timer that will expire in 30.00 seconds
- Countdown Timer - Create a timer window for VoteTimer with title |cffffcc00Voting Ends:|r
- Set VoteTimerWindow = (Last created timer window)
This one was simple, we turned on the trigger we will create next, started our VoteTimer, created a window for it, and set that window as our VoteTimerWindow variable. The timer, once triggered, will appear like this at the top right of your screen:
The second trigger, Vote Timer Expires, will fire when our VoteTimer (which we created above) expires. This trigger will be Initially Off.
-
Vote Timer Expires
-
Events
- Time - VoteTimer expires
- Conditions
-
Actions
- Trigger - Turn off (This trigger)
- Trigger - Turn off ClickButton <gen>
- Countdown Timer - Destroy VoteTimerWindow
- Multiboard - Destroy VotesMultiboard
- Dialog - Clear VoteKickDialog
- Dialog - Hide VoteKickDialog for Player 1 (Red)
- Dialog - Hide VoteKickDialog for Player 2 (Blue)
- Dialog - Hide VoteKickDialog for Player 3 (Teal)
- Dialog - Hide VoteKickDialog for Player 4 (Purple)
- Trigger - Turn on KickRed <gen>
- Trigger - Turn on KickBlue <gen>
- Trigger - Turn on KickTeal <gen>
- Trigger - Turn on KickPurple<gen>
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (KickPlayer slot status) Not equal to Has left the game
-
Then - Actions
- Game - Display to (All players) the text: (Not enough votes were cast to kick + ((|cffffcc00 + (Name of KickPlayer)) + |r from the game.))
- Else - Actions
-
If - Conditions
-
Events
Don't worry, you're not lost. What we did in the above trigger was told the editor that if the VoteTimer expires to;
- Destroy TimerWindow so that the game will no longer show VoteTimer
- Destroys our multiboard and clears our Dialog that we created in our KickPlayer triggers.
- Turn back on our main triggers (KickRed, KickBlue, etc.) that were created in Step 3. They can all be turned back on without worry, because the ones that have been used are destroyed after their use and therefore will not be reset.
- Checked to see if KickPlayer had been kicked/left the game, and if they hadn't then reports to every player that not enough votes were made to kick the Player from the game.
- Hides the Vote Dialog for everyone so no one gets bugged with an empty dialog.
In this step we will also edit the trigger ClickButton to make it capture and record each Yes/No vote. The triggering Event will be when any Dialog Button is clicked. The first Actions in the trigger deciphers if the Vote was Yes, which would mean that VoteYesDialogButton was clicked by a Player, and then adds 1 to the amount of Yes votes on our multiboard. Voting is anonymous so it will not show who cast this vote.
-
ClickButton
-
Events
- Dialog - A dialog button is clicked for VoteKickDialog
- Conditions
-
Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Clicked dialog button) Equal to VoteYesDialogButton
-
Then - Actions
- Set VotesYes = (VotesYes + 1)
- Multiboard - Set the text for VotesMultiboard item in column 2, row 1 to (String(VotesYes))
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
Events
Next we will check to see if after the Yes vote has been recorded if there are enough Yes votes to kick the player.
-
ClickButton (cont.)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- VotesYes Equal to VotesNeeded
-
Then - Actions
- Trigger - Turn off (This trigger)
- Trigger - Turn off Vote Timer Expires <gen>
- Countdown Timer - Destroy VoteTimerWindow
- Multiboard - Destroy VotesMultiboard
- Dialog - Clear VoteKickDialog
- Dialog - Hide VoteKickDialog for Player 1 (Red)
- Dialog - Hide VoteKickDialog for Player 2 (Blue)
- Dialog - Hide VoteKickDialog for Player 3 (Teal)
- Dialog - Hide VoteKickDialog for Player 4 (Purple)
- Game - Defeat KickPlayer with the message: Kicked!
- Trigger - Turn on KickRed <gen>
- Trigger - Turn on KickBlue <gen>
- Trigger - Turn on KickTeal <gen>
- Trigger - Turn on KickPurple <gen>
- Trigger - Turn on KickYellow <gen>
- Trigger - Turn on KickOrange <gen>
- Trigger - Turn on KickGreen <gen>
- Trigger - Turn on KickPink <gen>
- Else - Actions
-
If - Conditions
- Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If VotesYes = VotesNeeded, meaning if the amount of Yes votes equals the amount of votes needed to kick the Player from the game, then the Player is kicked and all of the KickPlayer triggers that have not been run already are turned back on, and the Multiboard , Dialog, and Countdown Timer's are destroyed. If VotesYes does not equal VotesNeeded, then the trigger continues and picks up under the last Else - Actions,
- ClickButton (cont.)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Clicked dialog button) Equal to VoteNoDialogButton
-
Then - Actions
- Set VotesNo = (VotesNo + 1)
- Multiboard - Set the text for VotesMultiboard item in column 2, row 2 to (String(VotesNo))
- Else - Actions
-
If - Conditions
The final part of the trigger, above, simply recorded the No vote and updated that value on our multiboard.
Step 3: A Player Initiates the Kick
Main triggering begins
Main triggering begins
In order for the game to realize that a Player has attempted to start the votekick, there must be an event that it will register with. In this case, we are going to make a Player types "-votekick [PlayerName]" the event.
- Player - Player 1 (Red) types a chat message containing (-votekick + (Name of Player # (Color))) as An exact match
Here, the Event is "Player 1 (Red) types "-votekick [Name of Player #(Color)]" In other words, Player 1 (Red) feels that Player # needs to be kicked from the game, so he has called for a votekick against Player #.
*Player # stands for any Player besides the Player who has cast the vote.
Since you will probably have more players than just 2, you would add more Events to this trigger for each Player, spare the Player being kicked. The addition would appear as follows. We will assume for the rest of this tutorial that Player # is Player 2 (Blue) and that there are 4 people total playing the game.
- KickBlue
- Player - Player 1 (Red) types a chat message containing (-votekick + (Name of Player # (Color))) as An exact match
- Player - Player 3 (Teal) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
- Player - Player 4 (Purple) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
Step 4: Primary Actions
(KickPlayer trigger prototype)
(KickPlayer trigger prototype)
To be concise, I am going to post the first Actions to be taken before I explain them. This will be your KickPlayer trigger prototype, exampled off of an attempt to kick Player 2 (Blue).
If you have more than 4 Players in your map, you need to go on creating the rest of the triggers modeled after this one and adjust your triggers to accommodate more than 4 Players.
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Player 1 (Red) slot status) Equal to Is playing
- (Player 1 (Red) controller) Equal to User
-
Then - Actions
- Set NoOfPlayers = (NoOfPlayers + 1)
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Player 2 (Blue) slot status) Equal to Is playing
- (Player 2 (Blue) controller) Equal to User
-
Then - Actions
- Set NoOfPlayers = (NoOfPlayers + 1)
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Player 3 (Teal) slot status) Equal to Is playing
- (Player 3 (Teal) controller) Equal to User
-
Then - Actions
- Set NoOfPlayers = (NoOfPlayers + 1)
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Player 4 (Purple) slot status) Equal to Is playing
- (Player 4 (Purple) controller) Equal to User
-
Then - Actions
- Set NoOfPlayers = (NoOfPlayers + 1)
- Else - Actions
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (Player 2 (Blue) slot status) Equal to Is playing
- (Player 2 (Blue) controller) Equal to User
-
Then - Actions
- Trigger - Turn off (This trigger)
- Set KickPlayer = Player 1 (Red)
- Trigger - Turn off KickRed <gen>
- Trigger - Turn off KickTeal <gen>
- Trigger - Turn off KickPurple <gen>
- Trigger - Turn on ClickButton <gen>
- Trigger - Run CreateVoteTimer <gen> (checking conditions)
- Trigger - Turn on Vote Timer Expires <gen>
- Set VotesNeeded = 0
- Set VotesYes = 0
- Set VotesNo = 0
-
If - Conditions
The above actions achieve the following;
- In order to have the correct amount of Votes needed to kick a Player, we first checked how many Players are playing/controlled by a User
- Check to see if the Player that the vote was cast against is playing and is a user, so null votekicks can't occur.
- Establish the Player being kicked
- Sets the variable that lets the editor know if this trigger has been run yet, for purposes that will be explained later
- Turns off the other KickPlayer triggers so that they will not interfere with this one
- Turns on the trigger (ClickButton) that will track the votes cast
- Turns on the trigger that will create the 30 second VoteTimer
- Turns on the trigger that will fire if VoteTimer expires before enough votes have been cast to kick the Player.
- Resets all vote variables to 0 in case they had been changed in a previous votekick.
Step 5: Secondary Actions
These actions are in the same trigger as the Primary Actions, but I have split up the single trigger to make it more easily understood. Place them directly after Set VotesNo = 0.
- KickBlue (cont.)
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (NoOfPlayers Equal to 4)
-
Then - Actions
- Set VotesNeeded = 3
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (NoOfPlayers Equal to 3)
-
Then - Actions
- Set VotesNeeded = 2
-
Else - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- (NoOfPlayers Equal to 2)
-
Then - Actions
- Set VotesNeeded = 1
- Else - Actions
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
Step 6: Setting up the Multiboard
These actions are also in the KickBlue trigger, directly after the Secondary Actions. This chunk of Actions focuses directly on creating the Multiboard.
- KickBlue (cont.)
-
Multiboard - Create a multiboard with 2 columns and 3 rows, titled (Votekick + ((Name of KickPlayer) + ?))
- Set VotesMultiboard = (Last created multiboard)
- Multiboard - Set the icon for MultiBoard item in column 0, row 0 to ReplaceableTextures\CommandButtons\BTNWirtsOtherLeg.blp
In the above Actions, we created a multiboard that will be 2 columns and 3 rows and be titled "Votekick [PlayerName]?", set our VotesMultiboard variable, and set the Icon of each row. We will now create the columns and rows.
-
KickBlue (cont.)
- Multiboard - Set the text for VotesMultiboard item in column 1, row 1 to |cff00FF00Yes:|r
- Multiboard - Set the text for VotesMultiboard item in column 2, row 1 to (String(VotesYes))
- Multiboard - Set the width for VotesMultiboard item in column 1, row 1 to 6.50% of the total screen width
- Multiboard - Set the text for VotesMultiboard item in column 1, row 2 to |cffFF0000No:|r
- Multiboard - Set the width for VotesMultiboard item in column 1, row 2 to 6.50% of the total screen width
- Multiboard - Set the text for VotesMultiboard item in column 2, row 2 to (String(VotesNo))
- Multiboard - Set the text for VotesMultiboard item in column 1, row 3 to |cffffcc00Needed:|r
- Multiboard - Set the width for VotesMultiboard item in column 1, row 3 to 6.50% of the total screen width
- Multiboard - Set the text for VotesMultiboard item in column 2, row 3 to (String(VotesNeeded))
- Multiboard - Maximize VotesMultiboard
- Multiboard - Show VotesMultiboard
Now we have also set the text for each row and column, the width of each row and column, and shown the multiboard to every Player. Our Yes row is in green, our No row is in red, and our Needed row is in gold. The VotesMultiboard has been setup. It should look just like the one in the following picture:
Step 7: Setting up the Dialog
At this point we must set-up our dialogs. We are going to be using a dialog as our means of asking each Player if they would like to kick the Player in question. We will create the dialog and its buttons.
-
KickBlue (cont.)
- Dialog - Clear VoteKickDialog
- Dialog - Change the title of VoteKickDialog to (Kick + ((Name of KickPlayer) + ?))
- Dialog - Create a dialog button for VoteKickDialog labelled Yes
- Set VoteYesDialogButton = (Last created dialog Button)
- Dialog - Create a dialog button for VoteKickDialog labelled No
- Set VoteNoDialogButton = (Last created dialog Button)
The dialog we have created is now titled "Kick [Player Name]?" and its buttons are Yes and No, which have both been assigned their proper variable. To finish the dialog setup we simply need to show it to every player besides Player 2 (Blue) because they are the ones being votekicked,
-
KickBlue (cont.)
- Dialog - Show VoteKickDialog for Player 1 (Red)
- Dialog - Show VoteKickDialog for Player 3 (Teal)
- Dialog - Show VoteKickDialog for Player 4 (Purple)
- Trigger - Turn on BlueAttempted <gen>
- Custom script: call DestroyTrigger( GetTriggeringTrigger() )
- Else - Actions
The Actions above also turn on "BlueAttempted" before it is destroyed. That is the trigger which will now fire in the place of this one. The dialog will now be shown to every player aside from the one being votekicked so that they can cast their vote. This trigger has been completed, but do not forget that you must create one of these for each Player, and change the Actions to correctly accommodate that player's KickPlayer trigger.
Step 8: Finishing the System
Editing the PlayerAttempted trigger prototype
Editing the PlayerAttempted trigger prototype
Lastly we will create the trigger that will turn on once a Player's KickPlayer trigger has been executed and destroyed. This trigger will simply inform someone trying to votekick the Player that a votekick attempt has already been made against them and another cannot be called for. This will be the PlayerAttempted trigger, or in this case BlueAttempted.
-
BlueAttempted
-
Events
- Player - Player 1 (Red) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
- Player - Player 3 (Teal) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
- Player - Player 4 (Purple) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
- Player - Player 5 (Yellow) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
- Player - Player 6 (Orange) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
- Player - Player 7 (Green) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
- Player - Player 8 (Pink) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
- Player - Player 11 (Dark Green) types a chat message containing (-votekick + (Name of Player 2 (Blue))) as An exact match
- Conditions
-
Actions
- Game - Display to (Player group((Triggering player))) the text: (A votekick attempt has already been registered for + (|cffffcc00 + ((Name of Player 2 (Blue)) + |r.)))
-
Events
As an end note, you may have been wondering why this entire time the Player that the trigger is made for does not appear in any of the "-votekick PlayerName" Events. This is because we do not want people to be able to votekick themselves. Make sure a player never is in the Event list for their own KickPlayer trigger. You are now done with the entire system!
Step 9: Making the Host Immune
This step is not necessary, but is recommended.
This step is not necessary, but is recommended.
First, make sure that you have followed ragingspeedhorn's HostFinder tutorial completely. Once you have your Host found and the Host variable created, simply add this Action-condition, 'Player being Kicked' Not equal to Host, into each of your KickPlayer triggers at the second If-then-else action. It will now look like this,
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- Player 2 (Blue) Not equal to Host
- (Player 2 (Blue) slot status) Equal to Is playing
- (Player 2 (Blue) controller) Equal to User
-
If - Conditions
Now at the very end of trigger under the blank "Else - Actions" create the following Actions.
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
- Player 2 (Blue) Equal to Host
-
Then - Actions
- Game - Display to (Player group((Triggering player))) the text: |cffffcc00You cannot votekick the Host.|r
- Else - Actions
-
If - Conditions
Now the Host of the game cannot be kicked and you should have a complete and working Votekick System!
Attachments
Last edited: