mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-04 22:40:05 +00:00
Summoned mobs are now actually treated as mobs.
Unfortunetly, this necessitated keeping around yet more JSON objects for the duration of the server's runtime. It also involved unifying the way NPC IDs are handled, such that they may be allocated and deallocated out of order. If any NPCID-related bugs occour, this commit should be regarded as the prime suspect.
This commit is contained in:
parent
cfb3d25bc5
commit
72d625fd8d
@ -215,6 +215,13 @@ void MobManager::deadStep(Mob *mob, time_t currTime) {
|
||||
s->sendPacket(&pkt, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||
}
|
||||
}
|
||||
|
||||
// if it was summoned, remove it permanently
|
||||
if (mob->summoned) {
|
||||
std::cout << "[INFO] Deallocating killed summoned mob" << std::endl;
|
||||
NPCManager::removeNPC(mob->appearanceData.iNPC_ID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (mob->killedTime != 0 && currTime - mob->killedTime < mob->regenTime * 100)
|
||||
|
@ -20,7 +20,7 @@ enum class MobState {
|
||||
struct Mob : public BaseNPC {
|
||||
// general
|
||||
MobState state;
|
||||
const int maxHealth;
|
||||
int maxHealth;
|
||||
int spawnX;
|
||||
int spawnY;
|
||||
int spawnZ;
|
||||
@ -28,6 +28,7 @@ struct Mob : public BaseNPC {
|
||||
// dead
|
||||
time_t killedTime = 0;
|
||||
time_t regenTime;
|
||||
bool summoned = false;
|
||||
bool despawned = false; // for the sake of death animations
|
||||
|
||||
// roaming
|
||||
@ -41,8 +42,8 @@ struct Mob : public BaseNPC {
|
||||
// temporary; until we're sure what's what
|
||||
nlohmann::json data;
|
||||
|
||||
Mob(int x, int y, int z, int type, int hp, int angle, nlohmann::json d)
|
||||
: BaseNPC(x, y, z, type), maxHealth(hp) {
|
||||
Mob(int x, int y, int z, int type, int hp, int angle, nlohmann::json d, int32_t id)
|
||||
: BaseNPC(x, y, z, type, id), maxHealth(hp) {
|
||||
state = MobState::ROAMING;
|
||||
|
||||
data = d;
|
||||
@ -58,7 +59,17 @@ struct Mob : public BaseNPC {
|
||||
|
||||
// NOTE: there appear to be discrepancies in the dump
|
||||
appearanceData.iHP = maxHealth;
|
||||
|
||||
npcClass = NPC_MOB;
|
||||
}
|
||||
|
||||
// constructor for /summon
|
||||
Mob(int x, int y, int z, int type, nlohmann::json d, int32_t id)
|
||||
: Mob(x, y, z, type, 0, 0, d, id) {
|
||||
summoned = true; // will be despawned and deallocated when killed
|
||||
appearanceData.iHP = maxHealth = d["m_iHP"];
|
||||
}
|
||||
|
||||
~Mob() {}
|
||||
|
||||
auto operator[](std::string s) {
|
||||
|
@ -8,7 +8,7 @@ public:
|
||||
NPCClass npcClass;
|
||||
|
||||
BaseNPC() {};
|
||||
BaseNPC(int x, int y, int z, int type) {
|
||||
BaseNPC(int x, int y, int z, int type, int id) {
|
||||
appearanceData.iX = x;
|
||||
appearanceData.iY = y;
|
||||
appearanceData.iZ = z;
|
||||
@ -17,11 +17,9 @@ public:
|
||||
appearanceData.iAngle = 0;
|
||||
appearanceData.iConditionBitFlag = 0;
|
||||
appearanceData.iBarkerType = 0;
|
||||
|
||||
// hopefully no collisions happen :eyes:
|
||||
appearanceData.iNPC_ID = (int32_t)rand();
|
||||
appearanceData.iNPC_ID = id;
|
||||
};
|
||||
BaseNPC(int x, int y, int z, int type, NPCClass classType) : BaseNPC(x, y, z, type) {
|
||||
BaseNPC(int x, int y, int z, int type, int id, NPCClass classType) : BaseNPC(x, y, z, type, id) {
|
||||
npcClass = classType;
|
||||
}
|
||||
};
|
||||
|
@ -8,13 +8,21 @@
|
||||
#include <list>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
#include <assert.h>
|
||||
|
||||
#include "contrib/JSON.hpp"
|
||||
|
||||
std::map<int32_t, BaseNPC*> NPCManager::NPCs;
|
||||
std::map<int32_t, WarpLocation> NPCManager::Warps;
|
||||
std::vector<WarpLocation> NPCManager::RespawnPoints;
|
||||
nlohmann::json NPCManager::NPCData;
|
||||
|
||||
/*
|
||||
* Initialized at the end of TableData::init().
|
||||
* This allows us to summon and kill mobs in arbitrary order without
|
||||
* NPC ID collisions.
|
||||
*/
|
||||
int32_t NPCManager::nextId;
|
||||
|
||||
void NPCManager::init() {
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_WARP_USE_NPC, npcWarpHandler);
|
||||
@ -481,15 +489,21 @@ void NPCManager::npcSummonHandler(CNSocket* sock, CNPacketData* data) {
|
||||
if (plr->accountLevel > 30 || req->iNPCType >= 3314)
|
||||
return;
|
||||
|
||||
resp.NPCAppearanceData.iNPC_ID = NPCs.size()+1;
|
||||
int team = NPCData[req->iNPCType]["m_iTeam"];
|
||||
|
||||
assert(nextId < INT32_MAX);
|
||||
resp.NPCAppearanceData.iNPC_ID = nextId++;
|
||||
resp.NPCAppearanceData.iNPCType = req->iNPCType;
|
||||
resp.NPCAppearanceData.iHP = 1000; // TODO: placeholder
|
||||
resp.NPCAppearanceData.iHP = 1000;
|
||||
resp.NPCAppearanceData.iX = plr->x;
|
||||
resp.NPCAppearanceData.iY = plr->y;
|
||||
resp.NPCAppearanceData.iZ = plr->z;
|
||||
|
||||
NPCs[resp.NPCAppearanceData.iNPC_ID] = new BaseNPC(plr->x, plr->y, plr->z, req->iNPCType);
|
||||
NPCs[resp.NPCAppearanceData.iNPC_ID]->appearanceData.iNPC_ID = resp.NPCAppearanceData.iNPC_ID;
|
||||
if (team == 2) {
|
||||
NPCs[resp.NPCAppearanceData.iNPC_ID] = new Mob(plr->x, plr->y, plr->z, req->iNPCType, NPCData[req->iNPCType], resp.NPCAppearanceData.iNPC_ID);
|
||||
MobManager::Mobs[resp.NPCAppearanceData.iNPC_ID] = (Mob*)NPCs[resp.NPCAppearanceData.iNPC_ID];
|
||||
} else
|
||||
NPCs[resp.NPCAppearanceData.iNPC_ID] = new BaseNPC(plr->x, plr->y, plr->z, req->iNPCType, resp.NPCAppearanceData.iNPC_ID);
|
||||
|
||||
ChunkManager::addNPC(plr->x, plr->y, resp.NPCAppearanceData.iNPC_ID);
|
||||
}
|
||||
|
@ -4,6 +4,8 @@
|
||||
#include "PlayerManager.hpp"
|
||||
#include "NPC.hpp"
|
||||
|
||||
#include "contrib/JSON.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
@ -18,6 +20,8 @@ namespace NPCManager {
|
||||
extern std::map<int32_t, BaseNPC*> NPCs;
|
||||
extern std::map<int32_t, WarpLocation> Warps;
|
||||
extern std::vector<WarpLocation> RespawnPoints;
|
||||
extern nlohmann::json NPCData;
|
||||
extern int32_t nextId;
|
||||
void init();
|
||||
|
||||
void addNPC(std::vector<Chunk*> viewableChunks, int32_t);
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <fstream>
|
||||
|
||||
void TableData::init() {
|
||||
int i = 0;
|
||||
int32_t nextId = 0;
|
||||
|
||||
// load NPCs from NPC.json
|
||||
try {
|
||||
@ -24,14 +24,11 @@ void TableData::init() {
|
||||
|
||||
for (nlohmann::json::iterator _npc = npcData.begin(); _npc != npcData.end(); _npc++) {
|
||||
auto npc = _npc.value();
|
||||
BaseNPC *tmp = new BaseNPC(npc["x"], npc["y"], npc["z"], npc["id"]);
|
||||
BaseNPC *tmp = new BaseNPC(npc["x"], npc["y"], npc["z"], npc["id"], nextId);
|
||||
|
||||
// Temporary fix, IDs will be pulled from json later
|
||||
tmp->appearanceData.iNPC_ID = i;
|
||||
|
||||
NPCManager::NPCs[i] = tmp;
|
||||
ChunkManager::addNPC(npc["x"], npc["y"], i);
|
||||
i++;
|
||||
NPCManager::NPCs[nextId] = tmp;
|
||||
ChunkManager::addNPC(npc["x"], npc["y"], nextId);
|
||||
nextId++;
|
||||
|
||||
if (npc["id"] == 641 || npc["id"] == 642)
|
||||
NPCManager::RespawnPoints.push_back({ npc["x"], npc["y"], ((int)npc["z"]) + RESURRECT_HEIGHT });
|
||||
@ -52,6 +49,9 @@ void TableData::init() {
|
||||
// read file into json
|
||||
infile >> xdtData;
|
||||
|
||||
// data we'll need for summoned mobs
|
||||
NPCManager::NPCData = xdtData["m_pNpcTable"]["m_pNpcData"];
|
||||
|
||||
try {
|
||||
// load warps
|
||||
nlohmann::json warpData = xdtData["m_pInstanceTable"]["m_pWarpData"];
|
||||
@ -74,7 +74,7 @@ void TableData::init() {
|
||||
TransportLocation transLoc = { tLoc["m_iNPCID"], tLoc["m_iXpos"], tLoc["m_iYpos"], tLoc["m_iZpos"] };
|
||||
TransportManager::Locations[tLoc["m_iLocationID"]] = transLoc;
|
||||
}
|
||||
std::cout << "[INFO] Loaded " << TransportManager::Locations.size() << " S.C.A.M.P.E.R. locations" << std::endl; // TODO: Skyway operates differently
|
||||
std::cout << "[INFO] Loaded " << TransportManager::Locations.size() << " S.C.A.M.P.E.R. locations" << std::endl;
|
||||
|
||||
for (nlohmann::json::iterator _tRoute = transRouteData.begin(); _tRoute != transRouteData.end(); _tRoute++) {
|
||||
auto tRoute = _tRoute.value();
|
||||
@ -165,21 +165,16 @@ void TableData::init() {
|
||||
// read file into json
|
||||
inFile >> npcData;
|
||||
|
||||
nlohmann::json npcTableData = xdtData["m_pNpcTable"]["m_pNpcData"];
|
||||
|
||||
for (nlohmann::json::iterator _npc = npcData.begin(); _npc != npcData.end(); _npc++) {
|
||||
auto npc = _npc.value();
|
||||
auto td = npcTableData[(int)npc["iNPCType"]];
|
||||
Mob *tmp = new Mob(npc["iX"], npc["iY"], npc["iZ"], npc["iNPCType"], npc["iHP"], npc["iAngle"], td);
|
||||
auto td = NPCManager::NPCData[(int)npc["iNPCType"]];
|
||||
Mob *tmp = new Mob(npc["iX"], npc["iY"], npc["iZ"], npc["iNPCType"], npc["iHP"], npc["iAngle"], td, nextId);
|
||||
|
||||
// Temporary fix, IDs will be pulled from json later
|
||||
tmp->appearanceData.iNPC_ID = i;
|
||||
NPCManager::NPCs[nextId] = tmp;
|
||||
MobManager::Mobs[nextId] = (Mob*)NPCManager::NPCs[nextId];
|
||||
ChunkManager::addNPC(npc["iX"], npc["iY"], nextId);
|
||||
|
||||
NPCManager::NPCs[i] = tmp;
|
||||
MobManager::Mobs[i] = (Mob*)NPCManager::NPCs[i];
|
||||
ChunkManager::addNPC(npc["iX"], npc["iY"], i);
|
||||
|
||||
i++;
|
||||
nextId++;
|
||||
}
|
||||
|
||||
std::cout << "[INFO] Populated " << NPCManager::NPCs.size() << " NPCs" << std::endl;
|
||||
@ -187,6 +182,8 @@ void TableData::init() {
|
||||
catch (const std::exception& err) {
|
||||
std::cerr << "[WARN] Malformed mobs.json file! Reason:" << err.what() << std::endl;
|
||||
}
|
||||
|
||||
NPCManager::nextId = nextId;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -18,7 +18,7 @@ void TransportManager::init() {
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_REGIST_TRANSPORTATION_LOCATION, transportRegisterLocationHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_WARP_USE_TRANSPORTATION, transportWarpHandler);
|
||||
|
||||
BaseNPC* bus = new BaseNPC(220447, 162431, -3650, 1, NPC_BUS);
|
||||
BaseNPC* bus = new BaseNPC(220447, 162431, -3650, 1, NPCManager::nextId++, NPC_BUS);
|
||||
NPCManager::NPCs[bus->appearanceData.iNPC_ID] = bus;
|
||||
ChunkManager::addNPC(bus->appearanceData.iX, bus->appearanceData.iY, bus->appearanceData.iNPC_ID);
|
||||
std::queue<WarpLocation> busPoints;
|
||||
|
Loading…
Reference in New Issue
Block a user