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.
- package/LICENSE +35 -0
- package/README.md +212 -0
- package/assets/claude/agents/mw-explore.md +46 -0
- package/assets/claude/agents/mw-fixture.md +33 -0
- package/assets/claude/agents/mw-rule-author.md +51 -0
- package/assets/claude/agents/mw-scaffold-author.md +48 -0
- package/assets/claude/skills/mw-author.md +59 -0
- package/assets/claude/skills/mw-new-item.md +51 -0
- package/assets/claude/skills/mw-new-spell.md +50 -0
- package/assets/claude/skills/mw-scaffold.md +59 -0
- package/assets/claude/skills/mw-ship.md +57 -0
- package/assets/claude/skills/mw-validate.md +51 -0
- package/assets/claude/skills/mw-verify.md +59 -0
- package/assets/nivalisnights/extract_resources.py +177 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Config.json +5 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapClient.lua +55 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapServer.lua +81 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Log.lua +96 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Probes.lua +1038 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/ProbesClient.lua +74 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Protocol.lua +985 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Watch.lua +175 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/meta.lsx +45 -0
- package/bridges/bg3-se/README.md +99 -0
- package/bridges/bg3-se/bridge.json +68 -0
- package/bridges/cp2077-cet/ModWrightBridge/init.lua +375 -0
- package/bridges/cp2077-cet/ModWrightBridge/probes.lua +1104 -0
- package/bridges/cp2077-cet/ModWrightBridge/protocol.lua +1306 -0
- package/bridges/cp2077-cet/README.md +165 -0
- package/bridges/cp2077-cet/bridge.json +53 -0
- package/dist/core/bridge/arm.js +175 -0
- package/dist/core/bridge/cet-console.js +26 -0
- package/dist/core/bridge/cet-log.js +362 -0
- package/dist/core/bridge/index.js +11 -0
- package/dist/core/bridge/locate.js +35 -0
- package/dist/core/bridge/paths.js +34 -0
- package/dist/core/bridge/pending.js +89 -0
- package/dist/core/bridge/poll.js +155 -0
- package/dist/core/bridge/stage.js +100 -0
- package/dist/core/bridge/status.js +97 -0
- package/dist/core/bridge/types.js +145 -0
- package/dist/core/bridge/validate.js +107 -0
- package/dist/core/build/index.js +6 -0
- package/dist/core/build/manifest.js +47 -0
- package/dist/core/build/paths.js +32 -0
- package/dist/core/build/run.js +342 -0
- package/dist/core/build/stage.js +265 -0
- package/dist/core/build/steps/bg3.js +129 -0
- package/dist/core/build/steps/core.js +195 -0
- package/dist/core/build/steps/cyberpunk.js +95 -0
- package/dist/core/build/steps/listing.js +35 -0
- package/dist/core/build/types.js +13 -0
- package/dist/core/build/zip.js +148 -0
- package/dist/core/compat/check.js +113 -0
- package/dist/core/compat/pe.js +220 -0
- package/dist/core/compat/types.js +1 -0
- package/dist/core/compat/version.js +70 -0
- package/dist/core/deploy/guards.js +292 -0
- package/dist/core/deploy/index.js +5 -0
- package/dist/core/deploy/plan.js +696 -0
- package/dist/core/deploy/reload-apply.js +361 -0
- package/dist/core/deploy/reload.js +358 -0
- package/dist/core/deploy/sources.js +169 -0
- package/dist/core/deploy/types.js +1 -0
- package/dist/core/epic.js +54 -0
- package/dist/core/fsutil.js +191 -0
- package/dist/core/home.js +70 -0
- package/dist/core/knowledge/facts.js +229 -0
- package/dist/core/knowledge/index.js +4 -0
- package/dist/core/knowledge/search.js +112 -0
- package/dist/core/knowledge/store.js +123 -0
- package/dist/core/knowledge/types.js +1 -0
- package/dist/core/ledger/check.js +42 -0
- package/dist/core/ledger/hooks.js +80 -0
- package/dist/core/ledger/index.js +7 -0
- package/dist/core/ledger/query.js +17 -0
- package/dist/core/ledger/record.js +84 -0
- package/dist/core/ledger/status.js +53 -0
- package/dist/core/ledger/store.js +98 -0
- package/dist/core/ledger/types.js +108 -0
- package/dist/core/logs/index.js +4 -0
- package/dist/core/logs/registry.js +50 -0
- package/dist/core/logs/scan.js +195 -0
- package/dist/core/logs/triage.js +160 -0
- package/dist/core/logs/types.js +1 -0
- package/dist/core/lsx.js +10 -0
- package/dist/core/lz4.js +66 -0
- package/dist/core/mods.js +229 -0
- package/dist/core/process.js +49 -0
- package/dist/core/project/build-steps.js +83 -0
- package/dist/core/project/describe.js +74 -0
- package/dist/core/project/index.js +5 -0
- package/dist/core/project/load.js +146 -0
- package/dist/core/project/schema.js +264 -0
- package/dist/core/project/types.js +3 -0
- package/dist/core/prompts.js +72 -0
- package/dist/core/registry.js +35 -0
- package/dist/core/safety/backup.js +206 -0
- package/dist/core/safety/execute.js +188 -0
- package/dist/core/safety/index.js +5 -0
- package/dist/core/safety/plan.js +122 -0
- package/dist/core/safety/restore.js +172 -0
- package/dist/core/safety/types.js +1 -0
- package/dist/core/scaffold/bootstrap.js +7 -0
- package/dist/core/scaffold/catalog.js +28 -0
- package/dist/core/scaffold/claude-assets.js +271 -0
- package/dist/core/scaffold/collisions.js +64 -0
- package/dist/core/scaffold/emit.js +356 -0
- package/dist/core/scaffold/engine.js +680 -0
- package/dist/core/scaffold/ids.js +78 -0
- package/dist/core/scaffold/index.js +10 -0
- package/dist/core/scaffold/jsonpath.js +121 -0
- package/dist/core/scaffold/load.js +81 -0
- package/dist/core/scaffold/render.js +85 -0
- package/dist/core/scaffold/sequence.js +396 -0
- package/dist/core/scaffold/types.js +309 -0
- package/dist/core/steam.js +63 -0
- package/dist/core/surfaceutil.js +36 -0
- package/dist/core/testplan/check.js +67 -0
- package/dist/core/testplan/index.js +5 -0
- package/dist/core/testplan/load.js +100 -0
- package/dist/core/testplan/registry.js +317 -0
- package/dist/core/testplan/run.js +389 -0
- package/dist/core/testplan/types.js +82 -0
- package/dist/core/text/converters/bg3.js +50 -0
- package/dist/core/text/converters/cyberpunk.js +36 -0
- package/dist/core/text/converters/index.js +261 -0
- package/dist/core/text/diff/cr2w.js +180 -0
- package/dist/core/text/diff/index.js +16 -0
- package/dist/core/text/diff/loca.js +43 -0
- package/dist/core/text/diff/lsx.js +126 -0
- package/dist/core/text/handles.js +86 -0
- package/dist/core/text/index.js +6 -0
- package/dist/core/text/json.js +46 -0
- package/dist/core/text/templates/cache.js +71 -0
- package/dist/core/text/templates/index.js +3 -0
- package/dist/core/text/templates/library.js +245 -0
- package/dist/core/text/templates/types.js +51 -0
- package/dist/core/text/toolchain.js +16 -0
- package/dist/core/text/types.js +1 -0
- package/dist/core/text/validate.js +149 -0
- package/dist/core/text/xml.js +58 -0
- package/dist/core/toolchain/datafetch.js +151 -0
- package/dist/core/toolchain/env.js +63 -0
- package/dist/core/toolchain/features.js +170 -0
- package/dist/core/toolchain/index.js +8 -0
- package/dist/core/toolchain/install.js +191 -0
- package/dist/core/toolchain/locate.js +275 -0
- package/dist/core/toolchain/remember.js +84 -0
- package/dist/core/toolchain/run.js +318 -0
- package/dist/core/toolchain/specs.js +351 -0
- package/dist/core/toolchain/types.js +1 -0
- package/dist/core/types.js +1 -0
- package/dist/core/userconfig.js +66 -0
- package/dist/core/validate/context.js +139 -0
- package/dist/core/validate/index.js +5 -0
- package/dist/core/validate/registry.js +58 -0
- package/dist/core/validate/run.js +131 -0
- package/dist/core/validate/suppressions.js +91 -0
- package/dist/core/validate/types.js +2 -0
- package/dist/core/yamledit.js +51 -0
- package/dist/index.js +389 -0
- package/dist/server.js +1914 -0
- package/dist/surfaces/baldursgate3/compat.js +164 -0
- package/dist/surfaces/baldursgate3/identity.js +110 -0
- package/dist/surfaces/baldursgate3/index/build.js +331 -0
- package/dist/surfaces/baldursgate3/index/index.js +17 -0
- package/dist/surfaces/baldursgate3/index/info.js +40 -0
- package/dist/surfaces/baldursgate3/index/parsers/loca.js +41 -0
- package/dist/surfaces/baldursgate3/index/parsers/lsx.js +137 -0
- package/dist/surfaces/baldursgate3/index/parsers/stats.js +45 -0
- package/dist/surfaces/baldursgate3/index/parsers/treasuretable.js +57 -0
- package/dist/surfaces/baldursgate3/index/parsers/xmlutil.js +142 -0
- package/dist/surfaces/baldursgate3/index/queries.js +327 -0
- package/dist/surfaces/baldursgate3/index/schema.js +62 -0
- package/dist/surfaces/baldursgate3/index.js +3 -0
- package/dist/surfaces/baldursgate3/logs.js +278 -0
- package/dist/surfaces/baldursgate3/modsettings.js +115 -0
- package/dist/surfaces/baldursgate3/pak.js +153 -0
- package/dist/surfaces/baldursgate3/settings.js +49 -0
- package/dist/surfaces/baldursgate3/surface.js +232 -0
- package/dist/surfaces/baldursgate3/validators/bridge.js +7 -0
- package/dist/surfaces/baldursgate3/validators/files.js +476 -0
- package/dist/surfaces/baldursgate3/validators/items.js +1001 -0
- package/dist/surfaces/baldursgate3/validators/progression.js +734 -0
- package/dist/surfaces/baldursgate3/validators/stats.js +1076 -0
- package/dist/surfaces/baldursgate3/validators/story.js +790 -0
- package/dist/surfaces/baldursgate3/validators/templates.js +7 -0
- package/dist/surfaces/cyberpunk2077/compat.js +223 -0
- package/dist/surfaces/cyberpunk2077/index/build.js +231 -0
- package/dist/surfaces/cyberpunk2077/index/index.js +17 -0
- package/dist/surfaces/cyberpunk2077/index/info.js +51 -0
- package/dist/surfaces/cyberpunk2077/index/model.js +52 -0
- package/dist/surfaces/cyberpunk2077/index/parsers/tweak.js +483 -0
- package/dist/surfaces/cyberpunk2077/index/parsers/tweakxl-yaml.js +183 -0
- package/dist/surfaces/cyberpunk2077/index/queries.js +504 -0
- package/dist/surfaces/cyberpunk2077/index/resource.js +135 -0
- package/dist/surfaces/cyberpunk2077/index/schema.js +90 -0
- package/dist/surfaces/cyberpunk2077/index.js +3 -0
- package/dist/surfaces/cyberpunk2077/logs.js +742 -0
- package/dist/surfaces/cyberpunk2077/paths.js +12 -0
- package/dist/surfaces/cyberpunk2077/surface.js +218 -0
- package/dist/surfaces/cyberpunk2077/validators/bridge.js +7 -0
- package/dist/surfaces/cyberpunk2077/validators/cr2w.js +349 -0
- package/dist/surfaces/cyberpunk2077/validators/garments.js +1181 -0
- package/dist/surfaces/cyberpunk2077/validators/mesh.js +338 -0
- package/dist/surfaces/cyberpunk2077/validators/modsettings.js +120 -0
- package/dist/surfaces/cyberpunk2077/validators/packaging.js +463 -0
- package/dist/surfaces/cyberpunk2077/validators/red4ext.js +318 -0
- package/dist/surfaces/cyberpunk2077/validators/redscript.js +193 -0
- package/dist/surfaces/cyberpunk2077/validators/templates.js +7 -0
- package/dist/surfaces/cyberpunk2077/validators/tweaks.js +768 -0
- package/dist/surfaces/cyberpunk2077/validators/vehicles.js +531 -0
- package/dist/surfaces/cyberpunk2077/validators/xl.js +308 -0
- package/dist/surfaces/eldenring/binders.js +111 -0
- package/dist/surfaces/eldenring/compat.js +166 -0
- package/dist/surfaces/eldenring/dcx.js +49 -0
- package/dist/surfaces/eldenring/index.js +13 -0
- package/dist/surfaces/eldenring/loaders.js +132 -0
- package/dist/surfaces/eldenring/logs.js +67 -0
- package/dist/surfaces/eldenring/paramdef.js +256 -0
- package/dist/surfaces/eldenring/params.js +129 -0
- package/dist/surfaces/eldenring/surface.js +121 -0
- package/dist/surfaces/eldenring/tools.js +52 -0
- package/dist/surfaces/eldenring/validators/binders.js +193 -0
- package/dist/surfaces/eldenring/validators/packages.js +159 -0
- package/dist/surfaces/eldenring/validators/params.js +334 -0
- package/dist/surfaces/eldenring/validators/profiles.js +287 -0
- package/dist/surfaces/index.js +34 -0
- package/dist/surfaces/nivalisnights/compat.js +229 -0
- package/dist/surfaces/nivalisnights/index/build.js +310 -0
- package/dist/surfaces/nivalisnights/index/index.js +5 -0
- package/dist/surfaces/nivalisnights/index/queries.js +231 -0
- package/dist/surfaces/nivalisnights/index.js +4 -0
- package/dist/surfaces/nivalisnights/logs.js +473 -0
- package/dist/surfaces/nivalisnights/surface.js +195 -0
- package/dist/surfaces/skyrimse/archives.js +229 -0
- package/dist/surfaces/skyrimse/compat.js +163 -0
- package/dist/surfaces/skyrimse/index.js +12 -0
- package/dist/surfaces/skyrimse/loadorder.js +174 -0
- package/dist/surfaces/skyrimse/logs.js +241 -0
- package/dist/surfaces/skyrimse/plugins.js +149 -0
- package/dist/surfaces/skyrimse/records.js +94 -0
- package/dist/surfaces/skyrimse/surface.js +240 -0
- package/dist/surfaces/skyrimse/validators/archive-records.js +165 -0
- package/dist/surfaces/skyrimse/validators/archives.js +110 -0
- package/dist/surfaces/skyrimse/validators/plugins.js +374 -0
- package/dist/surfaces/skyrimse/validators/records.js +117 -0
- package/dist/surfaces/stardewvalley/compat.js +190 -0
- package/dist/surfaces/stardewvalley/config.js +42 -0
- package/dist/surfaces/stardewvalley/contentpatcher.js +203 -0
- package/dist/surfaces/stardewvalley/index/index.js +229 -0
- package/dist/surfaces/stardewvalley/index/wiki.js +190 -0
- package/dist/surfaces/stardewvalley/index.js +12 -0
- package/dist/surfaces/stardewvalley/logs.js +307 -0
- package/dist/surfaces/stardewvalley/mods.js +182 -0
- package/dist/surfaces/stardewvalley/surface.js +244 -0
- package/dist/surfaces/stardewvalley/validators/content.js +321 -0
- package/dist/surfaces/stardewvalley/validators/fields.js +147 -0
- package/dist/surfaces/stardewvalley/validators/loadorder.js +69 -0
- package/dist/surfaces/stardewvalley/validators/manifest.js +221 -0
- package/dist/surfaces/subnautica2/compat.js +138 -0
- package/dist/surfaces/subnautica2/index.js +5 -0
- package/dist/surfaces/subnautica2/logs.js +129 -0
- package/dist/surfaces/subnautica2/paks.js +173 -0
- package/dist/surfaces/subnautica2/surface.js +151 -0
- package/dist/surfaces/subnautica2/validators/packaging.js +298 -0
- package/dist/surfaces/valheim/compat.js +171 -0
- package/dist/surfaces/valheim/index/index.js +301 -0
- package/dist/surfaces/valheim/index/tables.js +103 -0
- package/dist/surfaces/valheim/index.js +11 -0
- package/dist/surfaces/valheim/logs.js +197 -0
- package/dist/surfaces/valheim/packaging.js +131 -0
- package/dist/surfaces/valheim/plugins.js +270 -0
- package/dist/surfaces/valheim/references.js +121 -0
- package/dist/surfaces/valheim/surface.js +223 -0
- package/dist/surfaces/valheim/validators/packaging.js +218 -0
- package/dist/surfaces/valheim/validators/plugins.js +287 -0
- package/dist/surfaces/valheim/validators/references.js +169 -0
- package/knowledge/baldursgate3/animations.gr2.yaml +166 -0
- package/knowledge/baldursgate3/audio.voice.yaml +182 -0
- package/knowledge/baldursgate3/audio.wwise.yaml +104 -0
- package/knowledge/baldursgate3/charactercreation.heads-hair.yaml +193 -0
- package/knowledge/baldursgate3/communitylibrary.shared-content.yaml +129 -0
- package/knowledge/baldursgate3/compatibilityframework.api.yaml +176 -0
- package/knowledge/baldursgate3/crash.causes.yaml +90 -0
- package/knowledge/baldursgate3/dialogue.dialogbank.yaml +120 -0
- package/knowledge/baldursgate3/dialogue.files.yaml +236 -0
- package/knowledge/baldursgate3/dialogue.osiris-goals.yaml +386 -0
- package/knowledge/baldursgate3/dialogue.yaml +122 -0
- package/knowledge/baldursgate3/feats.classes.yaml +164 -0
- package/knowledge/baldursgate3/items.cloth-physics.yaml +167 -0
- package/knowledge/baldursgate3/items.roottemplates.yaml +320 -0
- package/knowledge/baldursgate3/items.visualbank.yaml +628 -0
- package/knowledge/baldursgate3/journal.quests.yaml +214 -0
- package/knowledge/baldursgate3/loadorder.modsettings.yaml +128 -0
- package/knowledge/baldursgate3/localization.handles.yaml +92 -0
- package/knowledge/baldursgate3/misc.encoding-and-practice.yaml +111 -0
- package/knowledge/baldursgate3/origins.companions.yaml +144 -0
- package/knowledge/baldursgate3/osiris.signatures.yaml +211 -0
- package/knowledge/baldursgate3/packaging.meta.yaml +155 -0
- package/knowledge/baldursgate3/packaging.paks.yaml +79 -0
- package/knowledge/baldursgate3/process.launch.yaml +34 -0
- package/knowledge/baldursgate3/progressions.yaml +92 -0
- package/knowledge/baldursgate3/publishing.modio-nexus.yaml +170 -0
- package/knowledge/baldursgate3/publishing.toolkit-modio.yaml +135 -0
- package/knowledge/baldursgate3/races.progression.yaml +228 -0
- package/knowledge/baldursgate3/scriptextender.console.yaml +257 -0
- package/knowledge/baldursgate3/scriptextender.yaml +252 -0
- package/knowledge/baldursgate3/stats.boosts.yaml +293 -0
- package/knowledge/baldursgate3/stats.equipment-kits.yaml +69 -0
- package/knowledge/baldursgate3/stats.interrupts.yaml +45 -0
- package/knowledge/baldursgate3/stats.itemcombos.yaml +65 -0
- package/knowledge/baldursgate3/stats.spells.yaml +293 -0
- package/knowledge/baldursgate3/stats.weapons.yaml +210 -0
- package/knowledge/baldursgate3/toolchain.divine.yaml +179 -0
- package/knowledge/baldursgate3/toolchain.lslib-formats.yaml +242 -0
- package/knowledge/baldursgate3/toolkit.levels.yaml +177 -0
- package/knowledge/baldursgate3/ui.icons-atlas.yaml +78 -0
- package/knowledge/baldursgate3/ui.icons.yaml +412 -0
- package/knowledge/baldursgate3/ui.mcm.yaml +161 -0
- package/knowledge/baldursgate3/vfx.materials.yaml +174 -0
- package/knowledge/baldursgate3/visuals.characterfix.yaml +73 -0
- package/knowledge/cyberpunk2077/animations.anims.yaml +118 -0
- package/knowledge/cyberpunk2077/anims.archivexl.yaml +163 -0
- package/knowledge/cyberpunk2077/anims.authoring.yaml +579 -0
- package/knowledge/cyberpunk2077/anims.encoder.yaml +156 -0
- package/knowledge/cyberpunk2077/anims.graph.yaml +629 -0
- package/knowledge/cyberpunk2077/anims.method.yaml +360 -0
- package/knowledge/cyberpunk2077/anims.pipeline.yaml +352 -0
- package/knowledge/cyberpunk2077/anims.roundtrip.yaml +222 -0
- package/knowledge/cyberpunk2077/anims.sets.yaml +176 -0
- package/knowledge/cyberpunk2077/archivexl.bodytypes.yaml +149 -0
- package/knowledge/cyberpunk2077/archivexl.dynamic-appearances.yaml +218 -0
- package/knowledge/cyberpunk2077/archivexl.manifest.yaml +214 -0
- package/knowledge/cyberpunk2077/audio.events.yaml +168 -0
- package/knowledge/cyberpunk2077/audio.sounds.yaml +164 -0
- package/knowledge/cyberpunk2077/audio.voicesets.yaml +146 -0
- package/knowledge/cyberpunk2077/cet.sandbox.yaml +219 -0
- package/knowledge/cyberpunk2077/clothing.garments.yaml +283 -0
- package/knowledge/cyberpunk2077/clothing.refits.yaml +215 -0
- package/knowledge/cyberpunk2077/codeware.overview.yaml +111 -0
- package/knowledge/cyberpunk2077/codeware.systems.yaml +192 -0
- package/knowledge/cyberpunk2077/drones.combat.yaml +416 -0
- package/knowledge/cyberpunk2077/drones.control.yaml +552 -0
- package/knowledge/cyberpunk2077/entities.appearance.yaml +166 -0
- package/knowledge/cyberpunk2077/equipmentex.slots.yaml +151 -0
- package/knowledge/cyberpunk2077/fx.effects.yaml +246 -0
- package/knowledge/cyberpunk2077/fx.lights.yaml +171 -0
- package/knowledge/cyberpunk2077/hair.modding.yaml +145 -0
- package/knowledge/cyberpunk2077/items.wiring.yaml +246 -0
- package/knowledge/cyberpunk2077/loadorder.archives.yaml +71 -0
- package/knowledge/cyberpunk2077/mesh.blender.yaml +209 -0
- package/knowledge/cyberpunk2077/nativedb.dump.yaml +98 -0
- package/knowledge/cyberpunk2077/npc.appearance.yaml +275 -0
- package/knowledge/cyberpunk2077/npc.behaviour.yaml +128 -0
- package/knowledge/cyberpunk2077/npc.locomotion.yaml +490 -0
- package/knowledge/cyberpunk2077/packaging.deploy.yaml +175 -0
- package/knowledge/cyberpunk2077/packaging.variants.yaml +176 -0
- package/knowledge/cyberpunk2077/player.control.yaml +918 -0
- package/knowledge/cyberpunk2077/process.assetbuild.yaml +154 -0
- package/knowledge/cyberpunk2077/process.lessons.yaml +276 -0
- package/knowledge/cyberpunk2077/quests.minor.yaml +46 -0
- package/knowledge/cyberpunk2077/quests.scenes.yaml +282 -0
- package/knowledge/cyberpunk2077/quickhacks.tiers.yaml +41 -0
- package/knowledge/cyberpunk2077/red4ext.api.yaml +645 -0
- package/knowledge/cyberpunk2077/red4ext.plugins.yaml +124 -0
- package/knowledge/cyberpunk2077/redhottools.hotreload.yaml +245 -0
- package/knowledge/cyberpunk2077/redscript.compile-log.yaml +76 -0
- package/knowledge/cyberpunk2077/redscript.modules.yaml +118 -0
- package/knowledge/cyberpunk2077/toolchain.wolvenkit.yaml +163 -0
- package/knowledge/cyberpunk2077/tweakdb.loot-recipes.yaml +184 -0
- package/knowledge/cyberpunk2077/tweakdb.melee.yaml +352 -0
- package/knowledge/cyberpunk2077/tweakdb.weapons.yaml +325 -0
- package/knowledge/cyberpunk2077/tweakxl.hotreload.yaml +151 -0
- package/knowledge/cyberpunk2077/tweakxl.yaml-syntax.yaml +208 -0
- package/knowledge/cyberpunk2077/ui.icons.yaml +259 -0
- package/knowledge/cyberpunk2077/ui.inkatlas.yaml +81 -0
- package/knowledge/cyberpunk2077/ui.modsettings.yaml +204 -0
- package/knowledge/cyberpunk2077/vehicles.control.yaml +475 -0
- package/knowledge/cyberpunk2077/vehicles.dashboard-ui.yaml +203 -0
- package/knowledge/cyberpunk2077/vehicles.entities.yaml +195 -0
- package/knowledge/cyberpunk2077/vehicles.wiring.yaml +137 -0
- package/knowledge/cyberpunk2077/wolvenkit.cli.yaml +167 -0
- package/knowledge/cyberpunk2077/workspot.system.yaml +55 -0
- package/knowledge/cyberpunk2077/world.interactions.yaml +41 -0
- package/knowledge/cyberpunk2077/world.loot-container.yaml +167 -0
- package/knowledge/cyberpunk2077/world.sectors.yaml +233 -0
- package/knowledge/eldenring/formats.binders.yaml +237 -0
- package/knowledge/eldenring/launcher.me3.yaml +230 -0
- package/knowledge/eldenring/launcher.modengine2.yaml +119 -0
- package/knowledge/eldenring/params.paramdef.yaml +149 -0
- package/knowledge/eldenring/params.regulation.yaml +142 -0
- package/knowledge/eldenring/saves.online.yaml +118 -0
- package/knowledge/eldenring/toolchain.cli.yaml +256 -0
- package/knowledge/nivalisnights/modding.runtime.yaml +157 -0
- package/knowledge/skyrimse/archives.bsa.yaml +212 -0
- package/knowledge/skyrimse/install.detection.yaml +41 -0
- package/knowledge/skyrimse/loadorder.files.yaml +242 -0
- package/knowledge/skyrimse/plugins.esl.yaml +189 -0
- package/knowledge/skyrimse/plugins.format.yaml +224 -0
- package/knowledge/skyrimse/skse.runtime.yaml +283 -0
- package/knowledge/skyrimse/toolchain.xedit-spriggit.yaml +336 -0
- package/knowledge/stardewvalley/contentpatcher.format.yaml +338 -0
- package/knowledge/stardewvalley/distribution.channels.yaml +236 -0
- package/knowledge/stardewvalley/game.versions.yaml +202 -0
- package/knowledge/stardewvalley/install.layout.yaml +277 -0
- package/knowledge/stardewvalley/smapi.loader.yaml +284 -0
- package/knowledge/stardewvalley/smapi.logs.yaml +329 -0
- package/knowledge/stardewvalley/smapi.manifest.yaml +293 -0
- package/knowledge/stardewvalley/toolchain.build.yaml +261 -0
- package/knowledge/stardewvalley/wiki.dataformat.yaml +130 -0
- package/knowledge/subnautica2/game.build.yaml +331 -0
- package/knowledge/subnautica2/modding.state.yaml +210 -0
- package/knowledge/subnautica2/ue5.containers.yaml +72 -0
- package/knowledge/subnautica2/ue5.paks.yaml +203 -0
- package/knowledge/subnautica2/ue5.tooling.yaml +175 -0
- package/knowledge/subnautica2/ue5.ue4ss.yaml +203 -0
- package/knowledge/valheim/bepinex.loader.yaml +247 -0
- package/knowledge/valheim/bepinex.plugins.yaml +251 -0
- package/knowledge/valheim/game.versions.yaml +321 -0
- package/knowledge/valheim/install.layout.yaml +216 -0
- package/knowledge/valheim/jotunn.library.yaml +334 -0
- package/knowledge/valheim/thunderstore.packaging.yaml +217 -0
- package/knowledge/valheim/toolchain.build.yaml +111 -0
- package/package.json +29 -0
- package/scaffolds/baldursgate3/new-class-injection.yaml +148 -0
- package/scaffolds/baldursgate3/new-item.yaml +264 -0
- package/scaffolds/baldursgate3/new-mod.yaml +174 -0
- package/scaffolds/baldursgate3/new-passive.yaml +100 -0
- package/scaffolds/baldursgate3/new-project.yaml +118 -0
- package/scaffolds/baldursgate3/new-quest-stub.yaml +159 -0
- package/scaffolds/baldursgate3/new-spell.yaml +102 -0
- package/scaffolds/baldursgate3/new-status.yaml +119 -0
- package/scaffolds/baldursgate3/sequences/subclass-kit.yaml +50 -0
- package/scaffolds/cyberpunk2077/edit-tweak.yaml +70 -0
- package/scaffolds/cyberpunk2077/mesh-export-preset.yaml +170 -0
- package/scaffolds/cyberpunk2077/new-entity-patch.yaml +255 -0
- package/scaffolds/cyberpunk2077/new-garment-refit.yaml +279 -0
- package/scaffolds/cyberpunk2077/new-item-chain.yaml +548 -0
- package/scaffolds/cyberpunk2077/new-localization.yaml +130 -0
- package/scaffolds/cyberpunk2077/new-mod-settings.yaml +133 -0
- package/scaffolds/cyberpunk2077/new-player-replacer.yaml +1003 -0
- package/scaffolds/cyberpunk2077/new-project.yaml +157 -0
- package/scaffolds/cyberpunk2077/new-sector-node.yaml +156 -0
- package/scaffolds/cyberpunk2077/new-tweak.yaml +121 -0
- package/scaffolds/cyberpunk2077/new-vehicle-livery.yaml +148 -0
- package/scaffolds/cyberpunk2077/new-workspot-entity.yaml +177 -0
- package/scaffolds/cyberpunk2077/sequences/iconic-weapon.yaml +72 -0
- package/scaffolds/cyberpunk2077/sequences/quickhack-takeover.yaml +213 -0
- package/scaffolds/stardewvalley/new-cp-patch.yaml +106 -0
- package/scaffolds/stardewvalley/new-csharp-mod.yaml +195 -0
- package/scaffolds/stardewvalley/new-project.yaml +184 -0
- package/scaffolds/stardewvalley/sequences/content-pack.yaml +31 -0
- package/scripts/mw-tool.mjs +184 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# new-entity-patch (Cyberpunk 2077) — observed in game (2026-09).
|
|
2
|
+
#
|
|
3
|
+
# Adds a component to vanilla entity templates through ArchiveXL's
|
|
4
|
+
# `resource.patch`: the same mechanism `new-garment-refit` uses on the two
|
|
5
|
+
# player entities, generalised to a list of targets and a chosen component.
|
|
6
|
+
# The first component kind is the camera an in-game test proved: a
|
|
7
|
+
# `gameCameraComponent` bound to a slot on the target (`Item_Attachment_Slot` / `Head`, read off the one archetype the test
|
|
8
|
+
# read in full — the citizen default male; the other 739 under
|
|
9
|
+
# `base\characters\entities\` were not checked, which is why the two
|
|
10
|
+
# binding names are inputs with those defaults rather than constants) plus
|
|
11
|
+
# the `gameDeviceCameraControlComponent` devices carry. Activated with high
|
|
12
|
+
# priority from a script, that camera takes the game view (observed in game,
|
|
13
|
+
# 2026-09: the spawned citizen's head became the view; the loader logged
|
|
14
|
+
# both components added to the archetype at load). The component ships at
|
|
15
|
+
# identity transform: the test set the orientation (roll 90 about the
|
|
16
|
+
# bone's X) and the offset (0.15 forward, 0.06 up) live through
|
|
17
|
+
# `SetLocalOrientation` and `SetLocalPosition`, so a mod tunes them at
|
|
18
|
+
# take-over time rather than baking one head's numbers into every
|
|
19
|
+
# archetype.
|
|
20
|
+
#
|
|
21
|
+
# What the test did NOT settle, and what this scaffold therefore does not
|
|
22
|
+
# claim: input. `DeviceStartPlayerCameraControlEvent` queued on the
|
|
23
|
+
# patched NPC did not give mouse look of that camera, and movement, aim
|
|
24
|
+
# and fire were not exercised at all — the test drove the camera and
|
|
25
|
+
# nothing else. `gameDeviceCameraControlComponent` is here because it is
|
|
26
|
+
# the component a device carries beside its camera and the pair is what
|
|
27
|
+
# was proven to load and activate, NOT because it was shown to route
|
|
28
|
+
# player input to a puppet. Whatever takes over control is the mod's own
|
|
29
|
+
# system, and it is unwritten. This scaffold places two components and
|
|
30
|
+
# registers them; everything past `Activate` is still open.
|
|
31
|
+
#
|
|
32
|
+
# Why a `type: list` input (engine): one patch entity serves
|
|
33
|
+
# many targets, and ArchiveXL takes the whole list on one manifest key; a
|
|
34
|
+
# scaffold that appended one target per apply would need hundreds of
|
|
35
|
+
# applies for the NPC set.
|
|
36
|
+
id: cyberpunk2077.new-entity-patch
|
|
37
|
+
game: cyberpunk2077
|
|
38
|
+
title: New Cyberpunk 2077 entity patch (a component added to vanilla entities)
|
|
39
|
+
summary: Write a patch entity carrying one chosen component (the camera kind ships a gameCameraComponent bound to a slot plus the device camera-control component), register it in the .archive.xl resource.patch for a list of vanilla entity templates, and add the deserialize build step.
|
|
40
|
+
modTypes: [entity-patch, quickhack, npc]
|
|
41
|
+
needs: {}
|
|
42
|
+
inputs:
|
|
43
|
+
- type: string
|
|
44
|
+
name: modSlug
|
|
45
|
+
prompt: "Lowercase depot folder name for this mod, e.g. mymod (the patch compiles to mod\\\\<slug>\\\\<patchName>.ent)."
|
|
46
|
+
pattern: "^[a-z][a-z0-9_]*$"
|
|
47
|
+
- type: string
|
|
48
|
+
name: patchName
|
|
49
|
+
prompt: "File stem of the patch entity, e.g. npc_camera_patch (source <patchName>.ent.json, compiled <patchName>.ent)."
|
|
50
|
+
pattern: "^[a-z][a-z0-9_]*$"
|
|
51
|
+
- type: enum
|
|
52
|
+
name: component
|
|
53
|
+
prompt: "Which component the patch adds. camera: a gameCameraComponent bound to a slot, plus the device camera-control component."
|
|
54
|
+
values: [camera]
|
|
55
|
+
- type: string
|
|
56
|
+
name: componentName
|
|
57
|
+
prompt: "Name of the added camera component (what a script passes to FindComponentByName)."
|
|
58
|
+
pattern: "^[A-Za-z][A-Za-z0-9_]*$"
|
|
59
|
+
default: "patchCamera"
|
|
60
|
+
- type: string
|
|
61
|
+
name: bindSlotComponent
|
|
62
|
+
prompt: "The target entity's slot component the camera binds to (Item_Attachment_Slot on the one archetype the test read in full; confirm it on yours)."
|
|
63
|
+
pattern: "^[A-Za-z][A-Za-z0-9_]*$"
|
|
64
|
+
default: "Item_Attachment_Slot"
|
|
65
|
+
- type: string
|
|
66
|
+
name: bindSlot
|
|
67
|
+
prompt: "The slot in that component (Head on that archetype)."
|
|
68
|
+
pattern: "^[A-Za-z][A-Za-z0-9_]*$"
|
|
69
|
+
default: "Head"
|
|
70
|
+
- type: list
|
|
71
|
+
name: targets
|
|
72
|
+
prompt: "Vanilla entity templates to patch, one depot path per line (or semicolon-separated), e.g. base\\\\characters\\\\entities\\\\citizen\\\\citizen__default_ma.ent. Backslashes, no leading slash, lowercase, .ent."
|
|
73
|
+
itemPattern: "^[a-z0-9_]+(\\\\[a-z0-9_.]+)+\\.ent$"
|
|
74
|
+
minItems: 1
|
|
75
|
+
- type: path
|
|
76
|
+
name: xlFile
|
|
77
|
+
prompt: "Destination .archive.xl manifest (created with an empty resource.patch skeleton if missing). Put it beside the staged folder, e.g. archive-staging/<Project>.archive.xl, not inside it."
|
|
78
|
+
mustExist: false
|
|
79
|
+
- type: path
|
|
80
|
+
name: patchSourceDir
|
|
81
|
+
prompt: "Directory the patch entity's JSON source is written to, typically sources/<modSlug>."
|
|
82
|
+
mustExist: false
|
|
83
|
+
- type: path
|
|
84
|
+
name: patchCompiledDir
|
|
85
|
+
prompt: "Directory the compiled <patchName>.ent lands in, typically <archive-staging>/<Project>/mod/<modSlug> — the folder the manifest's resource.patch key names."
|
|
86
|
+
mustExist: false
|
|
87
|
+
ids: []
|
|
88
|
+
emits:
|
|
89
|
+
# The whole patch entity in one op, and deliberately so. The earlier
|
|
90
|
+
# draft wrote an empty `components: []` skeleton and appended each
|
|
91
|
+
# component with `insert-xl-entry` at `components.-` (the shape
|
|
92
|
+
# `new-garment-refit` uses, where an input-derived depot path with
|
|
93
|
+
# backslashes in it cannot be substituted into hand-typed JSON text).
|
|
94
|
+
# Nothing that lands inside this body carries a backslash — every input
|
|
95
|
+
# reaching it is `[A-Za-z][A-Za-z0-9_]*` — and `.-` *appends*, so a
|
|
96
|
+
# second apply of this scaffold (exactly the re-run this scaffold is
|
|
97
|
+
# written for: the target list widening from one archetype to the
|
|
98
|
+
# eligible set) grew the file to two cameras and two control
|
|
99
|
+
# components, sharing names and `id`s, with nothing to catch it —
|
|
100
|
+
# `cp2077.vehicles.cr2w-unique-ids` checks `HandleId`/`BufferId`, not
|
|
101
|
+
# `id`. One `write-text` with `ifExists: skip` is idempotent instead,
|
|
102
|
+
# and writes exactly the test's own file.
|
|
103
|
+
#
|
|
104
|
+
# The camera block is the turret's `gameCameraComponent`
|
|
105
|
+
# (`security_turret_1.ent`, extracted and read) — its numeric, name,
|
|
106
|
+
# plane and zoom fields, at identity transform; the eighteen
|
|
107
|
+
# `animParam*` CName defaults it also carries are not copied, matching
|
|
108
|
+
# the test's own file, which compiled and loaded without them. The
|
|
109
|
+
# `parentTransform` binding is the shape the base entity uses for its
|
|
110
|
+
# own `Targeting_Head` component. `HandleId: "0"` is this file's only
|
|
111
|
+
# handle.
|
|
112
|
+
#
|
|
113
|
+
# The two `id`s are fixed, chosen above every component id seen in a
|
|
114
|
+
# vanilla archetype (those observed run 1.7e18 to 3.5e18) so the merged
|
|
115
|
+
# entity cannot collide with one of the target's own. They are fixed,
|
|
116
|
+
# not derived, because these exact values are what the test ran with;
|
|
117
|
+
# a project applying this scaffold a *second* time, for a second patch
|
|
118
|
+
# entity over the same targets, must hand-edit the second file's two
|
|
119
|
+
# ids before both are merged into one entity.
|
|
120
|
+
- op: write-text
|
|
121
|
+
path: "${input.patchSourceDir}/${input.patchName}.ent.json"
|
|
122
|
+
ifExists: skip
|
|
123
|
+
body: |
|
|
124
|
+
{
|
|
125
|
+
"Header": {
|
|
126
|
+
"WolvenKitVersion": "8.20.0",
|
|
127
|
+
"WKitJsonVersion": "0.0.9",
|
|
128
|
+
"GameVersion": 2310,
|
|
129
|
+
"DataType": "CR2W",
|
|
130
|
+
"ArchiveFileName": "${input.patchName}.ent"
|
|
131
|
+
},
|
|
132
|
+
"Data": {
|
|
133
|
+
"Version": 195,
|
|
134
|
+
"BuildVersion": 0,
|
|
135
|
+
"RootChunk": {
|
|
136
|
+
"$type": "entEntityTemplate",
|
|
137
|
+
"components": [
|
|
138
|
+
{
|
|
139
|
+
"$type": "gameCameraComponent",
|
|
140
|
+
"farPlaneOverride": 0,
|
|
141
|
+
"fov": 60,
|
|
142
|
+
"fovOverrideValue": 0,
|
|
143
|
+
"fovOverrideWeight": 0,
|
|
144
|
+
"id": "9010000000000000001",
|
|
145
|
+
"isReplicable": 0,
|
|
146
|
+
"localTransform": {
|
|
147
|
+
"$type": "WorldTransform",
|
|
148
|
+
"Orientation": { "$type": "Quaternion", "i": 0, "j": 0, "k": 0, "r": 1 },
|
|
149
|
+
"Position": {
|
|
150
|
+
"$type": "WorldPosition",
|
|
151
|
+
"x": { "$type": "FixedPoint", "Bits": 0 },
|
|
152
|
+
"y": { "$type": "FixedPoint", "Bits": 0 },
|
|
153
|
+
"z": { "$type": "FixedPoint", "Bits": 0 }
|
|
154
|
+
}
|
|
155
|
+
},
|
|
156
|
+
"motionBlurScale": 1,
|
|
157
|
+
"name": { "$type": "CName", "$storage": "string", "$value": "${input.componentName}" },
|
|
158
|
+
"nearPlaneOverride": 0,
|
|
159
|
+
"parentTransform": {
|
|
160
|
+
"HandleId": "0",
|
|
161
|
+
"Data": {
|
|
162
|
+
"$type": "entHardTransformBinding",
|
|
163
|
+
"bindName": { "$type": "CName", "$storage": "string", "$value": "${input.bindSlotComponent}" },
|
|
164
|
+
"enabled": 1,
|
|
165
|
+
"enableMask": {
|
|
166
|
+
"$type": "entTagMask",
|
|
167
|
+
"excludedTags": { "$type": "redTagList", "tags": [ { "$type": "CName", "$storage": "string", "$value": "NoBinding" } ] },
|
|
168
|
+
"hardTags": { "$type": "redTagList", "tags": [] },
|
|
169
|
+
"softTags": { "$type": "redTagList", "tags": [] }
|
|
170
|
+
},
|
|
171
|
+
"slotName": { "$type": "CName", "$storage": "string", "$value": "${input.bindSlot}" }
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"weaponPlane": { "$type": "SWeaponPlaneParams", "blurIntensity": 0, "weaponNearPlaneCM": 0 },
|
|
175
|
+
"zoom": 1,
|
|
176
|
+
"zoomOverrideValue": 0,
|
|
177
|
+
"zoomOverrideWeight": 0,
|
|
178
|
+
"zoomWeaponOverrideValue": 0,
|
|
179
|
+
"zoomWeaponOverrideWeight": 0
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"$type": "gameDeviceCameraControlComponent",
|
|
183
|
+
"id": "9010000000000000002",
|
|
184
|
+
"isReplicable": 0,
|
|
185
|
+
"name": { "$type": "CName", "$storage": "string", "$value": "${input.componentName}Control" },
|
|
186
|
+
"persistentState": null
|
|
187
|
+
}
|
|
188
|
+
]
|
|
189
|
+
},
|
|
190
|
+
"EmbeddedFiles": []
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
- op: write-text
|
|
194
|
+
path: "${input.xlFile}"
|
|
195
|
+
ifExists: skip
|
|
196
|
+
body: |
|
|
197
|
+
{
|
|
198
|
+
"resource": { "patch": {} }
|
|
199
|
+
}
|
|
200
|
+
- op: insert-xl-entry
|
|
201
|
+
path: "${input.xlFile}"
|
|
202
|
+
pointer: "resource.patch.'mod\\${input.modSlug}\\${input.patchName}.ent'"
|
|
203
|
+
value: "${input.targets}"
|
|
204
|
+
- op: patch-project
|
|
205
|
+
add:
|
|
206
|
+
outDir: "archive-staging"
|
|
207
|
+
sources:
|
|
208
|
+
- id: "xl-${input.modSlug}"
|
|
209
|
+
path: "${input.xlFile}"
|
|
210
|
+
kind: xl
|
|
211
|
+
steps:
|
|
212
|
+
- step: exec
|
|
213
|
+
id: "deserialize-${input.modSlug}-${input.patchName}"
|
|
214
|
+
command: wolvenkit-cli
|
|
215
|
+
args: ["convert", "deserialize", "${input.patchSourceDir}/${input.patchName}.ent.json", "-o", "${input.patchCompiledDir}"]
|
|
216
|
+
expectOutputs: ["${input.patchCompiledDir}/${input.patchName}.ent"]
|
|
217
|
+
before: stage
|
|
218
|
+
deployTargets:
|
|
219
|
+
- rootId: archive
|
|
220
|
+
from: "${input.xlFile}"
|
|
221
|
+
locked: false
|
|
222
|
+
backup: true
|
|
223
|
+
templates: []
|
|
224
|
+
satisfies:
|
|
225
|
+
- cp2077.history.xl-manifest-lint
|
|
226
|
+
- cp2077.vehicles.cr2w-unique-ids
|
|
227
|
+
- cp2077.vehicles.cr2w-resource-path-shape
|
|
228
|
+
- cp2077.vehicles.cr2w-gameversion-header
|
|
229
|
+
# `cp2077.garments.xl-entries-resolve` is deliberately absent. It resolves
|
|
230
|
+
# every `resource.patch` KEY against the staged tree, and this scaffold's
|
|
231
|
+
# key is `mod\<slug>\<patch>.ent` — the compiled output of the deserialize
|
|
232
|
+
# step it adds, which does not exist until the build runs. Claiming that
|
|
233
|
+
# rule would make the scaffold's own post-apply validate report it as
|
|
234
|
+
# unresolved on a clean project. The rule is the right one to run after a
|
|
235
|
+
# build, and the manual checklist says so.
|
|
236
|
+
manual:
|
|
237
|
+
- title: Tune the camera and confirm the patch on every target
|
|
238
|
+
steps:
|
|
239
|
+
- "At take-over time set the camera's local orientation and offset from your script (the test's values on an NPC head slot: roll 90 degrees about the bone's X, 0.15 forward, 0.06 up); the patch ships the component at identity so one block serves every target."
|
|
240
|
+
- "Confirm the targets list covers the entities the mod addresses: mechanical NPCs (drones, mechs, androids) live under other template folders than base\\\\characters\\\\entities, and the index does not yet map a Character record to its template path, so find those paths with a resource prefix lookup and add them."
|
|
241
|
+
- "After a launch, read ArchiveXL.log: one \"Component \\\"${input.componentName}\\\" ... added to <target>\" line per target the game loaded; a missing line means a path in the list did not resolve."
|
|
242
|
+
- "Run validate again after a build, not only after this scaffold: cp2077.garments.xl-entries-resolve checks that the manifest's resource.patch key resolves to a staged file, and mod\\\\${input.modSlug}\\\\${input.patchName}.ent only exists once the deserialize step has run."
|
|
243
|
+
- "Write the control system yourself. The test proved the camera takes the view on Activate and nothing beyond that: DeviceStartPlayerCameraControlEvent queued on the patched NPC gave no mouse look, and movement, aim and fire were never exercised. Do not assume the device camera-control component routes player input to a puppet."
|
|
244
|
+
- "Re-applying this scaffold for a second patch entity over the same targets: hand-edit the second file's two component ids (9010000000000000001/2 are fixed here), or the two patches merge into one entity with colliding component ids."
|
|
245
|
+
expected: "Every listed target carries ${input.componentName} at load, and activating it from a script puts the game view at the bound slot."
|
|
246
|
+
claim:
|
|
247
|
+
idSuffix: "${input.patchName}.applies"
|
|
248
|
+
claim: "ArchiveXL adds ${input.componentName} to each entity in ${input.patchName}'s target list at load, and the component is reachable through FindComponentByName on a spawned instance."
|
|
249
|
+
testRows:
|
|
250
|
+
- gate: P-1
|
|
251
|
+
title: "Patched component present on a spawned target"
|
|
252
|
+
expected: "Through the bridge, spawn one target entity and read FindComponentByName(\"${input.componentName}\") on it: non-nil, and ArchiveXL.log carries the added-component line for that target."
|
|
253
|
+
manual: true
|
|
254
|
+
probeKinds: []
|
|
255
|
+
evidence: ["ModWright research"]
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# new-garment-refit (Cyberpunk 2077) — registers a body type in ArchiveXL's
|
|
2
|
+
# `player.bodyTypes` with gendered patch `.ent`s supplying the `Body:<Type>`
|
|
3
|
+
# component PuppetStateSystem looks up, and a TweakXL record for the
|
|
4
|
+
# garment item itself.
|
|
5
|
+
#
|
|
6
|
+
# Scope: this scaffold stops at the body-type registration and the TweakXL
|
|
7
|
+
# record — it does NOT author the item's own dynamic-appearance mesh-entity pair (a
|
|
8
|
+
# blank-appearance root `.ent` plus a `{gender}`/`{body}`-substituted mesh
|
|
9
|
+
# entity, the shape `jacket.ok.synthetic` demonstrates). That pair *is* the
|
|
10
|
+
# Blender refit itself: the work splits as "Scaffolded: .xl registration,
|
|
11
|
+
# .ent patch entries, TweakXL record | Human: the Blender refit" — the mesh-entity `.ent`'s own substituted component depotPaths
|
|
12
|
+
# only exist once the refit's actual meshes do. Every garment rule this
|
|
13
|
+
# scaffold's own emits could trigger (dynamicappearance-tag-present,
|
|
14
|
+
# substitution-star-prefix, gendered-appearance-suffix, etc.) is
|
|
15
|
+
# consequently vacuous here — a real pass over the human's own mesh-entity
|
|
16
|
+
# `.ent` once written, not a promise this scaffold's output alone satisfies.
|
|
17
|
+
#
|
|
18
|
+
# Deviations observed in game (2026-09):
|
|
19
|
+
# - the `.archive.xl` `resource.patch` keys were hardcoded to
|
|
20
|
+
# `mod\<slug>\body_patch_male.ent` / `_female.ent` while the `.ent.json`
|
|
21
|
+
# sources were written to whatever free-form `malePatchEntFile` /
|
|
22
|
+
# `femalePatchEntFile` named — so the manifest could point at files
|
|
23
|
+
# nothing produces. Both free-form inputs are replaced with one
|
|
24
|
+
# `archiveStagingDir` input (a project source of kind "archive-staging"),
|
|
25
|
+
# so both ends share one `mod/<slug>/body_patch_<gender>` stem and agree
|
|
26
|
+
# by construction. The editable half was then moved out of the staging
|
|
27
|
+
# tree (2026-09-11): the sources are written to
|
|
28
|
+
# `sources/${modSlug}/body_patch_<gender>.ent.json` and the two
|
|
29
|
+
# `convert deserialize` build steps below compile them to
|
|
30
|
+
# `${archiveStagingDir}/mod/${modSlug}/body_patch_<gender>.ent` — the
|
|
31
|
+
# depot key unchanged, and no CR2W JSON left in the packed archive.
|
|
32
|
+
# - `cp2077.history.xl-manifest-lint` (src/surfaces/cyberpunk2077/
|
|
33
|
+
# validators/xl.ts) rejected the `player:` key this scaffold writes;
|
|
34
|
+
# fixed there — `player` is now a known top-level key with a
|
|
35
|
+
# `bodyTypes` shape check, citing
|
|
36
|
+
# cp2077.archivexl.bodytypes.player-bodytypes-key.
|
|
37
|
+
# - the same lint pass unconditionally required a `localization:`
|
|
38
|
+
# block with an `onscreens` mapping, but this scaffold writes no loca of
|
|
39
|
+
# its own. Fixed here (not in the validator, which stays untouched
|
|
40
|
+
# beyond the `player` key fix) by emitting the documented empty shape,
|
|
41
|
+
# `"localization": { "onscreens": {} }` — matching the skeleton
|
|
42
|
+
# `new-item-chain` already writes for the same reason (`new-project`
|
|
43
|
+
# writes no `.xl` at all).
|
|
44
|
+
id: cyberpunk2077.new-garment-refit
|
|
45
|
+
game: cyberpunk2077
|
|
46
|
+
title: New Cyberpunk 2077 garment body-type refit
|
|
47
|
+
summary: Register a body type in ArchiveXL's player.bodyTypes with gendered patch .ents carrying the Body:<Type> component, plus a TweakXL record for the garment item.
|
|
48
|
+
modTypes: [garment, refit]
|
|
49
|
+
needs: { index: true }
|
|
50
|
+
inputs:
|
|
51
|
+
- type: string
|
|
52
|
+
name: bodyType
|
|
53
|
+
prompt: "Body type name registered in player.bodyTypes, e.g. Adonis."
|
|
54
|
+
pattern: "^[A-Za-z][A-Za-z0-9_]*$"
|
|
55
|
+
- type: index-ref
|
|
56
|
+
name: base
|
|
57
|
+
prompt: "$base TweakDB record this garment item inherits from, e.g. Items.GenericInnerChestClothing."
|
|
58
|
+
lookup: { kind: record, params: { name: "${input.base}" } }
|
|
59
|
+
requires: []
|
|
60
|
+
- type: string
|
|
61
|
+
name: itemName
|
|
62
|
+
prompt: "TweakDB record name / appearanceResourceName for this garment item."
|
|
63
|
+
pattern: "^[A-Za-z][A-Za-z0-9_]*$"
|
|
64
|
+
- type: string
|
|
65
|
+
name: outfitSlot
|
|
66
|
+
prompt: "OutfitSlots.* value this garment's placementSlots should !append."
|
|
67
|
+
default: "OutfitSlots.TorsoInner"
|
|
68
|
+
- type: string
|
|
69
|
+
name: modSlug
|
|
70
|
+
prompt: "Lowercase depot folder name for this garment, e.g. hexweave."
|
|
71
|
+
pattern: "^[a-z][a-z0-9_]*$"
|
|
72
|
+
- type: string
|
|
73
|
+
name: maleMeshPath
|
|
74
|
+
prompt: "Depot path (backslash, lowercase) to the male body-type mesh, e.g. mod\\\\hexweave\\\\meshes\\\\body_ma.mesh."
|
|
75
|
+
pattern: "^[a-z0-9_]+(\\\\[a-z0-9_]+)*\\.mesh$"
|
|
76
|
+
- type: string
|
|
77
|
+
name: femaleMeshPath
|
|
78
|
+
prompt: "Depot path (backslash, lowercase) to the female body-type mesh."
|
|
79
|
+
pattern: "^[a-z0-9_]+(\\\\[a-z0-9_]+)*\\.mesh$"
|
|
80
|
+
- type: path
|
|
81
|
+
name: tweaksFile
|
|
82
|
+
prompt: "Destination .yaml under a project source of kind \"tweaks\" (created if missing)."
|
|
83
|
+
mustExist: false
|
|
84
|
+
- type: path
|
|
85
|
+
name: xlFile
|
|
86
|
+
prompt: "Destination .archive.xl manifest (created with an empty skeleton if missing). Put it beside the staged folder, e.g. archive-staging/<Project>.archive.xl, not inside it; it is registered as a project source and deployed to archive/pc/mod by its file name."
|
|
87
|
+
mustExist: false
|
|
88
|
+
- type: path
|
|
89
|
+
name: archiveStagingDir
|
|
90
|
+
prompt: "Project-relative archive-staging root (a project source of kind \"archive-staging\") this garment's compiled files land under. The male/female patch .ent.json sources are written to sources/<modSlug>/ and deserialized into mod/<modSlug>/body_patch_<gender>.ent within it by the build steps this scaffold adds, so they agree by construction with the mod\\<modSlug>\\body_patch_<gender>.ent depot keys it writes into resource.patch (observed in game, 2026-09-11)."
|
|
91
|
+
mustExist: false
|
|
92
|
+
ids:
|
|
93
|
+
- name: recordName
|
|
94
|
+
slot: "Items.${project.name}_${input.itemName}"
|
|
95
|
+
form: tweak-record
|
|
96
|
+
collision:
|
|
97
|
+
project: true
|
|
98
|
+
index: { kind: record, param: name }
|
|
99
|
+
emits:
|
|
100
|
+
- op: insert-block
|
|
101
|
+
path: "${input.tweaksFile}"
|
|
102
|
+
createIfMissing: ""
|
|
103
|
+
anchor: append
|
|
104
|
+
body: |
|
|
105
|
+
${ids.recordName}:
|
|
106
|
+
$base: ${input.base}
|
|
107
|
+
appearanceResourceName: ${input.itemName}
|
|
108
|
+
placementSlots:
|
|
109
|
+
- !append ${input.outfitSlot}
|
|
110
|
+
- op: write-text
|
|
111
|
+
path: "${input.xlFile}"
|
|
112
|
+
ifExists: skip
|
|
113
|
+
body: |
|
|
114
|
+
{
|
|
115
|
+
"localization": { "onscreens": {} },
|
|
116
|
+
"player": { "bodyTypes": [] },
|
|
117
|
+
"resource": { "patch": {} }
|
|
118
|
+
}
|
|
119
|
+
- op: insert-xl-entry
|
|
120
|
+
path: "${input.xlFile}"
|
|
121
|
+
pointer: player.bodyTypes.-
|
|
122
|
+
value: "${input.bodyType}"
|
|
123
|
+
# Observed in game (2026-09-11): with `value: []` ArchiveXL
|
|
124
|
+
# logged `[error] Line #N: Patch definition must have at least one
|
|
125
|
+
# target.` for each entry and `Archive extensions are loaded with issues`,
|
|
126
|
+
# so the patch .ents never attached to anything. The targets below are
|
|
127
|
+
# the vanilla player first-person entities, base plus the Phantom Liberty
|
|
128
|
+
# twin per gender: the pair a working project's own shipped manifest patches, which
|
|
129
|
+
# loaded in the same launch with ArchiveXL logging `[ResourcePatch]
|
|
130
|
+
# Component ... added to
|
|
131
|
+
# ep1\characters\entities\player\player_wa_fpp_ep1.ent`, and the pairing
|
|
132
|
+
# cp2077.history.xl-manifest-lint already requires. The base\ pair is in
|
|
133
|
+
# the vanilla index (`player_ma_fpp.ent`, `player_wa_fpp.ent`). Whether the
|
|
134
|
+
# third-person entities (player_XX_tpp.ent, present in the vanilla index)
|
|
135
|
+
# also need the component for a body mesh to show in third person is not
|
|
136
|
+
# yet observed; the ArchiveXL body-mod doc names "player_wa.ent /
|
|
137
|
+
# player_ma.ent" without a full path.
|
|
138
|
+
- op: insert-xl-entry
|
|
139
|
+
path: "${input.xlFile}"
|
|
140
|
+
pointer: "resource.patch.'mod\\${input.modSlug}\\body_patch_male.ent'"
|
|
141
|
+
value:
|
|
142
|
+
- "base\\characters\\entities\\player\\player_ma_fpp.ent"
|
|
143
|
+
- "ep1\\characters\\entities\\player\\player_ma_fpp_ep1.ent"
|
|
144
|
+
- op: insert-xl-entry
|
|
145
|
+
path: "${input.xlFile}"
|
|
146
|
+
pointer: "resource.patch.'mod\\${input.modSlug}\\body_patch_female.ent'"
|
|
147
|
+
value:
|
|
148
|
+
- "base\\characters\\entities\\player\\player_wa_fpp.ent"
|
|
149
|
+
- "ep1\\characters\\entities\\player\\player_wa_fpp_ep1.ent"
|
|
150
|
+
# A hand-typed JSON `write-text` body cannot safely carry a backslash-
|
|
151
|
+
# bearing depot path (`${input.maleMeshPath}`) as a raw string
|
|
152
|
+
# substitution — interpolation is plain text, not JSON-escaping, so an
|
|
153
|
+
# embedded single backslash breaks the JSON it lands in. `insert-xl-entry`
|
|
154
|
+
# sidesteps this: its `value` is a structured object, serialized through
|
|
155
|
+
# `JSON.stringify` (which escapes backslashes correctly), so the skeleton
|
|
156
|
+
# below is written free of any input-derived path text and the mesh
|
|
157
|
+
# component (the one field carrying a depot path) is appended separately.
|
|
158
|
+
- op: write-text
|
|
159
|
+
path: "sources/${input.modSlug}/body_patch_male.ent.json"
|
|
160
|
+
ifExists: skip
|
|
161
|
+
body: |
|
|
162
|
+
{
|
|
163
|
+
"Header": {
|
|
164
|
+
"WolvenKitVersion": "8.20.0",
|
|
165
|
+
"WKitJsonVersion": "0.0.9",
|
|
166
|
+
"GameVersion": 2310,
|
|
167
|
+
"DataType": "CR2W",
|
|
168
|
+
"ArchiveFileName": "body_patch_male.ent"
|
|
169
|
+
},
|
|
170
|
+
"Data": {
|
|
171
|
+
"Version": 195,
|
|
172
|
+
"BuildVersion": 0,
|
|
173
|
+
"RootChunk": { "$type": "entEntityTemplate", "components": [] },
|
|
174
|
+
"EmbeddedFiles": []
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
- op: insert-xl-entry
|
|
178
|
+
path: "sources/${input.modSlug}/body_patch_male.ent.json"
|
|
179
|
+
pointer: Data.RootChunk.components.-
|
|
180
|
+
value:
|
|
181
|
+
$type: entMeshComponent
|
|
182
|
+
name: { $type: CName, $storage: string, $value: "Body:${input.bodyType}" }
|
|
183
|
+
mesh:
|
|
184
|
+
DepotPath: { $type: ResourcePath, $storage: string, $value: "${input.maleMeshPath}" }
|
|
185
|
+
Flags: Soft
|
|
186
|
+
- op: write-text
|
|
187
|
+
path: "sources/${input.modSlug}/body_patch_female.ent.json"
|
|
188
|
+
ifExists: skip
|
|
189
|
+
body: |
|
|
190
|
+
{
|
|
191
|
+
"Header": {
|
|
192
|
+
"WolvenKitVersion": "8.20.0",
|
|
193
|
+
"WKitJsonVersion": "0.0.9",
|
|
194
|
+
"GameVersion": 2310,
|
|
195
|
+
"DataType": "CR2W",
|
|
196
|
+
"ArchiveFileName": "body_patch_female.ent"
|
|
197
|
+
},
|
|
198
|
+
"Data": {
|
|
199
|
+
"Version": 195,
|
|
200
|
+
"BuildVersion": 0,
|
|
201
|
+
"RootChunk": { "$type": "entEntityTemplate", "components": [] },
|
|
202
|
+
"EmbeddedFiles": []
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
- op: insert-xl-entry
|
|
206
|
+
path: "sources/${input.modSlug}/body_patch_female.ent.json"
|
|
207
|
+
pointer: Data.RootChunk.components.-
|
|
208
|
+
value:
|
|
209
|
+
$type: entMeshComponent
|
|
210
|
+
name: { $type: CName, $storage: string, $value: "Body:${input.bodyType}" }
|
|
211
|
+
mesh:
|
|
212
|
+
DepotPath: { $type: ResourcePath, $storage: string, $value: "${input.femaleMeshPath}" }
|
|
213
|
+
Flags: Soft
|
|
214
|
+
# Design change (2026-09-11): the two patch .ent.json sources used to be
|
|
215
|
+
# written straight into the archive-staging tree, where the pack step
|
|
216
|
+
# would ship them as JSON (a scratch project needed a hand
|
|
217
|
+
# `exclude` for them) and nothing compiled them. They now live under
|
|
218
|
+
# sources/<modSlug>/ and two deserialize steps, placed ahead of the stage
|
|
219
|
+
# step, compile them to the mod\<modSlug>\body_patch_<gender>.ent depot
|
|
220
|
+
# paths the resource.patch entries name. The manifest is registered as a
|
|
221
|
+
# project source and an archive deploy target.
|
|
222
|
+
- op: patch-project
|
|
223
|
+
add:
|
|
224
|
+
outDir: "archive-staging"
|
|
225
|
+
sources:
|
|
226
|
+
- id: "xl-${input.modSlug}"
|
|
227
|
+
path: "${input.xlFile}"
|
|
228
|
+
kind: xl
|
|
229
|
+
steps:
|
|
230
|
+
- step: exec
|
|
231
|
+
id: "deserialize-${input.modSlug}-patch-male"
|
|
232
|
+
command: wolvenkit-cli
|
|
233
|
+
args: ["convert", "deserialize", "sources/${input.modSlug}/body_patch_male.ent.json", "-o", "${input.archiveStagingDir}/mod/${input.modSlug}"]
|
|
234
|
+
expectOutputs: ["${input.archiveStagingDir}/mod/${input.modSlug}/body_patch_male.ent"]
|
|
235
|
+
before: stage
|
|
236
|
+
- step: exec
|
|
237
|
+
id: "deserialize-${input.modSlug}-patch-female"
|
|
238
|
+
command: wolvenkit-cli
|
|
239
|
+
args: ["convert", "deserialize", "sources/${input.modSlug}/body_patch_female.ent.json", "-o", "${input.archiveStagingDir}/mod/${input.modSlug}"]
|
|
240
|
+
expectOutputs: ["${input.archiveStagingDir}/mod/${input.modSlug}/body_patch_female.ent"]
|
|
241
|
+
before: stage
|
|
242
|
+
deployTargets:
|
|
243
|
+
- rootId: archive
|
|
244
|
+
from: "${input.xlFile}"
|
|
245
|
+
locked: false
|
|
246
|
+
backup: true
|
|
247
|
+
templates: []
|
|
248
|
+
satisfies:
|
|
249
|
+
- cp2077.garments.body-tag-registration
|
|
250
|
+
- cp2077.garments.substitution-star-prefix
|
|
251
|
+
- cp2077.garments.placeholder-known
|
|
252
|
+
- cp2077.garments.substitution-combination-resolves
|
|
253
|
+
- cp2077.garments.gendered-appearance-suffix
|
|
254
|
+
- cp2077.garments.dynamicappearance-tag-present
|
|
255
|
+
- cp2077.garments.visual-tags-resolve
|
|
256
|
+
- cp2077.garments.root-entity-blank-appearance
|
|
257
|
+
- cp2077.garments.xl-entries-resolve
|
|
258
|
+
manual:
|
|
259
|
+
- title: The refit itself (Blender) and base_body regression
|
|
260
|
+
steps:
|
|
261
|
+
- "In Blender, refit the garment mesh onto the ${input.bodyType} body shape and export the mesh-entity chain: a blank-appearance root .ent (DynamicAppearance tag) plus a mesh entity .ent whose component depotPath substitutes {gender}/{body}, per the jacket pilot's own shape."
|
|
262
|
+
- "Stage the refitted meshes at the {gender}/{body} combinations the mesh entity's substituted path names, or cp2077.garments.substitution-combination-resolves will block on the real chain once it exists."
|
|
263
|
+
- "Confirm base_body (the unmodified vanilla mesh) still renders correctly for players who have not selected ${input.bodyType} — the acceptance criterion this pilot's own table calls out."
|
|
264
|
+
expected: "The garment renders correctly on both ${input.bodyType} and base_body, with the right mesh for each registered gender."
|
|
265
|
+
claim:
|
|
266
|
+
idSuffix: body-type-registered
|
|
267
|
+
claim: "${input.bodyType} is registered in player.bodyTypes with gendered patch .ents supplying its Body:${input.bodyType} component, and ${ids.recordName} exists with $base ${input.base}."
|
|
268
|
+
testRows:
|
|
269
|
+
- gate: R-1
|
|
270
|
+
title: "TweakXL record and body-type patch load without error"
|
|
271
|
+
expected: "TweakXL-<timestamp>.log and ArchiveXL's own log show no error for ${input.xlFile} or ${input.tweaksFile}."
|
|
272
|
+
manual: true
|
|
273
|
+
probeKinds: []
|
|
274
|
+
- gate: R-2
|
|
275
|
+
title: "Correct mesh for the registered body tag; base_body unaffected"
|
|
276
|
+
expected: "CET spawn-and-inspect confirms the right mesh for ${input.bodyType} and that base_body still renders the vanilla mesh."
|
|
277
|
+
manual: true
|
|
278
|
+
probeKinds: []
|
|
279
|
+
evidence: ["ModWright research"]
|