1. Are you planning to upload your awesome spell or system to Hive? Please review the rules here.
    Dismiss Notice
  2. Updated Resource Submission Rules: All model & skin resource submissions must now include an in-game screenshot. This is to help speed up the moderation process and to show how the model and/or texture looks like from the in-game camera.
    Dismiss Notice
  3. DID YOU KNOW - That you can unlock new rank icons by posting on the forums or winning contests? Click here to customize your rank or read our User Rank Policy to see a list of ranks that you can unlock. Have you won a contest and still havn't received your rank award? Then please contact the administration.
    Dismiss Notice
  4. The Lich King demands your service! We've reached the 19th edition of the Icon Contest. Come along and make some chilling servants for the one true king.
    Dismiss Notice
  5. The 4th SFX Contest has started. Be sure to participate and have a fun factor in it.
    Dismiss Notice
  6. The poll for the 21st Terraining Contest is LIVE. Be sure to check out the entries and vote for one.
    Dismiss Notice
  7. The results are out! Check them out.
    Dismiss Notice
  8. Don’t forget to sign up for the Hive Cup. There’s a 555 EUR prize pool. Sign up now!
    Dismiss Notice
  9. The Hive Workshop Cup contest results have been announced! See the maps that'll be featured in the Hive Workshop Cup tournament!
    Dismiss Notice
  10. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

Ability Level up System 2.0

Submitted by -Kobas-
This bundle is marked as approved. It works and satisfies the submission rules.

Ability Level up System


Created on request for Spartipilo

You can buy item from shop and learn or level up your ability.
Difference from other systems is that this one will check some conditions like:

Has hero enough stats or level.

Triggers

  • Globals
    • Events
    • Conditions
    • Actions
      • Set KSHash = (Last created hashtable)


Code (vJASS):

    // ---------------------------------------------------------
    //                ABILITY LEVEL UP SYSTEM
    //             CREATED BY -KOBAS- ON REQUEST
    //                      VERSION 2.0
    // ---------------------------------------------------------


function ItemSystemSetup takes nothing returns nothing
    local integer ItemId
    set udg_KSHash = InitHashtable()
   
    set ItemId = 'I000' //FOR ITEM -> 'I000'
    call SaveInteger(udg_KSHash, ItemId,  0,    0  ) //Required Agility
    call SaveInteger(udg_KSHash, ItemId,  1,   40  ) //Required Intelligence
    call SaveInteger(udg_KSHash, ItemId,  2,    0  ) //Required Strength
    call SaveInteger(udg_KSHash, ItemId,  3,    0  ) //Required Level
    call SaveInteger(udg_KSHash, ItemId,  4,   10  ) //Ability Max Level
    call SaveInteger(udg_KSHash, ItemId,  5,    0  ) //Item Gold Cost
    call SaveInteger(udg_KSHash, ItemId,  6,    2  ) //Item Lumber Cost
    call SaveInteger(udg_KSHash, ItemId,  7, 'A000') //Ability Id
   
    set ItemId = 'I001' //FOR ITEM -> 'I001'
    call SaveInteger(udg_KSHash, ItemId,  0,    0  ) //Required Agility
    call SaveInteger(udg_KSHash, ItemId,  1,    0  ) //Required Intelligence
    call SaveInteger(udg_KSHash, ItemId,  2,   40  ) //Required Strength
    call SaveInteger(udg_KSHash, ItemId,  3,    0  ) //Required Level
    call SaveInteger(udg_KSHash, ItemId,  4,   10  ) //Ability Max Level
    call SaveInteger(udg_KSHash, ItemId,  5,    3  ) //Item Gold Cost
    call SaveInteger(udg_KSHash, ItemId,  6,    0  ) //Item Lumber Cost
    call SaveInteger(udg_KSHash, ItemId,  7, 'A001') //Ability Id
   
    // ---------------------------------------------------------
    //        HERE YOU CAN EDIT MSG DISPLAYED TO PLAYER
    // ---------------------------------------------------------
    call SaveStr(udg_KSHash, 0,  0, "Hero ability is already max level") //MSG Shown when unit has already ability level set to max
    call SaveStr(udg_KSHash, 0,  1, "Hero stats are low")                //MSG Shown when unit don't have required stats
    call SaveStr(udg_KSHash, 0,  2, "Hero level is low")                 //MSG Shown when unit don't have required level
    // ---------------------------------------------------------
    //   HERE YOU CAN EDIT SPECIAL EFFECTS DISPLAYED TO PLAYERS
    // ---------------------------------------------------------
    call SaveStr(udg_KSHash, 1,  0, "Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl") //Special Effect path: Learn ability
    call SaveStr(udg_KSHash, 1,  1, "Abilities\\Spells\\Human\\HolyBolt\\HolyBoltSpecialArt.mdl") //Special Effect path: level up ability
    call SaveStr(udg_KSHash, 1,  2, "Abilities\\Spells\\Items\\AIil\\AIilTarget.mdl")             //Special Effect path: Error
    // ---------------------------------------------------------
