diff --git a/src/MobManager.cpp b/src/MobManager.cpp index 7b22181..8cfdf2f 100644 --- a/src/MobManager.cpp +++ b/src/MobManager.cpp @@ -847,7 +847,7 @@ void MobManager::dotDamageOnOff(CNSocket *sock, CNPacketData *data) { pkt1.eCSTB = ECSB_INFECTION; // eCharStatusTimeBuffID pkt1.eTBU = 1; // eTimeBuffUpdate pkt1.eTBT = 0; // eTimeBuffType 1 means nano - pkt1.iConditionBitFlag = plr->iConditionBitFlag | plr->iGroupConditionBitFlag | plr->iEggConditionBitFlag; + pkt1.iConditionBitFlag = plr->iConditionBitFlag; sock->sendPacket((void*)&pkt1, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); } @@ -895,7 +895,7 @@ void MobManager::dealGooDamage(CNSocket *sock, int amount) { dmg->iID = plr->iID; dmg->iDamage = amount; dmg->iHP = plr->HP; - dmg->iConditionBitFlag = plr->iConditionBitFlag | plr->iGroupConditionBitFlag | plr->iEggConditionBitFlag; + dmg->iConditionBitFlag = plr->iConditionBitFlag; sock->sendPacket((void*)&respbuf, P_FE2CL_CHAR_TIME_BUFF_TIME_TICK, resplen); PlayerManager::sendToViewable(sock, (void*)&respbuf, P_FE2CL_CHAR_TIME_BUFF_TIME_TICK, resplen); diff --git a/src/NPCManager.cpp b/src/NPCManager.cpp index 4fbf371..3fda3c7 100644 --- a/src/NPCManager.cpp +++ b/src/NPCManager.cpp @@ -7,6 +7,7 @@ #include "NanoManager.hpp" #include "TableData.hpp" #include "ChatManager.hpp" +#include "GroupManager.hpp" #include #include @@ -570,93 +571,48 @@ BaseNPC* NPCManager::getNearestNPC(std::set* chunks, int X, int Y, int Z return npc; } -int NPCManager::eggBuffPlayer(CNSocket* sock, int skillId, int duration) { - +int NPCManager::eggBuffPlayer(CNSocket* sock, int skillId, int eggId) { Player* plr = PlayerManager::getPlayer(sock); + Player* otherPlr = PlayerManager::getPlayerFromID(plr->iIDGroup); - int32_t CBFlag = -1, iValue = 0, CSTB, EST; - - // damage and heal have to be set by hand - if (skillId == 183) { - // damage - CBFlag = CSB_BIT_INFECTION; - CSTB = ECSB_INFECTION; - EST = EST_INFECTIONDAMAGE; - } - else if (skillId == 150) { - // heal - CBFlag = CSB_BIT_HEAL; - CSTB = ECSB_HEAL; - EST = EST_HEAL_HP; - } - else { - // find the right passive power data - for (auto& pwr : NanoManager::PassivePowers) - if (pwr.powers.count(skillId)) { - CBFlag = pwr.iCBFlag; - CSTB = pwr.eCharStatusTimeBuffID; - EST = pwr.eSkillType; - iValue = pwr.iValue; - } - } - - if (CBFlag < 0) + if (otherPlr == nullptr) return -1; - std::pair key = std::make_pair(sock, CBFlag); + std::pair key = std::make_pair(sock, skillId); + int bitFlag = GroupManager::getGroupFlags(otherPlr); - // if player doesn't have this buff yet if (EggBuffs.find(key) == EggBuffs.end()) - { - // save new cbflag serverside - plr->iEggConditionBitFlag |= CBFlag; - - // send buff update package - INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, updatePacket); - updatePacket.eCSTB = CSTB; // eCharStatusTimeBuffID - updatePacket.eTBU = 1; // eTimeBuffUpdate 1 means Add - updatePacket.eTBT = 3; // eTimeBuffType 3 means egg - updatePacket.TimeBuff.iValue = iValue; - int32_t updatedFlag = plr->iConditionBitFlag | plr->iGroupConditionBitFlag | plr->iEggConditionBitFlag; - updatePacket.iConditionBitFlag = updatedFlag; - - sock->sendPacket((void*)&updatePacket, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); - } + if (!NanoManager::applyBuff(sock, skillId, 1, 3, bitFlag, true)) + return -1; // save the buff serverside; // if you get the same buff again, new duration will override the previous one - time_t until = getTime() + (time_t)duration * 1000; + time_t until = getTime() + (time_t)NanoManager::SkillTable[skillId].durationTime[0] * 10; EggBuffs[key] = until; - - /* - * to give player a visual effect (eg. blue particles for run or wings for jump) - * we have to send him NANO_SKILL_USE packet with nano Id set to 0 - * yes, this is utterly stupid and disgusting - */ - const size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE) + sizeof(sSkillResult_Buff); + const size_t resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT) + sizeof(sSkillResult_Buff); assert(resplen < CN_PACKET_BUFFER_SIZE - 8); // we know it's only one trailing struct, so we can skip full validation uint8_t respbuf[resplen]; // not a variable length array, don't worry - sP_FE2CL_NANO_SKILL_USE* skillUse = (sP_FE2CL_NANO_SKILL_USE*)respbuf; - sSkillResult_Buff* skill = (sSkillResult_Buff*)(respbuf + sizeof(sP_FE2CL_NANO_SKILL_USE)); + sP_FE2CL_NPC_SKILL_HIT* skillUse = (sP_FE2CL_NPC_SKILL_HIT*)respbuf; + sSkillResult_Buff* skill = (sSkillResult_Buff*)(respbuf + sizeof(sP_FE2CL_NPC_SKILL_HIT)); memset(respbuf, 0, resplen); - - skillUse->iPC_ID = plr->iID; + skillUse->iNPC_ID = eggId; skillUse->iSkillID = skillId; - skillUse->iNanoID = plr->activeNano; - skillUse->iNanoStamina = plr->activeNano < 1 ? 0 : plr->Nanos[plr->activeNano].iStamina; - skillUse->eST = EST; + if (skillId == 183) // The only exception + skillUse->eST = EST_INFECTIONDAMAGE; + else + skillUse->eST = NanoManager::SkillTable[skillId].skillType; skillUse->iTargetCnt = 1; skill->eCT = 1; skill->iID = plr->iID; - skill->iConditionBitFlag = plr->iConditionBitFlag | plr->iGroupConditionBitFlag | plr->iEggConditionBitFlag; + skill->iConditionBitFlag = plr->iConditionBitFlag; - sock->sendPacket((void*)&respbuf, P_FE2CL_NANO_SKILL_USE_SUCC, resplen); - PlayerManager::sendToViewable(sock, (void*)&respbuf, P_FE2CL_NANO_SKILL_USE, resplen); + sock->sendPacket((void*)&respbuf, P_FE2CL_NPC_SKILL_HIT, resplen); + PlayerManager::sendToViewable(sock, (void*)&respbuf, P_FE2CL_NPC_SKILL_HIT, resplen); return 0; } @@ -673,44 +629,15 @@ void NPCManager::eggStep(CNServer* serv, time_t currTime) { // if time reached 0 else { CNSocket* sock = it->first.first; + int32_t skillId = it->first.second; Player* plr = PlayerManager::getPlayer(sock); - - // if player is still on the server - if (plr != nullptr) { + Player* otherPlr = PlayerManager::getPlayerFromID(plr->iIDGroup); - int32_t CBFlag = it->first.second; - int32_t CSTB = -1, iValue = 0; + if (otherPlr == nullptr) + return; - // find CSTB Value - if (CBFlag == CSB_BIT_INFECTION) - CSTB = ECSB_INFECTION; - - else if (CBFlag == CSB_BIT_HEAL) - CSTB = ECSB_HEAL; - - else { - for (auto pwr : NanoManager::PassivePowers) { - if (pwr.iCBFlag == CBFlag) { - CSTB = pwr.eCharStatusTimeBuffID; - iValue = pwr.iValue; - break; - } - } - } - - if (CSTB > 0) { - // update CBFlag serverside - plr->iEggConditionBitFlag &= ~CBFlag; - // send buff update packet - INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, updatePacket); - updatePacket.eCSTB = CSTB; // eCharStatusTimeBuffID - updatePacket.eTBU = 2; // eTimeBuffUpdate 2 means remove - updatePacket.eTBT = 3; // eTimeBuffType 3 means egg - updatePacket.iConditionBitFlag = plr->iConditionBitFlag | plr->iGroupConditionBitFlag | plr->iEggConditionBitFlag; - updatePacket.TimeBuff.iValue = iValue; - sock->sendPacket((void*)&updatePacket, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); - } - } + int bitFlag = GroupManager::getGroupFlags(otherPlr); + NanoManager::applyBuff(sock, skillId, 2, 3, bitFlag); // remove buff from the map it = EggBuffs.erase(it); } @@ -779,7 +706,7 @@ void NPCManager::eggPickup(CNSocket* sock, CNPacketData* data) { // buff the player if (type->effectId != 0) - eggBuffPlayer(sock, type->effectId, type->duration); + eggBuffPlayer(sock, type->effectId, eggId); // damage egg if (type->effectId == 183) { diff --git a/src/NanoManager.cpp b/src/NanoManager.cpp index 17f18be..d656873 100644 --- a/src/NanoManager.cpp +++ b/src/NanoManager.cpp @@ -479,25 +479,33 @@ void NanoManager::nanoUnbuff(CNSocket* sock, int targetData[], int32_t bitFlag, } } -void NanoManager::applyBuff(CNSocket* sock, int skillID, int eTBU, int eTBT, int32_t groupFlags) { - if (SkillTable[skillID].drainType != 2) - return; +bool NanoManager::applyBuff(CNSocket* sock, int skillID, int eTBU, int eTBT, int32_t groupFlags, bool eggBuff) { + if (SkillTable[skillID].drainType == 1) + return false; + + int32_t bitFlag = 0; for (auto& pwr : NanoPowers) { if (pwr.skillType == SkillTable[skillID].skillType) { + bitFlag = pwr.bitFlag; Player *plr = PlayerManager::getPlayer(sock); - if (eTBU == 1 || !((groupFlags | plr->iSelfConditionBitFlag) & pwr.bitFlag)) { + if (eTBU == 1 || !((groupFlags | plr->iSelfConditionBitFlag) & bitFlag)) { INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, resp); resp.eCSTB = pwr.timeBuffID; resp.eTBU = eTBU; resp.eTBT = eTBT; resp.iConditionBitFlag = plr->iConditionBitFlag = groupFlags | plr->iSelfConditionBitFlag; + if (eggBuff) + resp.iConditionBitFlag = plr->iConditionBitFlag |= bitFlag; resp.TimeBuff.iValue = SkillTable[skillID].powerIntensity[0]; sock->sendPacket((void*)&resp, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); } + return true; } } + + return false; } // 0=A 1=B 2=C -1=Not found @@ -511,7 +519,7 @@ int* NanoManager::findTargets(Player* plr, int skillID, CNPacketData* data) { static int tD[5] = {0, 0, 0, 0, 0}; tD[0] = 0; - if (SkillTable[skillID].targetType == 1 && data != nullptr) { // client gives us the targets + if (SkillTable[skillID].targetType <= 2 && data != nullptr) { // client gives us the targets sP_CL2FE_REQ_NANO_SKILL_USE* pkt = (sP_CL2FE_REQ_NANO_SKILL_USE*)data->buf; // validate request check @@ -637,7 +645,7 @@ bool doHeal(CNSocket *sock, sSkillResult_Heal_HP *respdata, int i, int32_t targe return false; } - int healedAmount = PC_MAXHEALTH(plr->level) * amount / 1000; + int healedAmount = PC_MAXHEALTH(plr->level) * amount / 1500; plr->HP += healedAmount; @@ -667,7 +675,7 @@ bool doDamage(CNSocket *sock, sSkillResult_Damage *respdata, int i, int32_t targ if (plr == nullptr) return false; - int damage = MobManager::hitMob(sock, mob, PC_MAXHEALTH(plr->level) * amount / 1000); + int damage = MobManager::hitMob(sock, mob, PC_MAXHEALTH(plr->level) * amount / 2000 + mob->appearanceData.iHP * amount / 2000); respdata[i].eCT = 4; respdata[i].iDamage = damage; @@ -856,7 +864,7 @@ void nanoPower(CNSocket *sock, int targetData[], // nano power dispatch table std::vector NanoPowers = { NanoPower(EST_STUN, CSB_BIT_STUN, ECSB_STUN, nanoPower), - NanoPower(EST_HEAL_HP, CSB_BIT_NONE, ECSB_NONE, nanoPower), + NanoPower(EST_HEAL_HP, CSB_BIT_HEAL, ECSB_HEAL, nanoPower), NanoPower(EST_BOUNDINGBALL, CSB_BIT_BOUNDINGBALL, ECSB_BOUNDINGBALL, nanoPower), NanoPower(EST_SNARE, CSB_BIT_DN_MOVE_SPEED, ECSB_DN_MOVE_SPEED, nanoPower), NanoPower(EST_DAMAGE, CSB_BIT_NONE, ECSB_NONE, nanoPower), diff --git a/src/NanoManager.hpp b/src/NanoManager.hpp index 1cdb6c0..1a8c472 100644 --- a/src/NanoManager.hpp +++ b/src/NanoManager.hpp @@ -65,7 +65,7 @@ namespace NanoManager { void setNanoSkill(CNSocket* sock, sP_CL2FE_REQ_NANO_TUNE* skill); void resetNanoSkill(CNSocket* sock, int16_t nanoID); void nanoUnbuff(CNSocket* sock, int* targetData, int32_t bitFlag, int16_t timeBuffID, int16_t amount, bool groupPower); - void applyBuff(CNSocket* sock, int skillID, int eTBU, int eTBT, int32_t groupFlags); + bool applyBuff(CNSocket* sock, int skillID, int eTBU, int eTBT, int32_t groupFlags, bool eggBuff=false); int nanoStyle(int nanoID); int* findTargets(Player* plr, int skillID, CNPacketData* data = nullptr); }