System Libram

PurgeandFire

zxcvmkgdfg
Reaction score
509
Libram v3.0.0.0:

This is a library that creates a "libram", something very similar to a spellbook. It has the same functionality, but was made for convenience for gameplay.

A libram is essentially a bunch of pages with abilities on them. Much like an extended inventory system, you can flip through the pages and access whatever abilities you need. There are only 5 slots, but you can always remove the page up and page down abilities (and opt for the items or the arrow key method) for 2 more slots per page.

Essentially, you can cast whatever spells you want, and if you need to access another ability, just turn the page. This can lead to cool spell organization, such as if you want one page for damage spells, one page for healing spells, and one page for tank spells. All cooldowns are preserved, passives work just fine (if you read the documentation and follow the instructions), and all that good stuff. You can also edit abilities just as you normally would, so it is completely safe to change the level of an ability in the libram without the use of custom functions.

I also have an optional module that can enable the abilities for page up and page down, or you can alternatively use arrow keys. (or both) With 2.0.0.0, you can also use items for swapping. (they are all optional, but I recommend using at least one of them as it is a pain to code it yourself)

Requirements: Any unit indexer, such as AIDS, UnitIndexer, AutoIndex, Bribe's GUI Indexer, etc..

This library also features nice Lua for easy generation. Just read the trigger, "How to Implement" on how to setup the system in your map, it is pretty easy.

