The open source repository for the action RPG game in development by Sig Productions titled 'Adventures in Lestoria'!
https://forums.lestoria.net
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
345 lines
13 KiB
345 lines
13 KiB
#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
|
|
#pragma once
|
|
#include "olcUTIL_Camera2D.h"
|
|
#include "Animation.h"
|
|
#include "olcUTIL_Animate2D.h"
|
|
#include "Monster.h"
|
|
#include "olcPGEX_TransformedView.h"
|
|
#include "Player.h"
|
|
#include "Bullet.h"
|
|
#include "Effect.h"
|
|
#include "Map.h"
|
|
#include "TMXParser.h"
|
|
#include "olcUTIL_DataFile.h"
|
|
#include "GameState.h"
|
|
#ifndef __EMSCRIPTEN__
|
|
#include "discord.h"
|
|
#endif
|
|
#include "Audio.h"
|
|
#include "olcPGEX_SplashScreen.h"
|
|
#include "olcPixelGameEngine.h"
|
|
#include "DynamicCounter.h"
|
|
#include "UndefKeys.h"
|
|
#include "Minimap.h"
|
|
|
|
|
|
class SteamKeyboardCallbackHandler;
|
|
class SteamStatsReceivedHandler;
|
|
|
|
#define CreateBullet(type) BULLET_LIST.push_back(std::make_unique<type>(type
|
|
#define EndBullet ));
|
|
|
|
using HurtReturnValue=bool;
|
|
using MonsterHurtList=std::vector<std::pair<Monster*,HurtReturnValue>>;
|
|
|
|
class AiL : public olc::PixelGameEngine
|
|
{
|
|
friend class GameState;
|
|
friend class State_GameRun;
|
|
friend class SaveFile;
|
|
friend class sig::Animation;
|
|
friend class Audio;
|
|
std::unique_ptr<Player>player;
|
|
SplashScreen splash;
|
|
public:
|
|
enum MusicChange{
|
|
NO_MUSIC_CHANGE,
|
|
PLAY_LEVEL_MUSIC,
|
|
};
|
|
Pathfinding pathfinder;
|
|
static InputGroup KEY_BACK;
|
|
static InputGroup KEY_CONFIRM;
|
|
static InputGroup KEY_ATTACK;
|
|
static InputGroup KEY_LEFT;
|
|
static InputGroup KEY_RIGHT;
|
|
static InputGroup KEY_UP;
|
|
static InputGroup KEY_DOWN;
|
|
static InputGroup KEY_MENU;
|
|
static InputGroup KEY_UNEQUIP;
|
|
|
|
static InputGroup KEY_START;
|
|
static InputGroup KEY_CONTROLLER_START;
|
|
static InputGroup KEY_SELECT;
|
|
|
|
static InputGroup KEY_FACEUP;
|
|
static InputGroup KEY_FACERIGHT;
|
|
static InputGroup KEY_FACELEFT;
|
|
static InputGroup KEY_FACEDOWN;
|
|
|
|
static InputGroup KEY_FASTSCROLLDOWN;
|
|
static InputGroup KEY_FASTSCROLLUP;
|
|
static InputGroup KEY_SCROLLDOWN;
|
|
static InputGroup KEY_SCROLLUP;
|
|
static InputGroup KEY_SCROLLLEFT;
|
|
static InputGroup KEY_SCROLLRIGHT;
|
|
static InputGroup KEY_SCROLLHORZ;
|
|
static InputGroup KEY_SCROLLHORZ_L;
|
|
static InputGroup KEY_SCROLLHORZ_R;
|
|
static InputGroup KEY_SCROLLVERT;
|
|
static InputGroup KEY_SCROLLVERT_R;
|
|
static InputGroup KEY_SCROLLVERT_L;
|
|
static InputGroup KEY_SCROLL;
|
|
static InputGroup KEY_SHOULDER;
|
|
static InputGroup KEY_SHOULDER2;
|
|
static InputGroup KEY_CHANGE_LOADOUT;
|
|
static InputGroup KEY_ENTER;
|
|
|
|
static InputGroup KEY_MOUSE_RIGHT;
|
|
|
|
static float SIZE_CHANGE_SPEED;
|
|
double levelTime=0.;
|
|
Camera2D camera;
|
|
std::map<MapName,Map>MAP_DATA;
|
|
private:
|
|
std::vector<std::unique_ptr<Effect>>foregroundEffects,backgroundEffects,foregroundEffectsToBeInserted,backgroundEffectsToBeInserted;
|
|
std::vector<TileRenderData*>tilesWithCollision,tilesWithoutCollision;
|
|
std::vector<int>dropsBeforeLower,dropsAfterLower,dropsBeforeUpper,dropsAfterUpper;
|
|
std::vector<ZoneData>endZones,upperEndZones;
|
|
std::vector<vf2d>circleCooldownPoints;
|
|
std::vector<vf2d>squareCircleCooldownPoints;
|
|
std::map<std::string,TilesetData>MAP_TILESETS;
|
|
vf2d worldShake={};
|
|
float worldShakeTime=0;
|
|
float lastWorldShakeAdjust=0;
|
|
vf2d worldShakeVel={};
|
|
const float WORLD_SHAKE_ADJUST_MAX_TIME=0.4f;
|
|
MapName previousLevel="CAMPAIGN_1_1";
|
|
MapName currentLevel="CAMPAIGN_1_1";
|
|
std::vector<TileGroup>foregroundTileGroups;
|
|
std::vector<TileGroup>upperForegroundTileGroups;
|
|
int bridgeLayerIndex=-1;
|
|
float bridgeFadeFactor=0.f;
|
|
void InitializeClasses();
|
|
int DEBUG_PATHFINDING=0;
|
|
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;
|
|
float bossDisplayTimer=0;
|
|
std::string bossName;
|
|
int totalDamageDealt=0;
|
|
float encounterDuration=0;
|
|
bool encounterStarted=false;
|
|
int totalBossEncounterMobs=0;
|
|
int chapter=1; //We start at chapter 1.
|
|
std::array<std::shared_ptr<Item>,3>loadout;
|
|
float fadeOutDuration=0;
|
|
States::State transitionState=States::State::GAME_RUN;
|
|
bool gameEnd=false;
|
|
std::vector<Monster>monstersToBeSpawned;
|
|
time_t gameStarted;
|
|
std::function<void(std::string_view)>responseCallback;
|
|
float fadeInDuration=0;
|
|
float fadeOutTotalTime=0;
|
|
bool disableFadeIn=false;
|
|
DynamicCounter healthCounter;
|
|
DynamicCounter manaCounter;
|
|
Pixel worldColor=WHITE;
|
|
std::function<Pixel(vi2d)>worldColorFunc=[](vi2d pos){return WHITE;};
|
|
std::map<std::string,std::vector<::ZoneData>>ZONE_LIST;
|
|
float lastMouseMovement=0.f; //Amount of time since the last time the cursor was moved or interacted with.
|
|
vi2d lastMousePos={};
|
|
bool gameInitialized=false;
|
|
ResourcePack gamepack;
|
|
uint8_t mosaicEffectTransition=1U;
|
|
float saveGameDisplayTime=0.f;
|
|
float loadingWaitTime=0.f;
|
|
bool displayHud=true;
|
|
float vignetteDisplayTime=0.f;
|
|
bool savingFile=false;
|
|
bool prevStageCompleted=false;
|
|
Minimap minimap;
|
|
|
|
void ValidateGameStatus();
|
|
void _PrepareLevel(MapName map,MusicChange changeMusic);
|
|
//This function assigns the mode tile colors of each loaded tileset.
|
|
void ComputeModeColors(TilesetData&tileset);
|
|
#ifndef __EMSCRIPTEN__
|
|
::discord::Result SetupDiscord();
|
|
#endif
|
|
Audio audioEngine;
|
|
SteamKeyboardCallbackHandler*steamKeyboardCallbackListener=nullptr;
|
|
SteamStatsReceivedHandler*steamStatsReceivedHandlerListener=nullptr;
|
|
public:
|
|
AiL();
|
|
bool OnUserCreate() override;
|
|
bool OnUserUpdate(float fElapsedTime) override;
|
|
bool OnUserDestroy() override;
|
|
void GetAnyKeyPress(Key key)override final;
|
|
void GetAnyKeyRelease(Key key)override final;
|
|
void GetAnyMousePress(int32_t mouseButton)override final;
|
|
void GetAnyMouseHeld(int32_t mouseButton)override final;
|
|
void GetAnyMouseRelease(int32_t mouseButton)override final;
|
|
public:
|
|
geom2d::rect<float>NO_COLLISION={{0.f,0.f,},{0.f,0.f}};
|
|
TileTransformedView view;
|
|
void InitializeLevel(std::string mapFile,MapName map);
|
|
void LoadLevel(MapName map,MusicChange changeMusic=PLAY_LEVEL_MUSIC);
|
|
void HandleUserInput(float fElapsedTime);
|
|
void UpdateCamera(float fElapsedTime);
|
|
void UpdateEffects(float fElapsedTime);
|
|
void UpdateBullets(float fElapsedTime);
|
|
void RenderWorld(float fElapsedTime);
|
|
void RenderHud();
|
|
void RenderMenu();
|
|
bool MenuClicksDeactivated()const;
|
|
void AddEffect(std::unique_ptr<Effect>foreground,std::unique_ptr<Effect>background);
|
|
//If back is true, places the effect in the background
|
|
void AddEffect(std::unique_ptr<Effect>foreground,bool back=false);
|
|
const MonsterHurtList HurtEnemies(vf2d pos,float radius,int damage,bool upperLevel,float z)const;
|
|
//NOTE: This function will also add any enemies that were hit into the hit list!
|
|
const MonsterHurtList HurtEnemiesNotHit(vf2d pos,float radius,int damage,HitList&hitList,bool upperLevel,float z);
|
|
// angle: The central angle where the arc will extend from.
|
|
// sweepAngle: The amount of radians to extend in both directions from the central angle.
|
|
// NOTE: This function will also add any enemies that were hit into the hit list!
|
|
const MonsterHurtList HurtEnemiesConeNotHit(vf2d pos,float radius,float angle,float sweepAngle,int damage,HitList&hitList,bool upperLevel,float z);
|
|
vf2d GetWorldMousePos();
|
|
bool LeftHeld();
|
|
bool RightHeld();
|
|
bool UpHeld();
|
|
bool DownHeld();
|
|
bool LeftPressed();
|
|
bool RightPressed();
|
|
bool UpPressed();
|
|
bool DownPressed();
|
|
bool LeftReleased();
|
|
bool RightReleased();
|
|
bool UpReleased();
|
|
bool DownReleased();
|
|
Player*GetPlayer();
|
|
void SetupWorldShake(float duration);
|
|
//tileID is the tile number from the tilesets.
|
|
bool IsForegroundTile(TilesheetData sheet,int tileID);
|
|
//tileID is the tile number from the tilesets.
|
|
bool IsUpperForegroundTile(int tileID);
|
|
//tileID is the tile number from the tilesets.
|
|
TilesheetData GetTileSheet(MapName map,int tileID);
|
|
//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);
|
|
Pixel GetTileColor(MapName map,vf2d pos,bool upperLevel=false);
|
|
//Checks if the point resides inside of a collision tile.
|
|
bool HasTileCollision(MapName map,vf2d pos,bool upperLevel=false);
|
|
const MapName&GetCurrentLevel()const;
|
|
bool IsBridgeLayer(LayerTag&layer);
|
|
bool IsOverlayLayer(LayerTag&layer);
|
|
void PopulateRenderLists();
|
|
void ChangePlayerClass(Class cl);
|
|
std::string GetString(std::string key);
|
|
datafilestringdata GetStringList(std::string key);
|
|
int GetInt(std::string key);
|
|
datafileintdata GetIntList(std::string key);
|
|
float GetFloat(std::string key);
|
|
datafilefloatdata GetFloatList(std::string key);
|
|
double GetDouble(std::string key);
|
|
datafiledoubledata GetDoubleList(std::string key);
|
|
static void OutputDebugInfo(const char*key,std::size_t len);
|
|
void InitializeLevels();
|
|
void RenderTile(vi2d pos,TilesheetData tileSheet,int tileSheetIndex,vi2d tileSheetPos);
|
|
void RenderTile(TileRenderData&tileSheet,Pixel col);
|
|
bool IsReflectiveTile(TilesheetData tileSheet,int tileID);
|
|
void SpawnMonster(vf2d pos,MonsterData&data,bool upperLevel=false,bool isBossSpawn=false); //Queues a monster for spawning on the next frame.
|
|
void DrawPie(vf2d center,float radius,float degreesCut,Pixel col);
|
|
void DrawSquarePie(vf2d center,float radius,float degreesCut,Pixel col);
|
|
void RenderCooldowns();
|
|
void InitializeDefaultKeybinds();
|
|
void SetBossNameDisplay(std::string name,float time=5);
|
|
bool InBossEncounter();
|
|
void StartBossEncounter();
|
|
void DisplayBossEncounterInfo();
|
|
void BossDamageDealt(int damage);
|
|
void ReduceBossEncounterMobCount();
|
|
const uint8_t BossEncounterMobCount()const;
|
|
void InitializeGraphics();
|
|
void RenderVersionInfo();
|
|
const Map&GetCurrentMap()const;
|
|
const MapTag&GetCurrentMapData()const;
|
|
const MapName&GetCurrentMapName()const;
|
|
const std::string_view GetCurrentMapDisplayName()const;
|
|
int GetCurrentChapter();
|
|
void SetChapter(int chapter);
|
|
const std::weak_ptr<Item>GetLoadoutItem(int slot);
|
|
void SetLoadoutItem(int slot,std::string itemName);
|
|
int GetLoadoutSize()const;
|
|
void RestockLoadoutItems();
|
|
//Returns true if the item can be used (we have >0 of it)
|
|
bool UseLoadoutItem(int slot);
|
|
//Blanks out this loadout item.
|
|
void ClearLoadoutItem(int slot);
|
|
void RenderFadeout();
|
|
bool GamePaused();
|
|
void EndGame();
|
|
void UpdateDiscordStatus(std::string levelName,std::string className);
|
|
void InitializePlayerLevelCap();
|
|
void ResetGame(bool changeToMainMenu=true);
|
|
void OnRequestCompleted(const std::string_view receivedData)const override;
|
|
void DisableFadeIn(const bool disable);
|
|
//vi2d provides a tile in world coords.
|
|
void SetWorldColorFunc(std::function<Pixel(vi2d)>func);
|
|
void SetWorldColor(Pixel worldCol);
|
|
const Pixel&GetWorldColor()const;
|
|
//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);
|
|
//Returns the last time the mouse was moved or interacted with.
|
|
const float LastMouseMovement()const;
|
|
const bool GameInitialized()const;
|
|
rcode LoadResource(Renderable&renderable,std::string_view imgPath,bool filter=false,bool clamp=true);
|
|
void UpdateMonsters();
|
|
void ActivateActionSetForAllControllers(InputActionSetHandle_t actionSetHandle);
|
|
const float GetEncounterDuration()const;
|
|
void ShowDamageVignetteOverlay();
|
|
void GlobalGameUpdates();
|
|
const bool QuitRequested()const;
|
|
void SetQuitAllowed(bool quittingAllowed); //Locks the game from quitting during sensitive operations such as file saving/loading.
|
|
const bool PreviousStageCompleted()const;
|
|
void SetCompletedStageFlag();
|
|
void ResetCompletedStageFlag();
|
|
|
|
struct TileGroupData{
|
|
vi2d tilePos;
|
|
int layer;
|
|
bool operator<(const TileGroupData&rhs)const{
|
|
return layer<rhs.layer||(layer==rhs.layer&&tilePos<rhs.tilePos);
|
|
}
|
|
};
|
|
}; |