#pragma once #include "core/Core.hpp" #include "EntityRef.hpp" #include #include /* forward declaration(s) */ class Buff; template using BuffCallback = std::function; #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 }; enum class BuffValueSelector { MAX_VALUE, MIN_VALUE, MAX_MAGNITUDE, MIN_MAGNITUDE, NET_TOTAL }; struct BuffStack { int durationTicks; int value; EntityRef source; BuffClass buffStackClass; }; class Buff { private: EntityRef self; std::vector stacks; public: int id; /* called just after a stack is added or removed */ BuffCallback onUpdate; /* called when the buff is combat-ticked */ BuffCallback onCombatTick; void tick(time_t); void combatTick(time_t); void clear(); void clear(BuffClass buffClass); 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(); int getValue(BuffValueSelector selector); EntityRef getLastSource(); /* * 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(); void updateCallbacks(BuffCallback fOnUpdate, BuffCallback fonTick); Buff(int iid, EntityRef pSelf, BuffCallback fOnUpdate, BuffCallback fOnCombatTick, BuffStack* firstStack) : self(pSelf), id(iid), onUpdate(fOnUpdate), onCombatTick(fOnCombatTick) { addStack(firstStack); } }; namespace Buffs { void timeBuffUpdate(EntityRef self, Buff* buff, int status, BuffStack* stack); void timeBuffTick(EntityRef self, Buff* buff); void timeBuffTimeout(EntityRef self); void tickDrain(EntityRef self, Buff* buff, int mult); }