From 177c5f0f178aa984d631554d578d5ad3aae4b1cd Mon Sep 17 00:00:00 2001 From: Jade Date: Sat, 17 Oct 2020 18:26:09 +0100 Subject: [PATCH] Nano Drain, Debuffs are timed * Nano drain power works, currently does 30% damage over a period of 3 seconds. * Stun, Sleep and Snare powers will now run out of time on mobs. * A few other adjustments to mob mobility. --- src/MobManager.cpp | 46 ++++++++++++++++++++++++++++++++++----------- src/MobManager.hpp | 6 +++++- src/NanoManager.cpp | 16 +++++++++------- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/src/MobManager.cpp b/src/MobManager.cpp index 88ab1d2..4a96a4f 100644 --- a/src/MobManager.cpp +++ b/src/MobManager.cpp @@ -329,9 +329,16 @@ int MobManager::hitMob(CNSocket *sock, Mob *mob, int damage) { mob->appearanceData.iHP -= damage; - // wake up sleeping monster - // TODO: remove client-side bit somehow - mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ; + // wake up sleeping monster + if (mob->appearanceData.iConditionBitFlag & CSB_BIT_MEZ) { + mob->appearanceData.iConditionBitFlag &= ~CSB_BIT_MEZ; + + INITSTRUCT(sP_FE2CL_CHAR_TIME_BUFF_TIME_OUT, pkt1); + pkt1.eCT = 2; + pkt1.iID = mob->appearanceData.iNPC_ID; + pkt1.iConditionBitFlag = mob->appearanceData.iConditionBitFlag; + NPCManager::sendToViewable(mob, &pkt1, P_FE2CL_CHAR_TIME_BUFF_TIME_OUT, sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_OUT)); + } if (mob->appearanceData.iHP <= 0) killMob(mob->target, mob); @@ -503,10 +510,8 @@ void MobManager::combatStep(Mob *mob, time_t currTime) { pkt.iNPC_ID = mob->appearanceData.iNPC_ID; pkt.iSpeed = speed; - 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.iToX = mob->appearanceData.iX = targ.first; + pkt.iToY = mob->appearanceData.iY = targ.second; pkt.iToZ = mob->target->plr->z; // notify all nearby players @@ -608,10 +613,8 @@ void MobManager::retreatStep(Mob *mob, time_t currTime) { pkt.iSpeed = (int)mob->data["m_iRunSpeed"] * 2; mob->appearanceData.iX = targ.first; 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.iToX = mob->appearanceData.iX = targ.first; + pkt.iToY = mob->appearanceData.iY = targ.second; pkt.iToZ = mob->appearanceData.iZ; // notify all nearby players @@ -640,6 +643,27 @@ void MobManager::step(CNServer *serv, time_t currTime) { if (!ChunkManager::inPopulatedChunks(x, y, pair.second->instanceID)) continue; + // drain + if (pair.second->appearanceData.iConditionBitFlag & CSB_BIT_BOUNDINGBALL) { + pair.second->appearanceData.iHP -= pair.second->maxHealth / 50; // lose 10% every second + // TODO: Make this send a damage packet + } + + // unbuffing + for (auto& pair2 : pair.second->unbuffTimes) { + if (currTime >= pair2.second) { + pair.second->appearanceData.iConditionBitFlag &= ~pair2.first; + + INITSTRUCT(sP_FE2CL_CHAR_TIME_BUFF_TIME_OUT, pkt1); + pkt1.eCT = 2; + pkt1.iID = pair.second->appearanceData.iNPC_ID; + pkt1.iConditionBitFlag = pair.second->appearanceData.iConditionBitFlag; + NPCManager::sendToViewable(pair.second, &pkt1, P_FE2CL_CHAR_TIME_BUFF_TIME_OUT, sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_OUT)); + + pair.second->unbuffTimes.erase(pair2.first); + } + } + // skip mob movement and combat if disabled if (!simulateMobs && pair.second->state != MobState::DEAD && pair.second->state != MobState::RETREAT) diff --git a/src/MobManager.hpp b/src/MobManager.hpp index b79f84e..73682e2 100644 --- a/src/MobManager.hpp +++ b/src/MobManager.hpp @@ -8,6 +8,7 @@ #include "contrib/JSON.hpp" #include +#include #include enum class MobState { @@ -27,6 +28,8 @@ struct Mob : public BaseNPC { int spawnZ; int level; + std::unordered_map unbuffTimes; + // dead time_t killedTime = 0; time_t regenTime; @@ -38,11 +41,12 @@ struct Mob : public BaseNPC { const int sightRange; time_t nextMovement = 0; bool staticPath = false; + int roamX, roamY, roamZ; // combat CNSocket *target = nullptr; time_t nextAttack = 0; - int roamX, roamY, roamZ; + // drop int dropType; diff --git a/src/NanoManager.cpp b/src/NanoManager.cpp index 5237496..f661e6d 100644 --- a/src/NanoManager.cpp +++ b/src/NanoManager.cpp @@ -407,14 +407,14 @@ bool doDebuff(CNSocket *sock, int32_t *pktdata, sSkillResult_Damage_N_Debuff *re Mob* mob = MobManager::Mobs[pktdata[i]]; - int damage = MobManager::hitMob(sock, mob, amount); + int damage = MobManager::hitMob(sock, mob, 0); // using amount for something else respdata[i].eCT = 4; respdata[i].iDamage = damage; respdata[i].iID = mob->appearanceData.iNPC_ID; respdata[i].iHP = mob->appearanceData.iHP; respdata[i].iConditionBitFlag = mob->appearanceData.iConditionBitFlag |= iCBFlag; - + mob->unbuffTimes[iCBFlag] = getTime() + amount; std::cout << (int)mob->appearanceData.iNPC_ID << " was debuffed" << std::endl; return true; @@ -428,10 +428,12 @@ bool doBuff(CNSocket *sock, int32_t *pktdata, sSkillResult_Buff *respdata, int i } Mob* mob = MobManager::Mobs[pktdata[i]]; + MobManager::hitMob(sock, mob, 0); respdata[i].eCT = 4; respdata[i].iID = mob->appearanceData.iNPC_ID; respdata[i].iConditionBitFlag = mob->appearanceData.iConditionBitFlag |= iCBFlag; + mob->unbuffTimes[iCBFlag] = getTime() + amount; std::cout << (int)mob->appearanceData.iNPC_ID << " was debuffed" << std::endl; @@ -669,15 +671,15 @@ void activePower(CNSocket *sock, CNPacketData *data, // active nano power dispatch table std::vector ActivePowers = { - ActivePower(StunPowers, activePower, EST_STUN, CSB_BIT_STUN, 0), + ActivePower(StunPowers, activePower, EST_STUN, CSB_BIT_STUN, 2250), ActivePower(HealPowers, activePower, EST_HEAL_HP, CSB_BIT_NONE, 25), - ActivePower(GroupHealPowers, activePower,EST_HEAL_HP, CSB_BIT_NONE, 25), + ActivePower(GroupHealPowers, activePower,EST_HEAL_HP, CSB_BIT_NONE, 15), // TODO: Recall - ActivePower(DrainPowers, activePower, EST_BOUNDINGBALL, CSB_BIT_BOUNDINGBALL, 0), - ActivePower(SnarePowers, activePower, EST_SNARE, CSB_BIT_DN_MOVE_SPEED, 0), + ActivePower(DrainPowers, activePower, EST_BOUNDINGBALL, CSB_BIT_BOUNDINGBALL, 3000), + ActivePower(SnarePowers, activePower, EST_SNARE, CSB_BIT_DN_MOVE_SPEED, 4500), ActivePower(DamagePowers, activePower, EST_DAMAGE, CSB_BIT_NONE, 12), ActivePower(LeechPowers, activePower, EST_BLOODSUCKING, CSB_BIT_NONE, 18), - ActivePower(SleepPowers, activePower, EST_SLEEP, CSB_BIT_MEZ, 0), + ActivePower(SleepPowers, activePower, EST_SLEEP, CSB_BIT_MEZ, 4500), }; }; // namespace