• 🏆 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!
  • 🏆 Hive's 6th HD Modeling Contest: Mechanical is now open! Design and model a mechanical creature, mechanized animal, a futuristic robotic being, or anything else your imagination can tinker with! 📅 Submissions close on June 30, 2024. Don't miss this opportunity to let your creativity shine! Enter now and show us your mechanical masterpiece! 🔗 Click here to enter!

MUI Advanced Equipment System (+Save/Load +Event)

This is my Advanced Equipment System

It is based on the same idea like many others: click on an item and it gets equipped, click on it in the equipment screen to unequip it.

It is advanced because it has many special options available!
Prevent unit types from equipping certain items.
Items may change animations.
Save/load code integration
and many more...

For explaination of the included functions check the documentations included in the map

Features:
  • decide whether a weapon is one or twohanded
  • give a unit a special animation tag, depending on the equiped item
  • an offhand tag will overwrite all mainhand tags (a shield will always cause defend animation)
  • functions for forcing equip/unequip
  • functions for getting information
  • functions for prohibiting a unit from equipping an item (for example for race-only items)
  • Save/load code generator included
  • Register Events to your triggers, firing on item equip and unequip
  • items can give countless abilities



my system is MUI, so every unit can have its own equipment, and easy to customize.
full documentation included.

New improved "How to import" and "How to Use" included, too!!

YOU NEED JNGP AND JASS KNOWLEDGE TO GET THIS WORKING! WITHOUT JNGP AND JASS KNOWLEDGE IT IS IMPOSSIBLE!

I importet some files!!!
the icons and models don't violate any rules, because they are necessary to show what this system can do!! credits ingame.

comment and if you like it maybe +rep^^
give credits when used

have fun

IMPORTANT:
For all who ask me to make the system in a spellbook:
That would be much more work for the users of this system and highly inefficient!!
I will not change that so don't ask me to do that anymore!




UPDATE v.1.5:
I read vercas suggestions and improved my scripting.
Adding an item is now much more simple^^
thx to vercas for his review

UPDATE v.2.0:
Tige_R found a bug, reseting the shield animation when another item got unequipped
fixed that!!

UPDATE v.3.0: BIG thx to teldrassil who found a huge bug which was settled in all my systems!!! i managed to fix it and updated ALL my newer systems!!!

UPDATE v.4.0: now there is no need anymore that the equipable items are of one itemclass! added system code to the description here

UPDATE v.5.0: it's possible now, to make items give up to 3 abilities when equipped instead of 1 in the previous versions...

UPDATE v.6.0: The bug fixed in v.2.0 was still there... now its really gone AND the script is 1.24 compatible

UPDATE v.6.5: added a new function (IsEquipmentClassEmpty) to check whether a specific unit has something from class x equipped
more information in the code

UPDATE v.7.0: added a new function (GetEquipItemID) to get an items rawcode which is equipped
more information in the code

UPDATE v.8.0: added 3 new functions (GetEquipItemIndex, EquipItemByIndex and EquipItemByID) to get an items index which is equipped (not the same as rawcode) and to equip a item by this index, which helps with the usage of Save/Load Systems
the last function makes you able to equip an item by its rawcode.
more information in the code

UPDATE v.9.0: again 2 new functions for prohibiting a unit from equipping an item or allowing it again for it(EnableItemEquipByID and EnableItemEquipByIndex) and a new function for getting the index of an item (not of its rawcode) --> GetItemIndex
Also much better performance because of the use of hastables!

UPDATE v.10.0: all O(n) searches are now replaced by hashtables!! also there is a new function (TransferEquipment) to move the equipment from unit a to unit b

UPDATE v.11.0: made the item registeration useable outside the library, improved documentation

Update v.12.0: created a how to import and structured the code a little more. also improved the empty-slot-icons

Update v.13.0: New code for equipping items and a new workaround for twohanded items

Update v.14.0: Reworked the beginning of the code, changed variable names, and removed a last rest of german i left in the testmap...


NEW versions:
Update v.2.0: At first I'd like to thank you for your great support!!
As so many of you love it I decided to refresh this a little!
Well i got a lot more experience since i first uploaded this and decided to remake the code... now takes advantage of much more efficient struct usage, doesn't need any hashtable anymore, runs smoother, more ways to work with (if you understand vJass), and many more new things...
Whole new documentation and new methods to work with!
Of course I kept the old names for most of the functions to make it easier for you to apply the new update!
SO: Have fun :D

Update v.2.1: Added Save/Load system, fixed the unequip function, added unequipAll function

Update v.2.2: Added Events and updated the "how to use"

UPDATE v.2.3: Thanks to creativeRPG for finding a very bad bug! i fixed it and suggest everyone to only use the new code!! the one from 2.2 may not work and freeze your game!

