- Joined
- Jul 10, 2007
- Messages
- 6,306
For very simple save/load codes that don't need backwards compatibility or any of the advanced features of Encoder and only need to perhaps save a few values.
This includes all of the latest encryption as well as easy to edit configs. It is set up to be GUI friendly (if you want a vjass person to quickly set up a save/load code for you, they can easily read/write to your GUI variables).
This requires knowledge of BigInt as well as general saving and loading. I use this template for making simple save/load codes for people =P.
The only system that this does not include in it is UnitStatePercent as that requires some Lua, but it is simple enough to add to the bottom and make SL use at the top, so that can be added when needed.
In this template you will see 3 variables that it saves/loads-
test1
test2
test3
Those are just there so that one can quickly see how to use this. They can all be deleted.
Security Features-
player+salt+BASE based bases
player+salt+CHECKSUM bases checksums
player+salt based shuffling
Compression Features-
Plain old BigInt. No tree based structure like the one Encoder has. This is again for simple save/load codes.
Backwards Compatibility-
None, but it can be built in if needed.
This framework is very low level
If you have any of these resources in your map, delete them out of the script via CTRL+F library ResourceName
The reason these systems are in this is for easy cnp. I expect many users using this to be using this for making simple save/load systems for GUI friends that probably aren't using any of the above systems anyways.
This includes all of the latest encryption as well as easy to edit configs. It is set up to be GUI friendly (if you want a vjass person to quickly set up a save/load code for you, they can easily read/write to your GUI variables).
This requires knowledge of BigInt as well as general saving and loading. I use this template for making simple save/load codes for people =P.
The only system that this does not include in it is UnitStatePercent as that requires some Lua, but it is simple enough to add to the bottom and make SL use at the top, so that can be added when needed.
In this template you will see 3 variables that it saves/loads-
test1
test2
test3
Those are just there so that one can quickly see how to use this. They can all be deleted.
Security Features-
player+salt+BASE based bases
player+salt+CHECKSUM bases checksums
player+salt based shuffling
Compression Features-
Plain old BigInt. No tree based structure like the one Encoder has. This is again for simple save/load codes.
Backwards Compatibility-
None, but it can be built in if needed.
This framework is very low level
If you have any of these resources in your map, delete them out of the script via CTRL+F library ResourceName
- Table
- BigInt
- KnuthChecksum
- Scrambler
- Ascii
- Base
The reason these systems are in this is for easy cnp. I expect many users using this to be using this for making simple save/load systems for GUI friends that probably aren't using any of the above systems anyways.
JASS:
library SL uses BigInt, KnuthChecksum, Scrambler
/*************************************************************************************
*
* SETTINGS
*
*************************************************************************************/
globals
//character set
private constant string BASE="abcdefghijklmnopqrstuvwxyzABCDEFGHKLMNOPQRSTUVWXYZ0123456789@#$%&?"
private constant boolean LOAD_ONCE=false //if true, players can only successfully load once
private constant boolean ONLINE_ONLY=false //if true, game has to be on b.net or LAN to save/load
private constant integer MIN_SAVE_PLAYER=1 //minimum amount of players required in game to save
private constant integer MIN_LOAD_PLAYER=1 //minimum amount of players required in game to load
//max checksum: 214748364
private constant integer MAX_CHECKSUM =214748364 //maximum checksum
private constant integer SHUFFLES =3 //how many shuffles to perform
private constant real VARIANCE =.85 //checksum variance (shouldn't change)
private constant string NUM_COLOR ="|cff40e0d0" //what to color numbers
private constant string LOWER_COLOR ="|cffff69b4" //what to color lowercase characters
private constant string UPPER_COLOR ="|cff00AA00" //what to color uppercase characters
private constant string SPEC_COLOR ="|cffffff00" //what to color special characters
private constant string DELIMITER_COLOR ="|cffffffff" //what to color DELIMITER characters
private constant string DELIMITER ="-" //DELIMITER to make code easier to read
private constant integer DELIMITER_COUNT =4 //how many characters per DELIMITER
//makes it impossible to get checksum with JASS w/o this code
private constant string CHECKSUM_SALT ="123456"
private constant string START_MESSAGE="" //message displayed before code
private constant string END_MESSAGE="" //message displayed after code
private constant integer MAX_LOAD_ATTEMPT=-1 //<0 means infinite load attempts
private constant real LOAD_TIME=180 //how long the players can load for at the start of game
private constant string LOAD_STOP_IN="|cffff0000Loading will be disabled in "
//displayed when a player attempts to load and code was invalid
private constant string INVALID_CODE="|cffff0000Invalid Code"
//displayed after INVALID_CODE if MAX_LOAD_ATTEMPT is greater than 0
private constant string LOAD_ATTEMPT=" Load attempt(s) Left"
//displayed when a player successfully loads
private constant string VALID_CODE="|cff008B00Decoding Successful"
private constant integer MIN_CODE_LENGTH=10 //minimum length of code
private constant integer MAX_CODE_LENGTH=30 //maximum length of code
private constant string LOAD_DISABLED="|cffff0000Loading Disabled" //message displayed when loading is disabled
private constant string SAVE_DISABLED="|cffff0000Saving Disabled" //message displayed when saving is disabled
endglobals
//! textmacro SCRAMBLER_SETTINGS
globals
/*************************************************************************************
*
* SALT
*
* Refers to what to append to the player's name when generating scrambler keys
* for each player. This is essentially like a password. It's impossible for another
* map to descramble a number without this password.
*
* This password can be any string, such as "7/ah+53~r\\ZZ"
*
*************************************************************************************/
private constant string SALT="123456"
endglobals
/*************************************************************************************
*
* SetShuffleOrder
*
* Creates the shuffling algorithm using 5 different prime bases.
*
* Shuffling mixes a number up using a variety of bases to produce results rivaling
* top random number generators.
*
* Different bases ensure better mixes.
*
* Enabled Bases:
*
* 2
* Will shuffle number in groups of 1 bit
* 3
* Will shuffle number in groups of 1.58 bits
* 5
* Will shuffle number in groups of 2.32 bits
* 7
* Will shuffle in groups of 2.81 bits
* 11
* Will shuffle in groups of 3.46 bits
*
* Strategies:
*
* 1.
* shuffle by large1, shuffle by small1, shuffle by large2, etc
* 2.
* shuffle by small1, shuffle by large1, shuffle by small2, etc
* 3.
* shuffle by small1, shuffle by small2, shuffle by large1, shuffle by small3, etc
*
* Keep in mind that as fractional bits are shuffled, bits split/merge, meaning that the number
* can drastically change by becoming much smaller or much larger.
*
*
* Shuffle Array: so
*
* Ex:
*
* set so[0]=3 //first mix by 1.58 bits
* set so[1]=2 //second mix by 1 bit
* set so[2]=7 //third mix by 2.81 bits
* set so[3]=2 //fourth mix by 1 bit
*
* return 4 //return number of mixes
*
*************************************************************************************/
private keyword so
private function SetShuffleOrder takes nothing returns integer
/*************************************************************************************
*
* MIXES
*
* array: so
* bases: 2,3,5,7,11
*
*************************************************************************************/
set so[0]=2
/*************************************************************************************
*
* MIX COUNT
*
*************************************************************************************/
return 1
endfunction
//! endtextmacro
/*************************************************************************************
*
* SAVE/LOAD SETTINGS
*
*************************************************************************************/
globals
//the biggest value you can save of all of the values
private constant integer BIGGEST=1000000
//variables for copying GUI vars over
private integer array test
endglobals
//saves data from copied variables above
private function SaveData takes BigInt i, integer id returns nothing
if (test[0]>1000000-1) then
set test[0]=1000000-1
endif
if (test[1]>100000-1) then
set test[1]=100000-1
endif
if (test[2]>10000-1) then
set test[2]=10000-1
endif
call i.multiply(1000000)
call i.add(test[0],0)
call i.multiply(100000)
call i.add(test[1],0)
call i.multiply(10000)
call i.add(test[2],0)
endfunction
//copies GUI variable data into array vars
private function CopyData takes integer id returns nothing
set test[0]=udg_test[id]
set test[1]=udg_test2[id]
set test[2]=udg_test3[id]
endfunction
//loads values from code into arry vars
private function LoadData takes BigInt i, integer id returns nothing
set test[2]=i.divide(10000)
set test[1]=i.divide(100000)
set test[0]=i.divide(1000000)
endfunction
//erases GUI vars
private function UnloadData takes integer id returns nothing
set udg_test[id]=0
set udg_test2[id]=0
set udg_test3[id]=0
endfunction
//writes to GUI vars (creates units, does w/e)
private function FinalizeData takes integer id returns nothing
set udg_test[id]=test[0]
set udg_test2[id]=test[1]
set udg_test3[id]=test[2]
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,I2S(test[0]))
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,I2S(test[1]))
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,I2S(test[2]))
endfunction
/*************************************************************************************
*
* CODE
*
*************************************************************************************/
globals
private integer array ph
private Base array pb
private Base b10
private boolean array bl
private integer array pl
private integer c=0
private trigger t=null
private trigger t2=null
endglobals
function Save takes nothing returns boolean
local integer id=GetPlayerId(GetTriggerPlayer())
local BigInt i=BigInt.create(b10)
local string s=""
local integer h
local string c
local boolean l
local integer bs
local integer ch
call CopyData(id+1)
call SaveData(i,id+1)
set ch=GetKnuthChecksum(i,ph[id])
if (ph[id]>BIGGEST) then
call i.destroy()
set i=BigInt.create(b10)
call i.add(ch,0)
call SaveData(i,id+1)
else
call i.multiply(ph[id])
call i.add(ch,0)
endif
call Shuffle(i,id,SHUFFLES)
set i.base=pb[id]
set h=DELIMITER_COUNT
loop
set i=i.previous
exitwhen i.end
set c=pb[id].char(i.digit)
if (0==h) then
set h=DELIMITER_COUNT
set s=s+DELIMITER_COLOR+DELIMITER
endif
set l=StringCase(c,false)==c
if (c==StringCase(c,true) and l) then
if ("0"==c or 0!=S2I(c)) then
set s=s+NUM_COLOR+c
else
set s=s+SPEC_COLOR+c
endif
elseif (l) then
set s=s+LOWER_COLOR+c
else
set s=s+UPPER_COLOR+c
endif
set h=h-1
endloop
call i.destroy()
if (GetLocalPlayer()==GetTriggerPlayer()) then
call ClearTextMessages()
endif
call DisplayTimedTextToPlayer(GetTriggerPlayer(),.5,.5,60,START_MESSAGE+s+END_MESSAGE)
return false
endfunction
function Load takes nothing returns boolean
local integer id=GetPlayerId(GetTriggerPlayer())
local BigInt i
local string s2
local integer m
local string c
local string s=""
local integer bs
local integer ch
local boolean f
if ((not bl[id] or not LOAD_ONCE) and 0<pl[id]) then
set s2=GetEventPlayerChatString()
set s2=SubString(s2,6,StringLength(s2))
set m=StringLength(s2)
loop
exitwhen 0==m
set m=m-1
set c=SubString(s2,m,m+1)
if (c!=DELIMITER) then
set s=c+s
endif
endloop
if (0<MAX_LOAD_ATTEMPT) then
set pl[id]=pl[id]-1
endif
if (GetLocalPlayer()==GetTriggerPlayer()) then
call ClearTextMessages()
endif
set m=StringLength(s)
if (m<MIN_CODE_LENGTH or m>MAX_CODE_LENGTH) then
if (0<MAX_LOAD_ATTEMPT) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,INVALID_CODE+", "+I2S(pl[id])+LOAD_ATTEMPT)
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,INVALID_CODE)
endif
else
set i=BigInt.convertString(s,pb[id])
if (0==i) then
if (0<MAX_LOAD_ATTEMPT) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,INVALID_CODE+", "+I2S(pl[id])+LOAD_ATTEMPT)
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,INVALID_CODE)
endif
endif
set i.base=b10
call Unshuffle(i,id,SHUFFLES)
set f=ph[id]>BIGGEST
if (not f and i.divide(ph[id])!=GetKnuthChecksum(i,ph[id])) then
call i.destroy()
if (0<MAX_LOAD_ATTEMPT) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,INVALID_CODE+", "+I2S(pl[id])+LOAD_ATTEMPT)
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,INVALID_CODE)
endif
return false
else
call LoadData(i,id+1)
if (f) then
set ch=i.toInt()
call i.destroy()
set i=BigInt.create(b10)
call SaveData(i,id+1)
if (ch!=GetKnuthChecksum(i,ph[id])) then
call i.destroy()
if (MAX_LOAD_ATTEMPT>0) then
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,INVALID_CODE+", "+I2S(pl[id])+LOAD_ATTEMPT)
else
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,INVALID_CODE)
endif
return false
endif
endif
call i.destroy()
set bl[id]=true
call UnloadData(id+1)
call FinalizeData(id+1)
call DisplayTimedTextToPlayer(GetTriggerPlayer(),0,0,60,VALID_CODE)
endif
endif
endif
return false
endfunction
//this is run when a player leaves
private function Leave takes nothing returns boolean
set c=c-1 //decrease player count by 1
//if player count is under minimum count needed for saving
//and save trigger is enabled
//disable save trigger
if (c<MIN_SAVE_PLAYER and null!=t) then
call DestroyTrigger(t) //disable save trigger
set t=null
//display saving disabled message to all players
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,SAVE_DISABLED)
endif
//if player count is under minimum count for loading
//and load trigger is enabled
//disable load trigger
if (c<MIN_LOAD_PLAYER and null!=t2) then
call DestroyTrigger(t2) //disable load trigger
set t2=null
//display loading disabled message to all players
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,LOAD_DISABLED)
endif
return false
endfunction
//stops load
private function SO takes nothing returns nothing
//if loading is enabled
if (null!=t2) then
call DestroyTrigger(t2)
set t2=null
//display loading disabled message to all players
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,LOAD_DISABLED)
endif
call DestroyTimer(GetExpiredTimer())
endfunction
private module N
private static method onInit takes nothing returns nothing
local integer i=11 //players 0-11
local player p
local integer ch //player hash
local integer m //minimum checksum
local integer ma //checksums active
local trigger t3 //leave trigger
local Base y //BASE
local BigInt q //base as BigInt
local BigInt q2 //player unique base as BigInt
local integer ml=MAX_LOAD_ATTEMPT //max load attempts formatted
//is game not online?
local boolean f=(not ReloadGameCachesFromDisk() or not ONLINE_ONLY)
local real r=LOAD_TIME
//if MAX_LOAD_ATTEMPT is under 0, then set formatted max load to 1
//so that all players have infinite load attempts
if (ml<0) then
set ml=1
endif
//count how many players are in the map
loop
set p=Player(i)
if (GetPlayerSlotState(p)==PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p)==MAP_CONTROL_USER) then
set c=c+1
endif
exitwhen i==0
set i=i-1
endloop
//if not online or player count too small, display saving is disabled to all players
if (not f or c<MIN_SAVE_PLAYER) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,SAVE_DISABLED)
endif
//if not online or player count to small, display loading is disabled to all players
if (not f or c<MIN_LOAD_PLAYER) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,LOAD_DISABLED)
//disable load in a certain amount of time
elseif (r>0) then
call TimerStart(CreateTimer(),LOAD_TIME,false,function SO)
if (r<86400) then
if (r<3600) then
if (r<60) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,LOAD_STOP_IN+R2S(r)+" seconds")
else
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,LOAD_STOP_IN+R2S(r/60)+" minutes")
endif
else
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,LOAD_STOP_IN+R2S(r/360)+" hours")
endif
else
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0,60,LOAD_STOP_IN+R2S(r/3600)+" days")
endif
endif
//if online and either there are enough players to save or enough to load, then
//set up the save/load
if (f and (c>=MIN_SAVE_PLAYER or c>=MIN_LOAD_PLAYER)) then
set t3=CreateTrigger() //leave trigger
call TriggerAddCondition(t3,Condition(function Leave)) //add Leave function to leave trigger
//go back to player 11
set i=11
if (c>=MIN_SAVE_PLAYER) then
set t=CreateTrigger() //save trigger
call TriggerAddCondition(t,Condition(function Save))
endif
if (c>=MIN_LOAD_PLAYER) then
set t2=CreateTrigger() //load trigger
call TriggerAddCondition(t2,Condition(function Load))
endif
set m=R2I(MAX_CHECKSUM*VARIANCE) //minimum possible checksum
set ma=MAX_CHECKSUM-m //checksums active
//convert BASE string into a Base with 0 swapped with 1 so that 0 isn't lost
set y=Base[SubString(BASE,1,2)+SubString(BASE,0,1)+SubString(BASE,2,StringLength(BASE))]
//convert the BASE string into a big integer
set q=BigInt.convertString(BASE,y)
//create base 10
set b10=Base["0123456789"]
//set up save/load for each player
loop
set p=Player(i) //convert integer to player
//if the player is not a computer and is playing
if (GetPlayerSlotState(p)==PLAYER_SLOT_STATE_PLAYING and GetPlayerController(p)==MAP_CONTROL_USER) then
set q2=q.copy() //copy original base
call Scramble(q2,i,3,y,true) //scramble it
set pb[i]=Base[q2.toString()] //give to player
call q2.destroy() //clean
//get player hash (for player unique checksum)
set ch=IAbsBJ(StringHash(GetPlayerName(p)+CHECKSUM_SALT))
//generate player unique checksum
set ph[i]=ch-ch/ma*ma+m
//if enough players for saving, then register player to save trigger
if (c>=MIN_SAVE_PLAYER) then
call TriggerRegisterPlayerChatEvent(t,p,"-save",true)
endif
//if enough players for loading, then register player to load trigger
if (c>=MIN_LOAD_PLAYER) then
call TriggerRegisterPlayerChatEvent(t2,p,"-load ",false)
endif
//register player to player leave trigger
call TriggerRegisterPlayerEvent(t3,p,EVENT_PLAYER_LEAVE)
//give player formatted max load attempts remaining
set pl[i]=ml
endif
exitwhen i==0
set i=i-1
endloop
//clean handles
set t=null
set t2=null
set t3=null
endif
set p=null
endmethod
endmodule
private struct I extends array
implement N
endstruct
endlibrary
library BigInt uses Base
globals
private integer i=0
private integer array n
private integer array p
private integer array v
private Base array b
private boolean array e
private trigger j=CreateTrigger()
private trigger x=CreateTrigger()
private trigger x4=CreateTrigger()
private trigger x5=CreateTrigger()
private trigger y0=CreateTrigger()
private trigger y6=CreateTrigger()
private trigger y7=CreateTrigger()
private trigger y8=CreateTrigger()
private trigger y9=CreateTrigger()
private trigger x1=CreateTrigger()
private trigger x2=CreateTrigger()
private integer td=0
private integer my=0
private integer my3=0
private integer td2=0
private string yy=""
private integer dz
endglobals
private module IntMod
private static method onInit takes nothing returns nothing
call TriggerAddCondition(j,Condition(function thistype.ch))
call TriggerAddCondition(x,Condition(function thistype.ml))
call TriggerAddCondition(x4,Condition(function thistype.div))
call TriggerAddCondition(x5,Condition(function thistype.s2))
call TriggerAddCondition(y0,Condition(function thistype.a0))
call TriggerAddCondition(y7,Condition(function thistype.m0))
call TriggerAddCondition(y6,Condition(function thistype.tos))
call TriggerAddCondition(y8,Condition(function thistype.c0))
call TriggerAddCondition(y9,Condition(function thistype.a1))
call TriggerAddCondition(x1,Condition(function thistype.m1))
call TriggerAddCondition(x2,Condition(function thistype.m2))
endmethod
endmodule
struct BigInt extends array
method operator previous takes nothing returns thistype
return p[this]
endmethod
method operator next takes nothing returns thistype
return n[this]
endmethod
method operator digit takes nothing returns integer
return v[this]
endmethod
method operator digit= takes integer y returns nothing
set v[this] = y
endmethod
method operator end takes nothing returns boolean
return e[this]
endmethod
private static method c0 takes nothing returns boolean
local integer y
local integer z
local integer q
local integer k=td
if (0==n[0]) then
set i=i+1
set z=i
else
set z=n[0]
set n[0]=n[z]
endif
set e[z]=true
set b[z]=b[k]
set v[z]=0
set q=z
loop
set k=n[k]
exitwhen e[k]
if (0==n[0]) then
set i=i+1
set y=i
else
set y=n[0]
set n[0]=n[y]
endif
set n[q]=y
set p[y]=q
set v[y]=v[k]
set q=y
endloop
set p[z]=q
set n[q]=z
set dz=z
return true
endmethod
method copy takes nothing returns thistype
set td=this
call TriggerEvaluate(y8)
return dz
endmethod
private static method a1 takes nothing returns boolean
local integer y=td
local integer a
local integer z=b[y].size
local integer q=0
local integer m
local integer g=dz
local integer k=my
loop
if (e[n[y]]) then
if (0==n[0]) then
set i=i+1
set a=i
else
set a=n[0]
set n[0]=n[a]
endif
set p[a]=y
set n[a]=td
set n[y]=a
set p[td]=a
set v[a]=0
endif
set y=n[y]
exitwhen 0==g
set g=g-1
endloop
loop
set k=n[k]
set v[y]=v[y]+v[k]
set m=y
loop
exitwhen z>v[m]
set q=v[m]/z
set v[m]=v[m]-v[m]/z*z
if (e[n[m]]) then
if (0==n[0]) then
set i=i+1
set a=i
else
set a=n[0]
set n[0]=n[a]
endif
set p[a]=m
set n[a]=td
set n[m]=a
set p[td]=a
set v[a]=0
endif
set m=n[m]
set v[m]=v[m]+q
endloop
exitwhen e[n[k]]
if (e[n[y]]) then
if (0==n[0]) then
set i=i+1
set a=i
else
set a=n[0]
set n[0]=n[a]
endif
set p[a]=y
set n[a]=td
set n[y]=a
set p[td]=a
set v[a]=0
endif
set y=n[y]
endloop
return true
endmethod
method addBig takes BigInt k,integer g returns nothing
if (0<v[p[k]]) then
set td=this
set my=k
set dz=g
call TriggerEvaluate(y9)
endif
endmethod
private static integer array zs
private static method m2 takes nothing returns boolean
local integer q=td2
local integer m=dz
local integer a
local integer k=my3
loop
set q=q-1
if (e[n[m]]) then
if (0==n[0]) then
set i=i+1
set a=i
else
set a=n[0]
set n[0]=n[a]
endif
set p[a]=m
set n[a]=td
set n[m]=a
set p[td]=a
set v[a]=0
endif
set m=n[m]
set v[m]=v[m]+zs[q]*v[k]
exitwhen 0==q
endloop
return true
endmethod
private static method m1 takes nothing returns boolean
local integer y=0
local integer q=0
local integer a=td
local integer m=a
local integer w=a
local integer k=my
loop
set a=p[a]
exitwhen e[a]
set zs[y]=v[a]
set y=y+1
endloop
set n[p[a]]=n[0]
set n[0]=n[a]
set n[a]=a
set p[a]=a
loop
set k=n[k]
exitwhen e[k]
set td2=y
set w=n[w]
set dz=w
set my3=k
call TriggerEvaluate(x2)
endloop
set y=0
set a=td
set w=a
set q=a
set k=b[a].size
set m=a
loop
if (e[n[a]]) then
if (0==n[0]) then
set i=i+1
set m=i
else
set m=n[0]
set n[0]=n[m]
endif
set p[m]=a
set n[m]=w
set n[a]=m
set p[w]=m
set v[m]=0
endif
set a=n[a]
set y=y+v[a]
set v[a]=y-y/k*k
set y=y/k
exitwhen e[n[a]] and 0==y
endloop
return true
endmethod
method multiplyBig takes BigInt k returns nothing
if (0<v[p[k]]) then
set td=this
set my=k
call TriggerEvaluate(x1)
elseif (0==v[p[k]] and not e[p[this]]) then
set n[p[this]]=0
set n[0]=n[this]
set n[this]=this
set p[this]=this
endif
endmethod
static method create takes Base k returns thistype
local integer y
local integer z
if (0==n[0]) then
set i=i+1
set z=i
else
set z=n[0]
set n[0]=n[z]
endif
set e[z]=true
set b[z]=k
set n[z]=z
set p[z]=z
set v[z]=0
return z
endmethod
private static method a0 takes nothing returns boolean
local integer y=td
local integer a
local integer z=my3
local integer k=td2
loop
if (e[n[y]]) then
if (0==n[0]) then
set i=i+1
set a=i
else
set a=n[0]
set n[0]=n[a]
endif
set p[a]=y
set n[a]=td
set n[y]=a
set p[td]=a
set v[a]=0
endif
set y=n[y]
exitwhen 0==z
set z=z-1
endloop
set z=b[td].size
loop
set v[y]=v[y]+k
exitwhen z>v[y]
set k=v[y]/z
set v[y]=v[y]-k*z
if (e[n[y]]) then
if (0==n[0]) then
set i=i+1
set a=i
else
set a=n[0]
set n[0]=n[a]
endif
set p[a]=y
set n[a]=td
set n[y]=a
set p[td]=a
set v[a]=0
endif
set y=n[y]
endloop
return true
endmethod
method add takes integer k,integer g returns nothing
if (0<k) then
set td=this
set my3=g
set td2=k
call TriggerEvaluate(y0)
endif
endmethod
private static method ml takes nothing returns boolean
local integer y=td
local integer z=b[td].size
local integer a=0
local integer k=my
local integer q
loop
set y=n[y]
exitwhen e[y]
set v[y]=v[y]*k
endloop
set y=td
loop
set y=n[y]
exitwhen e[y]
set q=y
loop
exitwhen z>v[q]
if (e[n[q]]) then
if (0==n[0]) then
set i=i+1
set a=i
else
set a=n[0]
set n[0]=n[a]
endif
set p[a]=q
set n[a]=td
set n[q]=a
set p[td]=a
set v[a]=0
endif
set v[n[q]]=v[n[q]]+v[q]/z
set v[q]=v[q]-v[q]/z*z
endloop
endloop
return true
endmethod
method multiply takes integer k returns nothing
if (0<k) then
if (0<v[p[this]]) then
set td=this
set my=k
call TriggerEvaluate(x)
endif
elseif (0==k and not e[p[this]]) then
set n[p[this]]=n[0]
set n[0]=n[this]
set n[this]=this
set p[this]=this
endif
endmethod
method enq takes integer k returns nothing
local integer y=p[this]
local integer z
local integer a=b[this].size
loop
if (0==n[0]) then
set i=i+1
set z=i
else
set z=n[0]
set n[0]=n[z]
endif
set p[z]=y
set n[z]=n[y]
set n[y]=z
set p[n[z]]=z
set v[z]=k
set y=z
exitwhen a>v[y]
set k=v[y]/a
set v[y]=v[y]-k*a
endloop
endmethod
method deq takes nothing returns integer
local thistype z=p[this]
if (not e[z]) then
set p[this]=p[z]
set n[p[z]]=this
set n[z]=n[0]
set n[0]=z
endif
return v[z]
endmethod
method push takes integer k returns nothing
local integer y=this
local integer z
local integer a=b[this].size
loop
if (0==n[0]) then
set i=i+1
set z=i
else
set z=n[0]
set n[0]=n[z]
endif
set p[z]=y
set n[z]=n[y]
set n[y]=z
set p[n[z]]=z
set v[z]=k
set y=z
exitwhen a>v[y]
set k=v[y]/a
set v[y]=v[y]-k*a
endloop
endmethod
method pop takes nothing returns integer
local thistype z=n[this]
if (not e[z]) then
set n[this]=n[z]
set p[n[z]]=this
set n[z]=n[0]
set n[0]=z
endif
return v[z]
endmethod
method rr takes nothing returns nothing
local integer z
set z=p[this]
set n[z]=n[this]
set p[n[z]]=z
set p[this]=p[z]
set n[p[z]]=this
set p[z]=this
set n[this]=z
endmethod
method rl takes nothing returns nothing
local integer z
set z=n[this]
set p[z]=p[this]
set n[p[z]]=z
set n[this]=n[z]
set p[n[z]]=this
set n[z]=this
set p[this]=z
endmethod
private static method m0 takes nothing returns boolean
local integer z=0
local integer q=td
local integer u=b[q].size
local integer k=my
loop
set q=p[q]
exitwhen e[q]
set z=(z*u+v[q])
set z=z-z/k*k
endloop
set dz=z
return true
endmethod
method mod takes integer k returns integer
set td=this
set my=k
call TriggerEvaluate(y7)
return dz
endmethod
method destroy takes nothing returns nothing
set n[p[this]]=n[0]
set n[0]=this
set e[this]=false
endmethod
private static method tos takes nothing returns boolean
local string q=""
local integer y=td
local Base z=b[y]
loop
set y=n[y]
exitwhen e[y]
set q=z.char(v[y])+q
endloop
if (q=="") then
set yy=z.char(0)
else
set yy=q
endif
return true
endmethod
method toString takes nothing returns string
set td=this
call TriggerEvaluate(y6)
return yy
endmethod
method operator base= takes Base k returns nothing
if (b[this].size!=k.size and not e[n[this]]) then
set td=this
set td2=k
call TriggerEvaluate(j)
endif
set b[this]=k
endmethod
private static method ch takes nothing returns boolean
local integer q=td
local integer u
local integer k
if (0==n[0]) then
set i=i+1
set k=i
else
set k=n[0]
set n[0]=n[k]
endif
set e[k]=true
set u=p[q]
set p[q]=p[u]
set p[k]=u
set n[k]=u
set p[u]=k
set n[u]=k
set b[k]=td2
set v[k]=0
set my=Base(b[td]).size
set my3=0
set td=k
set td2=v[u]
set v[u]=0
loop
call TriggerEvaluate(y0)
exitwhen e[p[q]]
call TriggerEvaluate(x)
set u=p[q]
set p[q]=p[u]
set td2=v[u]
set n[u]=n[0]
set n[0]=u
endloop
set n[q]=n[k]
set p[q]=p[k]
set p[n[k]]=q
set n[p[k]]=q
set n[k]=n[0]
set n[0]=k
set e[k]=false
return true
endmethod
method toInt takes nothing returns integer
local integer k=0
local integer z=b[this].size
loop
set this=p[this]
exitwhen e[this]
set k=k*z
set k=k+v[this]
endloop
return k
endmethod
private static method div takes nothing returns boolean
local integer z=0
local integer a=td
local integer y=a
local integer h=b[a].size
local integer k=my
set y=p[y]
loop
set z=z*h+v[y]
exitwhen e[p[y]] or z>=k
set n[y]=n[0]
set n[0]=y
set y=p[y]
endloop
set p[a]=y
set n[y]=a
loop
set v[y]=z/k
set z=z-v[y]*k
set y=p[y]
exitwhen e[y]
set z=z*h+v[y]
endloop
set y=a
loop
set y=p[y]
exitwhen 0!=v[y] or e[y]
set n[y]=n[0]
set n[0]=y
endloop
set p[a]=y
set n[y]=a
set my=z
return true
endmethod
method divide takes integer k returns integer
if (0<k and 0<v[p[this]]) then
set td=this
set my=k
call TriggerEvaluate(x4)
else
return 0
endif
return my
endmethod
private static method s2 takes nothing returns boolean
local Base d=td
local string k=yy
local integer y
local integer z
local integer h=StringLength(k)
if (not d.isValid(k)) then
set td=0
return true
endif
if (0==n[0]) then
set i=i+1
set z=i
else
set z=n[0]
set n[0]=n[z]
endif
set e[z]=true
set b[z]=d
set n[z]=z
set p[z]=z
set v[z]=0
loop
set h=h-1
if (0==n[0]) then
set i=i+1
set y=i
else
set y=n[0]
set n[0]=n[y]
endif
set v[y]=d.ord(SubString(k,h,h+1))
set p[y]=p[z]
set n[y]=z
set n[p[z]]=y
set p[z]=y
exitwhen 0==h
endloop
set td=z
return true
endmethod
static method convertString takes string k,Base y returns thistype
set yy=k
set td=y
call TriggerEvaluate(x5)
return td
endmethod
method operator base takes nothing returns Base
return b[this]
endmethod
implement IntMod
endstruct
endlibrary
library Base uses Ascii,Table
globals
private Table gt=0
private integer array n
private string array b
private Table array t
private integer c=0
private integer array s
endglobals
private module Init
private static method onInit takes nothing returns nothing
set gt=Table.create()
endmethod
endmodule
struct Base extends array
static method operator [] takes string base returns thistype
local integer value
local string char
local integer i=0
local integer v
local integer dv
set value = StringHash(base)
set i = gt[value]
set v = i
if (0!=i) then
loop
exitwhen 0==i or base==b[i]
set i=n[i]
endloop
endif
if (0==i) then
set c=c+1
set i=c
set dv=v
set t[i]=Table.create()
set b[i]=base
set value=StringLength(base)
set s[i]=value
loop
set value=value-1
set char=SubString(base,value,value+1)
set v=Char2Ascii(char)
set t[i][v]=value
set t[i].string[-value]=char
exitwhen 0==value
endloop
if (0==dv) then
set gt[value]=i
else
set n[i]=n[dv]
set n[dv]=i
endif
endif
return i
endmethod
method convertToString takes integer i returns string
local integer k=s[this]
local string n=""
loop
exitwhen i<k
set n=t[this].string[-(i-i/k*k)]+n
set i=i/k
endloop
return t[this].string[-i]+n
endmethod
method convertToInteger takes string i returns integer
local integer n=0
local integer p=StringLength(i)
local integer l=0
local integer k=s[this]
local string char
loop
exitwhen 0==p
set p=p-1
set l=l+1
set char=SubString(i,l-1,l)
set n=n+t[this][Char2Ascii(char)]*R2I(Pow(k,p))
endloop
return n
endmethod
method ord takes string c returns integer
return t[this][Char2Ascii(c)]
endmethod
method char takes integer i returns string
return t[this].string[-i]
endmethod
method isValid takes string s returns boolean
local integer i=StringLength(s)
local string c
if (0<i) then
loop
set c=SubString(s,i-1,i)
if (not t[this].has(Char2Ascii(c))) then
return false
endif
set i=i-1
exitwhen 0==i
endloop
else
return false
endif
return true
endmethod
method operator size takes nothing returns integer
return s[this]
endmethod
implement Init
endstruct
endlibrary
library Scrambler uses BigInt
//! runtextmacro SCRAMBLER_SETTINGS()
globals
private integer array ss
private boolean array se
private BigInt array d
private integer i
private integer dc
private integer k
private integer s1
private integer s2
private integer s3
private integer pid
private trigger mt=CreateTrigger()
private trigger dt=CreateTrigger()
private trigger st=CreateTrigger()
private trigger ut=CreateTrigger()
private BigInt bi
private Base array bs
private integer array so
private integer sc=0
endglobals
private function LNF takes BigInt int,boolean i0 returns nothing
set dc=0
if (i0) then
loop
set int=int.next
exitwhen int.end
set d[dc]=int
set dc=dc+1
endloop
else
loop
set int=int.next
exitwhen int.next.end
set d[dc]=int
set dc=dc + 1
endloop
set int=int.next
endif
endfunction
private function LNB takes BigInt int,boolean i0 returns nothing
set dc=0
if (not i0) then
set int=int.previous
endif
loop
set int=int.previous
exitwhen int.end
set d[dc]=int
set dc=dc+1
endloop
endfunction
private function FLP takes integer id,integer i2 returns nothing
loop
exitwhen 0==i2
set s1=dc
loop
exitwhen 0==s1
set s1=s1-1
if (se[k]) then
set k=ss[id]
else
set k=k+1
endif
endloop
set i2=i2-1
endloop
endfunction
function Scramble takes BigInt int,integer id,integer shuffles,Base bb,boolean i0 returns nothing
local Base b=int.base
set pid=id
set k=ss[id]
set i=shuffles
if (b!=bb) then
set int.base=bb
endif
call LNF(int,i0)
call TriggerEvaluate(st)
if (b!=bb) then
set int.base=b
endif
endfunction
function Unscramble takes BigInt int,integer id,integer shuffles,integer bb,boolean i0 returns nothing
local Base b=int.base
set i=shuffles
set pid=id
set k=ss[id]
if (b!=bb) then
set int.base=bb
endif
call LNB(int,i0)
call FLP(id,shuffles)
call TriggerEvaluate(ut)
if (b!=bb) then
set int.base=b
endif
endfunction
private function St takes nothing returns boolean
loop
exitwhen 0==i
set s1=dc
loop
exitwhen 0==s1
set s1=s1-1
set s2=s1-ss[k]
loop
exitwhen 0<=s2
set s2=dc+s2
endloop
set s3=d[s2].digit
set d[s2].digit=d[s1].digit
set d[s1].digit=s3
if (se[k]) then
set k=ss[pid]
else
set k=k+1
endif
endloop
set i=i-1
endloop
return false
endfunction
private function Ut takes nothing returns boolean
loop
exitwhen 0==i
set s1 = dc
loop
exitwhen 0==s1
set s1=s1-1
set k=k-1
if (0==ss[k]) then
set k=ss[pid+12]
endif
set s2=s1+ss[k]
loop
exitwhen s2<dc
set s2=s2-dc
endloop
set s3=d[s2].digit
set d[s2].digit=d[s1].digit
set d[s1].digit=s3
endloop
set i=i-1
endloop
return false
endfunction
private function Mt takes nothing returns boolean
local integer sh=0
set k=ss[pid]
loop
exitwhen sh==sc
set i=1
set bi.base=bs[so[sh]]
call LNF(bi,false)
call St()
set sh=sh+1
set k=ss[pid]
endloop
return false
endfunction
private function Dt takes nothing returns boolean
local integer sh=sc
set k=ss[pid]
loop
exitwhen 0==sh
set sh=sh-1
set i=1
set bi.base=bs[so[sh]]
call LNB(bi,false)
call FLP(pid,1)
call Ut()
set k=ss[pid]
endloop
return false
endfunction
function Shuffle takes BigInt int, integer id, integer h returns nothing
local Base b=int.base
set bi=int
set pid=id
loop
exitwhen 0==h
call TriggerEvaluate(mt)
set h=h-1
endloop
set int.base=b
endfunction
function Unshuffle takes BigInt int, integer id, integer h returns nothing
local Base b=int.base
set bi=int
set pid=id
loop
exitwhen 0==h
call TriggerEvaluate(dt)
set h=h-1
endloop
set int.base=b
endfunction
private module Init
private static method onInit takes nothing returns nothing
local integer is=11
local integer hh
local integer ks=25
local Base b8=Base["012345678"]
local BigInt bg
call TriggerAddCondition(mt,Condition(function Mt))
call TriggerAddCondition(dt,Condition(function Dt))
call TriggerAddCondition(st,Condition(function St))
call TriggerAddCondition(ut,Condition(function Ut))
set bs[2]=Base["01"]
set bs[3]=Base["012"]
set bs[5]=Base["01234"]
set bs[7]=Base["0123456"]
set bs[11]=Base["0123456789A"]
set sc=SetShuffleOrder()
loop
if (GetPlayerSlotState(Player(is))==PLAYER_SLOT_STATE_PLAYING and GetPlayerController(Player(is))==MAP_CONTROL_USER) then
set ss[is]=ks
set hh=StringHash(StringCase(GetPlayerName(Player(is))+SALT,false))
if (0>hh) then
set hh=-hh
endif
set bg=BigInt.create(b8)
call bg.add(hh,0)
set bg=bg.previous
loop
set ss[ks]=bg.digit+1
set bg=bg.previous
exitwhen bg.end
set ks=ks+1
endloop
set se[ks]=true
set ss[is+12]=ks
call bg.destroy()
set ks=ks+2
endif
exitwhen 0==is
set is=is-1
endloop
endmethod
endmodule
private struct Inits extends array
implement Init
endstruct
endlibrary
library Ascii
globals
private integer array i
private string array c
endglobals
function Char2Ascii takes string s returns integer
local integer a
if ("\\"==s) then
return 92
endif
set a=i[StringHash(s)/0x1F0748+0x3EA]
if (s!=c[a]) then
return a+32
endif
return a
endfunction
function Ascii2Char takes integer a returns string
return c[a]
endfunction
function A2S takes integer a returns string
local string s=""
loop
set s=c[a-a/256*256]+s
set a=a/256
exitwhen 0==a
endloop
return s
endfunction
function S2A takes string s returns integer
local integer a=0
local integer l=StringLength(s)
local integer j=0
local string m
local integer h
loop
exitwhen j==l
set m=SubString(s,j,j+1)
if ("\\"==m) then
set a=a*256+92
else
set h=i[StringHash(m)/0x1F0748+0x3EA]
if (m!=c[h]) then
set a=a*256+h+32
else
set a=a*256+h
endif
endif
set j=j+1
endloop
return a
endfunction
private module Init
private static method onInit takes nothing returns nothing
set i[931]=8
set i[1075]=9
set i[1586]=10
set i[1340]=12
set i[412]=13
set i[198]=32
set i[1979]=33
set i[1313]=34
set i[1003]=35
set i[1264]=36
set i[983]=37
set i[1277]=38
set i[306]=39
set i[904]=40
set i[934]=41
set i[917]=42
set i[1972]=43
set i[1380]=44
set i[1985]=45
set i[869]=46
set i[1906]=47
set i[883]=48
set i[1558]=49
set i[684]=50
set i[582]=51
set i[668]=52
set i[538]=53
set i[672]=54
set i[1173]=55
set i[71]=56
set i[277]=57
set i[89]=58
set i[1141]=59
set i[39]=60
set i[1171]=61
set i[51]=62
set i[305]=63
set i[0]=64
set i[222]=65
set i[178]=66
set i[236] =67
set i[184]=68
set i[1295]=69
set i[1390]=70
set i[1276]=71
set i[203]=72
set i[1314]=73
set i[209]=74
set i[1315]=75
set i[170]=76
set i[1357]=77
set i[1343]=78
set i[1397]=79
set i[1420]=80
set i[1419]=81
set i[1396]=82
set i[1374]=83
set i[1407]=84
set i[499]=85
set i[1465]=86
set i[736]=87
set i[289]=88
set i[986]=89
set i[38]=90
set i[1230]=91
set i[1636]=93
set i[1416]=94
set i[1917]=95
set i[217]=96
set i[833]=123
set i[1219]=124
set i[553]=125
set i[58]=126
set c[8]="\b"
set c[9]="\t"
set c[10]="\n"
set c[12]="\f"
set c[13]="\r"
set c[32]=" "
set c[33]="!"
set c[34]="\""
set c[35]="#"
set c[36]="$"
set c[37]="%"
set c[38]="&"
set c[39]="'"
set c[40]="("
set c[41]=")"
set c[42]="*"
set c[43]="+"
set c[44]=","
set c[45]="-"
set c[46]="."
set c[47]="/"
set c[48]="0"
set c[49]="1"
set c[50]="2"
set c[51]="3"
set c[52]="4"
set c[53]="5"
set c[54]="6"
set c[55]="7"
set c[56]="8"
set c[57]="9"
set c[58]=":"
set c[59]=";"
set c[60]="<"
set c[61]="="
set c[62]=">"
set c[63]="?"
set c[64]="@"
set c[65]="A"
set c[66]="B"
set c[67]="C"
set c[68]="D"
set c[69]="E"
set c[70]="F"
set c[71]="G"
set c[72]="H"
set c[73]="I"
set c[74]="J"
set c[75]="K"
set c[76]="L"
set c[77]="M"
set c[78]="N"
set c[79]="O"
set c[80]="P"
set c[81]="Q"
set c[82]="R"
set c[83]="S"
set c[84]="T"
set c[85]="U"
set c[86]="V"
set c[87]="W"
set c[88]="X"
set c[89]="Y"
set c[90]="Z"
set c[92]="\\"
set c[97]="a"
set c[98]="b"
set c[99]="c"
set c[100]="d"
set c[101]="e"
set c[102]="f"
set c[103]="g"
set c[104]="h"
set c[105]="i"
set c[106]="j"
set c[107]="k"
set c[108]="l"
set c[109]="m"
set c[110]="n"
set c[111]="o"
set c[112]="p"
set c[113]="q"
set c[114]="r"
set c[115]="s"
set c[116]="t"
set c[117]="u"
set c[118]="v"
set c[119]="w"
set c[120]="x"
set c[121]="y"
set c[122]="z"
set c[91]="["
set c[93]="]"
set c[94]="^"
set c[95]="_"
set c[96]="`"
set c[123]="{"
set c[124]="|"
set c[125]="}"
set c[126]="~"
endmethod
endmodule
private struct Inits extends array
implement Init
endstruct
endlibrary
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
library Table
globals
private hashtable ht=InitHashtable()
private integer q=2
private integer w=0
endglobals
private struct dex extends array
static method operator size takes nothing returns Table
return 1
endmethod
static method operator list takes nothing returns Table
return 2
endmethod
endstruct
private struct strings extends array
method operator [] takes integer key returns string
return LoadStr(ht,this,key)
endmethod
method operator []= takes integer key,string value returns nothing
call SaveStr(ht,this,key,value)
endmethod
method has takes integer key returns boolean
return HaveSavedString(ht,this,key)
endmethod
method remove takes integer key returns nothing
call RemoveSavedString(ht,this,key)
endmethod
endstruct
private module stringm
method operator string takes nothing returns strings
return this
endmethod
endmodule
struct Table extends array
implement stringm
method operator [] takes integer key returns Table
return LoadInteger(ht,this,key)
endmethod
method operator []= takes integer key,Table a returns nothing
call SaveInteger(ht,this,key,a)
endmethod
method has takes integer key returns boolean
return HaveSavedInteger(ht,this,key)
endmethod
method remove takes integer key returns nothing
call RemoveSavedInteger(ht,this,key)
endmethod
method flush takes nothing returns nothing
call FlushChildHashtable(ht,this)
endmethod
static method create takes nothing returns Table
local Table this=dex.list[0]
if 0==this then
set q=q+1
set this=q
else
set dex.list[0]=dex.list[this]
call dex.list.remove(this)
endif
return this
endmethod
method destroy takes nothing returns nothing
call this.flush()
set dex.list[this]=dex.list[0]
set dex.list[0]=this
endmethod
endstruct
endlibrary
Attachments
Last edited: