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

[vJASS] ChargedAbility

JASS:
library ChargedAbility/*v1.2
*************************************************************************************
*
*   Charged Ability
*
*   Allows you to apply a charge-like feature to abilities.
*
*   a "Charged Ability" is made of an array of abilities called "states", where each 
*   represents a charge value. Whenever the charge is changed, it removes the previous
*   state and then replaces it with the new state based on the current charge value.
*
*************************************************************************************
*
*   */ uses /*
*
*       */ Table /* hiveworkshop.com/forums/jass-functions-413/snippet-new-table-188084/
*
*************************************************************************************
*
*   API
*
*       static method create takes integer base returns thistype
*           - Creates an instance for the ability with charges
*           - "base" is the ability when the "ability" has 0 charges.
*
*       method setState takes integer abil, integer charge returns nothing
*           - set the ability as the charge state for "charge"
*           - adding an ability with charge greater than the max charges
*             will automatically increase the max charges and then puts the
*             ability on that position.
*
*       method removeState takes integer charge returns nothing
*           - removes the state
*           - this automatically pushes the next indexes after it to it's position.
*               * for example, if the charge state removed was 2, 3 will be pushed to
*                 2, 4 will be pushed to 3 and so on.
*
*       method pushState takes integer abil returns nothing
*           - pushes an ability to the full charge state.
*
*       method popState takes nothing returns nothing
*           - removes the ability on full charge state.
*           - replaced by the charge state before it.
*
*
*       method add takes unit u, integer charge, integer level returns nothing
*           - adds the ability to unit u, defined by charge. level is optional.
*
*       method setCharge takes unit u, integer charge, integer level returns nothing
*           - Sets the ability charge to a unit. level is optional.
*
*       method getCharge takes unit u returns integer
*           - gets the current charge value
*
*       method incCharge takes unit u, integer level returns nothing
*           - Adds a charge to the unit. level is optional.
*
*       method decCharge takes unit u, integer level returns boolean
*           - Removes a charge from a unit. level is optional.
*
*       method isFull takes unit u returns boolean
*           - Checks whether the unit has full charges.
*
*       method isEmpty takes unit u returns boolean
*           - Checks wheter the unit has empty charges.
*
*       method emptyCharges takes unit u, integer level returns nothing
*           - Empties the charges(sets charge to 0)
*
*       method fillCharges takes unit u, integer level returns nothing
*           - Fills the charges (sets charge to max value)
*
*       method setChargeLevel takes unit u, integer level returns nothing
*           - Sets the ability level for charges
*
*************************************************************************************
*
*       Note
*
*       The reason "level" (the ability level for all states) is optional on most of 
*       the parameters is that the system fills it with 2 default values whenever the
*       value for level is unprovided.
*       This 2 default values are:
*           1 - applied if a unit receives the one of the states, only if the unit
*               never received any of it's states.
*           the current state level - applied if a unit already has one of the states
*
*       You can still change the ability level through setChargeLevel
*
*************************************************************************************
*
*       Credits
*
*       Bribe - Table
*
*************************************************************************************/

    struct ChargedAbility
        private Table abils
        private integer charges
        
        static method create takes integer base returns thistype
            local thistype this = allocate()
            set abils = Table.create()
            set charges = 0
            set abils[0] = base
            return this
        endmethod
        
        method setState takes integer abil, integer charge returns nothing
            if charge > 0 then
                if charge > charges then
                    set charges = charges + 1
                    set abils[charges] = abil
                else
                    set abils[charge] = abil
                endif
            endif
        endmethod
        
        method removeState takes integer charge returns nothing
            if charges >= charge and charge > 0 then
                loop
                    exitwhen charge == charges
                    set abils[charge] = abils[charge + 1]
                    set charge = charge + 1
                endloop
                set charges = charges - 1
            endif
        endmethod
        
        
        method pushState takes integer abil returns nothing
            call setState(abil, charges + 1)
        endmethod
        
        method popState takes nothing returns nothing
            call removeState(charges)
        endmethod
        
        method add takes unit u, integer charge, integer level returns nothing
            call UnitAddAbility(u, abils[charge])
            call SetUnitAbilityLevel(u, abils[charge], level)
        endmethod
        
        method getCharge takes unit u returns integer
            local integer i
            if u != null then
                set i = 0
                loop
                    exitwhen i == charges
                    if GetUnitAbilityLevel(u, abils[i]) > 0 then
                        return i
                    endif
                    set i = i + 1
                endloop
            endif
            return -1
        endmethod
        
        method isFull takes unit u returns boolean
            if u != null then
                return GetUnitAbilityLevel(u, abils[charges]) > 0
            endif
            return false
        endmethod
        
        method isEmpty takes unit u returns boolean
            if u != null then
                return GetUnitAbilityLevel(u, abils[0]) > 0
            endif
            return false
        endmethod
        
        method setCharge takes unit u, integer charge, integer level returns nothing
            local integer c
            if charge <= charges and charge >= 0 and u != null then
                set c = getCharge(u)
                if c > -1 then
                    if level <= 0 then
                        set level = GetUnitAbilityLevel(u, abils[c])
                        if level == 0 then
                            set level = 1
                        endif
                    endif
                    call UnitRemoveAbility(u, abils[c])
                    call UnitAddAbility(u, abils[charge])
                    call SetUnitAbilityLevel(u, abils[charge], level)
                endif
            endif
        endmethod
        
        method incCharge takes unit u, integer level returns nothing
            call setCharge(u, getCharge(u) + 1, level)
        endmethod
        
        method decCharge takes unit u, integer level returns boolean
            local integer c = getCharge(u)
            if c < 0 then
                return false
            endif
            call setCharge(u, c - 1, level)
            return true
        endmethod
        
        method emptyCharges takes unit u, integer level returns nothing
            local integer c = getCharge(u)
            if c > 0 then
                call setCharge(u, 0, level)
            endif
        endmethod
        
        method fillCharges takes unit u, integer level returns nothing
            local integer c = getCharge(u)
            if c < charges and c >= 0 then
                call setCharge(u, charges, level)
            endif
        endmethod
        
        method setChargeLevel takes unit u, integer level returns nothing
            local integer c = getCharge(u)
            if c >= 0 then
                call SetUnitAbilityLevel(u, abils[c], level)
            endif
        endmethod
    endstruct
