• 🏆 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!
  • It's time for the first HD Modeling Contest of 2024. Join the theme discussion for Hive's HD Modeling Contest #6! Click here to post your idea!

[vJASS] Making a GUI-vJASS Save system, need feedback

Status
Not open for further replies.
Level 19
Joined
Aug 8, 2007
Messages
2,765
My idea was basically this, make a version of Nestharus's vJass code system so that a GUI user (using jngp) could input variables inside of a GUI trigger and the vJass would handle the rest. The problem is im terribad at vJass so can anyone look over my trigger and give me any feedback? I haven't tested it yet.

One of the main points of the listing phase in this trigger is that, when you make a new version and add items, you can just say set saveAbilNextVersion = Your first item of the next version and older versions will still be compatible.

Save Load onInit
Events
Map initialization
Conditions
Actions
-------- Basic Variables --------
Set savedHero[1] = Blood Mage 0009 <gen>
Set savedBackpack[1] = Mountain King 0001 <gen>
Set saveItemsBackpack = True
Set saveItemsHero = True
-------- You need to set savedHero and/or savedBackpack if they are ever changed mid-game. Same with PointWhereHeroLoads --------
Set saveExp = True
Set saveLevel = True
Set saveMaxHeroLevel = 4000
Set savePointWhereHeroLoads = (Position of (Triggering unit))
-------- Setting only XP will result in a level 1 hero with # exp --------
Set saveAbilities = True
Set saveHeroStats = True
Set saveInitialStatMax = 10
Set saveStatMaxPerLevel = 5
-------- Self Explanatory. Note that it will only count added stats, NOT base stats --------
Set saveGold = True
Set saveWood = True
Set saveGoldMax = 1000000
Set saveWoodMax = 1000000
-------- States the maximum for a player's gold, wood, and a unit's three stats --------
Set saveMessage = Saving.
Set saveOnLoadMessage = Loaded
-------- Messages on Loading and Saving --------
Set saveRepeatedCharacter = -
Set saveRepeatingCharacterDelay = 4
-------- The character "repeatedCharacter" shows every "repeatingCharacterDelay" characters --------
Set savePassword = Af9gk3
-------- Change this to wipe codes --------
Set saveColorNumber = 40e0d0
Set saveColorLowercase = ff69b4
Set saveColoruppercase = 00AA00
Set saveColorSpecial = ffff00
-------- Color codes. Must be hexadecimal or codes will be messed up --------
Set saveAlphabet = 0123456789abcdefghijklmnopqrstuvwxyz
Custom script:
-------- Begin Listing Phase --------
Custom script:
-------- Items --------
Set saveItems[0] = Claws of Attack +15
Set saveItems[1] = Scroll of Animate Dead
Set saveItemCharges[1] = True
-------- The variable with "Charges" states that it should not only save the item but the item charges as well. By default it's false so you don't have to set it for 0 charge iteems --------
Set saveItems[2] = Gem Fragment
Set saveItems[3] = Red Drake Egg
Set saveItemCharges[3] = True
Set newItemVersion[1] = 4
-------- Starts a version with new items. This must be added when you add items onto the list or else the old codes won't work --------
-------- The # indicates the first item to use that version --------
Set saveItems[4] = Skeletal Artifact
Set saveItems[5] = Scroll of Resurrection
Set saveItemCharges[5] = True
Set newItemVersion[2] = 6
Set saveItems[6] = Amulet of the Wild
Set newItemVersionMax = 2
-------- The last version used --------
Set saveItemsMax = 6
-------- From Here On, the listing is the same as above --------
-------- Abilities --------
Set saveAbility[0] = Storm Bolt
Set saveAbility[1] = Storm Bolt
Set newAbilVersion[1] = 2
Set saveAbility[2] = Thunder Clap
Set saveAbility[3] = Bash
Set saveAbility[4] = Avatar
Set newAbilVersionMax = 1
Set saveAbilMax = 3
-------- Heroes --------
Set saveHeroes[0] = Mountain King
Set saveHeroes[1] = Blood Mage
Set newHeroVersion[1] = 2
Set saveHeroes[2] = Paladin
Set saveHeroes[3] = Archmage
Set newHeroVersionMax = 1
Set saveHeroesMax = 3


This is the main vJass counterpart to the trigger

