Enforce const-ness across tilesets to ensure copies and writes are explicitly allowed. Release Build 8990.

This commit is contained in:
sigonasr2 2024-04-19 02:45:43 -05:00
parent e2101d5da0
commit 64dc8bcf10
14 changed files with 161 additions and 121 deletions

View File

@ -451,8 +451,8 @@ void AiL::HandleUserInput(float fElapsedTime){
int truncatedPlayerY=int(player->GetY())/game->GetCurrentMapData().tilewidth; int truncatedPlayerY=int(player->GetY())/game->GetCurrentMapData().tilewidth;
int tileID=layer.tiles[truncatedPlayerY][truncatedPlayerX]; int tileID=layer.tiles[truncatedPlayerY][truncatedPlayerX];
TilesheetData dat=GetTileSheet(GetCurrentLevel(),tileID); TilesheetData dat=GetTileSheet(GetCurrentLevel(),tileID);
if (dat.tileset->staircaseTiles.find(tileID)!=dat.tileset->staircaseTiles.end()){ if (dat.tileset.staircaseTiles.find(tileID)!=dat.tileset.staircaseTiles.end()){
return dat.tileset->staircaseTiles[tileID].data["value"]; return dat.tileset.staircaseTiles.at(tileID).data.at("value");
} }
} }
return std::string("NONE"); return std::string("NONE");
@ -475,10 +475,10 @@ void AiL::HandleUserInput(float fElapsedTime){
player->SetY(player->GetY()-"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult()); player->SetY(player->GetY()-"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult());
player->movementVelocity.y+=-"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult(); player->movementVelocity.y+=-"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult();
} else } else
if(staircaseDirection=="LEFT"){ if(staircaseDirection=="LEFT"){
player->SetY(player->GetY()+"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult()); player->SetY(player->GetY()+"Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult());
player->movementVelocity.y+="Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult(); player->movementVelocity.y+="Player.StaircaseClimbSpd"_F*fElapsedTime*player->GetMoveSpdMult();
} }
newAimingAngle+=vf2d{1,0}; newAimingAngle+=vf2d{1,0};
@ -934,52 +934,52 @@ void AiL::PopulateRenderLists(){
void AiL::RenderTile(vi2d pos,TilesheetData tileSheet,int tileSheetIndex,vi2d tileSheetPos){ void AiL::RenderTile(vi2d pos,TilesheetData tileSheet,int tileSheetIndex,vi2d tileSheetPos){
Pixel tempCol=worldColorFunc(pos*game->GetCurrentMapData().tilewidth); Pixel tempCol=worldColorFunc(pos*game->GetCurrentMapData().tilewidth);
if(tileSheet.tileset->animationData.count(tileSheetIndex)){ if(tileSheet.tileset.animationData.count(tileSheetIndex)){
int animationDuration_ms=int(tileSheet.tileset->animationData[tileSheetIndex].size()*"animation_tile_precision"_I); int animationDuration_ms=int(tileSheet.tileset.animationData.at(tileSheetIndex).size()*"animation_tile_precision"_I);
int animatedIndex=tileSheet.tileset->animationData[tileSheetIndex][size_t(fmod(levelTime*1000.f,animationDuration_ms)/"animation_tile_precision"_I)]; int animatedIndex=tileSheet.tileset.animationData.at(tileSheetIndex)[size_t(fmod(levelTime*1000.f,animationDuration_ms)/"animation_tile_precision"_I)];
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth; int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/tileSheet.tileset.tilewidth;
int tileSheetX=animatedIndex%tileSheetWidth; int tileSheetX=animatedIndex%tileSheetWidth;
int tileSheetY=animatedIndex/tileSheetWidth; int tileSheetY=animatedIndex/tileSheetWidth;
if(tileSheet.tileset->tileRepeatData.count(tileSheetIndex)){ if(tileSheet.tileset.tileRepeatData.count(tileSheetIndex)){
for(int y=0;y<tileSheet.tileset->tileRepeatData[tileSheetIndex].y;y++){ for(int y=0;y<tileSheet.tileset.tileRepeatData.at(tileSheetIndex).y;y++){
for(int x=0;x<tileSheet.tileset->tileRepeatData[tileSheetIndex].x;x++){ for(int x=0;x<tileSheet.tileset.tileRepeatData.at(tileSheetIndex).x;x++){
view.DrawPartialDecal(pos*game->GetCurrentMapData().tilewidth+vf2d{float(x),float(y)}*game->GetCurrentMapData().tilewidth/vf2d{tileSheet.tileset->tileRepeatData[tileSheetIndex]},vf2d{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)}/vf2d{tileSheet.tileset->tileRepeatData[tileSheetIndex]},tileSheet.tileset->tileset->Decal(),vi2d{tileSheetX,tileSheetY}*tileSheet.tileset->tilewidth,{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)},tempCol); view.DrawPartialDecal(pos*game->GetCurrentMapData().tilewidth+vf2d{float(x),float(y)}*game->GetCurrentMapData().tilewidth/vf2d{tileSheet.tileset.tileRepeatData.at(tileSheetIndex)},vf2d{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)}/vf2d{tileSheet.tileset.tileRepeatData.at(tileSheetIndex)},tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*tileSheet.tileset.tilewidth,{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)},tempCol);
} }
} }
}else view.DrawPartialDecal(pos*game->GetCurrentMapData().tilewidth,{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)},tileSheet.tileset->tileset->Decal(),vi2d{tileSheetX,tileSheetY}*tileSheet.tileset->tilewidth,{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)},tempCol); }else view.DrawPartialDecal(pos*game->GetCurrentMapData().tilewidth,{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)},tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*tileSheet.tileset.tilewidth,{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)},tempCol);
}else{ }else{
if(tileSheet.tileset->tileRepeatData.count(tileSheetIndex)){ if(tileSheet.tileset.tileRepeatData.count(tileSheetIndex)){
for(int y=0;y<tileSheet.tileset->tileRepeatData[tileSheetIndex].y;y++){ for(int y=0;y<tileSheet.tileset.tileRepeatData.at(tileSheetIndex).y;y++){
for(int x=0;x<tileSheet.tileset->tileRepeatData[tileSheetIndex].x;x++){ for(int x=0;x<tileSheet.tileset.tileRepeatData.at(tileSheetIndex).x;x++){
view.DrawPartialDecal(pos*game->GetCurrentMapData().tilewidth+vi2d{x,y}*game->GetCurrentMapData().tilewidth/tileSheet.tileset->tileRepeatData[tileSheetIndex],{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)},tileSheet.tileset->tileset->Decal(),tileSheetPos*tileSheet.tileset->tilewidth,vf2d{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)}/tileSheet.tileset->tileRepeatData[tileSheetIndex],tempCol); view.DrawPartialDecal(pos*game->GetCurrentMapData().tilewidth+vi2d{x,y}*game->GetCurrentMapData().tilewidth/tileSheet.tileset.tileRepeatData.at(tileSheetIndex),{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)},tileSheet.tileset.tileset->Decal(),tileSheetPos*tileSheet.tileset.tilewidth,vf2d{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)}/tileSheet.tileset.tileRepeatData.at(tileSheetIndex),tempCol);
} }
} }
}else view.DrawPartialDecal(pos*game->GetCurrentMapData().tilewidth,{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)},tileSheet.tileset->tileset->Decal(),tileSheetPos*tileSheet.tileset->tilewidth,{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)},tempCol); }else view.DrawPartialDecal(pos*game->GetCurrentMapData().tilewidth,{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)},tileSheet.tileset.tileset->Decal(),tileSheetPos*tileSheet.tileset.tilewidth,{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)},tempCol);
} }
} }
void AiL::RenderTile(TileRenderData&tileSheet,Pixel col){ void AiL::RenderTile(TileRenderData&tileSheet,Pixel col){
if(tileSheet.tileSheet.tileset->animationData.count(tileSheet.tileID%1000000)){ if(tileSheet.tileSheet.tileset.animationData.count(tileSheet.tileID%1000000)){
int animationDuration_ms=int(tileSheet.tileSheet.tileset->animationData[tileSheet.tileID%1000000].size()*"animation_tile_precision"_I); int animationDuration_ms=int(tileSheet.tileSheet.tileset.animationData.at(tileSheet.tileID%1000000).size()*"animation_tile_precision"_I);
int animatedIndex=tileSheet.tileSheet.tileset->animationData[tileSheet.tileID%1000000][size_t(fmod(levelTime*1000.f,animationDuration_ms)/"animation_tile_precision"_I)]; int animatedIndex=tileSheet.tileSheet.tileset.animationData.at(tileSheet.tileID%1000000)[size_t(fmod(levelTime*1000.f,animationDuration_ms)/"animation_tile_precision"_I)];
int tileSheetWidth=tileSheet.tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileSheet.tileset->tilewidth; int tileSheetWidth=tileSheet.tileSheet.tileset.tileset->Sprite()->width/tileSheet.tileSheet.tileset.tilewidth;
int tileSheetX=animatedIndex%tileSheetWidth; int tileSheetX=animatedIndex%tileSheetWidth;
int tileSheetY=animatedIndex/tileSheetWidth; int tileSheetY=animatedIndex/tileSheetWidth;
if(tileSheet.tileSheet.tileset->tileRepeatData.count(animatedIndex)){ if(tileSheet.tileSheet.tileset.tileRepeatData.count(animatedIndex)){
for(int y=0;y<tileSheet.tileSheet.tileset->tileRepeatData[animatedIndex].y;y++){ for(int y=0;y<tileSheet.tileSheet.tileset.tileRepeatData.at(animatedIndex).y;y++){
for(int x=0;x<tileSheet.tileSheet.tileset->tileRepeatData[animatedIndex].x;x++){ for(int x=0;x<tileSheet.tileSheet.tileset.tileRepeatData.at(animatedIndex).x;x++){
view.DrawPartialDecal(tileSheet.pos+vi2d{x,y}*game->GetCurrentMapData().tilewidth/tileSheet.tileSheet.tileset->tileRepeatData[animatedIndex],{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)},tileSheet.tileSheet.tileset->tileset->Decal(),vi2d{tileSheetX,tileSheetY}*vf2d{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)},vf2d{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)}/tileSheet.tileSheet.tileset->tileRepeatData[animatedIndex],col); view.DrawPartialDecal(tileSheet.pos+vi2d{x,y}*game->GetCurrentMapData().tilewidth/tileSheet.tileSheet.tileset.tileRepeatData.at(animatedIndex),{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)},tileSheet.tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*vf2d{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)},vf2d{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)}/tileSheet.tileSheet.tileset.tileRepeatData.at(animatedIndex),col);
} }
} }
}else view.DrawPartialDecal(tileSheet.pos,{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)},tileSheet.tileSheet.tileset->tileset->Decal(),vi2d{tileSheetX,tileSheetY}*vf2d{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)},{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)},col); }else view.DrawPartialDecal(tileSheet.pos,{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)},tileSheet.tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*vf2d{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)},{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)},col);
}else{ }else{
if(tileSheet.tileSheet.tileset->tileRepeatData.count(tileSheet.tileID)){ if(tileSheet.tileSheet.tileset.tileRepeatData.count(tileSheet.tileID)){
for(int y=0;y<tileSheet.tileSheet.tileset->tileRepeatData[tileSheet.tileID].y;y++){ for(int y=0;y<tileSheet.tileSheet.tileset.tileRepeatData.at(tileSheet.tileID).y;y++){
for(int x=0;x<tileSheet.tileSheet.tileset->tileRepeatData[tileSheet.tileID].x;x++){ for(int x=0;x<tileSheet.tileSheet.tileset.tileRepeatData.at(tileSheet.tileID).x;x++){
view.DrawPartialDecal(tileSheet.pos+vi2d{x,y}*game->GetCurrentMapData().tilewidth/tileSheet.tileSheet.tileset->tileRepeatData[tileSheet.tileID],{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)},tileSheet.tileSheet.tileset->tileset->Decal(),tileSheet.tileSheetPos,vf2d{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)}/tileSheet.tileSheet.tileset->tileRepeatData[tileSheet.tileID],col); view.DrawPartialDecal(tileSheet.pos+vi2d{x,y}*game->GetCurrentMapData().tilewidth/tileSheet.tileSheet.tileset.tileRepeatData.at(tileSheet.tileID),{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)},tileSheet.tileSheet.tileset.tileset->Decal(),tileSheet.tileSheetPos,vf2d{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)}/tileSheet.tileSheet.tileset.tileRepeatData.at(tileSheet.tileID),col);
} }
} }
}else view.DrawPartialDecal(tileSheet.pos,{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)},tileSheet.tileSheet.tileset->tileset->Decal(),tileSheet.tileSheetPos,{float(tileSheet.tileSheet.tileset->tilewidth),float(tileSheet.tileSheet.tileset->tileheight)},col); }else view.DrawPartialDecal(tileSheet.pos,{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)},tileSheet.tileSheet.tileset.tileset->Decal(),tileSheet.tileSheetPos,{float(tileSheet.tileSheet.tileset.tilewidth),float(tileSheet.tileSheet.tileset.tileheight)},col);
} }
} }
@ -1086,8 +1086,8 @@ void AiL::RenderWorld(float fElapsedTime){
int tileID=layer.tiles[y][x]-1; int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){ if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID); TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth; int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/tileSheet.tileset.tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/tileSheet.tileset.tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth; int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth; int tileSheetY=tileSheetIndex/tileSheetWidth;
@ -1117,8 +1117,8 @@ void AiL::RenderWorld(float fElapsedTime){
int tileID=layer.tiles[y][x]-1; int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){ if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID); TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth; int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/tileSheet.tileset.tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/tileSheet.tileset.tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth; int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth; int tileSheetY=tileSheetIndex/tileSheetWidth;
@ -1230,12 +1230,12 @@ void AiL::RenderWorld(float fElapsedTime){
tile.group=&group; tile.group=&group;
#pragma region Unhiding tile detection #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. 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!=tile.tileSheet.tileset.foregroundTiles.end()){
if(!(*it).second.hide)tile.tileOpacity=0.f; if(!(*it).second.hide)tile.tileOpacity=0.f;
} }
#pragma endregion #pragma endregion
if(tile.tileSheet.tileset->collision.find(tile.tileID)!=tile.tileSheet.tileset->collision.end()){ if(tile.tileSheet.tileset.collision.find(tile.tileID)!=tile.tileSheet.tileset.collision.end()){
tilesWithCollision.push_back(&tile); tilesWithCollision.push_back(&tile);
}else{ }else{
tilesWithoutCollision.push_back(&tile); //Tiles without collision are assumed to always be in the foreground. They don't have any depth rules. tilesWithoutCollision.push_back(&tile); //Tiles without collision are assumed to always be in the foreground. They don't have any depth rules.
@ -1357,8 +1357,8 @@ void AiL::RenderWorld(float fElapsedTime){
#pragma endregion #pragma endregion
RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)}); RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
float distToPlayer=geom2d::line<float>(player->GetPos(),tile->pos+vf2d{12,12}).length(); float distToPlayer=geom2d::line<float>(player->GetPos(),tile->pos+vf2d{12,12}).length();
if(GameSettings::TerrainCollisionBoxesEnabled()&&distToPlayer<24*3&&tile->tileOpacity>0&&tile->tileSheet.tileset->collision.find(tile->tileID)!=tile->tileSheet.tileset->collision.end()){ if(GameSettings::TerrainCollisionBoxesEnabled()&&distToPlayer<24*3&&tile->tileOpacity>0&&tile->tileSheet.tileset.collision.find(tile->tileID)!=tile->tileSheet.tileset.collision.end()){
geom2d::rect<float>collision=tile->tileSheet.tileset->collision[tile->tileID].collision; const geom2d::rect<float>collision=const_cast<TilesetData&>(tile->tileSheet.tileset).collision.at(tile->tileID).collision;
distToPlayer/=4; distToPlayer/=4;
if(distToPlayer<1){distToPlayer=1;} if(distToPlayer<1){distToPlayer=1;}
view.FillRectDecal(tile->pos+collision.pos,collision.size,{255,0,0,uint8_t(128*tile->tileOpacity/sqrt(distToPlayer))}); view.FillRectDecal(tile->pos+collision.pos,collision.size,{255,0,0,uint8_t(128*tile->tileOpacity/sqrt(distToPlayer))});
@ -1411,8 +1411,8 @@ void AiL::RenderWorld(float fElapsedTime){
for(TileRenderData*tile:tilesWithoutCollision){ for(TileRenderData*tile:tilesWithoutCollision){
RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)}); RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
float distToPlayer=geom2d::line<float>(player->GetPos(),tile->pos+vf2d{12,12}).length(); float distToPlayer=geom2d::line<float>(player->GetPos(),tile->pos+vf2d{12,12}).length();
if(distToPlayer<24*3&&tile->tileOpacity>0&&tile->tileSheet.tileset->collision.find(tile->tileID)!=tile->tileSheet.tileset->collision.end()){ if(distToPlayer<24*3&&tile->tileOpacity>0&&tile->tileSheet.tileset.collision.find(tile->tileID)!=tile->tileSheet.tileset.collision.end()){
geom2d::rect<float>collision=tile->tileSheet.tileset->collision[tile->tileID].collision; const geom2d::rect<float>collision=const_cast<TilesetData&>(tile->tileSheet.tileset).collision.at(tile->tileID).collision;
distToPlayer/=4; distToPlayer/=4;
if(distToPlayer<1){distToPlayer=1;} if(distToPlayer<1){distToPlayer=1;}
view.FillRectDecal(tile->pos+collision.pos,collision.size,{255,0,0,uint8_t(128*tile->tileOpacity/sqrt(distToPlayer))}); view.FillRectDecal(tile->pos+collision.pos,collision.size,{255,0,0,uint8_t(128*tile->tileOpacity/sqrt(distToPlayer))});
@ -1440,12 +1440,12 @@ void AiL::RenderWorld(float fElapsedTime){
int tileID=bridgeLayer->tiles[y][x]-1; int tileID=bridgeLayer->tiles[y][x]-1;
if(tileID!=-1){ if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID); TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth; int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/tileSheet.tileset.tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/tileSheet.tileset.tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth; int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth; int tileSheetY=tileSheetIndex/tileSheetWidth;
view.DrawPartialDecal(vi2d{x,y}*game->GetCurrentMapData().tilewidth,{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)},tileSheet.tileset->tileset->Decal(),vi2d{tileSheetX,tileSheetY}*game->GetCurrentMapData().tilewidth,{float(tileSheet.tileset->tilewidth),float(tileSheet.tileset->tileheight)},{255,255,255,uint8_t(255-bridgeFadeFactor/TileGroup::FADE_TIME*TileGroup::FADE_AMT)}); view.DrawPartialDecal(vi2d{x,y}*game->GetCurrentMapData().tilewidth,{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)},tileSheet.tileset.tileset->Decal(),vi2d{tileSheetX,tileSheetY}*game->GetCurrentMapData().tilewidth,{float(tileSheet.tileset.tilewidth),float(tileSheet.tileset.tileheight)},{255,255,255,uint8_t(255-bridgeFadeFactor/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
#ifdef _DEBUG #ifdef _DEBUG
if("debug_collision_boxes"_I){ if("debug_collision_boxes"_I){
if(tileSheet.tileset->collision.find(tileSheetIndex)!=tileSheet.tileset->collision.end()){ if(tileSheet.tileset->collision.find(tileSheetIndex)!=tileSheet.tileset->collision.end()){
@ -1485,13 +1485,13 @@ void AiL::RenderWorld(float fElapsedTime){
tile.group=&group; tile.group=&group;
#pragma region Unhiding tile detection #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. 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!=tile.tileSheet.tileset.upperForegroundTiles.end()){
if(!(*it).second.hide)tile.tileOpacity=0.f; if(!(*it).second.hide)tile.tileOpacity=0.f;
} }
#pragma endregion #pragma endregion
if(tile.tileSheet.tileset->collision.find(tile.tileID)!=tile.tileSheet.tileset->collision.end()){ if(tile.tileSheet.tileset.collision.find(tile.tileID)!=tile.tileSheet.tileset.collision.end()){
tilesWithCollision.push_back(&tile); tilesWithCollision.push_back(&tile);
}else{ }else{
tilesWithoutCollision.push_back(&tile); tilesWithoutCollision.push_back(&tile);
@ -1613,8 +1613,8 @@ void AiL::RenderWorld(float fElapsedTime){
#pragma endregion #pragma endregion
RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)}); RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
float distToPlayer=geom2d::line<float>(player->GetPos(),tile->pos+vf2d{12,12}).length(); float distToPlayer=geom2d::line<float>(player->GetPos(),tile->pos+vf2d{12,12}).length();
if(GameSettings::TerrainCollisionBoxesEnabled()&&distToPlayer<24*3&&tile->tileOpacity>0&&tile->tileSheet.tileset->collision.find(tile->tileID)!=tile->tileSheet.tileset->collision.end()){ if(GameSettings::TerrainCollisionBoxesEnabled()&&distToPlayer<24*3&&tile->tileOpacity>0&&tile->tileSheet.tileset.collision.find(tile->tileID)!=tile->tileSheet.tileset.collision.end()){
geom2d::rect<float>collision=tile->tileSheet.tileset->collision[tile->tileID].collision; const geom2d::rect<float>collision=const_cast<TilesetData&>(tile->tileSheet.tileset).collision.at(tile->tileID).collision;
distToPlayer/=4; distToPlayer/=4;
if(distToPlayer<1){distToPlayer=1;} if(distToPlayer<1){distToPlayer=1;}
view.FillRectDecal(tile->pos+collision.pos,collision.size,{255,0,0,uint8_t(128*tile->tileOpacity/sqrt(distToPlayer))}); view.FillRectDecal(tile->pos+collision.pos,collision.size,{255,0,0,uint8_t(128*tile->tileOpacity/sqrt(distToPlayer))});
@ -1659,8 +1659,8 @@ void AiL::RenderWorld(float fElapsedTime){
for(TileRenderData*tile:tilesWithoutCollision){ for(TileRenderData*tile:tilesWithoutCollision){
RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)}); RenderTile(*tile,{255,255,255,uint8_t(255-tile->tileOpacity/TileGroup::FADE_TIME*TileGroup::FADE_AMT)});
float distToPlayer=geom2d::line<float>(player->GetPos(),tile->pos+vf2d{12,12}).length(); float distToPlayer=geom2d::line<float>(player->GetPos(),tile->pos+vf2d{12,12}).length();
if(distToPlayer<24*3&&tile->tileOpacity>0&&tile->tileSheet.tileset->collision.find(tile->tileID)!=tile->tileSheet.tileset->collision.end()){ if(distToPlayer<24*3&&tile->tileOpacity>0&&tile->tileSheet.tileset.collision.find(tile->tileID)!=tile->tileSheet.tileset.collision.end()){
geom2d::rect<float>collision=tile->tileSheet.tileset->collision[tile->tileID].collision; const geom2d::rect<float>collision=const_cast<TilesetData&>(tile->tileSheet.tileset).collision.at(tile->tileID).collision;
distToPlayer/=4; distToPlayer/=4;
if(distToPlayer<1){distToPlayer=1;} if(distToPlayer<1){distToPlayer=1;}
view.FillRectDecal(tile->pos+collision.pos,collision.size,{255,0,0,uint8_t(128*tile->tileOpacity/sqrt(distToPlayer))}); view.FillRectDecal(tile->pos+collision.pos,collision.size,{255,0,0,uint8_t(128*tile->tileOpacity/sqrt(distToPlayer))});
@ -2107,13 +2107,13 @@ void AiL::InitializeLevel(std::string mapFile,MapName map){
int tileID=layer.tiles[y][x]-1; int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){ if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(map,tileID); TilesheetData tileSheet=GetTileSheet(map,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth; int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/tileSheet.tileset.tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/tileSheet.tileset.tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int tileSheetX=tileSheetIndex%tileSheetWidth; int tileSheetX=tileSheetIndex%tileSheetWidth;
int tileSheetY=tileSheetIndex/tileSheetWidth; int tileSheetY=tileSheetIndex/tileSheetWidth;
vi2d pos=vi2d{x,y}*tileSheet.tileset->tilewidth; vi2d pos=vi2d{x,y}*tileSheet.tileset.tilewidth;
DrawPartialSprite(pos,tileSheet.tileset->tileset->Sprite(),vi2d{tileSheetX,tileSheetY}*tileSheet.tileset->tilewidth,{tileSheet.tileset->tilewidth,tileSheet.tileset->tileheight}); DrawPartialSprite(pos,tileSheet.tileset.tileset->Sprite(),vi2d{tileSheetX,tileSheetY}*tileSheet.tileset.tilewidth,{tileSheet.tileset.tilewidth,tileSheet.tileset.tileheight});
} }
} }
} }
@ -2276,8 +2276,8 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
int tileID=layer.tiles[y][x]-1; int tileID=layer.tiles[y][x]-1;
if(tileID!=-1){ if(tileID!=-1){
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID); TilesheetData tileSheet=GetTileSheet(currentLevel,tileID);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth; int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/tileSheet.tileset.tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/tileSheet.tileset.tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1); int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth; int tileSheetX=realTileSheetIndex%tileSheetWidth;
@ -2302,8 +2302,8 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
if(!loopAll&&&layer==&layer2){layer2ID++;continue;}; if(!loopAll&&&layer==&layer2){layer2ID++;continue;};
int tileID=layer2.tiles[pos.y][pos.x]-1; int tileID=layer2.tiles[pos.y][pos.x]-1;
TilesheetData tileSheet=GetTileSheet(currentLevel,tileID%1000000); TilesheetData tileSheet=GetTileSheet(currentLevel,tileID%1000000);
int tileSheetWidth=tileSheet.tileset->tileset->Sprite()->width/tileSheet.tileset->tilewidth; int tileSheetWidth=tileSheet.tileset.tileset->Sprite()->width/tileSheet.tileset.tilewidth;
int tileSheetHeight=tileSheet.tileset->tileset->Sprite()->height/tileSheet.tileset->tileheight; int tileSheetHeight=tileSheet.tileset.tileset->Sprite()->height/tileSheet.tileset.tileheight;
int tileSheetIndex=tileID-(tileSheet.firstgid-1); int tileSheetIndex=tileID-(tileSheet.firstgid-1);
int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1); int realTileSheetIndex=(tileID%1000000)-(tileSheet.firstgid-1);
int tileSheetX=realTileSheetIndex%tileSheetWidth; int tileSheetX=realTileSheetIndex%tileSheetWidth;
@ -2389,10 +2389,10 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
for(auto&it=find_tiles.first;it!=find_tiles.second;++it){ for(auto&it=find_tiles.first;it!=find_tiles.second;++it){
//These are all tiles that were found adjacent to the location we are checking for. See if they match a potential group. //These are all tiles that were found adjacent to the location we are checking for. See if they match a potential group.
TileRenderData&foundTile=(*it).second; TileRenderData&foundTile=(*it).second;
if(tile.tileSheet.tileset==foundTile.tileSheet.tileset){ //Let's first see if they are even in the same tileset. if(&tile.tileSheet.tileset==&foundTile.tileSheet.tileset){ //Let's first see if they are even in the same tileset.
//Let's get how many tiles wide this tile sheet is. //Let's get how many tiles wide this tile sheet is.
int tileWidth=tile.tileSheet.tileset->tilewidth; int tileWidth=tile.tileSheet.tileset.tilewidth;
int tileSheetWidth=tile.tileSheet.tileset->tileset->Sprite()->width/tileWidth; int tileSheetWidth=tile.tileSheet.tileset.tileset->Sprite()->width/tileWidth;
if(IsAdjacent(tile.tileID,foundTile.tileID,tileSheetWidth)){ if(IsAdjacent(tile.tileID,foundTile.tileID,tileSheetWidth)){
group.insert({loc,tile});//We add this tile to the group! It is adjacent! group.insert({loc,tile});//We add this tile to the group! It is adjacent!
groupFound=true; groupFound=true;
@ -2540,32 +2540,32 @@ bool AiL::IsUpperForegroundTile(int tileID){
} }
bool AiL::IsForegroundTile(TilesheetData sheet,int tileID){ bool AiL::IsForegroundTile(TilesheetData sheet,int tileID){
return sheet.tileset->foregroundTiles.find(tileID)!=sheet.tileset->foregroundTiles.end(); return sheet.tileset.foregroundTiles.find(tileID)!=sheet.tileset.foregroundTiles.end();
} }
TilesheetData AiL::GetTileSheet(MapName map,int tileID){ const TilesheetData AiL::GetTileSheet(MapName map,int tileID)const{
std::vector<XMLTag>&tileData=MAP_DATA[map].TilesetData; const std::vector<XMLTag>&tileData=MAP_DATA.at(map).TilesetData;
if(tileData.size()==1){ if(tileData.size()==1){
size_t slashMarkerSourceDir = tileData[0].data["source"].find_last_of('/'); size_t slashMarkerSourceDir = tileData[0].data.at("source").find_last_of('/');
std::string baseSourceDir=tileData[0].data["source"].substr(slashMarkerSourceDir+1); std::string baseSourceDir=tileData[0].data.at("source").substr(slashMarkerSourceDir+1);
return {&MAP_TILESETS["assets/maps/"+baseSourceDir],1,MAP_TILESETS["assets/maps/"+baseSourceDir].tilecols[tileID]}; return {MAP_TILESETS.at("assets/maps/"+baseSourceDir),1,MAP_TILESETS.at("assets/maps/"+baseSourceDir).tilecols[tileID]};
} else { } else {
for (int i=1;i<tileData.size();i++){ for (int i=1;i<tileData.size();i++){
int firstgid=stoi(tileData[i-1].data["firstgid"]); int firstgid=stoi(tileData[i-1].data.at("firstgid"));
if(tileID%1000000<stoi(tileData[i].data["firstgid"])-1){ if(tileID%1000000<stoi(tileData[i].data.at("firstgid"))-1){
size_t slashMarkerSourceDir = tileData[size_t(i-1)].data["source"].find_last_of('/'); size_t slashMarkerSourceDir = tileData[size_t(i-1)].data.at("source").find_last_of('/');
std::string baseSourceDir=tileData[size_t(i-1)].data["source"].substr(slashMarkerSourceDir+1); std::string baseSourceDir=tileData[size_t(i-1)].data.at("source").substr(slashMarkerSourceDir+1);
if(tileID!=-1){ if(tileID!=-1){
return {&MAP_TILESETS["assets/maps/"+baseSourceDir],firstgid,MAP_TILESETS["assets/maps/"+baseSourceDir].tilecols[tileID-(firstgid-1)]}; return {MAP_TILESETS.at("assets/maps/"+baseSourceDir),firstgid,MAP_TILESETS.at("assets/maps/"+baseSourceDir).tilecols[tileID-(firstgid-1)]};
}else{ }else{
return {&MAP_TILESETS["assets/maps/"+baseSourceDir],firstgid,BLANK}; return {MAP_TILESETS.at("assets/maps/"+baseSourceDir),firstgid,BLANK};
} }
} }
} }
size_t slashMarkerSourceDir = tileData[tileData.size()-1].data["source"].find_last_of('/'); size_t slashMarkerSourceDir = tileData[tileData.size()-1].data.at("source").find_last_of('/');
std::string baseSourceDir=tileData[tileData.size()-1].data["source"].substr(slashMarkerSourceDir+1); std::string baseSourceDir=tileData[tileData.size()-1].data.at("source").substr(slashMarkerSourceDir+1);
int firstgid=stoi(tileData[tileData.size()-1].data["firstgid"]); int firstgid=stoi(tileData[tileData.size()-1].data.at("firstgid"));
return {&MAP_TILESETS["assets/maps/"+baseSourceDir],firstgid,MAP_TILESETS["assets/maps/"+baseSourceDir].tilecols[tileID-(firstgid-1)]}; return {MAP_TILESETS.at("assets/maps/"+baseSourceDir),firstgid,MAP_TILESETS.at("assets/maps/"+baseSourceDir).tilecols[tileID-(firstgid-1)]};
} }
} }
@ -2584,18 +2584,18 @@ bool AiL::IsOverlayLayer(LayerTag&layer){
return layer.tag.data.find("class")!=layer.tag.data.end()&&layer.tag.data["class"]=="Overlay"; return layer.tag.data.find("class")!=layer.tag.data.end()&&layer.tag.data["class"]=="Overlay";
} }
geom2d::rect<float>AiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel){ const geom2d::rect<float>AiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel)const{
MapTag&mapData=MAP_DATA[map].MapData; const MapTag&mapData=MAP_DATA.at(map).MapData;
if(pos.x<0||pos.y<0||pos.x>=mapData.width*mapData.tilewidth||pos.y>=mapData.height*mapData.tilewidth)return NO_COLLISION; if(pos.x<0||pos.y<0||pos.x>=mapData.width*mapData.tilewidth||pos.y>=mapData.height*mapData.tilewidth)return NO_COLLISION;
if(MAP_DATA[map].optimizedTile)return NO_COLLISION; //Overworld map has no collision. if(MAP_DATA.at(map).optimizedTile)return NO_COLLISION; //Overworld map has no collision.
bool hasTerrain=false; bool hasTerrain=false;
for(const LayerTag&layer:MAP_DATA[map].LayerData){ //Figure out if any tile at this position is terrain. If so, we have a collision box to check. for(const LayerTag&layer:MAP_DATA.at(map).LayerData){ //Figure out if any tile at this position is terrain. If so, we have a collision box to check.
if(Unlock::IsUnlocked(layer.unlockCondition)){ if(Unlock::IsUnlocked(layer.unlockCondition)){
int tileID=layer.tiles[pos.y/mapData.tilewidth][pos.x/mapData.tilewidth]-1; int tileID=layer.tiles[pos.y/mapData.tilewidth][pos.x/mapData.tilewidth]-1;
if(tileID==-1)continue; if(tileID==-1)continue;
const TilesheetData&data=GetTileSheet(map,tileID); const TilesheetData&data=GetTileSheet(map,tileID);
if(data.tileset->isTerrain){ if(data.tileset.isTerrain){
hasTerrain=true; hasTerrain=true;
break; break;
} }
@ -2604,8 +2604,8 @@ geom2d::rect<float>AiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel){
if(!hasTerrain)return geom2d::rect<float>({0.f,0.f},{float(mapData.tilewidth),float(mapData.tilewidth)}); //We assume no terrain means we can't walk on this. if(!hasTerrain)return geom2d::rect<float>({0.f,0.f},{float(mapData.tilewidth),float(mapData.tilewidth)}); //We assume no terrain means we can't walk on this.
#pragma region Lower Bridge Collision Check #pragma region Lower Bridge Collision Check
if(!upperLevel){ //We are looking for lower bridge collisions. if(!upperLevel&&MAP_DATA.at(map).ZoneData.count("LowerBridgeCollision")){ //We are looking for lower bridge collisions.
for(ZoneData&zone:MAP_DATA[map].ZoneData["LowerBridgeCollision"]){ for(const ZoneData&zone:MAP_DATA.at(map).ZoneData.at("LowerBridgeCollision")){
if(geom2d::contains(zone.zone,pos)){ if(geom2d::contains(zone.zone,pos)){
return {{0,0},{float(mapData.tilewidth),float(mapData.tilewidth)}}; return {{0,0},{float(mapData.tilewidth),float(mapData.tilewidth)}};
} }
@ -2614,22 +2614,22 @@ geom2d::rect<float>AiL::GetTileCollision(MapName map,vf2d pos,bool upperLevel){
#pragma endregion #pragma endregion
//The logic here is, if there's a tile on the bridge, we respect that tile instead if we're on the upper level. So we don't check other layers when we are on the upper level and there is a tile below us. //The logic here is, if there's a tile on the bridge, we respect that tile instead if we're on the upper level. So we don't check other layers when we are on the upper level and there is a tile below us.
if(upperLevel&&bridgeLayerIndex!=-1){ if(upperLevel&&bridgeLayerIndex!=-1){
int tileID=MAP_DATA[map].LayerData[bridgeLayerIndex].tiles[int(pos.y)/mapData.tilewidth][int(pos.x)/mapData.tilewidth]-1; int tileID=MAP_DATA.at(map).LayerData[bridgeLayerIndex].tiles[int(pos.y)/mapData.tilewidth][int(pos.x)/mapData.tilewidth]-1;
if(tileID!=-1){ if(tileID!=-1){
if (GetTileSheet(map,tileID%1000000).tileset->collision.find(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1)!=GetTileSheet(map,tileID%1000000).tileset->collision.end()){ if (GetTileSheet(map,tileID%1000000).tileset.collision.find(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1)!=GetTileSheet(map,tileID%1000000).tileset.collision.end()){
return GetTileSheet(map,tileID%1000000).tileset->collision[tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1].collision; return const_cast<TilesetData&>(GetTileSheet(map,tileID%1000000).tileset).collision.at(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1).collision;
} }
return NO_COLLISION; return NO_COLLISION;
} }
} }
geom2d::rect<float>foundRect=NO_COLLISION; geom2d::rect<float>foundRect=NO_COLLISION;
for(int counter=0;LayerTag&layer:MAP_DATA[map].LayerData){ for(int counter=0;const LayerTag&layer:MAP_DATA.at(map).LayerData){
if(Unlock::IsUnlocked(layer.unlockCondition)){ if(Unlock::IsUnlocked(layer.unlockCondition)){
//auto HasNoClass=[&](){return layer.tag.data.find("class")==layer.tag.data.end();}; //auto HasNoClass=[&](){return layer.tag.data.find("class")==layer.tag.data.end();};
if(counter!=bridgeLayerIndex){ if(counter!=bridgeLayerIndex){
int tileID=layer.tiles[int(pos.y)/mapData.tilewidth][int(pos.x)/mapData.tilewidth]-1; int tileID=layer.tiles[int(pos.y)/mapData.tilewidth][int(pos.x)/mapData.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()){ 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; const geom2d::rect<float>collisionRect=const_cast<TilesetData&>(GetTileSheet(map,tileID%1000000).tileset).collision.at(tileID%1000000-GetTileSheet(map,tileID%1000000).firstgid+1).collision;
if(foundRect==NO_COLLISION){ if(foundRect==NO_COLLISION){
foundRect=collisionRect; foundRect=collisionRect;
}else{ }else{
@ -2981,7 +2981,7 @@ void AiL::OutputDebugInfo(const char*key,std::size_t len){
} }
bool AiL::IsReflectiveTile(TilesheetData tileSheet,int tileID){ bool AiL::IsReflectiveTile(TilesheetData tileSheet,int tileID){
return tileSheet.tileset->reflectiveData.find(tileID)!=tileSheet.tileset->reflectiveData.end(); return tileSheet.tileset.reflectiveData.find(tileID)!=tileSheet.tileset.reflectiveData.end();
} }
bool AiL::OnUserDestroy(){ bool AiL::OnUserDestroy(){

View File

@ -253,9 +253,9 @@ public:
//tileID is the tile number from the tilesets. //tileID is the tile number from the tilesets.
bool IsUpperForegroundTile(int tileID); bool IsUpperForegroundTile(int tileID);
//tileID is the tile number from the tilesets. //tileID is the tile number from the tilesets.
TilesheetData GetTileSheet(MapName map,int tileID); const TilesheetData GetTileSheet(MapName map,int tileID)const;
//Gets the rectangle of the tile collision at this tile. If upperLevel is set to true, the collision tile must be in a Bridge class layer for the tile to hit. Also, zones containing LowerBridgeCollision will apply when upperLevel is set to false. //Gets the rectangle of the tile collision at this tile. If upperLevel is set to true, the collision tile must be in a Bridge class layer for the tile to hit. Also, zones containing LowerBridgeCollision will apply when upperLevel is set to false.
geom2d::rect<float>GetTileCollision(MapName map,vf2d pos,bool upperLevel=false); const geom2d::rect<float>GetTileCollision(MapName map,vf2d pos,bool upperLevel=false)const;
Pixel GetTileColor(MapName map,vf2d pos,bool upperLevel=false); Pixel GetTileColor(MapName map,vf2d pos,bool upperLevel=false);
//Checks if the point resides inside of a collision tile. //Checks if the point resides inside of a collision tile.
bool HasTileCollision(MapName map,vf2d pos,bool upperLevel=false); bool HasTileCollision(MapName map,vf2d pos,bool upperLevel=false);

View File

@ -94,13 +94,19 @@ void Monster::STRATEGY::BOAR(Monster&m,float fElapsedTime,std::string strategy){
}break; }break;
case PhaseName::CHARGE:{ case PhaseName::CHARGE:{
float distToTarget=geom2d::line<float>(m.GetPos(),m.target).length(); float distToTarget=geom2d::line<float>(m.GetPos(),m.target).length();
if(m.bumpedIntoTerrain||distToTarget<4.f){
auto TransitionToRecoveryPhase=[&](){
m.phase=PhaseName::RECOVERY; m.phase=PhaseName::RECOVERY;
m.F(A::CHARGE_COOLDOWN)=ConfigFloat("Charge Recovery Time"); m.F(A::CHARGE_COOLDOWN)=ConfigFloat("Charge Recovery Time");
m.PerformIdleAnimation(); m.PerformIdleAnimation();
};
if(m.bumpedIntoTerrain||distToTarget<4.f){
TransitionToRecoveryPhase();
}else{ }else{
m.targetAcquireTimer=INFINITY; //Don't acquire a new target. m.targetAcquireTimer=INFINITY; //Don't acquire a new target.
RUN_TOWARDS(m,fElapsedTime,"Run Towards"); RUN_TOWARDS(m,fElapsedTime,"Run Towards");
if(!m.canMove)TransitionToRecoveryPhase();
} }
}break; }break;
case PhaseName::RECOVERY:{ case PhaseName::RECOVERY:{

View File

@ -11,6 +11,9 @@ Attack Strategie: If range to player >700 move closer.
if range 400-700 Scratch the ground twice and then charge with 30% Move-Spd bonus in the players direction for a distance of 900. if range 400-700 Scratch the ground twice and then charge with 30% Move-Spd bonus in the players direction for a distance of 900.
If range to player<400 backpaddle with 50% move-spd. if getting hit while backpaddling, start charge sequence. If range to player<400 backpaddle with 50% move-spd. if getting hit while backpaddling, start charge sequence.
Before a charge occurs, the boar will make sure to have full line-of-sight of the player before beginning a charge.
Once a charge begins, the direction cannot be modified.
Goblin (Dagger): Goblin (Dagger):
Hp: 120 Hp: 120

View File

@ -50,7 +50,7 @@ void ItemDrop::Initialize(){
gravity="ItemDrop.Item Drop Gravity"_F; gravity="ItemDrop.Item Drop Gravity"_F;
} }
ItemDrop::ItemDrop(ItemInfo*item,vf2d pos,bool isUpper) ItemDrop::ItemDrop(const ItemInfo*item,vf2d pos,bool isUpper)
:item(item),pos(pos),upperLevel(isUpper){ :item(item),pos(pos),upperLevel(isUpper){
speed.x=util::random("ItemDrop.Item Drop Horizontal Speed"_f[1]-"ItemDrop.Item Drop Horizontal Speed"_f[0])+"ItemDrop.Item Drop Horizontal Speed"_f[0]; speed.x=util::random("ItemDrop.Item Drop Horizontal Speed"_f[1]-"ItemDrop.Item Drop Horizontal Speed"_f[0])+"ItemDrop.Item Drop Horizontal Speed"_f[0];
speed.y=util::random("ItemDrop.Item Drop Vertical Speed"_f[1]-"ItemDrop.Item Drop Vertical Speed"_f[0])+"ItemDrop.Item Drop Vertical Speed"_f[0]; speed.y=util::random("ItemDrop.Item Drop Vertical Speed"_f[1]-"ItemDrop.Item Drop Vertical Speed"_f[0])+"ItemDrop.Item Drop Vertical Speed"_f[0];
@ -150,10 +150,10 @@ float ItemDrop::GetZ()const{
return z; return z;
} }
void ItemDrop::SpawnItem(ItemInfo*item,vf2d pos,bool isUpper){ void ItemDrop::SpawnItem(const ItemInfo*item,vf2d pos,bool isUpper){
drops.push_back(ItemDrop{item,pos,isUpper}); drops.push_back(ItemDrop{item,pos,isUpper});
} }
ItemInfo*ItemDrop::GetItem(){ const ItemInfo*ItemDrop::GetItem()const{
return item; return item;
} }

View File

@ -46,12 +46,12 @@ class ItemDrop{
float zSpeed=0; float zSpeed=0;
float z=0; float z=0;
float randomSpinOffset=0; float randomSpinOffset=0;
ItemInfo*item=nullptr; const ItemInfo*item=nullptr;
bool upperLevel=false; bool upperLevel=false;
static float gravity; static float gravity;
static std::vector<ItemDrop>drops; static std::vector<ItemDrop>drops;
bool collected=false; bool collected=false;
ItemDrop(ItemInfo*item,vf2d pos,bool isUpper); ItemDrop(const ItemInfo*item,vf2d pos,bool isUpper);
public: public:
static void Initialize(); static void Initialize();
vf2d GetPos()const; vf2d GetPos()const;
@ -59,6 +59,6 @@ public:
void Draw()const; void Draw()const;
static void UpdateDrops(float fElapsedTime); static void UpdateDrops(float fElapsedTime);
float GetZ()const; float GetZ()const;
static void SpawnItem(ItemInfo*item,vf2d pos,bool isUpper); static void SpawnItem(const ItemInfo*item,vf2d pos,bool isUpper);
ItemInfo*GetItem(); const ItemInfo*GetItem()const;
}; };

View File

@ -73,12 +73,12 @@ void TileGroup::InsertTile(TileRenderData tile){
} }
range={{minX,minY},{maxX-minX,maxY-minY}}; range={{minX,minY},{maxX-minX,maxY-minY}};
} }
if(tile.tileSheet.tileset->collision.find(tile.tileID%1000000)!=tile.tileSheet.tileset->collision.end()){ if(tile.tileSheet.tileset.collision.find(tile.tileID%1000000)!=tile.tileSheet.tileset.collision.end()){
if(collisionRange.size==vf2d{0,0}){ if(collisionRange.size==vf2d{0,0}){
geom2d::rect<float>collisionRect=tile.tileSheet.tileset->collision[tile.tileID%1000000].collision; const geom2d::rect<float>collisionRect=const_cast<TilesetData&>(tile.tileSheet.tileset).collision.at(tile.tileID%1000000).collision;
collisionRange={tile.pos+collisionRect.pos,collisionRect.size}; collisionRange={tile.pos+collisionRect.pos,collisionRect.size};
}else{ }else{
geom2d::rect<float>newCollision=tile.tileSheet.tileset->collision[tile.tileID%1000000].collision; geom2d::rect<float>newCollision=const_cast<TilesetData&>(tile.tileSheet.tileset).collision.at(tile.tileID%1000000).collision;
newCollision.pos+=tile.pos; newCollision.pos+=tile.pos;
float minX=collisionRange.top().start.x; float minX=collisionRange.top().start.x;

View File

@ -69,11 +69,17 @@ struct TilesetData{
}; };
struct TilesheetData{ struct TilesheetData{
TilesetData*tileset; const TilesetData&tileset;
int firstgid; int firstgid;
Pixel tilecol; Pixel tilecol;
TilesheetData(const TilesetData&tileset,const int firstgid,const Pixel tilecol)
:tileset(tileset),firstgid(firstgid),tilecol(tilecol){};
TilesheetData(const TilesheetData&ref)=default;
TilesheetData operator=(const TilesheetData&ref){
return {ref.tileset,ref.firstgid,ref.tilecol};
};
bool operator==(const TilesheetData&rhs){ bool operator==(const TilesheetData&rhs){
return tileset==rhs.tileset&&firstgid==rhs.firstgid; return &tileset==&rhs.tileset&&firstgid==rhs.firstgid;
} }
}; };
@ -86,7 +92,9 @@ struct TileRenderData{
int tileID; int tileID;
int layerID; int layerID;
TileGroup*group=nullptr; //The group that is tied to this render data. Set during rendering phase. TileGroup*group=nullptr; //The group that is tied to this render data. Set during rendering phase.
float tileOpacity; float tileOpacity=1.f;
TileRenderData(const TilesheetData&tileSheet,const vf2d pos,const vi2d tileSheetPos,const int tileID,const int layerID)
:tileSheet(tileSheet),pos(pos),tileSheetPos(tileSheetPos),tileID(tileID),layerID(layerID){};
bool operator==(const TileRenderData&rhs){ bool operator==(const TileRenderData&rhs){
return tileSheet==rhs.tileSheet&&pos==rhs.pos&&tileSheetPos==rhs.tileSheetPos return tileSheet==rhs.tileSheet&&pos==rhs.pos&&tileSheetPos==rhs.tileSheetPos
&&tileID==rhs.tileID&&layerID==rhs.layerID; &&tileID==rhs.tileID&&layerID==rhs.layerID;

View File

@ -589,7 +589,7 @@ bool MonsterSpawner::DoesUpperLevelSpawning(){
return upperLevel; return upperLevel;
} }
bool Monster::OnUpperLevel(){ const bool Monster::OnUpperLevel()const{
return upperLevel; return upperLevel;
} }
@ -703,8 +703,8 @@ std::map<ItemInfo*,uint16_t>Monster::SpawnDrops(){
//This isn't necessarily fair odds for each quantity dropped. //This isn't necessarily fair odds for each quantity dropped.
int dropQuantity=int(data.minQty+std::round(util::random(float(data.maxQty-data.minQty)))); int dropQuantity=int(data.minQty+std::round(util::random(float(data.maxQty-data.minQty))));
for(int i=0;i<dropQuantity;i++){ for(int i=0;i<dropQuantity;i++){
ItemDrop::SpawnItem(data.item,GetPos(),OnUpperLevel()); ItemDrop::SpawnItem(&data.item,GetPos(),OnUpperLevel());
drops[data.item]++; drops.at(const_cast<ItemInfo*>(&data.item))++;
} }
} }
} }
@ -851,3 +851,19 @@ const bool MonsterData::IsNPC()const{
const Animate2D::FrameSequence&Monster::GetCurrentAnimation()const{ const Animate2D::FrameSequence&Monster::GetCurrentAnimation()const{
return ANIMATION_DATA[animation.currentStateName]; return ANIMATION_DATA[animation.currentStateName];
} }
const bool Monster::HasLineOfSight(vf2d targetPos)const{
geom2d::line<float>losLine=geom2d::line<float>(GetPos(),targetPos);
float losLineLength=losLine.length();
float losLineMarker=0.f;
bool hasLoS=true;
while(losLineMarker<losLineLength){
vf2d checkPos=losLine.rpoint(losLineMarker);
if(game->GetTileCollision(game->GetCurrentMapName(),checkPos,OnUpperLevel())!=game->NO_COLLISION){
hasLoS=false;
break;
}
losLineMarker+=game->GetCurrentMapData().TileSize.x/2.f;
}
return hasLoS;
}

View File

@ -110,7 +110,7 @@ public:
void PerformNPCRightAnimation(); void PerformNPCRightAnimation();
void PerformOtherAnimation(const uint8_t otherInd); void PerformOtherAnimation(const uint8_t otherInd);
const Animate2D::FrameSequence&GetCurrentAnimation()const; const Animate2D::FrameSequence&GetCurrentAnimation()const;
bool OnUpperLevel(); const bool OnUpperLevel()const;
void Moved(); void Moved();
//Returns false if a path could not be found. //Returns false if a path could not be found.
bool StartPathfinding(float pathingTime); bool StartPathfinding(float pathingTime);
@ -146,6 +146,7 @@ public:
const float GetDamageReductionFromBuffs()const; const float GetDamageReductionFromBuffs()const;
const float GetCollisionDamage()const; const float GetCollisionDamage()const;
const bool IsNPC()const; const bool IsNPC()const;
const bool HasLineOfSight(vf2d targetPos)const;
private: private:
std::string name; std::string name;
vf2d pos; vf2d pos;

View File

@ -42,12 +42,18 @@ All rights reserved.
INCLUDE_ITEM_DATA INCLUDE_ITEM_DATA
struct MonsterDropData{ struct MonsterDropData{
ItemInfo*item; const ItemInfo&item;
float dropChance; float dropChance;
int minQty=1; int minQty=1;
int maxQty=1; int maxQty=1;
MonsterDropData(std::string itemName,float dropChance,int minQty=1,int maxQty=1) MonsterDropData(std::string itemName,float dropChance,int minQty=1,int maxQty=1)
:item(&ITEM_DATA.at(itemName)),dropChance(dropChance),minQty(minQty),maxQty(maxQty){} :item(ITEM_DATA.at(itemName)),dropChance(dropChance),minQty(minQty),maxQty(maxQty){}
MonsterDropData(const ItemInfo&item,float dropChance,int minQty=1,int maxQty=1)
:item(item),dropChance(dropChance),minQty(minQty),maxQty(maxQty){}
MonsterDropData(const MonsterDropData&ref)=default;
MonsterDropData operator=(const MonsterDropData&ref){
return {ref.item,ref.dropChance,ref.minQty,ref.maxQty};
}
}; };
struct MonsterData{ struct MonsterData{

View File

@ -39,7 +39,7 @@ All rights reserved.
#define VERSION_MAJOR 1 #define VERSION_MAJOR 1
#define VERSION_MINOR 2 #define VERSION_MINOR 2
#define VERSION_PATCH 0 #define VERSION_PATCH 0
#define VERSION_BUILD 8958 #define VERSION_BUILD 8990
#define stringify(a) stringify_(a) #define stringify(a) stringify_(a)
#define stringify_(a) #a #define stringify_(a) #a

View File

@ -86,7 +86,7 @@ public:
initialized=false; initialized=false;
map.clear(); map.clear();
} }
auto find(const T&key){ auto find(const T&key)const{
return map.find(key); return map.find(key);
} }
auto begin()const{ auto begin()const{