mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-25 22:40:16 +00:00
Cleaned up implementation of active nano powers.
This commit is contained in:
parent
0fc072d591
commit
dc9de5a54a
@ -5,6 +5,39 @@
|
||||
#include "NPCManager.hpp"
|
||||
#include "CombatManager.hpp"
|
||||
|
||||
namespace NanoManager {
|
||||
|
||||
// active powers
|
||||
std::set<int> StunPowers = {1, 13, 42, 59, 78, 103};
|
||||
std::set<int> HealPowers = {2, 7, 12, 38, 53, 61, 82, 92, 98};
|
||||
std::set<int> RecallPowers = {5, 25, 66, 69, 75, 87};
|
||||
std::set<int> DrainPowers = {10, 34, 37, 56, 93, 97};
|
||||
std::set<int> SnarePowers = {17, 18, 27, 41, 43, 47, 90, 96, 106};
|
||||
std::set<int> DamagePowers = {19, 21, 33, 45, 46, 52, 101, 105, 108};
|
||||
std::set<int> GroupRevivePowers = {20, 63, 91};
|
||||
std::set<int> LeechPowers = {24, 51, 89};
|
||||
std::set<int> SleepPowers = {28, 30, 32, 49, 70, 71, 81, 85, 94};
|
||||
|
||||
// passive powers
|
||||
std::set<int> ScavangePowers = {3, 50, 99};
|
||||
std::set<int> RunPowers = {4, 8, 62, 68, 73, 86};
|
||||
std::set<int> BonusPowers = {6, 54, 104};
|
||||
std::set<int> GuardPowers = {9, 57, 76};
|
||||
std::set<int> RadarPowers = {11, 67, 95};
|
||||
std::set<int> AnitdotePowers = {14, 58, 102};
|
||||
std::set<int> FreedomPowers = {15, 31, 39, 55, 77, 107};
|
||||
std::set<int> JumpPowers = {16, 35, 44, 60, 88, 100};
|
||||
std::set<int> SelfRevivePowers = {22, 48, 83};
|
||||
std::set<int> SneakPowers = {23, 29, 65, 72, 80, 82};
|
||||
std::set<int> TreasureFinderPowers = {26, 40, 74};
|
||||
|
||||
/*
|
||||
* The active nano power table is down below activePower<>() and its
|
||||
* worker functions so we don't have to have unsightly function declarations.
|
||||
*/
|
||||
|
||||
}; // namespace
|
||||
|
||||
void NanoManager::init() {
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_ACTIVE, nanoSummonHandler);
|
||||
REGISTER_SHARD_PACKET(P_CL2FE_REQ_NANO_EQUIP, nanoEquipHandler);
|
||||
@ -97,31 +130,13 @@ void NanoManager::nanoSummonHandler(CNSocket* sock, CNPacketData* data) {
|
||||
}
|
||||
|
||||
void NanoManager::nanoSkillUseHandler(CNSocket* sock, CNPacketData* data) {
|
||||
//if (data->size != sizeof(sP_CL2FE_REQ_NANO_SKILL_USE))
|
||||
// return; // malformed packet
|
||||
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
int16_t nanoId = plr->activeNano;
|
||||
int16_t skillId = plr->Nanos[nanoId].iSkillID;
|
||||
|
||||
if (skillId == 1 || skillId == 13 || skillId == 42 || skillId == 59 || skillId == 78 || skillId == 103)
|
||||
nanoDebuff(sock, data, nanoId, skillId, 8, 512); // Stun
|
||||
else if (skillId == 2 || skillId == 7 || skillId == 12 || skillId == 38 || skillId == 53 || skillId == 61 || skillId == 82 || skillId == 92 || skillId == 98 )
|
||||
nanoHeal(sock, data, nanoId, skillId, 333); // Heal
|
||||
else if (skillId == 5 || skillId == 25 || skillId == 66 || skillId == 69 || skillId == 75 || skillId == 87) {
|
||||
// Recall
|
||||
} else if (skillId == 10 || skillId == 34 || skillId == 37 || skillId == 56 || skillId == 93 || skillId == 97)
|
||||
nanoDebuff(sock, data, nanoId, skillId, 3, 262144); // Drain
|
||||
else if (skillId == 17 || skillId == 18 || skillId == 27 || skillId == 41 || skillId == 43 || skillId == 47 || skillId == 90 || skillId == 96 || skillId == 106)
|
||||
nanoDebuff(sock, data, nanoId, skillId, 5, 128); // Snare
|
||||
else if (skillId == 19 || skillId == 21 || skillId == 33 || skillId == 45 || skillId == 46 || skillId == 52 || skillId == 101 || skillId == 105 || skillId == 108)
|
||||
nanoDamage(sock, data, nanoId, skillId, 133); // Damage
|
||||
else if (skillId == 20 || skillId == 63 || skillId == 91) {
|
||||
// Group Revive
|
||||
} else if (skillId == 24 || skillId == 51 || skillId == 89) {
|
||||
nanoLeech(sock, data, nanoId, skillId, 133); // Leech
|
||||
} else if (skillId == 28 || skillId == 30 || skillId == 32 || skillId == 49 || skillId == 70 || skillId == 71 || skillId == 81 || skillId == 85 || skillId == 94)
|
||||
nanoDebuff(sock, data, nanoId, skillId, 4, 1024); // Sleep
|
||||
|
||||
for (auto& pwr : ActivePowers)
|
||||
if (pwr.powers.count(skillId)) // std::set's contains method is C++20 only...
|
||||
pwr.handle(sock, data, nanoId, skillId);
|
||||
|
||||
DEBUGLOG(
|
||||
std::cout << U16toU8(plr->PCStyle.szFirstName) << U16toU8(plr->PCStyle.szLastName) << " requested to summon nano skill " << std::endl;
|
||||
@ -328,127 +343,187 @@ void NanoManager::resetNanoSkill(CNSocket* sock, int16_t nanoId) {
|
||||
nano.iSkillID = 0;
|
||||
plr->Nanos[nanoId] = nano;
|
||||
}
|
||||
#pragma endregion
|
||||
|
||||
// this is where the fun begins
|
||||
void NanoManager::nanoDebuff(CNSocket* sock, CNPacketData* data, int16_t nanoId, int16_t skillId, int16_t eSkillType, int32_t iCBFlag, int32_t damageAmount) {
|
||||
sP_CL2FE_REQ_NANO_SKILL_USE* pkt = (sP_CL2FE_REQ_NANO_SKILL_USE*)data->buf;
|
||||
#pragma region Active Powers
|
||||
namespace NanoManager {
|
||||
|
||||
// sanity check
|
||||
if (!validInVarPacket(sizeof(sP_CL2FE_REQ_NANO_SKILL_USE), pkt->iTargetCnt, sizeof(int32_t), data->size)) {
|
||||
std::cout << "[WARN] bad sP_CL2FE_REQ_NANO_SKILL_USE packet size\n";
|
||||
return;
|
||||
bool doDebuff(CNSocket *sock, int32_t *pktdata, sSkillResult_Damage_N_Debuff *respdata, int i, int16_t iCBFlag, int32_t amount) {
|
||||
if (NPCManager::NPCs.find(pktdata[i]) == NPCManager::NPCs.end()) {
|
||||
// not sure how to best handle this
|
||||
std::cout << "[WARN] nanoDebuffEnemy: mob ID not found" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t *pktdata = (int32_t*)((uint8_t*)data->buf + sizeof(sP_CL2FE_REQ_NANO_SKILL_USE));
|
||||
BaseNPC& mob = NPCManager::NPCs[pktdata[i]];
|
||||
|
||||
mob.appearanceData.iHP -= amount;
|
||||
|
||||
/*
|
||||
* Due to the possibility of multiplication overflow (and regular buffer overflow),
|
||||
* both incoming and outgoing variable-length packets must be validated, at least if
|
||||
* the number of trailing structs isn't well known (ie. it's from the client).
|
||||
*/
|
||||
if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE), pkt->iTargetCnt, sizeof(sSkillResult_Damage_N_Debuff))) {
|
||||
std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE packet size\n";
|
||||
return;
|
||||
}
|
||||
if (mob.appearanceData.iHP <= 0)
|
||||
CombatManager::giveReward(sock);
|
||||
|
||||
size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE) + pkt->iTargetCnt * sizeof(sSkillResult_Damage_N_Debuff);
|
||||
uint8_t respbuf[4096];
|
||||
|
||||
memset(respbuf, 0, resplen);
|
||||
|
||||
sP_FE2CL_NANO_SKILL_USE *resp = (sP_FE2CL_NANO_SKILL_USE*)respbuf;
|
||||
sSkillResult_Damage_N_Debuff *respdata = (sSkillResult_Damage_N_Debuff*)(respbuf+sizeof(sP_FE2CL_NANO_SKILL_USE));
|
||||
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
resp->iPC_ID = plr->iID;
|
||||
resp->iSkillID = skillId;
|
||||
resp->iNanoID = nanoId;
|
||||
resp->iNanoStamina = 150;
|
||||
resp->eST = eSkillType;
|
||||
resp->iTargetCnt = pkt->iTargetCnt;
|
||||
|
||||
for (int i = 0; i < pkt->iTargetCnt; i++) {
|
||||
if (NPCManager::NPCs.find(pktdata[i]) == NPCManager::NPCs.end()) {
|
||||
// not sure how to best handle this
|
||||
std::cout << "[WARN] nanoDebuffEnemy: mob ID not found" << std::endl;
|
||||
return;
|
||||
respdata[i].eCT = 4;
|
||||
respdata[i].iDamage = amount;
|
||||
respdata[i].iID = mob.appearanceData.iNPC_ID;
|
||||
respdata[i].iHP = mob.appearanceData.iHP;
|
||||
respdata[i].iConditionBitFlag = iCBFlag;
|
||||
|
||||
std::cout << (int)mob.appearanceData.iNPC_ID << " was debuffed" << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool doHeal(CNSocket *sock, int32_t *pktdata, sSkillResult_Heal_HP *respdata, int i, int16_t iCBFlag, int32_t amount) {
|
||||
Player *plr = nullptr;
|
||||
|
||||
for (auto& pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == pktdata[i]) {
|
||||
plr = pair.second.plr;
|
||||
break;
|
||||
}
|
||||
BaseNPC& mob = NPCManager::NPCs[pktdata[i]];
|
||||
|
||||
mob.appearanceData.iHP -= damageAmount;
|
||||
|
||||
if (mob.appearanceData.iHP <= 0)
|
||||
CombatManager::giveReward(sock);
|
||||
|
||||
respdata[i].eCT = 4;
|
||||
respdata[i].iDamage = damageAmount;
|
||||
respdata[i].iID = mob.appearanceData.iNPC_ID;
|
||||
respdata[i].iHP = mob.appearanceData.iHP;
|
||||
respdata[i].iConditionBitFlag = iCBFlag;
|
||||
std::cout << (int)mob.appearanceData.iNPC_ID << " was debuffed" << std::endl;
|
||||
}
|
||||
|
||||
sock->sendPacket((void*)&respbuf, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
||||
for (CNSocket* s : PlayerManager::players[sock].viewable)
|
||||
s->sendPacket((void*)&respbuf, P_FE2CL_NANO_SKILL_USE, resplen);
|
||||
if (plr == nullptr)
|
||||
return false;
|
||||
|
||||
if (plr->HP + amount > PC_MAXHEALTH(plr->level))
|
||||
plr->HP = PC_MAXHEALTH(plr->level);
|
||||
else
|
||||
plr->HP += amount;
|
||||
|
||||
respdata[i].eCT = 1;
|
||||
respdata[i].iID = plr->iID;
|
||||
respdata[i].iHP = plr->HP;
|
||||
respdata[i].iHealHP = amount;
|
||||
|
||||
std::cout << (int)plr->iID << " was healed" << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void NanoManager::nanoHeal(CNSocket* sock, CNPacketData* data, int16_t nanoId, int16_t skillId, int16_t healAmount) {
|
||||
sP_CL2FE_REQ_NANO_SKILL_USE* pkt = (sP_CL2FE_REQ_NANO_SKILL_USE*)data->buf;
|
||||
bool doDamage(CNSocket *sock, int32_t *pktdata, sSkillResult_Damage *respdata, int i, int16_t iCBFlag, int32_t amount) {
|
||||
if (NPCManager::NPCs.find(pktdata[i]) == NPCManager::NPCs.end()) {
|
||||
// not sure how to best handle this
|
||||
std::cout << "[WARN] nanoDebuffEnemy: mob ID not found" << std::endl;
|
||||
return false;
|
||||
}
|
||||
BaseNPC& mob = NPCManager::NPCs[pktdata[i]];
|
||||
|
||||
mob.appearanceData.iHP -= amount;
|
||||
|
||||
if (mob.appearanceData.iHP <= 0)
|
||||
CombatManager::giveReward(sock);
|
||||
|
||||
respdata[i].eCT = 4;
|
||||
respdata[i].iDamage = amount;
|
||||
respdata[i].iID = mob.appearanceData.iNPC_ID;
|
||||
respdata[i].iHP = mob.appearanceData.iHP;
|
||||
|
||||
std::cout << (int)mob.appearanceData.iNPC_ID << " was damaged" << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: Leech is specially encoded.
|
||||
*
|
||||
* It manages to fit inside the activePower<>() mold with only a slight hack,
|
||||
* but it really is it's own thing. There is a hard assumption that players
|
||||
* will only every leech a single mob, and the sanity check that enforces that
|
||||
* assumption is critical.
|
||||
*/
|
||||
bool doLeech(CNSocket *sock, int32_t *pktdata, sSkillResult_Heal_HP *healdata, int i, int16_t iCBFlag, int32_t amount) {
|
||||
// this sanity check is VERY important
|
||||
if (i != 0) {
|
||||
std::cout << "[WARN] Player attempted to leech more than one mob!" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
sSkillResult_Damage *damagedata = (sSkillResult_Damage*)(((uint8_t*)healdata) + sizeof(sSkillResult_Heal_HP));
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
// sanity check
|
||||
if (plr->HP + amount > PC_MAXHEALTH(plr->level))
|
||||
plr->HP = PC_MAXHEALTH(plr->level);
|
||||
else
|
||||
plr->HP += amount;
|
||||
|
||||
healdata->eCT = 1;
|
||||
healdata->iID = plr->iID;
|
||||
healdata->iHP = plr->HP;
|
||||
healdata->iHealHP = amount;
|
||||
|
||||
if (NPCManager::NPCs.find(pktdata[i]) == NPCManager::NPCs.end()) {
|
||||
// not sure how to best handle this
|
||||
std::cout << "[WARN] doLeech: mob ID not found" << std::endl;
|
||||
return false;
|
||||
}
|
||||
BaseNPC& mob = NPCManager::NPCs[pktdata[i]];
|
||||
|
||||
mob.appearanceData.iHP -= amount;
|
||||
|
||||
if (mob.appearanceData.iHP <= 0)
|
||||
CombatManager::giveReward(sock);
|
||||
|
||||
damagedata->eCT = 4;
|
||||
damagedata->iDamage = amount;
|
||||
damagedata->iID = mob.appearanceData.iNPC_ID;
|
||||
damagedata->iHP = mob.appearanceData.iHP;
|
||||
|
||||
std::cout << (int)mob.appearanceData.iNPC_ID << " was leeched" << std::endl;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class sPAYLOAD,
|
||||
bool (*work)(CNSocket*,int32_t*,sPAYLOAD*,int,int16_t,int32_t),
|
||||
bool isLeech=false>
|
||||
void activePower(CNSocket *sock, CNPacketData *data,
|
||||
int16_t nanoId, int16_t skillId, SkillType eSkillType,
|
||||
int32_t iCBFlag, int32_t amount) {
|
||||
|
||||
sP_CL2FE_REQ_NANO_SKILL_USE* pkt = (sP_CL2FE_REQ_NANO_SKILL_USE*)data->buf;
|
||||
|
||||
// validate request check
|
||||
if (!validInVarPacket(sizeof(sP_CL2FE_REQ_NANO_SKILL_USE), pkt->iTargetCnt, sizeof(int32_t), data->size)) {
|
||||
std::cout << "[WARN] bad sP_CL2FE_REQ_NANO_SKILL_USE packet size\n";
|
||||
std::cout << "[WARN] bad sP_CL2FE_REQ_NANO_SKILL_USE packet size" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t *pktdata = (int32_t*)((uint8_t*)data->buf + sizeof(sP_CL2FE_REQ_NANO_SKILL_USE));
|
||||
|
||||
/*
|
||||
* Due to the possibility of multiplication overflow (and regular buffer overflow),
|
||||
* both incoming and outgoing variable-length packets must be validated, at least if
|
||||
* the number of trailing structs isn't well known (ie. it's from the client).
|
||||
*/
|
||||
if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE), pkt->iTargetCnt, sizeof(sSkillResult_Heal_HP))) {
|
||||
std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE packet size\n";
|
||||
// validate response packet
|
||||
if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC), pkt->iTargetCnt, sizeof(sPAYLOAD))) {
|
||||
std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE packet size" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE) + pkt->iTargetCnt * sizeof(sSkillResult_Heal_HP);
|
||||
uint8_t respbuf[4096];
|
||||
|
||||
|
||||
size_t resplen;
|
||||
|
||||
// special case since leech is atypically encoded
|
||||
if constexpr (isLeech)
|
||||
resplen = sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC) + sizeof(sSkillResult_Heal_HP) + sizeof(sSkillResult_Damage);
|
||||
else
|
||||
resplen = sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC) + pkt->iTargetCnt * sizeof(sPAYLOAD);
|
||||
|
||||
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
||||
|
||||
memset(respbuf, 0, resplen);
|
||||
|
||||
sP_FE2CL_NANO_SKILL_USE_SUCC *resp = (sP_FE2CL_NANO_SKILL_USE_SUCC*)respbuf;
|
||||
sPAYLOAD *respdata = (sPAYLOAD*)(respbuf+sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC));
|
||||
|
||||
sP_FE2CL_NANO_SKILL_USE *resp = (sP_FE2CL_NANO_SKILL_USE*)respbuf;
|
||||
sSkillResult_Heal_HP *respdata = (sSkillResult_Heal_HP*)(respbuf+sizeof(sP_FE2CL_NANO_SKILL_USE));
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
resp->iPC_ID = plr->iID;
|
||||
resp->iSkillID = skillId;
|
||||
resp->iNanoID = nanoId;
|
||||
resp->iNanoStamina = 150;
|
||||
resp->eST = 2; //heal enum TODO: Send these enums to Defines
|
||||
resp->eST = (int32_t)eSkillType;
|
||||
resp->iTargetCnt = pkt->iTargetCnt;
|
||||
|
||||
for (int i = 0; i < pkt->iTargetCnt; i++) {
|
||||
for (auto pair : PlayerManager::players) {
|
||||
if (pair.second.plr->iID == pktdata[i]) {
|
||||
Player* plr = pair.second.plr;
|
||||
|
||||
if (plr->HP + healAmount > 3625)
|
||||
plr->HP = 3625;
|
||||
else
|
||||
plr->HP += healAmount;
|
||||
|
||||
respdata[i].eCT = 1;
|
||||
respdata[i].iID = plr->iID;
|
||||
respdata[i].iHP = plr->HP;
|
||||
respdata[i].iHealHP = healAmount;
|
||||
|
||||
std::cout << (int)plr->iID << " was healed" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < pkt->iTargetCnt; i++) {
|
||||
if (!work(sock, pktdata, respdata, i, iCBFlag, amount))
|
||||
return;
|
||||
}
|
||||
|
||||
sock->sendPacket((void*)&respbuf, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
||||
@ -456,6 +531,23 @@ void NanoManager::nanoHeal(CNSocket* sock, CNPacketData* data, int16_t nanoId, i
|
||||
s->sendPacket((void*)&respbuf, P_FE2CL_NANO_SKILL_USE, resplen);
|
||||
}
|
||||
|
||||
// active nano power dispatch table
|
||||
std::vector<ActivePower> ActivePowers = {
|
||||
ActivePower(StunPowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, SkillType::STUN, 0x200, 0),
|
||||
ActivePower(HealPowers, activePower<sSkillResult_Heal_HP, doHeal>, SkillType::HEAL, 0, 333),
|
||||
// TODO: Recall
|
||||
ActivePower(DrainPowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, SkillType::DRAIN, 0x40000, 0),
|
||||
ActivePower(SnarePowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, SkillType::SNARE, 0x80, 0),
|
||||
ActivePower(DamagePowers, activePower<sSkillResult_Damage, doDamage>, SkillType::DAMAGE, 0, 133),
|
||||
// TODO: GroupRevive
|
||||
ActivePower(LeechPowers, activePower<sSkillResult_Heal_HP, doLeech, true>, SkillType::LEECH, 0, 133),
|
||||
ActivePower(SleepPowers, activePower<sSkillResult_Damage_N_Debuff, doDebuff>, SkillType::SLEEP, 0x400, 0),
|
||||
};
|
||||
|
||||
}; // namespace
|
||||
#pragma endregion
|
||||
|
||||
#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) {
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
@ -465,7 +557,7 @@ void NanoManager::nanoBuff(CNSocket* sock, int16_t nanoId, int skillId, int16_t
|
||||
}
|
||||
|
||||
size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE) + sizeof(sSkillResult_Buff);
|
||||
uint8_t respbuf[4096];
|
||||
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
||||
|
||||
memset(respbuf, 0, resplen);
|
||||
|
||||
@ -476,7 +568,7 @@ void NanoManager::nanoBuff(CNSocket* sock, int16_t nanoId, int skillId, int16_t
|
||||
resp->iSkillID = skillId;
|
||||
resp->iNanoID = nanoId;
|
||||
resp->iNanoStamina = 150;
|
||||
resp->eST = eSkillType; //run enum TODO: Send these enums to Defines
|
||||
resp->eST = eSkillType;
|
||||
resp->iTargetCnt = 1;
|
||||
|
||||
// this looks stupid but in the future there will be more counts (for group powers)
|
||||
@ -526,140 +618,4 @@ void NanoManager::nanoUnbuff(CNSocket* sock, int32_t iCBFlag, int16_t eCharStatu
|
||||
sock->sendPacket((void*)&resp1, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE));
|
||||
}
|
||||
|
||||
void NanoManager::nanoDamage(CNSocket* sock, CNPacketData* data, int16_t nanoId, int16_t skillId, int32_t damageAmount) {
|
||||
sP_CL2FE_REQ_NANO_SKILL_USE* pkt = (sP_CL2FE_REQ_NANO_SKILL_USE*)data->buf;
|
||||
|
||||
// sanity check
|
||||
if (!validInVarPacket(sizeof(sP_CL2FE_REQ_NANO_SKILL_USE), pkt->iTargetCnt, sizeof(int32_t), data->size)) {
|
||||
std::cout << "[WARN] bad sP_CL2FE_REQ_NANO_SKILL_USE packet size\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t *pktdata = (int32_t*)((uint8_t*)data->buf + sizeof(sP_CL2FE_REQ_NANO_SKILL_USE));
|
||||
|
||||
/*
|
||||
* Due to the possibility of multiplication overflow (and regular buffer overflow),
|
||||
* both incoming and outgoing variable-length packets must be validated, at least if
|
||||
* the number of trailing structs isn't well known (ie. it's from the client).
|
||||
*/
|
||||
if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE), pkt->iTargetCnt, sizeof(sSkillResult_Damage))) {
|
||||
std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE packet size\n";
|
||||
return;
|
||||
}
|
||||
|
||||
size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE) + pkt->iTargetCnt * sizeof(sSkillResult_Damage);
|
||||
uint8_t respbuf[4096];
|
||||
|
||||
memset(respbuf, 0, resplen);
|
||||
|
||||
sP_FE2CL_NANO_SKILL_USE *resp = (sP_FE2CL_NANO_SKILL_USE*)respbuf;
|
||||
sSkillResult_Damage *respdata = (sSkillResult_Damage*)(respbuf+sizeof(sP_FE2CL_NANO_SKILL_USE));
|
||||
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
resp->iPC_ID = plr->iID;
|
||||
resp->iSkillID = skillId;
|
||||
resp->iNanoID = nanoId;
|
||||
resp->iNanoStamina = 150;
|
||||
resp->eST = 1;
|
||||
resp->iTargetCnt = pkt->iTargetCnt;
|
||||
|
||||
for (int i = 0; i < pkt->iTargetCnt; i++) {
|
||||
if (NPCManager::NPCs.find(pktdata[i]) == NPCManager::NPCs.end()) {
|
||||
// not sure how to best handle this
|
||||
std::cout << "[WARN] nanoDebuffEnemy: mob ID not found" << std::endl;
|
||||
return;
|
||||
}
|
||||
BaseNPC& mob = NPCManager::NPCs[pktdata[i]];
|
||||
|
||||
mob.appearanceData.iHP -= damageAmount;
|
||||
|
||||
if (mob.appearanceData.iHP <= 0)
|
||||
CombatManager::giveReward(sock);
|
||||
|
||||
respdata[i].eCT = 4;
|
||||
respdata[i].iDamage = damageAmount;
|
||||
respdata[i].iID = mob.appearanceData.iNPC_ID;
|
||||
respdata[i].iHP = mob.appearanceData.iHP;
|
||||
std::cout << (int)mob.appearanceData.iNPC_ID << " was damaged" << std::endl;
|
||||
}
|
||||
|
||||
sock->sendPacket((void*)&respbuf, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
||||
for (CNSocket* s : PlayerManager::players[sock].viewable)
|
||||
s->sendPacket((void*)&respbuf, P_FE2CL_NANO_SKILL_USE, resplen);
|
||||
}
|
||||
|
||||
void NanoManager::nanoLeech(CNSocket* sock, CNPacketData* data, int16_t nanoId, int16_t skillId, int32_t leechAmount) {
|
||||
sP_CL2FE_REQ_NANO_SKILL_USE* pkt = (sP_CL2FE_REQ_NANO_SKILL_USE*)data->buf;
|
||||
|
||||
// sanity check
|
||||
if (!validInVarPacket(sizeof(sP_CL2FE_REQ_NANO_SKILL_USE), pkt->iTargetCnt, sizeof(int32_t), data->size)) {
|
||||
std::cout << "[WARN] bad sP_CL2FE_REQ_NANO_SKILL_USE packet size\n";
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t *pktdata = (int32_t*)((uint8_t*)data->buf + sizeof(sP_CL2FE_REQ_NANO_SKILL_USE));
|
||||
|
||||
/*
|
||||
* Due to the possibility of multiplication overflow (and regular buffer overflow),
|
||||
* both incoming and outgoing variable-length packets must be validated, at least if
|
||||
* the number of trailing structs isn't well known (ie. it's from the client).
|
||||
*/
|
||||
if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE) + sizeof(sSkillResult_Heal_HP), pkt->iTargetCnt, sizeof(sSkillResult_Damage))) {
|
||||
std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE packet size\n";
|
||||
return;
|
||||
}
|
||||
|
||||
size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE) + sizeof(sSkillResult_Heal_HP) + pkt->iTargetCnt * sizeof(sSkillResult_Damage);
|
||||
uint8_t respbuf[4096];
|
||||
|
||||
memset(respbuf, 0, resplen);
|
||||
|
||||
sP_FE2CL_NANO_SKILL_USE *resp = (sP_FE2CL_NANO_SKILL_USE*)respbuf;
|
||||
sSkillResult_Heal_HP *resp2 = (sSkillResult_Heal_HP*)(respbuf+sizeof(sP_FE2CL_NANO_SKILL_USE));
|
||||
sSkillResult_Damage *respdata = (sSkillResult_Damage*)(respbuf+sizeof(sP_FE2CL_NANO_SKILL_USE)+sizeof(sSkillResult_Heal_HP));
|
||||
|
||||
Player *plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
resp->iPC_ID = plr->iID;
|
||||
resp->iSkillID = skillId;
|
||||
resp->iNanoID = nanoId;
|
||||
resp->iNanoStamina = 150;
|
||||
resp->eST = 30;
|
||||
resp->iTargetCnt = pkt->iTargetCnt;
|
||||
|
||||
if (plr->HP + leechAmount > 3625)
|
||||
plr->HP = 3625;
|
||||
else
|
||||
plr->HP += leechAmount;
|
||||
|
||||
resp2->eCT = 1;
|
||||
resp2->iID = plr->iID;
|
||||
resp2->iHP = plr->HP;
|
||||
resp2->iHealHP = leechAmount;
|
||||
|
||||
for (int i = 0; i < pkt->iTargetCnt; i++) {
|
||||
if (NPCManager::NPCs.find(pktdata[i]) == NPCManager::NPCs.end()) {
|
||||
// not sure how to best handle this
|
||||
std::cout << "[WARN] nanoDebuffEnemy: mob ID not found" << std::endl;
|
||||
return;
|
||||
}
|
||||
BaseNPC& mob = NPCManager::NPCs[pktdata[i]];
|
||||
|
||||
mob.appearanceData.iHP -= leechAmount;
|
||||
|
||||
if (mob.appearanceData.iHP <= 0)
|
||||
CombatManager::giveReward(sock);
|
||||
|
||||
respdata[i].eCT = 4;
|
||||
respdata[i].iDamage = leechAmount;
|
||||
respdata[i].iID = mob.appearanceData.iNPC_ID;
|
||||
respdata[i].iHP = mob.appearanceData.iHP;
|
||||
std::cout << (int)mob.appearanceData.iNPC_ID << " was damaged" << std::endl;
|
||||
}
|
||||
|
||||
sock->sendPacket((void*)&respbuf, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
||||
for (CNSocket* s : PlayerManager::players[sock].viewable)
|
||||
s->sendPacket((void*)&respbuf, P_FE2CL_NANO_SKILL_USE, resplen);
|
||||
}
|
||||
#pragma endregion
|
||||
|
@ -1,9 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "CNShardServer.hpp"
|
||||
|
||||
enum class SkillType {
|
||||
DAMAGE = 1,
|
||||
HEAL = 2,
|
||||
DRAIN = 3,
|
||||
SLEEP = 4,
|
||||
SNARE = 5,
|
||||
STUN = 8,
|
||||
LEECH = 30, // ...what?
|
||||
};
|
||||
|
||||
typedef void (*ActivePowerHandler)(CNSocket*, CNPacketData*, int16_t, int16_t, SkillType, int32_t, int32_t);
|
||||
|
||||
struct ActivePower {
|
||||
std::set<int> powers;
|
||||
ActivePowerHandler handler;
|
||||
SkillType eSkillType;
|
||||
int32_t flag;
|
||||
int32_t amount;
|
||||
|
||||
ActivePower(std::set<int> p, ActivePowerHandler h, SkillType t, int32_t f, int32_t a) : powers(p), handler(h), eSkillType(t), flag(f), amount(a) {}
|
||||
|
||||
void handle(CNSocket *sock, CNPacketData *data, int16_t nanoId, int16_t skillId) {
|
||||
if (handler == nullptr)
|
||||
return;
|
||||
|
||||
handler(sock, data, nanoId, skillId, eSkillType, flag, amount);
|
||||
}
|
||||
};
|
||||
|
||||
namespace NanoManager {
|
||||
extern std::vector<ActivePower> ActivePowers;
|
||||
void init();
|
||||
|
||||
void nanoSummonHandler(CNSocket* sock, CNPacketData* data);
|
||||
void nanoEquipHandler(CNSocket* sock, CNPacketData* data);
|
||||
void nanoUnEquipHandler(CNSocket* sock, CNPacketData* data);
|
||||
@ -19,10 +53,6 @@ namespace NanoManager {
|
||||
void setNanoSkill(CNSocket* sock, int16_t nanoId, int16_t skillId);
|
||||
void resetNanoSkill(CNSocket* sock, int16_t nanoId);
|
||||
|
||||
void nanoDebuff(CNSocket* sock, CNPacketData* data, int16_t nanoId, int16_t skillId, int16_t eSkillType, int32_t iCBFlag, int32_t damageAmount = 0);
|
||||
void nanoHeal(CNSocket* sock, CNPacketData* data, int16_t nanoId, int16_t skillId, int16_t healAmount);
|
||||
void nanoBuff(CNSocket* sock, int16_t nanoId, int skillId, int16_t eSkillType, int32_t iCBFlag, int16_t eCharStatusTimeBuffID, int16_t iValue = 0);
|
||||
void nanoUnbuff(CNSocket* sock, int32_t iCBFlag, int16_t eCharStatusTimeBuffID, int16_t iValue = 0);
|
||||
void nanoDamage(CNSocket* sock, CNPacketData* data, int16_t nanoId, int16_t skillId, int32_t damageAmount);
|
||||
void nanoLeech(CNSocket* sock, CNPacketData* data, int16_t nanoId, int16_t skillId, int32_t leechAmount);
|
||||
}
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
#define ACTIVE_MISSION_COUNT 6
|
||||
|
||||
#define PC_MAXHEALTH(level) (925 + 75 * (level))
|
||||
|
||||
struct Player {
|
||||
int accountId;
|
||||
int64_t SerialKey;
|
||||
|
Loading…
Reference in New Issue
Block a user