mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-09-29 06:52:47 +00:00
f150595f70
The first implementation was way too complicated and prone to bugs. This is much more simple flexible; first off, std::function is now used instead of a raw function pointer, so lambdas and binds are fair game which is great for scripting. Second, callbacks for all stacks are executed. It is up to the callback target to ensure correct behavior.
100 lines
2.7 KiB
C++
100 lines
2.7 KiB
C++
#include "Buffs.hpp"
|
|
|
|
#include "PlayerManager.hpp"
|
|
|
|
using namespace Buffs;
|
|
|
|
void Buff::tick() {
|
|
auto it = stacks.begin();
|
|
while(it != stacks.end()) {
|
|
BuffStack& stack = *it;
|
|
if(stack.onTick) stack.onTick(self, &stack);
|
|
|
|
if(stack.durationTicks > 0) stack.durationTicks--;
|
|
if(stack.durationTicks == 0) {
|
|
it = stacks.erase(it);
|
|
if(stack.onExpire) stack.onExpire(self, &stack);
|
|
} else it++;
|
|
}
|
|
}
|
|
|
|
void Buff::clear() {
|
|
while(!stacks.empty()) {
|
|
BuffStack stack = stacks.back();
|
|
stacks.pop_back();
|
|
if(stack.onExpire) stack.onExpire(self, &stack);
|
|
}
|
|
}
|
|
|
|
void Buff::addStack(BuffStack* stack) {
|
|
if(stack->onApply) stack->onApply(self, stack);
|
|
stacks.push_back(*stack);
|
|
}
|
|
|
|
bool Buff::hasClass(BuffClass buffClass) {
|
|
for(BuffStack& stack : stacks) {
|
|
if(stack.buffClass == buffClass)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
BuffClass Buff::maxClass() {
|
|
BuffClass buffClass = BuffClass::NONE;
|
|
for(BuffStack& stack : stacks) {
|
|
if(stack.buffClass > buffClass)
|
|
buffClass = stack.buffClass;
|
|
}
|
|
return buffClass;
|
|
}
|
|
|
|
bool Buff::isStale() {
|
|
return stacks.empty();
|
|
}
|
|
|
|
#pragma region Handlers
|
|
void Buffs::timeBuffUpdate(EntityRef self, BuffStack* buff, int status) {
|
|
|
|
if(self.kind != EntityKind::PLAYER)
|
|
return; // not implemented
|
|
|
|
Player* plr = (Player*)self.getEntity();
|
|
if(plr == nullptr)
|
|
return;
|
|
|
|
if(status == ETBU_DEL && plr->hasBuff(buff->id))
|
|
return; // no premature status removal!
|
|
|
|
int cbf = plr->getCompositeCondition();
|
|
if(status == ETBU_ADD) cbf |= CSB_FROM_ECSB(buff->id);
|
|
|
|
INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, pkt);
|
|
pkt.eCSTB = buff->id; // eCharStatusTimeBuffID
|
|
pkt.eTBU = status; // eTimeBuffUpdate
|
|
pkt.eTBT = (int)buff->buffClass;
|
|
pkt.iConditionBitFlag = cbf;
|
|
self.sock->sendPacket((void*)&pkt, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE));
|
|
}
|
|
|
|
void Buffs::timeBuffTimeoutViewable(EntityRef self, BuffStack* buff, int ct) {
|
|
if(self.kind != EntityKind::PLAYER)
|
|
return; // not implemented
|
|
|
|
Player* plr = (Player*)self.getEntity();
|
|
if(plr == nullptr)
|
|
return;
|
|
|
|
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);
|
|
}
|
|
|
|
/* MOVE TO EGG LAMBDA
|
|
void Buffs::timeBuffTimeout(EntityRef self, BuffStack* buff) {
|
|
timeBuffUpdate(self, buff, ETBU_DEL);
|
|
timeBuffTimeoutViewable(self);
|
|
} */
|
|
#pragma endregion
|