JASS:
struct SavingvJassCounterpart extends array
    private static Base encryptionKey
    
    private static method save takes nothing returns boolean
        local NumberStack stack = NumberStack.create(encryptionKey)
        local string encrypted
        local unit herounit = udg_savedHero[GetPlayerId(GetTriggerPlayer())]
        local unit backpackunit = udg_savedBackpack[GetPlayerId(GetTriggerPlayer())]
        if udg_saveItemsBackpack then
            call SaveValues.SaveHeroInventory(stack, backpackunit)
        endif
        if udg_saveItemsHero then
            call SaveValues.SaveHeroInventory(stack, herounit)
        endif
        if udg_saveAbilities then
            call SaveValues.SaveAbilites(stack, herounit)
        endif
        if udg_saveHeroStats then
            call SaveValues.SaveStats(stack, herounit)
        endif
        if udg_saveGold then
            call SaveValues.SaveGold(stack, GetTriggerPlayer())
        endif
        if udg_saveWood then
            call SaveValues.SaveWood(stack, GetTriggerPlayer())
        endif
        if udg_saveExp then
            call stack.push(CompressInt(GetHeroXP(herounit) - SaveValues.GetRequiredXP(GetHeroLevel(herounit))), CompressInt(SaveValues.GetRequiredXP(udg_saveMaxHeroLevel) - SaveValues.GetRequiredXP(udg_saveMaxHeroLevel - 1)))
        endif
        if udg_saveLevel then
           call stack.push(GetHeroLevel(herounit), udg_saveMaxHeroLevel)
        endif
        call stack.push(Heroes[GetUnitTypeId(herounit)].id,Heroes.count)
        set encrypted=EncryptNumber(stack,      1000000,                                3, /*
        */                          GetPlayerId(GetTriggerPlayer()),    udg_savePassword,   .85)
        set encrypted=AddRepeatedString(encrypted,udg_saveRepeatedCharacter,udg_saveRepeatingCharacterDelay,0)
        set encrypted=ColorCodeString(encrypted, udg_saveColorNumber,  udg_saveColorLowercase,    udg_saveColoruppercase,  udg_saveColorSpecial,                   0)
        call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,encrypted)
        call stack.destroy()
        
        return false
    endmethod
    
    private static method load takes nothing returns boolean
        local string s=GetEventPlayerChatString()
        local unit herounit
        local unit backpackunit
        local NumberStack stack                    
        set s=RemoveString(s,GetEventPlayerChatStringMatched(),1,       0) 
        set s=RemoveString(s," ",0,0)     
        set s=RemoveString(s, udg_saveRepeatedCharacter,0,0)
        if (0<StringLength(s)) then
            set stack = DecryptNumber(s,        encryptionKey,                          1000000,/*
            */                      3,                              GetPlayerId(GetTriggerPlayer()),/*
            */                      udg_savePassword,                   .85)
            if (0!=stack) then
                call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,udg_saveOnLoadMessage)
                set herounit = CreateUnitAtLoc(GetTriggerPlayer(), Heroes[stack.pop(Heroes.count)].raw, udg_savePointWhereHeroLoads, 0.)
                set backpackunit = udg_savedBackpack[GetPlayerId(GetTriggerPlayer())]
                if udg_saveLevel then
                    call SetHeroLevel(herounit, stack.pop(udg_saveMaxHeroLevel), false)
                endif
                if udg_saveExp then
                    call AddHeroXP(herounit, stack.pop(SaveValues.GetRequiredXP(udg_saveMaxHeroLevel) - SaveValues.GetRequiredXP(udg_saveMaxHeroLevel - 1)), false)
                endif
                if udg_saveWood then
                    call SetPlayerState(GetTriggerPlayer(),PLAYER_STATE_RESOURCE_LUMBER, stack.pop(DecompressInt(udg_saveWoodMax)))
                endif
                if udg_saveGold then
                    call SetPlayerState(GetTriggerPlayer(), PLAYER_STATE_RESOURCE_GOLD, stack.pop(DecompressInt(udg_saveWoodMax)))
                endif
                if udg_saveHeroStats then
                    call LoadHeroStats(stack, herounit, udg_saveInitialStatMax + ((GetHeroLevel(herounit) * udg_saveStatMaxPerLevel)))
                endif
                if udg_saveAbilities then
                    call LoadHeroAbilities(stack, herounit, Abilites.catalog)
                endif
                if udg_saveItemsHero then
                    call LoadInventory(stack, herounit,Items.catalog)
                endif
                if udg_saveItemsBackpack then
                    call LoadInventory(stack, herounit,Items.catalog)
                endif
            else
                call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"Invalid Code")
            endif
        else
            call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,"Invalid Code")
        endif
        
        return false
    endmethod
    private static method onInit takes nothing returns nothing
        set encryptionKey=Base[udg_saveAlphabet]
        call InitSave("-save",      "-load",      Condition(function thistype.save),/*
                    */Condition(function thistype.load))
    endmethod
