From 41622ad8aab2941116d6d6ebc4985668532f736b Mon Sep 17 00:00:00 2001 From: gsemaj Date: Tue, 25 Jul 2023 17:05:44 +0000 Subject: [PATCH] Fix trailing structs The change to allow flexible trailing struct sizes broke `attachSkillResults` oops --- src/Abilities.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/Abilities.cpp b/src/Abilities.cpp index 73bf929..e218707 100644 --- a/src/Abilities.cpp +++ b/src/Abilities.cpp @@ -216,16 +216,18 @@ static std::vector handleSkill(SkillData* skill, int power, ICombat return results; } -static void attachSkillResults(std::vector results, size_t resultSize, uint8_t* pivot) { +static void attachSkillResults(std::vector results, uint8_t* pivot) { for(SkillResult& result : results) { - memcpy(pivot, result.payload, resultSize); - pivot += resultSize; + size_t sz = result.size; + memcpy(pivot, result.payload, sz); + pivot += sz; } } void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std::vector affected) { Player* plr = PlayerManager::getPlayer(sock); + ICombatant* combatant = dynamic_cast(plr); int boost = 0; if (Nanos::getNanoBoost(plr)) @@ -237,17 +239,19 @@ void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std: nano.iStamina = 0; } - std::vector results = handleSkill(skill, boost, plr, affected); + std::vector results = handleSkill(skill, boost, combatant, affected); if(results.empty()) return; // no effect; no need for confirmation packets - size_t resultSize = MAX_SKILLRESULT_SIZE; // lazy - if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC), results.size(), resultSize)) { + // lazy validation since skill results might be different sizes + if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC), results.size(), MAX_SKILLRESULT_SIZE)) { std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE_SUCC packet size\n"; return; } // initialize response struct - size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC) + results.size() * resultSize; + size_t resplen = sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC); + for(SkillResult& sr : results) + resplen += sr.size; uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; memset(respbuf, 0, resplen); @@ -260,7 +264,7 @@ void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std: pkt->eST = (int32_t)skill->skillType; pkt->iTargetCnt = (int32_t)results.size(); - attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1)); + attachSkillResults(results, (uint8_t*)(pkt + 1)); sock->sendPacket(pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen); if(skill->skillType == SkillType::RECALL_GROUP) @@ -284,15 +288,16 @@ void Abilities::useNPCSkill(EntityRef npc, int skillID, std::vector std::vector results = handleSkill(skill, 0, src, affected); if(results.empty()) return; // no effect; no need for confirmation packets - size_t resultSize = results.back().size; // guaranteed to be the same for every item - - if (!validOutVarPacket(sizeof(sP_FE2CL_NPC_SKILL_HIT), results.size(), resultSize)) { + // lazy validation since skill results might be different sizes + if (!validOutVarPacket(sizeof(sP_FE2CL_NPC_SKILL_HIT), results.size(), MAX_SKILLRESULT_SIZE)) { std::cout << "[WARN] bad sP_FE2CL_NPC_SKILL_HIT packet size\n"; return; } // initialize response struct - size_t resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT) + results.size() * resultSize; + size_t resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT); + for(SkillResult& sr : results) + resplen += sr.size; uint8_t respbuf[CN_PACKET_BUFFER_SIZE]; memset(respbuf, 0, resplen); @@ -302,7 +307,7 @@ void Abilities::useNPCSkill(EntityRef npc, int skillID, std::vector pkt->eST = (int32_t)skill->skillType; pkt->iTargetCnt = (int32_t)results.size(); - attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1)); + attachSkillResults(results, (uint8_t*)(pkt + 1)); NPCManager::sendToViewable(entity, pkt, P_FE2CL_NPC_SKILL_HIT, resplen); }