Add loading screen. Added flag for music change parameter when loading levels. Release Build 7558.

pull/35/head
sigonasr2 9 months ago
parent 76c1487871
commit 0861419582
  1. 530
      Adventures in Lestoria/AdventuresInLestoria.cpp
  2. 8
      Adventures in Lestoria/AdventuresInLestoria.h
  3. 33
      Adventures in Lestoria/Audio.cpp
  4. 2
      Adventures in Lestoria/Audio.h
  5. 1
      Adventures in Lestoria/GameState.h
  6. 56
      Adventures in Lestoria/LoadingScreen.cpp
  7. 12
      Adventures in Lestoria/LoadingScreen.h
  8. 2
      Adventures in Lestoria/State_GameHub.cpp
  9. 1
      Adventures in Lestoria/State_GameHub.h
  10. 1
      Adventures in Lestoria/State_GameRun.cpp
  11. 1
      Adventures in Lestoria/State_GameRun.h
  12. 1
      Adventures in Lestoria/State_LevelComplete.cpp
  13. 1
      Adventures in Lestoria/State_LevelComplete.h
  14. 1
      Adventures in Lestoria/State_MainMenu.cpp
  15. 1
      Adventures in Lestoria/State_MainMenu.h
  16. 4
      Adventures in Lestoria/State_OverworldMap.cpp
  17. 1
      Adventures in Lestoria/State_OverworldMap.h
  18. 1
      Adventures in Lestoria/State_Story.cpp
  19. 1
      Adventures in Lestoria/State_Story.h
  20. 2
      Adventures in Lestoria/Version.h
  21. BIN
      x64/Release/Adventures in Lestoria.exe

