2023-11-20 23:25:36 -06:00
# pragma region License
2023-11-14 18:11:32 -06:00
/*
License ( OLC - 3 )
~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~
2024-01-02 00:46:32 -06:00
Copyright 2024 Joshua Sigona < sigonasr2 @ gmail . com >
2023-11-14 18:11:32 -06:00
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 .
2023-11-29 00:50:00 -06:00
Portions of this software are copyright © 2023 The FreeType
Project ( www . freetype . org ) . Please see LICENSE_FT . txt for more information .
All rights reserved .
2023-11-14 18:11:32 -06:00
*/
2023-11-20 23:25:36 -06:00
# pragma endregion
2023-06-11 22:57:43 -05:00
# pragma once
2024-01-10 17:49:24 -06:00
# include "olcUTIL_Camera2D.h"
2023-06-11 22:57:43 -05:00
# include "Animation.h"
# include "olcUTIL_Animate2D.h"
# include "Monster.h"
# include "olcPGEX_TransformedView.h"
# include "Player.h"
2023-07-07 06:42:49 -05:00
# include "Bullet.h"
2023-06-15 00:11:39 -05:00
# include "Effect.h"
2023-06-21 14:30:14 -07:00
# include "Map.h"
# include "TMXParser.h"
2023-07-26 01:58:00 -05:00
# include "olcUTIL_DataFile.h"
2023-09-26 02:40:38 -05:00
# include "Key.h"
2023-11-28 18:29:06 -06:00
# include "GameState.h"
2023-12-21 18:06:17 -06:00
# ifndef __EMSCRIPTEN__
# include "discord.h"
# endif
2024-01-05 21:47:04 -06:00
# include "Audio.h"
2024-01-10 02:24:12 -06:00
# include "olcPGEX_SplashScreen.h"
2024-01-10 17:49:24 -06:00
# include "olcPixelGameEngine.h"
2024-01-23 23:04:29 -06:00
# include "DynamicCounter.h"
2023-06-21 14:30:14 -07:00
2024-01-12 11:51:07 -06:00
# define CreateBullet(type) BULLET_LIST.push_back(std::make_unique<type>(type
# define EndBullet ));
2024-01-15 01:30:06 -06:00
using HurtReturnValue = bool ;
using MonsterHurtList = std : : vector < std : : pair < Monster * , HurtReturnValue > > ;
2024-01-04 05:21:56 -06:00
class AiL : public olc : : PixelGameEngine
2023-06-11 22:57:43 -05:00
{
2023-11-28 18:29:06 -06:00
friend class GameState ;
2023-10-05 02:03:59 -05:00
friend class State_GameRun ;
2024-01-02 02:15:39 -06:00
friend class SaveFile ;
2023-07-12 00:23:36 -05:00
friend class sig : : Animation ;
2024-01-05 21:47:04 -06:00
friend class Audio ;
2023-07-13 20:24:47 +00:00
std : : unique_ptr < Player > player ;
2024-01-10 02:24:12 -06:00
SplashScreen splash ;
2023-06-24 01:18:21 -07:00
public :
2023-07-10 18:40:51 +00:00
Pathfinding pathfinder ;
2024-01-16 20:14:43 -06:00
static InputGroup KEY_SCROLLUP ;
static InputGroup KEY_SCROLLDOWN ;
static InputGroup KEY_BACK ;
2023-11-28 18:29:06 -06:00
static InputGroup KEY_CONFIRM ;
2023-09-26 02:40:38 -05:00
static InputGroup KEY_ATTACK ;
static InputGroup KEY_LEFT ;
static InputGroup KEY_RIGHT ;
static InputGroup KEY_UP ;
static InputGroup KEY_DOWN ;
2023-11-29 23:52:43 -06:00
static InputGroup KEY_MENU ;
2024-01-17 17:22:23 +00:00
static InputGroup KEY_START ;
static InputGroup KEY_SELECT ;
2024-01-19 15:17:17 +00:00
static InputGroup KEY_SCROLL ;
2024-01-20 14:42:35 -06:00
static InputGroup KEY_CHANGE_LOADOUT ;
2024-01-19 15:17:17 +00:00
2023-09-07 20:20:21 +00:00
static float SIZE_CHANGE_SPEED ;
2023-12-25 21:25:22 -06:00
double levelTime ;
2023-10-29 17:00:54 -05:00
Camera2D camera ;
2023-11-11 17:31:53 -06:00
std : : map < MapName , Map > MAP_DATA ;
2023-06-24 01:18:21 -07:00
private :
2023-07-21 15:20:56 -05:00
std : : vector < std : : unique_ptr < Effect > > foregroundEffects , backgroundEffects , foregroundEffectsToBeInserted , backgroundEffectsToBeInserted ;
2023-09-24 04:01:04 -05:00
std : : vector < TileRenderData * > tilePreparationList , tileForegroundList ;
2023-11-22 14:30:15 -06:00
std : : vector < int > dropsBeforeLower , dropsAfterLower , dropsBeforeUpper , dropsAfterUpper ;
2023-11-16 20:41:59 -06:00
std : : vector < ZoneData > endZones , upperEndZones ;
2023-09-24 05:23:49 -05:00
std : : vector < vf2d > circleCooldownPoints ;
2023-11-23 19:59:19 -06:00
std : : vector < vf2d > squareCircleCooldownPoints ;
2023-06-22 22:09:11 -07:00
std : : map < std : : string , TilesetData > MAP_TILESETS ;
2023-06-20 19:13:45 -07:00
vf2d worldShake = { } ;
float worldShakeTime = 0 ;
float lastWorldShakeAdjust = 0 ;
vf2d worldShakeVel = { } ;
2023-11-27 02:38:12 -06:00
const float WORLD_SHAKE_ADJUST_MAX_TIME = 0.4f ;
2024-01-09 04:50:01 -06:00
MapName currentLevel = " CAMPAIGN_1_1 " ;
2023-06-22 23:28:16 -07:00
std : : vector < TileGroup > foregroundTileGroups ;
2023-07-06 14:24:43 -05:00
std : : vector < TileGroup > upperForegroundTileGroups ;
2023-07-07 06:42:49 -05:00
int bridgeLayerIndex = - 1 ;
2023-07-11 17:24:50 +00:00
float bridgeFadeFactor = 0.f ;
2023-07-26 21:08:17 +00:00
void InitializeClasses ( ) ;
2023-09-12 19:36:25 +00:00
int DEBUG_PATHFINDING = 0 ;
2023-09-15 01:02:10 -05:00
std : : vector < Monster * > monstersBeforeLower , monstersAfterLower , monstersBeforeUpper , monstersAfterUpper ;
std : : vector < Bullet * > bulletsLower , bulletsUpper ;
std : : vector < Effect * > backgroundEffectsLower , backgroundEffectsUpper , foregroundEffectsLower , foregroundEffectsUpper ;
float reflectionUpdateTimer = 0 ;
float reflectionStepTime = 0 ;
std : : set < vi2d > visibleTiles ;
2023-09-26 05:22:04 -05:00
float bossDisplayTimer = 0 ;
std : : string bossName ;
2023-09-26 06:35:21 -05:00
int totalDamageDealt = 0 ;
float encounterDuration = 0 ;
bool encounterStarted = false ;
int totalBossEncounterMobs = 0 ;
2023-11-11 17:31:53 -06:00
int chapter = 1 ; //We start at chapter 1.
2023-12-22 06:14:37 -06:00
std : : array < std : : shared_ptr < Item > , 3 > loadout ;
2023-11-28 18:29:06 -06:00
float fadeOutDuration = 0 ;
States : : State transitionState = States : : State : : GAME_RUN ;
2023-11-29 23:52:43 -06:00
bool gameEnd = false ;
2023-10-05 02:03:59 -05:00
std : : vector < Monster > monstersToBeSpawned ;
2023-12-19 14:06:17 -06:00
time_t gameStarted ;
2024-01-02 20:58:04 -06:00
std : : function < void ( std : : string_view ) > responseCallback ;
2024-01-06 18:09:29 -06:00
float fadeInDuration = 0 ;
float fadeOutTotalTime = 0 ;
bool disableFadeIn = false ;
2024-01-23 23:04:29 -06:00
DynamicCounter healthCounter ;
DynamicCounter manaCounter ;
2024-01-24 21:11:16 -06:00
Pixel worldColor = WHITE ;
std : : function < Pixel ( vi2d ) > worldColorFunc = [ ] ( vi2d pos ) { return WHITE ; } ;
2024-01-28 19:39:01 -06:00
std : : map < std : : string , std : : vector < : : ZoneData > > ZONE_LIST ;
2023-10-24 04:52:24 -05:00
void ValidateGameStatus ( ) ;
2023-12-21 18:06:17 -06:00
# ifndef __EMSCRIPTEN__
: : discord : : Result SetupDiscord ( ) ;
# endif
2024-01-05 21:47:04 -06:00
Audio audioEngine ;
2023-06-11 22:57:43 -05:00
public :
2024-01-04 05:21:56 -06:00
AiL ( ) ;
2023-07-25 20:32:29 +00:00
bool OnUserCreate ( ) override ;
bool OnUserUpdate ( float fElapsedTime ) override ;
2023-09-16 07:00:38 -05:00
bool OnUserDestroy ( ) override ;
2023-06-11 22:57:43 -05:00
public :
2024-01-11 01:26:58 -06:00
geom2d : : rect < float > NO_COLLISION = { { 0.f , 0.f , } , { 0.f , 0.f } } ;
2023-06-15 00:11:39 -05:00
TileTransformedView view ;
2023-06-21 22:59:06 -07:00
void InitializeLevel ( std : : string mapFile , MapName map ) ;
2023-06-22 02:46:38 -07:00
void LoadLevel ( MapName map ) ;
2023-06-11 22:57:43 -05:00
void HandleUserInput ( float fElapsedTime ) ;
void UpdateCamera ( float fElapsedTime ) ;
2023-06-15 00:11:39 -05:00
void UpdateEffects ( float fElapsedTime ) ;
2023-06-16 01:41:38 -05:00
void UpdateBullets ( float fElapsedTime ) ;
2023-06-12 00:37:55 -05:00
void RenderWorld ( float fElapsedTime ) ;
2023-06-15 00:47:11 -05:00
void RenderHud ( ) ;
2023-09-29 00:03:20 -05:00
void RenderMenu ( ) ;
2023-07-13 01:35:51 -05:00
void AddEffect ( std : : unique_ptr < Effect > foreground , std : : unique_ptr < Effect > background ) ;
2023-06-19 03:25:01 -05:00
//If back is true, places the effect in the background
2023-07-13 01:35:51 -05:00
void AddEffect ( std : : unique_ptr < Effect > foreground , bool back = false ) ;
2024-01-15 01:30:06 -06:00
const MonsterHurtList HurtEnemies ( vf2d pos , float radius , int damage , bool upperLevel , float z ) ;
2023-06-15 04:53:57 -05:00
vf2d GetWorldMousePos ( ) ;
2023-06-15 05:06:50 -05:00
bool LeftHeld ( ) ;
bool RightHeld ( ) ;
bool UpHeld ( ) ;
bool DownHeld ( ) ;
2024-01-15 02:50:20 -06:00
bool LeftPressed ( ) ;
bool RightPressed ( ) ;
bool UpPressed ( ) ;
bool DownPressed ( ) ;
2023-06-15 05:06:50 -05:00
bool LeftReleased ( ) ;
bool RightReleased ( ) ;
bool UpReleased ( ) ;
bool DownReleased ( ) ;
2023-07-13 20:24:47 +00:00
Player * GetPlayer ( ) ;
2023-06-20 19:13:45 -07:00
void SetupWorldShake ( float duration ) ;
2023-06-22 04:34:23 -07:00
//tileID is the tile number from the tilesets.
2023-06-22 22:09:11 -07:00
bool IsForegroundTile ( TilesheetData sheet , int tileID ) ;
//tileID is the tile number from the tilesets.
2023-09-12 04:54:58 -05:00
bool IsUpperForegroundTile ( int tileID ) ;
2023-07-06 14:24:43 -05:00
//tileID is the tile number from the tilesets.
2023-06-22 04:34:23 -07:00
TilesheetData GetTileSheet ( MapName map , int tileID ) ;
2023-07-06 14:59:21 -05:00
//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.
2024-01-11 01:26:58 -06:00
geom2d : : rect < float > GetTileCollision ( MapName map , vf2d pos , bool upperLevel = false ) ;
2023-07-05 18:29:04 +00:00
//Checks if the point resides inside of a collision tile.
2023-07-06 14:59:21 -05:00
bool HasTileCollision ( MapName map , vf2d pos , bool upperLevel = false ) ;
2024-01-08 02:05:09 -06:00
const MapName & GetCurrentLevel ( ) const ;
2023-07-06 14:24:43 -05:00
bool IsBridgeLayer ( LayerTag & layer ) ;
2023-11-16 20:41:59 -06:00
std : : map < std : : string , std : : vector < ZoneData > > & GetZoneData ( MapName map ) ;
2023-09-15 01:02:10 -05:00
void PopulateRenderLists ( ) ;
2023-07-13 20:24:47 +00:00
void ChangePlayerClass ( Class cl ) ;
2023-07-26 01:58:00 -05:00
std : : string GetString ( std : : string key ) ;
2023-07-26 18:08:06 +00:00
datafilestringdata GetStringList ( std : : string key ) ;
2023-07-26 01:58:00 -05:00
int GetInt ( std : : string key ) ;
2023-07-26 18:08:06 +00:00
datafileintdata GetIntList ( std : : string key ) ;
2023-07-26 01:58:00 -05:00
float GetFloat ( std : : string key ) ;
2023-07-26 18:08:06 +00:00
datafilefloatdata GetFloatList ( std : : string key ) ;
2023-07-26 01:58:00 -05:00
double GetDouble ( std : : string key ) ;
2023-07-26 18:08:06 +00:00
datafiledoubledata GetDoubleList ( std : : string key ) ;
2023-09-07 01:35:23 -05:00
static void OutputDebugInfo ( const char * key , std : : size_t len ) ;
2023-09-07 03:28:37 -05:00
void InitializeLevels ( ) ;
2023-09-13 18:57:46 -05:00
void RenderTile ( vi2d pos , TilesheetData tileSheet , int tileSheetIndex , vi2d tileSheetPos ) ;
void RenderTile ( TileRenderData & tileSheet , Pixel col ) ;
2023-09-15 01:02:10 -05:00
bool IsReflectiveTile ( TilesheetData tileSheet , int tileID ) ;
2023-12-19 00:15:47 -06:00
void SpawnMonster ( vf2d pos , MonsterData & data , bool upperLevel = false , bool isBossSpawn = false ) ; //Queues a monster for spawning on the next frame.
2023-09-24 05:23:49 -05:00
void DrawPie ( vf2d center , float radius , float degreesCut , Pixel col ) ;
2023-11-23 19:59:19 -06:00
void DrawSquarePie ( vf2d center , float radius , float degreesCut , Pixel col ) ;
2023-09-26 00:32:54 -05:00
void RenderCooldowns ( ) ;
2023-09-26 02:40:38 -05:00
void InitializeDefaultKeybinds ( ) ;
2023-09-26 05:22:04 -05:00
void SetBossNameDisplay ( std : : string name , float time = 5 ) ;
2023-09-26 06:35:21 -05:00
bool InBossEncounter ( ) ;
void StartBossEncounter ( ) ;
void DisplayBossEncounterInfo ( ) ;
void BossDamageDealt ( int damage ) ;
void ReduceBossEncounterMobCount ( ) ;
2024-01-28 19:39:01 -06:00
const uint8_t BossEncounterMobCount ( ) const ;
2023-10-02 19:54:21 +00:00
void InitializeGraphics ( ) ;
2023-11-04 22:19:25 -05:00
void RenderVersionInfo ( ) ;
2024-01-08 02:05:09 -06:00
const Map & GetCurrentMap ( ) const ;
const MapTag & GetCurrentMapData ( ) const ;
const MapName & GetCurrentMapName ( ) const ;
2024-01-28 19:39:01 -06:00
const std : : string_view GetCurrentMapDisplayName ( ) const ;
2023-11-11 17:31:53 -06:00
int GetCurrentChapter ( ) ;
void SetChapter ( int chapter ) ;
2023-12-22 06:14:37 -06:00
const std : : weak_ptr < Item > GetLoadoutItem ( int slot ) ;
2023-11-14 23:20:13 -06:00
void SetLoadoutItem ( int slot , std : : string itemName ) ;
2023-11-26 15:51:13 -06:00
//Returns true if the item can be used (we have >0 of it)
bool UseLoadoutItem ( int slot ) ;
2023-11-14 23:20:13 -06:00
//Blanks out this loadout item.
void ClearLoadoutItem ( int slot ) ;
2023-11-28 18:29:06 -06:00
void RenderFadeout ( ) ;
bool GamePaused ( ) ;
2023-11-29 23:52:43 -06:00
void EndGame ( ) ;
2023-12-19 14:06:17 -06:00
void UpdateDiscordStatus ( std : : string levelName , std : : string className ) ;
2023-12-24 22:50:25 -06:00
void InitializePlayerLevelCap ( ) ;
2024-01-01 04:58:06 -06:00
void ResetGame ( ) ;
2024-01-02 04:45:44 -06:00
void OnRequestCompleted ( const std : : string_view receivedData ) const override ;
2024-01-06 18:09:29 -06:00
void DisableFadeIn ( const bool disable ) ;
2024-01-24 21:11:16 -06:00
//vi2d provides a tile in world coords.
void SetWorldColorFunc ( std : : function < Pixel ( vi2d ) > func ) ;
void SetWorldColor ( Pixel worldCol ) ;
const Pixel & GetWorldColor ( ) const ;
2024-01-28 19:39:01 -06:00
//Returns the zones in the current stage
const std : : map < std : : string , std : : vector < : : ZoneData > > & GetZones ( ) const ;
//Returns the zones of any given stage
const std : : map < std : : string , std : : vector < : : ZoneData > > & GetZones ( const std : : string_view mapName ) const ;
void AddZone ( const std : : string_view zoneName , const ZoneData & zone ) ;
2023-09-07 04:41:23 -05:00
struct TileGroupData {
vi2d tilePos ;
int layer ;
bool operator < ( const TileGroupData & rhs ) const {
return layer < rhs . layer | | ( layer = = rhs . layer & & tilePos < rhs . tilePos ) ;
}
} ;
} ;