endstruct

My self-creating iteem catalog (its after the onInit trigger so it will fire with the correct variables)

JASS:
/********************************************************************************************
                                Item Catalog Creation
********************************************************************************************/
    struct Items extends array
        private static integer array catalogs
        private static integer catalogCount=0
        private static integer versionCurrent=1
        
        private static method operator nextVersion takes nothing returns integer
            set catalogCount=catalogCount+1
            set catalogs[catalogCount]=CatalogCreate()
            if (catalogCount>1) then
                call CatalogAddCatalog(catalogs[catalogCount],catalogs[catalogCount-1])
            endif
            return catalogs[catalogCount]
        endmethod
        
        private static method isNextVersion takes integer current, integer catalog returns integer
            if current == udg_newItemVersion[versionCurrent] then
                set versionCurrent = versionCurrent + 1
                return nextVersion
                endif
            return catalog
        endmethod
        
        private static method onInit takes nothing returns nothing
            local integer catalog=nextVersion
            local integer loopingInteger=0
            loop
                exitwhen loopingInteger==udg_saveItemsMax
                if udg_saveItemsHero then
                set catalog = isNextVersion(loopingInteger, catalog)
                call CatalogAdd(catalog, udg_saveItems[loopingInteger])
                endif
            endloop
        endmethod
        
        static method operator version takes nothing returns integer
            return catalogCount
        endmethod
        
        method operator count takes nothing returns integer
            return CatalogCount(this)
        endmethod
        
        static method operator [] takes integer catalogVersion returns thistype
            return catalogs[catalogVersion]
        endmethod
        
        method catalog takes nothing returns integer
            return this
        endmethod
        
        method raw takes integer itemId returns integer
            return CatalogRaw(this,itemId)
        endmethod
        
        method id takes integer itemTypeId returns integer
            return CatalogId(this,itemTypeId)
        endmethod
        
        //Saving
            //Items.version.id('id00')
            //Items.version.id(GetItemTypeId(item))
            //call stack.push(Items.version.id(GetItemTypeId(item)),Items.version.count)
            
            //using specific version rather than latest
            //Items[1].id('id00')
        
        //Loading
            //CreateItem(Items.version.raw(itemIdFromCode),0,0)
            //call CreateItem(Items.version.raw(stack.pop(Items.count)),0,0)
            
        //keep in mind that this will also work
        //catalog1.add('id00')
        //catalog2.addCatalog(catalog1)
        //catalog1.add('id01')
        
        //catalog 2 will had id00 and id01 and will have 2 total in it
        //this is great because it makes hero specific w/ slots item catalogs easy
        //can layer just like general item catalogs
    endstruct

Ability Catalog

JASS:
/********************************************************************************************
                                Ability Catalog Creation
********************************************************************************************/
    struct Abilites extends array
        private static integer array catalogs
        private static integer catalogCount=0
        private static integer versionCurrent=1
        
        private static method operator nextVersion takes nothing returns integer
            set catalogCount=catalogCount+1
            set catalogs[catalogCount]=CatalogCreate()
            if (catalogCount>1) then
                call CatalogAddCatalog(catalogs[catalogCount],catalogs[catalogCount-1])
            endif
            return catalogs[catalogCount]
        endmethod
        
        private static method isNextVersion takes integer current, integer catalog returns integer
            if current == udg_newAbilVersion[versionCurrent] then
                set versionCurrent = versionCurrent + 1
                return nextVersion
                endif
            return catalog
        endmethod
        
        private static method onInit takes nothing returns nothing
            local integer catalog=nextVersion
            local integer loopingInteger=0
            loop
                exitwhen loopingInteger==udg_saveAbilMax
                if udg_saveAbilities then
                    set catalog = isNextVersion(loopingInteger, catalog)
                    call CatalogAdd(catalog, udg_saveAbility[loopingInteger])
                endif
            endloop
        endmethod
        
        static method operator version takes nothing returns integer
            return catalogCount
        endmethod
        
        method operator count takes nothing returns integer
            return CatalogCount(this)
        endmethod
        
        static method operator [] takes integer catalogVersion returns thistype
            return catalogs[catalogVersion]
        endmethod
        
        method catalog takes nothing returns integer
            return this
        endmethod
        
        method raw takes integer itemId returns integer
            return CatalogRaw(this,itemId)
        endmethod
        
        method id takes integer itemTypeId returns integer
            return CatalogId(this,itemTypeId)
        endmethod
        
        //Saving
            //Items.version.id('id00')
            //Items.version.id(GetItemTypeId(item))
            //call stack.push(Items.version.id(GetItemTypeId(item)),Items.version.count)
            
            //using specific version rather than latest
            //Items[1].id('id00')
        
        //Loading
            //CreateItem(Items.version.raw(itemIdFromCode),0,0)
            //call CreateItem(Items.version.raw(stack.pop(Items.count)),0,0)
            
        //keep in mind that this will also work
        //catalog1.add('id00')
        //catalog2.addCatalog(catalog1)
        //catalog1.add('id01')
        
        //catalog 2 will had id00 and id01 and will have 2 total in it
        //this is great because it makes hero specific w/ slots item catalogs easy
        //can layer just like general item catalogs
    endstruct

