Trigger types on areas

This commit is contained in:
2026-07-07 07:07:32 -05:00
parent 988a0f2294
commit 189babd2cf
3 changed files with 57 additions and 22 deletions
+26 -5
View File
@@ -8,6 +8,7 @@
#include "maparea.h"
#include "assert/assert.h"
#include "util/math.h"
#include "util/memory.h"
#include "rpg/overworld/map.h"
maparea_t MAP_AREAS[MAP_AREA_COUNT_MAX];
@@ -17,7 +18,8 @@ void mapAreaInit(
const worldpos_t min,
const worldpos_t max,
const mapareacallback_t callback,
const mapareanotify_t notify
const uint8_t notify,
const uint8_t trigger
) {
assertNotNull(area, "Map area pointer cannot be NULL");
assertNotNull(callback, "Map area callback cannot be NULL");
@@ -32,6 +34,9 @@ void mapAreaInit(
area->callback = callback;
area->notify = notify;
area->trigger = trigger;
memorySet(area->entities, 0, sizeof(area->entities));
}
bool_t mapAreaIsInside(const maparea_t *area, const worldpos_t position) {
@@ -94,11 +99,12 @@ uint8_t mapAreaAdd(
const worldpos_t min,
const worldpos_t max,
const mapareacallback_t callback,
const mapareanotify_t notify
const uint8_t notify,
const uint8_t trigger
) {
for(uint8_t i = 0; i < MAP_AREA_COUNT_MAX; i++) {
if(MAP_AREAS[i].callback != NULL) continue;
mapAreaInit(&MAP_AREAS[i], min, max, callback, notify);
mapAreaInit(&MAP_AREAS[i], min, max, callback, notify, trigger);
return i;
}
@@ -117,8 +123,23 @@ void mapAreaCheckEntity(entity_t *entity) {
for(uint8_t i = 0; i < MAP_AREA_COUNT_MAX; i++) {
maparea_t *area = &MAP_AREAS[i];
if(area->callback == NULL) continue;
if(!mapAreaIsInside(area, entity->position)) continue;
if(!mapAreaShouldNotify(area, entity)) continue;
area->callback(entity);
bool_t wasInside = area->entities[entity->id] != 0;
bool_t isInside = mapAreaIsInside(area, entity->position);
uint8_t trigger = 0;
if(isInside && !wasInside) {
area->entities[entity->id] = 1;
trigger = MAP_TRIGGER_ENTER;
} else if(isInside && wasInside) {
trigger = MAP_TRIGGER_STEP;
} else if(!isInside && wasInside) {
area->entities[entity->id] = 0;
trigger = MAP_TRIGGER_EXIT;
}
if(trigger == 0 || !(area->trigger & trigger)) continue;
area->callback(entity, trigger);
}
}
+27 -14
View File
@@ -7,39 +7,44 @@
#pragma once
#include "worldpos.h"
#include "rpg/entity/entity.h"
typedef struct chunk_s chunk_t;
typedef struct entity_s entity_t;
typedef struct maparea_s maparea_t;
#define MAP_AREA_COUNT_MAX 32
typedef uint8_t mapareanotify_t;
#define MAP_AREA_NOTIFY_PLAYER (1 << 0)
#define MAP_AREA_NOTIFY_NPC (1 << 1)
#define MAP_AREA_NOTIFY_ALL (MAP_AREA_NOTIFY_PLAYER | MAP_AREA_NOTIFY_NPC)
#define MAP_AREA_NOTIFY_PLAYER ((mapareanotify_t)(1 << 0))
#define MAP_AREA_NOTIFY_NPC ((mapareanotify_t)(1 << 1))
#define MAP_AREA_NOTIFY_ALL ((mapareanotify_t)( \
MAP_AREA_NOTIFY_PLAYER | MAP_AREA_NOTIFY_NPC \
))
#define MAP_TRIGGER_STEP (1 << 0)
#define MAP_TRIGGER_ENTER (1 << 1)
#define MAP_TRIGGER_EXIT (1 << 2)
#define MAP_TRIGGER_ALL (MAP_TRIGGER_STEP | MAP_TRIGGER_ENTER | MAP_TRIGGER_EXIT)
/**
* Callback invoked for a map area.
*
* @param entity Pointer to the entity associated with the callback.
* @param trigger Which MAP_TRIGGER_* condition invoked the callback.
*/
typedef void (*mapareacallback_t)(entity_t *entity);
typedef void (*mapareacallback_t)(entity_t *entity, const uint8_t trigger);
typedef struct maparea_s {
worldpos_t min;
worldpos_t max;
mapareacallback_t callback;
mapareanotify_t notify;
uint8_t notify;
uint8_t trigger;
uint8_t entities[ENTITY_COUNT];
} maparea_t;
extern maparea_t MAP_AREAS[MAP_AREA_COUNT_MAX];
/**
* Initializes a map area with the given bounds, callback and notify flags.
* Initializes a map area with the given bounds, callback, notify flags
* and trigger flags.
*
* @param area Pointer to the map area to initialize.
* @param min The minimum world position of the area.
@@ -47,13 +52,16 @@ extern maparea_t MAP_AREAS[MAP_AREA_COUNT_MAX];
* @param callback The callback to invoke for this area. Must not be NULL.
* @param notify Bitwise MAP_AREA_NOTIFY_* flags for which entity types
* should trigger the callback.
* @param trigger Bitwise MAP_TRIGGER_* flags for which conditions should
* invoke the callback.
*/
void mapAreaInit(
maparea_t *area,
const worldpos_t min,
const worldpos_t max,
const mapareacallback_t callback,
const mapareanotify_t notify
const uint8_t notify,
const uint8_t trigger
);
/**
@@ -106,13 +114,16 @@ bool_t mapAreaShouldNotify(const maparea_t *area, const entity_t *entity);
* @param callback The callback to invoke for this area. Must not be NULL.
* @param notify Bitwise MAP_AREA_NOTIFY_* flags for which entity types
* should trigger the callback.
* @param trigger Bitwise MAP_TRIGGER_* flags for which conditions should
* invoke the callback.
* @returns The ID of the newly added map area.
*/
uint8_t mapAreaAdd(
const worldpos_t min,
const worldpos_t max,
const mapareacallback_t callback,
const mapareanotify_t notify
const uint8_t notify,
const uint8_t trigger
);
/**
@@ -125,8 +136,10 @@ void mapAreaRemove(const uint8_t id);
/**
* Checks every active map area against an entity's current position,
* invoking each matching area's callback if the entity is inside it and
* its type is included in that area's notify flags.
* for areas whose notify flags include the entity's type. Invokes the
* area's callback with MAP_TRIGGER_ENTER the frame the entity first
* becomes inside, MAP_TRIGGER_STEP on every subsequent frame it remains
* inside, and MAP_TRIGGER_EXIT the frame it leaves.
*
* @param entity Pointer to the entity to check.
*/
+4 -3
View File
@@ -20,8 +20,8 @@
#include "assert/assert.h"
#include "console/console.h"
void rpgTestAreaCallback(entity_t *entity) {
consolePrint("rpgTestAreaCallback");
void rpgTestAreaCallback(entity_t *entity, const uint8_t trigger) {
consolePrint("rpgTestAreaCallback: trigger=%u", trigger);
}
errorret_t rpgInit(void) {
@@ -53,7 +53,8 @@ errorret_t rpgInit(void) {
(worldpos_t){ 11, 3, 0 },
(worldpos_t){ 16, 9, 10 },
rpgTestAreaCallback,
MAP_AREA_NOTIFY_ALL
MAP_AREA_NOTIFY_ALL,
MAP_TRIGGER_ENTER | MAP_TRIGGER_EXIT
);
assertTrue(areaIndex != 0xFF, "No available map area slots!.");