nestharus / JASS

MIT License
31 stars 8 forks source link

Save/Load Issues #25

Open DDLegionTN opened 9 years ago

DDLegionTN commented 9 years ago

First of all, thanks for reading my post. I had 2 issues currently regarding to your save/load system.

DDLegionTN commented 9 years ago

Sorry, accidentally posted without completing the post, 1st issue i facing is when my hero lv is 1, when loaded it became lv 2. For 2nd, the function SelectHeroSkill() doesn't works for me, and also my heroes don't have skill points, all the abilities are added/leveled through trigger. So i couldn't save abilities for my heroes, any ideas? Below is my save/load code :

Saver :

private function OnSave takes nothing returns nothing
    call SaveHeroAbilities(stack, udg_Hero[playerId], AbilityCatalog[GetUnitTypeId(udg_Hero[playerId])])
    call stack.push(GetPlayerState(triggerPlayer, PLAYER_STATE_RESOURCE_GOLD)/100, 10000)
    call stack.push(GetPlayerState(triggerPlayer, PLAYER_STATE_RESOURCE_LUMBER)/100, 10000)
    call stack.push(udg_Hero_XP[playerId+1], 10000) //Max 10000 (Current XP)
    call stack.push(udg_Hero_XP2[playerId+1], 10000) //Max 10000 (Lv up required XP)
    call stack.push(GetHeroLevel(udg_Hero[playerId]), 50) //Max lv 50 <-----Problem here
    call stack.push(S2I(udg_Player_DungeonString[playerId]), 2000) //Max Dungeon Integer 2000
    call SaveUnitMana(stack, udg_Hero[playerId])
    call SaveUnitLife(stack, udg_Hero[playerId])
    call SaveInventory(stack, udg_Hero[playerId], ItemCatalog.catalog)
    call SaveInventory(stack, udg_Player_Bag[playerId+1], ItemCatalog.catalog)
    call stack.push(Heroes[GetUnitTypeId(udg_Hero[playerId])].id, Heroes.count)
endfunction

Loader :

globals
    private constant integer VERSION_COUNT = 1

    private unit loadedUnit
endglobals

private function OnLoadBuffer1 takes nothing returns nothing
    set udg_Player_Bag[playerId+1] = CreateUnit(triggerPlayer, 'h006', GetRectCenterX(gg_rct_Starting_Point), GetRectCenterY(gg_rct_Starting_Point), 0)
    call Buffer.reset()

    set loadedUnit = CreateUnit(triggerPlayer, Heroes[stack.pop(Heroes.count)].raw, GetRectCenterX(gg_rct_Starting_Point), GetRectCenterY(gg_rct_Starting_Point), 0)
    call LoadInventory(stack, udg_Player_Bag[playerId+1], ItemCatalog.catalog)
    call LoadInventory(stack, loadedUnit, ItemCatalog.catalog)
    call LoadUnitLife(stack, loadedUnit)
    call LoadUnitMana(stack, loadedUnit)

    call Buffer.write(stack.pop(2000))
    call SetHeroLevel(loadedUnit, stack.pop(50), false) //Max lv 50 <---- Loaded here with lv2
    call Buffer.write(stack.pop(10000)) //Max XP 10000
    call Buffer.write(stack.pop(10000)) //Max XP 10000
    call Buffer.write(stack.pop(10000)*100)     //lumber
    call Buffer.write(stack.pop(10000)*100)     //gold
    call LoadHeroAbilities(stack, loadedUnit, AbilityCatalog[GetUnitTypeId(loadedUnit)])
endfunction
private function OnLoad1 takes nothing returns nothing
    local multiboarditem mb
    set udg_Hero[playerId] = loadedUnit
    set udg_Player_DungeonString[playerId] = I2S(Buffer.read())
    set udg_Hero_XP2[playerId+1] = Buffer.read()
      if udg_Hero_XP2[playerId+1] == 45 and GetHeroLevel(udg_Hero[playerId]) == 2 then
        call SetHeroLevel(loadedUnit, 1, false)
      endif
    set udg_Hero_XP[playerId+1] = Buffer.read()
    call PanCameraToTimed(GetRectCenterX(gg_rct_Starting_Point), GetRectCenterY(gg_rct_Starting_Point), 0)
    set mb = MultiboardGetItem(udg_Multiboard, playerId+1, 2)
    call MultiboardSetItemValue(mb, I2S(GetHeroLevel(loadedUnit)))
    set mb = MultiboardGetItem(udg_Multiboard, playerId+1, 1)
    call MultiboardSetItemStyle(mb, true, true)
    call MultiboardSetItemValue(mb, GetUnitName(loadedUnit))
      if GetUnitTypeId(loadedUnit) == 'E008' then
        call MultiboardSetItemIcon(mb, "ReplaceableTextures\\CommandButtons\\BTNArcher.blp")
      elseif GetUnitTypeId(loadedUnit) == 'H002' then
        call MultiboardSetItemIcon(mb, "ReplaceableTextures\\CommandButtons\\BTNFootman.blp")
      elseif GetUnitTypeId(loadedUnit) == 'H000' then
        call MultiboardSetItemIcon(mb, "ReplaceableTextures\\CommandButtons\\BTNPriest.blp")
      elseif GetUnitTypeId(loadedUnit) == 'E000' then
        call MultiboardSetItemIcon(mb, "ReplaceableTextures\\CommandButtons\\BTNNightElfRunner.blp")
      endif
    call SetPlayerState(triggerPlayer, PLAYER_STATE_RESOURCE_LUMBER, Buffer.read())
    call SetPlayerState(triggerPlayer, PLAYER_STATE_RESOURCE_GOLD, Buffer.read())
    call ShowUnit(udg_Player_Bag[playerId+1], false) 
    set mb = null
