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.
This commit is contained in:
Jade 2020-10-17 18:26:09 +01:00 committed by Gent Semaj
parent 2782706355
commit 177c5f0f17
No known key found for this signature in database
GPG Key ID: 76A006BEBA710050
3 changed files with 49 additions and 19 deletions

View File

@ -329,9 +329,16 @@ int MobManager::hitMob(CNSocket *sock, Mob *mob, int damage) {
mob->appearanceData.iHP -= damage; mob->appearanceData.iHP -= damage;
// wake up sleeping monster // wake up sleeping monster
// TODO: remove client-side bit somehow if (mob->appearanceData.iConditionBitFlag & CSB_BIT_MEZ) {
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) if (mob->appearanceData.iHP <= 0)
killMob(mob->target, mob); killMob(mob->target, mob);
@ -503,10 +510,8 @@ 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 = (targ.first - mob->appearanceData.iX) * 5 / 2 + mob->appearanceData.iX; pkt.iToX = mob->appearanceData.iX = targ.first;
pkt.iToY = (targ.second - mob->appearanceData.iY) * 5 / 2 + mob->appearanceData.iY; pkt.iToY = mob->appearanceData.iY = targ.second;
mob->appearanceData.iX = targ.first;
mob->appearanceData.iY = targ.second;
pkt.iToZ = mob->target->plr->z; pkt.iToZ = mob->target->plr->z;
// notify all nearby players // notify all nearby players
@ -608,10 +613,8 @@ void MobManager::retreatStep(Mob *mob, time_t currTime) {
pkt.iSpeed = (int)mob->data["m_iRunSpeed"] * 2; pkt.iSpeed = (int)mob->data["m_iRunSpeed"] * 2;
mob->appearanceData.iX = targ.first; mob->appearanceData.iX = targ.first;
mob->appearanceData.iY = targ.second; mob->appearanceData.iY = targ.second;
pkt.iToX = (targ.first - mob->appearanceData.iX) * 5 / 2 + mob->appearanceData.iX; pkt.iToX = mob->appearanceData.iX = targ.first;
pkt.iToY = (targ.second - mob->appearanceData.iY) * 5 / 2 + mob->appearanceData.iY; pkt.iToY = mob->appearanceData.iY = targ.second;
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
@ -640,6 +643,27 @@ void MobManager::step(CNServer *serv, time_t currTime) {
if (!ChunkManager::inPopulatedChunks(x, y, pair.second->instanceID)) if (!ChunkManager::inPopulatedChunks(x, y, pair.second->instanceID))
continue; 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 // skip mob movement and combat if disabled
if (!simulateMobs && pair.second->state != MobState::DEAD if (!simulateMobs && pair.second->state != MobState::DEAD
&& pair.second->state != MobState::RETREAT) && pair.second->state != MobState::RETREAT)

View File

@ -8,6 +8,7 @@
#include "contrib/JSON.hpp" #include "contrib/JSON.hpp"
#include <map> #include <map>
#include <unordered_map>
#include <queue> #include <queue>
enum class MobState { enum class MobState {
@ -27,6 +28,8 @@ struct Mob : public BaseNPC {
int spawnZ; int spawnZ;
int level; int level;
std::unordered_map<int32_t,time_t> unbuffTimes;
// dead // dead
time_t killedTime = 0; time_t killedTime = 0;
time_t regenTime; time_t regenTime;
@ -38,11 +41,12 @@ struct Mob : public BaseNPC {
const int sightRange; const int sightRange;
time_t nextMovement = 0; time_t nextMovement = 0;
bool staticPath = false; bool staticPath = false;
int roamX, roamY, roamZ;
// combat // combat
CNSocket *target = nullptr; CNSocket *target = nullptr;
time_t nextAttack = 0; time_t nextAttack = 0;
int roamX, roamY, roamZ;
// drop // drop
int dropType; int dropType;

View File

@ -407,14 +407,14 @@ bool doDebuff(CNSocket *sock, int32_t *pktdata, sSkillResult_Damage_N_Debuff *re
Mob* mob = MobManager::Mobs[pktdata[i]]; 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].eCT = 4;
respdata[i].iDamage = damage; 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;
mob->unbuffTimes[iCBFlag] = getTime() + amount;
std::cout << (int)mob->appearanceData.iNPC_ID << " was debuffed" << std::endl; std::cout << (int)mob->appearanceData.iNPC_ID << " was debuffed" << std::endl;
return true; return true;
@ -428,10 +428,12 @@ bool doBuff(CNSocket *sock, int32_t *pktdata, sSkillResult_Buff *respdata, int i
} }
Mob* mob = MobManager::Mobs[pktdata[i]]; Mob* mob = MobManager::Mobs[pktdata[i]];
MobManager::hitMob(sock, mob, 0);
respdata[i].eCT = 4; respdata[i].eCT = 4;
respdata[i].iID = mob->appearanceData.iNPC_ID; respdata[i].iID = mob->appearanceData.iNPC_ID;
respdata[i].iConditionBitFlag = mob->appearanceData.iConditionBitFlag |= iCBFlag; respdata[i].iConditionBitFlag = mob->appearanceData.iConditionBitFlag |= iCBFlag;
mob->unbuffTimes[iCBFlag] = getTime() + amount;
std::cout << (int)mob->appearanceData.iNPC_ID << " was debuffed" << std::endl; 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 // active nano power dispatch table
std::vector<ActivePower> ActivePowers = { std::vector<ActivePower> ActivePowers = {
ActivePower(StunPowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_STUN, CSB_BIT_STUN, 0), ActivePower(StunPowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_STUN, CSB_BIT_STUN, 2250),
ActivePower(HealPowers, activePower<sSkillResult_Heal_HP, doHeal>, EST_HEAL_HP, CSB_BIT_NONE, 25), ActivePower(HealPowers, activePower<sSkillResult_Heal_HP, doHeal>, EST_HEAL_HP, CSB_BIT_NONE, 25),
ActivePower(GroupHealPowers, activePower<sSkillResult_Heal_HP, doGroupHeal, GHEAL>,EST_HEAL_HP, CSB_BIT_NONE, 25), ActivePower(GroupHealPowers, activePower<sSkillResult_Heal_HP, doGroupHeal, GHEAL>,EST_HEAL_HP, CSB_BIT_NONE, 15),
// TODO: Recall // TODO: Recall
ActivePower(DrainPowers, activePower<sSkillResult_Buff, doBuff>, EST_BOUNDINGBALL, CSB_BIT_BOUNDINGBALL, 0), ActivePower(DrainPowers, activePower<sSkillResult_Buff, doBuff>, EST_BOUNDINGBALL, CSB_BIT_BOUNDINGBALL, 3000),
ActivePower(SnarePowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_SNARE, CSB_BIT_DN_MOVE_SPEED, 0), ActivePower(SnarePowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_SNARE, CSB_BIT_DN_MOVE_SPEED, 4500),
ActivePower(DamagePowers, activePower<sSkillResult_Damage, doDamage>, EST_DAMAGE, CSB_BIT_NONE, 12), ActivePower(DamagePowers, activePower<sSkillResult_Damage, doDamage>, EST_DAMAGE, CSB_BIT_NONE, 12),
ActivePower(LeechPowers, activePower<sSkillResult_Heal_HP, doLeech, LEECH>, EST_BLOODSUCKING, CSB_BIT_NONE, 18), ActivePower(LeechPowers, activePower<sSkillResult_Heal_HP, doLeech, LEECH>, EST_BLOODSUCKING, CSB_BIT_NONE, 18),
ActivePower(SleepPowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_SLEEP, CSB_BIT_MEZ, 0), ActivePower(SleepPowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, EST_SLEEP, CSB_BIT_MEZ, 4500),
}; };
}; // namespace }; // namespace