Here is the code:
JASS:
library Libram requires optional LibramPageShift // ALSO REQUIRES ANY UNIT INDEXER
//~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//
//      Libram                   v. 3 . 0 . 0 . 0
//      ¯¯¯¯¯¯                   ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
//
//          What is it?
//          ¯¯¯¯¯¯¯¯¯¯¯
//                  -  This library adds "pages" for abilities, which extends the limit of the amount of abilities
//                      a hero can have.
//                  -  It simulates a spellbook, but with a bit more convenience in that you still have access to
//                      standard abilities, such as "move" or "attack". 
//                  -  A libram acts as a "book" of one or more pages. Each page has several abilities.
//
//          Pros:
//          ¯¯¯¯
//                  -  It can support a very large amount of pages and abilities.
//                  -  It supports passive abilities.
//                  -  Cooldowns are maintained when switching between pages.
//                  -  You don't have to use special functions when handling with the abilities.
//
//          Cons:
//          ¯¯¯¯
//                  -  This currently supports only 11 PASSIVE abilities per unit, assuming you use the spellbook method.
//                  -  This does have a limit of pages and abilities, but you will most likely never reach it. (unless you have like 80 pages per unit)
//                  -  MUI: THIS IS MUI TO AN EXTENT. It will work perfectly fine with multiple units, but those units
//                  CANNOT share any abilities. For example, two heroes cannot both have the ability "Holy Light", or else
//                  it will bug out, even if only one of them have a libram activated.
//                  -  Autocast abilities won't be automatically casted if the libram is on a different page than the autocast.
//
//          Requirements:
//          ¯¯¯¯¯¯¯¯¯¯¯¯¯
//                - LibramPageShift : OPTIONAL
//                - Any unit indexer, AIDS, UnitIndexer, etc...
//
//          Usage:
//          ¯¯¯¯¯¯
//
/*              call Libram.create(unit) returns Libram                             */
//
//                  - This creates a new libram for a unit. It includes one empty, page. The instance returned is
//                      the user ID of the unit.
//
//                   Libram(instance).caster        - Returns the unit who has that libram.
//                   Libram(instance).first          - Returns the first page of the libram.
//                   Libram(instance).curr          - Returns the page that the player currently has open.
//
/*              call Libram(instance).createPage() returns LibramPage                     */
//  
//                  - This creates a new page for a unit, after the last page. 
//
/*              call Libram(instance).createPageAfter(Page previous) returns LibramPage  */
//
//                  - This creates a new page ordered after the page you specify.
//
/*              call Libram(instance).addAbility(Page, integer ID)                  */
//
//                  - This adds an ability to a page, of the "ID" provided. (rawcode) 
//
/*              call Libram(instance).addPassive(Page, integer ID, integer spellbookID) */
//
//                  - Adds a passive ability to a page. You must use this function to add
//                    it if you want it to work properly. However, you must create a dummy
//                    spellbook for it. You can use my Lua scripts to ease this process.
//                    If you don't want it to be applied when the page is not shown, then
//                    you can just add it as if it were a normal ability.  
//
/*              call Libram(instance).removeAbility(Page, integer ID)                  */
//
//                  - This removes an ability from a page, of the "ID" provided. (rawcode)
//
/*              call Libram(instance).shiftPages(Page toShiftTo)                       */
//          
//                  - This flips the page to the page you specify, unlocking its abilities.
//
/*              call Libram(instance).refresh()                                        */
//
//                  - If you had just setup passive abilities, all the abilities might not show up. Use this function
//                      to refresh the pages, just to make sure that everything displays correctly.
//
/*              call Libram(instance).removePage(Page)                              */
//
//                  - Removes the specified page and all the abilities associated with it.
//
/*              call Libram(instance).destroy()                                     */
//
//                  - Destroys the libram, removes all of its pages, and removes all of the abilities.
//
/*              call Page(instance).findAbility(integer ID) returns AbilityList         */
//
//                  - Finds an ability listed on a page, and returns its AbilityList instance. (return 0 = not found)
//    
//
//          Notes:
//          ¯¯¯¯¯¯
//                  - If you add an ability normally, without using this system, then it will automatically go in a 
//                  free slot. If there are no free slots, it will not be added. It will appear on each page, as long
//                  as there is a free slot.
//                  - If you remove an ability normally that has data on a page (without using this system), then
//                  it will successfully remove the ability, but the data for it will still exist, so be sure
//                  to remove it using this system.
//~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
    
    private struct AbilityList
        readonly thistype next
        readonly thistype prev
        readonly integer curr
        integer spellbookID 
        
        method destroy takes nothing returns nothing
            set this.next.prev      = this.prev
            set this.prev.next      = this.next
            call this.deallocate()
        endmethod
        
        static method attach takes integer abilID, thistype head returns thistype
            local thistype this  = thistype.allocate()
            set head.next.prev   = this        
            set this.next        = head.next    
            set head.next        = this        
            set this.prev        = head      
            set this.curr        = abilID
            return this
        endmethod
    endstruct 

    struct LibramPage 
        AbilityList list
        thistype next
        thistype prev
        
        method findAbility takes integer ID returns AbilityList
            local AbilityList i = this.list.next
            loop
                exitwhen i.curr == ID or i == 0
                set i = i.next
            endloop
            return i //it will return "0" if it is not found
        endmethod
        
        method destroy takes nothing returns nothing
            local AbilityList clear = this.list.next
            loop
                exitwhen clear == 0
                call clear.destroy()
                set clear = clear.next
            endloop
            call this.deallocate()
        endmethod
        
        method removeAbility takes integer ID returns nothing
            local AbilityList i = this.findAbility(ID)
            if i == 0 then
                debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,15,"PAGE_ERROR["+I2S(this)+"]: Ability not listed on this page.")
                return
            endif
            call i.destroy()
        endmethod
        
        method addAbility takes integer ID returns AbilityList
            return AbilityList.attach(ID, this.list)
        endmethod
        
        static method insertAfter takes thistype node returns thistype
            local thistype this  = thistype.allocate()
            set this.list        = AbilityList.create()
            set node.next.prev   = this
            set this.next        = node.next
            set node.next        = this
            set this.prev        = node
            return this
        endmethod
    endstruct

    struct Libram extends array
        readonly unit caster
        readonly LibramPage first
        readonly LibramPage curr
        private player owner
        
        static method operator [] takes unit u returns thistype
            return GetUnitUserData(u)
        endmethod
        
        method shiftPages takes LibramPage which returns nothing
            local AbilityList i = this.curr.list.next
            local integer lvl 
            loop
                exitwhen i == 0
                if i.spellbookID != 0 then
                    set lvl = GetUnitAbilityLevel(this.caster,i.curr)
                    call UnitRemoveAbility(this.caster,i.curr)
                    call UnitAddAbility(this.caster,i.spellbookID)
                    call SetUnitAbilityLevel(this.caster,i.curr,lvl)
                else
                    call SetPlayerAbilityAvailable(this.owner,i.curr,false)
                endif
                set i = i.next
            endloop
            set this.curr = which
            set i = which.list.next
            loop
                exitwhen i == 0
                if i.spellbookID != 0 then
                    set lvl = GetUnitAbilityLevel(this.caster,i.curr)
                    call UnitRemoveAbility(this.caster,i.spellbookID)
                    call UnitAddAbility(this.caster,i.curr)
                    call SetUnitAbilityLevel(this.caster,i.curr,lvl)
                else
                    call SetPlayerAbilityAvailable(this.owner,i.curr,true)
                endif
                set i = i.next
            endloop
        endmethod
        
        method refresh takes nothing returns nothing
            call this.shiftPages(this.curr.next)
            call this.shiftPages(this.curr.prev)
        endmethod
        
        method createPage takes nothing returns LibramPage
            return LibramPage.insertAfter(this.first.prev)
        endmethod
        
        method createPageAfter takes LibramPage previous returns LibramPage
            return LibramPage.insertAfter(previous)
        endmethod
        
        method removeAbility takes LibramPage source, integer abilityID returns nothing
            local AbilityList i = source.findAbility(abilityID)
            local LibramPage k  = source.next
            local boolean rem   = true
            if i.spellbookID != 0 then
                call UnitRemoveAbility(this.caster,i.spellbookID)
            endif
            loop
                exitwhen k == source
                set rem = k.findAbility(abilityID)==0 //check if any other pages have this ability
                set k   = k.next
            endloop
            call source.removeAbility(abilityID)
            if rem then
                call UnitRemoveAbility(this.caster,abilityID)
                call SetPlayerAbilityAvailable(this.owner,abilityID,true)
            elseif this.curr == source then
                call this.refresh()
            endif
        endmethod
        
        method addPassive takes LibramPage target, integer abilityID, integer spellbookID returns nothing
            set target.addAbility(abilityID).spellbookID = spellbookID
            if this.curr != target then
                call UnitAddAbility(this.caster,spellbookID)
            else
                call UnitAddAbility(this.caster,abilityID)
            endif
            call SetPlayerAbilityAvailable(this.owner,spellbookID,false)
        endmethod
        
        method addAbility takes LibramPage target, integer abilityID returns nothing
            call target.addAbility(abilityID)
            call UnitAddAbility(this.caster,abilityID)
            if this.curr != target then
                call SetPlayerAbilityAvailable(this.owner,abilityID,false)
            endif
        endmethod
        
        method removePage takes LibramPage toRemove returns nothing
            local AbilityList i = toRemove.list.next
            loop
                exitwhen i == 0
                call this.removeAbility(toRemove,i.curr)
                set i = i.next
            endloop
            if this.curr == toRemove then
                call this.shiftPages(this.curr.next)
            endif
            call toRemove.destroy()
        endmethod
        
        method destroy takes nothing returns nothing
            local LibramPage p = this.first.next
            loop
                exitwhen p == this.first
                call this.removePage(p)
                set p = p.next
            endloop
            call this.removePage(p) //remove the head as well
            static if LIBRARY_LibramPageShift then
                static if LibramPageShift_ENABLE_ABILITY_SHIFT then 
                    call UnitRemoveAbility(this.caster,thistype.PAGE_UP)
                    call UnitRemoveAbility(this.caster,thistype.PAGE_DOWN)
                endif
                static if LibramPageShift_ENABLE_ITEM_SHIFT then
                    call RemoveItem(UnitItemInSlot(this.caster,thistype.PAGE_UP_SLOT))
                    call RemoveItem(UnitItemInSlot(this.caster,thistype.PAGE_DOWN_SLOT))
                endif
            endif
            set this.caster = null
        endmethod
        
        static method create takes unit cast returns thistype
            local thistype this    = GetUnitUserData(cast)
            set this.first         = LibramPage.create()
            set this.first.next    = this.first
            set this.first.prev    = this.first
            set this.first.list    = AbilityList.create()
            set this.curr          = this.first
            set this.caster        = cast
            set this.owner         = GetOwningPlayer(cast)
            static if LIBRARY_LibramPageShift then
                static if LibramPageShift_ENABLE_ABILITY_SHIFT then
                    call UnitAddAbility(cast,thistype.PAGE_UP)
                    call UnitAddAbility(cast,thistype.PAGE_DOWN)
                endif
                static if LibramPageShift_ENABLE_ITEM_SHIFT then
                    call UnitAddItemToSlotById(this.caster,thistype.PAGE_UP_ITEM,thistype.PAGE_UP_SLOT)
                    call UnitAddItemToSlotById(this.caster,thistype.PAGE_DOWN_ITEM,thistype.PAGE_DOWN_SLOT)
                endif
            endif
            return this
        endmethod
        
        implement optional LibramInit
        
    endstruct
    
    // Wrapper functions, you can remove this if you don't need it.
    
    // call AddLibram( unit u ) 
        //  Creates a libram for a unit and assigns lastCreatedLibram to it.
    // call AddLibramPage()
        //  Adds a page to the last created libram.
    // call AddLibramAbility( integer abilityID )
        //  Adds an ability to the last created page.
    // call AddLibramPassive( integer abilityID , integer spellbookID )
        //  Adds a passive ability to the last created page. (see documentation for information on passives)
    // The functions above are order dependent. The functions below are for general access:
    
    // call AddPageToUnit( unit u )
        //  Adds a new page to a unit.
    // call AddAbilityToPage( unit u, LibramPage page, integer abilityID )
        //  Adds an ability to a specific page of a unit.
    // call AddPassiveToPage( unit u, LibramPage page, integer abilityID, integer spellbookID )
        //  Adds a passive ability to a specific page of a unit. (see documentation for information on passives)
    // call GetUnitLibram( unit u ) returns Libram
        //  Returns the Libram instance of a unit.
    // call GetLibramPageFromIndex( Libram which, integer index ) returns LibramPage
        //  Returns the nth page of a libram. The first page of a libram has an index
        //  of 1. The next page has an index of 2. Third page has an index of 3... etc.
        
    // lastCreatedLibram - The last created libram from the wrapper functions.
    // lastCreatedPage - The last created page from the wrapper functions.
    
    globals
        Libram lastCreatedLibram   = 0
        LibramPage lastCreatedPage = 0
    endglobals
    
    function AddLibram takes unit owner returns nothing
        set lastCreatedLibram = Libram.create(owner)
        set lastCreatedPage   = lastCreatedLibram.first
    endfunction
    
    function AddLibramPage takes nothing returns nothing
        set lastCreatedPage = lastCreatedLibram.createPage()
    endfunction
    
    function AddLibramAbility takes integer abilityID returns nothing
        call lastCreatedLibram.addAbility(lastCreatedPage, abilityID)
    endfunction
    
    function AddLibramPassive takes integer abilityID, integer spellbookID returns nothing
        call lastCreatedLibram.addPassive(lastCreatedPage, abilityID, spellbookID)
    endfunction
    
    function AddPageToUnit takes unit u returns nothing
        set lastCreatedPage = Libram<u>.createPage()
    endfunction
    
    function AddAbilityToPage takes unit u, LibramPage page, integer abilityID returns nothing
        call Libram<u>.addAbility(page, abilityID)
    endfunction
    
    function AddPassiveToPage takes unit u, LibramPage page, integer abilityID, integer spellbookID returns nothing
        call Libram<u>.addPassive(page, abilityID, spellbookID)
    endfunction
    
    function GetUnitLibram takes unit u returns Libram
        return Libram<u>
    endfunction
    
    function GetLibramPageFromIndex takes Libram which, integer index returns LibramPage
        local LibramPage i = which.first
        local integer c    = 1 
        loop
            if index == c then
                return i
            endif
            set i = i.next
            set c = c + 1
            exitwhen i == which.first
        endloop
        debug call DisplayTextToPlayer(GetLocalPlayer(),0,0,&quot;GetLibramPageFromIndex: Could not retrieve the page of index &quot;+I2S(index)+&quot; of Libram(&quot;+I2S(which)+&quot;).&quot;)
        return 0
    endfunction
    
