I Need Help

Level 7
Joined
Jul 20, 2009
Messages
295
Hello everyone.
Explanation:
Im creating several heroes each with different SpellBook Ability, after certain levels (in an irregular pattern) the SpellBook Ability increases in level (containing more spells in it as it levels)
Problem:
In triggers, I have to do the following [Shortened Version]:
  • Hero1 Levels
    • Events
      • Unit - A unit Gains a level
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Hero1
    • Actions
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Hero level of (Triggering unit)) Greater than or equal to 75
        • Then - Actions
          • Unit - Set level of SpellBook [Hero1] for (Triggering unit) to 16
        • Else - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Hero level of (Triggering unit)) Greater than or equal to 70
            • Then - Actions
              • Unit - Set level of SpellBook [Hero1] for (Triggering unit) to 15
            • Else - Actions
              • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
                • If - Conditions
                  • (Hero level of (Triggering unit)) Greater than or equal to 68
                • Then - Actions
                  • Unit - Set level of SpellBook [Hero1] for (Triggering unit) to 14
                • Else - Actions
I got to do this (IfThenElse sequence) for a single hero about 40 times, and times this by the number of heroes that my map contains (Number of triggers containing this amount of IfThenElse)... it will be a lot.
What I'm asking for is, is there a way to reduce this and make it as simple as possible without changing the concept of how I want it to be. (e.g. the SpellBook has to be levelled whenever the hero gains some irregular levels)

Thank you.
 
Level 22
Joined
Jan 1, 2011
Messages
1,453
My suggestion is to use a search method.
  • Hero Levels
    • Events
      • Unit - A unit Gains a level
    • Conditions
    • Actions
      • Set Ability = Spell Book
      • Set MaxLevels = 10
      • Set LvlNeeded[1] = 5
      • Set LvlNeeded[2] = 8
      • Set LvlNeeded[3] = 15
      • Set LvlNeeded[4] = 21
      • Set LvlNeeded[5] = 26
      • Set LvlNeeded[6] = 30
      • Set LvlNeeded[7] = 36
      • Set LvlNeeded[8] = 41
      • Set LvlNeeded[9] = 50
      • Set LvlNeeded[10] = 59
      • Custom script: call set udg_Integer1=udg_MaxLevels
      • Custom script: loop
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • (Hero level of (Triggering unit)) Equal to LvlNeeded[Integer1]
        • Then - Actions
          • Unit - Set level of Ability for (Triggering unit) to Integer1
        • Else - Actions
          • Custom script: call set udg_Integer1=udg_Integer1-1
          • Custom script: if udg_Integer1==0 then
          • Custom script: return
          • Custom script: endif
      • Custom script: exitwhen false
      • Custom script: endloop
 
Level 22
Joined
Jan 1, 2011
Messages
1,453
@maddeem
I believe all the constants should be set somewhere else.
It should not be repeated if you're calling it "constants".

If you were to use this method for more than one hero type then you'd have to make 3 variables per hero. However if you declare the constants over and over it allows for just 3 variables. I thought that would be more beginner friendly :3
 
Level 22
Joined
Jan 1, 2011
Messages
1,453
they arent constants then. also its a lot less efficient and just pointless since ur setting the exact same data into those variables.
K, lets hear your solution?
Not an edit of my solution, no. Your own please.

Yes there are many, many other more efficient ways of going about doing this. But I do believe this is the most simple and the most beginner friendly.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Actually a simple system could handle this.

1- Create a Hashtable
JASS:
globals
 hashtable YourHashName = InitHashtable()
endglobals

2- Index all the heroes Unit-Type in the Hashtable, and on each index add the corresponding ability.
JASS:
//               | Hashtable|  |Hero ID| | Level | |Ability Id|
call SaveInteger(YourHashName, 'abcd',      0,       'efgh')    // Units of type 'abcd' will receive ability 'efgh' on level 0.
call SaveInteger(YourHashName, 'xxja',      12,      'sdsa')    // UNits of type 'xxja' will receive ability 'sdsa' con level 12.

3- On level up, just use a function to add the ability, even if there is no ability on that level.
  • t
  • Events
  • Unit - A unit Gains a level
  • Actions
  • Custom script: local unit u = GetTriggerUnit()
  • Custom script: call UnitAddAbility(u, LoadInteger(YourHashName, GetUnitTypeId(u), GetUnitLevel(u))
  • Custom script: set u = null
These lines are more than enough to handle all your heroes, all your abilities, all your levels. No ITE chains, not variable arrays nor any other stuff. Just a table with data and a single function calling on Unit level up.

Let me know if you don't get the Jass scripts to make the system for you so you just "copy/paste" it to use.

This can also be made in GUI, but it's less efficient.


However, I would suggest the one below. You just have to create a trigger, name it "UnitLevelUp" (without quotes), convert it to custom text, delete everything inside, and copy/paste the code below. Then follow the instructions in the end of the script to add your heroes and abilities. The only downside for this is that it can only add one ability per level, meaning you can add 2 abilities on the same level up. I hope it doesn't bother you.


JASS:
globals
    hashtable AbilHash = InitHashtable()
endglobals

function Trig_UnitLevelUp_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer id = GetUnitTypeId(u)
    local integer lvl = GetUnitLevel(u)
    local integer abil = LoadInteger(AbilHash, id, lvl)
    
    if GetUnitAbilityLevel(u, abil) > 0 then
        call IncUnitAbilityLevel(u, abil)
    else
        call UnitAddAbility(u, abil)
    endif
    
    set u = null
endfunction

//===========================================================================
function InitTrig_UnitLevelUp takes nothing returns nothing
    set gg_trg_UnitLevelUp = CreateTrigger(  )
    call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )
    
// ADD ALL YOUR ABILITIES HERE THE WAY IT'S EXPLAINED BELOW
// Note: To see the ID of units and abilities press CTRL+D on the Object Editor.    
// In this example: 'Hpal' is the Human Paladin hero. 'Aloc' is "Locust" ability
// 'Afbt' is Feedback ability, and 'AHta' is "Reveal" ability.
    
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     2,     'Aloc')
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     5,     'Afbt')
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     8,     'AHta')

// If you want to increase the level of an ability, just add it again on the level you want to increase it.

// As example: The following would increase the level of 'AHta' (added on level 8) by 1 when hero reaches level 9.
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     9,     'AHta')
endfunction