endfunction

function ItemSystemCleanUp takes integer id, integer i returns nothing
    call SetPlayerState( GetTriggerPlayer(), PLAYER_STATE_RESOURCE_LUMBER, ( GetPlayerState( GetTriggerPlayer() ,PLAYER_STATE_RESOURCE_LUMBER) + LoadInteger(udg_KSHash, id, 6) ) ) // We add lumber back to player
    call SetPlayerState( GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD, ( GetPlayerState( GetTriggerPlayer() ,PLAYER_STATE_RESOURCE_GOLD) + LoadInteger(udg_KSHash, id, 5) ) )     // We add gold back to player
    call DisplayTextToPlayer(GetTriggerPlayer(), 0, 0, LoadStr(udg_KSHash, 0, i))
    call DestroyEffect(AddSpecialEffect(LoadStr(udg_KSHash, 1, 2),GetUnitX(GetTriggerUnit()),GetUnitY(GetTriggerUnit())))
endfunction

function ItemSystem takes nothing returns nothing
    local integer ItemId = GetItemTypeId(GetManipulatedItem())
    local unit u = GetTriggerUnit()
   
    // ---------------------------------------------------------
    //                   NO NEED TO BE CHANGED
    // ---------------------------------------------------------
    if GetHeroLevel(u) >= LoadInteger(udg_KSHash, ItemId, 3) then
        if GetHeroAgi(u, false) >= LoadInteger(udg_KSHash, ItemId, 0) and GetHeroInt(u, false) >= LoadInteger(udg_KSHash, ItemId, 1) and GetHeroStr(u, false) >= LoadInteger(udg_KSHash, ItemId, 2) then
            if GetUnitAbilityLevel(u, LoadInteger(udg_KSHash, ItemId, 7)) == 0 then
                call UnitAddAbility(u, LoadInteger(udg_KSHash, ItemId, 7))
                call UnitMakeAbilityPermanent(u,true, LoadInteger(udg_KSHash, ItemId, 7))
                call DestroyEffect(AddSpecialEffect(LoadStr(udg_KSHash, 1, 0),GetUnitX(u),GetUnitY(u)))
            elseif GetUnitAbilityLevel(u, LoadInteger(udg_KSHash, ItemId, 7)) == LoadInteger(udg_KSHash, ItemId, 4) then
                call ItemSystemCleanUp(ItemId, 0)
            else
                call IncUnitAbilityLevel(u, LoadInteger(udg_KSHash, ItemId, 7))
                call DestroyEffect(AddSpecialEffect(LoadStr(udg_KSHash, 1, 1),GetUnitX(u),GetUnitY(u)))
            endif
        else
            call ItemSystemCleanUp(ItemId, 1)
        endif
    else
        call ItemSystemCleanUp(ItemId, 2)
    endif
    call SetWidgetLife(GetManipulatedItem(),0.406)
    call RemoveItem(GetManipulatedItem())
    set u = null
endfunction

    // ---------------------------------------------------------
    // BJ BELOW WILL TRIGGER THIS FOR ANY PLAYER SO NO NEED FOR
    // CORRECTIONS, OFC EDIT IT IN CASE YOU USE THIS FOR 1 PLAYER
    // EXAMPLE FOR PLAYER RED:
    // TriggerRegisterPlayerUnitEvent(gg_trg_Kobas_System, player(0), EVENT_PLAYER_UNIT_PICKUP_ITEM, null)
    // ---------------------------------------------------------
