npc interact turn to face player

This commit is contained in:
2026-06-27 06:30:45 -05:00
parent 182428d6d6
commit 2a85c9503f
6 changed files with 42 additions and 57 deletions
-3
View File
@@ -43,9 +43,6 @@ void entityUpdate(entity_t *entity) {
entityAnimUpdate(entity); entityAnimUpdate(entity);
// Movement code. // Movement code.
if(ENTITY_CALLBACKS[entity->type].freeMovement != NULL) {
ENTITY_CALLBACKS[entity->type].freeMovement(entity);
}
if( if(
cutsceneModeIsInputAllowed() && cutsceneModeIsInputAllowed() &&
ENTITY_CALLBACKS[entity->type].movement != NULL ENTITY_CALLBACKS[entity->type].movement != NULL
-16
View File
@@ -37,20 +37,6 @@ typedef struct {
* @param entity Pointer to the entity to move. * @param entity Pointer to the entity to move.
*/ */
void (*movement)(entity_t *entity); void (*movement)(entity_t *entity);
/**
* Free movement callback. Always runs regardless of cutscene state.
* @param entity Pointer to the entity to move.
*/
void (*freeMovement)(entity_t *entity);
/**
* Interaction callback for the entity type.
* @param player Pointer to the player entity.
* @param entity Pointer to the entity to interact with.
* @return True if the entity handled the interaction, false otherwise.
*/
bool_t (*interact)(entity_t *player, entity_t *entity);
} entitycallback_t; } entitycallback_t;
static const entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = { static const entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = {
@@ -64,7 +50,5 @@ static const entitycallback_t ENTITY_CALLBACKS[ENTITY_TYPE_COUNT] = {
[ENTITY_TYPE_NPC] = { [ENTITY_TYPE_NPC] = {
.init = npcInit, .init = npcInit,
.movement = npcMovement, .movement = npcMovement,
.freeMovement = npcFreeMovement,
.interact = npcInteract
} }
}; };
+11 -5
View File
@@ -21,11 +21,20 @@ void entityInteractWith(entity_t *player, entity_t *target) {
"Interact cutscene pointer cannot be NULL" "Interact cutscene pointer cannot be NULL"
); );
cutsceneSystemStartCutscene(target->interact.data.cutscene); cutsceneSystemStartCutscene(target->interact.data.cutscene);
return; break;
case ENTITY_INTERACT_PRINT: case ENTITY_INTERACT_PRINT:
uiTextboxMainSetText(target->interact.data.message); uiTextboxMainSetText(target->interact.data.message);
return;
// If NPC turn to face player.
if(target->type == ENTITY_TYPE_NPC) {
target->data.npc.interactState = NPC_INTERACT_STATE_CONVERSING;
target->animation = ENTITY_ANIM_IDLE;
entityTurn(target, entityDirGetOpposite(player->direction));
}
// entityTurn(player, player->direction); // Redundant (for now)
break;
case ENTITY_INTERACT_NULL: case ENTITY_INTERACT_NULL:
break; break;
@@ -34,7 +43,4 @@ void entityInteractWith(entity_t *player, entity_t *target) {
assertUnreachable("Unknown entity interact type"); assertUnreachable("Unknown entity interact type");
break; break;
} }
if(ENTITY_CALLBACKS[target->type].interact == NULL) return;
ENTITY_CALLBACKS[target->type].interact(player, target);
} }
@@ -16,8 +16,11 @@ typedef struct entity_s entity_t;
*/ */
typedef enum { typedef enum {
ENTITY_INTERACT_NULL = 0, ENTITY_INTERACT_NULL = 0,
ENTITY_INTERACT_CUTSCENE, ENTITY_INTERACT_CUTSCENE,
ENTITY_INTERACT_PRINT, ENTITY_INTERACT_PRINT,
ENTITY_INTERACT_CALLBACK,
ENTITY_INTERACT_COUNT ENTITY_INTERACT_COUNT
} entityinteracttype_t; } entityinteracttype_t;
@@ -27,6 +30,7 @@ typedef enum {
typedef union { typedef union {
const cutscene_t *cutscene; const cutscene_t *cutscene;
const char_t *message; const char_t *message;
void (*callback)(entity_t *player, entity_t *target);
} entityinteractdata_t; } entityinteractdata_t;
/** /**
+17 -20
View File
@@ -12,17 +12,27 @@
#include "rpg/rpgtextbox.h" #include "rpg/rpgtextbox.h"
const npcmovecallback_t NPC_MOVE_CALLBACKS[NPC_MOVE_TYPE_COUNT] = { const npcmovecallback_t NPC_MOVE_CALLBACKS[NPC_MOVE_TYPE_COUNT] = {
[NPC_MOVE_TYPE_NULL] = { NULL, NULL }, [NPC_MOVE_TYPE_NULL] = { 0 },
[NPC_MOVE_TYPE_RANDOM_TURN] = { npcRandomTurnInit, npcRandomTurnMovement },
[NPC_MOVE_TYPE_RANDOM_TURN] = {
npcRandomTurnInit,
npcRandomTurnMovement
},
[NPC_MOVE_TYPE_RANDOM_WALK] = { [NPC_MOVE_TYPE_RANDOM_WALK] = {
npcRandomWalkInit, npcRandomWalkInit,
npcRandomWalkMovement npcRandomWalkMovement
}, },
[NPC_MOVE_TYPE_RANDOM_TURN_AND_WALK] = { [NPC_MOVE_TYPE_RANDOM_TURN_AND_WALK] = {
npcRandomTurnAndWalkInit, npcRandomTurnAndWalkInit,
npcRandomTurnAndWalkMovement npcRandomTurnAndWalkMovement
}, },
[NPC_MOVE_TYPE_PATH] = { npcPathInit, npcPathMovement, true },
[NPC_MOVE_TYPE_PATH] = {
npcPathInit,
npcPathMovement
},
}; };
void npcInit(entity_t *entity) { void npcInit(entity_t *entity) {
@@ -40,23 +50,10 @@ void npcSetMoveType(entity_t *entity, const npcmovetype_t moveType) {
void npcMovement(entity_t *entity) { void npcMovement(entity_t *entity) {
assertNotNull(entity, "Entity pointer cannot be NULL"); assertNotNull(entity, "Entity pointer cannot be NULL");
npc_t *npc = &entity->data.npc; npc_t *npc = &entity->data.npc;
if(npc->interactState != NPC_INTERACT_STATE_NONE) return;
const npcmovecallback_t *cb = &NPC_MOVE_CALLBACKS[npc->moveType]; const npcmovecallback_t *cb = &NPC_MOVE_CALLBACKS[npc->moveType];
if(!cb->alwaysRun && cb->movement != NULL) cb->movement(entity); if(cb->movement != NULL) cb->movement(entity);
}
void npcFreeMovement(entity_t *entity) {
assertNotNull(entity, "Entity pointer cannot be NULL");
npc_t *npc = &entity->data.npc;
const npcmovecallback_t *cb = &NPC_MOVE_CALLBACKS[npc->moveType];
if(cb->alwaysRun && cb->movement != NULL) cb->movement(entity);
}
bool_t npcInteract(entity_t *player, entity_t *npc) {
assertNotNull(player, "Player entity pointer cannot be NULL");
assertNotNull(npc, "NPC entity pointer cannot be NULL");
cutsceneSystemStartCutscene(&TEST_CUTSCENE);
// rpgTextboxShow(RPG_TEXTBOX_POS_BOTTOM, "Hello World!");
return false;
} }
+7 -10
View File
@@ -13,6 +13,12 @@
typedef struct entity_s entity_t; typedef struct entity_s entity_t;
typedef enum {
NPC_INTERACT_STATE_NONE,
NPC_INTERACT_STATE_CONVERSING,
NPC_INTERACT_STATE_COUNT
} npcinteractstate_t;
typedef enum { typedef enum {
NPC_MOVE_TYPE_NULL, NPC_MOVE_TYPE_NULL,
NPC_MOVE_TYPE_RANDOM_TURN, NPC_MOVE_TYPE_RANDOM_TURN,
@@ -30,6 +36,7 @@ typedef union {
} npcmovedata_t; } npcmovedata_t;
typedef struct npc_s { typedef struct npc_s {
npcinteractstate_t interactState;
npcmovetype_t moveType; npcmovetype_t moveType;
npcmovedata_t moveData; npcmovedata_t moveData;
} npc_t; } npc_t;
@@ -39,8 +46,6 @@ typedef struct {
void (*init)(npc_t *npc); void (*init)(npc_t *npc);
/** Called each movement tick. */ /** Called each movement tick. */
void (*movement)(entity_t *entity); void (*movement)(entity_t *entity);
/** True if movement runs regardless of cutscene state. */
bool_t alwaysRun;
} npcmovecallback_t; } npcmovecallback_t;
extern const npcmovecallback_t NPC_MOVE_CALLBACKS[NPC_MOVE_TYPE_COUNT]; extern const npcmovecallback_t NPC_MOVE_CALLBACKS[NPC_MOVE_TYPE_COUNT];
@@ -74,11 +79,3 @@ void npcMovement(entity_t *entity);
* @param entity Pointer to the entity structure to update. * @param entity Pointer to the entity structure to update.
*/ */
void npcFreeMovement(entity_t *entity); void npcFreeMovement(entity_t *entity);
/**
* Handles interaction with an NPC entity.
*
* @param player Pointer to the player entity.
* @param npc Pointer to the NPC entity.
*/
bool_t npcInteract(entity_t *player, entity_t *npc);