Edit: Thanks to maddeem for the Level Increase thing.
 
Last edited:
Level 22
Joined
Jan 1, 2011
Messages
1,453
Actually a simple system could handle this.

1- Create a Hashtable
JASS:
globals
 hashtable YourHashName = InitHashtable()
endglobals

2- Index all the heroes Unit-Type in the Hashtable, and on each index add the corresponding ability.
JASS:
//               | Hashtable|  |Hero ID| | Level | |Ability Id|
call SaveInteger(YourHashName, 'abcd',      0,       'efgh')    // Units of type 'abcd' will receive ability 'efgh' on level 0.
call SaveInteger(YourHashName, 'xxja',      12,      'sdsa')    // UNits of type 'xxja' will receive ability 'sdsa' con level 12.

3- On level up, just use a function to add the ability, even if there is no ability on that level.
  • t
  • Events
  • Unit - A unit Gains a level
  • Actions
  • Custom script: local unit u = GetTriggerUnit()
  • Custom script: call UnitAddAbility(u, LoadInteger(YourHashName, GetUnitTypeId(u), GetUnitLevel(u))
  • Custom script: set u = null
These lines are more than enough to handle all your heroes, all your abilities, all your levels. No ITE chains, not variable arrays nor any other stuff. Just a table with data and a single function calling on Unit level up.

Let me know if you don't get the Jass scripts to make the system for you so you just "copy/paste" it to use.

This can also be made in GUI, but it's less efficient.


However, I would suggest the one below. You just have to create a trigger, name it "UnitLevelUp" (without quotes), convert it to custom text, delete everything inside, and copy/paste the code below. Then follow the instructions in the end of the script to add your heroes and abilities. The only downside for this is that it can only add one ability per level, meaning you can add 2 abilities on the same level up. I hope it doesn't bother you.


JASS:
globals
    hashtable AbilHash = InitHashtable()
endglobals

function Trig_UnitLevelUp_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local integer id = GetUnitTypeId(u)
    local integer lvl = GetUnitLevel(u)
    local integer abil = LoadInteger(AbilHash, id, lvl)
    
    call UnitAddAbility(u, abil)
    
    set u = null
endfunction

//===========================================================================
function InitTrig_UnitLevelUp takes nothing returns nothing
    set gg_trg_UnitLevelUp = CreateTrigger(  )
    call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )
    
// ADD ALL YOUR ABILITIES HERE THE WAY IT'S EXPLAINED BELOW
// Note: To see the ID of units and abilities press CTRL+D on the Object Editor.    
// In this example: 'Hpal' is the Human Paladin hero. 'Aloc' is "Locust" ability
// 'Afbt' is Feedback ability, and 'AHta' is "Reveal" ability.
    
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     2,     'Aloc')
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     5,     'Afbt')
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     8,     'AHta')
endfunction
I doubt hashtables are at this user's level of expertise. However I believe you misunderstood the query. As seen in the first post, the hero already has the ability. So they key point of a needed system is not add abilities, but to increase their level based on the hero's level.

Now creating a system for this is far from difficult, so I'll leave you guys to it.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
You're right. Already edited my last post to add the Level increase feature.

The system may be "Complex" for begginers, but the user only has to add the data on a fairly easy way.

If he doesn't want to add the abilities, there is no problem. He can just add the abilities when they level up. If he wants to use also the system capabilities to add abilities on certain levels too, he can do it too.
 
Level 33
Joined
Mar 27, 2008
Messages
8,035
@maddeem
We're not saying your solution is bad, lol.
We're just saying that the constants should stay as constants, how to make them one ?
Follow the above post, it's simple as that.

If the user is beginner, doesn't mean we should teach him inefficient method of triggering, it will ruin his experience.
 
Level 7
Joined
Jul 20, 2009
Messages
295
Haha, calm down guys.

I still didn't get into hashtables nor Jass, (been like this for 4-5 years now).
I might use hashtables later, but for now i'll stick to variables and setting Custom Value to units.
As far as I can see, according to my modest understanding, maddeem's idea is the most efficient way.
I did use his idea but not the way. All I wanted is an easy-to-understand way to make a simpler method of levelling up abilities that a hero already had (be it 1 or more abilities (Spellbook)).
By that, I can see maddeem is the only one that understood what I exactly wanted.

This is how I used maddeem's way: (For now there is only 1 hero in my map which is Red-Mage=RDM)
  • Setup SpellBook Levels
    • Events
      • Time - Elapsed game time is 0.10 seconds
    • Conditions
    • Actions
      • Set Level_RDM_MagicSpells[0] = 4
      • Set Level_RDM_MagicSpells[1] = 5
      • Set Level_RDM_MagicSpells[2] = 9
      • Set Level_RDM_MagicSpells[3] = 10
      • Set Level_RDM_MagicSpells[4] = 14
      • Set Level_RDM_MagicSpells[5] = 19
      • Set Level_RDM_MagicSpells[6] = 24
      • Set Level_RDM_MagicSpells[7] = 29
      • Set Level_RDM_MagicSpells[8] = 31
      • Set Level_RDM_MagicSpells[9] = 35
      • Set Level_RDM_MagicSpells[10] = 36
      • Set Level_RDM_MagicSpells[11] = 40
      • Set Level_RDM_MagicSpells[12] = 45
      • Set Level_RDM_MagicSpells[13] = 46
      • Set Level_RDM_MagicSpells[14] = 50
      • Set Level_RDM_MagicSpells[15] = 55
      • Set Level_RDM_MagicSpells[16] = 60
      • Set Level_RDM_MagicSpells[17] = 65
      • Set Level_RDM_MagicSpells[18] = 67
      • Set Level_RDM_MagicSpells[19] = 69
      • Set Level_RDM_MagicSpells[20] = 71
      • Set Level_RDM_MagicSpells[21] = 73
      • Set Level_RDM_MagicSpells[22] = 75
      • Set Level_RDM_DebuffSpells[0] = 6
      • Set Level_RDM_DebuffSpells[1] = 8
      • Set Level_RDM_DebuffSpells[2] = 11
      • Set Level_RDM_DebuffSpells[3] = 13
      • Set Level_RDM_DebuffSpells[4] = 18
      • Set Level_RDM_DebuffSpells[5] = 21
      • Set Level_RDM_DebuffSpells[6] = 25
      • Set Level_RDM_DebuffSpells[7] = 32
      • Set Level_RDM_DebuffSpells[8] = 46
      • Set Level_RDM_ProtectiveSpells[0] = 3
      • Set Level_RDM_ProtectiveSpells[1] = 7
      • Set Level_RDM_ProtectiveSpells[2] = 10
      • Set Level_RDM_ProtectiveSpells[3] = 14
      • Set Level_RDM_ProtectiveSpells[4] = 20
      • Set Level_RDM_ProtectiveSpells[5] = 21
      • Set Level_RDM_ProtectiveSpells[6] = 26
      • Set Level_RDM_ProtectiveSpells[7] = 27
      • Set Level_RDM_ProtectiveSpells[8] = 33
      • Set Level_RDM_ProtectiveSpells[9] = 34
      • Set Level_RDM_ProtectiveSpells[10] = 40
      • Set Level_RDM_ProtectiveSpells[11] = 41
      • Set Level_RDM_ProtectiveSpells[12] = 47
      • Set Level_RDM_ProtectiveSpells[13] = 48
      • Set Level_RDM_ProtectiveSpells[14] = 63
      • Set Level_RDM_BuffSpells[0] = 20
      • Set Level_RDM_BuffSpells[1] = 30
      • Set Level_RDM_BuffSpells[2] = 40
      • Set Level_RDM_BuffSpells[3] = 50
      • Set Level_RDM_BuffSpells[4] = 60
      • Set Level_RDM_BuffSpells[5] = 75