and Hero Cat

JASS:
/********************************************************************************************
                                        Hero Catalog Creation
********************************************************************************************/
    struct Heroes extends array
        implement Catalog
        
        private static integer array catalogs
        private static integer catalogCount=0
        private static integer versionCurrent=1
        
        private static method operator nextVersion takes nothing returns integer
            set catalogCount=catalogCount+1
            set catalogs[catalogCount]=CatalogCreate()
            if (catalogCount>1) then
                call CatalogAddCatalog(catalogs[catalogCount],catalogs[catalogCount-1])
            endif
            return catalogs[catalogCount]
        endmethod
        
        private static method isNextVersion takes integer current, integer catalog returns integer
            if current == udg_newHeroVersion[versionCurrent] then
                set versionCurrent = versionCurrent + 1
                return nextVersion
                endif
            return catalog
        endmethod
        
        private static method onInit takes nothing returns nothing
            local integer catalog=nextVersion
            local integer loopingInteger=0
            loop
                exitwhen loopingInteger==udg_saveHeroesMax
                set catalog = isNextVersion(loopingInteger, catalog)
                call CatalogAdd(catalog, udg_saveHeroes[loopingInteger])
            endloop
        endmethod
        
        //Saving
            //Heroes['id00'].id
            //Heroes[GetUnitTypeId(hero)].id
            //call stack.push(Heroes[GetUnitTypeId(hero)].id,Heroes.count)
        
        //Loading
            //CreateUnit(Heroes[unitIdFromCode].raw,0,0)
            //call CreateUnit(Heroes[stack.pop(Heroes.count)].raw,0,0)
    endstruct

and a temporary struct, i might ditch this and inline it myself
JASS:
struct SaveValues
    static method SaveHeroInventory takes NumberStack stack, unit playerUnit returns nothing
        call SaveInventory(stack, playerUnit, Items.catalog)
    endmethod
    static method GetRequiredXP takes integer level returns integer
    local integer xp = 0
    loop
        exitwhen level == 0
        set xp = xp + (level + 1) * 100
        set level = level - 1
    endloop
    return xp
    endmethod
    static method SaveAbilites takes NumberStack stack, unit playerUnit returns nothing
        call SaveHeroAbilities(stack, playerUnit, Abilites.catalog)
    endmethod
    static method SaveStats takes NumberStack stack, unit playerUnit returns nothing
        call SaveHeroStats(stack, playerUnit, udg_saveInitialStatMax + (udg_saveStatMaxPerLevel * (GetHeroLevel(playerUnit) - 1)))
    endmethod
    static method SaveGold takes NumberStack stack, player triggering returns nothing
        call stack.push(CompressInt(GetPlayerState(triggering, PLAYER_STATE_RESOURCE_GOLD)), udg_saveGoldMax)
    endmethod
    static method SaveWood takes NumberStack stack, player triggering returns nothing
        call stack.push(CompressInt(GetPlayerState(triggering, PLAYER_STATE_RESOURCE_LUMBER)), udg_saveWoodMax)
    endmethod
    static method LoadHeroInventory takes NumberStack stack, unit target returns nothing
    endmethod
endstruct
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
Hm... actually, there is a much better way to do this.

You can essentially call vjass functions by using variable events. The GUI save/load system I was planning was going to do this.

For generating catalogs, you'd just set the createNewCatalog variable to 0 and then it'd create a new catalog for you. From there, you'd set the addCatalog value to w/e value you want and it'd add it to the catalog. You can also add catalogs to catalogs using this nifty trick.

After this, you can save values by just populating 2 arrays. One array would have the values and the other array would have the maxes. At the end, you'd set the saveValues to 0 or something to save all of the values. After this, you could set the checksum string to whatever checksum you wanted to use (multiple checksums if you wanted) and you could also set the encryptionStrength var to your desired encryption strength.

This design gives GUI users the same amount of power that vjass users have at the cost of a lot of performance ;p.

Another thing I could do to increase performance for init is to populate an array of values to be added to a catalog and then have an addValues variable where you set it to the catalog you want to add them to ; ).