Update v.2.4: creativeRPG found more deadly bugs: you could equip items with all units you wanted to the unit owning the inventory and when equipping a one handed weapon while a two handed weapon was equipped the "offhand slot not available" button didn't vanish... fixed now! redownload is necessary!!!!!

Update v.2.5: aaaand again creativeRPG found a bug when you have too many items in your map the index gets too high for the system and it stops working

Update v.3.0: I chagned the whole code for equipping and unequipping and improved the ability handling:
its possible to get up to 50 abilitites from each item
added disbtns for my icons

Update v.3.1: Fixed bugs with syncing the inventories causing mass item creation on the map, made items in the dummys inventory undropable

Update v.4.0: Reduced Abilities per item to 20, fixed a bug for multiplayer usage preventing a second player from using the system, fixed an animation bug where the shield animation didn't disappear

Update v.5.0: New code cause the old one was buggy as hell :D works like a charm now

Update v.5.1: Fixed a bug regarding set Equipment[].owner=

Update v.5.2: Fixed a bug causing standard items to unequip registered equipment



JASS:
library AdvancedEquipmentSystem requires LinkedListModule, RegisterPlayerUnitEvent

    // The_Witcher's Equipment System
    //
    // This is my easy to use equipment system, which adds an equipment screen to any unit you want.
    //  equipped items can give up abilities to the owner and can change the animations of him...
    //
    //
    //       To learn how to use this system please read the "How To Use" delivered in the demo map
    //
    //
    // Requirements:
    //    JASS knowledge
    //    LinkedList (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-linkedlistmodule-206552/)
    //    RegisterPlayerUnitEvent (http://www.hiveworkshop.com/forums/jass-resources-412/snippet-registerplayerunitevent-203338/)
    //
    // have fun^^

    //**************************************************
    //********************SETUP PART********************
    //**************************************************

    globals
        // this is the rawcode of the unit which works as inventory
        public constant integer INVENTORY_DUMMY = 'h007'
     
        // this is the class you selected as mainhand class
        public constant integer MAINHAND_CLASS = 0
     
        // this is the class you selected as offhand class
        public constant integer OFFHAND_CLASS = 1
        
        // this is the amount of total classes you have
        public constant integer CLASSES = 9
     
        // this is the ability to close the inventory
        public constant integer EXIT_ABILITY = 'A00G'
     
        // this is the ability to open the inventory
        public constant integer OPEN_ABILITY = 'A003'
        
        // this is the ability which gives the dummy the same inventory as your hero has
        public constant integer INVENTORY_ABILITY = 'AInv'
     
        // this is the icon ability shown in the offhand slot when a twhoanded weapon is equipeed
        public constant integer TWOHAND_ABILITY = 'A00Z'
        public constant boolean SHOW_TWOHAND_ABILITY = true
     
        // this is the text shown when a unit is trying to equip an item which it isnt allowed to
        // example: " can't equip " becomes ingame something like   Soldier can't equip Giant Sword
        public constant string UNABLE_TO_EQUIP_STRING = " can't equip "
    endglobals

    //************************************************************
    //********************SETUP PART ENDS HERE********************
    //************************************************************
    //*****************Don't edit anything below******************
    //************************************************************

    globals
        private trigger OnEquip
        private trigger OnUnequip
        private integer TriggeringItem
        private unit EquippingUnit
        private hashtable table
    endglobals
    
    private struct AbilityList extends array
        integer abi
        implement LinkedList
        
        static method create takes nothing returns thistype
            return .createNode()
        endmethod
        
        method remove takes nothing returns nothing
            call .removeNode()
            call .deallocate()
        endmethod
        
        method add takes integer abi returns nothing
            local thistype new = .allocate()
            set new.abi = abi
            call .insertNode(new)
        endmethod
    endstruct


    // **** struct EquipmentItem ****
    private struct EquipmentItem extends array
        readonly integer id
        readonly integer class
        readonly AbilityList abilities
        readonly integer icon
        readonly boolean twohanded
        readonly string tag

        static method operator [] takes integer itemid returns EquipmentItem
            return itemid - 'I000' + CLASSES + 1
        endmethod
    
        static method create takes integer id, integer icon, integer class, boolean twohanded, string animation returns EquipmentItem
            local EquipmentItem this = id - 'I000' + CLASSES + 1
            if id - 'I000' >= 0 then
                call SaveBoolean(table, id - 'I000', 0, true)
            endif
            set .id = id
            set .class = class
            set .icon = icon
            if id >= CLASSES + 1 then
                set .abilities = AbilityList.create()
                if class == MAINHAND_CLASS then
                    set .twohanded = twohanded
                else
                    set .twohanded = false
                endif
                if (class == MAINHAND_CLASS or class == OFFHAND_CLASS) and id != 0 then
                    set .tag = animation
                else
                    set .tag = ""
                endif
            endif
            return this
        endmethod
        
        method addAbility takes integer abi returns nothing
            call .abilities.add( abi)
        endmethod
        
        method applyAbilities takes unit u, boolean add returns nothing
            local AbilityList node = .abilities.next
            loop
                exitwhen node.head
                if add then
                    call UnitAddAbility(u, node.abi)
                else
                    call UnitRemoveAbility(u, node.abi)
                endif
                set node = node.next
            endloop
        endmethod
    endstruct

    public function RegisterNewClass takes integer emptyicon, integer class returns nothing
        call EquipmentItem.create('I000' - CLASSES - 1 + class, emptyicon, class, false, "")
    endfunction

    // **** struct Equipment ****    
    struct Equipment
        private static EquipmentItem twohandIcon
    
        private unit u
        private unit dummy
        readonly string animtag = ""
        readonly EquipmentItem array Item [12]
    
        static method operator [] takes unit u returns Equipment
            return LoadInteger(table, GetHandleId(u), 0)
        endmethod
    
        method operator owner takes nothing returns unit
            return .u
        endmethod
    
        method operator owner= takes unit new returns nothing
            local integer i = 0
            loop
                exitwhen i >= CLASSES
                if .Item[i] != 0 then
                    call .Item[i].applyAbilities(.u, false)
                    call .Item[i].applyAbilities(new, true)
                endif
                set i = i + 1
            endloop
            call AddUnitAnimationProperties(.u, .animtag, false)
            call UnitRemoveAbility(.u, OPEN_ABILITY)
            call AddUnitAnimationProperties(new, .animtag, true)
            call UnitAddAbility(new, OPEN_ABILITY)
            set .u = new
            call SaveInteger(table, GetHandleId(.u), 0, this)
            call SaveInteger(table, GetHandleId(.dummy), 0, this)
        endmethod
        
        method syncInventories takes nothing returns nothing
            local integer i = 0
            loop
                exitwhen i >= 6
                call RemoveItem(UnitItemInSlot(.dummy, i))
                call UnitAddItemToSlotById(.dummy, GetItemTypeId(UnitItemInSlot(.u, i)), i)
                call SetItemDroppable(UnitItemInSlot(.dummy, i), false)
                set i = i + 1
            endloop
        endmethod
    
        private method refreshAnimation takes nothing returns nothing
            local string a = .Item[MAINHAND_CLASS].tag
            if .Item[OFFHAND_CLASS] != 0 and .Item[OFFHAND_CLASS] != twohandIcon then
                set a = .Item[OFFHAND_CLASS].tag
            endif
            call AddUnitAnimationProperties(.u, .animtag, false)
            call AddUnitAnimationProperties(.u, a, true)
            set .animtag = a
        endmethod
        
        method equipEmptyClass takes integer class returns nothing
            call UnitAddAbility(.dummy, EquipmentItem(class).icon)
            set .Item[class] = 0
        endmethod
        
        method equipTwohandIcon takes nothing returns nothing
            call UnitAddAbility(.dummy, twohandIcon.icon)
            set .Item[OFFHAND_CLASS] = twohandIcon
        endmethod
    
        method unequip takes integer class returns nothing
            local integer i = 0
            local EquipmentItem toRemove = .Item[class]
            if toRemove != 0 then
                if toRemove.twohanded then
                    call UnitRemoveAbility(.dummy, TWOHAND_ABILITY)
                    call .equipEmptyClass(OFFHAND_CLASS)
                endif
                call toRemove.applyAbilities(.u, false)
                call UnitAddItemById(.u, toRemove.id)
                set TriggeringItem = toRemove.id
                set EquippingUnit = .u
                call TriggerEvaluate(OnUnequip)
                call UnitRemoveAbility(.dummy, toRemove.icon)
            else
                call UnitRemoveAbility(.dummy, EquipmentItem(class).icon)
            endif
            set .Item[class] = 0
            call .refreshAnimation()
        endmethod
        
        method equip takes integer id returns nothing
            local EquipmentItem toEquip = EquipmentItem[id]
            local EquipmentItem mainEquip = .Item[MAINHAND_CLASS]
            // remove existing
            if mainEquip != 0 then
                if toEquip.twohanded or (mainEquip.twohanded and (toEquip.class == OFFHAND_CLASS or toEquip.class == MAINHAND_CLASS)) then
                    call .unequip(MAINHAND_CLASS)
                    call .unequip(OFFHAND_CLASS)
                    if toEquip.class == MAINHAND_CLASS and not toEquip.twohanded then
                        call .equipEmptyClass(OFFHAND_CLASS)
                    elseif toEquip.class == OFFHAND_CLASS then
                        call .equipEmptyClass(MAINHAND_CLASS)
                    endif
                endif
            endif
            call .unequip(toEquip.class)
            // new is twohanded ?
            if toEquip.twohanded then
                call .unequip(OFFHAND_CLASS)
                call .equipTwohandIcon()
                if not SHOW_TWOHAND_ABILITY then
                    call UnitRemoveAbility(.dummy, twohandIcon.icon)
                endif
            endif
            // equip new
            call toEquip.applyAbilities(.u, true)
            call UnitAddAbility(.dummy, toEquip.icon)
            set .Item[toEquip.class] = toEquip
            call .refreshAnimation()
            // fire trigger
            set EquippingUnit = .u
            set TriggeringItem = id
            call TriggerEvaluate(OnEquip)
        endmethod
        
        static method disable takes integer itemId, integer unitType, boolean flag returns nothing
            call SaveBoolean(table, itemId - 'I000', unitType, flag)
        endmethod
        
        private method onDestroy takes nothing returns nothing
            local integer i = 0
            call RemoveUnit(.dummy)
            loop
                exitwhen i > 12
                if .Item[i] != 0 then
                    call .Item[i].applyAbilities(.u, false)
                endif
                set i = i + 1
            endloop
            call AddUnitAnimationProperties(.u, .animtag, false)
            call UnitRemoveAbility(.u, OPEN_ABILITY)
        endmethod
    
        static method create takes unit u returns Equipment
            local Equipment this = Equipment[u]
            local integer i = 0
            local integer id = GetPlayerId(GetOwningPlayer(u))
            if this != 0 then
                call RemoveUnit(.dummy)
            else
                set this = Equipment.allocate()
                call SaveInteger(table, GetHandleId(u), 0, this)
            endif
            set .u = u
            set .dummy = CreateUnit(GetOwningPlayer(u), INVENTORY_DUMMY, GetUnitX(u), GetUnitY(u), 0)
            call SaveInteger(table, GetHandleId(.dummy), 0, this)
            call UnitAddAbility(.dummy, INVENTORY_ABILITY)
            call UnitAddAbility(.dummy, EXIT_ABILITY)
            call UnitAddAbility(.u, OPEN_ABILITY)
            loop
                exitwhen i >= CLASSES
                call .equipEmptyClass(i)
                set i = i + 1
            endloop
            return this
        endmethod
        

    // **** Other Stuff ****
        private static method Access takes nothing returns boolean
            local unit u = GetTriggerUnit()
            local Equipment inv = Equipment[u]
            local integer class
            local integer i = 0
            if GetSpellAbilityId() == EXIT_ABILITY then
                if GetLocalPlayer() == GetOwningPlayer(inv.u) then
                    call ClearSelection()
                    call SelectUnit(inv.u, true)
                endif
            elseif GetSpellAbilityId() == OPEN_ABILITY then
                call SetUnitX(inv.dummy, GetUnitX(inv.u))
                call SetUnitY(inv.dummy, GetUnitY(inv.u))
                if GetLocalPlayer() == GetOwningPlayer(inv.u) then
                    call ClearSelection()
                    call SelectUnit(inv.dummy, true)
                endif
                call inv.syncInventories()
            elseif GetUnitTypeId(u) == INVENTORY_DUMMY then
                loop
                    exitwhen i >= CLASSES
                    if inv.Item[i].icon == GetSpellAbilityId() then
                        set class = i
                        set i = CLASSES
                    endif
                    set i = i + 1
                endloop
                call inv.unequip(class)
                call inv.equipEmptyClass(class)
                call inv.syncInventories()
            endif
            set u = null
            return false
        endmethod

        private static method ItemEquip takes nothing returns boolean
            local unit u = GetTriggerUnit()
            local item ite = GetManipulatedItem()
            local integer i = 0
            local Equipment inv = Equipment[u]
            local EquipmentItem invIte = EquipmentItem[GetItemTypeId(ite)]
            if GetItemTypeId(ite) - 'I000' >= 0 then
                if LoadBoolean(table, GetItemTypeId(ite) - 'I000', 0) then
                    if invIte != 0 and inv != 0 then
                        if not LoadBoolean(table, GetItemTypeId(ite) - 'I000', GetUnitTypeId(inv.u)) then
                            if u == inv.u then
                                call inv.equip(GetItemTypeId(ite))
                                call RemoveItem(ite)
                                call inv.syncInventories()
                            elseif u == inv.dummy then
                                loop
                                    exitwhen i >= 6
                                    if invIte.id == GetItemTypeId(UnitItemInSlot(inv.u, i)) then
                                        call UnitUseItem(inv.u, UnitItemInSlot(inv.u, i))
                                        call RemoveItem(ite)
                                        set i = 7
                                    endif
                                    set i = i + 1
                                endloop
                            endif
                        else
                            call DisplayTextToPlayer(GetOwningPlayer(inv.u), 0, 0, GetUnitName(inv.u) + UNABLE_TO_EQUIP_STRING + GetItemName(ite))
                        endif
                    endif
                endif
            endif
            set u = null
            set ite = null
            return false
        endmethod
        
        private static method onInit takes nothing returns nothing
            set OnEquip = CreateTrigger()
            set OnUnequip = CreateTrigger()
            call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_USE_ITEM, function Equipment.ItemEquip)
            call RegisterPlayerUnitEvent(EVENT_PLAYER_UNIT_SPELL_CAST, function Equipment.Access)
            set .twohandIcon = EquipmentItem.create('I000' - 1, TWOHAND_ABILITY, 0, false, "")
            set table = InitHashtable()
        endmethod
        
        implement optional SaveLoadPlugin
    
    endstruct

    // **** Trigger Events ****
    function RegisterItemEquipEvent takes code func returns nothing
        call TriggerAddCondition(OnEquip, Filter(func))
    endfunction
    
    function RegisterItemUnequipEvent takes code func returns nothing
        call TriggerAddCondition(OnUnequip, Filter(func))
    endfunction
    
    function GetTriggeringItemId takes nothing returns integer
        return TriggeringItem
    endfunction
    
    function GetEquippingUnit takes nothing returns unit
        return EquippingUnit
    endfunction
   
   //wrappers
    function InitEquipment takes unit whichunit returns nothing
        call Equipment.create(whichunit)
    endfunction

    public function RegisterItem takes integer itemid, integer icon, integer class, boolean twohanded, string animation returns nothing
        call EquipmentItem.create(itemid, icon, class, twohanded, animation)
    endfunction
    
    public function AddItemAbility takes integer itemid, integer abi returns nothing
        call EquipmentItem[itemid].addAbility(abi)
    endfunction
    
    function EnableItemEquip takes integer itemId, integer unitType, boolean flag returns nothing
        call Equipment.disable(itemId, unitType, not flag)
    endfunction

    function IsEquipmentClassEmpty takes unit u, integer class returns boolean
        return Equipment[u].Item[class] == 0
    endfunction

    function EquipItem takes unit u, item ite returns nothing
        call Equipment[u].equip(GetItemTypeId(ite))
        call RemoveItem(ite)
    endfunction
    function EquipItemById takes unit u, integer itemId returns nothing
        call Equipment[u].equip(itemId)
    endfunction

    function UnequipItemById takes unit u, integer itemid returns nothing
        local integer class = EquipmentItem[itemid].class
        if Equipment[u].Item[class].id == itemid then
            call Equipment[u].unequip(EquipmentItem[itemid].class)
            call Equipment[u].equipEmptyClass(class)
        endif
    endfunction

    function UnequipItemByClass takes unit u, integer class returns nothing
        call Equipment[u].unequip(class)
        call Equipment[u].equipEmptyClass(class)
    endfunction

    function GetEquippedItemTypeId takes unit u, integer class returns integer
        return Equipment[u].Item[class].id
    endfunction

    function ChangeEquipmentOwner takes unit u, unit newowner returns nothing
        set Equipment[u].owner = newowner
    endfunction

    function UnequipAll takes unit u returns nothing
        local integer i = 1
        loop
            call Equipment[u].unequip(i)
            call Equipment[u].equipEmptyClass(i)
            exitwhen i >= CLASSES
            set i = i + 1
        endloop
    endfunction

