2022-07-18 03:49:10 +00:00
|
|
|
#include "Buffs.hpp"
|
|
|
|
|
|
|
|
#include "PlayerManager.hpp"
|
|
|
|
|
|
|
|
using namespace Buffs;
|
|
|
|
|
2022-07-18 15:53:53 +00:00
|
|
|
void Buff::tick() {
|
2022-07-18 03:49:10 +00:00
|
|
|
auto it = stacks.begin();
|
|
|
|
while(it != stacks.end()) {
|
|
|
|
BuffStack& stack = *it;
|
2022-07-18 15:53:53 +00:00
|
|
|
if(stack.onTick) stack.onTick(self, &stack);
|
2022-07-18 03:49:10 +00:00
|
|
|
|
|
|
|
if(stack.durationTicks == 0) {
|
2022-07-19 16:14:38 +00:00
|
|
|
// erase() destroys the callbacks
|
|
|
|
// with the stack struct, so we need
|
|
|
|
// to copy it first.
|
|
|
|
BuffStack deadStack = stack;
|
2022-07-18 03:49:10 +00:00
|
|
|
it = stacks.erase(it);
|
2022-07-19 16:14:38 +00:00
|
|
|
if(deadStack.onExpire) deadStack.onExpire(self, &deadStack);
|
2022-07-20 16:15:01 +00:00
|
|
|
} else {
|
|
|
|
if(stack.durationTicks > 0) stack.durationTicks--;
|
|
|
|
it++;
|
|
|
|
}
|
2022-07-18 03:49:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-18 15:53:53 +00:00
|
|
|
void Buff::clear() {
|
2022-07-18 03:49:10 +00:00
|
|
|
while(!stacks.empty()) {
|
|
|
|
BuffStack stack = stacks.back();
|
|
|
|
stacks.pop_back();
|
2022-07-18 15:53:53 +00:00
|
|
|
if(stack.onExpire) stack.onExpire(self, &stack);
|
2022-07-18 03:49:10 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Buff::addStack(BuffStack* stack) {
|
2022-07-20 16:15:01 +00:00
|
|
|
BuffStack newStack = *stack;
|
|
|
|
newStack.buff = this;
|
|
|
|
if(newStack.onApply) newStack.onApply(self, &newStack);
|
|
|
|
stacks.push_back(newStack);
|
2022-07-18 03:49:10 +00:00
|
|
|
}
|
|
|
|
|
2022-07-18 15:53:53 +00:00
|
|
|
bool Buff::hasClass(BuffClass buffClass) {
|
|
|
|
for(BuffStack& stack : stacks) {
|
2022-07-19 08:09:25 +00:00
|
|
|
if(stack.buffStackClass == buffClass)
|
2022-07-18 15:53:53 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2022-07-18 03:49:10 +00:00
|
|
|
|
2022-07-18 15:53:53 +00:00
|
|
|
BuffClass Buff::maxClass() {
|
|
|
|
BuffClass buffClass = BuffClass::NONE;
|
2022-07-18 03:49:10 +00:00
|
|
|
for(BuffStack& stack : stacks) {
|
2022-07-19 08:09:25 +00:00
|
|
|
if(stack.buffStackClass > buffClass)
|
|
|
|
buffClass = stack.buffStackClass;
|
2022-07-18 03:49:10 +00:00
|
|
|
}
|
2022-07-18 15:53:53 +00:00
|
|
|
return buffClass;
|
2022-07-18 03:49:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool Buff::isStale() {
|
|
|
|
return stacks.empty();
|
|
|
|
}
|
|
|
|
|
2022-07-18 15:53:53 +00:00
|
|
|
#pragma region Handlers
|
2022-07-19 08:09:25 +00:00
|
|
|
void Buffs::timeBuffUpdate(EntityRef self, BuffStack* stack, int status) {
|
2022-07-18 03:49:10 +00:00
|
|
|
|
|
|
|
if(self.kind != EntityKind::PLAYER)
|
|
|
|
return; // not implemented
|
|
|
|
|
|
|
|
Player* plr = (Player*)self.getEntity();
|
|
|
|
if(plr == nullptr)
|
|
|
|
return;
|
2022-07-18 15:53:53 +00:00
|
|
|
|
2022-07-19 08:09:25 +00:00
|
|
|
if(status == ETBU_DEL && plr->hasBuff(stack->buff->id))
|
2022-07-18 15:53:53 +00:00
|
|
|
return; // no premature status removal!
|
|
|
|
|
|
|
|
int cbf = plr->getCompositeCondition();
|
2022-07-19 08:09:25 +00:00
|
|
|
if(status == ETBU_ADD && stack->buff->id > 0) cbf |= CSB_FROM_ECSB(stack->buff->id);
|
2022-07-18 03:49:10 +00:00
|
|
|
|
|
|
|
INITSTRUCT(sP_FE2CL_PC_BUFF_UPDATE, pkt);
|
2022-07-19 08:09:25 +00:00
|
|
|
pkt.eCSTB = stack->buff->id; // eCharStatusTimeBuffID
|
2022-07-18 15:53:53 +00:00
|
|
|
pkt.eTBU = status; // eTimeBuffUpdate
|
2022-07-19 08:09:25 +00:00
|
|
|
pkt.eTBT = (int)stack->buffStackClass;
|
2022-07-18 15:53:53 +00:00
|
|
|
pkt.iConditionBitFlag = cbf;
|
2022-07-18 03:49:10 +00:00
|
|
|
self.sock->sendPacket((void*)&pkt, P_FE2CL_PC_BUFF_UPDATE, sizeof(sP_FE2CL_PC_BUFF_UPDATE));
|
|
|
|
}
|
|
|
|
|
2022-07-19 08:09:25 +00:00
|
|
|
void Buffs::timeBuffTimeoutViewable(EntityRef self, BuffStack* stack, int ct) {
|
2022-07-18 03:49:10 +00:00
|
|
|
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
|
2022-07-18 15:53:53 +00:00
|
|
|
pkt.eCT = ct; // 1 for eggs, at least
|
2022-07-18 03:49:10 +00:00
|
|
|
pkt.iID = plr->iID;
|
|
|
|
pkt.iConditionBitFlag = plr->getCompositeCondition();
|
|
|
|
PlayerManager::sendToViewable(self.sock, pkt, P_FE2CL_CHAR_TIME_BUFF_TIME_OUT);
|
|
|
|
}
|
|
|
|
|
2022-07-18 15:53:53 +00:00
|
|
|
/* MOVE TO EGG LAMBDA
|
2022-07-18 03:49:10 +00:00
|
|
|
void Buffs::timeBuffTimeout(EntityRef self, BuffStack* buff) {
|
|
|
|
timeBuffUpdate(self, buff, ETBU_DEL);
|
|
|
|
timeBuffTimeoutViewable(self);
|
2022-07-18 15:53:53 +00:00
|
|
|
} */
|
|
|
|
#pragma endregion
|