@ -1911,58 +1911,6 @@ void AiL::RenderWorld(float fElapsedTime){
}
# pragma endregion
for ( std : : vector < std : : shared_ptr < DamageNumber > > : : iterator it = DAMAGENUMBER_LIST . begin ( ) ; it ! = DAMAGENUMBER_LIST . end ( ) ; + + it ) {
DamageNumber * dn = ( * it ) . get ( ) ;
# define NumberScalesWithDamage true
# define NormalNumber false
auto DrawDamageNumber = [ & ] ( const bool ScaleWithNumber , std : : string_view text , std : : pair < Pixel , Pixel > colorsEnemy , std : : pair < Pixel , Pixel > colorsFriendly , vf2d scaling = { 1.f , 1.f } ) {
vf2d textSize = GetTextSizeProp ( text ) * scaling ;
if ( ! dn - > friendly ) {
vf2d additionalScaling = { 1.f , 1.f } ;
if ( ScaleWithNumber ) additionalScaling = dn - > size ;
textSize * = additionalScaling ;
vf2d drawPos = dn - > pos - textSize / 2.f ;
drawPos . x = std : : clamp ( drawPos . x , view . GetWorldTL ( ) . x , view . GetWorldBR ( ) . x - textSize . x ) ;
drawPos . y = std : : clamp ( drawPos . y , view . GetWorldTL ( ) . y , view . GetWorldBR ( ) . y - textSize . y ) ;
view . DrawShadowStringPropDecal ( drawPos , text , colorsEnemy . first , colorsEnemy . second , scaling * additionalScaling ) ;
} else {
vf2d drawPos = dn - > pos - textSize / 2.f ;
drawPos . x = std : : clamp ( drawPos . x , view . GetWorldTL ( ) . x , view . GetWorldBR ( ) . x - textSize . x ) ;
drawPos . y = std : : clamp ( drawPos . y , view . GetWorldTL ( ) . y , view . GetWorldBR ( ) . y - textSize . y ) ;
view . DrawShadowStringPropDecal ( drawPos , text , colorsFriendly . first , colorsFriendly . second , scaling ) ;
}
} ;
switch ( dn - > type ) {
case HEALTH_LOSS : {
std : : string text = std : : to_string ( dn - > damage ) ;
DrawDamageNumber ( NumberScalesWithDamage , text , { DARK_RED , { 0 , 0 , 0 , 0 } } , { RED , VERY_DARK_GREY } ) ;
} break ;
case HEALTH_GAIN : {
std : : string text = " + " + std : : to_string ( dn - > damage ) ;
DrawDamageNumber ( NormalNumber , text , { DARK_GREEN , { 0 , 0 , 0 , 0 } } , { GREEN , VERY_DARK_GREY } ) ;
} break ;
case MANA_GAIN : {
std : : string text = " + " + std : : to_string ( dn - > damage ) ;
DrawDamageNumber ( NormalNumber , text , { BLUE , VERY_DARK_GREY } , { BLUE , VERY_DARK_GREY } ) ;
} break ;
case INTERRUPT : {
std : : string text = " Interrupted! " ;
DrawDamageNumber ( NormalNumber , text , { BLACK , VERY_DARK_GREY } , { BLACK , VERY_DARK_GREY } , { 0.5f , 1 } ) ;
} break ;
case CRIT : {
std : : string text = std : : to_string ( dn - > damage ) ;
DrawDamageNumber ( NumberScalesWithDamage , text , { YELLOW , DARK_YELLOW } , { BLACK , { 0 , 0 , 0 , 0 } } ) ;
} break ;
}
}
for ( std : : unique_ptr < Monster > & m : MONSTER_LIST ) {
m - > strategyDrawOverlay ( this , * m , MONSTER_DATA [ m - > GetName ( ) ] . GetAIStrategy ( ) ) ;
}
@ -2008,6 +1956,38 @@ void AiL::RenderHud(){
}
}
} ;
# pragma region Boss Indicators
if ( bossIndicatorPos . has_value ( ) ) {
const vf2d & bossIndicator = bossIndicatorPos . value ( ) ;
const bool BossIsOutsideView = ! geom2d : : overlaps ( geom2d : : rect < float > { view . GetWorldTL ( ) , view . GetWorldVisibleArea ( ) } , bossIndicator ) ;
if ( BossIsOutsideView ) {
const bool flicker = sinf ( GetRunTime ( ) ) > 0.5f & & sinf ( GetRunTime ( ) ) < 0.55f ;
# pragma region Side Indicators
const float yPos { std : : clamp ( view . WorldToScreen ( bossIndicator ) . y , 0.f , view . GetWorldVisibleArea ( ) . y ) } ;
if ( bossIndicator . x < view . GetWorldTL ( ) . x ) { //Left-side indicator
DrawRotatedDecal ( { 0 , yPos } , GFX [ " bossIndicator.png " ] . Decal ( ) , 0.f , { 0 , 16 } , { 8 , 1 } , flicker ? RED : DARK_RED ) ;
} else
if ( bossIndicator . x > view . GetWorldBR ( ) . x ) {
DrawRotatedDecal ( { float ( ScreenWidth ( ) - 8 ) , yPos } , GFX [ " bossIndicator.png " ] . Decal ( ) , 0.f , { 0 , 16 } , { 8 , 1 } , flicker ? RED : DARK_RED ) ;
}
# pragma endregion
# pragma region Top+Bottom Indicators
const float xPos { std : : clamp ( view . WorldToScreen ( bossIndicator ) . x , 0.f , view . GetWorldVisibleArea ( ) . x ) } ;
if ( bossIndicator . y < view . GetWorldTL ( ) . y ) { //Left-side indicator
DrawRotatedDecal ( { xPos , 4 } , GFX [ " bossIndicator.png " ] . Decal ( ) , PI / 2 , { 0.5f , 16.f } , { 8 , 1 } , flicker ? RED : DARK_RED ) ;
} else
if ( bossIndicator . y > view . GetWorldBR ( ) . y ) {
DrawRotatedDecal ( { xPos , float ( ScreenHeight ( ) - 4 ) } , GFX [ " bossIndicator.png " ] . Decal ( ) , PI / 2 , { 0.5f , 16.f } , { 8 , 1 } , flicker ? RED : DARK_RED ) ;
}
# pragma endregion
}
}
# pragma endregion
minimap . Update ( ) ;
minimap . Draw ( ) ;
@ -2040,7 +2020,7 @@ void AiL::RenderHud(){
Pixel healthOutlineCol = BLACK ;
if ( player - > GetHealth ( ) / player - > GetMaxHealth ( ) < = " Player.Health Warning Pct " _F / 100.f ) {
float runTimeAmt = fmod ( GetRunt ime ( ) , " Player.Health Warning Flicker Time " _F * 2 ) ;
float runTimeAmt = fmod ( GetRunT ime ( ) , " Player.Health Warning Flicker Time " _F * 2 ) ;
if ( runTimeAmt < " Player.Health Warning Flicker Time " _F ) {
healthOutlineCol = " Player.Health Warning Outline Color " _Pixel ;
}
@ -2084,6 +2064,59 @@ void AiL::RenderHud(){
}
DisplayBossEncounterInfo ( ) ;
for ( std : : vector < std : : shared_ptr < DamageNumber > > : : iterator it = DAMAGENUMBER_LIST . begin ( ) ; it ! = DAMAGENUMBER_LIST . end ( ) ; + + it ) {
DamageNumber * dn = ( * it ) . get ( ) ;
# define NumberScalesWithDamage true
# define NormalNumber false
auto DrawDamageNumber = [ & ] ( const bool ScaleWithNumber , std : : string_view text , std : : pair < Pixel , Pixel > colorsEnemy , std : : pair < Pixel , Pixel > colorsFriendly , vf2d scaling = { 1.f , 1.f } ) {
vf2d textSize = GetTextSizeProp ( text ) * scaling ;
if ( ! dn - > friendly ) {
vf2d additionalScaling = { 1.f , 1.f } ;
if ( ScaleWithNumber ) additionalScaling = dn - > size ;
textSize * = additionalScaling ;
vf2d drawPos = dn - > pos - textSize / 2.f ;
drawPos . x = std : : clamp ( drawPos . x , view . GetWorldTL ( ) . x , view . GetWorldBR ( ) . x - textSize . x ) ;
drawPos . y = std : : clamp ( drawPos . y , view . GetWorldTL ( ) . y , view . GetWorldBR ( ) . y - textSize . y ) ;
view . DrawShadowStringPropDecal ( drawPos , text , colorsEnemy . first , colorsEnemy . second , scaling * additionalScaling ) ;
} else {
vf2d drawPos = dn - > pos - textSize / 2.f ;
drawPos . x = std : : clamp ( drawPos . x , view . GetWorldTL ( ) . x , view . GetWorldBR ( ) . x - textSize . x ) ;
drawPos . y = std : : clamp ( drawPos . y , view . GetWorldTL ( ) . y , view . GetWorldBR ( ) . y - textSize . y ) ;
view . DrawShadowStringPropDecal ( drawPos , text , colorsFriendly . first , colorsFriendly . second , scaling ) ;
}
} ;
switch ( dn - > type ) {
case HEALTH_LOSS : {
std : : string text = std : : to_string ( dn - > damage ) ;
DrawDamageNumber ( NumberScalesWithDamage , text , { DARK_RED , { 0 , 0 , 0 , 0 } } , { RED , VERY_DARK_GREY } ) ;
} break ;
case HEALTH_GAIN : {
std : : string text = " + " + std : : to_string ( dn - > damage ) ;
DrawDamageNumber ( NormalNumber , text , { DARK_GREEN , { 0 , 0 , 0 , 0 } } , { GREEN , VERY_DARK_GREY } ) ;
} break ;
case MANA_GAIN : {
std : : string text = " + " + std : : to_string ( dn - > damage ) ;
DrawDamageNumber ( NormalNumber , text , { BLUE , VERY_DARK_GREY } , { BLUE , VERY_DARK_GREY } ) ;
} break ;
case INTERRUPT : {
std : : string text = " Interrupted! " ;
DrawDamageNumber ( NormalNumber , text , { BLACK , VERY_DARK_GREY } , { BLACK , VERY_DARK_GREY } , { 0.5f , 1 } ) ;
} break ;
case CRIT : {
std : : string text = std : : to_string ( dn - > damage ) ;
DrawDamageNumber ( NumberScalesWithDamage , text , { YELLOW , DARK_YELLOW } , { BLACK , { 0 , 0 , 0 , 0 } } ) ;
} break ;
}
}
# ifdef _DEBUG
if ( " debug_player_info " _I ) {
DrawShadowStringDecal ( { 0 , 128 } , player - > GetPos ( ) . str ( ) ) ;
@ -2390,6 +2423,7 @@ void AiL::_PrepareLevel(MapName map,MusicChange changeMusic){
}
# pragma endregion
bossIndicatorPos . reset ( ) ;
SPAWNER_LIST . clear ( ) ;
SPAWNER_CONTROLLER = { } ;
foregroundTileGroups . clear ( ) ;
@ -3775,7 +3809,7 @@ void AiL::ValidateGameStatus(){
void AiL : : RenderVersionInfo ( ) {
saveGameDisplayTime = std : : max ( 0.f , saveGameDisplayTime - game - > GetElapsedTime ( ) ) ;
if ( saveGameDisplayTime > 3.f ) {
DrawShadowStringDecal ( { 4.f , 4.f } , " Saving Game... " , { 255 , 255 , 255 , uint8_t ( ( sin ( game - > GetRunt ime ( ) ) + 1 ) * 127 ) } , { 0 , 0 , 0 , uint8_t ( ( sin ( game - > GetRunt ime ( ) ) + 1 ) * 127 ) } ) ;
DrawShadowStringDecal ( { 4.f , 4.f } , " Saving Game... " , { 255 , 255 , 255 , uint8_t ( ( sin ( game - > GetRunT ime ( ) ) + 1 ) * 127 ) } , { 0 , 0 , 0 , uint8_t ( ( sin ( game - > GetRunT ime ( ) ) + 1 ) * 127 ) } ) ;
} else
if ( saveGameDisplayTime > 0.f ) {
uint8_t alpha = uint8_t ( util : : lerp ( 0 , 255 , saveGameDisplayTime / 3.f ) ) ;
@ -4252,6 +4286,8 @@ rcode AiL::LoadResource(Renderable&renderable,std::string_view imgPath,bool filt
void AiL : : UpdateMonsters ( ) {
for ( std : : unique_ptr < Monster > & m : MONSTER_LIST ) {
if ( m - > HasArrowIndicator ( ) ) bossIndicatorPos = m - > GetPos ( ) ;
if ( m - > markedForDeletion ) {
AMonsterIsMarkedForDeletion ( ) ;
continue ;
@ -4289,6 +4325,8 @@ void AiL::ShowDamageVignetteOverlay(){
}
void AiL : : GlobalGameUpdates ( ) {
bossIndicatorPos = { } ;
levelTime + = GetElapsedTime ( ) ;
SteamAPI_RunCallbacks ( ) ;
STEAMINPUT (
@ -4388,4 +4426,8 @@ void AiL::UpdateEntities(){
void AiL : : AMonsterIsMarkedForDeletion ( ) {
aMonsterIsMarkedForDeletion = true ;
}
void AiL : : SetBossIndicatorPos ( const vf2d pos ) {
bossIndicatorPos = pos ;
}