endlibrary
Test code:
JASS:
struct Tester extends array

    static ChargedAbility bottle
    
    private static method onCast takes nothing returns nothing
        local unit u = GetTriggerUnit()
        /*
        *   remove one charge from unit
        */
        call bottle.decCharge(u, 1)
        /*
        *   check if unit has empty charges
        */
        if bottle.isEmpty(u) then
            call TriggerSleepAction(2.0)
            call BJDebugMsg("Charges refilled")
            /*
            *   add one charge to unit
            */
            call bottle.incCharge(u, 1)
            /*
            *   or just refill it :D
            */
            call bottle.fillCharges(u, 1)
        endif
        set u = null
    endmethod
    
    private static method onInit takes nothing returns nothing
        local trigger t = CreateTrigger()
        /*
        *   Create an instance called "bottle" with 'bot0' as the 0 charge state
        */
        set bottle = ChargedAbility.create('bot0')
        /*
        *   let 'bot1' represent the charge value of 1
        */
        call bottle.setState('bot1', 1)
        /*
        *   let 'bot2' represent the charge value of 2
        */
        call bottle.setState('bot2', 2)
         /*
        *   add ability to unit.
        */
        call bottle.add(gg_unit_Hpal_0001, 2, 1)
        call TriggerRegisterAnyUnitEventBJ(t, EVENT_PLAYER_UNIT_SPELL_EFFECT )
        call TriggerAddAction(t, function Tester.onCast)
    endmethod
endstruct
 

Attachments

  • Charged Ability.w3x
    32.6 KB · Views: 122
Last edited:

Bribe

Code Moderator
Level 50
Joined
Sep 26, 2009
Messages
9,464
The description is all but nonexistent. Going over the code, I think what this does is treat an ability like it's a charged item, but the user has to manually decrease charges. I'm not sure why multiple abilities are used. The installation needs to be documented as after going over all the API I have no idea what the parameters represent.

If my understanding of this resource was correct, then some additional advice I give you is to couple the spell event with this resource so when the effect happens the system automatically removes a charge.
 
Yeah, it's my fault that the description was not that comprehensible. I will try to create a new description.

The reason I didn't add a Spell event is because the system can also be treat as a toggle system or a switch ability system, and also items may trigger the event.


the purpose of the multiple abilities is that each ability represents an specific charge. Further explanations will be added after I fix the description :)

[edit]
Updated:
I have expanded the description ( a bit ) and tried to make it more comprehensible.
Added a new method "add", so that users won't have a problem adding the ability to a unit.
Renamed "popCharge" and "pushCharge" to "decCharge" and "incCharge"
 
Last edited:
I'm thinking about adding it to my map. But i would add it as a buyable item in a shop. A kind of magic bottle which fills up every 5min or something like that. Is it possible to use it as an item?

No. this system is made for abilities, specifically unit abilities.

if you want a magic bottle that refills, then you might want to use triggers to add charges or if you want, i might want to make an ItemState library with the same funcionality as what Dota provides(like their bottle mechanics, power treads, ring of basilius and aquilla, etc.)
 
The wording "charge" seems misleading for me. It is a List/Chain/Stack of abilites which the user can use to change abilities.

Allowing random "charge" would be useful.

It actually could be used I guess, might be handy in cases.
I even would suggest to write an addon to allow to add lists of abilites, so first ability is an element of {List_1_Element_1, List_1_Element_2, List_1_Element_3}, next ability when "increas the charge" is an element of {List_2_Element_1, List_2_Element_2, List_2_Element_3}, etc, also with modiyable chances for each element to be picked.

Edit: Seems author is not activ, gy for now, you can PM me anytime when you're back.
 
Last edited:
Top