Trigger types on areas
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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!.");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user