Minimap chunk revealing and updating is now stored in user save files. Fix minimap map alignment to match the tile size of the map (The camp has a different base tile size). Release Build 8825.

pull/57/head
sigonasr2 8 months ago
parent f2b17e8c85
commit 64a25dc66c
  1. 3
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 67
      Adventures in Lestoria/Minimap.cpp
  3. 7
      Adventures in Lestoria/Minimap.h
  4. 2
      Adventures in Lestoria/Player.cpp
  5. 210
      Adventures in Lestoria/SaveFile.cpp
  6. 2
      Adventures in Lestoria/Version.h
  7. 3
      Adventures in Lestoria/assets/config/Player.txt
  8. BIN
      x64/Release/Adventures in Lestoria.exe

@ -3778,12 +3778,13 @@ void AiL::ResetGame(bool changeToMainMenu){
game->ClearLoadoutItem(i); game->ClearLoadoutItem(i);
} }
Unlock::Initialize(); Unlock::Initialize();
State_OverworldMap::SetStageMarker("Story I"); State_OverworldMap::SetStageMarker("Player.Starting Location"_S);
State_OverworldMap::UpdateCurrentConnectionPoint(*State_OverworldMap::currentConnectionPoint); State_OverworldMap::UpdateCurrentConnectionPoint(*State_OverworldMap::currentConnectionPoint);
State_OverworldMap::ResetConnectionPoints(); State_OverworldMap::ResetConnectionPoints();
SetChapter(1); SetChapter(1);
SaveFile::SetSaveFileName(""); SaveFile::SetSaveFileName("");
Tutorial::Initialize(); Tutorial::Initialize();
minimap.EraseChunkData();
} }
void AiL::OnRequestCompleted(const std::string_view receivedData)const{ void AiL::OnRequestCompleted(const std::string_view receivedData)const{

@ -55,8 +55,6 @@ void Minimap::Initialize(){
} }
void Minimap::Reset(){ void Minimap::Reset(){
loadedChunks.clear();
if(minimap.Sprite()==nullptr)minimap.Create(1,1); if(minimap.Sprite()==nullptr)minimap.Create(1,1);
if(cover.Sprite()==nullptr)cover.Create(1,1); if(cover.Sprite()==nullptr)cover.Create(1,1);
@ -128,48 +126,63 @@ void Minimap::Reset(){
game->SetDrawTarget(nullptr); game->SetDrawTarget(nullptr);
minimap.Decal()->Update(); minimap.Decal()->Update();
#pragma region Load all minimap chunks already explored
for(auto&chunk:loadedChunks[game->GetCurrentMapName()]){
vi2d chunkPos={stoi(chunk.substr(0,chunk.find('_'))),stoi(chunk.substr(chunk.find('_')+1))};
UpdateChunk(game->GetCurrentMapName(),chunkPos);
}
#pragma endregion
} }
void Minimap::Update(){ void Minimap::Update(){
} }
void Minimap::UpdateChunk(const vi2d chunkPos){ void Minimap::UpdateChunk(const MapName map,const vi2d chunkPos){
if(!loadedChunks.count(std::format("{}_{}",chunkPos.x,chunkPos.y))){ loadedChunks[map].insert(std::format("{}_{}",chunkPos.x,chunkPos.y));
loadedChunks.insert(std::format("{}_{}",chunkPos.x,chunkPos.y));
vi2d centerChunkPos=chunkPos*"Minimap.Chunk Size"_I; if(game->GetCurrentMapName()!=map)return; //Don't update the minimap when the map name doesn't match the current map.
vi2d pixelPos=centerChunkPos-"Minimap.Chunk Size"_I*2; vi2d centerChunkPos=chunkPos*"Minimap.Chunk Size"_I;
vi2d chunkEndPixelPos=centerChunkPos+"Minimap.Chunk Size"_I*4;
//We start twice the distance we are supposed to outwards. vi2d pixelPos=centerChunkPos-"Minimap.Chunk Size"_I*2;
for(int y=pixelPos.y;y<chunkEndPixelPos.y;y++){ vi2d chunkEndPixelPos=centerChunkPos+"Minimap.Chunk Size"_I*4;
for(int x=pixelPos.x;x<chunkEndPixelPos.x;x++){
if(cover.Sprite()->GetPixel(x,y).a==255||minimap.Sprite()->GetPixel(x,y).a==0)continue; //Already revealed or invisible anyways.
vi2d chunk=vi2d{x,y}/"Minimap.Chunk Size"_I; //We start twice the distance we are supposed to outwards.
if(chunk==chunkPos){ for(int y=pixelPos.y;y<chunkEndPixelPos.y;y++){
cover.Sprite()->SetPixel(x,y,minimap.Sprite()->GetPixel(x,y)); for(int x=pixelPos.x;x<chunkEndPixelPos.x;x++){
}else{ if(cover.Sprite()->GetPixel(x,y).a==255||minimap.Sprite()->GetPixel(x,y).a==0)continue; //Already revealed or invisible anyways.
const vi2d chunkOffset={"Minimap.Chunk Size"_I/2,"Minimap.Chunk Size"_I/2};
const float distance=geom2d::line<float>(centerChunkPos+chunkOffset,vf2d{float(x),float(y)}).length(); vi2d chunk=vi2d{x,y}/"Minimap.Chunk Size"_I;
const int alpha=std::clamp(util::lerp(255,0,(distance-"Minimap.Chunk Size"_I)/"Minimap.Chunk Size"_I),0.f,255.f); if(chunk==chunkPos){
cover.Sprite()->SetPixel(x,y,minimap.Sprite()->GetPixel(x,y));
}else{
const vi2d chunkOffset={"Minimap.Chunk Size"_I/2,"Minimap.Chunk Size"_I/2};
if(cover.Sprite()->GetPixel(x,y).a>alpha)continue; //The distance was uncovered by another closer chunk, don't need to reveal it here. const float distance=geom2d::line<float>(centerChunkPos+chunkOffset,vf2d{float(x),float(y)}).length();
const int alpha=std::clamp(util::lerp(255,0,(distance-"Minimap.Chunk Size"_I)/"Minimap.Chunk Size"_I),0.f,255.f);
Pixel sourceCol=minimap.Sprite()->GetPixel(x,y); if(cover.Sprite()->GetPixel(x,y).a>alpha)continue; //The distance was uncovered by another closer chunk, don't need to reveal it here.
sourceCol.a=alpha;
cover.Sprite()->SetPixel(x,y,sourceCol); Pixel sourceCol=minimap.Sprite()->GetPixel(x,y);
} sourceCol.a=alpha;
cover.Sprite()->SetPixel(x,y,sourceCol);
} }
} }
cover.Decal()->Update();
} }
cover.Decal()->Update();
} }
void Minimap::Draw(){ void Minimap::Draw(){
if(!game->InBossEncounter())mapCircleHud.DrawRotatedDecal(vf2d{float("Minimap.Minimap HUD Size"_I),float("Minimap.Minimap HUD Size"_I)}/2,cover.Decal(),0.f,game->GetPlayer()->GetPos()/24,vf2d{0.5f,0.5f}); if(!game->InBossEncounter())mapCircleHud.DrawRotatedDecal(vf2d{float("Minimap.Minimap HUD Size"_I),float("Minimap.Minimap HUD Size"_I)}/2,cover.Decal(),0.f,game->GetPlayer()->GetPos()/game->GetCurrentMapData().tilewidth,vf2d{0.5f,0.5f});
}
void Minimap::EraseChunkData(){
loadedChunks.clear();
}
const std::unordered_map<MapName,std::unordered_set<std::string>>&Minimap::GetChunkData(){
return loadedChunks;
} }

@ -46,10 +46,13 @@ public:
void Update(); void Update();
void Draw(); void Draw();
void UpdateChunk(const vi2d chunkPos); void UpdateChunk(const MapName map,const vi2d chunkPos);
void EraseChunkData();
const std::unordered_map<MapName,std::unordered_set<std::string>>&GetChunkData();
private: private:
ViewPort mapCircleHud; ViewPort mapCircleHud;
Renderable minimap; Renderable minimap;
Renderable cover; Renderable cover;
std::unordered_set<std::string>loadedChunks; std::unordered_map<MapName,std::unordered_set<std::string>>loadedChunks;
}; };

