Implement indexeddb storage for emscripten version. Double running speed of bear charge attack

Co-authored-by: sigonasr2 <sigonasr2@gmail.com>
pull/35/head
Nic0Nic0Nii 10 months ago
parent 5ed991ec88
commit 5a16f7757b
  1. 2
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 22
      Adventures in Lestoria/SaveFile.cpp
  3. 97
      Adventures in Lestoria/Ursule.cpp
  4. 28
      Adventures in Lestoria/assets/config/MonsterStrategies.txt
  5. 2
      Adventures in Lestoria/assets/config/Monsters.txt
  6. 2
      CMakeLists.txt

@ -2200,7 +2200,7 @@ datafiledoubledata AiL::GetDoubleList(std::string key){
} }
int main() int main()
{ {
{ {
AiL demo; AiL demo;
if (demo.Construct(WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4)) if (demo.Construct(WINDOW_SIZE.x, WINDOW_SIZE.y, 4, 4))

@ -123,6 +123,22 @@ const void SaveFile::SaveGame(){
utils::datafile::INITIAL_SETUP_COMPLETE=true; utils::datafile::INITIAL_SETUP_COMPLETE=true;
#ifdef __EMSCRIPTEN__ #ifdef __EMSCRIPTEN__
std::stringstream fileContents;
std::ifstream file("save_file_path"_S+std::format("save.{:04}",saveFileID));
while(file.good()){
int val=file.get();
if(val!=-1){
fileContents<<char(val);
}
}
std::string contents=fileContents.str();
emscripten_idb_async_store("/assets",("save_file_path"_S+std::format("save.{:04}",saveFileID)).c_str(),contents.data(),contents.length(),0,[](void*arg){
std::cout<<"Success!"<<std::endl;
},[](void*arg){
std::cout<<"Failed!"<<std::endl;
});
file.close();
std::function<void(std::string_view response)>RetryResponse; std::function<void(std::string_view response)>RetryResponse;
RetryResponse=[&](std::string_view response){ RetryResponse=[&](std::string_view response){
if(response!="ERR"){ if(response!="ERR"){
@ -339,6 +355,12 @@ const void SaveFile::Server_SaveMetadataFile(std::function<void(std::string_view
fileContents<<char(val); fileContents<<char(val);
} }
} }
std::string contents=fileContents.str();
emscripten_idb_async_store("/assets",("save_file_path"_S+"metadata.dat").c_str(),contents.data(),contents.length(),0,[](void*arg){
std::cout<<"Success 2!"<<std::endl;
},[](void*arg){
std::cout<<"Failed 2!"<<std::endl;
});
game->SendRequest("save_server"_S,CreateServerRequest(SaveFileOperation::SAVE_METADATA_FILE,fileContents.str())); game->SendRequest("save_server"_S,CreateServerRequest(SaveFileOperation::SAVE_METADATA_FILE,fileContents.str()));
game->responseCallback=respCallbackFunc; game->responseCallback=respCallbackFunc;
} }

@ -53,6 +53,7 @@ INCLUDE_DATA
using A=Attribute; using A=Attribute;
void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy){ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy){
switch(m.phase){ switch(m.phase){
case 0:{ case 0:{
m.phase=ConfigInt("StartPhase"); m.phase=ConfigInt("StartPhase");
@ -74,7 +75,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
if(m.GetRemainingHPPct()<=ConfigFloat("Phase 2.Change")/100.f){ if(m.GetRemainingHPPct()<=ConfigFloat("Phase 2.Change")/100.f){
//before moving to Phase 2, we need to make sure we're in Phase 0 of the bear AI. //before moving to Phase 2, we need to make sure we're in Phase 0 of the bear AI.
if(m.overlaySpriteTransparency<210U){ if(m.overlaySpriteTransparency<210U){
if(m.I(A::PHASE)!=0.f)goto bear; if(m.I(A::PHASE)!=0)goto bear;
else{ else{
if(m.F(A::RUN_AWAY_TIMER)==0.f)m.F(A::RUN_AWAY_TIMER)=ConfigFloat("Phase 1.Fur Change Color Time"); if(m.F(A::RUN_AWAY_TIMER)==0.f)m.F(A::RUN_AWAY_TIMER)=ConfigFloat("Phase 1.Fur Change Color Time");
else{ else{
@ -226,6 +227,39 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
m.F(A::CHARGE_COOLDOWN)=std::max(0.f,m.F(A::CHARGE_COOLDOWN)-fElapsedTime); m.F(A::CHARGE_COOLDOWN)=std::max(0.f,m.F(A::CHARGE_COOLDOWN)-fElapsedTime);
if(m.I(A::PHASE)!=0)goto bear2; //Prevent doing anything else if a part of bear AI is still running. if(m.I(A::PHASE)!=0)goto bear2; //Prevent doing anything else if a part of bear AI is still running.
if(m.GetRemainingHPPct()<=ConfigFloat("Phase 4.Change")/100.f){
auto TransitionToPhase5=[&](){
m.phase=5;
m.PerformOtherAnimation(1);
m.I(A::PHASE_REPEAT_COUNT)=ConfigInt("Phase 4.Wisp Pattern Spawn Count");
SoundEffect::PlaySFX("Ursule Phase Transition",SoundEffect::CENTERED);
m.F(A::ENVIRONMENT_TIMER)=ConfigFloat("Phase 4.Environment Fade-out Time");
m.I(A::ENVIRONMENT_PHASE)=0;
};
//We also need to move to the center of the map.
if(m.F(A::RUN_AWAY_TIMER)==0.f)m.F(A::RUN_AWAY_TIMER)=ConfigFloat("Phase 4.Run to Center Time");
else{
m.F(A::RUN_AWAY_TIMER)=std::max(0.f,m.F(A::RUN_AWAY_TIMER)-fElapsedTime);
if(m.F(A::RUN_AWAY_TIMER)==0.f){
TransitionToPhase5();
break;
}
}
vf2d mapCenter=game->GetCurrentMap().MapData.MapSize*vf2d{float(game->GetCurrentMap().MapData.tilewidth),float(game->GetCurrentMap().MapData.tileheight)}/2.0f;
float distToCenter=geom2d::line<float>(m.GetPos(),mapCenter).length();
if(distToCenter>4.0f){
m.targetAcquireTimer=20.f;
m.target=mapCenter;
RUN_TOWARDS(m,fElapsedTime,"Run Towards");
break;
}else{ //Now we're finally good for phase 2.
TransitionToPhase5();
break;
}
}
if(distToPlayer>=ConfigFloat("Phase 3.Charge Range")/100.f*24.f&&m.F(A::CHARGE_COOLDOWN)==0.f){ if(distToPlayer>=ConfigFloat("Phase 3.Charge Range")/100.f*24.f&&m.F(A::CHARGE_COOLDOWN)==0.f){
if(ConfigFloat("Phase 3.Charge Cast Time")!=0.f){ if(ConfigFloat("Phase 3.Charge Cast Time")!=0.f){
@ -250,6 +284,7 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
BEAR(m,fElapsedTime,"Bear"); BEAR(m,fElapsedTime,"Bear");
}break; }break;
case 4:{ //A charging phase. case 4:{ //A charging phase.
if(geom2d::line(m.pos,m.target).length()>100*fElapsedTime*m.GetMoveSpdMult()){ if(geom2d::line(m.pos,m.target).length()>100*fElapsedTime*m.GetMoveSpdMult()){
vf2d newPos=m.pos+geom2d::line(m.pos,m.target).vector().norm()*100*fElapsedTime*m.GetMoveSpdMult(); vf2d newPos=m.pos+geom2d::line(m.pos,m.target).vector().norm()*100*fElapsedTime*m.GetMoveSpdMult();
m.SetPos(newPos); m.SetPos(newPos);
@ -265,6 +300,66 @@ void Monster::STRATEGY::URSULE(Monster&m,float fElapsedTime,std::string strategy
m.PerformIdleAnimation(); m.PerformIdleAnimation();
} }
}break; }break;
case 5:{ //Final boss phase.
#pragma region Environment Color Change Handling
m.F(A::ENVIRONMENT_TIMER)=std::max(0.f,m.F(A::ENVIRONMENT_TIMER)-fElapsedTime);
switch(m.I(A::ENVIRONMENT_PHASE)){
case 0:{ //Fade out. Use the phase 3 environment fade-in color as the previous color to lerp out from.
game->SetWorldColor(ConfigPixel("Phase 3.Environment Fade-In Color")*util::lerp(0.f,1.0f,m.F(A::ENVIRONMENT_TIMER)/ConfigFloat("Phase 4.Environment Fade-out Time")));
if(m.F(A::ENVIRONMENT_TIMER)==0.f){
game->SetWorldColor({0,0,0,255});
m.F(A::ENVIRONMENT_TIMER)=ConfigFloat("Phase 4.Environment Fade-in Time");
m.I(A::ENVIRONMENT_PHASE)++;
game->SetWorldColorFunc([&](vi2d pos){
float fadeInRange=DATA["MonsterStrategy"]["Ursule"]["Phase 4"]["Environment Fade-In Range"].GetReal()/100.f*24.f;
float distToPlayer=geom2d::line<float>(game->GetPlayer()->GetPos(),pos).length();
return game->GetWorldColor()*std::min(1.0f,fadeInRange/distToPlayer);
});
}
}break;
case 1:{ //Fade in.
Pixel fadeInCol=ConfigPixel("Phase 4.Environment Fade-In Color");
game->SetWorldColor(fadeInCol*util::lerp(1.f,0.f,m.F(A::ENVIRONMENT_TIMER)/ConfigFloat("Phase 4.Environment Fade-in Time")));
if(m.F(A::ENVIRONMENT_TIMER)==0.f){
game->SetWorldColor(fadeInCol);
}
}break;
}
#pragma endregion
if(m.F(A::SHOOT_TIMER)==0.f){
uint8_t wispPatternCount=ConfigInt("Wisp Pattern Count");
uint8_t wispPattern=util::random()%wispPatternCount;
if(ConfigString("Phase 4.Wisp Pattern Random Selection")=="Bag"){
if(m.VEC(A::WISP_PATTERN_LIST).size()==0){
for(uint8_t numb=0;numb<wispPatternCount;numb++){ //Numbers are randomly inserted into the list.
m.VEC(A::WISP_PATTERN_LIST).insert(m.VEC(A::WISP_PATTERN_LIST).begin()+(util::random()%(m.VEC(A::WISP_PATTERN_LIST).size()+1)),numb);
}
}
wispPattern=std::any_cast<uint8_t>(m.VEC(A::WISP_PATTERN_LIST).back());
m.VEC(A::WISP_PATTERN_LIST).pop_back();
}
m.F(A::SHOOT_TIMER)=ConfigFloat("Phase 4.Wisp Pattern Spawn Wait Time");
vi2d wispSize={ConfigIntArr("Phase 4.Wisp Size",0),ConfigIntArr("Phase 4.Wisp Size",1)};
float rowWidth=ConfigString(std::format("Wisp Pattern {}.Row[0]",wispPattern)).length()*wispSize.x; // Width of a wisp set in pixels.
float mapWidth=game->GetCurrentMap().MapData.MapSize.x*float(game->GetCurrentMap().MapData.tilewidth);
int rowCount=Config(std::format("Wisp Pattern {}",wispPattern)).GetKeys().size();
for(float x=0;x<mapWidth;x+=wispSize.x){
for(int y=0;y<rowCount;y++){
std::string_view row=ConfigString(std::format("Wisp Pattern {}.Row[{}]",wispPattern,y));
if(row[int(x/wispSize.x)%row.length()]!='.'){
float ySpawn=ConfigInt("Phase 4.Wisp Pattern Spawn Y")+y*wispSize.y;
BULLET_LIST.push_back(std::make_unique<Wisp>(vf2d{x,ySpawn},vf2d{0,ConfigFloat("Phase 4.Wisp Speed")},wispSize.x/3.f,m.GetAttack(),m.OnUpperLevel(),false,ConfigPixel("Phase 4.Wisp Color")));
}
}
}
}
}break;
default:{ default:{
ERR(std::format("WARNING! Unknown phase {} for {} reached!",m.phase,m.GetName())); ERR(std::format("WARNING! Unknown phase {} for {} reached!",m.phase,m.GetName()));
} }

@ -411,14 +411,29 @@ MonsterStrategy
} }
Phase 4 Phase 4
{ {
# Maximum amount of time the boss takes to run towards the center before giving up and continuing through Phase 2.
Run to Center Time = 10.0s
# Percentage of health to transition to Phase 4 # Percentage of health to transition to Phase 4
Change = 50% Change = 50%
# Percentage of damage reduced on the bear while the barrier is active. # Amount of time the environment fades out to pitch black.
Barrier Damage Reduction = 100% Environment Fade-out Time = 0.4s
# Amount of time for the environment to fade in with the new color.
Environment Fade-in Time = 2.0s
# New fade-in environment color.
Environment Fade-In Color = 255, 82, 82, 255
# The amount of range sight the player has with the new environment.
Environment Fade-In Range = 400
# Wisp size in pixels.
Wisp Size = 24,24
# Speed at which the wisp moves downwards. # Speed at which the wisp moves downwards.
Wisp Speed = 130% Wisp Speed = 90
# RGBA value of the wisp. # RGBA value of the wisp.
Wisp Color = 247, 95, 0, 255 Wisp Color = 247, 95, 0, 255
@ -426,9 +441,12 @@ MonsterStrategy
# There are 6 rows of wisps and we want them to spawn outside the arena # There are 6 rows of wisps and we want them to spawn outside the arena
Wisp Pattern Spawn Y = -144 Wisp Pattern Spawn Y = -144
# Amount of time the wisp fades out after hitting the player.
Wisp Fadeout Time = 0.3s
# How much time (in seconds) to wait between each pattern spawn. # How much time (in seconds) to wait between each pattern spawn.
# 130% speed means it takes 4.61 seconds for all the wisps to move entirely down. # 100% speed means it takes 6 seconds for all the wisps to move entirely down.
Wisp Pattern Spawn Wait Time = 4.61s Wisp Pattern Spawn Wait Time = 1.6s
# This value is either Bag or Random. Bag means every pattern gets selected once before re-cycling. Random is truly random with potential repeats. # This value is either Bag or Random. Bag means every pattern gets selected once before re-cycling. Random is truly random with potential repeats.
Wisp Pattern Random Selection = Random Wisp Pattern Random Selection = Random

@ -386,6 +386,6 @@ Monsters
ANIMATION[0] = 4, 0.1, OneShot ANIMATION[0] = 4, 0.1, OneShot
ANIMATION[1] = 6, 0.15, OneShot ANIMATION[1] = 6, 0.15, OneShot
ANIMATION[2] = 2, 0.2, Reverse ANIMATION[2] = 2, 0.2, Reverse
ANIMATION[3] = 5, 0.2, Repeat ANIMATION[3] = 5, 0.1, Repeat
} }
} }

@ -326,6 +326,7 @@ if (EMSCRIPTEN)
-sEXPORTED_RUNTIME_METHODS=stringToNewUTF8 -sEXPORTED_RUNTIME_METHODS=stringToNewUTF8
-std=c++20 -std=c++20
--proxy-to-worker --proxy-to-worker
-lidbfs.js
-O2 -O2
--preload-file ${SOURCE_DATA_DIR}@assets) --preload-file ${SOURCE_DATA_DIR}@assets)
else() else()
@ -341,6 +342,7 @@ if (EMSCRIPTEN)
-sEXPORTED_RUNTIME_METHODS=stringToNewUTF8 -sEXPORTED_RUNTIME_METHODS=stringToNewUTF8
-std=c++20 -std=c++20
--proxy-to-worker --proxy-to-worker
-lidbfs.js
-O2 -O2
-sLLD_REPORT_UNDEFINED) -sLLD_REPORT_UNDEFINED)
endif() endif()

Loading…
Cancel
Save