endlibrary


//Code indented using The_Witcher's Script Language Aligner
//Download the newest version and report bugs at www.hiveworkshop.com

Keywords:
equipment, equip, system, item, hero, unit, bonus, stat, vjass, jngp, mui, mpi, animation, ability, save, load, hashtable, code, Event, events
Contents

Advanced Equipment System (Map)

Reviews
20:01, 26th Oct 2009 TriggerHappy187: Approved because of so many minimod approvals and high ratings. I also couldn't see anything wrong inside the code.
Gah! Still having trouble! The love between me and technology is so one-sided. :vw_sad:

So yeah the issue I'm having still is reloading the equipment code from the last map. I'm thinking it may have something to do with how I saved the game cache, here's what it looks like:



JASS:
function SaveEquipment takes player p returns string
        local integer i = 0
        local string s = ""
        loop
            set i = i + 1
            if Equipment.Item[i].id != MAX_ITEMS then
                set s = s + I2S(Equipment.Item[i].id - 'I000')
            endif
            set s = s + "x"
            exitwhen i >= classes
        endloop
        return s
        call StoreString  (udg_RPGTest, "Stuff", "Gear", s)
        return s
    endfunction
Unless I'm mistaken, I believe the value "s" it's saving in the game cache is the same s value that is established just earlier in the code (the equipment loadcode). I only came up with the Stuff and Gear handles in order to save the string into the cache as I didn't know what else to use.

