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

[Snippet]Vote

Kazeon

Hosted Project: EC
Level 34
Joined
Oct 12, 2011
Messages
3,449
be wise! use this library from now :v

demo code is important here, you must read it bcs this is not a so easy to use system.
JASS:
library Vote /* v1.4 by Dalvengyr

    This library provides a voting system which you may determine the action
    when the voting is closed and whether its succeed or not. Success in this
    library means when a votings point reach the required vote. You are able
    to start as many as votings as you want at once. The next voting will be
    started right after the previous one has ended. See demo code to understand
    more how to use this.
    
    Link:
    [url]www.hiveworkshop.com/forums/submissions-414/snippet-vote-251241-new/[/url]
    
    
    API
    
    1. Start a new voting
    function StartVote takes integer requiredVote, real voteUptime, code func returns Vote
    
    2. End a voting
    function EndVote takes Vote whichVote returns nothing
    
    3. Add point(s) to a voting, when points >= required votes then the voting will be marked as succeed
       This also returns the current vote points of that voting
    function AddVotePoint takes Vote whichVote, integer amount returns integer
    
    4. You may start multiple votings at once so this function returns the votings index on that period
    function GetVoteIndex takes Vote whichVote returns integer
    
    5. Set a new voting requirement
    function SetVoteRequirement takes Vote whichVote, integer amount returns nothing
    
    
    Event Responses
    
    1. Return the current opened voting
    function GetTriggeringVote takes nothing returns Vote
    
    2. Return true when points >= required votes
    function IsVoteSuccess takes nothing returns boolean
    
    
    Methods
    
    1. Set a new voting up
    static method setup takes integer requiredVote, real voteUptime, code func returns thistype
    
    2. Add point(s) to a voting
       This also returns the current vote points of that voting
    method add takes integer amount returns integer
    
    3. End a voting
    method end takes nothing returns nothing
    
    4. Set a new voting requirement
    method require takes integer amount returns nothing
*/

    globals
        // This is the only thing which is configurable in this library
        private constant real ACCURACY = .03
        // Furthermore, edit it with your own risk
        private boolean IsSuccess = false
        private integer Total = -1
        private integer Done = 0
        private timer Timer = CreateTimer()
        private Vote array This
    endglobals
    
    function StartVote takes integer requiredVote, real voteUptime, code func returns Vote
        return Vote.setup(requiredVote, voteUptime, func)
    endfunction
    
    function EndVote takes Vote whichVote returns nothing
        call whichVote.end()
    endfunction
    
    function AddVotePoint takes Vote whichVote, integer amount returns integer
        return whichVote.add(amount)
    endfunction
    
    function SetVoteRequirement takes Vote whichVote, integer amount returns nothing
        call whichVote.require(amount)
    endfunction
    
    function GetVoteIndex takes Vote whichVote returns integer
        return whichVote.Index
    endfunction
    
    function GetTriggeringVote takes nothing returns Vote
        return This[0]
    endfunction
    
    function IsVoteSuccess takes nothing returns boolean
        return IsSuccess
    endfunction
    
    struct Vote
        
        integer Point
        integer Required
        integer Index
        real Duration
        trigger Trigger
        
        static method setup takes integer requiredVote, real voteUptime, code func returns thistype
        
            local thistype this = thistype.allocate()
            
            set Total = Total + 1
            set This[Total] = this
            set .Point = 0
            set .Required = requiredVote
            set .Index = Total + Done
            set .Duration = voteUptime
            set .Trigger = CreateTrigger()
            call TriggerAddCondition(.Trigger, Condition(func))
            if Total == 0 then
                call TimerStart(Timer, ACCURACY, true, function thistype.onPeriodic)
            endif
            
            return this
        endmethod
        
        method add takes integer amount returns integer
            set .Point = .Point + amount
            return .Point
        endmethod
        
        method require takes integer amount returns nothing
            set .Required = amount
        endmethod
        
        method end takes nothing returns nothing
        
            local boolean b
        
            if Total > -1 then
                set b = IsSuccess
                if .Point >= .Required then
                    set IsSuccess = true
                endif
                call TriggerEvaluate(.Trigger)
                call DestroyTrigger(.Trigger)
                call .destroy()
                set IsSuccess = b
            endif
            
        endmethod
        
        private static method onPeriodic takes nothing returns nothing
        
            local thistype this = This[0]
            
            if .Duration > 0. then
                set .Duration = .Duration - ACCURACY
                if .Duration <= ACCURACY then
                    call .end()
                endif
            endif
            
        endmethod
        
        private method destroy takes nothing returns nothing
            
            local integer i = 0
            
            loop
                exitwhen i == Total
                set This[i] = This[i + 1]
                set i = i + 1
            endloop
            call .deallocate()
            set Total = Total - 1
            if Total < 0 then
                set Done = 0
                call PauseTimer(Timer)
            else
                set Done = Done + 1
            endif
            
        endmethod
        
    endstruct
    
endlibrary