endfunction
private function OnUnload1 takes nothing returns nothing //Fail load
    call UnloadInventory(loadedUnit)
    call UnloadInventory(udg_Player_Bag[playerId+1])
    call RemoveUnit(loadedUnit)
    call RemoveUnit(udg_Player_Bag[playerId+1])
    set loadedUnit = null
endfunction
Arhowk commented 9 years ago

SetHeroLevel() on a level 1 to level 1 will make it level 2 because blizzard is lulzy. you hve to check if level != 1 or save exp instead

for abilities, just save them catalog style... you could push a # of abilities with a maximum as 16 (for non-spellbook) or 256 (for spellbook)

also if you're interested im looking for testers for my codeless save load system http://www.hiveworkshop.com/forums/lab-715/order-based-string-synchronization-260813/#post2631401 currently not totally tested but... you know... it needs testing...

DDLegionTN commented 9 years ago

thanks for your reply, but currently i don't want to waste my time again for another save/load system, so i will still continue using Nestharus's save/load system. From your answered, i learnt 1 thing again about the SetHeroLevel() from the lazy blizzard. For my 2nd question, after few times of testing, i realized that SelectHeroSkill() only will works only if hero has the ability is learn-able inside the OE, since my heroes don't have those, so its not working, guess i would need to take some time for working around.

Arhowk commented 9 years ago

The only reason I suggested it is because the system is fundamentally based on nestharus's system, except that instead of using -save as the event a dialog is used instead. The "Simple Save/Load" in my map should be familiar.

What do you mean? If you are adding learnable abilities via triggers to a unit than SetUnitAbilityLevel should work fine. On Friday, January 16, 2015, DDLegionTN notifications@github.com wrote:

thanks for your reply, but currently i don't want to waste my time again for another save/load system, so i will still continue using Nestharus's save/load system. From your answered, i learnt 1 thing again about the SetHeroLevel() from the lazy blizzard. For my 2nd question, after few times of testing, i realized that SelectHeroSkill() only will works only if hero has the ability is learn-able inside the OE, since my heroes don't have those, so its not working, guess i would need to take some time for working around.

— Reply to this email directly or view it on GitHub https://github.com/nestharus/JASS/issues/25#issuecomment-70251199.

nestharus commented 9 years ago

SaveHeroAbilities depends on a hero having the abilities in object editor. It uses a few optimization tricks based on the maximum number of ability points the hero can have at a given level and the max level an ability can be at a given level. This saves space. The same can be done with abilities that are managed completely by code, you just have to modify the algorithm.

Most code I write follows the default Warcraft 3 stuff. If you are doing a custom solution, the default code isn't going to work for you.

I have something for saving an inventory too, but if you use a custom inventory system, you can't use my function.

DDLegionTN commented 9 years ago

I'm not sure how to save the custom abilities that aren't added via OE. I've already tried few times, fail completely. Using AddUnitAbility() and SetUnitAbilityLevel() as well, its seem like AddUnitAbility sometimes could fails to function (fail to add ability to unit), i got a headache with is bug (or not sure if it my mistake?)

For inventory, i'm using default war3 inventory, so i have no problem with it.

nestharus commented 9 years ago

You need to keep a list of all abilities the unit knows. You also need to figure out the max ability level that each ability can be for the unit considering the unit's level. You also need to factor in how high an ability can be considering the level of the other abilities on the unit.

If the unit is level 3 and there is ability A, B, and C, then

A can be level 3 B can be level 3 C can be level 1

Overall, the unit has, by this example, 3 ability points.

The unit has learned A and C.

A is hit first. There are 3 ability points remaining and A's max level is 3. A is level 2. A is saved (the ability) as well as its level (2) with a max value of 3. The next ability that is hit is C. C is level 1 with a max level of 1 with 1 ability point remaining. C is saved as the ability, but the level is not saved because it can only ever be one. There are no ability points remaining, so B is skipped. You want to save this stuff in reverse order, and you want to be sure to load the hero and the hero level first.

On load, A is retrieved as well as its level. 2 ability points are used up to keep A. 1 ability point remains, this means that the next thing to be loaded will not have an ability level on it. C is loaded and is set to 1. There are no ability points left, so loading is done.

What happens if there are ability points left, but the hero doesn't use them all? 0 must be added to the end of the list. When 0 is retrieved, there are no abilities remaining.

Will B ever be hit? No, because the hero hasn't learned it, so it's not part of the list. What is B important for? The ability catalog. If a hero can only learn A, B, and C, then the catalog will have A, B, and C in it. What happens once you go over A? The catalog should only then have B and C in it. I haven't designed filters for this yet : |. I'm going to eventually make a filter that does this.

This is of course the most optimal way to save your data and it might merit a general function.

DDLegionTN commented 9 years ago

Uhh, i know how your Save Abilities works, just i want to know how could i save abilities that aren't in the list of hero spell. Although i may know how to make it, but i always facing weird bug while i finished it :/