Adapted Egg Buffing to Nano powers

* Adapted eggs to nano power data.
* Tweaked nano abilities.
This commit is contained in:
Jade 2020-11-13 03:20:51 +00:00 committed by Gent S
parent fe7ec44554
commit f7c0596a4c
4 changed files with 46 additions and 111 deletions

View File

@ -847,7 +847,7 @@ void MobManager::dotDamageOnOff(CNSocket *sock, CNPacketData *data) {
pkt1.eCSTB = ECSB_INFECTION; // eCharStatusTimeBuffID pkt1.eCSTB = ECSB_INFECTION; // eCharStatusTimeBuffID
pkt1.eTBU = 1; // eTimeBuffUpdate pkt1.eTBU = 1; // eTimeBuffUpdate
pkt1.eTBT = 0; // eTimeBuffType 1 means nano 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)); 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->iID = plr->iID;
dmg->iDamage = amount; dmg->iDamage = amount;
dmg->iHP = plr->HP; 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); 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); PlayerManager::sendToViewable(sock, (void*)&respbuf, P_FE2CL_CHAR_TIME_BUFF_TIME_TICK, resplen);

View File

@ -7,6 +7,7 @@
#include "NanoManager.hpp" #include "NanoManager.hpp"
#include "TableData.hpp" #include "TableData.hpp"
#include "ChatManager.hpp" #include "ChatManager.hpp"
#include "GroupManager.hpp"
#include <cmath> #include <cmath>
#include <algorithm> #include <algorithm>
@ -570,93 +571,48 @@ BaseNPC* NPCManager::getNearestNPC(std::set<Chunk*>* chunks, int X, int Y, int Z
return npc; 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* plr = PlayerManager::getPlayer(sock);
Player* otherPlr = PlayerManager::getPlayerFromID(plr->iIDGroup);
int32_t CBFlag = -1, iValue = 0, CSTB, EST; if (otherPlr == nullptr)
// 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)
return -1; return -1;
std::pair<CNSocket*, int32_t> key = std::make_pair(sock, CBFlag); std::pair<CNSocket*, int32_t> 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()) if (EggBuffs.find(key) == EggBuffs.end())
{ if (!NanoManager::applyBuff(sock, skillId, 1, 3, bitFlag, true))
// save new cbflag serverside return -1;
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));
}
// save the buff serverside; // save the buff serverside;
// if you get the same buff again, new duration will override the previous one // 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; 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); assert(resplen < CN_PACKET_BUFFER_SIZE - 8);
// we know it's only one trailing struct, so we can skip full validation // 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 uint8_t respbuf[resplen]; // not a variable length array, don't worry
sP_FE2CL_NANO_SKILL_USE* skillUse = (sP_FE2CL_NANO_SKILL_USE*)respbuf; sP_FE2CL_NPC_SKILL_HIT* skillUse = (sP_FE2CL_NPC_SKILL_HIT*)respbuf;
sSkillResult_Buff* skill = (sSkillResult_Buff*)(respbuf + sizeof(sP_FE2CL_NANO_SKILL_USE)); sSkillResult_Buff* skill = (sSkillResult_Buff*)(respbuf + sizeof(sP_FE2CL_NPC_SKILL_HIT));
memset(respbuf, 0, resplen); memset(respbuf, 0, resplen);
skillUse->iNPC_ID = eggId;
skillUse->iPC_ID = plr->iID;
skillUse->iSkillID = skillId; skillUse->iSkillID = skillId;
skillUse->iNanoID = plr->activeNano; if (skillId == 183) // The only exception
skillUse->iNanoStamina = plr->activeNano < 1 ? 0 : plr->Nanos[plr->activeNano].iStamina; skillUse->eST = EST_INFECTIONDAMAGE;
skillUse->eST = EST; else
skillUse->eST = NanoManager::SkillTable[skillId].skillType;
skillUse->iTargetCnt = 1; skillUse->iTargetCnt = 1;
skill->eCT = 1; skill->eCT = 1;
skill->iID = plr->iID; 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); sock->sendPacket((void*)&respbuf, P_FE2CL_NPC_SKILL_HIT, resplen);
PlayerManager::sendToViewable(sock, (void*)&respbuf, P_FE2CL_NANO_SKILL_USE, resplen); PlayerManager::sendToViewable(sock, (void*)&respbuf, P_FE2CL_NPC_SKILL_HIT, resplen);
return 0; return 0;
} }
@ -673,44 +629,15 @@ void NPCManager::eggStep(CNServer* serv, time_t currTime) {
// if time reached 0 // if time reached 0
else { else {
CNSocket* sock = it->first.first; CNSocket* sock = it->first.first;
int32_t skillId = it->first.second;
Player* plr = PlayerManager::getPlayer(sock); Player* plr = PlayerManager::getPlayer(sock);
Player* otherPlr = PlayerManager::getPlayerFromID(plr->iIDGroup);
// if player is still on the server
if (plr != nullptr) {
int32_t CBFlag = it->first.second; if (otherPlr == nullptr)
int32_t CSTB = -1, iValue = 0; return;
// find CSTB Value int bitFlag = GroupManager::getGroupFlags(otherPlr);
if (CBFlag == CSB_BIT_INFECTION) NanoManager::applyBuff(sock, skillId, 2, 3, bitFlag);
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));
}
}
// remove buff from the map // remove buff from the map
it = EggBuffs.erase(it); it = EggBuffs.erase(it);
} }
@ -779,7 +706,7 @@ void NPCManager::eggPickup(CNSocket* sock, CNPacketData* data) {
// buff the player // buff the player
if (type->effectId != 0) if (type->effectId != 0)
eggBuffPlayer(sock, type->effectId, type->duration); eggBuffPlayer(sock, type->effectId, eggId);
// damage egg // damage egg
if (type->effectId == 183) { if (type->effectId == 183) {

View File

@ -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) { bool NanoManager::applyBuff(CNSocket* sock, int skillID, int eTBU, int eTBT, int32_t groupFlags, bool eggBuff) {
if (SkillTable[skillID].drainType != 2) if (SkillTable[skillID].drainType == 1)
return; return false;
int32_t bitFlag = 0;
for (auto& pwr : NanoPowers) { for (auto& pwr : NanoPowers) {
if (pwr.skillType == SkillTable[skillID].skillType) { if (pwr.skillType == SkillTable[skillID].skillType) {
bitFlag = pwr.bitFlag;
Player *plr = PlayerManager::getPlayer(sock); 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); INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, resp);
resp.eCSTB = pwr.timeBuffID; resp.eCSTB = pwr.timeBuffID;
resp.eTBU = eTBU; resp.eTBU = eTBU;
resp.eTBT = eTBT; resp.eTBT = eTBT;
resp.iConditionBitFlag = plr->iConditionBitFlag = groupFlags | plr->iSelfConditionBitFlag; resp.iConditionBitFlag = plr->iConditionBitFlag = groupFlags | plr->iSelfConditionBitFlag;
if (eggBuff)
resp.iConditionBitFlag = plr->iConditionBitFlag |= bitFlag;
resp.TimeBuff.iValue = SkillTable[skillID].powerIntensity[0]; resp.TimeBuff.iValue = SkillTable[skillID].powerIntensity[0];
sock->sendPacket((void*)&resp, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE)); 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 // 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}; static int tD[5] = {0, 0, 0, 0, 0};
tD[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; sP_CL2FE_REQ_NANO_SKILL_USE* pkt = (sP_CL2FE_REQ_NANO_SKILL_USE*)data->buf;
// validate request check // validate request check
@ -637,7 +645,7 @@ bool doHeal(CNSocket *sock, sSkillResult_Heal_HP *respdata, int i, int32_t targe
return false; return false;
} }
int healedAmount = PC_MAXHEALTH(plr->level) * amount / 1000; int healedAmount = PC_MAXHEALTH(plr->level) * amount / 1500;
plr->HP += healedAmount; plr->HP += healedAmount;
@ -667,7 +675,7 @@ bool doDamage(CNSocket *sock, sSkillResult_Damage *respdata, int i, int32_t targ
if (plr == nullptr) if (plr == nullptr)
return false; 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].eCT = 4;
respdata[i].iDamage = damage; respdata[i].iDamage = damage;
@ -856,7 +864,7 @@ void nanoPower(CNSocket *sock, int targetData[],
// nano power dispatch table // nano power dispatch table
std::vector<NanoPower> NanoPowers = { std::vector<NanoPower> NanoPowers = {
NanoPower(EST_STUN, CSB_BIT_STUN, ECSB_STUN, nanoPower<sSkillResult_Damage_N_Debuff, doDamageNDebuff>), NanoPower(EST_STUN, CSB_BIT_STUN, ECSB_STUN, nanoPower<sSkillResult_Damage_N_Debuff, doDamageNDebuff>),
NanoPower(EST_HEAL_HP, CSB_BIT_NONE, ECSB_NONE, nanoPower<sSkillResult_Heal_HP, doHeal>), NanoPower(EST_HEAL_HP, CSB_BIT_HEAL, ECSB_HEAL, nanoPower<sSkillResult_Heal_HP, doHeal>),
NanoPower(EST_BOUNDINGBALL, CSB_BIT_BOUNDINGBALL, ECSB_BOUNDINGBALL, nanoPower<sSkillResult_Buff, doDebuff>), NanoPower(EST_BOUNDINGBALL, CSB_BIT_BOUNDINGBALL, ECSB_BOUNDINGBALL, nanoPower<sSkillResult_Buff, doDebuff>),
NanoPower(EST_SNARE, CSB_BIT_DN_MOVE_SPEED, ECSB_DN_MOVE_SPEED, nanoPower<sSkillResult_Damage_N_Debuff, doDamageNDebuff>), NanoPower(EST_SNARE, CSB_BIT_DN_MOVE_SPEED, ECSB_DN_MOVE_SPEED, nanoPower<sSkillResult_Damage_N_Debuff, doDamageNDebuff>),
NanoPower(EST_DAMAGE, CSB_BIT_NONE, ECSB_NONE, nanoPower<sSkillResult_Damage, doDamage>), NanoPower(EST_DAMAGE, CSB_BIT_NONE, ECSB_NONE, nanoPower<sSkillResult_Damage, doDamage>),

View File

@ -65,7 +65,7 @@ namespace NanoManager {
void setNanoSkill(CNSocket* sock, sP_CL2FE_REQ_NANO_TUNE* skill); void setNanoSkill(CNSocket* sock, sP_CL2FE_REQ_NANO_TUNE* skill);
void resetNanoSkill(CNSocket* sock, int16_t nanoID); 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 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 nanoStyle(int nanoID);
int* findTargets(Player* plr, int skillID, CNPacketData* data = nullptr); int* findTargets(Player* plr, int skillID, CNPacketData* data = nullptr);
} }