The hero has 4 SpellBook Abilities and as the hero levels for a certain level, the ability/abilities levels as well (1.MagicSpells, 2.DebuffSpells, 3.ProtectiveSpells, 4.BuffSpells)


  • Level Up RDM
    • Events
      • Unit - A unit Gains a level
    • Conditions
      • (Unit-type of (Triggering unit)) Equal to Red Mage
    • Actions
      • *Other Stuff no need to show*
      • Set Level_MaxSpellLvl = 22
      • For each (Integer TempInteger) from 0 to Level_MaxSpellLvl, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Hero level of (Triggering unit)) Greater than or equal to Level_RDM_MagicSpells[TempInteger]
            • Then - Actions
              • Unit - Set level of Magic Spells [RDM Offensive] for (Triggering unit) to (TempInteger + 2)
            • Else - Actions
      • Set Level_MaxSpellLvl = 8
      • For each (Integer TempInteger) from 0 to Level_MaxSpellLvl, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Hero level of (Triggering unit)) Greater than or equal to Level_RDM_DebuffSpells[TempInteger]
            • Then - Actions
              • Unit - Set level of Debuff Spells [RDM Offensive] for (Triggering unit) to (TempInteger + 2)
            • Else - Actions
      • Set Level_MaxSpellLvl = 14
      • For each (Integer TempInteger) from 0 to Level_MaxSpellLvl, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Hero level of (Triggering unit)) Greater than or equal to Level_RDM_ProtectiveSpells[TempInteger]
            • Then - Actions
              • Unit - Set level of Protective Spells [RDM Defensive] for (Triggering unit) to (TempInteger + 2)
            • Else - Actions
      • Set Level_MaxSpellLvl = 5
      • For each (Integer TempInteger) from 0 to Level_MaxSpellLvl, do (Actions)
        • Loop - Actions
          • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
            • If - Conditions
              • (Hero level of (Triggering unit)) Greater than or equal to Level_RDM_BuffSpells[TempInteger]
            • Then - Actions
              • Unit - Set level of Offensive Buffs [RDM Defensive] for (Triggering unit) to (TempInteger + 2)
            • Else - Actions
I thank you all for your contributions and help.
If there is even a way to make this more simpler (non-jass unless with explanation about it and how to use it, also all I got to do is copy-paste it) but containing the main principles.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Dude... i just did it before. Exactly what you requested. It adds abilities if the unit doesn't have them, and increases it's levels if the unit already has them. You just have to set the Unit Type, the level, and the ability. Besides it's commented and explained.

Basically, you have to expand the list at the end of the script with all your heroes, levels and abilities. The rest will just work.


JASS:
// No need to touch this
globals
    hashtable AbilHash = InitHashtable()
endglobals

// No need to touch this
function Trig_UnitLevelUp_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit() // Triggering Unit
    local integer id = GetUnitTypeId(u) // The HandleId of the Unit Type of the Triggering Unit
    local integer lvl = GetUnitLevel(u) // The Level of the Triggering Unit
    local integer abil = LoadInteger(AbilHash, id, lvl) // The Ability of that unit in that level (if there is one)
    
    if GetUnitAbilityLevel(u, abil) > 0 then // If the ability level is greater than 0 (Means the unit already has the ability)
        call IncUnitAbilityLevel(u, abil) // Increases the ability level
    else
        call UnitAddAbility(u, abil) // Else, adds the ability.
    endif
    
    set u = null // Clear leaks.
endfunction

//===========================================================================
function InitTrig_UnitLevelUp takes nothing returns nothing
    set gg_trg_UnitLevelUp = CreateTrigger(  )
    call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )
    
// ADD ALL YOUR ABILITIES HERE THE WAY IT'S EXPLAINED BELOW
// Note: To see the ID of units and abilities press CTRL+D on the Object Editor.    
// In this example: 'Hpal' is the Human Paladin hero. 'Aloc' is "Locust" ability
// 'Afbt' is Feedback ability, and 'AHta' is "Reveal" ability.
    
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     2,     'Aloc')
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     5,     'Afbt')
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     8,     'AHta')

// If you want to increase the level of an ability, just add it again on the level you want to increase it.

// As example: The following would increase the level of 'AHta' (added on level 8) by 1 when hero reaches level 9.
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     9,     'AHta')
endfunction


If you want to UNDERSTAND The system, look at these GUI Triggers. I hope you can easily see what it does and how it works.
If you want to USE THE SYSTEM, just copy/paste the JASS SCRIPT.

You can also make the GUI Triggers yourself following the same logic and idea as the shown below, but you'll save some time and wc3 memory resourced by just copy/pasting the Jass script.


