mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-22 05:20:05 +00:00
Compare commits
2 Commits
0b325f6f9f
...
02cc58dfb0
Author | SHA1 | Date | |
---|---|---|---|
|
02cc58dfb0 | ||
|
9b7656117d |
@ -57,6 +57,23 @@ static SkillResult handleSkillDamageNDebuff(SkillData* skill, int power, ICombat
|
||||
}
|
||||
|
||||
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{};
|
||||
result.eCT = target->getCharType();
|
||||
result.iID = target->getID();
|
||||
@ -206,14 +223,16 @@ void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std:
|
||||
if (Nanos::getNanoBoost(plr))
|
||||
boost = 3;
|
||||
|
||||
if(skill->drainType == SkillDrainType::ACTIVE) {
|
||||
nano.iStamina -= skill->batteryUse[boost];
|
||||
if (nano.iStamina < 0)
|
||||
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(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_NANO_SKILL_USE_SUCC), results.size(), resultSize)) {
|
||||
std::cout << "[WARN] bad sP_FE2CL_NANO_SKILL_USE_SUCC packet size\n";
|
||||
return;
|
||||
@ -241,9 +260,6 @@ void Abilities::useNanoSkill(CNSocket* sock, SkillData* skill, sNano& nano, std:
|
||||
PlayerManager::sendToGroup(sock, pkt, P_FE2CL_NANO_SKILL_USE, resplen);
|
||||
else
|
||||
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) {
|
||||
@ -293,14 +309,8 @@ static std::vector<ICombatant*> entityRefsToCombatants(std::vector<EntityRef> re
|
||||
|
||||
std::vector<ICombatant*> Abilities::matchTargets(ICombatant* src, SkillData* skill, int count, int32_t *ids) {
|
||||
|
||||
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 {};
|
||||
}
|
||||
if(skill->targetType == SkillTargetType::GROUP)
|
||||
return entityRefsToCombatants(src->getGroupMembers());
|
||||
}
|
||||
|
||||
// this check *has* to happen after the group check above due to cases like group recall that use both
|
||||
if(skill->effectTarget == SkillEffectTarget::SELF)
|
||||
@ -393,6 +403,8 @@ int Abilities::getCSTBFromST(SkillType skillType) {
|
||||
case SkillType::NANOSTIMPAK:
|
||||
result = ECSB_STIMPAKSLOT1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -874,9 +874,12 @@ static void playerTick(CNServer *serv, time_t currTime) {
|
||||
if (Abilities::SkillTable.find(nano->iSkillID) != Abilities::SkillTable.end()) {
|
||||
// nano has skill data
|
||||
SkillData* skill = &Abilities::SkillTable[nano->iSkillID];
|
||||
if (skill->drainType == SkillDrainType::PASSIVE)
|
||||
Nanos::applyNanoBuff(skill, plr);
|
||||
// ^ composite condition calculation is separate from combat for responsiveness
|
||||
if (skill->drainType == SkillDrainType::PASSIVE) {
|
||||
ICombatant* src = dynamic_cast<ICombatant*>(plr);
|
||||
int32_t targets[] = { plr->iID };
|
||||
std::vector<ICombatant*> affectedCombatants = Abilities::matchTargets(src, skill, 1, targets);
|
||||
Abilities::useNanoSkill(sock, skill, *nano, affectedCombatants);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,43 +69,6 @@ void Nanos::addNano(CNSocket* sock, int16_t nanoID, int16_t slot, bool spendfm)
|
||||
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) {
|
||||
INITSTRUCT(sP_FE2CL_REP_NANO_ACTIVE_SUCC, resp);
|
||||
resp.iActiveNanoSlotNum = slot;
|
||||
@ -130,8 +93,10 @@ void Nanos::summonNano(CNSocket *sock, int slot, bool silent) {
|
||||
if (slot != -1 && skill != nullptr && skill->drainType == SkillDrainType::PASSIVE) {
|
||||
// passive buff effect
|
||||
resp.eCSTB___Add = 1;
|
||||
std::vector<ICombatant*> affectedCombatants = applyNanoBuff(skill, plr);
|
||||
if(!affectedCombatants.empty()) Abilities::useNanoSkill(sock, skill, nano, affectedCombatants);
|
||||
ICombatant* src = dynamic_cast<ICombatant*>(plr);
|
||||
int32_t targets[] = { plr->iID };
|
||||
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
|
||||
@ -312,7 +277,7 @@ static void nanoSkillUseHandler(CNSocket* sock, CNPacketData* data) {
|
||||
std::vector<ICombatant*> targetData = Abilities::matchTargets(plrCombatant, skillData, pkt->iTargetCnt, (int32_t*)(pkt + 1));
|
||||
Abilities::useNanoSkill(sock, skillData, nano, targetData);
|
||||
|
||||
if (plr->Nanos[plr->activeNano].iStamina < 0)
|
||||
if (plr->Nanos[plr->activeNano].iStamina <= 0)
|
||||
summonNano(sock, -1);
|
||||
}
|
||||
|
||||
|
@ -26,5 +26,4 @@ namespace Nanos {
|
||||
void summonNano(CNSocket* sock, int slot, bool silent = false);
|
||||
int nanoStyle(int nanoID);
|
||||
bool getNanoBoost(Player* plr);
|
||||
std::vector<ICombatant*> applyNanoBuff(SkillData* skill, Player* plr);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user