It seems to compile fine in JNGP and the map runs fine in game, the problem arises when I try to reload it in the next map.

And here's the trigger (custom script in GUI) I used in the next map to restore the equipment:

  • Custom script: call LoadEquipment(player p, GetStoredString(udg_RPGTest, Stuff, Gear))
When I try to save this in JNGP I get syntax errors, and when I try to edit it I get more syntax and/or struct errors. I'm thinking the problem has something to do with the fact that the game when it reloads the map and runs this trigger it isn't sure what the "Stuff" and "Gear" values are and hence it will crash. Am I going about this the right way? The only thing I'm sure about is that I am doing something wrong lol.

Also@ Adkituz,

I remember you mentioned you were using this system for your own map. I was wondering if I could see what you used to get the save/load codes into a game cache and have it work between maps (I'm assuming that's what you meant earlier).


Thanks all.

Okay here is how to solve this ;)
after a function returns a value it doesn't execute the rest of its code!
just before you store the string there is a return which has to be removed so the function looks like this:

JASS:
function SaveEquipment takes player p returns string
        local integer i = 0
        local string s = ""
        loop
            set i = i + 1
            if Equipment.Item[i].id != MAX_ITEMS then
                set s = s + I2S(Equipment.Item[i].id - 'I000')
            endif
            set s = s + "x"
            exitwhen i >= classes
        endloop
        call StoreString  (udg_RPGTest, "Stuff", "Gear", s)
        return s
    endfunction
