[{"data":1,"prerenderedAt":755},["ShallowReactive",2],{"docs-navigation":3,"docs-\u002Fdocumentation\u002Ftutorials\u002Fdialogue-system-for-godot":102},[4],{"title":5,"path":6,"stem":7,"children":8},"LoreHub Dialogue System","\u002Fdocumentation","1.documentation\u002F0.index",[9,10,28,41],{"title":5,"path":6,"stem":7},{"title":11,"path":12,"stem":13,"children":14},"","\u002Fdocumentation\u002Fintroduction","1.documentation\u002F1.introduction\u002F0.index",[15,16,20,24],{"title":11,"path":12,"stem":13},{"title":17,"path":18,"stem":19},"Dialogue Schema","\u002Fdocumentation\u002Fintroduction\u002Fdialogue-system","1.documentation\u002F1.introduction\u002F1.dialogue-system",{"title":21,"path":22,"stem":23},"Concept","\u002Fdocumentation\u002Fintroduction\u002Fconcept","1.documentation\u002F1.introduction\u002F2.concept",{"title":25,"path":26,"stem":27},"Examples","\u002Fdocumentation\u002Fintroduction\u002Fexamples","1.documentation\u002F1.introduction\u002F3.examples",{"title":11,"path":29,"stem":30,"children":31},"\u002Fdocumentation\u002Ftutorials","1.documentation\u002F2.Tutorials\u002F0.index",[32,33,37],{"title":11,"path":29,"stem":30},{"title":34,"path":35,"stem":36},"Dialogue System for Unity","\u002Fdocumentation\u002Ftutorials\u002Fdialogue-system-for-unity","1.documentation\u002F2.Tutorials\u002F1.dialogue-system-for-Unity",{"title":38,"path":39,"stem":40},"Dialogue System for Godot","\u002Fdocumentation\u002Ftutorials\u002Fdialogue-system-for-godot","1.documentation\u002F2.Tutorials\u002F2.dialogue-system-for-Godot",{"title":11,"path":42,"stem":43,"children":44},"\u002Fdocumentation\u002Fdialogue-schema-api","1.documentation\u002F3.Dialogue-Schema-API\u002F0.index",[45,46,50,54,58,62,66,70,74,78,82,86,90,94,98],{"title":11,"path":42,"stem":43},{"title":47,"path":48,"stem":49},"Export Schema v.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fexport-schema-v1","1.documentation\u002F3.Dialogue-Schema-API\u002F1.export-schema-v1",{"title":51,"path":52,"stem":53},"Export Schema v.2","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fexport-schema-v2","1.documentation\u002F3.Dialogue-Schema-API\u002F1.export-schema-v2",{"title":55,"path":56,"stem":57},"Document v.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fdocument-v1","1.documentation\u002F3.Dialogue-Schema-API\u002F2.document-v1",{"title":59,"path":60,"stem":61},"Dialogue v.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fdialogue-v1","1.documentation\u002F3.Dialogue-Schema-API\u002F3.dialogue-v1",{"title":63,"path":64,"stem":65},"Dialogue v.2","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fdialogue-v2","1.documentation\u002F3.Dialogue-Schema-API\u002F3.dialogue-v2",{"title":67,"path":68,"stem":69},"Dialogue Node v.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fdialogue-node-v1","1.documentation\u002F3.Dialogue-Schema-API\u002F4.dialogue-node-v1",{"title":71,"path":72,"stem":73},"Dialogue Node v.2","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fdialogue-node-v2","1.documentation\u002F3.Dialogue-Schema-API\u002F4.dialogue-node-v2",{"title":75,"path":76,"stem":77},"Dialogue Node Option v.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fdialogue-node-option-v1","1.documentation\u002F3.Dialogue-Schema-API\u002F5.dialogue-node-option-v1",{"title":79,"path":80,"stem":81},"Dialogue Node Option v.2","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fdialogue-node-option-v2","1.documentation\u002F3.Dialogue-Schema-API\u002F5.dialogue-node-option-v2",{"title":83,"path":84,"stem":85},"Variable v.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fvariable-v1","1.documentation\u002F3.Dialogue-Schema-API\u002F6.variable-v1",{"title":87,"path":88,"stem":89},"Meta Schema v.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fmeta-schema-v1","1.documentation\u002F3.Dialogue-Schema-API\u002F7.meta-schema-v1",{"title":91,"path":92,"stem":93},"Content Block v.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Fcontent-block-v1","1.documentation\u002F3.Dialogue-Schema-API\u002F8.content-block-v1",{"title":95,"path":96,"stem":97},"Link v.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Flink-v1","1.documentation\u002F3.Dialogue-Schema-API\u002F9.link-v1",{"title":99,"path":100,"stem":101},"Link v.1.1","\u002Fdocumentation\u002Fdialogue-schema-api\u002Flink-v1-1","1.documentation\u002F3.Dialogue-Schema-API\u002F9.link-v1-1",{"id":103,"title":38,"body":104,"description":750,"extension":751,"meta":752,"navigation":337,"path":39,"seo":753,"stem":40,"__hash__":754},"docs\u002F1.documentation\u002F2.Tutorials\u002F2.dialogue-system-for-Godot.md",{"type":105,"value":106,"toc":737},"minimark",[107,111,126,136,142,147,173,179,184,188,208,212,216,237,241,244,273,277,284,288,291,294,309,312,316,322,450,453,488,493,507,511,521,525,528,698,702,721,725,733],[108,109,38],"h1",{"id":110},"dialogue-system-for-godot",[112,113,114,115,119,120,125],"p",{},"The ",[116,117,118],"strong",{},"LoreHub Dialogue Player"," addon plays dialogues you export from LoreHub in Godot 4.3 and later. It reads ",[121,122,124],"a",{"href":123},"..\u002Fdialogue-schema-api\u002Fexport-schema-v2","Export Schema v2"," JSON and follows the same rules as the player in LoreHub: options, links with conditions, number and boolean variables, played and selected state, and node meta data. It is pure GDScript, so it works in the standard and .NET builds of Godot and in every export target, web included.",[112,127,128,129,135],{},"The addon is free and open source under MIT: ",[121,130,134],{"href":131,"rel":132},"https:\u002F\u002Fgithub.com\u002Flostwood-games\u002Florehub-dialogue-player-godot",[133],"nofollow","lostwood-games\u002Florehub-dialogue-player-godot",".",[137,138],"img",{"src":139,"alt":140,"width":141},"\u002Fimages\u002Fdocs\u002Fgodot-tavern-sample.png","A LoreHub dialogue playing in Godot",1000,[143,144,146],"h2",{"id":145},"_1-install-the-addon","1. Install the addon",[112,148,149,150,153,154,157,158,163,164,168,169,172],{},"In the Godot editor open the ",[116,151,152],{},"Asset Store"," tab, search for ",[116,155,156],{},"LoreHub"," and install LoreHub Dialogue Player. You can also download the zip from the ",[121,159,162],{"href":160,"rel":161},"https:\u002F\u002Fgithub.com\u002Flostwood-games\u002Florehub-dialogue-player-godot\u002Freleases",[133],"releases on GitHub"," and copy ",[165,166,167],"code",{},"addons\u002Florehub_dialogue"," into your project's ",[165,170,171],{},"addons\u002F"," folder.",[112,174,175,176,135],{},"Then turn the plugin on in ",[116,177,178],{},"Project > Project Settings > Plugins",[137,180],{"src":181,"alt":182,"width":183},"\u002Fimages\u002Fdocs\u002Fgodot-enable-plugin.png","LoreHub Dialogue turned on in Godot's Project Settings, Plugins tab",900,[143,185,187],{"id":186},"_2-export-the-dialogue-from-lorehub","2. Export the dialogue from LoreHub",[112,189,190,191,195,196,199,200,203,204,207],{},"In ",[121,192,156],{"href":193,"target":194},"https:\u002F\u002Fapp.lorehub.app\u002F","_blank"," open the dialogue, go to ",[116,197,198],{},"Export"," and click ",[116,201,202],{},"Export JSON",". The ",[165,205,206],{},".json"," file holds the dialogue's nodes, options, links, variables, characters and node meta data.",[137,209],{"src":210,"alt":211,"width":141},"\u002Fimages\u002Fdocs\u002Florehub-export.png","Export JSON in LoreHub",[143,213,215],{"id":214},"_3-put-the-file-in-your-project","3. Put the file in your project",[112,217,218,219,221,222,225,226,229,230,232,233,236],{},"Drop the ",[165,220,206],{}," file anywhere under ",[165,223,224],{},"res:\u002F\u002F",", for example ",[165,227,228],{},"res:\u002F\u002Fdialogues\u002Ftavern.json",". Godot imports ",[165,231,206],{}," files as ",[165,234,235],{},"JSON"," resources and packs them into exported games, so there is nothing to convert. When the dialogue changes in LoreHub, export it again and overwrite the file.",[143,238,240],{"id":239},"_4-play-it-with-the-dialogue-box","4. Play it with the dialogue box",[112,242,243],{},"The addon comes with a small dialogue box you can use without code:",[245,246,247,258,267],"ol",{},[248,249,250,251,254,255,135],"li",{},"Drag ",[165,252,253],{},"addons\u002Florehub_dialogue\u002Fui\u002Florehub_dialogue_box.tscn"," into your scene, or add it with ",[116,256,257],{},"Instantiate Child Scene",[248,259,260,261,263,264,135],{},"In the Inspector, drag your ",[165,262,206],{}," file onto ",[116,265,266],{},"Dialogue",[248,268,269,270,135],{},"Turn on ",[116,271,272],{},"Autostart",[137,274],{"src":275,"alt":276,"width":141},"\u002Fimages\u002Fdocs\u002Fgodot-dialogue-box-inspector.png","LoreHubDialogueBox in the Godot Inspector with tavern.json assigned to Dialogue",[112,278,279,280,283],{},"Run the scene. The box shows the speaker, the line, a button per option and ",[116,281,282],{},"Continue"," for nodes without options, and hides itself when the dialogue ends.",[137,285],{"src":286,"alt":287,"width":141},"\u002Fimages\u002Fdocs\u002Fgodot-dialogue-box-game.png","The LoreHub dialogue box running in a Godot game",[112,289,290],{},"Options whose conditions fail are hidden. In this dialogue \"Buy a drink (10 gold)\" needs 10 gold and the player has 5, so only two options show. Compare it with the screenshot at the top of the page, where the player has 25 gold.",[112,292,293],{},"To start the box from code instead of Autostart:",[295,296,300],"pre",{"className":297,"code":298,"language":299,"meta":11,"style":11},"language-gdscript shiki shiki-themes dracula-soft","$LoreHubDialogueBox.play(preload(\"res:\u002F\u002Fdialogues\u002Ftavern.json\"))\n","gdscript",[165,301,302],{"__ignoreMap":11},[303,304,307],"span",{"class":305,"line":306},"line",1,[303,308,298],{},[112,310,311],{},"The box is meant as a starting point: copy the scene and restyle it, or build your own UI on the runner.",[143,313,315],{"id":314},"_5-your-own-ui-with-the-runner","5. Your own UI with the runner",[112,317,318,321],{},[165,319,320],{},"LoreHubRunner"," walks the dialogue and tells your UI what to show with signals. Feed your game's state in by LoreHub variable name before you start, and read node meta data on each line to drive the scene.",[295,323,325],{"className":297,"code":324,"language":299,"meta":11,"style":11},"var runner := LoreHubRunner.new(preload(\"res:\u002F\u002Fdialogues\u002Ftavern.json\"))\n\nfunc _ready() -> void:\n    runner.line_started.connect(_on_line)          # LoreHubLine: speaker_name, speaker_id, text, meta, has_options\n    runner.choices_presented.connect(_on_choices)  # Array of LoreHubChoice: id, text, index, available\n    runner.dialogue_finished.connect(_on_finished)\n    runner.set_variable(\"gold\", PlayerData.gold)   # LoreHub variable by name\n    runner.start(\"\", true)                         # true keeps the variable set above\n\nfunc _on_line(line: LoreHubLine) -> void:\n    label.text = \"%s: %s\" % [line.speaker_name, line.text]\n    if line.meta.has(\"event\"):                     # node meta data by name, ints for integer fields\n        trigger(line.meta[\"event\"])\n\nfunc _on_choices(choices: Array) -> void:\n    for choice in choices:\n        add_button(choice.text, runner.choose.bind(choice))\n\n# On Continue for a node without options:\nfunc _on_continue() -> void:\n    runner.advance()\n",[165,326,327,332,339,345,351,357,363,369,375,380,386,392,398,404,409,415,421,427,432,438,444],{"__ignoreMap":11},[303,328,329],{"class":305,"line":306},[303,330,331],{},"var runner := LoreHubRunner.new(preload(\"res:\u002F\u002Fdialogues\u002Ftavern.json\"))\n",[303,333,335],{"class":305,"line":334},2,[303,336,338],{"emptyLinePlaceholder":337},true,"\n",[303,340,342],{"class":305,"line":341},3,[303,343,344],{},"func _ready() -> void:\n",[303,346,348],{"class":305,"line":347},4,[303,349,350],{},"    runner.line_started.connect(_on_line)          # LoreHubLine: speaker_name, speaker_id, text, meta, has_options\n",[303,352,354],{"class":305,"line":353},5,[303,355,356],{},"    runner.choices_presented.connect(_on_choices)  # Array of LoreHubChoice: id, text, index, available\n",[303,358,360],{"class":305,"line":359},6,[303,361,362],{},"    runner.dialogue_finished.connect(_on_finished)\n",[303,364,366],{"class":305,"line":365},7,[303,367,368],{},"    runner.set_variable(\"gold\", PlayerData.gold)   # LoreHub variable by name\n",[303,370,372],{"class":305,"line":371},8,[303,373,374],{},"    runner.start(\"\", true)                         # true keeps the variable set above\n",[303,376,378],{"class":305,"line":377},9,[303,379,338],{"emptyLinePlaceholder":337},[303,381,383],{"class":305,"line":382},10,[303,384,385],{},"func _on_line(line: LoreHubLine) -> void:\n",[303,387,389],{"class":305,"line":388},11,[303,390,391],{},"    label.text = \"%s: %s\" % [line.speaker_name, line.text]\n",[303,393,395],{"class":305,"line":394},12,[303,396,397],{},"    if line.meta.has(\"event\"):                     # node meta data by name, ints for integer fields\n",[303,399,401],{"class":305,"line":400},13,[303,402,403],{},"        trigger(line.meta[\"event\"])\n",[303,405,407],{"class":305,"line":406},14,[303,408,338],{"emptyLinePlaceholder":337},[303,410,412],{"class":305,"line":411},15,[303,413,414],{},"func _on_choices(choices: Array) -> void:\n",[303,416,418],{"class":305,"line":417},16,[303,419,420],{},"    for choice in choices:\n",[303,422,424],{"class":305,"line":423},17,[303,425,426],{},"        add_button(choice.text, runner.choose.bind(choice))\n",[303,428,430],{"class":305,"line":429},18,[303,431,338],{"emptyLinePlaceholder":337},[303,433,435],{"class":305,"line":434},19,[303,436,437],{},"# On Continue for a node without options:\n",[303,439,441],{"class":305,"line":440},20,[303,442,443],{},"func _on_continue() -> void:\n",[303,445,447],{"class":305,"line":446},21,[303,448,449],{},"    runner.advance()\n",[112,451,452],{},"The rules are the same as in LoreHub's player:",[454,455,456,463,474,481],"ul",{},[248,457,458,459,462],{},"Entering a node applies the variables it sets (number variables can be added to or subtracted from; an ",[165,460,461],{},"unsignedNumber"," never goes below 0) and marks it played.",[248,464,465,466,469,470,473],{},"Options show in LoreHub's order. An option whose conditions fail is hidden; set ",[165,467,468],{},"runner.hide_unavailable_choices = false"," to get it with ",[165,471,472],{},"available == false",", for example to grey it out.",[248,475,476,477,480],{},"Picking an option marks it selected and follows its first link whose conditions all pass. ",[165,478,479],{},"advance()"," does the same for a node without options. No passing link ends the dialogue.",[248,482,483,484,135],{},"Conditions can check variables or whether a node was played or an option selected, see ",[121,485,487],{"href":486},"..\u002Fdialogue-schema-api\u002Flink-v1#state-data-conditions","state data conditions",[489,490,492],"h3",{"id":491},"save-and-load","Save and load",[112,494,495,498,499,502,503,506],{},[165,496,497],{},"runner.get_state()"," returns a plain Dictionary (variables by name, played nodes, selected options and the current node) that you can store with your save. ",[165,500,501],{},"runner.set_state(state)"," puts it back, and ",[165,504,505],{},"runner.resume()"," shows the current line again.",[489,508,510],{"id":509},"load-at-runtime","Load at runtime",[112,512,513,514,517,518,520],{},"Dialogues downloaded while the game runs load too: ",[165,515,516],{},"LoreHubDialogue.from_source(\"user:\u002F\u002Fintro.json\")"," takes a path, a ",[165,519,235],{}," resource, a parsed Dictionary or JSON text.",[489,522,524],{"id":523},"from-c","From C#",[112,526,527],{},"The addon is GDScript, so call it through Godot's API:",[295,529,533],{"className":530,"code":531,"language":532,"meta":11,"style":11},"language-csharp shiki shiki-themes dracula-soft","var script = GD.Load\u003CGDScript>(\"res:\u002F\u002Faddons\u002Florehub_dialogue\u002Florehub_runner.gd\");\nvar runner = script.New(GD.Load\u003CResource>(\"res:\u002F\u002Fdialogues\u002Ftavern.json\")).AsGodotObject();\nrunner.Connect(\"line_started\", Callable.From\u003CGodotObject>(line => GD.Print(line.Get(\"text\"))));\nrunner.Call(\"start\");\n","csharp",[165,534,535,578,620,680],{"__ignoreMap":11},[303,536,537,541,545,548,551,555,558,562,565,569,573,575],{"class":305,"line":306},[303,538,540],{"class":539},"suBnA","var",[303,542,544],{"class":543},"sptrb"," script ",[303,546,547],{"class":539},"=",[303,549,550],{"class":543}," GD.",[303,552,554],{"class":553},"sIY5v","Load",[303,556,557],{"class":543},"\u003C",[303,559,561],{"class":560},"sZqyT","GDScript",[303,563,564],{"class":543},">(",[303,566,568],{"class":567},"sWivA","\"",[303,570,572],{"class":571},"sBh-q","res:\u002F\u002Faddons\u002Florehub_dialogue\u002Florehub_runner.gd",[303,574,568],{"class":567},[303,576,577],{"class":543},");\n",[303,579,580,582,585,587,590,593,596,598,600,603,605,607,609,611,614,617],{"class":305,"line":334},[303,581,540],{"class":539},[303,583,584],{"class":543}," runner ",[303,586,547],{"class":539},[303,588,589],{"class":543}," script.",[303,591,592],{"class":553},"New",[303,594,595],{"class":543},"(GD.",[303,597,554],{"class":553},[303,599,557],{"class":543},[303,601,602],{"class":560},"Resource",[303,604,564],{"class":543},[303,606,568],{"class":567},[303,608,228],{"class":571},[303,610,568],{"class":567},[303,612,613],{"class":543},")).",[303,615,616],{"class":553},"AsGodotObject",[303,618,619],{"class":543},"();\n",[303,621,622,625,628,631,633,636,638,641,644,646,649,651,654,657,659,662,665,668,670,672,675,677],{"class":305,"line":341},[303,623,624],{"class":543},"runner.",[303,626,627],{"class":553},"Connect",[303,629,630],{"class":543},"(",[303,632,568],{"class":567},[303,634,635],{"class":571},"line_started",[303,637,568],{"class":567},[303,639,640],{"class":543},", Callable.",[303,642,643],{"class":553},"From",[303,645,557],{"class":543},[303,647,648],{"class":560},"GodotObject",[303,650,564],{"class":543},[303,652,305],{"class":653},"sGEwX",[303,655,656],{"class":539}," =>",[303,658,550],{"class":543},[303,660,661],{"class":553},"Print",[303,663,664],{"class":543},"(line.",[303,666,667],{"class":553},"Get",[303,669,630],{"class":543},[303,671,568],{"class":567},[303,673,674],{"class":571},"text",[303,676,568],{"class":567},[303,678,679],{"class":543},"))));\n",[303,681,682,684,687,689,691,694,696],{"class":305,"line":347},[303,683,624],{"class":543},[303,685,686],{"class":553},"Call",[303,688,630],{"class":543},[303,690,568],{"class":567},[303,692,693],{"class":571},"start",[303,695,568],{"class":567},[303,697,577],{"class":543},[143,699,701],{"id":700},"sample-project","Sample project",[112,703,704,705,708,709,712,713,716,717,720],{},"The addon's repository is a Godot project. Open it and press Play to see ",[165,706,707],{},"samples\u002Ftavern\u002F",", the game screen at the top of this page: a typewriter line with a speaker badge, choices, node meta data driving the scene (",[165,710,711],{},"mood"," tints the background, ",[165,714,715],{},"wait"," delays the line), buttons that feed gold into a LoreHub variable, and save and load in the middle of a dialogue. ",[165,718,719],{},"demo\u002F"," shows the drop-in dialogue box.",[143,722,724],{"id":723},"versions","Versions",[112,726,727,728,135],{},"The first release is 0.1.0. It reads Export Schema 2.x JSON and refuses a file from an unknown major schema version with an error that says to update the addon. Changes are listed in the ",[121,729,732],{"href":730,"rel":731},"https:\u002F\u002Fgithub.com\u002Flostwood-games\u002Florehub-dialogue-player-godot\u002Fblob\u002Fmain\u002FCHANGELOG.md",[133],"changelog",[734,735,736],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .suBnA, html code.shiki .suBnA{--shiki-default:#F286C4}html pre.shiki code .sptrb, html code.shiki .sptrb{--shiki-default:#F6F6F4}html pre.shiki code .sIY5v, html code.shiki .sIY5v{--shiki-default:#62E884}html pre.shiki code .sZqyT, html code.shiki .sZqyT{--shiki-default:#97E1F1;--shiki-default-font-style:italic}html pre.shiki code .sWivA, html code.shiki .sWivA{--shiki-default:#DEE492}html pre.shiki code .sBh-q, html code.shiki .sBh-q{--shiki-default:#E7EE98}html pre.shiki code .sGEwX, html code.shiki .sGEwX{--shiki-default:#FFB86C;--shiki-default-font-style:italic}",{"title":11,"searchDepth":341,"depth":341,"links":738},[739,740,741,742,743,748,749],{"id":145,"depth":334,"text":146},{"id":186,"depth":334,"text":187},{"id":214,"depth":334,"text":215},{"id":239,"depth":334,"text":240},{"id":314,"depth":334,"text":315,"children":744},[745,746,747],{"id":491,"depth":341,"text":492},{"id":509,"depth":341,"text":510},{"id":523,"depth":341,"text":524},{"id":700,"depth":334,"text":701},{"id":723,"depth":334,"text":724},"Play LoreHub dialogues in Godot 4 with the free LoreHub Dialogue Player addon: export JSON, drop it in your project and play it with a ready dialogue box or your own UI.","md",{},{"title":38,"description":750},"wUB8l4Edm7HtLC9adh_qBzaxLTUIqjPjaqdewmaB3C0",1794328421447]