mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-26 15:00:06 +00:00
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:
parent
2782706355
commit
177c5f0f17
@ -330,9 +330,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)
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user