@magicborn/dialogue-forge 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/README.md +233 -0
  2. package/bin/dialogue-forge.js +78 -0
  3. package/demo/app/layout.tsx +36 -0
  4. package/demo/app/page.tsx +440 -0
  5. package/demo/components/ThemeSwitcher.tsx +611 -0
  6. package/demo/next.config.mjs +7 -0
  7. package/demo/package.json +29 -0
  8. package/demo/postcss.config.mjs +7 -0
  9. package/demo/public/logo.svg +1 -0
  10. package/demo/styles/globals.css +19 -0
  11. package/demo/tailwind.config.ts +90 -0
  12. package/demo/tsconfig.json +42 -0
  13. package/dist/components/ChoiceEdgeV2.d.ts +3 -0
  14. package/dist/components/ChoiceEdgeV2.js +103 -0
  15. package/dist/components/CodeBlock.d.ts +8 -0
  16. package/dist/components/CodeBlock.js +24 -0
  17. package/dist/components/ConditionAutocomplete.d.ts +14 -0
  18. package/dist/components/ConditionAutocomplete.js +284 -0
  19. package/dist/components/ConditionalNodeV2.d.ts +16 -0
  20. package/dist/components/ConditionalNodeV2.js +147 -0
  21. package/dist/components/DialogueEditorV2.d.ts +22 -0
  22. package/dist/components/DialogueEditorV2.js +1170 -0
  23. package/dist/components/EdgeIcon.d.ts +8 -0
  24. package/dist/components/EdgeIcon.js +13 -0
  25. package/dist/components/ExampleLoader.d.ts +11 -0
  26. package/dist/components/ExampleLoader.js +52 -0
  27. package/dist/components/ExampleLoaderButton.d.ts +15 -0
  28. package/dist/components/ExampleLoaderButton.js +102 -0
  29. package/dist/components/FlagManager.d.ts +11 -0
  30. package/dist/components/FlagManager.js +282 -0
  31. package/dist/components/FlagSelector.d.ts +11 -0
  32. package/dist/components/FlagSelector.js +235 -0
  33. package/dist/components/GuidePanel.d.ts +7 -0
  34. package/dist/components/GuidePanel.js +1176 -0
  35. package/dist/components/Minimap.d.ts +16 -0
  36. package/dist/components/Minimap.js +93 -0
  37. package/dist/components/NPCEdgeV2.d.ts +3 -0
  38. package/dist/components/NPCEdgeV2.js +104 -0
  39. package/dist/components/NPCNodeV2.d.ts +26 -0
  40. package/dist/components/NPCNodeV2.js +86 -0
  41. package/dist/components/NodeEditor.d.ts +18 -0
  42. package/dist/components/NodeEditor.js +1025 -0
  43. package/dist/components/PlayView.d.ts +12 -0
  44. package/dist/components/PlayView.js +307 -0
  45. package/dist/components/PlayerNodeV2.d.ts +16 -0
  46. package/dist/components/PlayerNodeV2.js +139 -0
  47. package/dist/components/ReactFlowPOC.d.ts +61 -0
  48. package/dist/components/ReactFlowPOC.js +312 -0
  49. package/dist/components/ScenePlayer.d.ts +18 -0
  50. package/dist/components/ScenePlayer.js +196 -0
  51. package/dist/components/YarnView.d.ts +9 -0
  52. package/dist/components/YarnView.js +45 -0
  53. package/dist/components/ZoomControls.d.ts +11 -0
  54. package/dist/components/ZoomControls.js +34 -0
  55. package/dist/esm/components/ChoiceEdgeV2.d.ts +3 -0
  56. package/dist/esm/components/ChoiceEdgeV2.js +67 -0
  57. package/dist/esm/components/CodeBlock.d.ts +8 -0
  58. package/dist/esm/components/CodeBlock.js +18 -0
  59. package/dist/esm/components/ConditionAutocomplete.d.ts +14 -0
  60. package/dist/esm/components/ConditionAutocomplete.js +248 -0
  61. package/dist/esm/components/ConditionalNodeV2.d.ts +16 -0
  62. package/dist/esm/components/ConditionalNodeV2.js +111 -0
  63. package/dist/esm/components/DialogueEditorV2.d.ts +22 -0
  64. package/dist/esm/components/DialogueEditorV2.js +1134 -0
  65. package/dist/esm/components/EdgeIcon.d.ts +8 -0
  66. package/dist/esm/components/EdgeIcon.js +7 -0
  67. package/dist/esm/components/ExampleLoader.d.ts +11 -0
  68. package/dist/esm/components/ExampleLoader.js +46 -0
  69. package/dist/esm/components/ExampleLoaderButton.d.ts +15 -0
  70. package/dist/esm/components/ExampleLoaderButton.js +66 -0
  71. package/dist/esm/components/FlagManager.d.ts +11 -0
  72. package/dist/esm/components/FlagManager.js +246 -0
  73. package/dist/esm/components/FlagSelector.d.ts +11 -0
  74. package/dist/esm/components/FlagSelector.js +199 -0
  75. package/dist/esm/components/GuidePanel.d.ts +7 -0
  76. package/dist/esm/components/GuidePanel.js +1140 -0
  77. package/dist/esm/components/Minimap.d.ts +16 -0
  78. package/dist/esm/components/Minimap.js +57 -0
  79. package/dist/esm/components/NPCEdgeV2.d.ts +3 -0
  80. package/dist/esm/components/NPCEdgeV2.js +68 -0
  81. package/dist/esm/components/NPCNodeV2.d.ts +26 -0
  82. package/dist/esm/components/NPCNodeV2.js +80 -0
  83. package/dist/esm/components/NodeEditor.d.ts +18 -0
  84. package/dist/esm/components/NodeEditor.js +989 -0
  85. package/dist/esm/components/PlayView.d.ts +12 -0
  86. package/dist/esm/components/PlayView.js +271 -0
  87. package/dist/esm/components/PlayerNodeV2.d.ts +16 -0
  88. package/dist/esm/components/PlayerNodeV2.js +103 -0
  89. package/dist/esm/components/ReactFlowPOC.d.ts +61 -0
  90. package/dist/esm/components/ReactFlowPOC.js +275 -0
  91. package/dist/esm/components/ScenePlayer.d.ts +18 -0
  92. package/dist/esm/components/ScenePlayer.js +160 -0
  93. package/dist/esm/components/YarnView.d.ts +9 -0
  94. package/dist/esm/components/YarnView.js +39 -0
  95. package/dist/esm/components/ZoomControls.d.ts +11 -0
  96. package/dist/esm/components/ZoomControls.js +28 -0
  97. package/dist/esm/examples/example-loader.d.ts +29 -0
  98. package/dist/esm/examples/example-loader.js +103 -0
  99. package/dist/esm/examples/examples-registry.d.ts +38 -0
  100. package/dist/esm/examples/examples-registry.js +153 -0
  101. package/dist/esm/examples/index.d.ts +26 -0
  102. package/dist/esm/examples/index.js +50 -0
  103. package/dist/esm/examples/legacy-examples.d.ts +9 -0
  104. package/dist/esm/examples/legacy-examples.js +814 -0
  105. package/dist/esm/examples/yarn-examples.d.ts +35 -0
  106. package/dist/esm/examples/yarn-examples.js +181 -0
  107. package/dist/esm/index.d.ts +21 -0
  108. package/dist/esm/index.js +26 -0
  109. package/dist/esm/lib/flag-manager.d.ts +21 -0
  110. package/dist/esm/lib/flag-manager.js +93 -0
  111. package/dist/esm/lib/yarn-converter/__tests__/round-trip.test.d.ts +1 -0
  112. package/dist/esm/lib/yarn-converter/__tests__/round-trip.test.js +169 -0
  113. package/dist/esm/lib/yarn-converter.d.ts +17 -0
  114. package/dist/esm/lib/yarn-converter.js +521 -0
  115. package/dist/esm/lib/yarn-runner/__tests__/condition-evaluator.test.d.ts +1 -0
  116. package/dist/esm/lib/yarn-runner/__tests__/condition-evaluator.test.js +171 -0
  117. package/dist/esm/lib/yarn-runner/__tests__/node-processor.test.d.ts +1 -0
  118. package/dist/esm/lib/yarn-runner/__tests__/node-processor.test.js +237 -0
  119. package/dist/esm/lib/yarn-runner/__tests__/variable-manager.test.d.ts +1 -0
  120. package/dist/esm/lib/yarn-runner/__tests__/variable-manager.test.js +106 -0
  121. package/dist/esm/lib/yarn-runner/condition-evaluator.d.ts +12 -0
  122. package/dist/esm/lib/yarn-runner/condition-evaluator.js +56 -0
  123. package/dist/esm/lib/yarn-runner/index.d.ts +12 -0
  124. package/dist/esm/lib/yarn-runner/index.js +11 -0
  125. package/dist/esm/lib/yarn-runner/node-processor.d.ts +18 -0
  126. package/dist/esm/lib/yarn-runner/node-processor.js +129 -0
  127. package/dist/esm/lib/yarn-runner/variable-manager.d.ts +51 -0
  128. package/dist/esm/lib/yarn-runner/variable-manager.js +120 -0
  129. package/dist/esm/lib/yarn-runner/variable-operations.d.ts +16 -0
  130. package/dist/esm/lib/yarn-runner/variable-operations.js +88 -0
  131. package/dist/esm/types/conditionals.d.ts +29 -0
  132. package/dist/esm/types/conditionals.js +1 -0
  133. package/dist/esm/types/constants.d.ts +59 -0
  134. package/dist/esm/types/constants.js +55 -0
  135. package/dist/esm/types/flags.d.ts +49 -0
  136. package/dist/esm/types/flags.js +49 -0
  137. package/dist/esm/types/game-state.d.ts +62 -0
  138. package/dist/esm/types/game-state.js +6 -0
  139. package/dist/esm/types/index.d.ts +77 -0
  140. package/dist/esm/types/index.js +1 -0
  141. package/dist/esm/utils/constants.d.ts +5 -0
  142. package/dist/esm/utils/constants.js +5 -0
  143. package/dist/esm/utils/feature-flags.d.ts +11 -0
  144. package/dist/esm/utils/feature-flags.js +11 -0
  145. package/dist/esm/utils/game-state-flattener.d.ts +41 -0
  146. package/dist/esm/utils/game-state-flattener.js +135 -0
  147. package/dist/esm/utils/layout/collision.d.ts +27 -0
  148. package/dist/esm/utils/layout/collision.js +74 -0
  149. package/dist/esm/utils/layout/index.d.ts +82 -0
  150. package/dist/esm/utils/layout/index.js +98 -0
  151. package/dist/esm/utils/layout/registry.d.ts +91 -0
  152. package/dist/esm/utils/layout/registry.js +148 -0
  153. package/dist/esm/utils/layout/strategies/dagre.d.ts +19 -0
  154. package/dist/esm/utils/layout/strategies/dagre.js +182 -0
  155. package/dist/esm/utils/layout/strategies/force.d.ts +21 -0
  156. package/dist/esm/utils/layout/strategies/force.js +178 -0
  157. package/dist/esm/utils/layout/strategies/grid.d.ts +17 -0
  158. package/dist/esm/utils/layout/strategies/grid.js +91 -0
  159. package/dist/esm/utils/layout/strategies/index.d.ts +8 -0
  160. package/dist/esm/utils/layout/strategies/index.js +8 -0
  161. package/dist/esm/utils/layout/types.d.ts +100 -0
  162. package/dist/esm/utils/layout/types.js +7 -0
  163. package/dist/esm/utils/layout.d.ts +9 -0
  164. package/dist/esm/utils/layout.js +17 -0
  165. package/dist/esm/utils/node-helpers.d.ts +7 -0
  166. package/dist/esm/utils/node-helpers.js +94 -0
  167. package/dist/esm/utils/reactflow-converter.d.ts +42 -0
  168. package/dist/esm/utils/reactflow-converter.js +217 -0
  169. package/dist/examples/example-loader.d.ts +29 -0
  170. package/dist/examples/example-loader.js +109 -0
  171. package/dist/examples/examples-registry.d.ts +38 -0
  172. package/dist/examples/examples-registry.js +160 -0
  173. package/dist/examples/index.d.ts +26 -0
  174. package/dist/examples/index.js +63 -0
  175. package/dist/examples/legacy-examples.d.ts +9 -0
  176. package/dist/examples/legacy-examples.js +817 -0
  177. package/dist/examples/yarn-examples.d.ts +35 -0
  178. package/dist/examples/yarn-examples.js +189 -0
  179. package/dist/index.d.ts +21 -0
  180. package/dist/index.js +66 -0
  181. package/dist/lib/flag-manager.d.ts +21 -0
  182. package/dist/lib/flag-manager.js +99 -0
  183. package/dist/lib/yarn-converter/__tests__/round-trip.test.d.ts +1 -0
  184. package/dist/lib/yarn-converter/__tests__/round-trip.test.js +171 -0
  185. package/dist/lib/yarn-converter.d.ts +17 -0
  186. package/dist/lib/yarn-converter.js +525 -0
  187. package/dist/lib/yarn-runner/__tests__/condition-evaluator.test.d.ts +1 -0
  188. package/dist/lib/yarn-runner/__tests__/condition-evaluator.test.js +173 -0
  189. package/dist/lib/yarn-runner/__tests__/node-processor.test.d.ts +1 -0
  190. package/dist/lib/yarn-runner/__tests__/node-processor.test.js +239 -0
  191. package/dist/lib/yarn-runner/__tests__/variable-manager.test.d.ts +1 -0
  192. package/dist/lib/yarn-runner/__tests__/variable-manager.test.js +108 -0
  193. package/dist/lib/yarn-runner/condition-evaluator.d.ts +12 -0
  194. package/dist/lib/yarn-runner/condition-evaluator.js +60 -0
  195. package/dist/lib/yarn-runner/index.d.ts +12 -0
  196. package/dist/lib/yarn-runner/index.js +21 -0
  197. package/dist/lib/yarn-runner/node-processor.d.ts +18 -0
  198. package/dist/lib/yarn-runner/node-processor.js +133 -0
  199. package/dist/lib/yarn-runner/variable-manager.d.ts +51 -0
  200. package/dist/lib/yarn-runner/variable-manager.js +124 -0
  201. package/dist/lib/yarn-runner/variable-operations.d.ts +16 -0
  202. package/dist/lib/yarn-runner/variable-operations.js +92 -0
  203. package/dist/types/conditionals.d.ts +29 -0
  204. package/dist/types/conditionals.js +2 -0
  205. package/dist/types/constants.d.ts +59 -0
  206. package/dist/types/constants.js +58 -0
  207. package/dist/types/flags.d.ts +49 -0
  208. package/dist/types/flags.js +52 -0
  209. package/dist/types/game-state.d.ts +62 -0
  210. package/dist/types/game-state.js +7 -0
  211. package/dist/types/index.d.ts +77 -0
  212. package/dist/types/index.js +2 -0
  213. package/dist/utils/constants.d.ts +5 -0
  214. package/dist/utils/constants.js +8 -0
  215. package/dist/utils/feature-flags.d.ts +11 -0
  216. package/dist/utils/feature-flags.js +14 -0
  217. package/dist/utils/game-state-flattener.d.ts +41 -0
  218. package/dist/utils/game-state-flattener.js +140 -0
  219. package/dist/utils/layout/collision.d.ts +27 -0
  220. package/dist/utils/layout/collision.js +77 -0
  221. package/dist/utils/layout/index.d.ts +82 -0
  222. package/dist/utils/layout/index.js +109 -0
  223. package/dist/utils/layout/registry.d.ts +91 -0
  224. package/dist/utils/layout/registry.js +151 -0
  225. package/dist/utils/layout/strategies/dagre.d.ts +19 -0
  226. package/dist/utils/layout/strategies/dagre.js +189 -0
  227. package/dist/utils/layout/strategies/force.d.ts +21 -0
  228. package/dist/utils/layout/strategies/force.js +182 -0
  229. package/dist/utils/layout/strategies/grid.d.ts +17 -0
  230. package/dist/utils/layout/strategies/grid.js +95 -0
  231. package/dist/utils/layout/strategies/index.d.ts +8 -0
  232. package/dist/utils/layout/strategies/index.js +14 -0
  233. package/dist/utils/layout/types.d.ts +100 -0
  234. package/dist/utils/layout/types.js +8 -0
  235. package/dist/utils/layout.d.ts +9 -0
  236. package/dist/utils/layout.js +25 -0
  237. package/dist/utils/node-helpers.d.ts +7 -0
  238. package/dist/utils/node-helpers.js +101 -0
  239. package/dist/utils/reactflow-converter.d.ts +42 -0
  240. package/dist/utils/reactflow-converter.js +223 -0
  241. package/package.json +70 -0
