You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
860 lines
17 KiB
C++
860 lines
17 KiB
C++
#include "Entity.hpp"
|
|
#include "RLGame.hpp"
|
|
#include "utils.hpp"
|
|
//#include "Room.hpp"
|
|
//#include <iostream>
|
|
//#include <cmath>
|
|
|
|
Entity* Entity::m_pPlayer{};
|
|
|
|
Entity::Entity(const std::string& name, SPECIES type, Position position)
|
|
: m_Species{ SPECIES::UNDEFINED }
|
|
, m_Pos{ position }
|
|
, m_PreviousPos{ position }
|
|
, m_Dead{ false }
|
|
, m_UpperChar{ true }
|
|
, m_MaxHealth{ 100 }
|
|
, m_Health{ 100 }
|
|
, m_AttrStrength{}
|
|
, m_AttrIntellect{}
|
|
, m_AttrDeftness{}
|
|
, m_HugCounter{}
|
|
, m_Faction{ ENTITY_FACTION::NEUTRAL }
|
|
, m_pWeapon{}
|
|
, m_pArmor{}
|
|
, m_Inventory{}
|
|
, m_Name{ name }
|
|
{
|
|
SetSpecies(type);
|
|
}
|
|
|
|
Entity::~Entity()
|
|
{
|
|
m_Inventory.clear();
|
|
}
|
|
|
|
void Entity::Draw() const
|
|
{
|
|
terminal_color(GetColor());
|
|
terminal_put(m_Pos.x + G_OFFSET_X, m_Pos.y + G_OFFSET_Y, GetSymbol());
|
|
terminal_color(G_COL_WHITE);
|
|
}
|
|
|
|
void Entity::Update()
|
|
{
|
|
}
|
|
|
|
void Entity::Update(const std::vector<Entity*>& entities)
|
|
{
|
|
}
|
|
|
|
bool Entity::Fight(Entity& other)
|
|
{
|
|
if((&other == m_pPlayer && G_CH_BITS[G_CH_CODES::GOD]) || other.m_Dead || GetDistanceFrom(other) > 1)
|
|
return false;
|
|
|
|
if(utils::RandomBetween(0, (100 + other.m_AttrDeftness - m_AttrDeftness)) < 75) // I don't know how to make balanced dice rolls
|
|
{
|
|
//PRINT_STATUS(m_Name + " hits ");
|
|
int damage{ m_AttrStrength * 3 / 2 };
|
|
damage += utils::RandomBetween(-damage / 5 - 1, damage / 5 + 1);
|
|
if(m_pWeapon)
|
|
damage += utils::RandomBetween(m_pWeapon->weaponMinDamage, m_pWeapon->weaponMaxDamage);
|
|
|
|
if(other.m_pArmor)
|
|
damage -= other.m_pArmor->armorRating;
|
|
|
|
other.AddHealth(-damage);
|
|
if(!other.m_Dead)
|
|
{
|
|
if(m_pWeapon)
|
|
G_PRINT_STATUS(m_Name + " (" + std::to_string(m_Health) + ") hits " + other.m_Name + " (" + std::to_string(other.m_Health) + ") with " + m_pWeapon->itemName);
|
|
else
|
|
G_PRINT_STATUS(m_Name + " (" + std::to_string(m_Health) + ") hits " + other.m_Name + " (" + std::to_string(other.m_Health) + ')');
|
|
|
|
if(this == m_pPlayer)
|
|
{
|
|
switch(other.m_Faction)
|
|
{
|
|
case ENTITY_FACTION::NEUTRAL:
|
|
other.m_Faction = ENTITY_FACTION::EVIL;
|
|
break;
|
|
case ENTITY_FACTION::FRIENDLY:
|
|
other.m_Faction = ENTITY_FACTION::NEUTRAL;
|
|
break;
|
|
case ENTITY_FACTION::EVIL:
|
|
case ENTITY_FACTION::DEVOTED:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
G_PRINT_STATUS(m_Name + " misses");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool Entity::Hug(Entity& other)
|
|
{
|
|
if(&other != m_pPlayer)
|
|
{
|
|
G_PRINT_STATUS("You hug " + other.GetFullName());
|
|
}
|
|
else
|
|
{
|
|
G_PRINT_STATUS(GetFullName() + " hugs you");
|
|
}
|
|
|
|
if(other.m_Species != SPECIES::HUMAN)
|
|
{
|
|
++other.m_HugCounter;
|
|
other.AddHealth(utils::RandomBetweenSimple(2, 6));
|
|
if(&other != m_pPlayer && other.m_Faction == ENTITY_FACTION::NEUTRAL)
|
|
other.m_Faction = ENTITY_FACTION::FRIENDLY;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Entity::UseItem(unsigned int index)
|
|
{
|
|
if(m_Inventory.begin() == m_Inventory.end() || index >= m_Inventory.size())
|
|
return false;
|
|
|
|
Item* item{ m_Inventory[index] };
|
|
bool removeAfterUse{ false };
|
|
switch(item->itemType)
|
|
{
|
|
case ITEM_TYPE::DEFAULT:
|
|
{
|
|
// stuff I guess
|
|
G_PRINT_STATUS(m_Name + " used Item " + item->itemName);
|
|
removeAfterUse = false;
|
|
break;
|
|
}
|
|
case ITEM_TYPE::CONSUMABLE:
|
|
{
|
|
Consumable* consumable{ static_cast<Consumable*>(item) };
|
|
AddHealth(consumable->consumableHeal);
|
|
G_PRINT_STATUS(m_Name + " used Consumable " + consumable->itemName + " (" + std::to_string(consumable->consumableHeal) + " HP)");
|
|
removeAfterUse = true;
|
|
break;
|
|
}
|
|
case ITEM_TYPE::WEAPON:
|
|
{
|
|
Weapon* weapon{ static_cast<Weapon*>(item) };
|
|
if(m_pWeapon != nullptr) // add current weapon to inventory
|
|
AddItem(m_pWeapon);
|
|
m_pWeapon = weapon;
|
|
G_PRINT_STATUS(m_Name + " equipped Weapon " + weapon->itemName);
|
|
removeAfterUse = true;
|
|
break;
|
|
}
|
|
case ITEM_TYPE::ARMOR:
|
|
{
|
|
Armor* armor{ static_cast<Armor*>(item) };
|
|
if(m_pArmor != nullptr) // add current armor to inventory
|
|
AddItem(m_pArmor);
|
|
m_pArmor = armor;
|
|
G_PRINT_STATUS(m_Name + " equipped Armor " + armor->itemName);
|
|
removeAfterUse = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(removeAfterUse)
|
|
RemoveItem(index);
|
|
return true;
|
|
}
|
|
|
|
std::string Entity::PrintSheet() const
|
|
{
|
|
std::string sheet{};
|
|
sheet += GetFullName() + '\n'
|
|
+ "--------------------------------" + '\n'
|
|
+ "HEALTH:\t\t" + std::to_string(m_Health) + '\n'
|
|
+ "RACE:\t\t" + GetSpeciesString() + '\n'
|
|
+ "STRENGTH:\t" + std::to_string(m_AttrStrength) + '\n'
|
|
+ "INTELLECT:\t" + std::to_string(m_AttrIntellect) + '\n'
|
|
+ "DEFTNESS:\t" + std::to_string(m_AttrDeftness) + '\n'
|
|
+ "FACTION:\t" + std::to_string(short(m_Faction)) + '\n'
|
|
+ '\n';
|
|
return sheet;
|
|
}
|
|
|
|
/// GETTERS ///
|
|
|
|
const std::string& Entity::GetName() const
|
|
{
|
|
return m_Name;
|
|
}
|
|
|
|
const std::string Entity::GetFullName() const
|
|
{
|
|
return (m_Name + " the " + GetSpeciesString());
|
|
}
|
|
|
|
char Entity::GetSymbol() const
|
|
{
|
|
char speciesChar{ GetSpeciesString()[0] };
|
|
if(!m_UpperChar)
|
|
speciesChar = char(tolower(speciesChar));
|
|
|
|
return speciesChar;
|
|
}
|
|
|
|
SPECIES Entity::GetSpecies() const
|
|
{
|
|
return m_Species;
|
|
}
|
|
|
|
const char* Entity::GetSpeciesString() const
|
|
{
|
|
// TODO: load strings from language file?
|
|
// will allow translations and stuff
|
|
switch(m_Species)
|
|
{
|
|
case SPECIES::LIZARD:
|
|
return "Lizard";
|
|
break;
|
|
case SPECIES::KOBOLD:
|
|
return "Kobold";
|
|
break;
|
|
case SPECIES::HUMAN:
|
|
return "Human";
|
|
break;
|
|
case SPECIES::DRAGON:
|
|
return "Dragon";
|
|
break;
|
|
case SPECIES::WYVERN:
|
|
return "Wyvern";
|
|
break;
|
|
case SPECIES::HYDRA:
|
|
return "Hydra";
|
|
break;
|
|
case SPECIES::EEL:
|
|
return "Eel";
|
|
break;
|
|
case SPECIES::SNAKE:
|
|
return "Snake";
|
|
break;
|
|
case SPECIES::CRAB:
|
|
return "Crab";
|
|
break;
|
|
case SPECIES::UNDEFINED:
|
|
return "Nothing";
|
|
break;
|
|
default: // should be impossible
|
|
return "N/A";
|
|
break;
|
|
}
|
|
}
|
|
|
|
const Position& Entity::GetPosition() const
|
|
{
|
|
return m_Pos;
|
|
}
|
|
|
|
const int& Entity::GetHealth() const
|
|
{
|
|
return m_Health;
|
|
}
|
|
|
|
const int& Entity::GetMaxHealth() const
|
|
{
|
|
return m_MaxHealth;
|
|
}
|
|
|
|
const int& Entity::GetAttribute(ATTRIBUTES attribute) const
|
|
{
|
|
switch(attribute)
|
|
{
|
|
case ATTRIBUTES::STRENGTH:
|
|
return m_AttrStrength;
|
|
break;
|
|
case ATTRIBUTES::INTELLECT:
|
|
return m_AttrIntellect;
|
|
break;
|
|
case ATTRIBUTES::DEFTNESS:
|
|
return m_AttrDeftness;
|
|
break;
|
|
// default isn't really needed, ATTRIBUTES is an enum class so it should be safer than a simple enum
|
|
}
|
|
}
|
|
|
|
bool Entity::IsDead() const
|
|
{
|
|
return m_Dead;
|
|
}
|
|
|
|
int Entity::GetDistanceFrom(const Position& pos) const
|
|
{
|
|
/*int dx{ m_Pos.x - pos.x }, dy{ m_Pos.y - pos.y };
|
|
//return int(sqrt(dx * dx + dy * dy));
|
|
return (dx * dx + dy * dy) - 1;*/
|
|
return std::max(std::abs(m_Pos.x - pos.x), std::abs(m_Pos.y - pos.y));
|
|
}
|
|
|
|
int Entity::GetDistanceFrom(const Entity& other) const
|
|
{
|
|
return GetDistanceFrom(other.m_Pos);
|
|
}
|
|
|
|
std::vector<Entity*> Entity::GetClosest(const std::vector<Entity*>& entities, int range)
|
|
{
|
|
std::vector<Entity*> closestEntities{};
|
|
|
|
for(auto& entity : entities)
|
|
{
|
|
if(entity != this && !entity->m_Dead && GetDistanceFrom(*entity) <= range)
|
|
{
|
|
closestEntities.push_back(entity);
|
|
}
|
|
}
|
|
|
|
// uncomment to also include player
|
|
/*
|
|
if(m_pPlayer != this && !m_pPlayer->m_Dead && GetDistanceFrom(*m_pPlayer) <= range)
|
|
{
|
|
closestEntities.push_back(m_pPlayer);
|
|
}
|
|
*/
|
|
|
|
return closestEntities;
|
|
}
|
|
|
|
std::vector<Entity*> Entity::GetClosestWithState(const std::vector<Entity*>& entities, ENTITY_FACTION state, int range)
|
|
{
|
|
std::vector<Entity*> closestEntities{};
|
|
|
|
for(auto& entity : entities)
|
|
{
|
|
if(entity != this && !entity->m_Dead && GetDistanceFrom(*entity) <= range && entity->GetFaction() == state)
|
|
{
|
|
closestEntities.push_back(entity);
|
|
}
|
|
}
|
|
|
|
// uncomment to also include player
|
|
/*
|
|
if(m_pPlayer != this && !m_pPlayer->m_Dead && GetDistanceFrom(*m_pPlayer) <= range && m_pPlayer->GetFaction() == state)
|
|
{
|
|
closestEntities.push_back(m_pPlayer);
|
|
}
|
|
*/
|
|
|
|
return closestEntities;
|
|
}
|
|
|
|
color_t Entity::GetColor() const
|
|
{
|
|
/*switch(m_Species)
|
|
{
|
|
{
|
|
case SPECIES::LIZARD:
|
|
return m_ColorLizard;
|
|
break;
|
|
case SPECIES::KOBOLD:
|
|
return m_ColorKobold;
|
|
break;
|
|
case SPECIES::HUMAN:
|
|
return m_ColorHuman;
|
|
break;
|
|
case SPECIES::DRAGON:
|
|
return m_ColorDragon;
|
|
break;
|
|
case SPECIES::WYVERN:
|
|
return m_ColorWyvern;
|
|
break;
|
|
case SPECIES::HYDRA:
|
|
return m_ColorHydra;
|
|
break;
|
|
case SPECIES::EEL:
|
|
return m_ColorEel;
|
|
break;
|
|
case SPECIES::UNDEFINED:
|
|
default:
|
|
return G_BLACK;
|
|
break;
|
|
}
|
|
}*/
|
|
/*switch(m_Species)
|
|
{
|
|
case SPECIES::LIZARD:
|
|
return color_from_name("lizard");
|
|
break;
|
|
case SPECIES::KOBOLD:
|
|
return color_from_name("kobold");
|
|
break;
|
|
case SPECIES::HUMAN:
|
|
return color_from_name("human");
|
|
break;
|
|
case SPECIES::DRAGON:
|
|
return color_from_name("dragon");
|
|
break;
|
|
case SPECIES::WYVERN:
|
|
return color_from_name("wyvern");
|
|
break;
|
|
case SPECIES::HYDRA:
|
|
return color_from_name("hydra");
|
|
break;
|
|
case SPECIES::EEL:
|
|
return color_from_name("eel");
|
|
break;
|
|
case SPECIES::SNAKE:
|
|
return color_from_name("snake");
|
|
break;
|
|
case SPECIES::UNDEFINED:
|
|
default:
|
|
return G_WHITE;
|
|
break;
|
|
}*/
|
|
// better
|
|
if(m_Species == SPECIES::UNDEFINED)
|
|
return G_COL_WHITE;
|
|
|
|
std::string species{ GetSpeciesString() };
|
|
species[0] = char(tolower(species[0]));
|
|
return color_from_name(species.c_str());
|
|
}
|
|
|
|
int Entity::GetHug() const
|
|
{
|
|
return m_HugCounter;
|
|
}
|
|
|
|
ENTITY_FACTION Entity::GetFaction() const
|
|
{
|
|
return m_Faction;
|
|
}
|
|
|
|
Weapon* Entity::GetWeapon() const
|
|
{
|
|
return m_pWeapon;
|
|
}
|
|
|
|
Armor* Entity::GetArmor() const
|
|
{
|
|
return m_pArmor;
|
|
}
|
|
|
|
/// SETTERS ///
|
|
|
|
void Entity::SetName(const std::string& newName)
|
|
{
|
|
m_Name = newName;
|
|
m_Name.resize(newName.size());
|
|
}
|
|
|
|
void Entity::SetSpecies(const SPECIES& type)
|
|
{
|
|
m_Species = type;
|
|
int strengthBonus{};
|
|
int deftnessBonus{};
|
|
int intellectBonus{};
|
|
switch(type)
|
|
{
|
|
case SPECIES::LIZARD:
|
|
strengthBonus = 6;
|
|
deftnessBonus = 10;
|
|
intellectBonus = 5;
|
|
break;
|
|
case SPECIES::KOBOLD:
|
|
strengthBonus = -1;
|
|
deftnessBonus = 15;
|
|
intellectBonus = 3;
|
|
m_UpperChar = false;
|
|
break;
|
|
case SPECIES::HUMAN:
|
|
strengthBonus = 2;
|
|
deftnessBonus = 1;
|
|
intellectBonus = -2;
|
|
m_Faction = ENTITY_FACTION::EVIL;
|
|
m_UpperChar = false;
|
|
break;
|
|
case SPECIES::DRAGON:
|
|
strengthBonus = 15;
|
|
deftnessBonus = 5;
|
|
intellectBonus = 10;
|
|
break;
|
|
case SPECIES::WYVERN:
|
|
strengthBonus = 10;
|
|
deftnessBonus = 7;
|
|
intellectBonus = 10;
|
|
break;
|
|
case SPECIES::HYDRA:
|
|
strengthBonus = 20;
|
|
deftnessBonus = 3;
|
|
intellectBonus = 9;
|
|
break;
|
|
case SPECIES::EEL:
|
|
strengthBonus = 20;
|
|
deftnessBonus = 20;
|
|
intellectBonus = 20;
|
|
break;
|
|
case SPECIES::SNAKE:
|
|
strengthBonus = 5;
|
|
deftnessBonus = 20;
|
|
intellectBonus = 10;
|
|
break;
|
|
case SPECIES::CRAB:
|
|
strengthBonus = 6;
|
|
deftnessBonus = 3;
|
|
intellectBonus = 2;
|
|
m_UpperChar = false;
|
|
break;
|
|
case SPECIES::UNDEFINED:
|
|
default:
|
|
strengthBonus = -74; // -69 haha
|
|
deftnessBonus = strengthBonus;
|
|
intellectBonus = strengthBonus;
|
|
break;
|
|
}
|
|
m_AttrStrength = 5 + strengthBonus;
|
|
m_AttrDeftness = 5 + deftnessBonus;
|
|
m_AttrIntellect = 5 + intellectBonus;
|
|
}
|
|
|
|
void Entity::SetPosition(int x, int y)
|
|
{
|
|
if(x >= G_MAP_WIDTH - 1|| x < 0 || y >= G_MAP_HEIGHT - 1 || y < 0)
|
|
return;
|
|
|
|
m_Pos.x = x;
|
|
m_Pos.y = y;
|
|
}
|
|
|
|
void Entity::SetPosition(Position position)
|
|
{
|
|
SetPosition(position.x, position.y);
|
|
}
|
|
|
|
void Entity::SetHealth(int health)
|
|
{
|
|
m_Health = health;
|
|
}
|
|
|
|
void Entity::SetMaxHealth(int health)
|
|
{
|
|
m_MaxHealth = health;
|
|
}
|
|
|
|
void Entity::SetAttribute(ATTRIBUTES ATTRIBUTE, int value)
|
|
{
|
|
switch(ATTRIBUTE)
|
|
{
|
|
case ATTRIBUTES::STRENGTH:
|
|
m_AttrStrength = value;
|
|
break;
|
|
case ATTRIBUTES::INTELLECT:
|
|
m_AttrIntellect = value;
|
|
break;
|
|
case ATTRIBUTES::DEFTNESS:
|
|
m_AttrDeftness = value;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Entity::SetHug(int value)
|
|
{
|
|
m_HugCounter = value;
|
|
}
|
|
|
|
void Entity::SetFaction(ENTITY_FACTION state)
|
|
{
|
|
m_Faction = state;
|
|
}
|
|
|
|
/// CHANGERS ///
|
|
|
|
void Entity::AddHealth(int health)
|
|
{
|
|
if(m_Health + health > m_MaxHealth)
|
|
m_Health = m_MaxHealth;
|
|
else
|
|
m_Health += health;
|
|
|
|
if(m_Health <= 0)
|
|
{
|
|
m_Health = 0;
|
|
Die();
|
|
}
|
|
}
|
|
|
|
// Returns true if moved
|
|
bool Entity::Move(int x, int y)
|
|
{
|
|
// never move out of the window
|
|
if(m_Pos.x + x >= G_MAP_WIDTH || m_Pos.x + x < 0 || m_Pos.y + y >= G_MAP_HEIGHT || m_Pos.y + y < 0)
|
|
return false;
|
|
/*else if(utils::RandomBetweenSimple(0, 90 + m_AttrDeftness * 2) == 1)
|
|
{
|
|
PRINT_STATUS(GetFullName() + " stumbles.");
|
|
return false;
|
|
}*/
|
|
|
|
/*bool canMove{ true };
|
|
bool isFinished{ false };
|
|
do
|
|
{
|
|
for(size_t id{}; id < rooms.size(); ++id)
|
|
{
|
|
if(rooms[id].GetAtPosition(Position{ m_Pos.x + x, m_Pos.y + y }))
|
|
{
|
|
canMove = false;
|
|
break;
|
|
}
|
|
else
|
|
canMove = true;
|
|
}
|
|
isFinished = true;
|
|
}
|
|
while(!isFinished);
|
|
|
|
if(canMove)
|
|
{
|
|
m_PreviousPos = m_Pos;
|
|
m_Pos.x += x;
|
|
m_Pos.y += y;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}*/
|
|
// from previous version in switch statement
|
|
/*CURRENT_MAP.CheckTile(m_Pos.x + x, m_Pos.y + y)*/
|
|
//switch(GET_AT_POS(m_Pos.x + G_OFFSET_PREV_X + x, m_Pos.y + G_OFFSET_PREV_Y + y))
|
|
switch(G_CURRENT_MAP->CheckTile(m_Pos.x + x, m_Pos.y + y))
|
|
{
|
|
case G_MAPTILE_WALL:
|
|
case Map::WALLS_ARRAY[0]:
|
|
case Map::WALLS_ARRAY[1]:
|
|
case Map::WALLS_ARRAY[2]:
|
|
case Map::WALLS_ARRAY[3]:
|
|
case Map::WALLS_ARRAY[4]:
|
|
case Map::WALLS_ARRAY[5]:
|
|
return false;
|
|
break;
|
|
case '.':
|
|
case ',':
|
|
case '\'':
|
|
case '`':
|
|
case G_MAPTILE_DOOR: // +
|
|
case '@':
|
|
default:
|
|
m_PreviousPos = m_Pos;
|
|
m_Pos.x += x;
|
|
m_Pos.y += y;
|
|
return true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool Entity::Move(DIRECTION direction)
|
|
{
|
|
switch(direction)
|
|
{
|
|
case DIRECTION::NORTH:
|
|
return Move(0, -1);
|
|
break;
|
|
case DIRECTION::SOUTH:
|
|
return Move(0, 1);
|
|
break;
|
|
case DIRECTION::EAST:
|
|
return Move(1, 0);
|
|
break;
|
|
case DIRECTION::WEST:
|
|
return Move(-1, 0);
|
|
break;
|
|
case DIRECTION::NORTHEAST:
|
|
return Move(1, -1);
|
|
break;
|
|
case DIRECTION::SOUTHEAST:
|
|
return Move(1, 1);
|
|
break;
|
|
case DIRECTION::NORTHWEST:
|
|
return Move(-1, -1);
|
|
break;
|
|
case DIRECTION::SOUTHWEST:
|
|
return Move(-1, 1);
|
|
break;
|
|
default:
|
|
return false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Entity::MoveTo(Position position)
|
|
{
|
|
/*if(m_Dead) // shouldn't happen, maybe remove later
|
|
return;*/
|
|
|
|
///int currentDistance{ GetDistanceFrom(position) };
|
|
///if(currentDistance > 1)
|
|
///{
|
|
/*int newDistance{}; // old version
|
|
int randX{}, randY{};
|
|
bool moved{ true };
|
|
int counter{};
|
|
do
|
|
{
|
|
randX = rand() % 3 - 1;
|
|
randY = rand() % 3 - 1;
|
|
if(!Move(randX, randY))
|
|
moved = false;
|
|
newDistance = GetDistanceFrom(position);
|
|
if(currentDistance <= newDistance && moved)
|
|
{
|
|
Move(-randX, -randY);
|
|
--counter;
|
|
}
|
|
++counter;
|
|
} while(newDistance != currentDistance - 1 && counter == 0);*/
|
|
|
|
short x{};
|
|
short y{};
|
|
// x
|
|
if(m_Pos.x < position.x)
|
|
++x;
|
|
else if(m_Pos.x > position.x)
|
|
--x;
|
|
|
|
// y
|
|
if(m_Pos.y < position.y)
|
|
++y;
|
|
else if(m_Pos.y > position.y)
|
|
--y;
|
|
|
|
if(!Move(x, y))
|
|
{
|
|
//auto newPos{ utils::Pathfind(m_Pos, position.m_Pos).at(1) };
|
|
//auto newPos{ utils::BFS(m_Pos, position.m_Pos)[1] };
|
|
//Move(newPos.x - m_Pos.x, newPos.y - m_Pos.y);
|
|
|
|
// v1
|
|
bool randInt{ bool(utils::RandomBetweenSimple(0, 1)) };
|
|
if(!randInt)
|
|
{
|
|
if(x == 0)
|
|
{
|
|
if(utils::RandomBetweenSimple(0, 1))
|
|
++x;
|
|
else
|
|
--x;
|
|
}
|
|
|
|
if(m_Pos.x + x == m_PreviousPos.x || !Move(x, 0))
|
|
Move(-x, 0);
|
|
}
|
|
else
|
|
{
|
|
if(y == 0)
|
|
{
|
|
if(utils::RandomBetweenSimple(0, 1))
|
|
++y;
|
|
else
|
|
--y;
|
|
}
|
|
|
|
if(m_Pos.y + y == m_PreviousPos.y || !Move(0, y))
|
|
Move(0, -y);
|
|
}
|
|
|
|
// v2
|
|
/*if(m_Pos.x + x == m_PreviousPos.x || !Move(x, 0))
|
|
{
|
|
if(y == 0) ++y;
|
|
|
|
if(m_Pos.y - y == m_PreviousPos.y || !Move(0, -y))
|
|
{
|
|
if(m_Pos.y + y == m_PreviousPos.y || !Move(0, y))
|
|
Move(-x, 0);
|
|
}
|
|
}
|
|
else if(m_Pos.y + y == m_PreviousPos.y || !Move(0, y))
|
|
{
|
|
if(x == 0) ++x;
|
|
|
|
if(m_Pos.x + x == m_PreviousPos.x || !Move(0, x))
|
|
{
|
|
if(m_Pos.x - x == m_PreviousPos.x || !Move(-x, 0))
|
|
Move(0, -y);
|
|
}
|
|
}*/
|
|
}
|
|
}
|
|
|
|
void Entity::MoveTo(const Entity& other)
|
|
{
|
|
MoveTo(other.m_Pos);
|
|
}
|
|
|
|
void Entity::AddAttribute(ATTRIBUTES ATTRIBUTE, int amount)
|
|
{
|
|
switch(ATTRIBUTE)
|
|
{
|
|
case ATTRIBUTES::STRENGTH:
|
|
m_AttrStrength += amount;
|
|
break;
|
|
case ATTRIBUTES::INTELLECT:
|
|
m_AttrIntellect += amount;
|
|
break;
|
|
case ATTRIBUTES::DEFTNESS:
|
|
m_AttrDeftness += amount;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void Entity::AddHug(int amount)
|
|
{
|
|
m_HugCounter += amount;
|
|
}
|
|
|
|
/// INVENTORY THINGS ///
|
|
|
|
std::vector<Item*>& Entity::GetInventory()
|
|
{
|
|
return m_Inventory;
|
|
}
|
|
|
|
void Entity::AddItem(Item* item)
|
|
{
|
|
m_Inventory.push_back(item);
|
|
G_PRINT_STATUS(GetFullName() + " got " + item->itemName);
|
|
}
|
|
|
|
void Entity::RemoveItem(unsigned int index)
|
|
{
|
|
std::vector<Item*>::iterator it{ m_Inventory.begin() + index };
|
|
m_Inventory.erase(it);
|
|
}
|
|
|
|
bool Entity::DropItem(std::vector<ItemTile>& items, unsigned int index)
|
|
{
|
|
if(index > m_Inventory.size())
|
|
return false;
|
|
|
|
ItemTile droppedItem{ m_Inventory[index], m_Pos };
|
|
items.push_back(droppedItem);
|
|
|
|
RemoveItem(index);
|
|
return true;
|
|
}
|
|
|
|
/// PRIVATE THINGS ///
|
|
|
|
void Entity::Die()
|
|
{
|
|
G_PRINT_STATUS(GetFullName() + " died!");
|
|
m_Dead = true;
|
|
}
|