mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-04 22:40:05 +00:00
Group Mobs Initial Implementation
* For now only mob.json is read for grouped mobs. * Grouped mobs are fully functional granted the mobs.json is prepared correctly. * Removed redundant move packet.
This commit is contained in:
parent
e9ffbe6148
commit
883a1c17e6
@ -434,6 +434,10 @@ void MobManager::deadStep(Mob *mob, time_t currTime) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// to guide their groupmates, group leaders still need to move despite being dead
|
||||||
|
if (mob->groupLeader == mob->appearanceData.iNPC_ID)
|
||||||
|
roamingStep(mob, currTime);
|
||||||
|
|
||||||
if (mob->killedTime != 0 && currTime - mob->killedTime < mob->regenTime * 100)
|
if (mob->killedTime != 0 && currTime - mob->killedTime < mob->regenTime * 100)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -443,8 +447,21 @@ void MobManager::deadStep(Mob *mob, time_t currTime) {
|
|||||||
mob->state = MobState::ROAMING;
|
mob->state = MobState::ROAMING;
|
||||||
|
|
||||||
// reset position
|
// reset position
|
||||||
mob->appearanceData.iX = mob->spawnX;
|
if (mob->groupLeader != 0) {
|
||||||
mob->appearanceData.iY = mob->spawnY;
|
// mob is a group leader/follower, spawn where the group is.
|
||||||
|
if (Mobs.find(mob->groupLeader) != Mobs.end()) {
|
||||||
|
Mob* leaderMob = Mobs[mob->groupLeader];
|
||||||
|
mob->appearanceData.iX = leaderMob->appearanceData.iX + mob->offsetX;
|
||||||
|
mob->appearanceData.iY = leaderMob->appearanceData.iY + mob->offsetY;
|
||||||
|
} else {
|
||||||
|
std::cout << "[WARN] deadStep: mob cannot find it's leader!" << std::endl;
|
||||||
|
mob->appearanceData.iX = mob->spawnX;
|
||||||
|
mob->appearanceData.iY = mob->spawnY;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mob->appearanceData.iX = mob->spawnX;
|
||||||
|
mob->appearanceData.iY = mob->spawnY;
|
||||||
|
}
|
||||||
mob->appearanceData.iZ = mob->spawnZ;
|
mob->appearanceData.iZ = mob->spawnZ;
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_NPC_NEW, pkt);
|
INITSTRUCT(sP_FE2CL_NPC_NEW, pkt);
|
||||||
@ -523,15 +540,6 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
|||||||
if (distance <= (int)mob->data["m_iAtkRange"]) {
|
if (distance <= (int)mob->data["m_iAtkRange"]) {
|
||||||
// attack logic
|
// attack logic
|
||||||
if (mob->nextAttack == 0) {
|
if (mob->nextAttack == 0) {
|
||||||
INITSTRUCT(sP_FE2CL_NPC_MOVE, pkt);
|
|
||||||
pkt.iNPC_ID = mob->appearanceData.iNPC_ID;
|
|
||||||
pkt.iSpeed = (int)mob->data["m_iRunSpeed"];
|
|
||||||
pkt.iToX = mob->appearanceData.iX;
|
|
||||||
pkt.iToY = mob->appearanceData.iY;
|
|
||||||
pkt.iToZ = mob->target->plr->z;
|
|
||||||
pkt.iMoveStyle = 1;
|
|
||||||
NPCManager::sendToViewable(mob, &pkt, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
|
|
||||||
|
|
||||||
mob->nextAttack = currTime + (int)mob->data["m_iInitalTime"] * 100; //I *think* this is what this is
|
mob->nextAttack = currTime + (int)mob->data["m_iInitalTime"] * 100; //I *think* this is what this is
|
||||||
npcAttackPc(mob, currTime);
|
npcAttackPc(mob, currTime);
|
||||||
} else if (mob->nextAttack != 0 && currTime >= mob->nextAttack) {
|
} else if (mob->nextAttack != 0 && currTime >= mob->nextAttack) {
|
||||||
@ -562,6 +570,10 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
|||||||
pkt.iSpeed = speed;
|
pkt.iSpeed = speed;
|
||||||
pkt.iToX = mob->appearanceData.iX = targ.first;
|
pkt.iToX = mob->appearanceData.iX = targ.first;
|
||||||
pkt.iToY = mob->appearanceData.iY = targ.second;
|
pkt.iToY = mob->appearanceData.iY = targ.second;
|
||||||
|
if (mob->groupLeader != 0 && mob->groupLeader != mob->appearanceData.iNPC_ID) {
|
||||||
|
pkt.iToX += mob->offsetX;
|
||||||
|
pkt.iToY += mob->offsetY;
|
||||||
|
}
|
||||||
pkt.iToZ = mob->target->plr->z;
|
pkt.iToZ = mob->target->plr->z;
|
||||||
pkt.iMoveStyle = 1;
|
pkt.iMoveStyle = 1;
|
||||||
|
|
||||||
@ -591,8 +603,9 @@ void MobManager::roamingStep(Mob *mob, time_t currTime) {
|
|||||||
/*
|
/*
|
||||||
* We reuse nextAttack to avoid scanning for players all the time, but to still
|
* We reuse nextAttack to avoid scanning for players all the time, but to still
|
||||||
* do so more often than if we waited for nextMovement (which is way too slow).
|
* do so more often than if we waited for nextMovement (which is way too slow).
|
||||||
|
* In the case of group leaders, this step will be called by dead mobs, so disable attack.
|
||||||
*/
|
*/
|
||||||
if (mob->nextAttack == 0 || currTime >= mob->nextAttack) {
|
if (mob->state != MobState::DEAD && (mob->nextAttack == 0 || currTime >= mob->nextAttack)) {
|
||||||
mob->nextAttack = currTime + 500;
|
mob->nextAttack = currTime + 500;
|
||||||
if (aggroCheck(mob, currTime))
|
if (aggroCheck(mob, currTime))
|
||||||
return;
|
return;
|
||||||
@ -615,6 +628,9 @@ void MobManager::roamingStep(Mob *mob, time_t currTime) {
|
|||||||
* so we don't have to check if there's already entries in the queue since we know there won't be.
|
* so we don't have to check if there's already entries in the queue since we know there won't be.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
if (mob->groupLeader != 0 && mob->groupLeader != mob->appearanceData.iNPC_ID) // don't roam by yourself without group leader
|
||||||
|
return;
|
||||||
|
|
||||||
int xStart = mob->spawnX - mob->idleRange/2;
|
int xStart = mob->spawnX - mob->idleRange/2;
|
||||||
int yStart = mob->spawnY - mob->idleRange/2;
|
int yStart = mob->spawnY - mob->idleRange/2;
|
||||||
int speed = mob->data["m_iWalkSpeed"];
|
int speed = mob->data["m_iWalkSpeed"];
|
||||||
@ -622,10 +638,6 @@ void MobManager::roamingStep(Mob *mob, time_t currTime) {
|
|||||||
int farX, farY;
|
int farX, farY;
|
||||||
int distance; // for short walk detection
|
int distance; // for short walk detection
|
||||||
|
|
||||||
/*
|
|
||||||
* We don't want the mob to just take one step and stop, so we make sure
|
|
||||||
* it has walked a half-decent distance.
|
|
||||||
*/
|
|
||||||
do {
|
do {
|
||||||
farX = xStart + rand() % mob->idleRange;
|
farX = xStart + rand() % mob->idleRange;
|
||||||
farY = yStart + rand() % mob->idleRange;
|
farY = yStart + rand() % mob->idleRange;
|
||||||
@ -644,6 +656,26 @@ void MobManager::roamingStep(Mob *mob, time_t currTime) {
|
|||||||
// add a route to the queue; to be processed in TransportManager::stepNPCPathing()
|
// add a route to the queue; to be processed in TransportManager::stepNPCPathing()
|
||||||
TransportManager::lerp(&queue, from, to, speed);
|
TransportManager::lerp(&queue, from, to, speed);
|
||||||
TransportManager::NPCQueues[mob->appearanceData.iNPC_ID] = queue;
|
TransportManager::NPCQueues[mob->appearanceData.iNPC_ID] = queue;
|
||||||
|
|
||||||
|
if (mob->groupLeader != 0 && mob->groupLeader == mob->appearanceData.iNPC_ID) {
|
||||||
|
// make followers follow this npc.
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (mob->groupMember[i] == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (Mobs.find(mob->groupMember[i]) == Mobs.end()) {
|
||||||
|
std::cout << "[WARN] roamingStep: leader can't find a group member!" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::queue<WarpLocation> queue2;
|
||||||
|
Mob* followerMob = Mobs[mob->groupMember[i]];
|
||||||
|
from = { followerMob->appearanceData.iX, followerMob->appearanceData.iY, followerMob->appearanceData.iZ };
|
||||||
|
to = { farX + followerMob->offsetX, farY + followerMob->offsetY, followerMob->appearanceData.iZ };
|
||||||
|
TransportManager::lerp(&queue2, from, to, speed);
|
||||||
|
TransportManager::NPCQueues[followerMob->appearanceData.iNPC_ID] = queue2;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MobManager::retreatStep(Mob *mob, time_t currTime) {
|
void MobManager::retreatStep(Mob *mob, time_t currTime) {
|
||||||
|
@ -51,6 +51,11 @@ struct Mob : public BaseNPC {
|
|||||||
// drop
|
// drop
|
||||||
int dropType;
|
int dropType;
|
||||||
|
|
||||||
|
// group
|
||||||
|
int groupLeader = 0;
|
||||||
|
int offsetX, offsetY;
|
||||||
|
int groupMember[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
// temporary; until we're sure what's what
|
// temporary; until we're sure what's what
|
||||||
nlohmann::json data;
|
nlohmann::json data;
|
||||||
|
|
||||||
|
@ -201,17 +201,51 @@ void TableData::init() {
|
|||||||
|
|
||||||
// read file into json
|
// read file into json
|
||||||
inFile >> npcData;
|
inFile >> npcData;
|
||||||
|
int leaderMob = -1;
|
||||||
|
int leaderMobFollowers = 0;
|
||||||
|
|
||||||
for (nlohmann::json::iterator _npc = npcData.begin(); _npc != npcData.end(); _npc++) {
|
for (nlohmann::json::iterator _npc = npcData.begin(); _npc != npcData.end(); _npc++) {
|
||||||
auto npc = _npc.value();
|
auto npc = _npc.value();
|
||||||
auto td = NPCManager::NPCData[(int)npc["iNPCType"]];
|
auto td = NPCManager::NPCData[(int)npc["iNPCType"]];
|
||||||
uint64_t instanceID = npc.find("iMapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["iMapNum"];
|
uint64_t instanceID = npc.find("iMapNum") == npc.end() ? INSTANCE_OVERWORLD : (int)npc["iMapNum"];
|
||||||
|
|
||||||
Mob *tmp = new Mob(npc["iX"], npc["iY"], npc["iZ"], npc["iAngle"], instanceID, npc["iNPCType"], npc["iHP"], td, nextId);
|
Mob *tmp = new Mob(npc["iX"], npc["iY"], npc["iZ"], npc["iAngle"], instanceID, npc["iNPCType"], npc["iHP"], td, nextId);
|
||||||
|
|
||||||
NPCManager::NPCs[nextId] = tmp;
|
NPCManager::NPCs[nextId] = tmp;
|
||||||
MobManager::Mobs[nextId] = (Mob*)NPCManager::NPCs[nextId];
|
MobManager::Mobs[nextId] = (Mob*)NPCManager::NPCs[nextId];
|
||||||
NPCManager::updateNPCPosition(nextId, npc["iX"], npc["iY"], npc["iZ"], instanceID, npc["iAngle"]);
|
NPCManager::updateNPCPosition(nextId, npc["iX"], npc["iY"], npc["iZ"], instanceID, npc["iAngle"]);
|
||||||
|
|
||||||
|
// handling groups
|
||||||
|
if (npc.find("iOffsetX") != npc.end() && MobManager::Mobs.find(nextId) != MobManager::Mobs.end()) {
|
||||||
|
Mob* currNpc = MobManager::Mobs[nextId];
|
||||||
|
|
||||||
|
if (leaderMob == -1) {
|
||||||
|
if (MobManager::Mobs.find(nextId-1) != MobManager::Mobs.end()) {
|
||||||
|
Mob* leadNpc = MobManager::Mobs[nextId-1];
|
||||||
|
leaderMob = nextId-1;
|
||||||
|
leadNpc->groupMember[leaderMobFollowers] = nextId;
|
||||||
|
leaderMobFollowers++;
|
||||||
|
currNpc->groupLeader = nextId-1;
|
||||||
|
leadNpc->groupLeader = nextId-1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (MobManager::Mobs.find(leaderMob) != MobManager::Mobs.end()) {
|
||||||
|
Mob* leadNpc = MobManager::Mobs[leaderMob];
|
||||||
|
leaderMob = leaderMob;
|
||||||
|
leadNpc->groupMember[leaderMobFollowers] = nextId;
|
||||||
|
leaderMobFollowers++;
|
||||||
|
currNpc->groupLeader = leaderMob;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currNpc->offsetX = (int)npc["iOffsetX"];
|
||||||
|
currNpc->offsetY = npc.find("iOffsetY") == npc.end() ? 0 : (int)npc["iOffsetY"];
|
||||||
|
std::cout << "[INFO] Added group NPC " << nextId << " to ID " << currNpc->groupLeader << std::endl;
|
||||||
|
} else {
|
||||||
|
leaderMob = -1;
|
||||||
|
leaderMobFollowers = 0;
|
||||||
|
}
|
||||||
|
|
||||||
nextId++;
|
nextId++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user