• 💀 Happy Halloween! 💀 It's time to vote for the best terrain! Check out the entries to Hive's HD Terrain Contest #2 - Vampire Folklore.❗️Poll closes on November 14, 2023. 🔗Click here to cast your vote!
  • 🏆 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!
  • 🏆 HD Level Design Contest #1 is OPEN! Contestants must create a maze with at least one entry point, and at least one exit point. The map should be made in HD mode, and should not be openable in SD. Only custom models from Hive's HD model and texture sections are allowed. The only exceptions are DNC models and omnilights. This is mainly a visual and design oriented contest, not technical. The UI and video walkthrough rules are there to give everyone an equal shot at victory by standardizing how viewers see the terrain. 🔗Click here to enter!

[Snippet] [Needs work] Get Learned Abilities

Level 31
Joined
Jul 10, 2007
Messages
6,306
Not necessarily order learned. Just think of it like an ability array on the unit and index accesses that array. Count gets the count of that array.

edit
Sadly, this isn't useful for save/load ; P.


I actually made it for my custom xp script thingie as part of the fix to fix levels (UnitStripHeroLevel).
 
Last edited:
Well, how about this:

JASS:
private function Ability takes nothing returns boolean
        local integer i = GetUnitUserData(GetTriggerUnit())
        if (not Table(marked[i]).boolean.has(GetLearnedSkill())) then
            set Table(abils[i])[c[i]]=GetLearnedSkill()
            set Table(marked[i]).boolean[GetLearnedSkill()]=true
            set c[i]=c[i]+1
        endif
        return false
    endfunction

->

JASS:
    private function Ability takes nothing returns boolean
        local integer i = GetUnitUserData(GetTriggerUnit())
        local integer a = GetLearnedSkill()
        if (not Table(marked[i]).boolean.has(a)) then
            set Table(abils[i])[c[i]]=a
            set Table(marked[i]).boolean[a]=true
            set c[i]=c[i]+1
        endif
        return false
    endfunction

After all, it returns an integer, so creating a local here would be ok :)
 

Bribe

Code Moderator
Level 49
Joined
Sep 26, 2009
Messages
9,400
Ok, so suppose you are using Libram with hero abilities, and so you could have multiple layers of different hero abilities (of course you'd learn them along the way and some paradigms will display 0 abilities until you learn them)... will this still work?

Also, you still don't need the typecasting for the Tables, since they are already typecasted as Tables when you load them.
 

Bribe

Code Moderator
Level 49
Joined
Sep 26, 2009
Messages
9,400
Well it looks like you deallocate the learned ability if the ability was removed from the hero when you do the "count" method, and it would return 0 even for abilities that are potentially there just temporarily "removed" by Libram. I don't really see the point in checking if the ability was removed... I'm sure you have a reason though. Care to elaborate?
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
If a hero lost some levels or an ability was removed with UnitRemoveAbility >.>.

If Libram removes abilities, then yea, it'll return 0. The way to fix it is by hooking UnitAddAbility and UnitRemoveAbility, but that's a bit of overhead. This is only supposed to be for wc3 regular abilities, heh.


I could have a boolean option for hooking though ; )
 
I think Libram could use an update. I'll get around to it later on and try to make it compatible if it isn't already. Libram won't remove abilities aside from passives (unless you explicitly tell it to do so), it just disables them, so there shouldn't be a problem there as far as I know. (GetUnitAbilityLevel() will still != 0) But I will need to test it out for passives, ofc, since they are removed. :p

It actually should work fine with most learned abilities, but I haven't tested it yet. I'll test it sometime this weekend or something.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
You could still elimate all the "Table()" typecasting and this needs a better description how to use it and why to use it.

Eh, no real need to remove the table typecasting. It's just extra work for me with no benefit ; P.

why to use it

I'm not going to write something on that. You use it when you have a need for it, end of story -.-. I wrote it because I ended up having a need for it.

how to use it

I'll add that it's an indexed array of abilities ; )
 

Bribe

