mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-26 06:50:06 +00:00
Port egg buffs over to new system
This commit is contained in:
parent
cb94018e46
commit
0994aaff71
@ -40,7 +40,7 @@ static SkillResult handleSkillHealHP(SkillData* skill, int power, ICombatant* so
|
||||
sSkillResult_Heal_HP result{};
|
||||
result.eCT = target->getCharType();
|
||||
result.iID = target->getID();
|
||||
result.iHealHP = heal;
|
||||
result.iHealHP = healed;
|
||||
result.iHP = target->getCurrentHP();
|
||||
return SkillResult(sizeof(sSkillResult_Heal_HP), &result);
|
||||
}
|
||||
@ -170,7 +170,8 @@ static std::vector<SkillResult> handleSkill(SkillData* skill, int power, ICombat
|
||||
assert(skillHandler != nullptr);
|
||||
|
||||
for(ICombatant* target : targets) {
|
||||
SkillResult result = skillHandler(skill, power, src, target);
|
||||
assert(target != nullptr);
|
||||
SkillResult result = skillHandler(skill, power, src != nullptr ? src : target, target);
|
||||
if(result.size == 0) continue; // skill not applicable
|
||||
if(result.size != resultSize) {
|
||||
std::cout << "[WARN] bad skill result size for " << skill->skillType << " from " << (void*)handleSkillBuff << std::endl;
|
||||
@ -181,7 +182,14 @@ static std::vector<SkillResult> handleSkill(SkillData* skill, int power, ICombat
|
||||
return results;
|
||||
}
|
||||
|
||||
void Abilities::broadcastNanoSkill(CNSocket* sock, sNano& nano, std::vector<ICombatant*> affected) {
|
||||
static void attachSkillResults(std::vector<SkillResult> results, size_t resultSize, uint8_t* pivot) {
|
||||
for(SkillResult& result : results) {
|
||||
memcpy(pivot, result.payload, resultSize);
|
||||
pivot += resultSize;
|
||||
}
|
||||
}
|
||||
|
||||
void Abilities::useNanoSkill(CNSocket* sock, sNano& nano, std::vector<ICombatant*> affected) {
|
||||
if(SkillTable.count(nano.iSkillID) == 0)
|
||||
return;
|
||||
|
||||
@ -210,16 +218,45 @@ void Abilities::broadcastNanoSkill(CNSocket* sock, sNano& nano, std::vector<ICom
|
||||
pkt->eST = skill->skillType;
|
||||
pkt->iTargetCnt = (int32_t)results.size();
|
||||
|
||||
uint8_t* appended = (uint8_t*)(pkt + 1);
|
||||
for(SkillResult& result : results) {
|
||||
memcpy(appended, result.payload, resultSize);
|
||||
appended += resultSize;
|
||||
}
|
||||
|
||||
attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1));
|
||||
sock->sendPacket(pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
||||
PlayerManager::sendToViewable(sock, pkt, P_FE2CL_NANO_SKILL_USE_SUCC, resplen);
|
||||
}
|
||||
|
||||
void Abilities::useNPCSkill(EntityRef npc, int skillID, std::vector<ICombatant*> affected) {
|
||||
if(SkillTable.count(skillID) == 0)
|
||||
return;
|
||||
|
||||
Entity* entity = npc.getEntity();
|
||||
ICombatant* src = nullptr;
|
||||
if(npc.kind == EntityKind::COMBAT_NPC || npc.kind == EntityKind::MOB)
|
||||
src = dynamic_cast<ICombatant*>(entity);
|
||||
|
||||
SkillData* skill = &SkillTable[skillID];
|
||||
|
||||
std::vector<SkillResult> results = handleSkill(skill, 0, src, affected);
|
||||
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)) {
|
||||
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;
|
||||
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
||||
memset(respbuf, 0, resplen);
|
||||
|
||||
sP_FE2CL_NPC_SKILL_HIT* pkt = (sP_FE2CL_NPC_SKILL_HIT*)respbuf;
|
||||
pkt->iNPC_ID = npc.id;
|
||||
pkt->iSkillID = skillID;
|
||||
pkt->eST = skill->skillType;
|
||||
pkt->iTargetCnt = (int32_t)results.size();
|
||||
|
||||
attachSkillResults(results, resultSize, (uint8_t*)(pkt + 1));
|
||||
NPCManager::sendToViewable(entity, pkt, P_FE2CL_NPC_SKILL_HIT, resplen);
|
||||
}
|
||||
|
||||
std::vector<EntityRef> Abilities::matchTargets(SkillData* skill, int count, int32_t *ids) {
|
||||
|
||||
std::vector<EntityRef> targets;
|
||||
@ -303,53 +340,3 @@ int Abilities::getCSTBFromST(int eSkillType) {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<ICombatant*> Abilities::usePassiveNanoSkill(SkillData* skill, Player* plr) {
|
||||
assert(skill->drainType == SkillDrainType::PASSIVE);
|
||||
|
||||
EntityRef self = PlayerManager::getSockFromID(plr->iID);
|
||||
std::vector<ICombatant*> affected;
|
||||
std::vector<EntityRef> targets;
|
||||
if (skill->targetType == SkillTargetType::GROUP) {
|
||||
targets = plr->getGroupMembers(); // group
|
||||
}
|
||||
else if(skill->targetType == SkillTargetType::SELF) {
|
||||
targets.push_back(self); // self
|
||||
} else {
|
||||
std::cout << "[WARN] Passive skill with type " << skill->skillType << " has target type MOB" << std::endl;
|
||||
}
|
||||
|
||||
int timeBuffId = 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 (EntityRef target : targets) {
|
||||
Entity* entity = target.getEntity();
|
||||
if (entity->kind != PLAYER && entity->kind != COMBAT_NPC && entity->kind != MOB)
|
||||
continue; // not a combatant
|
||||
|
||||
passiveBuff.buffStackClass = target == self ? BuffClass::NANO : BuffClass::GROUP_NANO;
|
||||
ICombatant* combatant = dynamic_cast<ICombatant*>(entity);
|
||||
if(combatant->addBuff(timeBuffId,
|
||||
[](EntityRef self, Buff* buff, int status, BuffStack* stack) {
|
||||
Buffs::timeBuffUpdate(self, buff, status, stack);
|
||||
},
|
||||
[](EntityRef self, Buff* buff, time_t currTime) {
|
||||
// TODO time buff tick
|
||||
},
|
||||
&passiveBuff)) affected.push_back(combatant);
|
||||
}
|
||||
|
||||
return affected;
|
||||
}
|
||||
|
||||
void Abilities::init() {
|
||||
//REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_EMAIL_UPDATE_CHECK, emailUpdateCheck);
|
||||
}
|
||||
|
@ -60,11 +60,9 @@ struct SkillData {
|
||||
namespace Abilities {
|
||||
extern std::map<int32_t, SkillData> SkillTable;
|
||||
|
||||
void broadcastNanoSkill(CNSocket*, sNano&, std::vector<ICombatant*>);
|
||||
void useNanoSkill(CNSocket*, sNano&, std::vector<ICombatant*>);
|
||||
void useNPCSkill(EntityRef, int skillID, std::vector<ICombatant*>);
|
||||
|
||||
std::vector<EntityRef> matchTargets(SkillData*, int, int32_t*);
|
||||
int getCSTBFromST(int eSkillType);
|
||||
|
||||
std::vector<ICombatant*> usePassiveNanoSkill(SkillData*, Player*);
|
||||
|
||||
void init();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "Buffs.hpp"
|
||||
|
||||
#include "PlayerManager.hpp"
|
||||
#include "NPCManager.hpp"
|
||||
|
||||
using namespace Buffs;
|
||||
|
||||
@ -120,19 +121,15 @@ void Buffs::timeBuffUpdate(EntityRef self, Buff* buff, int status, BuffStack* st
|
||||
self.sock->sendPacket((void*)&pkt, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE));
|
||||
}
|
||||
|
||||
/*
|
||||
void Buffs::timeBuffTimeoutViewable(EntityRef self, Buff* buff, int ct) {
|
||||
void Buffs::timeBuffTimeout(EntityRef self) {
|
||||
if(self.kind != EntityKind::PLAYER && self.kind != EntityKind::COMBAT_NPC && self.kind != EntityKind::MOB)
|
||||
return; // not a combatant
|
||||
Entity* entity = self.getEntity();
|
||||
ICombatant* combatant = dynamic_cast<ICombatant*>(entity);
|
||||
INITSTRUCT(sP_FE2CL_CHAR_TIME_BUFF_TIME_OUT, pkt); // send a buff timeout to other players
|
||||
pkt.eCT = ct; // 1 for eggs, at least
|
||||
pkt.iID = plr->iID;
|
||||
pkt.iConditionBitFlag = plr->getCompositeCondition();
|
||||
PlayerManager::sendToViewable(self.sock, pkt, P_FE2CL_CHAR_TIME_BUFF_TIME_OUT);
|
||||
pkt.eCT = combatant->getCharType();
|
||||
pkt.iID = combatant->getID();
|
||||
pkt.iConditionBitFlag = combatant->getCompositeCondition();
|
||||
NPCManager::sendToViewable(entity, &pkt, P_FE2CL_CHAR_TIME_BUFF_TIME_OUT, sizeof(sP_FE2CL_CHAR_TIME_BUFF_TIME_OUT));
|
||||
}
|
||||
*/
|
||||
|
||||
/* MOVE TO EGG LAMBDA
|
||||
void Buffs::timeBuffTimeout(EntityRef self, BuffStack* buff) {
|
||||
timeBuffUpdate(self, buff, ETBU_DEL);
|
||||
timeBuffTimeoutViewable(self);
|
||||
} */
|
||||
#pragma endregion
|
||||
|
@ -84,5 +84,5 @@ public:
|
||||
|
||||
namespace Buffs {
|
||||
void timeBuffUpdate(EntityRef self, Buff* buff, int status, BuffStack* stack);
|
||||
//void timeBuffTimeoutViewable(EntityRef self, Buff* buff, int ct);
|
||||
void timeBuffTimeout(EntityRef self);
|
||||
}
|
||||
|
@ -805,7 +805,7 @@ static void playerTick(CNServer *serv, time_t currTime) {
|
||||
if (skill->drainType == SkillDrainType::PASSIVE) {
|
||||
// apply passive buff
|
||||
drainRate = skill->batteryUse[boost * 3];
|
||||
Abilities::usePassiveNanoSkill(skill, plr);
|
||||
Nanos::applyNanoBuff(skill, plr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "Missions.hpp"
|
||||
#include "Eggs.hpp"
|
||||
#include "Items.hpp"
|
||||
#include "Abilities.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <limits.h>
|
||||
@ -501,9 +502,12 @@ static void buffCommand(std::string full, std::vector<std::string>& args, CNSock
|
||||
if (*tmp)
|
||||
return;
|
||||
|
||||
if (Eggs::eggBuffPlayer(sock, skillId, 0, duration)<0)
|
||||
if (Abilities::SkillTable.count(skillId) == 0) {
|
||||
Chat::sendServerMessage(sock, "/buff: unknown skill Id");
|
||||
return;
|
||||
}
|
||||
|
||||
Eggs::eggBuffPlayer(sock, skillId, 0, duration);
|
||||
}
|
||||
|
||||
static void eggCommand(std::string full, std::vector<std::string>& args, CNSocket* sock) {
|
||||
|
89
src/Eggs.cpp
89
src/Eggs.cpp
@ -15,63 +15,47 @@ using namespace Eggs;
|
||||
|
||||
std::unordered_map<int, EggType> Eggs::EggTypes;
|
||||
|
||||
int Eggs::eggBuffPlayer(CNSocket* sock, int skillId, int eggId, int duration) {
|
||||
void Eggs::eggBuffPlayer(CNSocket* sock, int skillId, int eggId, int duration) {
|
||||
Player* plr = PlayerManager::getPlayer(sock);
|
||||
|
||||
// TODO ABILITIES
|
||||
// eggId might be 0 if the buff is made by the /buff command
|
||||
EntityRef src = eggId == 0 ? sock : EntityRef(eggId);
|
||||
|
||||
size_t resplen;
|
||||
|
||||
if (skillId == 183) {
|
||||
resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT) + sizeof(sSkillResult_Damage);
|
||||
} else if (skillId == 150) {
|
||||
resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT) + sizeof(sSkillResult_Heal_HP);
|
||||
} else {
|
||||
resplen = sizeof(sP_FE2CL_NPC_SKILL_HIT) + sizeof(sSkillResult_Buff);
|
||||
}
|
||||
assert(resplen < CN_PACKET_BUFFER_SIZE - 8);
|
||||
// we know it's only one trailing struct, so we can skip full validation
|
||||
|
||||
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
||||
auto skillUse = (sP_FE2CL_NPC_SKILL_HIT*)respbuf;
|
||||
|
||||
if (skillId == 183) { // damage egg
|
||||
auto skill = (sSkillResult_Damage*)(respbuf + sizeof(sP_FE2CL_NPC_SKILL_HIT));
|
||||
memset(respbuf, 0, resplen);
|
||||
skill->eCT = 1;
|
||||
skill->iID = plr->iID;
|
||||
skill->iDamage = PC_MAXHEALTH(plr->level) * Abilities::SkillTable[skillId].values[0][0] / 1000;
|
||||
plr->HP -= skill->iDamage;
|
||||
if (plr->HP < 0)
|
||||
plr->HP = 0;
|
||||
skill->iHP = plr->HP;
|
||||
} else if (skillId == 150) { // heal egg
|
||||
auto skill = (sSkillResult_Heal_HP*)(respbuf + sizeof(sP_FE2CL_NPC_SKILL_HIT));
|
||||
memset(respbuf, 0, resplen);
|
||||
skill->eCT = 1;
|
||||
skill->iID = plr->iID;
|
||||
skill->iHealHP = PC_MAXHEALTH(plr->level) * Abilities::SkillTable[skillId].values[0][0] / 1000;
|
||||
plr->HP += skill->iHealHP;
|
||||
if (plr->HP > PC_MAXHEALTH(plr->level))
|
||||
plr->HP = PC_MAXHEALTH(plr->level);
|
||||
skill->iHP = plr->HP;
|
||||
} else { // regular buff egg
|
||||
auto skill = (sSkillResult_Buff*)(respbuf + sizeof(sP_FE2CL_NPC_SKILL_HIT));
|
||||
memset(respbuf, 0, resplen);
|
||||
skill->eCT = 1;
|
||||
skill->iID = plr->iID;
|
||||
skill->iConditionBitFlag = plr->getCompositeCondition();
|
||||
if(Abilities::SkillTable.count(skillId) == 0) {
|
||||
std::cout << "[WARN] egg " << eggId << " has skill ID " << skillId << " which doesn't exist" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
skillUse->iNPC_ID = eggId;
|
||||
skillUse->iSkillID = skillId;
|
||||
skillUse->eST = Abilities::SkillTable[skillId].skillType;
|
||||
skillUse->iTargetCnt = 1;
|
||||
SkillData* skill = &Abilities::SkillTable[skillId];
|
||||
if(skill->drainType == SkillDrainType::PASSIVE) {
|
||||
// apply buff
|
||||
if(skill->targetType != SkillTargetType::SELF) {
|
||||
std::cout << "[WARN] weird skill type for egg " << eggId << " with skill " << skillId << ", should be " << (int)skill->targetType << std::endl;
|
||||
}
|
||||
|
||||
sock->sendPacket((void*)&respbuf, P_FE2CL_NPC_SKILL_HIT, resplen);
|
||||
PlayerManager::sendToViewable(sock, (void*)&respbuf, P_FE2CL_NPC_SKILL_HIT, resplen);
|
||||
int timeBuffId = Abilities::getCSTBFromST(skill->skillType);
|
||||
int value = skill->values[0][0];
|
||||
BuffStack eggBuff = {
|
||||
duration * 1000 / MS_PER_PLAYER_TICK,
|
||||
value,
|
||||
src,
|
||||
BuffClass::EGG
|
||||
};
|
||||
plr->addBuff(timeBuffId,
|
||||
[](EntityRef self, Buff* buff, int status, BuffStack* stack) {
|
||||
Buffs::timeBuffUpdate(self, buff, status, stack);
|
||||
if(status == ETBU_DEL) Buffs::timeBuffTimeout(self);
|
||||
},
|
||||
[](EntityRef self, Buff* buff, time_t currTime) {
|
||||
// no-op
|
||||
},
|
||||
&eggBuff);
|
||||
}
|
||||
|
||||
return 0;
|
||||
// use skill
|
||||
std::vector<ICombatant*> targets;
|
||||
targets.push_back(dynamic_cast<ICombatant*>(plr));
|
||||
Abilities::useNPCSkill(src, skillId, targets);
|
||||
}
|
||||
|
||||
static void eggStep(CNServer* serv, time_t currTime) {
|
||||
@ -141,16 +125,13 @@ static void eggPickup(CNSocket* sock, CNPacketData* data) {
|
||||
|
||||
EggType* type = &EggTypes[typeId];
|
||||
|
||||
// buff the player
|
||||
if (type->effectId != 0)
|
||||
eggBuffPlayer(sock, type->effectId, eggRef.id, type->duration);
|
||||
|
||||
/*
|
||||
* SHINY_PICKUP_SUCC is only causing a GUI effect in the client
|
||||
* (buff icon pops up in the bottom of the screen)
|
||||
* so we don't send it for non-effect
|
||||
*/
|
||||
if (type->effectId != 0) {
|
||||
eggBuffPlayer(sock, type->effectId, eggRef.id, type->duration);
|
||||
INITSTRUCT(sP_FE2CL_REP_SHINY_PICKUP_SUCC, resp);
|
||||
resp.iSkillID = type->effectId;
|
||||
|
||||
|
@ -14,7 +14,6 @@ namespace Eggs {
|
||||
|
||||
void init();
|
||||
|
||||
/// returns -1 on fail
|
||||
int eggBuffPlayer(CNSocket* sock, int skillId, int eggId, int duration);
|
||||
void eggBuffPlayer(CNSocket* sock, int skillId, int eggId, int duration);
|
||||
void npcDataToEggData(int x, int y, int z, sNPCAppearanceData* npc, sShinyAppearanceData* egg);
|
||||
}
|
||||
|
@ -240,27 +240,11 @@ void Groups::groupTickInfo(Player* plr) {
|
||||
sendToGroup(plr->group, (void*)&respbuf, P_FE2CL_PC_GROUP_MEMBER_INFO, resplen);
|
||||
}
|
||||
|
||||
static void groupUnbuff(Player* plr) {
|
||||
Group* group = plr->group;
|
||||
for (int i = 0; i < group->members.size(); i++) {
|
||||
for (int n = 0; n < group->members.size(); n++) {
|
||||
if (i == n)
|
||||
continue;
|
||||
|
||||
EntityRef other = group->members[n];
|
||||
|
||||
// TODO ABILITIES
|
||||
//Abilities::applyBuff(sock, otherPlr->Nanos[otherPlr->activeNano].iSkillID, 2, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Groups::groupKick(Player* plr) {
|
||||
Group* group = plr->group;
|
||||
|
||||
// if you are the group leader, destroy your own group and kick everybody
|
||||
if (plr->group->members[0] == PlayerManager::getSockFromID(plr->iID)) {
|
||||
groupUnbuff(plr);
|
||||
INITSTRUCT(sP_FE2CL_PC_GROUP_LEAVE_SUCC, resp1);
|
||||
sendToGroup(plr->group, (void*)&resp1, P_FE2CL_PC_GROUP_LEAVE_SUCC, sizeof(sP_FE2CL_PC_GROUP_LEAVE_SUCC));
|
||||
disbandGroup(plr->group);
|
||||
|
@ -503,7 +503,7 @@ static void itemUseHandler(CNSocket* sock, CNPacketData* data) {
|
||||
Buffs::timeBuffUpdate(self, buff, status, stack);
|
||||
},
|
||||
[](EntityRef self, Buff* buff, time_t currTime) {
|
||||
// TODO passive tick
|
||||
// no-op
|
||||
},
|
||||
&gumballBuff);
|
||||
|
||||
|
@ -81,7 +81,7 @@ void NPCManager::updateNPCPosition(int32_t id, int X, int Y, int Z, uint64_t I,
|
||||
Chunking::updateEntityChunk({id}, oldChunk, newChunk);
|
||||
}
|
||||
|
||||
void NPCManager::sendToViewable(BaseNPC *npc, void *buf, uint32_t type, size_t size) {
|
||||
void NPCManager::sendToViewable(Entity *npc, void *buf, uint32_t type, size_t size) {
|
||||
for (auto it = npc->viewableChunks.begin(); it != npc->viewableChunks.end(); it++) {
|
||||
Chunk* chunk = *it;
|
||||
for (const EntityRef& ref : chunk->entities) {
|
||||
|
@ -42,7 +42,7 @@ namespace NPCManager {
|
||||
void destroyNPC(int32_t);
|
||||
void updateNPCPosition(int32_t, int X, int Y, int Z, uint64_t I, int angle);
|
||||
|
||||
void sendToViewable(BaseNPC* npc, void* buf, uint32_t type, size_t size);
|
||||
void sendToViewable(Entity* npc, void* buf, uint32_t type, size_t size);
|
||||
|
||||
BaseNPC *summonNPC(int x, int y, int z, uint64_t instance, int type, bool respawn=false, bool baseInstance=false);
|
||||
|
||||
|
@ -69,6 +69,52 @@ 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);
|
||||
std::vector<ICombatant*> affected;
|
||||
std::vector<EntityRef> targets;
|
||||
if (skill->targetType == SkillTargetType::GROUP) {
|
||||
targets = plr->getGroupMembers(); // group
|
||||
}
|
||||
else if(skill->targetType == SkillTargetType::SELF) {
|
||||
targets.push_back(self); // self
|
||||
} else {
|
||||
std::cout << "[WARN] Passive skill with type " << skill->skillType << " has target type MOB" << std::endl;
|
||||
}
|
||||
|
||||
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 (EntityRef target : targets) {
|
||||
Entity* entity = target.getEntity();
|
||||
if (entity->kind != PLAYER && entity->kind != COMBAT_NPC && entity->kind != MOB)
|
||||
continue; // not a combatant
|
||||
|
||||
passiveBuff.buffStackClass = target == self ? BuffClass::NANO : BuffClass::GROUP_NANO;
|
||||
ICombatant* combatant = dynamic_cast<ICombatant*>(entity);
|
||||
if(combatant->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(combatant);
|
||||
}
|
||||
|
||||
return affected;
|
||||
}
|
||||
|
||||
void Nanos::summonNano(CNSocket *sock, int slot, bool silent) {
|
||||
INITSTRUCT(sP_FE2CL_REP_NANO_ACTIVE_SUCC, resp);
|
||||
resp.iActiveNanoSlotNum = slot;
|
||||
@ -94,8 +140,8 @@ void Nanos::summonNano(CNSocket *sock, int slot, bool silent) {
|
||||
// passive buff effect
|
||||
resp.eCSTB___Add = 1;
|
||||
int boost = Nanos::getNanoBoost(plr);
|
||||
std::vector<ICombatant*> affectedCombatants = Abilities::usePassiveNanoSkill(skill, plr);
|
||||
if(!affectedCombatants.empty()) Abilities::broadcastNanoSkill(sock, nano, affectedCombatants);
|
||||
std::vector<ICombatant*> affectedCombatants = applyNanoBuff(skill, plr);
|
||||
if(!affectedCombatants.empty()) Abilities::useNanoSkill(sock, nano, affectedCombatants);
|
||||
}
|
||||
|
||||
if (!silent) // silent nano death but only for the summoning player
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "core/Core.hpp"
|
||||
|
||||
#include "Player.hpp"
|
||||
#include "Abilities.hpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
@ -25,4 +26,5 @@ 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