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!
Hi guys!
I`m making a map, and i need system that would save integer array and convert it into code for loading in future by player.
I was searching for a long time, but no result.
I even tried to change classic codegen code, but it bugged and i can`t use it.
There is any possible solution, probly in JASS to do it. Asking for non-reforged one.
Thx a lot for answer
Information If you've ever wanted to transfer progress between multiplayer maps, you probably needed to type in a long code. That is no longer needed with this system. This will allow you to read save data from your WC3 folder and sync it to all other players in the map. The demo map...
They are probably asking for code that runs in a legacy build of Warcraft III. This means that it would need to be an older version of modern I/O based save/load systems due to the lack of synchronisation natives and instead using unit section.
The basic idea is you take the integers and encode them into a string that can then be decoded to reconstruct the integers. The most simple form of this would be saving the integers as decimal directly and separating them with dash '-' characters. For example the following 3 integers...
Code:
1337
42
9001
Could be encoded as the following string...
Code:
1337-42-9001
To decode such string you would iterate through it character by character until you find the next dash '-' character and then sub string out the decimal number string and convert that into an integer, repeating for all saved values.
Logically such encoding is not very efficient and can be improved. Better encoding would convert the integer to base 64 allowing the same number to be represented with fewer digits. Instead of using key characters to separate numbers, the numbers might be encoded with a fixed width saving more characters and speeding up the decode. Instead of storing a sequence of numbers, the code could represent a sequence of bits that is derived from compressing a buffer containing such a number sequence for larger space savings. A cryptographic hash could be added to the stored data to help detect errors or tampering. Some form of encryption could be used to try to obfuscate the contents of the code.
I made a few util function that I used for my "write code in chat" system.
Basically, use intToBase64 to get the string (base 64) for the given integer, and fromBase64.
In both cases, you need to know the "maxLength" (how many base64 characters are used for a given field).
In my map, I know that there are less than 64 "waves", so I only need 1 character to represent the wave-number.
I know that the exp is less than 50 000 (or something like that) because that's the amount you have at max-level on my map, so I only need 3 charaters for that, etc.
ofc it is possible to use some other character as separator and do it smarter or whatever, but I made this mostly by myself to learn and it works. I might've looked at how others do certain things, I don't remember.
JASS:
function base64CharFromIndex takes integer index returns string
return SubString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", index, index + 1)
endfunction
function base64IndexOfChar takes string input returns integer
local integer i = 0
loop
exitwhen base64CharFromIndex(i) == input
set i = i + 1
endloop
return i
endfunction
function intToBase64 takes integer input, integer capResultChars returns string
local integer currentValue = input
local string result = ""
loop
//call BJDebugMsg("current result=" + result + ", currentValue=" + I2S(currentValue))
set result = base64CharFromIndex(ModuloInteger(currentValue, 64)) + result
set currentValue = currentValue / 64
exitwhen currentValue == 0
endloop
//call BJDebugMsg("Final result=" + result + ", currentValue=" + I2S(currentValue))
return SubString(result + "====", 0, capResultChars)
endfunction
function fromBase64 takes string input, integer maxLength returns integer
local integer result = 0
local integer i = 0
local string currentChar
loop
set currentChar = SubString(input, i, i + 1)
exitwhen i > (maxLength - 1) or currentChar == "="
set i = i + 1
set result = result * 64 + base64IndexOfChar(currentChar)
endloop
return result
endfunction
I load by doing (I load the 6th (or 7th? depends how you count I think) character of the chat-string as the wave-number). set udg_current_wave_nr = fromBase64(SubString(udg_load_string, 6, 7), 1)
I "save" by adding my various values together to something player has to write. There is a description and then: call BJDebugMsg("-load " + intToBase64(udg_last_market_wave, 1) + intToBase64(udg_last_market_tot_gold, 4) + intToBase64(udg_last_market_exp, 3))
(where udg_last_market_wave, udg_last_market_tot_gold, udg_last_market_exp are the values I store, and the 1, 4, 3 are the "max lengths" I "support").
Note that the code needs to be adjusted if you plan to store values bigger than 64^4 (also known as over 16 million).
I made a few util function that I used for my "write code in chat" system.
Basically, use intToBase64 to get the string (base 64) for the given integer, and fromBase64.
In both cases, you need to know the "maxLength" (how many base64 characters are used for a given field).
In my map, I know that there are less than 64 "waves", so I only need 1 character to represent the wave-number.
I know that the exp is less than 50 000 (or something like that) because that's the amount you have at max-level on my map, so I only need 3 charaters for that, etc.
ofc it is possible to use some other character as separator and do it smarter or whatever, but I made this mostly by myself to learn and it works. I might've looked at how others do certain things, I don't remember.
JASS:
function base64CharFromIndex takes integer index returns string
return SubString("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", index, index + 1)
endfunction
function base64IndexOfChar takes string input returns integer
local integer i = 0
loop
exitwhen base64CharFromIndex(i) == input
set i = i + 1
endloop
return i
endfunction
function intToBase64 takes integer input, integer capResultChars returns string
local integer currentValue = input
local string result = ""
loop
//call BJDebugMsg("current result=" + result + ", currentValue=" + I2S(currentValue))
set result = base64CharFromIndex(ModuloInteger(currentValue, 64)) + result
set currentValue = currentValue / 64
exitwhen currentValue == 0
endloop
//call BJDebugMsg("Final result=" + result + ", currentValue=" + I2S(currentValue))
return SubString(result + "====", 0, capResultChars)
endfunction
function fromBase64 takes string input, integer maxLength returns integer
local integer result = 0
local integer i = 0
local string currentChar
loop
set currentChar = SubString(input, i, i + 1)
exitwhen i > (maxLength - 1) or currentChar == "="
set i = i + 1
set result = result * 64 + base64IndexOfChar(currentChar)
endloop
return result
endfunction
I load by doing (I load the 6th (or 7th? depends how you count I think) character of the chat-string as the wave-number). set udg_current_wave_nr = fromBase64(SubString(udg_load_string, 6, 7), 1)
I "save" by adding my various values together to something player has to write. There is a description and then: call BJDebugMsg("-load " + intToBase64(udg_last_market_wave, 1) + intToBase64(udg_last_market_tot_gold, 4) + intToBase64(udg_last_market_exp, 3))
(where udg_last_market_wave, udg_last_market_tot_gold, udg_last_market_exp are the values I store, and the 1, 4, 3 are the "max lengths" I "support").
Note that the code needs to be adjusted if you plan to store values bigger than 64^4 (also known as over 16 million).
I`ve got the idea of the code, but stil can`t understand how to use it correctly.
JASS:
function Trig_rea_save_Actions takes nothing returns nothing
call BJDebugMsg("-load " + intToBase64(udg_apt1[GetConvertedPlayerId(GetTriggerPlayer())],1))
endfunction
function InitTrig_rea_save takes nothing returns nothing
set gg_trg_rea_save = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_rea_save, Player(0), "-save", true )
call TriggerAddAction( gg_trg_rea_save, function Trig_rea_save_Actions )
endfunction
And if i load i guess
JASS:
function Trig_rea_save_Actions takes nothing returns nothing
call BJDebugMsg("-load " + intToBase64(udg_apt1[GetConvertedPlayerId(GetTriggerPlayer())],1))
endfunction
function InitTrig_rea_save takes nothing returns nothing
set gg_trg_rea_save = CreateTrigger( )
call TriggerRegisterPlayerChatEvent( gg_trg_rea_save, Player(0), "-save", true )
call TriggerAddAction( gg_trg_rea_save, function Trig_rea_save_Actions )
endfunction
Am i right?
I just wanna to use it in rpg maps.
I know there is a lot to can be do better like encryption or cheking code owner`s name, but for now i need to do it step by step.
This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
By continuing to use this site, you are consenting to our use of cookies.