Group warping & mob movement smoothing

* Warping into IZs and Fusion Lairs now will also take into account your group members.
* MobManager lerp does not confusingly divide speed by 2 anymore.
* Mobs pursue their targets more smoothly, they will avoid phasing into the player during combat.
* Nerfed retreat speed by a factor of 1.5, normal mobs retreated way too quickly however mobs like Don Doom and Bad Max do not retreat fast enough.
* Bugfixed sendPlayerTo, it did not call updatePlayerPosition leaving undesirable anomalies.
This commit is contained in:
Jade 2020-10-17 05:58:51 +01:00 committed by Gent Semaj
parent bf3c19764b
commit 2782706355
No known key found for this signature in database
GPG Key ID: 76A006BEBA710050
3 changed files with 55 additions and 16 deletions

View File

@ -467,6 +467,14 @@ 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;
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) {
@ -477,7 +485,9 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
// movement logic // movement logic
if (mob->nextMovement != 0 && currTime < mob->nextMovement) if (mob->nextMovement != 0 && currTime < mob->nextMovement)
return; return;
mob->nextMovement = currTime + 500; mob->nextMovement = currTime + 399;
if (currTime >= mob->nextAttack)
mob->nextAttack = 0;
int speed = mob->data["m_iRunSpeed"]; int speed = mob->data["m_iRunSpeed"];
@ -485,7 +495,7 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
if (mob->appearanceData.iConditionBitFlag & CSB_BIT_DN_MOVE_SPEED) if (mob->appearanceData.iConditionBitFlag & CSB_BIT_DN_MOVE_SPEED)
speed /= 2; speed /= 2;
auto targ = lerp(mob->appearanceData.iX, mob->appearanceData.iY, mob->target->plr->x, mob->target->plr->y, speed); auto targ = lerp(mob->appearanceData.iX, mob->appearanceData.iY, mob->target->plr->x, mob->target->plr->y,std::min(distance-(int)mob->data["m_iAtkRange"]+1, speed*2/5));
NPCManager::updateNPCPosition(mob->appearanceData.iNPC_ID, targ.first, targ.second, mob->appearanceData.iZ); NPCManager::updateNPCPosition(mob->appearanceData.iNPC_ID, targ.first, targ.second, mob->appearanceData.iZ);
@ -493,9 +503,11 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
pkt.iNPC_ID = mob->appearanceData.iNPC_ID; pkt.iNPC_ID = mob->appearanceData.iNPC_ID;
pkt.iSpeed = speed; pkt.iSpeed = speed;
pkt.iToX = mob->appearanceData.iX = targ.first; pkt.iToX = (targ.first - mob->appearanceData.iX) * 5 / 2 + mob->appearanceData.iX;
pkt.iToY = mob->appearanceData.iY = targ.second; pkt.iToY = (targ.second - mob->appearanceData.iY) * 5 / 2 + mob->appearanceData.iY;
pkt.iToZ = mob->appearanceData.iZ; mob->appearanceData.iX = targ.first;
mob->appearanceData.iY = targ.second;
pkt.iToZ = mob->target->plr->z;
// notify all nearby players // notify all nearby players
NPCManager::sendToViewable(mob, &pkt, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE)); NPCManager::sendToViewable(mob, &pkt, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
@ -581,7 +593,7 @@ void MobManager::retreatStep(Mob *mob, time_t currTime) {
if (mob->nextMovement != 0 && currTime < mob->nextMovement) if (mob->nextMovement != 0 && currTime < mob->nextMovement)
return; return;
mob->nextMovement = currTime + 500; mob->nextMovement = currTime + 399;
// distance between spawn point and current location // distance between spawn point and current location
int distance = hypot(mob->appearanceData.iX - mob->roamX, mob->appearanceData.iY - mob->roamY); int distance = hypot(mob->appearanceData.iX - mob->roamX, mob->appearanceData.iY - mob->roamY);
@ -590,12 +602,16 @@ void MobManager::retreatStep(Mob *mob, time_t currTime) {
if (distance > 10) { if (distance > 10) {
INITSTRUCT(sP_FE2CL_NPC_MOVE, pkt); INITSTRUCT(sP_FE2CL_NPC_MOVE, pkt);
auto targ = lerp(mob->appearanceData.iX, mob->appearanceData.iY, mob->roamX, mob->roamY, (int)mob->data["m_iRunSpeed"] * 3); auto targ = lerp(mob->appearanceData.iX, mob->appearanceData.iY, mob->roamX, mob->roamY, (int)mob->data["m_iRunSpeed"]*4/5);
pkt.iNPC_ID = mob->appearanceData.iNPC_ID; pkt.iNPC_ID = mob->appearanceData.iNPC_ID;
pkt.iSpeed = (int)mob->data["m_iRunSpeed"] * 3; pkt.iSpeed = (int)mob->data["m_iRunSpeed"] * 2;
pkt.iToX = mob->appearanceData.iX = targ.first; mob->appearanceData.iX = targ.first;
pkt.iToY = mob->appearanceData.iY = targ.second; mob->appearanceData.iY = targ.second;
pkt.iToX = (targ.first - mob->appearanceData.iX) * 5 / 2 + mob->appearanceData.iX;
pkt.iToY = (targ.second - mob->appearanceData.iY) * 5 / 2 + mob->appearanceData.iY;
mob->appearanceData.iX = targ.first;
mob->appearanceData.iY = targ.second;
pkt.iToZ = mob->appearanceData.iZ; pkt.iToZ = mob->appearanceData.iZ;
// notify all nearby players // notify all nearby players
@ -667,8 +683,6 @@ void MobManager::step(CNServer *serv, time_t currTime) {
std::pair<int,int> MobManager::lerp(int x1, int y1, int x2, int y2, int speed) { std::pair<int,int> MobManager::lerp(int x1, int y1, int x2, int y2, int speed) {
std::pair<int,int> ret = {x1, y1}; std::pair<int,int> ret = {x1, y1};
speed /= 2;
if (speed == 0) if (speed == 0)
return ret; return ret;

View File

@ -596,8 +596,31 @@ void NPCManager::handleWarp(CNSocket* sock, int32_t warpId) {
ChunkManager::createInstance(instanceID); ChunkManager::createInstance(instanceID);
} }
if (plrv.plr->iID == plrv.plr->iIDGroup && plrv.plr->groupCnt == 1)
PlayerManager::sendPlayerTo(sock, Warps[warpId].x, Warps[warpId].y, Warps[warpId].z, instanceID); PlayerManager::sendPlayerTo(sock, Warps[warpId].x, Warps[warpId].y, Warps[warpId].z, instanceID);
} else { else {
Player* leaderPlr = PlayerManager::getPlayerFromID(plrv.plr->iIDGroup);
for (int i = 0; i < leaderPlr->groupCnt; i++) {
Player* otherPlr = PlayerManager::getPlayerFromID(leaderPlr->groupIDs[i]);
CNSocket* sockTo = PlayerManager::getSockFromID(leaderPlr->groupIDs[i]);
if (otherPlr == nullptr || sockTo == nullptr)
continue;
if (otherPlr->instanceID == 0) {
otherPlr->lastX = otherPlr->x;
otherPlr->lastY = otherPlr->y;
otherPlr->lastZ = otherPlr->z;
otherPlr->lastAngle = otherPlr->angle;
}
PlayerManager::sendPlayerTo(sockTo, Warps[warpId].x, Warps[warpId].y, Warps[warpId].z, instanceID);
}
}
}
else
{
INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC, resp); //Can only be used for exiting instances because it sets the instance flag to false INITSTRUCT(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC, resp); //Can only be used for exiting instances because it sets the instance flag to false
resp.iX = Warps[warpId].x; resp.iX = Warps[warpId].x;
resp.iY = Warps[warpId].y; resp.iY = Warps[warpId].y;

View File

@ -261,6 +261,7 @@ void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z, uint64_t I
PlayerManager::removePlayerFromChunks(plrv.currentChunks, sock); PlayerManager::removePlayerFromChunks(plrv.currentChunks, sock);
plrv.currentChunks.clear(); plrv.currentChunks.clear();
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_NPC_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC)); sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_WARP_USE_NPC_SUCC, sizeof(sP_FE2CL_REP_PC_WARP_USE_NPC_SUCC));
updatePlayerPosition(sock, X, Y, Z);
} }
ChunkManager::destroyInstanceIfEmpty(fromInstance); ChunkManager::destroyInstanceIfEmpty(fromInstance);
@ -279,6 +280,7 @@ void PlayerManager::sendPlayerTo(CNSocket* sock, int X, int Y, int Z) {
plrv.currentChunks.clear(); plrv.currentChunks.clear();
plrv.chunkPos = std::make_tuple(0, 0, plrv.plr->instanceID); plrv.chunkPos = std::make_tuple(0, 0, plrv.plr->instanceID);
sock->sendPacket((void*)&pkt, P_FE2CL_REP_PC_GOTO_SUCC, sizeof(sP_FE2CL_REP_PC_GOTO_SUCC)); sock->sendPacket((void*)&pkt, P_FE2CL_REP_PC_GOTO_SUCC, sizeof(sP_FE2CL_REP_PC_GOTO_SUCC));
updatePlayerPosition(sock, X, Y, Z);
} }
void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) { void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {