mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 05:20:05 +00:00
[WIP] Active power handling
TODO: - recall (self and group) is broken - revive (only group) is broken - damage + debuff is unimplemented
This commit is contained in:
parent
273b73379e
commit
bbaaa53df2
@ -35,7 +35,8 @@ static SkillResult handleSkillDamage(SkillData* skill, int power, ICombatant* so
|
|||||||
static SkillResult handleSkillHealHP(SkillData* skill, int power, ICombatant* source, ICombatant* target) {
|
static SkillResult handleSkillHealHP(SkillData* skill, int power, ICombatant* source, ICombatant* target) {
|
||||||
EntityRef sourceRef = source->getRef();
|
EntityRef sourceRef = source->getRef();
|
||||||
int heal = skill->values[0][power];
|
int heal = skill->values[0][power];
|
||||||
int healed = target->heal(sourceRef, heal);
|
double scalingFactor = target->getMaxHP() / 1000.0;
|
||||||
|
int healed = target->heal(sourceRef, heal * scalingFactor);
|
||||||
|
|
||||||
sSkillResult_Heal_HP result{};
|
sSkillResult_Heal_HP result{};
|
||||||
result.eCT = target->getCharType();
|
result.eCT = target->getCharType();
|
||||||
@ -97,6 +98,7 @@ static SkillResult handleSkillMove(SkillData* skill, int power, ICombatant* sour
|
|||||||
if(source->getCharType() != 1)
|
if(source->getCharType() != 1)
|
||||||
return SkillResult(); // only Players are valid sources for recall
|
return SkillResult(); // only Players are valid sources for recall
|
||||||
Player* plr = dynamic_cast<Player*>(source);
|
Player* plr = dynamic_cast<Player*>(source);
|
||||||
|
PlayerManager::sendPlayerTo(source->getRef().sock, plr->recallX, plr->recallY, plr->recallZ, plr->recallInstance);
|
||||||
|
|
||||||
sSkillResult_Move result{};
|
sSkillResult_Move result{};
|
||||||
result.eCT = target->getCharType();
|
result.eCT = target->getCharType();
|
||||||
@ -154,20 +156,22 @@ static std::vector<SkillResult> handleSkill(SkillData* skill, int power, ICombat
|
|||||||
resultSize = sizeof(sSkillResult_BatteryDrain);
|
resultSize = sizeof(sSkillResult_BatteryDrain);
|
||||||
skillHandler = handleSkillBatteryDrain;
|
skillHandler = handleSkillBatteryDrain;
|
||||||
break;
|
break;
|
||||||
case EST_RECALL:
|
case EST_RECALL: // still soft lock
|
||||||
case EST_RECALL_GROUP:
|
case EST_RECALL_GROUP: // works for player who uses it
|
||||||
resultSize = sizeof(sSkillResult_Move);
|
resultSize = sizeof(sSkillResult_Move);
|
||||||
skillHandler = handleSkillMove;
|
skillHandler = handleSkillMove;
|
||||||
break;
|
break;
|
||||||
case EST_PHOENIX_GROUP:
|
case EST_PHOENIX_GROUP: // broken
|
||||||
resultSize = sizeof(sSkillResult_Resurrect);
|
resultSize = sizeof(sSkillResult_Resurrect);
|
||||||
skillHandler = handleSkillResurrect;
|
skillHandler = handleSkillResurrect;
|
||||||
break;
|
break;
|
||||||
|
case EST_RETROROCKET_SELF:
|
||||||
|
// no-op
|
||||||
|
return results;
|
||||||
default:
|
default:
|
||||||
std::cout << "[WARN] Unhandled skill type " << skill->skillType << std::endl;
|
std::cout << "[WARN] Unhandled skill type " << skill->skillType << std::endl;
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
assert(skillHandler != nullptr);
|
|
||||||
|
|
||||||
for(ICombatant* target : targets) {
|
for(ICombatant* target : targets) {
|
||||||
assert(target != nullptr);
|
assert(target != nullptr);
|
||||||
@ -189,15 +193,21 @@ static void attachSkillResults(std::vector<SkillResult> results, size_t resultSi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Abilities::useNanoSkill(CNSocket* sock, sNano& nano, std::vector<ICombatant*> affected) {
|
void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std::vector<ICombatant*> affected) {
|
||||||
if(SkillTable.count(nano.iSkillID) == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
SkillData* skill = &SkillTable[nano.iSkillID];
|
|
||||||
Player* plr = PlayerManager::getPlayer(sock);
|
Player* plr = PlayerManager::getPlayer(sock);
|
||||||
|
|
||||||
std::vector<SkillResult> results = handleSkill(skill, Nanos::getNanoBoost(plr), plr, affected);
|
int boost = 0;
|
||||||
size_t resultSize = results.back().size; // guaranteed to be the same for every item
|
if (Nanos::getNanoBoost(plr))
|
||||||
|
boost = 3;
|
||||||
|
|
||||||
|
nano.iStamina -= skill->batteryUse[boost];
|
||||||
|
if (nano.iStamina < 0)
|
||||||
|
nano.iStamina = 0;
|
||||||
|
|
||||||
|
std::vector<SkillResult> results = handleSkill(skill, boost, plr, affected);
|
||||||
|
size_t resultSize = 0; // guaranteed to be the same for every item
|
||||||
|
if (!results.empty()) resultSize = results.back().size;
|
||||||
|
|
||||||
if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC), results.size(), resultSize)) {
|
if (!validOutVarPacket(sizeof(sP_FE2CL_NANO_SKILL_USE_SUCC), results.size(), resultSize)) {
|
||||||
std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE_SUCC packet size\n";
|
std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE_SUCC packet size\n";
|
||||||
@ -221,6 +231,9 @@ void Abilities::useNanoSkill(CNSocket* sock, sNano& nano, std::vector<ICombatant
|
|||||||
attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1));
|
attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1));
|
||||||
sock->sendPacket(pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
sock->sendPacket(pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
||||||
PlayerManager::sendToViewable(sock, pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
PlayerManager::sendToViewable(sock, pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
||||||
|
|
||||||
|
if (nano.iStamina <= 0)
|
||||||
|
Nanos::summonNano(sock, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Abilities::useNPCSkill(EntityRef npc, int skillID, std::vector<ICombatant*> affected) {
|
void Abilities::useNPCSkill(EntityRef npc, int skillID, std::vector<ICombatant*> affected) {
|
||||||
@ -257,21 +270,30 @@ void Abilities::useNPCSkill(EntityRef npc, int skillID, std::vector<ICombatant*>
|
|||||||
NPCManager::sendToViewable(entity, pkt, P_FE2CL_NPC_SKILL_HIT, resplen);
|
NPCManager::sendToViewable(entity, pkt, P_FE2CL_NPC_SKILL_HIT, resplen);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<EntityRef> Abilities::matchTargets(SkillData* skill, int count, int32_t *ids) {
|
std::vector<ICombatant*> Abilities::matchTargets(SkillData* skill, int count, int32_t *ids) {
|
||||||
|
|
||||||
std::vector<EntityRef> targets;
|
std::vector<ICombatant*> targets;
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
int32_t id = ids[i];
|
int32_t id = ids[i];
|
||||||
if (skill->targetType == SkillTargetType::MOBS) {
|
if (skill->targetType == SkillTargetType::MOBS) {
|
||||||
// mob?
|
// mob
|
||||||
if (NPCManager::NPCs.find(id) != NPCManager::NPCs.end()) targets.push_back(id);
|
if (NPCManager::NPCs.find(id) != NPCManager::NPCs.end()) {
|
||||||
else std::cout << "[WARN] skill: id not found\n";
|
BaseNPC* npc = NPCManager::NPCs[id];
|
||||||
} else {
|
if (npc->kind == EntityKind::COMBAT_NPC || npc->kind == EntityKind::MOB) {
|
||||||
// player?
|
targets.push_back(dynamic_cast<ICombatant*>(npc));
|
||||||
CNSocket* sock = PlayerManager::getSockFromID(id);
|
continue;
|
||||||
if (sock != nullptr) targets.push_back(sock);
|
}
|
||||||
else std::cout << "[WARN] skill: sock not found\n";
|
}
|
||||||
|
std::cout << "[WARN] skill: invalid mob target (id " << id << ")\n";
|
||||||
|
} else if(skill->targetType == SkillTargetType::SELF || skill->targetType == SkillTargetType::GROUP) {
|
||||||
|
// players (?)
|
||||||
|
Player* plr = PlayerManager::getPlayerFromID(id);
|
||||||
|
if (plr != nullptr) {
|
||||||
|
targets.push_back(dynamic_cast<ICombatant*>(plr));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::cout << "[WARN] skill: invalid player target (id " << id << ")\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,9 +60,9 @@ struct SkillData {
|
|||||||
namespace Abilities {
|
namespace Abilities {
|
||||||
extern std::map<int32_t, SkillData> SkillTable;
|
extern std::map<int32_t, SkillData> SkillTable;
|
||||||
|
|
||||||
void useNanoSkill(CNSocket*, sNano&, std::vector<ICombatant*>);
|
void useNanoSkill(CNSocket*, SkillData*, sNano&, std::vector<ICombatant*>);
|
||||||
void useNPCSkill(EntityRef, int skillID, std::vector<ICombatant*>);
|
void useNPCSkill(EntityRef, int skillID, std::vector<ICombatant*>);
|
||||||
|
|
||||||
std::vector<EntityRef> matchTargets(SkillData*, int, int32_t*);
|
std::vector<ICombatant*> matchTargets(SkillData*, int, int32_t*);
|
||||||
int getCSTBFromST(int eSkillType);
|
int getCSTBFromST(int eSkillType);
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ void Nanos::summonNano(CNSocket *sock, int slot, bool silent) {
|
|||||||
// passive buff effect
|
// passive buff effect
|
||||||
resp.eCSTB___Add = 1;
|
resp.eCSTB___Add = 1;
|
||||||
std::vector<ICombatant*> affectedCombatants = applyNanoBuff(skill, plr);
|
std::vector<ICombatant*> affectedCombatants = applyNanoBuff(skill, plr);
|
||||||
if(!affectedCombatants.empty()) Abilities::useNanoSkill(sock, nano, affectedCombatants);
|
if(!affectedCombatants.empty()) Abilities::useNanoSkill(sock, skill, nano, affectedCombatants);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!silent) // silent nano death but only for the summoning player
|
if (!silent) // silent nano death but only for the summoning player
|
||||||
@ -309,26 +309,17 @@ static void nanoSkillUseHandler(CNSocket* sock, CNPacketData* data) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t skillID = plr->Nanos[plr->activeNano].iSkillID;
|
sNano& nano = plr->Nanos[plr->activeNano];
|
||||||
|
int16_t skillID = nano.iSkillID;
|
||||||
SkillData* skillData = &Abilities::SkillTable[skillID];
|
SkillData* skillData = &Abilities::SkillTable[skillID];
|
||||||
|
|
||||||
DEBUGLOG(
|
DEBUGLOG(
|
||||||
std::cout << PlayerManager::getPlayerName(plr) << " requested to summon nano skill " << std::endl;
|
std::cout << PlayerManager::getPlayerName(plr) << " requested to summon nano skill " << std::endl;
|
||||||
)
|
)
|
||||||
|
|
||||||
int boost = 0;
|
|
||||||
if (getNanoBoost(plr))
|
|
||||||
boost = 1;
|
|
||||||
|
|
||||||
plr->Nanos[plr->activeNano].iStamina -= Abilities::SkillTable[skillID].batteryUse[boost*3];
|
|
||||||
if (plr->Nanos[plr->activeNano].iStamina < 0)
|
|
||||||
plr->Nanos[plr->activeNano].iStamina = 0;
|
|
||||||
|
|
||||||
// TODO ABILITIES
|
// TODO ABILITIES
|
||||||
std::vector<EntityRef> targetData = Abilities::matchTargets(skillData, pkt->iTargetCnt, (int32_t*)(pkt + 1));
|
std::vector<ICombatant*> targetData = Abilities::matchTargets(skillData, pkt->iTargetCnt, (int32_t*)(pkt + 1));
|
||||||
/*for (auto& pwr : Abilities::Powers)
|
Abilities::useNanoSkill(sock, skillData, nano, targetData);
|
||||||
if (pwr.skillType == Abilities::SkillTable[skillID].skillType)
|
|
||||||
pwr.handle(sock, targetData, nanoID, skillID, Abilities::SkillTable[skillID].durationTime[boost], Abilities::SkillTable[skillID].powerIntensity[boost]);*/
|
|
||||||
|
|
||||||
if (plr->Nanos[plr->activeNano].iStamina < 0)
|
if (plr->Nanos[plr->activeNano].iStamina < 0)
|
||||||
summonNano(sock, -1);
|
summonNano(sock, -1);
|
||||||
|
Loading…
Reference in New Issue
Block a user