Make Unlock All button actually unlock every node. Allow tile fade groups to specify tiles that should be unhidden. NPCs have unlock conditions now. Layers have unlock conditions.

pull/35/head
sigonasr2 12 months ago
parent 7a41361710
commit 390e7fefbf
  1. 33
      Adventures in Lestoria/Adventures in Lestoria.tiled-project
  2. 4
      Adventures in Lestoria/Adventures in Lestoria.vcxproj
  3. 3
      Adventures in Lestoria/Adventures in Lestoria.vcxproj.filters
  4. 301
      Adventures in Lestoria/AdventuresInLestoria.cpp
  5. 4
      Adventures in Lestoria/Map.h
  6. 1
      Adventures in Lestoria/Menu.cpp
  7. 1
      Adventures in Lestoria/Menu.h
  8. 1
      Adventures in Lestoria/MenuType.h
  9. 5
      Adventures in Lestoria/SettingsWindow.cpp
  10. 50
      Adventures in Lestoria/ShermanWindow.cpp
  11. 19
      Adventures in Lestoria/TMXParser.h
  12. 18
      Adventures in Lestoria/TSXParser.h
  13. 2
      Adventures in Lestoria/Unlock.cpp
  14. 2
      Adventures in Lestoria/Version.h
  15. 25
      Adventures in Lestoria/assets/Campaigns/Hub_v2.tmx
  16. 121
      Adventures in Lestoria/assets/maps/16x16px_grid_Props_No_Shadow_12x12.tsx
  17. BIN
      x64/Release/Adventures in Lestoria.exe

@ -151,30 +151,16 @@
],
"valuesAsFlags": false
},
{
"id": 34,
"name": "EventFlag",
"storageType": "string",
"type": "enum",
"values": [
"None",
"UnlockBlacksmith",
"UnlockPotionCrafting",
"CompleteChapter1",
"UnlockArtificer"
],
"valuesAsFlags": false
},
{
"color": "#ffa0a0a4",
"drawFill": true,
"id": 35,
"members": [
{
"name": "Visibility Flag",
"propertyType": "EventFlag",
"name": "Layer Unlock Condition",
"propertyType": "Level",
"type": "string",
"value": "None"
"value": "WORLD_MAP"
}
],
"name": "EventLayer",
@ -223,7 +209,8 @@
"BOSS_1",
"HUB",
"CAMPAIGN_1_B1",
"BOSS_1_B"
"BOSS_1_B",
"STORY_2_1"
],
"valuesAsFlags": false
},
@ -370,15 +357,15 @@
"value": 0
},
{
"name": "Spawn Flag",
"propertyType": "EventFlag",
"name": "Spritesheet",
"type": "string",
"value": "None"
"value": ""
},
{
"name": "Spritesheet",
"name": "Unlock Condition",
"propertyType": "Level",
"type": "string",
"value": ""
"value": "WORLD_MAP"
}
],
"name": "NPC",

@ -656,6 +656,10 @@
</SubType>
</ClCompile>
<ClCompile Include="SettingsWindow.cpp" />
<ClCompile Include="ShermanWindow.cpp">
<SubType>
</SubType>
</ClCompile>
<ClCompile Include="ShootAfar.cpp" />
<ClCompile Include="SlimeKing.cpp" />
<ClCompile Include="SoundEffect.cpp">

@ -773,6 +773,9 @@
<ClCompile Include="NPC.cpp">
<Filter>Source Files\Monster Strategies</Filter>
</ClCompile>
<ClCompile Include="ShermanWindow.cpp">
<Filter>Source Files\Interface</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="cpp.hint" />

