mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-26 15:00:06 +00:00
Compare commits
1 Commits
02cc58dfb0
...
0b325f6f9f
Author | SHA1 | Date | |
---|---|---|---|
|
0b325f6f9f |
@ -57,23 +57,6 @@ static SkillResult handleSkillDamageNDebuff(SkillData* skill, int power, ICombat
|
|||||||
}
|
}
|
||||||
|
|
||||||
static SkillResult handleSkillBuff(SkillData* skill, int power, ICombatant* source, ICombatant* target) {
|
static SkillResult handleSkillBuff(SkillData* skill, int power, ICombatant* source, ICombatant* target) {
|
||||||
BuffStack passiveBuff = {
|
|
||||||
skill->drainType == SkillDrainType::PASSIVE ? 1 : skill->durationTime[power], // ticks
|
|
||||||
skill->values[0][power], // value
|
|
||||||
source->getRef(), // source
|
|
||||||
source == target ? BuffClass::NANO : BuffClass::GROUP_NANO, // buff class
|
|
||||||
};
|
|
||||||
|
|
||||||
int timeBuffId = Abilities::getCSTBFromST(skill->skillType);
|
|
||||||
if(!target->addBuff(timeBuffId,
|
|
||||||
[](EntityRef self, Buff* buff, int status, BuffStack* stack) {
|
|
||||||
Buffs::timeBuffUpdate(self, buff, status, stack);
|
|
||||||
},
|
|
||||||
[](EntityRef self, Buff* buff, time_t currTime) {
|
|
||||||
// no-op
|
|
||||||
},
|
|
||||||
&passiveBuff)) return SkillResult(); // no result if already buffed
|
|
||||||
|
|
||||||
sSkillResult_Buff result{};
|
sSkillResult_Buff result{};
|
||||||
result.eCT = target->getCharType();
|
result.eCT = target->getCharType();
|
||||||
result.iID = target->getID();
|
result.iID = target->getID();
|
||||||
@ -223,16 +206,14 @@ void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std:
|
|||||||
if (Nanos::getNanoBoost(plr))
|
if (Nanos::getNanoBoost(plr))
|
||||||
boost = 3;
|
boost = 3;
|
||||||
|
|
||||||
if(skill->drainType == SkillDrainType::ACTIVE) {
|
|
||||||
nano.iStamina -= skill->batteryUse[boost];
|
nano.iStamina -= skill->batteryUse[boost];
|
||||||
if (nano.iStamina <= 0)
|
if (nano.iStamina < 0)
|
||||||
nano.iStamina = 0;
|
nano.iStamina = 0;
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<SkillResult> results = handleSkill(skill, boost, plr, affected);
|
std::vector<SkillResult> results = handleSkill(skill, boost, plr, affected);
|
||||||
if(results.empty()) return; // no effect; no need for confirmation packets
|
size_t resultSize = 0; // guaranteed to be the same for every item
|
||||||
|
if (!results.empty()) resultSize = results.back().size;
|
||||||
|
|
||||||
size_t resultSize = results.back().size; // guaranteed to be the same for every item
|
|
||||||
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";
|
||||||
return;
|
return;
|
||||||
@ -260,6 +241,9 @@ void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std:
|
|||||||
PlayerManager::sendToGroup(sock, pkt, P_FE2CL_NANO_SKILL_USE, resplen);
|
PlayerManager::sendToGroup(sock, pkt, P_FE2CL_NANO_SKILL_USE, resplen);
|
||||||
else
|
else
|
||||||
PlayerManager::sendToViewable(sock, pkt, P_FE2CL_NANO_SKILL_USE, resplen);
|
PlayerManager::sendToViewable(sock, pkt, P_FE2CL_NANO_SKILL_USE, 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) {
|
||||||
@ -309,8 +293,14 @@ static std::vector<ICombatant*> entityRefsToCombatants(std::vector<EntityRef> re
|
|||||||
|
|
||||||
std::vector<ICombatant*> Abilities::matchTargets(ICombatant* src, SkillData* skill, int count, int32_t *ids) {
|
std::vector<ICombatant*> Abilities::matchTargets(ICombatant* src, SkillData* skill, int count, int32_t *ids) {
|
||||||
|
|
||||||
if(skill->targetType == SkillTargetType::GROUP)
|
if(skill->targetType == SkillTargetType::GROUP) {
|
||||||
|
// group
|
||||||
|
if(count != 1 || ids[0] != src->getID()) {
|
||||||
|
std::cout << "[WARN] skill: bad group targeting (id " << ids[0] << ")\n";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
return entityRefsToCombatants(src->getGroupMembers());
|
return entityRefsToCombatants(src->getGroupMembers());
|
||||||
|
}
|
||||||
|
|
||||||
// this check *has* to happen after the group check above due to cases like group recall that use both
|
// this check *has* to happen after the group check above due to cases like group recall that use both
|
||||||
if(skill->effectTarget == SkillEffectTarget::SELF)
|
if(skill->effectTarget == SkillEffectTarget::SELF)
|
||||||
@ -403,8 +393,6 @@ int Abilities::getCSTBFromST(SkillType skillType) {
|
|||||||
case SkillType::NANOSTIMPAK:
|
case SkillType::NANOSTIMPAK:
|
||||||
result = ECSB_STIMPAKSLOT1;
|
result = ECSB_STIMPAKSLOT1;
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -874,12 +874,9 @@ static void playerTick(CNServer *serv, time_t currTime) {
|
|||||||
if (Abilities::SkillTable.find(nano->iSkillID) != Abilities::SkillTable.end()) {
|
if (Abilities::SkillTable.find(nano->iSkillID) != Abilities::SkillTable.end()) {
|
||||||
// nano has skill data
|
// nano has skill data
|
||||||
SkillData* skill = &Abilities::SkillTable[nano->iSkillID];
|
SkillData* skill = &Abilities::SkillTable[nano->iSkillID];
|
||||||
if (skill->drainType == SkillDrainType::PASSIVE) {
|
if (skill->drainType == SkillDrainType::PASSIVE)
|
||||||
ICombatant* src = dynamic_cast<ICombatant*>(plr);
|
Nanos::applyNanoBuff(skill, plr);
|
||||||
int32_t targets[] = { plr->iID };
|
// ^ composite condition calculation is separate from combat for responsiveness
|
||||||
std::vector<ICombatant*> affectedCombatants = Abilities::matchTargets(src, skill, 1, targets);
|
|
||||||
Abilities::useNanoSkill(sock, skill, *nano, affectedCombatants);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +69,43 @@ void Nanos::addNano(CNSocket* sock, int16_t nanoID, int16_t slot, bool spendfm)
|
|||||||
PlayerManager::sendToViewable(sock, resp2, P_FE2CL_REP_PC_CHANGE_LEVEL);
|
PlayerManager::sendToViewable(sock, resp2, P_FE2CL_REP_PC_CHANGE_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<ICombatant*> Nanos::applyNanoBuff(SkillData* skill, Player* plr) {
|
||||||
|
assert(skill->drainType == SkillDrainType::PASSIVE);
|
||||||
|
|
||||||
|
EntityRef self = PlayerManager::getSockFromID(plr->iID);
|
||||||
|
|
||||||
|
int timeBuffId = Abilities::getCSTBFromST(skill->skillType);
|
||||||
|
int boost = Nanos::getNanoBoost(plr) ? 3 : 0;
|
||||||
|
int value = skill->values[0][boost];
|
||||||
|
|
||||||
|
BuffStack passiveBuff = {
|
||||||
|
1, // passive nano buffs refreshed every tick
|
||||||
|
value,
|
||||||
|
self,
|
||||||
|
BuffClass::NONE, // overwritten per target
|
||||||
|
};
|
||||||
|
|
||||||
|
// for passive skills, using just the player as a target is fine
|
||||||
|
// this is because the group skill type will ignore the count,
|
||||||
|
// and the other option is single-target
|
||||||
|
std::vector<ICombatant*> targets = Abilities::matchTargets(dynamic_cast<ICombatant*>(plr), skill, 1, &plr->iID);
|
||||||
|
std::vector<ICombatant*> affected;
|
||||||
|
for (ICombatant* target : targets) {
|
||||||
|
|
||||||
|
passiveBuff.buffStackClass = target == plr ? BuffClass::NANO : BuffClass::GROUP_NANO;
|
||||||
|
if(target->addBuff(timeBuffId,
|
||||||
|
[](EntityRef self, Buff* buff, int status, BuffStack* stack) {
|
||||||
|
Buffs::timeBuffUpdate(self, buff, status, stack);
|
||||||
|
},
|
||||||
|
[](EntityRef self, Buff* buff, time_t currTime) {
|
||||||
|
// no-op
|
||||||
|
},
|
||||||
|
&passiveBuff)) affected.push_back(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
return affected;
|
||||||
|
}
|
||||||
|
|
||||||
void Nanos::summonNano(CNSocket *sock, int slot, bool silent) {
|
void Nanos::summonNano(CNSocket *sock, int slot, bool silent) {
|
||||||
INITSTRUCT(sP_FE2CL_REP_NANO_ACTIVE_SUCC, resp);
|
INITSTRUCT(sP_FE2CL_REP_NANO_ACTIVE_SUCC, resp);
|
||||||
resp.iActiveNanoSlotNum = slot;
|
resp.iActiveNanoSlotNum = slot;
|
||||||
@ -93,10 +130,8 @@ void Nanos::summonNano(CNSocket *sock, int slot, bool silent) {
|
|||||||
if (slot != -1 && skill != nullptr && skill->drainType == SkillDrainType::PASSIVE) {
|
if (slot != -1 && skill != nullptr && skill->drainType == SkillDrainType::PASSIVE) {
|
||||||
// passive buff effect
|
// passive buff effect
|
||||||
resp.eCSTB___Add = 1;
|
resp.eCSTB___Add = 1;
|
||||||
ICombatant* src = dynamic_cast<ICombatant*>(plr);
|
std::vector<ICombatant*> affectedCombatants = applyNanoBuff(skill, plr);
|
||||||
int32_t targets[] = { plr->iID };
|
if(!affectedCombatants.empty()) Abilities::useNanoSkill(sock, skill, nano, affectedCombatants);
|
||||||
std::vector<ICombatant*> affectedCombatants = Abilities::matchTargets(src, skill, 1, targets);
|
|
||||||
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
|
||||||
@ -277,7 +312,7 @@ static void nanoSkillUseHandler(CNSocket* sock, CNPacketData* data) {
|
|||||||
std::vector<ICombatant*> targetData = Abilities::matchTargets(plrCombatant, skillData, pkt->iTargetCnt, (int32_t*)(pkt + 1));
|
std::vector<ICombatant*> targetData = Abilities::matchTargets(plrCombatant, skillData, pkt->iTargetCnt, (int32_t*)(pkt + 1));
|
||||||
Abilities::useNanoSkill(sock, skillData, nano, targetData);
|
Abilities::useNanoSkill(sock, skillData, nano, targetData);
|
||||||
|
|
||||||
if (plr->Nanos[plr->activeNano].iStamina <= 0)
|
if (plr->Nanos[plr->activeNano].iStamina < 0)
|
||||||
summonNano(sock, -1);
|
summonNano(sock, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,4 +26,5 @@ namespace Nanos {
|
|||||||
void summonNano(CNSocket* sock, int slot, bool silent = false);
|
void summonNano(CNSocket* sock, int slot, bool silent = false);
|
||||||
int nanoStyle(int nanoID);
|
int nanoStyle(int nanoID);
|
||||||
bool getNanoBoost(Player* plr);
|
bool getNanoBoost(Player* plr);
|
||||||
|
std::vector<ICombatant*> applyNanoBuff(SkillData* skill, Player* plr);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user