2021-03-21 01:42:45 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "core/Core.hpp"
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <set>
|
|
|
|
|
|
|
|
enum class EntityType {
|
2021-03-21 18:29:17 +00:00
|
|
|
INVALID,
|
2021-03-21 01:42:45 +00:00
|
|
|
PLAYER,
|
|
|
|
SIMPLE_NPC,
|
|
|
|
COMBAT_NPC,
|
2021-03-21 02:54:24 +00:00
|
|
|
MOB,
|
2021-03-21 01:42:45 +00:00
|
|
|
EGG,
|
|
|
|
BUS
|
|
|
|
};
|
|
|
|
|
|
|
|
class Chunk;
|
|
|
|
|
|
|
|
struct Entity {
|
2021-03-21 18:29:17 +00:00
|
|
|
EntityType type = EntityType::INVALID;
|
|
|
|
int x = 0, y = 0, z = 0;
|
|
|
|
uint64_t instanceID = 0;
|
|
|
|
ChunkPos chunkPos = {};
|
|
|
|
std::set<Chunk*> viewableChunks = {};
|
2021-03-21 01:42:45 +00:00
|
|
|
|
|
|
|
// destructor must be virtual, apparently
|
|
|
|
virtual ~Entity() {}
|
|
|
|
|
|
|
|
virtual bool isAlive() { return true; }
|
|
|
|
|
|
|
|
// stubs
|
|
|
|
virtual void enterIntoViewOf(CNSocket *sock) {}
|
|
|
|
virtual void disappearFromViewOf(CNSocket *sock) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct EntityRef {
|
|
|
|
EntityType type;
|
|
|
|
union {
|
|
|
|
CNSocket *sock;
|
|
|
|
int32_t id;
|
|
|
|
};
|
|
|
|
|
|
|
|
EntityRef(CNSocket *s);
|
|
|
|
EntityRef(int32_t i);
|
|
|
|
|
|
|
|
bool isValid() const;
|
|
|
|
Entity *getEntity() const;
|
|
|
|
|
|
|
|
bool operator==(const EntityRef& other) const {
|
|
|
|
if (type != other.type)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (type == EntityType::PLAYER)
|
|
|
|
return sock == other.sock;
|
|
|
|
|
|
|
|
return id == other.id;
|
|
|
|
}
|
|
|
|
|
|
|
|
// arbitrary ordering
|
|
|
|
bool operator<(const EntityRef& other) const {
|
|
|
|
if (type == other.type) {
|
|
|
|
if (type == EntityType::PLAYER)
|
|
|
|
return sock < other.sock;
|
|
|
|
else
|
|
|
|
return id < other.id;
|
|
|
|
}
|
|
|
|
|
|
|
|
return type < other.type;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-03-21 02:54:24 +00:00
|
|
|
/*
|
|
|
|
* Subclasses
|
|
|
|
*/
|
2021-03-21 01:42:45 +00:00
|
|
|
class BaseNPC : public Entity {
|
|
|
|
public:
|
2021-03-21 18:29:17 +00:00
|
|
|
sNPCAppearanceData appearanceData = {};
|
2021-03-21 02:54:24 +00:00
|
|
|
//NPCClass npcClass;
|
2021-03-21 01:42:45 +00:00
|
|
|
|
2021-03-21 18:29:17 +00:00
|
|
|
int playersInView = 0;
|
2021-03-21 01:42:45 +00:00
|
|
|
|
2021-03-21 02:54:24 +00:00
|
|
|
BaseNPC(int x, int y, int z, int angle, uint64_t iID, int t, int id) { // XXX
|
2021-03-21 01:42:45 +00:00
|
|
|
appearanceData.iX = x;
|
|
|
|
appearanceData.iY = y;
|
|
|
|
appearanceData.iZ = z;
|
2021-03-21 02:54:24 +00:00
|
|
|
appearanceData.iNPCType = t;
|
2021-03-21 01:42:45 +00:00
|
|
|
appearanceData.iHP = 400;
|
|
|
|
appearanceData.iAngle = angle;
|
|
|
|
appearanceData.iConditionBitFlag = 0;
|
|
|
|
appearanceData.iBarkerType = 0;
|
|
|
|
appearanceData.iNPC_ID = id;
|
|
|
|
|
2021-03-21 02:54:24 +00:00
|
|
|
type = EntityType::SIMPLE_NPC;
|
2021-03-21 01:42:45 +00:00
|
|
|
|
|
|
|
instanceID = iID;
|
|
|
|
|
|
|
|
chunkPos = std::make_tuple(0, 0, 0);
|
|
|
|
playersInView = 0;
|
|
|
|
};
|
2021-03-21 02:54:24 +00:00
|
|
|
BaseNPC(int x, int y, int z, int angle, uint64_t iID, int t, int id, EntityType entityType) : BaseNPC(x, y, z, angle, iID, t, id) {
|
|
|
|
type = entityType;
|
2021-03-21 01:42:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// XXX: move to CombatNPC, probably
|
|
|
|
virtual bool isAlive() override { return appearanceData.iHP > 0; }
|
|
|
|
|
|
|
|
virtual void enterIntoViewOf(CNSocket *sock) override;
|
|
|
|
virtual void disappearFromViewOf(CNSocket *sock) override;
|
|
|
|
};
|
|
|
|
|
2021-03-21 18:29:17 +00:00
|
|
|
struct CombatNPC : public BaseNPC {
|
|
|
|
int maxHealth = 0;
|
|
|
|
int spawnX = 0;
|
|
|
|
int spawnY = 0;
|
|
|
|
int spawnZ = 0;
|
|
|
|
int level = 0;
|
|
|
|
|
|
|
|
void (*_stepAI)() = nullptr;
|
|
|
|
|
|
|
|
// XXX
|
|
|
|
CombatNPC(int x, int y, int z, int angle, uint64_t iID, int t, int id, int maxHP) :
|
|
|
|
BaseNPC(x, y, z, angle, iID, t, id),
|
|
|
|
maxHealth(maxHP)
|
|
|
|
{}
|
|
|
|
|
|
|
|
virtual void stepAI() {
|
|
|
|
if (_stepAI != nullptr)
|
|
|
|
_stepAI();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Mob is in MobAI.hpp, Player is in Player.hpp
|
|
|
|
|
2021-03-21 01:42:45 +00:00
|
|
|
// TODO: decouple from BaseNPC
|
|
|
|
struct Egg : public BaseNPC {
|
2021-03-21 18:29:17 +00:00
|
|
|
bool summoned = false;
|
2021-03-21 01:42:45 +00:00
|
|
|
bool dead = false;
|
|
|
|
time_t deadUntil;
|
|
|
|
|
2021-03-21 02:54:24 +00:00
|
|
|
Egg(int x, int y, int z, uint64_t iID, int t, int32_t id, bool summon)
|
|
|
|
: BaseNPC(x, y, z, 0, iID, t, id) {
|
2021-03-21 01:42:45 +00:00
|
|
|
summoned = summon;
|
2021-03-21 02:54:24 +00:00
|
|
|
type = EntityType::EGG;
|
2021-03-21 01:42:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool isAlive() override { return !dead; }
|
|
|
|
|
|
|
|
virtual void enterIntoViewOf(CNSocket *sock) override;
|
|
|
|
virtual void disappearFromViewOf(CNSocket *sock) override;
|
|
|
|
};
|
|
|
|
|
|
|
|
// TODO: decouple from BaseNPC
|
|
|
|
struct Bus : public BaseNPC {
|
|
|
|
virtual void enterIntoViewOf(CNSocket *sock) override;
|
|
|
|
virtual void disappearFromViewOf(CNSocket *sock) override;
|
|
|
|
};
|