mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-25 22:40:16 +00:00
Various bugfixes and adjustments
* Nano missions should now stop repeating. * Bitwise operators are now used to handle buff/debuff bitfields. * Changing nano powers will no longer grant you infinite buffs. * Mobs now heal up client-side after retreating, this comes with candy effect being played however. * Lower level mobs now hit harder. * Nanos drain stamina quicker when they grant passive powers. * Healing, damage and leech powers scale up with your level. * Player on player damage now accounts for damage and armor.
This commit is contained in:
parent
3f35d2e960
commit
ab990116a2
@ -167,11 +167,8 @@ bool MissionManager::endTask(CNSocket *sock, int32_t taskNum) {
|
|||||||
saveMission(plr, (int)(task["m_iHMissionID"])-1);
|
saveMission(plr, (int)(task["m_iHMissionID"])-1);
|
||||||
|
|
||||||
// if it's a nano mission, reward the nano.
|
// if it's a nano mission, reward the nano.
|
||||||
if (task["m_iSTNanoID"] != 0) {
|
if (task["m_iSTNanoID"] != 0)
|
||||||
NanoManager::addNano(sock, task["m_iSTNanoID"], 0, true);
|
NanoManager::addNano(sock, task["m_iSTNanoID"], 0, true);
|
||||||
// check if the player already has enough fm for the next mission
|
|
||||||
updateFusionMatter(sock, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// remove current mission
|
// remove current mission
|
||||||
plr->CurrentMissionID = 0;
|
plr->CurrentMissionID = 0;
|
||||||
|
@ -114,7 +114,7 @@ void MobManager::npcAttackPc(Mob *mob) {
|
|||||||
sP_FE2CL_NPC_ATTACK_PCs *pkt = (sP_FE2CL_NPC_ATTACK_PCs*)respbuf;
|
sP_FE2CL_NPC_ATTACK_PCs *pkt = (sP_FE2CL_NPC_ATTACK_PCs*)respbuf;
|
||||||
sAttackResult *atk = (sAttackResult*)(respbuf + sizeof(sP_FE2CL_NPC_ATTACK_PCs));
|
sAttackResult *atk = (sAttackResult*)(respbuf + sizeof(sP_FE2CL_NPC_ATTACK_PCs));
|
||||||
|
|
||||||
auto damage = getDamage(440 + (int)mob->data["m_iPower"], plr->defense, false, 36 - (int)mob->data["m_iNpcLevel"]);
|
auto damage = getDamage(470 + (int)mob->data["m_iPower"], plr->defense, false, 1);
|
||||||
plr->HP -= damage.first;
|
plr->HP -= damage.first;
|
||||||
|
|
||||||
pkt->iNPC_ID = mob->appearanceData.iNPC_ID;
|
pkt->iNPC_ID = mob->appearanceData.iNPC_ID;
|
||||||
@ -443,6 +443,11 @@ void MobManager::retreatStep(Mob *mob, time_t currTime) {
|
|||||||
mob->killedTime = 0;
|
mob->killedTime = 0;
|
||||||
mob->nextAttack = 0;
|
mob->nextAttack = 0;
|
||||||
mob->appearanceData.iConditionBitFlag = 0;
|
mob->appearanceData.iConditionBitFlag = 0;
|
||||||
|
|
||||||
|
//INITSTRUCT(sP_FE2CL_NPC_ENTER, enterData);
|
||||||
|
//enterData.NPCAppearanceData = mob->appearanceData;
|
||||||
|
//NPCManager::sendToViewable(mob, &enterData, P_FE2CL_NPC_ENTER, sizeof(sP_FE2CL_NPC_ENTER));
|
||||||
|
resendMobHP(mob);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,19 +494,21 @@ void MobManager::step(CNServer *serv, time_t currTime) {
|
|||||||
* only returns the first step, since the rest will need to be recalculated anyway if chasing player.
|
* only returns the first step, since the rest will need to be recalculated anyway if chasing player.
|
||||||
*/
|
*/
|
||||||
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 = {};
|
std::pair<int,int> ret = {x1, y1};
|
||||||
|
|
||||||
speed /= 2;
|
speed /= 2;
|
||||||
|
|
||||||
|
if (speed == 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
int distance = hypot(x1 - x2, y1 - y2);
|
int distance = hypot(x1 - x2, y1 - y2);
|
||||||
|
|
||||||
if (distance > speed) {
|
if (distance > speed) {
|
||||||
if (speed == 0)
|
|
||||||
speed = 1;
|
|
||||||
|
|
||||||
int lerps = distance / speed;
|
int lerps = distance / speed;
|
||||||
|
|
||||||
// interpolate only the first point
|
// interpolate only the first point
|
||||||
float frac = 1.0f / (lerps);
|
float frac = 1.0f / lerps;
|
||||||
|
|
||||||
ret.first = (x1 + (x2 - x1) * frac);
|
ret.first = (x1 + (x2 - x1) * frac);
|
||||||
ret.second = (y1 + (y2 - y1) * frac);
|
ret.second = (y1 + (y2 - y1) * frac);
|
||||||
@ -579,15 +586,11 @@ void MobManager::playerTick(CNServer *serv, time_t currTime) {
|
|||||||
|
|
||||||
// fm patch/lake damage
|
// fm patch/lake damage
|
||||||
if (plr->dotDamage)
|
if (plr->dotDamage)
|
||||||
dealGooDamage(sock, 150);
|
dealGooDamage(sock, PC_MAXHEALTH(plr->level) * 3 / 20);
|
||||||
|
|
||||||
// a somewhat hacky way tick goo damage faster than heal, but eh
|
|
||||||
if (currTime - lastHealTime < 4000)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// heal
|
// heal
|
||||||
if (!plr->inCombat && plr->HP < PC_MAXHEALTH(plr->level)) {
|
if (currTime - lastHealTime >= 6000 && !plr->inCombat && plr->HP < PC_MAXHEALTH(plr->level)) {
|
||||||
plr->HP += 200;
|
plr->HP += PC_MAXHEALTH(plr->level) / 5;
|
||||||
if (plr->HP > PC_MAXHEALTH(plr->level))
|
if (plr->HP > PC_MAXHEALTH(plr->level))
|
||||||
plr->HP = PC_MAXHEALTH(plr->level);
|
plr->HP = PC_MAXHEALTH(plr->level);
|
||||||
transmit = true;
|
transmit = true;
|
||||||
@ -595,7 +598,10 @@ void MobManager::playerTick(CNServer *serv, time_t currTime) {
|
|||||||
|
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
if (plr->activeNano != 0 && plr->equippedNanos[i] == plr->activeNano) { // spend stamina
|
if (plr->activeNano != 0 && plr->equippedNanos[i] == plr->activeNano) { // spend stamina
|
||||||
plr->Nanos[plr->activeNano].iStamina -= 3;
|
plr->Nanos[plr->activeNano].iStamina -= 1;
|
||||||
|
|
||||||
|
if (plr->passiveNanoOut)
|
||||||
|
plr->Nanos[plr->activeNano].iStamina -= 1;
|
||||||
|
|
||||||
if (plr->Nanos[plr->activeNano].iStamina < 0)
|
if (plr->Nanos[plr->activeNano].iStamina < 0)
|
||||||
plr->activeNano = 0;
|
plr->activeNano = 0;
|
||||||
@ -603,7 +609,7 @@ void MobManager::playerTick(CNServer *serv, time_t currTime) {
|
|||||||
transmit = true;
|
transmit = true;
|
||||||
} else if (plr->Nanos[plr->equippedNanos[i]].iStamina < 150) { // regain stamina
|
} else if (plr->Nanos[plr->equippedNanos[i]].iStamina < 150) { // regain stamina
|
||||||
sNano& nano = plr->Nanos[plr->equippedNanos[i]];
|
sNano& nano = plr->Nanos[plr->equippedNanos[i]];
|
||||||
nano.iStamina += 3;
|
nano.iStamina += 1;
|
||||||
|
|
||||||
if (nano.iStamina > 150)
|
if (nano.iStamina > 150)
|
||||||
nano.iStamina = 150;
|
nano.iStamina = 150;
|
||||||
@ -627,7 +633,7 @@ void MobManager::playerTick(CNServer *serv, time_t currTime) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// if this was a heal tick, update the counter outside of the loop
|
// if this was a heal tick, update the counter outside of the loop
|
||||||
if (currTime - lastHealTime < 4000)
|
if (currTime - lastHealTime >= 6000)
|
||||||
lastHealTime = currTime;
|
lastHealTime = currTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -694,14 +700,21 @@ void MobManager::pcAttackChars(CNSocket *sock, CNPacketData *data) {
|
|||||||
std::cout << "[WARN] pcAttackChars: player ID not found" << std::endl;
|
std::cout << "[WARN] pcAttackChars: player ID not found" << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<int,int> damage;
|
||||||
|
|
||||||
|
if (pkt->iTargetCnt > 1)
|
||||||
|
damage = getDamage(plr->groupDamage, target->defense, true, 1);
|
||||||
|
else
|
||||||
|
damage = getDamage(plr->pointDamage, target->defense, true, 1);
|
||||||
|
|
||||||
target->HP -= 700;
|
target->HP -= damage.first;
|
||||||
|
|
||||||
respdata[i].eCT = pktdata[i*2+1];
|
respdata[i].eCT = pktdata[i*2+1];
|
||||||
respdata[i].iID = target->iID;
|
respdata[i].iID = target->iID;
|
||||||
respdata[i].iDamage = 700;
|
respdata[i].iDamage = damage.first;
|
||||||
respdata[i].iHP = target->HP;
|
respdata[i].iHP = target->HP;
|
||||||
respdata[i].iHitFlag = 2; // hitscan, not a rocket or a grenade
|
respdata[i].iHitFlag = damage.second; // hitscan, not a rocket or a grenade
|
||||||
} else { // eCT == 4; attack mob
|
} else { // eCT == 4; attack mob
|
||||||
if (Mobs.find(pktdata[i*2]) == Mobs.end()) {
|
if (Mobs.find(pktdata[i*2]) == Mobs.end()) {
|
||||||
// not sure how to best handle this
|
// not sure how to best handle this
|
||||||
@ -738,3 +751,25 @@ void MobManager::pcAttackChars(CNSocket *sock, CNPacketData *data) {
|
|||||||
// send to other players
|
// send to other players
|
||||||
PlayerManager::sendToViewable(sock, (void*)respbuf, P_FE2CL_PC_ATTACK_CHARs, resplen);
|
PlayerManager::sendToViewable(sock, (void*)respbuf, P_FE2CL_PC_ATTACK_CHARs, resplen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MobManager::resendMobHP(Mob *mob) {
|
||||||
|
size_t resplen = sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK) + sizeof(sSkillResult_Heal_HP);
|
||||||
|
assert(resplen < CN_PACKET_BUFFER_SIZE - 8);
|
||||||
|
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
||||||
|
|
||||||
|
memset(respbuf, 0, resplen);
|
||||||
|
|
||||||
|
sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK *pkt = (sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK*)respbuf;
|
||||||
|
sSkillResult_Heal_HP *heal = (sSkillResult_Heal_HP*)(respbuf + sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_TICK));
|
||||||
|
|
||||||
|
pkt->iID = mob->appearanceData.iNPC_ID;
|
||||||
|
pkt->eCT = 4; // mob
|
||||||
|
pkt->iTB_ID = ECSB_HEAL; // sSkillResult_Heal_HP
|
||||||
|
|
||||||
|
heal->eCT = 4;
|
||||||
|
heal->iID = mob->appearanceData.iNPC_ID;
|
||||||
|
heal->iHealHP = 0;
|
||||||
|
heal->iHP = mob->appearanceData.iHP;
|
||||||
|
|
||||||
|
NPCManager::sendToViewable(mob, (void*)&respbuf, P_FE2CL_CHAR_TIME_BUFF_TIME_TICK, resplen);
|
||||||
|
}
|
@ -107,4 +107,5 @@ namespace MobManager {
|
|||||||
std::pair<int,int> getDamage(int, int, bool, int);
|
std::pair<int,int> getDamage(int, int, bool, int);
|
||||||
|
|
||||||
void pcAttackChars(CNSocket *sock, CNPacketData *data);
|
void pcAttackChars(CNSocket *sock, CNPacketData *data);
|
||||||
|
void resendMobHP(Mob *mob);
|
||||||
}
|
}
|
||||||
|
@ -230,8 +230,10 @@ void NanoManager::addNano(CNSocket* sock, int16_t nanoId, int16_t slot, bool spe
|
|||||||
* Note the use of the not-yet-incremented plr->level as opposed to level.
|
* Note the use of the not-yet-incremented plr->level as opposed to level.
|
||||||
* Doing it the other way always leaves the FM at 0. Jade totally called it.
|
* Doing it the other way always leaves the FM at 0. Jade totally called it.
|
||||||
*/
|
*/
|
||||||
|
plr->level = level;
|
||||||
|
|
||||||
if (spendfm)
|
if (spendfm)
|
||||||
MissionManager::updateFusionMatter(sock, -(int)MissionManager::AvatarGrowth[plr->level]["m_iReqBlob_NanoCreate"]);
|
MissionManager::updateFusionMatter(sock, -(int)MissionManager::AvatarGrowth[plr->level-1]["m_iReqBlob_NanoCreate"]);
|
||||||
|
|
||||||
// Send to client
|
// Send to client
|
||||||
INITSTRUCT(sP_FE2CL_REP_PC_NANO_CREATE_SUCC, resp);
|
INITSTRUCT(sP_FE2CL_REP_PC_NANO_CREATE_SUCC, resp);
|
||||||
@ -241,10 +243,11 @@ void NanoManager::addNano(CNSocket* sock, int16_t nanoId, int16_t slot, bool spe
|
|||||||
resp.iPC_Level = level;
|
resp.iPC_Level = level;
|
||||||
resp.iPC_FusionMatter = plr->fusionmatter;
|
resp.iPC_FusionMatter = plr->fusionmatter;
|
||||||
|
|
||||||
|
if (plr->activeNano > 0 && plr->activeNano == nanoId)
|
||||||
|
summonNano(sock, -1); // just unsummon the nano to prevent infinite buffs
|
||||||
|
|
||||||
// Update player
|
// Update player
|
||||||
plr->Nanos[nanoId] = resp.Nano;
|
plr->Nanos[nanoId] = resp.Nano;
|
||||||
plr->level = level;
|
|
||||||
plr->iConditionBitFlag = 0;
|
|
||||||
|
|
||||||
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_NANO_CREATE_SUCC, sizeof(sP_FE2CL_REP_PC_NANO_CREATE_SUCC));
|
sock->sendPacket((void*)&resp, P_FE2CL_REP_PC_NANO_CREATE_SUCC, sizeof(sP_FE2CL_REP_PC_NANO_CREATE_SUCC));
|
||||||
|
|
||||||
@ -281,8 +284,10 @@ void NanoManager::summonNano(CNSocket *sock, int slot) {
|
|||||||
|
|
||||||
if (plr->activeNano > 0)
|
if (plr->activeNano > 0)
|
||||||
for (auto& pwr : PassivePowers)
|
for (auto& pwr : PassivePowers)
|
||||||
if (pwr.powers.count(plr->Nanos[plr->activeNano].iSkillID)) // std::set's contains method is C++20 only...
|
if (pwr.powers.count(plr->Nanos[plr->activeNano].iSkillID)) { // std::set's contains method is C++20 only...
|
||||||
nanoUnbuff(sock, pwr.iCBFlag, pwr.eCharStatusTimeBuffID, pwr.iValue);
|
nanoUnbuff(sock, pwr.iCBFlag, pwr.eCharStatusTimeBuffID, pwr.iValue);
|
||||||
|
plr->passiveNanoOut = false;
|
||||||
|
}
|
||||||
|
|
||||||
sNano nano = plr->Nanos[nanoId];
|
sNano nano = plr->Nanos[nanoId];
|
||||||
skillId = nano.iSkillID;
|
skillId = nano.iSkillID;
|
||||||
@ -294,6 +299,7 @@ void NanoManager::summonNano(CNSocket *sock, int slot) {
|
|||||||
if (pwr.powers.count(skillId)) { // std::set's contains method is C++20 only...
|
if (pwr.powers.count(skillId)) { // std::set's contains method is C++20 only...
|
||||||
resp.eCSTB___Add = 1;
|
resp.eCSTB___Add = 1;
|
||||||
nanoBuff(sock, nanoId, skillId, pwr.eSkillType, pwr.iCBFlag, pwr.eCharStatusTimeBuffID, pwr.iValue);
|
nanoBuff(sock, nanoId, skillId, pwr.eSkillType, pwr.iCBFlag, pwr.eCharStatusTimeBuffID, pwr.iValue);
|
||||||
|
plr->passiveNanoOut = true;
|
||||||
}
|
}
|
||||||
} else
|
} else
|
||||||
plr->activeNano = 0;
|
plr->activeNano = 0;
|
||||||
@ -325,6 +331,9 @@ void NanoManager::setNanoSkill(CNSocket* sock, int16_t nanoId, int16_t skillId)
|
|||||||
if (plr == nullptr)
|
if (plr == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (plr->activeNano > 0 && plr->activeNano == nanoId)
|
||||||
|
summonNano(sock, -1); // just unsummon the nano to prevent infinite buffs
|
||||||
|
|
||||||
sNano nano = plr->Nanos[nanoId];
|
sNano nano = plr->Nanos[nanoId];
|
||||||
|
|
||||||
nano.iSkillID = skillId;
|
nano.iSkillID = skillId;
|
||||||
@ -417,16 +426,18 @@ bool doHeal(CNSocket *sock, int32_t *pktdata, sSkillResult_Heal_HP *respdata, in
|
|||||||
// player not found
|
// player not found
|
||||||
if (plr == nullptr)
|
if (plr == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (plr->HP + amount > PC_MAXHEALTH(plr->level))
|
int healedAmount = PC_MAXHEALTH(plr->level) * amount / 100;
|
||||||
|
|
||||||
|
plr->HP += healedAmount;
|
||||||
|
|
||||||
|
if (plr->HP > PC_MAXHEALTH(plr->level))
|
||||||
plr->HP = PC_MAXHEALTH(plr->level);
|
plr->HP = PC_MAXHEALTH(plr->level);
|
||||||
else
|
|
||||||
plr->HP += amount;
|
|
||||||
|
|
||||||
respdata[i].eCT = 1;
|
respdata[i].eCT = 1;
|
||||||
respdata[i].iID = plr->iID;
|
respdata[i].iID = plr->iID;
|
||||||
respdata[i].iHP = plr->HP;
|
respdata[i].iHP = plr->HP;
|
||||||
respdata[i].iHealHP = amount;
|
respdata[i].iHealHP = healedAmount;
|
||||||
|
|
||||||
std::cout << (int)plr->iID << " was healed" << std::endl;
|
std::cout << (int)plr->iID << " was healed" << std::endl;
|
||||||
|
|
||||||
@ -441,7 +452,12 @@ bool doDamage(CNSocket *sock, int32_t *pktdata, sSkillResult_Damage *respdata, i
|
|||||||
}
|
}
|
||||||
Mob* mob = MobManager::Mobs[pktdata[i]];
|
Mob* mob = MobManager::Mobs[pktdata[i]];
|
||||||
|
|
||||||
int damage = MobManager::hitMob(sock, mob, amount);
|
Player *plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
|
if (plr == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int damage = MobManager::hitMob(sock, mob, PC_MAXHEALTH(plr->level) * amount / 100);
|
||||||
|
|
||||||
respdata[i].eCT = 4;
|
respdata[i].eCT = 4;
|
||||||
respdata[i].iDamage = damage;
|
respdata[i].iDamage = damage;
|
||||||
@ -474,15 +490,17 @@ bool doLeech(CNSocket *sock, int32_t *pktdata, sSkillResult_Heal_HP *healdata, i
|
|||||||
if (plr == nullptr)
|
if (plr == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (plr->HP + amount > PC_MAXHEALTH(plr->level))
|
int healedAmount = PC_MAXHEALTH(plr->level) * amount / 100;
|
||||||
|
|
||||||
|
plr->HP += healedAmount;
|
||||||
|
|
||||||
|
if (plr->HP > PC_MAXHEALTH(plr->level))
|
||||||
plr->HP = PC_MAXHEALTH(plr->level);
|
plr->HP = PC_MAXHEALTH(plr->level);
|
||||||
else
|
|
||||||
plr->HP += amount;
|
|
||||||
|
|
||||||
healdata->eCT = 1;
|
healdata->eCT = 1;
|
||||||
healdata->iID = plr->iID;
|
healdata->iID = plr->iID;
|
||||||
healdata->iHP = plr->HP;
|
healdata->iHP = plr->HP;
|
||||||
healdata->iHealHP = amount;
|
healdata->iHealHP = healedAmount;
|
||||||
|
|
||||||
if (MobManager::Mobs.find(pktdata[i]) == MobManager::Mobs.end()) {
|
if (MobManager::Mobs.find(pktdata[i]) == MobManager::Mobs.end()) {
|
||||||
// not sure how to best handle this
|
// not sure how to best handle this
|
||||||
@ -491,7 +509,7 @@ bool doLeech(CNSocket *sock, int32_t *pktdata, sSkillResult_Heal_HP *healdata, i
|
|||||||
}
|
}
|
||||||
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, PC_MAXHEALTH(plr->level) * amount / 100);
|
||||||
|
|
||||||
damagedata->eCT = 4;
|
damagedata->eCT = 4;
|
||||||
damagedata->iDamage = damage;
|
damagedata->iDamage = damage;
|
||||||
@ -567,13 +585,13 @@ 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, 0),
|
||||||
ActivePower(HealPowers, activePower<sSkillResult_Heal_HP, doHeal>, EST_HEAL_HP, CSB_BIT_NONE, 333),
|
ActivePower(HealPowers, activePower<sSkillResult_Heal_HP, doHeal>, EST_HEAL_HP, CSB_BIT_NONE, 25),
|
||||||
// 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, 0),
|
||||||
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, 0),
|
||||||
ActivePower(DamagePowers, activePower<sSkillResult_Damage, doDamage>, EST_DAMAGE, CSB_BIT_NONE, 133),
|
ActivePower(DamagePowers, activePower<sSkillResult_Damage, doDamage>, EST_DAMAGE, CSB_BIT_NONE, 12),
|
||||||
// TODO: GroupRevive
|
// TODO: GroupRevive
|
||||||
ActivePower(LeechPowers, activePower<sSkillResult_Heal_HP, doLeech, true>, EST_BLOODSUCKING, CSB_BIT_NONE, 133),
|
ActivePower(LeechPowers, activePower<sSkillResult_Heal_HP, doLeech, true>, 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, 0),
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -610,7 +628,8 @@ void NanoManager::nanoBuff(CNSocket* sock, int16_t nanoId, int skillId, int16_t
|
|||||||
// this looks stupid but in the future there will be more counts (for group powers)
|
// this looks stupid but in the future there will be more counts (for group powers)
|
||||||
for (int i = 0; i < 1; i++) {
|
for (int i = 0; i < 1; i++) {
|
||||||
|
|
||||||
plr->iConditionBitFlag += iCBFlag;
|
if (!(plr->iConditionBitFlag & iCBFlag))
|
||||||
|
plr->iConditionBitFlag ^= iCBFlag;
|
||||||
|
|
||||||
respdata[i].eCT = 1;
|
respdata[i].eCT = 1;
|
||||||
respdata[i].iID = plr->iID;
|
respdata[i].iID = plr->iID;
|
||||||
@ -641,10 +660,8 @@ void NanoManager::nanoUnbuff(CNSocket* sock, int32_t iCBFlag, int16_t eCharStatu
|
|||||||
if (plr == nullptr)
|
if (plr == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (iCBFlag < plr->iConditionBitFlag) // prevents integer underflow
|
if (plr->iConditionBitFlag & iCBFlag)
|
||||||
plr->iConditionBitFlag -= iCBFlag;
|
plr->iConditionBitFlag ^= iCBFlag;
|
||||||
else
|
|
||||||
plr->iConditionBitFlag = 0;
|
|
||||||
|
|
||||||
resp1.eCSTB = eCharStatusTimeBuffID; //eCharStatusTimeBuffID
|
resp1.eCSTB = eCharStatusTimeBuffID; //eCharStatusTimeBuffID
|
||||||
resp1.eTBU = 2; //eTimeBuffUpdate
|
resp1.eTBU = 2; //eTimeBuffUpdate
|
||||||
|
@ -47,6 +47,7 @@ struct Player {
|
|||||||
|
|
||||||
bool inCombat;
|
bool inCombat;
|
||||||
bool dotDamage;
|
bool dotDamage;
|
||||||
|
bool passiveNanoOut;
|
||||||
|
|
||||||
int pointDamage;
|
int pointDamage;
|
||||||
int groupDamage;
|
int groupDamage;
|
||||||
|
Loading…
Reference in New Issue
Block a user