mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-05 06:50:04 +00:00
Apply matching paths to NPCs and mobs on spawn
This commit is contained in:
parent
2721f21427
commit
c960b06227
@ -34,6 +34,31 @@ public:
|
|||||||
const char *what() const throw() { return msg.c_str(); }
|
const char *what() const throw() { return msg.c_str(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Find and return the first path that targets either the type or the ID.
|
||||||
|
* If no matches are found, return nullptr
|
||||||
|
*/
|
||||||
|
static NPCPath* findApplicablePath(int32_t id, int32_t type) {
|
||||||
|
NPCPath* match = nullptr;
|
||||||
|
for (auto _path = Transport::NPCPaths.begin(); _path != Transport::NPCPaths.end(); _path++) {
|
||||||
|
// search target IDs
|
||||||
|
for (int32_t pID : _path->targetIDs) {
|
||||||
|
if (id == pID) match = &(*_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// search target types
|
||||||
|
for (int32_t pType : _path->targetTypes) {
|
||||||
|
if (type == pType) match = &(*_path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (match != nullptr)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a full and properly-paced path by interpolating between keyframes.
|
* Create a full and properly-paced path by interpolating between keyframes.
|
||||||
*/
|
*/
|
||||||
@ -55,26 +80,35 @@ static void constructPathSkyway(json& pathData) {
|
|||||||
Transport::SkywayPaths[pathData["iRouteID"]] = points;
|
Transport::SkywayPaths[pathData["iRouteID"]] = points;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void constructPathNPC(json& pathData, int32_t id=0) {
|
static void constructPathNPC(int32_t id, NPCPath* path) {
|
||||||
// Interpolate
|
BaseNPC* npc = NPCManager::NPCs[id];
|
||||||
json pathPoints = pathData["aPoints"];
|
if(npc->type == EntityType::MOB)
|
||||||
std::queue<Vec3> points;
|
((Mob*)(npc))->staticPath = true;
|
||||||
json::iterator _point = pathPoints.begin();
|
|
||||||
auto point = _point.value();
|
|
||||||
Vec3 from = { point["iX"] , point["iY"] , point["iZ"] }; // point A coords
|
|
||||||
int stopTime = point["iStopTicks"];
|
|
||||||
for (_point++; _point != pathPoints.end(); _point++) { // loop through all point Bs
|
|
||||||
point = _point.value();
|
|
||||||
for(int i = 0; i < stopTime + 1; i++) // repeat point if it's a stop
|
|
||||||
points.push(from); // add point A to the queue
|
|
||||||
Vec3 to = { point["iX"] , point["iY"] , point["iZ"] }; // point B coords
|
|
||||||
Transport::lerp(&points, from, to, pathData["iBaseSpeed"]); // lerp from A to B
|
|
||||||
from = to; // update point A
|
|
||||||
stopTime = point["iStopTicks"];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (id == 0)
|
// Interpolate
|
||||||
id = pathData["iNPCID"];
|
std::vector<Vec3> pathPoints = path->points;
|
||||||
|
std::queue<Vec3> points;
|
||||||
|
|
||||||
|
auto _point = pathPoints.begin();
|
||||||
|
Vec3 from = *_point; // point A coords
|
||||||
|
for (_point++; _point != pathPoints.end(); _point++) { // loop through all point Bs
|
||||||
|
Vec3 to = *_point; // point B coords
|
||||||
|
// add point A to the queue
|
||||||
|
if (path->isRelative) {
|
||||||
|
// relative; the NPCs current position is assumed to be its spawn point
|
||||||
|
Vec3 fromReal = { from.x + npc->x, from.y + npc->y, from.z + npc->z };
|
||||||
|
Vec3 toReal = { to.x + npc->x, to.y + npc->y, to.z + npc->z };
|
||||||
|
points.push(fromReal);
|
||||||
|
Transport::lerp(&points, fromReal, toReal, path->speed); // lerp from A to B
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// absolute
|
||||||
|
points.push(from);
|
||||||
|
Transport::lerp(&points, from, to, path->speed); // lerp from A to B
|
||||||
|
}
|
||||||
|
|
||||||
|
from = to; // update point A
|
||||||
|
}
|
||||||
|
|
||||||
Transport::NPCQueues[id] = points;
|
Transport::NPCQueues[id] = points;
|
||||||
}
|
}
|
||||||
@ -366,31 +400,6 @@ static void loadPaths(json& pathData, int32_t* nextId) {
|
|||||||
Transport::NPCPaths.push_back(pathTemplate);
|
Transport::NPCPaths.push_back(pathTemplate);
|
||||||
}
|
}
|
||||||
std::cout << "[INFO] Loaded " << Transport::NPCPaths.size() << " NPC paths" << std::endl;
|
std::cout << "[INFO] Loaded " << Transport::NPCPaths.size() << " NPC paths" << std::endl;
|
||||||
|
|
||||||
// mob paths
|
|
||||||
pathDataNPC = pathData["mob"];
|
|
||||||
for (json::iterator npcPath = pathDataNPC.begin(); npcPath != pathDataNPC.end(); npcPath++) {
|
|
||||||
for (auto& pair : NPCManager::NPCs) {
|
|
||||||
if (pair.second->type != EntityType::MOB)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
Mob* mob = (Mob*)pair.second;
|
|
||||||
if (mob->appearanceData.iNPCType == npcPath.value()["iNPCType"]) {
|
|
||||||
std::cout << "[INFO] Using static path for mob " << mob->appearanceData.iNPCType << " with ID " << pair.first << std::endl;
|
|
||||||
|
|
||||||
auto firstPoint = npcPath.value()["points"][0];
|
|
||||||
if (firstPoint["iX"] != mob->spawnX || firstPoint["iY"] != mob->spawnY) {
|
|
||||||
std::cout << "[FATAL] The first point of the route for mob " << pair.first <<
|
|
||||||
" (type " << mob->appearanceData.iNPCType << ") does not correspond with its spawn point." << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructPathNPC(*npcPath, pair.first);
|
|
||||||
mob->staticPath = true;
|
|
||||||
break; // only one NPC per path
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& err) {
|
catch (const std::exception& err) {
|
||||||
@ -866,6 +875,13 @@ static void loadNPCs(json& npcData) {
|
|||||||
|
|
||||||
if (npc["iNPCType"] == 641 || npc["iNPCType"] == 642)
|
if (npc["iNPCType"] == 641 || npc["iNPCType"] == 642)
|
||||||
NPCManager::RespawnPoints.push_back({ npc["iX"], npc["iY"], ((int)npc["iZ"]) + RESURRECT_HEIGHT, instanceID });
|
NPCManager::RespawnPoints.push_back({ npc["iX"], npc["iY"], ((int)npc["iZ"]) + RESURRECT_HEIGHT, instanceID });
|
||||||
|
|
||||||
|
// see if any paths target this NPC
|
||||||
|
NPCPath* npcPath = findApplicablePath(npcID, npc["iNPCType"]);
|
||||||
|
if (npcPath != nullptr) {
|
||||||
|
//std::cout << "[INFO] Found path for NPC " << npcID << std::endl;
|
||||||
|
constructPathNPC(npcID, npcPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (const std::exception& err) {
|
catch (const std::exception& err) {
|
||||||
@ -900,6 +916,13 @@ static void loadMobs(json& npcData, int32_t* nextId) {
|
|||||||
|
|
||||||
NPCManager::NPCs[npcID] = tmp;
|
NPCManager::NPCs[npcID] = tmp;
|
||||||
NPCManager::updateNPCPosition(npcID, npc["iX"], npc["iY"], npc["iZ"], instanceID, npc["iAngle"]);
|
NPCManager::updateNPCPosition(npcID, npc["iX"], npc["iY"], npc["iZ"], instanceID, npc["iAngle"]);
|
||||||
|
|
||||||
|
// see if any paths target this mob
|
||||||
|
NPCPath* npcPath = findApplicablePath(npcID, npc["iNPCType"]);
|
||||||
|
if (npcPath != nullptr) {
|
||||||
|
//std::cout << "[INFO] Found path for mob " << npcID << std::endl;
|
||||||
|
constructPathNPC(npcID, npcPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mob groups
|
// mob groups
|
||||||
@ -923,6 +946,13 @@ static void loadMobs(json& npcData, int32_t* nextId) {
|
|||||||
NPCManager::NPCs[leadID] = tmp;
|
NPCManager::NPCs[leadID] = tmp;
|
||||||
NPCManager::updateNPCPosition(leadID, leader["iX"], leader["iY"], leader["iZ"], instanceID, leader["iAngle"]);
|
NPCManager::updateNPCPosition(leadID, leader["iX"], leader["iY"], leader["iZ"], instanceID, leader["iAngle"]);
|
||||||
|
|
||||||
|
// see if any paths target this group leader
|
||||||
|
NPCPath* npcPath = findApplicablePath(leadID, leader["iNPCType"]);
|
||||||
|
if (npcPath != nullptr) {
|
||||||
|
//std::cout << "[INFO] Found path for mob " << leadID << std::endl;
|
||||||
|
constructPathNPC(leadID, npcPath);
|
||||||
|
}
|
||||||
|
|
||||||
tmp->groupLeader = leadID;
|
tmp->groupLeader = leadID;
|
||||||
|
|
||||||
// followers (have dynamic IDs)
|
// followers (have dynamic IDs)
|
||||||
@ -957,31 +987,6 @@ static void loadMobs(json& npcData, int32_t* nextId) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Find and return the first path that targets either the type or the ID.
|
|
||||||
* If no matches are found, return nullptr
|
|
||||||
*/
|
|
||||||
static NPCPath* findApplicablePath(int32_t id, int32_t type) {
|
|
||||||
NPCPath* match = nullptr;
|
|
||||||
for (auto _path = Transport::NPCPaths.begin(); _path != Transport::NPCPaths.end(); _path++) {
|
|
||||||
// search target IDs
|
|
||||||
for (int32_t pID : _path->targetIDs) {
|
|
||||||
if (id == pID) match = &(*_path);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// search target types
|
|
||||||
for (int32_t pType : _path->targetTypes) {
|
|
||||||
if (type == pType) match = &(*_path);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (match != nullptr)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return match;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Transform `base` based on the value of `patch`.
|
* Transform `base` based on the value of `patch`.
|
||||||
* Parameters must be of the same type and must not be null.
|
* Parameters must be of the same type and must not be null.
|
||||||
|
Loading…
Reference in New Issue
Block a user