So nice try with your GUI thing, but not good enough. It's too limited for practical use.


Unless the GUI system can handle exactly what the vjass system can handle, it's no good ;p. The only problem I was having was with making the GUI users able to create loaders for different versions, but I solved that problem. Register to a loadVersion event ^)^. I set the loadVersion variable to the version and that will in turn run their trigger ; ).


Now, if you want to continue with this (restarting your whole thing from square 1), you can do that. I will eventually get to the GUI save/load system as I have had many requests for one, but if you beat me to it, w/e, less work for me. Just be sure to design it right >.>. If it can't do what the vjass counterpart can do, it's no good, so keep trying until you can support everything that the vjass can support. This was the reason I was trying to teach you those advanced algorithms, so that you'd understand that the way you were going prevented GUI users from doing advanced save/load techniques.

When I am done updating the save/load with snippets map, I will be sure to move on to GUI save/load before I move on to the AI stuff I want to do.

GUI users don't need another save/load system with limited capabilities : |. They need the final answer, a framework with a GUI API for save/load that'll allow them to do whatever they want to do. It won't be as good as the vjass as vjass users will be able to pick and choose whatever snippets they want, but the framework will at least be able to be modified by a vjass coder so that the GUI user can do what they want.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
tbh i could barely understand any of that., but thats an achievement for me. First time i ever spoke to you my mind just about blew up. (below here, the # is the # of the paragraph)

2) Really? lol. I "might" do this if this turns out to be an init blower

3) I couldn't understand this too well... but instead of this (in the catalog triggers)
return nextVersion
i would swap it to
set createNewCatalog = 0
return catalog (or id just remove the return value and use it as a function)

5) elaborate? "performance" as in literal FPS or "performance" as in (see the statement below with a ton of #s)

6) Kinda repeating yourself there

The rest of the paragraphs reguarding the power that your system has over this ones) You're totally misconscruding the point. The purpose of this system is not to have the most efficient method, like your systems. My method is to have an easy-to-setup, easy-to-use GUI system that easily hits 1/3 the size of AceHart's and 100x the protection. While doing it in vJass is 1/5 the size and 500x more protection, thats not really the point.

When you say its "too limited for practical use", your totally right it is. Practical. A practical user should not be using GUI in the first place ...

(kinda tired and i cant speak straight, but if u dont get the point im saying its 100x better and easier than the current gui systems and will simply act as a bridge to vJass and your system)
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
My thing isn't a system though. The whole concept of what I wrote was to allow users to pick from many different written snippets to do what they want with ease. My thing is a collection of snippets that are put together to create a save/load system specifically tailored to the user's map. I'd want a GUI thing to achieve the same thing. By creating a general API for GUI users, you should be able to swap different snippets out for different purposes like you do in vjass.

What I am saying is that you can do better than this for GUI. Don't waste your time on this if you aren't going to do it perfectly because I'll just end up coming along later to replace what you wrote with something better >.>.


You can either keep working at it or give up here and now ; ). You need to either do as well or outdo my future design, or your thing will end up getting replaced. I may seem like I'm just being mean right now, but I'm really just being blunt with you so that you don't end up wasting your time on something that'll end up getting replaced later ;\.
 
Level 19
Joined
Aug 8, 2007
Messages
2,765
Yes, thats what you were trying to do. I was just trying to simply write a centralized system that anyone can import into their map, punch in some catalog values, and b00m.

i also loled at your "outdo my future design" your.. if i had to guess... mid-late college student and i havent even entered high school yet. Doubt i could pull that off.

Still, i have to ask, bit personal but why do you still mod wc3? There are infinitely better possibilites elsewhere (sc2, udk, and the one that starts with an s that i forgot) yet you waste your talents with this worthless engine-of-a-pixel.

