I'm Joker(Div) on the Helper, in case your wondering why my names don't match.
I got tired of all these GUI kick systems, so I decided to make a JASS one myself.
Enjoy. :)
Code
//============================================================================== // VOTEKICK SYSTEM BY JOKER(DIV) -- v1.11 //============================================================================== // // PURPOSE: // * To kick annoying players with majority vote. // // // HOW TO USE: // * My Vote Kick system is just a simple trigger. // // * Just Type: "-kick player ##" (i.e. -kick player 12) to kick that player. // // * Everyone is able to request a kick. // // PROS: // * Extremelly easy to use // * Somewhat configurable (not that you need to anyway...) // // CONS: // * Limited to a certain extent. (I suppose...) // // CREDITS: // * Cohadar (I Stole this outline from him :D) // * All you darn GUI'ers, enough GUI already :P // // REQUIREMENTS: // * Dialogs system by Cohadar (Requires ABC) // * NewGen Editor by Vexorian/PitzerMike // // HOW TO IMPORT: // * Just create a trigger named VK // * convert it to text and replace the whole trigger text with this one // //============================================================================== library VK uses Dialogs
globals //==================================== privateconstantreal SECONDS_BETWEEN_VOTES = 25. //Only thing you need to touch. privateconstantstring YesColor = "|cFFFF0000"//(Unless you know what you are doing.) privateconstantstring NoColor = "|cFF00FF00" //====================================
//I set it to 16 since Player(16) doesn't exist, incase this bugs...somehow. privateinteger WhichPlayer = 16
//Maybe you can find this global useful. publicinteger CountPlayers = 0 endglobals
//=========================================================================== privatefunction AllowVote takesnothingreturnsnothing //Have to set everything back to default set Running = false set AllVote = 0 set Yes = 0 set No = 0 call PauseTimer(Timer) endfunction
//=========================================================================== privatefunction VoteAction takesnothingreturnsnothing localinteger Result = Dlog.GetResult()//Dialogs localplayer TPlayer = GetTriggerPlayer() set AllVote = AllVote + 1 call Dlog.Hide(TPlayer)//Dialogs
if Result == HK_1 then set Yes = Yes + 1 call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS,3.5, YesColor + GetPlayerName(TPlayer) + " has voted yes. (" + I2S(AllVote) + "/" + I2S(CountPlayers) + ")") elseif Result == HK_2 then set No = No + 1 call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS,3.5, NoColor + GetPlayerName(TPlayer) + " has voted no. (" + I2S(AllVote) + "/" + I2S(CountPlayers) + ")") elseif Result == HK_3 then call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS,3.5, NoColor + GetPlayerName(TPlayer) + " will not vote. (" + I2S(AllVote) + "/" + I2S(CountPlayers) + ")") endif
if AllVote == CountPlayers then call TimerStart( Timer, SECONDS_BETWEEN_VOTES, false, function AllowVote ) call ClearTextMessages() call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS,2.5, "|cFFC0C000Vote Count:|r"+YesColor +" Yes: "+I2S(Yes)+"|r"+NoColor+" No: "+I2S(No)+"|r Null: "+I2S(CountPlayers-(Yes+No)))
if Yes > No then call CustomDefeatBJ(Player(WhichPlayer), "You have been kicked.") call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS,2., GetPlayerName(Player(WhichPlayer)) + " has been kicked.") else call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS,2., GetPlayerName(Player(WhichPlayer)) + " will not be kicked.") endif endif endfunction
//I'm using all these if/then's so that I can put in messages. ifnot Running then
if 0 <= WhichPlayer and WhichPlayer <= 11 then
if GetPlayerSlotState(Player(WhichPlayer)) == PLAYER_SLOT_STATE_PLAYING then set Running = true call DisplayTimedTextToForce( bj_FORCE_ALL_PLAYERS,2., GetPlayerName(TPlayer) + " has requested to kick player " + I2S(WhichPlayer+1) + ".") call Vote() else call DisplayTimedTextToPlayer(TPlayer, 0,0,1.,"|c00FF0000Player(" + I2S(WhichPlayer+1) + ") is not playing!") endif else call DisplayTimedTextToPlayer(TPlayer, 0,0,1.,"|c00FF0000Player(" + I2S(WhichPlayer+1) + ") does not exist!") endif else //This is the only reason why I have a global timer. call DisplayTimedTextToPlayer(TPlayer, 0,0,1.,"|c00FF0000Please wait " + I2S(R2I(TimerGetRemaining(Timer)+0.5)) + " more seconds to request a new vote.") endif endfunction
//=========================================================================== privatefunction PlayerGone takesnothingreturnsnothing set CountPlayers = CountPlayers-1 endfunction
if GetPlayerSlotState(Player(count)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(count)) == MAP_CONTROL_USER then set CountPlayers = CountPlayers + 1 endif
exitwhen count == 0 endloop call TriggerAddAction(trig, function Request)
//----------------------- set trig = CreateTrigger() loop call TriggerRegisterPlayerEvent(trig, Player(count), EVENT_PLAYER_LEAVE) set count = count + 1 exitwhen count == 12 endloop call TriggerAddAction(trig, function PlayerGone)
endfunction
endlibrary
Dialog System
//============================================================================== // DIALOG SYSTEM BY COHADAR -- v2.1b //============================================================================== // // PURPOUSE: // * Displaying dialogs the easy way // * Retrieving dialog results the easy way // // // HOW TO USE: // * Dialog is basically a struct wrapper around native dialog // // * First create a dialog, // # local Dialog d = NewDialog() // // than we add a title, // # call d.SetMessage("Some Text") // // and than we add couple of buttons // # call d.AddButton("First Button", HK_A) // # call d.AddButton("Second Button", HK_B) // # call d.AddButton("Third", HK_C) // // HK_X is a hotkey constant for a button, // there are constants for all letters + numbers 0..9 // hotkeys are not case-sensitive // // now we add a callback method for our dialog // # call d.AddAction( function SomeFunction ) // this is the function witch will be called when a player presses a button // // And finally we show the dialog in one of two ways: // # call d.ShowAll() // Displays dialog to all human players // # call d.Show( player ) // Displays dialog to specified player // // Inside your callback function you can get the clicked Dialog struct like this // local Dialog d = GetTriggerDialog() // and then use d.GetResult() to get the hotkey of a clicked button // // You can also use GetTriggerPlayer() to find out witch player pressed the button // // PROS: // * Extremelly easy to use compared to native dialogs // * It is fool-proof and will warn you if you try to do something stupid // // CONS: // * You can have a maximum of 16 dialog buttons, lol // // DETAILS: // // * Don't release Dialogs before you are sure user has selected something // I recommend to never destroy Dialogs, // just create them when they are first time called and then show/hide them as needed // // REQUIREMENTS: // * ABC v5.1 or higher // // HOW TO IMPORT: // * Just create a trigger named Dialogs // * convert it to text and replace the whole trigger text with this one // //============================================================================== library Dialogs uses ABC
globals privateconstantinteger MAX_BUTTONS = 16 // maximum of buttons on dialog endglobals
//=========================================================================== // Use this inside dialog action function //=========================================================================== function GetTriggerDialog takesnothingreturns Dialog return GetDialogStructA(GetClickedDialog())// ABC endfunction
//=========================================================================== struct Dialog privatetrigger t = CreateTrigger() privatedialog d = DialogCreate() privateboolean isActionSet = false
method GetResult takesnothingreturnsinteger localbutton b = GetClickedButton() localinteger i = 0 loop exitwhen i >= MAX_BUTTONS if b == this.buttons[i]then return this.hotkeys[i] endif set i = i + 1 endloop call BJDebugMsg("|c00FF0000ERROR: Unknown dialog hotkey") return 0 endmethod
method SetMessage takesstring messageText returnsnothing set .messageText = messageText endmethod
method AddButton takesstring buttonText, integer hotkey returnsnothing if this.button_count >= MAX_BUTTONS then call BJDebugMsg("|c00FF0000ERROR: Maximum number of dialog buttons is " + I2S(MAX_BUTTONS)) else set this.buttons[this.button_count] = DialogAddButton( this.d, buttonText , hotkey ) set this.hotkeys[this.button_count] = hotkey set this.button_count = this.button_count + 1 endif endmethod
method AddAction takescode actionFunc returnsnothing if this.isActionSet == truethen call BJDebugMsg("|c00FF0000ERROR: Dialog.AddAction - you cannot set more than one dialog action") else set this.isActionSet = true call TriggerAddAction( this.t, actionFunc ) endif endmethod
method Show takesplayer whichPlayer returnsnothing if this.isActionSet == falsethen call BJDebugMsg("|c00FF0000WARNING: You forgot to set a dialog action") endif if this.button_count == 0 then call BJDebugMsg("|c00FF0000ERROR: You cannot show dialog with no buttons") else // message must be set before every display because of some bug. call DialogSetMessage( this.d, this.messageText ) call DialogDisplay(whichPlayer, this.d, true) endif endmethod
method ShowAll takesnothingreturnsnothing localinteger i = 0 loop exitwhen i>=12 // maximum of human players is 12 if GetPlayerController(Player(i)) == MAP_CONTROL_USER and GetPlayerSlotState(Player(i)) == PLAYER_SLOT_STATE_PLAYING then call this.Show(Player(i)) endif set i = i + 1 endloop endmethod
method HideAll takesnothingreturnsnothing localinteger i = 0 loop exitwhen i>=12 // maximum of human players is 12 call this.Hide(Player(i)) set i = i + 1 endloop endmethod
endstruct
endlibrary
ABC System
//============================================================================== // ABC -- STRUCT ATTACHMENT SYSTEM BY COHADAR -- v5.1b //==============================================================================
//============================================================================== // DOCUMENTATION: //============================================================================== // // PURPOUSE OF ABC: // * Attaching multiple structs to a <handle> // * Not using stupid game cache. // // * Currently supported <handle> types are timer, trigger and dialog // ABC can NOT be used to attach things to units, // Systems that can attach stuff to units require a mission key // ABC does not have mission keys, witch is one of the reasons it is so fast. // // * These are the only 3 handle types I found that need attaching (except units) // If you have the need for some other handle types please let me know // // HOW TO USE: // * Lets assume you want to attach some spell data to a timer. // You would do the following: // // 1. Create struct that will contain all your data. // 2. call SetTimerStructA(myTimer, myStruct) // // and then you decide you need one more struct on that timer... // // call SetTimerStructB(myTimer, myStruct2) // // Then in a periodic timer you just get the stored value // set myStruct = GetTimerStructA(myTimer) // // In your final itearation of periodic timer // you need to clear stored values // ClearTimerStructA(myTimer) // ClearTimerStructB(myTimer) // If you don't system will start to overflow // // DIFFERENCE FROM v5.0: // * You cannot use SetStructA two times on the same <handle> // without clearing the previous value. // // * ABC v5.0 used to overwrite the old values when you did that. // This caused errors when collisions get over 3 // Since collisions almost never happen in real maps noone noticed this before // Only some hardcore tests will detect this // // * New version of ABC treats overwrite as an error. // BAD: SetStructA(X, value1); SetStructA(X, value2) // GOOD: SetStructA(X, value1); ClearStructA(X); SetStructA(X, value2) // // * HASH_COLLISION_LIMIT is reduced from 8 to 7 to simplyfy algorithms // (using null borders at modulo 8) // This effectively means that you can store around 6000 attachments per hash // before you get an overflow. (used to be 7000) // // * This simplyfication increased ABC speed a little. // // PROS: // * ABC is faster than any gamecache based system. // // * you can attach any struct to any supported <handle> type // // * you CAN attach up to 3 structs on the same <handle> // but only if you use different functions, for example // SetTriggerStructA(), SetTriggerStructB(), SetTriggerStructC() // // * get and set functions are extremelly fast (using hash algorithm) // // * System reports collision, overwrite and overflow. // Basically if you do anything stupid system will tell you. // // * This system will work even if your map leaks // and will NOT slow down because of it. // // * This is the system that spits torment test in the eye. // // * For compatibility with ABC v4.6 look at ABCC library // // // CONS: // * you must manually clean the stored value - REMEMBER THIS RULE!!! // Don't forget to use ClearStruct() functions // // * you should NOT use Get without a Set - REMEMBER THIS RULE!!! // It will simply return a zero and nothing bad will happen, // but it will lag really really bad // (system will report this as an error) // // * System starts to collide if you have more than 1024 structs in one hash. // (you can see this very obviosly with -overload test) // If that happens it can mean one of 2 things: // 1. you are using more than 1024 timers, triggers or dialogs - !? // 2. you forgot to use ClearStruct and you are leaking handles somewhere // if this is the case simply do a search on your code and find // what trigger uses ABC but has no ClearStruct calls. // // DETAILS: // * when struct is detached from <handle> it is not destroyed // you still have to do that manually if necessary // // * ABC will not interfere with other attachemt systems // You can freely use any other system alongside ABC // But if you use only ABC for attachments in your map // you don't have to null local variables. // The reason for this is that gamecache gets abnormaly slow // when you don't null locals, ABC does not have this flaw. // // // SPECIAL THANKS TO: // * NagelBagel - for finding errors in versions 4.3 and 4.4 // * Here-b-Trollz - for testing ABC and for making cool spells with it. // * Toadcop - for being pain in the ass and for pushing me to improve ABC. // * emjlr3 - for pointing out the need for non-generic trigger attachments // * PandaMine - I found a bug in ABC by examining his HSAS vs ABC test // * All those people out there who use and support ABC // Thank you guys. // // HOW TO IMPORT: // * Just create a trigger named ABC // * convert it to text and replace the whole trigger text with this one // //==============================================================================
//------------------------------------------------------------------------------ // We will use textmacros to create multiple instances of system //------------------------------------------------------------------------------ //! textmacro ABC takes X, NAME, TYPE
//------------------------------------------------------------------------------ // Global arrays represent our hash tables. // System is currently using 3 hash tables per handle type. (A, B, C) //------------------------------------------------------------------------------ globals private $TYPE$ array $TYPE$Key$X$ privateintegerarray $TYPE$Value$X$ privateinteger $TYPE$maxCollision$X$ = 0 endglobals
//------------------------------------------------------------------------------ // returns the maximum collision so far //------------------------------------------------------------------------------ function Get$NAME$Collision$X$ takesnothingreturnsinteger return $TYPE$maxCollision$X$ endfunction
//------------------------------------------------------------------------------ // initializes hash arrays to prevent lag when ABC is used for the first time //------------------------------------------------------------------------------ privatefunction Init$NAME$Hash$X$ takesnothingreturnsnothing set $TYPE$Key$X$[HASH_INDEX_LIMIT] = null set $TYPE$Value$X$[HASH_INDEX_LIMIT] = 0 endfunction
//------------------------------------------------------------------------------ // attaches struct to a handle by using hash table //------------------------------------------------------------------------------ function Set$NAME$Struct$X$ takes $TYPE$ t, integer s returnsnothing debuglocalinteger collision
// hash using 32-bit integer overflow localinteger i = (H2I(t) * HASH_UP) / HASH_DOWN + HASH_BIAS
if $TYPE$Key$X$[i] == nullthen set $TYPE$Value$X$[i] = s set $TYPE$Key$X$[i] = t return endif
debugif $TYPE$Key$X$[i] == t then debugcall BJDebugMsg("|cFFFF0000ERROR: $NAME$_Hash[$X$] attachment overwrite on #" +I2S(H2I(t))) debugreturn debugendif
// if function gets below this line we have a collision debugset collision = 1 loop debugif collision >= HASH_COLLISION_LIMIT then debugcall BJDebugMsg("|cFFFF0000ERROR: $NAME$_Hash[$X$] overflow") debugreturn debugendif debugset collision = collision + 1
set i = i + 1 exitwhen $TYPE$Key$X$[i] == null
debugif $TYPE$Key$X$[i] == t then debugcall BJDebugMsg("|cFFFF0000ERROR: $NAME$_Hash[$X$] attachment overwrite on #" +I2S(H2I(t))) debugreturn debugendif endloop
debugif collision > $TYPE$maxCollision$X$ then debugcall BJDebugMsg("|cFFFF4444Warning: $NAME$_Hash[$X$] maximum collision is now: " + I2S(collision)) debugset $TYPE$maxCollision$X$ = collision debugendif
set $TYPE$Value$X$[i] = s set $TYPE$Key$X$[i] = t
return endfunction
//------------------------------------------------------------------------------ // gets stored struct from a handle //------------------------------------------------------------------------------ function Get$NAME$Struct$X$ takes $TYPE$ t returnsinteger debuglocalinteger collision
// hash using 32-bit integer overflow localinteger i = (H2I(t) * HASH_UP) / HASH_DOWN + HASH_BIAS
if $TYPE$Key$X$[i] == t then return $TYPE$Value$X$[i] endif
// if function gets below this line we have a collision debugset collision = 1 loop debugif collision >= HASH_COLLISION_LIMIT then debugcall BJDebugMsg("|cFFFF0000ERROR: $NAME$_Hash[$X$] : get request on unknown handle") debugreturn 0 debugendif debugset collision = collision + 1
set i = i + 1 exitwhen $TYPE$Key$X$[i] == t endloop
return $TYPE$Value$X$[i] endfunction
//------------------------------------------------------------------------------ // clears stored struct from a handle, also returns cleared value //------------------------------------------------------------------------------ function Clear$NAME$Struct$X$ takes $TYPE$ t returnsinteger debuglocalinteger collision localinteger ik localinteger ret
// hash using 32-bit integer overflow localinteger i = (H2I(t) * HASH_UP) / HASH_DOWN + HASH_BIAS
// first find the index on witch key is stored debugset collision = 0 loop debugif collision >= HASH_COLLISION_LIMIT then debugcall BJDebugMsg("|cFFFF0000ERROR: $NAME$_Hash[$X$] : clear request on unknown handle") debugreturn 0 debugendif debugset collision = collision + 1
exitwhen $TYPE$Key$X$[i] == t set i = i + 1 endloop
set ik = i set ret = $TYPE$Value$X$[ik]
// then find last used key index in bucket loop set i = i + 1 // we use the fact bucket borders (mod 8 indexes) are always null exitwhen $TYPE$Key$X$[i] == null endloop
// shift last bucket entry to the place of removed one set $TYPE$Key$X$[ik] = $TYPE$Key$X$[i-1] set $TYPE$Value$X$[ik] = $TYPE$Value$X$[i-1] // clear the previous last bucket entry set $TYPE$Key$X$[i-1] = null
return ret endfunction
//! endtextmacro
//============================================================================== // Macro execution -- this is where real functions get created //============================================================================== library ABC initializer Init
globals publicconstantinteger HASH_SIZE = 8192 publicconstantinteger HASH_INDEX_LIMIT = 8190 publicconstantinteger HASH_DOWN = 524288 // 2^19 publicconstantinteger HASH_UP = 2134900736 // 2^22 * 509 publicconstantinteger HASH_BIAS = 4096 // HASH_SIZE / 2 publicconstantinteger HASH_COLLISION_LIMIT = 7 // ABC v5.0 had limit 8 // 509 is the prime closest to 512 endglobals
//------------------------------------------------------------------------------ // conversion function used by the system internally // you will not need to use it directly //------------------------------------------------------------------------------ publicfunction H2I takeshandle h returnsinteger return h return 0 endfunction
endlibrary //============================================================================== // END OF ABC STRUCT ATTACHMENT SYSTEM //==============================================================================
Changelog
Code:
<<--- v.1.11 --->>
* 1 possible bug fix
* Few text changes
* Added a null vote
<<--- v1.01 --->>
* 2 bug fixes
<<--- v1.00 --->>
* Initial Release
if GetPlayerSlotState(Player(count)) == PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(count)) == MAP_CONTROL_USER then set CountPlayers = CountPlayers + 1 endif
exitwhen count == 0 endloop
Why is that if indented? And why is the chat event registration line not in the if?
#3: I've always been far too lazy to remember player IDs. Why not use a syntax that allows colours, player names, or player IDs?
#4: the "-kick player" string is hard-coded in. Thats bad.
#5: Why do you use the DisplayTimedTextToForce() BJ function when you can just use the line call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, duration, message) ?
#6: There are far too few configuration options. No boolean to display or not display who voted? bah.
#7: CustomDefeatBJ() displays a message when not in single player. This is bad, considering you already display a "____ has been kicked" message.
ifnot bj_isSinglePlayer then call DisplayTimedTextFromPlayer(whichPlayer, 0, 0, 60, GetLocalizedString("PLAYER_DEFEATED")) endif
#8: What happens if someone is AFK? The vote just hangs and nothing happens untill he comes back? lame.
#9: Player names aren't displayed with that players colour? Lame.
#10: Two dependencies for such a little system? mhhh. Not too awesome.
__________________
Giving reputation is a nice way to say thank you to someone that helps you!