diff --git a/src/dusk/engine/engine.c b/src/dusk/engine/engine.c index 2fc084ec..a9cda295 100644 --- a/src/dusk/engine/engine.c +++ b/src/dusk/engine/engine.c @@ -56,7 +56,7 @@ errorret_t engineInit(const int32_t argc, const char_t **argv) { /* Run the init script. */ consolePrint("Engine initialized"); - sceneSet(SCENE_TYPE_INITIAL); + sceneSet(SCENE_TYPE_OVERWORLD); errorOk(); } diff --git a/src/dusk/entity/component/overworld/CMakeLists.txt b/src/dusk/entity/component/overworld/CMakeLists.txt index dab461f5..ed9e8864 100644 --- a/src/dusk/entity/component/overworld/CMakeLists.txt +++ b/src/dusk/entity/component/overworld/CMakeLists.txt @@ -8,5 +8,6 @@ target_sources(${DUSK_LIBRARY_TARGET_NAME} entityinteractable.c entityoverworld.c entityoverworldcamera.c + entityoverworldtrigger.c entityplayer.c ) diff --git a/src/dusk/entity/component/overworld/entityoverworldtrigger.c b/src/dusk/entity/component/overworld/entityoverworldtrigger.c new file mode 100644 index 00000000..1521724d --- /dev/null +++ b/src/dusk/entity/component/overworld/entityoverworldtrigger.c @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#include "entityoverworldtrigger.h" +#include "entity/entitymanager.h" +#include "entity/component/display/entityposition.h" + +static void entityOverworldTriggerUpdate( + const entityid_t entityId, + const componentid_t componentId, + void *user +) { + entityoverworldtrigger_t *t = entityOverworldTriggerGet(entityId, componentId); + + // Find the player position. + vec3 playerPos; + bool_t playerFound = false; + for(entityid_t i = 0; i < ENTITY_COUNT_MAX; i++) { + if((ENTITY_MANAGER.entities[i].state & ENTITY_STATE_ACTIVE) == 0) continue; + if(entityGetComponent(i, COMPONENT_TYPE_PLAYER) == COMPONENT_ID_INVALID) continue; + componentid_t posComp = entityGetComponent(i, COMPONENT_TYPE_POSITION); + if(posComp == COMPONENT_ID_INVALID) continue; + entityPositionGetWorldPosition(i, posComp, playerPos); + playerFound = true; + break; + } + + bool_t wasInside = t->playerInside; + bool_t nowInside = playerFound && ( + playerPos[0] >= t->min[0] && playerPos[0] <= t->max[0] && + playerPos[1] >= t->min[1] && playerPos[1] <= t->max[1] && + playerPos[2] >= t->min[2] && playerPos[2] <= t->max[2] + ); + t->playerInside = nowInside; + + if(nowInside) { + if(!wasInside && t->onEnter) t->onEnter(entityId, componentId, t->user); + if(t->onStay) t->onStay(entityId, componentId, t->user); + } else { + if(wasInside && t->onExit) t->onExit(entityId, componentId, t->user); + if(t->onOutside) t->onOutside(entityId, componentId, t->user); + } +} + +void entityOverworldTriggerInit( + const entityid_t entityId, + const componentid_t componentId +) { + entityoverworldtrigger_t *t = entityOverworldTriggerGet(entityId, componentId); + glm_vec3_zero(t->min); + glm_vec3_zero(t->max); + t->playerInside = false; + t->onEnter = NULL; + t->onExit = NULL; + t->onStay = NULL; + t->onOutside = NULL; + t->user = NULL; + entityUpdateAdd(entityId, entityOverworldTriggerUpdate, componentId, NULL); +} + +entityoverworldtrigger_t * entityOverworldTriggerGet( + const entityid_t entityId, + const componentid_t componentId +) { + return componentGetData( + entityId, componentId, COMPONENT_TYPE_OVERWORLD_TRIGGER + ); +} + +void entityOverworldTriggerSetBounds( + const entityid_t entityId, + const componentid_t componentId, + const vec3 min, + const vec3 max +) { + entityoverworldtrigger_t *t = entityOverworldTriggerGet(entityId, componentId); + glm_vec3_copy((float_t*)min, t->min); + glm_vec3_copy((float_t*)max, t->max); +} diff --git a/src/dusk/entity/component/overworld/entityoverworldtrigger.h b/src/dusk/entity/component/overworld/entityoverworldtrigger.h new file mode 100644 index 00000000..6f31178f --- /dev/null +++ b/src/dusk/entity/component/overworld/entityoverworldtrigger.h @@ -0,0 +1,54 @@ +/** + * Copyright (c) 2026 Dominic Masters + * + * This software is released under the MIT License. + * https://opensource.org/licenses/MIT + */ + +#pragma once +#include "entity/entitybase.h" + +typedef void (*entityoverworldtriggercallback_t)( + const entityid_t entityId, + const componentid_t componentId, + void *user +); + +typedef struct { + vec3 min; + vec3 max; + bool_t playerInside; + entityoverworldtriggercallback_t onEnter; + entityoverworldtriggercallback_t onExit; + entityoverworldtriggercallback_t onStay; + entityoverworldtriggercallback_t onOutside; + void *user; +} entityoverworldtrigger_t; + +/** + * Initializes the overworld trigger component and registers its update + * callback with the entity manager. The trigger is entirely self-contained + * after init — no scene-level wiring required. + */ +void entityOverworldTriggerInit( + const entityid_t entityId, + const componentid_t componentId +); + +/** + * Returns a pointer to the overworld trigger component data. + */ +entityoverworldtrigger_t * entityOverworldTriggerGet( + const entityid_t entityId, + const componentid_t componentId +); + +/** + * Sets the trigger AABB bounds. + */ +void entityOverworldTriggerSetBounds( + const entityid_t entityId, + const componentid_t componentId, + const vec3 min, + const vec3 max +); diff --git a/src/dusk/entity/componentlist.h b/src/dusk/entity/componentlist.h index 80075a5b..fbf30ebf 100644 --- a/src/dusk/entity/componentlist.h +++ b/src/dusk/entity/componentlist.h @@ -11,6 +11,7 @@ #include "entity/component/physics/entityphysics.h" #include "entity/component/trigger/entitytrigger.h" #include "entity/component/overworld/entityoverworld.h" +#include "entity/component/overworld/entityoverworldtrigger.h" #include "entity/component/overworld/entityplayer.h" #include "entity/component/overworld/entityinteractable.h" #include "entity/component/overworld/entityoverworldcamera.h" @@ -31,3 +32,4 @@ X(OVERWORLD, entityoverworld_t, overworld, entityOverworldInit, NULL, NULL) X(PLAYER, entityplayer_t, player, entityPlayerInit, NULL, NULL) X(INTERACTABLE, entityinteractable_t, interactable, entityInteractableInit, NULL, NULL) X(OVERWORLD_CAMERA, entityoverworldcamera_t, overworldCamera, entityOverworldCameraInit, NULL, entityOverworldCameraRender) +X(OVERWORLD_TRIGGER, entityoverworldtrigger_t, overworldTrigger, entityOverworldTriggerInit, NULL, NULL) diff --git a/src/dusk/scene/overworld/overworldscene.c b/src/dusk/scene/overworld/overworldscene.c index 80a27498..284220b1 100644 --- a/src/dusk/scene/overworld/overworldscene.c +++ b/src/dusk/scene/overworld/overworldscene.c @@ -15,6 +15,7 @@ #include "display/shader/shaderlist.h" #include "entity/component/overworld/entityinteractable.h" #include "entity/component/overworld/entityoverworldcamera.h" +#include "entity/component/overworld/entityoverworldtrigger.h" #include "display/mesh/cube.h" #include "display/mesh/plane.h" #include "display/displaystate.h" @@ -23,6 +24,22 @@ #define OVERWORLD (SCENE.data.overworld) +static void overworldSceneTestTriggerEnter( + const entityid_t entityId, + const componentid_t componentId, + void *user +) { + consolePrint("Test trigger: player entered"); +} + +static void overworldSceneTestTriggerExit( + const entityid_t entityId, + const componentid_t componentId, + void *user +) { + consolePrint("Test trigger: player exited"); +} + static void overworldSceneNpcInteract( const entityid_t entityId, const componentid_t componentId, @@ -118,6 +135,21 @@ void overworldSceneInit(void) { OVERWORLD.npc.entityId, OVERWORLD.npc.interactableCompId, overworldSceneNpcInteract, NULL ); + + OVERWORLD.testTriggerId = entityManagerAdd(); + OVERWORLD.testTriggerCompId = entityAddComponent( + OVERWORLD.testTriggerId, COMPONENT_TYPE_OVERWORLD_TRIGGER + ); + entityOverworldTriggerSetBounds( + OVERWORLD.testTriggerId, OVERWORLD.testTriggerCompId, + (vec3){ -2.0f, -1.0f, -2.0f }, + (vec3){ 2.0f, 1.0f, 2.0f } + ); + entityoverworldtrigger_t *testTrigger = entityOverworldTriggerGet( + OVERWORLD.testTriggerId, OVERWORLD.testTriggerCompId + ); + testTrigger->onEnter = overworldSceneTestTriggerEnter; + testTrigger->onExit = overworldSceneTestTriggerExit; } errorret_t overworldSceneUpdate(void) { diff --git a/src/dusk/scene/overworld/overworldscene.h b/src/dusk/scene/overworld/overworldscene.h index 2bb7e7fe..048fdfba 100644 --- a/src/dusk/scene/overworld/overworldscene.h +++ b/src/dusk/scene/overworld/overworldscene.h @@ -21,6 +21,8 @@ typedef struct { overworldplayer_t player; overworldground_t ground; overworldnpc_t npc; + entityid_t testTriggerId; + componentid_t testTriggerCompId; } overworldscene_t; /**