modwright 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (455) hide show
  1. package/LICENSE +35 -0
  2. package/README.md +212 -0
  3. package/assets/claude/agents/mw-explore.md +46 -0
  4. package/assets/claude/agents/mw-fixture.md +33 -0
  5. package/assets/claude/agents/mw-rule-author.md +51 -0
  6. package/assets/claude/agents/mw-scaffold-author.md +48 -0
  7. package/assets/claude/skills/mw-author.md +59 -0
  8. package/assets/claude/skills/mw-new-item.md +51 -0
  9. package/assets/claude/skills/mw-new-spell.md +50 -0
  10. package/assets/claude/skills/mw-scaffold.md +59 -0
  11. package/assets/claude/skills/mw-ship.md +57 -0
  12. package/assets/claude/skills/mw-validate.md +51 -0
  13. package/assets/claude/skills/mw-verify.md +59 -0
  14. package/assets/nivalisnights/extract_resources.py +177 -0
  15. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Config.json +5 -0
  16. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapClient.lua +55 -0
  17. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapServer.lua +81 -0
  18. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Log.lua +96 -0
  19. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Probes.lua +1038 -0
  20. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/ProbesClient.lua +74 -0
  21. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Protocol.lua +985 -0
  22. package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Watch.lua +175 -0
  23. package/bridges/bg3-se/Mods/ModWrightBridge/meta.lsx +45 -0
  24. package/bridges/bg3-se/README.md +99 -0
  25. package/bridges/bg3-se/bridge.json +68 -0
  26. package/bridges/cp2077-cet/ModWrightBridge/init.lua +375 -0
  27. package/bridges/cp2077-cet/ModWrightBridge/probes.lua +1104 -0
  28. package/bridges/cp2077-cet/ModWrightBridge/protocol.lua +1306 -0
  29. package/bridges/cp2077-cet/README.md +165 -0
  30. package/bridges/cp2077-cet/bridge.json +53 -0
  31. package/dist/core/bridge/arm.js +175 -0
  32. package/dist/core/bridge/cet-console.js +26 -0
  33. package/dist/core/bridge/cet-log.js +362 -0
  34. package/dist/core/bridge/index.js +11 -0
  35. package/dist/core/bridge/locate.js +35 -0
  36. package/dist/core/bridge/paths.js +34 -0
  37. package/dist/core/bridge/pending.js +89 -0
  38. package/dist/core/bridge/poll.js +155 -0
  39. package/dist/core/bridge/stage.js +100 -0
  40. package/dist/core/bridge/status.js +97 -0
  41. package/dist/core/bridge/types.js +145 -0
  42. package/dist/core/bridge/validate.js +107 -0
  43. package/dist/core/build/index.js +6 -0
  44. package/dist/core/build/manifest.js +47 -0
  45. package/dist/core/build/paths.js +32 -0
  46. package/dist/core/build/run.js +342 -0
  47. package/dist/core/build/stage.js +265 -0
  48. package/dist/core/build/steps/bg3.js +129 -0
  49. package/dist/core/build/steps/core.js +195 -0
  50. package/dist/core/build/steps/cyberpunk.js +95 -0
  51. package/dist/core/build/steps/listing.js +35 -0
  52. package/dist/core/build/types.js +13 -0
  53. package/dist/core/build/zip.js +148 -0
  54. package/dist/core/compat/check.js +113 -0
  55. package/dist/core/compat/pe.js +220 -0
  56. package/dist/core/compat/types.js +1 -0
  57. package/dist/core/compat/version.js +70 -0
  58. package/dist/core/deploy/guards.js +292 -0
  59. package/dist/core/deploy/index.js +5 -0
  60. package/dist/core/deploy/plan.js +696 -0
  61. package/dist/core/deploy/reload-apply.js +361 -0
  62. package/dist/core/deploy/reload.js +358 -0
  63. package/dist/core/deploy/sources.js +169 -0
  64. package/dist/core/deploy/types.js +1 -0
  65. package/dist/core/epic.js +54 -0
  66. package/dist/core/fsutil.js +191 -0
  67. package/dist/core/home.js +70 -0
  68. package/dist/core/knowledge/facts.js +229 -0
  69. package/dist/core/knowledge/index.js +4 -0
  70. package/dist/core/knowledge/search.js +112 -0
  71. package/dist/core/knowledge/store.js +123 -0
  72. package/dist/core/knowledge/types.js +1 -0
  73. package/dist/core/ledger/check.js +42 -0
  74. package/dist/core/ledger/hooks.js +80 -0
  75. package/dist/core/ledger/index.js +7 -0
  76. package/dist/core/ledger/query.js +17 -0
  77. package/dist/core/ledger/record.js +84 -0
  78. package/dist/core/ledger/status.js +53 -0
  79. package/dist/core/ledger/store.js +98 -0
  80. package/dist/core/ledger/types.js +108 -0
  81. package/dist/core/logs/index.js +4 -0
  82. package/dist/core/logs/registry.js +50 -0
  83. package/dist/core/logs/scan.js +195 -0
  84. package/dist/core/logs/triage.js +160 -0
  85. package/dist/core/logs/types.js +1 -0
  86. package/dist/core/lsx.js +10 -0
  87. package/dist/core/lz4.js +66 -0
  88. package/dist/core/mods.js +229 -0
  89. package/dist/core/process.js +49 -0
  90. package/dist/core/project/build-steps.js +83 -0
  91. package/dist/core/project/describe.js +74 -0
  92. package/dist/core/project/index.js +5 -0
  93. package/dist/core/project/load.js +146 -0
  94. package/dist/core/project/schema.js +264 -0
  95. package/dist/core/project/types.js +3 -0
  96. package/dist/core/prompts.js +72 -0
  97. package/dist/core/registry.js +35 -0
  98. package/dist/core/safety/backup.js +206 -0
  99. package/dist/core/safety/execute.js +188 -0
  100. package/dist/core/safety/index.js +5 -0
  101. package/dist/core/safety/plan.js +122 -0
  102. package/dist/core/safety/restore.js +172 -0
  103. package/dist/core/safety/types.js +1 -0
  104. package/dist/core/scaffold/bootstrap.js +7 -0
  105. package/dist/core/scaffold/catalog.js +28 -0
  106. package/dist/core/scaffold/claude-assets.js +271 -0
  107. package/dist/core/scaffold/collisions.js +64 -0
  108. package/dist/core/scaffold/emit.js +356 -0
  109. package/dist/core/scaffold/engine.js +680 -0
  110. package/dist/core/scaffold/ids.js +78 -0
  111. package/dist/core/scaffold/index.js +10 -0
  112. package/dist/core/scaffold/jsonpath.js +121 -0
  113. package/dist/core/scaffold/load.js +81 -0
  114. package/dist/core/scaffold/render.js +85 -0
  115. package/dist/core/scaffold/sequence.js +396 -0
  116. package/dist/core/scaffold/types.js +309 -0
  117. package/dist/core/steam.js +63 -0
  118. package/dist/core/surfaceutil.js +36 -0
  119. package/dist/core/testplan/check.js +67 -0
  120. package/dist/core/testplan/index.js +5 -0
  121. package/dist/core/testplan/load.js +100 -0
  122. package/dist/core/testplan/registry.js +317 -0
  123. package/dist/core/testplan/run.js +389 -0
  124. package/dist/core/testplan/types.js +82 -0
  125. package/dist/core/text/converters/bg3.js +50 -0
  126. package/dist/core/text/converters/cyberpunk.js +36 -0
  127. package/dist/core/text/converters/index.js +261 -0
  128. package/dist/core/text/diff/cr2w.js +180 -0
  129. package/dist/core/text/diff/index.js +16 -0
  130. package/dist/core/text/diff/loca.js +43 -0
  131. package/dist/core/text/diff/lsx.js +126 -0
  132. package/dist/core/text/handles.js +86 -0
  133. package/dist/core/text/index.js +6 -0
  134. package/dist/core/text/json.js +46 -0
  135. package/dist/core/text/templates/cache.js +71 -0
  136. package/dist/core/text/templates/index.js +3 -0
  137. package/dist/core/text/templates/library.js +245 -0
  138. package/dist/core/text/templates/types.js +51 -0
  139. package/dist/core/text/toolchain.js +16 -0
  140. package/dist/core/text/types.js +1 -0
  141. package/dist/core/text/validate.js +149 -0
  142. package/dist/core/text/xml.js +58 -0
  143. package/dist/core/toolchain/datafetch.js +151 -0
  144. package/dist/core/toolchain/env.js +63 -0
  145. package/dist/core/toolchain/features.js +170 -0
  146. package/dist/core/toolchain/index.js +8 -0
  147. package/dist/core/toolchain/install.js +191 -0
  148. package/dist/core/toolchain/locate.js +275 -0
  149. package/dist/core/toolchain/remember.js +84 -0
  150. package/dist/core/toolchain/run.js +318 -0
  151. package/dist/core/toolchain/specs.js +351 -0
  152. package/dist/core/toolchain/types.js +1 -0
  153. package/dist/core/types.js +1 -0
  154. package/dist/core/userconfig.js +66 -0
  155. package/dist/core/validate/context.js +139 -0
  156. package/dist/core/validate/index.js +5 -0
  157. package/dist/core/validate/registry.js +58 -0
  158. package/dist/core/validate/run.js +131 -0
  159. package/dist/core/validate/suppressions.js +91 -0
  160. package/dist/core/validate/types.js +2 -0
  161. package/dist/core/yamledit.js +51 -0
  162. package/dist/index.js +389 -0
  163. package/dist/server.js +1914 -0
  164. package/dist/surfaces/baldursgate3/compat.js +164 -0
  165. package/dist/surfaces/baldursgate3/identity.js +110 -0
  166. package/dist/surfaces/baldursgate3/index/build.js +331 -0
  167. package/dist/surfaces/baldursgate3/index/index.js +17 -0
  168. package/dist/surfaces/baldursgate3/index/info.js +40 -0
  169. package/dist/surfaces/baldursgate3/index/parsers/loca.js +41 -0
  170. package/dist/surfaces/baldursgate3/index/parsers/lsx.js +137 -0
  171. package/dist/surfaces/baldursgate3/index/parsers/stats.js +45 -0
  172. package/dist/surfaces/baldursgate3/index/parsers/treasuretable.js +57 -0
  173. package/dist/surfaces/baldursgate3/index/parsers/xmlutil.js +142 -0
  174. package/dist/surfaces/baldursgate3/index/queries.js +327 -0
  175. package/dist/surfaces/baldursgate3/index/schema.js +62 -0
  176. package/dist/surfaces/baldursgate3/index.js +3 -0
  177. package/dist/surfaces/baldursgate3/logs.js +278 -0
  178. package/dist/surfaces/baldursgate3/modsettings.js +115 -0
  179. package/dist/surfaces/baldursgate3/pak.js +153 -0
  180. package/dist/surfaces/baldursgate3/settings.js +49 -0
  181. package/dist/surfaces/baldursgate3/surface.js +232 -0
  182. package/dist/surfaces/baldursgate3/validators/bridge.js +7 -0
  183. package/dist/surfaces/baldursgate3/validators/files.js +476 -0
  184. package/dist/surfaces/baldursgate3/validators/items.js +1001 -0
  185. package/dist/surfaces/baldursgate3/validators/progression.js +734 -0
  186. package/dist/surfaces/baldursgate3/validators/stats.js +1076 -0
  187. package/dist/surfaces/baldursgate3/validators/story.js +790 -0
  188. package/dist/surfaces/baldursgate3/validators/templates.js +7 -0
  189. package/dist/surfaces/cyberpunk2077/compat.js +223 -0
  190. package/dist/surfaces/cyberpunk2077/index/build.js +231 -0
  191. package/dist/surfaces/cyberpunk2077/index/index.js +17 -0
  192. package/dist/surfaces/cyberpunk2077/index/info.js +51 -0
  193. package/dist/surfaces/cyberpunk2077/index/model.js +52 -0
  194. package/dist/surfaces/cyberpunk2077/index/parsers/tweak.js +483 -0
  195. package/dist/surfaces/cyberpunk2077/index/parsers/tweakxl-yaml.js +183 -0
  196. package/dist/surfaces/cyberpunk2077/index/queries.js +504 -0
  197. package/dist/surfaces/cyberpunk2077/index/resource.js +135 -0
  198. package/dist/surfaces/cyberpunk2077/index/schema.js +90 -0
  199. package/dist/surfaces/cyberpunk2077/index.js +3 -0
  200. package/dist/surfaces/cyberpunk2077/logs.js +742 -0
  201. package/dist/surfaces/cyberpunk2077/paths.js +12 -0
  202. package/dist/surfaces/cyberpunk2077/surface.js +218 -0
  203. package/dist/surfaces/cyberpunk2077/validators/bridge.js +7 -0
  204. package/dist/surfaces/cyberpunk2077/validators/cr2w.js +349 -0
  205. package/dist/surfaces/cyberpunk2077/validators/garments.js +1181 -0
  206. package/dist/surfaces/cyberpunk2077/validators/mesh.js +338 -0
  207. package/dist/surfaces/cyberpunk2077/validators/modsettings.js +120 -0
  208. package/dist/surfaces/cyberpunk2077/validators/packaging.js +463 -0
  209. package/dist/surfaces/cyberpunk2077/validators/red4ext.js +318 -0
  210. package/dist/surfaces/cyberpunk2077/validators/redscript.js +193 -0
  211. package/dist/surfaces/cyberpunk2077/validators/templates.js +7 -0
  212. package/dist/surfaces/cyberpunk2077/validators/tweaks.js +768 -0
  213. package/dist/surfaces/cyberpunk2077/validators/vehicles.js +531 -0
  214. package/dist/surfaces/cyberpunk2077/validators/xl.js +308 -0
  215. package/dist/surfaces/eldenring/binders.js +111 -0
  216. package/dist/surfaces/eldenring/compat.js +166 -0
  217. package/dist/surfaces/eldenring/dcx.js +49 -0
  218. package/dist/surfaces/eldenring/index.js +13 -0
  219. package/dist/surfaces/eldenring/loaders.js +132 -0
  220. package/dist/surfaces/eldenring/logs.js +67 -0
  221. package/dist/surfaces/eldenring/paramdef.js +256 -0
  222. package/dist/surfaces/eldenring/params.js +129 -0
  223. package/dist/surfaces/eldenring/surface.js +121 -0
  224. package/dist/surfaces/eldenring/tools.js +52 -0
  225. package/dist/surfaces/eldenring/validators/binders.js +193 -0
  226. package/dist/surfaces/eldenring/validators/packages.js +159 -0
  227. package/dist/surfaces/eldenring/validators/params.js +334 -0
  228. package/dist/surfaces/eldenring/validators/profiles.js +287 -0
  229. package/dist/surfaces/index.js +34 -0
  230. package/dist/surfaces/nivalisnights/compat.js +229 -0
  231. package/dist/surfaces/nivalisnights/index/build.js +310 -0
  232. package/dist/surfaces/nivalisnights/index/index.js +5 -0
  233. package/dist/surfaces/nivalisnights/index/queries.js +231 -0
  234. package/dist/surfaces/nivalisnights/index.js +4 -0
  235. package/dist/surfaces/nivalisnights/logs.js +473 -0
  236. package/dist/surfaces/nivalisnights/surface.js +195 -0
  237. package/dist/surfaces/skyrimse/archives.js +229 -0
  238. package/dist/surfaces/skyrimse/compat.js +163 -0
  239. package/dist/surfaces/skyrimse/index.js +12 -0
  240. package/dist/surfaces/skyrimse/loadorder.js +174 -0
  241. package/dist/surfaces/skyrimse/logs.js +241 -0
  242. package/dist/surfaces/skyrimse/plugins.js +149 -0
  243. package/dist/surfaces/skyrimse/records.js +94 -0
  244. package/dist/surfaces/skyrimse/surface.js +240 -0
  245. package/dist/surfaces/skyrimse/validators/archive-records.js +165 -0
  246. package/dist/surfaces/skyrimse/validators/archives.js +110 -0
  247. package/dist/surfaces/skyrimse/validators/plugins.js +374 -0
  248. package/dist/surfaces/skyrimse/validators/records.js +117 -0
  249. package/dist/surfaces/stardewvalley/compat.js +190 -0
  250. package/dist/surfaces/stardewvalley/config.js +42 -0
  251. package/dist/surfaces/stardewvalley/contentpatcher.js +203 -0
  252. package/dist/surfaces/stardewvalley/index/index.js +229 -0
  253. package/dist/surfaces/stardewvalley/index/wiki.js +190 -0
  254. package/dist/surfaces/stardewvalley/index.js +12 -0
  255. package/dist/surfaces/stardewvalley/logs.js +307 -0
  256. package/dist/surfaces/stardewvalley/mods.js +182 -0
  257. package/dist/surfaces/stardewvalley/surface.js +244 -0
  258. package/dist/surfaces/stardewvalley/validators/content.js +321 -0
  259. package/dist/surfaces/stardewvalley/validators/fields.js +147 -0
  260. package/dist/surfaces/stardewvalley/validators/loadorder.js +69 -0
  261. package/dist/surfaces/stardewvalley/validators/manifest.js +221 -0
  262. package/dist/surfaces/subnautica2/compat.js +138 -0
  263. package/dist/surfaces/subnautica2/index.js +5 -0
  264. package/dist/surfaces/subnautica2/logs.js +129 -0
  265. package/dist/surfaces/subnautica2/paks.js +173 -0
  266. package/dist/surfaces/subnautica2/surface.js +151 -0
  267. package/dist/surfaces/subnautica2/validators/packaging.js +298 -0
  268. package/dist/surfaces/valheim/compat.js +171 -0
  269. package/dist/surfaces/valheim/index/index.js +301 -0
  270. package/dist/surfaces/valheim/index/tables.js +103 -0
  271. package/dist/surfaces/valheim/index.js +11 -0
  272. package/dist/surfaces/valheim/logs.js +197 -0
  273. package/dist/surfaces/valheim/packaging.js +131 -0
  274. package/dist/surfaces/valheim/plugins.js +270 -0
  275. package/dist/surfaces/valheim/references.js +121 -0
  276. package/dist/surfaces/valheim/surface.js +223 -0
  277. package/dist/surfaces/valheim/validators/packaging.js +218 -0
  278. package/dist/surfaces/valheim/validators/plugins.js +287 -0
  279. package/dist/surfaces/valheim/validators/references.js +169 -0
  280. package/knowledge/baldursgate3/animations.gr2.yaml +166 -0
  281. package/knowledge/baldursgate3/audio.voice.yaml +182 -0
  282. package/knowledge/baldursgate3/audio.wwise.yaml +104 -0
  283. package/knowledge/baldursgate3/charactercreation.heads-hair.yaml +193 -0
  284. package/knowledge/baldursgate3/communitylibrary.shared-content.yaml +129 -0
  285. package/knowledge/baldursgate3/compatibilityframework.api.yaml +176 -0
  286. package/knowledge/baldursgate3/crash.causes.yaml +90 -0
  287. package/knowledge/baldursgate3/dialogue.dialogbank.yaml +120 -0
  288. package/knowledge/baldursgate3/dialogue.files.yaml +236 -0
  289. package/knowledge/baldursgate3/dialogue.osiris-goals.yaml +386 -0
  290. package/knowledge/baldursgate3/dialogue.yaml +122 -0
  291. package/knowledge/baldursgate3/feats.classes.yaml +164 -0
  292. package/knowledge/baldursgate3/items.cloth-physics.yaml +167 -0
  293. package/knowledge/baldursgate3/items.roottemplates.yaml +320 -0
  294. package/knowledge/baldursgate3/items.visualbank.yaml +628 -0
  295. package/knowledge/baldursgate3/journal.quests.yaml +214 -0
  296. package/knowledge/baldursgate3/loadorder.modsettings.yaml +128 -0
  297. package/knowledge/baldursgate3/localization.handles.yaml +92 -0
  298. package/knowledge/baldursgate3/misc.encoding-and-practice.yaml +111 -0
  299. package/knowledge/baldursgate3/origins.companions.yaml +144 -0
  300. package/knowledge/baldursgate3/osiris.signatures.yaml +211 -0
  301. package/knowledge/baldursgate3/packaging.meta.yaml +155 -0
  302. package/knowledge/baldursgate3/packaging.paks.yaml +79 -0
  303. package/knowledge/baldursgate3/process.launch.yaml +34 -0
  304. package/knowledge/baldursgate3/progressions.yaml +92 -0
  305. package/knowledge/baldursgate3/publishing.modio-nexus.yaml +170 -0
  306. package/knowledge/baldursgate3/publishing.toolkit-modio.yaml +135 -0
  307. package/knowledge/baldursgate3/races.progression.yaml +228 -0
  308. package/knowledge/baldursgate3/scriptextender.console.yaml +257 -0
  309. package/knowledge/baldursgate3/scriptextender.yaml +252 -0
  310. package/knowledge/baldursgate3/stats.boosts.yaml +293 -0
  311. package/knowledge/baldursgate3/stats.equipment-kits.yaml +69 -0
  312. package/knowledge/baldursgate3/stats.interrupts.yaml +45 -0
  313. package/knowledge/baldursgate3/stats.itemcombos.yaml +65 -0
  314. package/knowledge/baldursgate3/stats.spells.yaml +293 -0
  315. package/knowledge/baldursgate3/stats.weapons.yaml +210 -0
  316. package/knowledge/baldursgate3/toolchain.divine.yaml +179 -0
  317. package/knowledge/baldursgate3/toolchain.lslib-formats.yaml +242 -0
  318. package/knowledge/baldursgate3/toolkit.levels.yaml +177 -0
  319. package/knowledge/baldursgate3/ui.icons-atlas.yaml +78 -0
  320. package/knowledge/baldursgate3/ui.icons.yaml +412 -0
  321. package/knowledge/baldursgate3/ui.mcm.yaml +161 -0
  322. package/knowledge/baldursgate3/vfx.materials.yaml +174 -0
  323. package/knowledge/baldursgate3/visuals.characterfix.yaml +73 -0
  324. package/knowledge/cyberpunk2077/animations.anims.yaml +118 -0
  325. package/knowledge/cyberpunk2077/anims.archivexl.yaml +163 -0
  326. package/knowledge/cyberpunk2077/anims.authoring.yaml +579 -0
  327. package/knowledge/cyberpunk2077/anims.encoder.yaml +156 -0
  328. package/knowledge/cyberpunk2077/anims.graph.yaml +629 -0
  329. package/knowledge/cyberpunk2077/anims.method.yaml +360 -0
  330. package/knowledge/cyberpunk2077/anims.pipeline.yaml +352 -0
  331. package/knowledge/cyberpunk2077/anims.roundtrip.yaml +222 -0
  332. package/knowledge/cyberpunk2077/anims.sets.yaml +176 -0
  333. package/knowledge/cyberpunk2077/archivexl.bodytypes.yaml +149 -0
  334. package/knowledge/cyberpunk2077/archivexl.dynamic-appearances.yaml +218 -0
  335. package/knowledge/cyberpunk2077/archivexl.manifest.yaml +214 -0
  336. package/knowledge/cyberpunk2077/audio.events.yaml +168 -0
  337. package/knowledge/cyberpunk2077/audio.sounds.yaml +164 -0
  338. package/knowledge/cyberpunk2077/audio.voicesets.yaml +146 -0
  339. package/knowledge/cyberpunk2077/cet.sandbox.yaml +219 -0
  340. package/knowledge/cyberpunk2077/clothing.garments.yaml +283 -0
  341. package/knowledge/cyberpunk2077/clothing.refits.yaml +215 -0
  342. package/knowledge/cyberpunk2077/codeware.overview.yaml +111 -0
  343. package/knowledge/cyberpunk2077/codeware.systems.yaml +192 -0
  344. package/knowledge/cyberpunk2077/drones.combat.yaml +416 -0
  345. package/knowledge/cyberpunk2077/drones.control.yaml +552 -0
  346. package/knowledge/cyberpunk2077/entities.appearance.yaml +166 -0
  347. package/knowledge/cyberpunk2077/equipmentex.slots.yaml +151 -0
  348. package/knowledge/cyberpunk2077/fx.effects.yaml +246 -0
  349. package/knowledge/cyberpunk2077/fx.lights.yaml +171 -0
  350. package/knowledge/cyberpunk2077/hair.modding.yaml +145 -0
  351. package/knowledge/cyberpunk2077/items.wiring.yaml +246 -0
  352. package/knowledge/cyberpunk2077/loadorder.archives.yaml +71 -0
  353. package/knowledge/cyberpunk2077/mesh.blender.yaml +209 -0
  354. package/knowledge/cyberpunk2077/nativedb.dump.yaml +98 -0
  355. package/knowledge/cyberpunk2077/npc.appearance.yaml +275 -0
  356. package/knowledge/cyberpunk2077/npc.behaviour.yaml +128 -0
  357. package/knowledge/cyberpunk2077/npc.locomotion.yaml +490 -0
  358. package/knowledge/cyberpunk2077/packaging.deploy.yaml +175 -0
  359. package/knowledge/cyberpunk2077/packaging.variants.yaml +176 -0
  360. package/knowledge/cyberpunk2077/player.control.yaml +918 -0
  361. package/knowledge/cyberpunk2077/process.assetbuild.yaml +154 -0
  362. package/knowledge/cyberpunk2077/process.lessons.yaml +276 -0
  363. package/knowledge/cyberpunk2077/quests.minor.yaml +46 -0
  364. package/knowledge/cyberpunk2077/quests.scenes.yaml +282 -0
  365. package/knowledge/cyberpunk2077/quickhacks.tiers.yaml +41 -0
  366. package/knowledge/cyberpunk2077/red4ext.api.yaml +645 -0
  367. package/knowledge/cyberpunk2077/red4ext.plugins.yaml +124 -0
  368. package/knowledge/cyberpunk2077/redhottools.hotreload.yaml +245 -0
  369. package/knowledge/cyberpunk2077/redscript.compile-log.yaml +76 -0
  370. package/knowledge/cyberpunk2077/redscript.modules.yaml +118 -0
  371. package/knowledge/cyberpunk2077/toolchain.wolvenkit.yaml +163 -0
  372. package/knowledge/cyberpunk2077/tweakdb.loot-recipes.yaml +184 -0
  373. package/knowledge/cyberpunk2077/tweakdb.melee.yaml +352 -0
  374. package/knowledge/cyberpunk2077/tweakdb.weapons.yaml +325 -0
  375. package/knowledge/cyberpunk2077/tweakxl.hotreload.yaml +151 -0
  376. package/knowledge/cyberpunk2077/tweakxl.yaml-syntax.yaml +208 -0
  377. package/knowledge/cyberpunk2077/ui.icons.yaml +259 -0
  378. package/knowledge/cyberpunk2077/ui.inkatlas.yaml +81 -0
  379. package/knowledge/cyberpunk2077/ui.modsettings.yaml +204 -0
  380. package/knowledge/cyberpunk2077/vehicles.control.yaml +475 -0
  381. package/knowledge/cyberpunk2077/vehicles.dashboard-ui.yaml +203 -0
  382. package/knowledge/cyberpunk2077/vehicles.entities.yaml +195 -0
  383. package/knowledge/cyberpunk2077/vehicles.wiring.yaml +137 -0
  384. package/knowledge/cyberpunk2077/wolvenkit.cli.yaml +167 -0
  385. package/knowledge/cyberpunk2077/workspot.system.yaml +55 -0
  386. package/knowledge/cyberpunk2077/world.interactions.yaml +41 -0
  387. package/knowledge/cyberpunk2077/world.loot-container.yaml +167 -0
  388. package/knowledge/cyberpunk2077/world.sectors.yaml +233 -0
  389. package/knowledge/eldenring/formats.binders.yaml +237 -0
  390. package/knowledge/eldenring/launcher.me3.yaml +230 -0
  391. package/knowledge/eldenring/launcher.modengine2.yaml +119 -0
  392. package/knowledge/eldenring/params.paramdef.yaml +149 -0
  393. package/knowledge/eldenring/params.regulation.yaml +142 -0
  394. package/knowledge/eldenring/saves.online.yaml +118 -0
  395. package/knowledge/eldenring/toolchain.cli.yaml +256 -0
  396. package/knowledge/nivalisnights/modding.runtime.yaml +157 -0
  397. package/knowledge/skyrimse/archives.bsa.yaml +212 -0
  398. package/knowledge/skyrimse/install.detection.yaml +41 -0
  399. package/knowledge/skyrimse/loadorder.files.yaml +242 -0
  400. package/knowledge/skyrimse/plugins.esl.yaml +189 -0
  401. package/knowledge/skyrimse/plugins.format.yaml +224 -0
  402. package/knowledge/skyrimse/skse.runtime.yaml +283 -0
  403. package/knowledge/skyrimse/toolchain.xedit-spriggit.yaml +336 -0
  404. package/knowledge/stardewvalley/contentpatcher.format.yaml +338 -0
  405. package/knowledge/stardewvalley/distribution.channels.yaml +236 -0
  406. package/knowledge/stardewvalley/game.versions.yaml +202 -0
  407. package/knowledge/stardewvalley/install.layout.yaml +277 -0
  408. package/knowledge/stardewvalley/smapi.loader.yaml +284 -0
  409. package/knowledge/stardewvalley/smapi.logs.yaml +329 -0
  410. package/knowledge/stardewvalley/smapi.manifest.yaml +293 -0
  411. package/knowledge/stardewvalley/toolchain.build.yaml +261 -0
  412. package/knowledge/stardewvalley/wiki.dataformat.yaml +130 -0
  413. package/knowledge/subnautica2/game.build.yaml +331 -0
  414. package/knowledge/subnautica2/modding.state.yaml +210 -0
  415. package/knowledge/subnautica2/ue5.containers.yaml +72 -0
  416. package/knowledge/subnautica2/ue5.paks.yaml +203 -0
  417. package/knowledge/subnautica2/ue5.tooling.yaml +175 -0
  418. package/knowledge/subnautica2/ue5.ue4ss.yaml +203 -0
  419. package/knowledge/valheim/bepinex.loader.yaml +247 -0
  420. package/knowledge/valheim/bepinex.plugins.yaml +251 -0
  421. package/knowledge/valheim/game.versions.yaml +321 -0
  422. package/knowledge/valheim/install.layout.yaml +216 -0
  423. package/knowledge/valheim/jotunn.library.yaml +334 -0
  424. package/knowledge/valheim/thunderstore.packaging.yaml +217 -0
  425. package/knowledge/valheim/toolchain.build.yaml +111 -0
  426. package/package.json +29 -0
  427. package/scaffolds/baldursgate3/new-class-injection.yaml +148 -0
  428. package/scaffolds/baldursgate3/new-item.yaml +264 -0
  429. package/scaffolds/baldursgate3/new-mod.yaml +174 -0
  430. package/scaffolds/baldursgate3/new-passive.yaml +100 -0
  431. package/scaffolds/baldursgate3/new-project.yaml +118 -0
  432. package/scaffolds/baldursgate3/new-quest-stub.yaml +159 -0
  433. package/scaffolds/baldursgate3/new-spell.yaml +102 -0
  434. package/scaffolds/baldursgate3/new-status.yaml +119 -0
  435. package/scaffolds/baldursgate3/sequences/subclass-kit.yaml +50 -0
  436. package/scaffolds/cyberpunk2077/edit-tweak.yaml +70 -0
  437. package/scaffolds/cyberpunk2077/mesh-export-preset.yaml +170 -0
  438. package/scaffolds/cyberpunk2077/new-entity-patch.yaml +255 -0
  439. package/scaffolds/cyberpunk2077/new-garment-refit.yaml +279 -0
  440. package/scaffolds/cyberpunk2077/new-item-chain.yaml +548 -0
  441. package/scaffolds/cyberpunk2077/new-localization.yaml +130 -0
  442. package/scaffolds/cyberpunk2077/new-mod-settings.yaml +133 -0
  443. package/scaffolds/cyberpunk2077/new-player-replacer.yaml +1003 -0
  444. package/scaffolds/cyberpunk2077/new-project.yaml +157 -0
  445. package/scaffolds/cyberpunk2077/new-sector-node.yaml +156 -0
  446. package/scaffolds/cyberpunk2077/new-tweak.yaml +121 -0
  447. package/scaffolds/cyberpunk2077/new-vehicle-livery.yaml +148 -0
  448. package/scaffolds/cyberpunk2077/new-workspot-entity.yaml +177 -0
  449. package/scaffolds/cyberpunk2077/sequences/iconic-weapon.yaml +72 -0
  450. package/scaffolds/cyberpunk2077/sequences/quickhack-takeover.yaml +213 -0
  451. package/scaffolds/stardewvalley/new-cp-patch.yaml +106 -0
  452. package/scaffolds/stardewvalley/new-csharp-mod.yaml +195 -0
  453. package/scaffolds/stardewvalley/new-project.yaml +184 -0
  454. package/scaffolds/stardewvalley/sequences/content-pack.yaml +31 -0
  455. package/scripts/mw-tool.mjs +184 -0
