Clarified and split active zones from base map zones, adding corresponding functions. Changed zone data and map data to use safemaps instead. Separated and fixed map stage name from map names (ids). Fixed story nodes causing an additional map to be generated. Removed STORY and BLACKSMITH map enums. Release Build 12770.
Some checks failed
Emscripten Build / Build_and_Deploy_Web_Build (push) Failing after 3m6s
Some checks failed
Emscripten Build / Build_and_Deploy_Web_Build (push) Failing after 3m6s
This commit is contained in:
parent
2ccf58f938
commit
82ca726ad0
@ -18,12 +18,6 @@
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="GeometryTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MonsterTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\Adventures in Lestoria\discord-files\achievement_manager.cpp">
|
||||
<Filter>Source Files\discord-files</Filter>
|
||||
</ClCompile>
|
||||
@ -66,7 +60,7 @@
|
||||
<ClCompile Include="PlayerTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ItemTests.cpp">
|
||||
<ClCompile Include="BuffTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="EnchantTests.cpp">
|
||||
@ -75,10 +69,16 @@
|
||||
<ClCompile Include="EngineTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BuffTests.cpp">
|
||||
<ClCompile Include="FileTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="FileTests.cpp">
|
||||
<ClCompile Include="GeometryTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ItemTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MonsterTests.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
||||
@ -81,6 +81,7 @@ namespace BuffTests
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
#pragma region Setup a fake test map
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
game->_SetCurrentLevel("CAMPAIGN_1_1");
|
||||
ItemDrop::ClearDrops();
|
||||
@ -92,9 +93,10 @@ namespace BuffTests
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
void SetupMockMap(){
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
game->MAP_DATA.at("CAMPAIGN_1_1")=Map{};
|
||||
ItemDrop::ClearDrops();
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
@ -89,8 +89,9 @@ namespace EnchantTests
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
#pragma region Setup a fake test map and test monster
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
game->MAP_DATA["CAMPAIGN_1_1"]._SetMapData(MapTag{24*24,24*24,24,24});
|
||||
game->MAP_DATA.at("CAMPAIGN_1_1")._SetMapData(MapTag{24*24,24*24,24,24});
|
||||
ItemDrop::ClearDrops();
|
||||
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
MONSTER_DATA["TestName"]=testMonsterData;
|
||||
@ -108,6 +109,7 @@ namespace EnchantTests
|
||||
GFX.SetInitialized();
|
||||
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
TEST_METHOD_CLEANUP(EnchantTestCleanup){
|
||||
testGame->EndGame();
|
||||
|
||||
@ -83,6 +83,7 @@ namespace EngineTests
|
||||
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
|
||||
|
||||
#pragma region Setup a fake test map and test monster
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
ItemDrop::ClearDrops();
|
||||
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
@ -99,6 +100,7 @@ namespace EngineTests
|
||||
GFX.SetInitialized();
|
||||
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
TEST_METHOD_CLEANUP(CleanupTests){
|
||||
testGame->EndGame();
|
||||
|
||||
@ -82,6 +82,7 @@ namespace FileTests
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
#pragma region Setup a fake test map
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
game->_SetCurrentLevel("CAMPAIGN_1_1");
|
||||
ItemDrop::ClearDrops();
|
||||
@ -93,9 +94,10 @@ namespace FileTests
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
void SetupMockMap(){
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
game->MAP_DATA.at("CAMPAIGN_1_1")=Map{};
|
||||
ItemDrop::ClearDrops();
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
@ -89,6 +89,12 @@ namespace Game{
|
||||
game->ResetPlayerAndChangeClass(cl);
|
||||
pl=game->GetPlayer(); //The player pointer has been reassigned...
|
||||
}
|
||||
|
||||
inline void LoadLevel(const std::string&mapKeyname,AiL*const game){
|
||||
game->InitializeLevel("map_path"_S+DATA["Levels"][mapKeyname]["Map File"].GetString(),mapKeyname);
|
||||
game->SetupLevel(game->MAP_DATA[mapKeyname]);
|
||||
game->_SetCurrentLevel(mapKeyname);
|
||||
}
|
||||
}
|
||||
|
||||
namespace Test
|
||||
|
||||
@ -82,6 +82,7 @@ namespace ItemTests
|
||||
|
||||
testGame->ResetLevelStates();
|
||||
#pragma region Setup a fake test map and test monster
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
ItemDrop::ClearDrops();
|
||||
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
@ -95,6 +96,7 @@ namespace ItemTests
|
||||
testGame->olc_UpdateKeyFocus(true); //Force the game to be "focused" for tests. Required if we want keyboard inputs to work.
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
TEST_METHOD_CLEANUP(ItemCleanupTests){
|
||||
testGame->EndGame();
|
||||
|
||||
@ -88,9 +88,11 @@ namespace MonsterTests
|
||||
testGame->ResetLevelStates();
|
||||
|
||||
#pragma region Setup a fake test map
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
game->_SetCurrentLevel("CAMPAIGN_1_1");
|
||||
ItemDrop::ClearDrops();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
#pragma endregion
|
||||
|
||||
MonsterData testMonsterData{"TestName","Test Monster",30,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
@ -99,9 +101,10 @@ namespace MonsterTests
|
||||
Menu::themes.SetInitialized();
|
||||
GFX.SetInitialized();
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
void SetupMockMap(){
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
game->MAP_DATA.at("CAMPAIGN_1_1")=Map{};
|
||||
ItemDrop::ClearDrops();
|
||||
}
|
||||
#pragma endregion
|
||||
@ -557,8 +560,7 @@ namespace MonsterTests
|
||||
Monster&parrot{game->SpawnMonster({},MONSTER_DATA.at("Parrot"))};
|
||||
}
|
||||
TEST_METHOD(MonsterRunRightTest){
|
||||
testGame->InitializeLevel("map_path"_S+DATA["Levels"]["TEST_MAP"]["Map File"].GetString(),"TEST_MAP");
|
||||
testGame->_SetCurrentLevel("TEST_MAP");
|
||||
Game::LoadLevel("TEST_MAP",testGame.get());
|
||||
testGame->GetPlayer()->ForceSetPos({100,100});
|
||||
Monster&boar{game->SpawnMonster({24,24},MONSTER_DATA.at("Boar"))};
|
||||
Game::Update(0.f); // Make sure monster spawns first.
|
||||
@ -568,8 +570,7 @@ namespace MonsterTests
|
||||
Assert::IsTrue(originalBoarPos+vf2d{50.f*boar.GetMoveSpdMult(),0.f}==boar.GetPos(),util::wformat("The boar should have moved {} units in half a second. Expected {}=={}",50.f*boar.GetMoveSpdMult(),(originalBoarPos+vf2d{50.f*boar.GetMoveSpdMult(),0.f}).str(),boar.GetPos().str()).c_str());
|
||||
}
|
||||
TEST_METHOD(MonsterHasteMoveTest){
|
||||
testGame->InitializeLevel("map_path"_S+DATA["Levels"]["TEST_MAP"]["Map File"].GetString(),"TEST_MAP");
|
||||
testGame->_SetCurrentLevel("TEST_MAP");
|
||||
Game::LoadLevel("TEST_MAP",testGame.get());
|
||||
Monster&parrot{game->SpawnMonster({24,24},MONSTER_DATA.at("Parrot"))};
|
||||
Game::Update(0.f); // Make sure monster spawns first.
|
||||
parrot.strategy="[TEST]Run Right";
|
||||
|
||||
@ -84,6 +84,7 @@ namespace PlayerTests
|
||||
GameState::STATE=GameState::states.at(States::State::GAME_RUN);
|
||||
|
||||
#pragma region Setup a fake test map and test monster
|
||||
game->MAP_DATA.Unlock();
|
||||
game->MAP_DATA["CAMPAIGN_1_1"];
|
||||
ItemDrop::ClearDrops();
|
||||
MonsterData testMonsterData{"TestName","Test Monster",1000,10,5,{MonsterDropData{"Health Potion",100.f,1,1}},200.f};
|
||||
@ -100,6 +101,7 @@ namespace PlayerTests
|
||||
GFX.SetInitialized();
|
||||
|
||||
DAMAGENUMBER_LIST.clear();
|
||||
game->MAP_DATA.SetInitialized();
|
||||
}
|
||||
TEST_METHOD_CLEANUP(CleanupTests){
|
||||
testGame->EndGame();
|
||||
@ -800,8 +802,7 @@ namespace PlayerTests
|
||||
Assert::AreEqual(player->GetMaxHealth()-10,player->GetHealth(),L"Player now takes damage with 0 shield.");
|
||||
}
|
||||
TEST_METHOD(PlayerHasteMoveCheck){
|
||||
testGame->InitializeLevel("map_path"_S+DATA["Levels"]["TEST_MAP"]["Map File"].GetString(),"TEST_MAP");
|
||||
testGame->_SetCurrentLevel("TEST_MAP");
|
||||
Game::LoadLevel("TEST_MAP",testGame.get());
|
||||
player=testGame->GetPlayer();
|
||||
player->ForceSetPos({12,12});
|
||||
testKeyboardInput.AddKeybind(Input{InputType::KEY,D});
|
||||
@ -828,8 +829,7 @@ namespace PlayerTests
|
||||
}
|
||||
}
|
||||
TEST_METHOD(PlayerHasteCooldownCheck){
|
||||
testGame->InitializeLevel("map_path"_S+DATA["Levels"]["TEST_MAP"]["Map File"].GetString(),"TEST_MAP");
|
||||
testGame->_SetCurrentLevel("TEST_MAP");
|
||||
Game::LoadLevel("TEST_MAP",testGame.get());
|
||||
player=testGame->GetPlayer();
|
||||
player->ForceSetPos({12,12});
|
||||
testKeyboardInput.AddKeybind(Input{InputType::KEY,D});
|
||||
|
||||
@ -7,8 +7,6 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Adventures in Lestoria", "A
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Adventures in Lestoria Tests", "Adventures in Lestoria Tests\Adventures in Lestoria Tests.vcxproj", "{11969B7B-3D50-4825-9584-AF01D15B88E0}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MapPreloader", "MapPreloader\MapPreloader.vcxproj", "{C19BD586-D45F-48B3-9666-EAD3F92EB526}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@ -63,30 +61,6 @@ Global
|
||||
{11969B7B-3D50-4825-9584-AF01D15B88E0}.Unit Testing|x64.Build.0 = Unit Testing|x64
|
||||
{11969B7B-3D50-4825-9584-AF01D15B88E0}.Unit Testing|x86.ActiveCfg = Unit Testing|Win32
|
||||
{11969B7B-3D50-4825-9584-AF01D15B88E0}.Unit Testing|x86.Build.0 = Unit Testing|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Debug|x64.Build.0 = Debug|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Debug|x86.Build.0 = Debug|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Emscripten Debug|x64.ActiveCfg = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Emscripten Debug|x64.Build.0 = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Emscripten Debug|x86.ActiveCfg = Release|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Emscripten Debug|x86.Build.0 = Release|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Emscripten|x64.ActiveCfg = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Emscripten|x64.Build.0 = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Emscripten|x86.ActiveCfg = Release|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Emscripten|x86.Build.0 = Release|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Release Desktop|x64.ActiveCfg = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Release Desktop|x64.Build.0 = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Release Desktop|x86.ActiveCfg = Release|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Release Desktop|x86.Build.0 = Release|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Release|x64.ActiveCfg = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Release|x64.Build.0 = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Release|x86.ActiveCfg = Release|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Release|x86.Build.0 = Release|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Unit Testing|x64.ActiveCfg = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Unit Testing|x64.Build.0 = Release|x64
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Unit Testing|x86.ActiveCfg = Release|Win32
|
||||
{C19BD586-D45F-48B3-9666-EAD3F92EB526}.Unit Testing|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@ -334,8 +334,6 @@
|
||||
"values": [
|
||||
"Dungeon",
|
||||
"Boss",
|
||||
"Story",
|
||||
"Blacksmith",
|
||||
"World Map",
|
||||
"Hub"
|
||||
],
|
||||
|
||||
@ -456,7 +456,7 @@ bool AiL::OnConsoleCommand(const std::string& sCommand){
|
||||
if(args[0]=="/generatecache"){
|
||||
ConsoleOut()<<"Generating map caches."<<std::endl;
|
||||
for(auto&map:MAP_DATA){
|
||||
if(!map.GetMapName().starts_with("STORY"))TileGroupDataFile::AddToMapCacheQueue(map.GetMapName());
|
||||
if(!map.GetMapKeyName().starts_with("STORY"))TileGroupDataFile::AddToMapCacheQueue(map.GetMapKeyName());
|
||||
}
|
||||
GameState::ChangeState(States::GAME_RUN);
|
||||
}else{
|
||||
@ -1063,8 +1063,8 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
auto foregroundEffectsLower{foregroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return !effect->OnUpperLevel();})};
|
||||
auto backgroundEffectsUpper{backgroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return effect->OnUpperLevel();})};
|
||||
auto backgroundEffectsLower{backgroundEffects|std::views::filter([](const std::unique_ptr<Effect>&effect){return !effect->OnUpperLevel();})};
|
||||
auto upperEndZones{ZONE_LIST["EndZone"]|std::views::filter([](const ZoneData&zone){return zone.isUpper;})};
|
||||
auto endZones{ZONE_LIST["EndZone"]|std::views::filter([](const ZoneData&zone){return !zone.isUpper;})};
|
||||
auto upperEndZones{GetActiveZonesForCurrentMap()["EndZone"]|std::views::filter([](const ZoneData&zone){return zone.isUpper;})};
|
||||
auto endZones{GetActiveZonesForCurrentMap()["EndZone"]|std::views::filter([](const ZoneData&zone){return !zone.isUpper;})};
|
||||
#pragma endregion
|
||||
|
||||
auto RenderPlayer=[&](vf2d pos,vf2d scale){
|
||||
@ -1123,7 +1123,7 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
}
|
||||
};
|
||||
|
||||
auto RenderZone=[&](geom2d::rect<int>&zone){
|
||||
auto RenderZone=[&](const geom2d::rect<int>&zone){
|
||||
game->SetDecalMode(DecalMode::ADDITIVE);
|
||||
Pixel ringColor={128,128,128,uint8_t(abs(sin(game->levelTime))*255)};
|
||||
Decal*ringDecal=GFX["finishring_green.png"].Decal();
|
||||
@ -1322,7 +1322,7 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
for(ZoneData&zone:endZones){
|
||||
for(const ZoneData&zone:endZones){
|
||||
RenderZone(zone.zone);
|
||||
}
|
||||
auto RenderPrecastTargetingIndicator=[&](){
|
||||
@ -1635,7 +1635,7 @@ void AiL::RenderWorld(float fElapsedTime){
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
for(ZoneData&zone:upperEndZones){
|
||||
for(const ZoneData&zone:upperEndZones){
|
||||
RenderZone(zone.zone);
|
||||
}
|
||||
|
||||
@ -2281,127 +2281,10 @@ void AiL::InitializeLevel(std::string mapFile,MapName map){
|
||||
|
||||
size_t slashMarker = mapFile.find_last_of('/');
|
||||
std::string baseDir=mapFile.substr(0,slashMarker+1);
|
||||
if(TestingModeEnabled())MAP_DATA.Unlock();
|
||||
MAP_DATA[map]=level.GetData();
|
||||
|
||||
for(auto&[key,size]:DATA["Levels"][map]){
|
||||
if(key.starts_with("Loot")){
|
||||
datafile data=DATA["Levels"][map][key];
|
||||
int pctChance=100;
|
||||
if(data.GetValueCount()>3)pctChance=data.GetInt(3U);
|
||||
MAP_DATA[map].stageLoot.push_back(ItemMapData(data.GetString(0U),data.GetInt(1U),data.GetInt(2U),pctChance));
|
||||
}else
|
||||
if(key.starts_with("Skip Loadout Selection")){
|
||||
MAP_DATA[map].skipLoadoutScreen=DATA["Levels"][map]["Skip Loadout Selection"].GetBool();
|
||||
}
|
||||
}
|
||||
|
||||
for(XMLTag&tag:MAP_DATA[map].TilesetData){
|
||||
size_t slashMarkerSourceDir = tag.data["source"].find_last_of('/');
|
||||
std::string baseSourceDir=tag.data["source"].substr(slashMarkerSourceDir+1);
|
||||
if(MAP_TILESETS.find("assets/maps/"+baseSourceDir)==MAP_TILESETS.end()){
|
||||
TSXParser tileset(baseDir+tag.data["source"]);
|
||||
Renderable*r=NEW Renderable();
|
||||
|
||||
if(tileset.GetData().tilewidth==0||tileset.GetData().tileheight==0)ERR(std::format("WARNING! Failed to load map {}! Found a tileset {} with a width of {} and height of {}. Zero values are not allowed!",map,"assets/maps/"+baseSourceDir,tileset.GetData().tilewidth,tileset.GetData().tileheight));
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].tilewidth=tileset.GetData().tilewidth;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].tileheight=tileset.GetData().tileheight;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].tileset=r;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].foregroundTiles=tileset.GetData().ForegroundTileData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].upperForegroundTiles=tileset.GetData().UpperForegroundTileData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].collision=tileset.GetData().CollisionData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].staircaseTiles=tileset.GetData().StaircaseData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].animationData=tileset.GetData().AnimationData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].reflectiveData=tileset.GetData().ReflectiveData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].tileRepeatData=tileset.GetData().TileRepeatData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].isTerrain=tileset.GetData().isTerrain;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].collision.SetInitialized();
|
||||
LOG("assets/maps/"+baseSourceDir<<" Animation Data Size: "<<MAP_TILESETS["assets/maps/"+baseSourceDir].animationData.size());
|
||||
std::string mapPath="assets/maps/"+tileset.GetData().ImageData.data["source"];
|
||||
if(gamepack.Loaded()){
|
||||
r->Load(mapPath,&gamepack);
|
||||
}else
|
||||
if(std::filesystem::exists(mapPath)){
|
||||
r->Load(mapPath);
|
||||
if("GENERATE_GAMEPACK"_B){
|
||||
gamepack.AddFile(mapPath);
|
||||
}
|
||||
}else{
|
||||
LOG("WARNING! "<<mapPath<<" does not exist, auto-generating mock-up texture");
|
||||
r->Create(tileset.GetData().imagewidth,tileset.GetData().imageheight);
|
||||
SetDrawTarget(r->Sprite());
|
||||
int tileXCount=tileset.GetData().imagewidth/tileset.GetData().tilewidth;
|
||||
int tileYCount=tileset.GetData().imageheight/tileset.GetData().tileheight;
|
||||
vi2d tileSize={tileset.GetData().tilewidth,tileset.GetData().tileheight};
|
||||
|
||||
const int colorCombinations=255*6;
|
||||
|
||||
for(int y=0;y<tileYCount;y++){
|
||||
for(int x=0;x<tileXCount;x++){
|
||||
int colorCycleIndex=(y*255+x)%colorCombinations;
|
||||
Pixel tileCol=WHITE;
|
||||
if(colorCycleIndex<255){
|
||||
tileCol={uint8_t(colorCycleIndex%255),0,0};
|
||||
}else
|
||||
if(colorCycleIndex<255*2){
|
||||
tileCol={0,uint8_t(colorCycleIndex%255),0};
|
||||
}else
|
||||
if(colorCycleIndex<255*3){
|
||||
tileCol={0,0,uint8_t(colorCycleIndex%255)};
|
||||
}else
|
||||
if(colorCycleIndex<255*4){
|
||||
tileCol={uint8_t(colorCycleIndex%255),uint8_t(colorCycleIndex%255),0};
|
||||
}else
|
||||
if(colorCycleIndex<255*5){
|
||||
tileCol={0,uint8_t(colorCycleIndex%255),uint8_t(colorCycleIndex%255)};
|
||||
}else{
|
||||
tileCol={uint8_t(colorCycleIndex%255),0,uint8_t(colorCycleIndex%255)};
|
||||
}
|
||||
FillRect(vi2d{x,y}*tileSize,tileSize,tileCol);
|
||||
DrawRect(vi2d{x,y}*tileSize,tileSize,GREY);
|
||||
DrawString(vi2d{x,y}*tileSize+vi2d{1,1},std::to_string(y*255+x),DARK_GREY);
|
||||
}
|
||||
}
|
||||
SetDrawTarget(nullptr);
|
||||
r->Decal()->Update();
|
||||
}
|
||||
|
||||
ComputeModeColors(MAP_TILESETS["assets/maps/"+baseSourceDir]);
|
||||
}
|
||||
}
|
||||
|
||||
if(MAP_DATA[map].MapData.optimized||MAP_DATA[map].MapData.provideOptimization){
|
||||
LOG("Generating optimized map for Map "<<map);
|
||||
MAP_DATA[map].optimizedTile=NEW Renderable();
|
||||
MAP_DATA[map].optimizedTile->Create(MAP_DATA[map].MapData.width*MAP_DATA[map].MapData.tilewidth,MAP_DATA[map].MapData.height*MAP_DATA[map].MapData.tileheight);
|
||||
SetDrawTarget(MAP_DATA[map].optimizedTile->Sprite());
|
||||
Pixel::Mode prevMode=GetPixelMode();
|
||||
SetPixelMode(Pixel::Mode::MASK);
|
||||
Clear(BLANK);
|
||||
for(int y=0;y<MAP_DATA[map].MapData.height;y++){
|
||||
for(int x=0;x<MAP_DATA[map].MapData.width;x++){
|
||||
for(auto&layer:MAP_DATA[map].LayerData){
|
||||
int tileID=layer.tiles[y][x]-1;
|
||||
if(tileID!=-1){
|
||||
TilesheetData tileSheet=GetTileSheet(map,tileID);
|
||||
int tileSheetWidth=MAP_TILESETS.at(tileSheet.tilesetName).tileset->Sprite()->width/MAP_TILESETS.at(tileSheet.tilesetName).tilewidth;
|
||||
int tileSheetHeight=MAP_TILESETS.at(tileSheet.tilesetName).tileset->Sprite()->height/MAP_TILESETS.at(tileSheet.tilesetName).tileheight;
|
||||
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
|
||||
int tileSheetX=tileSheetIndex%tileSheetWidth;
|
||||
int tileSheetY=tileSheetIndex/tileSheetWidth;
|
||||
vi2d pos=vi2d{x,y}*MAP_TILESETS.at(tileSheet.tilesetName).tilewidth;
|
||||
DrawPartialSprite(pos,MAP_TILESETS.at(tileSheet.tilesetName).tileset->Sprite(),vi2d{tileSheetX,tileSheetY}*MAP_TILESETS.at(tileSheet.tilesetName).tilewidth,{MAP_TILESETS.at(tileSheet.tilesetName).tilewidth,MAP_TILESETS.at(tileSheet.tilesetName).tileheight});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetPixelMode(prevMode);
|
||||
MAP_DATA[map].optimizedTile->Decal()->Update();
|
||||
SetDrawTarget(nullptr);
|
||||
if(!MAP_DATA[map].MapData.provideOptimization){
|
||||
MAP_DATA[map].LayerData.clear();
|
||||
LOG(" Clearing Layer Data...");
|
||||
}
|
||||
}
|
||||
MAP_DATA.at(map).name=map;
|
||||
if(TestingModeEnabled())MAP_DATA.SetInitialized();
|
||||
}
|
||||
|
||||
void AiL::LoadLevel(MapName map,MusicChange changeMusic){
|
||||
@ -2418,7 +2301,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
||||
#pragma region Reset all data (Loading phase 1)
|
||||
LoadingScreen::AddPhase([&](){
|
||||
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));
|
||||
if(game->MAP_DATA[GetCurrentLevel()].GetMapType()==Map::MapType::HUB&&GameState::STATE!=GameState::states[States::GAME_HUB]&&!TileGroupDataFile::HasMapsInCacheQueue())ERR("WARNING! A hub level should only be initiated in the GAME_HUB game state!");
|
||||
if(game->MAP_DATA[GetCurrentLevel()].GetMapType()==Map::MapType::HUB&&GameState::STATE!=GameState::states[States::GAME_HUB]&&!game->MapCacheIsRunning)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[previousLevel].environmentalAudioData){
|
||||
@ -2434,6 +2317,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
||||
)
|
||||
|
||||
ZONE_LIST=game->MAP_DATA[game->GetCurrentLevel()].ZoneData;
|
||||
ZONE_LIST.SetInitialized();
|
||||
return true;
|
||||
});
|
||||
#pragma endregion
|
||||
@ -2475,7 +2359,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
||||
|
||||
const int spawnerId=spawnData.ObjectData.GetInteger("id");
|
||||
|
||||
if(SPAWNER_LIST.count(spawnerId))ERR(std::format("WARNING! Spawner ID {} for Map {} is somehow duplicated! THIS SHOULD NOT BE HAPPENING!",spawnData.ObjectData.GetInteger("id"),GetCurrentMapDisplayName()))
|
||||
if(SPAWNER_LIST.count(spawnerId))ERR(std::format("WARNING! Spawner ID {} for Map {} is somehow duplicated! THIS SHOULD NOT BE HAPPENING!",spawnData.ObjectData.GetInteger("id"),GetCurrentMapStageName()))
|
||||
SPAWNER_LIST[spawnerId]=MonsterSpawner{{spawnData.ObjectData.GetFloat("x"),spawnData.ObjectData.GetFloat("y")},spawnerRadius*2,monster_list,spawnData.upperLevel,spawnData.bossNameDisplay};
|
||||
if(IdsToDisable.count(spawnerId))SPAWNER_LIST.at(spawnerId).SetTriggered(true,false); //Force this spawner to be deactivated because it is in a spawn controller.
|
||||
}
|
||||
@ -2487,12 +2371,8 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
|
||||
#pragma region Identify Upper Foreground Tiles (Loading phase 3)
|
||||
LoadingScreen::AddPhase([&](){
|
||||
auto GetUpperZones=[&](){
|
||||
for(auto&zoneSet:MAP_DATA[GetCurrentLevel()].ZoneData){
|
||||
if(zoneSet.first=="UpperZone"){ //We are interested in all upper zones.
|
||||
return zoneSet.second;
|
||||
}
|
||||
}
|
||||
return std::vector<ZoneData>{};
|
||||
if(MAP_DATA[GetCurrentLevel()].ZoneData.count("UpperZone")){return MAP_DATA[GetCurrentLevel()].ZoneData["UpperZone"];}
|
||||
else return std::vector<ZoneData>{};
|
||||
};
|
||||
for(ZoneData&zone:GetUpperZones()){
|
||||
int zoneX=zone.zone.pos.x/game->GetCurrentMapData().tilewidth; //snap to grid
|
||||
@ -3388,6 +3268,12 @@ void AiL::InitializeLevels(){
|
||||
InitializeLevel("map_path"_S+DATA["Levels"][key]["Map File"].GetString(),key);
|
||||
}
|
||||
|
||||
MAP_DATA.SetInitialized();
|
||||
|
||||
for(auto&map:MAP_DATA){
|
||||
SetupLevel(map);
|
||||
}
|
||||
|
||||
std::set<std::string>cpNames;
|
||||
for(ConnectionPoint&cp:State_OverworldMap::connections){
|
||||
if(cpNames.count(cp.name)>0)ERR(std::format("WARNING! More than one connection point has the same name: {} THIS IS NOT ALLOWED!",cp.name));
|
||||
@ -3400,10 +3286,10 @@ void AiL::InitializeLevels(){
|
||||
cp.levelDataExists=true;
|
||||
}
|
||||
if(MAP_DATA.count(cp.map)){
|
||||
MAP_DATA[cp.map].name=cp.name;
|
||||
MAP_DATA[cp.map].stageName=cp.name;
|
||||
|
||||
//Boss arena map zone check.
|
||||
if(MAP_DATA[cp.map].GetMapType()==Map::MapType::BOSS&&MAP_DATA[cp.map].GetZones().at("BossArena").size()==0)ERR(std::format("WARNING! Map {} doesn't have a boss arena region defined! Add an object of class BossArena to the map.",MAP_DATA[cp.map].GetMapDisplayName()));
|
||||
if(MAP_DATA[cp.map].GetMapType()==Map::MapType::BOSS&&MAP_DATA[cp.map].GetZones().at("BossArena").size()==0)ERR(std::format("WARNING! Map {} doesn't have a boss arena region defined! Add an object of class BossArena to the map.",MAP_DATA[cp.map].GetMapStageName()));
|
||||
|
||||
for(std::string spawn:MAP_DATA[cp.map].spawns){
|
||||
cp.spawns.push_back(MONSTER_DATA.at(spawn).GetDisplayName());
|
||||
@ -3861,9 +3747,9 @@ void AiL::ValidateGameStatus(){
|
||||
}
|
||||
}
|
||||
|
||||
auto MapStoryDataExists = [&](const std::string&mapName){
|
||||
return MAP_DATA.count(MapName(mapName))>0||
|
||||
VisualNovel::storyLevelData.count(mapName)>0;
|
||||
auto MapStoryDataExists = [&](const std::string&levelName){
|
||||
return MAP_DATA.count(MapName(levelName))>0||
|
||||
VisualNovel::storyLevelData.count(levelName)>0;
|
||||
};
|
||||
|
||||
if(!MapStoryDataExists("NPCs.Sherman.Potion Crafting Unlock Condition"_S))ERR(std::format("WARNING! Sherman's Potion Crafting Unlock Condition: {} is not a valid map!","NPCs.Sherman.Potion Crafting Unlock Condition"_S))
|
||||
@ -3882,7 +3768,7 @@ void AiL::ValidateGameStatus(){
|
||||
monsterCounts[monsterName]++;
|
||||
}
|
||||
}
|
||||
LOG("Spawns Report for "<<map.GetMapDisplayName()<<":");
|
||||
LOG("Spawns Report for "<<map.GetMapStageName()<<":");
|
||||
for(auto&[monster,count]:monsterCounts){
|
||||
LOG("\t"<<count<<"x "<<monster);
|
||||
}
|
||||
@ -4282,22 +4168,23 @@ const Pixel&AiL::GetWorldColor()const{
|
||||
return worldColor;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string,std::vector<::ZoneData>>&AiL::GetZones(const std::string_view mapName)const{
|
||||
if(GetCurrentMapDisplayName()==mapName)return GetZones();
|
||||
return MAP_DATA.at(std::string(mapName)).ZoneData;
|
||||
}
|
||||
|
||||
const std::unordered_map<std::string,std::vector<::ZoneData>>&AiL::GetZones()const{
|
||||
const safeunorderedmap<std::string,std::vector<::ZoneData>>&AiL::GetActiveZonesForCurrentMap()const{
|
||||
return ZONE_LIST;
|
||||
}
|
||||
|
||||
void AiL::AddZone(const std::string_view zoneName,const ZoneData&zone){
|
||||
if(ZONE_LIST.count(std::string(zoneName))==0)ERR(std::format("WARNING! Trying to add non-existent Zone Key {} to zone list of map {}. THIS IS NOT ALLOWED!",zoneName,std::string(GetCurrentMapName())));
|
||||
ZONE_LIST[std::string(zoneName)].push_back(zone);
|
||||
const safeunorderedmap<std::string,std::vector<::ZoneData>>&AiL::GetZones(const std::string&mapKey)const{
|
||||
return MAP_DATA[mapKey].ZoneData;
|
||||
}
|
||||
|
||||
const std::string_view AiL::GetCurrentMapDisplayName()const{
|
||||
return GetCurrentMap().GetMapDisplayName();
|
||||
void AiL::AddActiveZoneToCurrentMap(const std::string&zoneName,const ZoneData&zone){
|
||||
ZONE_LIST.Unlock();
|
||||
if(ZONE_LIST.count(zoneName)==0)ERR(std::format("WARNING! Trying to add non-existent Zone Key {} to zone list of map {}. THIS IS NOT ALLOWED!",zoneName,GetCurrentMapName()));
|
||||
ZONE_LIST[zoneName].emplace_back(zone);
|
||||
ZONE_LIST.SetInitialized();
|
||||
}
|
||||
|
||||
const std::string_view AiL::GetCurrentMapStageName()const{
|
||||
return GetCurrentMap().GetMapStageName();
|
||||
}
|
||||
|
||||
const uint8_t AiL::BossEncounterMobCount()const{
|
||||
@ -4777,19 +4664,142 @@ void AiL::PrecacheNewLevels(){
|
||||
const std::string precacheConfigurationFilepath{std::format("{}{}","config_path"_S,"map_precache_timestamp_config"_S)};
|
||||
if(std::filesystem::exists(precacheConfigurationFilepath))datafile::Read(cacheTimestampsData,precacheConfigurationFilepath);
|
||||
for(auto&map:MAP_DATA){
|
||||
const std::string mapFileName{std::format("assets/Campaigns/{}",DATA["Levels"][map.GetMapName()]["Map File"].GetString())};
|
||||
const std::string mapCacheFileName{std::format("assets/cache/foregroundTileData_{}.data",map.GetMapName())};
|
||||
const std::string mapFileName{std::format("assets/Campaigns/{}",DATA["Levels"][map.GetMapKeyName()]["Map File"].GetString())};
|
||||
const std::string mapCacheFileName{std::format("assets/cache/foregroundTileData_{}.data",map.GetMapKeyName())};
|
||||
const std::string lastWriteTimestamp{std::format("{}",std::filesystem::last_write_time(mapFileName))};
|
||||
|
||||
const bool PrecacheFileExists{game->gamepack.FileExists(mapCacheFileName)};
|
||||
const bool CacheTimestampDiffersFromLastWriteTime{!cacheTimestampsData.HasProperty(map.GetMapName())||cacheTimestampsData[map.GetMapName()].GetString()!=lastWriteTimestamp};
|
||||
const bool MapCacheOutOfDate{!cacheTimestampsData.HasProperty(map.GetMapName())||CacheTimestampDiffersFromLastWriteTime};
|
||||
const bool CacheTimestampDiffersFromLastWriteTime{!cacheTimestampsData.HasProperty(map.GetMapKeyName())||cacheTimestampsData[map.GetMapKeyName()].GetString()!=lastWriteTimestamp};
|
||||
const bool MapCacheOutOfDate{!cacheTimestampsData.HasProperty(map.GetMapKeyName())||CacheTimestampDiffersFromLastWriteTime};
|
||||
|
||||
if(!PrecacheFileExists||MapCacheOutOfDate){
|
||||
cacheTimestampsData[map.GetMapName()].SetString(lastWriteTimestamp);
|
||||
TileGroupDataFile::AddToMapCacheQueue(map.GetMapName());
|
||||
cacheTimestampsData[map.GetMapKeyName()].SetString(lastWriteTimestamp);
|
||||
TileGroupDataFile::AddToMapCacheQueue(map.GetMapKeyName());
|
||||
}
|
||||
}
|
||||
datafile::Write(cacheTimestampsData,precacheConfigurationFilepath);
|
||||
datafile::INITIAL_SETUP_COMPLETE=true;
|
||||
}
|
||||
|
||||
void AiL::SetupLevel(Map&map){
|
||||
datafile mapData{DATA["Levels"][map.GetMapKeyName()]};
|
||||
for(auto&[key,size]:mapData){
|
||||
if(key.starts_with("Loot")){
|
||||
datafile data=DATA["Levels"][map.GetMapKeyName()][key];
|
||||
int pctChance=100;
|
||||
if(data.GetValueCount()>3)pctChance=data.GetInt(3U);
|
||||
MAP_DATA[map.GetMapKeyName()].stageLoot.push_back(ItemMapData(data.GetString(0U),data.GetInt(1U),data.GetInt(2U),pctChance));
|
||||
}else
|
||||
if(key.starts_with("Skip Loadout Selection")){
|
||||
MAP_DATA[map.GetMapKeyName()].skipLoadoutScreen=DATA["Levels"][map.GetMapKeyName()]["Skip Loadout Selection"].GetBool();
|
||||
}
|
||||
}
|
||||
|
||||
for(XMLTag&tag:MAP_DATA[map.GetMapKeyName()].TilesetData){
|
||||
size_t slashMarkerSourceDir = tag.data["source"].find_last_of('/');
|
||||
std::string baseSourceDir=tag.data["source"].substr(slashMarkerSourceDir+1);
|
||||
if(MAP_TILESETS.find("assets/maps/"+baseSourceDir)==MAP_TILESETS.end()){
|
||||
TSXParser tileset("map_path"_S+tag.data["source"]);
|
||||
Renderable*r=NEW Renderable();
|
||||
|
||||
if(tileset.GetData().tilewidth==0||tileset.GetData().tileheight==0)ERR(std::format("WARNING! Failed to load map {}! Found a tileset {} with a width of {} and height of {}. Zero values are not allowed!",map.GetMapStageName(),"assets/maps/"+baseSourceDir,tileset.GetData().tilewidth,tileset.GetData().tileheight));
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].tilewidth=tileset.GetData().tilewidth;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].tileheight=tileset.GetData().tileheight;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].tileset=r;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].foregroundTiles=tileset.GetData().ForegroundTileData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].upperForegroundTiles=tileset.GetData().UpperForegroundTileData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].collision=tileset.GetData().CollisionData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].staircaseTiles=tileset.GetData().StaircaseData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].animationData=tileset.GetData().AnimationData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].reflectiveData=tileset.GetData().ReflectiveData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].tileRepeatData=tileset.GetData().TileRepeatData;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].isTerrain=tileset.GetData().isTerrain;
|
||||
MAP_TILESETS["assets/maps/"+baseSourceDir].collision.SetInitialized();
|
||||
LOG("assets/maps/"+baseSourceDir<<" Animation Data Size: "<<MAP_TILESETS["assets/maps/"+baseSourceDir].animationData.size());
|
||||
std::string mapPath="assets/maps/"+tileset.GetData().ImageData.data["source"];
|
||||
if(gamepack.Loaded()){
|
||||
r->Load(mapPath,&gamepack);
|
||||
}else
|
||||
if(std::filesystem::exists(mapPath)){
|
||||
r->Load(mapPath);
|
||||
if("GENERATE_GAMEPACK"_B){
|
||||
gamepack.AddFile(mapPath);
|
||||
}
|
||||
}else{
|
||||
LOG("WARNING! "<<mapPath<<" does not exist, auto-generating mock-up texture");
|
||||
r->Create(tileset.GetData().imagewidth,tileset.GetData().imageheight);
|
||||
SetDrawTarget(r->Sprite());
|
||||
int tileXCount=tileset.GetData().imagewidth/tileset.GetData().tilewidth;
|
||||
int tileYCount=tileset.GetData().imageheight/tileset.GetData().tileheight;
|
||||
vi2d tileSize={tileset.GetData().tilewidth,tileset.GetData().tileheight};
|
||||
|
||||
const int colorCombinations=255*6;
|
||||
|
||||
for(int y=0;y<tileYCount;y++){
|
||||
for(int x=0;x<tileXCount;x++){
|
||||
int colorCycleIndex=(y*255+x)%colorCombinations;
|
||||
Pixel tileCol=WHITE;
|
||||
if(colorCycleIndex<255){
|
||||
tileCol={uint8_t(colorCycleIndex%255),0,0};
|
||||
}else
|
||||
if(colorCycleIndex<255*2){
|
||||
tileCol={0,uint8_t(colorCycleIndex%255),0};
|
||||
}else
|
||||
if(colorCycleIndex<255*3){
|
||||
tileCol={0,0,uint8_t(colorCycleIndex%255)};
|
||||
}else
|
||||
if(colorCycleIndex<255*4){
|
||||
tileCol={uint8_t(colorCycleIndex%255),uint8_t(colorCycleIndex%255),0};
|
||||
}else
|
||||
if(colorCycleIndex<255*5){
|
||||
tileCol={0,uint8_t(colorCycleIndex%255),uint8_t(colorCycleIndex%255)};
|
||||
}else{
|
||||
tileCol={uint8_t(colorCycleIndex%255),0,uint8_t(colorCycleIndex%255)};
|
||||
}
|
||||
FillRect(vi2d{x,y}*tileSize,tileSize,tileCol);
|
||||
DrawRect(vi2d{x,y}*tileSize,tileSize,GREY);
|
||||
DrawString(vi2d{x,y}*tileSize+vi2d{1,1},std::to_string(y*255+x),DARK_GREY);
|
||||
}
|
||||
}
|
||||
SetDrawTarget(nullptr);
|
||||
r->Decal()->Update();
|
||||
}
|
||||
|
||||
ComputeModeColors(MAP_TILESETS["assets/maps/"+baseSourceDir]);
|
||||
}
|
||||
}
|
||||
|
||||
if(MAP_DATA[map.GetMapKeyName()].MapData.optimized||MAP_DATA[map.GetMapKeyName()].MapData.provideOptimization){
|
||||
LOG("Generating optimized map for Map "<<map);
|
||||
MAP_DATA[map.GetMapKeyName()].optimizedTile=NEW Renderable();
|
||||
MAP_DATA[map.GetMapKeyName()].optimizedTile->Create(MAP_DATA[map.GetMapKeyName()].MapData.width*MAP_DATA[map.GetMapKeyName()].MapData.tilewidth,MAP_DATA[map.GetMapKeyName()].MapData.height*MAP_DATA[map.GetMapKeyName()].MapData.tileheight);
|
||||
SetDrawTarget(MAP_DATA[map.GetMapKeyName()].optimizedTile->Sprite());
|
||||
Pixel::Mode prevMode=GetPixelMode();
|
||||
SetPixelMode(Pixel::Mode::MASK);
|
||||
Clear(BLANK);
|
||||
for(int y=0;y<MAP_DATA[map.GetMapKeyName()].MapData.height;y++){
|
||||
for(int x=0;x<MAP_DATA[map.GetMapKeyName()].MapData.width;x++){
|
||||
for(auto&layer:MAP_DATA[map.GetMapKeyName()].LayerData){
|
||||
int tileID=layer.tiles[y][x]-1;
|
||||
if(tileID!=-1){
|
||||
TilesheetData tileSheet=GetTileSheet(map.GetMapKeyName(),tileID);
|
||||
int tileSheetWidth=MAP_TILESETS.at(tileSheet.tilesetName).tileset->Sprite()->width/MAP_TILESETS.at(tileSheet.tilesetName).tilewidth;
|
||||
int tileSheetHeight=MAP_TILESETS.at(tileSheet.tilesetName).tileset->Sprite()->height/MAP_TILESETS.at(tileSheet.tilesetName).tileheight;
|
||||
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
|
||||
int tileSheetX=tileSheetIndex%tileSheetWidth;
|
||||
int tileSheetY=tileSheetIndex/tileSheetWidth;
|
||||
vi2d pos=vi2d{x,y}*MAP_TILESETS.at(tileSheet.tilesetName).tilewidth;
|
||||
DrawPartialSprite(pos,MAP_TILESETS.at(tileSheet.tilesetName).tileset->Sprite(),vi2d{tileSheetX,tileSheetY}*MAP_TILESETS.at(tileSheet.tilesetName).tilewidth,{MAP_TILESETS.at(tileSheet.tilesetName).tilewidth,MAP_TILESETS.at(tileSheet.tilesetName).tileheight});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SetPixelMode(prevMode);
|
||||
MAP_DATA[map.GetMapKeyName()].optimizedTile->Decal()->Update();
|
||||
SetDrawTarget(nullptr);
|
||||
if(!MAP_DATA[map.GetMapKeyName()].MapData.provideOptimization){
|
||||
MAP_DATA[map.GetMapKeyName()].LayerData.clear();
|
||||
LOG(" Clearing Layer Data...");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -188,6 +188,7 @@ public:
|
||||
geom2d::rect<float>NO_COLLISION={{0.f,0.f,},{0.f,0.f}};
|
||||
TileTransformedView view;
|
||||
void InitializeLevel(std::string mapFile,MapName map);
|
||||
void SetupLevel(Map&map);
|
||||
void LoadLevel(MapName map,MusicChange changeMusic=PLAY_LEVEL_MUSIC);
|
||||
void HandleUserInput(float fElapsedTime);
|
||||
void UpdateCamera(float fElapsedTime);
|
||||
@ -273,7 +274,7 @@ public:
|
||||
const Map&GetCurrentMap()const;
|
||||
const MapTag&GetCurrentMapData()const;
|
||||
const MapName&GetCurrentMapName()const;
|
||||
const std::string_view GetCurrentMapDisplayName()const;
|
||||
const std::string_view GetCurrentMapStageName()const;
|
||||
int GetCurrentChapter();
|
||||
void SetChapter(int chapter);
|
||||
const std::weak_ptr<Item>GetLoadoutItem(int slot); //Slot range is 0-2.
|
||||
@ -296,11 +297,11 @@ public:
|
||||
void SetWorldColorFunc(std::function<Pixel(vi2d)>func);
|
||||
void SetWorldColor(Pixel worldCol);
|
||||
const Pixel&GetWorldColor()const;
|
||||
//Returns the zones in the current stage
|
||||
const std::unordered_map<std::string,std::vector<::ZoneData>>&GetZones()const;
|
||||
//Returns the active zones in the current stage (Originally populated by the zone data inside of the stage's map data)
|
||||
const safeunorderedmap<std::string,std::vector<::ZoneData>>&GetActiveZonesForCurrentMap()const;
|
||||
//Returns the zones of any given stage
|
||||
const std::unordered_map<std::string,std::vector<::ZoneData>>&GetZones(const std::string_view mapName)const;
|
||||
void AddZone(const std::string_view zoneName,const ZoneData&zone);
|
||||
const safeunorderedmap<std::string,std::vector<::ZoneData>>&GetZones(const std::string&mapName)const;
|
||||
void AddActiveZoneToCurrentMap(const std::string&zoneName,const ZoneData&zone);
|
||||
//Returns the last time the mouse was moved or interacted with.
|
||||
const float LastMouseMovement()const;
|
||||
const bool GameInitialized()const;
|
||||
@ -395,7 +396,7 @@ private:
|
||||
int playerShieldDisplayAmt{};
|
||||
Pixel worldColor=WHITE;
|
||||
std::function<Pixel(vi2d)>worldColorFunc=[](vi2d pos){return WHITE;};
|
||||
std::unordered_map<std::string,std::vector<::ZoneData>>ZONE_LIST;
|
||||
safeunorderedmap<std::string,std::vector<::ZoneData>>ZONE_LIST;
|
||||
float lastMouseMovement=0.f; //Amount of time since the last time the cursor was moved or interacted with.
|
||||
vi2d lastMousePos={};
|
||||
bool gameInitialized=false;
|
||||
|
||||
@ -39,6 +39,7 @@ All rights reserved.
|
||||
#include "EnvironmentalAudio.h"
|
||||
#include "Audio.h"
|
||||
#include "AdventuresInLestoria.h"
|
||||
#include"VisualNovel.h"
|
||||
|
||||
INCLUDE_game
|
||||
INCLUDE_DATA
|
||||
@ -80,6 +81,7 @@ void EnvironmentalAudio::Deactivate(){
|
||||
activated=false;
|
||||
}
|
||||
void EnvironmentalAudio::UpdateEnvironmentalAudio(){
|
||||
if(GameState::GetCurrentState()==States::STORY)return;
|
||||
for(const EnvironmentalAudio&aud:game->GetCurrentMap().GetEnvironmentalAudio()){
|
||||
EnvironmentalAudio&audio=const_cast<EnvironmentalAudio&>(aud);
|
||||
audio.Update();
|
||||
|
||||
@ -186,7 +186,7 @@ DEFINE_STRATEGY(GHOST_OF_PIRATE_CAPTAIN)
|
||||
if(!OnLastCursePhase)game->AddEffect(std::make_unique<FlipCoinEffect>(Oscillator<vf2d>{m.GetPos(),m.V(A::TOSS_COIN_TARGET),1.f/m.F(A::TOSS_COIN_WAIT_TIMER)/2.f},ConfigFloat("Coin Toss Rise Amount"),m.F(A::TOSS_COIN_WAIT_TIMER),"coin.png",m.OnUpperLevel(),3.f));
|
||||
|
||||
#pragma region Determine a hiding spot
|
||||
const auto&hidingSpots{game->GetZones().at("Hiding Spot")};
|
||||
const auto&hidingSpots{game->GetActiveZonesForCurrentMap().at("Hiding Spot")};
|
||||
if(hidingSpots.size()==0)ERR("WARNING! Could not find any zones with the name \"Hiding Spot\" on the map!! THIS SHOULD NOT BE HAPPENING!")
|
||||
m.V(A::HIDING_POS)=hidingSpots[util::random()%hidingSpots.size()].zone.middle();
|
||||
#pragma endregion
|
||||
|
||||
@ -55,7 +55,7 @@ ItemDrop::ItemDrop(const ItemInfo*item,const vf2d pos,const bool isUpper)
|
||||
:item(item),pos(pos),upperLevel(isUpper){
|
||||
const bool HasBossArenaBounds=game->GetCurrentMap().GetMapType()==Map::MapType::BOSS;
|
||||
if(HasBossArenaBounds){
|
||||
const geom2d::rect<int>arenaBounds=game->GetZones().at("BossArena")[0].zone;
|
||||
const geom2d::rect<int>arenaBounds=game->GetActiveZonesForCurrentMap()["BossArena"][0].zone;
|
||||
this->pos.x=std::clamp(this->pos.x,float(arenaBounds.pos.x),float(arenaBounds.pos.x+arenaBounds.size.x));
|
||||
this->pos.y=std::clamp(this->pos.y,float(arenaBounds.pos.y),float(arenaBounds.pos.y+arenaBounds.size.y));
|
||||
}
|
||||
@ -124,7 +124,7 @@ void ItemDrop::UpdateDrops(float fElapsedTime){
|
||||
|
||||
#pragma region Handle Upper/Lower Level Zone Intersecting
|
||||
if(drop.speed.mag()>0){
|
||||
const std::unordered_map<std::string,std::vector<ZoneData>>&zoneData=game->GetZones(game->GetCurrentLevel());
|
||||
const safeunorderedmap<std::string,std::vector<ZoneData>>&zoneData=game->GetZones(game->GetCurrentLevel());
|
||||
for(const ZoneData&upperLevelZone:zoneData.at("UpperZone")){
|
||||
if(geom2d::overlaps(upperLevelZone.zone,drop.pos)){
|
||||
drop.upperLevel=true;
|
||||
|
||||
@ -140,8 +140,8 @@ void Minimap::Reset(){
|
||||
}
|
||||
}
|
||||
|
||||
if(game->GetZones().count("EndZone")){
|
||||
for(const ZoneData&zone:game->GetZones().at("EndZone")){
|
||||
if(game->GetActiveZonesForCurrentMap().count("EndZone")){
|
||||
for(const ZoneData&zone:game->GetActiveZonesForCurrentMap()["EndZone"]){
|
||||
vf2d ringPos=zone.zone.pos/game->GetCurrentMapData().TileSize;
|
||||
vf2d ringSize=zone.zone.size/game->GetCurrentMapData().TileSize;
|
||||
vf2d ringCenter=ringPos+ringSize/2;
|
||||
|
||||
@ -205,7 +205,7 @@ bool Monster::_SetX(float x,const bool monsterInvoked){
|
||||
bool insideArenaBounds=true;
|
||||
#pragma region Calculate Arena Bounds check for Bosses
|
||||
if(isBoss){
|
||||
const geom2d::rect<int>arenaBounds=game->GetZones().at("BossArena")[0].zone;
|
||||
const geom2d::rect<int>arenaBounds=game->GetActiveZonesForCurrentMap()["BossArena"][0].zone;
|
||||
if(!geom2d::contains(arenaBounds,newPos)){
|
||||
insideArenaBounds=false;
|
||||
}
|
||||
@ -245,7 +245,7 @@ bool Monster::_SetY(float y,const bool monsterInvoked){
|
||||
bool insideArenaBounds=true;
|
||||
#pragma region Calculate Arena Bounds check for Bosses
|
||||
if(isBoss){
|
||||
const geom2d::rect<int>arenaBounds=game->GetZones().at("BossArena")[0].zone;
|
||||
const geom2d::rect<int>arenaBounds=game->GetActiveZonesForCurrentMap()["BossArena"][0].zone;
|
||||
if(!geom2d::contains(arenaBounds,newPos)){
|
||||
insideArenaBounds=false;
|
||||
}
|
||||
@ -746,7 +746,7 @@ bool Monster::SetPos(vf2d pos){
|
||||
return resultX||resultY;
|
||||
}
|
||||
void Monster::Moved(){
|
||||
const std::unordered_map<std::string,std::vector<ZoneData>>&zoneData=game->GetZones(game->GetCurrentLevel());
|
||||
const safeunorderedmap<std::string,std::vector<ZoneData>>&zoneData=game->GetZones(game->GetCurrentLevel());
|
||||
for(const ZoneData&upperLevelZone:zoneData.at("UpperZone")){
|
||||
if(geom2d::overlaps(upperLevelZone.zone,pos)){
|
||||
upperLevel=true;
|
||||
@ -1139,13 +1139,13 @@ void Monster::OnDeath(){
|
||||
}else{
|
||||
ZoneData exitRing{geom2d::rect<int>{vi2d{GetPos()-vf2d{"boss_spawn_ring_radius"_F,"boss_spawn_ring_radius"_F}},vi2d{"boss_spawn_ring_radius"_I*2,"boss_spawn_ring_radius"_I*2}},OnUpperLevel()};
|
||||
|
||||
const geom2d::rect<int>arenaBounds=game->GetZones().at("BossArena")[0].zone;
|
||||
const geom2d::rect<int>arenaBounds=game->GetActiveZonesForCurrentMap()["BossArena"][0].zone;
|
||||
geom2d::rect<int>clampedArena{vi2d(arenaBounds.pos+"boss_spawn_ring_radius"_I),vi2d(arenaBounds.size-"boss_spawn_ring_radius"_I*2)};
|
||||
|
||||
exitRing.zone.pos.x=std::clamp(exitRing.zone.pos.x,clampedArena.pos.x-"boss_spawn_ring_radius"_I,clampedArena.pos.x-"boss_spawn_ring_radius"_I+clampedArena.size.x);
|
||||
exitRing.zone.pos.y=std::clamp(exitRing.zone.pos.y,clampedArena.pos.y-"boss_spawn_ring_radius"_I,clampedArena.pos.y-"boss_spawn_ring_radius"_I+clampedArena.size.y);
|
||||
|
||||
game->AddZone("EndZone",exitRing); //Create a 144x144 ring around the dead boss.
|
||||
game->AddActiveZoneToCurrentMap("EndZone",exitRing); //Create a 144x144 ring around the dead boss.
|
||||
|
||||
Audio::SetAudioEvent("BossFanfare");
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ void Menu::InitializeOverworldMapLevelWindow(){
|
||||
levelSelectWindow->ADD("Enter Button",MenuComponent)(geom2d::rect<float>{{0,166},{windowSize.x-1,16}},"Enter",[](MenuFuncData data){
|
||||
game->RestockLoadoutItems();
|
||||
|
||||
if(game->MAP_DATA[State_OverworldMap::GetCurrentConnectionPoint().map].skipLoadoutScreen||
|
||||
if(game->MAP_DATA.count(State_OverworldMap::GetCurrentConnectionPoint().map)&&game->MAP_DATA[State_OverworldMap::GetCurrentConnectionPoint().map].skipLoadoutScreen||
|
||||
State_OverworldMap::GetCurrentConnectionPoint().type.starts_with("STORY")){
|
||||
State_OverworldMap::StartLevel();
|
||||
}else{
|
||||
|
||||
@ -1083,21 +1083,21 @@ void Player::Moved(MoveFlag::MoveFlag flags){
|
||||
spawner.SetTriggered(true);
|
||||
}
|
||||
}
|
||||
const std::unordered_map<std::string,std::vector<ZoneData>>&zoneData=game->GetZones(game->GetCurrentLevel());
|
||||
const safeunorderedmap<std::string,std::vector<ZoneData>>&zoneData=game->GetZones(game->GetCurrentLevel());
|
||||
if(zoneData.count("UpperZone")){
|
||||
for(const ZoneData&upperLevelZone:zoneData.at("UpperZone")){
|
||||
if(geom2d::overlaps(upperLevelZone.zone,pos)){
|
||||
upperLevel=true;
|
||||
}
|
||||
}
|
||||
}else if(!game->TestingModeEnabled())ERR(std::format("WARNING! Map {} is missing Upper Zones! THIS SHOULD NOT BE HAPPENING!",game->GetCurrentMapDisplayName()));
|
||||
}else if(!game->TestingModeEnabled())ERR(std::format("WARNING! Map {} is missing Upper Zones! THIS SHOULD NOT BE HAPPENING!",game->GetCurrentMapStageName()));
|
||||
if(zoneData.count("LowerZone")){
|
||||
for(const ZoneData&lowerLevelZone:zoneData.at("LowerZone")){
|
||||
if(geom2d::overlaps(lowerLevelZone.zone,pos)){
|
||||
upperLevel=false;
|
||||
}
|
||||
}
|
||||
}else if(!game->TestingModeEnabled())ERR(std::format("WARNING! Map {} is missing Lower Zones! THIS SHOULD NOT BE HAPPENING!",game->GetCurrentMapDisplayName()));
|
||||
}else if(!game->TestingModeEnabled())ERR(std::format("WARNING! Map {} is missing Lower Zones! THIS SHOULD NOT BE HAPPENING!",game->GetCurrentMapStageName()));
|
||||
EnvironmentalAudio::UpdateEnvironmentalAudio();
|
||||
|
||||
if(!std::isfinite(pos.x)){
|
||||
@ -1337,11 +1337,11 @@ float Player::GetEndZoneStandTime(){
|
||||
|
||||
void Player::CheckEndZoneCollision(){
|
||||
auto HasZoneData=[&](){
|
||||
return game->GetZones().count("EndZone");
|
||||
return game->GetActiveZonesForCurrentMap().count("EndZone");
|
||||
};
|
||||
|
||||
if(IsOutOfCombat()&&HasZoneData()){
|
||||
for(const ZoneData&zone:game->GetZones().at("EndZone")){
|
||||
for(const ZoneData&zone:game->GetActiveZonesForCurrentMap()["EndZone"]){
|
||||
if(zone.isUpper==upperLevel&&geom2d::overlaps(GetPos(),zone.zone)){
|
||||
endZoneStandTime+=game->GetElapsedTime();
|
||||
if(endZoneStandTime>="Player.End Zone Wait Time"_F){
|
||||
|
||||
@ -89,13 +89,13 @@ void State_MainMenu::Draw(AiL*game){
|
||||
|
||||
const ZoneData&State_MainMenu::ChooseRandomFocusArea(){
|
||||
//std::vector<ZoneData>
|
||||
if(game->GetZones().count("Focus Area")>0){
|
||||
const std::vector<ZoneData>&zones=game->GetZones().at("Focus Area");
|
||||
if(game->GetActiveZonesForCurrentMap().count("Focus Area")>0){
|
||||
const std::vector<ZoneData>&zones=game->GetActiveZonesForCurrentMap()["Focus Area"];
|
||||
newSelectedFocusAreaIndex=util::random()%zones.size();
|
||||
return zones[newSelectedFocusAreaIndex];
|
||||
}else ERR("WARNING! No focus areas included in the intro map!");
|
||||
|
||||
return game->GetZones().at("Focus Area")[0];
|
||||
return game->GetActiveZonesForCurrentMap()["Focus Area"][0];
|
||||
}
|
||||
|
||||
void State_MainMenu::SelectAndMoveToNewFocusArea(){
|
||||
|
||||
@ -133,14 +133,13 @@ struct Map{
|
||||
enum class MapType{
|
||||
DUNGEON,
|
||||
BOSS,
|
||||
STORY,
|
||||
BLACKSMITH,
|
||||
WORLD_MAP,
|
||||
HUB
|
||||
};
|
||||
private:
|
||||
MapTag MapData;
|
||||
std::string name;
|
||||
std::string stageName;
|
||||
Renderable*optimizedTile=nullptr;
|
||||
std::vector<TilesetTag> TilesetData;
|
||||
std::vector<LayerTag> LayerData;
|
||||
@ -155,7 +154,7 @@ private:
|
||||
std::set<std::string>spawns;
|
||||
std::map<int,SpawnerTag>SpawnerData; //Spawn groups have IDs, mobs associate which spawner they are tied to via this ID.
|
||||
std::optional<std::queue<MonsterSpawnerID>>spawnControllerIDs;
|
||||
std::unordered_map<std::string,std::vector<::ZoneData>>ZoneData;
|
||||
safeunorderedmap<std::string,std::vector<::ZoneData>>ZoneData;
|
||||
public:
|
||||
Map();
|
||||
void _SetMapData(MapTag data);
|
||||
@ -166,12 +165,12 @@ public:
|
||||
const std::vector<LayerTag>&GetLayers()const;
|
||||
const std::vector<EnvironmentalAudio>&GetEnvironmentalAudio()const;
|
||||
const float GetDevCompletionTime(Class cl)const;
|
||||
const MapName&GetMapName()const;
|
||||
const std::string_view GetMapDisplayName()const;
|
||||
const MapName&GetMapKeyName()const;
|
||||
const std::string&GetMapStageName()const;
|
||||
const bool HasMoreSpawns()const; //Returns whether or not there are more spawns for the spawn controller.
|
||||
const int Spawn_pop(); //Grabs the next spawn controller ID and removes it from the stack.
|
||||
const Renderable*const GetOptimizedMap()const;
|
||||
const std::unordered_map<std::string,std::vector<::ZoneData>>&GetZones()const;
|
||||
const safeunorderedmap<std::string,std::vector<::ZoneData>>&GetZones()const;
|
||||
const std::string&GetDefaultAudioEvent()const;
|
||||
std::string FormatLayerData(std::ostream& os, std::vector<LayerTag>tiles);
|
||||
std::string FormatSpawnerData(std::ostream& os, std::map<int,SpawnerTag>tiles);
|
||||
@ -281,8 +280,15 @@ class TMXParser{
|
||||
}
|
||||
}
|
||||
Map::Map(){
|
||||
ZoneData["UpperZone"];
|
||||
//Initialize these so that they are valid entries for zones.
|
||||
ZoneData["LowerZone"];
|
||||
ZoneData["UpperZone"];
|
||||
ZoneData["EndZone"];
|
||||
ZoneData["BossArena"];
|
||||
ZoneData["Focus Area"];
|
||||
ZoneData["TrialClock"];
|
||||
ZoneData["LowerBridgeCollision"];
|
||||
ZoneData["Hiding Spot"];
|
||||
}
|
||||
MapTag::MapTag(){}
|
||||
MapTag::MapTag(int width,int height,int tilewidth,int tileheight)
|
||||
@ -323,7 +329,7 @@ class TMXParser{
|
||||
const Map::MapType&Map::GetMapType()const{
|
||||
return mapType;
|
||||
}
|
||||
const MapName&Map::GetMapName()const{
|
||||
const MapName&Map::GetMapKeyName()const{
|
||||
return name;
|
||||
}
|
||||
void Map::_SetMapData(MapTag data){
|
||||
@ -335,7 +341,7 @@ class TMXParser{
|
||||
const std::vector<EnvironmentalAudio>&Map::GetEnvironmentalAudio()const{
|
||||
return environmentalAudioData;
|
||||
}
|
||||
const std::unordered_map<std::string,std::vector<::ZoneData>>&Map::GetZones()const{
|
||||
const safeunorderedmap<std::string,std::vector<::ZoneData>>&Map::GetZones()const{
|
||||
return ZoneData;
|
||||
}
|
||||
const std::vector<ItemMapData>&Map::GetStageLoot()const{
|
||||
@ -344,8 +350,8 @@ class TMXParser{
|
||||
const std::vector<LayerTag>&Map::GetLayers()const{
|
||||
return LayerData;
|
||||
}
|
||||
const std::string_view Map::GetMapDisplayName()const{
|
||||
return name;
|
||||
const std::string&Map::GetMapStageName()const{
|
||||
return stageName;
|
||||
}
|
||||
const bool Map::HasMoreSpawns()const{
|
||||
return spawnControllerIDs.has_value()&&spawnControllerIDs.value().size()>0;
|
||||
@ -626,7 +632,7 @@ class TMXParser{
|
||||
}else
|
||||
if (newTag.tag=="object"){
|
||||
if(newTag.data["type"]=="")newTag.data["type"]=newTag.data["name"]; //Found a blank type name! Try to set the type as its name.
|
||||
std::vector<ZoneData>&zones=parsedMapInfo.ZoneData[newTag.data["type"]];
|
||||
std::vector<ZoneData>&zones=parsedMapInfo.ZoneData.at(newTag.data["type"]);
|
||||
float width=1.f;
|
||||
float height=1.f;
|
||||
if(newTag.data.count("width")>0)width=newTag.GetFloat("width");
|
||||
@ -648,11 +654,6 @@ class TMXParser{
|
||||
|
||||
std::string accumulator="";
|
||||
|
||||
//Initialize these so that they are valid entries for zones.
|
||||
parsedMapInfo.ZoneData["LowerZone"];
|
||||
parsedMapInfo.ZoneData["UpperZone"];
|
||||
parsedMapInfo.ZoneData["EndZone"];
|
||||
parsedMapInfo.ZoneData["BossArena"];
|
||||
|
||||
while (f.good()&&!infiniteMap) {
|
||||
std::string data;
|
||||
@ -705,16 +706,16 @@ class TMXParser{
|
||||
parsedMapInfo.SpawnerData[monster.GetInteger("spawnerLink")].monsters.push_back(monster);
|
||||
}
|
||||
|
||||
parsedMapInfo.ZoneData.SetInitialized();
|
||||
|
||||
for(auto&spawnerData:parsedMapInfo.SpawnerData){
|
||||
SpawnerTag&spawner=spawnerData.second;
|
||||
for(auto&zoneData:parsedMapInfo.ZoneData){
|
||||
if(zoneData.first=="UpperZone"){
|
||||
std::vector<ZoneData>&zones=zoneData.second;
|
||||
for(ZoneData&zone:zones){
|
||||
if(geom2d::overlaps(zone.zone,geom2d::rect<int>{{spawner.ObjectData.GetInteger("x"),spawner.ObjectData.GetInteger("y")},{spawner.ObjectData.GetInteger("width"),spawner.ObjectData.GetInteger("height")}})){
|
||||
spawner.upperLevel=true;
|
||||
goto continueSpawnerLoop;
|
||||
}
|
||||
if(parsedMapInfo.ZoneData.count("UpperZone")){
|
||||
std::vector<ZoneData>&zones=parsedMapInfo.ZoneData["UpperZone"];
|
||||
for(ZoneData&zone:zones){
|
||||
if(geom2d::overlaps(zone.zone,geom2d::rect<int>{{spawner.ObjectData.GetInteger("x"),spawner.ObjectData.GetInteger("y")},{spawner.ObjectData.GetInteger("width"),spawner.ObjectData.GetInteger("height")}})){
|
||||
spawner.upperLevel=true;
|
||||
goto continueSpawnerLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -724,6 +725,7 @@ class TMXParser{
|
||||
|
||||
std::sort(parsedMapInfo.TilesetData.begin(),parsedMapInfo.TilesetData.end(),[](XMLTag&t1,XMLTag&t2){return t1.GetInteger("firstgid")<t2.GetInteger("firstgid");});
|
||||
|
||||
|
||||
std::map<int,int>idToIndexMap; //Since the original map data relies on IDs decided by Tiled and we are condensing all this data into a vector of connection points, each connection point is going to be in a different ID.
|
||||
//therefore, we need to convert the Tiled IDs into whatever vector index we insert each connection into for State_OverworldMap::connections.
|
||||
for(auto key:stagePlates){
|
||||
|
||||
@ -23,6 +23,7 @@ Cherry pick 66a10cee9f874f024633efdc84ebb4432752ab15 from SkeletonFireMage
|
||||
Snow particles must fade away when Blizzard dies
|
||||
Blizzard blue area circle should remain during the duration of the attack
|
||||
Add comments to Effect child Update and Draw declarations
|
||||
Check for precache locally generated file to re-add to pack first if the date is still current.
|
||||
|
||||
|
||||
DEMO
|
||||
|
||||
@ -56,14 +56,15 @@ void Test::RunMapTests(){
|
||||
is("There are two LowerBridgeCollision zones in Campaign I-I",
|
||||
game->GetZones("CAMPAIGN_1_1").count("LowerBridgeCollision")
|
||||
&&game->GetZones("CAMPAIGN_1_1").at("LowerBridgeCollision").size()>=2);
|
||||
for(auto&map:game->MAP_DATA){
|
||||
for(auto&[key,size]:DATA["Levels"]){
|
||||
const Map&map{game->MAP_DATA[key]};
|
||||
if(map.GetMapType()==Map::MapType::DUNGEON){
|
||||
is("There is an EndZone in Dungeon "+std::string{map.GetMapDisplayName()},
|
||||
game->GetZones(map.GetMapName()).count("EndZone"));
|
||||
is("There is an EndZone in Dungeon "+std::string{map.GetMapStageName()},
|
||||
game->GetZones(map.GetMapKeyName()).count("EndZone"));
|
||||
}
|
||||
|
||||
for(const ZoneData&endZone:map.GetZones().at("EndZone")){
|
||||
if(endZone.isUpper&&(!map.GetZones().count("UpperZone")||map.GetZones().at("UpperZone").size()==0))ERR(std::format("WARNING! An End Zone was found in map {} with the upper flag when no upper transition zones have been defined in a stage!",map.GetMapDisplayName()));
|
||||
for(const ZoneData&endZone:map.GetZones()["EndZone"]){
|
||||
if(endZone.isUpper&&(!map.GetZones().count("UpperZone")||map.GetZones().at("UpperZone").size()==0))ERR(std::format("WARNING! An End Zone was found in map {} with the upper flag when no upper transition zones have been defined in a stage!",map.GetMapStageName()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -53,8 +53,6 @@ using A=Attribute;
|
||||
INCLUDE_game
|
||||
INCLUDE_DEMO_BUILD
|
||||
|
||||
#undef BLACKSMITH
|
||||
|
||||
enum class TutorialTaskName{
|
||||
SET_LOADOUT_ITEM,
|
||||
MOVE_AROUND,
|
||||
|
||||
@ -39,7 +39,7 @@ All rights reserved.
|
||||
#define VERSION_MAJOR 1
|
||||
#define VERSION_MINOR 3
|
||||
#define VERSION_PATCH 0
|
||||
#define VERSION_BUILD 12701
|
||||
#define VERSION_BUILD 12770
|
||||
|
||||
#define stringify(a) stringify_(a)
|
||||
#define stringify_(a) #a
|
||||
|
||||
@ -269,7 +269,6 @@
|
||||
<ellipse/>
|
||||
</object>
|
||||
<object id="6" name="Boss Arena" type="BossArena" x="196" y="285" width="1339" height="1395"/>
|
||||
<object id="7" x="29" y="444"/>
|
||||
<object id="9" template="../maps/Monsters/Slime King.tx" x="768" y="768">
|
||||
<properties>
|
||||
<property name="spawner" type="object" value="3"/>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="foresty_loop1"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="5"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="3"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="../maps/Tilesheet_No_Shadow24x24.tsx"/>
|
||||
<tileset firstgid="2913" source="../maps/No_Shadow_Campfire_24x24.tsx"/>
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="forest"/>
|
||||
<property name="Background Music" propertytype="BGM" value="base_camp"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="5"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="3"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="../maps/Tilesheet_No_Shadow24x24as12x12.tsx"/>
|
||||
<tileset firstgid="11649" source="../maps/16x16px_grid_Props_No_Shadow_12x12.tsx"/>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="right-down" width="152" height="114" tilewidth="24" tileheight="24" infinite="0" nextlayerid="25" nextobjectid="72">
|
||||
<properties>
|
||||
<property name="Backdrop" propertytype="Backdrop" value="None"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="4"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="2"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="../maps/Tilesheet_No_Shadow24x24.tsx"/>
|
||||
<tileset firstgid="2913" source="../maps/Decorations_c1_No_Shadow24x24.tsx"/>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<map version="1.10" tiledversion="1.10.2" class="Map" orientation="orthogonal" renderorder="left-down" width="266" height="184" tilewidth="4" tileheight="4" infinite="0" nextlayerid="5" nextobjectid="66">
|
||||
<properties>
|
||||
<property name="Background Music" propertytype="BGM" value="overworld"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="4"/>
|
||||
<property name="Level Type" type="int" propertytype="LevelType" value="2"/>
|
||||
<property name="Optimize" type="bool" value="true"/>
|
||||
</properties>
|
||||
<tileset firstgid="1" source="../maps/Minifantasy_TinyOverworldAllTiles.tsx"/>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
INTRO_MAP = 2026-02-23 21:02:53.4861099
|
||||
HUB = 2024-09-13 21:41:17.0093533
|
||||
INTRO_MAP = 2026-02-25 23:20:16.1394483
|
||||
HUB = 2026-02-25 23:20:30.2917000
|
||||
TEST_MAP = 2026-01-26 20:40:12.7201277
|
||||
BOSS_1 = 2026-02-23 20:43:43.6912540
|
||||
WORLD_MAP = 2026-01-26 20:47:50.3754255
|
||||
BOSS_1 = 2026-02-25 22:36:51.8834583
|
||||
WORLD_MAP = 2026-02-25 23:20:16.1384937
|
||||
CAMPAIGN_1_1 = 2026-01-21 20:30:58.3723266
|
||||
BOSS_1_B = 2024-09-13 21:28:58.8886132
|
||||
BOSS_2 = 2026-01-21 20:30:58.4312572
|
||||
|
||||
@ -41,6 +41,7 @@ All rights reserved.
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include<algorithm>
|
||||
#include<ranges>
|
||||
|
||||
//A class that has an initialization lock so that when the lock is activated, any further gets that are missing items in it will report themselves for easier debugging detection.
|
||||
template<typename T,typename O>
|
||||
@ -72,7 +73,7 @@ public:
|
||||
auto insert(T key,O obj){
|
||||
return map.insert({key,obj});
|
||||
}
|
||||
size_t count(T key){
|
||||
size_t count(T key)const{
|
||||
return map.count(key);
|
||||
}
|
||||
void SetInitialized(){
|
||||
@ -137,18 +138,28 @@ public:
|
||||
return items[map[key]];
|
||||
}
|
||||
}
|
||||
const O&operator[](T key)const{
|
||||
if(initialized&&map.count(key)==0){
|
||||
ERR("WARNING! Trying to get non-existent key "<<key<<"!")
|
||||
}
|
||||
return items.at(map.at(key));
|
||||
}
|
||||
O&at(T key){
|
||||
return items.at(map.at(key));
|
||||
}
|
||||
const O&at(T key)const{
|
||||
return items.at(map.at(key));
|
||||
}
|
||||
size_t count(T key){
|
||||
size_t count(T key)const{
|
||||
return map.count(key);
|
||||
}
|
||||
void SetInitialized(){
|
||||
initialized=true;
|
||||
}
|
||||
//Unlocks the map so items can be added to it again. USE WITH CAUTION! And make sure to lock the map again.
|
||||
void Unlock(){
|
||||
initialized=false;
|
||||
}
|
||||
size_t size(){
|
||||
return map.size();
|
||||
}
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user