endlibrary</u></u></u></u>


JASS:
library LibramPageShift
//~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
//
//      LibramPageShift                 
//      ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯                      
//
//          What is it?
//          ¯¯¯¯¯¯¯¯¯¯¯
//                  -  This library enables shifting with abilities, items, and arrow keys. (up and down)
//                  -  All of them can be disabled/enabled.
//
//          Usage:
//          ¯¯¯¯¯
//                  ENABLE_KEY_SHIFT     - Enables shifting pages with arrow keys.
//                  ENABLE_ABILITY_SHIFT - Enables shifting pages with abilities.
//                  ENABLE_ITEM_SHIFT    - Enables shifting pages with items.
//
//                  PAGE_UP              - The rawcode of the &quot;Page Up&quot; ability.
//                  PAGE_DOWN            - The rawcode of the &quot;Page Down&quot; ability.
//
//                  PAGE_UP_ITEM         - The rawcode of the &quot;Page Up&quot; item.
//                  PAGE_DOWN_ITEM       - The rawcode of the &quot;Page Down&quot; item.    
//
//                  PAGE_UP_BUFF         - In order for the abilities to not interrupt the current order,
//                                       they must be based off specific spells. Currently, it is using
//                                       Mana Shield and Berserk. If you change it to something else, then
//                                       you have to change the corresponding buff, so that the buff won&#039;t appear.
//                  PAGE_DOWN_BUFF       - Same as above.    
//
//          NOTE:
//          ¯¯¯¯
//              For this to work properly, your unit cannot have any abilities based off of Berserk or Mana Shield.
//          If you do, then you either need to change the ability or change the abilities in this system. Simply base 
//          the spell off of a different spell that does not interrupt order:
//              Berserk, Defend, Magical Defense, Mana Shield, Immolation, Divine Shield
//          And then change the PAGE_UP_BUFF and/or PAGE_DOWN_BUFF accordingly.                         
//
//~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

    globals
        public  constant boolean ENABLE_KEY_SHIFT     = true
        public  constant boolean ENABLE_ABILITY_SHIFT = true
        public  constant boolean ENABLE_ITEM_SHIFT    = true
    endglobals 

    module LibramInit
        static if ENABLE_KEY_SHIFT then
            private static group G = CreateGroup()
            static eventid ev
        endif
        
        static constant integer PAGE_UP_BUFF   = &#039;BNms&#039; // Mana Shield
        static constant integer PAGE_DOWN_BUFF = &#039;Bbsk&#039; // Berserk
        
        static if ENABLE_ABILITY_SHIFT then
            static constant integer PAGE_UP   = &#039;Apup&#039;
            static constant integer PAGE_DOWN = &#039;Apdn&#039;
        endif
        static if ENABLE_ITEM_SHIFT then
            static constant integer PAGE_UP_ITEM           = &#039;Ipup&#039;
            static constant integer PAGE_DOWN_ITEM         = &#039;Ipdn&#039;
            static constant integer PAGE_UP_SLOT           = 4
            static constant integer PAGE_DOWN_SLOT         = 5
        endif
        
        static if ENABLE_KEY_SHIFT then
            private static method filter takes nothing returns boolean
                local thistype this = Libram(GetUnitUserData(GetFilterUnit()))
                if this.caster != null then
                    if thistype.ev == EVENT_PLAYER_ARROW_UP_DOWN then
                        call this.shiftPages(this.curr.next)
                    elseif thistype.ev == EVENT_PLAYER_ARROW_DOWN_DOWN then
                        call this.shiftPages(this.curr.prev)
                    endif
                endif
                return false
            endmethod
        endif
        
        static timer        BuffRemoval = CreateTimer()
        static integer      RemoveBuffMax = 0
        static unit array   RemoveBuff
        
        static method RemoveBuffs takes nothing returns nothing
            loop
                exitwhen RemoveBuffMax == 0
                call UnitRemoveAbility(RemoveBuff[RemoveBuffMax], PAGE_UP_BUFF)
                call UnitRemoveAbility(RemoveBuff[RemoveBuffMax], PAGE_DOWN_BUFF)
                set RemoveBuffMax = RemoveBuffMax - 1
            endloop
        endmethod

        static method onShift takes nothing returns boolean
            local unit     cast = GetTriggerUnit()
            local thistype this = GetUnitUserData(cast)
            local integer  id   = GetSpellAbilityId()
            
            if cast == null then
                static if ENABLE_KEY_SHIFT then
                    set thistype.ev = GetTriggerEventId()
                    call GroupEnumUnitsSelected(thistype.G,GetTriggerPlayer(),Condition(function thistype.filter))
                    return false
                endif
            endif
            static if ENABLE_ABILITY_SHIFT then
                if id == thistype.PAGE_UP or id == thistype.PAGE_DOWN then
                    set RemoveBuffMax = RemoveBuffMax + 1
                    set RemoveBuff[RemoveBuffMax] = cast
                    call TimerStart(thistype.BuffRemoval,0,false,function thistype.RemoveBuffs)
                    if id == thistype.PAGE_UP then
                        if UnitRemoveAbility(cast,id) then
                            call UnitAddAbility(cast,id)
                        endif
                        call this.shiftPages(this.curr.next)
                    elseif id == thistype.PAGE_DOWN then
                        call this.shiftPages(this.curr.prev)
                    endif
                    set cast = null
                    return false
                endif
            endif
            static if ENABLE_ITEM_SHIFT then
                set id = GetItemTypeId(GetManipulatedItem())
                if id != 0 then
                    set RemoveBuffMax = RemoveBuffMax + 1
                    set RemoveBuff[RemoveBuffMax] = cast
                    call TimerStart(thistype.BuffRemoval,0,false,function thistype.RemoveBuffs)
                    if id == thistype.PAGE_UP_ITEM then
                        call this.shiftPages(this.curr.next)
                    elseif id == thistype.PAGE_DOWN_ITEM then
                        call this.shiftPages(this.curr.prev)
                    endif
                endif
            endif
            return false
        endmethod
    
        static method onInit takes nothing returns nothing
            local trigger t  = CreateTrigger()
            local integer i  = 11
            loop
                if GetPlayerSlotState(Player(i))==PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(i))==MAP_CONTROL_USER then
                    static if ENABLE_ABILITY_SHIFT then
                        call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_SPELL_EFFECT,null)
                    endif
                    static if ENABLE_ITEM_SHIFT then
                        call TriggerRegisterPlayerUnitEvent(t,Player(i),EVENT_PLAYER_UNIT_USE_ITEM,null)
                    endif
                    static if ENABLE_KEY_SHIFT then
                        call TriggerRegisterPlayerEvent(t,Player(i),EVENT_PLAYER_ARROW_UP_DOWN)
                        call TriggerRegisterPlayerEvent(t,Player(i),EVENT_PLAYER_ARROW_DOWN_DOWN)
                    endif
                endif
                exitwhen i == 0
                set i = i - 1
            endloop
            call TriggerAddCondition(t,Condition(function thistype.onShift))
        endmethod
    endmodule

