diff --git a/resources/config2/npcs.json b/resources/config2/npcs.json index 291d783..39c26e7 100644 --- a/resources/config2/npcs.json +++ b/resources/config2/npcs.json @@ -15,6 +15,7 @@ "modelCorrectionRotX": 0.0, "modelCorrectionRotY": 180.0, "modelCorrectionRotZ": 0.0, + "interactionRadius": 2.0, "gift": { "id": "guard_token", "name": "Guard's Token", @@ -37,6 +38,7 @@ "modelCorrectionRotX": 0.0, "modelCorrectionRotY": 0.0, "modelCorrectionRotZ": 0.0, + "interactionRadius": 1.0, "gift": { "id": "ghost_essence", "name": "Ghost's Essence", diff --git a/resources/config2/ui_inventory.json b/resources/config2/ui_inventory.json index 5f2a167..80f9500 100644 --- a/resources/config2/ui_inventory.json +++ b/resources/config2/ui_inventory.json @@ -26,18 +26,25 @@ { "type": "FrameLayout", "name": "inventory_items_panel", - "x": 100.0, + "x": 50.0, "y": 150.0, - "width": 500.0, - "height": 600.0, + "width": 250.0, + "height": 300.0, "children": [ + { + "type": "StaticImage", + "name": "panel_background", + "width": 200, + "height": 400, + "texture": "resources/sand2.png" + }, { "type": "TextView", "name": "inventory_items_text", - "x": 100.0, - "y": 30.0, - "width": 460.0, - "height": 450.0, + "x": -100.0, + "y": -100.0, + "width": 250.0, + "height": 300.0, "text": "Inventory (Empty)", "fontSize": 18, "fontPath": "resources/fonts/DroidSans.ttf", @@ -47,8 +54,8 @@ { "type": "TextButton", "name": "close_inventory_button", - "x": 200.0, - "y": 20.0, + "x": 165.0, + "y": 0.0, "width": 40.0, "height": 40.0, "text": "X", diff --git a/resources/dialogue/sample_dialogues.json b/resources/dialogue/sample_dialogues.json index 7c5f018..3e5c7e0 100644 --- a/resources/dialogue/sample_dialogues.json +++ b/resources/dialogue/sample_dialogues.json @@ -176,7 +176,8 @@ "speaker": "Ghost", "portrait": "resources/ghost_avatar.png", "text": "Some memories never fade.", - "durationMs": 2600 + "durationMs": 2600, + "background": "resources/loading.png" } ] } diff --git a/resources/start.lua b/resources/start.lua index 6135227..168b3fe 100644 --- a/resources/start.lua +++ b/resources/start.lua @@ -32,7 +32,12 @@ end function on_npc_interact(npc_index) print("[Lua] NPC interaction! Index: " .. tostring(npc_index)) - game_api.receive_npc_gift(npc_index) + + if npc_index == 1 then + game_api.start_dialogue("test_line_dialogue") + else + game_api.receive_npc_gift(npc_index) + end end print("Lua script loaded successfully!") \ No newline at end of file diff --git a/src/Character.h b/src/Character.h index 578fd0a..52d0f55 100644 --- a/src/Character.h +++ b/src/Character.h @@ -60,6 +60,7 @@ public: std::string npcName; bool giftReceived = false; + int battle_state = 0; bool resetAnim = false; int attack = 0; @@ -70,6 +71,9 @@ public: bool isPlayer = false; bool useGpuSkinning = true; + float interactionRadius = 0.0f; + + private: struct AnimationData { BoneSystem model; diff --git a/src/Game.cpp b/src/Game.cpp index b4ca16e..0b8b000 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -275,14 +275,14 @@ namespace ZL dialogueSystem.init(renderer, CONST_ZIP_FILE); dialogueSystem.loadDatabase("resources/dialogue/sample_dialogues.json"); - dialogueSystem.addTriggerZone({ + /*dialogueSystem.addTriggerZone({ "ghost_room_trigger", "test_line_dialogue", Eigen::Vector3f(0.0f, 0.0f, -8.5f), 2.0f, true, false - }); + });*/ scriptEngine.init(this); @@ -773,7 +773,11 @@ namespace ZL lastTickCount = newTickCount; - if (player) player->update(delta); + //if (player) player->update(delta); + if (player) { + player->update(delta); + dialogueSystem.update(static_cast(delta), player->position); + } for (auto& npc : npcs) npc->update(delta); @@ -806,9 +810,9 @@ namespace ZL } //for (auto& npc : npcs) npc->update(delta); - if (player) { - dialogueSystem.update(static_cast(delta), player->position); - } + //if (player) { + // dialogueSystem.update(static_cast(delta), player->position); + //} } // Some AI stuff @@ -904,6 +908,10 @@ namespace ZL handleDown(ZL::UiManager::MOUSE_FINGER_ID, mx, my); player->attackTarget = nullptr; + if (menuManager.uiManager.isUiInteractionForFinger(ZL::UiManager::MOUSE_FINGER_ID)) { + std::cout << "[CLICK] UI handled, skipping character movement" << std::endl; + continue; + } // Calculate ray for picking if (dialogueSystem.blocksGameplayInput()) { @@ -948,22 +956,28 @@ namespace ZL // Check if we clicked on an NPC Character* clickedNpc = raycastNpcs(camPos, rayDir); if (clickedNpc && player) { - int npcIndex = -1; - for (size_t i = 0; i < npcs.size(); ++i) { - if (npcs[i].get() == clickedNpc) { - npcIndex = static_cast(i); - break; + float distance = (player->position - clickedNpc->position).norm(); + if (distance <= clickedNpc->interactionRadius) { + int npcIndex = -1; + for (size_t i = 0; i < npcs.size(); ++i) { + if (npcs[i].get() == clickedNpc) { + npcIndex = static_cast(i); + break; + } + } + if (npcIndex != -1) { + std::cout << "[CLICK] *** SUCCESS: Clicked on NPC index: " << npcIndex << " ***" << std::endl; + scriptEngine.callNpcInteractCallback(npcIndex); + + if (clickedNpc->canAttack) + { + player->attackTarget = clickedNpc; + } } } - if (npcIndex != -1) { - std::cout << "[CLICK] *** SUCCESS: Clicked on NPC index: " << npcIndex << " ***" << std::endl; - scriptEngine.callNpcInteractCallback(npcIndex); - - if (clickedNpc->canAttack) - { - player->attackTarget = clickedNpc; - } - + else { + std::cout << "[CLICK] Too far from NPC (distance " << distance + << " > " << clickedNpc->interactionRadius << ")" << std::endl; } } else if (rayDir.y() < -0.001f && player) { diff --git a/src/dialogue/DialogueDatabase.cpp b/src/dialogue/DialogueDatabase.cpp index 77177a3..07f17b2 100644 --- a/src/dialogue/DialogueDatabase.cpp +++ b/src/dialogue/DialogueDatabase.cpp @@ -121,6 +121,7 @@ CutsceneLine DialogueDatabase::parseCutsceneLine(const json& j) { line.text = j.value("text", ""); line.portrait = j.value("portrait", ""); line.sfx = j.value("sfx", ""); + line.background = j.value("background", ""); line.durationMs = j.value("durationMs", 0); line.waitForConfirm = j.value("waitForConfirm", false); return line; diff --git a/src/dialogue/DialogueRuntime.cpp b/src/dialogue/DialogueRuntime.cpp index e7307a2..32fccf1 100644 --- a/src/dialogue/DialogueRuntime.cpp +++ b/src/dialogue/DialogueRuntime.cpp @@ -325,6 +325,7 @@ void DialogueRuntime::startCutscene(const std::string& cutsceneId, const std::st activeCutscene = cutscene; pendingNodeAfterCutscene = nextNodeAfterCutscene; + currentCutsceneBackground = cutscene->background; mode = Mode::PlayingCutscene; currentCutsceneLine = -1; cutsceneTimerMs = 0; @@ -363,12 +364,18 @@ void DialogueRuntime::refreshCutscenePresentation() { } const CutsceneLine& line = activeCutscene->lines[currentCutsceneLine]; + + if (!line.background.empty()) { + currentCutsceneBackground = line.background; + } + presentation.mode = PresentationMode::Cutscene; presentation.speaker = line.speaker; presentation.fullText = line.text; presentation.visibleText = line.text; presentation.portraitPath = line.portrait; - presentation.backgroundPath = activeCutscene->background; + //presentation.backgroundPath = activeCutscene->background; + presentation.backgroundPath = currentCutsceneBackground; presentation.choices.clear(); presentation.selectedChoice = 0; presentation.revealCompleted = true; diff --git a/src/dialogue/DialogueRuntime.h b/src/dialogue/DialogueRuntime.h index f810834..031e9ae 100644 --- a/src/dialogue/DialogueRuntime.h +++ b/src/dialogue/DialogueRuntime.h @@ -64,6 +64,8 @@ private: int currentCutsceneLine = -1; int cutsceneTimerMs = 0; + std::string currentCutsceneBackground; + bool evaluateConditions(const std::vector& conditions) const; void applyEffects(const std::vector& effects); diff --git a/src/dialogue/DialogueTypes.h b/src/dialogue/DialogueTypes.h index 76cd925..0b6bd8b 100644 --- a/src/dialogue/DialogueTypes.h +++ b/src/dialogue/DialogueTypes.h @@ -87,6 +87,7 @@ struct CutsceneLine { std::string text; std::string portrait; std::string sfx; + std::string background; int durationMs = 0; bool waitForConfirm = false; }; diff --git a/src/items/GameObjectLoader.cpp b/src/items/GameObjectLoader.cpp index e64701d..b19044b 100644 --- a/src/items/GameObjectLoader.cpp +++ b/src/items/GameObjectLoader.cpp @@ -280,6 +280,7 @@ namespace ZL { data.id = item.value("id", "npc_unknown"); data.name = item.value("name", "Unknown NPC"); data.texturePath = item.value("texturePath", ""); + data.interactionRadius = item.value("interactionRadius", 0.0f); data.animationIdlePath = item.value("animationIdlePath", ""); data.animationWalkPath = item.value("animationWalkPath", ""); @@ -379,6 +380,7 @@ namespace ZL { npc->rotationSpeed = npcData.rotationSpeed; npc->modelScale = npcData.modelScale; npc->position = Eigen::Vector3f(npcData.positionX, npcData.positionY, npcData.positionZ); + npc->interactionRadius = npcData.interactionRadius; // Set NPC metadata npc->npcId = npcData.id; diff --git a/src/items/GameObjectLoader.h b/src/items/GameObjectLoader.h index 575dd00..72be42d 100644 --- a/src/items/GameObjectLoader.h +++ b/src/items/GameObjectLoader.h @@ -57,6 +57,7 @@ namespace ZL { float modelCorrectionRotY = 0.0f; float modelCorrectionRotZ = 0.0f; GiftData gift; + float interactionRadius = 0.0f; }; struct LoadedGameObject {