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.
SeasonI/object.h

246 lines
7.8 KiB

#ifndef OBJECT_H
#define OBJECT_H
#include "pixelGameEngine.h"
#include "flags.h"
#include "animation.h"
#include "defines.h"
#include "layers.h"
#include "item.h"
#include "states.h"
#include "SeasonI.h"
using namespace olc;
struct Interaction{
std::vector<std::string> messages={};
Item*item=nullptr;
Flag flag=Flag::NONE;
};
class Object{
private:
vd2d scale={1,1};
vd2d pos;
public:
int id;
Animation*spr;
int frameIndex=0;
int frameCount=0;
int animationSpd=12; //How many frames to wait between each frame. Setting to 0 pauses the animation.
std::string name;
Pixel color=WHITE;
vd2d originPoint={0,0};
bool drawn=false;
Flag disableFlag=Flag::NONE;
Flag enableFlag=Flag::NONE;
int objArrElement; //Which element in the object array this object is located in. For sorting purposes.
bool temp=false; //If set to true, it's marked for deletion after cutscene handling.
bool enc=false; //If set to true, it's not included in the main list of entities for map saving because it's from an encounter.
bool dead=false; //If set to true, this object was properly part of an Entity and got declared as dead.
int blinkFrames=0; //Frame count of how much time is left for the image to be blinking. Used when enemies take damage.
//animationSpd is how long to wait before switching frames.
bool highlighted=false; //Whether or not this object has been declared as highlighted by a target range selector.
bool Collision(vd2d pos) {
GAME->SetDrawTarget(layer::COLLISION);
Pixel collisionData = GAME->GetDrawTarget()->GetPixel((int)pos.x-cameraPos.x,(int)pos.y-cameraPos.y);
return collisionData!=MAGENTA;
}
//A grid version of the constructor. used ONLY for battle setups.
Object(int id,std::string name,int gridx,int gridy,Animation*spr,vd2d scale={1,1},Pixel color=WHITE,int animationSpd=1,bool temp=false)
:Object(id,name,{gridx*32-(spr->width*0.5)*(scale.x-1),gridy*32-(spr->spr->sprite->height-4)*(scale.y-1)},spr,scale,color,animationSpd,temp) {}
Object(int id,std::string name,vd2d pos,Animation*spr,vd2d scale={1,1},Pixel color=WHITE,int animationSpd=1,bool temp=false) {
this->spr=spr;
this->pos=pos;
this->id=id;
this->name=name;
this->color=color;
this->animationSpd=animationSpd;
SetScale(scale);
this->temp=temp;
}
virtual Object* CreateType(int id,std::string name,vd2d pos,Animation*spr,vd2d scale={1,1},Pixel color=WHITE,int animationSpd=1,bool temp=false)=0;
//When the player tries to interact with this object.
virtual Interaction Interact()=0;
virtual void ChoiceMade(int choice)=0;
virtual void DialogClosed()=0;
virtual void ShoppingCompleted()=0;
void SetScale(vd2d scale) {
this->scale=scale;
if (spr!=nullptr) {
this->originPoint={spr->width/2*scale.x,(spr->spr->sprite->height-4)*scale.y};
}
}
vd2d GetScale() {
return scale;
}
vd2d GetPos() {
return pos;
}
void Move(vd2d move);
void SetPos(vd2d pos) {
Move(pos-this->pos);
}
vd2d GetPosWithOrigin() {
return GetPos()+originPoint;
}
bool SmoothMove(vd2d move) {
const int wiggleRoom=5;
vd2d originPos = {pos.x+originPoint.x,pos.y-1+originPoint.y};
if (!Collision(originPos+move)) {
Move(move);
return true;
} else
if (move.x!=0&&!Collision({originPos.x+move.x,originPos.y})) {
Move({move.x,0});
return true;
} else
if (move.y!=0&&!Collision({originPos.x,originPos.y+move.y})) {
Move({0,move.y});
return true;
}
else
if (move.x>0) {
for (int i=0;i<wiggleRoom;i++) { //Search Up.
if (!Collision({originPos.x+move.x,originPos.y-i})) {
//There is potentially to move up-right here, so we will do so.
Move({0,-1});
originPos.y+=-1;
return true;
}
}
for (int i=0;i<wiggleRoom;i++) { //Search Down.
if (!Collision({originPos.x+move.x,originPos.y+i})) {
//There is potentially to move down-right here, so we will do so.
Move({0,1});
return true;
}
if (!Collision({originPos.x+move.x,originPos.y-i})) {
//There is potentially to move up-left here, so we will do so.
Move({0,-1});
return true;
}
}
for (int i=0;i<wiggleRoom;i++) { //Search Down.
if (!Collision({originPos.x+move.x,originPos.y+i})) {
//There is potentially to move down-left here, so we will do so.
Move({0,1});
return true;
}
}
}
if (move.y>0) {
for (int i=0;i<wiggleRoom;i++) { //Search Left.
if (!Collision({originPos.x-i,originPos.y+move.y})) {
//There is potentially to move down-left here, so we will do so.
Move({-1,0});
return true;
}
}
for (int i=0;i<wiggleRoom;i++) { //Search Right.
if (!Collision({originPos.x+i,originPos.y+move.y})) {
//There is potentially to move down-right here, so we will do so.
Move({1,0});
return true;
}
}
} else
if (move.y<0) {
for (int i=0;i<wiggleRoom;i++) { //Search Left.
if (!Collision({originPos.x-i,originPos.y+move.y})) {
//There is potentially to move up-left here, so we will do so.
Move({-1,0});
return true;
}
}
for (int i=0;i<wiggleRoom;i++) { //Search Right.
if (!Collision({originPos.x+i,originPos.y+move.y})) {
//There is potentially to move up-right here, so we will do so.
Move({1,0});
return true;
}
}
}
return false;
}
};
#define DynamicObject(objName) public:\
objName(int id,std::string name,int gridx,int gridy,Animation*spr,vd2d scale={1,1},Pixel color=WHITE,int animationSpd=1,bool temp=false)\
:Object(id,name,gridx,gridy,spr,scale,color,animationSpd,temp){};\
objName(int id,std::string name,vd2d pos,Animation*spr,vd2d scale={1,1},Pixel color=WHITE,int animationSpd=1,bool temp=false)\
:Object(id,name,pos,spr,scale,color,animationSpd,temp){};\
Object* CreateType(int id,std::string name,vd2d pos,Animation*spr,vd2d scale={1,1},Pixel color=WHITE,int animationSpd=1,bool temp=false)override{\
return new objName(id,name,pos,spr,scale,color,animationSpd,temp);\
}
class Standard_Obj : public Object{
DynamicObject(Standard_Obj)
Interaction Interact()override{return {};}
void DialogClosed()override{};
void ChoiceMade(int choice)override{};
void ShoppingCompleted()override{};
};
class TrashCan_Obj : public Object{
DynamicObject(TrashCan_Obj)
Interaction Interact()override{
frameIndex=1;
return {{"You dig around the trash can.","Nope! Just looks like plain ol' trash."}};}
void DialogClosed()override{};
void ChoiceMade(int choice)override{};
void ShoppingCompleted()override{};
};
extern int MESSAGE_BOX_DIALOG_ANSWER;
extern bool GAME_FLAGS[128];
extern int GAME_STATE;
extern void SetupShop(Object*shopkeeper,std::vector<std::pair<Item*,int>> shopItems);
extern std::map<ItemName,Item*>ITEMLIST;
extern void DisplayMessageBox(std::string targetT);
class Shopkeeper_Obj : public Object{
DynamicObject(Shopkeeper_Obj)
std::vector<std::pair<Item*,int>> itemList;
std::string welcomeMessage="Welcome! Please choose an option: [BUY,SELL,FDSAJIVDSAJ]\
>0:Please take a look through our wares.\
>1:What would you like to sell?\
>2:Are you okay?<";
Interaction Interact()override{
if (GAME_FLAGS[(int)Flag::SHOPKEER_BRANCH1]) {
GAME_FLAGS[(int)Flag::SHOPKEER_BRANCH1]=false;
switch (MESSAGE_BOX_DIALOG_ANSWER) {
case 2:{
return {{"No! Stay away! [Okay,Ignore]\
>0:Yeah I thought so.\
>1:...<"}};
}break;
}
} else {
return {{welcomeMessage},flag:Flag::SHOPKEER_BRANCH1};
}
}
void ChoiceMade(int choice)override{
if (GAME_FLAGS[(int)Flag::SHOPKEER_BRANCH1]) {
if (choice!=2) {
GAME_FLAGS[(int)Flag::SHOPKEER_BRANCH1]=false;
}
}
}
void DialogClosed()override{
GAME_STATE = GameState::SHOPKEEPER_MENU;
SetupShop(
this,
{
{ITEMLIST[ItemName::EGG],8},
{ITEMLIST[ItemName::COOKIE],4},
{ITEMLIST[ItemName::PIZZA],36},
{ITEMLIST[ItemName::SOME_STUPIDLY_LONG_FEATHER],46},
}
);
}
void ShoppingCompleted()override{
DisplayMessageBox("Thanks for shopping with us! Have a great day.");
};
};
#endif