a far easier way, using the function i implemented and not your edited version, would be:

JASS:
call StoreString (udg_RPGTest, "Stuff", "Gear", SaveEquipment( <yourplayerhere> ) )
call this in the trigger where you want to save the code and its done ;)

the mistake when loading is that jass strings have to be in "
you used
  • Custom script: call LoadEquipment(player p, GetStoredString(udg_RPGTest, Stuff, Gear))
but it has to be

  • Custom script: call LoadEquipment(player p, GetStoredString(udg_RPGTest, "Stuff", "Gear"))
after you initialized your gamecache ;)

I hope this helps

The_Witcher
 
JASS:
        static method operator [] takes player p returns Equipment
            local integer id = GetPlayerId(p)
            if p==null or id > 11 then
                return 0
            endif
            return .all[id]
        endmethod
>

JASS:
static method operator [] takes player p returns Equipment
    debug if p==null or GetPlayerId(p) > 11 then
        debug return -1
    debug endif
    return GetPlayerId(p) // why not set 'this' to the player id?
    // you can make your struct extend an array too (you don't need
    // allocate and deallocate methods since you can easily have 
    // each struct index set to the player id (We have one struct per 
    // player))
endmethod

There are lots of things that could be optimized.
The system is still pretty cool though.
 
Level 2
Joined
Oct 18, 2011
Messages
10
So I tried both of your suggestions, the load script still does not compile. I tried all sorts of variations on the load script, and it doesn't want to compile. Is it possible we are using different versions of JNGP? I'm using the 5d edition.
 