@ -937,32 +937,64 @@ void AiL::RenderWorld(float fElapsedTime){
switch(mode){
case RenderMode::NORMAL_TILES:{
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
if(IsBridgeLayer(layer)){
bridgeLayer=&layer;
if(!bridgeLayerFade&&!player->upperLevel){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
int playerXTruncated=int(player->GetPos().x)/GetCurrentMapData().tilewidth;
int playerYTruncated=int(player->GetPos().y)/GetCurrentMapData().tilewidth;
if(playerXTruncated==x&&playerYTruncated==y){
bridgeLayerFade=true;
if(Unlock::IsUnlocked(layer.unlockCondition)){
if(IsBridgeLayer(layer)){
bridgeLayer=&layer;
if(!bridgeLayerFade&&!player->upperLevel){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
int playerXTruncated=int(player->GetPos().x)/GetCurrentMapData().tilewidth;
int playerYTruncated=int(player->GetPos().y)/GetCurrentMapData().tilewidth;
if(playerXTruncated==x&&playerYTruncated==y){
bridgeLayerFade=true;
}
}
}
continue;
}
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
if(!IsForegroundTile(tileSheet,tileSheetIndex)&&!IsUpperForegroundTile(tileSheetIndex)&&!IsReflectiveTile(tileSheet,tileSheetIndex)){
if(layer.tag.data["class"]!="CollisionOnly"){visibleTiles.erase({x,y});}
RenderTile({x,y},tileSheet,tileSheetIndex,{tileSheetX,tileSheetY});
#pragma region Debug Collision boxes
#ifdef _DEBUG
if("debug_collision_boxes"_I){
if(tileSheet.tileset->collision.find(tileSheetIndex)!=tileSheet.tileset->collision.end()){
geom2d::rect<float>collision=tileSheet.tileset->collision[tileSheetIndex].collision;
view.FillRectDecal(vf2d{float(x),float(y)}*float(GetCurrentMapData().tilewidth)+collision.pos,collision.size,{0,0,0,128});
view.DrawRectDecal(vf2d{float(x),float(y)}*float(GetCurrentMapData().tilewidth)+collision.pos,collision.size,GREY);
}
}
#endif
#pragma endregion
}
}
continue;
}
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
if(!IsForegroundTile(tileSheet,tileSheetIndex)&&!IsUpperForegroundTile(tileSheetIndex)&&!IsReflectiveTile(tileSheet,tileSheetIndex)){
if(layer.tag.data["class"]!="CollisionOnly"){visibleTiles.erase({x,y});}
RenderTile({x,y},tileSheet,tileSheetIndex,{tileSheetX,tileSheetY});
#pragma region Debug Collision boxes
}
}break;
case RenderMode::REFLECTIVE_TILES:{
visibleTiles.insert({x,y});
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
if(Unlock::IsUnlocked(layer.unlockCondition)){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
if(IsReflectiveTile(tileSheet,tileSheetIndex)){
if(layer.tag.data["class"]!="CollisionOnly"){visibleTiles.erase({x,y});}
RenderTile({x,y},tileSheet,tileSheetIndex,{tileSheetX,tileSheetY});
}
#ifdef _DEBUG
if("debug_collision_boxes"_I){
if(tileSheet.tileset->collision.find(tileSheetIndex)!=tileSheet.tileset->collision.end()){
@ -972,38 +1004,10 @@ void AiL::RenderWorld(float fElapsedTime){
}
}
#endif
#pragma endregion
}
}
}
}break;
case RenderMode::REFLECTIVE_TILES:{
visibleTiles.insert({x,y});
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth;
if(IsReflectiveTile(tileSheet,tileSheetIndex)){
if(layer.tag.data["class"]!="CollisionOnly"){visibleTiles.erase({x,y});}
RenderTile({x,y},tileSheet,tileSheetIndex,{tileSheetX,tileSheetY});
}
#ifdef _DEBUG
if("debug_collision_boxes"_I){
if(tileSheet.tileset->collision.find(tileSheetIndex)!=tileSheet.tileset->collision.end()){
geom2d::rect<float>collision=tileSheet.tileset->collision[tileSheetIndex].collision;
view.FillRectDecal(vf2d{float(x),float(y)}*float(GetCurrentMapData().tilewidth)+collision.pos,collision.size,{0,0,0,128});
view.DrawRectDecal(vf2d{float(x),float(y)}*float(GetCurrentMapData().tilewidth)+collision.pos,collision.size,GREY);
}
}
#endif
}
}
}break;
case RenderMode::EMPTY_TILES:{
if(visibleTiles.count({x,y})){
#pragma region Render Backdrop
@ -1120,6 +1124,13 @@ void AiL::RenderWorld(float fElapsedTime){
}
for(TileRenderData&tile:group.GetTiles()){
tile.tileOpacity=group.fadeFactor;
#pragma region Unhiding tile detection
auto it=tile.tileSheet.tileset->foregroundTiles.find(tile.tileID); //We're looking for tiles that are marked as should not be faded away by a tile group.
if(it!=tile.tileSheet.tileset->foregroundTiles.end()){
if(!(*it).second.hide)tile.tileOpacity=0.f;
}
#pragma endregion
if(tile.tileSheet.tileset->collision.find(tile.tileID)!=tile.tileSheet.tileset->collision.end()){
tilePreparationList.push_back(&tile);
}else{
@ -1279,6 +1290,14 @@ void AiL::RenderWorld(float fElapsedTime){
}
for(TileRenderData&tile:group.GetTiles()){
tile.tileOpacity=group.fadeFactor;
#pragma region Unhiding tile detection
auto it=tile.tileSheet.tileset->upperForegroundTiles.find(tile.tileID); //We're looking for tiles that are marked as should not be faded away by a tile group.
if(it!=tile.tileSheet.tileset->upperForegroundTiles.end()){
if(!(*it).second.hide)tile.tileOpacity=0.f;
}
#pragma endregion
if(tile.tileSheet.tileset->collision.find(tile.tileID)!=tile.tileSheet.tileset->collision.end()){
tilePreparationList.push_back(&tile);
}else{
@ -1843,74 +1862,76 @@ void AiL::LoadLevel(MapName map){
for(int y=0;y<GetCurrentMapData().height;y++){
int layerID=0;
for(LayerTag&layer:MAP_DATA[currentLevel].LayerData){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth;
int tileSheetY=realTileSheetIndex/tileSheetWidth;
int checkTileIndex=tileID;
int checkTileID=tileSheetIndex;
#pragma region TileGroupShenanigans
auto SetupTileGroups=[&](std::function<bool(TilesheetData,int)>IsForeground,TileRenderData tile,std::set<vi2d>&foregroundTilesIncluded,std::vector<TileGroup>&groups){
if(foregroundTilesIncluded.find({x,y})==foregroundTilesIncluded.end()&&IsForeground(tileSheet,tileSheetIndex)){
std::queue<vi2d>tileGroupChecks;
TileGroup group;
foregroundTilesIncluded.insert({x,y});
group.InsertTile(tile);
if(x>0&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{-1,0})==foregroundTilesIncluded.end())tileGroupChecks.push({x-1,y});
if(x<GetCurrentMapData().width-1&&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(y<GetCurrentMapData().height-1&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{0,1})==foregroundTilesIncluded.end())tileGroupChecks.push({x,y+1});
auto IterateThroughOtherLayers=[&](vi2d pos,bool loopAll=false){
int layer2ID=0;
bool hadForeground=false;
for(LayerTag&layer2:MAP_DATA[currentLevel].LayerData){
if(!loopAll&&&layer==&layer2){layer2ID++;continue;};
int tileID=layer2.tiles[pos.y][pos.x]-1;
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID%1000000);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth;
int tileSheetY=realTileSheetIndex/tileSheetWidth;
TileRenderData tile={tileSheet,vi2d{pos.x,pos.y}*game->GetCurrentMapData().tilewidth,vi2d{tileSheetX,tileSheetY}*game->GetCurrentMapData().tilewidth,realTileSheetIndex,layer2ID};
if(IsForeground(tileSheet,tileSheetIndex)){
foregroundTilesIncluded.insert({pos.x,pos.y});
group.InsertTile(tile);
hadForeground=true;
if(Unlock::IsUnlocked(layer.unlockCondition)){
int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth;
int tileSheetY=realTileSheetIndex/tileSheetWidth;
int checkTileIndex=tileID;
int checkTileID=tileSheetIndex;
#pragma region TileGroupShenanigans
auto SetupTileGroups=[&](std::function<bool(TilesheetData,int)>IsForeground,TileRenderData tile,std::set<vi2d>&foregroundTilesIncluded,std::vector<TileGroup>&groups){
if(foregroundTilesIncluded.find({x,y})==foregroundTilesIncluded.end()&&IsForeground(tileSheet,tileSheetIndex)){
std::queue<vi2d>tileGroupChecks;
TileGroup group;
foregroundTilesIncluded.insert({x,y});
group.InsertTile(tile);
if(x>0&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{-1,0})==foregroundTilesIncluded.end())tileGroupChecks.push({x-1,y});
if(x<GetCurrentMapData().width-1&&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(y<GetCurrentMapData().height-1&&foregroundTilesIncluded.find(vi2d{x,y}+vi2d{0,1})==foregroundTilesIncluded.end())tileGroupChecks.push({x,y+1});
auto IterateThroughOtherLayers=[&](vi2d pos,bool loopAll=false){
int layer2ID=0;
bool hadForeground=false;
for(LayerTag&layer2:MAP_DATA[currentLevel].LayerData){
if(!loopAll&&&layer==&layer2){layer2ID++;continue;};
int tileID=layer2.tiles[pos.y][pos.x]-1;
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID%1000000);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth;
int tileSheetY=realTileSheetIndex/tileSheetWidth;
TileRenderData tile={tileSheet,vi2d{pos.x,pos.y}*game->GetCurrentMapData().tilewidth,vi2d{tileSheetX,tileSheetY}*game->GetCurrentMapData().tilewidth,realTileSheetIndex,layer2ID};
if(IsForeground(tileSheet,tileSheetIndex)){
foregroundTilesIncluded.insert({pos.x,pos.y});
group.InsertTile(tile);
hadForeground=true;
}
layer2ID++;
}
layer2ID++;
}
return hadForeground;
};
IterateThroughOtherLayers({x,y});
while(!tileGroupChecks.empty()){
vi2d&pos=tileGroupChecks.front();
if(IterateThroughOtherLayers(pos,true)){
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.
vi2d targetPos=pos+vi2d{-1,0};
if(pos.x>0&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{1,0};
if(pos.x<GetCurrentMapData().width-1&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{0,-1};
if(pos.y>0&&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);}
return hadForeground;
};
IterateThroughOtherLayers({x,y});
while(!tileGroupChecks.empty()){
vi2d&pos=tileGroupChecks.front();
if(IterateThroughOtherLayers(pos,true)){
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.
vi2d targetPos=pos+vi2d{-1,0};
if(pos.x>0&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{1,0};
if(pos.x<GetCurrentMapData().width-1&&foregroundTilesIncluded.find(targetPos)==foregroundTilesIncluded.end()){tileGroupChecks.push(targetPos);foregroundTilesIncluded.insert(targetPos);}
targetPos=pos+vi2d{0,-1};
if(pos.y>0&&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);
SetupTileGroups([&](TilesheetData sheet,int tileID){return IsUpperForegroundTile(tileID);},tile,upperForegroundTilesAdded,upperForegroundTileGroups);
#pragma endregion
};
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);
SetupTileGroups([&](TilesheetData sheet,int tileID){return IsUpperForegroundTile(tileID);},tile,upperForegroundTilesAdded,upperForegroundTileGroups);
#pragma endregion
}
}
layerID++;
}
@ -2003,9 +2024,11 @@ void AiL::LoadLevel(MapName map){
#pragma endregion
for(NPCData data:game->MAP_DATA[game->GetCurrentLevel()].npcs){
MONSTER_LIST.push_back(Monster{data.spawnPos,MONSTER_DATA[data.name]});
MONSTER_LIST.back().iframe_timer=INFINITE;
MONSTER_LIST.back().npcData=data;
if(Unlock::IsUnlocked(data.unlockCondition)){
MONSTER_LIST.push_back(Monster{data.spawnPos,MONSTER_DATA[data.name]});
MONSTER_LIST.back().iframe_timer=INFINITE;
MONSTER_LIST.back().npcData=data;
}
}
player->GetAbility1().cooldown=0.f;
@ -2077,12 +2100,14 @@ geom2d::rect<float>AiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel){
bool hasTerrain=false;
for(const LayerTag&layer:GetCurrentMap().LayerData){ //Figure out if any tile at this position is terrain. If so, we have a collision box to check.
int tileID=layer.tiles[pos.y/GetCurrentMapData().tilewidth][pos.x/GetCurrentMapData().tilewidth]-1;
if(tileID==-1)continue;
const TilesheetData&data=GetTileSheet(GetCurrentLevel(),tileID);
if(data.tileset->isTerrain){
hasTerrain=true;
break;
if(Unlock::IsUnlocked(layer.unlockCondition)){
int tileID=layer.tiles[pos.y/GetCurrentMapData().tilewidth][pos.x/GetCurrentMapData().tilewidth]-1;
if(tileID==-1)continue;
const TilesheetData&data=GetTileSheet(GetCurrentLevel(),tileID);
if(data.tileset->isTerrain){
hasTerrain=true;
break;
}
}
}
if(!hasTerrain)return geom2d::rect<float>({0.f,0.f},{float(GetCurrentMapData().tilewidth),float(GetCurrentMapData().tilewidth)}); //We assume no terrain means we can't walk on this.
@ -2108,19 +2133,21 @@ geom2d::rect<float>AiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel){
}
geom2d::rect<float>foundRect=NO_COLLISION;
for(int counter=0;LayerTag&layer:MAP_DATA[map].LayerData){
//auto HasNoClass=[&](){return layer.tag.data.find("class")==layer.tag.data.end();};
if(counter!=bridgeLayerIndex){
int tileID=layer.tiles[int(pos.y)/GetCurrentMapData().tilewidth][int(pos.x)/GetCurrentMapData().tilewidth]-1;
if(tileID!=-1&&GetTileSheet(map,tileID%1000000).tileset->collision.find(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1)!=GetTileSheet(map,tileID%1000000).tileset->collision.end()){
geom2d::rect<float>collisionRect=GetTileSheet(map,tileID%1000000).tileset->collision[tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1].collision;
if(foundRect==NO_COLLISION){
foundRect=collisionRect;
}else{
//When we find another rectangle in the same square, we expand it to consume the area, whichever tile creates a larger surface or the combination of the two.
foundRect.pos.x=std::min(foundRect.pos.x,collisionRect.pos.x);
foundRect.pos.y=std::min(foundRect.pos.y,collisionRect.pos.y);
foundRect.size.x=std::max(foundRect.size.x,collisionRect.size.x);
foundRect.size.y=std::max(foundRect.size.y,collisionRect.size.y);
if(Unlock::IsUnlocked(layer.unlockCondition)){
//auto HasNoClass=[&](){return layer.tag.data.find("class")==layer.tag.data.end();};
if(counter!=bridgeLayerIndex){
int tileID=layer.tiles[int(pos.y)/GetCurrentMapData().tilewidth][int(pos.x)/GetCurrentMapData().tilewidth]-1;
if(tileID!=-1&&GetTileSheet(map,tileID%1000000).tileset->collision.find(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1)!=GetTileSheet(map,tileID%1000000).tileset->collision.end()){
geom2d::rect<float>collisionRect=GetTileSheet(map,tileID%1000000).tileset->collision[tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1].collision;
if(foundRect==NO_COLLISION){
foundRect=collisionRect;
}else{
//When we find another rectangle in the same square, we expand it to consume the area, whichever tile creates a larger surface or the combination of the two.
foundRect.pos.x=std::min(foundRect.pos.x,collisionRect.pos.x);
foundRect.pos.y=std::min(foundRect.pos.y,collisionRect.pos.y);
foundRect.size.x=std::max(foundRect.size.x,collisionRect.size.x);
foundRect.size.y=std::max(foundRect.size.y,collisionRect.size.y);
}
}
}
}

@ -57,8 +57,8 @@ struct TilesetData{
Renderable*tileset=nullptr;
int tilewidth=0,tileheight=0;
bool isTerrain=false;
std::map<int,XMLTag>foregroundTiles;
std::map<int,XMLTag>upperForegroundTiles;
std::map<int,ForegroundTileTag>foregroundTiles;
std::map<int,ForegroundTileTag>upperForegroundTiles;
std::map<float,TileCollisionData>collision;
std::map<int,XMLTag>staircaseTiles;
std::map<int,std::vector<int>>animationData;

@ -98,6 +98,7 @@ void Menu::InitializeMenus(){
InitializeLoadGameWindow();
InitializeUserIDWindow();
InitializeSettingsWindow();
InitializeShermanWindow();
for(MenuType type=MenuType(int(MenuType::ENUM_START)+1);type<MenuType::ENUM_END;type=MenuType(int(type+1))){
if(menus.count(type)==0){

@ -110,6 +110,7 @@ class Menu:public IAttributable{
static void InitializeLoadGameWindow();
static void InitializeUserIDWindow();
static void InitializeSettingsWindow();
static void InitializeShermanWindow();
friend class AiL;
friend class ItemInfo;

@ -62,6 +62,7 @@ enum MenuType{
LOAD_GAME,
USER_ID,
SETTINGS,
SHERMAN,
///////////////////////////////////////////////////////////
/*DO NOT REMOVE!!*/ENUM_END////////////////////////////////
///////////////////////////////////////////////////////////

@ -43,6 +43,7 @@ All rights reserved.
#include "DEFINES.h"
#include "olcUTIL_DataFile.h"
#include "Unlock.h"
#include "State_OverworldMap.h"
INCLUDE_DATA
INCLUDE_game
@ -53,8 +54,8 @@ void Menu::InitializeSettingsWindow(){
Menu*settingsWindow=CreateMenu(SETTINGS,CENTERED,windowSize);
settingsWindow->ADD("Unlock All Button",MenuComponent)(geom2d::rect<float>{{4,4},{72,12}},"Unlock All",[](MenuFuncData data){
for(auto&[key,size]:DATA["Levels"]){
Unlock::UnlockArea(key);
for(auto&cp:State_OverworldMap::connections){
Unlock::UnlockArea(cp.map);
}
SoundEffect::PlaySFX("Buy Item",SoundEffect::CENTERED);
return true;

@ -0,0 +1,50 @@
#pragma region License
/*
License (OLC-3)
~~~~~~~~~~~~~~~
Copyright 2024 Joshua Sigona <sigonasr2@gmail.com>
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions or derivations of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice. This list of conditions and the following disclaimer must be
reproduced in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
Portions of this software are copyright © 2023 The FreeType
Project (www.freetype.org). Please see LICENSE_FT.txt for more information.
All rights reserved.
*/
#pragma endregion
#include "Menu.h"
#include "MenuComponent.h"
#include "GameState.h"
void Menu::InitializeShermanWindow(){
Menu*shermanWindow=CreateMenu(SHERMAN,CENTERED,vi2d{144,120});
shermanWindow->ADD("Leave Button",MenuComponent)(geom2d::rect<float>{{-48.f,4.f},{96.f,24.f}},"Leave",MenuType::ENUM_END,[](MenuFuncData data){
GameState::ChangeState(States::OVERWORLD_MAP,0.3f);
return true;
},vf2d{2.f,2.f})END;
}

@ -62,6 +62,11 @@ struct XMLTag{
std::string GetString(std::string dataTag);
};
struct ForegroundTileTag:public XMLTag{
//Whether or not to hide this foreground tile
bool hide=true;
};
struct MapTag{
int width=0,height=0;
int tilewidth=0,tileheight=0;
@ -77,6 +82,7 @@ struct MapTag{
struct LayerTag{
XMLTag tag;
std::vector<std::vector<int>> tiles;
std::string unlockCondition="";
std::string str();
};
@ -98,7 +104,7 @@ struct NPCData{
std::string function="";
std::string name="";
std::string sprite="";
std::string spawnFlag="";
std::string unlockCondition="";
uint32_t roamingRange=0;
vf2d spawnPos;
NPCData();
@ -173,6 +179,7 @@ class TMXParser{
std::vector<XMLTag>accumulatedMonsterTags;
std::map<int,StagePlate>stagePlates;
bool infiniteMap=false;
LayerTag*currentLayerTag=nullptr;
public:
TMXParser(std::string file);
};
@ -299,7 +306,7 @@ class TMXParser{
}
NPCData::NPCData(){}
NPCData::NPCData(XMLTag npcTag){
const std::array<std::string,7>tags={"Function","NPC Name","Roaming Range","Spawn Flag","Spritesheet","x","y"};
const std::array<std::string,7>tags={"Function","NPC Name","Roaming Range","Unlock Condition","Spritesheet","x","y"};
for(int i=0;i<tags.size();i++){
if(npcTag.data.contains(tags[i])){
@ -313,8 +320,8 @@ class TMXParser{
case 2:{ //Roaming Range
roamingRange=npcTag.GetInteger(tags[i]);
}break;
case 3:{ //Spawn Flag
spawnFlag=npcTag.GetString(tags[i]);
case 3:{ //Unlock Condition
unlockCondition=npcTag.GetString(tags[i]);
}break;
case 4:{ //Spritesheet
sprite=npcTag.GetString(tags[i]);
@ -427,6 +434,7 @@ class TMXParser{
if (newTag.tag=="layer"){
LayerTag l = {newTag};
parsedMapInfo.LayerData.push_back(l);
currentLayerTag=&parsedMapInfo.LayerData.back();
}else
if (newTag.tag=="object"&&newTag.data["type"]=="SpawnGroup"){
if(newTag.GetInteger("id")!=0){
@ -434,6 +442,9 @@ class TMXParser{
prevSpawner=newTag.GetInteger("id");
}
} else
if(newTag.tag=="property"&&newTag.data["name"]=="Layer Unlock Condition"&&currentLayerTag!=nullptr){
currentLayerTag->unlockCondition=newTag.data["value"];
} else
if(newTag.tag=="property"&&newTag.data["name"]=="Upper?"&&prevZoneData!=nullptr){
prevZoneData->isUpper=newTag.GetBool("value");
}else

@ -49,8 +49,8 @@ struct Tileset{
int tilewidth=0,tileheight=0;
int imagewidth=0,imageheight=0;
bool isTerrain=false;
std::map<int,XMLTag> ForegroundTileData;
std::map<int,XMLTag> UpperForegroundTileData;
std::map<int,ForegroundTileTag> ForegroundTileData;
std::map<int,ForegroundTileTag> UpperForegroundTileData;
std::map<float,TileCollisionData> CollisionData;
std::map<int,XMLTag> StaircaseData;
std::map<int,std::vector<int>> AnimationData;
@ -67,6 +67,7 @@ class TSXParser{
std::string previousTag;
int previousTagID;
std::string staircaseTag="";
ForegroundTileTag*currentTileTag=nullptr;
public:
TSXParser(std::string file);
};
@ -145,13 +146,22 @@ class TSXParser{
if (newTag.tag=="tile"&&newTag.data["type"]=="ForegroundTile"){
previousTag=newTag.tag;
previousTagID=newTag.GetInteger("id");
parsedTilesetInfo.ForegroundTileData[newTag.GetInteger("id")]=newTag;
currentTileTag=&parsedTilesetInfo.ForegroundTileData[newTag.GetInteger("id")];
parsedTilesetInfo.ForegroundTileData[newTag.GetInteger("id")].tag=newTag.tag;
parsedTilesetInfo.ForegroundTileData[newTag.GetInteger("id")].data=newTag.data;
} else
if (newTag.tag=="tile"&&newTag.data["type"]=="UpperForegroundTile"){
previousTag=newTag.tag;
previousTagID=newTag.GetInteger("id");
parsedTilesetInfo.UpperForegroundTileData[newTag.GetInteger("id")]=newTag;
currentTileTag=&parsedTilesetInfo.ForegroundTileData[newTag.GetInteger("id")];
parsedTilesetInfo.UpperForegroundTileData[newTag.GetInteger("id")].tag=newTag.tag;
parsedTilesetInfo.UpperForegroundTileData[newTag.GetInteger("id")].data=newTag.data;
} else
if (newTag.tag=="property"&&newTag.data["name"]=="Hide?"){
if(currentTileTag==nullptr)ERR("WARNING! Cannot set hide value for a nullptr currentTileTag! THIS SHOULD NOT BE HAPPENING!");
currentTileTag->hide=newTag.GetBool("value");
}else
if (newTag.tag=="tile"&&newTag.data["type"]=="Staircase"){
previousTag=newTag.tag;
staircaseTag=newTag.tag;

@ -48,7 +48,7 @@ void Unlock::UnlockArea(std::string mapName){
unlocks.insert(mapName);
}
bool Unlock::IsUnlocked(std::string mapName){
return unlocks.count(mapName);
return unlocks.count(mapName)||mapName.length()==0;
}
bool Unlock::IsUnlocked(ConnectionPoint&cp){

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

@ -138,7 +138,10 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="4" name="Layer 3 (Blacksmith)" width="70" height="60">
<layer id="4" name="Layer 3 (Blacksmith)" class="EventLayer" width="70" height="60">
<properties>
<property name="Layer Unlock Condition" propertytype="Level" value="STORY_1_2"/>
</properties>
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -202,7 +205,10 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="5" name="Layer 4 (Artificer)" width="70" height="60">
<layer id="5" name="Layer 4 (Artificer)" class="EventLayer" width="70" height="60">
<properties>
<property name="Layer Unlock Condition" propertytype="Level" value="STORY_2_1"/>
</properties>
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@ -266,7 +272,10 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="6" name="Layer 5 (after Chapter 1)" width="70" height="60">
<layer id="6" name="Layer 5 (after Chapter 1)" class="EventLayer" width="70" height="60">
<properties>
<property name="Layer Unlock Condition" propertytype="Level" value="STORY_2_1"/>
</properties>
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12957,12958,0,12957,12958,0,12957,12958,0,12957,12958,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13006,13007,0,13006,13007,0,13006,13007,0,13006,13007,0,
@ -330,7 +339,10 @@
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
</data>
</layer>
<layer id="7" name="Layer 6 (after Chapter 1)" width="70" height="60">
<layer id="7" name="Layer 6 (after Chapter 1)" class="EventLayer" width="70" height="60">
<properties>
<property name="Layer Unlock Condition" propertytype="Level" value="STORY_2_1"/>
</properties>
<data encoding="csv">
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12410,12411,0,12410,12411,0,12410,12411,0,12410,12411,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12459,12460,0,12459,12460,0,12459,12460,0,12459,12460,0,
@ -406,8 +418,9 @@
<property name="Function" propertytype="NPCFunction" value="Blacksmith"/>
<property name="NPC Name" value="Greg"/>
<property name="Roaming Range" type="int" value="300"/>
<property name="Spawn Flag" propertytype="EventFlag" value="UnlockBlacksmith"/>
<property name="Spawn Flag" type="int" value="1"/>
<property name="Spritesheet" value="Greg.png"/>
<property name="Unlock Condition" propertytype="Level" value="STORY_1_2"/>
</properties>
<point/>
</object>
@ -417,6 +430,7 @@
<property name="NPC Name" value="Traveling Merchant"/>
<property name="Roaming Range" type="int" value="100"/>
<property name="Spritesheet" value="Traveling Merchant.png"/>
<property name="Unlock Condition" propertytype="Level" value="WORLD_MAP"/>
</properties>
<point/>
</object>
@ -425,6 +439,7 @@
<property name="Function" propertytype="NPCFunction" value="PotionCrafting"/>
<property name="NPC Name" value="Sherman"/>
<property name="Spritesheet" value="Sherman.png"/>
<property name="Unlock Condition" propertytype="Level" value="WORLD_MAP"/>
</properties>
<point/>
</object>

@ -1,52 +1,107 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.10" tiledversion="1.10.1" name="16x16px_grid_Props_No_Shadow_12x12" tilewidth="12" tileheight="12" tilecount="2107" columns="49">
<image source="commercial_assets/16x16px_grid_Props_No_Shadow_12x12.png" width="588" height="516"/>
<tile id="85">
<tile id="36" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="37" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="38" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="39" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="40" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="85" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="3">
<object id="2" x="7" y="9" width="5" height="3"/>
</objectgroup>
</tile>
<tile id="86">
<tile id="86" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="0" y="9" width="12" height="3"/>
</objectgroup>
</tile>
<tile id="87">
<tile id="87" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="0" y="9" width="12" height="3"/>
</objectgroup>
</tile>
<tile id="88">
<tile id="88" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="0" y="9" width="12" height="3"/>
</objectgroup>
</tile>
<tile id="89">
<tile id="89" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="0" y="9" width="6" height="3"/>
</objectgroup>
</tile>
<tile id="134">
<tile id="134" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="7" y="0" width="5" height="7"/>
</objectgroup>
</tile>
<tile id="135">
<tile id="135" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="0" y="0" width="12" height="5"/>
</objectgroup>
</tile>
<tile id="136">
<tile id="136" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="0" y="0" width="12" height="5"/>
</objectgroup>
</tile>
<tile id="137">
<tile id="137" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="0" y="0" width="12" height="5"/>
</objectgroup>
</tile>
<tile id="138">
<tile id="138" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="0" y="0" width="6" height="7"/>
</objectgroup>
@ -506,6 +561,36 @@
<object id="1" x="0" y="0" width="1" height="1"/>
</objectgroup>
</tile>
<tile id="761" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="762" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="810" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="811" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="859" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="860" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="884" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
@ -521,6 +606,22 @@
<property name="Hide?" type="bool" value="false"/>
</properties>
</tile>
<tile id="908" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="10" y="0" width="2" height="7"/>
</objectgroup>
</tile>
<tile id="909" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>
</properties>
<objectgroup draworder="index" id="2">
<object id="1" x="0" y="0" width="3" height="8"/>
</objectgroup>
</tile>
<tile id="931" type="ForegroundTile">
<properties>
<property name="Hide?" type="bool" value="false"/>

Loading…
Cancel
Save