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