- Joined
- Feb 20, 2020
- Messages
- 219
My save/load trigger sometimes doesnt load everything properly, sometimes it does... the only thing it messes up is the tamer, the monsters, the IV of the monsters, the items of the monsters, levels are everything okay... just the Tamer is getting mixed up...
Type Save
Type Load
Load Event
Save Actions
Load Actions
THIS are the libraries used for the codeless save/load:
Type Save
-
Type 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
-
Player - Player 5 (Yellow) types a chat message containing -save as An exact match
-
Player - Player 6 (Orange) types a chat message containing -save as An exact match
-
-
Conditions
-
Player_Trainer[(Player number of (Triggering player))] Not equal to No unit
-
-
Actions
-
Set VariableSet SaveLoadEvent_Player = (Triggering player)
-
Set VariableSet SaveCount = -1
-
Custom script: call DisplayTextToPlayer(GetTriggerPlayer(), 0, 0, "Saved " + User[udg_SaveLoadEvent_Player].nameColored)
-
-------- --------
-
-------- Run the trigger that contains everything you want to save: --------
-
Set VariableSet PNSAVE = (Player number of SaveLoadEvent_Player)
-
Trigger - Run Save Actions <gen> (ignoring conditions)
-
-------- --------
-
-------- Save to disk --------
-
Custom script: set udg_SaveTempInt = Savecode.create()
-
For each (Integer A) from 0 to SaveCount, do (Actions)
-
Loop - Actions
-
Custom script: call Savecode(udg_SaveTempInt).Encode(udg_SaveValue[bj_forLoopAIndex], udg_SaveMaxValue[bj_forLoopAIndex])
-
-
-
Set VariableSet SaveTempString = <Empty String>
-
Custom script: set udg_SaveTempString = Savecode(udg_SaveTempInt).Save(udg_SaveLoadEvent_Player, 1)
-
Custom script: call SaveFile.create(udg_SaveLoadEvent_Player, "Save", 1, udg_SaveTempString)
-
-
-
Type Load
-
Events
-
Player - Player 1 (Red) types a chat message containing -load as An exact match
-
Player - Player 2 (Blue) types a chat message containing -load as An exact match
-
Player - Player 3 (Teal) types a chat message containing -load as An exact match
-
Player - Player 4 (Purple) types a chat message containing -load as An exact match
-
Player - Player 5 (Yellow) types a chat message containing -load as An exact match
-
Player - Player 6 (Orange) types a chat message containing -load as An exact match
-
-
Conditions
-
CantLoad[(Player number of (Triggering player))] Equal to False
-
-
Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
Loading Equal to False
-
-
Then - Actions
-
Set VariableSet SaveLoadEvent_Player = (Triggering player)
-
Set VariableSet PNLOAD = (Player number of SaveLoadEvent_Player)
-
-------- ------------------- --------
-
-------- This runs the Event used in Load Event and tells it to load Save Slot 1 --------
-
Custom script: call LoadSaveSlot(udg_SaveLoadEvent_Player, 1)
-
-
Else - Actions
-
Set VariableSet PGroup = (Player group((Triggering player)))
-
Game - Display to PGroup for 10.00 seconds the text: (|cff808000Wait until |r + ((Name of SaveLoadEvent_Player) + |cff808000finishes loading!))
-
Custom script: call DestroyForce(udg_PGroup)
-
-
-
-
-
Load Event
-
Events
-
Game - SaveLoadEvent becomes Equal to 1.00
-
-
Conditions
-
Actions
-
-------- This runs when you type -load --------
-
-------- ------------------- --------
-
-------- Validate --------
-
-------- ------------------- --------
-
Set VariableSet SaveCount = 0
-
Custom script: set udg_SaveTempInt = integer(Savecode.create())
-
Custom script: if not (Savecode(udg_SaveTempInt).Load(udg_SaveLoadEvent_Player, udg_SaveLoadEvent_Code, 1)) then
-
Game - Display to (Player group(SaveLoadEvent_Player)) the text: Invalid load code (...
-
Set VariableSet Loading = False
-
Skip remaining actions
-
Custom script: endif
-
Custom script: call DisplayTextToPlayer(GetLocalPlayer(), 0, 0, "Loaded " + User[udg_SaveLoadEvent_Player].nameColored)
-
-------- --------
-
Set VariableSet Loading = True
-
-------- --------
-
Unit Group - Remove all units from Player_MonsterGroup[PNLOAD].
-
-------- --------
-
-------- I remove all of the existing Heroes since we're about to load new ones --------
-
Set VariableSet TempGroup = (Units owned by SaveLoadEvent_Player matching (((Matching unit) is A Hero) Equal to True).)
-
Unit Group - Pick every unit in TempGroup and do (Actions)
-
Loop - Actions
-
Unit - Remove (Picked unit) from the game
-
-
-
Custom script: call DestroyGroup(udg_TempGroup)
-
-------- --------
-
-------- Create New Tamer --------
-
Set VariableSet TempPoint = (Center of begin <gen>)
-
Unit - Create 1 Tamer for SaveLoadEvent_Player at TempPoint facing Default building facing degrees
-
Camera - Pan camera for SaveLoadEvent_Player to TempPoint over 0.00 seconds
-
Custom script: call RemoveLocation (udg_TempPoint)
-
Set VariableSet Player_Trainer[PNLOAD] = (Last created unit)
-
-------- --------
-
-------- Reset the player's Monster Hashtable --------
-
For each (Integer Monster_Loop) from 1 to 10, do (Actions)
-
Loop - Actions
-
Hashtable - Save Handle OfPlayer_Trainer[PNLOAD] as Monster_Loop of PNLOAD in Monster_Hashtable.
-
Hashtable - Save Handle OfPlayer_Trainer[PNLOAD] as (20 + Monster_Loop) of PNLOAD in Monster_Hashtable.
-
-
-
-------- --------
-
Set VariableSet MonsterOutsideBall[PNLOAD] = 0
-
-------- --------
-
-------- Players can only Load once --------
-
Set VariableSet CantLoad[PNLOAD] = True
-
-------- --------
-
-------- Run the trigger that contains everything you want to load: --------
-
Trigger - Run Load Actions <gen> (ignoring conditions)
-
-------- --------
-
Custom script: call Savecode(udg_SaveTempInt).destroy()
-
-
-
Save Actions
-
Events
-
Conditions
-
Actions
-
Set VariableSet TempPlayer = SaveLoadEvent_Player
-
Set VariableSet TempGroup = (Units owned by TempPlayer.)
-
Unit Group - Pick every unit in TempGroup and do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Unit-type of (Picked unit)) Equal to Tamer
-
-
Then - Actions
-
Set VariableSet Player_Trainer[PNSAVE] = (Picked unit)
-
-
Else - Actions
-
-
-------- --------
-
-------- Move Chosen Monster --------
-
-
-
Custom script: call DestroyGroup (udg_TempGroup)
-
-------- Put everything that you want to Save here! --------
-
-------- THE ORDER IS IMPORTANT! If you move these Actions around it will break the Load trigger. --------
-
-------- --------
-
-------- Set this variable first --------
-
Set VariableSet TotalSaveMonsters = (Number of units in Player_MonsterGroup[PNSAVE])
-
-------- --------
-
-------- Save Trainer Level --------
-
Set VariableSet Integer = (Hero level of Player_Trainer[PNSAVE])
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = Integer
-
Set VariableSet SaveMaxValue[SaveCount] = 99
-
-------- --------
-
-------- Save Trainer Item Charges --------
-
Set VariableSet ItemCount = (Number of items carried by Player_Trainer[PNSAVE])
-
For each (Integer A) from 1 to ItemCount, do (Actions)
-
Loop - Actions
-
-------- Set Integer = The value that you want to save --------
-
Set VariableSet Integer = (Charges remaining in (Item carried by Player_Trainer[PNSAVE] in slot (Integer A)))
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = Integer
-
Set VariableSet SaveMaxValue[SaveCount] = 10
-
-
-
-------- --------
-
-------- Save Trainer Items --------
-
For each (Integer A) from 1 to ItemCount, do (Actions)
-
Loop - Actions
-
For each (Integer B) from 1 to Setup_Total_ItemTypes, do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Item-type of (Item carried by Player_Trainer[PNSAVE] in slot (Integer A))) Equal to Setup_ItemType[(Integer B)]
-
-
Then - Actions
-
-------- Set Integer = The value that you want to save --------
-
Set VariableSet Integer = (Integer B)
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = Integer
-
Set VariableSet SaveMaxValue[SaveCount] = Setup_Total_ItemTypes
-
-
Else - Actions
-
-
-
-
-
-
-------- --------
-
-------- Save ItemCount of Trainer --------
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = ItemCount
-
Set VariableSet SaveMaxValue[SaveCount] = 6
-
-------- --------
-
-------- Save Gold --------
-
Set VariableSet Integer = (SaveLoadEvent_Player Current gold)
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = Integer
-
Set VariableSet SaveMaxValue[SaveCount] = 9999
-
-------- --------
-
-------- Save Lumber --------
-
Set VariableSet Integer = (SaveLoadEvent_Player Current lumber)
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = Integer
-
Set VariableSet SaveMaxValue[SaveCount] = 9999
-
-------- --------
-
-------- Save Monster Items --------
-
For each (Integer Monster_Loop) from 1 to TotalSaveMonsters, do (Actions)
-
Loop - Actions
-
Set VariableSet TempUnit = (Load Monster_Loop of PNSAVE in Monster_Hashtable.)
-
-------- --------
-
Set VariableSet ItemCount = (Number of items carried by TempUnit)
-
-------- --------
-
For each (Integer A) from 1 to ItemCount, do (Actions)
-
Loop - Actions
-
For each (Integer B) from 1 to Setup_Total_ItemTypes, do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Item-type of (Item carried by TempUnit in slot (Integer A))) Equal to Setup_ItemType[(Integer B)]
-
-
Then - Actions
-
-------- Set Integer = The value that you want to save --------
-
Set VariableSet Integer = (Integer B)
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = Integer
-
Set VariableSet SaveMaxValue[SaveCount] = Setup_Total_ItemTypes
-
-
Else - Actions
-
-
-
-
-
-
-------- --------
-
-------- Save Monster ItemCount --------
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = ItemCount
-
Set VariableSet SaveMaxValue[SaveCount] = 1
-
-
-
-------- --------
-
-------- Save Monster Levels --------
-
For each (Integer Monster_Loop) from 1 to TotalSaveMonsters, do (Actions)
-
Loop - Actions
-
Set VariableSet TempUnit = (Load Monster_Loop of PNSAVE in Monster_Hashtable.)
-
-------- --------
-
Set VariableSet Integer = (Hero level of TempUnit)
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = Integer
-
Set VariableSet SaveMaxValue[SaveCount] = 99
-
-
-
-------- --------
-
-------- Save Hidden Abilities --------
-
For each (Integer Monster_Loop) from 1 to TotalSaveMonsters, do (Actions)
-
Loop - Actions
-
Set VariableSet TempUnit = (Load Monster_Loop of PNSAVE in Monster_Hashtable.)
-
-------- --------
-
For each (Integer A) from 1 to Setup_Total_HiddenAbilities, do (Actions)
-
Loop - Actions
-
Set VariableSet Integer = (Level of Setup_HiddenAbilities[(Integer A)] for TempUnit)
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = Integer
-
Set VariableSet SaveMaxValue[SaveCount] = 15
-
-
-
-
-
-------- --------
-
-------- Save Monster Unit-Types --------
-
For each (Integer Monster_Loop) from 1 to TotalSaveMonsters, do (Actions)
-
Loop - Actions
-
For each (Integer A) from 1 to Setup_Total_UnitTypes, do (Actions)
-
Loop - Actions
-
Set VariableSet TempUnit = (Load Monster_Loop of PNSAVE in Monster_Hashtable.)
-
-------- --------
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Unit-type of TempUnit) Equal to Setup_UnitType[(Integer A)]
-
-
Then - Actions
-
-------- Set Integer = The value that you want to save --------
-
Set VariableSet Integer = (Integer A)
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = Integer
-
Set VariableSet SaveMaxValue[SaveCount] = Setup_Total_UnitTypes
-
-
Else - Actions
-
-
-
-
-
-
-------- --------
-
-------- Save Total Monsters --------
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveValue[SaveCount] = TotalSaveMonsters
-
Set VariableSet SaveMaxValue[SaveCount] = 9
-
-
-
Load Actions
-
Events
-
Conditions
-
Actions
-
Item - Pick every item in (Playable map area) and do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Owner of (Picked item)) Equal to SaveLoadEvent_Player
-
-
Then - Actions
-
Item - Remove (Picked item)
-
-
Else - Actions
-
-
-
-
-------- Put everything that you want to Load here! --------
-
-------- You must LOAD in the REVERSE order of how you saved --------
-
-------- --------
-
-------- Load Total Monsters --------
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = 9
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet TotalSaveMonsters = SaveValue[SaveCount]
-
-------- --------
-
-------- Load Monsters first since we saved them last (plus they need to exist before we can give them Items/Exp/etc...) --------
-
Set VariableSet ReverseLoop = TotalSaveMonsters
-
For each (Integer A) from 1 to TotalSaveMonsters, do (Actions)
-
Loop - Actions
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = Setup_Total_UnitTypes
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet Integer = SaveValue[SaveCount]
-
-------- --------
-
Set VariableSet Load_Monster_Type[ReverseLoop] = Integer
-
-------- --------
-
Set VariableSet ReverseLoop = (ReverseLoop - 1)
-
-
-
-------- --------
-
-------- Create the monsters (reverse the order) --------
-
Set VariableSet ReverseLoop = TotalSaveMonsters
-
For each (Integer A) from 1 to TotalSaveMonsters, do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Integer A) Less than or equal to 6
-
-
Then - Actions
-
Set VariableSet TempPoint = (Center of Player_Region[PNLOAD])
-
Unit - Create 1 Setup_UnitType[Load_Monster_Type[(Integer A)]] for SaveLoadEvent_Player at TempPoint facing Default building facing degrees
-
Custom script: call RemoveLocation(udg_TempPoint)
-
-
Else - Actions
-
Set VariableSet TempPoint = (Center of Player_RegionPC[PNLOAD])
-
Unit - Create 1 Setup_UnitType[Load_Monster_Type[(Integer A)]] for SaveLoadEvent_Player at TempPoint facing Default building facing degrees
-
Custom script: call RemoveLocation(udg_TempPoint)
-
-
-
-------- --------
-
-------- --------
-
Set VariableSet Temp_Heroes[ReverseLoop] = (Last created unit)
-
-------- --------
-
Set VariableSet ChosenMonster = (Last created unit)
-
Trigger - Run Add Monster to List <gen> (ignoring conditions)
-
-------- --------
-
Set VariableSet ReverseLoop = (ReverseLoop - 1)
-
-
-
-------- --------
-
-------- Load Monster Hidden Abilities --------
-
For each (Integer A) from 1 to TotalSaveMonsters, do (Actions)
-
Loop - Actions
-
Set VariableSet ReverseLoop = Setup_Total_HiddenAbilities
-
For each (Integer B) from 1 to Setup_Total_HiddenAbilities, do (Actions)
-
Loop - Actions
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = 15
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet Integer = SaveValue[SaveCount]
-
Unit - Add Setup_HiddenAbilities[ReverseLoop] to Temp_Heroes[(Integer A)]
-
Unit - Set level of Setup_HiddenAbilities[ReverseLoop] for Temp_Heroes[(Integer A)] to Integer
-
-------- --------
-
Set VariableSet ReverseLoop = (ReverseLoop - 1)
-
-
-
-
-
-------- --------
-
-------- Load Monster Levels --------
-
For each (Integer A) from 1 to TotalSaveMonsters, do (Actions)
-
Loop - Actions
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = 99
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet Integer = SaveValue[SaveCount]
-
Hero - Set Temp_Heroes[(Integer A)] Hero-level to Integer, Hide level-up graphics
-
-
-
-------- --------
-
-------- Load Monster Items --------
-
For each (Integer A) from 1 to TotalSaveMonsters, do (Actions)
-
Loop - Actions
-
-------- Load ItemCount for the Monster then load it's Items --------
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = 1
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet ItemCount = SaveValue[SaveCount]
-
-------- --------
-
For each (Integer B) from 1 to ItemCount, do (Actions)
-
Loop - Actions
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = Setup_Total_ItemTypes
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet Integer = SaveValue[SaveCount]
-
Hero - Create Setup_ItemType[Integer] and give it to Temp_Heroes[(Integer A)]
-
Item - Change ownership of (Last created item) to SaveLoadEvent_Player and Change color
-
-
-
-
-
-------- --------
-
-------- Load Lumber --------
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = 9999
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet Integer = SaveValue[SaveCount]
-
Player - Set SaveLoadEvent_Player.Current lumber to Integer
-
-------- --------
-
-------- Load Gold --------
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = 9999
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet Integer = SaveValue[SaveCount]
-
Player - Set SaveLoadEvent_Player.Current gold to Integer
-
-------- --------
-
-------- Load Trainer Item Count --------
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = 6
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet ItemCount = SaveValue[SaveCount]
-
-------- --------
-
-------- Load Trainer Items --------
-
For each (Integer A) from 1 to ItemCount, do (Actions)
-
Loop - Actions
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = Setup_Total_ItemTypes
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet Integer = SaveValue[SaveCount]
-
-------- --------
-
-------- --------
-
Hero - Create Setup_ItemType[Integer] and give it to Player_Trainer[PNLOAD]
-
Item - Change ownership of (Last created item) to SaveLoadEvent_Player and Change color
-
-
-
-------- --------
-
-------- Load Trainer Item Charges --------
-
For each (Integer A) from 1 to ItemCount, do (Actions)
-
Loop - Actions
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = 10
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet Integer = SaveValue[SaveCount]
-
-------- --------
-
-------- --------
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
Integer Greater than 0
-
-
Then - Actions
-
Item - Set charges remaining in (Item carried by Player_Trainer[PNLOAD] in slot (Integer A)) to Integer
-
-
Else - Actions
-
-
-
-
-------- --------
-
-------- Load Trainer Level --------
-
Set VariableSet SaveCount = (SaveCount + 1)
-
Set VariableSet SaveMaxValue[SaveCount] = 99
-
Custom script: call SaveHelper.GUILoadNext()
-
Set VariableSet Integer = SaveValue[SaveCount]
-
-------- --------
-
-------- --------
-
Hero - Set Player_Trainer[PNLOAD] Hero-level to Integer, Hide level-up graphics
-
-------- --------
-
-------- This makes sure that the Trainer's Manual is in Slot 1 --------
-
Set VariableSet TempUnit = Player_Trainer[PNLOAD]
-
For each (Integer A) from 2 to 6, do (Actions)
-
Loop - Actions
-
If (All Conditions are True) then do (Then Actions) else do (Else Actions)
-
If - Conditions
-
(Item-class of (Item carried by TempUnit in slot (Integer A))) Equal to Campaign
-
-
Then - Actions
-
Item - Make (Item carried by TempUnit in slot (Integer A)) Droppable
-
Unit - Order TempUnit to move (Item carried by TempUnit in slot (Integer A)) to inventory slot 1.
-
Item - Make (Item carried by TempUnit in slot 1) Undroppable
-
-
Else - Actions
-
-
-
-
-------- --------
-
Set VariableSet MonsterOutsideBall[PNLOAD] = 0
-
-------- --------
-
Set VariableSet Loading = False
-
Set VariableSet ProfessorQuest[PNLOAD] = finished
-
Set VariableSet HuntQuest[PNLOAD] = notstarted
-
Set VariableSet HuntQuest2[PNLOAD] = notstarted
-
Set VariableSet HuntQuest3[PNLOAD] = notstarted
-
Set VariableSet HuntQuest4[PNLOAD] = notstarted
-
Set VariableSet HuntQuest5[PNLOAD] = notstarted
-
Set VariableSet HuntQuest6[PNLOAD] = notstarted
-
Set VariableSet HuntQuest7[PNLOAD] = notstarted
-
Set VariableSet HuntQuest8[PNLOAD] = notstarted
-
Set VariableSet HuntQuest9[PNLOAD] = notstarted
-
Set VariableSet HuntQuest10[PNLOAD] = notstarted
-
Set VariableSet InAGym[PNLOAD] = False
-
Set VariableSet CaptainQuestDelivered[PNLOAD] = False
-
Set VariableSet CaptainQuestDelivered_1[PNLOAD] = False
-
Set VariableSet CaptainQuestDelivered_2[PNLOAD] = False
-
Set VariableSet CaptainQuestDelivered_3[PNLOAD] = False
-
Set VariableSet CaptainQuestDelivered_4[PNLOAD] = False
-
-
THIS are the libraries used for the codeless save/load:
JASS:
library SaveHelperLib initializer Init requires SyncHelper, PlayerUtils, SaveFile
// Uses GUI variables from the "Save Init" trigger. You can modify these functions to use your own variables.
private keyword SaveHelperInit
struct SaveHelper extends array
static method IsUserLoading takes User user returns boolean
return udg_SavePlayerLoading[user.id]
endmethod
static method SetUserLoading takes User user, boolean flag returns nothing
set udg_SavePlayerLoading[user.id] = flag
endmethod
static method SetSaveSlot takes User user, integer slot returns nothing
set udg_SaveCurrentSlot[user.id] = slot
endmethod
static method GetMapName takes nothing returns string
return udg_MapName
endmethod
static method GUILoadNext takes nothing returns nothing
set udg_SaveValue[udg_SaveCount] = Savecode(udg_SaveTempInt).Decode(udg_SaveMaxValue[udg_SaveCount])
endmethod
endstruct
private function LoadSaveSlot_OnLoad takes nothing returns nothing
local player p = GetTriggerPlayer()
local string prefix = BlzGetTriggerSyncPrefix()
local string data = BlzGetTriggerSyncData()
local User user = User[p]
call SaveHelper.SetUserLoading(user, false)
set udg_SaveLoadEvent_Code = data
set udg_SaveLoadEvent_Player = p
set udg_SaveLoadEvent = 1.
set udg_SaveLoadEvent = -1
endfunction
function LoadSaveSlot takes player p, integer slot returns nothing
local SaveFile savefile = SaveFile(slot)
local string s
local User user = User[p]
if (SaveHelper.IsUserLoading(user)) then
call DisplayTextToPlayer(p, 0, 0, "Please wait while your character synchronizes.")
else
set s = savefile.getData()
if s != null then
if (GetLocalPlayer() == p) then
call SyncString(s)
endif
call ClearTextMessages()
call DisplayTimedTextToPlayer(p, 0, 0, 15, "Synchronizing with other players...")
call SaveHelper.SetSaveSlot(user, slot)
else
call DisplayTimedTextToPlayer(p, 0, 0, 10, "The |cff00ff00Save|r file was not found.")
endif
endif
endfunction
private function Init takes nothing returns nothing
call OnSyncString(function LoadSaveSlot_OnLoad)
endfunction
endlibrary
JASS:
library SyncHelper
globals
public constant string SYNC_PREFIX = "S"
endglobals
private keyword INITS
private struct Sync extends array
static trigger Trigger = CreateTrigger()
implement INITS
endstruct
function SyncString takes string s returns boolean
return BlzSendSyncData(SYNC_PREFIX, s)
endfunction
function OnSyncString takes code func returns triggeraction
return TriggerAddAction(Sync.Trigger, func)
endfunction
function RemoveSyncString takes triggeraction t returns nothing
call TriggerRemoveAction(Sync.Trigger, t)
endfunction
private module INITS
private static method onInit takes nothing returns nothing
local integer i = 0
loop
call BlzTriggerRegisterPlayerSyncEvent(.Trigger, Player(i), SYNC_PREFIX, false)
set i = i + 1
exitwhen i == bj_MAX_PLAYER_SLOTS
endloop
endmethod
endmodule
endlibrary
JASS:
library SaveFile requires FileIO
private keyword SaveFileInit
struct SaveFile extends array
static constant string ManualPath = "Manual"
static constant string InvalidPath = "Unknown"
static constant integer MIN = 1
static constant integer MAX = 10
private File file
static method operator Folder takes nothing returns string
return udg_MapName
endmethod
static method getPath takes integer slot returns string
if (slot == 0) then
return .Folder + "\\SaveSlot_" + .InvalidPath + ".pld"
elseif (slot > 0 and (slot < .MIN or slot > .MAX)) then
return .Folder + "\\SaveSlot_" + .InvalidPath + ".pld"
elseif (slot < 0) then
return .Folder + "\\SaveSlot_" + .ManualPath + ".pld"
endif
return .Folder + "\\SaveSlot_" + I2S(slot) + ".pld"
endmethod
static method create takes player p, string title, integer slot, string data returns thistype
if (GetLocalPlayer() == p) then
call FileIO_Write(.getPath(slot), title + "\n" + data)
endif
return slot
endmethod
static method clear takes player p, integer slot returns thistype
if (GetLocalPlayer() == p) then
call FileIO_Write(.getPath(slot), "")
endif
return slot
endmethod
static method exists takes integer slot returns boolean // async
return FileIO_Read(.getPath(slot)) != null
endmethod
method getLines takes integer line, boolean includePrevious returns string // async
local string contents = FileIO_Read(.getPath(this))
local integer len = StringLength(contents)
local string char = null
local string buffer = ""
local integer curLine = 0
local integer i = 0
loop
exitwhen i > len
set char = SubString(contents, i, i + 1)
if (char == "\n") then
set curLine = curLine + 1
if (curLine > line) then
return buffer
endif
if (not includePrevious) then
set buffer = ""
endif
else
set buffer = buffer + char
endif
set i = i + 1
endloop
if (curLine == line) then
return buffer
endif
return null
endmethod
method getLine takes integer line returns string // async
return .getLines(line, false)
endmethod
method getTitle takes nothing returns string // async
return .getLines(0, false)
endmethod
method getData takes nothing returns string // async
return .getLines(1, false)
endmethod
implement SaveFileInit
endstruct
private module SaveFileInit
private static method onInit takes nothing returns nothing
//set thistype.Folder = udg_MapName
endmethod
endmodule
endlibrary
JASS:
library PlayerUtils
/**************************************************************
*
* v1.2.9 by TriggerHappy
*
[LIST]
[*]This library provides a struct which caches data about players
[*]as well as provides functionality for manipulating player colors.
[/LIST]
*
[LIST]
[*]Constants
[*]------------------
[/LIST]
*
* force FORCE_PLAYING - Player group of everyone who is playing.
*
[LIST]
[*]Struct API
[*]-------------------
[*]struct User
[/LIST]
*
[LIST]
[*]static method fromIndex takes integer i returns User
[*]static method fromLocal takes nothing returns User
[*]static method fromPlaying takes integer id returns User
[/LIST]
*
[LIST]
[*]static method operator [] takes integer id returns User
[*]static method operator count takes nothing returns integer
[/LIST]
*
[LIST]
[*]method operator name takes nothing returns string
[*]method operator name= takes string name returns nothing
[*]method operator color takes nothing returns playercolor
[*]method operator color= takes playercolor c returns nothing
[*]method operator defaultColor takes nothing returns playercolor
[*]method operator hex takes nothing returns string
[*]method operator nameColored takes nothing returns string
[/LIST]
*
[LIST]
[*]method toPlayer takes nothing returns player
[*]method colorUnits takes playercolor c returns nothing
[/LIST]
*
[LIST]
[*]readonly string originalName
[*]readonly boolean isPlaying
[*]readonly static player Local
[*]readonly static integer LocalId
[*]readonly static integer AmountPlaying
[*]readonly static playercolor array Color
[*]readonly static player array PlayingPlayer
[/LIST]
*
**************************************************************/
globals
// automatically change unit colors when changing player color
private constant boolean AUTO_COLOR_UNITS = true
// use an array for name / color lookups (instead of function calls)
private constant boolean ARRAY_LOOKUP = false
// this only applies if ARRAY_LOOKUP is true
private constant boolean HOOK_SAFETY = false // disable for speed, but only use the struct to change name/color safely
constant force FORCE_PLAYING = CreateForce()
private string array Name
private string array Hex
private string array OriginalHex
private playercolor array CurrentColor
endglobals
private keyword PlayerUtilsInit
struct User extends array
static constant integer NULL = bj_MAX_PLAYER_SLOTS
readonly player handle
readonly integer id
readonly thistype next
readonly thistype prev
readonly string originalName
readonly boolean isPlaying
readonly static thistype first
readonly static thistype last
readonly static player Local
readonly static integer LocalId
readonly static integer AmountPlaying = 0
readonly static playercolor array Color
static if not (LIBRARY_GroupUtils) then
readonly static group ENUM_GROUP = CreateGroup()
endif
private static thistype array PlayingPlayer
private static integer array PlayingPlayerIndex
// similar to Player(#)
static method fromIndex takes integer i returns thistype
return thistype(i)
endmethod
// similar to GetLocalPlayer
static method fromLocal takes nothing returns thistype
return thistype(thistype.LocalId)
endmethod
// access active players array
static method fromPlaying takes integer index returns thistype
return PlayingPlayer[index]
endmethod
static method operator [] takes player p returns thistype
return thistype(GetPlayerId(p))
endmethod
method toPlayer takes nothing returns player
return this.handle
endmethod
method operator name takes nothing returns string
static if (ARRAY_LOOKUP) then
return Name[this]
else
return GetPlayerName(this.handle)
endif
endmethod
method operator name= takes string newName returns nothing
call SetPlayerName(this.handle, newName)
static if (ARRAY_LOOKUP) then
static if not (HOOK_SAFETY) then
set Name[this] = newName
endif
endif
endmethod
method operator color takes nothing returns playercolor
static if (ARRAY_LOOKUP) then
return CurrentColor[this]
else
return GetPlayerColor(this.handle)
endif
endmethod
method operator hex takes nothing returns string
return OriginalHex[GetHandleId(this.color)]
endmethod
method operator color= takes playercolor c returns nothing
call SetPlayerColor(this.handle, c)
static if (ARRAY_LOOKUP) then
set CurrentColor[this] = c
static if not (HOOK_SAFETY) then
static if (AUTO_COLOR_UNITS) then
call this.colorUnits(color)
endif
endif
endif
endmethod
method operator defaultColor takes nothing returns playercolor
return Color[this]
endmethod
method operator nameColored takes nothing returns string
return hex + this.name + "|r"
endmethod
method colorUnits takes playercolor c returns nothing
local unit u
call GroupEnumUnitsOfPlayer(ENUM_GROUP, this.handle, null)
loop
set u = FirstOfGroup(ENUM_GROUP)
exitwhen u == null
call SetUnitColor(u, c)
call GroupRemoveUnit(ENUM_GROUP, u)
endloop
endmethod
static method onLeave takes nothing returns boolean
local thistype p = thistype[GetTriggerPlayer()]
local integer i = .PlayingPlayerIndex[p.id]
// clean up
call ForceRemovePlayer(FORCE_PLAYING, p.toPlayer())
// recycle index
set .AmountPlaying = .AmountPlaying - 1
set .PlayingPlayerIndex[i] = .PlayingPlayerIndex[.AmountPlaying]
set .PlayingPlayer[i] = .PlayingPlayer[.AmountPlaying]
if (.AmountPlaying == 1) then
set p.prev.next = User.NULL
set p.next.prev = User.NULL
else
set p.prev.next = p.next
set p.next.prev = p.prev
endif
set .last = .PlayingPlayer[.AmountPlaying]
set p.isPlaying = false
return false
endmethod
implement PlayerUtilsInit
endstruct
private module PlayerUtilsInit
private static method onInit takes nothing returns nothing
local trigger t = CreateTrigger()
local integer i = 0
local thistype p
set thistype.Local = GetLocalPlayer()
set thistype.LocalId = GetPlayerId(thistype.Local)
set OriginalHex[0] = "|cffff0303"
set OriginalHex[1] = "|cff0042ff"
set OriginalHex[2] = "|cff1ce6b9"
set OriginalHex[3] = "|cff540081"
set OriginalHex[4] = "|cfffffc01"
set OriginalHex[5] = "|cfffe8a0e"
set OriginalHex[6] = "|cff20c000"
set OriginalHex[7] = "|cffe55bb0"
set OriginalHex[8] = "|cff959697"
set OriginalHex[9] = "|cff7ebff1"
set OriginalHex[10] = "|cff106246"
set OriginalHex[11] = "|cff4e2a04"
if (bj_MAX_PLAYERS > 12) then
set OriginalHex[12] = "|cff9B0000"
set OriginalHex[13] = "|cff0000C3"
set OriginalHex[14] = "|cff00EAFF"
set OriginalHex[15] = "|cffBE00FE"
set OriginalHex[16] = "|cffEBCD87"
set OriginalHex[17] = "|cffF8A48B"
set OriginalHex[18] = "|cffBFFF80"
set OriginalHex[19] = "|cffDCB9EB"
set OriginalHex[20] = "|cff282828"
set OriginalHex[21] = "|cffEBF0FF"
set OriginalHex[22] = "|cff00781E"
set OriginalHex[23] = "|cffA46F33"
endif
set thistype.first = User.NULL
loop
exitwhen i == bj_MAX_PLAYERS
set p = User(i)
set p.handle = Player(i)
set p.id = i
set thistype.Color[i] = GetPlayerColor(p.handle)
set CurrentColor[i] = thistype.Color[i]
if (GetPlayerController(p.handle) == MAP_CONTROL_USER and GetPlayerSlotState(p.handle) == PLAYER_SLOT_STATE_PLAYING) then
set .PlayingPlayer[AmountPlaying] = p
set .PlayingPlayerIndex[i] = .AmountPlaying
set .last = i
if (.first == User.NULL) then
set .first = i
set User(i).next = User.NULL
set User(i).prev = User.NULL
else
set User(i).prev = PlayingPlayer[AmountPlaying-1].id
set PlayingPlayer[AmountPlaying-1].next = User(i)
set User(i).next = User.NULL
endif
set p.isPlaying = true
call TriggerRegisterPlayerEvent(t, p.handle, EVENT_PLAYER_LEAVE)
call ForceAddPlayer(FORCE_PLAYING, p.handle)
set Hex[p] = OriginalHex[GetHandleId(thistype.Color[i])]
set .AmountPlaying = .AmountPlaying + 1
endif
set Name[p] = GetPlayerName(p.handle)
set p.originalName=Name[p]
set i = i + 1
endloop
call TriggerAddCondition(t, Filter(function thistype.onLeave))
endmethod
endmodule
//===========================================================================
static if (ARRAY_LOOKUP) then
static if (HOOK_SAFETY) then
private function SetPlayerNameHook takes player whichPlayer, string name returns nothing
set Name[GetPlayerId(whichPlayer)] = name
endfunction
private function SetPlayerColorHook takes player whichPlayer, playercolor color returns nothing
local User p = User[whichPlayer]
set Hex[p] = OriginalHex[GetHandleId(color)]
set CurrentColor[p] = color
static if (AUTO_COLOR_UNITS) then
call p.colorUnits(color)
endif
endfunction
hook SetPlayerName SetPlayerNameHook
hook SetPlayerColor SetPlayerColorHook
endif
endif
endlibrary
JASS:
library FileIO
/***************************************************************
*
[LIST]
[*]v1.1.0, by TriggerHappy
[*]¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
[/LIST]
*
[LIST]
[*]Provides functionality to read and write files.
[*]_________________________________________________________________________
[*]1. Requirements
[*]¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
[*]- Patch 1.29 or higher.
[*]- JassHelper (vJASS)
[*]_________________________________________________________________________
[*]2. Installation
[*]¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
[*]Copy the script to your map and save it.
[*]_________________________________________________________________________
[*]3. API
[*]¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
[*]struct File extends array
[/LIST]
*
[LIST]
[*]static constant integer AbilityCount
[*]static constant integer PreloadLimit
[/LIST]
*
[LIST]
[*]readonly static boolean ReadEnabled
[*]readonly static integer Counter
[*]readonly static integer array List
[/LIST]
*
[LIST]
[*]static method open takes string filename returns File
[*]static method create takes string filename returns File
[/LIST]
*
* ---------
*
[LIST]
[*]method write takes string value returns File
[*]method read takes nothing returns string
[/LIST]
*
[LIST]
[*]method readEx takes boolean close returns string
[*]method readAndClose takes nothing returns string
[*]method readBuffer takes nothing returns string
[*]method writeBuffer takes string contents returns nothing
[*]method appendBuffer takes string contents returns nothing
[/LIST]
*
* method close takes nothing returns nothing
*
[LIST]
[*]public function Write takes string filename, string contents returns nothing
[*]public function Read takes string filename returns string
[/LIST]
*
***************************************************************/
globals
// Enable this if you want to allow the system to read files generated in patch 1.30 or below.
// NOTE: For this to work properly you must edit the 'Amls' ability and change the levels to 2
// as well as typing something in "Level 2 - Text - Tooltip - Normal" text field.
//
// Enabling this will also cause the system to treat files written with .write("") as empty files.
//
// This setting is really only intended for those who were already using the system in their map
// prior to patch 1.31 and want to keep old files created with this system to still work.
private constant boolean BACKWARDS_COMPATABILITY = true
endglobals
private keyword FileInit
struct File extends array
static constant integer AbilityCount = 10
static constant integer PreloadLimit = 200
readonly static integer Counter = 0
readonly static integer array List
readonly static integer array AbilityList
readonly static boolean ReadEnabled
readonly string filename
private string buffer
static method open takes string filename returns thistype
local thistype this = .List[0]
if (this == 0) then
set this = Counter + 1
set Counter = this
else
set .List[0] = .List[this]
endif
set this.filename = filename
set this.buffer = null
debug if (this >= JASS_MAX_ARRAY_SIZE) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0, 120, "FileIO(" + filename + ") WARNING: Maximum instance limit " + I2S(JASS_MAX_ARRAY_SIZE) + " reached.")
debug endif
return this
endmethod
// This is used to detect invalid characters which aren't supported in preload files.
static if (DEBUG_MODE) then
private static method validateInput takes string contents returns string
local integer i = 0
local integer l = StringLength(contents)
local string ch = ""
loop
exitwhen i >= l
set ch = SubString(contents, i, i + 1)
if (ch == "\\") then
return ch
elseif (ch == "\"") then
return ch
endif
set i = i + 1
endloop
return null
endmethod
endif
method write takes string contents returns thistype
local integer i = 0
local integer c = 0
local integer len = StringLength(contents)
local integer lev = 0
local string prefix = "-" // this is used to signify an empty string vs a null one
local string chunk
debug if (.validateInput(contents) != null) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0, 120, "FileIO(" + filename + ") ERROR: Invalid character |cffffcc00" + .validateInput(contents) + "|r")
debug return this
debug endif
set this.buffer = null
// Check if the string is empty. If null, the contents will be cleared.
if (contents == "") then
set len = len + 1
endif
// Begin to generate the file
call PreloadGenClear()
call PreloadGenStart()
loop
exitwhen i >= len
debug if (c >= .AbilityCount) then
debug call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0, 120, "FileIO(" + filename + ") ERROR: String exceeds max length (" + I2S(.AbilityCount * .PreloadLimit) + ").|r")
debug endif
set lev = 0
static if (BACKWARDS_COMPATABILITY) then
if (c == 0) then
set lev = 1
set prefix = ""
else
set prefix = "-"
endif
endif
set chunk = SubString(contents, i, i + .PreloadLimit)
call Preload("\" )\ncall BlzSetAbilityTooltip(" + I2S(.AbilityList[c]) + ", \"" + prefix + chunk + "\", " + I2S(lev) + ")\n//")
set i = i + .PreloadLimit
set c = c + 1
endloop
call Preload("\" )\nendfunction\nfunction a takes nothing returns nothing\n //")
call PreloadGenEnd(this.filename)
return this
endmethod
method clear takes nothing returns thistype
return this.write(null)
endmethod
private method readPreload takes nothing returns string
local integer i = 0
local integer lev = 0
local string array original
local string chunk = ""
local string output = ""
loop
exitwhen i == .AbilityCount
set original[i] = BlzGetAbilityTooltip(.AbilityList[i], 0)
set i = i + 1
endloop
// Execute the preload file
call Preloader(this.filename)
// Read the output
set i = 0
loop
exitwhen i == .AbilityCount
set lev = 0
// Read from ability index 1 instead of 0 if
// backwards compatability is enabled
static if (BACKWARDS_COMPATABILITY) then
if (i == 0) then
set lev = 1
endif
endif
// Make sure the tooltip has changed
set chunk = BlzGetAbilityTooltip(.AbilityList[i], lev)
if (chunk == original[i]) then
if (i == 0 and output == "") then
return null // empty file
endif
return output
endif
// Check if the file is an empty string or null
static if not (BACKWARDS_COMPATABILITY) then
if (i == 0) then
if (SubString(chunk, 0, 1) != "-") then
return null // empty file
endif
set chunk = SubString(chunk, 1, StringLength(chunk))
endif
endif
// Remove the prefix
if (i > 0) then
set chunk = SubString(chunk, 1, StringLength(chunk))
endif
// Restore the tooltip and append the chunk
call BlzSetAbilityTooltip(.AbilityList[i], original[i], lev)
set output = output + chunk
set i = i + 1
endloop
return output
endmethod
method close takes nothing returns nothing
if (this.buffer != null) then
call .write(.readPreload() + this.buffer)
set this.buffer = null
endif
set .List[this] = .List[0]
set .List[0] = this
endmethod
method readEx takes boolean close returns string
local string output = .readPreload()
local string buf = this.buffer
if (close) then
call this.close()
endif
if (output == null) then
return buf
endif
if (buf != null) then
set output = output + buf
endif
return output
endmethod
method read takes nothing returns string
return .readEx(false)
endmethod
method readAndClose takes nothing returns string
return .readEx(true)
endmethod
method appendBuffer takes string contents returns thistype
set .buffer = .buffer + contents
return this
endmethod
method readBuffer takes nothing returns string
return .buffer
endmethod
method writeBuffer takes string contents returns nothing
set .buffer = contents
endmethod
static method create takes string filename returns thistype
return .open(filename).write("")
endmethod
implement FileInit
endstruct
private module FileInit
private static method onInit takes nothing returns nothing
local string originalTooltip
// We can't use a single ability with multiple levels because
// tooltips return the first level's value if the value hasn't
// been set. This way we don't need to edit any object editor data.
set File.AbilityList[0] = 'Amls'
set File.AbilityList[1] = 'Aroc'
set File.AbilityList[2] = 'Amic'
set File.AbilityList[3] = 'Amil'
set File.AbilityList[4] = 'Aclf'
set File.AbilityList[5] = 'Acmg'
set File.AbilityList[6] = 'Adef'
set File.AbilityList[7] = 'Adis'
set File.AbilityList[8] = 'Afbt'
set File.AbilityList[9] = 'Afbk'
// Backwards compatability check
static if (BACKWARDS_COMPATABILITY) then
static if (DEBUG_MODE) then
set originalTooltip = BlzGetAbilityTooltip(File.AbilityList[0], 1)
call BlzSetAbilityTooltip(File.AbilityList[0], SCOPE_PREFIX, 1)
if (BlzGetAbilityTooltip(File.AbilityList[0], 1) == originalTooltip) then
call DisplayTimedTextToPlayer(GetLocalPlayer(),0,0, 120, "FileIO WARNING: Backwards compatability enabled but \"" + GetObjectName(File.AbilityList[0]) + "\" isn't setup properly.|r")
endif
endif
endif
// Read check
set File.ReadEnabled = File.open("FileTester.pld").write(SCOPE_PREFIX).readAndClose() == SCOPE_PREFIX
endmethod
endmodule
public function Write takes string filename, string contents returns nothing
call File.open(filename).write(contents).close()
endfunction
public function Read takes string filename returns string
return File.open(filename).readEx(true)
endfunction
endlibrary
JASS:
library Savecode requires BigNum
private constant function uppercolor takes nothing returns string
return "|cffff0000"
endfunction
private constant function lowercolor takes nothing returns string
return "|cff00ff00"
endfunction
private constant function numcolor takes nothing returns string
return "|cff0000ff"
endfunction
private function player_charset takes nothing returns string
return "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
endfunction
private function player_charsetlen takes nothing returns integer
return StringLength(player_charset())
endfunction
private function charset takes nothing returns string
return "!#$%&'()*+,-.0123456789:;=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{|}`"
endfunction
private function charsetlen takes nothing returns integer
return StringLength(charset())
endfunction
private function BASE takes nothing returns integer
return charsetlen()
endfunction
private constant function HASHN takes nothing returns integer
return 5000 //1./HASHN() is the probability of a random code being valid
endfunction
private constant function MAXINT takes nothing returns integer
return 2147483647
endfunction
private function player_chartoi takes string c returns integer
local integer i = 0
local string cs = player_charset()
local integer len = player_charsetlen()
loop
exitwhen i>=len or c == SubString(cs,i,i+1)
set i = i + 1
endloop
return i
endfunction
private function chartoi takes string c returns integer
local integer i = 0
local string cs = charset()
local integer len = charsetlen()
loop
exitwhen i>=len or c == SubString(cs,i,i+1)
set i = i + 1
endloop
return i
endfunction
private function itochar takes integer i returns string
return SubString(charset(),i,i+1)
endfunction
//You probably want to use a different char set for this
//Also, use a hash that doesn't suck so much
private function scommhash takes string s returns integer
local integer array count
local integer i = 0
local integer len = StringLength(s)
local integer x
set s = StringCase(s,true)
loop
exitwhen i >= len
set x = player_chartoi(SubString(s,i,i+1))
set count[x] = count[x] + 1
set i = i + 1
endloop
set i = 0
set len = player_charsetlen()
set x = 0
loop
exitwhen i>= len
set x = count[i]*count[i]*i+count[i]*x+x+199
// call BJDebugMsg(I2S(x)+" "+I2S(count[i]))
// call TriggerSleepAction(0.)
set i = i + 1
endloop
if x < 0 then
set x = -x
endif
return x
endfunction
private function modb takes integer x returns integer
if x >= BASE() then
return x - BASE()
elseif x < 0 then
return x + BASE()
else
return x
endif
endfunction
struct Savecode
real digits //logarithmic approximation
BigNum bignum
static method create takes nothing returns Savecode
local Savecode sc = Savecode.allocate()
set sc.digits = 0.
set sc.bignum = BigNum.create(BASE())
return sc
endmethod
method onDestroy takes nothing returns nothing
call .bignum.destroy()
endmethod
method Encode takes integer val, integer max returns nothing
set .digits = .digits + log(max+1,BASE())
call .bignum.MulSmall(max+1)
call .bignum.AddSmall(val)
endmethod
method Decode takes integer max returns integer
return .bignum.DivSmall(max+1)
endmethod
method IsEmpty takes nothing returns boolean
return .bignum.IsZero()
endmethod
method Length takes nothing returns real
return .digits
endmethod
method Clean takes nothing returns nothing
call .bignum.Clean()
endmethod
//These functions get too intimate with BigNum_l
method Pad takes nothing returns nothing
local BigNum_l cur = .bignum.list
local BigNum_l prev
local integer maxlen = R2I(1.0 + .Length())
loop
exitwhen cur == 0
set prev = cur
set cur = cur.next
set maxlen = maxlen - 1
endloop
loop
exitwhen maxlen <= 0
set prev.next = BigNum_l.create()
set prev = prev.next
set maxlen = maxlen - 1
endloop
endmethod
method ToString takes nothing returns string
local BigNum_l cur = .bignum.list
local string s = ""
loop
exitwhen cur == 0
set s = itochar(cur.leaf) + s
set cur = cur.next
endloop
return s
endmethod
method FromString takes string s returns nothing
local integer i = StringLength(s)-1
local BigNum_l cur = BigNum_l.create()
set .bignum.list = cur
loop
set cur.leaf = chartoi(SubString(s,i,i+1))
exitwhen i <= 0
set cur.next = BigNum_l.create()
set cur = cur.next
set i = i - 1
endloop
endmethod
method Hash takes nothing returns integer
local integer hash = 0
local integer x
local BigNum_l cur = .bignum.list
loop
exitwhen cur == 0
set x = cur.leaf
set hash = ModuloInteger(hash+79*hash/(x+1) + 293*x/(1+hash - (hash/BASE())*BASE()) + 479,HASHN())
set cur = cur.next
endloop
return hash
endmethod
//this is not cryptographic which is fine for this application
//sign = 1 is forward
//sign = -1 is backward
method Obfuscate takes integer key, integer sign returns nothing
local integer seed = GetRandomInt(0,MAXINT())
local integer advance
local integer x
local BigNum_l cur = .bignum.list
if sign == -1 then
call SetRandomSeed(.bignum.LastDigit())
set cur.leaf = modb(cur.leaf + sign*GetRandomInt(0,BASE()-1))
set x = cur.leaf
endif
call SetRandomSeed(key)
loop
exitwhen cur == 0
if sign == -1 then
set advance = cur.leaf
endif
set cur.leaf = modb(cur.leaf + sign*GetRandomInt(0,BASE()-1))
if sign == 1 then
set advance = cur.leaf
endif
set advance = advance + GetRandomInt(0,BASE()-1)
call SetRandomSeed(advance)
set x = cur.leaf
set cur = cur.next
endloop
if sign == 1 then
call SetRandomSeed(x)
set .bignum.list.leaf = modb(.bignum.list.leaf + sign*GetRandomInt(0,BASE()-1))
endif
call SetRandomSeed(seed)
endmethod
method Dump takes nothing returns nothing
local BigNum_l cur = .bignum.list
local string s = ""
set s = "max: "+R2S(.digits)
loop
exitwhen cur == 0
set s = I2S(cur.leaf)+" "+s
set cur = cur.next
endloop
call BJDebugMsg(s)
endmethod
method Save takes player p, integer loadtype returns string
local integer key = scommhash(GetPlayerName(p))+loadtype*73
local string s
local integer hash
call .Clean()
set hash = .Hash()
call .Encode(hash,HASHN())
call .Clean()
/////////////////////// Save code information. Comment out next two lines in implementation
//call BJDebugMsg("Expected length: " +I2S(R2I(1.0+.Length())))
//call BJDebugMsg("Room left in last char: "+R2S(1.-ModuloReal((.Length()),1)))
///////////////////////
call .Pad()
call .Obfuscate(key,1)
return .ToString()
endmethod
method Load takes player p, string s, integer loadtype returns boolean
local integer ikey = scommhash(GetPlayerName(p))+loadtype*73
local integer inputhash
call .FromString(s)
call .Obfuscate(ikey,-1)
set inputhash = .Decode(HASHN())
call .Clean()
return inputhash == .Hash()
endmethod
endstruct
private function isupper takes string c returns boolean
return c == StringCase(c,true)
endfunction
private function ischar takes string c returns boolean
return S2I(c) == 0 and c!= "0"
endfunction
private function chartype takes string c returns integer
if(ischar(c)) then
if isupper(c) then
return 0
else
return 1
endif
else
return 2
endif
endfunction
private function testchar takes string c returns nothing
if(ischar(c)) then
if isupper(c) then
call BJDebugMsg(c+" isupper")
else
call BJDebugMsg(c+" islower")
endif
else
call BJDebugMsg(c+ " isnumber")
endif
endfunction
public function colorize takes string s returns string
local string out = ""
local integer i = 0
local integer len = StringLength(s)
local integer ctype
local string c
loop
exitwhen i >= len
set c = SubString(s,i,i+1)
set ctype = chartype(c)
if ctype == 0 then
set out = out + uppercolor()+c+"|r"
elseif ctype == 1 then
set out = out + lowercolor()+c+"|r"
else
set out = out + numcolor()+c+"|r"
endif
set i = i + 1
endloop
return out
endfunction
private function prop_Savecode takes nothing returns boolean
local string s
local Savecode loadcode
//--- Data you want to save ---
local integer medal1 = 10
local integer medal2 = 3
local integer medalmax = 13
local integer XP = 1337
local integer XPmax = 1000000
local Savecode savecode = Savecode.create()
call SetPlayerName(Player(0),"yomp")
call SetPlayerName(Player(1),"fruitcup")
call savecode.Encode(medal1,medalmax)
call savecode.Encode(medal2,medalmax)
call savecode.Encode(XP,XPmax)
//--- Savecode_save generates the savecode for a specific player ---
set s = savecode.Save(Player(0),1)
call savecode.destroy()
// call BJDebugMsg("Savecode: " + Savecode_colorize(s))
//--- User writes down code, inputs again ---
set loadcode = Savecode.create()
if loadcode.Load(Player(0),s,1) then
// call BJDebugMsg("load ok")
else
call BJDebugMsg("load failed")
return false
endif
//Must decode in reverse order of encodes
// load object : max value that data can take
if XP != loadcode.Decode(XPmax) then
return false
elseif medal2 != loadcode.Decode(medalmax) then
return false
elseif medal1 != loadcode.Decode(medalmax) then
return false
endif
call loadcode.destroy()
return true
endfunction
endlibrary
//===========================================================================
function InitTrig_save_system takes nothing returns nothing
endfunction
JASS:
library BigNum
//prefer algebraic approach because of real subtraction issues
function log takes real y, real base returns real
local real x
local real factor = 1.0
local real logy = 0.0
local real sign = 1.0
if(y < 0.) then
return 0.0
endif
if(y < 1.) then
set y = 1.0/y
set sign = -1.0
endif
//Chop out powers of the base
loop
exitwhen y < 1.0001 //decrease this ( bounded below by 1) to improve precision
if(y > base) then
set y = y / base
set logy = logy + factor
else
set base = SquareRoot(base) //If you use just one base a lot, precompute its squareroots
set factor = factor / 2.
endif
endloop
return sign*logy
endfunction
struct BigNum_l
integer leaf
BigNum_l next
debug static integer nalloc = 0
static method create takes nothing returns BigNum_l
local BigNum_l bl = BigNum_l.allocate()
set bl.next = 0
set bl.leaf = 0
debug set BigNum_l.nalloc = BigNum_l.nalloc + 1
return bl
endmethod
method onDestroy takes nothing returns nothing
debug set BigNum_l.nalloc = BigNum_l.nalloc - 1
endmethod
//true: want destroy
method Clean takes nothing returns boolean
if .next == 0 and .leaf == 0 then
return true
elseif .next != 0 and .next.Clean() then
call .next.destroy()
set .next = 0
return .leaf == 0
else
return false
endif
endmethod
method DivSmall takes integer base, integer denom returns integer
local integer quotient
local integer remainder = 0
local integer num
if .next != 0 then
set remainder = .next.DivSmall(base,denom)
endif
set num = .leaf + remainder*base
set quotient = num/denom
set remainder = num - quotient*denom
set .leaf = quotient
return remainder
endmethod
endstruct
struct BigNum
BigNum_l list
integer base
static method create takes integer base returns BigNum
local BigNum b = BigNum.allocate()
set b.list = 0
set b.base = base
return b
endmethod
method onDestroy takes nothing returns nothing
local BigNum_l cur = .list
local BigNum_l next
loop
exitwhen cur == 0
set next = cur.next
call cur.destroy()
set cur = next
endloop
endmethod
method IsZero takes nothing returns boolean
local BigNum_l cur = .list
loop
exitwhen cur == 0
if cur.leaf != 0 then
return false
endif
set cur = cur.next
endloop
return true
endmethod
method Dump takes nothing returns nothing
local BigNum_l cur = .list
local string s = ""
loop
exitwhen cur == 0
set s = I2S(cur.leaf)+" "+s
set cur = cur.next
endloop
call BJDebugMsg(s)
endmethod
method Clean takes nothing returns nothing
local BigNum_l cur = .list
call cur.Clean()
endmethod
//fails if bignum is null
//BASE() + carry must be less than MAXINT()
method AddSmall takes integer carry returns nothing
local BigNum_l next
local BigNum_l cur = .list
local integer sum
if cur == 0 then
set cur = BigNum_l.create()
set .list = cur
endif
loop
exitwhen carry == 0
set sum = cur.leaf + carry
set carry = sum / .base
set sum = sum - carry*.base
set cur.leaf = sum
if cur.next == 0 then
set cur.next = BigNum_l.create()
endif
set cur = cur.next
endloop
endmethod
//x*BASE() must be less than MAXINT()
method MulSmall takes integer x returns nothing
local BigNum_l cur = .list
local integer product
local integer remainder
local integer carry = 0
loop
exitwhen cur == 0 and carry == 0
set product = x * cur.leaf + carry
set carry = product/.base
set remainder = product - carry*.base
set cur.leaf = remainder
if cur.next == 0 and carry != 0 then
set cur.next = BigNum_l.create()
endif
set cur = cur.next
endloop
endmethod
//Returns remainder
method DivSmall takes integer denom returns integer
return .list.DivSmall(.base,denom)
endmethod
method LastDigit takes nothing returns integer
local BigNum_l cur = .list
local BigNum_l next
loop
set next = cur.next
exitwhen next == 0
set cur = next
endloop
return cur.leaf
endmethod
endstruct
private function prop_Allocator1 takes nothing returns boolean
local BigNum b1
local BigNum b2
set b1 = BigNum.create(37)
call b1.destroy()
set b2 = BigNum.create(37)
call b2.destroy()
return b1 == b2
endfunction
private function prop_Allocator2 takes nothing returns boolean
local BigNum b1
local boolean b = false
set b1 = BigNum.create(37)
call b1.AddSmall(17)
call b1.MulSmall(19)
debug if BigNum_l.nalloc < 1 then
debug return false
debug endif
call b1.destroy()
debug set b = BigNum_l.nalloc == 0
return b
endfunction
private function prop_Arith takes nothing returns boolean
local BigNum b1
set b1 = BigNum.create(37)
call b1.AddSmall(73)
call b1.MulSmall(39)
call b1.AddSmall(17)
//n = 2864
if b1.DivSmall(100) != 64 then
return false
elseif b1.DivSmall(7) != 0 then
return false
elseif b1.IsZero() then
return false
elseif b1.DivSmall(3) != 1 then
return false
elseif b1.DivSmall(3) != 1 then
return false
elseif not b1.IsZero() then
return false
endif
return true
endfunction
endlibrary
//===========================================================================
function InitTrig_bignum_lib takes nothing returns nothing
endfunction
Last edited: