mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 13:30:06 +00:00
Mob-related cleanup.
* NPCs now keep track of their chunk information like PlayerView does for players * NPCManager::sendToViewable() parallels PlayerManager::sendToViewable() * Nano damage and debuffs now count as attacking a mob * Mobs will de-aggro if something else killed their target
This commit is contained in:
parent
72d625fd8d
commit
279cb78d5f
@ -60,33 +60,10 @@ void MobManager::pcAttackNpcs(CNSocket *sock, CNPacketData *data) {
|
|||||||
}
|
}
|
||||||
Mob *mob = Mobs[pktdata[i]];
|
Mob *mob = Mobs[pktdata[i]];
|
||||||
|
|
||||||
// cannot kill mobs multiple times; cannot harm retreating mobs
|
int damage = hitMob(sock, mob, 100);
|
||||||
if (mob->state != MobState::ROAMING && mob->state != MobState::COMBAT) {
|
|
||||||
respdata[i].iID = mob->appearanceData.iNPC_ID;
|
|
||||||
respdata[i].iHP = mob->appearanceData.iHP;
|
|
||||||
respdata[i].iHitFlag = 2; // probably still necessary
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mob->state == MobState::ROAMING) {
|
|
||||||
assert(mob->target == nullptr);
|
|
||||||
mob->target = sock;
|
|
||||||
mob->state = MobState::COMBAT;
|
|
||||||
mob->nextMovement = getTime();
|
|
||||||
//std::cout << "combat state\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
mob->appearanceData.iHP -= 100;
|
|
||||||
|
|
||||||
// wake up sleeping monster
|
|
||||||
// TODO: remove client-side bit somehow
|
|
||||||
mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ;
|
|
||||||
|
|
||||||
if (mob->appearanceData.iHP <= 0)
|
|
||||||
killMob(mob->target, mob);
|
|
||||||
|
|
||||||
respdata[i].iID = mob->appearanceData.iNPC_ID;
|
respdata[i].iID = mob->appearanceData.iNPC_ID;
|
||||||
respdata[i].iDamage = 100;
|
respdata[i].iDamage = damage;
|
||||||
respdata[i].iHP = mob->appearanceData.iHP;
|
respdata[i].iHP = mob->appearanceData.iHP;
|
||||||
respdata[i].iHitFlag = 2; // hitscan, not a rocket or a grenade
|
respdata[i].iHitFlag = 2; // hitscan, not a rocket or a grenade
|
||||||
}
|
}
|
||||||
@ -131,7 +108,6 @@ void MobManager::npcAttackPc(Mob *mob) {
|
|||||||
if (plr->HP <= 0) {
|
if (plr->HP <= 0) {
|
||||||
mob->target = nullptr;
|
mob->target = nullptr;
|
||||||
mob->state = MobState::RETREAT;
|
mob->state = MobState::RETREAT;
|
||||||
//std::cout << "retreat state\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,14 +160,37 @@ void MobManager::giveReward(CNSocket *sock) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int MobManager::hitMob(CNSocket *sock, Mob *mob, int damage) {
|
||||||
|
// cannot kill mobs multiple times; cannot harm retreating mobs
|
||||||
|
if (mob->state != MobState::ROAMING && mob->state != MobState::COMBAT) {
|
||||||
|
return 0; // no damage
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mob->state == MobState::ROAMING) {
|
||||||
|
assert(mob->target == nullptr);
|
||||||
|
mob->target = sock;
|
||||||
|
mob->state = MobState::COMBAT;
|
||||||
|
mob->nextMovement = getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
mob->appearanceData.iHP -= damage;
|
||||||
|
|
||||||
|
// wake up sleeping monster
|
||||||
|
// TODO: remove client-side bit somehow
|
||||||
|
mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ;
|
||||||
|
|
||||||
|
if (mob->appearanceData.iHP <= 0)
|
||||||
|
killMob(mob->target, mob);
|
||||||
|
|
||||||
|
return damage;
|
||||||
|
}
|
||||||
|
|
||||||
void MobManager::killMob(CNSocket *sock, Mob *mob) {
|
void MobManager::killMob(CNSocket *sock, Mob *mob) {
|
||||||
mob->state = MobState::DEAD;
|
mob->state = MobState::DEAD;
|
||||||
mob->target = nullptr;
|
mob->target = nullptr;
|
||||||
mob->appearanceData.iConditionBitFlag = 0;
|
mob->appearanceData.iConditionBitFlag = 0;
|
||||||
mob->killedTime = getTime(); // XXX: maybe introduce a shard-global time for each step?
|
mob->killedTime = getTime(); // XXX: maybe introduce a shard-global time for each step?
|
||||||
|
|
||||||
//std::cout << "dead state mob " << mob->appearanceData.iNPC_ID << std::endl;
|
|
||||||
|
|
||||||
giveReward(sock);
|
giveReward(sock);
|
||||||
MissionManager::mobKilled(sock, mob->appearanceData.iNPCType);
|
MissionManager::mobKilled(sock, mob->appearanceData.iNPCType);
|
||||||
|
|
||||||
@ -199,9 +198,6 @@ void MobManager::killMob(CNSocket *sock, Mob *mob) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MobManager::deadStep(Mob *mob, time_t currTime) {
|
void MobManager::deadStep(Mob *mob, time_t currTime) {
|
||||||
auto chunk = ChunkManager::grabChunk(mob->appearanceData.iX, mob->appearanceData.iY);
|
|
||||||
auto chunks = ChunkManager::grabChunks(chunk);
|
|
||||||
|
|
||||||
// despawn the mob after a short delay
|
// despawn the mob after a short delay
|
||||||
if (mob->killedTime != 0 && !mob->despawned && currTime - mob->killedTime > 2000) {
|
if (mob->killedTime != 0 && !mob->despawned && currTime - mob->killedTime > 2000) {
|
||||||
mob->despawned = true;
|
mob->despawned = true;
|
||||||
@ -210,11 +206,7 @@ void MobManager::deadStep(Mob *mob, time_t currTime) {
|
|||||||
|
|
||||||
pkt.iNPC_ID = mob->appearanceData.iNPC_ID;
|
pkt.iNPC_ID = mob->appearanceData.iNPC_ID;
|
||||||
|
|
||||||
for (Chunk *chunk : chunks) {
|
NPCManager::sendToViewable(mob, &pkt, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
||||||
for (CNSocket *s : chunk->players) {
|
|
||||||
s->sendPacket(&pkt, P_FE2CL_NPC_EXIT, sizeof(sP_FE2CL_NPC_EXIT));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if it was summoned, remove it permanently
|
// if it was summoned, remove it permanently
|
||||||
if (mob->summoned) {
|
if (mob->summoned) {
|
||||||
@ -231,18 +223,13 @@ void MobManager::deadStep(Mob *mob, time_t currTime) {
|
|||||||
|
|
||||||
mob->appearanceData.iHP = mob->maxHealth;
|
mob->appearanceData.iHP = mob->maxHealth;
|
||||||
mob->state = MobState::ROAMING;
|
mob->state = MobState::ROAMING;
|
||||||
//std::cout << "roaming state\n";
|
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_NPC_NEW, pkt);
|
INITSTRUCT(sP_FE2CL_NPC_NEW, pkt);
|
||||||
|
|
||||||
pkt.NPCAppearanceData = mob->appearanceData;
|
pkt.NPCAppearanceData = mob->appearanceData;
|
||||||
|
|
||||||
// notify all nearby players
|
// notify all nearby players
|
||||||
for (Chunk *chunk : chunks) {
|
NPCManager::sendToViewable(mob, &pkt, P_FE2CL_NPC_NEW, sizeof(sP_FE2CL_NPC_NEW));
|
||||||
for (CNSocket *s : chunk->players) {
|
|
||||||
s->sendPacket(&pkt, P_FE2CL_NPC_NEW, sizeof(sP_FE2CL_NPC_NEW));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MobManager::combatStep(Mob *mob, time_t currTime) {
|
void MobManager::combatStep(Mob *mob, time_t currTime) {
|
||||||
@ -252,14 +239,16 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
|||||||
if (PlayerManager::players.find(mob->target) == PlayerManager::players.end()) {
|
if (PlayerManager::players.find(mob->target) == PlayerManager::players.end()) {
|
||||||
mob->target = nullptr;
|
mob->target = nullptr;
|
||||||
mob->state = MobState::RETREAT;
|
mob->state = MobState::RETREAT;
|
||||||
//std::cout << "RETREAT state\n";
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Player *plr = PlayerManager::getPlayer(mob->target);
|
Player *plr = PlayerManager::getPlayer(mob->target);
|
||||||
|
|
||||||
// skip attack/move if stunned or asleep
|
// did something else kill the player in the mean time?
|
||||||
if (mob->appearanceData.iConditionBitFlag & (CSB_BIT_STUN|CSB_BIT_MEZ))
|
if (plr->HP <= 0) {
|
||||||
|
mob->target = nullptr;
|
||||||
|
mob->state = MobState::RETREAT;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int distance = hypot(plr->x - mob->appearanceData.iX, plr->y - mob->appearanceData.iY);
|
int distance = hypot(plr->x - mob->appearanceData.iX, plr->y - mob->appearanceData.iY);
|
||||||
|
|
||||||
@ -268,7 +257,6 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
|||||||
* No, I'm not 100% sure this is how it's supposed to work.
|
* No, I'm not 100% sure this is how it's supposed to work.
|
||||||
*/
|
*/
|
||||||
if (distance <= (int)mob->data["m_iAtkRange"]) {
|
if (distance <= (int)mob->data["m_iAtkRange"]) {
|
||||||
//std::cout << "attack logic\n";
|
|
||||||
// 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
|
mob->nextAttack = currTime + (int)mob->data["m_iInitalTime"] * 100; // I *think* this is what this is
|
||||||
@ -278,8 +266,6 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
|||||||
npcAttackPc(mob);
|
npcAttackPc(mob);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//std::cout << "movement logic\n";
|
|
||||||
//std::cout << "distance: " << distance << " attack range: " << mob->data["m_iAtkRange"] << std::endl;
|
|
||||||
// movement logic
|
// movement logic
|
||||||
if (mob->nextMovement != 0 && currTime < mob->nextMovement)
|
if (mob->nextMovement != 0 && currTime < mob->nextMovement)
|
||||||
return;
|
return;
|
||||||
@ -301,15 +287,8 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
|||||||
pkt.iToY = mob->appearanceData.iY = targ.second;
|
pkt.iToY = mob->appearanceData.iY = targ.second;
|
||||||
pkt.iToZ = mob->appearanceData.iZ;
|
pkt.iToZ = mob->appearanceData.iZ;
|
||||||
|
|
||||||
auto chunk = ChunkManager::grabChunk(mob->appearanceData.iX, mob->appearanceData.iY);
|
|
||||||
auto chunks = ChunkManager::grabChunks(chunk);
|
|
||||||
|
|
||||||
// notify all nearby players
|
// notify all nearby players
|
||||||
for (Chunk *chunk : chunks) {
|
NPCManager::sendToViewable(mob, &pkt, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
|
||||||
for (CNSocket *s : chunk->players) {
|
|
||||||
s->sendPacket(&pkt, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// retreat if kited too far
|
// retreat if kited too far
|
||||||
@ -317,7 +296,6 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
|
|||||||
if (distance >= mob->data["m_iCombatRange"]) {
|
if (distance >= mob->data["m_iCombatRange"]) {
|
||||||
mob->target = nullptr;
|
mob->target = nullptr;
|
||||||
mob->state = MobState::RETREAT;
|
mob->state = MobState::RETREAT;
|
||||||
//std::cout << "retreat state\n";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,10 +316,6 @@ void MobManager::roamingStep(Mob *mob, time_t currTime) {
|
|||||||
int delay = (int)mob->data["m_iDelayTime"] * 1000;
|
int delay = (int)mob->data["m_iDelayTime"] * 1000;
|
||||||
mob->nextMovement = currTime + delay/2 + rand() % (delay/2);
|
mob->nextMovement = currTime + delay/2 + rand() % (delay/2);
|
||||||
|
|
||||||
// skip move if stunned or asleep
|
|
||||||
if (mob->appearanceData.iConditionBitFlag & (CSB_BIT_STUN|CSB_BIT_MEZ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_NPC_MOVE, pkt);
|
INITSTRUCT(sP_FE2CL_NPC_MOVE, pkt);
|
||||||
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;
|
||||||
@ -362,15 +336,8 @@ void MobManager::roamingStep(Mob *mob, time_t currTime) {
|
|||||||
pkt.iToY = mob->appearanceData.iY = targ.second;
|
pkt.iToY = mob->appearanceData.iY = targ.second;
|
||||||
pkt.iToZ = mob->appearanceData.iZ;
|
pkt.iToZ = mob->appearanceData.iZ;
|
||||||
|
|
||||||
auto chunk = ChunkManager::grabChunk(mob->appearanceData.iX, mob->appearanceData.iY);
|
|
||||||
auto chunks = ChunkManager::grabChunks(chunk);
|
|
||||||
|
|
||||||
// notify all nearby players
|
// notify all nearby players
|
||||||
for (Chunk *chunk : chunks) {
|
NPCManager::sendToViewable(mob, &pkt, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
|
||||||
for (CNSocket *s : chunk->players) {
|
|
||||||
s->sendPacket(&pkt, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MobManager::retreatStep(Mob *mob, time_t currTime) {
|
void MobManager::retreatStep(Mob *mob, time_t currTime) {
|
||||||
@ -380,9 +347,6 @@ void MobManager::retreatStep(Mob *mob, time_t currTime) {
|
|||||||
if (distance > mob->data["m_iIdleRange"]) {
|
if (distance > mob->data["m_iIdleRange"]) {
|
||||||
INITSTRUCT(sP_FE2CL_NPC_MOVE, pkt);
|
INITSTRUCT(sP_FE2CL_NPC_MOVE, pkt);
|
||||||
|
|
||||||
auto chunk = ChunkManager::grabChunk(mob->appearanceData.iX, mob->appearanceData.iY);
|
|
||||||
auto chunks = ChunkManager::grabChunks(chunk);
|
|
||||||
|
|
||||||
auto targ = lerp(mob->appearanceData.iX, mob->appearanceData.iY, mob->spawnX, mob->spawnY, mob->data["m_iRunSpeed"]);
|
auto targ = lerp(mob->appearanceData.iX, mob->appearanceData.iY, mob->spawnX, mob->spawnY, mob->data["m_iRunSpeed"]);
|
||||||
|
|
||||||
pkt.iNPC_ID = mob->appearanceData.iNPC_ID;
|
pkt.iNPC_ID = mob->appearanceData.iNPC_ID;
|
||||||
@ -392,17 +356,12 @@ void MobManager::retreatStep(Mob *mob, time_t currTime) {
|
|||||||
pkt.iToZ = mob->appearanceData.iZ;
|
pkt.iToZ = mob->appearanceData.iZ;
|
||||||
|
|
||||||
// notify all nearby players
|
// notify all nearby players
|
||||||
for (Chunk *chunk : chunks) {
|
NPCManager::sendToViewable(mob, &pkt, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
|
||||||
for (CNSocket *s : chunk->players) {
|
|
||||||
s->sendPacket(&pkt, P_FE2CL_NPC_MOVE, sizeof(sP_FE2CL_NPC_MOVE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we got there
|
// if we got there
|
||||||
if (distance <= mob->data["m_iIdleRange"]) {
|
if (distance <= mob->data["m_iIdleRange"]) {
|
||||||
mob->state = MobState::ROAMING;
|
mob->state = MobState::ROAMING;
|
||||||
//std::cout << "roaming state\n";
|
|
||||||
mob->appearanceData.iHP = mob->maxHealth;
|
mob->appearanceData.iHP = mob->maxHealth;
|
||||||
mob->killedTime = 0;
|
mob->killedTime = 0;
|
||||||
mob->nextAttack = 0;
|
mob->nextAttack = 0;
|
||||||
@ -423,6 +382,11 @@ void MobManager::step(CNServer *serv, time_t currTime) {
|
|||||||
if (!settings::SIMULATEMOBS && pair.second->state != MobState::DEAD)
|
if (!settings::SIMULATEMOBS && pair.second->state != MobState::DEAD)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// skip attack/move if stunned or asleep
|
||||||
|
if (pair.second->appearanceData.iConditionBitFlag & (CSB_BIT_STUN|CSB_BIT_MEZ)
|
||||||
|
&& (pair.second->state == MobState::ROAMING || pair.second->state == MobState::COMBAT))
|
||||||
|
continue;
|
||||||
|
|
||||||
switch (pair.second->state) {
|
switch (pair.second->state) {
|
||||||
case MobState::INACTIVE:
|
case MobState::INACTIVE:
|
||||||
// no-op
|
// no-op
|
||||||
|
@ -94,6 +94,7 @@ namespace MobManager {
|
|||||||
void dotDamageOnOff(CNSocket *sock, CNPacketData *data);
|
void dotDamageOnOff(CNSocket *sock, CNPacketData *data);
|
||||||
|
|
||||||
void npcAttackPc(Mob *mob);
|
void npcAttackPc(Mob *mob);
|
||||||
|
int hitMob(CNSocket *sock, Mob *mob, int damage);
|
||||||
void killMob(CNSocket *sock, Mob *mob);
|
void killMob(CNSocket *sock, Mob *mob);
|
||||||
void giveReward(CNSocket *sock);
|
void giveReward(CNSocket *sock);
|
||||||
std::pair<int,int> lerp(int, int, int, int, int);
|
std::pair<int,int> lerp(int, int, int, int, int);
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CNStructs.hpp"
|
#include "CNStructs.hpp"
|
||||||
|
#include "ChunkManager.hpp"
|
||||||
|
|
||||||
class BaseNPC {
|
class BaseNPC {
|
||||||
public:
|
public:
|
||||||
sNPCAppearanceData appearanceData;
|
sNPCAppearanceData appearanceData;
|
||||||
NPCClass npcClass;
|
NPCClass npcClass;
|
||||||
|
std::pair<int, int> chunkPos;
|
||||||
|
std::vector<Chunk*> currentChunks;
|
||||||
|
|
||||||
BaseNPC() {};
|
BaseNPC() {};
|
||||||
BaseNPC(int x, int y, int z, int type, int id) {
|
BaseNPC(int x, int y, int z, int type, int id) {
|
||||||
@ -18,6 +21,9 @@ public:
|
|||||||
appearanceData.iConditionBitFlag = 0;
|
appearanceData.iConditionBitFlag = 0;
|
||||||
appearanceData.iBarkerType = 0;
|
appearanceData.iBarkerType = 0;
|
||||||
appearanceData.iNPC_ID = id;
|
appearanceData.iNPC_ID = id;
|
||||||
|
|
||||||
|
chunkPos = ChunkManager::grabChunk(x, y);
|
||||||
|
currentChunks = ChunkManager::grabChunks(chunkPos);
|
||||||
};
|
};
|
||||||
BaseNPC(int x, int y, int z, int type, int id, NPCClass classType) : BaseNPC(x, y, z, type, id) {
|
BaseNPC(int x, int y, int z, int type, int id, NPCClass classType) : BaseNPC(x, y, z, type, id) {
|
||||||
npcClass = classType;
|
npcClass = classType;
|
||||||
|
@ -147,6 +147,14 @@ void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z) {
|
|||||||
ChunkManager::addNPC(X, Y, npc->appearanceData.iNPC_ID);
|
ChunkManager::addNPC(X, Y, npc->appearanceData.iNPC_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NPCManager::sendToViewable(BaseNPC *npc, void *buf, uint32_t type, size_t size) {
|
||||||
|
for (Chunk *chunk : npc->currentChunks) {
|
||||||
|
for (CNSocket *s : chunk->players) {
|
||||||
|
s->sendPacket(buf, type, size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NPCManager::npcVendorBuy(CNSocket* sock, CNPacketData* data) {
|
void NPCManager::npcVendorBuy(CNSocket* sock, CNPacketData* data) {
|
||||||
if (data->size != sizeof(sP_CL2FE_REQ_PC_VENDOR_ITEM_BUY))
|
if (data->size != sizeof(sP_CL2FE_REQ_PC_VENDOR_ITEM_BUY))
|
||||||
return; // malformed packet
|
return; // malformed packet
|
||||||
|
@ -28,6 +28,8 @@ namespace NPCManager {
|
|||||||
void removeNPC(int32_t);
|
void removeNPC(int32_t);
|
||||||
void updateNPCPosition(int32_t, int X, int Y, int Z);
|
void updateNPCPosition(int32_t, int X, int Y, int Z);
|
||||||
|
|
||||||
|
void sendToViewable(BaseNPC* npc, void* buf, uint32_t type, size_t size);
|
||||||
|
|
||||||
void npcBarkHandler(CNSocket* sock, CNPacketData* data);
|
void npcBarkHandler(CNSocket* sock, CNPacketData* data);
|
||||||
void npcSummonHandler(CNSocket* sock, CNPacketData* data);
|
void npcSummonHandler(CNSocket* sock, CNPacketData* data);
|
||||||
void npcUnsummonHandler(CNSocket* sock, CNPacketData* data);
|
void npcUnsummonHandler(CNSocket* sock, CNPacketData* data);
|
||||||
|
@ -309,13 +309,10 @@ bool doDebuff(CNSocket *sock, int32_t *pktdata, sSkillResult_Damage_N_Debuff *re
|
|||||||
|
|
||||||
Mob* mob = MobManager::Mobs[pktdata[i]];
|
Mob* mob = MobManager::Mobs[pktdata[i]];
|
||||||
|
|
||||||
mob->appearanceData.iHP -= amount;
|
int damage = MobManager::hitMob(sock, mob, amount);
|
||||||
|
|
||||||
if (mob->appearanceData.iHP <= 0)
|
|
||||||
MobManager::killMob(sock, mob);
|
|
||||||
|
|
||||||
respdata[i].eCT = 4;
|
respdata[i].eCT = 4;
|
||||||
respdata[i].iDamage = amount;
|
respdata[i].iDamage = damage;
|
||||||
respdata[i].iID = mob->appearanceData.iNPC_ID;
|
respdata[i].iID = mob->appearanceData.iNPC_ID;
|
||||||
respdata[i].iHP = mob->appearanceData.iHP;
|
respdata[i].iHP = mob->appearanceData.iHP;
|
||||||
respdata[i].iConditionBitFlag = mob->appearanceData.iConditionBitFlag |= iCBFlag;
|
respdata[i].iConditionBitFlag = mob->appearanceData.iConditionBitFlag |= iCBFlag;
|
||||||
@ -380,16 +377,10 @@ bool doDamage(CNSocket *sock, int32_t *pktdata, sSkillResult_Damage *respdata, i
|
|||||||
}
|
}
|
||||||
Mob* mob = MobManager::Mobs[pktdata[i]];
|
Mob* mob = MobManager::Mobs[pktdata[i]];
|
||||||
|
|
||||||
mob->appearanceData.iHP -= amount;
|
int damage = MobManager::hitMob(sock, mob, amount);
|
||||||
|
|
||||||
// wake up sleeping monster
|
|
||||||
mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ;
|
|
||||||
|
|
||||||
if (mob->appearanceData.iHP <= 0)
|
|
||||||
MobManager::killMob(sock, mob);
|
|
||||||
|
|
||||||
respdata[i].eCT = 4;
|
respdata[i].eCT = 4;
|
||||||
respdata[i].iDamage = amount;
|
respdata[i].iDamage = damage;
|
||||||
respdata[i].iID = mob->appearanceData.iNPC_ID;
|
respdata[i].iID = mob->appearanceData.iNPC_ID;
|
||||||
respdata[i].iHP = mob->appearanceData.iHP;
|
respdata[i].iHP = mob->appearanceData.iHP;
|
||||||
|
|
||||||
@ -433,16 +424,10 @@ bool doLeech(CNSocket *sock, int32_t *pktdata, sSkillResult_Heal_HP *healdata, i
|
|||||||
}
|
}
|
||||||
Mob* mob = MobManager::Mobs[pktdata[i]];
|
Mob* mob = MobManager::Mobs[pktdata[i]];
|
||||||
|
|
||||||
mob->appearanceData.iHP -= amount;
|
int damage = MobManager::hitMob(sock, mob, amount);
|
||||||
|
|
||||||
// wake up sleeping monster
|
|
||||||
mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ;
|
|
||||||
|
|
||||||
if (mob->appearanceData.iHP <= 0)
|
|
||||||
MobManager::killMob(sock, mob);
|
|
||||||
|
|
||||||
damagedata->eCT = 4;
|
damagedata->eCT = 4;
|
||||||
damagedata->iDamage = amount;
|
damagedata->iDamage = damage;
|
||||||
damagedata->iID = mob->appearanceData.iNPC_ID;
|
damagedata->iID = mob->appearanceData.iNPC_ID;
|
||||||
damagedata->iHP = mob->appearanceData.iHP;
|
damagedata->iHP = mob->appearanceData.iHP;
|
||||||
|
|
||||||
|
@ -2,4 +2,5 @@ leak:TableData::init
|
|||||||
leak:ChunkManager::addPlayer
|
leak:ChunkManager::addPlayer
|
||||||
leak:ChunkManager::addNPC
|
leak:ChunkManager::addNPC
|
||||||
leak:NPCManager::npcSummonHandler
|
leak:NPCManager::npcSummonHandler
|
||||||
|
leak:BaseNPC::BaseNPC
|
||||||
leak:nlohmann::basic_json
|
leak:nlohmann::basic_json
|
||||||
|
Loading…
Reference in New Issue
Block a user