| 11-26-2004, 07:31 PM | #1 |
Intro First off this is a tutorial -- not a CnP trigger. This save code is directly from my map, and so chances are it won't be adequate for your map, and im not explaining what everything does for the fun of it. In fact that is why I specifically defined variables as I went along as opposed to putting it all at the front, so it would be harder to copy it without understanding it. It is SO much better to grit it and make a save code for your map, instead of trying to adjust your map to the save code (which is what I tried and failed at in the start), so make an effort and learn the trigger instead of copying it. Also this is somewhat advanced, if you want a great basic save code trigger tutorial check out JohnFms Save+Load code tutorial , considering I used his trigger as a base for mine, it might be a good idea to check that first. Btw I have had people ask me about what arrays are all the time, just think of it as a whole bunch of variables with the same name (the array is the number of variables with that name). Why I hate the Dewey Decimal System If you want the greatest selection for the save code numbers are bad, very, very, bad (unless working with large numbers at least) Let me explain this to you, so you will understand how the rest of my code works. The numeric system has only ten combinations (0, 1, 2, etc.) for one digit, and 100 combinations for two digits. However there is 69 feasible enterable keyboard combinations for one digit. Now to understand the significance of this, let me explain it to you. If you tried to save, say, items, you could only have 10 saveable choices if you wanted to use one digit. if you used the keyboard system, you could have 69. If you had more then 69 items, 2 digits with numerics would give you 100 possible items that you could save. With the keyboard system, you could save up to 4761 items. Which would you rather use? Granted you could stick in a bunch of other digits, but the idea is to keep the code as short as possible (ive tried to shorten this down as much as possible but even so its still nearly 50 characters) Setting up starting variables Lots of starting variables for this... Usually however you want to spread out your initilization triggers on a map that would use this save code (if its big enough). A prime example of this is dark lineage, where he sets initilization triggers over 30 seconds to prevent lag. Thus set it up as an inilization trigger, but as a general advice try to set it up before they can load/save but not at initilization. Anyway... the code. Also Pay attention to the name of the trigger in the code section, if its the same name and doesn't have any event/condition that doesn't mean its a new trigger, but starting from an interruption in the previous trigger (most likely an explanation). Finally if there is no initial value for the triggers, then it wont' be mentioned. Also the variables that are mentioned are for that particular trigger, but might be used later (in which case ill mention in the next trigger, but won't say the details) Code:
Variables Needed (if not defined earlier):
UnencryptedCode [Type: String] [Initial Value: ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890`~!@#$%^&*()_=+[{]}*|;:'",<.>/?- \\Include the hyphon at the end]
SaveCode [Type: String] [Array = 1296]
ItemSets [Type: Item] [Array = \\Whatever number of items you want to save]
SpellSets [Type: Ability] [Array = \\Whatever number of spells you want to save]
HeroSets [Type: Unit] [Array = \\Whatever number of heroes you want to save]
LoopingItems [Type: Integer] \\Note, if you like to use custom text, you can put this as a local variable
Setting Save Code Vars
Event - Map Initilization
Conditions -
Actions -
For each (Integer A) from 1 to 36, do (Actions)
Loop - Actions
For Each (Integer B) from 1 to 36, do (Actions)
Set SaveCode[LoopingItems] = ((Substring(UnencryptedCode, (Integer A), (Integer A))) + (Substring(CodeSetNormal, (Integer B), (Integer B))))
Set LoopingItems = (LoopingItems + 1)Also you might have noticed that I used 1-36, insteald of 1-69. This is because 1-36 on the variable only includes a-z and 1-10. This still has 1296 possible saves (which should be more then enough), and I have noticed that if you set up loops that are too large (somewhere around 3,000) The trigger will actually stop working past that point (you can still restart it but it will only work up the loop then crash again). I have been fiddling around with this, but it has pissed me off to no end so if thats a problem try to isolate it and find ways to lower the amount of the loop. Not only that but symbols can sometimes be hard to decipher from one another and makes it easier for the person to copy down. Anyway lets continue Code:
Actions -
\\Don't set ItemSets[1] or SpellSets[1], you will see why
Set ItemSets[2] = \\whatever spell you plan to save, one for each array
Set SpellSets[2] = \\whatever spell you plan to save (if you plan to use tombs to learn spells at least, otherwise just let them choose from the hero skill menu and get rid of anything that has to do with spells), one for each array
Set HeroSets[1] = \\Whatever hero you plan to save, one for each arrayCode:
Variables Needed:
Units[Type: Unit] [Array: 12]
SettingUnits
Events -
Unit - A unit enters Rect<Gen>
Conditions -
((Triggering Unit) is A Hero) Equal to True
Actions -
Set Units[(Player number of (Owner of (Triggering Unit))))] = (Triggering Unit)Save Code Whew! lets start the actual code! lots of variables here, so make sure not to get confused Code:
Variables Needed:
UnencryptedCode(Defined Earlier)
Units(Defined Earlier)
EncryptedCode [Type: String] [Initial Value: \\Just take the unencrypted code and scramble it about. This will make sure it is a unique code, you MUST keep the - at the end though]
SaveProof [Type: Boolean] [Array: 12] [Initial Value: True]
PasswordParts [Type: String]
SaveCode
Event -
Player - Player 1 (Red) types a chat message containing -save as an Exact Match \\Just continue the events from 1-12 for each player
Conditions -
SaveProof[(Player number of Triggering Player))] Equal to True
Units[(Player number of (Triggering Player))] Not Equal to No Unit
Actions -
Set PasswordParts = Empty String
If ((Hero Level of (Units[Player number of (Triggering Player)]) Greater than 9) then Do (Set PasswordParts = (PasswordParts + (String((Hero Level of (Units[Player number of (Triggering Player)]) else do (Set PasswordParts = (PasswordParts = (0 + (String(Hero Level of Saving_Unit)))))Anyway Continuing Code:
Variables Needed:
Gold [Type: Integer]
Actions -
If ((Length of (String((Triggering Player) Current Gold)))) Greater than or equal to 5) Then do (Set PasswordParts = (PasswordParts + (Substring((String(((Triggering Player) Current Gold))), 1, 4))) else do Set PasswordParts = (PasswordParts + (String(((Triggering Player) Current Gold))))
Set
If (All Coditions are True) then do (Then Actions) Else do (Else Actions)
If - Conditions
((Triggering Player) Current gold) Greater than or Equal to 100
Then - Actions
Set Gold = (Substring((String (((Triggering Player) Current gold))), 1, ((Length of (String(((Triggering Player) Current gold))) - 2)))
Else - Actions
Set Gold = (Substring((String(((Triggering Player) Current Gold)), 1, 1))
Set PasswordParts = (PasswordParts + (Substring(XXXX, 1, (4 - (Length of Gold)))))To continue Code:
Variables Needed:
Units (Defined Earlier)
HeroSets (Defined Earlier)
PasswordParts (Defined Earlier)
Actions -
For Each (Integer A) from 1 to \\Number of HeroTypes// Do (Actions)
If - Conditions
(Unit-Type of Units[Player number of (Triggering Player)] Equal to HeroSets[Integer A])
Then - Actions
Set PasswordParts = (PasswordParts + (String((Integer A)]
If (All Conditions are True) Then do (Then Actions) else do (else Actions)
If - Conditions
(Integer A) Greater then or Equal to 0
(Integer A) Less then or Equal to 9
Then - Actions
Set Passwordparts = (PasswordParts + 0)
Else - Actions
Else - ActionsNow for the items Code:
Variables Needed:
Units (Defined Earlier)
ItemSets (Defined Earlier)
PasswordParts (Defined Earlier)
Actions -
For Each (Integer A) from 1 to 6 do (Actions)
If (All Conditions are True) Then do (Then Actions) Else do (Else Actions)
If - Conditions
(Item Carried by Units[Player Number of (Triggering Player) in Slot (Integer A)) Equal to No Item
Then - Actions
Set PasswordParts = (PasswordParts + SaveCode[1])
Else - Actions
For Each (Integer B) from 1 to \\Number of Items// Do (Actions)
If (All Conditions are True) Then do (Then Actions) Else do (Else Actions)
If - Conditions
Item Carried by Units[Player Number of (Triggering Player) In Slot (Integer A)) Equal to ItemSets[Integer B]
Then - Actions
Set PasswordParts = (Password Parts + SaveCode[Integer B])
Else - ActionsNow Saving Spells is a lot harder, as there is no way to define what slot you are saving the spell from. Thus you have to remove spells as you go, and ultimately that is the only reason you have to remove the character at the end. To get around that you can run the loadcode with the finished savecode, ignoring conditions to get the same hero back, but I don't cover that in this particular tutorial. Code:
Variables:
SpellSets (defined)
Units (Defined)
PasswordParts (Defined)
Actions-
For Each (Integer A) from 1 to 7, do (Actions)
Loop - Actions
For Each (Integer B) from 1 to \\amount of spells//, do (Actions)
Loop - Actions
If (All Conditions are True) Then do (Then Actions) Else do (Else Actions)
If - Conditions
(Level of SpellSets[Integer B] for Units[Player Number of (Triggering Player)] Greater then 0
Then - Actions
Set PasswordParts = (PasswordParts + SaveCode[(Integer B)]
Set PasswordParts = (PasswordParts + (String((Level of SpellSets[(Integer B]) for (Units[Player number of (Triggering Player)])
Remove SpellSets[(Integer B)] from Units[Player number of (Triggering Player)]
Else - Actions
If ((Integer B) Equal to \\Number of Spells//) then (set PasswordParts = PasswordParts + AA0) Else (Do Nothing)Now for the Player name Code:
Variables:
PasswordParts (Defined Earlier)
PlayerName (String)
Actions -
Set Player Name = (Name of (Triggering Player))
For each (Integer B) from 1 to 15, do ((If Length of Playername) Equal to (Integer B)) then do (Set Playername = Playername + Z)) Else do (Do Nothing)
Set Playername = Substring(Playername, 1, 3)
Set Playername = (String(Playername) as Upper Case)
Set PasswordParts = (PasswordParts + PlayerName)Now that we have the information, it is time to encrypt it! Code:
Variables:
OutPutCode (String, Array = length of string + the multiples of 6, read below)
OutPutCodeNum (Integer, init. Value 1)
Actions-
Set OutPutCode = Empty String
Set OutPutCodeNum = 1
For Each (Integer A) from 1 to 53\\or whatever the length of your code is + the multiples of 6, do (Actions)
If (All Conditions are True) Then do (Then Actions) else do (Else Actions
If - Conditions
(Integer A) not Equal to 6
(Integer A) not Equal to 12
\\Continue in multiples of six until the next multiple takes you past the end of the code including the dashes, in this case the last would be 48
Then - Actions
Set OutPutCode[(Integer A)] = (Substring(PasswordParts, OutPutCodeNum, OutPutCodeNum))
Set OutPutCodeNum = (OutPutCodeNum + 1)
Else - Actions
Set OutPutCode[(Integer A)] = -Now to scramble the code Code:
Variables
OutPutCode2 (String)
Actions -
Set OutPutCode2 = Empty String
For Each (Integer A) from 1 to 53, do (Actions)
Loop - Actions
For Each (Integer B) from 1 to 69, do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
OutPutCode[(Integer A)] Equal to (SubString(CodeSetNormal, (Integer B), (Integer B))
Then - Actions
Set OutPutCode2 = (OutPutCode2 + (Substring(CodeSetEncrypted, (Integer B), (Integer B))))
Else - ActionsNow to reverse the code, you might recognize this from the basic save code Code:
Variables:
OutPutCode3 (String)
OutPutCode2 (Defined Earlier)
Actions -
For Each (Integer A) from 0 to ((Length of OutPutCode2) - 1), do (Actions
Loop - Actions
Set OutPutCode3 = (OutPutCode3 + (Substring(OutPutCode2, ((Length of OutPutCode2) - (Integer A)), ((Length of OutPutCode2) - (Integer A) + 0))))And now lets color code it! Code:
Variables:
OutPutCode3 (Defined Earlier)
FinalCode (String)
Actions-
For Each Integer A from 1 to 53, do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
or - Any (Conditions) are true
Conditions
Substring(OutPutCode3, (Integer A), (IntegerA) Equal to -
Substring(OutPutCode3, (Integer A), (Integer A) Equal to 0
Substring(OutPutCode3, (Integer A), (Integer A) Equal to 1
\\Continue this until you get up to 9, I tried used greater/lesser but it didn't work.
Then - Actions
Set FinalCode = (Final Code + (|1C86EE)+(SubString(OutPutCode3, (Integer A), (Integer A) + |r)
Else - Actions
\\Do the same as you did for the then actions, but using a different color.
Set SaveProof[(Player Number of (Triggering Player))] = False
Set LoadProof[(Player Number of (Triggering Player))] = False
Unit - Remove Units[(Player Number of (Triggering Player))] From the game.
Game - Display to (Triggering Player) for 300 Seconds (FinalCode + is your code, enjoy and play again!OMG WE ARE DONE WITH THE SAVE CODE! Load Code Code:
Variables:
CodeSetNormal (Defined Earlier)
CodeSetEncrypted (Defined Earlier)
LoadString1 (Type: String)
LoadString2 (Type: String)
LoadString4 (Type: String)
LoadCode (Type: Integer)
LoadCode
Events-
Player 1 (red) types a chat message containing -load as a substring
\\Just copy that until you get to player 12
Conditions-
(Length of(Entered Chat String)) Equal to 59 \\or whatever your code length is + 6
LoadProof is Equal to True
Actions-
Set LoadString1 = (SubString((Entered Chat String), 6, (Length of (Entered chat string)))
Set LoadString1 = (String((LoadString1) As Upper Case)
Set LoadString2 = Empty String
Set LoadString4 = Empty String
Set LoadCode = 1
For Each (Integer A) from 0 to ((Length of LoadString1) - 1), do (Set LoadString2 = (LoadString2 + (Substring(LoadString1, (Length of LoadString1) - (Integer A)), ((Length of LoadString1) - (Integer A)))))
Code:
Variables:
LoadString3 (Type: String) (Array: //Whatever length the code is without dashes)
LoadString2 (Defined Earlier)
Actions-
For Each (Integer A) from 1 to (Length of LoadString2), do (Actions)
Loop - Actions
If (All Conditions Are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(SubString(LoadString2, (Integer A), (Integer A))) Not Equal to -
Then - Actions
Set LoadString3[LoadCode] = (SubString(LoadString2, (Integer A), (Integer A))
Set LoadCode = (LoadCode + 1)
Else - ActionsCode:
Variables:
Actions-
For Each (Integer A) from 1 to 45, do (Actions)
Loop - Actions
For Each (Integer B) from 1 to 69, do (Actions)
Loop - Actions
If (All Conditions are True) then do (Then Actions) Else do (Else Actions)
If - Conditions
LoadString3[(Integer A)] Equal to (Substring(CodeSetEncrypted, (Integer B), (Integer B)))
Then - Actions
Set LoadString4 = (LoadString4 + (SubString(CodeSetNormal, (Integer B), (Integer B))
Else - ActionsCode:
Variables:
Playername(Defined Earlier)
Actions-
Set Playername = Name of (Triggering Player)
(For Each (Integer B) from 1 to 15, do (If (Length of PlayerName) Equal to (Integer B) Then do (Set Playername = PlayerName + Z)) else do (Do Nothing)
Set Playername = (Substring(Playername, 1, 3))
Set Playername = (String(Playername) As Upper Case)Code:
Variables:
LoadString4 (Defined Earlier)
Race (the unmentioned variable)
HeroSets (Defined Earlier)
Actions-
If (Substring(LoadString4, 43, 45)) Not Equal to Playername Then do (Skip Remaining Actions) Else do (Do Nothing)
Set Race[(Player number of (Triggering Player)] = (Integer(Substring(Loadstring4, 42, 42))))
Wait .01 seconds
Unit - Create 1 HeroSets[(Integer((Substring(Loadstring4, 7, 8))))] for (Triggering Player) at (Center of StartingCity<gen>) Facing Default Building (270.0) degreesCode:
Variables:
LoadingHero (Type: Unit)
Loadstring4 (Defined Earlier)
Actions-
Set LoadingHero = (Last Created Unit)
If (Integer((Substring(LoadString4, 1, 2))) Greater then or Equal to 10) Then do (Hero - Set LoadingHero Hero-Level to (Integer(Substring(Loadstring4, 1, 2))), Hide Level-up Graphics, Else do (Hero - Set LoadingHero Hero-Level to (Integer((Substring(Loadstring4, 2, 2))) Hide level-up Graphics)Code:
Variables:
Loadstring4 (Defined Earlier)
Gold2 (type: String)
Actions-
Set Gold2 = Empty String
For Each (Integer A) from 1 to 4, do (Actions)
Loop - Actions
If (All Conditions are True) Then do (Then Actions) Else do (Else Actions)
If - Conditions
(Substring((Substring(Loadstring4, 3, 6((Integer A), (Integer A)), Not Equal to X
Then - Actions
Set Gold2 = (Gold2 + (Substring((Substring(Loadstring3, 3, 6)), (Integer A), (Integer A)))
Else - Actions
Player - Set (Triggering player) Current Gold to (Integer(Gold2 X 100))Now for items and spells it is basically the same action over and over Code:
Actions-
For each(Integer A) from 1 to \\Amount of Saveable Items// do (Actions)
Loop - Actions
If ((Substring(LoadString3, 9, 10)) Equal to Letters[(Integer A)]) then do (Hero - Create Item[(Integer A)] and give it to LoadingHero) else do (Do nothing)
For each(Integer A) from 1 to \\Amount of Saveable Items// do (Actions)
Loop - Actions
If ((Substring(LoadString3, 11, 12)) Equal to Letters[(Integer A)]) then do (Hero - Create Item[(Integer A)] and give it to LoadingHero) else do (Do nothing)
\\Keep on doing this until you finish all 6 slots (for me it finishes with 19 and 20)Code:
Variables:
LoadSpells (Integer)
Loadstring4 (Defined Earlier)
Actions-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
If - Conditions
(Substring(LoadString3, 21, 22)) Not equal to AA
Then - Actions
For each (Integer A) from 1 to 676, do (Actions)
Loop - Actions
If ((Substring(LoadString3, 21, 22)) Equal to Letters[(Integer A)]) then do (Unit - Add Spells[(Integer A)] to LoadingHero) else do (Do nothing)
If ((Substring(LoadString3, 21, 22)) Equal to Letters[(Integer A)]) then do (Set LoadSpells = Spells[(Integer A)]) else do (Do nothing)
Else - Actions
If ((Substring(LoadString3, 21, 22)) Not equal to AA) then do (Unit - Set Level of LoadSpells for (Triggering unit) to (Integer((Substring(LoadString3, 23, 23))))) else do (Do nothing)
\\Continue this for each spell, for me ending at 41 (3 numbers for each spell)
Set LoadProof[(Player number of (Triggering player))] = FalseAnd omg we are finally done with the load part too. Congratulate yourself for being able to read all of this stuff without your head exploding! Any feedback is much appreciated, as shallow as it sounds I do kind of write these to hear how it helps people. Anyway enjoy! Also if you find any mistakes (And I can almost guarantee there will be 2-3) please say so, same with if there is any questions. Also my other post got into the tutorials if any admins want to delete this one. |
| 12-01-2004, 02:22 AM | #2 |
No feedback at all? I mean 45 views.... or is it just because people are too lazy to read it all ^_^ . |
| 12-04-2004, 10:13 PM | #3 |
Guest | Wow this is taking me long enough, but its helping me thx o_O |
| 01-10-2005, 11:38 PM | #4 |
Is this the save system that will reset your code after about a month???it always ticks me off when that happens! |
| 01-11-2005, 12:47 AM | #5 |
Guest | thanks for the codes, thy are so good |
| 01-12-2005, 09:07 PM | #6 | |
Quote:
The number one thing to remember with this save code is that it technically isn't saving. It is just creating a "blank" then using the digits you stick in to give it the characteristics of your previous character. You cannot save characters, at all, unless using caching (which is single player only. This shoudl work fine for multiplayer), and thus unless you change where things are on the items and whatnot setting it will never change. when something changes thats because the items change, not because your character becomes inferior or changes or something. I imagine that if you are losing save codes after a while, thats probably because A) you wrote it down wrong or B) in the case of dark deeds they don't compensate for letters that aren't capital, and doesn't recognize them if they are. You have to deal with this by lowering all the letters. To try to keep an accurate code, always takea screenshot of it. Just hit print screen and it sends it to the screenshot directory in your w3 folder. If you screw up the code you can just go there and look it up, and they are easy to delete if you start running out of space (and considering they are only a meg each that isn't likely to happen.) Also if you can't open the file try using Internet explorer. They are saved as a .targa file and not many basic Microsoft programs can open that type of file. Ironically internet explorer can however. |
| 01-17-2005, 10:01 AM | #7 |
actually, maps like waugriffs RPG will delete. im pretty sure they actually save it!!im not sure though, and i even check it 3 times, but it'll still just "go away" if i wait too long. plus, im not the only 1 who have witnessed this |
| 01-23-2005, 03:37 PM | #8 |
erm lol that save code is unneccesarily long...i can do 3000+item 1200+hero save code easier than that....wtf is the point in it?? also includes gold, wood and can be incorporated for other stuff as well! |
| 01-23-2005, 05:02 PM | #9 |
well post it, prove that ur not all talk - i've heard countless ppl saying "my save code can save X heros, Y items and Z spells" unless you are willing to post it dont brag. |
| 01-24-2005, 05:02 AM | #10 | ||
Quote:
And since when has mine not done any of that... I could say I could build a stadium using a piece of string but that doesn't make it true. Its as short as it can get saving what it does, you have to cut it out to make it shorter. But I have a feeling you know that, and just trying to be jackass because... well I don't know how jackasses think. Anyway have a nice life making idiotic comments. Quote:
I can guarantee that it doesn't save it. It will never save it if its multiplayer, because that requires saving cookies on your computer. And since that isn't covered in the user license agreement for warcraft 3 that would be... how do you say it... a jailable offense. That would be considered what we like to call "hacking" if it saved your character on the hard drive, and I don't think someone would go to the trouble to bypass a firewall to put some character information in your cookie folder. The only reason cookies can be saved from internet explorer is because that is covered in the windows use license agreement for htat particular product. That doesn't cover warcraft3. |
| 01-24-2005, 12:36 PM | #11 |
the data is stored and represented as a character... like in this and all save codes. ie. for items A= boots of speed 3= claws of attack +3 A3= crown of kings +5 also save codes come in various forms, for example some only save the level of the hero wheres others save the actual experience. with waurgriffs, the case is most likely. you have aquired a new item, 1 stat has changed, you moved an item, you have gained a lvl or experience (pending on the save system). all kinds of little things. |
| 01-24-2005, 05:36 PM | #12 |
u want me to make a new one, coz i aint posting the one i use and i need to make a new one neway...come to my freelance thread in like 4-5 days, o and btw it will be limited in 55 item storage, total item combos 3000+ just u watch and learn, i got my name for a reason |
| 02-04-2005, 04:04 AM | #13 |
if it'll shut you up, then go ahead and TRY to show off. btw, im pretty sure this is for the world editor??can you do this w/o WEU?? im already pissed off, so i dont wanna here any crap right now |
| 02-04-2005, 08:04 AM | #14 |
yes most of these are made without WEU, the is no need to rely on third party programs |
| 02-11-2005, 07:47 AM | #15 | |
Guest | Quote:
Get a doctor! Quick! If your head keeps growing it will IMPLODE!! Actually, the save code system I myself use is almost the same as this one, and I'd hope someone would have posted it someday, coz I myself am very very lazy ^_^, good job for telling it to the people |
