gold, hero type, hero stats maybe, item slots 1-6, and 9 item rawcodes
Gold
http://www.hiveworkshop.com/forums/2040489-post663.html
call stack.push(CompressInt(GetPlayerState(triggerPlayer, PLAYER_STATE_RESOURCE_GOLD)), CompressInt(1000000))
Why do you compress the value? To make the code smaller ofc.
Hero Stats
xp
http://www.hiveworkshop.com/forums/1994345-post546.html
where accuracy is how many decimal places up to 2.
function SaveHeroXP takes NumberStack stack, unit whichUnit, integer accuracy returns nothing
call SaveHeroXP(stack, heroUnit, 2)
life/mana
http://www.hiveworkshop.com/forums/2001776-post562.html
save stats (str, agi, int)
JASS:
library SaveHeroStats /*
*************************************************************************************
*
* Saves hero strength, agility, and intelligence
*
*************************************************************************************
*
* */uses/*
*
* */ NumberStack /* hiveworkshop.com/forums/1993458-post521.html
*
************************************************************************************
*
*
* SETTINGS
*/
globals
/*************************************************************************************
*
* ALL_STATS_SPENT
*
* Every stat point is spent at every level
*
* If every stat point is spent at every level, the strength can be calculated from
* the remaining stat points. If the stat points are not spent, the strength has
* to be stored in the code.
*
* Stat points spent at every level means a smaller code.
*
*************************************************************************************/
private constant boolean ALL_STATS_SPENT = true
/*************************************************************************************
*
* SPLIT_BONUSES
*
* Makes bonus specific to each stat rather than shared among all stats.
*
* If SPLIT_BONUSES is true and 1024 is passed in as a max bonus, 1024 will be the cap
* for each individual stat.
*
* If SPLIT_BONUSES is false and 1024 is passed in as a max bonus, 1024 will be the cap
* for all three stats put together. If intelligence is 500, then 524 bonus stats
* will be left.
*
*************************************************************************************/
private constant boolean SPLIT_BONUSES = false
endglobals
/*
************************************************************************************
* function SaveHeroStats takes NumberStack stack, unit whichUnit, integer maxBonusForLevel returns nothing
* function LoadHeroStats takes NumberStack stack, unit whichUnit, integer maxBonusForLevel returns nothing
*
************************************************************************************/
function SaveHeroStats takes NumberStack stack, unit whichUnit, integer maxBonusForLevel returns nothing
local unit u
static if SPLIT_BONUSES then
local integer bonusStr
elseif not ALL_STATS_SPENT then
local integer bonusStr
endif
local integer bonusAgi
local integer bonusInt
static if LIBRARY_UnitIndexer then
set UnitIndexer.enabled = false
endif
set u = CreateUnit(Player(15), GetUnitTypeId(whichUnit), GetRectMaxX(bj_mapInitialPlayableArea), GetRectMaxY(bj_mapInitialPlayableArea), 0)
call SetHeroLevel(u, GetHeroLevel(whichUnit), false)
static if SPLIT_BONUSES then
set bonusStr = GetHeroStr(whichUnit, false)-GetHeroStr(u, false)
elseif not ALL_STATS_SPENT then
set bonusStr = GetHeroStr(whichUnit, false)-GetHeroStr(u, false)
endif
set bonusAgi = GetHeroAgi(whichUnit, false)-GetHeroAgi(u, false)
set bonusInt = GetHeroInt(whichUnit, false)-GetHeroInt(u, false)
static if SPLIT_BONUSES then
call stack.push(bonusStr, maxBonusForLevel)
call stack.push(bonusAgi, maxBonusForLevel)
call stack.push(bonusInt, maxBonusForLevel)
else
static if not ALL_STATS_SPENT then
call stack.push(bonusStr, maxBonusForLevel-bonusAgi-bonusInt)
endif
//else
//bonus strength is the remaining bonus points
call stack.push(bonusAgi, maxBonusForLevel-bonusInt)
call stack.push(bonusInt, maxBonusForLevel)
endif
call RemoveUnit(u)
set u = null
static if LIBRARY_UnitIndexer then
set UnitIndexer.enabled = true
endif
endfunction
function LoadHeroStats takes NumberStack stack, unit whichUnit, integer maxBonusForLevel returns nothing
local unit u
local integer bonusStr
local integer bonusAgi
local integer bonusInt
static if LIBRARY_UnitIndexer then
set UnitIndexer.enabled = false
endif
set u = CreateUnit(Player(15), GetUnitTypeId(whichUnit), GetRectMaxX(bj_mapInitialPlayableArea), GetRectMaxY(bj_mapInitialPlayableArea), 0)
call SetHeroLevel(u, GetHeroLevel(whichUnit), false)
static if SPLIT_BONUSES then
set bonusInt = stack.pop(maxBonusForLevel)
set bonusAgi = stack.pop(maxBonusForLevel)
set bonusStr = stack.pop(maxBonusForLevel)
else
set bonusInt = stack.pop(maxBonusForLevel)
set bonusAgi = stack.pop(maxBonusForLevel-bonusInt)
static if ALL_STATS_SPENT then
set bonusStr = maxBonusForLevel-bonusAgi-bonusInt
else
set bonusStr = stack.pop(maxBonusForLevel-bonusAgi-bonusInt)
endif
endif
call SetHeroInt(whichUnit, bonusInt+GetHeroInt(u, false), true)
call SetHeroAgi(whichUnit, bonusAgi+GetHeroAgi(u, false), true)
call SetHeroStr(whichUnit, bonusStr+GetHeroStr(u, false), true)
call RemoveUnit(u)
set u = null
static if LIBRARY_UnitIndexer then
set UnitIndexer.enabled = true
endif
endfunction
endlibrary
function SaveHeroStats takes NumberStack stack, unit whichUnit, integer maxBonusForLevel returns nothing
call SaveHeroStats(stack, myHero, maxBonusForLevel
where max bonus is like how much +str they can have from upgrades or w/e =). For example, a map that allows a player to add +1 to any stat at every level saving a level 10 hero would have a max +str of 10. SPLIT_BONUSES split them, like if you put in 10, you can have +10 str, +10 agi, +10 int instead of a combination of all 3 adding to 10.
Item Slots 1-6 of the custom inventory?
loop through the inventory ->
Equipment.Item[i].id
Collect all non null items, then save them. If the inventory wasn't completely saved, save a 0 as a null item first. For item charges, only save the item charge if the item has an item charge. This means an if statement. If item max charge > 1, save item charge. If not, don't save item charge ;p. Pretty simple no?
Random 9 items? You still should never save rawcodes, use a catalog.
http://www.hiveworkshop.com/forums/jass-resources-412/snippet-catalog-192452/
For example
JASS:
struct ItemCatalog extends array
implement Catalog
private static method onInit takes nothing returns nothing
call add(itemRawCode1)
call add(itemRawCode2)
call add(itemRawCode3)
call add(itemRawCode4)
endmethod
endstruct
From there, you can convert raw codes into catalog ids and back. It's for converting a massive number into a small one ;p
Also keep in mind that you should only save items that aren't null : O. Partial sets of data just plain rock.
For version control, the standard method is to now add the version to the checksum and use the version as a CRC.
JASS:
library KnuthChecksum uses BigInt
function GetKnuthChecksum takes BigInt k, integer m returns integer
local BigInt c = k.copy()
local BigInt c2 = k.copy()
call c.add(3,0)
call c2.multiplyBig(c)
call c.destroy()
set c = c2.mod(m)
call c2.destroy()
return c
endfunction
endlibrary
call stack.push(GetKnuthChecksum(stack, checksumMax+1)+versionNumber, checksumMax+maxVersionNumber)
And at the very start, before you do anything else
call BigInt(stack).add(versionNumber, 0)
You can then also encrypt the number using Scrambler.
Now this may seem like mumbo jumbo and super complicated stuff to you, but that is only because there is so much stuff being used here >.<. If you know the bajillion snippets, using and modifying them is actually really easy ;o.
Sadly, xp can only be safely saved with HeroReward. However, if you do have smaller levels that don't have a chance of overflowing, then you can save xp another way ^)^.
Here's how you save xp
Create a dummy hero. Set that hero level to the same level as the hero you are saving (only if that hero being saved is >1). From there, saving hero xp - dummy hero xp. Next, add 1 level to the dummy hero. From there, dummy hero xp new - dummy hero xp old. Now, compress the first value you retrieved (hero xp) and the second value you retrieved (max possible xp for that level). Now save that + the level ^)^.
Another method is to save the xp as a % into the level by doing hero xp / dummy hero xp of hero level + 1 * 100. This will then cap the value to a max of 99, a bit less accurate but still works.
Finally, you can also just save the xp as a compressed value, something I wouldn't recommend. Just compress the hero xp and store it in a max of all of the possible xp. Saving the xp in a compressed form with the level will give you a smaller value than just the plain xp. Saving the xp as a percent may or may not give you a smaller value, it depends ; ).
The good thing about HeroReward is that there is only percent hero xp. All levels are out of 10,000, which is essentially 100.00, which is a percent with 2 decimal places. That makes saving hero xp using HeroReward super easy. You can easily change your map settings to use % xp by looking at the custom values used in Hero Reward and changing your xp settings to those. However, you will need to change your xp algorithm to work with %s rather than raw values. Working with %s also makes it safe to go up to a level like 10,000 without overflowing.
My final recommendation is to, at a bare minimum, use BigInt. BigInt is not a save/load system but rather a system to handle really big numbers. Save/Load codes, if done correctly, are
really big numbers. If you know how to do the math, you can just use BigInt and forgo all of the save/load system nonsense ;D.
The stuff isn't complicated, there are just many ways to save things and different things need to be saved in different ways. For example, gold is saved differently from an inventory ;p. The naive approach is to save everything the same way, which is what older systems do. If you know a value is part of a set of a value has a relation with another value, you can take advantage of that. For example, will a level 1 hero ever have 1,000,000 gold? Probably not. Will a max level hero have that? Possibly. Take advantage of all of these things to minimize your save/load code ;p.
And you should always use Scrambler for protection. It adds absolutely nothing to the code and produces almost randomized output. Just adding 1 to a single value will change the entire code ;o. It also makes codes player unique. You can use Scrambler to scramble up the encryption keys too ; ).