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

Creating a Votekick System

Level 18
Joined
Nov 1, 2006
Messages
1,612
Creating a Votekick System
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

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: VoteTimer.jpg

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

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))

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

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

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
Obtaining the amount of Players in the game


Step 4: Primary Actions
(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 (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

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

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: Multiboard.jpg


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. votekickdialog.jpg


Step 8: Finishing the System
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.)))

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.

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

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

Now the Host of the game cannot be kicked and you should have a complete and working Votekick System!
 

Attachments

  • 1)ark_NiTe's VotekickSystem Guide.w3x
    27.1 KB · Views: 895
Last edited:
Level 18
Joined
Nov 1, 2006
Messages
1,612
A votekick system is a general vote system where the result is the player being kicked.

This if a general vote system were too simple, a votekick system would be too.

And if you don't want the host to have almighty power, why'd you make them unkickable? =o

No. A general kick system is where a Host decides who goes and who stays. A votekick system is where all of the Players in the game can decide who stays or who goes. They are much different, and a votekick system is much more complicated. The only reason that the host can be exempt from this is because if you kick the host it can cause the game to split and/or disconnect everyone else, thus ruining the game. If you look closely you will see that adding the option to make the host immune is not necessary, but simply recommended.
 
Level 18
Joined
Nov 1, 2006
Messages
1,612
OHH I see. I'm sorry for my ignorance haha. I understand now. Ummm, well, that would be a lot more complicated than this, considering all the specifics of a general vote system. I can't think of a way to go about doing that without having to specify for each possible option, since there are different procedures for different types of things to vote on.
 
Level 29
Joined
Jul 29, 2007
Messages
5,174
I would like to comment on 2 things.

First, if you would have used Substrings instead of Exact Match strings it could shorten to code by... a lot.

And the second thing is, vote kickes should ultimatly have the option for ANY play to start a vote kick and by this removing the "ultimate power" of the host.
 
Level 18
Joined
Nov 1, 2006
Messages
1,612
I would like to comment on 2 things.

First, if you would have used Substrings instead of Exact Match strings it could shorten to code by... a lot.

And the second thing is, vote kickes should ultimatly have the option for ANY play to start a vote kick and by this removing the "ultimate power" of the host.

Any player can start a vote kick. Also, any player can be kicked unless the mapmaker used Step 9 and created the Host-Immune section of the system. I recommended that it be used because if someone kicks the host and no one else in the game can host, the game will end for everybody.
 
Level 2
Joined
Dec 23, 2007
Messages
3
dude, i like you votekick, but you made it way to hard...
="http://www.megaupload.com/?d=M0BD7ML2"
if you want to add the host code, add that code into it and change the \votekick call triggers by adding another action
if all conditions are true, then do actions:
condition, player 1 not equal to host
action:Sorry, host cannot be kicked game text
else:do action, (what normally follows in this script)
 
Level 2
Joined
Jan 5, 2008
Messages
22
Simple Way
Useful tutorial. Thanks. But it's to complicated. it would be easier to:
ADemon(all):Guys, do you want to kick him?
Someone(all):Yup!
ADemon(all):/kick x
 
Level 2
Joined
Dec 23, 2007
Messages
3
:D

i just made an complete votekick system with just 6 triggers, exceptions added, anyone can type:\votekick and then a dialog list shows up of all active players, and then the player can select 1 of them, (meanwhile vote there can not be voted against another player)
then all active players besides the voted against one get an menu called:
kick <playername>?
yes
no

after 20 seconds or so the game will compare all no and yes votes, if yes is greater then no then votekick selected player.
it will auto-fix the list with active players and the name will be set to: kicked

if you want this for test of use in your map just ask, i will save it as seperate map so you can import it, or test it.

it also has hostfinding code so every player CAn be host, and host cannot be kicked!
 
Level 3
Joined
Nov 2, 2008
Messages
38
for making the host immune, does it really matter whether you put it under the second or first 'if,then,else' thing? All in all, a good tutorial, but too confusing. You have a lot of seperate pieces of triggers, and I think you should have made one with ALL of them put together, so you know exactly where everything goes
 
Top