So I tried both of your suggestions, the load script still does not compile. I tried all sorts of variations on the load script, and it doesn't want to compile. Is it possible we are using different versions of JNGP? I'm using the 5d edition.
Post your new load code? And update ur jass helper
 
Level 2
Joined
Oct 18, 2011
Messages
10
Tried looking for an updated Jasshelper. 0.9.1.2. is the most recent version correct? I got it from http://www.hiveworkshop.com/forums/warcraft-editing-tools-277/jasshelper-jass-newgen-pack-151844/

As for the load code:

  • Actions
    • Set p = Player 1 (Red)
    • Custom script: call LoadEquipment(player p, GetStoredString(udg_RPGTest, "Stuff", "Gear"))
This trigger is enabled by a series of triggers preceding it which also load up other game cache data such as the hero and the inventory dummy and resource count. If you want I'll also post those.

Do I need to establish the "Stuff" and "Gear" handles of the string prior to my loading the loadcode? I only chose those two since those names didn't appear anywhere else in all the code so I could avoid any sort of confusion of the other functions.
 
Level 2
Joined
Oct 18, 2011
Messages
10
Yep, that was what was causing it to hang up. Works perfectly now. I feel like such a tool lol. Thanks so much for the help Adiktuz and Witcher! :ogre_haosis:
 
Witcher, you do know that the save/load in this resource is garbage right? You should either remove the save/load or update it. Don't mislead people into using it ;o.

What makes a post a good post?
giving some helping advises and not only saying that somethings bad!

so tell me what you think is garbage? i agree that the code is easily modifyable but any advanced user could easily crypt the code.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
I am saying that you're save/load is 100% bad. I'd have to list everything it does. You can not fix it, you have to completely delete it and start over. There is no one problem, the entire thing is quite literally garbage.


For one, using BigInt will cut code size by half. Encryption is weak, player unique codes? versioned codes??

Even your catalog is poor : |

>.>

I am also not going to go over how to completely write a good save/load system from scratch... there is a tutorial for that