@ -866,7 +866,7 @@ void Player::Moved(){
ForceSetPos({pos.x,float(game->GetCurrentMapData().playerSpawnLocation.y)}); ForceSetPos({pos.x,float(game->GetCurrentMapData().playerSpawnLocation.y)});
} }
game->minimap.UpdateChunk(GetPos()/24/"Minimap.Chunk Size"_I); game->minimap.UpdateChunk(game->GetCurrentMapName(),GetPos()/24/"Minimap.Chunk Size"_I);
} }
void Player::Spin(float duration,float spinSpd){ void Player::Spin(float duration,float spinSpd){

@ -86,108 +86,123 @@ const void SaveFile::SaveGame(){
game->SetQuitAllowed(false); game->SetQuitAllowed(false);
std::filesystem::create_directories("save_file_path"_S); std::filesystem::create_directories("save_file_path"_S);
utils::datafile saveFile;
utils::datafile saveSystemFile; utils::datafile saveSystemFile;
utils::datafile::INITIAL_SETUP_COMPLETE=false; {
for(size_t itemCount=0;auto&item:Inventory::GetInventory()){ utils::datafile saveFile;
saveFile["Items"][std::format("Item[{}]",itemCount)]["Amt"].SetInt(item->Amt()); utils::datafile::INITIAL_SETUP_COMPLETE=false;
saveFile["Items"][std::format("Item[{}]",itemCount)]["Enhancement Level"].SetInt(item->EnhancementLevel()); for(size_t itemCount=0;auto&item:Inventory::GetInventory()){
saveFile["Items"][std::format("Item[{}]",itemCount)]["Item Name"].SetString(item->ActualName()); saveFile["Items"][std::format("Item[{}]",itemCount)]["Amt"].SetInt(item->Amt());
saveFile["Items"][std::format("Item[{}]",itemCount)]["Equip Slot"].SetInt(int(Inventory::GetSlotEquippedIn(item))); saveFile["Items"][std::format("Item[{}]",itemCount)]["Enhancement Level"].SetInt(item->EnhancementLevel());
saveFile["Items"][std::format("Item[{}]",itemCount)]["Locked"].SetBool(item->IsLocked()); saveFile["Items"][std::format("Item[{}]",itemCount)]["Item Name"].SetString(item->ActualName());
uint8_t loadoutSlotNumber=255; saveFile["Items"][std::format("Item[{}]",itemCount)]["Equip Slot"].SetInt(int(Inventory::GetSlotEquippedIn(item)));
for(int i=0;i<game->loadout.size();i++){ saveFile["Items"][std::format("Item[{}]",itemCount)]["Locked"].SetBool(item->IsLocked());
if(item==game->GetLoadoutItem(i)){loadoutSlotNumber=i;break;} uint8_t loadoutSlotNumber=255;
for(int i=0;i<game->loadout.size();i++){
if(item==game->GetLoadoutItem(i)){loadoutSlotNumber=i;break;}
}
saveFile["Items"][std::format("Item[{}]",itemCount)]["LoadoutSlot"].SetInt(loadoutSlotNumber);
for(const auto&[attr,val]:item->RandomStats()){
saveFile["Items"][std::format("Item[{}]",itemCount)]["Attributes"][std::string(attr.ActualName())].SetReal(val);
}
itemCount++;
} }
saveFile["Items"][std::format("Item[{}]",itemCount)]["LoadoutSlot"].SetInt(loadoutSlotNumber); saveFile["Player"]["Class"].SetString(game->GetPlayer()->GetClassName());
for(const auto&[attr,val]:item->RandomStats()){ saveFile["Player"]["Level"].SetInt(game->GetPlayer()->Level());
saveFile["Items"][std::format("Item[{}]",itemCount)]["Attributes"][std::string(attr.ActualName())].SetReal(val); saveFile["Player"]["Money"].SetInt(game->GetPlayer()->GetMoney());
saveFile["Player"]["Current EXP"].SetInt(game->GetPlayer()->CurrentXP());
saveFile["Player"]["Total EXP"].SetInt(game->GetPlayer()->TotalXP());
for(const auto&[attr,val]:game->GetPlayer()->GetBaseStats()){
saveFile["Player"]["Base Stats"][std::string(attr.ActualName())].SetReal(val);
} }
itemCount++; for(const std::string&unlockName:Unlock::unlocks){
} if(unlockName=="WORLD_MAP")continue; //This is a special exception, because the world map is not an actual stage.
saveFile["Player"]["Class"].SetString(game->GetPlayer()->GetClassName()); saveFile["Unlocks"][unlockName].SetString("True");
saveFile["Player"]["Level"].SetInt(game->GetPlayer()->Level());
saveFile["Player"]["Money"].SetInt(game->GetPlayer()->GetMoney()); auto opt_cp=State_OverworldMap::ConnectionPointFromString(unlockName);
saveFile["Player"]["Current EXP"].SetInt(game->GetPlayer()->CurrentXP()); if(!opt_cp.has_value())continue; //Harmless, we probably just deleted the map.
saveFile["Player"]["Total EXP"].SetInt(game->GetPlayer()->TotalXP()); if(opt_cp.value()->Visited()){
for(const auto&[attr,val]:game->GetPlayer()->GetBaseStats()){ saveFile["Unlocks"][unlockName].SetString("True",1U);
saveFile["Player"]["Base Stats"][std::string(attr.ActualName())].SetReal(val); }else{
} saveFile["Unlocks"][unlockName].SetString("False",1U);
for(const std::string&unlockName:Unlock::unlocks){ }
if(unlockName=="WORLD_MAP")continue; //This is a special exception, because the world map is not an actual stage.
saveFile["Unlocks"][unlockName].SetString("True");
auto opt_cp=State_OverworldMap::ConnectionPointFromString(unlockName);
if(!opt_cp.has_value())continue; //Harmless, we probably just deleted the map.
if(opt_cp.value()->Visited()){
saveFile["Unlocks"][unlockName].SetString("True",1U);
}else{
saveFile["Unlocks"][unlockName].SetString("False",1U);
} }
}
for(auto&[taskName,task]:Tutorial::taskList){
saveFile["Tutorial"][std::to_string(int(taskName))].SetBool(Tutorial::TaskIsComplete(taskName));
}
saveFile["Overworld Map Location"].SetString(State_OverworldMap::GetCurrentConnectionPoint().name); for(auto&[taskName,task]:Tutorial::taskList){
saveFile["Chapter"].SetInt(game->GetCurrentChapter()); saveFile["Tutorial"][std::to_string(int(taskName))].SetBool(Tutorial::TaskIsComplete(taskName));
saveFile["Save Name"].SetString(std::string(GetSaveFileName())); }
saveFile["Game Time"].SetReal(game->GetRuntime());
saveFile["TravelingMerchant"].SetString(std::string(Merchant::GetCurrentTravelingMerchant().GetKeyName()));
#pragma region Save Keyboard/Controller mappings saveFile["Overworld Map Location"].SetString(State_OverworldMap::GetCurrentConnectionPoint().name);
//NOTE: We are shadowing code from InputKeyboardWindow! If at some point the retrival method for getting input displays changes, we likely will be changing the code here as well! saveFile["Chapter"].SetInt(game->GetCurrentChapter());
//ALSO NOTE: The menu inputs are saved to the system file while gameplay inputs are per-character and saved to the character settings file! saveFile["Save Name"].SetString(std::string(GetSaveFileName()));
const int menuRowCount=DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2+1; saveFile["Game Time"].SetReal(game->GetRuntime());
const int menuColCount=2; saveFile["TravelingMerchant"].SetString(std::string(Merchant::GetCurrentTravelingMerchant().GetKeyName()));
for(int row=0;row<menuRowCount;row++){
for(int col=0;col<menuColCount;col++){ #pragma region Save Keyboard/Controller mappings
int inputID=row*menuColCount+col; //NOTE: We are shadowing code from InputKeyboardWindow! If at some point the retrival method for getting input displays changes, we likely will be changing the code here as well!
if(DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==1&&col==1&&row==menuRowCount-1)continue; //We only continue on a blank space when we have an odd number of elements. //ALSO NOTE: The menu inputs are saved to the system file while gameplay inputs are per-character and saved to the character settings file!
saveSystemFile["Menu Keyboard Input_"+"Inputs.Menu Input Names"_s[inputID]].SetInt(Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput().GetPrimaryKey(KEY).value().GetKeyCode()); const int menuRowCount=DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()/2+1;
saveSystemFile["Menu Controller Input_"+"Inputs.Menu Input Names"_s[inputID]].SetInt(Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput().GetPrimaryKey(CONTROLLER).value().GetKeyCode()); const int menuColCount=2;
for(int row=0;row<menuRowCount;row++){
for(int col=0;col<menuColCount;col++){
int inputID=row*menuColCount+col;
if(DATA.GetProperty("Inputs.Menu Input Names").GetValueCount()%2==1&&col==1&&row==menuRowCount-1)continue; //We only continue on a blank space when we have an odd number of elements.
saveSystemFile["Menu Keyboard Input_"+"Inputs.Menu Input Names"_s[inputID]].SetInt(Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput().GetPrimaryKey(KEY).value().GetKeyCode());
saveSystemFile["Menu Controller Input_"+"Inputs.Menu Input Names"_s[inputID]].SetInt(Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Input Displayer",row,col))->GetInput().GetPrimaryKey(CONTROLLER).value().GetKeyCode());
}
} }
} const int ingameControlsRowCount=DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2+1;
const int ingameControlsRowCount=DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2+1; const int ingameControlsColCount=2;
const int ingameControlsColCount=2; for(int row=0;row<ingameControlsRowCount;row++){
for(int row=0;row<ingameControlsRowCount;row++){ for(int col=0;col<ingameControlsColCount;col++){
for(int col=0;col<ingameControlsColCount;col++){ int inputID=row*menuColCount+col;
int inputID=row*menuColCount+col; if(DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==1&&col==1&&row==ingameControlsRowCount-1)continue; //We only continue on a blank space when we have an odd number of elements.
if(DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==1&&col==1&&row==ingameControlsRowCount-1)continue; //We only continue on a blank space when we have an odd number of elements. saveFile["Gameplay Keyboard Input_"+"Inputs.Gameplay Input Names"_s[inputID]].SetInt(Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Gameplay Input Displayer",row,col))->GetInput().GetPrimaryKey(KEY).value().GetKeyCode());
saveFile["Gameplay Keyboard Input_"+"Inputs.Gameplay Input Names"_s[inputID]].SetInt(Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Gameplay Input Displayer",row,col))->GetInput().GetPrimaryKey(KEY).value().GetKeyCode()); saveFile["Gameplay Controller Input_"+"Inputs.Gameplay Input Names"_s[inputID]].SetInt(Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Gameplay Input Displayer",row,col))->GetInput().GetPrimaryKey(CONTROLLER).value().GetKeyCode());
saveFile["Gameplay Controller Input_"+"Inputs.Gameplay Input Names"_s[inputID]].SetInt(Component<InputDisplayComponent>(INPUT_KEY_DISPLAY,std::format("Input_{}_{} Gameplay Input Displayer",row,col))->GetInput().GetPrimaryKey(CONTROLLER).value().GetKeyCode()); }
}
#pragma endregion
#pragma region Save System Settings
saveSystemFile["BGM Level"].SetReal(Audio::GetBGMVolume());
saveSystemFile["SFX Level"].SetReal(Audio::GetSFXVolume());
saveSystemFile["Show Max Health"].SetBool(GameSettings::ShowMaxHealth());
saveSystemFile["Show Max Mana"].SetBool(GameSettings::ShowMaxMana());
saveSystemFile["Screen Shake"].SetBool(GameSettings::ScreenShakeEnabled());
saveSystemFile["Controller Rumble"].SetBool(GameSettings::RumbleEnabled());
saveSystemFile["Terrain Collision Boxes"].SetBool(GameSettings::TerrainCollisionBoxesEnabled());
saveSystemFile["Keyboard Auto-Aim"].SetBool(GameSettings::KeyboardAutoAimEnabled());
saveSystemFile["Controller Icons"].SetInt(int(GameSettings::GetIconType()));
saveSystemFile["VSync"].SetBool(GameSettings::VSyncEnabled());
saveSystemFile["Window Pos"].SetInt(game->GetActualWindowPos().x,0);
saveSystemFile["Window Pos"].SetInt(game->GetActualWindowPos().y,1);
saveSystemFile["Window Size"].SetInt(game->GetWindowSize().x,0);
saveSystemFile["Window Size"].SetInt(game->GetWindowSize().y,1);
saveSystemFile["Fullscreen"].SetBool(game->IsFullscreen());
#pragma endregion
saveFile["Hash"].SetString("");
for(auto&[mapName,chunks]:game->minimap.GetChunkData()){
size_t chunkInd=0;
for(auto&chunk:chunks){
saveFile["Minimap"][mapName].SetString(chunk,chunkInd);
chunkInd++;
} }
} }
#pragma endregion
#pragma region Save save file and prep File Hash
#pragma region Save System Settings utils::datafile::Write(saveFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
saveSystemFile["BGM Level"].SetReal(Audio::GetBGMVolume());
saveSystemFile["SFX Level"].SetReal(Audio::GetSFXVolume()); std::string fileHash=util::GetHash("save_file_path"_S+std::format("save.{:04}",saveFileID));
saveSystemFile["Show Max Health"].SetBool(GameSettings::ShowMaxHealth()); saveFile["Hash"].SetString(fileHash);
saveSystemFile["Show Max Mana"].SetBool(GameSettings::ShowMaxMana());
saveSystemFile["Screen Shake"].SetBool(GameSettings::ScreenShakeEnabled()); utils::datafile::Write(saveFile,"save_file_path"_S+std::format("save.{:04}",saveFileID)); //Once the hash has been computed and added, save the file a second time.
saveSystemFile["Controller Rumble"].SetBool(GameSettings::RumbleEnabled()); #pragma endregion
saveSystemFile["Terrain Collision Boxes"].SetBool(GameSettings::TerrainCollisionBoxesEnabled()); //WARNING! DO NOT WRITE ANY CODE BELOW HERE!!!!! THE HASH HAS ALREADY BEEN WRITTEN.
saveSystemFile["Keyboard Auto-Aim"].SetBool(GameSettings::KeyboardAutoAimEnabled()); //FILES BECOME CORRUPTED IF THE SAVE FILE IS MODIFIED FROM HERE ONWARDS.
saveSystemFile["Controller Icons"].SetInt(int(GameSettings::GetIconType())); }
saveSystemFile["VSync"].SetBool(GameSettings::VSyncEnabled());
saveSystemFile["Window Pos"].SetInt(game->GetActualWindowPos().x,0);
saveSystemFile["Window Pos"].SetInt(game->GetActualWindowPos().y,1);
saveSystemFile["Window Size"].SetInt(game->GetWindowSize().x,0);
saveSystemFile["Window Size"].SetInt(game->GetWindowSize().y,1);
saveSystemFile["Fullscreen"].SetBool(game->IsFullscreen());
#pragma endregion
saveFile["Hash"].SetString("");
utils::datafile::Write(saveFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
std::string fileHash=util::GetHash("save_file_path"_S+std::format("save.{:04}",saveFileID));
saveFile["Hash"].SetString(fileHash);
utils::datafile::Write(saveFile,"save_file_path"_S+std::format("save.{:04}",saveFileID)); //Once the hash has been computed and added, save the file a second time.
utils::datafile::Write(saveSystemFile,"save_file_path"_S+"system.conf"); utils::datafile::Write(saveSystemFile,"save_file_path"_S+"system.conf");
utils::datafile metadata; utils::datafile metadata;
if(onlineMode){ if(onlineMode){
@ -379,6 +394,15 @@ void SaveFile::LoadFile(){
game->GetPlayer()->RecalculateEquipStats(); game->GetPlayer()->RecalculateEquipStats();
if(loadFile.HasProperty("TravelingMerchant"))Merchant::SetTravelingMerchant(loadFile["TravelingMerchant"].GetString()); if(loadFile.HasProperty("TravelingMerchant"))Merchant::SetTravelingMerchant(loadFile["TravelingMerchant"].GetString());
if(loadFile.HasProperty("Minimap")){
for(auto&[key,size]:loadFile["Minimap"].GetKeys()){
for(const std::string&chunk:loadFile["Minimap"][key].GetValues()){
vi2d chunkPos={stoi(chunk.substr(0,chunk.find('_'))),stoi(chunk.substr(chunk.find('_')+1))};
game->minimap.UpdateChunk(key,chunkPos);
}
}
}
#pragma region Load Keyboard/Controller mappings #pragma region Load Keyboard/Controller mappings
//NOTE: We are shadowing code from InputKeyboardWindow! If at some point the retrival method for getting input displays changes, we likely will be changing the code here as well! //NOTE: We are shadowing code from InputKeyboardWindow! If at some point the retrival method for getting input displays changes, we likely will be changing the code here as well!
const int ingameControlsRowCount=DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2+1; const int ingameControlsRowCount=DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()%2==0?DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2:DATA.GetProperty("Inputs.Gameplay Input Names").GetValueCount()/2+1;

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 1 #define VERSION_MINOR 1
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_BUILD 8819 #define VERSION_BUILD 8825
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

@ -3,6 +3,9 @@ Player
BaseMana = 100 BaseMana = 100
MoveSpd = 100 MoveSpd = 100
# Game Map Starting Location
Starting Location = Story I
# Starting base crit rate. # Starting base crit rate.
Crit Rate = 0% Crit Rate = 0%

Loading…
Cancel
Save