The "GUI" form of my trigger to Increase/Add the ability for specific units on specific levels is the following:
  • t
  • Events
    • A unit gains a level
  • Actions
    • Set YourUnit = (Triggering Unit)
    • Set UnitType = (Unit type of YourUnit)
    • Set Level = (Level of YourUnit)
    • Set Ability = (Load Level of UnitType from AbilHash)
    • If (Conditions) then (Actions) else (Actions)
      • If - (Conditions)
        • Level > 0
      • Then - (Actions)
        • Unit - Increase level of Ability for YourUnit
      • Else - (Actions)
        • Unit - Add Ability to Your Unit
The "GUI" form of my data list to input the heroes and abilities and levels is the following
  • t
  • Events
    • Map Initialization
  • Actions
    • -------- Creating Hashtable --------
    • Hashtable - Create a hashtable
    • Set AbilHash = (Last Created Hashtable)
    • -------- Your Hero --------
    • Set YourUnitType = Paladin
    • -------- The Level --------
    • Set YourLevel = 2
    • -------- The Abiltiy --------
    • Set YourAbility = Animate Dead
    • -------- Stores your hero, your level, and your ability in a Hashtable --------
    • Hashtable - Save YourAbility as YourLevel of YourUnitType in AbilHash
    • -------- --------
    • -------- Now repeat the process for all your heroes and abilities --------
    • -------- --------
    • -------- Add LOCUST to PALADIN on level 4 --------
    • Set YourUnitType = Paladin
    • Set YourLevel = 4
    • Set YourAbility = Locust
    • Hashtable - Save YourAbility as YourLevel of YourUnitType in AbilHash
    • -------- Add BLADESTORM to PALADIN on level 8 --------
    • Set YourUnitType = Paladin
    • Set YourLevel = 8
    • Set YourAbility = Bladestorm
    • Hashtable - Save YourAbility as YourLevel of YourUnitType in AbilHash
    • -------- Next Ability --------
    • and so on...
 
Last edited:
Level 7
Joined
Jul 20, 2009
Messages
295
Dude... i just did it before. Exactly what you requested. It adds abilities if the unit doesn't have them, and increases it's levels if the unit already has them. You just have to set the Unit Type, the level, and the ability. Besides it's commented and explained.

Basically, you have to expand the list at the end of the script with all your heroes, levels and abilities. The rest will just work.


JASS:
// No need to touch this
globals
    hashtable AbilHash = InitHashtable()
endglobals

// No need to touch this
function Trig_UnitLevelUp_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit() // Triggering Unit
    local integer id = GetUnitTypeId(u) // The HandleId of the Unit Type of the Triggering Unit
    local integer lvl = GetUnitLevel(u) // The Level of the Triggering Unit
    local integer abil = LoadInteger(AbilHash, id, lvl) // The Ability of that unit in that level (if there is one)
    
    if GetUnitAbilityLevel(u, abil) > 0 then // If the ability level is greater than 0 (Means the unit already has the ability)
        call IncUnitAbilityLevel(u, abil) // Increases the ability level
    else
        call UnitAddAbility(u, abil) // Else, adds the ability.
    endif
    
    set u = null // Clear leaks.
endfunction

//===========================================================================
function InitTrig_UnitLevelUp takes nothing returns nothing
    set gg_trg_UnitLevelUp = CreateTrigger(  )
    call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )
    
// ADD ALL YOUR ABILITIES HERE THE WAY IT'S EXPLAINED BELOW
// Note: To see the ID of units and abilities press CTRL+D on the Object Editor.    
// In this example: 'Hpal' is the Human Paladin hero. 'Aloc' is "Locust" ability
// 'Afbt' is Feedback ability, and 'AHta' is "Reveal" ability.
    
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     2,     'Aloc')
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     5,     'Afbt')
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     8,     'AHta')

// If you want to increase the level of an ability, just add it again on the level you want to increase it.

// As example: The following would increase the level of 'AHta' (added on level 8) by 1 when hero reaches level 9.
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
    call SaveInteger(AbilHash,   'Hpal',     9,     'AHta')
endfunction


If you want to UNDERSTAND The system, look at these GUI Triggers. I hope you can easily see what it does and how it works.
If you want to USE THE SYSTEM, just copy/paste the JASS SCRIPT.

You can also make the GUI Triggers yourself following the same logic and idea as the shown below, but you'll save some time and wc3 memory resourced by just copy/pasting the Jass script.


The "GUI" form of my trigger to Increase/Add the ability for specific units on specific levels is the following:
  • t
  • Events
    • A unit gains a level
  • Actions
    • Set YourUnit = (Triggering Unit)
    • Set UnitType = (Unit type of YourUnit)
    • Set Level = (Level of YourUnit)
    • Set Ability = (Load Level of UnitType from AbilHash)
    • If (Conditions) then (Actions) else (Actions)
      • If - (Conditions)
        • Level > 0
      • Then - (Actions)
        • Unit - Increase level of Ability for YourUnit
      • Else - (Actions)
        • Unit - Add Ability to Your Unit
The "GUI" form of my data list to input the heroes and abilities and levels is the following
  • t
  • Events
    • Map Initialization
  • Actions
    • -------- Creating Hashtable --------
    • Hashtable - Create a hashtable
    • Set AbilHash = (Last Created Hashtable)
    • -------- Your Hero --------
    • Set YourUnitType = Paladin
    • -------- The Level --------
    • Set YourLevel = 2
    • -------- The Abiltiy --------
    • Set YourAbility = Animate Dead
    • -------- Stores your hero, your level, and your ability in a Hashtable --------
    • Hashtable - Save YourAbility as YourLevel of YourUnitType in AbilHash
    • -------- --------
    • -------- Now repeat the process for all your heroes and abilities --------
    • -------- --------
    • -------- Add LOCUST to PALADIN on level 4 --------
    • Set YourUnitType = Paladin
    • Set YourLevel = 4
    • Set YourAbility = Locust
    • Hashtable - Save YourAbility as YourLevel of YourUnitType in AbilHash
    • -------- Add BLADESTORM to PALADIN on level 8 --------
    • Set YourUnitType = Paladin
    • Set YourLevel = 8
    • Set YourAbility = Bladestorm
    • Hashtable - Save YourAbility as YourLevel of YourUnitType in AbilHash
    • -------- Next Ability --------
    • and so on...

Alright, I guess i'll use your Jass method, though, I do not want to add the ability, just increase it's level as hero levels by some number.
Let me rephrase, do I have to add all of the abilities for the first time and set it's Level to 1. e.g:
JASS:
// No need to touch this
globals
     hashtable AbilHash = InitHashtable()
endglobals

// No need to touch this
function Trig_UnitLevelUp_Actions takes nothing returns nothing
     local unit u = GetTriggerUnit() // Triggering Unit
     local integer id = GetUnitTypeId(u) // The HandleId of the Unit Type of the Triggering Unit
     local integer lvl = GetUnitLevel(u) // The Level of the Triggering Unit
     local integer abil = LoadInteger(AbilHash, id, lvl) // The Ability of that unit in that level (if there is one)
     
     if GetUnitAbilityLevel(u, abil) > 0 then // If the ability level is greater than 0 (Means the unit already has the ability)
         call IncUnitAbilityLevel(u, abil) // Increases the ability level
     else
         call UnitAddAbility(u, abil) // Else, adds the ability.
     endif
     
     set u = null // Clear leaks.
endfunction

//===========================================================================
function InitTrig_UnitLevelUp takes nothing returns nothing
     set gg_trg_UnitLevelUp = CreateTrigger(  )
     call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )
     
// ADD ALL YOUR ABILITIES HERE THE WAY IT'S EXPLAINED BELOW
// Note: To see the ID of units and abilities press CTRL+D on the Object Editor.    
// In this example: 'Hpal' is the Human Paladin hero. 'Aloc' is "Locust" ability
// 'Afbt' is Feedback ability, and 'AHta' is "Reveal" ability.
     
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
     call SaveInteger(AbilHash,   'Hpal',     1,     'Aloc') <== The hero will already have these abilities at level 1 and onwards, so do I have to add this line?
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
     call SaveInteger(AbilHash,   'Hpal',     1,     'Afbt') <== The hero will already have these abilities at level 1 and onwards, so do I have to add this line?
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
     call SaveInteger(AbilHash,   'Hpal',     1,     'AHta') <== The hero will already have these abilities at level 1 and onwards, so do I have to add this line?

// If you want to increase the level of an ability, just add it again on the level you want to increase it.

// As example: The following would increase the level of 'AHta' (added on level 8) by 1 when hero reaches level 9.
//  |    Function   | Hash   | UnitTypeID| Level| |Ability |        
     call SaveInteger(AbilHash,   'Hpal',     2,     'AHta') <== then these lines to make my abilities increase in level when hero reaches the number under 'Level'?
     call SaveInteger(AbilHash,   'Hpal',     5,     'AHta')
     call SaveInteger(AbilHash,   'Hpal',     9,     'AHta')
     call SaveInteger(AbilHash,   'Hpal',     4,     'Afbt')
     call SaveInteger(AbilHash,   'Hpal',     9,     'Afbt')
     call SaveInteger(AbilHash,   'Hpal',     20,     'Afbt')
endfunction

Edit: Also I'm confused for setting my abilities ID, as I stated before, my hero's abilities are all of the same type which are SpellBooks.
They all seem to have the same second part of their IDs: Aspb
This is how their names are:
A02R:Aspb (Debuff Spells)
A005:Aspb (Magic Spells)
A023:Apsb (Offensive Spells)
Ao1W:Aspb (Protective Spells)
So, how do I add their IDs?
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
JASS:
call SaveInteger(AbilHash,   'Hpal',     1,     'Aloc') <== The hero will already have these abilities at level 1 and onwards, so do I have to add this line?

No. There is no need to add that line. If you add the abilities by default on the Object Editor, when the unit levels up (means it goes from lvl 2 and above) the ability level will increase. If the unit doesn't have the ability, it will be added. Since your units will already have the abilities, they will just increase level when you tell the system to.