Here is the #1 save/load so you can compare
http://www.hiveworkshop.com/forums/spells-569/save-load-snippets-v1-2-1-2-a-202714/?prev=u=Nestharus


Your code uses a very obsolete method for save/load, which is what makes it so bad.

It is outdated ; P


edit
A tutorial that works to good save/load

http://www.hiveworkshop.com/forums/jass-ai-scripts-tutorials-280/saving-loading-192851/#post1884704

I am also writing an interactive tutorial that goes over everything in the above tutorial, but in a way so that it is understandable by anyone ; P. Someone who is very poor with math etc has been testing that interactive tutorial as I've been writing it and he has so far understood every chapter =). The interactive tutorial is still not done though ; P.

The tutorial is mainly up there if peope are curious about how save/load works or perhaps want to work on new encryption schemes =).


I apologize if I am being a bit rough ; P

edit
What you can do is write a SaveInventory and LoadInventory function for your inventory system that works with the save/load system I linked to =). I wrote one for default inventories, so why not write one for yours ; P.

The one I wrote is the absolute best one out there, so you might as well use it for your 2 functions =). You can put a static if in there to see if w/e lib exists (NumberStack or Buffer, don't remember which one you need to check). If it exists, then you include the save and load functions : ).
 
Last edited:
I am saying that you're save/load is 100% bad. I'd have to list everything it does. You can not fix it, you have to completely delete it and start over. There is no one problem, the entire thing is quite literally garbage.


For one, using BigInt will cut code size by half. Encryption is weak, player unique codes? versioned codes??

Even your catalog is poor : |

>.>

I am also not going to go over how to completely write a good save/load system from scratch... there is a tutorial for that


Here is the #1 save/load so you can compare
http://www.hiveworkshop.com/forums/spells-569/save-load-snippets-v1-2-1-2-a-202714/?prev=u=Nestharus


Your code uses a very obsolete method for save/load, which is what makes it so bad.

It is outdated ; P


edit
A tutorial that works to good save/load

http://www.hiveworkshop.com/forums/jass-ai-scripts-tutorials-280/saving-loading-192851/#post1884704

I am also writing an interactive tutorial that goes over everything in the above tutorial, but in a way so that it is understandable by anyone ; P. Someone who is very poor with math etc has been testing that interactive tutorial as I've been writing it and he has so far understood every chapter =). The interactive tutorial is still not done though ; P.

The tutorial is mainly up there if peope are curious about how save/load works or perhaps want to work on new encryption schemes =).


I apologize if I am being a bit rough ; P

edit
What you can do is write a SaveInventory and LoadInventory function for your inventory system that works with the save/load system I linked to =). I wrote one for default inventories, so why not write one for yours ; P.

The one I wrote is the absolute best one out there, so you might as well use it for your 2 functions =). You can put a static if in there to see if w/e lib exists (NumberStack or Buffer, don't remember which one you need to check). If it exists, then you include the save and load functions : ).

Some people simply don't get it-.- gratulations for your save sys but thats simply not what i aimed at.
and something that works well and was requested by many many users simply can't be garbage ;)
the implementation won't give users perfect load codes for a
multiplayer map! it is just one easy way to do so, for example to
store the systems data in a gamecache! if you are a map maker you
could take the code and split it up, mix it into other systems or even
write your own function...
thanks for your comment, i always appreciate helpful critism but this was just in the wrong direction...
and please stop advertising your system!
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
edit
Ok, rather than fight about this, run this map and do lessons 23-30 and 34-40 (34-40 cover conditional save/load, which can be used to save partial inventories). For partial inventories on your inventory system, you will need some advanced catalog design. The only tuts on that are in my save/load with snippets map right now ; |.
Interactive Save/Load Tutorial


That will fully tell you what I am talking about.


After you have done those lessons, then tell me what you are going to do. There is a resource out there called http://www.hiveworkshop.com/forums/jass-functions-413/system-bigint-188973/. My save/load stuff completely runs off of BigInt. BigInt just allows for really really big integers. I suggest you take a BigInt and put your data into that. Any good save/load resource should run off of BigInt ; |.


The NumberStack resource I wrote is just a wrapper for BigInt that stores values into single digits like the tutorial talks about.


The next thing you can do to improve your resource is very advanced catalog stuff, but that would require a lot of effort ; P.


If you insist on sticking with the strings even after seeing how terrible they are, then please delete the 2 functions as it would be better not to have them at all.
 
Last edited:
Your "itemData" should instead just be one hashtable, and instead of parent key "1" use "this" as the parent key.

This should use a module initializer, as if you are doing things from structs or classes the library init will fail to initialize first.

Nestharus, if someone has a problem with his save/load system they can request to Witcher to make it better. I don't think it necessary that he needs to delete everything and start over when you are the only one making the request, you being someone who isn't coming here with interests to use his system but just to comment on it.

I do not like the idea of Witcher coupling bad save/load codes with his own inventory, however it is an advantage for users that he has it instead of not having it, and users can decide for themselves how sucky it is.

If this was *only* a save/load system then there would be lots of room for breaking down every little fault it has, but since it is more of an afterthought than a core system component I just don't see the point in attacking it.
 

I agree with Bribe since its up to the users whether they use the SL code here or not since it is just a bonus optional stuff...

and for example on Sir_Render's case, it doesn't matter how long the code is I think since he saves it in a game cache rather than print it out... so in the end, it has no effect on the player since the player won't even see the code...

and if users want to have a good SL system, they can just get Nestharus' system... or they probably already have it so there's no point in The_Witcher duplicating a part of that into his system...


one thing I really like in this system (aside from the fact that its really easy to use), is that its also easy to modify.
 
I'd recommend making the save/load in a seperate trigger inside a module and implement the module optionally into your main struct.
This way, anyone who has problems with the save/load feature can modify it easily.

JASS:
module SaveLoadPlugin
    function SaveInventory takes unit u returns BigInt

    endfunction

    function LoadInventory takes unit u, BigInt k returns nothing

    endfunction
endmodule

implement optional SaveLoadPlugin

What I would do as a user:
call SaveInventory to get a BigInt and push it to the NumberStack.
When loading, I'd pop the BigInt and call LoadInventory.
Pretty easy ;P
 
Level 2
Joined
Dec 23, 2011
Messages
8
I'll give a 5/5 for this system. But I have 1 problem.

When I copy the triggers in my map, it shows many errors. I don't know VJass. It shows more than 6000 errors. I just copied the last 2 triggers.
 
Level 8
Joined
May 30, 2009
Messages
266
I dont know if you still work on this, but I found a few bugs ;)

