mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-14 02:10:06 +00:00
Generalize NPC AI stepping logic
The MobAI::Mobs map still needs to be removed.
This commit is contained in:
parent
3325397d17
commit
65462d01e3
@ -30,12 +30,8 @@ struct Entity {
|
||||
virtual bool isAlive() { return true; }
|
||||
|
||||
// stubs
|
||||
virtual void enterIntoViewOf(CNSocket *sock) {}
|
||||
virtual void disappearFromViewOf(CNSocket *sock) {}
|
||||
|
||||
// we don't want objects of this base class to exist
|
||||
protected:
|
||||
Entity() {}
|
||||
virtual void enterIntoViewOf(CNSocket *sock) = 0;
|
||||
virtual void disappearFromViewOf(CNSocket *sock) = 0;
|
||||
};
|
||||
|
||||
struct EntityRef {
|
||||
@ -106,16 +102,16 @@ struct CombatNPC : public BaseNPC {
|
||||
int spawnZ = 0;
|
||||
int level = 0;
|
||||
|
||||
void (*_stepAI)() = nullptr;
|
||||
void (*_stepAI)(CombatNPC*, time_t) = 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() {
|
||||
virtual void stepAI(time_t currTime) {
|
||||
if (_stepAI != nullptr)
|
||||
_stepAI();
|
||||
_stepAI(this, currTime);
|
||||
}
|
||||
|
||||
virtual bool isAlive() override { return appearanceData.iHP > 0; }
|
||||
|
@ -12,9 +12,8 @@
|
||||
using namespace MobAI;
|
||||
|
||||
std::map<int32_t, Mob*> MobAI::Mobs;
|
||||
static std::queue<int32_t> RemovalQueue;
|
||||
|
||||
bool MobAI::simulateMobs;
|
||||
bool MobAI::simulateMobs = settings::SIMULATEMOBS;
|
||||
|
||||
static void roamingStep(Mob *mob, time_t currTime);
|
||||
|
||||
@ -451,7 +450,7 @@ static void deadStep(Mob *mob, time_t currTime) {
|
||||
// if it was summoned, mark it for removal
|
||||
if (mob->summoned) {
|
||||
std::cout << "[INFO] Queueing killed summoned mob for removal" << std::endl;
|
||||
RemovalQueue.push(mob->appearanceData.iNPC_ID);
|
||||
NPCManager::queueNPCRemoval(mob->appearanceData.iNPC_ID);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -774,44 +773,33 @@ static void retreatStep(Mob *mob, time_t currTime) {
|
||||
}
|
||||
}
|
||||
|
||||
static void step(CNServer *serv, time_t currTime) {
|
||||
for (auto& pair : Mobs) {
|
||||
if (pair.second->playersInView < 0)
|
||||
std::cout << "[WARN] Weird playerview value " << pair.second->playersInView << std::endl;
|
||||
void MobAI::step(CombatNPC *npc, time_t currTime) {
|
||||
assert(npc->type == EntityType::MOB);
|
||||
auto mob = (Mob*)npc;
|
||||
|
||||
// skip mob movement and combat if disabled or not in view
|
||||
if ((!simulateMobs || pair.second->playersInView == 0) && pair.second->state != MobState::DEAD
|
||||
&& pair.second->state != MobState::RETREAT)
|
||||
continue;
|
||||
if (mob->playersInView < 0)
|
||||
std::cout << "[WARN] Weird playerview value " << mob->playersInView << std::endl;
|
||||
|
||||
switch (pair.second->state) {
|
||||
case MobState::INACTIVE:
|
||||
// no-op
|
||||
break;
|
||||
case MobState::ROAMING:
|
||||
roamingStep(pair.second, currTime);
|
||||
break;
|
||||
case MobState::COMBAT:
|
||||
combatStep(pair.second, currTime);
|
||||
break;
|
||||
case MobState::RETREAT:
|
||||
retreatStep(pair.second, currTime);
|
||||
break;
|
||||
case MobState::DEAD:
|
||||
deadStep(pair.second, currTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// skip mob movement and combat if disabled or not in view
|
||||
if ((!simulateMobs || mob->playersInView == 0) && mob->state != MobState::DEAD
|
||||
&& mob->state != MobState::RETREAT)
|
||||
return;
|
||||
|
||||
// deallocate all NPCs queued for removal
|
||||
while (RemovalQueue.size() > 0) {
|
||||
NPCManager::destroyNPC(RemovalQueue.front());
|
||||
RemovalQueue.pop();
|
||||
switch (mob->state) {
|
||||
case MobState::INACTIVE:
|
||||
// no-op
|
||||
break;
|
||||
case MobState::ROAMING:
|
||||
roamingStep(mob, currTime);
|
||||
break;
|
||||
case MobState::COMBAT:
|
||||
combatStep(mob, currTime);
|
||||
break;
|
||||
case MobState::RETREAT:
|
||||
retreatStep(mob, currTime);
|
||||
break;
|
||||
case MobState::DEAD:
|
||||
deadStep(mob, currTime);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MobAI::init() {
|
||||
REGISTER_SHARD_TIMER(step, 200);
|
||||
|
||||
simulateMobs = settings::SIMULATEMOBS;
|
||||
}
|
||||
|
@ -11,6 +11,11 @@ enum class MobState {
|
||||
DEAD
|
||||
};
|
||||
|
||||
namespace MobAI {
|
||||
// needs to be declared before Mob's constructor
|
||||
void step(CombatNPC*, time_t);
|
||||
};
|
||||
|
||||
struct Mob : public CombatNPC {
|
||||
// general
|
||||
MobState state = MobState::INACTIVE;
|
||||
@ -76,6 +81,7 @@ struct Mob : public CombatNPC {
|
||||
appearanceData.iHP = maxHealth;
|
||||
|
||||
type = EntityType::MOB;
|
||||
_stepAI = MobAI::step;
|
||||
}
|
||||
|
||||
// constructor for /summon
|
||||
@ -98,8 +104,6 @@ namespace MobAI {
|
||||
extern bool simulateMobs;
|
||||
extern std::map<int32_t, Mob*> Mobs;
|
||||
|
||||
void init();
|
||||
|
||||
// TODO: make this internal later
|
||||
void incNextMovement(Mob *mob, time_t currTime=0);
|
||||
bool aggroCheck(Mob *mob, time_t currTime);
|
||||
|
@ -23,11 +23,13 @@
|
||||
|
||||
using namespace NPCManager;
|
||||
|
||||
std::map<int32_t, BaseNPC*> NPCManager::NPCs;
|
||||
std::unordered_map<int32_t, BaseNPC*> NPCManager::NPCs;
|
||||
std::map<int32_t, WarpLocation> NPCManager::Warps;
|
||||
std::vector<WarpLocation> NPCManager::RespawnPoints;
|
||||
nlohmann::json NPCManager::NPCData;
|
||||
|
||||
static std::queue<int32_t> RemovalQueue;
|
||||
|
||||
/*
|
||||
* Initialized at the end of TableData::init().
|
||||
* This allows us to summon and kill mobs in arbitrary order without
|
||||
@ -349,10 +351,32 @@ std::vector<NPCEvent> NPCManager::NPCEvents = {
|
||||
|
||||
#pragma endregion NPCEvents
|
||||
|
||||
void NPCManager::queueNPCRemoval(int32_t id) {
|
||||
RemovalQueue.push(id);
|
||||
}
|
||||
|
||||
static void step(CNServer *serv, time_t currTime) {
|
||||
for (auto& pair : NPCs) {
|
||||
if (pair.second->type != EntityType::COMBAT_NPC && pair.second->type != EntityType::MOB)
|
||||
continue;
|
||||
auto npc = (CombatNPC*)pair.second;
|
||||
|
||||
npc->stepAI(currTime);
|
||||
}
|
||||
|
||||
// deallocate all NPCs queued for removal
|
||||
while (RemovalQueue.size() > 0) {
|
||||
NPCManager::destroyNPC(RemovalQueue.front());
|
||||
RemovalQueue.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void NPCManager::init() {
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_WARP_USE_NPC, npcWarpHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_TIME_TO_GO_WARP, npcWarpTimeMachine);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_NPC_SUMMON, npcSummonHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_NPC_UNSUMMON, npcUnsummonHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_BARKER, npcBarkHandler);
|
||||
|
||||
REGISTER_SHARD_TIMER(step, 200);
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ struct WarpLocation {
|
||||
};
|
||||
|
||||
namespace NPCManager {
|
||||
extern std::map<int32_t, BaseNPC*> NPCs;
|
||||
extern std::unordered_map<int32_t, BaseNPC*> NPCs;
|
||||
extern std::map<int32_t, WarpLocation> Warps;
|
||||
extern std::vector<WarpLocation> RespawnPoints;
|
||||
extern std::vector<NPCEvent> NPCEvents;
|
||||
@ -42,6 +42,7 @@ namespace NPCManager {
|
||||
extern int32_t nextId;
|
||||
void init();
|
||||
|
||||
void queueNPCRemoval(int32_t);
|
||||
void destroyNPC(int32_t);
|
||||
void updateNPCPosition(int32_t, int X, int Y, int Z, uint64_t I, int angle);
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#pragma once
|
||||
#include <map>
|
||||
|
||||
#include "JSON.hpp"
|
||||
#include "NPCManager.hpp"
|
||||
|
||||
namespace TableData {
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "Buddies.hpp"
|
||||
#include "CustomCommands.hpp"
|
||||
#include "Combat.hpp"
|
||||
#include "MobAI.hpp"
|
||||
#include "Items.hpp"
|
||||
#include "Missions.hpp"
|
||||
#include "Nanos.hpp"
|
||||
@ -107,7 +106,6 @@ int main() {
|
||||
CustomCommands::init();
|
||||
Combat::init();
|
||||
Chat::init();
|
||||
MobAI::init();
|
||||
Items::init();
|
||||
Eggs::init();
|
||||
Missions::init();
|
||||
|
Loading…
Reference in New Issue
Block a user