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,
"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",

View File

@ -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",

View File

@ -176,7 +176,8 @@
"speaker": "Ghost",
"portrait": "resources/ghost_avatar.png",
"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)
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!")

View File

@ -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;

View File

@ -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<int>(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<int>(delta), player->position);
}
//if (player) {
// dialogueSystem.update(static_cast<int>(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<int>(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<int>(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) {

View File

@ -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;

View File

@ -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;

View File

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

View File

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

View File

@ -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;

View File

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