generated from sigonasr2/CPlusPlusProjectTemplate
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.
301 lines
10 KiB
301 lines
10 KiB
#ifndef ENTITY_H
|
|
#define ENTITY_H
|
|
|
|
#include "pixelGameEngine.h"
|
|
#include "item.h"
|
|
#include <cassert>
|
|
|
|
extern std::vector<Item*>PARTY_INVENTORY;
|
|
extern int INVENTORY_CONSUMABLE_OFFSET[4];
|
|
extern int ITEM_SELECTION_CURSOR;
|
|
extern int ITEM_SELECTION_OFFSET;
|
|
|
|
using namespace olc;
|
|
|
|
class Object;
|
|
|
|
struct BoostData{
|
|
int atk=0,hp=0,pp=0,spd=0;
|
|
};
|
|
|
|
|
|
class Entity{
|
|
public:
|
|
struct pstats_t{
|
|
public:
|
|
int HP=0;
|
|
int maxHP=0;
|
|
int PP=0;
|
|
int maxPP=0;
|
|
int targetHP=0;
|
|
int targetPP=0;
|
|
int baseAtk=0;
|
|
int speed=0;
|
|
std::array<int,4>resistances={0,0,0,0};
|
|
int damageReduction=0; //A percentage of how much damage to reduce.
|
|
bool smart=false;
|
|
bool dumb=false;
|
|
};
|
|
struct stats_t{
|
|
private:
|
|
int HP=0;
|
|
public:
|
|
int maxHP=0;
|
|
private:
|
|
int PP=0;
|
|
public:
|
|
int maxPP=0;
|
|
private:
|
|
int targetHP=0;
|
|
int targetPP=0;
|
|
public:
|
|
int baseAtk=0;
|
|
int speed=0;
|
|
std::array<int,4>resistances={0,0,0,0};
|
|
int damageReduction=0; //A percentage of how much damage to reduce.
|
|
bool smart=false;
|
|
bool dumb=false;
|
|
stats_t(pstats_t stats) {
|
|
this->HP=stats.HP;
|
|
this->maxHP=stats.maxHP;
|
|
this->PP=stats.PP;
|
|
this->maxPP=stats.maxPP;
|
|
this->targetHP=stats.targetHP;
|
|
this->targetPP=stats.targetPP;
|
|
this->baseAtk=stats.baseAtk;
|
|
this->speed=stats.speed;
|
|
this->resistances=stats.resistances;
|
|
this->damageReduction=stats.damageReduction;
|
|
this->smart=stats.smart;
|
|
this->dumb=stats.dumb;
|
|
};
|
|
bool operator==(const stats_t&t)const{
|
|
return HP==t.HP&&
|
|
maxHP==t.maxHP&&
|
|
PP==t.PP&&
|
|
maxPP==t.maxPP&&
|
|
baseAtk==t.baseAtk&&
|
|
speed==t.speed&&
|
|
resistances==t.resistances&&
|
|
damageReduction==t.damageReduction&&
|
|
smart==t.smart&&
|
|
dumb==t.dumb;
|
|
}
|
|
//Get the HP that the rolling counter is moving towards.
|
|
int GetTargetHP(){
|
|
return targetHP;
|
|
}
|
|
//Gets the current actual health of the target.
|
|
int GetHP(){
|
|
return HP;
|
|
}
|
|
//Get the PP that the rolling counter is moving towards.
|
|
int GetTargetPP() {
|
|
return targetPP;
|
|
}
|
|
//Gets the current actual pp of the target.
|
|
int GetPP() {
|
|
return PP;
|
|
}
|
|
//Sets the rolling counter target to this health value.
|
|
void SetTargetHP(int hp) {
|
|
targetHP=hp;
|
|
}
|
|
//Sets the rolling counter target to this pp value.
|
|
void SetTargetPP(int pp) {
|
|
targetPP=pp;
|
|
}
|
|
//Subtracts from the rolling counter target from this health value.
|
|
void SubtractHP(int hp) {
|
|
targetHP-=hp;
|
|
}
|
|
//Adds to the rolling counter target from this health value.
|
|
void AddHP(int hp) {
|
|
targetHP=std::clamp(targetHP+hp,0,maxHP);
|
|
}
|
|
//Subtracts from the rolling counter target from this pp value.
|
|
void SubtractPP(int pp) {
|
|
targetPP=std::clamp(targetPP-pp,0,maxPP);
|
|
}
|
|
//Adds to the rolling counter target from this pp value.
|
|
void AddPP(int pp) {
|
|
targetPP=std::clamp(targetPP+pp,0,maxPP);
|
|
}
|
|
//THIS IS FOR SPECIAL USE CASES ONLY! Normally you want to touch the rolling counter amount instead using SetTargetHP()!
|
|
void _SetDirectHP(int hp) {
|
|
HP=hp;
|
|
}
|
|
//THIS IS FOR SPECIAL USE CASES ONLY! Normally you want to touch the rolling counter amount instead using SetTargetPP()!
|
|
void _SetDirectPP(int pp) {
|
|
PP=pp;
|
|
}
|
|
};
|
|
private:
|
|
pstats_t pstats;
|
|
int partyMemberID;
|
|
public:
|
|
stats_t stats;
|
|
int atb=0; //When this value reaches 1000, it's this entity's turn.
|
|
public:
|
|
Object* obj;
|
|
std::vector<Battle::Move*> moveSet;
|
|
std::map<Property,int> statusEffects;
|
|
int selectedTarget = NO_TARGET;
|
|
Battle::Move*selectedMove = nullptr; //The index of the selected move.
|
|
int channelTimeRemaining = 0; //The amount of channel time left until move can be performed.
|
|
vd2d channelPos = DEFAULT_CHANNELPOS; //Where our channel is happening.
|
|
std::vector<Item*> inventory; //Used mostly for enemy spoils.
|
|
int money=0; //Amount of money this entity will drop when defeated.
|
|
std::array<Item*,3> equipment = {nullptr,nullptr,nullptr}; //Equipment this character is using.
|
|
bool isPlayer=false; //Whether or not this is a player entity.
|
|
BoostData boosts = {0,0,0,0};
|
|
//Used for initializing players.
|
|
Entity(int partyMemberID,pstats_t stats,std::vector<Battle::Move*>moveSet,std::vector<Item*>items={},int money=0,std::array<Item*,3>equipment={})
|
|
:Entity(nullptr,stats,moveSet,items,money,equipment){
|
|
this->partyMemberID=partyMemberID;
|
|
isPlayer=true;
|
|
}
|
|
//Use this for initializing enemies as it lets you specify an object.
|
|
Entity(Object*obj,pstats_t stats,std::vector<Battle::Move*>moveSet,std::vector<Item*>items={},int money=0,std::array<Item*,3>equipment={})
|
|
:obj(obj),stats({HP:stats.HP,maxHP:stats.maxHP,PP:stats.PP,maxPP:stats.maxPP,targetHP:stats.targetHP,targetPP:stats.targetPP,baseAtk:stats.baseAtk,speed:stats.speed,resistances:stats.resistances,damageReduction:stats.damageReduction,smart:stats.smart,dumb:stats.dumb}),equipment(equipment),moveSet(moveSet),inventory(items),money(money){
|
|
for (int i=0;i<4;i++) {
|
|
this->stats.resistances[i]=stats.resistances[i];
|
|
}
|
|
this->stats.SetTargetHP(stats.HP);
|
|
this->stats.SetTargetPP(stats.PP);
|
|
}
|
|
//Get the HP that the rolling counter is moving towards.
|
|
int GetTargetHP() {
|
|
return stats.GetTargetHP();
|
|
}
|
|
//Gets the current actual health of the target.
|
|
int GetHP() {
|
|
return stats.GetHP();
|
|
}
|
|
//Get the PP that the rolling counter is moving towards.
|
|
int GetTargetPP() {
|
|
return stats.GetTargetPP();
|
|
}
|
|
//Gets the current actual pp of the target.
|
|
int GetPP() {
|
|
return stats.GetPP();
|
|
}
|
|
//Sets the rolling counter target to this health value.
|
|
void SetTargetHP(int hp) {
|
|
stats.SetTargetHP(hp);
|
|
}
|
|
//Sets the rolling counter target to this pp value.
|
|
void SetTargetPP(int pp) {
|
|
stats.SetTargetPP(pp);
|
|
}
|
|
//Subtracts from the rolling counter target from this health value.
|
|
void SubtractHP(int hp) {
|
|
stats.SubtractHP(hp);
|
|
}
|
|
//Adds to the rolling counter target from this health value.
|
|
void AddHP(int hp) {
|
|
stats.AddHP(hp);
|
|
}
|
|
//Subtracts from the rolling counter target from this pp value.
|
|
void SubtractPP(int pp) {
|
|
stats.SubtractPP(pp);
|
|
}
|
|
//Adds to the rolling counter target from this pp value.
|
|
void AddPP(int pp) {
|
|
stats.AddPP(pp);
|
|
}
|
|
//THIS IS FOR SPECIAL USE CASES ONLY! Normally you want to touch the rolling counter amount instead using SetTargetHP()!
|
|
void _SetDirectHP(int hp) {
|
|
stats._SetDirectHP(hp);
|
|
}
|
|
//THIS IS FOR SPECIAL USE CASES ONLY! Normally you want to touch the rolling counter amount instead using SetTargetPP()!
|
|
void _SetDirectPP(int pp) {
|
|
stats._SetDirectPP(pp);
|
|
}
|
|
|
|
friend std::ostream&operator<<(std::ostream &os,Entity&ent);
|
|
|
|
Property GetPrimaryStatusEffect() {
|
|
for (std::map<Property,int>::iterator it = statusEffects.begin();it!=statusEffects.end();++it) {
|
|
if (it->second!=0) {
|
|
return it->first;
|
|
}
|
|
}
|
|
return Property::NONE;
|
|
}
|
|
|
|
void RemoveItem(int index) {
|
|
int prevPartyInvenSize=PARTY_INVENTORY.size();
|
|
if (isPlayer) {
|
|
for (int i=0;i<4;i++) {
|
|
if (index<INVENTORY_CONSUMABLE_OFFSET[i]) {
|
|
INVENTORY_CONSUMABLE_OFFSET[i]--; //Items
|
|
}
|
|
}
|
|
PARTY_INVENTORY.erase(PARTY_INVENTORY.begin()+index);
|
|
} else {
|
|
inventory.erase(inventory.begin()+index);
|
|
}
|
|
if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()&&prevPartyInvenSize&1&&PARTY_INVENTORY.size()==prevPartyInvenSize-1) {
|
|
ITEM_SELECTION_OFFSET-=2;
|
|
}
|
|
ITEM_SELECTION_CURSOR=std::clamp(ITEM_SELECTION_CURSOR,0,(int)PARTY_INVENTORY.size()-1);
|
|
}
|
|
|
|
//If index is -1, the item is inserted at the end of the list. Otherwise it's going to overwrite a certain slot. Be certain you swap the item before doing this!
|
|
void RemoveEquip(EquipSlot::Equip slot,int index=-1) {
|
|
Item*CurrentEquip=equipment[slot];
|
|
if (CurrentEquip==nullptr) {
|
|
return;
|
|
}
|
|
if (isPlayer) {
|
|
if (index==-1) {
|
|
PARTY_INVENTORY.push_back(CurrentEquip);
|
|
} else {
|
|
PARTY_INVENTORY[index]=CurrentEquip;
|
|
}
|
|
equipment[slot]=nullptr;
|
|
} else {
|
|
if (index==-1) {
|
|
inventory.push_back(CurrentEquip);
|
|
} else {
|
|
inventory[index]=CurrentEquip;
|
|
}
|
|
equipment[slot]=nullptr;
|
|
}
|
|
}
|
|
|
|
//Will automatically swap items with current equipment so no need to call remove first.
|
|
void EquipItem(int index) {
|
|
int prevPartyInvenSize=PARTY_INVENTORY.size();
|
|
Item*equip=nullptr;
|
|
if (isPlayer) {
|
|
equip=PARTY_INVENTORY[index];
|
|
} else {
|
|
equip=inventory[index];
|
|
}
|
|
if (equip==nullptr) {
|
|
return;
|
|
}
|
|
if (equip->stats.equip==EquipSlot::NONE) {
|
|
printf("Cannot equip %s! Does not have a valid Equip slot!\n",equip->name.c_str());
|
|
return;
|
|
}
|
|
Item*CurrentEquip=equipment[equip->stats.equip];
|
|
if (CurrentEquip==nullptr) {
|
|
if (isPlayer) {
|
|
PARTY_INVENTORY.erase(PARTY_INVENTORY.begin()+index);
|
|
} else {
|
|
inventory.erase(inventory.begin()+index);
|
|
}
|
|
} else {
|
|
RemoveEquip(CurrentEquip->stats.equip,index);
|
|
}
|
|
equipment[equip->stats.equip]=equip;
|
|
if (ITEM_SELECTION_CURSOR>=PARTY_INVENTORY.size()&&prevPartyInvenSize&1&&PARTY_INVENTORY.size()==prevPartyInvenSize-1) {
|
|
ITEM_SELECTION_OFFSET-=2;
|
|
}
|
|
ITEM_SELECTION_CURSOR=std::clamp(ITEM_SELECTION_CURSOR,0,(int)PARTY_INVENTORY.size()-1);
|
|
}
|
|
};
|
|
#endif |