# pragma region License
/*
License ( OLC - 3 )
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
Copyright 2024 Joshua Sigona < sigonasr2 @ gmail . com >
Redistribution and use in source and binary forms , with or without modification ,
are permitted provided that the following conditions are met :
1. Redistributions or derivations of source code must retain the above copyright
notice , this list of conditions and the following disclaimer .
2. Redistributions or derivative works in binary form must reproduce the above
copyright notice . This list of conditions and the following disclaimer must be
reproduced in the documentation and / or other materials provided with the distribution .
3. Neither the name of the copyright holder nor the names of its contributors may
be used to endorse or promote products derived from this software without specific
prior written permission .
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS " AS IS " AND ANY
EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT LIMITED TO , THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING , BUT NOT LIMITED
TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR
BUSINESS INTERRUPTION ) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN
CONTRACT , STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE .
Portions of this software are copyright © 2024 The FreeType
Project ( www . freetype . org ) . Please see LICENSE_FT . txt for more information .
All rights reserved .
*/
# pragma endregion
# include "State_LevelComplete.h"
# include "AdventuresInLestoria.h"
# include "DEFINES.h"
# include "Menu.h"
# include "MenuLabel.h"
# include "SaveFile.h"
# include "ProgressBar.h"
# include "SoundEffect.h"
INCLUDE_MONSTER_LIST
INCLUDE_game
void State_LevelComplete : : OnStateChange ( GameState * prevState ) {
if ( xpGainSound = = std : : numeric_limits < size_t > : : max ( ) ) {
xpGainSound = Audio : : LoadAndPlay ( " xpgain.ogg " _SFX , true ) ;
Audio : : Engine ( ) . SetVolume ( xpGainSound , 0.f ) ;
}
if ( Menu : : IsMenuOpen ( ) ) {
Menu : : CloseAllMenus ( ) ;
}
levelUpTextPos = { - 100.f , - 100.f } ;
Component < ProgressBar > ( MenuType : : LEVEL_COMPLETE , " XP Bar " ) - > ResetProgressBar ( game - > GetPlayer ( ) - > CurrentXP ( ) , game - > GetPlayer ( ) - > NextLevelXPRequired ( ) ) ;
accumulatedXP = game - > GetPlayer ( ) - > GetAccumulatedXP ( ) ;
gainRate = ( game - > GetPlayer ( ) - > NextLevelXPRequired ( ) * 0.5f ) ;
float xpBonus = 1.1f ; //10% XP bonus for finishing a stage.
if ( Component < MenuLabel > ( LEVEL_COMPLETE , " Stage Complete Label " ) - > GetLabel ( ) ! = " Stage Summary " ) { //If the label says stage summary, we didn't actually complete the level. Don't reward any stage items to the player.
for ( const ItemMapData & data : game - > GetCurrentMap ( ) . GetStageLoot ( ) ) {
uint8_t amountDiff = data . maxAmt - data . minAmt ;
uint8_t randomAmt = data . maxAmt ;
if ( amountDiff > 0 ) { //This check avoids division by zero.
randomAmt = util : : random ( ) % ( amountDiff + 1 ) + data . minAmt ;
}
for ( uint8_t rolls = 0 ; rolls < randomAmt ; rolls + + ) {
if ( util : : random ( 1.0f ) < data . chance / 100.f ) {
Inventory : : AddItem ( data . item , 1U ) ;
}
}
}
xpBonus = 1.0f ;
}
accumulatedXP * = xpBonus ;
Component < MenuLabel > ( MenuType : : LEVEL_COMPLETE , " Level EXP Gain Outline " ) - > SetLabel ( std : : format ( " +{} Exp " , accumulatedXP ) ) ;
game - > GetPlayer ( ) - > AddXP ( game - > GetPlayer ( ) - > GetAccumulatedXP ( ) ) ;
game - > GetPlayer ( ) - > SetState ( State : : NORMAL ) ;
Menu : : OpenMenu ( LEVEL_COMPLETE ) ;
} ;
void State_LevelComplete : : OnLevelLoad ( ) { }
void State_LevelComplete : : OnUserUpdate ( AiL * game ) {
if ( levelUpTimer > 0.f ) {
levelUpTimer = std : : max ( 0.f , levelUpTimer - game - > GetElapsedTime ( ) ) ;
levelUpTextPos . y - = ( 16 / " Interface.HUD Level Up Timer " _F ) * game - > GetElapsedTime ( ) ;
if ( levelUpTimer < 0.f ) {
levelUpTimer = 0.f ;
levelUpTextPos = Menu : : menus [ LEVEL_COMPLETE ] - > pos . x + Component < MenuLabel > ( LEVEL_COMPLETE , " Level Display " ) - > GetPos ( ) + Component < MenuLabel > ( LEVEL_COMPLETE , " Level Display " ) - > GetSize ( ) - vf2d { 0.f , 16.f } ;
}
}
lastXPGain - = game - > GetElapsedTime ( ) ;
if ( accumulatedXP > 0 ) {
Audio : : Engine ( ) . SetVolume ( xpGainSound , Audio : : GetCalculatedSFXVolume ( 0.6f ) ) ;
if ( lastXPGain < = 0.f ) {
int incrementAmt = gainRate * ( 1 / 60.f ) + 1 ;
accumulatedXP = std : : max ( 0 , accumulatedXP - incrementAmt ) ;
auto progressBar = Component < ProgressBar > ( MenuType : : LEVEL_COMPLETE , " XP Bar " ) ;
progressBar - > UpdateProgressBar ( progressBar - > GetCurrentProgress ( ) + incrementAmt ) ;
if ( progressBar - > GetCurrentProgress ( ) > = progressBar - > GetFinalProgress ( ) ) {
levelUpTextPos = Menu : : menus [ LEVEL_COMPLETE ] - > pos + Component < MenuLabel > ( LEVEL_COMPLETE , " Level Display " ) - > GetPos ( ) + Component < MenuLabel > ( LEVEL_COMPLETE , " Level Display " ) - > GetSize ( ) ;
levelUpTimer = " Interface.HUD Level Up Timer " _F ;
progressBar - > ResetProgressBar ( progressBar - > GetCurrentProgress ( ) - progressBar - > GetFinalProgress ( ) , game - > GetPlayer ( ) - > NextLevelXPRequired ( ) ) ;
SoundEffect : : PlaySFX ( " Level Up " , SoundEffect : : CENTERED ) ;
}
lastXPGain = 1 / 60.f ;
}
} else {
Audio : : Engine ( ) . SetVolume ( xpGainSound , 0.f ) ;
}
} ;
void State_LevelComplete : : Draw ( AiL * game ) {
game - > RenderHud ( ) ;
} ;
void State_LevelComplete : : DrawOverlay ( AiL * game ) {
game - > DrawShadowStringPropDecal ( levelUpTextPos + vf2d { 8.f , 0.f } , " Level Up! " , YELLOW ) ;
game - > DrawRotatedDecal ( levelUpTextPos + vf2d { 2.f , 1.f } , GFX [ " overworld_arrow.png " ] . Decal ( ) , - PI / 2 , GFX [ " overworld_arrow.png " ] . Sprite ( ) - > Size ( ) , { 1.f , 1.f } , BLACK ) ;
game - > DrawRotatedDecal ( levelUpTextPos + vf2d { 2.f , 0.f } , GFX [ " overworld_arrow.png " ] . Decal ( ) , - PI / 2 , GFX [ " overworld_arrow.png " ] . Sprite ( ) - > Size ( ) , { 1.f , 1.f } , YELLOW ) ;
}
void State_LevelComplete : : TurnOffXPSound ( ) {
Audio : : Engine ( ) . SetVolume ( ( ( State_LevelComplete * ) ( GameState : : states [ States : : LEVEL_COMPLETE ] ) ) - > xpGainSound , 0.f ) ;
}