Refactored Nano Powers

* All nano power functions have been merged into one goliath of a function.
* Nano powers consume the correct amount of stamina.
* Bugfixed gumball issues, gumballed nanos now perform better.
* Revive powers now work correctly.
* Recall powers both self and group are functional.
* Removed nanoBuff.
* Added a new applyBuff function, this allows for quick and easy application of nano skills.
* Numerous other bugfixes.
This commit is contained in:
Jade 2020-11-08 00:26:44 +00:00 committed by Gent S
parent 2acb90f2d2
commit 299fc1b461
8 changed files with 574 additions and 571 deletions

View File

@ -106,8 +106,6 @@ void GroupManager::joinGroup(CNSocket* sock, CNPacketData* data) {
return; return;
} }
int bitFlagBefore = getGroupFlags(otherPlr);
plr->iIDGroup = otherPlr->iID; plr->iIDGroup = otherPlr->iID;
otherPlr->groupCnt += 1; otherPlr->groupCnt += 1;
otherPlr->groupIDs[otherPlr->groupCnt-1] = plr->iID; otherPlr->groupIDs[otherPlr->groupCnt-1] = plr->iID;
@ -148,7 +146,10 @@ void GroupManager::joinGroup(CNSocket* sock, CNPacketData* data) {
respdata[i].iZ = varPlr->z; respdata[i].iZ = varPlr->z;
// client doesnt read nano data here // client doesnt read nano data here
NanoManager::nanoChangeBuff(sockTo, varPlr, bitFlagBefore | varPlr->iConditionBitFlag, bitFlag | varPlr->iConditionBitFlag); if (varPlr != plr) {
NanoManager::applyBuff(sock, varPlr->Nanos[varPlr->activeNano].iSkillID, 1, 1, bitFlag);
NanoManager::applyBuff(sockTo, plr->Nanos[plr->activeNano].iSkillID, 1, 1, bitFlag);
}
} }
sendToGroup(otherPlr, (void*)&respbuf, P_FE2CL_PC_GROUP_JOIN, resplen); sendToGroup(otherPlr, (void*)&respbuf, P_FE2CL_PC_GROUP_JOIN, resplen);
@ -302,10 +303,14 @@ void GroupManager::groupKickPlayer(Player* plr) {
resp->iID_LeaveMember = plr->iID; resp->iID_LeaveMember = plr->iID;
resp->iMemberPCCnt = otherPlr->groupCnt - 1; resp->iMemberPCCnt = otherPlr->groupCnt - 1;
int bitFlagBefore = getGroupFlags(otherPlr); int bitFlag = getGroupFlags(otherPlr) & ~plr->iGroupConditionBitFlag;
int bitFlag = bitFlagBefore & ~plr->iGroupConditionBitFlag;
int moveDown = 0; int moveDown = 0;
CNSocket* sock = PlayerManager::getSockFromID(plr->iID);
if (sock == nullptr)
return;
for (int i = 0; i < otherPlr->groupCnt; i++) { for (int i = 0; i < otherPlr->groupCnt; i++) {
Player* varPlr = PlayerManager::getPlayerFromID(otherPlr->groupIDs[i]); Player* varPlr = PlayerManager::getPlayerFromID(otherPlr->groupIDs[i]);
CNSocket* sockTo = PlayerManager::getSockFromID(otherPlr->groupIDs[i]); CNSocket* sockTo = PlayerManager::getSockFromID(otherPlr->groupIDs[i]);
@ -335,9 +340,10 @@ void GroupManager::groupKickPlayer(Player* plr) {
if (varPlr == plr) { if (varPlr == plr) {
moveDown = 1; moveDown = 1;
otherPlr->groupIDs[i] = 0; otherPlr->groupIDs[i] = 0;
NanoManager::nanoChangeBuff(sockTo, varPlr, bitFlagBefore | varPlr->iConditionBitFlag, varPlr->iConditionBitFlag); } else {
} else NanoManager::applyBuff(sock, varPlr->Nanos[varPlr->activeNano].iSkillID, 2, 1, 0);
NanoManager::nanoChangeBuff(sockTo, varPlr, bitFlagBefore | varPlr->iConditionBitFlag, bitFlag | varPlr->iConditionBitFlag); NanoManager::applyBuff(sockTo, plr->Nanos[plr->activeNano].iSkillID, 2, 1, bitFlag);
}
} }
plr->iIDGroup = plr->iID; plr->iIDGroup = plr->iID;
@ -345,26 +351,24 @@ void GroupManager::groupKickPlayer(Player* plr) {
sendToGroup(otherPlr, (void*)&respbuf, P_FE2CL_PC_GROUP_LEAVE, resplen); sendToGroup(otherPlr, (void*)&respbuf, P_FE2CL_PC_GROUP_LEAVE, resplen);
CNSocket* sock = PlayerManager::getSockFromID(plr->iID);
if (sock == nullptr)
return;
INITSTRUCT(sP_FE2CL_PC_GROUP_LEAVE_SUCC, resp1); 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)); sock->sendPacket((void*)&resp1, P_FE2CL_PC_GROUP_LEAVE_SUCC, sizeof(sP_FE2CL_PC_GROUP_LEAVE_SUCC));
} }
void GroupManager::groupUnbuff(Player* plr) { void GroupManager::groupUnbuff(Player* plr) {
int bitFlag = getGroupFlags(plr);
for (int i = 0; i < plr->groupCnt; i++) { for (int i = 0; i < plr->groupCnt; i++) {
CNSocket* sock = PlayerManager::getSockFromID(plr->groupIDs[i]); for (int n = 0; n < plr->groupCnt; n++) {
if (i == n)
continue;
if (sock == nullptr) Player* otherPlr = PlayerManager::getPlayerFromID(plr->groupIDs[i]);
continue; CNSocket* sock = PlayerManager::getSockFromID(plr->groupIDs[n]);
Player* otherPlr = PlayerManager::getPlayer(sock); if (otherPlr == nullptr || sock == nullptr)
NanoManager::nanoChangeBuff(sock, otherPlr, bitFlag | otherPlr->iConditionBitFlag, otherPlr->iConditionBitFlag); continue;
NanoManager::applyBuff(sock, otherPlr->Nanos[otherPlr->activeNano].iSkillID, 2, 1, 0);
}
} }
} }