Code Moderator
Level 49
Joined
Sep 26, 2009
Messages
9,400
Then your resource suffers obscurity. I can't really think of a reason for it other than the reason you already supported for your other resource, and with that in mind I feel it better to just inline it directly into that other resource. I know how much you hate to couple resources but I feel without any real purpose of this system aside from that one other library it kind of doesn't belong on its own. I think it was troll-brain who said "Cool!=Useful" and I agree with that here --

  1. Get learned abilities
  2. ???
  3. Profit!! (but what kind of profit?)
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Then your resource suffers obscurity. I can't really think of a reason for it other than the reason you already supported for your other resource, and with that in mind I feel it better to just inline it directly into that other resource. I know how much you hate to couple resources but I feel without any real purpose of this system aside from that one other library it kind of doesn't belong on its own. I think it was troll-brain who said "Cool!=Useful" and I agree with that here --

You know that almost no matter what, I refuse to couple. I will never couple 2 resources together for modularity purposes ; ).


And obviously gy'ing this will require gy'ing Hero Reward, which is an extremely useful lib.
 

Bribe

Code Moderator
Level 49
Joined
Sep 26, 2009
Messages
9,400
I'm not gonna graveyard it so long as it's not inlined but sometimes with JASS you gotta do some ugly stuff inside your code.

With your normal programming you have other rules that help to support modularity but in this case I just don't see the point in adding a requirement that's only going to ever be used for one resource.
 
  1. Get learned abilities
  2. ???
  3. Profit!! (but what kind of profit?)

Works for me
TrollFace.png


I guess one way to save this resource is by making another one that requires it. (lol)
 

Bribe

Code Moderator
Level 49
Joined
Sep 26, 2009
Messages
9,400
This version has the updates I have been looking for:

JASS:
library GetLearnedAbilities /* v1.1.0.0
*************************************************************************************
*
*   Allows one to retrieve all currently learned abilities of a unit
*
*************************************************************************************
*
*   */ requires /*
*
*       */ UnitIndexer /*             hiveworkshop.com/forums/showthread.php?t=172090
*       */ Table /*                   hiveworkshop.com/forums/showthread.php?t=188084
*       */ RegisterPlayerUnitEvent /* hiveworkshop.com/forums/showthread.php?t=203338
*
************************************************************************************
*
*   struct LearnedAbilities extends array
*
*       static method operator [] takes unit u returns LearnedAbilities
*       method operator [] takes integer index returns integer abilityId
*
*       method operator count takes nothing returns integer abilityCount
*
***********************************************************************************/
    globals
        private Table abils
        private Table marked
        private integer array c
    endglobals
    private function Index takes nothing returns boolean
        set abils[GetIndexedUnitId()] = Table.create()
        set marked[GetIndexedUnitId()] = Table.create()
        return false
    endfunction
    private function Deindex takes nothing returns boolean
        call abils[GetIndexedUnitId()].destroy()
        call marked[GetIndexedUnitId()].destroy()
        set c[GetIndexedUnitId()] = 0
        return false
    endfunction
    private function Ability takes nothing returns nothing
        local integer i = GetUnitUserData(GetTriggerUnit())
        if (not marked[i].boolean.has(GetLearnedSkill())) then
            set abils[i][c[i]] = GetLearnedSkill()
            set marked[i].boolean[GetLearnedSkill()] = true
            set c[i] = c[i] + 1
        endif
    endfunction
    private module M
        private static method onInit takes nothing returns nothing
            set abils = Table.create()
            set marked = Table.create()
            call RegisterUnitIndexEvent(Filter(function Index), UnitIndexer.INDEX)
            call RegisterUnitIndexEvent(Filter(function Deindex), UnitIndexer.DEINDEX)
            call RegisterPlayerUnitEvent(EVENT_PLAYER_HERO_SKILL, function Ability)
        endmethod
    endmodule
    struct LearnedAbilities extends array
        static method operator [] takes unit u returns LearnedAbilities
            return GetUnitUserData(u)
        endmethod
        method operator [] takes integer index returns integer
            return abils[this][index]
        endmethod
        method operator count takes nothing returns integer
            local integer i = c[this]
            local integer m
            loop
                exitwhen i == 0
                set i = i - 1
                set m = abils[this][i]
                if GetUnitAbilityLevel(GetUnitById(this), m) == 0 then
                    call marked[this].remove(m)
                    set c[this] = c[this] - 1
                    set abils[this][i] = abils[this][c[this]]
                    call abils[this].remove(c[this])
                endif
            endloop
            return c[this]
        endmethod
        implement M
    endstruct
endlibrary
 
Top