# 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