endlibrary


abilsys04.png


It is decently light, as it is just a bunch of linked lists. The lists themselves will normally be short (unless you are insane/doing something weird), so it shouldn't be a problem in terms of speed.

Please report any bugs you find (aside from the fact that Illidan doesn't properly metamorphosis, lol). Sorry if I didn't explain it properly. The test map will explain it all, hopefully. Enjoy!

Also, thanks to Weep for confirming something for me in a thread.

Changelog:
3.0.0.0
  • It is now MUI, to an extent. See the documentation for details.
  • The code has been improved, and it now requires an indexer.
  • Lua has been added to instantly generate the needed objects for the Libram Page Shift add-on.
  • The spells and items no longer interrupt the unit's order.
  • Simple wrapper functions have been added, to make it easier for those who wish to use GUI or simpler JASS. (you still end up using mostly JASS)
2.0.0.0
  • Added support for ordering pages. (at least upon creation)
  • Added support for using items to shift pages.
  • No longer requires the "Alloc" library.
  • Improved the code and made more of the variables readonly.
  • Fixed a bug concerning one ability on multiple pages. If it were removed, it would affect the other pages as well, and they would not have it. But now I fixed that so that the data is still removed from the page, but the ability itself is not removed unless it is not on any other pages.
1.0.0.0
  • Initial release.
 

Attachments

  • Libram 3.0.0.0.w3x
    63.5 KB · Views: 404

Lyerae

I keep popping up on this site from time to time.
Reaction score
105
Pretty cool. One small note, when you use the hotkey (V I think it was) to change it, it stops the hero from moving, and that's quite annoying.
 

luorax

Invasion in Duskwood
Reaction score
67
Yep, use thunderclap to create it. There're more instant casted spells, but that's the only I can remember right now.
 

tooltiperror

Super Moderator
Reaction score
231
JASS:
//                  -  It is MPI, so only one unit per player can use this system. Sadly, that is not fixable without
//                      breaking the system.


Surely this can be MUI?
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Yeah, it can be MUI, but there are a few things:
- If it is MUI, each unit with the library of a specific player must have different abilities than any other hero. (so two units can't have storm bolt for the same player)

It uses SetPlayerAbilityAvailable, so I made it MPI. I guess I can make it MUI though.. I just wasn't sure how many people would use this for more than one unit. :p

EDIT: I forgot to mention that in the documentation. That rule applies regardless of whether it is MPI or MUI, so I'll add it soon.
 

Sevion

The DIY Ninja
Reaction score
413
;P It's the first time I actually saw any real use for AIDS (or any Unit Indexing system). With this though, AIDS would make it so much easier.
 

Sim

Forum Administrator
Staff member
Reaction score
534
If you can fix that MPI-MUI problem, I'd definitely approve this.

Sounds really neat. :p
 

NeuroToxin

New Member
Reaction score
46
Download from me.

To any RPGers this sounds interesting.

To add GUI easiness to this, just make functions which create the unit for them?
JASS:
function AddLibram takes unit u returns integer
local structtype s = structtype.create(u)
endfunction
//Of course I&#039;m too lazy to look at your code above to fix this, but you get the jist.
 

Narks

Vastly intelligent whale-like being from the stars
Reaction score
90
JASS:
call SetPlayerAbilityAvailable(p,i.curr,true)


I don't think this can become MUI.

On another note, I just figured out how I'm going to do my MUI spellbooks...
 

PurgeandFire

zxcvmkgdfg
Reaction score
509
Download from me.

To any RPGers this sounds interesting.

To add GUI easiness to this, just make functions which create the unit for them?
JASS:
function AddLibram takes unit u returns integer
local structtype s = structtype.create(u)
endfunction
//Of course I&#039;m too lazy to look at your code above to fix this, but you get the jist.

Will do, thanks. :)

JASS:
call SetPlayerAbilityAvailable(p,i.curr,true)


I don't think this can become MUI.

On another note, I just figured out how I'm going to do my MUI spellbooks...

It can be MUI... but to a certain extent. :p

It will allow for multiple units per player, but each unit must have different abilities than any other unit of that player with the libram activated. Otherwise, it may disable the spells for a unit and stuff. I may be able to add something to detect selection to make it MUI, but it wouldn't work with multi-selection. I'll keep it MUI, but to an extent. :D

I'll update this eventually; I already have a working version and stuff, I just need to fix a few quirks.
 

Sevion

The DIY Ninja
Reaction score
413
Instead of [ljass]SetPlayerAbilityAvailable[/ljass], why not use [ljass]UnitAddAbility[/ljass] and [ljass]UnitRemoveAbility[/ljass]? A little more work, but it should work fine.
 

Laiev

Hey Listen!!
Reaction score
188
@Sevion

Because it bug the animation/cast of ability.

ie: Do it with a morph ability, will crash the game.
 

luorax

Invasion in Duskwood
Reaction score
67
Instead of [ljass]SetPlayerAbilityAvailable[/ljass], why not use [ljass]UnitAddAbility[/ljass] and [ljass]UnitRemoveAbility[/ljass]? A little more work, but it should work fine.

That would remove the cooldowns.
 

tooltiperror

Super Moderator
Reaction score
231
Although MPI, it is MPI at the cost of what Warcraft III has given us, and I guess it must remain this way to be functional.

However, for the majority of AoS-genre maps, this is good enough, and it serves its purpose fine.

Approved.
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    I am great and it is fantastic to see you my friend!
    +1
  • The Helper The Helper:
    If you are new to the site please check out the Recipe and Food Forum https://www.thehelper.net/forums/recipes-and-food.220/
  • Monovertex Monovertex:
    How come you're so into recipes lately? Never saw this much interest in this topic in the old days of TH.net
  • Monovertex Monovertex:
    Hmm, how do I change my signature?
  • tom_mai78101 tom_mai78101:
    Signatures can be edit in your account profile. As for the old stuffs, I'm thinking it's because Blizzard is now under Microsoft, and because of Microsoft Xbox going the way it is, it's dreadful.
  • The Helper The Helper:
    I am not big on the recipes I am just promoting them - I use the site as a practice place promoting stuff
    +2
  • Monovertex Monovertex:
    @tom_mai78101 I must be blind. If I go on my profile I don't see any area to edit the signature; If I go to account details (settings) I don't see any signature area either.
  • The Helper The Helper:
    You can get there if you click the bell icon (alerts) and choose preferences from the bottom, signature will be in the menu on the left there https://www.thehelper.net/account/preferences
  • The Helper The Helper:
    I think I need to split the Sci/Tech news forum into 2 one for Science and one for Tech but I am hating all the moving of posts I would have to do
  • The Helper The Helper:
    What is up Old Mountain Shadow?
  • The Helper The Helper:
    Happy Thursday!
    +1
  • Varine Varine:
    Crazy how much 3d printing has come in the last few years. Sad that it's not as easily modifiable though
  • Varine Varine:
    I bought an Ender 3 during the pandemic and tinkered with it all the time. Just bought a Sovol, not as easy. I'm trying to make it use a different nozzle because I have a fuck ton of Volcanos, and they use what is basically a modified volcano that is just a smidge longer, and almost every part on this thing needs to be redone to make it work
  • Varine Varine:
    Luckily I have a 3d printer for that, I guess. But it's ridiculous. The regular volcanos are 21mm, these Sovol versions are about 23.5mm
  • Varine Varine:
    So, 2.5mm longer. But the thing that measures the bed is about 1.5mm above the nozzle, so if I swap it with a volcano then I'm 1mm behind it. So cool, new bracket to swap that, but THEN the fan shroud to direct air at the part is ALSO going to be .5mm to low, and so I need to redo that, but by doing that it is a little bit off where it should be blowing and it's throwing it at the heating block instead of the part, and fuck man
  • Varine Varine:
    I didn't realize they designed this entire thing to NOT be modded. I would have just got a fucking Bambu if I knew that, the whole point was I could fuck with this. And no one else makes shit for Sovol so I have to go through them, and they have... interesting pricing models. So I have a new extruder altogether that I'm taking apart and going to just design a whole new one to use my nozzles. Dumb design.
  • Varine Varine:
    Can't just buy a new heatblock, you need to get a whole hotend - so block, heater cartridge, thermistor, heatbreak, and nozzle. And they put this fucking paste in there so I can't take the thermistor or cartridge out with any ease, that's 30 dollars. Or you can get the whole extrudor with the direct driver AND that heatblock for like 50, but you still can't get any of it to come apart
  • Varine Varine:
    Partsbuilt has individual parts I found but they're expensive. I think I can get bits swapped around and make this work with generic shit though
  • Ghan Ghan:
    Heard Houston got hit pretty bad by storms last night. Hope all is well with TH.
  • The Helper The Helper:
    Power back on finally - all is good here no damage
    +2
  • V-SNES V-SNES:
    Happy Friday!
    +1
  • The Helper The Helper:
    New recipe is another summer dessert Berry and Peach Cheesecake - https://www.thehelper.net/threads/recipe-berry-and-peach-cheesecake.194169/

      The Helper Discord

      Members online

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials

      Network Sponsors

      Apex Steel Pipe - Buys and sells Steel Pipe.
      Top