From d99dad261c404065fdce57daa3c10c6e878e147e Mon Sep 17 00:00:00 2001 From: Jade Date: Fri, 9 Oct 2020 01:01:35 +0100 Subject: [PATCH] Bugfixes + Damage Formula Adjustment * Entering/exiting groups should apply/remove group buffs. * Fixed issues with nanos losing all stamina from various revives/warp away. * Heavily tweaked damage formula, nano types now boost/decrease damage. * Weapons can consume battery returning extra damage, battery consumed depends on enemy level. --- src/GroupManager.cpp | 65 +++++++++++++++++---- src/GroupManager.hpp | 2 + src/MobManager.cpp | 81 +++++++++++++++++++++----- src/MobManager.hpp | 2 +- src/NanoManager.cpp | 132 +++++++++++++++++++++++++++--------------- src/NanoManager.hpp | 1 + src/Player.hpp | 1 + src/PlayerManager.cpp | 6 +- 8 files changed, 213 insertions(+), 77 deletions(-) diff --git a/src/GroupManager.cpp b/src/GroupManager.cpp index d3902f0..d356a9a 100644 --- a/src/GroupManager.cpp +++ b/src/GroupManager.cpp @@ -3,6 +3,7 @@ #include "ChatManager.hpp" #include "PlayerManager.hpp" #include "GroupManager.hpp" +#include "NanoManager.hpp" #include #include @@ -93,7 +94,7 @@ void GroupManager::joinGroup(CNSocket* sock, CNPacketData* data) { if (otherPlr == nullptr) return; - // fail if the group is full the other player is already in a group + // fail if the group is full or the other player is already in a group if (plr->groupCnt > 1 || plr->iIDGroup != plr->iID || otherPlr->groupCnt >= 4) { INITSTRUCT(sP_FE2CL_PC_GROUP_INVITE_FAIL, resp); sock->sendPacket((void*)&resp, P_FE2CL_PC_GROUP_JOIN_FAIL, sizeof(sP_FE2CL_PC_GROUP_JOIN_FAIL)); @@ -104,6 +105,8 @@ void GroupManager::joinGroup(CNSocket* sock, CNPacketData* data) { std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_JOIN packet size\n"; return; } + + int bitFlagBefore = getGroupFlags(otherPlr); plr->iIDGroup = otherPlr->iID; otherPlr->groupCnt += 1; @@ -119,11 +122,14 @@ void GroupManager::joinGroup(CNSocket* sock, CNPacketData* data) { resp->iID_NewMember = plr->iID; resp->iMemberPCCnt = otherPlr->groupCnt; + + int bitFlag = getGroupFlags(otherPlr); for (int i = 0; i < otherPlr->groupCnt; i++) { Player* varPlr = PlayerManager::getPlayerFromID(otherPlr->groupIDs[i]); + CNSocket* sockTo = PlayerManager::getSockFromID(otherPlr->groupIDs[i]); - if (varPlr == nullptr) + if (varPlr == nullptr || sockTo == nullptr) continue; respdata[i].iPC_ID = varPlr->iID; @@ -141,8 +147,10 @@ void GroupManager::joinGroup(CNSocket* sock, CNPacketData* data) { respdata[i].iY = varPlr->y; respdata[i].iZ = varPlr->z; // client doesnt read nano data here + + NanoManager::nanoChangeBuff(sockTo, varPlr, bitFlagBefore | varPlr->iConditionBitFlag, bitFlag | varPlr->iConditionBitFlag); } - + sendToGroup(otherPlr, (void*)&respbuf, P_FE2CL_PC_GROUP_JOIN, resplen); } @@ -228,10 +236,10 @@ void GroupManager::groupTickInfo(Player* plr) { for (int i = 0; i < plr->groupCnt; i++) { Player* varPlr = PlayerManager::getPlayerFromID(plr->groupIDs[i]); - + if (varPlr == nullptr) continue; - + respdata[i].iPC_ID = varPlr->iID; respdata[i].iPCUID = varPlr->PCStyle.iPC_UID; respdata[i].iNameCheck = varPlr->PCStyle.iNameCheck; @@ -255,9 +263,10 @@ void GroupManager::groupTickInfo(Player* plr) { sendToGroup(plr, (void*)&respbuf, P_FE2CL_PC_GROUP_MEMBER_INFO, resplen); } -void GroupManager::groupKickPlayer(Player* plr) { +void GroupManager::groupKickPlayer(Player* plr) { // if you are the group leader, destroy your own group and kick everybody if (plr->iID == plr->iIDGroup) { + groupUnbuff(plr); INITSTRUCT(sP_FE2CL_PC_GROUP_LEAVE_SUCC, resp1); sendToGroup(plr, (void*)&resp1, P_FE2CL_PC_GROUP_LEAVE_SUCC, sizeof(sP_FE2CL_PC_GROUP_LEAVE_SUCC)); plr->groupCnt = 1; @@ -273,7 +282,7 @@ void GroupManager::groupKickPlayer(Player* plr) { std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_LEAVE packet size\n"; return; } - + size_t resplen = sizeof(sP_FE2CL_PC_GROUP_LEAVE) + (otherPlr->groupCnt - 1) * sizeof(sPCGroupMemberInfo); uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; @@ -285,12 +294,15 @@ void GroupManager::groupKickPlayer(Player* plr) { resp->iID_LeaveMember = plr->iID; resp->iMemberPCCnt = otherPlr->groupCnt - 1; + int bitFlagBefore = getGroupFlags(otherPlr); + int bitFlag = bitFlagBefore & ~plr->iGroupConditionBitFlag; int moveDown = 0; for (int i = 0; i < otherPlr->groupCnt; i++) { Player* varPlr = PlayerManager::getPlayerFromID(otherPlr->groupIDs[i]); + CNSocket* sockTo = PlayerManager::getSockFromID(otherPlr->groupIDs[i]); - if (varPlr == nullptr) + if (varPlr == nullptr || sockTo == nullptr) continue; if (moveDown == 1) @@ -315,14 +327,16 @@ void GroupManager::groupKickPlayer(Player* plr) { if (varPlr == plr) { moveDown = 1; otherPlr->groupIDs[i] = 0; - } + NanoManager::nanoChangeBuff(sockTo, varPlr, bitFlagBefore | varPlr->iConditionBitFlag, varPlr->iConditionBitFlag); + } else + NanoManager::nanoChangeBuff(sockTo, varPlr, bitFlagBefore | varPlr->iConditionBitFlag, bitFlag | varPlr->iConditionBitFlag); } plr->iIDGroup = plr->iID; otherPlr->groupCnt -= 1; - + sendToGroup(otherPlr, (void*)&respbuf, P_FE2CL_PC_GROUP_LEAVE, resplen); - + CNSocket* sock = PlayerManager::getSockFromID(plr->iID); if (sock == nullptr) @@ -331,3 +345,32 @@ void GroupManager::groupKickPlayer(Player* plr) { INITSTRUCT(sP_FE2CL_PC_GROUP_LEAVE_SUCC, resp1); sock->sendPacket((void*)&resp1, P_FE2CL_PC_GROUP_LEAVE_SUCC, sizeof(sP_FE2CL_PC_GROUP_LEAVE_SUCC)); } + +void GroupManager::groupUnbuff(Player* plr) { + int bitFlag = getGroupFlags(plr); + + for (int i = 0; i < plr->groupCnt; i++) { + CNSocket* sock = PlayerManager::getSockFromID(plr->groupIDs[i]); + + if (sock == nullptr) + continue; + + Player* otherPlr = PlayerManager::getPlayer(sock); + NanoManager::nanoChangeBuff(sock, otherPlr, bitFlag | otherPlr->iConditionBitFlag, otherPlr->iConditionBitFlag); + } +} + +int GroupManager::getGroupFlags(Player* plr) { + int bitFlag = 0; + + for (int i = 0; i < plr->groupCnt; i++) { + Player* otherPlr = PlayerManager::getPlayerFromID(plr->groupIDs[i]); + + if (otherPlr == nullptr) + continue; + + bitFlag |= otherPlr->iGroupConditionBitFlag; + } + + return bitFlag; +} \ No newline at end of file diff --git a/src/GroupManager.hpp b/src/GroupManager.hpp index ad89c2c..3f6860f 100644 --- a/src/GroupManager.hpp +++ b/src/GroupManager.hpp @@ -20,4 +20,6 @@ namespace GroupManager { void sendToGroup(Player* plr, void* buf, uint32_t type, size_t size); void groupTickInfo(Player* plr); void groupKickPlayer(Player* plr); + void groupUnbuff(Player* plr); + int getGroupFlags(Player* plr); } diff --git a/src/MobManager.cpp b/src/MobManager.cpp index 819fde3..15c1d72 100644 --- a/src/MobManager.cpp +++ b/src/MobManager.cpp @@ -75,9 +75,16 @@ void MobManager::pcAttackNpcs(CNSocket *sock, CNPacketData *data) { std::pair damage; if (pkt->iNPCCnt > 1) - damage = getDamage(plr->groupDamage, (int)mob->data["m_iProtection"], true, (int)mob->data["m_iNpcLevel"]); + damage.first = plr->groupDamage; else - damage = getDamage(plr->pointDamage, (int)mob->data["m_iProtection"], true, (int)mob->data["m_iNpcLevel"]); + damage.first = plr->pointDamage; + + int difficulty = (int)mob->data["m_iNpcLevel"]; + + damage = getDamage(damage.first, (int)mob->data["m_iProtection"], true, (plr->batteryW >= 11 + difficulty), NanoManager::nanoStyle(plr->activeNano), (int)mob->data["m_iNpcStyle"], difficulty); + + if (plr->batteryW >= 11 + difficulty) + plr->batteryW -= 11 + difficulty; damage.first = hitMob(sock, mob, damage.first); @@ -114,7 +121,7 @@ void MobManager::npcAttackPc(Mob *mob, time_t currTime) { sP_FE2CL_NPC_ATTACK_PCs *pkt = (sP_FE2CL_NPC_ATTACK_PCs*)respbuf; sAttackResult *atk = (sAttackResult*)(respbuf + sizeof(sP_FE2CL_NPC_ATTACK_PCs)); - auto damage = getDamage(470 + (int)mob->data["m_iPower"], plr->defense, false, 1); + auto damage = getDamage(475 + (int)mob->data["m_iPower"], plr->defense, false, false, -1, -1, 1); plr->HP -= damage.first; pkt->iNPC_ID = mob->appearanceData.iNPC_ID; @@ -224,8 +231,26 @@ void MobManager::killMob(CNSocket *sock, Mob *mob) { // check for the edge case where hitting the mob did not aggro it if (sock != nullptr) { - giveReward(sock); - MissionManager::mobKilled(sock, mob->appearanceData.iNPCType); + Player* plr = PlayerManager::getPlayer(sock); + + if (plr == nullptr) + return; + + if (plr->groupCnt == 1 && plr->iIDGroup == plr->iID) { + giveReward(sock); + MissionManager::mobKilled(sock, mob->appearanceData.iNPCType); + } else { + plr = PlayerManager::getPlayerFromID(plr->iIDGroup); + + if (plr == nullptr) + return; + + for (int i = 0; i < plr->groupCnt; i++) { + CNSocket* sockTo = PlayerManager::getSockFromID(plr->groupIDs[i]); + giveReward(sockTo); + MissionManager::mobKilled(sockTo, mob->appearanceData.iNPCType); + } + } } mob->despawned = false; @@ -676,12 +701,26 @@ void MobManager::playerTick(CNServer *serv, time_t currTime) { lastHealTime = currTime; } -std::pair MobManager::getDamage(int attackPower, int defensePower, bool shouldCrit, int crutchLevel) { +std::pair MobManager::getDamage(int attackPower, int defensePower, bool shouldCrit, bool batteryBoost, int attackerStyle, int defenderStyle, int difficulty) { + std::pair ret = {0, 1}; + if (attackPower + defensePower * 2 == 0) + return ret; - std::pair ret = {}; - - int damage = (std::max(40, attackPower - defensePower) * (34 + crutchLevel) + std::min(attackPower, attackPower * attackPower / defensePower) * (36 - crutchLevel)) / 70; - ret.first = damage * (rand() % 40 + 80) / 100; // 20% variance + int damage = attackPower * attackPower / (attackPower + defensePower); + damage = std::max(std::max(29, attackPower / 7), damage - defensePower * (12 + difficulty) / 65); + damage = damage * (rand() % 40 + 80) / 100; + + if (attackerStyle != -1 && defenderStyle != -1 && attackerStyle != defenderStyle) { + if (attackerStyle < defenderStyle || attackerStyle - defenderStyle == 2) + damage = damage * 5 / 4; + else + damage = damage * 4 / 5; + } + + if (batteryBoost) + damage = damage * 5 / 4; + + ret.first = damage; ret.second = 1; if (shouldCrit && rand() % 20 == 0) { @@ -743,9 +782,14 @@ void MobManager::pcAttackChars(CNSocket *sock, CNPacketData *data) { std::pair damage; if (pkt->iTargetCnt > 1) - damage = getDamage(plr->groupDamage, target->defense, true, 1); + damage.first = plr->groupDamage; else - damage = getDamage(plr->pointDamage, target->defense, true, 1); + damage.first = plr->pointDamage; + + damage = getDamage(damage.first, target->defense, true, (plr->batteryW >= 12), -1, -1, 1); + + if (plr->batteryW >= 12) + plr->batteryW -= 12; target->HP -= damage.first; @@ -765,9 +809,16 @@ void MobManager::pcAttackChars(CNSocket *sock, CNPacketData *data) { std::pair damage; if (pkt->iTargetCnt > 1) - damage = getDamage(plr->groupDamage, (int)mob->data["m_iProtection"], true, (int)mob->data["m_iNpcLevel"]); + damage.first = plr->groupDamage; else - damage = getDamage(plr->pointDamage, (int)mob->data["m_iProtection"], true, (int)mob->data["m_iNpcLevel"]); + damage.first = plr->pointDamage; + + int difficulty = (int)mob->data["m_iNpcLevel"]; + + damage = getDamage(damage.first, (int)mob->data["m_iProtection"], true, (plr->batteryW >= 11 + difficulty), NanoManager::nanoStyle(plr->activeNano), (int)mob->data["m_iNpcStyle"], difficulty); + + if (plr->batteryW >= 11 + difficulty) + plr->batteryW -= 11 + difficulty; damage.first = hitMob(sock, mob, damage.first); @@ -782,7 +833,7 @@ void MobManager::pcAttackChars(CNSocket *sock, CNPacketData *data) { sock->sendPacket((void*)respbuf, P_FE2CL_PC_ATTACK_CHARs_SUCC, resplen); // a bit of a hack: these are the same size, so we can reuse the response packet - assert(sizeof(sP_FE2CL_PC_ATTACK_NPCs_SUCC) == sizeof(sP_FE2CL_PC_ATTACK_CHARs)); + assert(sizeof(sP_FE2CL_PC_ATTACK_CHARs_SUCC) == sizeof(sP_FE2CL_PC_ATTACK_CHARs)); sP_FE2CL_PC_ATTACK_CHARs *resp1 = (sP_FE2CL_PC_ATTACK_CHARs*)respbuf; resp1->iPC_ID = plr->iID; diff --git a/src/MobManager.hpp b/src/MobManager.hpp index 19d168d..b3e3d42 100644 --- a/src/MobManager.hpp +++ b/src/MobManager.hpp @@ -107,7 +107,7 @@ namespace MobManager { void killMob(CNSocket *sock, Mob *mob); void giveReward(CNSocket *sock); std::pair lerp(int, int, int, int, int); - std::pair getDamage(int, int, bool, int); + std::pair getDamage(int, int, bool, bool, int, int, int); void pcAttackChars(CNSocket *sock, CNPacketData *data); void resendMobHP(Mob *mob); diff --git a/src/NanoManager.cpp b/src/NanoManager.cpp index 2454800..21e6f45 100644 --- a/src/NanoManager.cpp +++ b/src/NanoManager.cpp @@ -5,6 +5,7 @@ #include "NPCManager.hpp" #include "MobManager.hpp" #include "MissionManager.hpp" +#include "GroupManager.hpp" namespace NanoManager { @@ -685,26 +686,29 @@ std::vector ActivePowers = { #pragma region Passive Powers void NanoManager::nanoBuff(CNSocket* sock, int16_t nanoId, int skillId, int16_t eSkillType, int32_t iCBFlag, int16_t eCharStatusTimeBuffID, int16_t iValue, bool groupPower) { Player *plr = PlayerManager::getPlayer(sock); - Player *leader; if (plr == nullptr) return; - - if (plr->iID == plr->iIDGroup) - leader = plr; - else - leader = PlayerManager::getPlayerFromID(plr->iIDGroup); + + int pktCnt = 1; + Player *leader = plr; + plr->iConditionBitFlag |= iCBFlag; + + if (groupPower) { + plr->iGroupConditionBitFlag |= iCBFlag; + + if (plr->iID != plr->iIDGroup) + leader = PlayerManager::getPlayerFromID(plr->iIDGroup); + + if (leader == nullptr) + return; + + pktCnt = leader->groupCnt; + } if (leader == nullptr) return; - - int pktCnt = 1; - - if (groupPower) - pktCnt = leader->groupCnt; - else - leader = plr; - + if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE), pktCnt, sizeof(sSkillResult_Buff))) { std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE packet size\n"; return; @@ -724,6 +728,8 @@ void NanoManager::nanoBuff(CNSocket* sock, int16_t nanoId, int skillId, int16_t resp->iNanoStamina = plr->Nanos[plr->activeNano].iStamina; resp->eST = eSkillType; resp->iTargetCnt = pktCnt; + + int bitFlag = GroupManager::getGroupFlags(leader); for (int i = 0; i < pktCnt; i++) { Player* varPlr; @@ -738,21 +744,17 @@ void NanoManager::nanoBuff(CNSocket* sock, int16_t nanoId, int skillId, int16_t } if (varPlr == nullptr || sockTo == nullptr) - return; - - if (!(varPlr->iConditionBitFlag & iCBFlag)) - varPlr->iConditionBitFlag ^= iCBFlag; - + continue; + respdata[i].eCT = 1; respdata[i].iID = varPlr->iID; respdata[i].iConditionBitFlag = iCBFlag; INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, pkt1); - pkt1.eCSTB = eCharStatusTimeBuffID; //eCharStatusTimeBuffID pkt1.eTBU = 1; //eTimeBuffUpdate pkt1.eTBT = 1; //eTimeBuffType 1 means nano - pkt1.iConditionBitFlag = varPlr->iConditionBitFlag; + pkt1.iConditionBitFlag = bitFlag | varPlr->iConditionBitFlag; if (iValue > 0) pkt1.TimeBuff.iValue = iValue; @@ -765,28 +767,28 @@ void NanoManager::nanoBuff(CNSocket* sock, int16_t nanoId, int skillId, int16_t } void NanoManager::nanoUnbuff(CNSocket* sock, int32_t iCBFlag, int16_t eCharStatusTimeBuffID, int16_t iValue, bool groupPower) { - INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, resp1); - Player *plr = PlayerManager::getPlayer(sock); - Player *leader; if (plr == nullptr) return; - - if (plr->iID == plr->iIDGroup) - leader = plr; - else - leader = PlayerManager::getPlayerFromID(plr->iIDGroup); - - if (leader == nullptr) - return; - + int pktCnt = 1; - - if (groupPower) + Player *leader = plr; + plr->iConditionBitFlag &= ~iCBFlag; + + if (groupPower) { + plr->iGroupConditionBitFlag &= ~iCBFlag; + + if (plr->iID != plr->iIDGroup) + leader = PlayerManager::getPlayerFromID(plr->iIDGroup); + + if (leader == nullptr) + return; + pktCnt = leader->groupCnt; - else - leader = plr; + } + + int bitFlag = GroupManager::getGroupFlags(leader); for (int i = 0; i < pktCnt; i++) { Player* varPlr; @@ -799,14 +801,12 @@ void NanoManager::nanoUnbuff(CNSocket* sock, int32_t iCBFlag, int16_t eCharStatu varPlr = PlayerManager::getPlayerFromID(leader->groupIDs[i]); sockTo = PlayerManager::getSockFromID(leader->groupIDs[i]); } - - if (varPlr->iConditionBitFlag & iCBFlag) - varPlr->iConditionBitFlag ^= iCBFlag; - + + INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, resp1); resp1.eCSTB = eCharStatusTimeBuffID; //eCharStatusTimeBuffID resp1.eTBU = 2; //eTimeBuffUpdate resp1.eTBT = 1; //eTimeBuffType 1 means nano - resp1.iConditionBitFlag = varPlr->iConditionBitFlag; + resp1.iConditionBitFlag = bitFlag | varPlr->iConditionBitFlag; if (iValue > 0) resp1.TimeBuff.iValue = iValue; @@ -817,7 +817,7 @@ void NanoManager::nanoUnbuff(CNSocket* sock, int32_t iCBFlag, int16_t eCharStatu // 0=A 1=B 2=C -1=Not found int NanoManager::nanoStyle(int nanoId) { - if (nanoId < 0 || nanoId >= (int)NanoTable.size()) + if (nanoId < 1 || nanoId >= (int)NanoTable.size()) return -1; return NanoTable[nanoId].style; } @@ -854,11 +854,12 @@ void NanoManager::revivePlayer(Player* plr) { // Nanos int activeSlot = -1; - for (int n = 0; n < 3; n++) { - int nanoID = plr->equippedNanos[n]; + for (int i = 0; i < 3; i++) { + int nanoID = plr->equippedNanos[i]; if (plr->activeNano == nanoID) { - activeSlot = n; + activeSlot = i; } + response.PCRegenData.Nanos[i] = plr->Nanos[nanoID]; } // Response parameters @@ -884,4 +885,43 @@ void NanoManager::revivePlayer(Player* plr) { PlayerManager::sendToViewable(sock, (void*)&resp2, P_FE2CL_PC_REGEN, sizeof(sP_FE2CL_PC_REGEN)); } + +void NanoManager::nanoChangeBuff(CNSocket* sock, Player* plr, int32_t cbFrom, int32_t cbTo) { + bool sentPacket = false; + INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, resp); + resp.eTBU = 3; + resp.eTBT = 1; + resp.iConditionBitFlag = cbTo; + + if (!(cbFrom & CSB_BIT_UP_MOVE_SPEED) && (cbTo & CSB_BIT_UP_MOVE_SPEED)) { + resp.eCSTB = ECSB_UP_MOVE_SPEED; + resp.eTBU = 1; + resp.TimeBuff.iValue = 200; + sock->sendPacket((void*)&resp, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); + sentPacket = true; + } else if ((cbFrom & CSB_BIT_UP_MOVE_SPEED) && !(cbTo & CSB_BIT_UP_MOVE_SPEED)) { + resp.eCSTB = ECSB_UP_MOVE_SPEED; + resp.eTBU = 2; + resp.TimeBuff.iValue = 200; + sock->sendPacket((void*)&resp, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); + sentPacket = true; + } + + if (!(cbFrom & CSB_BIT_UP_JUMP_HEIGHT) && (cbTo & CSB_BIT_UP_JUMP_HEIGHT)) { + resp.eCSTB = ECSB_UP_JUMP_HEIGHT; + resp.eTBU = 1; + resp.TimeBuff.iValue = 400; + sock->sendPacket((void*)&resp, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); + sentPacket = true; + } else if ((cbFrom & CSB_BIT_UP_JUMP_HEIGHT) && !(cbTo & CSB_BIT_UP_JUMP_HEIGHT)) { + resp.eCSTB = ECSB_UP_JUMP_HEIGHT; + resp.eTBU = 2; + resp.TimeBuff.iValue = 400; + sock->sendPacket((void*)&resp, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); + sentPacket = true; + } + + if (!sentPacket) + sock->sendPacket((void*)&resp, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); +} #pragma endregion diff --git a/src/NanoManager.hpp b/src/NanoManager.hpp index 4ec6748..ec9fd2b 100644 --- a/src/NanoManager.hpp +++ b/src/NanoManager.hpp @@ -66,4 +66,5 @@ namespace NanoManager { int nanoStyle(int nanoId); void revivePlayer(Player* plr); + void nanoChangeBuff(CNSocket* sock, Player* plr, int32_t cbFrom, int32_t cbTo); } diff --git a/src/Player.hpp b/src/Player.hpp index ebdca18..5499812 100644 --- a/src/Player.hpp +++ b/src/Player.hpp @@ -64,4 +64,5 @@ struct Player { int32_t iIDGroup; int groupCnt; int32_t groupIDs[4]; + int32_t iGroupConditionBitFlag; }; diff --git a/src/PlayerManager.cpp b/src/PlayerManager.cpp index 4d978ca..f45fd88 100644 --- a/src/PlayerManager.cpp +++ b/src/PlayerManager.cpp @@ -765,11 +765,9 @@ void PlayerManager::revivePlayer(CNSocket* sock, CNPacketData* data) { int nanoID = plr->equippedNanos[i]; // halve nano health if respawning - if (reviveData->iRegenType != 5) { + if (reviveData->iRegenType != 5) plr->Nanos[nanoID].iStamina = 75; // max is 150, so 75 is half - response.PCRegenData.Nanos[i] = plr->Nanos[nanoID]; - } - + response.PCRegenData.Nanos[i] = plr->Nanos[nanoID]; if (plr->activeNano == nanoID) activeSlot = i; }