Dialogue uses arrays
This commit is contained in:
@@ -17,10 +17,10 @@
|
||||
* Only active in game mode (GamePlayState::Playing).
|
||||
*
|
||||
* Event payload (EventParams) parameters:
|
||||
* "text" (string) - Narration text to display
|
||||
* "choices" (string) - Comma-separated list of choice labels
|
||||
* "speaker" (string) - Optional speaker name
|
||||
* "auto_progress" (int) - If 1, clicking anywhere progresses (no choices)
|
||||
* "text" (string) - Narration text to display
|
||||
* "choices" (string_array) - Array of choice label strings (Lua table)
|
||||
* "speaker" (string) - Optional speaker name
|
||||
* "auto_progress" (int) - If 1, clicking anywhere progresses (no choices)
|
||||
*
|
||||
* Component state transitions:
|
||||
* Idle -> Showing (on show() or event)
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
-- Event payload parameters:
|
||||
-- "text" (string) - Narration text to display
|
||||
-- "speaker" (string) - Optional speaker name (shown above text)
|
||||
-- "choices" (string) - Comma-separated choice labels (optional)
|
||||
-- "auto_progress" (int) - If 1, click anywhere progresses (no choices)
|
||||
-- "choices" (table) - Array of choice label strings (optional)
|
||||
-- =============================================================================
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
@@ -55,13 +54,13 @@ print("Sent basic narration dialogue")
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- 3. Show dialogue with player choices
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- When "choices" is provided (comma-separated), the dialogue box shows
|
||||
-- When "choices" is provided as a table, the dialogue box shows
|
||||
-- buttons instead of click-to-progress. The player must pick one.
|
||||
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "Where would you like to go?",
|
||||
speaker = "Guide",
|
||||
choices = "The Forest,The Village,The Mountains"
|
||||
choices = { "The Forest", "The Village", "The Mountains" }
|
||||
})
|
||||
|
||||
print("Sent dialogue with choices")
|
||||
@@ -92,10 +91,10 @@ print("Sent multi-line dialogue")
|
||||
-- =============================================================================
|
||||
-- To show dialogue from Lua:
|
||||
-- 1. Ensure an entity with DialogueComponent exists (create one if needed)
|
||||
-- 2. Call ecs.send_event("dialogue_show", { text = "...", speaker = "...", choices = "..." })
|
||||
-- 2. Call ecs.send_event("dialogue_show", { text = "...", speaker = "...", choices = { ... } })
|
||||
-- 3. Required: text = "The narration text"
|
||||
-- 4. Optional: speaker = "Speaker Name"
|
||||
-- 5. Optional: choices = "Choice1,Choice2,Choice3" (comma-separated)
|
||||
-- 5. Optional: choices = { "Choice1", "Choice2", "Choice3" } (table of strings)
|
||||
-- 6. EventParams uses flat key-value pairs (no nested stringValues/floatValues/etc.)
|
||||
-- 7. Type metadata is available via params._types table
|
||||
-- =============================================================================
|
||||
|
||||
@@ -180,7 +180,6 @@ update_npc_dialogue(guard, "At ease, friend. The town is safe with you around.")
|
||||
|
||||
function show_dialogue_with_dynamic_choices(npc_entity, base_text, choice_list)
|
||||
-- choice_list is a table of strings
|
||||
local choices_str = table.concat(choice_list, ",")
|
||||
|
||||
-- Update the component
|
||||
ecs.set_field(npc_entity, "Dialogue", "text", base_text)
|
||||
@@ -189,7 +188,7 @@ function show_dialogue_with_dynamic_choices(npc_entity, base_text, choice_list)
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = base_text,
|
||||
speaker = ecs.get_field(npc_entity, "Dialogue", "speaker"),
|
||||
choices = choices_str
|
||||
choices = choice_list
|
||||
})
|
||||
end
|
||||
|
||||
@@ -210,7 +209,7 @@ show_dialogue_with_dynamic_choices(merchant, "What would you like to buy?", shop
|
||||
--
|
||||
-- EventBus (ecs.send_event "dialogue_show"):
|
||||
-- - Triggers proper state transitions
|
||||
-- - Parses choices from comma-separated string
|
||||
-- - Parses choices from table of strings
|
||||
-- - Best for showing dialogue to the player
|
||||
--
|
||||
-- Best practice: Use the EventBus to SHOW dialogue, and the component API
|
||||
|
||||
@@ -87,7 +87,7 @@ function on_player_near_npc(npc_name, distance)
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "Hello there! I have a quest for a brave adventurer.",
|
||||
speaker = npc_name,
|
||||
choices = "I'll help!,What's the reward?,Not interested"
|
||||
choices = { "I'll help!", "What's the reward?", "Not interested" }
|
||||
})
|
||||
end
|
||||
end
|
||||
@@ -119,14 +119,14 @@ local choice_sub = ecs.subscribe_event("dialogue_choice", function(event, params
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "Excellent! The ancient artifact was stolen from the temple.\nBring it back and you'll be richly rewarded!",
|
||||
speaker = "QuestGiver",
|
||||
choices = "Where is the temple?,I'm on it!,Tell me more"
|
||||
choices = { "Where is the temple?", "I'm on it!", "Tell me more" }
|
||||
})
|
||||
|
||||
elseif choice_text == "What's the reward?" then
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "100 gold pieces and a magical amulet! What do you say?",
|
||||
speaker = "QuestGiver",
|
||||
choices = "I'll help!,Sounds good,Maybe later"
|
||||
choices = { "I'll help!", "Sounds good", "Maybe later" }
|
||||
})
|
||||
|
||||
elseif choice_text == "Not interested" then
|
||||
|
||||
@@ -74,12 +74,12 @@ print("Subscribed to dialogue_dismiss events (ID: " .. dismiss_sub .. ")")
|
||||
local show_sub = ecs.subscribe_event("dialogue_show", function(event, params)
|
||||
local text = params.text or ""
|
||||
local speaker = params.speaker or "Unknown"
|
||||
local choices = params.choices or ""
|
||||
local choices = params.choices or {}
|
||||
|
||||
print("[Dialogue Log] " .. speaker .. ": \"" .. text .. "\"")
|
||||
|
||||
if choices ~= "" then
|
||||
print("[Dialogue Log] Choices: " .. choices)
|
||||
if #choices > 0 then
|
||||
print("[Dialogue Log] Choices: " .. table.concat(choices, ", "))
|
||||
end
|
||||
end)
|
||||
|
||||
@@ -95,7 +95,7 @@ function show_branching_dialogue()
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "You see a dark cave entrance. What do you do?",
|
||||
speaker = "Narrator",
|
||||
choices = "Enter the cave,Look around first,Leave"
|
||||
choices = { "Enter the cave", "Look around first", "Leave" }
|
||||
})
|
||||
|
||||
-- Step 2: The choice will be handled by our subscriber above.
|
||||
@@ -114,7 +114,7 @@ function npc_greeting(npc_name, greeting_text)
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = greeting_text,
|
||||
speaker = npc_name,
|
||||
choices = "Who are you?,Tell me about this place,Goodbye"
|
||||
choices = { "Who are you?", "Tell me about this place", "Goodbye" }
|
||||
})
|
||||
|
||||
-- The choice subscriber will handle the response.
|
||||
|
||||
@@ -56,14 +56,14 @@ end)
|
||||
--- Show a line of dialogue and wait for the player to respond.
|
||||
--- @param text string The narration text
|
||||
--- @param speaker string|nil Optional speaker name
|
||||
--- @param choices string|nil Comma-separated choices (nil = click to dismiss)
|
||||
--- @param choices table|nil Array of choice label strings (nil = click to dismiss)
|
||||
--- @return number choice_index (0 if dismissed, 1+ for choices)
|
||||
function show_and_wait(text, speaker, choices)
|
||||
-- Send the dialogue event
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = text,
|
||||
speaker = speaker or "",
|
||||
choices = choices or ""
|
||||
choices = choices or {}
|
||||
})
|
||||
|
||||
-- Wait for player response
|
||||
@@ -106,7 +106,7 @@ function simple_conversation()
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "I've been expecting you. The darkness grows stronger each day.",
|
||||
speaker = "Old Man",
|
||||
choices = "Tell me more,How can I help?,I must go"
|
||||
choices = { "Tell me more", "How can I help?", "I must go" }
|
||||
})
|
||||
|
||||
print(" (Player would now see choices and pick one)")
|
||||
@@ -212,23 +212,21 @@ function run_conversation(tree, start_node)
|
||||
break
|
||||
end
|
||||
|
||||
-- Build choices string from the node's choices table
|
||||
local choices_str = ""
|
||||
-- Build choices table from the node's choices
|
||||
local choices = {}
|
||||
local choice_map = {}
|
||||
if node.choices then
|
||||
local parts = {}
|
||||
for i, choice in ipairs(node.choices) do
|
||||
table.insert(parts, choice.text)
|
||||
table.insert(choices, choice.text)
|
||||
choice_map[i] = choice
|
||||
end
|
||||
choices_str = table.concat(parts, ",")
|
||||
end
|
||||
|
||||
-- Show the dialogue
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = node.text,
|
||||
speaker = node.speaker or "",
|
||||
choices = choices_str
|
||||
choices = choices
|
||||
})
|
||||
|
||||
-- In a real game, you'd wait for the player's choice here.
|
||||
@@ -272,7 +270,7 @@ function talk_to_elder_marcus()
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "Ah, a new face! I am Elder Marcus, keeper of this village.\nIt's been so long since we had visitors.",
|
||||
speaker = "Elder Marcus",
|
||||
choices = "Pleasure to meet you,I've heard stories about you,Hello"
|
||||
choices = { "Pleasure to meet you", "I've heard stories about you", "Hello" }
|
||||
})
|
||||
elseif npc_state.quest_active and npc_state.quest_completed then
|
||||
-- Quest completed
|
||||
@@ -281,21 +279,21 @@ function talk_to_elder_marcus()
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "You did it! The village is safe thanks to you.\nPlease, take this reward.",
|
||||
speaker = "Elder Marcus",
|
||||
choices = "Thank you, elder,I was happy to help"
|
||||
choices = { "Thank you, elder", "I was happy to help" }
|
||||
})
|
||||
elseif npc_state.quest_active then
|
||||
-- Quest in progress
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "Have you dealt with those bandits yet?\nThe villagers are growing anxious.",
|
||||
speaker = "Elder Marcus",
|
||||
choices = "I'm working on it,I need more information,Not yet"
|
||||
choices = { "I'm working on it", "I need more information", "Not yet" }
|
||||
})
|
||||
else
|
||||
-- Regular greeting
|
||||
ecs.send_event("dialogue_show", {
|
||||
text = "Welcome back, friend. The village is peaceful today.",
|
||||
speaker = "Elder Marcus",
|
||||
choices = "Any news?,I need supplies,Goodbye"
|
||||
choices = { "Any news?", "I need supplies", "Goodbye" }
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1251,7 +1251,8 @@ static void registerAllComponents()
|
||||
lua_pushstring(L, c.text.c_str());
|
||||
lua_setfield(L, -2, "text");
|
||||
lua_pushstring(L, c.speaker.c_str());
|
||||
lua_setfield(L, -2, "speaker");
|
||||
lua_setfield(L, -2, "speaker"); pushStringVector(L, c.choices);
|
||||
lua_setfield(L, -2, "choices");
|
||||
lua_pushstring(L, c.fontName.c_str());
|
||||
lua_setfield(L, -2, "fontName"); lua_pushnumber(L, c.fontSize);
|
||||
lua_setfield(L, -2, "fontSize");
|
||||
@@ -1269,6 +1270,9 @@ static void registerAllComponents()
|
||||
if (lua_getfield(L, idx, "speaker"), lua_isstring(L, -1))
|
||||
c.speaker = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
if (lua_getfield(L, idx, "choices"), lua_istable(L, -1))
|
||||
c.choices = readStringVector(L, lua_gettop(L));
|
||||
lua_pop(L, 1);
|
||||
if (lua_getfield(L, idx, "fontName"), lua_isstring(L, -1))
|
||||
c.fontName = lua_tostring(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
@@ -21,45 +21,37 @@ DialogueSystem::DialogueSystem(flecs::world &world,
|
||||
"dialogue_show", [this](const Ogre::String &,
|
||||
const editScene::EventParams ¶ms) {
|
||||
// Find the first entity with DialogueComponent
|
||||
m_world.query<DialogueComponent>().each([&](flecs::entity
|
||||
e,
|
||||
DialogueComponent
|
||||
&dc) {
|
||||
if (!dc.enabled)
|
||||
return;
|
||||
m_world.query<DialogueComponent>().each(
|
||||
[&](flecs::entity e, DialogueComponent &dc) {
|
||||
if (!dc.enabled)
|
||||
return;
|
||||
|
||||
Ogre::String text = params.getString("text");
|
||||
if (text.empty())
|
||||
return;
|
||||
Ogre::String text =
|
||||
params.getString("text");
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
// Parse choices from comma-separated
|
||||
// string
|
||||
std::vector<Ogre::String> choices;
|
||||
Ogre::String choicesStr =
|
||||
params.getString("choices");
|
||||
if (!choicesStr.empty()) {
|
||||
Ogre::String::size_type start = 0;
|
||||
Ogre::String::size_type end;
|
||||
while ((end = choicesStr.find(",",
|
||||
start)) !=
|
||||
Ogre::String::npos) {
|
||||
choices.push_back(
|
||||
choicesStr.substr(
|
||||
start,
|
||||
end - start));
|
||||
start = end + 1;
|
||||
// Parse choices from string array
|
||||
std::vector<Ogre::String> choices;
|
||||
const editScene::EventValue *choicesVal =
|
||||
params.get("choices");
|
||||
if (choicesVal &&
|
||||
choicesVal->getType() ==
|
||||
editScene::EventValue::
|
||||
STRING_ARRAY) {
|
||||
const auto &arr =
|
||||
choicesVal
|
||||
->getStringArray();
|
||||
choices.reserve(arr.size());
|
||||
for (const auto &s : arr)
|
||||
choices.push_back(s);
|
||||
}
|
||||
if (start < choicesStr.length())
|
||||
choices.push_back(
|
||||
choicesStr.substr(
|
||||
start));
|
||||
}
|
||||
|
||||
Ogre::String speaker =
|
||||
params.getString("speaker");
|
||||
Ogre::String speaker =
|
||||
params.getString("speaker");
|
||||
|
||||
dc.show(text, choices, speaker);
|
||||
});
|
||||
dc.show(text, choices, speaker);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user