mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 21:40:05 +00:00
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:
parent
bf3c19764b
commit
2782706355
@ -467,7 +467,15 @@ 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) {
|
||||||
mob->nextAttack = currTime + (int)mob->data["m_iInitalTime"] * 100; // I *think* this is what this is
|
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
|
||||||
npcAttackPc(mob, currTime);
|
npcAttackPc(mob, currTime);
|
||||||
} else if (mob->nextAttack != 0 && currTime >= mob->nextAttack) {
|
} else if (mob->nextAttack != 0 && currTime >= mob->nextAttack) {
|
||||||
mob->nextAttack = currTime + (int)mob->data["m_iDelayTime"] * 100;
|
mob->nextAttack = currTime + (int)mob->data["m_iDelayTime"] * 100;
|
||||||
@ -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;
|
||||||
|
|
||||||
|
@ -596,9 +596,32 @@ void NPCManager::handleWarp(CNSocket* sock, int32_t warpId) {
|
|||||||
ChunkManager::createInstance(instanceID);
|
ChunkManager::createInstance(instanceID);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerManager::sendPlayerTo(sock, Warps[warpId].x, Warps[warpId].y, Warps[warpId].z, instanceID);
|
if (plrv.plr->iID == plrv.plr->iIDGroup && plrv.plr->groupCnt == 1)
|
||||||
} else {
|
PlayerManager::sendPlayerTo(sock, Warps[warpId].x, Warps[warpId].y, Warps[warpId].z, instanceID);
|
||||||
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
|
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
|
||||||
resp.iX = Warps[warpId].x;
|
resp.iX = Warps[warpId].x;
|
||||||
resp.iY = Warps[warpId].y;
|
resp.iY = Warps[warpId].y;
|
||||||
resp.iZ = Warps[warpId].z;
|
resp.iZ = Warps[warpId].z;
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user