View File

@ -263,25 +263,44 @@ void ItemManager::itemUseHandler(CNSocket* sock, CNPacketData* data) {
if (gumball.iOpt == 0) if (gumball.iOpt == 0)
gumball = {}; gumball = {};
INITSTRUCT(sP_FE2CL_REP_PC_ITEM_USE_SUCC, response); size_t resplen = sizeof(sP_FE2CL_REP_PC_ITEM_USE_SUCC) + sizeof(sSkillResult_Buff);
response.iPC_ID = player->iID;
response.eIL = 1;
response.iSlotNum = request->iSlotNum;
response.RemainItem = gumball;
// response.iTargetCnt = ?
// response.eST = ?
// response.iSkillID = ?
sock->sendPacket((void*)&response, P_FE2CL_REP_PC_ITEM_USE_SUCC, sizeof(sP_FE2CL_REP_PC_ITEM_USE_SUCC)); // validate response packet
// update inventory serverside if (!validOutVarPacket(sizeof(sP_FE2CL_REP_PC_ITEM_USE_SUCC), 1, sizeof(sSkillResult_Buff))) {
player->Inven[response.iSlotNum] = response.RemainItem; std::cout << "[WARN] bad sP_FE2CL_REP_PC_ITEM_USE_SUCC packet size" << std::endl;
return;
}
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
memset(respbuf, 0, resplen);
sP_FE2CL_REP_PC_ITEM_USE_SUCC *resp = (sP_FE2CL_REP_PC_ITEM_USE_SUCC*)respbuf;
sSkillResult_Buff *respdata = (sSkillResult_Buff*)(respbuf+sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC));
resp->iPC_ID = player->iID;
resp->eIL = 1;
resp->iSlotNum = request->iSlotNum;
resp->RemainItem = gumball;
resp->iTargetCnt = 1;
resp->eST = EST_NANOSTIMPAK;
resp->iSkillID = 144;
// this is a temporary way of calling buff efect
// TODO: send buff data via response packet
int value1 = CSB_BIT_STIMPAKSLOT1 << request->iNanoSlot; int value1 = CSB_BIT_STIMPAKSLOT1 << request->iNanoSlot;
int value2 = ECSB_STIMPAKSLOT1 + request->iNanoSlot; int value2 = ECSB_STIMPAKSLOT1 + request->iNanoSlot;
NanoManager::nanoBuff(sock, nano.iID, 144, EST_NANOSTIMPAK, value1, value2, 0); respdata->eCT = 1;
respdata->iID = player->iID;
respdata->iConditionBitFlag = value1;
INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, pkt);
pkt.eCSTB = value2; // eCharStatusTimeBuffID
pkt.eTBU = 1; // eTimeBuffUpdate
pkt.eTBT = 1; // eTimeBuffType 1 means nano
pkt.iConditionBitFlag = player->iConditionBitFlag |= value1;
sock->sendPacket((void*)&pkt, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE));
sock->sendPacket((void*)&respbuf, P_FE2CL_REP_PC_ITEM_USE_SUCC, resplen);
// update inventory serverside
player->Inven[resp->iSlotNum] = resp->RemainItem;
} }
void ItemManager::itemBankOpenHandler(CNSocket* sock, CNPacketData* data) { void ItemManager::itemBankOpenHandler(CNSocket* sock, CNPacketData* data) {

View File

@ -505,7 +505,7 @@ void MobManager::combatStep(Mob *mob, time_t currTime) {
// drain // drain
if ((mob->lastDrainTime == 0 || currTime - mob->lastDrainTime >= 1000) && mob->appearanceData.iConditionBitFlag & CSB_BIT_BOUNDINGBALL) { if ((mob->lastDrainTime == 0 || currTime - mob->lastDrainTime >= 1000) && mob->appearanceData.iConditionBitFlag & CSB_BIT_BOUNDINGBALL) {
drainMobHP(mob, mob->maxHealth / 15); // lose 6.67% every second drainMobHP(mob, mob->maxHealth / 20); // lose 5% every second
mob->lastDrainTime = currTime; mob->lastDrainTime = currTime;
} }
@ -934,10 +934,7 @@ 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 -= 1; plr->Nanos[plr->activeNano].iStamina -= 1 + plr->nanoDrainRate * 2 / 5;
if (plr->passiveNanoOut)
plr->Nanos[plr->activeNano].iStamina -= 1;
if (plr->Nanos[plr->activeNano].iStamina <= 0) { if (plr->Nanos[plr->activeNano].iStamina <= 0) {
plr->Nanos[plr->activeNano].iStamina = 0; plr->Nanos[plr->activeNano].iStamina = 0;

File diff suppressed because it is too large Load Diff

View File

@ -5,22 +5,25 @@
#include "CNShardServer.hpp" #include "CNShardServer.hpp"
typedef void (*ActivePowerHandler)(CNSocket*, CNPacketData*, int16_t, int16_t, int16_t, int32_t, int32_t); struct TargetData {
int targetID[4];
};
typedef void (*PowerHandler)(CNSocket*, TargetData, int16_t, int16_t, int16_t, int16_t, int16_t, int32_t, int16_t);
struct ActivePower { struct ActivePower {
std::set<int> powers; int16_t skillType;
ActivePowerHandler handler; int32_t bitFlag;
int16_t eSkillType; int16_t timeBuffID;
int32_t flag; PowerHandler handler;
int32_t amount;
ActivePower(std::set<int> p, ActivePowerHandler h, int16_t t, int32_t f, int32_t a) : powers(p), handler(h), eSkillType(t), flag(f), amount(a) {} ActivePower(int16_t s, int32_t b, int16_t t, PowerHandler h) : skillType(s), bitFlag(b), timeBuffID(t), handler(h) {}
void handle(CNSocket *sock, CNPacketData *data, int16_t nanoId, int16_t skillId) { void handle(CNSocket *sock, TargetData targetData, int16_t nanoID, int16_t skillID, int16_t duration, int16_t amount) {
if (handler == nullptr) if (handler == nullptr)
return; return;
handler(sock, data, nanoId, skillId, eSkillType, flag, amount); handler(sock, targetData, nanoID, skillID, duration, amount, skillType, bitFlag, timeBuffID);
} }
}; };
@ -47,6 +50,7 @@ struct NanoTuning {
struct SkillData { struct SkillData {
int skillType; int skillType;
int targetType; int targetType;
int drainType;
int batteryUse[4]; int batteryUse[4];
int durationTime[4]; int durationTime[4];
int powerIntensity[4]; int powerIntensity[4];
@ -67,19 +71,16 @@ namespace NanoManager {
void nanoSkillUseHandler(CNSocket* sock, CNPacketData* data); void nanoSkillUseHandler(CNSocket* sock, CNPacketData* data);
void nanoSkillSetHandler(CNSocket* sock, CNPacketData* data); void nanoSkillSetHandler(CNSocket* sock, CNPacketData* data);
void nanoSkillSetGMHandler(CNSocket* sock, CNPacketData* data); void nanoSkillSetGMHandler(CNSocket* sock, CNPacketData* data);
void nanoRecallRegisterHandler(CNSocket* sock, CNPacketData* data);
void nanoRecallHandler(CNSocket* sock, CNPacketData* data); void nanoRecallHandler(CNSocket* sock, CNPacketData* data);
void nanoPotionHandler(CNSocket* sock, CNPacketData* data); void nanoPotionHandler(CNSocket* sock, CNPacketData* data);
// Helper methods // Helper methods
void addNano(CNSocket* sock, int16_t nanoId, int16_t slot, bool spendfm=false); void addNano(CNSocket* sock, int16_t nanoID, int16_t slot, bool spendfm=false);
void summonNano(CNSocket* sock, int slot); void summonNano(CNSocket* sock, int slot);
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, TargetData targetData, int32_t bitFlag, int16_t timeBuffID, int16_t amount, bool groupPower);
void nanoBuff(CNSocket* sock, int16_t nanoId, int skillId, int16_t eSkillType, int32_t iCBFlag, int16_t eCharStatusTimeBuffID, int16_t iValue = 0, bool groupPower = false); void applyBuff(CNSocket* sock, int skillID, int eTBU, int eTBT, int32_t groupFlags);
void nanoUnbuff(CNSocket* sock, int32_t iCBFlag, int16_t eCharStatusTimeBuffID, int16_t iValue = 0, bool groupPower = false); int nanoStyle(int nanoID);
int nanoStyle(int nanoId);
void revivePlayer(Player* plr);
void nanoChangeBuff(CNSocket* sock, Player* plr, int32_t cbFrom, int32_t cbTo);
} }

View File

@ -36,10 +36,12 @@ struct Player {
int32_t iWarpLocationFlag; int32_t iWarpLocationFlag;
int64_t aSkywayLocationFlag[2]; int64_t aSkywayLocationFlag[2];
int32_t iConditionBitFlag; int32_t iConditionBitFlag;
int32_t iSelfConditionBitFlag;
int8_t iSpecialState; int8_t iSpecialState;
int x, y, z, angle; int x, y, z, angle;
int lastX, lastY, lastZ, lastAngle; int lastX, lastY, lastZ, lastAngle;
int recallX, recallY, recallZ, recallInstance;
uint64_t instanceID; uint64_t instanceID;
sItemBase Equip[AEQUIP_COUNT]; sItemBase Equip[AEQUIP_COUNT];
sItemBase Inven[AINVEN_COUNT]; sItemBase Inven[AINVEN_COUNT];
@ -51,7 +53,7 @@ struct Player {
bool inCombat; bool inCombat;
bool onMonkey; bool onMonkey;
bool passiveNanoOut; int nanoDrainRate;
int healCooldown; int healCooldown;
int pointDamage; int pointDamage;

View File

@ -712,10 +712,16 @@ void PlayerManager::revivePlayer(CNSocket* sock, CNPacketData* data) {
bool move = false; bool move = false;
if (reviveData->iRegenType == 3 && plr->iConditionBitFlag & CSB_BIT_PHOENIX) { if (reviveData->iRegenType == 3 && plr->iConditionBitFlag & CSB_BIT_PHOENIX || reviveData->iRegenType == 4) {
// nano revive // nano revive
plr->Nanos[plr->activeNano].iStamina = 0; plr->Nanos[plr->activeNano].iStamina = 0;
NanoManager::nanoUnbuff(sock, CSB_BIT_PHOENIX, ECSB_PHOENIX, 0, false);
INITSTRUCT(TargetData, targetData);
targetData.targetID[0] = plr->iID;
for (int i = 1; i < 4; i++)
targetData.targetID[i] = -1;
NanoManager::nanoUnbuff(sock, targetData, CSB_BIT_PHOENIX, ECSB_PHOENIX, 0, false);
plr->HP = PC_MAXHEALTH(plr->level); plr->HP = PC_MAXHEALTH(plr->level);
} else { } else {
move = true; move = true;

View File

@ -195,7 +195,7 @@ void TableData::init() {
for (nlohmann::json::iterator _skills = skills.begin(); _skills != skills.end(); _skills++) { for (nlohmann::json::iterator _skills = skills.begin(); _skills != skills.end(); _skills++) {
auto skills = _skills.value(); auto skills = _skills.value();
SkillData skillData = {skills["m_iSkillType"], skills["m_iTargetType"]}; SkillData skillData = {skills["m_iSkillType"], skills["m_iTargetType"], skills["m_iBatteryDrainType"]};
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
skillData.batteryUse[i] = skills["m_iBatteryDrainUse"][i]; skillData.batteryUse[i] = skills["m_iBatteryDrainUse"][i];
skillData.durationTime[i] = skills["m_iDurationTime"][i]; skillData.durationTime[i] = skills["m_iDurationTime"][i];