This commit is contained in:
Vladislav Khorev 2026-04-16 13:24:04 +03:00
commit cc2eba1352
12 changed files with 79 additions and 32 deletions

View File

@ -15,6 +15,7 @@
"modelCorrectionRotX": 0.0, "modelCorrectionRotX": 0.0,
"modelCorrectionRotY": 180.0, "modelCorrectionRotY": 180.0,
"modelCorrectionRotZ": 0.0, "modelCorrectionRotZ": 0.0,
"interactionRadius": 2.0,
"gift": { "gift": {
"id": "guard_token", "id": "guard_token",
"name": "Guard's Token", "name": "Guard's Token",
@ -37,6 +38,7 @@
"modelCorrectionRotX": 0.0, "modelCorrectionRotX": 0.0,
"modelCorrectionRotY": 0.0, "modelCorrectionRotY": 0.0,
"modelCorrectionRotZ": 0.0, "modelCorrectionRotZ": 0.0,
"interactionRadius": 1.0,
"gift": { "gift": {
"id": "ghost_essence", "id": "ghost_essence",
"name": "Ghost's Essence", "name": "Ghost's Essence",

View File

@ -26,18 +26,25 @@
{ {
"type": "FrameLayout", "type": "FrameLayout",
"name": "inventory_items_panel", "name": "inventory_items_panel",
"x": 100.0, "x": 50.0,
"y": 150.0, "y": 150.0,
"width": 500.0, "width": 250.0,
"height": 600.0, "height": 300.0,
"children": [ "children": [
{
"type": "StaticImage",
"name": "panel_background",
"width": 200,
"height": 400,
"texture": "resources/sand2.png"
},
{ {
"type": "TextView", "type": "TextView",
"name": "inventory_items_text", "name": "inventory_items_text",
"x": 100.0, "x": -100.0,
"y": 30.0, "y": -100.0,
"width": 460.0, "width": 250.0,
"height": 450.0, "height": 300.0,
"text": "Inventory (Empty)", "text": "Inventory (Empty)",
"fontSize": 18, "fontSize": 18,
"fontPath": "resources/fonts/DroidSans.ttf", "fontPath": "resources/fonts/DroidSans.ttf",
@ -47,8 +54,8 @@
{ {
"type": "TextButton", "type": "TextButton",
"name": "close_inventory_button", "name": "close_inventory_button",
"x": 200.0, "x": 165.0,
"y": 20.0, "y": 0.0,
"width": 40.0, "width": 40.0,
"height": 40.0, "height": 40.0,
"text": "X", "text": "X",

View File

@ -176,7 +176,8 @@
"speaker": "Ghost", "speaker": "Ghost",
"portrait": "resources/ghost_avatar.png", "portrait": "resources/ghost_avatar.png",
"text": "Some memories never fade.", "text": "Some memories never fade.",
"durationMs": 2600 "durationMs": 2600,
"background": "resources/loading.png"
} }
] ]
} }

View File

@ -32,7 +32,12 @@ end
function on_npc_interact(npc_index) function on_npc_interact(npc_index)
print("[Lua] NPC interaction! Index: " .. tostring(npc_index)) print("[Lua] NPC interaction! Index: " .. tostring(npc_index))
if npc_index == 1 then
game_api.start_dialogue("test_line_dialogue")
else
game_api.receive_npc_gift(npc_index) game_api.receive_npc_gift(npc_index)
end end
end
print("Lua script loaded successfully!") print("Lua script loaded successfully!")

View File

@ -60,6 +60,7 @@ public:
std::string npcName; std::string npcName;
bool giftReceived = false; bool giftReceived = false;
int battle_state = 0; int battle_state = 0;
bool resetAnim = false; bool resetAnim = false;
int attack = 0; int attack = 0;
@ -70,6 +71,9 @@ public:
bool isPlayer = false; bool isPlayer = false;
bool useGpuSkinning = true; bool useGpuSkinning = true;
float interactionRadius = 0.0f;
private: private:
struct AnimationData { struct AnimationData {
BoneSystem model; BoneSystem model;

View File

@ -275,14 +275,14 @@ namespace ZL
dialogueSystem.init(renderer, CONST_ZIP_FILE); dialogueSystem.init(renderer, CONST_ZIP_FILE);
dialogueSystem.loadDatabase("resources/dialogue/sample_dialogues.json"); dialogueSystem.loadDatabase("resources/dialogue/sample_dialogues.json");
dialogueSystem.addTriggerZone({ /*dialogueSystem.addTriggerZone({
"ghost_room_trigger", "ghost_room_trigger",
"test_line_dialogue", "test_line_dialogue",
Eigen::Vector3f(0.0f, 0.0f, -8.5f), Eigen::Vector3f(0.0f, 0.0f, -8.5f),
2.0f, 2.0f,
true, true,
false false
}); });*/
scriptEngine.init(this); scriptEngine.init(this);
@ -773,7 +773,11 @@ namespace ZL
lastTickCount = newTickCount; lastTickCount = newTickCount;
if (player) player->update(delta); //if (player) player->update(delta);
if (player) {
player->update(delta);
dialogueSystem.update(static_cast<int>(delta), player->position);
}
for (auto& npc : npcs) npc->update(delta); for (auto& npc : npcs) npc->update(delta);
@ -806,9 +810,9 @@ namespace ZL
} }
//for (auto& npc : npcs) npc->update(delta); //for (auto& npc : npcs) npc->update(delta);
if (player) { //if (player) {
dialogueSystem.update(static_cast<int>(delta), player->position); // dialogueSystem.update(static_cast<int>(delta), player->position);
} //}
} }
// Some AI stuff // Some AI stuff
@ -904,6 +908,10 @@ namespace ZL
handleDown(ZL::UiManager::MOUSE_FINGER_ID, mx, my); handleDown(ZL::UiManager::MOUSE_FINGER_ID, mx, my);
player->attackTarget = nullptr; 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 // Calculate ray for picking
if (dialogueSystem.blocksGameplayInput()) { if (dialogueSystem.blocksGameplayInput()) {
@ -948,6 +956,8 @@ namespace ZL
// Check if we clicked on an NPC // Check if we clicked on an NPC
Character* clickedNpc = raycastNpcs(camPos, rayDir); Character* clickedNpc = raycastNpcs(camPos, rayDir);
if (clickedNpc && player) { if (clickedNpc && player) {
float distance = (player->position - clickedNpc->position).norm();
if (distance <= clickedNpc->interactionRadius) {
int npcIndex = -1; int npcIndex = -1;
for (size_t i = 0; i < npcs.size(); ++i) { for (size_t i = 0; i < npcs.size(); ++i) {
if (npcs[i].get() == clickedNpc) { if (npcs[i].get() == clickedNpc) {
@ -963,7 +973,11 @@ namespace ZL
{ {
player->attackTarget = clickedNpc; player->attackTarget = clickedNpc;
} }
}
}
else {
std::cout << "[CLICK] Too far from NPC (distance " << distance
<< " > " << clickedNpc->interactionRadius << ")" << std::endl;
} }
} }
else if (rayDir.y() < -0.001f && player) { else if (rayDir.y() < -0.001f && player) {

View File

@ -121,6 +121,7 @@ CutsceneLine DialogueDatabase::parseCutsceneLine(const json& j) {
line.text = j.value("text", ""); line.text = j.value("text", "");
line.portrait = j.value("portrait", ""); line.portrait = j.value("portrait", "");
line.sfx = j.value("sfx", ""); line.sfx = j.value("sfx", "");
line.background = j.value("background", "");
line.durationMs = j.value("durationMs", 0); line.durationMs = j.value("durationMs", 0);
line.waitForConfirm = j.value("waitForConfirm", false); line.waitForConfirm = j.value("waitForConfirm", false);
return line; return line;

View File

@ -325,6 +325,7 @@ void DialogueRuntime::startCutscene(const std::string& cutsceneId, const std::st
activeCutscene = cutscene; activeCutscene = cutscene;
pendingNodeAfterCutscene = nextNodeAfterCutscene; pendingNodeAfterCutscene = nextNodeAfterCutscene;
currentCutsceneBackground = cutscene->background;
mode = Mode::PlayingCutscene; mode = Mode::PlayingCutscene;
currentCutsceneLine = -1; currentCutsceneLine = -1;
cutsceneTimerMs = 0; cutsceneTimerMs = 0;
@ -363,12 +364,18 @@ void DialogueRuntime::refreshCutscenePresentation() {
} }
const CutsceneLine& line = activeCutscene->lines[currentCutsceneLine]; const CutsceneLine& line = activeCutscene->lines[currentCutsceneLine];
if (!line.background.empty()) {
currentCutsceneBackground = line.background;
}
presentation.mode = PresentationMode::Cutscene; presentation.mode = PresentationMode::Cutscene;
presentation.speaker = line.speaker; presentation.speaker = line.speaker;
presentation.fullText = line.text; presentation.fullText = line.text;
presentation.visibleText = line.text; presentation.visibleText = line.text;
presentation.portraitPath = line.portrait; presentation.portraitPath = line.portrait;
presentation.backgroundPath = activeCutscene->background; //presentation.backgroundPath = activeCutscene->background;
presentation.backgroundPath = currentCutsceneBackground;
presentation.choices.clear(); presentation.choices.clear();
presentation.selectedChoice = 0; presentation.selectedChoice = 0;
presentation.revealCompleted = true; presentation.revealCompleted = true;

View File

@ -64,6 +64,8 @@ private:
int currentCutsceneLine = -1; int currentCutsceneLine = -1;
int cutsceneTimerMs = 0; int cutsceneTimerMs = 0;
std::string currentCutsceneBackground;
bool evaluateConditions(const std::vector<Condition>& conditions) const; bool evaluateConditions(const std::vector<Condition>& conditions) const;
void applyEffects(const std::vector<Effect>& effects); void applyEffects(const std::vector<Effect>& effects);

View File

@ -87,6 +87,7 @@ struct CutsceneLine {
std::string text; std::string text;
std::string portrait; std::string portrait;
std::string sfx; std::string sfx;
std::string background;
int durationMs = 0; int durationMs = 0;
bool waitForConfirm = false; bool waitForConfirm = false;
}; };

View File

@ -280,6 +280,7 @@ namespace ZL {
data.id = item.value("id", "npc_unknown"); data.id = item.value("id", "npc_unknown");
data.name = item.value("name", "Unknown NPC"); data.name = item.value("name", "Unknown NPC");
data.texturePath = item.value("texturePath", ""); data.texturePath = item.value("texturePath", "");
data.interactionRadius = item.value("interactionRadius", 0.0f);
data.animationIdlePath = item.value("animationIdlePath", ""); data.animationIdlePath = item.value("animationIdlePath", "");
data.animationWalkPath = item.value("animationWalkPath", ""); data.animationWalkPath = item.value("animationWalkPath", "");
@ -379,6 +380,7 @@ namespace ZL {
npc->rotationSpeed = npcData.rotationSpeed; npc->rotationSpeed = npcData.rotationSpeed;
npc->modelScale = npcData.modelScale; npc->modelScale = npcData.modelScale;
npc->position = Eigen::Vector3f(npcData.positionX, npcData.positionY, npcData.positionZ); npc->position = Eigen::Vector3f(npcData.positionX, npcData.positionY, npcData.positionZ);
npc->interactionRadius = npcData.interactionRadius;
// Set NPC metadata // Set NPC metadata
npc->npcId = npcData.id; npc->npcId = npcData.id;

View File

@ -57,6 +57,7 @@ namespace ZL {
float modelCorrectionRotY = 0.0f; float modelCorrectionRotY = 0.0f;
float modelCorrectionRotZ = 0.0f; float modelCorrectionRotZ = 0.0f;
GiftData gift; GiftData gift;
float interactionRadius = 0.0f;
}; };
struct LoadedGameObject { struct LoadedGameObject {