Address Issue#45. Pressing opposite movement keys now properly stops animation. Movement with analog stick now properly sets last moved direction key as well instead of facing last digital input direction. Velocity is now applied and footsteps factor in total velocity before playing. Fixed a bug where the game could be closed by the player during a file save, causing the hash of the file to potentially become corrupted and unplayable. Fix some tiles at the end of 1-1 to match the underlying color of the surrounding forest. Removed erroneous upwards path from base camp on the world map. Release Build 8630.
This commit is contained in:
parent
c864e0f155
commit
35c269bd8b
@ -382,6 +382,7 @@ bool AiL::OnUserUpdate(float fElapsedTime){
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if(QuitRequested())EndGame();
|
||||
return !gameEnd;
|
||||
}
|
||||
|
||||
@ -470,7 +471,6 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
player->SetY(player->GetY()+"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult());
|
||||
player->movementVelocity.y+="Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult();
|
||||
}
|
||||
player->SetFacingDirection(RIGHT);
|
||||
|
||||
newAimingAngle+=vf2d{1,0};
|
||||
|
||||
@ -547,20 +547,48 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
}
|
||||
}
|
||||
if(heldDownMovementKey){
|
||||
if(abs(player->movementVelocity.x)>abs(player->movementVelocity.y)){ //Greater Horizontal movement.
|
||||
if(player->movementVelocity.x!=0.f){
|
||||
player->SetFacingDirection(player->movementVelocity.x>0?RIGHT:LEFT);
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(player->GetFacingDirection(),animationSpd);
|
||||
if(player->movementVelocity.x!=0.f||player->movementVelocity.y!=0.f){
|
||||
if(abs(player->movementVelocity.x)>abs(player->movementVelocity.y)){ //Greater Horizontal movement.
|
||||
if(player->movementVelocity.x!=0.f){
|
||||
player->SetFacingDirection(player->movementVelocity.x>0?RIGHT:LEFT);
|
||||
player->SetLastReleasedMovementKey(player->GetFacingDirection());
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(player->GetFacingDirection(),animationSpd);
|
||||
}
|
||||
}
|
||||
}else{ //Greater Vertical movement.
|
||||
if(player->movementVelocity.y!=0.f){
|
||||
player->SetFacingDirection(player->movementVelocity.y>0?DOWN:UP);
|
||||
player->SetLastReleasedMovementKey(player->GetFacingDirection());
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(player->GetFacingDirection(),animationSpd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{ //Greater Vertical movement.
|
||||
if(player->movementVelocity.y!=0.f){
|
||||
player->SetFacingDirection(player->movementVelocity.y>0?DOWN:UP);
|
||||
if(player->GetState()==State::NORMAL||player->GetState()==State::PREP_CAST){
|
||||
player->UpdateWalkingAnimation(player->GetFacingDirection(),animationSpd);
|
||||
#pragma region Footstep code
|
||||
player->footstepTimer+=GetElapsedTime()*animationSpd;
|
||||
if(player->footstepTimer>"Player.Footstep Timer"_F){
|
||||
player->footstepTimer-="Player.Footstep Timer"_F;
|
||||
|
||||
bool inWater=true;
|
||||
|
||||
for(const LayerTag&layer:GetCurrentMap().LayerData){
|
||||
int tileID=layer.tiles[player->GetY()/24][player->GetX()/24]-1;
|
||||
if(tileID!=-1&&!IsReflectiveTile(GetTileSheet(GetCurrentLevel(),tileID),tileID)){
|
||||
inWater=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(inWater){
|
||||
SoundEffect::PlaySFX("Footstep - Wet",SoundEffect::CENTERED);
|
||||
}else{
|
||||
SoundEffect::PlaySFX("Footstep",SoundEffect::CENTERED);
|
||||
}
|
||||
}
|
||||
#pragma endregion
|
||||
}else{ //This means we are holding down movement keys but we aren't actually moving anywhere, so don't.
|
||||
setIdleAnimation=true;
|
||||
}
|
||||
}
|
||||
if(UpReleased()){
|
||||
@ -624,29 +652,6 @@ void AiL::HandleUserInput(float fElapsedTime){
|
||||
setIdleAnimation=false;
|
||||
}
|
||||
|
||||
if(heldDownMovementKey){
|
||||
player->footstepTimer+=GetElapsedTime()*animationSpd;
|
||||
if(player->footstepTimer>"Player.Footstep Timer"_F){
|
||||
player->footstepTimer-="Player.Footstep Timer"_F;
|
||||
|
||||
bool inWater=true;
|
||||
|
||||
for(const LayerTag&layer:GetCurrentMap().LayerData){
|
||||
int tileID=layer.tiles[player->GetY()/24][player->GetX()/24]-1;
|
||||
if(tileID!=-1&&!IsReflectiveTile(GetTileSheet(GetCurrentLevel(),tileID),tileID)){
|
||||
inWater=false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(inWater){
|
||||
SoundEffect::PlaySFX("Footstep - Wet",SoundEffect::CENTERED);
|
||||
}else{
|
||||
SoundEffect::PlaySFX("Footstep",SoundEffect::CENTERED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(setIdleAnimation){
|
||||
switch(player->GetLastReleasedMovementKey()){
|
||||
case UP:{
|
||||
@ -2893,27 +2898,32 @@ bool AiL::IsReflectiveTile(TilesheetData tileSheet,int tileID){
|
||||
}
|
||||
|
||||
bool AiL::OnUserDestroy(){
|
||||
#ifndef __EMSCRIPTEN__
|
||||
SteamAPI_Shutdown();
|
||||
#endif
|
||||
GFX.Reset();
|
||||
for(auto&[key,value]:MAP_DATA){
|
||||
if(MAP_DATA[key].optimizedTile!=nullptr){
|
||||
delete MAP_DATA[key].optimizedTile;
|
||||
gameEnd=true;
|
||||
if(!savingFile){
|
||||
#ifndef __EMSCRIPTEN__
|
||||
SteamAPI_Shutdown();
|
||||
#endif
|
||||
GFX.Reset();
|
||||
for(auto&[key,value]:MAP_DATA){
|
||||
if(MAP_DATA[key].optimizedTile!=nullptr){
|
||||
delete MAP_DATA[key].optimizedTile;
|
||||
}
|
||||
}
|
||||
for(auto&[key,value]:MAP_TILESETS){
|
||||
delete value.tileset;
|
||||
}
|
||||
for(auto&[key,value]:GameState::states){
|
||||
delete value;
|
||||
}
|
||||
Menu::CleanupAllMenus();
|
||||
for(auto&[key,value]:MonsterData::imgs){
|
||||
delete value;
|
||||
}
|
||||
BACKDROP_DATA.clear();
|
||||
return true;
|
||||
}else{
|
||||
return false; //Something is preventing us from quitting. We wait patiently...
|
||||
}
|
||||
for(auto&[key,value]:MAP_TILESETS){
|
||||
delete value.tileset;
|
||||
}
|
||||
for(auto&[key,value]:GameState::states){
|
||||
delete value;
|
||||
}
|
||||
Menu::CleanupAllMenus();
|
||||
for(auto&[key,value]:MonsterData::imgs){
|
||||
delete value;
|
||||
}
|
||||
BACKDROP_DATA.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void AiL::InitializeLevels(){
|
||||
@ -3954,4 +3964,12 @@ void AiL::GlobalGameUpdates(){
|
||||
}else{
|
||||
ClearTimedOutGarbage();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const bool AiL::QuitRequested()const{
|
||||
return gameEnd;
|
||||
}
|
||||
void AiL::SetQuitAllowed(bool quittingAllowed){
|
||||
savingFile=!quittingAllowed;
|
||||
}
|
@ -183,6 +183,7 @@ private:
|
||||
float loadingWaitTime=0.f;
|
||||
bool displayHud=true;
|
||||
float vignetteDisplayTime=0.f;
|
||||
bool savingFile=false;
|
||||
|
||||
void ValidateGameStatus();
|
||||
void _PrepareLevel(MapName map,MusicChange changeMusic);
|
||||
@ -322,6 +323,8 @@ public:
|
||||
const float GetEncounterDuration()const;
|
||||
void ShowDamageVignetteOverlay();
|
||||
void GlobalGameUpdates();
|
||||
const bool QuitRequested()const;
|
||||
void SetQuitAllowed(bool quittingAllowed); //Locks the game from quitting during sensitive operations such as file saving/loading.
|
||||
|
||||
struct TileGroupData{
|
||||
vi2d tilePos;
|
||||
|
@ -82,6 +82,8 @@ const size_t SaveFile::GetOnlineSaveFileCount(){
|
||||
|
||||
const void SaveFile::SaveGame(){
|
||||
game->saveGameDisplayTime=6.f;
|
||||
|
||||
game->SetQuitAllowed(false);
|
||||
|
||||
std::filesystem::create_directories("save_file_path"_S);
|
||||
utils::datafile saveFile;
|
||||
@ -222,6 +224,7 @@ const void SaveFile::SaveGame(){
|
||||
}else{
|
||||
LOG("WARNING! Could not save metadata to server!");
|
||||
}
|
||||
game->SetQuitAllowed(true);
|
||||
};
|
||||
Server_SaveMetadataFile(RetryResponse);
|
||||
}else{
|
||||
@ -271,38 +274,46 @@ const void SaveFile::SaveGame(){
|
||||
std::string systemContents=systemFileContents.str();
|
||||
emscripten_idb_async_store("/assets",("save_file_path"_S+"system.conf").c_str(),systemContents.data(),systemContents.length(),0,[](void*arg){
|
||||
LOG("Successfully saved system file!");
|
||||
game->SetQuitAllowed(true);
|
||||
},[](void*arg){
|
||||
LOG("Failed to save system file!");
|
||||
game->SetQuitAllowed(true);
|
||||
});
|
||||
|
||||
systemfile.close();
|
||||
#else
|
||||
game->SetQuitAllowed(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define HASH_VERIFICATION_REQUIRED true
|
||||
|
||||
void SaveFile::LoadFile(){
|
||||
utils::datafile loadFile;
|
||||
|
||||
|
||||
std::string loadFilename="save_file_path"_S+std::format("save.{:04}",saveFileID);
|
||||
|
||||
if(std::filesystem::exists(loadFilename)){
|
||||
utils::datafile::Read(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
if(!loadFile.HasProperty("Hash")){
|
||||
LOG(std::format("WARNING! Filehash for file {} does not exist!","save_file_path"_S+std::format("save.{:04}",saveFileID)));
|
||||
return;
|
||||
}
|
||||
if(loadFile.HasProperty("Hash")){
|
||||
std::string expectedFileHash=loadFile["Hash"].GetString();
|
||||
loadFile["Hash"].SetString("");
|
||||
utils::datafile::Write(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
std::string fileHash=util::GetHash("save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
|
||||
if(expectedFileHash!=fileHash){
|
||||
LOG(std::format("WARNING! Filehash for file {} was not identified as proper! Will not load this file!","save_file_path"_S+std::format("save.{:04}",saveFileID)));
|
||||
if(HASH_VERIFICATION_REQUIRED){
|
||||
if(!loadFile.HasProperty("Hash")){
|
||||
LOG(std::format("WARNING! Filehash for file {} does not exist!","save_file_path"_S+std::format("save.{:04}",saveFileID)));
|
||||
return;
|
||||
}
|
||||
if(loadFile.HasProperty("Hash")){
|
||||
std::string expectedFileHash=loadFile["Hash"].GetString();
|
||||
loadFile["Hash"].SetString("");
|
||||
utils::datafile::Write(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
std::string fileHash=util::GetHash("save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
|
||||
loadFile["Hash"].SetString(expectedFileHash); //Now write the hash back into the file since we tampered with it.
|
||||
utils::datafile::Write(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
if(expectedFileHash!=fileHash){
|
||||
LOG(std::format("WARNING! Filehash for file {} was not identified as proper! Will not load this file!","save_file_path"_S+std::format("save.{:04}",saveFileID)));
|
||||
return;
|
||||
}
|
||||
|
||||
loadFile["Hash"].SetString(expectedFileHash); //Now write the hash back into the file since we tampered with it.
|
||||
utils::datafile::Write(loadFile,"save_file_path"_S+std::format("save.{:04}",saveFileID));
|
||||
}
|
||||
}
|
||||
game->ResetGame();
|
||||
for(auto&[key,data]:loadFile["Items"].GetOrderedKeys()){
|
||||
@ -398,6 +409,8 @@ void SaveFile::LoadFile(){
|
||||
|
||||
const void SaveFile::LoadGame(){
|
||||
std::filesystem::create_directories("save_file_path"_S);
|
||||
|
||||
game->SetQuitAllowed(false);
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
if(onlineMode){
|
||||
@ -410,6 +423,7 @@ const void SaveFile::LoadGame(){
|
||||
}else{
|
||||
LOG("WARNING! Could not load save file!");
|
||||
}
|
||||
game->SetQuitAllowed(true);
|
||||
});
|
||||
}else{
|
||||
emscripten_idb_async_load("/assets",("save_file_path"_S+std::format("save.{:04}",saveFileID)).c_str(),0,[](void*arg,void*data,int length){
|
||||
@ -422,12 +436,15 @@ const void SaveFile::LoadGame(){
|
||||
}
|
||||
file.close();
|
||||
LoadFile();
|
||||
game->SetQuitAllowed(true);
|
||||
},[](void*arg){
|
||||
LOG("Failed to load Save File "<<saveFileID<<"!");
|
||||
game->SetQuitAllowed(true);
|
||||
});
|
||||
}
|
||||
#else
|
||||
LoadFile();
|
||||
game->SetQuitAllowed(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 8619
|
||||
#define VERSION_BUILD 8630
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
@ -104,7 +104,7 @@
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1462,1462,1462,1462,1462,1462,1462,1462,1046,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,1048,4821,4822,4823,4824,4825,4826,4827,4828,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1462,1462,1462,1462,1462,1462,1462,1462,1046,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,1048,4861,4862,4863,4864,4865,4866,4867,4868,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1462,1462,1462,1462,1462,1462,1462,1462,1046,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,1048,4901,4902,4903,4904,4905,4906,4907,4908,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1462,1462,1462,1462,1462,1462,1462,1462,1046,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,995,1046,1046,1046,1046,1046,1046,1046,1046,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1462,1462,1462,1462,1462,1462,1462,1462,1046,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,995,79,79,79,79,79,79,79,79,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1462,1462,1462,1462,1462,1462,1462,1462,1046,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1462,1462,1462,1462,1462,1462,1462,1462,1046,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1462,1462,1462,1462,1462,1462,1462,1462,1046,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,678,
|
||||
|
@ -603,7 +603,6 @@
|
||||
</object>
|
||||
<object id="8" name="Camp" type="StagePlate" x="416" y="416" width="20" height="24">
|
||||
<properties>
|
||||
<property name="Connection 1 - North" type="object" value="0"/>
|
||||
<property name="Map" propertytype="Level" value="HUB"/>
|
||||
<property name="Type" propertytype="StageType" value="HUB"/>
|
||||
<property name="Unlock Condition" propertytype="Level" value="STORY_1_1"/>
|
||||
|
@ -176,6 +176,7 @@ std::string util::GetHash(std::string fileName){
|
||||
}
|
||||
hashIndex++;
|
||||
}
|
||||
file.close();
|
||||
return hash;
|
||||
}
|
||||
#pragma endregion
|
||||
|
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user