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.
121 lines
3.3 KiB
C++
121 lines
3.3 KiB
C++
#include "NPC.hpp"
|
|
#include "RLGame.hpp"
|
|
#include "utils.hpp"
|
|
#include "ItemList.hpp"
|
|
|
|
#ifdef _DEBUG
|
|
#include <iostream>
|
|
#endif
|
|
|
|
NPC::NPC()
|
|
: NPC{ "", SPECIES::UNDEFINED, Position{} }
|
|
{
|
|
}
|
|
|
|
NPC::NPC(const std::string& name, SPECIES species, Position position)
|
|
: Entity{ name, species, position }
|
|
{
|
|
// give random items
|
|
unsigned int randomItem{ uint32_t(utils::RandomBetween(0, G_ITEM_LIST->GetAmountOfWeapons() + 5)) };
|
|
if(randomItem < G_ITEM_LIST->GetAmountOfWeapons())
|
|
{
|
|
m_pWeapon = nullptr;
|
|
#ifdef _DEBUG
|
|
//std::cout << name << " (" << GetSpeciesString() << ") got weapon " << m_pWeapon->itemName << '\n';
|
|
#endif
|
|
}
|
|
|
|
randomItem = uint32_t(utils::RandomBetween(0, G_ITEM_LIST->GetAmountOfArmors() + 7));
|
|
if(randomItem < G_ITEM_LIST->GetAmountOfArmors())
|
|
{
|
|
m_pArmor = nullptr;
|
|
#ifdef _DEBUG
|
|
//std::cout << name << " (" << GetSpeciesString() << ") got armor " << m_pArmor->itemName << '\n';
|
|
#endif
|
|
}
|
|
}
|
|
|
|
void NPC::Update(const std::vector<Entity*>& entities)
|
|
{
|
|
/*if(m_Species == SPECIES::HUMAN)
|
|
{
|
|
if(GetDistanceFrom(*m_pPlayer) > 1)
|
|
MoveTo(*m_pPlayer);
|
|
else
|
|
Fight(*m_pPlayer);
|
|
}
|
|
else if(m_HugCounter > 0)
|
|
{
|
|
if(GetDistanceFrom(*m_pPlayer) > 1)
|
|
MoveTo(*m_pPlayer);
|
|
else if(utils::RandomBetween(0, 100) < 5)
|
|
Hug(*m_pPlayer);
|
|
}*/
|
|
|
|
/*
|
|
auto closeNPCs{ GetClosestWithState(entities, (m_Faction == ENTITY_FACTION::FRIENDLY || m_Faction == ENTITY_FACTION::DEVOTED) ? ENTITY_FACTION::EVIL : ENTITY_FACTION::FRIENDLY) };
|
|
if(m_Faction == ENTITY_FACTION::EVIL)
|
|
{
|
|
auto otherCloseNPCs{ GetClosestWithState(entities, ENTITY_FACTION::DEVOTED) };
|
|
for(auto& npc : otherCloseNPCs)
|
|
closeNPCs.push_back(npc);
|
|
}
|
|
*/
|
|
|
|
switch(m_Faction)
|
|
{
|
|
case ENTITY_FACTION::NEUTRAL:
|
|
{
|
|
if(m_Health < m_MaxHealth / 2)
|
|
CheckInventory(ITEM_TYPE::CONSUMABLE);
|
|
else if(utils::RandomBetweenSimple(0, 10) < 2)
|
|
Move(DIRECTION(utils::RandomBetweenSimple(0, 7)));
|
|
break;
|
|
}
|
|
case ENTITY_FACTION::FRIENDLY:
|
|
case ENTITY_FACTION::DEVOTED:
|
|
{
|
|
std::vector<Entity*> closeNPCs{ GetClosestWithState(entities, ENTITY_FACTION::EVIL) };
|
|
|
|
if(m_Health < m_MaxHealth / 2)
|
|
CheckInventory(ITEM_TYPE::CONSUMABLE);
|
|
else if(closeNPCs.size() > 0)
|
|
Fight(*closeNPCs[utils::RandomBetween(0, closeNPCs.size() - 1)]);
|
|
else if(GetDistanceFrom(*m_pPlayer) > 1)
|
|
MoveTo(*m_pPlayer);
|
|
else if(utils::RandomBetween(0, 10) < 1)
|
|
Hug(*m_pPlayer);
|
|
break;
|
|
}
|
|
case ENTITY_FACTION::EVIL:
|
|
{
|
|
std::vector<Entity*> closeNPCs{ GetClosestWithState(entities, ENTITY_FACTION::FRIENDLY) };
|
|
std::vector<Entity*> otherCloseNPCs{ GetClosestWithState(entities, ENTITY_FACTION::DEVOTED) };
|
|
for(auto& npc : otherCloseNPCs) // put them all in one vector
|
|
closeNPCs.push_back(npc);
|
|
|
|
if(m_Health < m_MaxHealth / 2)
|
|
CheckInventory(ITEM_TYPE::CONSUMABLE);
|
|
else if(closeNPCs.size() > 0 && utils::RandomBetweenSimple(0, 1)) // fight close npcs or player but closeNPCs also contains the player EDIT 2020-08-01: player isn't actually included, was wrong
|
|
Fight(*closeNPCs[utils::RandomBetween(0, closeNPCs.size() - 1)]);
|
|
else if(GetDistanceFrom(*m_pPlayer) > 1)
|
|
MoveTo(*m_pPlayer);
|
|
else
|
|
Fight(*m_pPlayer);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void NPC::CheckInventory(ITEM_TYPE itemType)
|
|
{
|
|
for(size_t id{}; id < m_Inventory.size(); ++id)
|
|
{
|
|
if(m_Inventory[id]->itemType == itemType)
|
|
{
|
|
UseItem(id);
|
|
break;
|
|
}
|
|
}
|
|
}
|