Interact
This commit is contained in:
@@ -8,7 +8,8 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME}
|
|||||||
PUBLIC
|
PUBLIC
|
||||||
entity.c
|
entity.c
|
||||||
entityanim.c
|
entityanim.c
|
||||||
|
entitydir.c
|
||||||
|
entityinteract.c
|
||||||
npc.c
|
npc.c
|
||||||
player.c
|
player.c
|
||||||
entitydir.c
|
|
||||||
)
|
)
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "entitydir.h"
|
#include "entitydir.h"
|
||||||
#include "entityanim.h"
|
#include "entityanim.h"
|
||||||
|
#include "entityinteract.h"
|
||||||
#include "entitytype.h"
|
#include "entitytype.h"
|
||||||
#include "npc.h"
|
#include "npc.h"
|
||||||
|
|
||||||
@@ -25,6 +26,8 @@ typedef struct entity_s {
|
|||||||
|
|
||||||
entityanim_t animation;
|
entityanim_t animation;
|
||||||
fixed_t animTime;
|
fixed_t animTime;
|
||||||
|
|
||||||
|
entityinteract_t interact;
|
||||||
} entity_t;
|
} entity_t;
|
||||||
|
|
||||||
extern entity_t ENTITIES[ENTITY_COUNT];
|
extern entity_t ENTITIES[ENTITY_COUNT];
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "dusk.h"
|
#include "dusk.h"
|
||||||
#include "util/fixed.h"
|
#include "util/fixed.h"
|
||||||
|
|
||||||
#define ENTITY_ANIM_TURN_DURATION FIXED(0.12f)
|
#define ENTITY_ANIM_TURN_DURATION FIXED(0.06f)
|
||||||
#define ENTITY_ANIM_WALK_DURATION FIXED(0.1f)
|
#define ENTITY_ANIM_WALK_DURATION FIXED(0.1f)
|
||||||
|
|
||||||
typedef struct entity_s entity_t;
|
typedef struct entity_s entity_t;
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "entity.h"
|
||||||
|
#include "assert/assert.h"
|
||||||
|
#include "console/console.h"
|
||||||
|
#include "rpg/cutscene/cutscenesystem.h"
|
||||||
|
|
||||||
|
void entityInteractWith(entity_t *player, entity_t *target) {
|
||||||
|
assertNotNull(player, "Player entity pointer cannot be NULL");
|
||||||
|
assertNotNull(target, "Target entity pointer cannot be NULL");
|
||||||
|
|
||||||
|
switch(target->interact.type) {
|
||||||
|
case ENTITY_INTERACT_CUTSCENE:
|
||||||
|
assertNotNull(
|
||||||
|
target->interact.data.cutscene,
|
||||||
|
"Interact cutscene pointer cannot be NULL"
|
||||||
|
);
|
||||||
|
cutsceneSystemStartCutscene(target->interact.data.cutscene);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ENTITY_INTERACT_PRINT:
|
||||||
|
consolePrint(target->interact.data.message);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case ENTITY_INTERACT_NULL:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assertUnreachable("Unknown entity interact type");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ENTITY_CALLBACKS[target->type].interact == NULL) return;
|
||||||
|
ENTITY_CALLBACKS[target->type].interact(player, target);
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2026 Dominic Masters
|
||||||
|
*
|
||||||
|
* This software is released under the MIT License.
|
||||||
|
* https://opensource.org/licenses/MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "dusk.h"
|
||||||
|
#include "rpg/cutscene/cutscene.h"
|
||||||
|
|
||||||
|
typedef struct entity_s entity_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describes the type of interaction an entity supports.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ENTITY_INTERACT_NULL = 0,
|
||||||
|
ENTITY_INTERACT_CUTSCENE,
|
||||||
|
ENTITY_INTERACT_PRINT,
|
||||||
|
ENTITY_INTERACT_COUNT
|
||||||
|
} entityinteracttype_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Per-type data for an entity's interact component.
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
const cutscene_t *cutscene;
|
||||||
|
char_t message[32];
|
||||||
|
} entityinteractdata_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interact component attached to any entity that can be interacted with.
|
||||||
|
* Set type to ENTITY_INTERACT_NULL to mark the entity as non-interactable.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
entityinteracttype_t type;
|
||||||
|
entityinteractdata_t data;
|
||||||
|
} entityinteract_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to interact with the target entity on behalf of the player.
|
||||||
|
* Dispatches via the interact component; falls back to the entity type
|
||||||
|
* callback if no component is set.
|
||||||
|
*
|
||||||
|
* @param player Pointer to the player entity.
|
||||||
|
* @param target Pointer to the entity to interact with.
|
||||||
|
*/
|
||||||
|
void entityInteractWith(entity_t *player, entity_t *target);
|
||||||
@@ -43,12 +43,11 @@ void playerInput(entity_t *entity) {
|
|||||||
worldunits_t relX, relY;
|
worldunits_t relX, relY;
|
||||||
entityDirGetRelative(entity->direction, &relX, &relY);
|
entityDirGetRelative(entity->direction, &relX, &relY);
|
||||||
worldpos_t cur = fixedToWorldPos(entity->position);
|
worldpos_t cur = fixedToWorldPos(entity->position);
|
||||||
entity_t *interact = entityGetAt(
|
entity_t *target = entityGetAt(
|
||||||
(worldpos_t){ cur.x + relX, cur.y + relY, cur.z }
|
(worldpos_t){ cur.x + relX, cur.y + relY, cur.z }
|
||||||
);
|
);
|
||||||
if(interact != NULL && ENTITY_CALLBACKS[interact->type].interact != NULL) {
|
if(target == NULL) return;
|
||||||
if(ENTITY_CALLBACKS[interact->type].interact(entity, interact)) return;
|
entityInteractWith(entity, target);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
#include "rpgcamera.h"
|
#include "rpgcamera.h"
|
||||||
#include "rpgtextbox.h"
|
#include "rpgtextbox.h"
|
||||||
#include "util/memory.h"
|
#include "util/memory.h"
|
||||||
|
#include "util/string.h"
|
||||||
#include "assert/assert.h"
|
#include "assert/assert.h"
|
||||||
|
|
||||||
errorret_t rpgInit(void) {
|
errorret_t rpgInit(void) {
|
||||||
@@ -43,6 +44,8 @@ errorret_t rpgInit(void) {
|
|||||||
entity_t *npc = &ENTITIES[npcIndex];
|
entity_t *npc = &ENTITIES[npcIndex];
|
||||||
entityInit(npc, ENTITY_TYPE_NPC);
|
entityInit(npc, ENTITY_TYPE_NPC);
|
||||||
worldPosToFixed(&(worldpos_t){ 3, 3, 0 }, npc->position);
|
worldPosToFixed(&(worldpos_t){ 3, 3, 0 }, npc->position);
|
||||||
|
npc->interact.type = ENTITY_INTERACT_PRINT;
|
||||||
|
stringCopy(npc->interact.data.message, "hello world", 32);
|
||||||
|
|
||||||
// All Good!
|
// All Good!
|
||||||
errorOk();
|
errorOk();
|
||||||
|
|||||||
Reference in New Issue
Block a user