Just sayin'. Wc3s basically already dead. I only mod because its SOO much easier but the innards of wc3 are starting to make me leave lol
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
wc3 has a great online community, meaning that you can create a map and put it up and have people play it with you. I hate SC2's editor and limitations and udk doesn't offer the same online community (I don't like single player games). Furthermore, udk doesn't have all of the art in it (models, icons, etc) that wc3 has.


I do own a commercial game engine that can be used for AAA games, but again, no art and the lack of the infrastructure that wc3 has makes me not work with it at all.



Also, I gave you my design... all you have to do is implement it. I'm not going to complain if you implement it as that means that there is less work for me to do. I personally detest GUI, so if you did it instead, that'd mean I wouldn't have to put myself through the nonsense of creating a GUI save/load resource.


Don't just give up with it. Keep going until you get it perfect ;p. Do you have any idea how many times I have rewritten save/load stuff? I spent like 3 months on Encoder only to trash it all and start over from scratch.


I first suggest that you read my entire save/load interactive tutorial and understand it all (work with the problems until you can get them). If you can do this, you will have mastered save/load. From here, you will then be able to work on that GUI resource you want to do. If you can't master save/load, then you obviously can't work on resources for save/load as you will not understand the consequences of your design.


Also, keep in mind that many people who use GUI do not want to use vjass at all because they are afraid of it. A GUI save/load system running on vjass is no good. The first step is to convert all of the vjass into JASS, which is something that I don't particularly want to do.
 
Level 31
Joined
Jul 10, 2007
Messages
6,306
This is what I'm talking about for the catalog stuff (the loading up)
JASS:
library CatalogGUI uses LevelGroupSlotVersionCatalog, LevelGroupVersionCatalog, LevelVersionCatalog, GroupVersionCatalog, VersionCatalog
    globals
        private Table charges
        private Table perishable
        
        private LevelGroupSlotVersionCatalog array levelGroupSlotVersionCatalog
        private LevelGroupVersionCatalog array levelGroupVersionCatalog
        private LevelVersionCatalog array levelVersionCatalog
        private GroupVersionCatalog array groupVersionCatalog
        private VersionCatalog array versionCatalog
    endglobals
    
    private struct itemCharge extends array
        static method operator [] takes integer index returns integer
            return udg_saveLoad_itemCharge[index]
        endmethod
    endstruct
    private struct itemPerishable extends array
        static method operator [] takes integer index returns boolean
            return udg_saveLoad_itemPerishable[index]
        endmethod
    endstruct
    
    private struct catalogGroup extends array
        static method operator [] takes integer index returns integer
            return udg_saveLoad_catalogGroup[index]
        endmethod
    endstruct
    private struct catalogSubGroup extends array
        static method operator [] takes integer index returns integer
            return udg_saveLoad_catalogSubGroup[index]
        endmethod
    endstruct
    private struct catalogLevel extends array
        static method operator [] takes integer index returns integer
            return udg_saveLoad_catalogLevel[index]
        endmethod
    endstruct
    private struct catalogSlot extends array
        static method operator [] takes integer index returns integer
            return udg_saveLoad_catalogSlot[index]
        endmethod
    endstruct
    private struct catalogValue extends array
        static method operator [] takes integer index returns integer
            return udg_saveLoad_catalogValue[index]
        endmethod
    endstruct
    private struct catalogVersion extends array
        static method operator [] takes integer index returns integer
            return udg_saveLoad_catalogVersion[index]
        endmethod
    endstruct
    private struct loadToCatalog extends array
        static method operator [] takes integer index returns integer
            return udg_saveLoad_loadToCatalog[index]
        endmethod
    endstruct
    
    private function LoadLevelGroupSlotVersionCatalog takes integer cur, LevelGroupSlotVersionCatalog curCatalog, integer curLevel, integer curGroup, integer curSubGroup, integer curSlot, integer curVersion returns integer
        /*
            /*************************************************************************************************
            *             version    parent group   sub group   slot
            *************************************************************************************************/
            call addGroup(cver,     'Hpal',         1,          1)
            
            /*************************************************************************************************
            *        item id    version     group id    slot id   level   max charge      isPerishable
            *************************************************************************************************/
            call add('totw',    cver,       1,          1,          1,      3,              true)
        */
        loop
            if (0 == curSubGroup) then
                call curCatalog.add(catalogValue[cur], curVersion, curGroup, curSlot, curLevel)
                if (0 != itemCharge[cur]) then
                    set charges[catalogValue[cur]] = itemCharge[cur]
                    set perishable.boolean[catalogValue[cur]] = itemPerishable[cur]
                endif
            else
                call curCatalog.addGroup(curVersion, curGroup, curSubGroup, curSlot)
            endif
            
            set cur = cur + 1
            exitwhen 0 != loadToCatalog[cur]
            if (0 != catalogSlot[cur]) then
                set curSlot = catalogSlot[cur]
            endif
            if (0 != catalogLevel[cur]) then
                set curLevel = catalogLevel[cur]
            endif
            if (0 != catalogGroup[cur]) then
                set curGroup = catalogGroup[cur]
            endif
            if (0 != catalogVersion[cur]) then
                set curVersion = catalogVersion[cur]
            endif
            set curSubGroup = catalogSubGroup[cur]
        endloop
        return cur
    endfunction
    private function LoadLevelGroupVersionCatalog takes integer cur, LevelGroupVersionCatalog curCatalog, integer curLevel, integer curGroup, integer curSubGroup, integer curVersion returns integer
        /*
            /*************************************************************************************************
            *             version    parent group   sub group
            *************************************************************************************************/
            call addGroup(cver,     'Hpal',         1)
            
            /*************************************************************************************************
            *        item id    version     group id    level   max charge      isPerishable
            *************************************************************************************************/
            call add('totw',    cver,       1,          1,      3,              true)
        */
        loop
            if (0 == curSubGroup) then
                call curCatalog.add(catalogValue[cur], curVersion, curGroup, curLevel)
                if (0 != itemCharge[cur]) then
                    set charges[catalogValue[cur]] = itemCharge[cur]
                    set perishable.boolean[catalogValue[cur]] = itemPerishable[cur]
                endif
            else
                call curCatalog.addGroup(curVersion, curGroup, curSubGroup)
            endif
            set cur = cur + 1
            exitwhen 0 != loadToCatalog[cur]
            if (0 != catalogLevel[cur]) then
                set curLevel = catalogLevel[cur]
            endif
            if (0 != catalogGroup[cur]) then
                set curGroup = catalogGroup[cur]
            endif
            if (0 != catalogVersion[cur]) then
                set curVersion = catalogVersion[cur]
            endif
            set curSubGroup = catalogSubGroup[cur]
        endloop
        return cur
    endfunction
    private function LoadLevelVersionCatalog takes integer cur, LevelVersionCatalog curCatalog, integer curLevel, integer curVersion returns integer
        /*
            /*************************************************************************************************
            *        item id    version     level   max charge      isPerishable
            *************************************************************************************************/
            call add('totw',    cver,       1,      3,              true)
        */
        loop
            call curCatalog.add(catalogValue[cur], curVersion, curLevel)
            if (0 != itemCharge[cur]) then
                set charges[catalogValue[cur]] = itemCharge[cur]
                set perishable.boolean[catalogValue[cur]] = itemPerishable[cur]
            endif
            set cur = cur + 1
            exitwhen 0 != loadToCatalog[cur]
            if (0 != catalogLevel[cur]) then
                set curLevel = catalogLevel[cur]
            endif
            if (0 != catalogVersion[cur]) then
                set curVersion = catalogVersion[cur]
            endif
        endloop
        return cur
    endfunction
    private function LoadGroupVersionCatalog takes integer cur, GroupVersionCatalog curCatalog, integer curGroup, integer curSubGroup, integer curVersion returns integer
        /*
            /*************************************************************************************************
            *             version    parent group   sub group
            *************************************************************************************************/
            call addGroup(cver,     'Hpal',         1)
            
            /*************************************************************************************************
            *        item id    version     group id    max charge      isPerishable
            *************************************************************************************************/
            call add('totw',    cver,       1,          3,              true)
        */
        loop
            if (0 == curSubGroup) then
                call curCatalog.add(catalogValue[cur], curVersion, curGroup)
                if (0 != itemCharge[cur]) then
                    set charges[catalogValue[cur]] = itemCharge[cur]
                    set perishable.boolean[catalogValue[cur]] = itemPerishable[cur]
                endif
            else
                call curCatalog.addGroup(curVersion, curGroup, curSubGroup)
            endif
            set cur = cur + 1
            exitwhen 0 != loadToCatalog[cur]
            if (0 != catalogGroup[cur]) then
                set curGroup = catalogGroup[cur]
            endif
            if (0 != catalogVersion[cur]) then
                set curVersion = catalogVersion[cur]
            endif
            set curSubGroup = catalogSubGroup[cur]
        endloop
        return cur
    endfunction
    private function LoadVersionCatalog takes integer cur, VersionCatalog curCatalog, integer curVersion returns integer
        /*
            /*************************************************************************************************
            *        item id    version     max charge      isPerishable
            *************************************************************************************************/
            call add('totw',    cver,       3,              true)
        */
        loop
            call curCatalog.add(catalogValue[cur], curVersion)
            if (0 != itemCharge[cur]) then
                set charges[catalogValue[cur]] = itemCharge[cur]
                set perishable.boolean[catalogValue[cur]] = itemPerishable[cur]
            endif
            set cur = cur + 1
            exitwhen 0 != loadToCatalog[cur]
            if (0 != catalogVersion[cur]) then
                set curVersion = catalogVersion[cur]
            endif
        endloop
        return cur
    endfunction
    
    private function LoadCatalogs takes nothing returns boolean
        local integer cur = 0
        local integer curLevel = 0
        local integer curGroup = 0
        local integer curSubGroup = 0
        local integer curSlot = 0
        local integer curVersion = 0
        local integer curCatalog = 0
        
        set udg_saveLoad_loadCatalogs = 0
        
        loop
            exitwhen 0 == catalogValue[cur]
            
            if (0 != catalogLevel[cur]) then
                set curLevel = catalogLevel[cur]
            endif
            if (0 != catalogGroup[cur]) then
                set curGroup = catalogGroup[cur]
            endif
            if (0 != catalogSubGroup[cur]) then
                set curSubGroup = catalogSubGroup[cur]
            endif
            if (0 != catalogSlot[cur]) then
                set curSlot = catalogSlot[cur]
            endif
            if (0 != catalogVersion[cur]) then
                set curVersion = catalogVersion[cur]
            endif
            if (0 != loadToCatalog[cur]) then
                set curCatalog = loadToCatalog[cur]
            endif
            
            if (0 == curSlot) then
                if (0 == curLevel and 0 == curGroup) then
                    //LoadVersionCatalog
                    if (0 == versionCatalog[curCatalog]) then
                        set versionCatalog[curCatalog] = VersionCatalog.create()
                    endif
                    set cur = LoadVersionCatalog(cur, versionCatalog[curCatalog], curVersion)
                elseif (0 == curLevel) then
                    //LoadGroupVersionCatalog
                    if (0 == groupVersionCatalog[curCatalog]) then
                        set groupVersionCatalog[curCatalog] = GroupVersionCatalog.create()
                    endif
                    set cur = LoadGroupVersionCatalog(cur, groupVersionCatalog[curCatalog], curGroup, curSubGroup, curVersion)
                elseif (0 == curGroup) then
                    //LoadLevelVersionCatalog
                    if (0 == levelVersionCatalog[curCatalog]) then
                        set levelVersionCatalog[curCatalog] = LevelVersionCatalog.create()
                    endif
                    set cur = LoadLevelVersionCatalog(cur, levelVersionCatalog[curCatalog], curLevel, curVersion)
                else
                    //LoadLevelGroupVersionCatalog
                    if (0 == levelGroupVersionCatalog[curCatalog]) then
                        set levelGroupVersionCatalog[curCatalog] = LevelGroupVersionCatalog.create()
                    endif
                    set cur = LoadLevelGroupVersionCatalog(cur, levelGroupVersionCatalog[curCatalog], curLevel, curGroup, curSubGroup, curVersion)
                endif
            else
                //LoadLevelGroupSlotVersionCatalog
                if (0 == levelGroupSlotVersionCatalog[curCatalog]) then
                    set levelGroupSlotVersionCatalog[curCatalog] = LevelGroupSlotVersionCatalog.create()
                endif
                set cur = LoadLevelGroupSlotVersionCatalog(cur, levelGroupSlotVersionCatalog[curCatalog], curLevel, curGroup, curSubGroup, curSlot, curVersion)
            endif
        endloop
        
        return false
    endfunction
    private module Init
        private static method onInit takes nothing returns nothing
            local trigger trig = CreateTrigger()
            call TriggerAddCondition(trig, Condition(function LoadCatalogs))
            call TriggerRegisterVariableEvent(trig, "udg_saveLoad_loadCatalogs", GREATER_THAN, 0)
            set trig = null
            set charges = Table.create()
            set perishable = Table.create()
        endmethod
    endmodule
    private struct Inits extends array
        implement Init
    endstruct
endlibrary

Still gotta write the reading part, but hopefully you get it. All of the catalog GUI vars are shown (look at structs and trigger register var event)

It's still limited as a GUI user probably won't be able to extend the catalogs to make more advanced catalogs, but they could get help from a vjass user to extend the API + catalogs =).

If I were very lazy, I could run everything through a 12 slot 12 range catalog filter, which is prob more than enough for any GUI user to ever use, but eh, I'll leave it up to vjass peeps to extend it where needed. The great thing about this design is that you can really add whatever you want to it pretty easily ;p.

Also, values like group ids and what not are kept until it runs into another non 0 value, so you don't have to populate tons of crap =). You can set the version once and it'll stay on that version until you set it to something else.


I would ofc love it if you took the above design and continued it so that I don't have to write a GUI save/load resource, lol.

edit
brilliant.. apparently need 3 different value arrays because you can't type things like 'belv' into an integer array for GUI... man do I seriously hate GUI with a passion.

I'm already annoyed now to the point where I don't want to work on this anymore just because of that, so I'll leave this to you. Be sure to put up what you do so that we make sure you are following the correct designs. Also be sure to completely master save/load, otherwise you won't be able to build a good GUI save/load resource.
 
Status
Not open for further replies.
Top