[{"data":1,"prerenderedAt":1128},["ShallowReactive",2],{"navigation_docs":3,"-docs-culttweaker-modding-api":166,"-docs-culttweaker-modding-api-surround":1123},[4,9,76,106,148,162],{"title":5,"path":6,"stem":7,"icon":8},"Overview","\u002Fdocs","docs\u002Findex","i-lucide-book-open",{"title":10,"path":11,"stem":12,"children":13,"icon":15},"CultTweaker","\u002Fdocs\u002Fculttweaker","docs\u002F1.culttweaker\u002F01.index",[14,16,21,26,31,36,41,46,51,56,61,66,71],{"title":5,"path":11,"stem":12,"icon":15},"i-lucide-wand",{"title":17,"path":18,"stem":19,"icon":20},"Installation","\u002Fdocs\u002Fculttweaker\u002Finstallation","docs\u002F1.culttweaker\u002F02.installation","i-lucide-download",{"title":22,"path":23,"stem":24,"icon":25},"Worldshaper","\u002Fdocs\u002Fculttweaker\u002Fworldshaper","docs\u002F1.culttweaker\u002F03.worldshaper","i-lucide-hammer",{"title":27,"path":28,"stem":29,"icon":30},"Player spines","\u002Fdocs\u002Fculttweaker\u002Fplayer-spines","docs\u002F1.culttweaker\u002F04.player-spines","i-lucide-user",{"title":32,"path":33,"stem":34,"icon":35},"Follower forms","\u002Fdocs\u002Fculttweaker\u002Ffollower-forms","docs\u002F1.culttweaker\u002F05.follower-forms","i-lucide-users",{"title":37,"path":38,"stem":39,"icon":40},"Custom structures","\u002Fdocs\u002Fculttweaker\u002Fcustom-structures","docs\u002F1.culttweaker\u002F06.custom-structures","i-lucide-home",{"title":42,"path":43,"stem":44,"icon":45},"Items and meals","\u002Fdocs\u002Fculttweaker\u002Fcustom-items-and-meals","docs\u002F1.culttweaker\u002F07.custom-items-and-meals","i-lucide-package",{"title":47,"path":48,"stem":49,"icon":50},"Tarot cards","\u002Fdocs\u002Fculttweaker\u002Fcustom-tarot-cards","docs\u002F1.culttweaker\u002F08.custom-tarot-cards","i-lucide-sparkles",{"title":52,"path":53,"stem":54,"icon":55},"Custom enemies","\u002Fdocs\u002Fculttweaker\u002Fcustom-enemies","docs\u002F1.culttweaker\u002F09.custom-enemies","i-lucide-skull",{"title":57,"path":58,"stem":59,"icon":60},"Custom weapons","\u002Fdocs\u002Fculttweaker\u002Fcustom-weapons","docs\u002F1.culttweaker\u002F10.custom-weapons","i-lucide-sword",{"title":62,"path":63,"stem":64,"icon":65},"NPC quests","\u002Fdocs\u002Fculttweaker\u002Fcustom-npc-quests","docs\u002F1.culttweaker\u002F11.custom-npc-quests","i-lucide-message-square",{"title":67,"path":68,"stem":69,"icon":70},"Modding API","\u002Fdocs\u002Fculttweaker\u002Fmodding-api","docs\u002F1.culttweaker\u002F12.modding-api","i-lucide-plug",{"title":72,"path":73,"stem":74,"icon":75},"Changelog","\u002Fdocs\u002Fculttweaker\u002Fchangelog","docs\u002F1.culttweaker\u002F13.changelog","i-lucide-history",{"title":77,"path":78,"stem":79,"children":80,"icon":82},"Supercharged","\u002Fdocs\u002Fsupercharged","docs\u002F2.supercharged\u002F1.index",[81,83,92],{"title":5,"path":78,"stem":79,"icon":82},"i-lucide-zap",{"title":84,"path":85,"stem":86,"children":87,"icon":35},"Followers","\u002Fdocs\u002Fsupercharged\u002Ffollowers","docs\u002F2.supercharged\u002Ffollowers\u002F1.index",[88,89],{"title":5,"path":85,"stem":86,"icon":35},{"title":72,"path":90,"stem":91,"icon":75},"\u002Fdocs\u002Fsupercharged\u002Ffollowers\u002Fchangelog","docs\u002F2.supercharged\u002Ffollowers\u002F2.changelog",{"title":93,"path":94,"stem":95,"children":96,"icon":50},"Tarots","\u002Fdocs\u002Fsupercharged\u002Ftarots","docs\u002F2.supercharged\u002Ftarots\u002F1.index",[97,98,103],{"title":5,"path":94,"stem":95,"icon":50},{"title":99,"path":100,"stem":101,"icon":102},"Card list","\u002Fdocs\u002Fsupercharged\u002Ftarots\u002Fcards","docs\u002F2.supercharged\u002Ftarots\u002F2.cards","i-lucide-layers",{"title":72,"path":104,"stem":105,"icon":75},"\u002Fdocs\u002Fsupercharged\u002Ftarots\u002Fchangelog","docs\u002F2.supercharged\u002Ftarots\u002F3.changelog",{"title":107,"path":108,"stem":109,"children":110,"icon":112},"MiniMods","\u002Fdocs\u002Fminimods","docs\u002F3.minimods\u002F1.index",[111,113,118,122,127,132,136,140,143],{"title":5,"path":108,"stem":109,"icon":112},"i-lucide-boxes",{"title":114,"path":115,"stem":116,"icon":117},"Trial of the Gods","\u002Fdocs\u002Fminimods\u002Ftrial-of-the-gods","docs\u002F3.minimods\u002F2.trial-of-the-gods","i-lucide-flame",{"title":119,"path":120,"stem":121,"icon":25},"Structures","\u002Fdocs\u002Fminimods\u002Fstructures","docs\u002F3.minimods\u002F3.structures",{"title":123,"path":124,"stem":125,"icon":126},"Roles","\u002Fdocs\u002Fminimods\u002Froles","docs\u002F3.minimods\u002F4.roles","i-lucide-briefcase",{"title":128,"path":129,"stem":130,"icon":131},"Rituals","\u002Fdocs\u002Fminimods\u002Frituals","docs\u002F3.minimods\u002F5.rituals","i-lucide-flame-kindling",{"title":133,"path":134,"stem":135,"icon":65},"Commands","\u002Fdocs\u002Fminimods\u002Fcommands","docs\u002F3.minimods\u002F6.commands",{"title":137,"path":138,"stem":139,"icon":45},"Items","\u002Fdocs\u002Fminimods\u002Fitems","docs\u002F3.minimods\u002F7.items",{"title":72,"path":141,"stem":142,"icon":75},"\u002Fdocs\u002Fminimods\u002Fchangelog","docs\u002F3.minimods\u002F8.changelog",{"title":144,"path":145,"stem":146,"icon":147},"Credits","\u002Fdocs\u002Fminimods\u002Fcredits","docs\u002F3.minimods\u002F9.credits","i-lucide-heart",{"title":149,"path":150,"stem":151,"children":152,"icon":35},"MP Steam","\u002Fdocs\u002Fmpsteam","docs\u002F4.mpsteam\u002F1.index",[153,154,159],{"title":5,"path":150,"stem":151,"icon":35},{"title":155,"path":156,"stem":157,"icon":158},"Hosting and joining","\u002Fdocs\u002Fmpsteam\u002Fhosting-and-joining","docs\u002F4.mpsteam\u002F2.hosting-and-joining","i-lucide-play",{"title":72,"path":160,"stem":161,"icon":75},"\u002Fdocs\u002Fmpsteam\u002Fchangelog","docs\u002F4.mpsteam\u002F3.changelog",{"title":163,"path":164,"stem":165,"icon":70},"MCP server","\u002Fdocs\u002Fmcp","docs\u002F5.mcp",{"id":167,"title":67,"body":168,"description":1116,"extension":1117,"links":1118,"meta":1119,"navigation":1120,"path":68,"seo":1121,"stem":69,"__hash__":1122},"docs\u002Fdocs\u002F1.culttweaker\u002F12.modding-api.md",{"type":169,"value":170,"toc":1103},"minimark",[171,175,180,187,197,200,213,217,232,239,272,276,279,468,472,476,483,790,800,804,849,852,856,876,882,886,921,935,950,953,957,992,999,1003,1009,1020,1023,1027,1041,1045,1051,1060,1096,1099],[172,173,174],"p",{},"There are two ways to build on CultTweaker: ship content as files and write no\ncode at all, or reference the assembly and call a small contract. Most mods want\nthe first.",[176,177,179],"h2",{"id":178},"shipping-content-with-no-code","Shipping content with no code",[172,181,182,183,186],{},"Every content folder is read from two places: CultTweaker's own plugin folder,\nand a folder named ",[184,185,10],"code",{}," inside any other mod's folder. Put your files\nthere and they load beside the player's own, with no reference to our assembly\nand no code from you:",[188,189,195],"pre",{"className":190,"code":192,"language":193,"meta":194},[191],"language-text","BepInEx\u002Fplugins\u002FYourMod\u002FCultTweaker\u002FCustomDungeonMaps\u002FYourDungeon.json\nBepInEx\u002Fplugins\u002FYourMod\u002FCultTweaker\u002FCustomLevelBlueprints\u002FYourLevel.json\nBepInEx\u002Fplugins\u002FYourMod\u002FCultTweaker\u002FCustomNodeBlueprints\u002FYourRoom.json\nBepInEx\u002Fplugins\u002FYourMod\u002FCultTweaker\u002FCustomNpcs\u002FYourNpc\u002Fconfig.json\nBepInEx\u002Fplugins\u002FYourMod\u002FCultTweaker\u002FCustomEnemies\u002FYourEnemy\u002Fconfig.json\nBepInEx\u002Fplugins\u002FYourMod\u002FCultTweaker\u002FPlayerSkins\u002FYourSkin\u002Fconfig.json\n","text","",[184,196,192],{"__ignoreMap":194},[172,198,199],{},"The search is a bounded walk three folders deep, so a nested install is still\nfound. Three rules apply:",[201,202,203,207,210],"ul",{},[204,205,206],"li",{},"Reading is shared but writing is not, so your files are never edited in place.",[204,208,209],{},"Where two mods use the same name, the player's own copy wins and the other is\nskipped with a warning.",[204,211,212],{},"Everything the editors save goes to CultTweaker's own folder, never into yours.",[176,214,216],{"id":215},"the-code-contract","The code contract",[172,218,219,220,223,224,227,228,231],{},"One class: ",[184,221,222],{},"CustomSpineLoader.Api.CultTweakerApi",", in ",[184,225,226],{},"CultTweaker.dll",".\nEverything else in the assembly is internal in spirit and gets rearranged without\nnotice. Members here are never removed or changed in meaning; new ones are added\nand ",[184,229,230],{},"ContractVersion"," is raised.",[172,233,234,235,238],{},"Reference the DLL with ",[184,236,237],{},"Private=\"false\""," so you do not ship a copy of it:",[188,240,244],{"className":241,"code":242,"language":243,"meta":194,"style":194},"language-xml shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003CReference Include=\"CultTweaker\">\n  \u003CHintPath>lib\\CultTweaker.dll\u003C\u002FHintPath>\n  \u003CPrivate>false\u003C\u002FPrivate>\n\u003C\u002FReference>\n","xml",[184,245,246,254,260,266],{"__ignoreMap":194},[247,248,251],"span",{"class":249,"line":250},"line",1,[247,252,253],{},"\u003CReference Include=\"CultTweaker\">\n",[247,255,257],{"class":249,"line":256},2,[247,258,259],{},"  \u003CHintPath>lib\\CultTweaker.dll\u003C\u002FHintPath>\n",[247,261,263],{"class":249,"line":262},3,[247,264,265],{},"  \u003CPrivate>false\u003C\u002FPrivate>\n",[247,267,269],{"class":249,"line":268},4,[247,270,271],{},"\u003C\u002FReference>\n",[176,273,275],{"id":274},"reaching-it-safely","Reaching it safely",[172,277,278],{},"Declare a soft dependency, probe before the first call, and keep every call to\nour types inside a method marked no-inlining so the JIT never loads them when\nCultTweaker is absent:",[188,280,284],{"className":281,"code":282,"language":283,"meta":194,"style":194},"language-csharp shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","[BepInDependency(\"InfernoDragon0.cotl.CustomSpineLoader\", BepInDependency.DependencyFlags.SoftDependency)]\npublic class YourPlugin : BaseUnityPlugin\n{\n    private static bool _available;\n\n    private void Awake()\n    {\n        _available = Chainloader.PluginInfos.ContainsKey(\"InfernoDragon0.cotl.CustomSpineLoader\")\n                     && Probe();\n        if (_available) Bridge.WhenReady();\n    }\n\n    private static bool Probe()\n    {\n        try\n        {\n            var type = Type.GetType(\"CustomSpineLoader.Api.CultTweakerApi, CultTweaker\");\n            return type != null && CultTweakerApi.ContractVersion >= 1;\n        }\n        catch (Exception) { return false; }\n    }\n}\n\ninternal static class Bridge\n{\n    [MethodImpl(MethodImplOptions.NoInlining)]\n    public static void WhenReady() => CultTweakerApi.OnReady(() =>\n    {\n        foreach (var name in CultTweakerApi.Names(CultTweakerApi.Kind.Dungeons))\n            Log.LogInfo(\"CultTweaker dungeon available: \" + name);\n    });\n}\n","csharp",[184,285,286,291,296,301,306,313,319,325,331,337,343,349,354,360,365,371,377,383,389,395,401,406,412,417,423,428,434,440,445,451,457,463],{"__ignoreMap":194},[247,287,288],{"class":249,"line":250},[247,289,290],{},"[BepInDependency(\"InfernoDragon0.cotl.CustomSpineLoader\", BepInDependency.DependencyFlags.SoftDependency)]\n",[247,292,293],{"class":249,"line":256},[247,294,295],{},"public class YourPlugin : BaseUnityPlugin\n",[247,297,298],{"class":249,"line":262},[247,299,300],{},"{\n",[247,302,303],{"class":249,"line":268},[247,304,305],{},"    private static bool _available;\n",[247,307,309],{"class":249,"line":308},5,[247,310,312],{"emptyLinePlaceholder":311},true,"\n",[247,314,316],{"class":249,"line":315},6,[247,317,318],{},"    private void Awake()\n",[247,320,322],{"class":249,"line":321},7,[247,323,324],{},"    {\n",[247,326,328],{"class":249,"line":327},8,[247,329,330],{},"        _available = Chainloader.PluginInfos.ContainsKey(\"InfernoDragon0.cotl.CustomSpineLoader\")\n",[247,332,334],{"class":249,"line":333},9,[247,335,336],{},"                     && Probe();\n",[247,338,340],{"class":249,"line":339},10,[247,341,342],{},"        if (_available) Bridge.WhenReady();\n",[247,344,346],{"class":249,"line":345},11,[247,347,348],{},"    }\n",[247,350,352],{"class":249,"line":351},12,[247,353,312],{"emptyLinePlaceholder":311},[247,355,357],{"class":249,"line":356},13,[247,358,359],{},"    private static bool Probe()\n",[247,361,363],{"class":249,"line":362},14,[247,364,324],{},[247,366,368],{"class":249,"line":367},15,[247,369,370],{},"        try\n",[247,372,374],{"class":249,"line":373},16,[247,375,376],{},"        {\n",[247,378,380],{"class":249,"line":379},17,[247,381,382],{},"            var type = Type.GetType(\"CustomSpineLoader.Api.CultTweakerApi, CultTweaker\");\n",[247,384,386],{"class":249,"line":385},18,[247,387,388],{},"            return type != null && CultTweakerApi.ContractVersion >= 1;\n",[247,390,392],{"class":249,"line":391},19,[247,393,394],{},"        }\n",[247,396,398],{"class":249,"line":397},20,[247,399,400],{},"        catch (Exception) { return false; }\n",[247,402,404],{"class":249,"line":403},21,[247,405,348],{},[247,407,409],{"class":249,"line":408},22,[247,410,411],{},"}\n",[247,413,415],{"class":249,"line":414},23,[247,416,312],{"emptyLinePlaceholder":311},[247,418,420],{"class":249,"line":419},24,[247,421,422],{},"internal static class Bridge\n",[247,424,426],{"class":249,"line":425},25,[247,427,300],{},[247,429,431],{"class":249,"line":430},26,[247,432,433],{},"    [MethodImpl(MethodImplOptions.NoInlining)]\n",[247,435,437],{"class":249,"line":436},27,[247,438,439],{},"    public static void WhenReady() => CultTweakerApi.OnReady(() =>\n",[247,441,443],{"class":249,"line":442},28,[247,444,324],{},[247,446,448],{"class":249,"line":447},29,[247,449,450],{},"        foreach (var name in CultTweakerApi.Names(CultTweakerApi.Kind.Dungeons))\n",[247,452,454],{"class":249,"line":453},30,[247,455,456],{},"            Log.LogInfo(\"CultTweaker dungeon available: \" + name);\n",[247,458,460],{"class":249,"line":459},31,[247,461,462],{},"    });\n",[247,464,466],{"class":249,"line":465},32,[247,467,411],{},[469,470,471],"note",{},"Nothing throws out of the contract. A query for a kind this build does not know\nlogs a warning and returns an empty list.",[176,473,475],{"id":474},"content-kinds","Content kinds",[172,477,478,479,482],{},"Pass one of these to the queries. The constants are on ",[184,480,481],{},"CultTweakerApi.Kind",".",[484,485,486,502],"table",{},[487,488,489],"thead",{},[490,491,492,496,499],"tr",{},[493,494,495],"th",{},"Kind",[493,497,498],{},"What it lists",[493,500,501],{},"Folder",[503,504,505,519,534,549,564,579,594,609,624,638,652,667,681,699,715,729,744,759,773],"tbody",{},[490,506,507,513,516],{},[508,509,510],"td",{},[184,511,512],{},"Dungeons",[508,514,515],{},"Playable custom dungeons, by internal name",[508,517,518],{},"none, registered at runtime",[490,520,521,526,529],{},[508,522,523],{},[184,524,525],{},"DungeonMaps",[508,527,528],{},"Dungeon map documents",[508,530,531],{},[184,532,533],{},"CustomDungeonMaps",[490,535,536,541,544],{},[508,537,538],{},[184,539,540],{},"Levels",[508,542,543],{},"Level documents",[508,545,546],{},[184,547,548],{},"CustomLevelBlueprints",[490,550,551,556,559],{},[508,552,553],{},[184,554,555],{},"Rooms",[508,557,558],{},"Room blueprint documents",[508,560,561],{},[184,562,563],{},"CustomNodeBlueprints",[490,565,566,571,574],{},[508,567,568],{},[184,569,570],{},"WorldMaps",[508,572,573],{},"World map documents",[508,575,576],{},[184,577,578],{},"CustomWorldMaps",[490,580,581,586,589],{},[508,582,583],{},[184,584,585],{},"MainMenus",[508,587,588],{},"Main menu presets",[508,590,591],{},[184,592,593],{},"CustomMainMenus",[490,595,596,601,604],{},[508,597,598],{},[184,599,600],{},"Npcs",[508,602,603],{},"Registered custom NPCs",[508,605,606],{},[184,607,608],{},"CustomNpcs",[490,610,611,616,619],{},[508,612,613],{},[184,614,615],{},"Enemies",[508,617,618],{},"Registered custom enemies",[508,620,621],{},[184,622,623],{},"CustomEnemies",[490,625,626,630,633],{},[508,627,628],{},[184,629,119],{},[508,631,632],{},"Registered custom structures",[508,634,635],{},[184,636,637],{},"CustomStructures",[490,639,640,644,647],{},[508,641,642],{},[184,643,137],{},[508,645,646],{},"Registered inventory items",[508,648,649],{},[184,650,651],{},"CustomInventoryItems",[490,653,654,659,662],{},[508,655,656],{},[184,657,658],{},"Meals",[508,660,661],{},"Registered meals",[508,663,664],{},[184,665,666],{},"CustomMeals",[490,668,669,673,676],{},[508,670,671],{},[184,672,93],{},[508,674,675],{},"Registered tarot cards",[508,677,678],{},[184,679,680],{},"CustomTarotCards",[490,682,683,688,694],{},[508,684,685],{},[184,686,687],{},"Weapons",[508,689,690,691],{},"Custom weapons, as ",[184,692,693],{},"spineFolder\u002FweaponName",[508,695,696],{},[184,697,698],{},"PlayerSkins",[490,700,701,705,711],{},[508,702,703],{},[184,704,698],{},[508,706,707,708],{},"Player spines, as ",[184,709,710],{},"spineFolder\u002FskinName",[508,712,713],{},[184,714,698],{},[490,716,717,722,725],{},[508,718,719],{},[184,720,721],{},"FollowerSkins",[508,723,724],{},"Custom follower skins",[508,726,727],{},[184,728,721],{},[490,730,731,736,739],{},[508,732,733],{},[184,734,735],{},"Cutscenes",[508,737,738],{},"Cutscene videos",[508,740,741],{},[184,742,743],{},"CustomCutscenes",[490,745,746,751,754],{},[508,747,748],{},[184,749,750],{},"ShapeProfiles",[508,752,753],{},"Sprite shape profiles",[508,755,756],{},[184,757,758],{},"CustomShapeProfiles",[490,760,761,766,769],{},[508,762,763],{},[184,764,765],{},"BuildingOverrides",[508,767,768],{},"Buildings with overridden art",[508,770,771],{},[184,772,765],{},[490,774,775,780,786],{},[508,776,777],{},[184,778,779],{},"Quests",[508,781,782,783],{},"Quests declared by custom NPCs, as ",[184,784,785],{},"npcInternalName\u002FquestId",[508,787,788],{},[184,789,608],{},[172,791,792,795,796,799],{},[184,793,794],{},"CultTweakerApi.Kinds()"," returns the whole list, so you can iterate without\nhard-coding it, and ",[184,797,798],{},"FolderFor(kind)"," gives the folder name, or null for a kind\nwith no folder.",[176,801,803],{"id":802},"queries","Queries",[188,805,807],{"className":281,"code":806,"language":283,"meta":194,"style":194},"IReadOnlyList\u003Cstring> Names(string kind);   \u002F\u002F what this install has\nbool                  Has(string kind, string name);\nint                   IdOf(string kind, string name);   \u002F\u002F see the warning below\nstring                FolderFor(string kind);\nIReadOnlyList\u003Cstring> Kinds();\nbool                  Ready { get; }\nstring                Version { get; }\nvoid                  OnReady(Action callback);\n",[184,808,809,814,819,824,829,834,839,844],{"__ignoreMap":194},[247,810,811],{"class":249,"line":250},[247,812,813],{},"IReadOnlyList\u003Cstring> Names(string kind);   \u002F\u002F what this install has\n",[247,815,816],{"class":249,"line":256},[247,817,818],{},"bool                  Has(string kind, string name);\n",[247,820,821],{"class":249,"line":262},[247,822,823],{},"int                   IdOf(string kind, string name);   \u002F\u002F see the warning below\n",[247,825,826],{"class":249,"line":268},[247,827,828],{},"string                FolderFor(string kind);\n",[247,830,831],{"class":249,"line":308},[247,832,833],{},"IReadOnlyList\u003Cstring> Kinds();\n",[247,835,836],{"class":249,"line":315},[247,837,838],{},"bool                  Ready { get; }\n",[247,840,841],{"class":249,"line":321},[247,842,843],{},"string                Version { get; }\n",[247,845,846],{"class":249,"line":327},[247,847,848],{},"void                  OnReady(Action callback);\n",[172,850,851],{},"Registered kinds answer with what actually loaded. Document kinds answer with the\nfile names found across every mod's folders, including yours.",[176,853,855],{"id":854},"actions","Actions",[188,857,859],{"className":281,"code":858,"language":283,"meta":194,"style":194},"bool       EnterDungeon(string name);   \u002F\u002F by internal name or in-game name\nstring     CurrentDungeon();            \u002F\u002F internal name, or null\nGameObject SpawnNpc(string name, Vector3 position, Transform parent = null);\n",[184,860,861,866,871],{"__ignoreMap":194},[247,862,863],{"class":249,"line":250},[247,864,865],{},"bool       EnterDungeon(string name);   \u002F\u002F by internal name or in-game name\n",[247,867,868],{"class":249,"line":256},[247,869,870],{},"string     CurrentDungeon();            \u002F\u002F internal name, or null\n",[247,872,873],{"class":249,"line":262},[247,874,875],{},"GameObject SpawnNpc(string name, Vector3 position, Transform parent = null);\n",[172,877,878,881],{},[184,879,880],{},"EnterDungeon"," starts a run the way the player entering it would, so call it from\na normal gameplay moment rather than during a load. It returns false when this\ninstall does not have that dungeon.",[176,883,885],{"id":884},"quests-contract-version-2","Quests (contract version 2)",[188,887,889],{"className":281,"code":888,"language":283,"meta":194,"style":194},"string                QuestState(string key);   \u002F\u002F notStarted, active, ready, done, failed, or null\nIReadOnlyList\u003Cstring> ActiveQuests();\nbool                  GiveQuest(string key);\nbool                  TurnInQuest(string key);\nbool                  AbandonQuest(string key);\nvoid                  NoteQuestEvent(string flag);\n",[184,890,891,896,901,906,911,916],{"__ignoreMap":194},[247,892,893],{"class":249,"line":250},[247,894,895],{},"string                QuestState(string key);   \u002F\u002F notStarted, active, ready, done, failed, or null\n",[247,897,898],{"class":249,"line":256},[247,899,900],{},"IReadOnlyList\u003Cstring> ActiveQuests();\n",[247,902,903],{"class":249,"line":262},[247,904,905],{},"bool                  GiveQuest(string key);\n",[247,907,908],{"class":249,"line":268},[247,909,910],{},"bool                  TurnInQuest(string key);\n",[247,912,913],{"class":249,"line":308},[247,914,915],{},"bool                  AbandonQuest(string key);\n",[247,917,918],{"class":249,"line":315},[247,919,920],{},"void                  NoteQuestEvent(string flag);\n",[172,922,923,924,927,928,930,931,934],{},"Keys are the names ",[184,925,926],{},"Names(Kind.Quests)"," returns: ",[184,929,785],{},".\n",[184,932,933],{},"ready"," means every goal is met and the player has not handed the quest in yet.",[172,936,937,940,941,944,945,949],{},[184,938,939],{},"NoteQuestEvent"," is the hook for a quest that has to wait on something the game\nnever announces: declare a goal of type ",[184,942,943],{},"flag"," with a name of your choosing, and\nraise that name when your own mod decides the moment has come. Quests, their\ngoals and their text are written by whoever makes the NPC - see\n",[946,947,948],"a",{"href":63},"custom NPC quests"," - so a mod can ship a\nquest with no code at all and only reach for these calls when it needs to drive\none.",[172,951,952],{},"Quest progress is CultTweaker's own per-slot file, not the game's save, and it is\nkeyed by name throughout, so none of this carries the id warning below.",[176,954,956],{"id":955},"where-content-lives","Where content lives",[188,958,960],{"className":281,"code":959,"language":283,"meta":194,"style":194},"string                ContentRoot(string folderName);        \u002F\u002F CultTweaker's own folder\nIReadOnlyList\u003Cstring> ContentRoots(string folderName);       \u002F\u002F ours, then every mod's\nIReadOnlyList\u003Cstring> ContentDirectories(string folderName); \u002F\u002F per-item folders, absolute\nIReadOnlyList\u003Cstring> ContentFiles(string folderName, string pattern);\nstring                FindContentFile(string folderName, string fileName);\nstring                FindContentDirectory(string folderName, string subFolder);\n",[184,961,962,967,972,977,982,987],{"__ignoreMap":194},[247,963,964],{"class":249,"line":250},[247,965,966],{},"string                ContentRoot(string folderName);        \u002F\u002F CultTweaker's own folder\n",[247,968,969],{"class":249,"line":256},[247,970,971],{},"IReadOnlyList\u003Cstring> ContentRoots(string folderName);       \u002F\u002F ours, then every mod's\n",[247,973,974],{"class":249,"line":262},[247,975,976],{},"IReadOnlyList\u003Cstring> ContentDirectories(string folderName); \u002F\u002F per-item folders, absolute\n",[247,978,979],{"class":249,"line":268},[247,980,981],{},"IReadOnlyList\u003Cstring> ContentFiles(string folderName, string pattern);\n",[247,983,984],{"class":249,"line":308},[247,985,986],{},"string                FindContentFile(string folderName, string fileName);\n",[247,988,989],{"class":249,"line":315},[247,990,991],{},"string                FindContentDirectory(string folderName, string subFolder);\n",[172,993,994,995,998],{},"Use these to find your own shipped content on disk, or to read a document a\nplayer made. Do not write into ",[184,996,997],{},"ContentRoot",": that folder holds the player's own\ncreations. Ship your files inside your own plugin folder as shown at the top.",[176,1000,1002],{"id":1001},"ids-and-why-you-must-not-save-them","Ids and why you must not save them",[172,1004,1005,1008],{},[184,1006,1007],{},"IdOf"," returns the number the game gave a piece of content, for the kinds backed\nby a game enum: items, meals, tarots, structures, enemies, weapons and dungeons.",[1010,1011,1012,1016,1017,1019],"warning",{},[1013,1014,1015],"strong",{},"These numbers are allocated per install, in load order."," The same dungeon is a\ndifferent number on another machine, and adding or removing any mod can renumber\neverything. Use an id for an immediate call into the game and nothing else. Never\nwrite one to a save file and never send one to another machine: send the name and\ncall ",[184,1018,1007],{}," again on the other side.",[172,1021,1022],{},"This is not theoretical. A multiplayer mod sent a custom dungeon's raw id to the\nother player, whose install had a different number for it, and the guest sat on a\nblack loading screen because the dungeon it was told to load did not exist there.",[176,1024,1026],{"id":1025},"load-order","Load order",[172,1028,1029,1030,1033,1034,1036,1037,1040],{},"CultTweaker registers its content during its own ",[184,1031,1032],{},"Awake",", and BepInEx does not\npromise plugin order. A mod that reads the registries from its own ",[184,1035,1032],{}," may\nsee nothing. Either read them lazily, when a scene loads or when the player does\nsomething, or pass a callback to ",[184,1038,1039],{},"CultTweakerApi.OnReady",", which runs immediately\nif content is already loaded and at the end of our boot otherwise.",[176,1042,1044],{"id":1043},"versioning","Versioning",[172,1046,1047,1050],{},[184,1048,1049],{},"CultTweakerApi.ContractVersion"," started at 1 and goes up by one whenever members\nare added. Members are never removed and never change meaning, so code written\nagainst 1 keeps working against 2. Check it once at startup if you need a member\nadded later:",[188,1052,1054],{"className":281,"code":1053,"language":283,"meta":194,"style":194},"if (CultTweakerApi.ContractVersion >= 2) { \u002F* the quest members *\u002F }\n",[184,1055,1056],{"__ignoreMap":194},[247,1057,1058],{"class":249,"line":250},[247,1059,1053],{},[484,1061,1062,1072],{},[487,1063,1064],{},[490,1065,1066,1069],{},[493,1067,1068],{},"Version",[493,1070,1071],{},"Added",[503,1073,1074,1085],{},[490,1075,1076,1079],{},[508,1077,1078],{},"1",[508,1080,1081,1082,482],{},"The kinds, the queries, the actions, the content paths, ",[184,1083,1084],{},"OnReady",[490,1086,1087,1090],{},[508,1088,1089],{},"2",[508,1091,1092,1095],{},[184,1093,1094],{},"Kind.Quests"," and the quest members.",[172,1097,1098],{},"If you need something the contract does not expose, ask rather than reflecting\ninto the assembly: anything reached by reflection will break the next time those\ninternals move.",[1100,1101,1102],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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);}",{"title":194,"searchDepth":256,"depth":256,"links":1104},[1105,1106,1107,1108,1109,1110,1111,1112,1113,1114,1115],{"id":178,"depth":256,"text":179},{"id":215,"depth":256,"text":216},{"id":274,"depth":256,"text":275},{"id":474,"depth":256,"text":475},{"id":802,"depth":256,"text":803},{"id":854,"depth":256,"text":855},{"id":884,"depth":256,"text":885},{"id":955,"depth":256,"text":956},{"id":1001,"depth":256,"text":1002},{"id":1025,"depth":256,"text":1026},{"id":1043,"depth":256,"text":1044},"Ship content through CultTweaker with no code, or reference CultTweakerApi for queries, actions, quests and content paths.","md",null,{},{"title":67,"icon":70},{"title":67,"description":1116},"6_EcZz2oDOL48l7v8prPOgxmg2koV47O73zl8U1HtHE",[1124,1126],{"title":62,"path":63,"stem":64,"description":1125,"icon":65,"children":-1},"Give a custom NPC quests that appear in the game's own objectives panel - goals, dialogue, entry conditions, rewards and where progress is saved.",{"title":72,"path":73,"stem":74,"description":1127,"icon":75,"children":-1},"Every CultTweaker release, newest first - the 2.0 Worldshaper pre-releases, then the 1.x and 0.x history.",1789208920288]