Adding abilities on level 1 will not work, because when the unit levels up, it will already be lvl 2. Also this only supports one ability level increase per unit level (Meaning you can't increase the level of more than 1 ability in the same Unit Level Up)

JASS:
    call SaveInteger(AbilHash,   'Hpal',     2,     'AHta') <== then these lines to make my abilities increase in level when hero reaches the number under 'Level'?
     call SaveInteger(AbilHash,   'Hpal',     5,     'AHta')
     call SaveInteger(AbilHash,   'Hpal',     9,     'AHta') // Error. 'Afbt' also levels up on lvl 9.
     call SaveInteger(AbilHash,   'Hpal',     4,     'Afbt')
     call SaveInteger(AbilHash,   'Hpal',     9,     'Afbt') // Error. 'AHta' also levels up on lvl 9.
     call SaveInteger(AbilHash,   'Hpal',     20,     'Afbt')

Exactly. The abilities you placed in those levels will increase when the hero reaches those levels.

The ID are the first 4 characters: A02R, A005, A023, Ao1W. The other charaters (Asbp) reference to the ability the first one is based on. Means that these 4 spellbooks are all based on 'Asbp'. You just have to use the first 4, just as you did in the last quoted text.

I would suggest you to add comments (using //) after every data save so you can read it clearly. I would also suggest you to place the abilities in the same order they will level up. Like this:
JASS:
     call SaveInteger(AbilHash,   'Hpal',     4,     'Afbt') // Bash lvl 2
     call SaveInteger(AbilHash,   'Hpal',     5,     'AHta') // Evasion Lvl 2
     call SaveInteger(AbilHash,   'Hpal',     9,     'AHta') // Evasion Lvl 3
     call SaveInteger(AbilHash,   'Hpal',     10,     'Afbt') // Bash lvl 3
     call SaveInteger(AbilHash,   'Hpal',     20,     'Afbt') // Bash lvl 4
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Edit: Fixed Everything.

Now see how the abilities have to be saved at the end of the script.

JASS:
// No need to touch this
globals
    hashtable AbilHash = InitHashtable()
endglobals

// No need to touch this
function Trig_UnitLevelUp_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local string s = LoadStr(AbilHash, GetUnitTypeId(u), GetUnitLevel(u))
    local integer AbilCount = S2I(SubString(s, 0, 2))
    local integer StrStart = 4
    local integer StrEnd = 10
    local integer looper = 1
    
    loop
        exitwhen looper > AbilCount
        call IncUnitAbilityLevel(u, S2I(SubString(s, StrStart, StrEnd)))
        set StrStart = StrStart + 8
        set StrEnd = StrStart + 6
        set looper = looper + 1
    endloop
    
    set u = null
    set s = null
endfunction

//===========================================================================
function InitTrig_UnitLevelUp takes nothing returns nothing
    set gg_trg_UnitLevelUp = CreateTrigger(  )
    call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )
                                   
    call SaveStr(AbilHash, 'Hpal', 05, "04, 'Abi1', 'Abi2', 'Abi3', 'Abi4'") // 4 Abilities
    call SaveStr(AbilHash, 'Hpal', 06, "01, 'Abi1'") // 1 Ability
    call SaveStr(AbilHash, 'Hpal', 07, "02, 'Abi1', 'Abi2'") // 2 Abilities
endfunction

You have to be carefull with the input text string. It has to match exactly just as the examples.

1- First you open the String with a double quote (")
2- The first 2 numbers are the amount of abilities you're going to handle. You have to input 2 numbers ALWAYS between 01 and 99.
3- Then comes a coma and a blank space (, )
4- Then comes a single quote (')
5- Then comes the 4 characters of the Ability Id ('Abix')
6- Then comes another single quote (')
7- If you have a single ability, you close the string with a double quote ("), else, you jump over to step 3.

Also, remember the function Arguments.
1- The Hashtable (AbilHash)
2- The UnitType ID ('Hpal')
3- The Level where the ability increases (Doesn't matter if you place 5, or 0000005 here)
4- The String with the above specifications.

Changes:
1- I removed the "Add Ability" Feature. Now it just increases the ability level.

Limitations:
1- This works from lvl 2 and above. Abilities saved on lvl 1 won't be added nor upgraded when the Hero enters the map at lvl 1.
 
Last edited:
Level 29
Joined
Oct 24, 2012
Messages
6,545
it is pretty neat.

@kaizar
hashtables and jass r very easy lol.
there are plenty of hashtable guides around that can get u started. i think i provide a short one in my tutorial things a GUIer should know.
jass isnt a must for writing code but it is a lot better. its faster to type and faster to edit. there is also a lot more u can do in jass than in GUI. if u decide to try jass check out my other tutorial GUI to efficient Jass as i tried to show what happens when u convert GUI to Jass to make it an easier stepping stone when starting to write jass. feel free to ask questions on my tutorial if u do decide to switch over.

@maddeem
my earlier statement may of sounded really rude and like i was attacking u. if it did im sry that was not my intention. i was just trying to point out a few things.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
I never though about finding a way around to the problem so fast xD I suddenly though "It would be nice if I could turn a string into a integer.... oh... wait a minute, I can..." The rest is just... what you see in the script above xD
 
Level 7
Joined
Jul 20, 2009
Messages
295
@Spartipilo
Great, I'll check it out.
Thanks again. ^^

@deathismyfriend
I'll check out your tuts later, thanks to you all and +reps.

Edit:
When I saved the map, the trigger became disabled and showed error for each line.
Do I need VJass for introducing the trigger into my map or normal wc3 editor would do fine? If so, then what should I do to make it work?
 
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
I don't know vJass :$

And yeah he can do the declaration in the Map header, I just like keeping the global declaration within the system that uses it.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
There are so many things i should... :) But vJASS is somehow hard to me, i'm not really that into programming. Private and Public constants, structs, methods, libraries... Maybe with someone guiding me step by step :)
 
Level 7
Joined
Jul 20, 2009
Messages
295
Good, now just 1 more error which is 'Invalid digit in octal integer notation'

call SaveStr(AbilHash, 'Hblm', 07, "01, 'A01W'")
call SaveStr(AbilHash, 'Hblm', 08, "01, 'A02R'") <== Due to this
call SaveStr(AbilHash, 'Hblm', 09, "01, 'A005'") <== and this
call SaveStr(AbilHash, 'Hblm', 10, "02, 'A005', 'A01W'")
call SaveStr(AbilHash, 'Hblm', 11, "01, 'A02R'")
call SaveStr(AbilHash, 'Hblm', 12, "01, 'A01W'")

What's wrong with levels 8 and 9?

Edit: I removed these 2 lines just to check if the trigger works and it isn't working for some reason. :S
When my hero gains the levels listed the ability doesnt increase in lvl.
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
It's because of some weird thing related to Program Languages and stuff that uses several different numerical interpretations or something like that.

call SaveStr(AbilHash, 'Hblm', 08, "01, 'A02R'") <== Due to this
call SaveStr(AbilHash, 'Hblm', 09, "01, 'A005'") <== and this

The problem lies in the "08" and "09". The octal integer notation (I have no idea what it is) allows having "0x" when x = to a number between 0 and 7. From 8 and above it doesn't allow having a "0" in front of the "x".

So, 00, 01, 02, 03, 04, 05, 06, and 07 works. 08, 09, and above doesn't work. (don't ask me why).

Anyway, it doesn't matter since it's the level where the unit acquires the ability, so you can just place "8" and "9". The "0x" is important just in the string of the number of abilities and the ability id's. I'll explain why:

If you save

"02, 'asdf', 'abcd'":
- The system takes the first 2 numbers as the amount of abilities: 02. (String from 0 to 2)
- Then jumps 2 characters, and takes from the blank space to the second quote (String from 4 to 10)
- Then jumps 2 characters agains, and repeats the process untill the loop count reaches the number of abilities (02).

So, (String, 0, 2) takes the "02"
Then (String, 4, 10) takes the 'asdf'
Then (String, 12, 18) taking the 'abcd'

If you place just a "2" it will be like

- (String, 0, 2) takes the "2,"
- (String, 4, 10) takes "asdf',"
- (String, 12, 18) takes "abcd' "

As you can see, all the characters are missplaced, and the "'asdf'" is now "asdf',". That screws up everything :)
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
Because i'm using String to Integer conversion. It's the asiest way I found to add the number of abilities to upgrade in the level, and the abilities to upgrade in the string.

S2I("'asdf'") turns "'asdf'" into 'asdf' which is an integer.
 
Level 7
Joined
Jul 20, 2009
Messages
295
But still, the trigger isn't working.
When my hero levels, his abilities do not increase in level.
JASS:
// No need to touch this
globals
    hashtable AbilHash = InitHashtable()
endglobals

// No need to touch this
function Trig_UnitLevelUp_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local string s = LoadStr(AbilHash, GetUnitTypeId(u), GetUnitLevel(u))
    local integer AbilCount = S2I(SubString(s, 0, 2))
    local integer StrStart = 4
    local integer StrEnd = 10
    local integer looper = 1
   
    loop
        exitwhen looper > AbilCount
        call IncUnitAbilityLevel(u, S2I(SubString(s, StrStart, StrEnd)))
        set StrStart = StrStart + 8
        set StrEnd = StrStart + 6
        set looper = looper + 1
    endloop
   
    set u = null
    set s = null
endfunction

//===========================================================================
function InitTrig_UnitLevelUp takes nothing returns nothing
    set gg_trg_UnitLevelUp = CreateTrigger(  )
    call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )
    
    call SaveStr(AbilHash, 'Hblm', 03, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 04, "01, 'A005'") // 4 Abilities
    call SaveStr(AbilHash, 'Hblm', 05, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 06, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 07, "01, 'A01W'")
    //call SaveStr(AbilHash, 'Hblm', 08, "01, 'A02R'")
    //call SaveStr(AbilHash, 'Hblm', 09, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 10, "02, 'A005', 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 11, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 12, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 13, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 14, "02, 'A005', 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 16, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 18, "02, 'A02R', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 19, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 20, "02, 'A01W', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 21, "02, 'A02R', 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 22, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 24, "02, 'A005', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 25, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 26, "02, 'A01W', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 27, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 29, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 31, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 32, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 33, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 34, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 35, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 36, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 40, "03, 'A005', 'A01W', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 41, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 45, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 46, "02, 'A005', 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 47, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 48, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 50, "02, 'A005', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 52, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 54, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 55, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 56, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 58, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 60, "02, 'A005', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 63, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 65, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 67, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 69, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 71, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 73, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 75, "01, 'A005'")
    
    
    
    //call SaveStr(AbilHash, 'Hpal', 06, "01, 'Abi1'") // 1 Ability
    //call SaveStr(AbilHash, 'Hpal', 07, "02, 'Abi1', 'Abi2'") // 2 Abilities
endfunction
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
I'm working on it. For some reason the String to Integer conversion isn't working.

EDIT: Found that String 2 Integer function returns "0" if there is a non-numeric character in the string. Not even single quotes are allowed :'(

EDIT: OMG I'm so amazed about this. I actually found a system (made by AceHart) that succesfully analyzes any imput string, and makes some weird numeric analisys to convert it to it's corresponding integer value in the ASCII numeric value table (The same Wc3 uses to turn non-numeric characters into numbers. Check this: http://www.asciitable.com/).

1- Create a New Trigger
2- Name it "Char2IdLibrary"
3- Convert it to custom text and replace everything inside with the following
JASS:
// Credits to AceHart for this.

library Char2IdLib

// No need to touch this. Credits to AceHart for this.
function Char2Id takes string c returns integer
    local integer i = 0
    local string abc = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    local string t

    loop
        set t = SubString(abc,i,i + 1)
        exitwhen t == null
        exitwhen t == c
        set i = i + 1
    endloop
    if i < 10 then
        return i + 48
    elseif i < 36 then
        return i + 65 - 10
    endif
    return i + 97 - 36
endfunction

// No need to touch this. Credits to AceHart for this.
function String2Id takes string s returns integer
    return ((Char2Id(SubString(s,0,1)) * 256 + Char2Id(SubString(s,1,2))) * 256 + Char2Id(SubString(s,2,3))) * 256 + Char2Id(SubString(s,3,4))
endfunction

endlibrary

4- In the UnitLevelUp trigger you have to add the indicated line.
JASS:
    set gg_trg_UnitLevelUp = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_UnitLevelUp, EVENT_PLAYER_HERO_LEVEL ) // THIS ONE RIGHT HERE
    call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )

5- You're done. AceHart system will take the String and successfully convert it into a Integer. Warcraft 3 will turn that integer into an Ability, and my script will increase it's level.

6- I will definitely share this as a resource and give you and AceHart credits.
 
Last edited:
Level 7
Joined
Jul 20, 2009
Messages
295
Nope, still not working :S

JASS:
// Credits to AceHart for this.

library Char2IdLib

// No need to touch this. Credits to AceHart for this.
function Char2Id takes string c returns integer
    local integer i = 0
    local string abc = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    local string t

    loop
        set t = SubString(abc,i,i + 1)
        exitwhen t == null
        exitwhen t == c
        set i = i + 1
    endloop
    if i < 10 then
        return i + 48
    elseif i < 36 then
        return i + 65 - 10
    endif
    return i + 97 - 36
endfunction

// No need to touch this. Credits to AceHart for this.
function String2Id takes string s returns integer
    return ((Char2Id(SubString(s,0,1)) * 256 + Char2Id(SubString(s,1,2))) * 256 + Char2Id(SubString(s,2,3))) * 256 + Char2Id(SubString(s,3,4))
endfunction

endlibrary

JASS:
// No need to touch this
globals
    hashtable AbilHash = InitHashtable()
endglobals

// No need to touch this
function Trig_UnitLevelUp_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local string s = LoadStr(AbilHash, GetUnitTypeId(u), GetUnitLevel(u))
    local integer AbilCount = S2I(SubString(s, 0, 2))
    local integer StrStart = 4
    local integer StrEnd = 10
    local integer looper = 1
   
    loop
        exitwhen looper > AbilCount
        call IncUnitAbilityLevel(u, S2I(SubString(s, StrStart, StrEnd)))
        set StrStart = StrStart + 8
        set StrEnd = StrStart + 6
        set looper = looper + 1
    endloop
   
    set u = null
    set s = null
endfunction

//===========================================================================
function InitTrig_UnitLevelUp takes nothing returns nothing
    set gg_trg_UnitLevelUp = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_UnitLevelUp, EVENT_PLAYER_HERO_LEVEL )
    call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )
    
    call SaveStr(AbilHash, 'Hblm', 03, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 04, "01, 'A005'") // 4 Abilities
    call SaveStr(AbilHash, 'Hblm', 05, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 06, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 07, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 8, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 9, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 10, "02, 'A005', 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 11, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 12, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 13, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 14, "02, 'A005', 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 16, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 18, "02, 'A02R', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 19, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 20, "02, 'A01W', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 21, "02, 'A02R', 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 22, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 24, "02, 'A005', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 25, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 26, "02, 'A01W', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 27, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 29, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 31, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 32, "01, 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 33, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 34, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 35, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 36, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 40, "03, 'A005', 'A01W', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 41, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 45, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 46, "02, 'A005', 'A02R'")
    call SaveStr(AbilHash, 'Hblm', 47, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 48, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 50, "02, 'A005', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 52, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 54, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 55, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 56, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 58, "01, 'A023'")
    call SaveStr(AbilHash, 'Hblm', 60, "02, 'A005', 'A023'")
    call SaveStr(AbilHash, 'Hblm', 63, "01, 'A01W'")
    call SaveStr(AbilHash, 'Hblm', 65, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 67, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 69, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 71, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 73, "01, 'A005'")
    call SaveStr(AbilHash, 'Hblm', 75, "01, 'A005'")
    
    
    
    //call SaveStr(AbilHash, 'Hpal', 06, "01, 'Abi1'") // 1 Ability
    //call SaveStr(AbilHash, 'Hpal', 07, "02, 'Abi1', 'Abi2'") // 2 Abilities
endfunction
 
Level 20
Joined
Jul 14, 2011
Messages
3,213
You didn't update the UnitLevelUp script... which i forgot to tell you to :) Here's the final script.

JASS:
// No need to touch this
globals
    hashtable Spart_AbilHash = InitHashtable()
endglobals

// Add your abilities here
function UnitLevelUpData takes nothing returns nothing
    local hashtable h = Spart_AbilHash

// call SaveStr(h, // Must remain like it's. Don't touch it
// 'Hpal' references to a Unit-Type (In this case, 'Hpal' references to Human Paladin). You can see Object Id's by pressing CTRL+D in the Object Editor
// The "2", "7", "10", and "15" references to the level where the unit acquires/upgrades the abilities
// The string to save the abilities has the following composition:
    // The first 2 characters MUST BE 2 NUMBERS between 00 and 99
    // Then comes a coma and a blank space
    // Then comes the first ability 'Abi1'
    // If there are no more abilities, close the string with a double quote.
    // Else, if there are more abilities, just add a coma, a blank space, and the other ability.

// | Function | Hash |  Unit-TypeID | Level |  ##, Abilities
    call SaveStr(h,       'Hpal',      2,     "01, 'Abi1'")
    call SaveStr(h,       'Hpal',      7,     "02, 'Abi2', 'Abi3'")
    call SaveStr(h,       'Hpal',      10,    "04, 'Abi4', 'Abi5', 'Abi6', 'Abi7'")
    call SaveStr(h,       'Hpal',      15,    "03, 'Abi8', 'Abi9', 'AbiX'")
    
    set h = null
endfunction


// No need to touch this
function Trig_UnitLevelUp_Actions takes nothing returns nothing
    local unit u = GetTriggerUnit()
    local string s = LoadStr(Spart_AbilHash, GetUnitTypeId(u), GetUnitLevel(u))
    local integer AbilCount = S2I(SubString(s, 0, 2))
    local integer abil 
    local integer StrStart = 5
    local integer StrEnd = 9
    local integer looper = 1
    
    loop
        exitwhen looper > AbilCount
        set abil = String2Id(SubString(s, StrStart, StrEnd))
        if GetUnitAbilityLevel(u, abil) > 0 then
            call IncUnitAbilityLevel(u, abil)
        else
            call UnitAddAbility(u, abil)
        endif
        set StrStart = StrEnd + 4
        set StrEnd = StrStart + 4
        set looper = looper + 1
    endloop
   
    set u = null
    set s = null
endfunction

//===========================================================================
function InitTrig_UnitLevelUp takes nothing returns nothing
    set gg_trg_UnitLevelUp = CreateTrigger(  )
    call TriggerRegisterAnyUnitEventBJ( gg_trg_UnitLevelUp, EVENT_PLAYER_HERO_LEVEL )
    call TriggerAddAction( gg_trg_UnitLevelUp, function Trig_UnitLevelUp_Actions )
    call UnitLevelUpData()
 endfunction

Here's the final Char2Id Library
JASS:
// Credits to AceHart for this.
library Char2IdLib

    // No need to touch this. Credits to AceHart for this.
    function Char2Id takes string c returns integer
        local integer i = 0
        local string abc = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
        local string t

        loop
            set t = SubString(abc,i,i + 1)
            exitwhen t == null or t == c
            set i = i + 1
        endloop
        if i < 10 then
            return i + 48
        elseif i < 36 then
            return i + 55
        endif
        return i + 61
    endfunction

    // No need to touch this. Credits to AceHart for this.
    function String2Id takes string s returns integer
        return ((Char2Id(SubString(s,0,1)) * 256 + Char2Id(SubString(s,1,2))) * 256 + Char2Id(SubString(s,2,3))) * 256 + Char2Id(SubString(s,3,4))
    endfunction
endlibrary
 
Last edited:
Level 20
Joined
Jul 14, 2011
Messages
3,213
dimf: Yeah, they're integers. They can be handled as integers, that's all ok... But how complex would it be to handle X amount of heroes upgrading X amount of abilities on X levels with another system?

What would you suggest in change of the strings?
 
Last edited:
Level 29
Joined
Oct 24, 2012
Messages
6,545
i would keep everything an integer. since they are integers.
then use a hashtable keyed to the hero and the level that it is supposed to gain a lvl in a new skill. when he gains the lvl u load the integer u saved ( the ability id) then increase the lvl of that ability.

this would be much nicer with structs as u could store all the abilities in the struct then when the lvl appears load the struct and lvl up the abilities that are supposed to lvl at that point.

if more than one ability should lvl up when hero gains a lvl. then u use a hashtable but key it to the unit and its lvl but instead of storing the ability id u store an indexed number. so if that unit is supposed to lvl 2 abilities at that point it will be 2. then u load the ability either in the same hashtable keyed to the unit and the number 1001 and 1002 since 2 abilities should be lvld. then u lvl those 2 abilities.

u can also use a modulo integer and lets say u have 6 abilities for that unit. when u load the integer from the hashtable keyed to the unit and its lvl if its a 14 then u use modulo integer and lvl abilities 1 and 4. this way u dont have to store a ton of things in the hashtable. this is probably the best option. and the easiest.
 
Top