[{"data":1,"prerenderedAt":1473},["ShallowReactive",2],{"doc-global_essentials\u002Fadvanced\u002Fregistry":3},{"id":4,"title":5,"body":6,"description":1464,"extension":1465,"meta":1466,"navigation":164,"path":1469,"seo":1470,"stem":1471,"__hash__":1472},"docs\u002Fdocs\u002Fglobal_essentials\u002Fadvanced\u002Fregistry.md","Registry",{"type":7,"value":8,"toc":1452},"minimark",[9,14,23,26,29,34,44,51,53,57,63,69,74,87,273,284,294,296,300,305,310,314,325,466,473,475,479,484,489,493,504,639,646,648,652,657,662,666,677,769,776,778,782,787,796,800,811,875,882,884,888,893,898,902,913,1083,1091,1093,1097,1102,1107,1111,1122,1349,1362,1364,1368,1371,1410,1413,1415,1419,1448],[10,11,13],"h1",{"id":12},"engine-registry-overview","Engine Registry Overview",[15,16,17,18,22],"p",{},"Dryad Engine uses a ",[19,20,21],"strong",{},"registry system"," to manage all the moving parts of your game. Think of it as a central directory where different systems register themselves so they can talk to each other.",[15,24,25],{},"This page explains each registry type in simple terms. For complete lists and examples, see the linked reference pages.",[27,28],"hr",{},[30,31,33],"h2",{"id":32},"viewing-the-registry-in-game","Viewing the Registry In-Game",[15,35,36,37,40,41,43],{},"During development, you can inspect all registered items in real-time using the ",[19,38,39],{},"Debug Registry"," panel. When you playtest your game from the Engine Editor, the debug panel is visible automatically. Navigate to the ",[19,42,5],{}," tab to see all registered emitters, states, actions, conditions, placeholders, stat computers, and components - including any custom ones you've added via scripts.",[15,45,46],{},[47,48],"img",{"alt":49,"src":50},"registry","\u002Fplay\u002Fassets\u002Fengine_files\u002Fplugins\u002Fglobal_essentials\u002Fdocs\u002Fen\u002Fimages\u002Fregistry.png",[27,52],{},[30,54,56],{"id":55},"lifecycle-emitters","Lifecycle Emitters",[15,58,59,62],{},[19,60,61],{},"What they are:"," Hooks that let you run code when something happens in the game.",[15,64,65,68],{},[19,66,67],{},"How they work:"," The engine broadcasts emitters like \"a character was created\" or \"the player entered a room\". Your scripts can listen for these and react to them.",[15,70,71],{},[19,72,73],{},"Example use cases:",[75,76,77,81,84],"ul",{},[78,79,80],"li",{},"Play a sound when entering a dungeon",[78,82,83],{},"Modify item prices when a shop opens",[78,85,86],{},"Track statistics when characters level up",[88,89,94],"pre",{"className":90,"code":91,"language":92,"meta":93,"style":93},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F Listen to a built-in emitter\ngame.on(\"dungeon_enter\", (dungeonId, roomId) => {\n  \u002F\u002F Your code runs whenever a dungeon is entered\n});\n\n\u002F\u002F Register a custom emitter\ngame.registerEmitter(\"battle_started\");\n\n\u002F\u002F Listen to your custom emitter\ngame.on(\"battle_started\", (enemyId) => {\n  console.log(\"Battle with\", enemyId);\n});\n\n\u002F\u002F Trigger your custom emitter from anywhere\ngame.trigger(\"battle_started\", \"goblin\");\n","javascript","",[95,96,97,106,147,153,159,166,172,188,193,199,221,238,243,248,254],"code",{"__ignoreMap":93},[98,99,102],"span",{"class":100,"line":101},"line",1,[98,103,105],{"class":104},"sJ8bj","\u002F\u002F Listen to a built-in emitter\n",[98,107,109,113,117,120,124,127,131,134,137,140,144],{"class":100,"line":108},2,[98,110,112],{"class":111},"sVt8B","game.",[98,114,116],{"class":115},"sScJk","on",[98,118,119],{"class":111},"(",[98,121,123],{"class":122},"sZZnC","\"dungeon_enter\"",[98,125,126],{"class":111},", (",[98,128,130],{"class":129},"s4XuR","dungeonId",[98,132,133],{"class":111},", ",[98,135,136],{"class":129},"roomId",[98,138,139],{"class":111},") ",[98,141,143],{"class":142},"szBVR","=>",[98,145,146],{"class":111}," {\n",[98,148,150],{"class":100,"line":149},3,[98,151,152],{"class":104},"  \u002F\u002F Your code runs whenever a dungeon is entered\n",[98,154,156],{"class":100,"line":155},4,[98,157,158],{"class":111},"});\n",[98,160,162],{"class":100,"line":161},5,[98,163,165],{"emptyLinePlaceholder":164},true,"\n",[98,167,169],{"class":100,"line":168},6,[98,170,171],{"class":104},"\u002F\u002F Register a custom emitter\n",[98,173,175,177,180,182,185],{"class":100,"line":174},7,[98,176,112],{"class":111},[98,178,179],{"class":115},"registerEmitter",[98,181,119],{"class":111},[98,183,184],{"class":122},"\"battle_started\"",[98,186,187],{"class":111},");\n",[98,189,191],{"class":100,"line":190},8,[98,192,165],{"emptyLinePlaceholder":164},[98,194,196],{"class":100,"line":195},9,[98,197,198],{"class":104},"\u002F\u002F Listen to your custom emitter\n",[98,200,202,204,206,208,210,212,215,217,219],{"class":100,"line":201},10,[98,203,112],{"class":111},[98,205,116],{"class":115},[98,207,119],{"class":111},[98,209,184],{"class":122},[98,211,126],{"class":111},[98,213,214],{"class":129},"enemyId",[98,216,139],{"class":111},[98,218,143],{"class":142},[98,220,146],{"class":111},[98,222,224,227,230,232,235],{"class":100,"line":223},11,[98,225,226],{"class":111},"  console.",[98,228,229],{"class":115},"log",[98,231,119],{"class":111},[98,233,234],{"class":122},"\"Battle with\"",[98,236,237],{"class":111},", enemyId);\n",[98,239,241],{"class":100,"line":240},12,[98,242,158],{"class":111},[98,244,246],{"class":100,"line":245},13,[98,247,165],{"emptyLinePlaceholder":164},[98,249,251],{"class":100,"line":250},14,[98,252,253],{"class":104},"\u002F\u002F Trigger your custom emitter from anywhere\n",[98,255,257,259,262,264,266,268,271],{"class":100,"line":256},15,[98,258,112],{"class":111},[98,260,261],{"class":115},"trigger",[98,263,119],{"class":111},[98,265,184],{"class":122},[98,267,133],{"class":111},[98,269,270],{"class":122},"\"goblin\"",[98,272,187],{"class":111},[15,274,275,278,279],{},[19,276,277],{},"Reference:"," ",[280,281,283],"a",{"href":282},"\u002Fdocs\u002Fglobal_essentials\u002Fbuiltins\u002Fgame_emitters","Game Emitters",[15,285,286,289,290,293],{},[19,287,288],{},"Note:"," These are game lifecycle emitters registered via ",[95,291,292],{},"game.on()"," in scripts. Don't confuse them with dungeon events (dialogues, scenes) which are content created in Google Docs.",[27,295],{},[30,297,299],{"id":298},"states","States",[15,301,302,304],{},[19,303,61],{}," Named values that control the UI and game behavior.",[15,306,307,309],{},[19,308,67],{}," States are like switches or dials that different parts of the engine read. Changing a state can show\u002Fhide UI panels, enable\u002Fdisable features, or switch between game modes.",[15,311,312],{},[19,313,73],{},[75,315,316,319,322],{},[78,317,318],{},"Show the character sheet panel",[78,320,321],{},"Disable the UI during cutscenes",[78,323,324],{},"Switch between exploration and battle modes",[88,326,328],{"className":90,"code":327,"language":92,"meta":93,"style":93},"\u002F\u002F Register a custom state\ngame.registerState(\"battle_mode\", false);\n\n\u002F\u002F Read a state\nlet isBattle = game.getState(\"battle_mode\");\n\n\u002F\u002F Change a state\ngame.setState(\"battle_mode\", true);\n\n\u002F\u002F Built-in states work the same way\ngame.setState(\"progression_state\", \"character\");  \u002F\u002F Open character sheet\ngame.setState(\"disable_ui\", true);                \u002F\u002F Lock the UI\n",[95,329,330,335,355,359,364,387,391,396,414,418,423,445],{"__ignoreMap":93},[98,331,332],{"class":100,"line":101},[98,333,334],{"class":104},"\u002F\u002F Register a custom state\n",[98,336,337,339,342,344,347,349,353],{"class":100,"line":108},[98,338,112],{"class":111},[98,340,341],{"class":115},"registerState",[98,343,119],{"class":111},[98,345,346],{"class":122},"\"battle_mode\"",[98,348,133],{"class":111},[98,350,352],{"class":351},"sj4cs","false",[98,354,187],{"class":111},[98,356,357],{"class":100,"line":149},[98,358,165],{"emptyLinePlaceholder":164},[98,360,361],{"class":100,"line":155},[98,362,363],{"class":104},"\u002F\u002F Read a state\n",[98,365,366,369,372,375,378,381,383,385],{"class":100,"line":161},[98,367,368],{"class":142},"let",[98,370,371],{"class":111}," isBattle ",[98,373,374],{"class":142},"=",[98,376,377],{"class":111}," game.",[98,379,380],{"class":115},"getState",[98,382,119],{"class":111},[98,384,346],{"class":122},[98,386,187],{"class":111},[98,388,389],{"class":100,"line":168},[98,390,165],{"emptyLinePlaceholder":164},[98,392,393],{"class":100,"line":174},[98,394,395],{"class":104},"\u002F\u002F Change a state\n",[98,397,398,400,403,405,407,409,412],{"class":100,"line":190},[98,399,112],{"class":111},[98,401,402],{"class":115},"setState",[98,404,119],{"class":111},[98,406,346],{"class":122},[98,408,133],{"class":111},[98,410,411],{"class":351},"true",[98,413,187],{"class":111},[98,415,416],{"class":100,"line":195},[98,417,165],{"emptyLinePlaceholder":164},[98,419,420],{"class":100,"line":201},[98,421,422],{"class":104},"\u002F\u002F Built-in states work the same way\n",[98,424,425,427,429,431,434,436,439,442],{"class":100,"line":223},[98,426,112],{"class":111},[98,428,402],{"class":115},[98,430,119],{"class":111},[98,432,433],{"class":122},"\"progression_state\"",[98,435,133],{"class":111},[98,437,438],{"class":122},"\"character\"",[98,440,441],{"class":111},");  ",[98,443,444],{"class":104},"\u002F\u002F Open character sheet\n",[98,446,447,449,451,453,456,458,460,463],{"class":100,"line":240},[98,448,112],{"class":111},[98,450,402],{"class":115},[98,452,119],{"class":111},[98,454,455],{"class":122},"\"disable_ui\"",[98,457,133],{"class":111},[98,459,411],{"class":351},[98,461,462],{"class":111},");                ",[98,464,465],{"class":104},"\u002F\u002F Lock the UI\n",[15,467,468,278,470],{},[19,469,277],{},[280,471,299],{"href":472},"\u002Fdocs\u002Fglobal_essentials\u002Fbuiltins\u002Fstates",[27,474],{},[30,476,478],{"id":477},"actions","Actions",[15,480,481,483],{},[19,482,61],{}," Named commands that do things in the game.",[15,485,486,488],{},[19,487,67],{}," Actions are reusable pieces of logic. You can trigger them from dialogue scripts, item effects, or your own code. Built-in actions handle common tasks like giving items, changing scenes, or modifying flags.",[15,490,491],{},[19,492,73],{},[75,494,495,498,501],{},[78,496,497],{},"Give the player gold",[78,499,500],{},"Start a scene or dialogue",[78,502,503],{},"Add\u002Fremove items from inventory",[88,505,507],{"className":90,"code":506,"language":92,"meta":93,"style":93},"\u002F\u002F Register a custom action\ngame.registerAction(\"heal_party\", () => {\n  for (let char of game.getParty()) {\n    char.setResource(\"health\", char.getStat(\"health\"));\n  }\n});\n\n\u002F\u002F Trigger your custom action\ngame.execute({ heal_party: true });\n\n\u002F\u002F Trigger a built-in action (> adds, \u003C subtracts, = sets)\ngame.execute({ flag: \"gold>100\" });\n",[95,508,509,514,533,557,583,588,592,596,601,616,620,625],{"__ignoreMap":93},[98,510,511],{"class":100,"line":101},[98,512,513],{"class":104},"\u002F\u002F Register a custom action\n",[98,515,516,518,521,523,526,529,531],{"class":100,"line":108},[98,517,112],{"class":111},[98,519,520],{"class":115},"registerAction",[98,522,119],{"class":111},[98,524,525],{"class":122},"\"heal_party\"",[98,527,528],{"class":111},", () ",[98,530,143],{"class":142},[98,532,146],{"class":111},[98,534,535,538,541,543,546,549,551,554],{"class":100,"line":149},[98,536,537],{"class":142},"  for",[98,539,540],{"class":111}," (",[98,542,368],{"class":142},[98,544,545],{"class":111}," char ",[98,547,548],{"class":142},"of",[98,550,377],{"class":111},[98,552,553],{"class":115},"getParty",[98,555,556],{"class":111},"()) {\n",[98,558,559,562,565,567,570,573,576,578,580],{"class":100,"line":155},[98,560,561],{"class":111},"    char.",[98,563,564],{"class":115},"setResource",[98,566,119],{"class":111},[98,568,569],{"class":122},"\"health\"",[98,571,572],{"class":111},", char.",[98,574,575],{"class":115},"getStat",[98,577,119],{"class":111},[98,579,569],{"class":122},[98,581,582],{"class":111},"));\n",[98,584,585],{"class":100,"line":161},[98,586,587],{"class":111},"  }\n",[98,589,590],{"class":100,"line":168},[98,591,158],{"class":111},[98,593,594],{"class":100,"line":174},[98,595,165],{"emptyLinePlaceholder":164},[98,597,598],{"class":100,"line":190},[98,599,600],{"class":104},"\u002F\u002F Trigger your custom action\n",[98,602,603,605,608,611,613],{"class":100,"line":195},[98,604,112],{"class":111},[98,606,607],{"class":115},"execute",[98,609,610],{"class":111},"({ heal_party: ",[98,612,411],{"class":351},[98,614,615],{"class":111}," });\n",[98,617,618],{"class":100,"line":201},[98,619,165],{"emptyLinePlaceholder":164},[98,621,622],{"class":100,"line":223},[98,623,624],{"class":104},"\u002F\u002F Trigger a built-in action (> adds, \u003C subtracts, = sets)\n",[98,626,627,629,631,634,637],{"class":100,"line":240},[98,628,112],{"class":111},[98,630,607],{"class":115},[98,632,633],{"class":111},"({ flag: ",[98,635,636],{"class":122},"\"gold>100\"",[98,638,615],{"class":111},[15,640,641,278,643],{},[19,642,277],{},[280,644,478],{"href":645},"\u002Fdocs\u002Fglobal_essentials\u002Fbuiltins\u002Factions",[27,647],{},[30,649,651],{"id":650},"conditions","Conditions",[15,653,654,656],{},[19,655,61],{}," Named checks that return true or false.",[15,658,659,661],{},[19,660,67],{}," Conditions let you test game state in a reusable way. Use them in dialogue branches, to show\u002Fhide choices, or anywhere you need to check \"is this true?\"",[15,663,664],{},[19,665,73],{},[75,667,668,671,674],{},[78,669,670],{},"Check if player has enough gold",[78,672,673],{},"Test if a character is in the party",[78,675,676],{},"Verify quest progress",[88,678,680],{"className":90,"code":679,"language":92,"meta":93,"style":93},"\u002F\u002F Register a custom condition\ngame.registerCondition(\"can_afford\", (amount) => {\n  let partyInv = game.getInventory(\"_party_inventory\");\n  return partyInv.getCurrencyAmount(\"gold\") >= amount;\n});\n\n\u002F\u002F Used in dialogue: if{can_afford(100) = true}You can buy this.fi{}\n",[95,681,682,687,710,732,756,760,764],{"__ignoreMap":93},[98,683,684],{"class":100,"line":101},[98,685,686],{"class":104},"\u002F\u002F Register a custom condition\n",[98,688,689,691,694,696,699,701,704,706,708],{"class":100,"line":108},[98,690,112],{"class":111},[98,692,693],{"class":115},"registerCondition",[98,695,119],{"class":111},[98,697,698],{"class":122},"\"can_afford\"",[98,700,126],{"class":111},[98,702,703],{"class":129},"amount",[98,705,139],{"class":111},[98,707,143],{"class":142},[98,709,146],{"class":111},[98,711,712,715,718,720,722,725,727,730],{"class":100,"line":149},[98,713,714],{"class":142},"  let",[98,716,717],{"class":111}," partyInv ",[98,719,374],{"class":142},[98,721,377],{"class":111},[98,723,724],{"class":115},"getInventory",[98,726,119],{"class":111},[98,728,729],{"class":122},"\"_party_inventory\"",[98,731,187],{"class":111},[98,733,734,737,740,743,745,748,750,753],{"class":100,"line":155},[98,735,736],{"class":142},"  return",[98,738,739],{"class":111}," partyInv.",[98,741,742],{"class":115},"getCurrencyAmount",[98,744,119],{"class":111},[98,746,747],{"class":122},"\"gold\"",[98,749,139],{"class":111},[98,751,752],{"class":142},">=",[98,754,755],{"class":111}," amount;\n",[98,757,758],{"class":100,"line":161},[98,759,158],{"class":111},[98,761,762],{"class":100,"line":168},[98,763,165],{"emptyLinePlaceholder":164},[98,765,766],{"class":100,"line":174},[98,767,768],{"class":104},"\u002F\u002F Used in dialogue: if{can_afford(100) = true}You can buy this.fi{}\n",[15,770,771,278,773],{},[19,772,277],{},[280,774,651],{"href":775},"\u002Fdocs\u002Fglobal_essentials\u002Fbuiltins\u002Fconditions",[27,777],{},[30,779,781],{"id":780},"placeholders","Placeholders",[15,783,784,786],{},[19,785,61],{}," Dynamic text substitutions.",[15,788,789,791,792,795],{},[19,790,67],{}," Placeholders let you insert values into text. Write ",[95,793,794],{},"|placeholder_name|"," in your dialogue or descriptions, and the engine replaces it with the actual value at runtime.",[15,797,798],{},[19,799,73],{},[75,801,802,805,808],{},[78,803,804],{},"Show character names: \"Hello, |player_name|!\"",[78,806,807],{},"Display resource values: \"You have |flag(gold)| gold\"",[78,809,810],{},"Insert item names in descriptions",[88,812,814],{"className":90,"code":813,"language":92,"meta":93,"style":93},"\u002F\u002F Register a custom placeholder\ngame.registerPlaceholder(\"player_name\", () => {\n  return game.getCharacter(\"mc\").getName();\n});\n\n\u002F\u002F Used in text: \"Welcome back, |player_name|!\"\n",[95,815,816,821,839,862,866,870],{"__ignoreMap":93},[98,817,818],{"class":100,"line":101},[98,819,820],{"class":104},"\u002F\u002F Register a custom placeholder\n",[98,822,823,825,828,830,833,835,837],{"class":100,"line":108},[98,824,112],{"class":111},[98,826,827],{"class":115},"registerPlaceholder",[98,829,119],{"class":111},[98,831,832],{"class":122},"\"player_name\"",[98,834,528],{"class":111},[98,836,143],{"class":142},[98,838,146],{"class":111},[98,840,841,843,845,848,850,853,856,859],{"class":100,"line":149},[98,842,736],{"class":142},[98,844,377],{"class":111},[98,846,847],{"class":115},"getCharacter",[98,849,119],{"class":111},[98,851,852],{"class":122},"\"mc\"",[98,854,855],{"class":111},").",[98,857,858],{"class":115},"getName",[98,860,861],{"class":111},"();\n",[98,863,864],{"class":100,"line":155},[98,865,158],{"class":111},[98,867,868],{"class":100,"line":161},[98,869,165],{"emptyLinePlaceholder":164},[98,871,872],{"class":100,"line":168},[98,873,874],{"class":104},"\u002F\u002F Used in text: \"Welcome back, |player_name|!\"\n",[15,876,877,278,879],{},[19,878,277],{},[280,880,781],{"href":881},"\u002Fdocs\u002Fglobal_essentials\u002Fbuiltins\u002Fplaceholders",[27,883],{},[30,885,887],{"id":886},"stat-computers","Stat Computers",[15,889,890,892],{},[19,891,61],{}," Functions that calculate derived character stats.",[15,894,895,897],{},[19,896,67],{}," Some stats depend on other stats or complex formulas. Instead of storing them directly, you register a function that computes the value whenever it's needed. The function returns an object with stat names and their bonus values.",[15,899,900],{},[19,901,73],{},[75,903,904,907,910],{},[78,905,906],{},"Calculate damage from strength and equipment",[78,908,909],{},"Derive max health from level and constitution",[78,911,912],{},"Compute defense from armor pieces",[88,914,916],{"className":90,"code":915,"language":92,"meta":93,"style":93},"\u002F\u002F Register a stat computer\ngame.registerStatComputer(\"strengthBonus\", (character) => {\n  const strength = character.getStat(\"strength\") || 0;\n  return {\n    attack: strength * 2,\n    carry_capacity: strength * 10\n  };\n});\n\n\u002F\u002F Attach it to a character template in the editor:\n\u002F\u002F computed_stats: [\"strengthBonus\"]\n\n\u002F\u002F Then access the computed stats normally\nlet mc = game.getCharacter(\"mc\");\nlet attack = mc.getStat(\"attack\");  \u002F\u002F Includes the strength bonus\n",[95,917,918,923,946,978,984,998,1008,1013,1017,1021,1026,1031,1035,1040,1059],{"__ignoreMap":93},[98,919,920],{"class":100,"line":101},[98,921,922],{"class":104},"\u002F\u002F Register a stat computer\n",[98,924,925,927,930,932,935,937,940,942,944],{"class":100,"line":108},[98,926,112],{"class":111},[98,928,929],{"class":115},"registerStatComputer",[98,931,119],{"class":111},[98,933,934],{"class":122},"\"strengthBonus\"",[98,936,126],{"class":111},[98,938,939],{"class":129},"character",[98,941,139],{"class":111},[98,943,143],{"class":142},[98,945,146],{"class":111},[98,947,948,951,954,957,960,962,964,967,969,972,975],{"class":100,"line":149},[98,949,950],{"class":142},"  const",[98,952,953],{"class":351}," strength",[98,955,956],{"class":142}," =",[98,958,959],{"class":111}," character.",[98,961,575],{"class":115},[98,963,119],{"class":111},[98,965,966],{"class":122},"\"strength\"",[98,968,139],{"class":111},[98,970,971],{"class":142},"||",[98,973,974],{"class":351}," 0",[98,976,977],{"class":111},";\n",[98,979,980,982],{"class":100,"line":155},[98,981,736],{"class":142},[98,983,146],{"class":111},[98,985,986,989,992,995],{"class":100,"line":161},[98,987,988],{"class":111},"    attack: strength ",[98,990,991],{"class":142},"*",[98,993,994],{"class":351}," 2",[98,996,997],{"class":111},",\n",[98,999,1000,1003,1005],{"class":100,"line":168},[98,1001,1002],{"class":111},"    carry_capacity: strength ",[98,1004,991],{"class":142},[98,1006,1007],{"class":351}," 10\n",[98,1009,1010],{"class":100,"line":174},[98,1011,1012],{"class":111},"  };\n",[98,1014,1015],{"class":100,"line":190},[98,1016,158],{"class":111},[98,1018,1019],{"class":100,"line":195},[98,1020,165],{"emptyLinePlaceholder":164},[98,1022,1023],{"class":100,"line":201},[98,1024,1025],{"class":104},"\u002F\u002F Attach it to a character template in the editor:\n",[98,1027,1028],{"class":100,"line":223},[98,1029,1030],{"class":104},"\u002F\u002F computed_stats: [\"strengthBonus\"]\n",[98,1032,1033],{"class":100,"line":240},[98,1034,165],{"emptyLinePlaceholder":164},[98,1036,1037],{"class":100,"line":245},[98,1038,1039],{"class":104},"\u002F\u002F Then access the computed stats normally\n",[98,1041,1042,1044,1047,1049,1051,1053,1055,1057],{"class":100,"line":250},[98,1043,368],{"class":142},[98,1045,1046],{"class":111}," mc ",[98,1048,374],{"class":142},[98,1050,377],{"class":111},[98,1052,847],{"class":115},[98,1054,119],{"class":111},[98,1056,852],{"class":122},[98,1058,187],{"class":111},[98,1060,1061,1063,1066,1068,1071,1073,1075,1078,1080],{"class":100,"line":256},[98,1062,368],{"class":142},[98,1064,1065],{"class":111}," attack ",[98,1067,374],{"class":142},[98,1069,1070],{"class":111}," mc.",[98,1072,575],{"class":115},[98,1074,119],{"class":111},[98,1076,1077],{"class":122},"\"attack\"",[98,1079,441],{"class":111},[98,1081,1082],{"class":104},"\u002F\u002F Includes the strength bonus\n",[15,1084,1085,278,1087],{},[19,1086,277],{},[280,1088,1090],{"href":1089},"\u002Fdocs\u002Fglobal_essentials\u002Fcharacters\u002Fcharacters_computed","Computed Stats",[27,1092],{},[30,1094,1096],{"id":1095},"components","Components",[15,1098,1099,1101],{},[19,1100,61],{}," Vue components plugged into UI slots.",[15,1103,1104,1106],{},[19,1105,67],{}," The engine UI has designated \"slots\" where components can appear. You register your own components into these slots to add tabs, buttons, panels, or entirely new screens. Slots automatically pass context props from the parent component to your custom component.",[15,1108,1109],{},[19,1110,73],{},[75,1112,1113,1116,1119],{},[78,1114,1115],{},"Add a custom tab to the character sheet",[78,1117,1118],{},"Insert a button into the toolbar",[78,1120,1121],{},"Add action buttons to ability cards",[88,1123,1125],{"className":90,"code":1124,"language":92,"meta":93,"style":93},"const { vue, game } = window.engine;\nconst { defineComponent } = vue;\n\n\u002F\u002F Create a component that uses context props from the slot\nconst UseAbilityButton = defineComponent({\n  props: ['abilityId', 'characterId'],  \u002F\u002F Received from slot context\n  setup(props) {\n    function useAbility() {\n      const character = game.getCharacter(props.characterId);\n      character?.useAbility(props.abilityId);\n    }\n    return { useAbility };\n  },\n  template: \u002F*html*\u002F`\u003Cbutton @click=\"useAbility\">Use\u003C\u002Fbutton>`\n});\n\n\u002F\u002F Register into a slot\ngame.registerCustomComponent({\n  id: \"use-ability-button\",\n  slot: \"ability-card-footer\",\n  component: UseAbilityButton\n});\n",[95,1126,1127,1151,1167,1171,1176,1191,1210,1223,1234,1251,1262,1267,1275,1280,1291,1295,1300,1306,1316,1327,1338,1344],{"__ignoreMap":93},[98,1128,1129,1132,1135,1138,1140,1143,1146,1148],{"class":100,"line":101},[98,1130,1131],{"class":142},"const",[98,1133,1134],{"class":111}," { ",[98,1136,1137],{"class":351},"vue",[98,1139,133],{"class":111},[98,1141,1142],{"class":351},"game",[98,1144,1145],{"class":111}," } ",[98,1147,374],{"class":142},[98,1149,1150],{"class":111}," window.engine;\n",[98,1152,1153,1155,1157,1160,1162,1164],{"class":100,"line":108},[98,1154,1131],{"class":142},[98,1156,1134],{"class":111},[98,1158,1159],{"class":351},"defineComponent",[98,1161,1145],{"class":111},[98,1163,374],{"class":142},[98,1165,1166],{"class":111}," vue;\n",[98,1168,1169],{"class":100,"line":149},[98,1170,165],{"emptyLinePlaceholder":164},[98,1172,1173],{"class":100,"line":155},[98,1174,1175],{"class":104},"\u002F\u002F Create a component that uses context props from the slot\n",[98,1177,1178,1180,1183,1185,1188],{"class":100,"line":161},[98,1179,1131],{"class":142},[98,1181,1182],{"class":351}," UseAbilityButton",[98,1184,956],{"class":142},[98,1186,1187],{"class":115}," defineComponent",[98,1189,1190],{"class":111},"({\n",[98,1192,1193,1196,1199,1201,1204,1207],{"class":100,"line":168},[98,1194,1195],{"class":111},"  props: [",[98,1197,1198],{"class":122},"'abilityId'",[98,1200,133],{"class":111},[98,1202,1203],{"class":122},"'characterId'",[98,1205,1206],{"class":111},"],  ",[98,1208,1209],{"class":104},"\u002F\u002F Received from slot context\n",[98,1211,1212,1215,1217,1220],{"class":100,"line":174},[98,1213,1214],{"class":115},"  setup",[98,1216,119],{"class":111},[98,1218,1219],{"class":129},"props",[98,1221,1222],{"class":111},") {\n",[98,1224,1225,1228,1231],{"class":100,"line":190},[98,1226,1227],{"class":142},"    function",[98,1229,1230],{"class":115}," useAbility",[98,1232,1233],{"class":111},"() {\n",[98,1235,1236,1239,1242,1244,1246,1248],{"class":100,"line":195},[98,1237,1238],{"class":142},"      const",[98,1240,1241],{"class":351}," character",[98,1243,956],{"class":142},[98,1245,377],{"class":111},[98,1247,847],{"class":115},[98,1249,1250],{"class":111},"(props.characterId);\n",[98,1252,1253,1256,1259],{"class":100,"line":201},[98,1254,1255],{"class":111},"      character?.",[98,1257,1258],{"class":115},"useAbility",[98,1260,1261],{"class":111},"(props.abilityId);\n",[98,1263,1264],{"class":100,"line":223},[98,1265,1266],{"class":111},"    }\n",[98,1268,1269,1272],{"class":100,"line":240},[98,1270,1271],{"class":142},"    return",[98,1273,1274],{"class":111}," { useAbility };\n",[98,1276,1277],{"class":100,"line":245},[98,1278,1279],{"class":111},"  },\n",[98,1281,1282,1285,1288],{"class":100,"line":250},[98,1283,1284],{"class":111},"  template: ",[98,1286,1287],{"class":104},"\u002F*html*\u002F",[98,1289,1290],{"class":122},"`\u003Cbutton @click=\"useAbility\">Use\u003C\u002Fbutton>`\n",[98,1292,1293],{"class":100,"line":256},[98,1294,158],{"class":111},[98,1296,1298],{"class":100,"line":1297},16,[98,1299,165],{"emptyLinePlaceholder":164},[98,1301,1303],{"class":100,"line":1302},17,[98,1304,1305],{"class":104},"\u002F\u002F Register into a slot\n",[98,1307,1309,1311,1314],{"class":100,"line":1308},18,[98,1310,112],{"class":111},[98,1312,1313],{"class":115},"registerCustomComponent",[98,1315,1190],{"class":111},[98,1317,1319,1322,1325],{"class":100,"line":1318},19,[98,1320,1321],{"class":111},"  id: ",[98,1323,1324],{"class":122},"\"use-ability-button\"",[98,1326,997],{"class":111},[98,1328,1330,1333,1336],{"class":100,"line":1329},20,[98,1331,1332],{"class":111},"  slot: ",[98,1334,1335],{"class":122},"\"ability-card-footer\"",[98,1337,997],{"class":111},[98,1339,1341],{"class":100,"line":1340},21,[98,1342,1343],{"class":111},"  component: UseAbilityButton\n",[98,1345,1347],{"class":100,"line":1346},22,[98,1348,158],{"class":111},[15,1350,1351,278,1353,1357,1358],{},[19,1352,277],{},[280,1354,1356],{"href":1355},"\u002Fdocs\u002Fglobal_essentials\u002Fbuiltins\u002Fcomponents_export","Components Export"," and ",[280,1359,1361],{"href":1360},"\u002Fdocs\u002Fglobal_essentials\u002Fadvanced\u002Fcustom_vue","Custom Vue Features",[27,1363],{},[30,1365,1367],{"id":1366},"how-it-all-connects","How It All Connects",[15,1369,1370],{},"These systems work together to make your game extensible:",[1372,1373,1374,1380,1385,1390,1395,1400,1405],"ol",{},[78,1375,1376,1379],{},[19,1377,1378],{},"Event Emitters"," notify you when things happen",[78,1381,1382,1384],{},[19,1383,299],{}," control what the UI shows",[78,1386,1387,1389],{},[19,1388,478],{}," execute game logic",[78,1391,1392,1394],{},[19,1393,651],{}," gate content based on game state",[78,1396,1397,1399],{},[19,1398,781],{}," make text dynamic",[78,1401,1402,1404],{},[19,1403,887],{}," derive calculated values",[78,1406,1407,1409],{},[19,1408,1096],{}," extend the UI",[15,1411,1412],{},"Your scripts can register new items in any of these registries, letting you extend the engine without modifying its core code.",[27,1414],{},[30,1416,1418],{"id":1417},"next-steps","Next Steps",[75,1420,1421,1426,1431,1436,1441],{},[78,1422,1423,1425],{},[280,1424,283],{"href":282}," - Full emitter reference",[78,1427,1428,1430],{},[280,1429,299],{"href":472}," - All built-in states",[78,1432,1433,1435],{},[280,1434,478],{"href":645}," - Action reference",[78,1437,1438,1440],{},[280,1439,651],{"href":775}," - Condition reference",[78,1442,1443,1447],{},[280,1444,1446],{"href":1445},"\u002Fdocs\u002Fglobal_essentials\u002Fadvanced\u002Fvue","Vue Components"," - Creating custom components",[1449,1450,1451],"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 .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}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 .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":93,"searchDepth":108,"depth":108,"links":1453},[1454,1455,1456,1457,1458,1459,1460,1461,1462,1463],{"id":32,"depth":108,"text":33},{"id":55,"depth":108,"text":56},{"id":298,"depth":108,"text":299},{"id":477,"depth":108,"text":478},{"id":650,"depth":108,"text":651},{"id":780,"depth":108,"text":781},{"id":886,"depth":108,"text":887},{"id":1095,"depth":108,"text":1096},{"id":1366,"depth":108,"text":1367},{"id":1417,"depth":108,"text":1418},"Dryad Engine uses a registry system to manage all the moving parts of your game. Think of it as a central directory where different systems register themselves so they can talk to each other.","md",{"plugin":1467,"category":1468,"page":49},"global_essentials","advanced","\u002Fdocs\u002Fglobal_essentials\u002Fadvanced\u002Fregistry",{"title":5,"description":1464},"docs\u002Fglobal_essentials\u002Fadvanced\u002Fregistry","G6je8H5j8_PRoILZg9cGWu7HuSln-Lfu_yRl6Y8bsYc",1779582261876]