OpenFusion/src/Buffs.hpp
gsemaj f150595f70
Rework buff callbacks
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.
2023-07-11 13:52:56 -04:00

80 lines
1.7 KiB
C++

#pragma once
#include "core/Core.hpp"
#include "Entities.hpp"
#include <vector>
#include <functional>
/* forward declaration(s) */
struct BuffStack;
#define CSB_FROM_ECSB(x) (1 << (x - 1))
enum class BuffClass {
NONE = ETBT_NONE,
NANO = ETBT_NANO,
GROUP_NANO = ETBT_GROUPNANO,
EGG = ETBT_SHINY,
ENVIRONMENT = ETBT_LANDEFFECT,
ITEM = ETBT_ITEM,
CASH_ITEM = ETBT_CASHITEM
};
typedef std::function<void(EntityRef, BuffStack*)> BuffCallback;
struct BuffStack {
int id; // ECSB
int durationTicks;
EntityRef source;
BuffClass buffClass;
/* called just before the stack is added */
BuffCallback onApply;
/* called when the stack is ticked */
BuffCallback onTick;
/* called just after the stack is removed */
BuffCallback onExpire;
};
class Buff {
private:
EntityRef self;
std::vector<BuffStack> stacks;
public:
void tick();
void clear();
void addStack(BuffStack* stack);
/*
* Sometimes we need to determine if a buff
* is covered by a certain class, ex: nano
* vs. coco egg in the case of infection protection
*/
bool hasClass(BuffClass buffClass);
BuffClass maxClass();
/*
* In general, a Buff object won't exist
* unless it has stacks. However, when
* popping stacks during iteration (onExpire),
* stacks will be empty for a brief moment
* when the last stack is popped.
*/
bool isStale();
Buff(EntityRef pSelf, BuffStack* firstStack)
: self(pSelf) {
addStack(firstStack);
}
};
namespace Buffs {
void timeBuffUpdate(EntityRef self, BuffStack* buff, int status);
void timeBuffTimeoutViewable(EntityRef self, BuffStack* buff, int ct);
}