Example global ent
This commit is contained in:
@@ -14,4 +14,5 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
|
|
||||||
add_subdirectory(anim)
|
add_subdirectory(anim)
|
||||||
add_subdirectory(interact)
|
add_subdirectory(interact)
|
||||||
add_subdirectory(npc)
|
add_subdirectory(npc)
|
||||||
|
add_subdirectory(global)
|
||||||
@@ -10,7 +10,6 @@
|
|||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
#include "time/time.h"
|
#include "time/time.h"
|
||||||
#include "util/math.h"
|
#include "util/math.h"
|
||||||
#include "util/random.h"
|
|
||||||
#include "rpg/overworld/map.h"
|
#include "rpg/overworld/map.h"
|
||||||
#include "rpg/overworld/chunk.h"
|
#include "rpg/overworld/chunk.h"
|
||||||
#include "rpg/overworld/tile.h"
|
#include "rpg/overworld/tile.h"
|
||||||
@@ -28,7 +27,7 @@ void entityInit(entity_t *entity, const entitytype_t type) {
|
|||||||
|
|
||||||
memoryZero(entity, sizeof(entity_t));
|
memoryZero(entity, sizeof(entity_t));
|
||||||
entity->id = (uint8_t)(entity - ENTITIES);
|
entity->id = (uint8_t)(entity - ENTITIES);
|
||||||
entity->globalId = (entityglobalid_t)randomInt(0, ENTITY_GLOBAL_ID_START);
|
entity->globalId = ENTITY_GLOBAL_ID_NULL;
|
||||||
entity->type = type;
|
entity->type = type;
|
||||||
entity->chunkIndex = 0xFF;
|
entity->chunkIndex = 0xFF;
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,9 @@ typedef struct map_s map_t;
|
|||||||
|
|
||||||
typedef uint16_t entityglobalid_t;
|
typedef uint16_t entityglobalid_t;
|
||||||
|
|
||||||
#define ENTITY_GLOBAL_ID_START 1000
|
#define ENTITY_GLOBAL_ID_NULL 0
|
||||||
#define ENTITY_GLOBAL_ID_PLAYER UINT16_MAX
|
#define ENTITY_GLOBAL_ID_START 1
|
||||||
|
#define ENTITY_GLOBAL_ID_PLAYER 1
|
||||||
|
|
||||||
typedef struct entity_s {
|
typedef struct entity_s {
|
||||||
uint8_t id;
|
uint8_t id;
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
# Copyright (c) 2026 Dominic Masters
|
||||||
|
#
|
||||||
|
# This software is released under the MIT License.
|
||||||
|
# https://opensource.org/licenses/MIT
|
||||||
|
|
||||||
|
# Sources
|
||||||
|
target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
||||||
|
PUBLIC
|
||||||
|
)
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "entityglobaldefs.h"
|
||||||
|
#include "entitygloballist.h"
|
||||||
|
|
||||||
|
#define ENTITY_GLOBAL_LIST_COUNT ( \
|
||||||
|
sizeof(ENTITY_GLOBAL_LIST) / \
|
||||||
|
sizeof(ENTITY_GLOBAL_LIST[0]) \
|
||||||
|
)
|
||||||
|
|
||||||
|
//EOF
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "error/error.h"
|
||||||
|
#include "rpg/overworld/worldpos.h"
|
||||||
|
#include "rpg/entity/entity.h"
|
||||||
|
|
||||||
|
typedef struct entity_s entity_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
entity_t *entity;
|
||||||
|
worldpos_t position;
|
||||||
|
} entityglobalcreate_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback invoked to initialize a global entity.
|
||||||
|
*
|
||||||
|
* @param create Pointer to the entity/position being initialized.
|
||||||
|
* @returns An error code.
|
||||||
|
*/
|
||||||
|
typedef void (*entityglobalinitcallback_t)(
|
||||||
|
entityglobalcreate_t *create
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
entitytype_t type;
|
||||||
|
entityglobalinitcallback_t callback;
|
||||||
|
} entityglobaldef_t;
|
||||||
|
|
||||||
|
#define ENTITY_GLOBAL(id, entType, callbackFn) \
|
||||||
|
[id] = { .type = entType, .callback = callbackFn }
|
||||||
|
|
||||||
|
#define ENTITY_GLOBAL_CALLBACK(id) \
|
||||||
|
static void ENTTIYT_GLOBAL_CALLBACK_##id(entityglobalcreate_t *create)
|
||||||
|
|
||||||
|
#define ENTITY_GLOBAL_REF(id) \
|
||||||
|
ENTTIYT_GLOBAL_CALLBACK_##id
|
||||||
|
|
||||||
|
//EOF
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "entityglobaldefs.h"
|
||||||
|
#include "rpg/cutscene/scene/testcutscene.h"
|
||||||
|
|
||||||
|
ENTITY_GLOBAL_CALLBACK(3) {
|
||||||
|
create->entity->data.npc.moveType = NPC_MOVE_TYPE_PATH;
|
||||||
|
npcPathAddNode(&create->entity->data.npc, (worldpos_t){ 4, 4, 0 });
|
||||||
|
npcPathAddNode(&create->entity->data.npc, (worldpos_t){ 10, 10, 1 });
|
||||||
|
npcPathAddNode(&create->entity->data.npc, (worldpos_t){ 4, 4, 0 });
|
||||||
|
npcPathAddNode(&create->entity->data.npc, (worldpos_t){ 10, 10, 1 });
|
||||||
|
|
||||||
|
create->entity->interact.type = ENTITY_INTERACT_CUTSCENE;
|
||||||
|
create->entity->interact.data.cutscene = CUTSCENE_REFERENCE(TEST_TWO);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const entityglobaldef_t ENTITY_GLOBAL_LIST[] = {
|
||||||
|
ENTITY_GLOBAL(ENTITY_GLOBAL_ID_NULL, ENTITY_TYPE_NULL, NULL),
|
||||||
|
ENTITY_GLOBAL(ENTITY_GLOBAL_ID_PLAYER, ENTITY_TYPE_PLAYER, NULL),
|
||||||
|
|
||||||
|
ENTITY_GLOBAL(3, ENTITY_TYPE_NPC, ENTITY_GLOBAL_REF(3)),
|
||||||
|
};
|
||||||
|
|
||||||
|
//EOF
|
||||||
@@ -12,8 +12,8 @@
|
|||||||
#include "asset/loader/assetloader.h"
|
#include "asset/loader/assetloader.h"
|
||||||
#include "console/console.h"
|
#include "console/console.h"
|
||||||
#include "event/event.h"
|
#include "event/event.h"
|
||||||
#include "rpg/entity/entity.h"
|
|
||||||
#include "util/string.h"
|
#include "util/string.h"
|
||||||
|
#include "rpg/entity/global/entityglobal.h"
|
||||||
|
|
||||||
map_t MAP;
|
map_t MAP;
|
||||||
|
|
||||||
@@ -268,6 +268,49 @@ bool_t mapGetWalkableZNear(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
entity_t * mapSpawnEntity(
|
||||||
|
const entityglobalid_t globalId,
|
||||||
|
const worldpos_t position
|
||||||
|
) {
|
||||||
|
assertTrue(
|
||||||
|
globalId > ENTITY_GLOBAL_ID_START,
|
||||||
|
"mapSpawnEntity requires a global ID greater than ENTITY_GLOBAL_ID_START"
|
||||||
|
);
|
||||||
|
assertTrue(
|
||||||
|
globalId < ENTITY_GLOBAL_LIST_COUNT,
|
||||||
|
"Global ID is out of range for entity global init callbacks"
|
||||||
|
);
|
||||||
|
|
||||||
|
// See if there is a callback for this entity first.
|
||||||
|
const entityglobaldef_t *def = &ENTITY_GLOBAL_LIST[globalId];
|
||||||
|
assertNotNull(def, "No global entity definition for this ID");
|
||||||
|
assertNotNull(def->callback, "No callback registered for this global ID");
|
||||||
|
|
||||||
|
// Get available entity.
|
||||||
|
uint8_t index = entityGetAvailable();
|
||||||
|
assertTrue(index != 0xFF, "No available entity slots for mapSpawnEntity");
|
||||||
|
|
||||||
|
// Get the pointer and do the init.
|
||||||
|
entity_t *entity = &ENTITIES[index];
|
||||||
|
entityInit(entity, def->type);
|
||||||
|
entity->globalId = globalId;
|
||||||
|
entityPositionSet(entity, position);
|
||||||
|
|
||||||
|
// Assign to the local chunk.
|
||||||
|
chunkpos_t cp;
|
||||||
|
worldPosToChunkPos(&entity->position, &cp);
|
||||||
|
chunkindex_t ci = mapGetChunkIndexAt(cp);
|
||||||
|
if(ci != -1) entitySetChunk(entity, (uint8_t)ci);
|
||||||
|
|
||||||
|
// Invoke the callback to initialize the entity.
|
||||||
|
entityglobalcreate_t create = {
|
||||||
|
.entity = entity,
|
||||||
|
.position = position
|
||||||
|
};
|
||||||
|
def->callback(&create);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
void mapRebuildChunkOrder() {
|
void mapRebuildChunkOrder() {
|
||||||
memoryZero(MAP.chunkOrder, sizeof(MAP.chunkOrder));
|
memoryZero(MAP.chunkOrder, sizeof(MAP.chunkOrder));
|
||||||
for(chunkindex_t i = 0; i < MAP_LOADED_CHUNK_COUNT; i++) {
|
for(chunkindex_t i = 0; i < MAP_LOADED_CHUNK_COUNT; i++) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "error/error.h"
|
#include "error/error.h"
|
||||||
#include "rpg/overworld/chunk.h"
|
#include "rpg/overworld/chunk.h"
|
||||||
|
#include "rpg/entity/entity.h"
|
||||||
|
|
||||||
#define MAP_FILE_PATH_MAX 128
|
#define MAP_FILE_PATH_MAX 128
|
||||||
|
|
||||||
@@ -36,18 +37,6 @@ errorret_t mapInit();
|
|||||||
*/
|
*/
|
||||||
bool_t mapIsLoaded();
|
bool_t mapIsLoaded();
|
||||||
|
|
||||||
/**
|
|
||||||
* Loads a map from the given file path.
|
|
||||||
*
|
|
||||||
* @param path The file path.
|
|
||||||
* @param position The initial chunk position.
|
|
||||||
* @return An error code.
|
|
||||||
*/
|
|
||||||
// errorret_t mapLoad(
|
|
||||||
// const char_t *path,
|
|
||||||
// const chunkpos_t position
|
|
||||||
// );
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates the map.
|
* Updates the map.
|
||||||
*
|
*
|
||||||
@@ -150,4 +139,19 @@ bool_t mapGetWalkableZNear(
|
|||||||
const worldunit_t y,
|
const worldunit_t y,
|
||||||
const worldunit_t nearZ,
|
const worldunit_t nearZ,
|
||||||
worldunit_t *outZ
|
worldunit_t *outZ
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawns a global (persistent) entity into the world at the given position.
|
||||||
|
* Asserts globalId is greater than ENTITY_GLOBAL_ID_START - use entityInit
|
||||||
|
* directly for ephemeral, non-global entities.
|
||||||
|
*
|
||||||
|
* @param globalId The global entity ID to assign, must be greater than
|
||||||
|
* ENTITY_GLOBAL_ID_START.
|
||||||
|
* @param position The world position to spawn the entity at.
|
||||||
|
* @return Pointer to the spawned entity.
|
||||||
|
*/
|
||||||
|
entity_t * mapSpawnEntity(
|
||||||
|
const entityglobalid_t globalId,
|
||||||
|
const worldpos_t position
|
||||||
);
|
);
|
||||||
+1
-19
@@ -45,25 +45,7 @@ errorret_t rpgInit(void) {
|
|||||||
if(ci != -1) entitySetChunk(ent, (uint8_t)ci);
|
if(ci != -1) entitySetChunk(ent, (uint8_t)ci);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t npcIndex = entityGetAvailable();
|
mapSpawnEntity(3, (worldpos_t){ 8, 8, 1 });
|
||||||
entity_t *npc = &ENTITIES[npcIndex];
|
|
||||||
entityInit(npc, ENTITY_TYPE_NPC);
|
|
||||||
npc->globalId = ENTITY_GLOBAL_ID_START;
|
|
||||||
npcSetMoveType(npc, NPC_MOVE_TYPE_PATH);
|
|
||||||
entityPositionSet(npc, (worldpos_t){ 8, 8, 1 });
|
|
||||||
npc->interact.type = ENTITY_INTERACT_CUTSCENE;
|
|
||||||
npc->interact.data.cutscene = CUTSCENE_REFERENCE(TEST_TWO);
|
|
||||||
{
|
|
||||||
chunkpos_t cp;
|
|
||||||
worldPosToChunkPos(&npc->position, &cp);
|
|
||||||
chunkindex_t ci = mapGetChunkIndexAt(cp);
|
|
||||||
if(ci != -1) entitySetChunk(npc, (uint8_t)ci);
|
|
||||||
}
|
|
||||||
|
|
||||||
npcPathAddNode(&npc->data.npc, (worldpos_t){ 4, 4, 0 });
|
|
||||||
npcPathAddNode(&npc->data.npc, (worldpos_t){ 10, 10, 1 });
|
|
||||||
npcPathAddNode(&npc->data.npc, (worldpos_t){ 4, 4, 0 });
|
|
||||||
npcPathAddNode(&npc->data.npc, (worldpos_t){ 10, 10, 1 });
|
|
||||||
|
|
||||||
// All Good!
|
// All Good!
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
Reference in New Issue
Block a user