Disabling items does not work in any way, All items i register with the system are automatically disabled

The Ability loop when adding and removing items stops at 19 abilities instead of 20, because you use >=

The documentation uses deprecated and removed function calls as examples and has some statements wrong like 50 abilities per item etc.

You should mention what kind of abilities do not need an icon so that you can add them to heroes without problems (e.g. you cant add trueshot auras, because they have an icon) in the documentation.

Oh and I couldn't find a quick way to remove the offhand and mainhand class without destroying the whole code. Some users don't need those classes and you should think about an alternative for those. And also some users might want to have 3 ring slots instead of only 1, so maybe improve this aswell :)
 
For the last one, its pretty easy easy to do those if you know how the system works... I think the item classes here as the basic of what one would use, and its just up to the user if he wants to modify them...

for the trueshot, I think all auras behave like that so you can't really add auras without having to use the disabled spellbook method... maybe he can add a how to do that on the documentation...
 
Level 3
Joined
Jul 8, 2011
Messages
22
Edit: i finally found what the problem is you can't use this system in a map if u have lot of items because there is a limitation of it so it sux , sry the system is very good and a very good ideea but only if you use it on a map with few items
 
Last edited:
Level 3
Joined
Dec 4, 2008
Messages
24
Hey guys Hey Witcher love ur system man 5/5
but i hav a little problem with the so called equipment transfer function where as the others said will transfer the current equipment of "u"(variable) to another version of the unit lets say a range version SO.....

My question is can anyone provide with an EXAMPLE not some explaination of this function where my hero will change to a range version of itself WHEN equiping lets say... a range weapon and if i unequip it my hero will revert to its melee form while retaining its equipments

TY in advance
 
Last edited:
Huge update!
I recreated nearly the whole code ;)

nothing was removed but a lot improved:
- fixed a bug at transfering equipments between units
- made the save/load codes optional plugins
- improved the event handling
- uses linkedList and RegisterPlayerUnitEvent now
- many more fixes ;)

please keep up your helpful critism!
and thanks for making this system #1 in top 20 ;)

The_Witcher
 
Big question... how do you run activated item abilities? It doesn't seem possible when using this since clicking on the item unequips it ; ).

You could add activated abilities to the unit, so you'd get an ability if you equip an item ;o.

what do you mean with "activated item abilities"?

in general all you do is register the abilities to an item type and everytime you equip the item, the system runs through the list of abilities and adds them or removes them on unequip to/from the equipment's owner...

if it has no icon it simply doesn't show up (mostly item abilities) and if it has one (active/aura) you have to cast it or maybe add it via a disabled spellbook.
 
Level 1
Joined
May 11, 2010
Messages
2
How can I fix this error?

Line 156 (found in Linked List): The only static operators supported so far are [] and [] = wait for another version.
 
How can I fix this error?

Line 156 (found in Linked List): The only static operators supported so far are [] and [] = wait for another version.

The LinkedList Module works flawless! besides it's not even coded by me.
Please update your jasshelper to the newest version or even better, install cohadars mod!
 
Top