• Listen to a special audio message from Bill Roper to the Hive Workshop community (Bill is a former Vice President of Blizzard Entertainment, Producer, Designer, Musician, Voice Actor) 🔗Click here to hear his message!
  • Read Evilhog's interview with Gregory Alper, the original composer of the music for WarCraft: Orcs & Humans 🔗Click here to read the full interview.

Simple Save/Load code to get started?

Status
Not open for further replies.
Level 2
Joined
Aug 22, 2010
Messages
5
Hey guys i was just wondering if any of you guys are willing to help me learn about save/load coding. i've got minimal logic of it, i've looked through tutorials but they seem abit complicated. Any advice?
 
Level 6
Joined
Jan 31, 2009
Messages
166
A few details necessarily to give a good answer to this.

First do any of the many existing save/load systems work for you? There are quite a few in both GUI and Jass in the spell section. Second why not? What specifically do you need it to do that the existing systems do not (they are quite good)? Finally are you planning on building it in GUI or Jass.
 
Level 28
Joined
Jan 26, 2007
Messages
4,789
And another question from me, do you understand what Nestharus wrote in his tutorial (http://www.hiveworkshop.com/forums/jass-ai-scripts-tutorials-280/saving-loading-192851/)?
The intro is quite important. Once he starts about BigInt and such, you can stop reading :p

It explains the basics of how a code is formed (well, the very basics, really).


A working save/load code would be to set all heroes and items in arrayed variables, like:
  • Set hero[1] = Lich
  • Set hero[2] = Dreadlord
  • Set item[1] = Claws of Attack +15
  • Set item[2] = Mask of Death
  • Set item[3] = Wirt's Leg
  • Set heroAmount = 2
  • Set itemAmount = 3
And then checking "is the hero of the triggering player hero[X]"? (With a loop), such as:

  • Actions
    • Set saveString = <Empty String>
    • For each (Integer A) from 1 to heroAmount, do (Actions)
      • Loop - Actions
        • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
          • If - Conditions
            • (Unit-type of playerHero[(Player number of (Triggering player))]) Equal to hero[(Integer A)]
          • Then - Actions
            • Set saveString = (saveString + (String((Integer A))))
          • Else - Actions
I mean, that works.
If you do the same for items (say "no item" is 0, the rest is the array), then my hero's save-code could look like:
2100320

To break it down:

2: Hero - Dreadlord
1: Item - Claws
0 - Item - no item (empty slot)
0 - Item - no item (empty slot)
3 - Item - Wirt's Leg
2 - Item - Mask
0 - Item - no item (empty slot)


This is the absolute basis, I don't think it can get any easier than this.
Extremely easy to crack and change to what you want, but it works! :D

Loading would be the other way around: the first number is 2, so create "hero[2]" for player.
Give items in the same order (you can use dummy items for the zero's so the items are assigned in the correct slot as well).


The hard part is when you start encrypting/decrypting and shortening the code.
Saving isn't hard, but remember: you need to load it as well.
If I add experience (hero - experience - items), then my code could be: 18001 (Lich (1), 800 XP, claws).
It could also be: 1100001 (Lich (1), 1000 XP, Claws).

Do you see the problem that arises? You HAVE to let your system know that the first code only uses 3 characters for the XP and the last uses 4 characters.
Otherwise it would either give 8001 XP for the first code and no item, or 100 XP for the second code and empty slot - claws as items.

You can do this by setting a maximum value, say 5400XP. That is 4 characters.
Now the first code becomes: 108001 (Lich (1), 0800 XP, Claws).

However, this stretches your code to the maximum (literally, as all codes will have the maximum possible length, as even the lowest values will be increased so they're longer).

2 options:
1) Deal with it Let players type the full code the entire time (the only advantage is that the code will always have the same ordening).
2) Do like Nestharus did and do some complicated stuff to make it dynamic (I don't recommend the QueueQueue for you yet though, it's a complex data structure, really useful for this).


And this is where my story ends... and I didn't even get to actually encrypting the code yet (with the magics of math).
 
Well, using a BigInt is really recommended so that you at least get a minimal code size when you aren't dealing with values that may or may not exist, like item charges.


However, BigInt requires that you understand the math behind mashing numbers together ;D.

This is an example of some save/load just using BigInt. The numbers I'm multiplying by are the max values + 1. Numbers I'm dividing by are max values + 1. You always put the biggest number first.
JASS:
struct tester extends array
    private static method save takes nothing returns string
        local Base encryptKey = Base["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
        local BigInt int = BigInt.create(encryptKey)
        local string s
        
        //storing values of
        //501 out of a max of 1000000 (gold) (d1)
        //1938 out of a max of 1000000 (d2)
        //5821 out of a max of 28392 (super powers) (d3)
        //1 out of a max of 1 (bool) (d4)
        //0 out of a max of 1 (bool) (d5)
        //11 out of a max of 11 (player id?) (d6)
        //19 out of a max of 1000 (unit level) (d7)
        //12 out of a max of 16 (flags) (d8)

        call int.add(501,0) //encode 501 (max doesn't matter, put biggest value here)

        call int.multiply(1000000+1)
        call int.add(1938,0) //encode 1938

        call int.multiply(28392+1)
        call int.add(5821,0) //encode 5821

        call int.multiply(1+1)
        call int.add(1,0) //encode 1

        call int.multiply(1+1)
        call int.add(0,0) //encode 0

        call int.multiply(11+1)
        call int.add(11,0) //encode 11

        call int.multiply(1000+1)
        call int.add(19,0) //encode 19

        call int.multiply(16+1)
        call int.add(12,0) //encode 12
        
        set s = int.toString()
        call int.destroy()

        //display the code ^_^
        return s
    endmethod
    
    private static method load takes string s returns nothing
        local Base encryptKey = Base["0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"]
        local string loadCode = s
        local BigInt int = BigInt.convertString(loadCode, encryptKey)
        
        local integer d8 = int.divide(16+1) //12
        local integer d7 = int.divide(1000+1) //19
        local integer d6 = int.divide(11+1) //11
        local integer d5 = int.divide(1+1) //0
        local integer d4 = int.divide(1+1) //1
        local integer d3 = int.divide(28392+1) //5821
        local integer d2 = int.divide(1000000+1) //1938
        local integer d1 = int.toInt() //501
        
        call int.destroy()
        
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "d1: " + I2S(d1) + "==" + "501")
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "d2: " + I2S(d2) + "==" + "1938")
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "d3: " + I2S(d3) + "==" + "5821")
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "d4: " + I2S(d4) + "==" + "1")
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "d5: " + I2S(d5) + "==" + "0")
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "d6: " + I2S(d6) + "==" + "11")
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "d7: " + I2S(d7) + "==" + "19")
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "d8: " + I2S(d8) + "==" + "12")
    endmethod
    
    private static method onInit takes nothing returns nothing
        local string s = save()
        call DisplayTimedTextToPlayer(GetLocalPlayer(), 0, 0, 60, "2G9Z2EVGV87IY\n" + s)
        call load(s)
    endmethod
endstruct



Also, there is a save/load system that is extremely simple and uses all of the latest security techniques and almost all of the latest compression techniques, however it requires a vjass friend that knows save/load math to set up and does not support backwards compatible codes or values that may or may not exist =).

http://www.hiveworkshop.com/forums/...-simple-low-level-save-load-framework-197557/


I don't recommend Encoder as the code structures in that can get extremely complicated.. people have spent 24-48 hours creating encoder objects/catalogs for that >.<. I remember one dude asked me for an example of a ridiculously complex catalog ^)^.
 
Status
Not open for further replies.
Top