2021-03-21 01:42:45 +00:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "core/Core.hpp"
|
2022-07-22 00:40:33 +00:00
|
|
|
#include "Chunking.hpp"
|
2021-03-21 01:42:45 +00:00
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <set>
|
|
|
|
|
2021-03-22 16:53:46 +00:00
|
|
|
enum class EntityType : uint8_t {
|
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
|
|
|
|
};
|
|
|
|
|
|
|
|
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
|
2021-03-31 19:05:49 +00:00
|
|
|
virtual void enterIntoViewOf(CNSocket *sock) = 0;
|
|
|
|
virtual void disappearFromViewOf(CNSocket *sock) = 0;
|
2021-03-21 01:42:45 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
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-05-09 12:37:36 +00:00
|
|
|
bool loopingPath = false;
|
2021-03-21 01:42:45 +00:00
|
|
|
|
2021-04-14 00:57:24 +00:00
|
|
|
BaseNPC(int _X, int _Y, int _Z, int angle, uint64_t iID, int t, int id) { // XXX
|
|
|
|
x = _X;
|
|
|
|
y = _Y;
|
|
|
|
z = _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;
|
|
|
|
|
|
|
|
instanceID = iID;
|
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
2021-04-30 00:20:53 +00:00
|
|
|
int speed = 300;
|
2021-03-21 18:29:17 +00:00
|
|
|
|
2021-03-31 19:05:49 +00:00
|
|
|
void (*_stepAI)(CombatNPC*, time_t) = nullptr;
|
2021-03-21 18:29:17 +00:00
|
|
|
|
|
|
|
// 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),
|
2021-03-22 16:53:46 +00:00
|
|
|
maxHealth(maxHP) {}
|
2021-03-21 18:29:17 +00:00
|
|
|
|
2021-03-31 19:05:49 +00:00
|
|
|
virtual void stepAI(time_t currTime) {
|
2021-03-21 18:29:17 +00:00
|
|
|
if (_stepAI != nullptr)
|
2021-03-31 19:05:49 +00:00
|
|
|
_stepAI(this, currTime);
|
2021-03-21 18:29:17 +00:00
|
|
|
}
|
2021-03-22 16:53:46 +00:00
|
|
|
|
|
|
|
virtual bool isAlive() override { return appearanceData.iHP > 0; }
|
2021-03-21 18:29:17 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
// 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 {
|
2021-03-22 16:53:46 +00:00
|
|
|
Bus(int x, int y, int z, int angle, uint64_t iID, int t, int id) :
|
|
|
|
BaseNPC(x, y, z, angle, iID, t, id) {
|
|
|
|
type = EntityType::BUS;
|
2021-05-16 19:39:45 +00:00
|
|
|
loopingPath = true;
|
2021-03-22 16:53:46 +00:00
|
|
|
}
|
|
|
|
|
2021-03-21 01:42:45 +00:00
|
|
|
virtual void enterIntoViewOf(CNSocket *sock) override;
|
|
|
|
virtual void disappearFromViewOf(CNSocket *sock) override;
|
|
|
|
};
|