diff --git a/src/dusk/rpg/entity/entity.c b/src/dusk/rpg/entity/entity.c index 844fdfde..103bae0b 100644 --- a/src/dusk/rpg/entity/entity.c +++ b/src/dusk/rpg/entity/entity.c @@ -10,6 +10,7 @@ #include "util/memory.h" #include "time/time.h" #include "util/math.h" +#include "util/random.h" #include "rpg/overworld/map.h" #include "rpg/overworld/chunk.h" #include "rpg/overworld/tile.h" @@ -27,6 +28,7 @@ void entityInit(entity_t *entity, const entitytype_t type) { memoryZero(entity, sizeof(entity_t)); entity->id = (uint8_t)(entity - ENTITIES); + entity->globalId = (entityglobalid_t)randomInt(0, ENTITY_GLOBAL_ID_START); entity->type = type; entity->chunkIndex = 0xFF; @@ -60,6 +62,10 @@ bool_t entityCanRun(entity_t *entity) { return entity->animation == ENTITY_ANIM_IDLE; } +bool_t entityCanUnload(entity_t *entity) { + return entity->globalId < ENTITY_GLOBAL_ID_START; +} + void entityTurn(entity_t *entity, const entitydir_t direction) { if(!entityCanTurn(entity)) return; entity->direction = direction; diff --git a/src/dusk/rpg/entity/entity.h b/src/dusk/rpg/entity/entity.h index d924addf..500b73ff 100644 --- a/src/dusk/rpg/entity/entity.h +++ b/src/dusk/rpg/entity/entity.h @@ -14,8 +14,14 @@ typedef struct map_s map_t; +typedef uint16_t entityglobalid_t; + +#define ENTITY_GLOBAL_ID_START 1000 +#define ENTITY_GLOBAL_ID_PLAYER UINT16_MAX + typedef struct entity_s { uint8_t id; + entityglobalid_t globalId; entitytype_t type; entitytypedata_t data; @@ -75,6 +81,16 @@ bool_t entityCanWalk(entity_t *entity); */ bool_t entityCanRun(entity_t *entity); +/** + * Returns true if the entity is allowed to be unloaded. By default this is + * true for entities whose global ID falls within the randomly assigned + * range below ENTITY_GLOBAL_ID_START. + * + * @param entity Pointer to the entity to check. + * @returns True if the entity can be unloaded. + */ +bool_t entityCanUnload(entity_t *entity); + /** * Turn an entity to face a new direction. * diff --git a/src/dusk/rpg/entity/entitypathstep.c b/src/dusk/rpg/entity/entitypathstep.c index 003b03a9..bd474415 100644 --- a/src/dusk/rpg/entity/entitypathstep.c +++ b/src/dusk/rpg/entity/entitypathstep.c @@ -24,7 +24,9 @@ bool_t entityPathStep( "Entity pointer is out of bounds" ); - if(worldPosIsEqual(entity->position, target)) return true; + if(worldPosIsEqual(entity->position, target) && entityCanWalk(entity)) { + return true; + } if(!entityCanWalk(entity)) return false; entitydir_t dir; diff --git a/src/dusk/rpg/entity/player.c b/src/dusk/rpg/entity/player.c index 07ce68c8..9ea1fad6 100644 --- a/src/dusk/rpg/entity/player.c +++ b/src/dusk/rpg/entity/player.c @@ -16,6 +16,7 @@ void playerInit(entity_t *entity) { assertNotNull(entity, "Entity pointer cannot be NULL"); + entity->globalId = ENTITY_GLOBAL_ID_PLAYER; } bool_t playerCanInteract(entity_t *entity) { diff --git a/src/dusk/rpg/overworld/map.c b/src/dusk/rpg/overworld/map.c index 420387d4..ac176c91 100644 --- a/src/dusk/rpg/overworld/map.c +++ b/src/dusk/rpg/overworld/map.c @@ -141,7 +141,7 @@ void mapChunkUnload(chunk_t *chunk) { for(uint8_t i = 0; i < CHUNK_ENTITY_COUNT_MAX; i++) { if(chunk->entities[i] == 0xFF) continue; entity_t *entity = &ENTITIES[chunk->entities[i]]; - if(entity->type == ENTITY_TYPE_PLAYER) { + if(!entityCanUnload(entity)) { entitySetChunk(entity, 0xFF); } else { entity->type = ENTITY_TYPE_NULL; diff --git a/src/dusk/rpg/rpg.c b/src/dusk/rpg/rpg.c index 5bb58688..fe0869ef 100644 --- a/src/dusk/rpg/rpg.c +++ b/src/dusk/rpg/rpg.c @@ -48,6 +48,7 @@ errorret_t rpgInit(void) { uint8_t npcIndex = entityGetAvailable(); 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; diff --git a/src/dusk/util/random.c b/src/dusk/util/random.c index ded6b7d0..c7974029 100644 --- a/src/dusk/util/random.c +++ b/src/dusk/util/random.c @@ -11,3 +11,7 @@ float_t randomFloat(const float_t min, const float_t max) { return min + ((float_t)rand() / (float_t)RAND_MAX) * (max - min); } + +int_t randomInt(const int_t min, const int_t max) { + return min + (rand() % (max - min)); +} diff --git a/src/dusk/util/random.h b/src/dusk/util/random.h index 3968e2af..1fba6946 100644 --- a/src/dusk/util/random.h +++ b/src/dusk/util/random.h @@ -16,3 +16,12 @@ * @returns A random float in [min, max). */ float_t randomFloat(const float_t min, const float_t max); + +/** + * Returns a random integer between min (inclusive) and max (exclusive). + * + * @param min Lower bound. + * @param max Upper bound. + * @returns A random integer in [min, max). + */ +int_t randomInt(const int_t min, const int_t max);