function InitTrig_Kobas_System takes nothing returns nothing
    set gg_trg_Kobas_System = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_Kobas_System, EVENT_PLAYER_UNIT_PICKUP_ITEM )
    call TriggerAddAction( gg_trg_Kobas_System, function ItemSystem )
    call ItemSystemSetup()
endfunction
 

Version 2.0
- Fixed another small error pointed by Maker
Version 1.9
- Fixed small errors pointed by Maker
Version 1.8
- Optimized
Version 1.7
- Replaced vjass globals with user defined globals
- Added gui trigger for easier import
Version 1.6
- Used hashtables
Version 1.5
- Added Special Effects
- Replaced globals with user defined globals
- Added GUI trigger for easy import
- Optimized script a little
Version 1.4
- Fixed silly bag (Thanks to Magtheridon96 for creating and fixing same :razz:)
Version 1.3
- Fixed that Remove Item problems
- Optimized code a little
Version 1.2
- Replaced annoying if the else block (Thanks to Magtheridon96)
- Added permanent ability thing (Thanks to Maker)
Version 1.1
- Uploaded spell here

Opinions please.

Keywords:
Ability, Item, Learn, Level up, Requirements, System, -Kobas-
Contents

ABILITY LEVEL UP SYSTEM (Map)

Reviews
Moderator
Approved. You could set triggering unit into a local variable in cleanup trigger. Additionally, you don't have to save 0 values for integers into hashtable. Integers are 0 by default. That could make it easier to add new item types....
  1. Maker, Ability Level up System 2.0, 23rd Nov 2011

    Approved.

    You could set triggering unit into a local variable in cleanup trigger.
    Additionally, you don't have to save 0 values for integers into hashtable. Integers are 0 by default. That could make it easier to add new item types.


    Old reviews

    Maker, Ability Level up System 1.6, 2nd Nov 2011

    Code (vJASS):

    function InitTrig_Kobas_System_Setup takes nothing returns nothing
        set gg_trg_Kobas_System_Setup = CreateTrigger(  )
        call TriggerAddAction( gg_trg_Kobas_System_Setup, function ItemSystemSetup )
    endfunction
     

    ->
    Code (vJASS):

    function InitTrig_Kobas_System_Setup takes nothing returns nothing
        call ItemSystemSetup()
    endfunction
     

    ^You don't really need to create a trigger there.

    The system removes all acquired items. You need to test that the item type is initialized, with HaveSavedInteger() for example.

    You could store triggering unit into a variable in ItemSystem function
    You could use only one trigger, combine Loop and Setup.
    ItemSystemCleanUp could take player as a parameter.


    16:34, 1st Nov 2011
    Pharaoh_: Don't force the use of JNGP just for a block of globals. Turn them to udg, to result plain Jass.
     
  2. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Code (vJASS):
    // ---------------------------------------------------------
        // THIS CAN BE REMOVED WHEN YOU IMPORT SYSTEM INTO YOUR MAP
        // ---------------------------------------------------------
        call SetPlayerState( Player(0), PLAYER_STATE_RESOURCE_GOLD, 50 )
        call SetPlayerState( Player(0), PLAYER_STATE_RESOURCE_LUMBER, 50 )


    Here's a trick:

    In the testmap, create an empty trigger and paste this in it:

    Code (vJASS):

    library IN_TEST_MAP
    endlibrary
     


    Then, inside the system, all you have to do is this:

    Code (vJASS):

    static if LIBRARY_IN_TEST_MAP then
        call SetPlayerState( Player(0), PLAYER_STATE_RESOURCE_GOLD, 50 )
        call SetPlayerState( Player(0), PLAYER_STATE_RESOURCE_LUMBER, 50 )
    endif


    Or, you can do it in some seperate trigger only for the testmap.

    Code (vJASS):
    if ID == 'I000' then
        set i = 1
        elseif ID == 'I001' then
        set i = 2
        endif


    ->


    set i = 1 + ID - 'I000'


    Yes, I know it isn't safe, but it's fast :p
    All you have to do is add a boolean to list of globals that checks whether an item is registered or not.
     
  3. Pharaoh_

    Pharaoh_

    Joined:
    Nov 6, 2008
    Messages:
    8,127
    Resources:
    11
    Icons:
    3
    Skins:
    1
    Spells:
    6
    Tutorials:
    1
    Resources:
    11
    • Players don't need to be nulled.
    • GetOwningPlayer(u): You can change it to its faster pal, GetTriggerPlayer().
    Code (vJASS):
        if ID == 'I000' then
        set i = 1
        elseif ID == 'I001' then
        set i = 2
        endif

    Use a loop instead of a possibly huge if/then/else statement and register the Item Types in the globals (= make them configurable), just like you did with the abilities.
    • Not confirmed, but RemoveItem() might cause a leak. To be safe, add SetWidgetLife (Item, 0) before that line. If you use this one, the item "dies", so RemoveItem() is no longer needed. However, keep it, in case the item's model has no death animation (which is by extension affected by the Gameplay Constants values for the effect's death).
    • Globals imply vJass; you should use a library.
     
  4. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Yeah, but doing so is a better practice.

    It does cause a leak, but you shouldn't do that :p
    You should
    call SetWidgetLife(item,0.406)
    , then remove it because only dead items cant be removed.

    True ^^
     
  5. -Kobas-

    -Kobas-

    Joined:
    Jan 17, 2010
    Messages:
    5,894
    Resources:
    28
    Icons:
    1
    Tools:
    2
    Maps:
    10
    Spells:
    4
    Template:
    5
    Tutorials:
    6
    Resources:
    28
    Thank you guys a lot, this whole jass in new to me, I code like week and half with it for now :)

    I will improve it as soon as possible.
     
  6. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,052
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    There is a big thing going around that says no nulling player handles
    causes the RAM to go up over time. I want to look into this but in lieu
    of it I recommend nulling every local handle variable.
     
  7. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,181
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    When you add an ability, you could use UnitMakeAbilityPermanent() so the bonus stays even when morped.

    You could utilize SimError library, make it optional.
     
  8. -Kobas-

    -Kobas-

    Joined:
    Jan 17, 2010
    Messages:
    5,894
    Resources:
    28
    Icons:
    1
    Tools:
    2
    Maps:
    10
    Spells:
    4
    Template:
    5
    Tutorials:
    6
    Resources:
    28
    There I improved it, fixed suggested, tested it again and everything works fine.

    Sorry about that library and things related to vjass I still didn't started learning it :sad:
    Usually I just make things work, but in this case I want to learn more about efficiency :)

    Thank you for your time :)
    I would like to hear some opinions about system usefulness as well :)
     
  9. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Oh Shit!

    local integer i = 1 + ID - 'I000'


    How stupid of me :D

    That wouldn't work unless you register ALL the items starting from 'I000' and only increasing the IDs by 1 each time ^^

    You could do this instead:

    Create an integer array for the item ids.
    Whenever you add an item to the system, set it's ID to:
    Code (vJASS):

    set itemIds[counter] = The Item ID
    set counter = counter + 1
     


    counter should originally be 0.

    When you want to find the integer i in the function, do this:

    Code (vJASS):

    local integer i = -1
    local integer k = 0
    loop
        exitwhen k==counter
        if itemIds[k]==ID then
            set i = k
            exitwhen true
        endif
        set k=k+1
    endloop
    if i==-1 then
        return
    endif
     
  10. Maker

    Maker

    Joined:
    Mar 6, 2006
    Messages:
    9,181
    Resources:
    17
    Maps:
    2
    Spells:
    14
    Tutorials:
    1
    Resources:
    17
    ^exiwthen null?
     
  11. Magtheridon96

    Magtheridon96

    Joined:
    Dec 12, 2008
    Messages:
    6,006
    Resources:
    26
    Maps:
    1
    Spells:
    8
    Tutorials:
    7
    JASS:
    10
    Resources:
    26
    Huh? :p

    edit
    Looking good :)

    One last fix:
    Use local triggers in the InitTrig_ functions because using the globals is quite cumbersome :p
     
    Last edited: Sep 19, 2011
  12. -Kobas-

    -Kobas-

    Joined:
    Jan 17, 2010
    Messages:
    5,894
    Resources:
    28
    Icons:
    1
    Tools:
    2
    Maps:
    10
    Spells:
    4
    Template:
    5
    Tutorials:
    6
    Resources:
    28
    Well I edited code once again and it works...
    Thank you once again :)
     
  13. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    A lol suggestion:
    Code (vJASS):

        // ---------------------------------------------------------
        // IT IS EASIER NOW TO WRITE 1 OR 2 BUT AFTER 20 ITEMS
        //             INTEGER i WILL SAVE YOU TIME
        // ---------------------------------------------------------
     


    interger i no longer exists, it's [COUNTER] now :p (at least in the Global one, since it's 'i' again in the second trigger)

    EDIT: You could make some small modifications to release a 'Item Requirement System'. One of these would make a big change in the upcoming RPG.
     
  14. -Kobas-

    -Kobas-

    Joined:
    Jan 17, 2010
    Messages:
    5,894
    Resources:
    28
    Icons:
    1
    Tools:
    2
    Maps:
    10
    Spells:
    4
    Template:
    5
    Tutorials:
    6
    Resources:
    28
    Oh silly me...

    What is that system supposed to do?
     
  15. Spartipilo

    Spartipilo

    Joined:
    Jul 14, 2011
    Messages:
    3,190
    Resources:
    0
    Resources:
    0
    Almost the same. Str/Agi/Int/Level needed to hold an item :) If not, item is dropped, 'Unit doesn't meet the requirements' message, and restore founds and remove item if it's bough from shop :)
     
  16. Bannar

    Bannar

    Joined:
    Mar 19, 2008
    Messages:
    3,087
    Resources:
    20
    Spells:
    5
    Tutorials:
    1
    JASS:
    14
    Resources:
    20
    I just hate seeing vanilla Jass script requiring JNPG only because of globals.
     
  17. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,052
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    Hence why I code in GUIJASS so the globals get auto-created on copy/paste.
     
  18. Bannar

    Bannar

    Joined:
    Mar 19, 2008
    Messages:
    3,087
    Resources:
    20
    Spells:
    5
    Tutorials:
    1
    JASS:
    14
    Resources:
    20
    ^Bribe, in my opinion you should make vanilla Jass systems (GUI-friendly) without converting it into GUI actually. You can always create additional trigger "Variable Creator", like Weep was doing. I don't think GUI-users understand your systems, nor with change there anything. And you can always save some memory and increase the speed.

    @Kobas:
    Code (vJASS):
        set gg_trg_Kobas_System_Loop = CreateTrigger(  )

    // Into:
        local trigger t = CreateTrigger()
    Now just use the local trigger instead, while registering actions/conditions/events. Null at the end of init trig.
    local integer ID = (GetItemTypeId(Item))
    Doesn't require brackets actually ;P Use lower letters for locals, save the big ones for globals.

    Code (vJASS):
    if GetUnitAbilityLevel(u,ABI[i]) == 0 then
        call UnitAddAbility(u,ABI[i])
        call UnitMakeAbilityPermanent(u,true,ABI[i])

    // Into:
    if UnitAddAbility(u,ABI[i]) then
        call UnitMakeAbilityPermanent(u,true,ABI[i])

    call IncUnitAbilityLevel(u,ABI[i])
    Sucks alone ;P If you don't know, it refreshes tooltip, therefore forcing player to "re-hold" mouse over ability's button.
    Code (vJASS):
        call SetPlayerAbilityAvailable(p, ABI[i], false)
        call DecUnitAbilityLevel(u, ABI[i])
        call SetPlayerAbilityAvailable(p, ABI[i], true)
    ^Is much smoother.

    Btw, instead of actions, use conditions to perform the task. They tend to be faster.
    I recommend setting local 'k' as 0 while declaring. It's pointless to campare it to "COUNTER + 1" while the index size can be lowered to omit it.
     
  19. Bribe

    Bribe

    Joined:
    Sep 26, 2009
    Messages:
    8,052
    Resources:
    25
    Maps:
    3
    Spells:
    10
    Tutorials:
    3
    JASS:
    9
    Resources:
    25
    I like having it all in one trigger, without needing a variable creator, for two reasons:

    1) Less work for the user
    2) User can configure conditions block in GUI, because I always point out where to configure. If I coded it all in JASS, user would not always know where to configure things or where to set object editor data, etc.

    It is not worth it to throw away an interface like GUI because if you code it well the speed difference is pointless. Vexorian's optimizer will crunch the BJ's and weird functions for you, if one cares about speed so much.

    I really like enumerating units in JASS and then using a GUI "pick all units" function. It reminds me of anonymous functions in Zinc.