[{"data":1,"prerenderedAt":1401},["ShallowReactive",2],{"doc-global_essentials\u002Fdungeons\u002Fglossary":3},{"id":4,"title":5,"body":6,"description":449,"extension":1393,"meta":1394,"navigation":550,"path":1397,"seo":1398,"stem":1399,"__hash__":1400},"docs\u002Fdocs\u002Fglobal_essentials\u002Fdungeons\u002Fglossary.md","Glossary",{"type":7,"value":8,"toc":1382},"minimark",[9,13,18,46,49,115,118,132,135,138,142,148,156,159,220,223,240,242,246,252,289,292,300,302,306,315,342,345,421,436,443,632,635,643,645,649,655,662,665,688,691,707,713,789,792,798,801,813,815,819,828,847,853,861,878,881,887,890,912,925,944,970,973,979,982,1001,1008,1010,1014,1020,1031,1053,1056,1114,1120,1197,1207,1213,1220,1222,1226,1236,1254,1262,1268,1274,1298,1301,1305,1308,1314,1316,1320,1327,1333,1336,1353,1363,1370,1378],[10,11,5],"h1",{"id":12},"glossary",[14,15,17],"h3",{"id":16},"dryadscript-markup-how-dungeons-are-written","DryadScript Markup: How Dungeons Are Written",[19,20,21,22,26,27,30,31,38,39,45],"p",{},"Dungeon content uses a lightweight markup called ",[23,24,25],"strong",{},"DryadScript",".",[28,29],"br",{},"\nYou'll usually write it in the ",[23,32,33],{},[34,35,37],"a",{"href":36},"\u002Fdocs\u002Fglobal_essentials\u002Fdungeons\u002Fvisual_editor","Visual Editor"," (recommended); you can also author in ",[23,40,41],{},[34,42,44],{"href":43},"\u002Fdocs\u002Fglobal_essentials\u002Fdungeons\u002Fgoogle_docs_integration","Google Docs Integration"," for collaboration.",[19,47,48],{},"At a high level, you use special markers to tell the engine what each piece of text is:",[50,51,52,63,73,83,97,106],"ul",{},[53,54,55,59,60,26],"li",{},[56,57,58],"code",{},"^room_id"," – start content for a ",[23,61,62],{},"room",[53,64,65,68,69,72],{},[56,66,67],{},"@description"," – the ",[23,70,71],{},"description encounter"," for that room.",[53,74,75,78,79,82],{},[56,76,77],{},"@some_encounter"," – a specific ",[23,80,81],{},"encounter"," in that room.",[53,84,85,88,89,92,93,96],{},[56,86,87],{},"!"," and ",[56,90,91],{},"~"," – ",[23,94,95],{},"choices"," and branching logic.",[53,98,99,92,102,105],{},[56,100,101],{},"#",[23,103,104],{},"events"," that can be triggered manually or automatically when conditions are met.",[53,107,108,111,112,26],{},[56,109,110],{},"character_id:"," – prefix dialogue with a character ID to set the ",[23,113,114],{},"speaker",[19,116,117],{},"The engine parses this text into structured data and uses it to drive:",[50,119,120,123,126,129],{},[53,121,122],{},"What the player sees when they enter a room.",[53,124,125],{},"Which encounters are visible or clickable.",[53,127,128],{},"Which choices appear and where they lead.",[53,130,131],{},"When events fire and how they change the game state.",[19,133,134],{},"You can build surprisingly rich dungeons just by writing text and using these markers.",[136,137],"hr",{},[14,139,141],{"id":140},"flags-dungeon-memory","Flags: Dungeon Memory",[19,143,144,147],{},[23,145,146],{},"Flags"," are small numeric values the dungeon uses to remember what has happened:",[50,149,150,153],{},[53,151,152],{},"Whether a room was visited, a choice was picked, a chest was opened, a scene was seen, etc.",[53,154,155],{},"They live in the dungeon’s data and are saved\u002Floaded with the game.",[19,157,158],{},"Key ideas:",[50,160,161,175,186],{},[53,162,163,164,167,168,171,172,26],{},"Flags are referenced by ",[23,165,166],{},"ID",", like ",[56,169,170],{},"door_opened"," or ",[56,173,174],{},"tutorial.completed_intro",[53,176,177,178,181,182,185],{},"You can scope a flag to another dungeon using ",[56,179,180],{},"dungeon_id.flag_id"," (for example, ",[56,183,184],{},"tutorial.seen_intro",").",[53,187,188,189,171,192,195,196,199,200],{},"Flags can be ",[23,190,191],{},"set",[23,193,194],{},"modified"," via the ",[56,197,198],{},"flag"," action, e.g.:\n",[50,201,202,208,214],{},[53,203,204,207],{},[56,205,206],{},"door_opened=1"," – set a value.",[53,209,210,213],{},[56,211,212],{},"coins>5"," – add 5 coins.",[53,215,216,219],{},[56,217,218],{},"coins\u003C2"," – subtract 2 coins.",[19,221,222],{},"You usually:",[50,224,225,231],{},[53,226,227,230],{},[23,228,229],{},"Change flags"," in actions blocks (for example when a choice is picked).",[53,232,233,236,237,239],{},[23,234,235],{},"Read flags"," in conditions (for branching) or via the ",[56,238,198],{}," placeholder (see below) to show values in text.",[136,241],{},[14,243,245],{"id":244},"anchors-named-jump-points-in-content","Anchors: Named Jump Points in Content",[19,247,248,251],{},[23,249,250],{},"Anchors"," let you mark important spots in your dungeon content and jump to them later.",[50,253,254,261],{},[53,255,256,257,260],{},"Conceptually, an anchor is a ",[23,258,259],{},"named scene target"," inside a dungeon.",[53,262,263,264,267,268,271,272],{},"You can reference an anchor in ",[23,265,266],{},"scene‑type actions"," using the ",[56,269,270],{},"&"," prefix:\n",[50,273,274,283],{},[53,275,276,279,280,26],{},[56,277,278],{},"&my_anchor"," – jump to an anchor in the ",[23,281,282],{},"current dungeon",[53,284,285,288],{},[56,286,287],{},"&other_dungeon.my_anchor"," – jump to an anchor in another dungeon.",[19,290,291],{},"The engine’s dungeon system resolves these via its scene resolver, so you can:",[50,293,294,297],{},[53,295,296],{},"Keep your document readable (anchors have human‑friendly names).",[53,298,299],{},"Reuse the same content from multiple rooms, encounters, or even other dungeons.",[136,301],{},[14,303,305],{"id":304},"actions-things-that-happen","Actions: Things That Happen",[19,307,308,311,312,314],{},[23,309,310],{},"Actions"," are commands executed when a scene, event, or choice runs.",[28,313],{},"\nThey live inside curly‑brace blocks in your content (usually coming from Google Docs), for example:",[50,316,317,322,327,332,337],{},[53,318,319],{},[56,320,321],{},"{flag: \"door_opened=1\"}",[53,323,324],{},[56,325,326],{},"{enter: \"tutorial.entrance\"}",[53,328,329],{},[56,330,331],{},"{scene: \"&intro_scene\"}",[53,333,334],{},[56,335,336],{},"{asset: \"bg_room\"}",[53,338,339],{},[56,340,341],{},"{quest: \"my_cool_quest.main.first_stage\"}",[19,343,344],{},"Broad groups of actions (see the Actions Reference for full lists):",[50,346,347,370,383,400],{},[53,348,349,92,352,355,356,355,359,355,362,355,365,355,367,26],{},[23,350,351],{},"Flow & navigation",[56,353,354],{},"scene",", ",[56,357,358],{},"enter",[56,360,361],{},"exit",[56,363,364],{},"redirect",[56,366,95],{},[56,368,369],{},"choices_over",[53,371,372,92,375,355,377,355,380,26],{},[23,373,374],{},"State & progression",[56,376,198],{},[56,378,379],{},"state",[56,381,382],{},"quest",[53,384,385,92,388,355,391,355,394,355,397,26],{},[23,386,387],{},"Visuals & audio",[56,389,390],{},"music",[56,392,393],{},"sound",[56,395,396],{},"asset",[56,398,399],{},"actor",[53,401,402,92,405,355,408,355,411,355,414,355,417,420],{},[23,403,404],{},"UI & systems",[56,406,407],{},"popup",[56,409,410],{},"notification",[56,412,413],{},"loot",[56,415,416],{},"trade",[56,418,419],{},"learn_recipe",", etc.",[19,422,423,424,427,428,431,432,435],{},"You can also define ",[23,425,426],{},"custom actions"," in JavaScript via ",[56,429,430],{},"game.registerAction(...)"," (see the Tutorial’s ",[56,433,434],{},"script1.mjs"," for examples) and then call them from your content the same way you call built‑in ones.",[19,437,438,439,442],{},"Example – custom ",[56,440,441],{},"genderbend"," action (from the Tutorial game):",[444,445,450],"pre",{"className":446,"code":447,"language":448,"meta":449,"style":449},"language-js shiki shiki-themes github-light github-dark","\u002F\u002F In your script file, e.g. \u002Fassets\u002Fgames_assets\u002F[game]\u002F_core\u002Fscripts\u002Fscript1.mjs\ngame.registerAction(\"genderbend\", () => {\n  const mc = game.getCharacter(\"mc\");         \u002F\u002F get main character\n  const sex = mc.getAttribute(\"sex\");         \u002F\u002F read current sex attribute\n\n  if (sex === \"male\") {\n    mc.setAttribute(\"sex\", \"female\");\n  } else {\n    mc.setAttribute(\"sex\", \"male\");\n  }\n});\n","js","",[56,451,452,461,489,519,545,552,570,591,602,620,626],{"__ignoreMap":449},[453,454,457],"span",{"class":455,"line":456},"line",1,[453,458,460],{"class":459},"sJ8bj","\u002F\u002F In your script file, e.g. \u002Fassets\u002Fgames_assets\u002F[game]\u002F_core\u002Fscripts\u002Fscript1.mjs\n",[453,462,464,468,472,475,479,482,486],{"class":455,"line":463},2,[453,465,467],{"class":466},"sVt8B","game.",[453,469,471],{"class":470},"sScJk","registerAction",[453,473,474],{"class":466},"(",[453,476,478],{"class":477},"sZZnC","\"genderbend\"",[453,480,481],{"class":466},", () ",[453,483,485],{"class":484},"szBVR","=>",[453,487,488],{"class":466}," {\n",[453,490,492,495,499,502,505,508,510,513,516],{"class":455,"line":491},3,[453,493,494],{"class":484},"  const",[453,496,498],{"class":497},"sj4cs"," mc",[453,500,501],{"class":484}," =",[453,503,504],{"class":466}," game.",[453,506,507],{"class":470},"getCharacter",[453,509,474],{"class":466},[453,511,512],{"class":477},"\"mc\"",[453,514,515],{"class":466},");         ",[453,517,518],{"class":459},"\u002F\u002F get main character\n",[453,520,522,524,527,529,532,535,537,540,542],{"class":455,"line":521},4,[453,523,494],{"class":484},[453,525,526],{"class":497}," sex",[453,528,501],{"class":484},[453,530,531],{"class":466}," mc.",[453,533,534],{"class":470},"getAttribute",[453,536,474],{"class":466},[453,538,539],{"class":477},"\"sex\"",[453,541,515],{"class":466},[453,543,544],{"class":459},"\u002F\u002F read current sex attribute\n",[453,546,548],{"class":455,"line":547},5,[453,549,551],{"emptyLinePlaceholder":550},true,"\n",[453,553,555,558,561,564,567],{"class":455,"line":554},6,[453,556,557],{"class":484},"  if",[453,559,560],{"class":466}," (sex ",[453,562,563],{"class":484},"===",[453,565,566],{"class":477}," \"male\"",[453,568,569],{"class":466},") {\n",[453,571,573,576,579,581,583,585,588],{"class":455,"line":572},7,[453,574,575],{"class":466},"    mc.",[453,577,578],{"class":470},"setAttribute",[453,580,474],{"class":466},[453,582,539],{"class":477},[453,584,355],{"class":466},[453,586,587],{"class":477},"\"female\"",[453,589,590],{"class":466},");\n",[453,592,594,597,600],{"class":455,"line":593},8,[453,595,596],{"class":466},"  } ",[453,598,599],{"class":484},"else",[453,601,488],{"class":466},[453,603,605,607,609,611,613,615,618],{"class":455,"line":604},9,[453,606,575],{"class":466},[453,608,578],{"class":470},[453,610,474],{"class":466},[453,612,539],{"class":477},[453,614,355],{"class":466},[453,616,617],{"class":477},"\"male\"",[453,619,590],{"class":466},[453,621,623],{"class":455,"line":622},10,[453,624,625],{"class":466},"  }\n",[453,627,629],{"class":455,"line":628},11,[453,630,631],{"class":466},"});\n",[19,633,634],{},"Then in your dungeon content you can call it like any other action:",[444,636,641],{"className":637,"code":639,"language":640,"meta":449},[638],"language-text","riko: Want to try something different?\n{ genderbend: true }\n","text",[56,642,639],{"__ignoreMap":449},[136,644],{},[14,646,648],{"id":647},"placeholders-live-values-inside-text","Placeholders: Live Values Inside Text",[19,650,651,654],{},[23,652,653],{},"Placeholders"," let you inject dynamic values into text, using the syntax:",[50,656,657],{},[53,658,659],{},[56,660,661],{},"|placeholderName(arg1, arg2)|",[19,663,664],{},"Examples:",[50,666,667,676,682],{},[53,668,669,672,673,26],{},[56,670,671],{},"|flag(coins)|"," – show the current value of a dungeon flag called ",[56,674,675],{},"coins",[53,677,678,681],{},[56,679,680],{},"|item|"," – show the display name of an active item.",[53,683,684,687],{},[56,685,686],{},"|mc|"," – show the main character’s name (as implemented in the Tutorial script).",[19,689,690],{},"Under the hood:",[50,692,693,701],{},[53,694,695,696,88,698,185],{},"The engine provides some built‑in placeholders (like ",[56,697,198],{},[56,699,700],{},"item",[53,702,703,704,26],{},"You can register your own via ",[56,705,706],{},"game.registerPlaceholder(\"name\", (args...) => value)",[19,708,438,709,712],{},[56,710,711],{},"mc"," placeholder (from the Tutorial game):",[444,714,716],{"className":446,"code":715,"language":448,"meta":449,"style":449},"\u002F\u002F Shows the main character's current name when you use |mc| in text\ngame.registerPlaceholder(\"mc\", () => {\n  const mc = game.getCharacter(\"mc\");\n  return mc.getTrait(\"name\") || \"\";\n});\n",[56,717,718,723,740,758,785],{"__ignoreMap":449},[453,719,720],{"class":455,"line":456},[453,721,722],{"class":459},"\u002F\u002F Shows the main character's current name when you use |mc| in text\n",[453,724,725,727,730,732,734,736,738],{"class":455,"line":463},[453,726,467],{"class":466},[453,728,729],{"class":470},"registerPlaceholder",[453,731,474],{"class":466},[453,733,512],{"class":477},[453,735,481],{"class":466},[453,737,485],{"class":484},[453,739,488],{"class":466},[453,741,742,744,746,748,750,752,754,756],{"class":455,"line":491},[453,743,494],{"class":484},[453,745,498],{"class":497},[453,747,501],{"class":484},[453,749,504],{"class":466},[453,751,507],{"class":470},[453,753,474],{"class":466},[453,755,512],{"class":477},[453,757,590],{"class":466},[453,759,760,763,765,768,770,773,776,779,782],{"class":455,"line":521},[453,761,762],{"class":484},"  return",[453,764,531],{"class":466},[453,766,767],{"class":470},"getTrait",[453,769,474],{"class":466},[453,771,772],{"class":477},"\"name\"",[453,774,775],{"class":466},") ",[453,777,778],{"class":484},"||",[453,780,781],{"class":477}," \"\"",[453,783,784],{"class":466},";\n",[453,786,787],{"class":455,"line":547},[453,788,631],{"class":466},[19,790,791],{},"Usage in dungeon content:",[444,793,796],{"className":794,"code":795,"language":640,"meta":449},[638],"mc: My name is |mc|.\n",[56,797,795],{"__ignoreMap":449},[19,799,800],{},"Placeholders are great for:",[50,802,803,810],{},[53,804,805,806,809],{},"Referring to ",[23,807,808],{},"flag values"," in narration (for example, “You have |flag(coins)| coins left.”).",[53,811,812],{},"Showing character names, item names, and other data that can change during play.",[136,814],{},[14,816,818],{"id":817},"if-conditional-actions-and-inline-text","If: Conditional Actions and Inline Text",[19,820,821,822,827],{},"The ",[23,823,824],{},[56,825,826],{},"if"," keyword comes in two closely related flavors:",[829,830,831,838],"ol",{},[53,832,833,834,837],{},"As an ",[23,835,836],{},"action",", attached to a choice, encounter, or event.",[53,839,833,840,843,844,846],{},[23,841,842],{},"inline text block",", which can also include ",[56,845,599],{}," branches.",[19,848,849,850,26],{},"Both use the ",[23,851,852],{},"same condition syntax",[854,855,857,858,860],"h4",{"id":856},"_1-if-as-an-action-on-choices-encounters-events","1) ",[56,859,826],{}," as an action on choices \u002F encounters \u002F events",[19,862,863,864,866,867,869,870,873,874,877],{},"You can attach ",[56,865,826],{}," directly to a choice, encounter, or event via its action block.",[28,868],{},"\nIf the condition is ",[23,871,872],{},"false",", that block simply ",[23,875,876],{},"won’t run"," (for example, the choice won’t appear).",[19,879,880],{},"Example – a clickable encounter that only appears when a button is working:",[444,882,885],{"className":883,"code":884,"language":640,"meta":449},[638],"!click{if: \"button_working = 1\"}\nPress the button.\n",[56,886,884],{"__ignoreMap":449},[19,888,889],{},"Here:",[50,891,892,898,909],{},[53,893,894,897],{},[56,895,896],{},"if: \"button_working = 1\""," uses the same comparison syntax as other conditions.",[53,899,900,901,904,905,908],{},"When the player has ",[56,902,903],{},"button_working = 1",", the ",[56,906,907],{},"!click"," choice is available.",[53,910,911],{},"Otherwise, the engine skips this choice entirely.",[854,913,915,916,918,919,918,921,924],{"id":914},"_2-if-else-fi-inside-dungeon-text","2) ",[56,917,826],{}," \u002F ",[56,920,599],{},[56,922,923],{},"fi"," inside dungeon text",[19,926,927,928,931,932,934,935,943],{},"Inside normal dungeon text you can use ",[23,929,930],{},"inline if‑blocks"," to show different lines based on conditions.",[28,933],{},"\nUnlike the action form, ",[23,936,937,938,88,940],{},"inline if‑blocks support ",[56,939,599],{},[56,941,942],{},"else if",", using this pattern:",[50,945,946,952,958,964],{},[53,947,948,951],{},[56,949,950],{},"if{condition}"," – start a conditional block.",[53,953,954,957],{},[56,955,956],{},"else{condition}"," – optional “else if” branch (the condition is optional).",[53,959,960,963],{},[56,961,962],{},"else{}"," – final “else” branch (no condition).",[53,965,966,969],{},[56,967,968],{},"fi{}"," – closes the whole block.",[19,971,972],{},"Example – describing a button differently based on how many times it was pressed:",[444,974,977],{"className":975,"code":976,"language":640,"meta":449},[638],"You see a button. It is\nif{button_pressed \u003C 2}\nworking\nelse{button_pressed \u003C 3}\nalmost broken\nelse{}\nbroken\nfi{}\n",[56,978,976],{"__ignoreMap":449},[19,980,981],{},"In words:",[50,983,984,991,998],{},[53,985,986,987,990],{},"If ",[56,988,989],{},"button_pressed \u003C 2",", the player sees “working”.",[53,992,993,994,997],{},"Else, if ",[56,995,996],{},"button_pressed \u003C 3",", they see “almost broken”.",[53,999,1000],{},"Otherwise they see “broken”.",[19,1002,1003,1004,1007],{},"This lets you keep your narrative ",[23,1005,1006],{},"branchy and reactive"," directly in the text, without splitting everything into separate events.",[136,1009],{},[14,1011,1013],{"id":1012},"conditions-branching-and-checks","Conditions: Branching and Checks",[19,1015,1016,1019],{},[23,1017,1018],{},"Conditions"," works the same way as flags but provide custom logic to decide whether a block of content should run or a choice should be available.",[19,1021,1022,1023,1026,1027,1030],{},"They are used inside if statements and compare a ",[23,1024,1025],{},"left‑hand side"," to a ",[23,1028,1029],{},"right‑hand side",", for example:",[50,1032,1033,1038,1043,1048],{},[53,1034,1035],{},[56,1036,1037],{},"_room_visited(tutorial.entrance) = true",[53,1039,1040],{},[56,1041,1042],{},"_selected_character = alice",[53,1044,1045],{},[56,1046,1047],{},"_item_on(alice, sword) = true",[53,1049,1050],{},[56,1051,1052],{},"_char(alice.attribute.sex) = female",[19,1054,1055],{},"Concepts:",[50,1057,1058,1072,1107],{},[53,1059,1060,1061,1064,1065,1068,1069,26],{},"Condition names starting with ",[56,1062,1063],{},"_"," (underscore) refer to ",[23,1066,1067],{},"condition functions",", registered in code via ",[56,1070,1071],{},"game.registerCondition(...)",[53,1073,1074,1075],{},"The engine comes with several built‑ins for dungeons, like:\n",[50,1076,1077,1083,1089,1095,1101],{},[53,1078,1079,1082],{},[56,1080,1081],{},"_room_visited(dungeonId.roomId)"," – has the room ever been visited?",[53,1084,1085,1088],{},[56,1086,1087],{},"_scene"," – is there an active scene right now?",[53,1090,1091,1094],{},[56,1092,1093],{},"_selected_character"," – ID of the currently selected character.",[53,1096,1097,1100],{},[56,1098,1099],{},"_item_on(characterId, itemId)"," – whether a character has an item equipped.",[53,1102,1103,1106],{},[56,1104,1105],{},"_char(charId.type.key)"," – access character traits, attributes, stats, resources, or skin styles.",[53,1108,1109,1110,1113],{},"You can define your own conditions (for example ",[56,1111,1112],{},"_female(mc) = true",") in scripts and use them directly in dungeon text.",[19,1115,438,1116,1119],{},[56,1117,1118],{},"_female"," condition (from the Tutorial game):",[444,1121,1123],{"className":446,"code":1122,"language":448,"meta":449,"style":449},"\u002F\u002F Returns true if the given character is female\ngame.registerCondition(\"_female\", (charId) => {\n  const char = game.getCharacter(charId);\n  return char.getAttribute(\"sex\") === \"female\";\n});\n",[56,1124,1125,1130,1155,1171,1193],{"__ignoreMap":449},[453,1126,1127],{"class":455,"line":456},[453,1128,1129],{"class":459},"\u002F\u002F Returns true if the given character is female\n",[453,1131,1132,1134,1137,1139,1142,1145,1149,1151,1153],{"class":455,"line":463},[453,1133,467],{"class":466},[453,1135,1136],{"class":470},"registerCondition",[453,1138,474],{"class":466},[453,1140,1141],{"class":477},"\"_female\"",[453,1143,1144],{"class":466},", (",[453,1146,1148],{"class":1147},"s4XuR","charId",[453,1150,775],{"class":466},[453,1152,485],{"class":484},[453,1154,488],{"class":466},[453,1156,1157,1159,1162,1164,1166,1168],{"class":455,"line":491},[453,1158,494],{"class":484},[453,1160,1161],{"class":497}," char",[453,1163,501],{"class":484},[453,1165,504],{"class":466},[453,1167,507],{"class":470},[453,1169,1170],{"class":466},"(charId);\n",[453,1172,1173,1175,1178,1180,1182,1184,1186,1188,1191],{"class":455,"line":521},[453,1174,762],{"class":484},[453,1176,1177],{"class":466}," char.",[453,1179,534],{"class":470},[453,1181,474],{"class":466},[453,1183,539],{"class":477},[453,1185,775],{"class":466},[453,1187,563],{"class":484},[453,1189,1190],{"class":477}," \"female\"",[453,1192,784],{"class":466},[453,1194,1195],{"class":455,"line":547},[453,1196,631],{"class":466},[19,1198,1199,1200,1203,1204,1206],{},"Usage in dungeon content (for example, inside an inline ",[56,1201,1202],{},"if{}"," block or an ",[56,1205,826],{}," action):",[444,1208,1211],{"className":1209,"code":1210,"language":640,"meta":449},[638],"if{_female(mc) = true}\nShe smiles in a way that only makes sense if MC is female.\nfi{}\n",[56,1212,1210],{"__ignoreMap":449},[19,1214,1215,1216,1219],{},"Conditions are what make your dungeons ",[23,1217,1218],{},"reactive"," – they look at inventory, party, or any custom logic and decide what the player can see or do.",[136,1221],{},[14,1223,1225],{"id":1224},"templates-reusable-text-blocks","Templates: Reusable Text Blocks",[19,1227,1228,1231,1232,1235],{},[23,1229,1230],{},"Templates"," are dungeon lines whose ID starts with ",[56,1233,1234],{},"$",". They let you store reusable text snippets and compose them into larger narratives.",[50,1237,1238,1244,1247],{},[53,1239,1240,1241,26],{},"Reference a template in text with ",[56,1242,1243],{},"|$template_id|",[53,1245,1246],{},"The engine resolves the template's content through the full text pipeline (placeholders, conditions, nested templates, etc.).",[53,1248,1249,1250,1253],{},"Cross-dungeon: ",[56,1251,1252],{},"|$other_dungeon.template_id|"," fetches from a different dungeon.",[854,1255,1257,1258,1261],{"id":1256},"variants-n","Variants (",[56,1259,1260],{},"~N",")",[19,1263,1264,1265,1267],{},"Any template can have numbered variants using the ",[56,1266,91],{}," suffix:",[444,1269,1272],{"className":1270,"code":1271,"language":640,"meta":449},[638],"$greeting\nHello there!\n\n$greeting~2\nHey, what's up?\n\n$greeting~3\nGreetings, traveler.\n",[56,1273,1271],{"__ignoreMap":449},[19,1275,1276,1277,1280,1281,355,1284,355,1287,1290,1291,1294,1295,1297],{},"When the engine resolves ",[56,1278,1279],{},"|$greeting|",", it automatically detects all variants (",[56,1282,1283],{},"$greeting",[56,1285,1286],{},"$greeting~2",[56,1288,1289],{},"$greeting~3",") and ",[23,1292,1293],{},"randomly picks one",". No special syntax needed from the caller – just write ",[56,1296,1279],{}," and the engine handles the rest.",[19,1299,1300],{},"This is useful for adding variety to repeated text (encounter descriptions, NPC reactions, flavor text) without any scripting.",[854,1302,1304],{"id":1303},"composition","Composition",[19,1306,1307],{},"Templates can reference other templates, creating a composition tree:",[444,1309,1312],{"className":1310,"code":1311,"language":640,"meta":449},[638],"$battle_scene\n|$battle_intro| |$battle_body|\n\n$battle_intro\nThe enemy charges forward.\n\n$battle_body\nif{_has_allies = true}Your allies stand beside you.else{}You face them alone.fi{}\n",[56,1313,1311],{"__ignoreMap":449},[136,1315],{},[14,1317,1319],{"id":1318},"talking-characters-speaker-attribution","Talking Characters: Speaker Attribution",[19,1321,1322,1323,1326],{},"When writing dialogue, you can prefix a line with a ",[23,1324,1325],{},"character ID"," followed by a colon to indicate who is speaking:",[444,1328,1331],{"className":1329,"code":1330,"language":640,"meta":449},[638],"riko: Hey there! I'm Riko. Welcome to this tutorial!\n\nmc: Nice to meet you.\n",[56,1332,1330],{"__ignoreMap":449},[19,1334,1335],{},"The engine automatically:",[829,1337,1338,1347,1350],{},[53,1339,1340,1341,171,1344,1346],{},"Extracts the character ID (e.g., ",[56,1342,1343],{},"riko",[56,1345,711],{},") from the prefix.",[53,1348,1349],{},"Sets the current speaker, so the UI can display their name, portrait, and dialogue box styling.",[53,1351,1352],{},"Returns just the dialogue text (everything after the colon) for display.",[19,1354,1355,1358,1359,1362],{},[23,1356,1357],{},"Important:"," The character ID must match a ",[23,1360,1361],{},"live character instance"," – meaning the character must be defined in the editor and exist in the game's character system. If the ID doesn't match any registered character, the engine won't know which portrait or name to display.",[19,1364,1365,1366,26],{},"To create and configure characters, see ",[34,1367,1369],{"href":1368},"\u002Fdocs\u002Fglobal_essentials\u002Fcharacters\u002Fcharacters_overview","Overview",[19,1371,1372,1373,1377],{},"To see a list of all registered characters during development, use ",[34,1374,1376],{"href":1375},"\u002Fdocs\u002Fglobal_essentials\u002Fadvanced\u002Fdebugging","Debugging"," – the debug panel shows which characters are currently loaded.",[1379,1380,1381],"style",{},"html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}",{"title":449,"searchDepth":463,"depth":463,"links":1383},[1384,1385,1386,1387,1388,1389,1390,1391,1392],{"id":16,"depth":491,"text":17},{"id":140,"depth":491,"text":141},{"id":244,"depth":491,"text":245},{"id":304,"depth":491,"text":305},{"id":647,"depth":491,"text":648},{"id":817,"depth":491,"text":818},{"id":1012,"depth":491,"text":1013},{"id":1224,"depth":491,"text":1225},{"id":1318,"depth":491,"text":1319},"md",{"plugin":1395,"category":1396,"page":12},"global_essentials","dungeons","\u002Fdocs\u002Fglobal_essentials\u002Fdungeons\u002Fglossary",{"title":5,"description":449},"docs\u002Fglobal_essentials\u002Fdungeons\u002Fglossary","lXkrIZawkyb3vZkyYnWFtoMTuCpuc2_SKVdWS0NMF44",1779582261012]