@ -279,7 +279,7 @@ bool AiL::OnUserCreate(){
Inventory::AddItem("Minor Health Potion"s,3); Inventory::AddItem("Minor Health Potion"s,3);
Inventory::AddItem("Bandages"s,10); Inventory::AddItem("Bandages"s,10);
LoadLevel("starting_map"_S); LoadLevel("starting_map"_S,NO_MUSIC_CHANGE);
ChangePlayerClass(WARRIOR); ChangePlayerClass(WARRIOR);
GameState::Initialize(); GameState::Initialize();
@ -1821,295 +1821,353 @@ void AiL::InitializeLevel(std::string mapFile,MapName map){
} }
} }
void AiL::LoadLevel(MapName map){ void AiL::LoadLevel(MapName map,MusicChange changeMusic){
LoadingScreen::loading=true; LoadingScreen::loading=true;
#pragma region Reset all data (Loading phase 1) _PrepareLevel(map,changeMusic);
if(game->MAP_DATA.count(map)==0)ERR(std::format("WARNING! Could not load map {}! Does not exist! Refer to levels.txt for valid maps.",map)); }
if(game->MAP_DATA[map].GetMapType()=="Hub"&&GameState::STATE!=GameState::states[States::GAME_HUB])ERR("WARNING! A hub level should only be initiated in the GAME_HUB game state!");
#pragma region Reset Environmental Audio
for(EnvironmentalAudio&audio:MAP_DATA[GetCurrentLevel()].environmentalAudioData){
audio.Deactivate();
}
#pragma endregion
SPAWNER_LIST.clear(); void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
foregroundTileGroups.clear(); LoadingScreen::Reset();
upperForegroundTileGroups.clear(); previousLevel=currentLevel;
MONSTER_LIST.clear();
ZONE_LIST.clear();
ItemDrop::drops.clear();
GameEvent::events.clear();
worldColor=WHITE;
worldColorFunc=[&](vi2d pos){return game->worldColor;};
currentLevel=map; currentLevel=map;
levelTime=0; #pragma region Reset all data (Loading phase 1)
bossName=""; LoadingScreen::AddPhase([&](){
encounterDuration=0; if(game->MAP_DATA.count(GetCurrentLevel())==0)ERR(std::format("WARNING! Could not load map {}! Does not exist! Refer to levels.txt for valid maps.",map));
totalDamageDealt=0; if(game->MAP_DATA[GetCurrentLevel()].GetMapType()=="Hub"&&GameState::STATE!=GameState::states[States::GAME_HUB])ERR("WARNING! A hub level should only be initiated in the GAME_HUB game state!");
encounterStarted=false;
totalBossEncounterMobs=0;
Inventory::Clear("Monster Loot");
Inventory::Clear("Stage Loot");
GetPlayer()->hp=GetPlayer()->GetMaxHealth();
GetPlayer()->mana=GetPlayer()->GetMaxMana();
GetPlayer()->SetState(State::NORMAL);
GetPlayer()->GetCastInfo()={};
GetPlayer()->ResetAccumulatedXP();
#pragma endregion #pragma region Reset Environmental Audio
for(EnvironmentalAudio&audio:MAP_DATA[previousLevel].environmentalAudioData){
audio.Deactivate();
}
#pragma endregion
ZONE_LIST=game->MAP_DATA[game->GetCurrentLevel()].ZoneData; SPAWNER_LIST.clear();
foregroundTileGroups.clear();
upperForegroundTileGroups.clear();
MONSTER_LIST.clear();
ZONE_LIST.clear();
ItemDrop::drops.clear();
GameEvent::events.clear();
worldColor=WHITE;
worldColorFunc=[&](vi2d pos){return game->worldColor;};
levelTime=0;
bossName="";
encounterDuration=0;
totalDamageDealt=0;
encounterStarted=false;
totalBossEncounterMobs=0;
Inventory::Clear("Monster Loot");
Inventory::Clear("Stage Loot");
GetPlayer()->hp=GetPlayer()->GetMaxHealth();
GetPlayer()->mana=GetPlayer()->GetMaxMana();
GetPlayer()->SetState(State::NORMAL);
GetPlayer()->GetCastInfo()={};
GetPlayer()->ResetAccumulatedXP();
ZONE_LIST=game->MAP_DATA[game->GetCurrentLevel()].ZoneData;
return true;
});
#pragma endregion
#pragma region Monster Spawn Data Setup (Loading phase 2) #pragma region Monster Spawn Data Setup (Loading phase 2)
for(auto&[key,value]:MAP_DATA[map].SpawnerData){ LoadingScreen::AddPhase([&](){
SpawnerTag&spawnData=MAP_DATA[map].SpawnerData[key]; for(auto&[key,value]:MAP_DATA[GetCurrentLevel()].SpawnerData){
std::vector<std::pair<std::string,vf2d>>monster_list; SpawnerTag&spawnData=MAP_DATA[GetCurrentLevel()].SpawnerData[key];
std::vector<std::pair<std::string,vf2d>>monster_list;
vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2;
for(XMLTag&monster:spawnData.monsters){ vf2d spawnerRadius=vf2d{spawnData.ObjectData.GetFloat("width"),spawnData.ObjectData.GetFloat("height")}/2;
std::string monsterName=monster.GetString("value"); for(XMLTag&monster:spawnData.monsters){
monster_list.push_back({monsterName,{monster.GetInteger("x")-spawnData.ObjectData.GetFloat("x"),monster.GetInteger("y")-spawnData.ObjectData.GetFloat("y")}}); std::string monsterName=monster.GetString("value");
monster_list.push_back({monsterName,{monster.GetInteger("x")-spawnData.ObjectData.GetFloat("x"),monster.GetInteger("y")-spawnData.ObjectData.GetFloat("y")}});
}
SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel,spawnData.bossNameDisplay});
} }
SPAWNER_LIST.push_back(MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel,spawnData.bossNameDisplay}); return true;
} });
#pragma endregion #pragma endregion
#pragma region Identify Upper Foreground Tiles (Loading phase 3) #pragma region Identify Upper Foreground Tiles (Loading phase 3)
auto GetUpperZones=[&](){ LoadingScreen::AddPhase([&](){
for(auto&zoneSet:MAP_DATA[map].ZoneData){ auto GetUpperZones=[&](){
if(zoneSet.first=="UpperZone"){ //We are interested in all upper zones. for(auto&zoneSet:MAP_DATA[GetCurrentLevel()].ZoneData){
return zoneSet.second; if(zoneSet.first=="UpperZone"){ //We are interested in all upper zones.
return zoneSet.second;
}
} }
} return std::vector<ZoneData>{};
return std::vector<ZoneData>{}; };
}; for(ZoneData&zone:GetUpperZones()){
for(ZoneData&zone:GetUpperZones()){ int zoneX=zone.zone.pos.x/game->GetCurrentMapData().tilewidth; //snap to grid
int zoneX=zone.zone.pos.x/game->GetCurrentMapData().tilewidth; //snap to grid int zoneY=zone.zone.pos.y/game->GetCurrentMapData().tilewidth;
int zoneY=zone.zone.pos.y/game->GetCurrentMapData().tilewidth; int zoneW=zone.zone.right().start.x/game->GetCurrentMapData().tilewidth-zoneX;
int zoneW=zone.zone.right().start.x/game->GetCurrentMapData().tilewidth-zoneX; int zoneH=zone.zone.bottom().start.y/game->GetCurrentMapData().tilewidth-zoneY;
int zoneH=zone.zone.bottom().start.y/game->GetCurrentMapData().tilewidth-zoneY; for(int x=zoneX;x<zoneX+zoneW;x++){
for(int x=zoneX;x<zoneX+zoneW;x++){ for(int y=zoneY;y<zoneY+zoneH;y++){
for(int y=zoneY;y<zoneY+zoneH;y++){ for(LayerTag&layer:MAP_DATA[GetCurrentLevel()].LayerData){
for(LayerTag&layer:MAP_DATA[map].LayerData){ int tile=layer.tiles[y][x]-1;
int tile=layer.tiles[y][x]-1; TilesheetData tileSheet=GetTileSheet(currentLevel,tile);
TilesheetData tileSheet=GetTileSheet(currentLevel,tile); int tileSheetIndex=tile-(tileSheet.firstgid-1);
int tileSheetIndex=tile-(tileSheet.firstgid-1); if(IsForegroundTile(tileSheet,tileSheetIndex)){
if(IsForegroundTile(tileSheet,tileSheetIndex)){ layer.tiles[y][x]+=1000000;
layer.tiles[y][x]+=1000000; }
} }
} }
} }
} }
} return true;
});
#pragma endregion #pragma endregion
#pragma region Foreground and Upper Foreground Tile Fade Group Setup (Loading phase 4) #pragma region Foreground and Upper Foreground Tile Fade Group Setup (Loading phase 4)
std::set<vi2d>foregroundTilesAdded,upperForegroundTilesAdded; LoadingScreen::AddPhase([&](){
for(int x=0;x<GetCurrentMapData().width;x++){ std::set<vi2d>foregroundTilesAdded,upperForegroundTilesAdded;
for(int y=0;y<GetCurrentMapData().height;y++){ for(int x=0;x<GetCurrentMapData().width;x++){
int layerID=0; for(int y=0;y<GetCurrentMapData().height;y++){
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){ int layerID=0;
if(Unlock::IsUnlocked(layer.unlockCondition)){ for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
int tileID=layer.tiles[y][x]-1; if(Unlock::IsUnlocked(layer.unlockCondition)){
if(tileID!=-1){ int tileID=layer.tiles[y][x]-1;
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID); if(tileID!=-1){
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth; TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight; int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1); int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth; int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetY=realTileSheetIndex/tileSheetWidth; int tileSheetX=realTileSheetIndex%tileSheetWidth;
int checkTileIndex=tileID; int tileSheetY=realTileSheetIndex/tileSheetWidth;
int checkTileID=tileSheetIndex; int checkTileIndex=tileID;
#pragma region TileGroupShenanigans int checkTileID=tileSheetIndex;
auto SetupTileGroups=[&](std::function<bool(TilesheetData,int)>IsForeground,TileRenderData tile,std::set<vi2d>&foregroundTilesIncluded,std::vector<TileGroup>&groups){ #pragma region TileGroupShenanigans
if(foregroundTilesIncluded.find({x,y})==foregroundTilesIncluded.end()&&IsForeground(tileSheet,tileSheetIndex)){ auto SetupTileGroups=[&](std::function<bool(TilesheetData,int)>IsForeground,TileRenderData tile,std::set<vi2d>&foregroundTilesIncluded,std::vector<TileGroup>&groups){
std::queue<vi2d>tileGroupChecks; if(foregroundTilesIncluded.find({x,y})==foregroundTilesIncluded.end()&&IsForeground(tileSheet,tileSheetIndex)){
TileGroup group; std::queue<vi2d>tileGroupChecks;
foregroundTilesIncluded.insert({x,y}); TileGroup group;
group.InsertTile(tile); foregroundTilesIncluded.insert({x,y});
if(x>0&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{-1,0})==foregroundTilesIncluded.end())tileGroupChecks.push({x-1,y}); group.InsertTile(tile);
if(x<GetCurrentMapData().width-1&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{1,0})==foregroundTilesIncluded.end())tileGroupChecks.push({x+1,y}); if(x>0&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{-1,0})==foregroundTilesIncluded.end())tileGroupChecks.push({x-1,y});
if(y>0&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{0,-1})==foregroundTilesIncluded.end())tileGroupChecks.push({x,y-1}); if(x<GetCurrentMapData().width-1&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{1,0})==foregroundTilesIncluded.end())tileGroupChecks.push({x+1,y});
if(y<GetCurrentMapData().height-1&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{0,1})==foregroundTilesIncluded.end())tileGroupChecks.push({x,y+1}); if(y>0&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{0,-1})==foregroundTilesIncluded.end())tileGroupChecks.push({x,y-1});
auto IterateThroughOtherLayers=[&](vi2d pos,bool loopAll=false){ if(y<GetCurrentMapData().height-1&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{0,1})==foregroundTilesIncluded.end())tileGroupChecks.push({x,y+1});
int layer2ID=0; auto IterateThroughOtherLayers=[&](vi2d pos,bool loopAll=false){
bool hadForeground=false; int layer2ID=0;
for(LayerTag&layer2:MAP_DATA[currentLevel].LayerData){ bool hadForeground=false;
if(!loopAll&&&layer==&layer2){layer2ID++;continue;}; for(LayerTag&layer2:MAP_DATA[currentLevel].LayerData){
int tileID=layer2.tiles[pos.y][pos.x]-1; if(!loopAll&&&layer==&layer2){layer2ID++;continue;};
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID%1000000); int tileID=layer2.tiles[pos.y][pos.x]-1;
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth; TilesheetData tileSheet=GetTileSheet(currentLevel,tileID%1000000);
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight; int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1); int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth; int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetY=realTileSheetIndex/tileSheetWidth; int tileSheetX=realTileSheetIndex%tileSheetWidth;
TileRenderData tile={tileSheet,vi2d{pos.x,pos.y}*game->GetCurrentMapData().tilewidth,vi2d{tileSheetX,tileSheetY}*game->GetCurrentMapData().tilewidth,realTileSheetIndex,layer2ID}; int tileSheetY=realTileSheetIndex/tileSheetWidth;
if(IsForeground(tileSheet,tileSheetIndex)){ TileRenderData tile={tileSheet,vi2d{pos.x,pos.y}*game->GetCurrentMapData().tilewidth,vi2d{tileSheetX,tileSheetY}*game->GetCurrentMapData().tilewidth,realTileSheetIndex,layer2ID};
foregroundTilesIncluded.insert({pos.x,pos.y}); if(IsForeground(tileSheet,tileSheetIndex)){
group.InsertTile(tile); foregroundTilesIncluded.insert({pos.x,pos.y});
hadForeground=true; group.InsertTile(tile);
hadForeground=true;
}
layer2ID++;
} }
layer2ID++; return hadForeground;
} };
return hadForeground; IterateThroughOtherLayers({x,y});
}; while(!tileGroupChecks.empty()){
IterateThroughOtherLayers({x,y}); vi2d&pos=tileGroupChecks.front();
while(!tileGroupChecks.empty()){ if(IterateThroughOtherLayers(pos,true)){
vi2d&pos=tileGroupChecks.front(); foregroundTilesIncluded.insert({pos.x,pos.y}); //Regardless of if we found a foreground tile or not, we need to add this to not get stuck in an infinite loop.
if(IterateThroughOtherLayers(pos,true)){ vi2d targetPos=pos+vi2d{-1,0};
foregroundTilesIncluded.insert({pos.x,pos.y}); //Regardless of if we found a foreground tile or not, we need to add this to not get stuck in an infinite loop. if(pos.x>0&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
vi2d targetPos=pos+vi2d{-1,0}; targetPos=pos+vi2d{1,0};
if(pos.x>0&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);} if(pos.x<GetCurrentMapData().width-1&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{1,0}; targetPos=pos+vi2d{0,-1};
if(pos.x<GetCurrentMapData().width-1&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);} if(pos.y>0&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{0,-1}; targetPos=pos+vi2d{0,1};
if(pos.y>0&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);} if(pos.y<GetCurrentMapData().height-1&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{0,1}; }
if(pos.y<GetCurrentMapData().height-1&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);} tileGroupChecks.pop();
} }
tileGroupChecks.pop(); groups.push_back(group);
} }
groups.push_back(group); };
} TileRenderData tile={tileSheet,vi2d{x,y}*game->GetCurrentMapData().tilewidth,vi2d{tileSheetX,tileSheetY}*game->GetCurrentMapData().tilewidth,realTileSheetIndex,layerID};
}; SetupTileGroups([&](TilesheetData sheet,int tileID){return IsForegroundTile(sheet,tileID);},tile,foregroundTilesAdded,foregroundTileGroups);
TileRenderData tile={tileSheet,vi2d{x,y}*game->GetCurrentMapData().tilewidth,vi2d{tileSheetX,tileSheetY}*game->GetCurrentMapData().tilewidth,realTileSheetIndex,layerID}; SetupTileGroups([&](TilesheetData sheet,int tileID){return IsUpperForegroundTile(tileID);},tile,upperForegroundTilesAdded,upperForegroundTileGroups);
SetupTileGroups([&](TilesheetData sheet,int tileID){return IsForegroundTile(sheet,tileID);},tile,foregroundTilesAdded,foregroundTileGroups); #pragma endregion
SetupTileGroups([&](TilesheetData sheet,int tileID){return IsUpperForegroundTile(tileID);},tile,upperForegroundTilesAdded,upperForegroundTileGroups); }
#pragma endregion
} }
layerID++;
} }
layerID++;
} }
} }
}
for(TileGroup&group:foregroundTileGroups){ for(TileGroup&group:foregroundTileGroups){
std::sort(group.GetTiles().begin(),group.GetTiles().end(),[](TileRenderData&t1,TileRenderData&t2){return t1.layerID<t2.layerID;}); std::sort(group.GetTiles().begin(),group.GetTiles().end(),[](TileRenderData&t1,TileRenderData&t2){return t1.layerID<t2.layerID;});
} }
for(TileGroup&group:upperForegroundTileGroups){ for(TileGroup&group:upperForegroundTileGroups){
std::sort(group.GetTiles().begin(),group.GetTiles().end(),[](TileRenderData&t1,TileRenderData&t2){return t1.layerID<t2.layerID;}); std::sort(group.GetTiles().begin(),group.GetTiles().end(),[](TileRenderData&t1,TileRenderData&t2){return t1.layerID<t2.layerID;});
} }
return true;
});
#pragma endregion #pragma endregion
#pragma region Foreground and Upper Foreground Tile Fade Group Individual Object Grouping Splitting (Loading phase 5) #pragma region Foreground and Upper Foreground Tile Fade Group Individual Object Grouping Splitting (Loading phase 5)
auto SplitUp=[&](std::vector<TileGroup>&group){ LoadingScreen::AddPhase([&](){
std::multimap<vi2d,TileRenderData>data; auto SplitUp=[&](std::vector<TileGroup>&group){
using TileDataGroup=std::multimap<vi2d,TileRenderData>; //See below. std::multimap<vi2d,TileRenderData>data;
std::vector<TileDataGroup>splitUpData; //This stores every tile group with tiles as a multi map. using TileDataGroup=std::multimap<vi2d,TileRenderData>; //See below.
std::set<vi2d>iteratedTiles; std::vector<TileDataGroup>splitUpData; //This stores every tile group with tiles as a multi map.
for(TileGroup&group:group){ std::set<vi2d>iteratedTiles;
for(TileRenderData&tile:group.GetTiles()){ for(TileGroup&group:group){
data.insert({tile.pos,tile}); for(TileRenderData&tile:group.GetTiles()){
data.insert({tile.pos,tile});
}
} }
}
auto IsAdjacent=[](int tile1,int tile2,int tileSheetWidth){ auto IsAdjacent=[](int tile1,int tile2,int tileSheetWidth){
return abs(tile1-tile2)==1||abs(tile1-tile2)>=tileSheetWidth-1&&abs(tile1-tile2)<=tileSheetWidth+1; return abs(tile1-tile2)==1||abs(tile1-tile2)>=tileSheetWidth-1&&abs(tile1-tile2)<=tileSheetWidth+1;
}; };
for(auto&[key,tile]:data){ for(auto&[key,tile]:data){
if(iteratedTiles.count(key))continue; if(iteratedTiles.count(key))continue;
vi2d loc=key; vi2d loc=key;
auto loc_tiles=data.equal_range(loc); auto loc_tiles=data.equal_range(loc);
for(auto&it=loc_tiles.first;it!=loc_tiles.second;++it){ //For each tile that exists at this position... for(auto&it=loc_tiles.first;it!=loc_tiles.second;++it){ //For each tile that exists at this position...
TileRenderData&tile=(*it).second; TileRenderData&tile=(*it).second;
bool groupFound=false; bool groupFound=false;
for(TileDataGroup&group:splitUpData){ //See if this position can fit into any existing tile groups for(TileDataGroup&group:splitUpData){ //See if this position can fit into any existing tile groups
for(int y=-game->GetCurrentMapData().tileheight;y<=game->GetCurrentMapData().tileheight;y+=game->GetCurrentMapData().tileheight){ for(int y=-game->GetCurrentMapData().tileheight;y<=game->GetCurrentMapData().tileheight;y+=game->GetCurrentMapData().tileheight){
for(int x=-game->GetCurrentMapData().tilewidth;x<=game->GetCurrentMapData().tilewidth;x+=game->GetCurrentMapData().tilewidth){ for(int x=-game->GetCurrentMapData().tilewidth;x<=game->GetCurrentMapData().tilewidth;x+=game->GetCurrentMapData().tilewidth){
if(x!=0||y!=0){ //Check every adjacent location for a possible adjacent tile. if(x!=0||y!=0){ //Check every adjacent location for a possible adjacent tile.
vi2d checkOffset=loc+vi2d{x,y}; vi2d checkOffset=loc+vi2d{x,y};
auto find_tiles=group.equal_range(checkOffset);//Each tile group consists of tiles that may be adjacent to us. Find all tiles that are adjacent to us in this tile group. auto find_tiles=group.equal_range(checkOffset);//Each tile group consists of tiles that may be adjacent to us. Find all tiles that are adjacent to us in this tile group.
for(auto&it=find_tiles.first;it!=find_tiles.second;++it){ for(auto&it=find_tiles.first;it!=find_tiles.second;++it){
//These are all tiles that were found adjacent to the location we are checking for. See if they match a potential group. //These are all tiles that were found adjacent to the location we are checking for. See if they match a potential group.
TileRenderData&foundTile=(*it).second; TileRenderData&foundTile=(*it).second;
if(tile.tileSheet.tileset==foundTile.tileSheet.tileset){ //Let's first see if they are even in the same tileset. if(tile.tileSheet.tileset==foundTile.tileSheet.tileset){ //Let's first see if they are even in the same tileset.
//Let's get how many tiles wide this tile sheet is. //Let's get how many tiles wide this tile sheet is.
int tileWidth=tile.tileSheet.tileset->tilewidth; int tileWidth=tile.tileSheet.tileset->tilewidth;
int tileSheetWidth=tile.tileSheet.tileset->tileset->Sprite()->width/tileWidth; int tileSheetWidth=tile.tileSheet.tileset->tileset->Sprite()->width/tileWidth;
if(IsAdjacent(tile.tileID,foundTile.tileID,tileSheetWidth)){ if(IsAdjacent(tile.tileID,foundTile.tileID,tileSheetWidth)){
group.insert({loc,tile});//We add this tile to the group! It is adjacent! group.insert({loc,tile});//We add this tile to the group! It is adjacent!
groupFound=true; groupFound=true;
goto groupIterationDone; goto groupIterationDone;
}
} }
} }
} }
} }
} }
} }
groupIterationDone:
if(!groupFound){
splitUpData.push_back({});
splitUpData.back().insert({loc,tile}); //Since we could not find a group to fit in, we had to start a brand new group.
}
} }
groupIterationDone: iteratedTiles.insert(loc);
if(!groupFound){
splitUpData.push_back({});
splitUpData.back().insert({loc,tile}); //Since we could not find a group to fit in, we had to start a brand new group.
}
} }
iteratedTiles.insert(loc); group.clear();
} for(auto&split:splitUpData){
group.clear(); TileGroup newGroup;
for(auto&split:splitUpData){ for(auto&[key,value]:split){
TileGroup newGroup; newGroup.InsertTile(value);
for(auto&[key,value]:split){ }
newGroup.InsertTile(value); group.push_back(newGroup);
} }
group.push_back(newGroup); };
} SplitUp(foregroundTileGroups);
}; SplitUp(upperForegroundTileGroups);
SplitUp(foregroundTileGroups); return true;
SplitUp(upperForegroundTileGroups); });
#pragma endregion #pragma endregion
#pragma region Bridge Layer Setup (Loading Phase 6) #pragma region Bridge Layer Setup (Loading Phase 6)
bridgeLayerIndex=-1; LoadingScreen::AddPhase([&](){
for(int counter=0;LayerTag&layer:MAP_DATA[map].LayerData){ bridgeLayerIndex=-1;
if(IsBridgeLayer(layer)){ for(int counter=0;LayerTag&layer:MAP_DATA[GetCurrentLevel()].LayerData){
bridgeLayerIndex=counter; if(IsBridgeLayer(layer)){
bridgeLayerIndex=counter;
}
counter++;
} }
counter++; return true;
} });
#pragma endregion #pragma endregion
#pragma region Setup NPCs (Loading Phase 7) #pragma region Setup NPCs (Loading Phase 7)
for(NPCData data:game->MAP_DATA[game->GetCurrentLevel()].npcs){ LoadingScreen::AddPhase([&](){
if(Unlock::IsUnlocked(data.unlockCondition)){ for(NPCData data:game->MAP_DATA[game->GetCurrentLevel()].npcs){
MONSTER_LIST.push_back(Monster{data.spawnPos,MONSTER_DATA[data.name]}); if(Unlock::IsUnlocked(data.unlockCondition)){
MONSTER_LIST.back().iframe_timer=INFINITE; MONSTER_LIST.push_back(Monster{data.spawnPos,MONSTER_DATA[data.name]});
MONSTER_LIST.back().npcData=data; MONSTER_LIST.back().iframe_timer=INFINITE;
} MONSTER_LIST.back().npcData=data;
} }
}
return true;
});
#pragma endregion #pragma endregion
#pragma region Setup Player and Camera (Loading Phase 8) #pragma region Setup Player and Camera (Loading Phase 8)
player->GetAbility1().cooldown=0.f; LoadingScreen::AddPhase([&](){
player->GetAbility2().cooldown=0.f; player->GetAbility1().cooldown=0.f;
player->GetAbility3().cooldown=0.f; player->GetAbility2().cooldown=0.f;
player->GetAbility4().cooldown=0.f; player->GetAbility3().cooldown=0.f;
player->GetRightClickAbility().cooldown=0.f; player->GetAbility4().cooldown=0.f;
player->useItem1.cooldown=0.f; player->GetRightClickAbility().cooldown=0.f;
player->useItem2.cooldown=0.f; player->useItem1.cooldown=0.f;
player->useItem3.cooldown=0.f; player->useItem2.cooldown=0.f;
player->useItem3.cooldown=0.f;
player->upperLevel=false; //Assume player starts on lower level.
player->ForceSetPos(MAP_DATA[map].MapData.playerSpawnLocation); //Normal set pos does one axis and then the other, so this will make sure that we actually end up at the right spot and ignore collision rules. player->upperLevel=false; //Assume player starts on lower level.
player->ForceSetPos(MAP_DATA[GetCurrentLevel()].MapData.playerSpawnLocation); //Normal set pos does one axis and then the other, so this will make sure that we actually end up at the right spot and ignore collision rules.
vf2d cameraStartPos=player->GetPos()+vf2d(-24*6,0);
camera.MoveCamera(cameraStartPos); vf2d cameraStartPos=player->GetPos()+vf2d(-24*6,0);
camera.MoveCamera(cameraStartPos);
return true;
});
#pragma endregion #pragma endregion
#pragma region Setup Pathfinding (Loading Phase 9) #pragma region Setup Pathfinding (Loading Phase 9)
pathfinder.Initialize(); LoadingScreen::AddPhase([&](){
pathfinder.Initialize();
return true;
});
#pragma endregion #pragma endregion
Audio::SetAudioEvent("Default Volume"); if(changeMusic==PLAY_LEVEL_MUSIC){
game->audioEngine.fullyLoaded=true; //We assume there's no audio to load, so we just set the audio as fully loaded by default. #pragma region Audio Preparation (Loading Phase 10)
if(MAP_DATA[map].bgmSongName.length()>0){ LoadingScreen::AddPhase([&](){
Audio::PlayBGM(MAP_DATA[map].bgmSongName); Audio::SetAudioEvent("Default Volume");
DisableFadeIn(true); game->audioEngine.fullyLoaded=true; //We assume there's no audio to load, so we just set the audio as fully loaded by default.
if(MAP_DATA[GetCurrentLevel()].bgmSongName.length()>0){
Audio::PrepareBGM(MAP_DATA[GetCurrentLevel()].bgmSongName);
DisableFadeIn(true);
}
return true;
});
#pragma endregion
//Until the audio has stopped (by waiting for a set amount of time), we will respect the audio engine's wishes and not proceed.
LoadingScreen::DeferLoad([&](){return audioEngine.playBGMWaitTime==0.f;}); //This is the wait time for the audio engine to finish.
#pragma region Audio Channel Loading (Count based on Audio::GetPrepareBGMLoopIterations)
for(int i=0;i<Audio::GetPrepareBGMLoopIterations(MAP_DATA[GetCurrentLevel()].bgmSongName);i++){
LoadingScreen::AddPhase([&](){
Audio::UpdateLoop();
return true;
});
}
#pragma endregion
LoadingScreen::AddPhase([&](){
Audio::BGM&track=audioEngine.bgm[audioEngine.GetTrackName()];
for(int trackID:track.GetChannelIDs()){
audioEngine.Engine().Play(trackID,true);
}
return true;
});
} }
LoadingScreen::loading=false;
} }
bool AiL::IsUpperForegroundTile(int tileID){ bool AiL::IsUpperForegroundTile(int tileID){
@ -3113,7 +3171,7 @@ void AiL::RenderFadeout(){
} }
bool AiL::GamePaused(){ bool AiL::GamePaused(){
return fadeOutDuration>0||disableFadeIn||paused; return fadeOutDuration>0||disableFadeIn||paused||LoadingScreen::loading;
} }
void AiL::PauseGame(){ void AiL::PauseGame(){
@ -3351,9 +3409,9 @@ const bool AiL::GameInitialized()const {
rcode AiL::LoadResource(Renderable&renderable,std::string_view imgPath,bool filter,bool clamp){ rcode AiL::LoadResource(Renderable&renderable,std::string_view imgPath,bool filter,bool clamp){
rcode returnCode; rcode returnCode;
if(gamepack.Loaded()){ if(gamepack.Loaded()){
returnCode=renderable.Load(std::string(imgPath),&gamepack); returnCode=renderable.Load(std::string(imgPath),&gamepack,filter,clamp);
}else{ }else{
returnCode=renderable.Load(std::string(imgPath)); returnCode=renderable.Load(std::string(imgPath),nullptr,filter,clamp);
if("GENERATE_GAMEPACK"_B){ if("GENERATE_GAMEPACK"_B){
gamepack.AddFile(std::string(imgPath)); gamepack.AddFile(std::string(imgPath));
} }

@ -72,6 +72,10 @@ class AiL : public olc::PixelGameEngine
std::unique_ptr<Player>player; std::unique_ptr<Player>player;
SplashScreen splash; SplashScreen splash;
public: public:
enum MusicChange{
NO_MUSIC_CHANGE,
PLAY_LEVEL_MUSIC,
};
Pathfinding pathfinder; Pathfinding pathfinder;
static InputGroup KEY_BACK; static InputGroup KEY_BACK;
static InputGroup KEY_CONFIRM; static InputGroup KEY_CONFIRM;
@ -127,6 +131,7 @@ private:
float lastWorldShakeAdjust=0; float lastWorldShakeAdjust=0;
vf2d worldShakeVel={}; vf2d worldShakeVel={};
const float WORLD_SHAKE_ADJUST_MAX_TIME=0.4f; const float WORLD_SHAKE_ADJUST_MAX_TIME=0.4f;
MapName previousLevel="CAMPAIGN_1_1";
MapName currentLevel="CAMPAIGN_1_1"; MapName currentLevel="CAMPAIGN_1_1";
std::vector<TileGroup>foregroundTileGroups; std::vector<TileGroup>foregroundTileGroups;
std::vector<TileGroup>upperForegroundTileGroups; std::vector<TileGroup>upperForegroundTileGroups;
@ -169,6 +174,7 @@ private:
ResourcePack gamepack; ResourcePack gamepack;
void ValidateGameStatus(); void ValidateGameStatus();
void _PrepareLevel(MapName map,MusicChange changeMusic);
#ifndef __EMSCRIPTEN__ #ifndef __EMSCRIPTEN__
::discord::Result SetupDiscord(); ::discord::Result SetupDiscord();
#endif #endif
@ -186,7 +192,7 @@ public:
geom2d::rect<float>NO_COLLISION={{0.f,0.f,},{0.f,0.f}}; geom2d::rect<float>NO_COLLISION={{0.f,0.f,},{0.f,0.f}};
TileTransformedView view; TileTransformedView view;
void InitializeLevel(std::string mapFile,MapName map); void InitializeLevel(std::string mapFile,MapName map);
void LoadLevel(MapName map); void LoadLevel(MapName map,MusicChange changeMusic=PLAY_LEVEL_MUSIC);
void HandleUserInput(float fElapsedTime); void HandleUserInput(float fElapsedTime);
void UpdateCamera(float fElapsedTime); void UpdateCamera(float fElapsedTime);
void UpdateEffects(float fElapsedTime); void UpdateEffects(float fElapsedTime);

@ -160,10 +160,14 @@ void Audio::BGM::Load(){
if(!Self().trackLoadStarted){ if(!Self().trackLoadStarted){
Self().trackLoadStarted=true; Self().trackLoadStarted=true;
if(Self().BGMIsPlaying()){ if(Self().BGMIsPlaying()){
if(Self().GetTrackName()==songFileName)return; //We are already playing the current track. if(Self().GetTrackName()==songFileName){ //We are already playing the current track.
BGM&bgm=Self().bgm[Self().GetTrackName()]; Self().trackLoadComplete=Self().channelPlayingComplete=Self().fullyLoaded=true;
if(Self().BGMIsPlaying()){ return;
bgm.Unload(); }else{
BGM&bgm=Self().bgm[Self().GetTrackName()];
if(Self().BGMIsPlaying()){
bgm.Unload();
}
} }
} }
Self().currentBGM=songFileName; Self().currentBGM=songFileName;
@ -290,22 +294,22 @@ void Audio::UpdateLoop(){
Self().currentLoopIndex=0; Self().currentLoopIndex=0;
Self().channelPlayingStarted=true; Self().channelPlayingStarted=true;
}else{ }else{
int trackID=track.GetChannelIDs()[Self().currentLoopIndex]; int trackID=track.GetChannelIDs()[Self().currentLoopIndex];
float channelVol=track.GetVolume(Self().currentAudioEvent,Self().currentLoopIndex); float channelVol=track.GetVolume(Self().currentAudioEvent,Self().currentLoopIndex);
Self().prevVolumes.push_back(channelVol); Self().prevVolumes.push_back(channelVol);
Self().targetVolumes.push_back(channelVol); Self().targetVolumes.push_back(channelVol);
Engine().SetVolume(trackID,channelVol*GetBGMVolume()); Engine().SetVolume(trackID,channelVol*GetBGMVolume());
Engine().Play(trackID,Self().playParams.loop);
#pragma region Handle threaded loop indexing #pragma region Handle threaded loop indexing
Self().currentLoopIndex++; Self().currentLoopIndex++;
if(Self().currentLoopIndex>=track.GetChannelIDs().size()){ if(Self().currentLoopIndex>=track.GetChannelIDs().size()){
Self().channelPlayingComplete=true; Self().channelPlayingComplete=true;
Self().fullyLoaded=true;
} }
#pragma endregion #pragma endregion
} }
}else{ }else
Self().fullyLoaded=true; if(!Self().fullyLoaded){
ERR("Invalid loading state or too many calls to initialize audio loop! The audio is still not fully loaded!");
} }
} }
} }
@ -316,12 +320,18 @@ void Audio::PlayBGM(const std::string_view sound,const bool loop){
} }
void Audio::Update(){ void Audio::Update(){
if(Self().playBGMWaitTime>0.f){ if(Self().fadeToTargetVolumeTime==0.f&&Self().playBGMWaitTime>0.f){
Self().playBGMWaitTime=std::max(Self().playBGMWaitTime-game->GetElapsedTime(),0.f); Self().playBGMWaitTime=std::max(Self().playBGMWaitTime-game->GetElapsedTime(),0.f);
if(Self().playBGMWaitTime==0.f&&Self().immediatelyLoadAudio){ if(Self().playBGMWaitTime==0.f&&Self().immediatelyLoadAudio){
while(!Self().BGMFullyLoaded()){ while(!Self().BGMFullyLoaded()){
UpdateLoop(); //We immediately load the file. In a loading screen setting we would defer UpdateLoop() such that we have extra time to update the screen, UpdateLoop() is divided into many parts of the music loading process. UpdateLoop(); //We immediately load the file. In a loading screen setting we would defer UpdateLoop() such that we have extra time to update the screen, UpdateLoop() is divided into many parts of the music loading process.
} }
//Start playing the tracks.
Audio::BGM&track=Self().bgm[Self().GetTrackName()];
for(int trackID:track.GetChannelIDs()){
Self().Engine().Play(trackID,true);
}
} }
} }
if(Self().fadeToTargetVolumeTime>0.f){ if(Self().fadeToTargetVolumeTime>0.f){
@ -364,3 +374,8 @@ float Audio::GetMuteMult(){
if(muted)return 0.f; if(muted)return 0.f;
return 1.f; return 1.f;
} }
int Audio::GetPrepareBGMLoopIterations(std::string_view sound){
BGM&newBgm=Self().bgm[std::string(sound)];
return newBgm.GetChannels().size()*2+2; //The channels list gets populated by calling newBgm.Load(), which then provides the list of channels that need to be loaded and played. This is why we multiply by 2. Each of the loading phases also consist of an initialization phase, so we add 2 as well.
}

@ -75,6 +75,8 @@ public:
static float&GetBGMVolume(); static float&GetBGMVolume();
static float&GetSFXVolume(); static float&GetSFXVolume();
static float GetMuteMult(); static float GetMuteMult();
//This will get a prepared BGM loop iteration count which is useful for loading stages.
static int GetPrepareBGMLoopIterations(std::string_view sound);
private: private:
bool trackLoadStarted=false; bool trackLoadStarted=false;
bool trackLoadComplete=false; bool trackLoadComplete=false;

@ -73,4 +73,5 @@ public:
virtual void GetAnyMousePress(int32_t mouseButton); virtual void GetAnyMousePress(int32_t mouseButton);
virtual void GetAnyMouseRelease(int32_t mouseButton); virtual void GetAnyMouseRelease(int32_t mouseButton);
static void ChangeState(States::State newState,float fadeOutDuration=0); static void ChangeState(States::State newState,float fadeOutDuration=0);
virtual void OnLevelLoad()=0;
}; };

@ -38,27 +38,71 @@ All rights reserved.
#include "AdventuresInLestoria.h" #include "AdventuresInLestoria.h"
#include "LoadingScreen.h" #include "LoadingScreen.h"
#include "util.h"
INCLUDE_game INCLUDE_game
INCLUDE_WINDOW_SIZE INCLUDE_WINDOW_SIZE
INCLUDE_ANIMATION_DATA
bool LoadingScreen::loading=false; bool LoadingScreen::loading=false;
int LoadingScreen::totalProgress=0;
int LoadingScreen::currentProgress=0; int LoadingScreen::currentProgress=0;
float LoadingScreen::waitTime=0.01f; int LoadingScreen::totalProgress=0;
std::queue<std::function<bool()>>LoadingScreen::loadingPhases;
void LoadingScreen::DeferLoad(float waitTime){ bool LoadingScreen::showGhost=false;
bool LoadingScreen::showLarge=false;
void LoadingScreen::DeferLoad(std::function<bool()>waitCondition){
AddPhase(waitCondition);
} }
void LoadingScreen::Update(){ void LoadingScreen::Update(){
if(loading){ if(loading){
if(loadingPhases.size()>0){
std::function<bool()>&loadFunc=loadingPhases.front();
if(loadFunc()){
currentProgress++;
loadingPhases.pop();
}
}else{
loading=false;
GameState::STATE->OnLevelLoad();
}
} }
} }
void LoadingScreen::Draw(){ void LoadingScreen::Draw(){
if(loading){ if(loading){
game->FillRectDecal({0,0},WINDOW_SIZE,VERY_DARK_GREEN); game->FillRectDecal({0,0},WINDOW_SIZE,{VERY_DARK_GREEN.r,VERY_DARK_GREEN.g,VERY_DARK_GREEN.b,230});
game->FillRectDecal({22.f,WINDOW_SIZE.y-46.f},{(float(currentProgress)/totalProgress)*(WINDOW_SIZE.x-48.f)+4.f,28.f},VERY_DARK_GREEN/2);
game->FillRectDecal({24.f,WINDOW_SIZE.y-48.f},{(float(currentProgress)/totalProgress)*(WINDOW_SIZE.x-48.f),24.f},DARK_YELLOW);
game->DrawShadowStringPropDecal({24.f,WINDOW_SIZE.y-60.f},"Loading...",{170,210,0},BLACK,{1.f,1.5f});
game->FillRectDecal({24.f,WINDOW_SIZE.y-48.f},{float(currentProgress/totalProgress)*WINDOW_SIZE.x-48,24.f},DARK_YELLOW); vf2d playerScale=vf2d(game->GetPlayer()->GetSizeMult(),game->GetPlayer()->GetSizeMult());
float scale=1.f;
if(showLarge){
scale=2.f;
}
const std::vector<Buff>attackBuffs=game->GetPlayer()->GetStatBuffs({"Attack","Attack %"});
Pixel blendCol=attackBuffs.size()>0?Pixel{255,uint8_t(255*abs(sin(1.4*attackBuffs[0].duration))),uint8_t(255*abs(sin(1.4*attackBuffs[0].duration)))}:WHITE;
if(showGhost){
blendCol=BLACK;
}
game->GetPlayer()->GetWalkEAnimation();
Animate2D::FrameSequence&playerWalkE=ANIMATION_DATA[game->GetPlayer()->GetWalkEAnimation()];
game->DrawPartialRotatedDecal({(float(currentProgress)/totalProgress)*(WINDOW_SIZE.x-48.f),WINDOW_SIZE.y-36.f},playerWalkE.GetFrame(game->GetRuntime()).GetSourceImage()->Decal(),game->GetPlayer()->GetSpinAngle(),{12,12},playerWalkE.GetFrame(game->GetRuntime()).GetSourceRect().pos,playerWalkE.GetFrame(game->GetRuntime()).GetSourceRect().size,playerScale*scale,blendCol);
} }
} }
void LoadingScreen::Reset(){
currentProgress=0;
totalProgress=0;
showGhost=util::random()%6==0;
showLarge=util::random()%6==0;
while(loadingPhases.size()>0)ERR("WARNING! Previous loading phase was not properly cleared! This probably means some part of a previous load did not execute!");
}
void LoadingScreen::AddPhase(std::function<bool()>loadFunc){
loadingPhases.push(loadFunc);
totalProgress++;
}

@ -37,13 +37,21 @@ All rights reserved.
#pragma endregion #pragma endregion
#pragma once #pragma once
#include <queue>
#include "olcUTIL_Animate2D.h"
class LoadingScreen{ class LoadingScreen{
public: public:
static bool loading; static bool loading;
static int totalProgress;
static int currentProgress; static int currentProgress;
static int totalProgress;
static float waitTime; static float waitTime;
static bool showGhost;
static bool showLarge;
static std::queue<std::function<bool()>>loadingPhases;
static void Update(); static void Update();
static void Draw(); static void Draw();
static void DeferLoad(float waitTime); static void DeferLoad(std::function<bool()>waitCondition);
static void Reset();
static void AddPhase(std::function<bool()>loadFunc);
}; };

@ -59,6 +59,8 @@ void State_GameHub::OnStateChange(GameState*prevState){
game->GetPlayer()->SetState(State::NORMAL); game->GetPlayer()->SetState(State::NORMAL);
game->LoadLevel("HUB"); game->LoadLevel("HUB");
}
void State_GameHub::OnLevelLoad(){
game->UpdateDiscordStatus("Hub Area",game->GetPlayer()->GetClassName()); game->UpdateDiscordStatus("Hub Area",game->GetPlayer()->GetClassName());
} }
void State_GameHub::OnUserUpdate(AiL*game){ void State_GameHub::OnUserUpdate(AiL*game){

@ -45,4 +45,5 @@ class State_GameHub:public State_GameRun{
virtual void OnStateChange(GameState*prevState)override final; virtual void OnStateChange(GameState*prevState)override final;
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void OnLevelLoad()override final;
}; };

@ -73,6 +73,7 @@ void State_GameRun::OnStateChange(GameState*prevState){
game->LoadLevel(State_OverworldMap::GetCurrentConnectionPoint().map); game->LoadLevel(State_OverworldMap::GetCurrentConnectionPoint().map);
} }
void State_GameRun::OnLevelLoad(){}
void State_GameRun::OnUserUpdate(AiL*game){ void State_GameRun::OnUserUpdate(AiL*game){
game->bossDisplayTimer=std::max(0.f,game->bossDisplayTimer-game->GetElapsedTime()); game->bossDisplayTimer=std::max(0.f,game->bossDisplayTimer-game->GetElapsedTime());
if(game->encounterStarted&&game->totalBossEncounterMobs>0){ if(game->encounterStarted&&game->totalBossEncounterMobs>0){

@ -46,6 +46,7 @@ protected:
virtual void OnStateChange(GameState*prevState)override; virtual void OnStateChange(GameState*prevState)override;
virtual void OnUserUpdate(AiL*game)override; virtual void OnUserUpdate(AiL*game)override;
virtual void Draw(AiL*game)override; virtual void Draw(AiL*game)override;
virtual void OnLevelLoad()override;
void FontTest(); void FontTest();
void FontSpriteTest(); void FontSpriteTest();
}; };

@ -76,6 +76,7 @@ void State_LevelComplete::OnStateChange(GameState*prevState){
game->GetPlayer()->SetState(State::NORMAL); game->GetPlayer()->SetState(State::NORMAL);
Menu::OpenMenu(LEVEL_COMPLETE); Menu::OpenMenu(LEVEL_COMPLETE);
}; };
void State_LevelComplete::OnLevelLoad(){}
void State_LevelComplete::OnUserUpdate(AiL*game){ void State_LevelComplete::OnUserUpdate(AiL*game){
if(levelUpTimer>0.f){ if(levelUpTimer>0.f){
levelUpTimer=std::max(0.f,levelUpTimer-game->GetElapsedTime()); levelUpTimer=std::max(0.f,levelUpTimer-game->GetElapsedTime());

@ -48,4 +48,5 @@ class State_LevelComplete:public GameState{
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void DrawOverlay(AiL*game)override final; virtual void DrawOverlay(AiL*game)override final;
virtual void OnLevelLoad()override final;
}; };

@ -48,6 +48,7 @@ void State_MainMenu::OnStateChange(GameState*prevState){
TitleScreen::Reset(); TitleScreen::Reset();
game->UpdateDiscordStatus("Main Menu",""); game->UpdateDiscordStatus("Main Menu","");
}; };
void State_MainMenu::OnLevelLoad(){}
void State_MainMenu::OnUserUpdate(AiL*game){ void State_MainMenu::OnUserUpdate(AiL*game){
TitleScreen::Update(); TitleScreen::Update();
if(AiL::KEY_CONFIRM.Released()){ if(AiL::KEY_CONFIRM.Released()){

@ -41,4 +41,5 @@ class State_MainMenu:public GameState{
virtual void OnStateChange(GameState*prevState)override final; virtual void OnStateChange(GameState*prevState)override final;
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void OnLevelLoad()override final;
}; };

@ -63,6 +63,8 @@ void State_OverworldMap::OnStateChange(GameState*prevState){
Component<MenuComponent>(MenuType::PAUSE,"Return to Camp Button")->SetGrayedOut(false); Component<MenuComponent>(MenuType::PAUSE,"Return to Camp Button")->SetGrayedOut(false);
SaveFile::SaveGame(); SaveFile::SaveGame();
game->LoadLevel("WORLD_MAP"); game->LoadLevel("WORLD_MAP");
};
void State_OverworldMap::OnLevelLoad(){
if(Menu::IsMenuOpen()){ if(Menu::IsMenuOpen()){
Menu::CloseAllMenus(); Menu::CloseAllMenus();
} }
@ -82,7 +84,7 @@ void State_OverworldMap::OnStateChange(GameState*prevState){
} }
Menu::OpenMenu(OVERWORLD_LEVEL_SELECT,false); Menu::OpenMenu(OVERWORLD_LEVEL_SELECT,false);
game->UpdateDiscordStatus("Overworld Map",game->GetPlayer()->GetClassName()); game->UpdateDiscordStatus("Overworld Map",game->GetPlayer()->GetClassName());
}; }
void State_OverworldMap::OnUserUpdate(AiL*game){ void State_OverworldMap::OnUserUpdate(AiL*game){
if(Menu::stack.size()>1)return; if(Menu::stack.size()>1)return;

@ -60,6 +60,7 @@ public:
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void DrawOverlay(AiL*game)override final; virtual void DrawOverlay(AiL*game)override final;
virtual void OnLevelLoad()override final;
static void StartLevel(); static void StartLevel();
static void UpdateCurrentConnectionPoint(const ConnectionPoint&connection); static void UpdateCurrentConnectionPoint(const ConnectionPoint&connection);
}; };

@ -42,6 +42,7 @@ All rights reserved.
void State_Story::OnStateChange(GameState*prevState){ void State_Story::OnStateChange(GameState*prevState){
Menu::CloseAllMenus(); Menu::CloseAllMenus();
}; };
void State_Story::OnLevelLoad(){}
void State_Story::OnUserUpdate(AiL*game){ void State_Story::OnUserUpdate(AiL*game){
VisualNovel::novel.Update(); VisualNovel::novel.Update();
}; };

@ -42,4 +42,5 @@ class State_Story:public GameState{
virtual void OnStateChange(GameState*prevState)override final; virtual void OnStateChange(GameState*prevState)override final;
virtual void OnUserUpdate(AiL*game)override final; virtual void OnUserUpdate(AiL*game)override final;
virtual void Draw(AiL*game)override final; virtual void Draw(AiL*game)override final;
virtual void OnLevelLoad()override final;
}; };

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 3 #define VERSION_MINOR 3
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_BUILD 7526 #define VERSION_BUILD 7558
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

Loading…
Cancel
Save