|
|
|
#ifndef CUTSCENE_H
|
|
|
|
#define CUTSCENE_H
|
|
|
|
#include "pixelGameEngine.h"
|
|
|
|
#include "defines.h"
|
|
|
|
#include "flags.h"
|
|
|
|
#include "object.h"
|
|
|
|
|
|
|
|
#define CAMERA_MOVESPD 5
|
|
|
|
#define BATTLE_CAMERA_MOVESPD 2.5
|
|
|
|
|
|
|
|
using namespace olc;
|
|
|
|
|
|
|
|
namespace CutsceneName{
|
|
|
|
enum Cutscene{
|
|
|
|
TEST_CUTSCENE,
|
|
|
|
TRANSFER_MAP_CUTSCENE,
|
|
|
|
LOAD_FILE_CUTSCENE,
|
|
|
|
INTRO_CUTSCENE,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
enum class ActionType{
|
|
|
|
NONE,
|
|
|
|
PAN_CAMERA,
|
|
|
|
CREATE_OBJECTS,
|
|
|
|
CLEANUP,
|
|
|
|
SET_FLAG_WHEN_CUTSCENE_ENDS,
|
|
|
|
FADE,
|
|
|
|
DIALOG,
|
|
|
|
MOVE_CUTSCENE_OBJ,
|
|
|
|
PAN_CAMERA_ASYNC,
|
|
|
|
FADE_ASYNC,
|
|
|
|
DIALOG_ASYNC,
|
|
|
|
MOVE_CUTSCENE_OBJ_ASYNC,
|
|
|
|
MODIFY_OBJECT,
|
|
|
|
LOAD_MAP,
|
|
|
|
MOVE_PLAYER_OBJS,
|
|
|
|
LOAD_FILE,
|
|
|
|
SET_FLAG,
|
|
|
|
SET_CUTSCENE_DISPLAY_TEXT,
|
|
|
|
};
|
|
|
|
|
|
|
|
class CutsceneAction{
|
|
|
|
bool queued=false; //Set to true when added to action asynchronous queue.
|
|
|
|
public:
|
|
|
|
virtual ActionType GetActionType()=0;
|
|
|
|
bool InQueue() {
|
|
|
|
return queued;
|
|
|
|
}
|
|
|
|
void SetQueued(bool queued=true) {
|
|
|
|
this->queued=queued;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class Cleanup:public CutsceneAction{
|
|
|
|
public:
|
|
|
|
ActionType GetActionType() override{return ActionType::CLEANUP;}
|
|
|
|
};
|
|
|
|
|
|
|
|
class Object;
|
|
|
|
class Animation;
|
|
|
|
class Map;
|
|
|
|
|
|
|
|
class CreateObjects:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
std::vector<Object*>objs;
|
|
|
|
public:
|
|
|
|
template <class T>
|
|
|
|
CreateObjects(std::initializer_list<T> objs) {
|
|
|
|
for( auto elem : objs )
|
|
|
|
{
|
|
|
|
this->objs.push_back(elem);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ActionType GetActionType() override{return ActionType::CREATE_OBJECTS;}
|
|
|
|
std::vector<Object*> GetObjects() {
|
|
|
|
return objs;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
class PanCamera:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
vd2d targetPos;
|
|
|
|
PriorityDirection dir;
|
|
|
|
double cameraSpd;
|
|
|
|
public:
|
|
|
|
PanCamera(vd2d targetPos,PriorityDirection dir,double cameraSpd=CAMERA_MOVESPD) {
|
|
|
|
this->targetPos=targetPos;
|
|
|
|
this->dir=dir;
|
|
|
|
this->cameraSpd=cameraSpd;
|
|
|
|
}
|
|
|
|
ActionType GetActionType() override{return ActionType::PAN_CAMERA;}
|
|
|
|
vd2d GetCameraTargetPos() {
|
|
|
|
return targetPos;
|
|
|
|
}
|
|
|
|
PriorityDirection GetPriorityDirection() {
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
double GetCameraSpeed() {
|
|
|
|
return cameraSpd;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class PanCameraAsync:public PanCamera{
|
|
|
|
public:
|
|
|
|
PanCameraAsync(vd2d targetPos,PriorityDirection dir,double cameraSpd=CAMERA_MOVESPD)
|
|
|
|
:PanCamera(targetPos,dir,cameraSpd){}
|
|
|
|
ActionType GetActionType() override{return ActionType::PAN_CAMERA_ASYNC;}
|
|
|
|
};
|
|
|
|
|
|
|
|
class MoveCutsceneObject:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
int objID;
|
|
|
|
vd2d targetPos;
|
|
|
|
double moveSpd;
|
|
|
|
PriorityDirection dir;
|
|
|
|
public:
|
|
|
|
MoveCutsceneObject(int objID,vd2d targetPos,double moveSpd=CAMERA_MOVESPD,PriorityDirection dir=BOTH) {
|
|
|
|
this->objID=objID;
|
|
|
|
this->targetPos=targetPos;
|
|
|
|
this->moveSpd=moveSpd;
|
|
|
|
this->dir=dir;
|
|
|
|
}
|
|
|
|
ActionType GetActionType() override{return ActionType::MOVE_CUTSCENE_OBJ;}
|
|
|
|
//Based on how they were created in the cutscene, an object ID starting from 0 indicating which object you want to manipulate.
|
|
|
|
int GetObjectID() {
|
|
|
|
return objID;
|
|
|
|
}
|
|
|
|
double GetMoveSpd() {
|
|
|
|
return moveSpd;
|
|
|
|
}
|
|
|
|
vd2d GetTargetPos() {
|
|
|
|
return targetPos;
|
|
|
|
}
|
|
|
|
PriorityDirection GetMovement() {
|
|
|
|
return dir;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class MoveCutsceneObjectAsync:public MoveCutsceneObject{
|
|
|
|
public:
|
|
|
|
MoveCutsceneObjectAsync(int objID,vd2d targetPos,double moveSpd=CAMERA_MOVESPD,PriorityDirection dir=BOTH)
|
|
|
|
:MoveCutsceneObject(objID,targetPos,moveSpd){}
|
|
|
|
ActionType GetActionType() override{return ActionType::MOVE_CUTSCENE_OBJ_ASYNC;}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SetFlagWhenCutsceneEnds:public CutsceneAction{
|
|
|
|
private:
|
|
|
|
Flag flag;
|
|
|
|
bool val;
|
|
|
|
public:
|
|
|
|
SetFlagWhenCutsceneEnds(Flag flag,bool val=true) {
|
|
|
|
this->flag=flag;
|
|
|
|
this->val=val;
|
|
|
|
}
|
|
|
|
ActionType GetActionType() override{return ActionType::SET_FLAG_WHEN_CUTSCENE_ENDS;}
|
|
|
|
Flag GetCutsceneEndingFlag() {
|
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
bool GetCutsceneEndingVal() {
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class Fade:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
bool fadeIn=true; //If false, it fades out instead.
|
|
|
|
double fadeSpd=0;
|
|
|
|
public:
|
|
|
|
//If false, it fades out instead.
|
|
|
|
Fade(bool fadeIn=false,double fadeSpd=4) {
|
|
|
|
this->fadeIn=fadeIn;
|
|
|
|
this->fadeSpd=fadeSpd;
|
|
|
|
}
|
|
|
|
ActionType GetActionType() override{return ActionType::FADE;}
|
|
|
|
//If false, then it means we need to fade out instead.
|
|
|
|
bool FadeIn() {
|
|
|
|
return fadeIn;
|
|
|
|
}
|
|
|
|
double GetFadeSpd() {
|
|
|
|
return fadeSpd;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class FadeAsync:public Fade{
|
|
|
|
public:
|
|
|
|
//If false, it fades out instead.
|
|
|
|
FadeAsync(bool fadeIn=false,double fadeSpd=4)
|
|
|
|
:Fade(fadeIn,fadeSpd){}
|
|
|
|
ActionType GetActionType() override{return ActionType::FADE_ASYNC;}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DialogBox:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
std::string message;
|
|
|
|
bool messageBoxVisible=false;
|
|
|
|
public:
|
|
|
|
//If false, it fades out instead.
|
|
|
|
DialogBox(std::string message) {
|
|
|
|
this->message=message;
|
|
|
|
}
|
|
|
|
ActionType GetActionType() override{return ActionType::DIALOG;}
|
|
|
|
//If false, then it means we need to fade out instead.
|
|
|
|
std::string GetMessage() {
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
void SetMessageBoxVisible() {
|
|
|
|
this->messageBoxVisible=true;
|
|
|
|
}
|
|
|
|
bool MessageHasBeenShown() {
|
|
|
|
return messageBoxVisible;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class DialogBoxAsync:public DialogBox{
|
|
|
|
public:
|
|
|
|
//If false, it fades out instead.
|
|
|
|
DialogBoxAsync(std::string message)
|
|
|
|
:DialogBox(message){}
|
|
|
|
ActionType GetActionType() override{return ActionType::DIALOG_ASYNC;}
|
|
|
|
};
|
|
|
|
|
|
|
|
class ModifyObject:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
int objID;
|
|
|
|
vd2d scale;
|
|
|
|
Pixel col;
|
|
|
|
Animation*spr;
|
|
|
|
int animationFrame; //Defaults to -1, meaning don't touch the animation frame at all.
|
|
|
|
int animationSpd; //How many frames to wait between each animation frame. Setting to 0 pauses the animation.
|
|
|
|
public:
|
|
|
|
ModifyObject(int objID,Animation*spr,vd2d scale={1,1},Pixel col=WHITE,int animationFrame=-1,int animationSpd=12) {
|
|
|
|
this->objID=objID;
|
|
|
|
this->scale=scale;
|
|
|
|
this->col=col;
|
|
|
|
this->spr=spr;
|
|
|
|
this->animationFrame=animationFrame;
|
|
|
|
this->animationSpd=animationSpd;
|
|
|
|
}
|
|
|
|
ActionType GetActionType() override{return ActionType::MODIFY_OBJECT;}
|
|
|
|
int GetCutsceneObjID(){
|
|
|
|
return objID;
|
|
|
|
}
|
|
|
|
vd2d GetObjScale() {
|
|
|
|
return scale;
|
|
|
|
}
|
|
|
|
Pixel GetObjCol() {
|
|
|
|
return col;
|
|
|
|
}
|
|
|
|
Animation*GetObjSpr() {
|
|
|
|
return spr;
|
|
|
|
}
|
|
|
|
//Defaults to -1, meaning don't touch the animation frame at all.
|
|
|
|
int GetFrameIndex() {
|
|
|
|
return animationFrame;
|
|
|
|
}
|
|
|
|
//How many frames to wait between each animation frame. Setting to 0 pauses the animation.
|
|
|
|
int GetAnimationSpeed() {
|
|
|
|
return animationSpd;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class LoadMap:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
Map*map;
|
|
|
|
public:
|
|
|
|
LoadMap(Map*newMap)
|
|
|
|
:map(newMap) {}
|
|
|
|
ActionType GetActionType() override{return ActionType::LOAD_MAP;}
|
|
|
|
Map*GetTargetMap(){
|
|
|
|
return map;
|
|
|
|
}
|
|
|
|
void SetTargetMap(Map*map){
|
|
|
|
this->map=map;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class MovePlayerObjects:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
vd2d newPos;
|
|
|
|
public:
|
|
|
|
MovePlayerObjects(vd2d newPos)
|
|
|
|
:newPos(newPos) {}
|
|
|
|
ActionType GetActionType() override{return ActionType::MOVE_PLAYER_OBJS;}
|
|
|
|
vd2d GetTargetPos(){
|
|
|
|
return newPos;
|
|
|
|
}
|
|
|
|
void SetTargetPos(vd2d newPos){
|
|
|
|
this->newPos=newPos;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class LoadGame:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
int saveslot;
|
|
|
|
public:
|
|
|
|
LoadGame(int saveslot)
|
|
|
|
:saveslot(saveslot) {}
|
|
|
|
ActionType GetActionType() override{return ActionType::LOAD_FILE;}
|
|
|
|
int GetSaveFileSlot(){
|
|
|
|
return saveslot;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SetFlag:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
Flag flag;
|
|
|
|
bool value;
|
|
|
|
public:
|
|
|
|
SetFlag(Flag flag,bool value)
|
|
|
|
:flag(flag),value(value) {}
|
|
|
|
ActionType GetActionType() override{return ActionType::SET_FLAG;}
|
|
|
|
Flag GetFlag(){
|
|
|
|
return flag;
|
|
|
|
}
|
|
|
|
bool GetValue(){
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class SetCutsceneDisplayText:public CutsceneAction{
|
|
|
|
protected:
|
|
|
|
std::string text;
|
|
|
|
int delay;
|
|
|
|
public:
|
|
|
|
//delay in frames
|
|
|
|
SetCutsceneDisplayText(std::string text,int delay)
|
|
|
|
:text(text),delay(delay) {}
|
|
|
|
ActionType GetActionType() override{return ActionType::SET_CUTSCENE_DISPLAY_TEXT;}
|
|
|
|
std::string GetCutsceneText(){
|
|
|
|
return text;
|
|
|
|
}
|
|
|
|
int GetDelay() {
|
|
|
|
return delay;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
To use this class, specify multiple actions back-to-back, filling their appropriate arguments.
|
|
|
|
|
|
|
|
In responsive events, poll what CurrentAction() is, and if it's suitable, then use LockAction()
|
|
|
|
to lock the event and perform whatever actions are required. When the cutscene action is complete,
|
|
|
|
you can advance the action using AdvanceAction().
|
|
|
|
*/
|
|
|
|
class Cutscene{
|
|
|
|
private:
|
|
|
|
int actionMarker=0;
|
|
|
|
bool actionIsActive=false;
|
|
|
|
std::vector<Object*>cutsceneObjs;
|
|
|
|
Flag storedFlag=Flag::NONE;
|
|
|
|
bool storedVal=true;
|
|
|
|
protected:
|
|
|
|
std::vector<CutsceneAction*> actions;
|
|
|
|
public:
|
|
|
|
template <class T>
|
|
|
|
Cutscene(std::initializer_list<T> actions) {
|
|
|
|
AddAction(actions);
|
|
|
|
};
|
|
|
|
template <class T>
|
|
|
|
void AddAction(std::initializer_list<T> actions )
|
|
|
|
{
|
|
|
|
for( auto elem : actions )
|
|
|
|
{
|
|
|
|
this->actions.push_back(elem);
|
|
|
|
}
|
|
|
|
this->actions.push_back(new Cleanup());
|
|
|
|
}
|
|
|
|
CutsceneAction*GetAction(){
|
|
|
|
return actions[actionMarker];
|
|
|
|
}
|
|
|
|
ActionType CurrentAction(){
|
|
|
|
if (!actionIsActive&&actionMarker<actions.size()) {
|
|
|
|
return actions[actionMarker]->GetActionType();
|
|
|
|
} else {
|
|
|
|
return ActionType::NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void LockAction() {
|
|
|
|
actionIsActive=true;
|
|
|
|
}
|
|
|
|
ActionType PeekNextAction(){
|
|
|
|
if (actionMarker+1<actions.size()) {
|
|
|
|
return actions[actionMarker+1]->GetActionType();
|
|
|
|
} else {
|
|
|
|
return ActionType::NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void AdvanceAction(){
|
|
|
|
actionIsActive=false;
|
|
|
|
actionMarker++;
|
|
|
|
}
|
|
|
|
void ResetCutscene(){
|
|
|
|
actionMarker=0;
|
|
|
|
actionIsActive=false;
|
|
|
|
for (auto&action:actions) {
|
|
|
|
action->SetQueued(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Object*AddCutsceneObject(Object*obj) {
|
|
|
|
this->cutsceneObjs.push_back(obj);
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
std::vector<Object*> GetCutsceneObjects() {
|
|
|
|
return cutsceneObjs;
|
|
|
|
}
|
|
|
|
//Does things like reset cutscene flags and removing objects.
|
|
|
|
//
|
|
|
|
//MAKE SURE TO DELETE ALL OBJECTS IN THE OBJECTS WORLD ARRAY BEFORE CALLING THIS!
|
|
|
|
//THIS FUNCTION WILL DELETE THE POINTERS FOR YOU!
|
|
|
|
void CleanupCutscene() {
|
|
|
|
cutsceneObjs.clear();
|
|
|
|
}
|
|
|
|
void SetupEndingCutsceneFlag(Flag flag,bool val=true) {
|
|
|
|
storedFlag=flag;
|
|
|
|
storedVal=val;
|
|
|
|
}
|
|
|
|
Flag GetEndingCutsceneFlag() {
|
|
|
|
return storedFlag;
|
|
|
|
}
|
|
|
|
bool GetEndingCutsceneVal() {
|
|
|
|
return storedVal;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class MapTransitionCutscene:public Cutscene{
|
|
|
|
public:
|
|
|
|
MapTransitionCutscene()
|
|
|
|
:Cutscene({
|
|
|
|
액션 Fade(),
|
|
|
|
액션 LoadMap(nullptr),
|
|
|
|
액션 MovePlayerObjects({0,0}),
|
|
|
|
액션 Fade(true),
|
|
|
|
}){}
|
|
|
|
std::vector<CutsceneAction*>GetActions(){
|
|
|
|
return actions;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
extern std::array<NPC_Obj*,4> PARTY_MEMBER_OBJ;
|
|
|
|
|
|
|
|
class LoadFileCutscene:public Cutscene{
|
|
|
|
public:
|
|
|
|
LoadFileCutscene()
|
|
|
|
:Cutscene({
|
|
|
|
액션 Fade(),
|
|
|
|
액션 LoadGame(0),
|
|
|
|
액션 Fade(true),
|
|
|
|
}){}
|
|
|
|
std::vector<CutsceneAction*>GetActions(){
|
|
|
|
return actions;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
#endif
|