Save/Load Code, Yet Another

AceHart

Your Friendly Neighborhood Admin
Reaction score
1,505
Yes, there's already plenty of them around.

But, well, they didn't really work as I needed it.
And, they didn't really work as I needed it.
Not to mention that they didn't really work as I needed it.


So, here's my own.

Any and all comments and feedback welcome.
(Other than "Can you please stop making maps? Thank you.")


My actual question was: What do I want this to be able to do?
And I wanted something that can be used to save just about anything, be it Heroes, items, health, number of kills, your grand-ma's shoe-size (rounded down), ...

And, hey, I wrote it myself! Which also counts for something.
For example, it clearly says that I have too much free time currently.


Let's say you want to save a Hero and the player's Gold:
Set Save[1] = Player 1's current Gold
Set Save[2] = Hero[ Player number of Player 1 ]
Set SaveCount = 2
...

Simple?
Yes.

Now, we want to add the Hero's level:
Set Save[1] = Player 1's current Gold
Set Save[2] = Hero[ Player number of Player 1 ]
Set Save[3] = Level of (Hero[ Player number of Player 1 ])
Set SaveCount = 3
...

Yes, that's it already.

Adding lumber too?
Set Save[1] = Player 1's current Gold
Set Save[2] = Player 1's current Lumber
Set Save[3] = Hero[ Player number of Player 1 ]
Set Save[4] = Level of (Hero[ Player number of Player 1 ])
Set SaveCount = 4
...

Need to add something else?
Well, then do it.



Have fun,
Try it all,
Run your own system,
Find bugs (Bugs? What bugs?).


Yours,
AceHart



Yet Another Save / Load Code :p


This is much less a tutorial than a "How do I use it?" guide.


I'm not going to bore you with 500+ lines of GUI code triggers.

Why not?
You won't get it anyway...
More seriously though, simply because no one's going to read it all.

And, actually, only the "save" and "load" parts are in GUI, for easier reading.
The actual coding / decoding is in JASS.


What's it doing?

You want a save / load code in your map?
Well, take this map, copy the needed parts over to yours, done.

All in all, it takes a bunch of numbers, converts them into a code.
When you type that code back in, the numbers will be reconstructed.
That's it.

I'm kidding, right?
Well, no.

That is really all this map is doing.
It takes a bunch of numbers, turns them into a code that can be typed back to reconstruct those numbers.


Inner workings:

1: take all numbers and make a huge string from that
2: pretend that's a number in base 11
3: convert to base 36

Unless you really insist, that's all the details I'm going to post here.

Feel free to ask whatever you don't get.


Importing to your map:

I've provided three different "a player types '-save' / '-load <code>'" versions.
Have a look, take the one you like, and copy & paste the category you like into your map.

Open the custom script section (at the top of the trigger list is your map's name, click there):
Copy & paste anything in there to your map.

Done.


The real deal:

Trigger:
  • SaveLoad Save
    • Events
      • Player - Player 1 (Red) types a chat message containing -save as An exact match
      • Player - Player 2 (Blue) types a chat message containing -save as An exact match
      • Player - Player 3 (Teal) types a chat message containing -save as An exact match
      • Player - Player 4 (Purple) types a chat message containing -save as An exact match
    • Conditions
    • Actions
      • -------- Those values need saving --------
      • Set Save[1] = 123
      • Set Save[2] = 456
      • Set Save[3] = 7890
      • -------- The number of values we have --------
      • Set SaveCount = 3
      • -------- Turn values into code --------
      • Custom script: set udg_Code = SaveLoad_Encode()
      • -------- Show code to player --------
      • Quest - Display to (Player group((Triggering player))) the Secret message: Your code:
      • Game - Display to (Player group((Triggering player))) for 60.00 seconds the text: Code


> Player - Player 1 (Red) types a chat message containing -save as An exact match

The most basic use.
A player types "-save".

> Set Save[1] = 123
> Set Save[2] = 456
> Set Save[3] = 7890

Some numbers (123, 456 and 7890) are put into the "Save" array.

> Set SaveCount = 3

We set "SaveCount" to how many numbers we have, 3 with this example.

> Custom script: set udg_Code = SaveLoad_Encode()

This calls the code generator.
It will take the three (as set in "SaveCount") values in the "Save" array.
And return the save code in some global variable called "Code".

> Quest - Display to (Player group((Triggering player))) the Secret message: Your code:
> Game - Display to (Player group((Triggering player))) for 60.00 seconds the text: Code

Show the code to the player.


Looks simple?
I hope so.

Now, those three numbers probably don't make much sense, but, that's also not the point.
The point was more to have something to look at, to see how it works.

You may wonder how to get a Hero into that "Save" array.
Valid question.

Unfortunately, you can't just write:
Set Save[1] = Unit-type of ("Paladin").

Which is why I provided a custom JASS function to do so.

In the example trigger "SaveLoad Save Hero", there's this line:
> Set TempUnit = (Picked unit) ("Picked unit"? Well, it's inside a "Pick every unit" loop, that's why.)
> Custom script: set udg_Save[udg_SaveCount] = SaveLoad_Unit2Integer( udg_TempUnit )

As you may see, in GUI, if this were possible, this would say:
Set Save[SaveCount] = Unit-type of (TempUnit)

You have your Heroes in some unit array called "Heroes"? Indexed by player number?
No problem, use
> Set TempUnit = Heroes[ Player number of (Triggering player) ]
> Custom script: set udg_Save[udg_SaveCount] = SaveLoad_Unit2Integer( udg_TempUnit )

Again, in GUI, if this were possible, would read:
Set Save[SaveCount] = Unit-type of (Heroes[Player number of (Triggering player)])

Should be simple enough, even for people that never used any JASS before.


There's also the equivalent for items:
> Set TempItem = (Item carried by (Picked unit) in slot (Integer A))
> Custom script: set udg_Save[udg_SaveCount] = SaveLoad_Item2Integer( udg_TempItem )


Now, since it uses JASS to turn unit or item types into numbers, there's also something to do it the other way around?
Yes, there is:
> Custom script: set udg_TempUnitType = SaveLoad_Integer2Unit(udg_Save[udg_SaveCount])
> Unit - Create 1 TempUnitType for (Triggering player) at ((Triggering player) start location) facing Default building facing degrees
and
> Custom script: set udg_TempItemType = SaveLoad_Integer2Item(udg_Save[udg_SaveCount])
> Hero - Create TempItemType and give it to (Last created unit)

Those are used when loading a code.


As a complete example on how to load a Hero:
Trigger:
  • SaveLoad Load Hero
    • Events
      • Player - Player 1 (Red) types a chat message containing -load as A substring
      • Player - Player 2 (Blue) types a chat message containing -load as A substring
      • Player - Player 3 (Teal) types a chat message containing -load as A substring
      • Player - Player 4 (Purple) types a chat message containing -load as A substring
    • Conditions
      • (Substring((Entered chat string), 1, 6)) Equal to (Matched chat string)
      • (Length of (Entered chat string)) Greater than 6
    • Actions
      • -------- Try to decode what was typed --------
      • Set Code = (Substring((Entered chat string), 7, (Length of (Entered chat string))))
      • Custom script: set udg_Validate = SaveLoad_Decode( udg_Code )
      • If (All Conditions are True) then do (Then Actions) else do (Else Actions)
        • If - Conditions
          • Validate Equal to False
        • Then - Actions
          • -------- Invalid code --------
          • Game - Display to (Player group((Triggering player))) the text: There&#039;s some error in this code, sorry.
          • Skip remaining actions
        • Else - Actions
      • -------- It worked, let&#039;s do something with it --------
      • Set SaveCount = 1
      • Custom script: set udg_TempUnitType = SaveLoad_Integer2Unit(udg_Save[udg_SaveCount])
      • Unit - Create 1 TempUnitType for (Triggering player) at ((Triggering player) start location) facing Default building facing degrees
      • Set SaveCount = (SaveCount + 1)
      • Hero - Set (Last created unit) Hero-level to Save[SaveCount], Hide level-up graphics
      • Set SaveCount = (SaveCount + 1)
      • For each (Integer A) from 1 to Save[SaveCount], do (Actions)
        • Loop - Actions
          • Set SaveCount = (SaveCount + 1)
          • Custom script: set udg_TempItemType = SaveLoad_Integer2Item(udg_Save[udg_SaveCount])
          • Hero - Create TempItemType and give it to (Last created unit)
          • Set SaveCount = (SaveCount + 1)
          • Item - Set charges remaining in (Last created item) to Save[SaveCount]


In more details:

> Player - Player 1 (Red) types a chat message containing -load as A substring
> Player - Player 2 (Blue) types a chat message containing -load as A substring
> Player - Player 3 (Teal) types a chat message containing -load as A substring
> Player - Player 4 (Purple) types a chat message containing -load as A substring

We wait for some player to type "-load <code>".

> (Substring((Entered chat string), 1, 6)) Equal to (Matched chat string)
> (Length of (Entered chat string)) Greater than 6

If the message he typed didn't start with "-load " or if it did but there was no code, this trigger won't run.

> Set Code = (Substring((Entered chat string), 7, (Length of (Entered chat string))))

Take the part that comes after "-load ", i.e. the actual code.

> Custom script: set udg_Validate = SaveLoad_Decode( udg_Code )

Call the decoding function.
This function will refill the "Save" array with all numbers that were saved with in that code.
It will set "SaveCount" to how many numbers it did find.
And, finally, it will return either "true" or "false", a result we catch in some variable called "Validate" (of type "Boolean").

> If (All Conditions are True) then do (Then Actions) else do (Else Actions)
> - Validate Equal to False

If "Validate" is false, as opposed to true, there's some problem with the code.
Missing characters, swapped characters, wrong player... some problem.

> Game - Display to (Player group((Triggering player))) the text: There's some error in this code, sorry.
> Skip remaining actions

So, yes, didn't work. Tell the player and skip the rest of the trigger.

> Set SaveCount = 1
> Custom script: set udg_TempUnitType = SaveLoad_Integer2Unit(udg_Save[udg_SaveCount])

The first thing we put into the "Save" array was the Hero.
We also take the Hero out of it first.

> Unit - Create 1 TempUnitType for (Triggering player) at ((Triggering player) start location) facing Default building facing degrees

Create the Hero.

> Set SaveCount = (SaveCount + 1)
> Hero - Set (Last created unit) Hero-level to Save[SaveCount], Hide level-up graphics

Set his level to whatever level he had when saved.

> Set SaveCount = (SaveCount + 1)
> For each (Integer A) from 1 to Save[SaveCount], do (Actions)

The code had a counter for how many items the Hero carried, this line will recreate an equal amount.

> - Set SaveCount = (SaveCount + 1)
> - Custom script: set udg_TempItemType = SaveLoad_Integer2Item(udg_Save[udg_SaveCount])

Read the next value, and convert it to an item-type.

> - Hero - Create TempItemType and give it to (Last created unit)

Create the item for the Hero.

> - Set SaveCount = (SaveCount + 1)
> - Item - Set charges remaining in (Last created item) to Save[SaveCount]

Set the charges to those saved.


There's also a save / load version called "SaveLoad ALL".
Which saves several Heroes, complete with items and charges, experience, position and the player's Gold.

Feel free to change to whatever you need in your map.


More on Heroes and items and general initialization:

Have a look at "SaveLoad_Initialization".
See those Hero and item arrays?
Well, if you're going to use this to save Heroes and items, or just one of those,
I strongly recommend putting them all in those arrays.

The code will still work for Heroes or items that aren't in the array, it will even (try to) compress it a bit,
but, still, if the Hero, or the item, isn't found in the array, the code will be longer.
With six items on your Hero, it's several characters difference already.


Other stuff of interest are the following three lines:
> Set SaveLoad_Alphabet = ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789

The code you get will consist of upper case letters and digits.
You can change this if you want.
You could, for example, only use "ABC123", and the code would only use those.

However, the less characters, the longer the code.

So, I can just add abc...z too to have more characters and I will get a shorter code?
Yes, but, that's where the next line comes into play:
> Set SaveLoad_CaseSensitive = False

If your code uses both upper and lower case characters, this must be set to true.

By default, if you get "ABCD-1234" as code, and type "abcd-1234", it will work.
But, if the code is case sensitive, you must type it back exactly as you got it.

I wouldn't recommend changing this, but, well, your map, your choice.

> Set SaveLoad_UsePlayername = True

The code includes a simple check for the player that got it, and compares it, later on, when you type it back.
If you set this to false, the code won't care for the player.


Questions that are usually asked for Save / Load Codes:

Q: I used this to save three Heroes, complete with items, charges, position, experience, strength, agility, intelligence, my Gold and Lumber and my current top "kills" and "deaths" scores...
A: Impressive. Though, while this works just fine, the code length will be out of league...

Q: I forgot to put my Hero into the "SaveLoad_Heroes" array, but the code still worked.
A: Yes.

Q: I didn't add my Hero to the Hero array, got a working code, but it was very long.
A1: Put Heroes and items into the provided "hero" and "item" arrays, as seen in "SaveLoad_Initialization".
A2: That's the very reason to have those arrays.

Q: If I put a second Hero on your demo map, and enable the triggers in the "all" category, it will give me a code for both Heroes at once?
A: Yes.

Q: Why is the "initialization" trigger repeated three times?
A: Because, usually, you just copy & paste the category you need, not all of them. Keeps it simpler to import to your map.

Q: How many "digits" does it use to save a Hero (just the Hero, no level, attributes, items, ...)?
A: Best case: less than one.

Q: How many "digits" does it use worst case to save a Hero?
A: More than one.

Q: Can it save Strength / Agility / Intelligence?
A: Yes.

Q: Can it save both Gold and Lumber?
A: Yes.

Q: How much Gold can I save?
A: All you can carry.

Q: Can it save Lumber only?
A: Yes.

Q: LEAKS!
A: STFU.

Q: This must use heavy encryption, right?
A: Security through obscurity never works.

Q: What digit, in the final code, holds the Hero's level if I put it in Save[3]?
A: No idea.

Q: My Heroes can go up to level 666, will this still work?
A: Yes.

Q: So, if I want to save some other thing, like the number of units owned by Neutral Hostile killed so far with that Hero, I can simply add another number to the save array, and it will turn that too into a code?
A: Yes.

Q: I'm l33t!
A: Cool...

Q: Why is that thing in JASS?
A: Doing heavy math in GUI is a pain.

Q: Why isn't everything in JASS then?
A: ...



Anything I forgot here?
Something not very clear yet?

Let's hear it.


See the link below for the demo map:
 

Attachments

  • SaveLoad_Demo_AceHart.w3x
    38.3 KB · Views: 4,278
You can optimize some lines like :

Code:
(256 * 256 * 256) = 16777216
(256 * 256) = 65536
(64 * 64 * 64) = 262144
(64 * 64) = 4096
CONST = 1000000

Quite nice. :p
 
Well, there's nothing to win there. A micro-second execution time or so.
But, you lose on readability.
Readability is very imported in 400 lines of math-intense JASS :p
 
Umm....took about 4 minutes to read the whole thing :D

anyways seeing your beautiful work in the past must mean this should stand out more than normal Save/Load Codes...and in fact...I think you should submit this to the resource part(if you already didn't)

this code provides more flexible settings correct me if I am wrong?

BTW Acehart can you give me an estimate of how long this took you to write out?
 
Well, the usual save / loads I met so far all use pretty much the same way of doing things,
they start with an empty string,
then "encrypt" the hero and add it,
then "encrypt" his level and add it,
then...
and so on.

However, that's waste of characters.
As in, the code will be rather fixed.
Hero level takes 3 characters for example, and is in positions 3-5 of the final code.

That's clearly something I wasn't looking for.
The code is made from all information that goes in it in one go.
Makes for slightly shorter codes.

And, yes, you can store pretty much anything... anything that may fit in a number that is.


Estimated coding time: 4 - 6 hours, depending on what part you consider "coding" and what would be more "testing".


> Resource part...

Some comments or suggestions or other stuff... and we'll see.
 
Questions that are usually asked for Save / Load Codes:


Q: LEAKS!
A: STFU.

Q: I'm l33t!
A: Cool...
Didn' t get the second one, I never get it how l33t and cool are connected. When AceHart does something it has to be good otherwise he isn' t doing it. Nice idea outputing each variable arry as independent code. It allows to save everything/ anything. I would use it defenetly in my map if I only find use for it (But who cares what I got or don' t :p .) You sure spent much time making it and thanks for doing it.
 
Didn' t get the second one, I never get it how l33t and cool are connected. When AceHart does something it has to be good otherwise he isn' t doing it. Nice idea outputing each variable arry as independent code. It allows to save everything/ anything. I would use it defenetly in my map if I only find use for it (But who cares what I got or don' t :p .) You sure spent much time making it and thanks for doing it.

Yep it saves whatever. I tryed 2147483647, some Conversion, an ASCII compression, saving reals; booleans; strings... just remember to copy variables and the map header.
 
> remember to copy variables

The "SaveLoad_Initialization" trigger is doing that, it has all variables used by the code.

Remember to check "auto-create variables" in menu: File / Preferences (general tab).


> I tried ... strings ...

Strings?
 
> I tried ... strings ...

Strings?[/QUOTE]

Strings after converting them in Base10.
 
> how can you make it equal to a unit?

Reading post #1? :p


> Set TempUnit = <some unit>
> Custom script: set udg_Save[udg_SaveCount] = SaveLoad_Unit2Integer( udg_TempUnit )

Which does
Set Save[SaveCount] = Unit-type of (TempUnit)
Well, not exactly, but, let's accept it as such.

And, the other way around:
> Custom script: set udg_TempUnitType = SaveLoad_Integer2Unit(udg_Save[udg_SaveCount])
> Unit - Create 1 TempUnitType for (Triggering player) at ((Triggering player) start location) facing Default building facing degrees
 
> how can you make it equal to a unit?

Reading post #1? :p


> Set TempUnit = <some unit>
> Custom script: set udg_Save[udg_SaveCount] = SaveLoad_Unit2Integer( udg_TempUnit )

Which does
Set Save[SaveCount] = Unit-type of (TempUnit)
Well, not exactly, but, let's accept it as such.

And, the other way around:
> Custom script: set udg_TempUnitType = SaveLoad_Integer2Unit(udg_Save[udg_SaveCount])
> Unit - Create 1 TempUnitType for (Triggering player) at ((Triggering player) start location) facing Default building facing degrees
in short u convert unit to integer (if its even possible....)
 
> as I needed it.
Does this mean we should expect a new map from you? :)
 
wth

U2I?

Unit to integer conversion? wth... lol...

Cool, looks good anyway

I wish I knew how to write a saveload code, O_O

- I just thought of something, even if you can't do U2I...

You can set the Point value, of each unit with a unique code...

and then load the hero based off the point value of the unit :)

O_O
 
> Unit to integer conversion?

Unit, ability, item and other IDs are already integers.
You've probably seen them already, they look like A001 or hfoo or nskk or U123...
 
OMG!

Cool...

AceHart's smart:)

> Unit to integer conversion?

Unit, ability, item and other IDs are already integers.
You've probably seen them already, they look like A001 or hfoo or nskk or U123...

U2I?

Unit to integer conversion? wth... lol...

Cool, looks good anyway

I wish I knew how to write a saveload code, O_O

- I just thought of something, even if you can't do U2I...

You can set the Point value, of each unit with a unique code...

and then load the hero based off the point value of the unit :)

O_O

Let me guess, simply a loop that uses an array variable with presets until it finds its equivalent, isn't it? :p
 
yea so i got like 1/5th way through it, said omg, and quit

but it is really impressive, gj
 
> got like 1/5th way through it, said omg, and quit

Hm... expert in molecular biology but can't do some basic rocket science? Strange... :p

But, well, like Chocobo said, in the end, it all comes down to some loops and a couple IFs...
 
So with this code, you can make a campaign, that literally does alter the settings of one map based on what you accomplished in the previous maps?

Like lets say you are playing an over harvesting orc, and you and the computer harvest the ENTIRE of Map A. then you can use the settings from this map, to alter triggers that will change th elandscape of Map B (such as initializing a trigger that causes flash floods since you took out all of the undergrowth in Map A).
 
General chit-chat
Help Users
  • No one is chatting at the moment.
  • The Helper The Helper:
    and about the AI psych I notice chatGPT always being affirming towards me and giving me advice and stuff, I rarely take it but it does do it I guess as part of the algorithm
  • Varine Varine:
    I opened today. Last year we had a very big difference in our shifts that I would call unfair, because my average shift was 10 hours because I ran dinner shift every day, Ben ran lunch shift and his average was less than 7. We both do doubles on our days off
  • Varine Varine:
    Like not obviously we work doubles on our days off, but I have doubles on his, he has doubles on mine
  • Varine Varine:
    I am technically at work though, I have to update all our online shit. We just changed menus and no one else knows how to do the online ordering and shit
  • Varine Varine:
    I think they just forgot their passwords
    +1
  • Varine Varine:
    But we're trading the day shifts out in an attempt at fairness. Also our main staff had to do the same thing, so we had a big issue with day and night shifts being upset with each other, and that is really fucking difficult to resolve because they are all both wrong and right. Like yes, this should have been done but I'm not going to bring it up, for the same reason I'm not bringing up this shit not getting done by you, things are going to get missed sometimes and that is just a reality we have to do
  • Varine Varine:
    So hopefully with everyone having a little bit of each they are more understanding with each other and a bit more empathy and realization of my thing of we cannot leave things with the expectation that other people will do them. It if they both do it and then it also falls on them then I hope that kind of fixes that problem
  • Varine Varine:
    And it also gets all of us a couple afternoons off too, it's really envy inducing when you never get to go do stuff after work, and then day side always talking about how much they got done after work and being dicks that we aren't doing all our stuff before work
  • Varine Varine:
    Like, it's a bit different when you have to wake up at 7 to have the same amount of daylight before work and then GO TO WORK all night than it is waking up at 7 to go to work and having the rest of the evening free
  • Varine Varine:
    I can't go hiking before work and hope I don't burn myself out on my way back or get caught up doing something than it is to leave at 3 and go
  • Varine Varine:
    Anyway I'm losing my fucking mind with how much I've been staring at this menu so I'm going to go have a drink and see if I can come back to it and not lose myself on it
  • Varine Varine:
    You know how when you saw a word like a hundred times over it loses any meaning? That's where I'm at on this now.
  • Varine Varine:
    I had to allergen guides earlier this week and that is SO MUCH just looking through ingredients and trying to figure out if a company is correct
  • Varine Varine:
    Like did you know you can have gluten free products that still technically contain wheat?
  • Varine Varine:
    I did know that but forgot and spent several hours learning why until I remembered I knew that
  • Varine Varine:
    Xanthum gum can be made from wheat, but is processed in a way that no gluten is present, but it still presents a risk for severe wheat allergies that are NOT gluten
  • Varine Varine:
    Do you think the people that answer the phone for that company have any idea about that? Because they do not, nor can they tell me where they get that xanthum gum usually so I can't ask the people that make it, nor do they particularly care if I'm the one risking people's lives and not them.
  • Varine Varine:
    So that was my week building up to today, because that is when I got the menu and had to guess at the actual recipes for two of those days, because again I think he threw this into AI and ran with a lot of it
  • Varine Varine:
    I should have had all of this like a month ago but whatever, it's fine. He's trying a thing, idk it's his menu I don
  • Varine Varine:
    I don't care.
  • Varine Varine:
    Fuck I need more saturday nights off. Turns out I'm much cooler to drunk girls. If I hang out with enough people like that, eventually I'll meet one that likes me sober too
  • Varine Varine:
    idk if anyone has ever done IT. I am not IT but I just got off a 20 minute phone call with the general manager asking me how to make her new computer print. I do adore her, like I know her personally, but I asked three times if the printer was on. She apologized for bothering me, and Chef Ben walked in a few minutes later, turned the printer on apparently, and then called to ask if I was trying to print shit from my house again
  • Varine Varine:
    So I have a newfound appreciation
  • Varine Varine:
    And also I'm going to remove that one from my secondary career options

      The Helper Discord

      Members online

      No members online now.

      Affiliates

      Hive Workshop NUON Dome World Editor Tutorials
      Top