JASS:
library Demo initializer ini uses Vote

    /* !! Read this paragraph first !!
        Okay, its not so easy to use this system, you have to understand some
        tricks in this system to declare a proper voting. So here is an example
        how to properly declare a voting.
    */

    // Anticipating multiple voting declaration so we need these variables
    globals
        private integer Total = -1
        private Vote array v
    endglobals

    // To ease you understand :v this function is executed when a voting is ended
    function show takes nothing returns boolean
    
        local integer i = 0
        local integer j
        
        loop
            exitwhen i > Total
            // If ended-voting matched one of started votings
            if GetTriggeringVote() == v[i] then
                // If the voting was success
                if IsVoteSuccess() then
                    // Nah, look here. (GetVoteIndex(v[i]) + 1) is equal to votings index at declaration
                    // At voting declaration, votings are placed in order. So the first declared voting
                    // has 0 as index, the second has 1, the third has 2, etc.
                    call BJDebugMsg("Your " + I2S(GetVoteIndex(v[i]) + 1) + "th voting was succeed")
                else
                    // Same here
                    call BJDebugMsg("Your " + I2S(GetVoteIndex(v[i]) + 1) + "th voting was FAIL! :v")
                endif
                // Look at here!! this is one important thing
                // Look closely at how I de-index them. It's different with common index recycling.
                // Why? Because the votings must be placed in order and we must keep that order.
                // Otherwise, the voting won't be executed in order as our expectation.
                set j = 0
                loop
                    exitwhen j == Total
                    set v[j] = v[j + 1]
                    set j = j + 1
                endloop
                set Total = Total - 1
                set i = i - 1
            endif
            set i = i + 1
        endloop
        
        return false
    endfunction

    private function act takes nothing returns boolean
        
        // Declare a new voting
        if GetEventPlayerChatStringMatched() == "-start" then
            set Total = Total + 1
            // Voting requires 1 point to be marked as succeed
            // will be ended after 15. seconds
            // and will execute a function named show when the voting is ended
            set v[Total] = Vote.setup(1, 15., function show)
            // Or call StartVote(1, 15., function show)
            // Show debug message right after declaration
            // Well, it's hard to explain why, you need to understand it by yourself
            call BJDebugMsg("You have just started " + I2S(GetVoteIndex(v[Total]) + 1) + "th voting")
        // Close a voting
        elseif GetEventPlayerChatStringMatched() == "-end" then
            // Show debug message right before the index is recycled
            call BJDebugMsg("You have just ended " + I2S(GetVoteIndex(v[0]) + 1) + "th voting")
            // Always use 0 as index to access current executed voting
            // Don't be confused, v is a "Vote" global variable
            // So v[0] is the curren executed Vote variable
            call v[0].end()
            // Or call EndVote(v[0])
        // When a player is voting for (agreed with the given statement)
        elseif GetEventPlayerChatStringMatched() == "-yes" then
            call BJDebugMsg(GetPlayerName(GetTriggerPlayer()) + " has voted for your " + I2S(GetVoteIndex(v[0]) + 1) + "th voting")
            // As I said before, when you add a point to v[0] it will give point to current executed voting
            call AddVotePoint(v[0], 1)
            // Or call v[0].add(1)
        endif
        
        return false
    endfunction
    
    /* Nah, that was an example how to declare multiple votings at once
       and handle them properly.
       Dont worry, mostly you will just need to declare one voting at once.
       How? it is much more simple. First, show a message to players, as
       example: "Dalvengyr is cool? Type '-yes' if you agree"
       and do the exact same things like the example above (how to add points,
       how to declare and stop a voting)
       
       But, you need some additional conditions so that a player cannot vote for
       multiple times which you must configure it by yourself :p Good luck
    */

    private function ini takes nothing returns nothing

        local trigger t = CreateTrigger()
        
        call TriggerRegisterPlayerChatEvent(t, Player(0), "-start", false)
        call TriggerRegisterPlayerChatEvent(t, Player(0), "-end", false)
        call TriggerRegisterPlayerChatEvent(t, Player(0), "-yes", false)
        call BJDebugMsg("Enter \"-start\" to start a new voting. And enter \"-end\" to close current voting")
        call BJDebugMsg("Enter \"-yes\" to add 1 point to the current voting")
        call TriggerAddCondition(t, Condition(function act))
        
    endfunction
    

endlibrary
 
Last edited:

Kazeon

Hosted Project: EC
Level 34
Joined
Oct 12, 2011
Messages
3,449
okay, I admit! struct is beautiful :v

there is a minor update but I wont change the version since it was just some fixes at documentations

EDIT:
someone please rename this thread to "[Snippet] Vote" :V

EDIT 2:
or "[System] Vote" ? whatever

EDIT 3:
wait a minute, the system hasn't worked correctly, I need to somehow write my own destroy() method which I don't know how :v

EDIT 4:
updated. Now it works correctly, time to optimize it :3

about example, no worry, I will upload a vote system at spell section which will show you how to use this library at so maaaaany cases, basicaly you can use this to vote for everything, and with particular trick you can even give multiple options for your voting.

updated to v1.4
it works correctly actually, but if nobody find it useful so please just gy.. :3 because it's quite hard to use this..
 
Last edited:
Top