@@ -0,0 +1,177 @@
1
+ # new-workspot-entity (Cyberpunk 2077) — observed in game (2026-09-19).
2
+ #
3
+ # A spawnable entity whose only job is to carry a workspot, so a script can
4
+ # pose any puppet with it: spawn the entity at the puppet's transform, then
5
+ # WorkspotSystem.PlayInDeviceSimple(entity, puppet, false, n"<componentName>",
6
+ # n"", n"", 0.0, WorkspotSlidingBehaviour.DontPlayAtResourcePosition, null)
7
+ # and, when the workspot's animation set has several entries,
8
+ # WorkspotSystem.SendJumpToAnimEnt(puppet, n"<animation>", true).
9
+ # That is exactly how Appearance Menu Mod poses NPCs and spawned V clones
10
+ # (its `base\amm_workspots\entity\workspot_anim.ent`, one
11
+ # `workWorkspotResourceComponent` named `amm_workspot_base`), and what an
12
+ # in-game test confirmed on a spawned `Character.TPP_Player_Cutscene_Female`:
13
+ # `NPCPuppet.ChangeStanceState(Crouch)` sets the blackboard and poses
14
+ # nothing, the workspot kneels it. The game itself ships no entity that is
15
+ # only a workspot (the 2,607 `.workspot` resources under `base\workspots\`
16
+ # are referenced from sector nodes and device entities), which is why a mod
17
+ # that wants a pose must ship its own — and why this scaffold exists rather
18
+ # than a dependency on AMM.
19
+ #
20
+ # The component block is the `workWorkspotResourceComponent` read off the
21
+ # vanilla `base\gameplay\devices\utilities\netrunner\netrunner_chair.ent`
22
+ # (extracted 2026-09-19): `workspotResource` is the one field that matters,
23
+ # the two `*ResourceSync` paths stay unset (uint64 0, as the chair's own
24
+ # personal-link workspot has them), `syncSlotName` None, `shouldCrouch` 0,
25
+ # `parentTransform` null, identity transform. The root is a `gameObject`,
26
+ # not a bare `entEntity`: `PlayInDeviceSimple` takes the device as a
27
+ # `GameObject`, and a script resolving the spawned entity casts it to one
28
+ # (observed in game, 2026-09-19: an `entEntity` root spawned
29
+ # but never cast, so the clone was never posed). The component `id` is
30
+ # fixed above the vanilla range like `new-entity-patch`'s.
31
+ #
32
+ # `workspotResource` is a plain string, not an `index-ref`: the resource
33
+ # index answers existence (`lookup` kind `resource`, `path`), and the
34
+ # manual step says to ask it, but a scaffold that needs the index cannot
35
+ # run in a project without one, and the pose is chosen by eye in any case.
36
+ id: cyberpunk2077.new-workspot-entity
37
+ game: cyberpunk2077
38
+ title: New Cyberpunk 2077 workspot entity (a spawnable pose holder)
39
+ summary: Write a spawnable entity carrying one workWorkspotResourceComponent that points at a vanilla .workspot, plus its deserialize build step, so a script can pose a puppet with PlayInDeviceSimple.
40
+ modTypes: [quickhack, npc, entity-patch]
41
+ needs: {}
42
+ inputs:
43
+ - type: string
44
+ name: modSlug
45
+ prompt: "Lowercase depot folder name for this mod, e.g. mymod (the entity compiles to mod\\\\<slug>\\\\<entityName>.ent)."
46
+ pattern: "^[a-z][a-z0-9_]*$"
47
+ - type: string
48
+ name: entityName
49
+ prompt: "File stem of the entity, e.g. kneel_workspot (source <entityName>.ent.json, compiled <entityName>.ent)."
50
+ pattern: "^[a-z][a-z0-9_]*$"
51
+ - type: string
52
+ name: componentName
53
+ prompt: "Name of the workspot component (what a script passes as actorDataCompName to PlayInDeviceSimple)."
54
+ pattern: "^[A-Za-z][A-Za-z0-9_]*$"
55
+ default: "workspot"
56
+ - type: string
57
+ name: workspotResource
58
+ prompt: "Depot path of the vanilla .workspot the entity plays, backslashes, lowercase, e.g. base\\\\workspots\\\\common\\\\ground\\\\generic__kneel_ground__cover__01.workspot. Confirm it exists with lookup kind resource (path) first."
59
+ pattern: "^[a-z0-9_]+(\\\\[a-z0-9_.]+)+\\.workspot$"
60
+ - type: path
61
+ name: sourceDir
62
+ prompt: "Directory the entity's JSON source is written to, typically sources/<modSlug>."
63
+ mustExist: false
64
+ - type: path
65
+ name: compiledDir
66
+ prompt: "Directory the compiled <entityName>.ent lands in, typically <archive-staging>/<Project>/mod/<modSlug> — the folder the script's ResRef names (mod\\\\<modSlug>\\\\<entityName>.ent)."
67
+ mustExist: false
68
+ ids: []
69
+ emits:
70
+ # One write-text with ifExists: skip, idempotent, for the same reason
71
+ # new-entity-patch gives: an append at `components.-` would grow a second
72
+ # component with the same name and id on a re-run. The depot path does
73
+ # NOT land inside this JSON text: a backslash substituted raw into JSON
74
+ # is an invalid escape (`\w`), and the engine's string context does not
75
+ # JSON-escape. So the body carries an empty `$value` and the structured
76
+ # `insert-xl-entry` below sets the leaf by pointer (a numeric segment
77
+ # indexes the components array), which is also a plain set on a re-run.
78
+ - op: write-text
79
+ path: "${input.sourceDir}/${input.entityName}.ent.json"
80
+ ifExists: skip
81
+ body: |
82
+ {
83
+ "Header": {
84
+ "WolvenKitVersion": "8.20.0",
85
+ "WKitJsonVersion": "0.0.9",
86
+ "GameVersion": 2310,
87
+ "DataType": "CR2W",
88
+ "ArchiveFileName": "${input.entityName}.ent"
89
+ },
90
+ "Data": {
91
+ "Version": 195,
92
+ "BuildVersion": 0,
93
+ "RootChunk": {
94
+ "$type": "entEntityTemplate",
95
+ "appearances": [],
96
+ "components": [
97
+ {
98
+ "$type": "workWorkspotResourceComponent",
99
+ "deviceWorkspotResourceSync": {
100
+ "DepotPath": { "$type": "ResourcePath", "$storage": "uint64", "$value": "0" },
101
+ "Flags": "Default"
102
+ },
103
+ "id": "9020000000000000001",
104
+ "isReplicable": 0,
105
+ "localTransform": {
106
+ "$type": "WorldTransform",
107
+ "Orientation": { "$type": "Quaternion", "i": 0, "j": 0, "k": 0, "r": 1 },
108
+ "Position": {
109
+ "$type": "WorldPosition",
110
+ "x": { "$type": "FixedPoint", "Bits": 0 },
111
+ "y": { "$type": "FixedPoint", "Bits": 0 },
112
+ "z": { "$type": "FixedPoint", "Bits": 0 }
113
+ }
114
+ },
115
+ "name": { "$type": "CName", "$storage": "string", "$value": "${input.componentName}" },
116
+ "npcWorkspotResourceSync": {
117
+ "DepotPath": { "$type": "ResourcePath", "$storage": "uint64", "$value": "0" },
118
+ "Flags": "Default"
119
+ },
120
+ "parentTransform": null,
121
+ "shouldCrouch": 0,
122
+ "syncSlotName": { "$type": "CName", "$storage": "string", "$value": "None" },
123
+ "workspotResource": {
124
+ "DepotPath": { "$type": "ResourcePath", "$storage": "string", "$value": "" },
125
+ "Flags": "Default"
126
+ }
127
+ }
128
+ ],
129
+ "cookingPlatform": "PLATFORM_None",
130
+ "defaultAppearance": { "$type": "CName", "$storage": "string", "$value": "default" },
131
+ "entity": {
132
+ "HandleId": "0",
133
+ "Data": { "$type": "gameObject" }
134
+ },
135
+ "includes": [],
136
+ "resolvedDependencies": []
137
+ },
138
+ "EmbeddedFiles": []
139
+ }
140
+ }
141
+ - op: insert-xl-entry
142
+ path: "${input.sourceDir}/${input.entityName}.ent.json"
143
+ pointer: "Data.RootChunk.components.0.workspotResource.DepotPath.$value"
144
+ value: "${input.workspotResource}"
145
+ - op: patch-project
146
+ add:
147
+ outDir: "archive-staging"
148
+ steps:
149
+ - step: exec
150
+ id: "deserialize-${input.modSlug}-${input.entityName}"
151
+ command: wolvenkit-cli
152
+ args: ["convert", "deserialize", "${input.sourceDir}/${input.entityName}.ent.json", "-o", "${input.compiledDir}"]
153
+ expectOutputs: ["${input.compiledDir}/${input.entityName}.ent"]
154
+ before: stage
155
+ templates: []
156
+ satisfies:
157
+ - cp2077.vehicles.cr2w-unique-ids
158
+ - cp2077.vehicles.cr2w-resource-path-shape
159
+ - cp2077.vehicles.cr2w-gameversion-header
160
+ manual:
161
+ - title: Spawn it and pose a puppet
162
+ steps:
163
+ - "Confirm the workspot exists in the install: lookup kind resource, path ${input.workspotResource}; a count of 0 means the pose will silently not play."
164
+ - "Build, then from a script (Codeware's DynamicEntitySystem, or exEntitySpawner.Spawn from the CET console) spawn mod\\\\${input.modSlug}\\\\${input.entityName}.ent at the puppet's transform, wait for the entity to resolve (one frame; two armed bridge requests), then WorkspotSystem.PlayInDeviceSimple(entity, puppet, false, n\"${input.componentName}\", n\"\", n\"\", 0.0, WorkspotSlidingBehaviour.DontPlayAtResourcePosition, null)."
165
+ - "IsActorInWorkspot(puppet) reads true only a frame after PlayInDeviceSimple, not in the same call; if the puppet stays standing with it true, the workspot's animation does not fit the puppet's rig (observed in game: a player-rig animation did nothing on the cutscene V, the woman-average one posed it) — pick a workspot authored for that rig, or SendJumpToAnimEnt a named animation from the set."
166
+ - "Release with WorkspotSystem.StopInDevice(puppet) before despawning the entity; a puppet left in a workspot whose device vanished keeps the pose."
167
+ expected: "The puppet holds the workspot's pose from the entity's position and facing, and StopInDevice returns it to its own animation."
168
+ claim:
169
+ idSuffix: "${input.entityName}.poses"
170
+ claim: "mod\\${input.modSlug}\\${input.entityName}.ent spawns, and PlayInDeviceSimple on it with actorDataCompName ${input.componentName} puts a puppet into ${input.workspotResource}."
171
+ testRows:
172
+ - gate: P-1
173
+ title: "Spawned workspot entity poses a puppet"
174
+ expected: "Through the bridge, spawn the entity at a spawned puppet, PlayInDeviceSimple, and read IsActorInWorkspot(puppet) true a request later; the pose is visible in game."
175
+ manual: true
176
+ probeKinds: []
177
+ evidence: ["ModWright research"]
@@ -0,0 +1,72 @@
1
+ # iconic-weapon (Cyberpunk 2077) — the authoring sequence for a weapon mod:
2
+ # a project, the kitbashed mesh, the item chain, and the world placement of
3
+ # the prop that holds the acquisition. Each step names the asset it needs from the
4
+ # modder at the point it needs it; `scaffold action=plan` asks for exactly
5
+ # those and nothing is guessed. Applying a step is still `scaffold run`.
6
+ id: cyberpunk2077.iconic-weapon
7
+ game: cyberpunk2077
8
+ title: Iconic weapon from nothing
9
+ summary: Project, kitbashed mesh export, TweakXL item chain with its own blueprint and localization, and a world-placed prop for the acquisition.
10
+ modType: weapon
11
+ inputs:
12
+ - name: modName
13
+ prompt: "Mod name, used for the project and its r6/tweaks/<name> and scripts/<name> folders, e.g. MyWeapon."
14
+ - name: modSlug
15
+ prompt: "Lowercase depot folder name, used in every mod\\<slug>\\... path, e.g. myweapon."
16
+ - name: itemName
17
+ prompt: "Item name, used for the TweakDB record and LocKey namespace, e.g. MyWeapon."
18
+ steps:
19
+ - id: project
20
+ scaffold: cyberpunk2077.new-project
21
+ title: The project file and source trees
22
+ skipIf: project-exists
23
+ inputs:
24
+ name: "${sequence.modName}"
25
+ - id: mesh
26
+ scaffold: cyberpunk2077.mesh-export-preset
27
+ title: The mesh export preset (Blender join-by-material export, WolvenKit import over a donor mesh)
28
+ inputs:
29
+ presetId: "${sequence.modSlug}"
30
+ exportScriptFile: "blender/export_${sequence.modSlug}.py"
31
+ glbOutputPath: "${stage}/${sequence.modSlug}.glb"
32
+ outputMeshDir: "archive-staging/${sequence.modName}/mod/${sequence.modSlug}/meshes"
33
+ assets:
34
+ - name: blend
35
+ prompt: "The editable .blend of the kitbash, parts kept as separate objects (e.g. blender/myweapon_kitbash_edit.blend). Path relative to the project."
36
+ inputs: [blendFile]
37
+ - name: donorMesh
38
+ prompt: "The staged vanilla .mesh WolvenKit imports the exported glb over, for its chunkMaterials and skinning (extract it from the base weapon's own archive; keep it under 65,535 vertices per submesh). Path relative to the project."
39
+ inputs: [baseMeshPath]
40
+ - id: chain
41
+ scaffold: cyberpunk2077.new-item-chain
42
+ title: The item chain (TweakXL record, its own blueprint with the iconic slot, factory row, localization, cloned .app)
43
+ inputs:
44
+ itemName: "${sequence.itemName}"
45
+ modSlug: "${sequence.modSlug}"
46
+ tweaksFile: "r6/tweaks/${sequence.modName}/${sequence.modSlug}.yaml"
47
+ xlFile: "archive-staging/${sequence.modName}.archive.xl"
48
+ factoryCsvFile: "archive-staging/${sequence.modName}/mod/${sequence.modSlug}/factory_parts.csv"
49
+ enUsSourceDir: "sources/${sequence.modSlug}"
50
+ entSourceDir: "sources/entities/${sequence.modSlug}"
51
+ entCompiledDir: "archive-staging/${sequence.modName}/mod/${sequence.modSlug}"
52
+ assets:
53
+ - name: appTemplate
54
+ prompt: "The cached template-record directory of the base weapon's own .app (template extract of the .app that weapons_appearances.csv maps the base's appearanceResourceName to, kind weapon-app; it must be the base's kind, or the game hangs on equip). The record.json + content.json directory path."
55
+ inputs: [entTemplate]
56
+ - name: icon
57
+ prompt: "The inventory icon: a PNG authored dark (the png→xbm import lifts gamma in game; power-curve the pixels, ~3.0) and the .inkatlas rectangle it occupies. Not a scaffold input; say where both went."
58
+ - id: place
59
+ scaffold: cyberpunk2077.new-sector-node
60
+ title: The world-placed prop that holds the acquisition (a case, a spec)
61
+ inputs:
62
+ outputDir: "archive-staging/${sequence.modName}/mod/${sequence.modSlug}/sectors"
63
+ outputPath: "archive-staging/${sequence.modName}/mod/${sequence.modSlug}/sectors/${sequence.modSlug}.streamingsector"
64
+ assets:
65
+ - name: sectorSource
66
+ prompt: "The mod's own .streamingsector JSON source (an entSpawner export run through WolvenKit's import script; category Exterior, level 1). Path relative to the project; it must already exist."
67
+ inputs: [file]
68
+ - name: propEntity
69
+ prompt: "Depot path of the .ent the node spawns (backslashes, lowercase), e.g. mod\\myweapon\\cache_case.ent, with an appearanceName the .ent actually declares (a wrong name spawns an invisible entity)."
70
+ inputs: [entityTemplatePath]
71
+ evidence:
72
+ - cp2077.tweakdb.iconic-blueprint-required-for-mod-slot
@@ -0,0 +1,213 @@
1
+ # quickhack-takeover (Cyberpunk 2077) — the authoring sequence for a mod that
2
+ # takes an NPC over through a quickhack: a camera patched into NPC archetypes,
3
+ # the control system's quickhack records, and its Mod Settings page.
4
+ #
5
+ # The `hack` step is FIVE `new-tweak` runs, because a quickhack is five records
6
+ # and the plan runs `scaffold run` once per step (a step cannot be several
7
+ # records). Four clone a vanilla `$base` — the objectActionUI interaction, the
8
+ # status effect (the only bridge to script), the cyberdeck program, and the
9
+ # hack itself — and the eligibility wrapper is a `$type: ObjectActionPrereq`
10
+ # record with no base, written through new-tweak's `type` mode.
11
+ #
12
+ # The flats are FIXED here: this sequence records the shape of a working
13
+ # takeover mod, so it encodes the takeover wiring rather than leaving the modder to
14
+ # rediscover it. The four dependent records cross-link by
15
+ # `${steps.<id>.ids.recordName}`, so each names exactly the record the earlier
16
+ # step allocated. Values are that mod's own (memory cost 6, 30 s status duration,
17
+ # Rare program) — a sensible takeover default; the modder edits the produced
18
+ # yaml or tunes at runtime through the Mod Settings page. The flats are written
19
+ # as natural block scalars and normalized to nest under the record by
20
+ # new-tweak's `flats` `reindent`.
21
+ #
22
+ # Target-side registration: the hack only
23
+ # appears on an NPC whose `objectActions` list names it (matched by actionName),
24
+ # so the two `register-*` steps edit `Character.Interactable_NPC_Base` (humans)
25
+ # and `Character.Mechanical_NPC_Base` (mechanicals) — the bases most NPCs
26
+ # inherit their hack list from — with `objectActions: [!append <hack>]` through
27
+ # `edit-tweak`. A handful of NPC families (arasaka, Cerberus,
28
+ # drones, exos in the working mod's own tree) RE-DECLARE their own hack list
29
+ # rather than inheriting; which ones is install-version-specific (found by
30
+ # indexing the install), so registering the hack on those is left to the modder
31
+ # as extra `edit-tweak` runs rather than hardcoded here.
32
+ #
33
+ # Localization: the three `loca-*` steps define the
34
+ # `LocKey#${modName}-Name/-Description/-Ineligible` handles the records
35
+ # reference, each through `new-localization` (one en-us on-screen entry, sharing
36
+ # one source and one deserialize step across the three runs).
37
+ #
38
+ # ONE thing this sequence still does NOT do: the
39
+ # scripted eligibility class `${modName}.${modName}TargetPrereq` is redscript
40
+ # the modder writes; this sequence assumes that name in the wrapper's
41
+ # prereqClassName (ModWright has no redscript scaffold yet).
42
+ id: cyberpunk2077.quickhack-takeover
43
+ game: cyberpunk2077
44
+ title: Quickhack that takes an NPC over
45
+ summary: A camera patched into NPC archetypes, the five-record quickhack chain (interaction, status effect, eligibility wrapper, the hack, the cyberdeck program), and a Mod Settings page.
46
+ modType: quickhack
47
+ inputs:
48
+ - name: modName
49
+ prompt: "Mod name, used for the project and its r6/tweaks/<name> and scripts/<name> folders, e.g. MyTakeover."
50
+ - name: modSlug
51
+ prompt: "Lowercase depot folder name, e.g. mytakeover."
52
+ - name: patchName
53
+ prompt: "File stem of the patch entity, e.g. npc_camera_patch."
54
+ steps:
55
+ - id: project
56
+ scaffold: cyberpunk2077.new-project
57
+ title: The project file and source trees
58
+ skipIf: project-exists
59
+ inputs:
60
+ name: "${sequence.modName}"
61
+ - id: patch
62
+ scaffold: cyberpunk2077.new-entity-patch
63
+ title: The camera patched into the target archetypes
64
+ inputs:
65
+ modSlug: "${sequence.modSlug}"
66
+ patchName: "${sequence.patchName}"
67
+ component: camera
68
+ xlFile: "archive-staging/${sequence.modName}.archive.xl"
69
+ patchSourceDir: "sources/${sequence.modSlug}"
70
+ patchCompiledDir: "archive-staging/${sequence.modName}/mod/${sequence.modSlug}"
71
+ assets:
72
+ - name: targets
73
+ prompt: "The vanilla entity templates to patch, one depot path per line (backslashes, no leading slash, lowercase, .ent) — list them from the install's own archives, not from memory; a working takeover mod patched 426 human NPC archetypes."
74
+ inputs: [targets]
75
+ - id: interaction
76
+ scaffold: cyberpunk2077.new-tweak
77
+ title: The objectActionUI interaction (the hack's on-screen entry)
78
+ inputs:
79
+ file: "r6/tweaks/${sequence.modName}/${sequence.modSlug}.yaml"
80
+ recordName: "Interactions.${sequence.modName}Hack"
81
+ base: Interactions.BlindHack
82
+ flats: |
83
+ name: ${sequence.modName}Hack
84
+ caption: LocKey#${sequence.modName}-Name
85
+ description: LocKey#${sequence.modName}-Description
86
+ captionIcon: ChoiceCaptionParts.CyberwareMalfunctionIcon
87
+ - id: status-effect
88
+ scaffold: cyberpunk2077.new-tweak
89
+ title: The status effect the hack applies (the only bridge to script)
90
+ inputs:
91
+ file: "r6/tweaks/${sequence.modName}/${sequence.modSlug}.yaml"
92
+ recordName: "BaseStatusEffect.${sequence.modName}Takeover"
93
+ base: BaseStatusEffect.WasQuickHacked
94
+ flats: |
95
+ gameplayTags: [Debuff, Quickhack, ${sequence.modName}]
96
+ duration:
97
+ statModifiers:
98
+ - $type: ConstantStatModifier
99
+ statType: BaseStats.MaxDuration
100
+ modifierType: Additive
101
+ value: 30
102
+ - id: wrapper
103
+ scaffold: cyberpunk2077.new-tweak
104
+ title: The eligibility prereq wrapper ($type-only, no vanilla base)
105
+ inputs:
106
+ file: "r6/tweaks/${sequence.modName}/${sequence.modSlug}.yaml"
107
+ recordName: "Prereqs.${sequence.modName}TargetPrereq"
108
+ type: ObjectActionPrereq
109
+ flats: |
110
+ failureConditionPrereq:
111
+ - $type: IPrereq
112
+ prereqClassName: ${sequence.modName}.${sequence.modName}TargetPrereq
113
+ failureExplanation: LocKey#${sequence.modName}-Ineligible
114
+ - id: hack
115
+ scaffold: cyberpunk2077.new-tweak
116
+ title: The quickhack record (QuickHack.BaseBlindHack family), wiring the interaction, status effect and prereq
117
+ inputs:
118
+ file: "r6/tweaks/${sequence.modName}/${sequence.modSlug}.yaml"
119
+ recordName: "QuickHack.${sequence.modName}Hack"
120
+ base: QuickHack.BaseBlindHack
121
+ flats: |
122
+ actionName: ${sequence.modName}
123
+ priority: 1
124
+ objectActionUI: ${steps.interaction.ids.recordName}
125
+ costs:
126
+ - $base: QuickHack.MemoryCostControl
127
+ costMods:
128
+ - $base: QuickHack.MemoryMod
129
+ value: 6
130
+ completionEffects:
131
+ - !append
132
+ statusEffect: ${steps.status-effect.ids.recordName}
133
+ recipient: ObjectActionReference.Target
134
+ targetActivePrereqs:
135
+ - !append ${steps.wrapper.ids.recordName}
136
+ - id: program
137
+ scaffold: cyberpunk2077.new-tweak
138
+ title: The cyberdeck program item that carries the hack
139
+ inputs:
140
+ file: "r6/tweaks/${sequence.modName}/${sequence.modSlug}.yaml"
141
+ recordName: "Items.${sequence.modName}Program"
142
+ base: Items.BlindLvl1Program
143
+ flats: |
144
+ displayName: LocKey#${sequence.modName}-Name
145
+ localizedDescription: LocKey#${sequence.modName}-Description
146
+ quality: Quality.Rare
147
+ objectActions:
148
+ - ItemAction.ProgramDisassemble
149
+ - ${steps.hack.ids.recordName}
150
+ OnAttach:
151
+ - $type: GameplayLogicPackage
152
+ UIData:
153
+ iconPath: ability_utility
154
+ localizedName: LocKey#${sequence.modName}-Name
155
+ localizedDescription: LocKey#${sequence.modName}-Description
156
+ - id: register-humans
157
+ scaffold: cyberpunk2077.edit-tweak
158
+ title: Register the hack on human NPC hack lists (edits Character.Interactable_NPC_Base)
159
+ inputs:
160
+ file: "r6/tweaks/${sequence.modName}/${sequence.modSlug}.yaml"
161
+ recordName: Character.Interactable_NPC_Base
162
+ flats: |
163
+ objectActions:
164
+ - !append ${steps.hack.ids.recordName}
165
+ - id: register-mechanical
166
+ scaffold: cyberpunk2077.edit-tweak
167
+ title: Register the hack on mechanical NPC hack lists (edits Character.Mechanical_NPC_Base)
168
+ inputs:
169
+ file: "r6/tweaks/${sequence.modName}/${sequence.modSlug}.yaml"
170
+ recordName: Character.Mechanical_NPC_Base
171
+ flats: |
172
+ objectActions:
173
+ - !append ${steps.hack.ids.recordName}
174
+ - id: loca-name
175
+ scaffold: cyberpunk2077.new-localization
176
+ title: The player-facing name text (LocKey#<mod>-Name)
177
+ inputs:
178
+ modSlug: "${sequence.modSlug}"
179
+ xlFile: "archive-staging/${sequence.modName}.archive.xl"
180
+ enUsSourceDir: "sources/${sequence.modSlug}"
181
+ entCompiledDir: "archive-staging/${sequence.modName}/mod/${sequence.modSlug}"
182
+ secondaryKey: "${sequence.modName}-Name"
183
+ - id: loca-description
184
+ scaffold: cyberpunk2077.new-localization
185
+ title: The description text (LocKey#<mod>-Description)
186
+ inputs:
187
+ modSlug: "${sequence.modSlug}"
188
+ xlFile: "archive-staging/${sequence.modName}.archive.xl"
189
+ enUsSourceDir: "sources/${sequence.modSlug}"
190
+ entCompiledDir: "archive-staging/${sequence.modName}/mod/${sequence.modSlug}"
191
+ secondaryKey: "${sequence.modName}-Description"
192
+ - id: loca-ineligible
193
+ scaffold: cyberpunk2077.new-localization
194
+ title: The "ineligible target" text (LocKey#<mod>-Ineligible)
195
+ inputs:
196
+ modSlug: "${sequence.modSlug}"
197
+ xlFile: "archive-staging/${sequence.modName}.archive.xl"
198
+ enUsSourceDir: "sources/${sequence.modSlug}"
199
+ entCompiledDir: "archive-staging/${sequence.modName}/mod/${sequence.modSlug}"
200
+ secondaryKey: "${sequence.modName}-Ineligible"
201
+ - id: settings-trigger
202
+ scaffold: cyberpunk2077.new-mod-settings
203
+ title: The Mod Settings page — first setting (a trigger)
204
+ inputs:
205
+ file: "scripts/${sequence.modName}/${sequence.modSlug}_settings.reds"
206
+ className: "${sequence.modName}Settings"
207
+ - id: settings-multiplier
208
+ scaffold: cyberpunk2077.new-mod-settings
209
+ title: The Mod Settings page — second setting (a multiplier), added to the same class
210
+ inputs:
211
+ file: "scripts/${sequence.modName}/${sequence.modSlug}_settings.reds"
212
+ className: "${sequence.modName}Settings"
213
+ evidence: ["ModWright research"]
@@ -0,0 +1,106 @@
1
+ # new-cp-patch (Stardew Valley). Appends one
2
+ # patch to an existing pack's content.json, with LogName set, because
3
+ # Content Patcher's troubleshooting guide says to "make sure you set a
4
+ # LogName field ... and then search the SMAPI log file for that name".
5
+ # Limited to the two file-backed actions (Load, EditImage): their required
6
+ # fields are the same three (Target, FromFile, plus the action), every
7
+ # other action needs a body this scaffold cannot author honestly without
8
+ # the data index, and an Include is
9
+ # one line by hand.
10
+ #
11
+ # The asset FromFile names is the author's to supply: this scaffold writes
12
+ # no image. Until it exists, `stardewvalley.content.fromfile-exists` blocks
13
+ # with the file's exact path, which is the scaffold's own next step
14
+ # reported by the postcondition validate rather than a failure of it.
15
+ id: stardewvalley.new-cp-patch
16
+ game: stardewvalley
17
+ title: New Content Patcher patch (Load or EditImage)
18
+ summary: Append one Load or EditImage patch, with a LogName, to an existing pack's content.json; the FromFile asset is the author's to add under the pack.
19
+ modTypes: [content-pack]
20
+ needs: {}
21
+ inputs:
22
+ # A `path`, not a `string`, for the same two reasons every other
23
+ # append-into-an-existing-file scaffold makes its destination one
24
+ # (cyberpunk2077 new-tweak's `file`, new-mod-settings' `file`): the folder
25
+ # has to be there already — `mustExist` refuses a typo before the
26
+ # insert-xl-entry op creates a stray content.json under it, outside every
27
+ # project source where no rule would ever see it — and the engine builds
28
+ # the ledger claim id from the first `string`/`index-ref` input, so leaving
29
+ # the pack folder first would give every patch in one pack the same claim
30
+ # id (a second run is then an idempotent authored→authored no-op that keeps
31
+ # the *first* patch's claim text; `core/ledger/status.ts`). `logName` is the
32
+ # input that actually distinguishes one run from the next.
33
+ - type: path
34
+ name: folder
35
+ mustExist: true
36
+ prompt: The pack folder holding content.json, relative to the project (e.g. "[CP] YourModName"); it must already exist.
37
+ - type: string
38
+ name: logName
39
+ prompt: LogName for the patch — the name to search the SMAPI log for.
40
+ pattern: "^[^\\r\\n]+$"
41
+ - type: enum
42
+ name: action
43
+ prompt: Load replaces the whole asset with FromFile; EditImage edits or overlays part of it.
44
+ values: [Load, EditImage]
45
+ - type: string
46
+ name: target
47
+ prompt: The asset name (no Content/ prefix, no extension, no language code), e.g. "Portraits/Abigail".
48
+ pattern: "^(?!Content/)[^\\\\]+(?<!\\.xnb|\\.png|\\.json|\\.tbin|\\.tmx)$"
49
+ - type: string
50
+ name: fromFile
51
+ prompt: The file to load, relative to the pack folder (the assets/ subfolder by convention), e.g. "assets/abigail.png".
52
+ default: "assets/example.png"
53
+ ids: []
54
+ emits:
55
+ # content.json must already exist (new-project writes it); a missing file
56
+ # would come back as a Changes-only document with no Format, which the
57
+ # format rule then blocks — the report says so rather than guessing one.
58
+ # The append re-serializes the whole document (`emit.ts`), so it parses the
59
+ # file as strict JSON: a content.json carrying the `//` comments or
60
+ # trailing commas Content Patcher's own reader tolerates (and the author
61
+ # guide's examples use) fails the run with a named parse error rather than
62
+ # being silently rewritten without them. Add that patch by hand.
63
+ - op: insert-xl-entry
64
+ path: "${input.folder}/content.json"
65
+ pointer: "Changes.-"
66
+ value:
67
+ LogName: "${input.logName}"
68
+ Action: "${input.action}"
69
+ Target: "${input.target}"
70
+ FromFile: "${input.fromFile}"
71
+ templates: []
72
+ # The rules the appended patch itself must pass. fromfile-exists is
73
+ # deliberately not listed: it is expected to block until the asset is in
74
+ # place (header comment), and a satisfies rule must come back clean.
75
+ satisfies:
76
+ - stardewvalley.content.parses
77
+ - stardewvalley.content.format
78
+ - stardewvalley.content.changes-present
79
+ - stardewvalley.content.patch-action
80
+ - stardewvalley.content.patch-target
81
+ - stardewvalley.content.patch-fields
82
+ - stardewvalley.content.when-tokens
83
+ manual:
84
+ - title: Add the asset
85
+ steps:
86
+ - "Put the image at <folder>/<fromFile>; for a Load it replaces the whole asset, so unpack the original with StardewXnbHack first to match its size."
87
+ - "Re-run validate: stardewvalley.content.fromfile-exists must no longer report the file."
88
+ expected: "validate is clean for the pack."
89
+ - title: Check in game
90
+ steps:
91
+ - "Launch through SMAPI, run `patch summary` in the console, and find the LogName in the table with applied = X."
92
+ - "If it is loaded but not applied, run `patch export \"<target>\"` to see what the game currently has for that asset."
93
+ expected: "The patch shows as loaded and applied under its LogName; the asset in game is the one from FromFile."
94
+ claim:
95
+ idSuffix: patch
96
+ claim: "content.json in ${input.folder} carries a ${input.action} patch \"${input.logName}\" on ${input.target} from ${input.fromFile}."
97
+ testRows:
98
+ - gate: S-1
99
+ title: "Patch applies"
100
+ expected: "`patch summary` lists the LogName with applied = X and the asset in game is the FromFile image."
101
+ manual: true
102
+ probeKinds: []
103
+ evidence:
104
+ - "stardewvalley.contentpatcher.format.five-actions"
105
+ - "stardewvalley.contentpatcher.format.patch-fields"
106
+ - "stardewvalley.contentpatcher.format.patch-console-commands"