@@ -0,0 +1,814 @@
1
+ import { FLAG_TYPE, FLAG_VALUE_TYPE, NODE_TYPE, CONDITION_OPERATOR } from '../types/constants';
2
+ /**
3
+ * Legacy TypeScript examples
4
+ * These are kept for backward compatibility while we migrate to Yarn format
5
+ * TODO: Convert these to Yarn format and remove this file
6
+ */
7
+ export const demoFlagSchemas = {
8
+ basic: {
9
+ categories: ['quests', 'items', 'stats'],
10
+ flags: [
11
+ { id: 'quest_intro', name: 'Introduction Quest', type: FLAG_TYPE.QUEST, category: 'quests', valueType: FLAG_VALUE_TYPE.STRING },
12
+ { id: 'item_key', name: 'Key', type: FLAG_TYPE.ITEM, category: 'items' },
13
+ { id: 'stat_reputation', name: 'Reputation', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 0 },
14
+ ]
15
+ },
16
+ rpg: {
17
+ categories: ['quests', 'achievements', 'items', 'stats', 'titles'],
18
+ flags: [
19
+ { id: 'quest_dragon_slayer', name: 'Dragon Slayer Quest', type: FLAG_TYPE.QUEST, category: 'quests', valueType: FLAG_VALUE_TYPE.STRING },
20
+ { id: 'quest_dragon_slayer_complete', name: 'Dragon Slayer Complete', type: FLAG_TYPE.QUEST, category: 'quests' },
21
+ { id: 'quest_find_key', name: 'Find the Key', type: FLAG_TYPE.QUEST, category: 'quests', valueType: FLAG_VALUE_TYPE.STRING },
22
+ { id: 'achievement_first_quest', name: 'First Quest', type: FLAG_TYPE.ACHIEVEMENT, category: 'achievements' },
23
+ { id: 'achievement_dragon_slayer', name: 'Dragon Slayer', type: FLAG_TYPE.ACHIEVEMENT, category: 'achievements' },
24
+ { id: 'achievement_hero', name: 'Hero', type: FLAG_TYPE.ACHIEVEMENT, category: 'achievements' },
25
+ { id: 'item_ancient_key', name: 'Ancient Key', type: FLAG_TYPE.ITEM, category: 'items' },
26
+ { id: 'item_map', name: 'Treasure Map', type: FLAG_TYPE.ITEM, category: 'items' },
27
+ { id: 'item_sword', name: 'Legendary Sword', type: FLAG_TYPE.ITEM, category: 'items' },
28
+ { id: 'stat_gold', name: 'Gold', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 0 },
29
+ { id: 'stat_reputation', name: 'Reputation', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 0 },
30
+ { id: 'stat_charisma', name: 'Charisma', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 10 },
31
+ { id: 'title_hero', name: 'Hero', type: FLAG_TYPE.TITLE, category: 'titles' },
32
+ { id: 'title_merchant', name: 'Merchant', type: FLAG_TYPE.TITLE, category: 'titles' },
33
+ { id: 'dialogue_met_stranger', name: 'Met Stranger', type: FLAG_TYPE.DIALOGUE, category: 'dialogue' },
34
+ { id: 'dialogue_hostile', name: 'Hostile Response', type: FLAG_TYPE.DIALOGUE, category: 'dialogue' },
35
+ ]
36
+ },
37
+ conditional: {
38
+ categories: ['quests', 'items', 'stats'],
39
+ flags: [
40
+ { id: 'quest_main', name: 'Main Quest', type: FLAG_TYPE.QUEST, category: 'quests', valueType: FLAG_VALUE_TYPE.STRING },
41
+ { id: 'item_key', name: 'Key', type: FLAG_TYPE.ITEM, category: 'items' },
42
+ { id: 'stat_gold', name: 'Gold', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 0 },
43
+ { id: 'stat_reputation', name: 'Reputation', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 0 },
44
+ ]
45
+ },
46
+ complex_conditional: {
47
+ categories: ['quests', 'achievements', 'items', 'stats', 'titles', 'global', 'dialogue'],
48
+ flags: [
49
+ { id: 'quest_ancient_ruins', name: 'Ancient Ruins Quest', type: FLAG_TYPE.QUEST, category: 'quests', valueType: FLAG_VALUE_TYPE.STRING },
50
+ { id: 'quest_ancient_ruins_complete', name: 'Ancient Ruins Complete', type: FLAG_TYPE.QUEST, category: 'quests' },
51
+ { id: 'quest_treasure_hunt', name: 'Treasure Hunt', type: FLAG_TYPE.QUEST, category: 'quests', valueType: FLAG_VALUE_TYPE.STRING },
52
+ { id: 'quest_treasure_hunt_complete', name: 'Treasure Hunt Complete', type: FLAG_TYPE.QUEST, category: 'quests' },
53
+ { id: 'quest_dragon_slayer', name: 'Dragon Slayer Quest', type: FLAG_TYPE.QUEST, category: 'quests', valueType: FLAG_VALUE_TYPE.STRING },
54
+ { id: 'achievement_explorer', name: 'Explorer', type: FLAG_TYPE.ACHIEVEMENT, category: 'achievements' },
55
+ { id: 'achievement_rich', name: 'Rich', type: FLAG_TYPE.ACHIEVEMENT, category: 'achievements' },
56
+ { id: 'achievement_hero', name: 'Hero', type: FLAG_TYPE.ACHIEVEMENT, category: 'achievements' },
57
+ { id: 'achievement_diplomat', name: 'Diplomat', type: FLAG_TYPE.ACHIEVEMENT, category: 'achievements' },
58
+ { id: 'item_ancient_key', name: 'Ancient Key', type: FLAG_TYPE.ITEM, category: 'items' },
59
+ { id: 'item_treasure_map', name: 'Treasure Map', type: FLAG_TYPE.ITEM, category: 'items' },
60
+ { id: 'item_legendary_sword', name: 'Legendary Sword', type: FLAG_TYPE.ITEM, category: 'items' },
61
+ { id: 'item_gold_coin', name: 'Gold Coin', type: FLAG_TYPE.ITEM, category: 'items' },
62
+ { id: 'stat_gold', name: 'Gold', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 0 },
63
+ { id: 'stat_reputation', name: 'Reputation', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 0 },
64
+ { id: 'stat_charisma', name: 'Charisma', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 10 },
65
+ { id: 'stat_strength', name: 'Strength', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 10 },
66
+ { id: 'stat_wisdom', name: 'Wisdom', type: FLAG_TYPE.STAT, category: 'stats', valueType: FLAG_VALUE_TYPE.NUMBER, defaultValue: 10 },
67
+ { id: 'title_hero', name: 'Hero', type: FLAG_TYPE.TITLE, category: 'titles' },
68
+ { id: 'title_explorer', name: 'Explorer', type: FLAG_TYPE.TITLE, category: 'titles' },
69
+ { id: 'title_merchant', name: 'Merchant', type: FLAG_TYPE.TITLE, category: 'titles' },
70
+ { id: 'global_game_started', name: 'Game Started', type: FLAG_TYPE.GLOBAL, category: 'global' },
71
+ { id: 'global_first_visit', name: 'First Visit', type: FLAG_TYPE.GLOBAL, category: 'global' },
72
+ { id: 'global_difficulty', name: 'Difficulty', type: FLAG_TYPE.GLOBAL, category: 'global', valueType: FLAG_VALUE_TYPE.STRING },
73
+ { id: 'dialogue_met_guard', name: 'Met Guard', type: FLAG_TYPE.DIALOGUE, category: 'dialogue' },
74
+ { id: 'dialogue_hostile', name: 'Hostile Response', type: FLAG_TYPE.DIALOGUE, category: 'dialogue' },
75
+ { id: 'dialogue_friendly', name: 'Friendly Response', type: FLAG_TYPE.DIALOGUE, category: 'dialogue' },
76
+ { id: 'dialogue_seeks_knowledge', name: 'Seeks Knowledge', type: FLAG_TYPE.DIALOGUE, category: 'dialogue' },
77
+ { id: 'dialogue_offered_bribe', name: 'Offered Bribe', type: FLAG_TYPE.DIALOGUE, category: 'dialogue' },
78
+ ]
79
+ }
80
+ };
81
+ export const exampleDialogues = {
82
+ basic: {
83
+ id: 'basic-example',
84
+ title: 'Basic Dialogue Example',
85
+ startNodeId: 'start',
86
+ nodes: {
87
+ start: {
88
+ id: 'start',
89
+ type: NODE_TYPE.NPC,
90
+ speaker: 'Merchant',
91
+ content: 'Welcome to my shop! How can I help you?',
92
+ nextNodeId: 'player_choice',
93
+ x: 300,
94
+ y: 100
95
+ },
96
+ player_choice: {
97
+ id: 'player_choice',
98
+ type: NODE_TYPE.PLAYER,
99
+ content: '',
100
+ choices: [
101
+ {
102
+ id: 'buy',
103
+ text: 'I want to buy something',
104
+ nextNodeId: 'shop',
105
+ setFlags: ['dialogue_shopping']
106
+ },
107
+ {
108
+ id: 'sell',
109
+ text: 'I want to sell something',
110
+ nextNodeId: 'sell',
111
+ },
112
+ {
113
+ id: 'leave',
114
+ text: 'Never mind',
115
+ nextNodeId: 'goodbye'
116
+ }
117
+ ],
118
+ x: 300,
119
+ y: 250
120
+ },
121
+ shop: {
122
+ id: 'shop',
123
+ type: NODE_TYPE.NPC,
124
+ speaker: 'Merchant',
125
+ content: 'What would you like to buy?',
126
+ x: 100,
127
+ y: 400
128
+ },
129
+ sell: {
130
+ id: 'sell',
131
+ type: NODE_TYPE.NPC,
132
+ speaker: 'Merchant',
133
+ content: 'Show me what you have.',
134
+ x: 300,
135
+ y: 400
136
+ },
137
+ goodbye: {
138
+ id: 'goodbye',
139
+ type: NODE_TYPE.NPC,
140
+ speaker: 'Merchant',
141
+ content: 'Come back anytime!',
142
+ x: 500,
143
+ y: 400
144
+ }
145
+ }
146
+ },
147
+ conditional: {
148
+ id: 'conditional-example',
149
+ title: 'Conditional Dialogue Example',
150
+ startNodeId: 'start',
151
+ nodes: {
152
+ start: {
153
+ id: 'start',
154
+ type: NODE_TYPE.NPC,
155
+ speaker: 'Guard',
156
+ content: 'Halt! Who goes there?',
157
+ nextNodeId: 'check_reputation',
158
+ x: 300,
159
+ y: 100
160
+ },
161
+ check_reputation: {
162
+ id: 'check_reputation',
163
+ type: NODE_TYPE.PLAYER,
164
+ content: '',
165
+ choices: [
166
+ {
167
+ id: 'high_rep',
168
+ text: 'I am a hero of this land!',
169
+ nextNodeId: 'high_rep_response',
170
+ conditions: [
171
+ { flag: 'stat_reputation', operator: CONDITION_OPERATOR.GREATER_THAN, value: 50 }
172
+ ]
173
+ },
174
+ {
175
+ id: 'low_rep',
176
+ text: 'Just a traveler...',
177
+ nextNodeId: 'low_rep_response',
178
+ conditions: [
179
+ { flag: 'stat_reputation', operator: CONDITION_OPERATOR.LESS_EQUAL, value: 50 }
180
+ ]
181
+ },
182
+ {
183
+ id: 'has_key',
184
+ text: 'I have the key!',
185
+ nextNodeId: 'key_response',
186
+ conditions: [
187
+ { flag: 'item_key', operator: CONDITION_OPERATOR.IS_SET }
188
+ ]
189
+ }
190
+ ],
191
+ x: 300,
192
+ y: 250
193
+ },
194
+ high_rep_response: {
195
+ id: 'high_rep_response',
196
+ type: NODE_TYPE.NPC,
197
+ speaker: 'Guard',
198
+ content: 'Hero! Please, come in. The city welcomes you.',
199
+ setFlags: ['stat_reputation'],
200
+ x: 100,
201
+ y: 400
202
+ },
203
+ low_rep_response: {
204
+ id: 'low_rep_response',
205
+ type: NODE_TYPE.NPC,
206
+ speaker: 'Guard',
207
+ content: 'Hmm... you may pass, but watch yourself.',
208
+ x: 300,
209
+ y: 400
210
+ },
211
+ key_response: {
212
+ id: 'key_response',
213
+ type: NODE_TYPE.NPC,
214
+ speaker: 'Guard',
215
+ content: 'Ah, you have the key! Please enter.',
216
+ x: 500,
217
+ y: 400
218
+ }
219
+ }
220
+ },
221
+ quest_progression: {
222
+ id: 'quest-progression-example',
223
+ title: 'Quest Progression Example',
224
+ startNodeId: 'start',
225
+ nodes: {
226
+ start: {
227
+ id: 'start',
228
+ type: NODE_TYPE.NPC,
229
+ speaker: 'Quest Giver',
230
+ content: 'I need your help! A dragon threatens our village.',
231
+ nextNodeId: 'quest_offer',
232
+ x: 300,
233
+ y: 100
234
+ },
235
+ quest_offer: {
236
+ id: 'quest_offer',
237
+ type: NODE_TYPE.PLAYER,
238
+ content: '',
239
+ choices: [
240
+ {
241
+ id: 'accept',
242
+ text: 'I will help you!',
243
+ nextNodeId: 'quest_started',
244
+ setFlags: ['quest_dragon_slayer']
245
+ },
246
+ {
247
+ id: 'decline',
248
+ text: 'I cannot help right now.',
249
+ nextNodeId: 'quest_declined'
250
+ }
251
+ ],
252
+ x: 300,
253
+ y: 250
254
+ },
255
+ quest_started: {
256
+ id: 'quest_started',
257
+ type: NODE_TYPE.NPC,
258
+ speaker: 'Quest Giver',
259
+ content: 'Thank you! Here is a map to the dragon\'s lair.',
260
+ setFlags: ['item_map', 'achievement_first_quest'],
261
+ nextNodeId: 'quest_continue',
262
+ x: 100,
263
+ y: 400
264
+ },
265
+ quest_continue: {
266
+ id: 'quest_continue',
267
+ type: NODE_TYPE.PLAYER,
268
+ content: '',
269
+ choices: [
270
+ {
271
+ id: 'ask_details',
272
+ text: 'Tell me more about the dragon',
273
+ nextNodeId: 'dragon_info'
274
+ },
275
+ {
276
+ id: 'leave',
277
+ text: 'I will return when I have slain the dragon',
278
+ nextNodeId: 'quest_end'
279
+ }
280
+ ],
281
+ x: 100,
282
+ y: 550
283
+ },
284
+ dragon_info: {
285
+ id: 'dragon_info',
286
+ type: NODE_TYPE.NPC,
287
+ speaker: 'Quest Giver',
288
+ content: 'The dragon is ancient and powerful. You will need the legendary sword to defeat it.',
289
+ nextNodeId: 'quest_continue',
290
+ x: 300,
291
+ y: 550
292
+ },
293
+ quest_declined: {
294
+ id: 'quest_declined',
295
+ type: NODE_TYPE.NPC,
296
+ speaker: 'Quest Giver',
297
+ content: 'I understand. Return if you change your mind.',
298
+ x: 500,
299
+ y: 400
300
+ },
301
+ quest_end: {
302
+ id: 'quest_end',
303
+ type: NODE_TYPE.NPC,
304
+ speaker: 'Narrator',
305
+ content: 'You set off on your quest...\n\n— TO BE CONTINUED —',
306
+ x: 100,
307
+ y: 700
308
+ }
309
+ }
310
+ },
311
+ complex_conditional: {
312
+ id: 'complex-conditional-example',
313
+ title: 'Complex Conditional Example',
314
+ startNodeId: 'guard_encounter',
315
+ nodes: {
316
+ guard_encounter: {
317
+ id: 'guard_encounter',
318
+ type: NODE_TYPE.NPC,
319
+ speaker: 'Guard',
320
+ content: 'Halt! Who goes there?',
321
+ nextNodeId: 'player_response',
322
+ setFlags: ['dialogue_met_guard'],
323
+ x: 400,
324
+ y: 100
325
+ },
326
+ player_response: {
327
+ id: 'player_response',
328
+ type: NODE_TYPE.PLAYER,
329
+ content: '',
330
+ choices: [
331
+ {
332
+ id: 'friendly',
333
+ text: 'I mean no harm. I\'m just passing through.',
334
+ nextNodeId: 'guard_friendly',
335
+ setFlags: ['dialogue_friendly']
336
+ },
337
+ {
338
+ id: 'hostile',
339
+ text: 'None of your business!',
340
+ nextNodeId: 'guard_hostile',
341
+ setFlags: ['dialogue_hostile']
342
+ },
343
+ {
344
+ id: 'bribe',
345
+ text: 'Perhaps we can come to an arrangement?',
346
+ nextNodeId: 'guard_bribe',
347
+ conditions: [
348
+ { flag: 'stat_gold', operator: CONDITION_OPERATOR.GREATER_THAN, value: 50 }
349
+ ],
350
+ setFlags: ['dialogue_offered_bribe']
351
+ },
352
+ {
353
+ id: 'knowledge',
354
+ text: 'I seek knowledge of the ancient ruins.',
355
+ nextNodeId: 'guard_knowledge',
356
+ conditions: [
357
+ { flag: 'stat_wisdom', operator: CONDITION_OPERATOR.GREATER_EQUAL, value: 15 }
358
+ ],
359
+ setFlags: ['dialogue_seeks_knowledge']
360
+ },
361
+ {
362
+ id: 'hero',
363
+ text: 'I am a hero on a quest!',
364
+ nextNodeId: 'guard_hero',
365
+ conditions: [
366
+ { flag: 'title_hero', operator: CONDITION_OPERATOR.IS_SET }
367
+ ]
368
+ }
369
+ ],
370
+ x: 400,
371
+ y: 250
372
+ },
373
+ guard_friendly: {
374
+ id: 'guard_friendly',
375
+ type: NODE_TYPE.NPC,
376
+ speaker: 'Guard',
377
+ content: 'Very well. You may pass, but be careful. The ruins ahead are dangerous.',
378
+ nextNodeId: 'reputation_check',
379
+ x: 200,
380
+ y: 400
381
+ },
382
+ guard_hostile: {
383
+ id: 'guard_hostile',
384
+ type: NODE_TYPE.NPC,
385
+ speaker: 'Guard',
386
+ content: 'That\'s not a good attitude. I\'ll be watching you.',
387
+ nextNodeId: 'reputation_check',
388
+ setFlags: ['stat_reputation'],
389
+ x: 600,
390
+ y: 400
391
+ },
392
+ guard_bribe: {
393
+ id: 'guard_bribe',
394
+ type: NODE_TYPE.NPC,
395
+ speaker: 'Guard',
396
+ content: 'Ah, a person of culture! Very well, I\'ll look the other way... for now.',
397
+ nextNodeId: 'reputation_check',
398
+ setFlags: ['stat_gold'],
399
+ x: 400,
400
+ y: 400
401
+ },
402
+ guard_knowledge: {
403
+ id: 'guard_knowledge',
404
+ type: NODE_TYPE.NPC,
405
+ speaker: 'Guard',
406
+ content: 'The ancient ruins? You must be a scholar. I can tell you about them, but it will cost you.',
407
+ nextNodeId: 'knowledge_choice',
408
+ x: 200,
409
+ y: 400
410
+ },
411
+ guard_hero: {
412
+ id: 'guard_hero',
413
+ type: NODE_TYPE.NPC,
414
+ speaker: 'Guard',
415
+ content: 'A hero! We\'ve been waiting for someone like you. Please, come with me to meet the captain.',
416
+ nextNodeId: 'hero_path',
417
+ setFlags: ['quest_dragon_slayer'],
418
+ x: 800,
419
+ y: 400
420
+ },
421
+ knowledge_choice: {
422
+ id: 'knowledge_choice',
423
+ type: NODE_TYPE.PLAYER,
424
+ content: '',
425
+ choices: [
426
+ {
427
+ id: 'pay_knowledge',
428
+ text: 'I\'ll pay for the information.',
429
+ nextNodeId: 'knowledge_paid',
430
+ conditions: [
431
+ { flag: 'stat_gold', operator: CONDITION_OPERATOR.GREATER_EQUAL, value: 100 }
432
+ ],
433
+ setFlags: ['stat_gold', 'item_treasure_map']
434
+ },
435
+ {
436
+ id: 'decline_knowledge',
437
+ text: 'Never mind, I\'ll find out myself.',
438
+ nextNodeId: 'reputation_check'
439
+ }
440
+ ],
441
+ x: 200,
442
+ y: 550
443
+ },
444
+ knowledge_paid: {
445
+ id: 'knowledge_paid',
446
+ type: NODE_TYPE.NPC,
447
+ speaker: 'Guard',
448
+ content: 'The ruins are to the east. Here\'s a map. Be careful - many have entered, few have returned.',
449
+ nextNodeId: 'reputation_check',
450
+ x: 100,
451
+ y: 700
452
+ },
453
+ hero_path: {
454
+ id: 'hero_path',
455
+ type: NODE_TYPE.CONDITIONAL,
456
+ content: '',
457
+ conditionalBlocks: [
458
+ {
459
+ id: 'hero_if_quest',
460
+ type: 'if',
461
+ condition: [
462
+ { flag: 'quest_dragon_slayer', operator: CONDITION_OPERATOR.IS_SET }
463
+ ],
464
+ content: 'Captain: We need your help! A dragon has been terrorizing our lands.',
465
+ speaker: 'Captain',
466
+ nextNodeId: 'dragon_quest_start'
467
+ },
468
+ {
469
+ id: 'hero_elseif_achievement',
470
+ type: 'elseif',
471
+ condition: [
472
+ { flag: 'achievement_hero', operator: CONDITION_OPERATOR.IS_SET }
473
+ ],
474
+ content: 'Captain: Ah, the hero returns! We have a new mission for you.',
475
+ speaker: 'Captain',
476
+ nextNodeId: 'new_mission'
477
+ },
478
+ {
479
+ id: 'hero_else',
480
+ type: 'else',
481
+ content: 'Captain: Welcome, traveler. Perhaps you can help us with a problem.',
482
+ speaker: 'Captain',
483
+ nextNodeId: 'general_help'
484
+ }
485
+ ],
486
+ x: 800,
487
+ y: 550
488
+ },
489
+ dragon_quest_start: {
490
+ id: 'dragon_quest_start',
491
+ type: NODE_TYPE.PLAYER,
492
+ content: '',
493
+ choices: [
494
+ {
495
+ id: 'accept_dragon',
496
+ text: 'I accept the quest!',
497
+ nextNodeId: 'dragon_quest_accepted',
498
+ setFlags: ['quest_dragon_slayer', 'achievement_hero']
499
+ },
500
+ {
501
+ id: 'decline_dragon',
502
+ text: 'I need to prepare first.',
503
+ nextNodeId: 'dragon_quest_declined'
504
+ },
505
+ {
506
+ id: 'ask_reward',
507
+ text: 'What\'s the reward?',
508
+ nextNodeId: 'dragon_reward_info',
509
+ conditions: [
510
+ { flag: 'stat_gold', operator: CONDITION_OPERATOR.LESS_THAN, value: 1000 }
511
+ ]
512
+ }
513
+ ],
514
+ x: 800,
515
+ y: 700
516
+ },
517
+ dragon_quest_accepted: {
518
+ id: 'dragon_quest_accepted',
519
+ type: NODE_TYPE.NPC,
520
+ speaker: 'Captain',
521
+ content: 'Excellent! The dragon\'s lair is in the mountains. You\'ll need the legendary sword to defeat it.',
522
+ nextNodeId: 'reputation_check',
523
+ setFlags: ['quest_dragon_slayer', 'title_hero'],
524
+ x: 600,
525
+ y: 850
526
+ },
527
+ dragon_quest_declined: {
528
+ id: 'dragon_quest_declined',
529
+ type: NODE_TYPE.NPC,
530
+ speaker: 'Captain',
531
+ content: 'Very well. Return when you\'re ready. We\'ll be waiting.',
532
+ nextNodeId: 'reputation_check',
533
+ x: 1000,
534
+ y: 850
535
+ },
536
+ dragon_reward_info: {
537
+ id: 'dragon_reward_info',
538
+ type: NODE_TYPE.NPC,
539
+ speaker: 'Captain',
540
+ content: 'The reward is 10,000 gold pieces and the title of "Dragon Slayer".',
541
+ nextNodeId: 'dragon_quest_start',
542
+ x: 800,
543
+ y: 850
544
+ },
545
+ new_mission: {
546
+ id: 'new_mission',
547
+ type: NODE_TYPE.NPC,
548
+ speaker: 'Captain',
549
+ content: 'We need you to investigate the ancient ruins. Strange things have been happening there.',
550
+ nextNodeId: 'ruins_quest_choice',
551
+ setFlags: ['quest_ancient_ruins'],
552
+ x: 1000,
553
+ y: 700
554
+ },
555
+ general_help: {
556
+ id: 'general_help',
557
+ type: NODE_TYPE.PLAYER,
558
+ content: '',
559
+ choices: [
560
+ {
561
+ id: 'help_yes',
562
+ text: 'I\'ll help!',
563
+ nextNodeId: 'reputation_check',
564
+ setFlags: ['stat_reputation']
565
+ },
566
+ {
567
+ id: 'help_no',
568
+ text: 'I\'m just passing through.',
569
+ nextNodeId: 'reputation_check'
570
+ }
571
+ ],
572
+ x: 1000,
573
+ y: 550
574
+ },
575
+ ruins_quest_choice: {
576
+ id: 'ruins_quest_choice',
577
+ type: NODE_TYPE.PLAYER,
578
+ content: '',
579
+ choices: [
580
+ {
581
+ id: 'accept_ruins',
582
+ text: 'I\'ll investigate the ruins.',
583
+ nextNodeId: 'ruins_conditional',
584
+ setFlags: ['quest_ancient_ruins']
585
+ },
586
+ {
587
+ id: 'decline_ruins',
588
+ text: 'I have other priorities.',
589
+ nextNodeId: 'reputation_check'
590
+ }
591
+ ],
592
+ x: 1000,
593
+ y: 850
594
+ },
595
+ ruins_conditional: {
596
+ id: 'ruins_conditional',
597
+ type: NODE_TYPE.CONDITIONAL,
598
+ content: '',
599
+ conditionalBlocks: [
600
+ {
601
+ id: 'ruins_if_key',
602
+ type: 'if',
603
+ condition: [
604
+ { flag: 'item_ancient_key', operator: CONDITION_OPERATOR.IS_SET }
605
+ ],
606
+ content: 'You use the ancient key to unlock the ruins entrance. Inside, you find a treasure chest!',
607
+ nextNodeId: 'ruins_treasure'
608
+ },
609
+ {
610
+ id: 'ruins_elseif_strength',
611
+ type: 'elseif',
612
+ condition: [
613
+ { flag: 'stat_strength', operator: CONDITION_OPERATOR.GREATER_EQUAL, value: 20 }
614
+ ],
615
+ content: 'You force the door open with your strength. The entrance creaks open.',
616
+ nextNodeId: 'ruins_inside'
617
+ },
618
+ {
619
+ id: 'ruins_elseif_charisma',
620
+ type: 'elseif',
621
+ condition: [
622
+ { flag: 'stat_charisma', operator: CONDITION_OPERATOR.GREATER_EQUAL, value: 18 }
623
+ ],
624
+ content: 'You find a hidden mechanism and convince it to open through clever words.',
625
+ nextNodeId: 'ruins_inside'
626
+ },
627
+ {
628
+ id: 'ruins_else',
629
+ type: 'else',
630
+ content: 'The ruins entrance is sealed. You cannot enter without a key or sufficient strength.',
631
+ nextNodeId: 'reputation_check'
632
+ }
633
+ ],
634
+ x: 1000,
635
+ y: 1000
636
+ },
637
+ ruins_treasure: {
638
+ id: 'ruins_treasure',
639
+ type: NODE_TYPE.PLAYER,
640
+ content: '',
641
+ choices: [
642
+ {
643
+ id: 'open_treasure',
644
+ text: 'Open the treasure chest',
645
+ nextNodeId: 'treasure_reward',
646
+ setFlags: ['quest_ancient_ruins_complete', 'achievement_explorer']
647
+ },
648
+ {
649
+ id: 'leave_treasure',
650
+ text: 'Leave it for now',
651
+ nextNodeId: 'reputation_check'
652
+ }
653
+ ],
654
+ x: 800,
655
+ y: 1150
656
+ },
657
+ treasure_reward: {
658
+ id: 'treasure_reward',
659
+ type: NODE_TYPE.CONDITIONAL,
660
+ content: '',
661
+ conditionalBlocks: [
662
+ {
663
+ id: 'treasure_if_gold',
664
+ type: 'if',
665
+ condition: [
666
+ { flag: 'stat_gold', operator: CONDITION_OPERATOR.LESS_THAN, value: 500 }
667
+ ],
668
+ content: 'You find 1000 gold pieces inside! This is a fortune!',
669
+ nextNodeId: 'treasure_gold_reward'
670
+ },
671
+ {
672
+ id: 'treasure_else',
673
+ type: 'else',
674
+ content: 'You find a legendary sword! This will be useful against the dragon.',
675
+ nextNodeId: 'treasure_sword_reward'
676
+ }
677
+ ],
678
+ x: 600,
679
+ y: 1300
680
+ },
681
+ treasure_gold_reward: {
682
+ id: 'treasure_gold_reward',
683
+ type: NODE_TYPE.NPC,
684
+ speaker: 'Narrator',
685
+ content: 'You gain 1000 gold pieces and the "Rich" achievement!',
686
+ nextNodeId: 'reputation_check',
687
+ setFlags: ['stat_gold', 'achievement_rich'],
688
+ x: 400,
689
+ y: 1450
690
+ },
691
+ treasure_sword_reward: {
692
+ id: 'treasure_sword_reward',
693
+ type: NODE_TYPE.NPC,
694
+ speaker: 'Narrator',
695
+ content: 'You obtain the legendary sword! This will be useful against the dragon.',
696
+ nextNodeId: 'reputation_check',
697
+ setFlags: ['item_legendary_sword'],
698
+ x: 800,
699
+ y: 1450
700
+ },
701
+ ruins_inside: {
702
+ id: 'ruins_inside',
703
+ type: NODE_TYPE.PLAYER,
704
+ content: '',
705
+ choices: [
706
+ {
707
+ id: 'explore_ruins',
708
+ text: 'Explore the ruins',
709
+ nextNodeId: 'ruins_exploration',
710
+ setFlags: ['achievement_explorer']
711
+ },
712
+ {
713
+ id: 'search_key',
714
+ text: 'Search for a key',
715
+ nextNodeId: 'key_found',
716
+ conditions: [
717
+ { flag: 'stat_wisdom', operator: CONDITION_OPERATOR.GREATER_EQUAL, value: 15 }
718
+ ]
719
+ },
720
+ {
721
+ id: 'leave_ruins',
722
+ text: 'Leave the ruins',
723
+ nextNodeId: 'reputation_check'
724
+ }
725
+ ],
726
+ x: 1200,
727
+ y: 1150
728
+ },
729
+ ruins_exploration: {
730
+ id: 'ruins_exploration',
731
+ type: NODE_TYPE.NPC,
732
+ speaker: 'Narrator',
733
+ content: 'You explore the ancient ruins and discover ancient texts. Your wisdom increases.',
734
+ nextNodeId: 'reputation_check',
735
+ setFlags: ['stat_wisdom', 'quest_ancient_ruins_complete'],
736
+ x: 1200,
737
+ y: 1300
738
+ },
739
+ key_found: {
740
+ id: 'key_found',
741
+ type: NODE_TYPE.NPC,
742
+ speaker: 'Narrator',
743
+ content: 'Your wisdom guides you to a hidden alcove. You find an ancient key!',
744
+ nextNodeId: 'reputation_check',
745
+ setFlags: ['item_ancient_key'],
746
+ x: 1400,
747
+ y: 1300
748
+ },
749
+ reputation_check: {
750
+ id: 'reputation_check',
751
+ type: NODE_TYPE.CONDITIONAL,
752
+ content: '',
753
+ conditionalBlocks: [
754
+ {
755
+ id: 'rep_if_high',
756
+ type: 'if',
757
+ condition: [
758
+ { flag: 'stat_reputation', operator: CONDITION_OPERATOR.GREATER_EQUAL, value: 50 }
759
+ ],
760
+ content: 'Your reputation precedes you. People recognize you as a hero and treat you with respect.',
761
+ nextNodeId: 'ending'
762
+ },
763
+ {
764
+ id: 'rep_elseif_medium',
765
+ type: 'elseif',
766
+ condition: [
767
+ { flag: 'stat_reputation', operator: CONDITION_OPERATOR.GREATER_EQUAL, value: 20 }
768
+ ],
769
+ content: 'You have a decent reputation. Some people know of your deeds.',
770
+ nextNodeId: 'ending'
771
+ },
772
+ {
773
+ id: 'rep_else',
774
+ type: 'else',
775
+ content: 'You are relatively unknown. Your journey is just beginning.',
776
+ nextNodeId: 'ending'
777
+ }
778
+ ],
779
+ x: 400,
780
+ y: 1000
781
+ },
782
+ ending: {
783
+ id: 'ending',
784
+ type: NODE_TYPE.PLAYER,
785
+ content: '',
786
+ choices: [
787
+ {
788
+ id: 'continue',
789
+ text: 'Continue your adventure',
790
+ nextNodeId: 'final_message'
791
+ },
792
+ {
793
+ id: 'rest',
794
+ text: 'Take a rest',
795
+ nextNodeId: 'final_message',
796
+ conditions: [
797
+ { flag: 'stat_strength', operator: CONDITION_OPERATOR.LESS_THAN, value: 15 }
798
+ ]
799
+ }
800
+ ],
801
+ x: 400,
802
+ y: 1150
803
+ },
804
+ final_message: {
805
+ id: 'final_message',
806
+ type: NODE_TYPE.NPC,
807
+ speaker: 'Narrator',
808
+ content: 'Your adventure continues...\n\nThis example demonstrates:\n- Conditional nodes with if/elseif/else\n- Conditional choices on player nodes\n- Multiple flag types (quest, achievement, item, stat, title, global, dialogue)\n- Complex conditions with various operators\n- Flag setting throughout the dialogue flow',
809
+ x: 400,
810
+ y: 1300
811
+ }
812
+ }
813
+ }
814
+ };