Files
HackerOoT/include/event_manager.h
Yanis 3505a2e1ac New Animated Material types (#192)
* don't use playstate everywhere

* add color/textime cycle and start event system

* implement inventory events

* improvements and add time event

* add obtained flag

* move event handler to its own file

* header stuff

* implement magic level

* add getfreezetype and default texture

* add multitexture type (and improvements)

* add texture, event and surface swap

* added oscillating water (thanks kenton!) and start implementing the first freeze type

* fix drawevent

* improvements and fixes

* more improvements

* misc stuff

* little changes

* note

* removed condition type for age

* fixed cond enum names

* small fix

* initialize sceneMaterialAnimCamParams properly

* fixes related to animated materials changes

* improvements and fixes

* make sure everything is initialized !

* add color switch type
2025-11-26 16:01:42 +01:00

253 lines
8.5 KiB
C

#ifndef EVENT_MANAGER_H
#define EVENT_MANAGER_H
#include "ultra64.h"
#include "config.h"
#include "command_macros_base.h"
typedef enum EventCondition {
EVENT_COND_NONE,
EVENT_COND_EQUAL, // b == a
EVENT_COND_DIFF, // b != a
EVENT_COND_INFERIOR, // b < a
EVENT_COND_SUPERIOR, // b > a
EVENT_COND_INFERIOR_EQ, // b <= a
EVENT_COND_SUPERIOR_EQ, // b >= a
} EventCondition;
typedef enum EventFlagType {
EVENT_FLAG_TYPE_SWITCH_FLAG,
EVENT_FLAG_TYPE_EVENTCHKINF_FLAG,
EVENT_FLAG_TYPE_INF_FLAG,
EVENT_FLAG_TYPE_COLLECTIBLE_FLAG,
EVENT_FLAG_TYPE_TREASURE_FLAG,
EVENT_FLAG_TYPE_TEMPCLEAR_FLAG,
EVENT_FLAG_TYPE_CLEAR_FLAG,
EVENT_FLAG_TYPE_MAX,
} EventFlagType;
typedef enum EventInvType {
EVENT_INV_TYPE_ITEMS,
EVENT_INV_TYPE_EQUIPMENT,
EVENT_INV_TYPE_QUEST,
EVENT_INV_TYPE_DUNGEON_ITEMS,
EVENT_INV_TYPE_DUNGEON_KEYS,
EVENT_INV_TYPE_GS_TOKENS,
EVENT_INV_TYPE_MAX,
} EventInvType;
typedef enum EventGameType {
EVENT_GAME_TYPE_AGE,
EVENT_GAME_TYPE_HEALTH,
EVENT_GAME_TYPE_RUPEES,
EVENT_GAME_TYPE_MAGIC,
EVENT_GAME_TYPE_INVENTORY,
EVENT_GAME_TYPE_MAX,
} EventGameType;
typedef enum EventTimeType {
EVENT_TIME_TYPE_CLOCK,
EVENT_TIME_TYPE_CONDITIONAL,
EVENT_TIME_TYPE_DAY,
EVENT_TIME_TYPE_NIGHT,
EVENT_TIME_TYPE_MAX,
} EventTimeType;
// only used by the system using this
//! TODO: add a type that can let a draw to complete its loop before freezing
typedef enum EventActionType {
EVENT_ACTION_TYPE_NONE, // no special behavior
EVENT_ACTION_TYPE_INVERTED, // inverts the event behavior
EVENT_ACTION_TYPE_INVERTED_KEEP, // same as above but allows to continue to draw the last state
} EventActionType;
typedef enum EventType {
EVENT_TYPE_NONE,
EVENT_TYPE_FLAG,
EVENT_TYPE_GAME,
EVENT_TYPE_TIME,
EVENT_TYPE_MAX,
} EventType;
typedef union EventData {
s32 i;
f32 f;
s16 s[2];
s8 b[4];
} EventData;
typedef union EventFlag {
struct {
u32 type; // see EventFlagType
u32 flag;
};
s32 _words[2];
} EventFlag;
typedef union EventGame {
struct {
u8 type; // see EventGameType
u8 condType; // see EventCondition
union {
// EVENT_GAME_TYPE_AGE
s8 age;
// EVENT_GAME_TYPE_HEALTH
s16 health;
// EVENT_GAME_TYPE_RUPEES
s16 rupees;
// EVENT_GAME_TYPE_MAGIC
s8 magic;
// EVENT_GAME_TYPE_INVENTORY
struct {
u8 type; // see EventInvType
union {
u8 itemId;
u8 upgradeType;
u8 unused;
u8 sceneId;
u8 questItem;
};
union {
// EVENT_INV_TYPE_ITEMS and EVENT_INV_TYPE_DUNGEON_KEYS
struct {
u8 obtained;
union {
s8 amount; // EVENT_INV_TYPE_ITEMS: -1 means no ammo check
// EVENT_INV_TYPE_EQUIPMENT
u8 swordHealth; // -1 means no sword health check
u8 upgradeValue;
};
};
// EVENT_INV_TYPE_DUNGEON_ITEMS
// EVENT_INV_TYPE_GS_TOKENS
s16 gsTokens;
};
} inventory;
};
};
s32 _words[2];
} EventGame;
typedef union EventTime {
struct {
u8 type; // see EventTimeType
u8 isClock; // set to true to check for a specific time range
union {
u8 isRange;
u8 nightFlag; // 0 for day, 1 for night
};
struct {
u8 condType;
u8 hour;
u8 minute;
} clocks[2];
};
s32 _words[3];
} EventTime;
typedef struct EventScriptEntry {
EventData* script; // list of events to process, must be the same size as keyframeList
u8 actionType; // see EventActionType
} EventScriptEntry;
struct GameState;
u8 EventManager_GetFreezeType(void);
u8 EventManager_ProcessScript(struct GameState* gameState, EventScriptEntry* eventEntry);
// useful macros to declare an event entry
// generic flag macro
#define EVENT_FLAG(type, flag) EVENT_TYPE_FLAG, CMD_W((type)), CMD_W((flag))
// specific flag macros
#define EVENT_SWITCH_FLAG(flag) EVENT_FLAG(EVENT_FLAG_TYPE_SWITCH_FLAG, (flag))
#define EVENT_EVENTCHKINF_FLAG(flag) EVENT_FLAG(EVENT_FLAG_TYPE_EVENTCHKINF_FLAG, (flag))
#define EVENT_INF_FLAG(flag) EVENT_FLAG(EVENT_FLAG_TYPE_INF_FLAG, (flag))
#define EVENT_COLLECTIBLE_FLAG(flag) EVENT_FLAG(EVENT_FLAG_TYPE_COLLECTIBLE_FLAG, (flag))
#define EVENT_TREASURE_FLAG(flag) EVENT_FLAG(EVENT_FLAG_TYPE_TREASURE_FLAG, (flag))
#define EVENT_TEMPCLEAR_FLAG(flag) EVENT_FLAG(EVENT_FLAG_TYPE_TEMPCLEAR_FLAG, (flag))
#define EVENT_CLEAR_FLAG(flag) EVENT_FLAG(EVENT_FLAG_TYPE_CLEAR_FLAG, (flag))
// age macro
#define EVENT_AGE(age) EVENT_TYPE_GAME, CMD_BBBB(EVENT_GAME_TYPE_AGE, 0, (age), 0), CMD_W(0)
// health macro
#define EVENT_HEALTH(condType, amount) \
EVENT_TYPE_GAME, CMD_BBBB(EVENT_GAME_TYPE_HEALTH, (condType), 0, (amount)), CMD_W(0)
// rupees macro
#define EVENT_RUPEES(condType, amount) \
EVENT_TYPE_GAME, CMD_BBBB(EVENT_GAME_TYPE_RUPEES, (condType), 0, (amount)), CMD_W(0)
// magic macro
#define EVENT_MAGIC(condType, amount) \
EVENT_TYPE_GAME, CMD_BBBB(EVENT_GAME_TYPE_MAGIC, (condType), 0, (amount)), CMD_W(0)
// generic item macro
#define EVENT_ITEM_BASE(condType, itemId, obtained, amount) \
EVENT_TYPE_GAME, CMD_BBBB(EVENT_GAME_TYPE_INVENTORY, (condType), EVENT_INV_TYPE_ITEMS, (itemId)), \
CMD_BBH((obtained), (amount), 0)
// item macro (either the player has the item or not)
#define EVENT_ITEM(itemId, obtained) EVENT_ITEM_BASE(EVENT_COND_NONE, itemId, obtained, -1)
// ammo macro (same as above but also check the amount)
#define EVENT_ITEM_AMMO(condType, itemId, amount) EVENT_ITEM_BASE(condType, itemId, true, amount)
// generic equipment macro
#define EVENT_EQUIPMENT_BASE(condType, itemIdOrUpgradeType, obtained, healthOrUpgrade) \
EVENT_TYPE_GAME, CMD_BBBB(EVENT_GAME_TYPE_INVENTORY, (condType), EVENT_INV_TYPE_EQUIPMENT, (itemIdOrUpgradeType)), \
CMD_BBH((obtained), (healthOrUpgrade), 0)
// equipment macro (either the player has the equipment or not)
#define EVENT_EQUIPMENT(itemId, obtained) EVENT_EQUIPMENT_BASE(EVENT_COND_NONE, itemId, obtained, -1)
// biggoron sword macro (same as above but also check the sword's health)
#define EVENT_EQUIPMENT_BGS(condType, swordHealth) \
EVENT_EQUIPMENT_BASE(condType, ITEM_SWORD_BIGGORON, true, swordHealth)
// upgrade macro
#define EVENT_EQUIPMENT_UPG(condType, upgradeType, upgradeValue) \
EVENT_EQUIPMENT_BASE(condType, upgradeType, true, upgradeValue)
// quest items
#define EVENT_QUEST_ITEM(questItem, obtained) \
EVENT_TYPE_GAME, CMD_BBBB(EVENT_GAME_TYPE_INVENTORY, EVENT_COND_NONE, EVENT_INV_TYPE_QUEST, (questItem)), \
CMD_BBH((obtained), 0, 0)
// skulltula tokens
#define EVENT_GS_TOKEN(condType, gsTokens) \
EVENT_TYPE_GAME, CMD_BBBB(EVENT_GAME_TYPE_INVENTORY, (condType), EVENT_INV_TYPE_GS_TOKENS, 0), CMD_HH((gsTokens), 0)
// generic time macro
#define EVENT_TIME(type, isClock, isRangeOrNightFlag, condType1, hour1, minute1, condType2, hour2, minute2) \
EVENT_TYPE_TIME, CMD_BBBB((type), (isClock), (isRangeOrNightFlag), (condType1)), \
CMD_BBBB((hour1), (minute1), (condType2), (hour2)), CMD_BBH((minute2), 0, 0)
// specific time of day
#define EVENT_TIME_CLOCK(condType, hour, minute) \
EVENT_TIME(EVENT_TIME_TYPE_CLOCK, true, false, condType, hour, minute, 0, 0, 0)
// conditional clock (for example: time1 != CLOCK_TIME(10, 0) && time2 < CLOCK_TIME(15, 0)
#define EVENT_TIME_CONDITIONAL(condType1, hour1, minute1, condType2, hour2, minute2) \
EVENT_TIME(EVENT_TIME_TYPE_CONDITIONAL, true, true, condType1, hour1, minute1, condType2, hour2, minute2)
// check if this is currently daytime
#define EVENT_TIME_DAY() EVENT_TIME(EVENT_TIME_TYPE_DAY, false, 0, 0, 0, 0, 0, 0, 0)
// checks if the this is currently nighttime
#define EVENT_TIME_NIGHT() EVENT_TIME(EVENT_TIME_TYPE_NIGHT, false, 1, 0, 0, 0, 0, 0, 0)
// the process will end whenever this is the next type (or if an unknown type is found)
#define EVENT_END() EVENT_TYPE_NONE
#endif