modwright 0.1.2 → 0.1.4
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/README.md +43 -4
- package/bridges/bg3-se/README.md +3 -2
- package/bridges/bg3-se/bridge.json +1 -1
- package/bridges/cp2077-cet/ModWrightBridge/probes.lua +228 -1
- package/bridges/cp2077-cet/README.md +6 -3
- package/bridges/cp2077-cet/bridge.json +2 -2
- package/dist/core/bridge/remove.js +48 -0
- package/dist/core/build/stage.js +3 -2
- package/dist/core/ini.js +26 -0
- package/dist/core/knowledge/facts.js +0 -12
- package/dist/core/logs/registry.js +19 -0
- package/dist/core/logs/scan.js +44 -5
- package/dist/core/logs/triage.js +79 -2
- package/dist/core/managers/mo2.js +121 -0
- package/dist/core/managers/vortex.js +52 -0
- package/dist/core/ownership/index.js +364 -0
- package/dist/core/project/index.js +1 -1
- package/dist/core/project/load.js +5 -0
- package/dist/core/testplan/registry.js +84 -2
- package/dist/core/writes/index.js +206 -0
- package/dist/index.js +0 -2
- package/dist/server.js +180 -15
- package/dist/surfaces/baldursgate3/surface.js +3 -0
- package/dist/surfaces/baldursgate3/validators/story.js +3 -3
- package/dist/surfaces/baldursgate3/writes.js +152 -0
- package/dist/surfaces/cyberpunk2077/index/parsers/tweakxl-yaml.js +2 -2
- package/dist/surfaces/cyberpunk2077/logs.js +82 -3
- package/dist/surfaces/cyberpunk2077/surface.js +11 -0
- package/dist/surfaces/cyberpunk2077/writes.js +67 -0
- package/dist/surfaces/skyrimse/loadorder.js +2 -26
- package/dist/surfaces/skyrimse/surface.js +1 -0
- package/dist/surfaces/stardewvalley/logs.js +41 -0
- package/dist/surfaces/stardewvalley/surface.js +2 -0
- package/dist/surfaces/stardewvalley/writes.js +136 -0
- package/knowledge/baldursgate3/dialogue.osiris-goals.yaml +29 -0
- package/knowledge/baldursgate3/osiris.tags.yaml +78 -0
- package/knowledge/cyberpunk2077/cet.natives.yaml +48 -0
- package/knowledge/cyberpunk2077/cet.rtti-binding.yaml +227 -0
- package/knowledge/cyberpunk2077/cet.sandbox.yaml +22 -0
- package/knowledge/cyberpunk2077/codeware.overview.yaml +63 -16
- package/knowledge/cyberpunk2077/codeware.systems.yaml +152 -33
- package/knowledge/cyberpunk2077/entities.queries.yaml +275 -0
- package/knowledge/cyberpunk2077/redhottools.hotreload.yaml +30 -4
- package/knowledge/cyberpunk2077/rtti.game-systems.yaml +224 -0
- package/package.json +1 -1
|
@@ -15,20 +15,42 @@ facts:
|
|
|
15
15
|
- redscript
|
|
16
16
|
- cet
|
|
17
17
|
- red4ext
|
|
18
|
-
detail:
|
|
19
|
-
|
|
18
|
+
detail: >-
|
|
19
|
+
Source corrected 2026-09-07: RED4ext is listed under Installation, not Compatibility, and the
|
|
20
|
+
previous claim's parenthetical "(per its own README, version 1.18.0 wiki)" conflated two
|
|
20
21
|
things. 1.18.0 is the version stamped on line 1 of the Codeware wiki's Home page, and is what
|
|
21
22
|
every API fact in this file was read against; it is not a floor. Framework versions stay in
|
|
22
|
-
the claim;
|
|
23
|
+
the claim; "Cyberpunk 2077 2.31" is the game version this Codeware release targets, not an
|
|
23
24
|
observation date, so there is no `verified_on`. This instantiates the general
|
|
24
|
-
cp2077.packaging.version-matrix-breakage.
|
|
25
|
+
cp2077.packaging.version-matrix-breakage.
|
|
26
|
+
|
|
27
|
+
Checked against commit 3a43182 (2026-08-28): README.md's Compatibility and Installation
|
|
28
|
+
sections are byte-for-byte unchanged (game 2.31, redscript 0.5.31+, CET 1.37.0+, RED4ext
|
|
29
|
+
1.29.0+) — neither confirmed nor contradicted by executable code, since these are floors on
|
|
30
|
+
other projects' version numbers, not something Codeware's own build asserts. xmake.lua's
|
|
31
|
+
`set_version("1.20.4", ...)` is a fourth, unrelated axis: Codeware's own release version, now
|
|
32
|
+
ahead of the "1.18.0" still stamped on the wiki's Home page at this same commit — the wiki
|
|
33
|
+
page has not been bumped to match the 1.20.4 project version.
|
|
25
34
|
- id: cp2077.codeware.systems.service-persists-between-sessions
|
|
26
35
|
claim: '"Services are singletons that created on scripts initialization and, unlike scriptable
|
|
27
36
|
systems, live between game sessions. To create your own service, you have to define a class
|
|
28
37
|
derived from `ScriptableService`." The instance is reached with
|
|
29
38
|
`GameInstance.GetScriptableServiceContainer().GetService(n"MyService") as MyService`.'
|
|
30
|
-
status:
|
|
31
|
-
source: cp2077-codeware wiki Home, section "Lifecycle > Scriptable services"
|
|
39
|
+
status: inferred
|
|
40
|
+
source: "cp2077-codeware wiki Home, section \"Lifecycle > Scriptable services\"; confirmed against
|
|
41
|
+
commit 3a43182 in scripts/Scripting/ScriptableService.reds (`public abstract native class
|
|
42
|
+
ScriptableService` with commented-out `OnLoad`/`OnReload`/ `OnInitialize`/`OnUninitialize`
|
|
43
|
+
callback signatures) and scripts/Scripting/ScriptableServiceContainer.reds (`public abstract
|
|
44
|
+
native class ScriptableServiceContainer extends IGameSystem { public native func
|
|
45
|
+
GetService(name: CName) -> ref<ScriptableService> }`, reached via `@addMethod(GameInstance)
|
|
46
|
+
public static native func GetScriptableServiceContainer()`). The cross-session persistence is
|
|
47
|
+
implemented in src/App/Scripting/ScriptableServiceContainer.cpp: `OnInitializeScripts`
|
|
48
|
+
instantiates every non-abstract `ScriptableService` subclass and calls `OnLoad` (or `OnReload`
|
|
49
|
+
if `m_scriptsLoaded` is already true, distinguishing the two lifecycle events exactly as the
|
|
50
|
+
wiki describes); `LoadState`/`SaveState` (de)serialize `m_services` to a `.dat` file under
|
|
51
|
+
Codeware's own persistent-data directory (`s_stateDir`, separate from any save file) via
|
|
52
|
+
`Red::ObjectSerializer`, with `SaveState` called from `OnInitializeGameInstance`,
|
|
53
|
+
`OnBeforeWorldDetach` and `OnBeforeGameSave`."
|
|
32
54
|
tags:
|
|
33
55
|
- codeware
|
|
34
56
|
- scriptableservice
|
|
@@ -42,8 +64,16 @@ facts:
|
|
|
42
64
|
claim: '"If you declare `MyService` in a module, you must include the full path of the module to get
|
|
43
65
|
the service" — a service declared in `module MyModule.Services` is fetched as
|
|
44
66
|
`GetService(n"MyModule.Services.MyService")`.'
|
|
45
|
-
status:
|
|
46
|
-
source: cp2077-codeware wiki Home, section "Lifecycle > Scriptable services"
|
|
67
|
+
status: inferred
|
|
68
|
+
source: "cp2077-codeware wiki Home, section \"Lifecycle > Scriptable services\"; confirmed against
|
|
69
|
+
commit 3a43182: `GetService` in src/App/Scripting/ScriptableServiceContainer.cpp looks the
|
|
70
|
+
service up by exact `Red::CName` key
|
|
71
|
+
(`m_services.find(aType)`/`m_services.emplace(serviceType->name, ...)`), where
|
|
72
|
+
`serviceType->name` is the RTTI class's full name as registered by the redscript compiler —
|
|
73
|
+
module-qualified for a class declared inside a `module` block. The same full-path pattern is
|
|
74
|
+
used elsewhere in Codeware's own scripts, e.g. scripts/Localization/LocalizationSystem.reds's
|
|
75
|
+
`GameInstance.GetScriptableSystemsContainer(game).Get(n\"Codeware.Localization.LocalizationSy\
|
|
76
|
+
stem\")`."
|
|
47
77
|
tags:
|
|
48
78
|
- codeware
|
|
49
79
|
- scriptableservice
|
|
@@ -56,7 +86,15 @@ facts:
|
|
|
56
86
|
systems, service state storage is not tied to save files." "Persistence is available for all
|
|
57
87
|
types except `String`, `ResRef`, `Variant`."'
|
|
58
88
|
status: community
|
|
59
|
-
source: cp2077-codeware wiki Home, section "Lifecycle > Scriptable services"
|
|
89
|
+
source: "cp2077-codeware wiki Home, section \"Lifecycle > Scriptable services\". Checked against
|
|
90
|
+
commit 3a43182: found the `persistent` field qualifier handled by the generic
|
|
91
|
+
`RTTI_PERSISTENT`/`RTTI_PERSISTENT_FQN` macros in the vendored
|
|
92
|
+
lib/Red/TypeInfo/Macros/Definition.hpp, which Codeware uses on its own internal state
|
|
93
|
+
(`RTTI_DEFINE_CLASS(App::ScriptableServiceContainerState, { RTTI_PERSISTENT(services); })` in
|
|
94
|
+
src/App/Scripting/ScriptableServiceContainer.hpp) — but no C++ in src/App enumerates or
|
|
95
|
+
enforces a `String`/`ResRef`/`Variant` exclusion list for user-declared `persistent` fields on
|
|
96
|
+
mod services. That exclusion looks like native engine/redscript-compiler behavior outside
|
|
97
|
+
Codeware's own source, so this claim is neither confirmed nor contradicted here."
|
|
60
98
|
tags:
|
|
61
99
|
- codeware
|
|
62
100
|
- persistent
|
|
@@ -70,7 +108,12 @@ facts:
|
|
|
70
108
|
are reset to defaults on each game launch. It's safe to change persistent data structure at
|
|
71
109
|
any time.\""
|
|
72
110
|
status: community
|
|
73
|
-
source: cp2077-codeware wiki Home, section "Lifecycle > Scriptable services"
|
|
111
|
+
source: 'cp2077-codeware wiki Home, section "Lifecycle > Scriptable services". Checked against
|
|
112
|
+
commit 3a43182: this describes how the native object serializer restores only
|
|
113
|
+
`persistent`-flagged fields (see cp2077.codeware.systems.persistent-field-type-exclusions for
|
|
114
|
+
what was found on that mechanism); no Codeware C++ specifically implements the "unmarked
|
|
115
|
+
fields reset to defaults" behavior for user service objects beyond relying on that native
|
|
116
|
+
(de)serialization, so it is left unconfirmed rather than promoted.'
|
|
74
117
|
tags:
|
|
75
118
|
- codeware
|
|
76
119
|
- persistent
|
|
@@ -83,8 +126,9 @@ facts:
|
|
|
83
126
|
disposed when game session ends. An unreleased reference can interfere with normal object
|
|
84
127
|
disposal and lead to bugs such as disappearing sounds or crashes."'
|
|
85
128
|
status: community
|
|
86
|
-
source: cp2077-codeware wiki Home, section "Lifecycle > Scriptable services" (the "Referencing game
|
|
87
|
-
objects" blockquote)
|
|
129
|
+
source: 'cp2077-codeware wiki Home, section "Lifecycle > Scriptable services" (the "Referencing game
|
|
130
|
+
objects" blockquote). Checked against commit 3a43182: this is a caution in prose with no
|
|
131
|
+
single API to test it against — left community.'
|
|
88
132
|
tags:
|
|
89
133
|
- codeware
|
|
90
134
|
- scriptableservice
|
|
@@ -102,8 +146,26 @@ facts:
|
|
|
102
146
|
`EntityTarget.ID`/`.Type`/`.RecordID(TweakDBID)`/`.Template`/`.Appearance`/`.Definition`,
|
|
103
147
|
`ComponentTarget.ID`/`.Name`, `InputTarget.Key`/`.Axis`,
|
|
104
148
|
`inkWidgetTarget.Library`/`.Controller`.
|
|
105
|
-
status:
|
|
106
|
-
source: cp2077-codeware wiki Home, section "Lifecycle > Game events"
|
|
149
|
+
status: inferred
|
|
150
|
+
source: "cp2077-codeware wiki Home, section \"Lifecycle > Game events\"; confirmed against commit
|
|
151
|
+
3a43182 in scripts/Callback/CallbackSystem.reds (`public native class CallbackSystem extends
|
|
152
|
+
IGameSystem` with `RegisterCallback (eventName: CName, target: ref<IScriptable>, function:
|
|
153
|
+
CName, opt sticky: Bool) -> ref<CallbackSystemHandler>`, reached via
|
|
154
|
+
`GameInstance.GetCallbackSystem()`) and scripts/Callback/CallbackSystemHandler.reds
|
|
155
|
+
(`AddTarget(target: ref<CallbackSystemTarget>) -> ref<CallbackSystemHandler>`, `SetRunMode`,
|
|
156
|
+
`SetLifetime`). All 15 event names are exact `Red::CName` constants in
|
|
157
|
+
src/App/Callback/Controllers/*Hook.hpp and src/App/Callback/CallbackSystem.hpp
|
|
158
|
+
(`Resource/Load`, `Resource/PostLoad`, `Session/BeforeStart`, `Session/Start`,
|
|
159
|
+
`Session/Ready`, `Session/BeforeSave`, `Entity/Extract`, `Entity/Assemble`,
|
|
160
|
+
`Entity/Initialize`, `Entity/Reassemble`, `Entity/Attach`, `Entity/Detach`,
|
|
161
|
+
`Component/Toggle`, `Input/Key`, `Input/Axis`, `InkWidget/Spawn` — note CallbackSystem.hpp
|
|
162
|
+
also defines further Session events, `Session/BeforeEnd`/`Session/End`/
|
|
163
|
+
`Session/AfterSave`/`Session/Pause`/`Session/Resume`, not in the wiki's table, consistent with
|
|
164
|
+
the claim's \"include\" wording rather than an exhaustive list). All selectors confirmed in
|
|
165
|
+
scripts/Callback/Targets/*.reds: `ResourceTarget.Path`/`.Type`,
|
|
166
|
+
`EntityTarget.ID`/`.Type`/`.RecordID`/`.Template`/`.Appearance`/ `.Definition`,
|
|
167
|
+
`ComponentTarget.ID`/`.Name`, `InputTarget.Key`/`.Axis`,
|
|
168
|
+
`inkWidgetTarget.Library`/`.Controller`."
|
|
107
169
|
tags:
|
|
108
170
|
- codeware
|
|
109
171
|
- callbacksystem
|
|
@@ -112,16 +174,32 @@ facts:
|
|
|
112
174
|
- syntax
|
|
113
175
|
detail: "Caution for a validator: the event table names `Entity/Attach`, but the wiki's own
|
|
114
176
|
`SetRunMode` example registers `n\"Entity/Attached\"` — the two spellings disagree on the same
|
|
115
|
-
page.
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
177
|
+
page. Still true at commit 3a43182: wiki/Home.md lines ~152 and ~294 still write
|
|
178
|
+
`n\"Entity/Attached\"` in worked examples, while `Entity/Attach` is the only name any hook
|
|
179
|
+
registers (src/App/Callback/Controllers/EntityAttachHook.hpp) — the wiki's own examples appear
|
|
180
|
+
to reference an event that does not exist; `Entity/Attach` (the table entry) is the one
|
|
181
|
+
confirmed by source. Callback lifetime: \"When defined inside scriptable service, callback
|
|
182
|
+
stays registered until you manually unregister it. When defined in other contexts, callback is
|
|
183
|
+
auto removed at the end of the session\", overridable with
|
|
184
|
+
`.SetLifetime(CallbackLifetime.Forever)` or `...Session)`. Confirmed in
|
|
185
|
+
src/App/Callback/CallbackSystem.cpp's `RegisterCallback`/ `RegisterStaticCallback`: `if
|
|
186
|
+
(aSticky || (aFrame && aFrame->context &&
|
|
187
|
+
Red::IsInstanceOf<ScriptableService>(aFrame->context)))
|
|
188
|
+
handler->SetLifetime(CallbackLifetime::Forever);` — a callback registered from inside a
|
|
189
|
+
`ScriptableService` gets `Forever` by default; otherwise it defaults to
|
|
190
|
+
`CallbackLifetime.Session` (value `0` in scripts/Callback/CallbackLifetime.reds) and is torn
|
|
191
|
+
down with the session. The callback system can be accessed before the game instance is
|
|
192
|
+
initialized."
|
|
119
193
|
- id: cp2077.codeware.systems.callback-once-run-mode
|
|
120
194
|
claim: '"You can make callback to auto unregister after being fired by calling
|
|
121
195
|
`.SetRunMode(CallbackRunMode.Once)`." `CallbackRunMode.OncePerTarget` instead auto-unregisters
|
|
122
196
|
"after being fired for each listed target".'
|
|
123
|
-
status:
|
|
124
|
-
source: cp2077-codeware wiki Home, section "Lifecycle > Game events"
|
|
197
|
+
status: inferred
|
|
198
|
+
source: 'cp2077-codeware wiki Home, section "Lifecycle > Game events"; confirmed against commit
|
|
199
|
+
3a43182 in scripts/Callback/CallbackRunMode.reds: `public enum CallbackRunMode { Default = 0,
|
|
200
|
+
Once = 1, OncePerTarget = 2 }`, set via `CallbackSystemHandler.SetRunMode(runMode:
|
|
201
|
+
CallbackRunMode) -> ref<CallbackSystemHandler>` in
|
|
202
|
+
scripts/Callback/CallbackSystemHandler.reds.'
|
|
125
203
|
tags:
|
|
126
204
|
- codeware
|
|
127
205
|
- callbacksystem
|
|
@@ -133,21 +211,42 @@ facts:
|
|
|
133
211
|
require loading resources you can refresh appearance\" with `comp.RefreshAppearance()`.
|
|
134
212
|
Supported components are `entMeshComponent`, `entSkinnedMeshComponent`,
|
|
135
213
|
`entGarmentSkinnedMeshComponent` and `entMorphTargetSkinnedMeshComponent`."
|
|
136
|
-
status:
|
|
137
|
-
source: cp2077-codeware wiki Home, section "Entities > Mesh appearances"
|
|
214
|
+
status: inferred
|
|
215
|
+
source: "cp2077-codeware wiki Home, section \"Entities > Mesh appearances\"; confirmed against
|
|
216
|
+
commit 3a43182 in scripts/Entity/IComponent.reds: `@addMethod(IComponent) public native func
|
|
217
|
+
LoadAppearance(opt wait: Bool) -> Bool` and `public native func RefreshAppearance() -> Bool`.
|
|
218
|
+
The exact four supported component types are confirmed in
|
|
219
|
+
src/App/Entity/ComponentWrapper.cpp's constructor, which classifies a component into
|
|
220
|
+
`ComponentType::MeshComponent`, `::SkinnedMeshComponent`, `::GarmentSkinnedMeshComponent` or
|
|
221
|
+
`::MorphTargetSkinnedMeshComponent` (else `::Unsupported`) by RTTI `IsA` checks against
|
|
222
|
+
`Red::ent::MeshComponent`, `Red::ent::SkinnedMeshComponent`,
|
|
223
|
+
`Red::ent::GarmentSkinnedMeshComponent` and `Red::ent::MorphTargetSkinnedMeshComponent` —
|
|
224
|
+
matching `entMeshComponent`/`entSkinnedMeshComponent`/
|
|
225
|
+
`entGarmentSkinnedMeshComponent`/`entMorphTargetSkinnedMeshComponent` exactly."
|
|
138
226
|
tags:
|
|
139
227
|
- codeware
|
|
140
228
|
- loadappearance
|
|
141
229
|
- refreshappearance
|
|
142
230
|
- entity-component
|
|
143
|
-
detail: The worked example is `comp.mesh *= r"mod
|
|
144
|
-
n"neon_red"; comp.LoadAppearance();`. Softened on 2026-09-07 from "must be called ... (it
|
|
145
|
-
re-resolves resources)" to the wiki's own "you can request it to load".
|
|
231
|
+
detail: "The worked example is `comp.mesh *= r\"mod\\player\\dynamic.mesh\"; comp.meshAppearance =
|
|
232
|
+
n\"neon_red\"; comp.LoadAppearance();`. Softened on 2026-09-07 from \"must be called ... (it
|
|
233
|
+
re-resolves resources)\" to the wiki's own \"you can request it to load\". Confirmed the
|
|
234
|
+
resource re-resolution distinction in src/App/Entity/ComponentEx.cpp: `LoadAppearance` calls
|
|
235
|
+
`ComponentWrapper::LoadResource(/*refresh=*/true, aWait)`, which re-resolves the mesh/morph
|
|
236
|
+
resource path and then refreshes the appearance; `RefreshAppearance` calls
|
|
237
|
+
`ComponentWrapper::RefreshAppearance()` directly without touching the resource path — matching
|
|
238
|
+
the wiki's \"changed mesh/appearance\" vs. \"changed other properties\" split."
|
|
146
239
|
- id: cp2077.codeware.systems.static-entity-reposition-without-respawn
|
|
147
240
|
claim: '"Static entities can be moved now without respawning them at new position" via
|
|
148
241
|
`entity.SetWorldTransform(transform)`.'
|
|
149
|
-
status:
|
|
150
|
-
source: cp2077-codeware wiki Home, section "Entities > World transform"
|
|
242
|
+
status: inferred
|
|
243
|
+
source: 'cp2077-codeware wiki Home, section "Entities > World transform"; confirmed against commit
|
|
244
|
+
3a43182 in scripts/Entity/Entity.reds: `@addMethod(Entity) public native func
|
|
245
|
+
SetWorldTransform(transform: WorldTransform)`. The method is added to the base `Entity` class
|
|
246
|
+
(usable on any entity, not only ones spawned via StaticEntitySystem), implemented in
|
|
247
|
+
src/App/Entity/EntityEx.hpp as `Raw::IPlacedComponent::SetTransform(transformComponent,
|
|
248
|
+
aTransform)` — a direct transform-component update, confirming the "without respawning" claim
|
|
249
|
+
(no despawn/respawn round-trip).'
|
|
151
250
|
tags:
|
|
152
251
|
- codeware
|
|
153
252
|
- setworldtransform
|
|
@@ -157,8 +256,17 @@ facts:
|
|
|
157
256
|
`playerSystem.GetCustomizationPuppet()`, `GetInventoryPuppet()` and `GetPhotoPuppet()`, from
|
|
158
257
|
`GameInstance.GetPlayerSystem(GetGameInstance())`, for the customization screen, inventory
|
|
159
258
|
screen and photo mode respectively.
|
|
160
|
-
status:
|
|
161
|
-
source: cp2077-codeware wiki Home, section "Player > Accessing player objects"
|
|
259
|
+
status: inferred
|
|
260
|
+
source: "cp2077-codeware wiki Home, section \"Player > Accessing player objects\"; confirmed against
|
|
261
|
+
commit 3a43182 in scripts/Player/PlayerSystem.reds: `@addMethod(PlayerSystem) public func
|
|
262
|
+
GetCustomizationPuppet() -> wref<gamePuppet>`, `GetInventoryPuppet() -> wref<gamePuppet>` and
|
|
263
|
+
`GetPhotoPuppet() -> wref<gamePuppet>`, each backed by an `@addField`-ed `wref<gamePuppet>`
|
|
264
|
+
set via `@wrapMethod(inkPuppetPreviewGameController) OnPreviewInitialized`
|
|
265
|
+
(customization/inventory, keyed on the controller's class name
|
|
266
|
+
`gameuiCharacterCreationPuppetPreviewGameController`/
|
|
267
|
+
`gameuiInventoryPuppetPreviewGameController`) and `@wrapMethod(PhotoModePlayerEntityComponent)
|
|
268
|
+
SetupInventory` (photo mode) — matching the claimed customization/inventory/photo-mode mapping
|
|
269
|
+
exactly."
|
|
162
270
|
tags:
|
|
163
271
|
- codeware
|
|
164
272
|
- playersystem
|
|
@@ -168,8 +276,12 @@ facts:
|
|
|
168
276
|
- id: cp2077.codeware.systems.wardrobe-forget-item
|
|
169
277
|
claim: '"Items can be permanently removed from wardrobe" with
|
|
170
278
|
`GameInstance.GetWardrobeSystem(GetGameInstance()).ForgetItemID(ItemID.FromTDBID("Items.Glasses_03_basic_09"))`.'
|
|
171
|
-
status:
|
|
172
|
-
source: cp2077-codeware wiki Home, section "Player > Managing wardrobe"
|
|
279
|
+
status: inferred
|
|
280
|
+
source: 'cp2077-codeware wiki Home, section "Player > Managing wardrobe"; confirmed against commit
|
|
281
|
+
3a43182 in scripts/Player/WardrobeSystem.reds: `@addMethod(WardrobeSystem) public native func
|
|
282
|
+
ForgetItemID(itemID: ItemID) -> Bool` (the only member Codeware adds to `WardrobeSystem`).
|
|
283
|
+
`ItemID.FromTDBID` itself is a base-game function (`gameItemID.FromTDBID`, called via
|
|
284
|
+
`Red::CallStatic` in src/App/World/OpenWorldSystem.cpp), not something Codeware defines.'
|
|
173
285
|
tags:
|
|
174
286
|
- codeware
|
|
175
287
|
- wardrobesystem
|
|
@@ -181,8 +293,15 @@ facts:
|
|
|
181
293
|
retrieved at runtime\" —
|
|
182
294
|
`GameInstance.GetVehicleSystem(GetGameInstance()).EnablePlayerVehicleID(t\"Vehicle.v_sport2_q\
|
|
183
295
|
uadra_type66_avenger_player\", true)`."
|
|
184
|
-
status:
|
|
185
|
-
source: cp2077-codeware wiki Home, section "Player > Unlocking vehicles"
|
|
296
|
+
status: inferred
|
|
297
|
+
source: 'cp2077-codeware wiki Home, section "Player > Unlocking vehicles"; confirmed against commit
|
|
298
|
+
3a43182 in scripts/Vehicle/VehicleSystem.reds: `@addMethod(VehicleSystem) public func
|
|
299
|
+
EnablePlayerVehicleID(vehicleID: TweakDBID, enable: Bool, opt despawnIfDisabling: Bool) ->
|
|
300
|
+
Bool`, which checks `vehicleID` against
|
|
301
|
+
`TweakDBInterface.GetForeignKeyArray(t"Vehicle.vehicle_list.list")` before calling the native
|
|
302
|
+
`ToggleGarageVehicle(garageID: GarageVehicleID, enable: Bool) -> Bool`. Note the actual
|
|
303
|
+
signature has a third, optional `despawnIfDisabling: Bool` parameter not mentioned in the
|
|
304
|
+
claim (despawns the vehicle if disabling succeeds).'
|
|
186
305
|
tags:
|
|
187
306
|
- codeware
|
|
188
307
|
- vehiclesystem
|
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
game: cyberpunk2077
|
|
2
|
+
topic: entities.queries
|
|
3
|
+
title: "Finding entities at runtime: what the dynamic-entity tag registry does and does not see, and
|
|
4
|
+
the RTTI-confirmed spatial query methods"
|
|
5
|
+
facts:
|
|
6
|
+
- id: cp2077.entities.gettaggedids-is-a-dynamic-entity-registry-not-a-node-lookup
|
|
7
|
+
claim: "Game.GetDynamicEntitySystem():GetTaggedIDs(tag) is Codeware's DynamicEntitySystem, and it
|
|
8
|
+
returns only entities that system itself created (DynamicEntitySpec.tags) or was told about
|
|
9
|
+
with AssignTag. A sector-placed static prop (a worldEntityNode in a .streamingsector) was not
|
|
10
|
+
found by it in two in-game checks (2026-08 and 2026-09-09), and the source shows why: nothing
|
|
11
|
+
a streaming sector spawns is ever entered into that registry."
|
|
12
|
+
status: verified
|
|
13
|
+
verified_on: "2.31"
|
|
14
|
+
source: ModWright field verification
|
|
15
|
+
tags:
|
|
16
|
+
- entity
|
|
17
|
+
- tag
|
|
18
|
+
- gettaggedids
|
|
19
|
+
- dynamic-entity
|
|
20
|
+
- codeware
|
|
21
|
+
- world-placement
|
|
22
|
+
- gotcha
|
|
23
|
+
related:
|
|
24
|
+
- cp2077.entities.native-gametagsystem-finds-entities-by-tag
|
|
25
|
+
- cp2077.entities.codeware-staticentitysystem-spawns-tagged-static-entities
|
|
26
|
+
detail: "What is verified in-engine is the negative: an untagged sector node is invisible to
|
|
27
|
+
GetTaggedIDs, and the tags the test mod used only ever marked entities its earlier experiments
|
|
28
|
+
spawned dynamically (which is why its cleanup script deletes them by tag). A claim briefly
|
|
29
|
+
recorded as verified on 2026-09-10 and corrected the same day — that setting the sector node's
|
|
30
|
+
`tag` CName would make GetTaggedIDs find it — is ruled out by the source: the registry is
|
|
31
|
+
populated from DynamicEntitySpec.tags and AssignTag calls only, never from streaming-sector
|
|
32
|
+
node data or from the native per-object tag list. Codeware does mirror its tags into the
|
|
33
|
+
native side on spawn (DynamicEntitySystem.cpp: gameObject->tags.Add on spawn; AssignTag also
|
|
34
|
+
calls Raw::TagSystem::AssignTag), but the direction is Codeware -> engine, not engine ->
|
|
35
|
+
Codeware. So \"tag the node, then GetTaggedIDs\" is dead; the live question is whether a node
|
|
36
|
+
tag reaches the *native* tag system, which is the next fact. The scaffold
|
|
37
|
+
cyberpunk2077.new-sector-node therefore ships `tag: None` (the vanilla entSpawner export
|
|
38
|
+
shape) and keeps its N-1 row manual."
|
|
39
|
+
- id: cp2077.entities.native-gametagsystem-finds-entities-by-tag
|
|
40
|
+
claim: "The shipped game has its own tag lookup, separate from Codeware's: gameGameTagSystem
|
|
41
|
+
(obtained via ScriptGameInstance::GetGameTagSystem, so from CET presumably
|
|
42
|
+
Game.GetGameTagSystem()) exposes GetAnyMatchingEntity(tag: CName) -> ref<entEntity> and
|
|
43
|
+
GetAllMatchingEntities(tag: CName, out entities: array<ref<entEntity>>) -> Bool; gameObject
|
|
44
|
+
carries a native `tags: redTagList` field and a native HasTag(tag: CName) -> Bool method.
|
|
45
|
+
Whether a worldEntityNode's `tag` field lands in that list or that system is untested."
|
|
46
|
+
status: unverified
|
|
47
|
+
source: "rayshader/cp2077-nativedb@b5d29af classes.json: class gameGameTagSystem (parent
|
|
48
|
+
gameIGameSystem) with exactly those two functions; ScriptGameInstance function
|
|
49
|
+
GetGameTagSystem returning ref<gameGameTagSystem>; class gameObject field tags of type
|
|
50
|
+
redTagList and function HasTag(tag: CName) -> Bool; class redTagSystem (no scripted
|
|
51
|
+
functions). psiberx/cp2077-codeware@3a43182 src/Red/TagSystem.hpp wraps the engine's
|
|
52
|
+
TagSystem_AssignTag/UnassignTag by address and scripts/Entity/GameObject.reds adds
|
|
53
|
+
`AddTag(tag: CName)` to GameObject — so the native list is real and writable. Read 2026-09-10;
|
|
54
|
+
nothing on disk calls GetGameTagSystem from Lua or redscript. Negative searches (2026-09-11):
|
|
55
|
+
CDPR-Modding-Documentation/Cyberpunk-Modding-Docs at 4e798d6 (591 pages) and NativeDB-wiki at
|
|
56
|
+
ed4e34d document neither this system nor a world node's tag/tagExt fields."
|
|
57
|
+
tags:
|
|
58
|
+
- entity
|
|
59
|
+
- tag
|
|
60
|
+
- gametagsystem
|
|
61
|
+
- hastag
|
|
62
|
+
- rtti
|
|
63
|
+
- world-placement
|
|
64
|
+
- live-check-next
|
|
65
|
+
related:
|
|
66
|
+
- cp2077.entities.gettaggedids-is-a-dynamic-entity-registry-not-a-node-lookup
|
|
67
|
+
detail: >-
|
|
68
|
+
This is the mechanism an auto-tag idea would actually need, and it is a hypothesis with two
|
|
69
|
+
halves to test: (1) does the CET global Game.GetGameTagSystem() resolve, and does
|
|
70
|
+
GetAnyMatchingEntity find an entity Codeware tagged (a known-positive control: spawn or
|
|
71
|
+
AssignTag something with Codeware, then look it up natively — Codeware mirrors its tags into
|
|
72
|
+
the native system, per the previous fact); (2) does a sector node authored with a non-None
|
|
73
|
+
`tag` come back from the same call, or at least answer obj:HasTag(tag) once the object is in
|
|
74
|
+
hand. Console lines (save loaded, standing near a placed prop whose node has a tag, and near
|
|
75
|
+
any Codeware-tagged dynamic entity):
|
|
76
|
+
local ts = Game.GetGameTagSystem(); print(type(ts))
|
|
77
|
+
local e = ts:GetAnyMatchingEntity("<codeware tag>"); print(e, e and e:GetClassName())
|
|
78
|
+
local ok, all = ts:GetAllMatchingEntities("<node tag>"); print(ok, type(all), all and all[1] and all[1]:GetClassName())
|
|
79
|
+
local o = Game.GetTargetingSystem():GetLookAtObject(Game.GetPlayer(), true, false); print(o and o:GetClassName(), o and o:HasTag("<node tag>"), o and o:GetCurrentAppearanceName())
|
|
80
|
+
GetAllMatchingEntities has an out-parameter, which CET returns as a second value after the
|
|
81
|
+
Bool (cp2077.cet.member-calls-via-colon-and-out-params-as-extra-returns), hence `ok, all`. The
|
|
82
|
+
last line is also the cheapest way yet found to get a handle on a placed prop with no position
|
|
83
|
+
probe at all: look at it. GetLookAtObject(instigator: wref<gameObject>, withLOS: Bool,
|
|
84
|
+
ignoreTranparent: Bool) -> ref<gameObject> is RTTI-listed on gametargetingTargetingSystem
|
|
85
|
+
(cp2077.rtti.targetingsystem-crosshair-and-distance-queries; an earlier draft of this line
|
|
86
|
+
named GetObjectClosestToCrosshair, which actually takes an instigator, an EulerAngles and a
|
|
87
|
+
gameTargetSearchQuery) and is unattested from Lua. If half (2) passes, the scaffold can tag
|
|
88
|
+
its nodes again and N-1 becomes an automated row against a *new* probe kind over
|
|
89
|
+
GetGameTagSystem, not over cp2077.entity.tagged; if it fails, node tags are a dead end and
|
|
90
|
+
only the position-based calls remain.
|
|
91
|
+
- id: cp2077.entities.codeware-staticentitysystem-spawns-tagged-static-entities
|
|
92
|
+
claim: 'Codeware also ships a StaticEntitySystem (Game.GetStaticEntitySystem() by the same
|
|
93
|
+
@addMethod pattern): SpawnEntity(StaticEntitySpec{templatePath, appearanceName, position,
|
|
94
|
+
orientation, attached, tags}) spawns an entity "the way world nodes usually do", with its own
|
|
95
|
+
tag registry (IsPopulated/GetTagged/GetTaggedIDs/DespawnTagged/AttachTagged/DetachTagged), no
|
|
96
|
+
persistent state, and no distance-based visibility. Its tag registry is as private as the
|
|
97
|
+
dynamic one: it does not see sector-placed nodes either.'
|
|
98
|
+
status: inferred
|
|
99
|
+
source: psiberx/cp2077-codeware@3a43182 wiki/Home.md "Spawning static entities" (option table and
|
|
100
|
+
ladder example); scripts/World/StaticEntitySystem.reds and StaticEntitySpec.reds;
|
|
101
|
+
src/App/World/StaticEntitySystem.cpp GetTaggedIDs() reads m_entityIDsByTag only; the
|
|
102
|
+
callback-target table lists StaticEntityTarget.Tag(CName) alongside
|
|
103
|
+
DynamicEntityTarget.Tag(CName).
|
|
104
|
+
tags:
|
|
105
|
+
- entity
|
|
106
|
+
- codeware
|
|
107
|
+
- static-entity
|
|
108
|
+
- spawn
|
|
109
|
+
- tag
|
|
110
|
+
- world-placement
|
|
111
|
+
related:
|
|
112
|
+
- cp2077.entities.gettaggedids-is-a-dynamic-entity-registry-not-a-node-lookup
|
|
113
|
+
- cp2077.loot.streaming-sector-required-for-loot
|
|
114
|
+
detail: Recorded because it is the third tagged spawn path and easy to confuse with the other two
|
|
115
|
+
when a probe says "tagged". It is not a replacement for sector placement — the
|
|
116
|
+
streaming-sector rule (cp2077.loot.streaming-sector-required-for-loot) is about loot
|
|
117
|
+
interactions on containers, which no script-side spawn path has been shown to provide — but
|
|
118
|
+
for a placement a mod is willing to make at runtime it would come with verification built in
|
|
119
|
+
(its own GetTaggedIDs). ModWright's CET bridge does not call it.
|
|
120
|
+
- id: cp2077.entities.gameobject-getnpcsaroundobject-exists-in-rtti
|
|
121
|
+
claim: "gameObject (parent entGameEntity; every puppet and most world objects descend from it)
|
|
122
|
+
carries the RTTI-registered method GetNPCsAroundObject(range: Float) returning
|
|
123
|
+
array<ref<NPCPuppet>> — NPCs within that range of the object it is called on."
|
|
124
|
+
status: inferred
|
|
125
|
+
source: 'rayshader/cp2077-nativedb@b5d29af classes.json, class entry {"a": "entGameEntity", "b":
|
|
126
|
+
"gameObject"} ("a" is the parent, "b" the class name in this dump), function entry {"a":
|
|
127
|
+
"GetNPCsAroundObject;Float", "e": [{"b": "range"}], "c": array<ref<NPCPuppet>>}. Read from the
|
|
128
|
+
committed dump on 2026-09-10 and re-checked 2026-10-04; the dumper was not run.'
|
|
129
|
+
tags:
|
|
130
|
+
- entity
|
|
131
|
+
- spatial-query
|
|
132
|
+
- rtti
|
|
133
|
+
- npc
|
|
134
|
+
- unverified-call
|
|
135
|
+
detail: "The dump is real reflection data from the shipped build, so the method's existence and
|
|
136
|
+
signature are solid. An earlier version of this fact placed the method on entGameEntity; that
|
|
137
|
+
came from reading the dump's \"a\"/\"b\" keys backwards. Not confirmed: that CET exposes it as
|
|
138
|
+
a Lua member call (`obj:GetNPCsAroundObject(r)` is assumed, matching every other RTTI method
|
|
139
|
+
the bridge calls that way) and what the returned array looks like from Lua. No CET mod or wiki
|
|
140
|
+
page calls it. ModWright's cp2077.entity.nearby probe kind attempts this call live,
|
|
141
|
+
pcall-wrapped, and stays unverified until a live run exercises it."
|
|
142
|
+
- id: cp2077.entities.gameobject-getentitiesaroundobject-filter-constructors-exist
|
|
143
|
+
claim: "gameObject also carries GetEntitiesAroundObject(range: Float, searchFilter:
|
|
144
|
+
gameTargetSearchFilter) returning array<ref<entEntity>> — any entity type, filtered.
|
|
145
|
+
gameTargetSearchFilter is an opaque native struct (a class entry with no listed fields), but
|
|
146
|
+
the same dump's globals.json lists constructor functions that return one: TSF_All(mask),
|
|
147
|
+
TSF_Any(mask), TSF_Not(mask), TSF_And(tsf1..tsf4), TSF_Or(tsf1..tsf4), TSF_NPC(),
|
|
148
|
+
TSF_EnemyNPC(), TSF_Quickhackable(); the mask type is
|
|
149
|
+
gametargetingSystemSearchFilterMaskValue."
|
|
150
|
+
status: unverified
|
|
151
|
+
source: 'rayshader/cp2077-nativedb@b5d29af classes.json: gameObject function entry {"a":
|
|
152
|
+
"GetEntitiesAroundObject;FloatTargetSearchFilter", "e": [{"b": "range"}, {"b": "searchFilter",
|
|
153
|
+
"a": {"b": "gameTargetSearchFilter"}}]}; class entry {"b": "gameTargetSearchFilter"} with zero
|
|
154
|
+
fields and zero functions; globals.json entries TSF_All, TSF_Any, TSF_Not, TSF_And, TSF_Or,
|
|
155
|
+
TSF_EnemyNPC, TSF_NPC, TSF_Quickhackable, each with return type gameTargetSearchFilter;
|
|
156
|
+
enums.json gametargetingSystemSearchFilterMaskValue. Also in classes.json:
|
|
157
|
+
gameTargetSearchQuery (fields testedSet, searchFilter, includeSecondaryTargets,
|
|
158
|
+
ignoreInstigator, maxDistance, filterObjectByDistance, queryTarget; SetComponentFilter). Read
|
|
159
|
+
2026-09-10, re-checked 2026-10-04.'
|
|
160
|
+
tags:
|
|
161
|
+
- entity
|
|
162
|
+
- spatial-query
|
|
163
|
+
- rtti
|
|
164
|
+
- target-search-filter
|
|
165
|
+
- live-check-next
|
|
166
|
+
detail: >-
|
|
167
|
+
This is the call that would verify a world placement that is not an NPC (a sector-placed prop,
|
|
168
|
+
say). An earlier version of this fact said no TargetSearchFilter class appears in the dump and
|
|
169
|
+
that constructing the struct would mean guessing a native layout; both were wrong — the class
|
|
170
|
+
is there (opaque), and the struct is meant to be obtained from the TSF_* constructor globals,
|
|
171
|
+
not built by hand. The Lua side is largely settled from CET's own source (the cp2077.cet.*
|
|
172
|
+
binding facts, 2026-09-11): non-member RTTI globals are exposed as bare names, as Game.Name
|
|
173
|
+
and as Game["Name;"]; a returned struct is a ClassReference copy that passes straight back
|
|
174
|
+
into a struct-typed parameter; an array return is a 1-based table whose null handles become
|
|
175
|
+
nil holes. The mask enum is in the dump too: enums.json
|
|
176
|
+
gametargetingSystemSearchFilterMaskValue (alias TSFMV): Obj_Player=1, Obj_Puppet=2,
|
|
177
|
+
Obj_Sensor=4, Obj_Device=8, Obj_Other=16, Att_Friendly=32, Att_Hostile=64, Att_Neutral=128,
|
|
178
|
+
Sp_AimAssistEnabled=256, Sp_Aggressive=512, St_Alive=2048, St_Dead=4096, St_NotDefeated=8192,
|
|
179
|
+
St_Defeated=16384, St_Conscious=32768, St_Unconscious=65536, St_TurnedOn=131072,
|
|
180
|
+
St_TurnedOff=262144, St_QuickHackable=524288, St_AliveAndActive=174080. CET coerces an
|
|
181
|
+
undeclared enum value to 0 silently
|
|
182
|
+
(cp2077.cet.enum-params-accept-number-string-or-enum-but-undeclared-values-become-zero), so
|
|
183
|
+
"every object" cannot be one ORed mask; it is TSF_Or(TSF_Any(E"Obj_Device"),
|
|
184
|
+
TSF_Any(E"Obj_Other"), TSF_Any(E"Obj_Puppet"), TSF_Any(E"Obj_Sensor")) with each member built
|
|
185
|
+
by Enum.new("gametargetingSystemSearchFilterMaskValue", name), the one form that fails loudly
|
|
186
|
+
on a wrong type name. Still unverified: whether the game marks TSF_* isExec (which would drop
|
|
187
|
+
only the bare-global form), the semantics of TSF_Any vs TSF_All and TSF_Or, whether a static
|
|
188
|
+
prop is in the targeting set at all (a loot-case template that carries a
|
|
189
|
+
gameTargetingComponent is the likely case), and what the calls return on a real prop.
|
|
190
|
+
ModWright's cp2077.entity.nearby handler attempts exactly this behind `filter: "objects"`,
|
|
191
|
+
pcall-wrapped. Console lines (a save loaded, standing near a known placed entity), counting
|
|
192
|
+
with pairs because of the nil holes:
|
|
193
|
+
print(type(TSF_NPC), type(TSF_All), type(Game.TSF_NPC), type(Game["TSF_NPC;"]))
|
|
194
|
+
local f = TSF_NPC(); print(type(f))
|
|
195
|
+
local r = Game.GetPlayer():GetNPCsAroundObject(20.0); local n=0; for _ in pairs(r or {}) do n=n+1 end; print(type(r), n)
|
|
196
|
+
local e = Game.GetPlayer():GetEntitiesAroundObject(20.0, f); local m=0; for _ in pairs(e or {}) do m=m+1 end; print(type(e), m, e and e[1] and e[1]:GetClassName())
|
|
197
|
+
local E = function(n) return Enum.new("gametargetingSystemSearchFilterMaskValue", n) end
|
|
198
|
+
local g = TSF_Or(TSF_Any(E("Obj_Device")), TSF_Any(E("Obj_Other")), TSF_Any(E("Obj_Puppet")), TSF_Any(E("Obj_Sensor")))
|
|
199
|
+
local a = Game.GetPlayer():GetEntitiesAroundObject(20.0, g); local k=0; for _,x in pairs(a or {}) do k=k+1; print(x:GetClassName()) end; print(type(a), k)
|
|
200
|
+
Record each line's exact output.
|
|
201
|
+
- id: cp2077.entities.spatial-and-targeting-systems-exist-but-are-heavier
|
|
202
|
+
claim: "Two other RTTI-registered systems expose broader spatial/targeting capability:
|
|
203
|
+
gameISpatialQueriesSystem (Overlap/OverlapByQueryFilter/SyncRaycastBy* — physics-engine
|
|
204
|
+
overlap and raycast queries) and gametargetingTargetingSystem (the concrete class behind
|
|
205
|
+
ScriptGameInstance::GetTargetingSystem; gameITargetingSystem is its empty interface parent):
|
|
206
|
+
GetTargetClosestByDistance, GetObjectClosestToCrosshair(instigator, angleDistance, query),
|
|
207
|
+
GetLookAtObject(instigator, withLOS, ignoreTranparent) -> ref<gameObject>, GetTargetParts, and
|
|
208
|
+
other player-aim-centric lookups (signatures in
|
|
209
|
+
cp2077.rtti.targetingsystem-crosshair-and-distance-queries). Neither is a simple \"list of
|
|
210
|
+
entities near a point\" call the way GetEntitiesAroundObject's name suggests; both need more
|
|
211
|
+
setup (a query shape or filter, or player-aim context) than a probe should invent blind."
|
|
212
|
+
status: unverified
|
|
213
|
+
source: rayshader/cp2077-nativedb@b5d29af classes.json, gameISpatialQueriesSystem and
|
|
214
|
+
gametargetingTargetingSystem class entries (captured 2026-09-10; class name corrected
|
|
215
|
+
2026-09-11 — the functions live on the concrete class, not the interface).
|
|
216
|
+
tags:
|
|
217
|
+
- entity
|
|
218
|
+
- spatial-query
|
|
219
|
+
- rtti
|
|
220
|
+
- targeting-system
|
|
221
|
+
- future-work
|
|
222
|
+
detail: "Recorded so a future session does not re-derive this from scratch: these exist and are real
|
|
223
|
+
engine capability, but gameObject's own GetEntitiesAroundObject/GetNPCsAroundObject are the
|
|
224
|
+
more directly applicable pair for \"what did ModWright place nearby\" and were pursued first
|
|
225
|
+
for that reason. GetTargetParts takes a gameTargetSearchQuery, whose searchFilter field is the
|
|
226
|
+
same gameTargetSearchFilter the TSF_* constructors produce."
|
|
227
|
+
- id: cp2077.entities.ententity-getcurrentappearancename-exists-in-rtti
|
|
228
|
+
claim: "entEntity carries GetCurrentAppearanceName() -> CName (no parameters) and
|
|
229
|
+
GetCurrentColorVariantName() -> CName; entIComponent carries GetAppearanceName() -> CName. A
|
|
230
|
+
sector-placed loot-case prop inherits the entity-level read: a template whose entity class is
|
|
231
|
+
LootContainerObjectAnimatedByTransform reaches entEntity through its parent chain."
|
|
232
|
+
status: inferred
|
|
233
|
+
source: ModWright research
|
|
234
|
+
tags:
|
|
235
|
+
- entity
|
|
236
|
+
- appearance
|
|
237
|
+
- rtti
|
|
238
|
+
- unverified-call
|
|
239
|
+
- live-check-next
|
|
240
|
+
related:
|
|
241
|
+
- cp2077.entities.native-gametagsystem-finds-entities-by-tag
|
|
242
|
+
detail: This is a direct read of the question cp2077.entity.appearance asks by differential
|
|
243
|
+
inference (did the sector node's appearanceName resolve?). One scalar return, the same risk
|
|
244
|
+
class as GetWorldYaw. Once any handle to the placed prop is in hand (GetLookAtObject, a native
|
|
245
|
+
tag lookup, or a position query), `obj:GetCurrentAppearanceName()` compared with the node's
|
|
246
|
+
authored appearanceName is the whole check. Registered nowhere yet; the probe registry's
|
|
247
|
+
cp2077.entity.appearance row names it as the candidate for the next live run.
|
|
248
|
+
- id: cp2077.entities.loot-case-template-component-names
|
|
249
|
+
claim: 'A sector-placed loot-case entity template (entity class
|
|
250
|
+
LootContainerObjectAnimatedByTransform) declares eleven components, by class and CName:
|
|
251
|
+
gameInventory "inventory", gameinteractionsComponent "interactions", gameScanningComponent
|
|
252
|
+
"scanning", WorkspotMapperComponent "workspotMapper", entPlaceholderComponent "root",
|
|
253
|
+
gameaudioSoundComponent "audioSound", gameVisionModeComponent "vision", entSlotComponent
|
|
254
|
+
"UI_Slots", GameplayRoleComponent "GameplayRole", entEffectSpawnerComponent "state_fxes",
|
|
255
|
+
gameTargetingComponent "targeting". A light-prop template declares one, a gameLightComponent
|
|
256
|
+
under a mod-chosen name.'
|
|
257
|
+
status: inferred
|
|
258
|
+
source: ModWright research
|
|
259
|
+
tags:
|
|
260
|
+
- entity
|
|
261
|
+
- component
|
|
262
|
+
- template
|
|
263
|
+
- interaction
|
|
264
|
+
- loot-container
|
|
265
|
+
related:
|
|
266
|
+
- cp2077.entities.ententity-getcurrentappearancename-exists-in-rtti
|
|
267
|
+
detail: Design-time template fields from one mod's loot case and another's light prop, not an
|
|
268
|
+
in-engine observation that each component resolves on the streamed instance; the registry rows
|
|
269
|
+
that ask for component names stay unverified, but no longer have to say the interaction name
|
|
270
|
+
is unattested anywhere. The light-prop mod's CET script calls ent:FindComponentByName(<its
|
|
271
|
+
light's name>) — a live call against a name taken from the template, which is the pattern
|
|
272
|
+
cp2077.entity.components and cp2077.interaction.present rely on. The presence of
|
|
273
|
+
gameTargetingComponent "targeting" on the case is also the first evidence that a sector-placed
|
|
274
|
+
prop of this kind is in the targeting set, which the GetEntitiesAroundObject and
|
|
275
|
+
GetLookAtObject lines depend on.
|
|
@@ -199,10 +199,12 @@ facts:
|
|
|
199
199
|
reload completed" after the trigger — see the archives read-back and
|
|
200
200
|
hot-folder-moves-into-mods); the `.hot-tweaks` half is VERIFIED INEFFECTIVE — the sentinel is
|
|
201
201
|
deleted/consumed but no TweakXL.Reload follows (see hot-tweaks-consumed-without-reload-1.3.0);
|
|
202
|
-
`.hot-scripts`
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
cp2077.
|
|
202
|
+
`.hot-scripts` drove real script reloads on 2026-09-13, but only seen fired together with a
|
|
203
|
+
second trigger, and that run ended in a crash (see
|
|
204
|
+
reloadscripts-recompiles-cleanly-storm-crash-1.3.0). So "ModWright can drive all three" holds
|
|
205
|
+
for archives; tweaks must go through TweakXL.Reload() via cp2077.lua.eval; scripts reload, but
|
|
206
|
+
one trigger at a time. RELATED: cp2077.redhottools.hotreload.hot-folder-moves-into-mods (the
|
|
207
|
+
archive half) and cp2077.process.assetbuild.rht-hot-folder-banned-for-whole-mesh-archives.'
|
|
206
208
|
- id: cp2077.redhottools.hotreload.hot-tweaks-consumed-without-reload-1.3.0
|
|
207
209
|
claim: "In Red Hot Tools 1.3.0.33690, dropping `red4ext/plugins/RedHotTools/.hot-tweaks` is consumed
|
|
208
210
|
(RHT deletes the file) but does NOT drive a TweakXL reload: after an edited `r6/tweaks` file
|
|
@@ -243,3 +245,27 @@ facts:
|
|
|
243
245
|
(src/core/deploy/reload.ts detectRedHotTools) now gates the RHT-dependent rows on the DLL +
|
|
244
246
|
the watcher line instead. RHT 1.3.0 is installed and current while the README floors read
|
|
245
247
|
2.21, so a floor check would have refused it."
|
|
248
|
+
- id: cp2077.redhottools.hotreload.reloadscripts-recompiles-cleanly-storm-crash-1.3.0
|
|
249
|
+
claim: "In Red Hot Tools 1.3.0.33690 a redscript hot reload recompiles and rebinds cleanly: RHT's
|
|
250
|
+
ScriptLoader logs Compiling, Reading blob, Validating, Capturing scriptable data, Binding,
|
|
251
|
+
Translating bytecode, Initializing runtime, Restoring scriptable data and \"Scripts reload
|
|
252
|
+
completed.\" with no compile or bind error. But with a save loaded, firing two script-reload
|
|
253
|
+
triggers at once (the `.hot-scripts` sentinel and the `RedHotTools.ReloadScripts()` facade,
|
|
254
|
+
called from CET Lua) produced about five full recompile-and-rebind cycles in 8 seconds, and
|
|
255
|
+
the game crashed to desktop just after the last one."
|
|
256
|
+
status: verified
|
|
257
|
+
verified_on: "2.31"
|
|
258
|
+
source: ModWright field verification
|
|
259
|
+
tags:
|
|
260
|
+
- redhottools
|
|
261
|
+
- hot-scripts
|
|
262
|
+
- reloadscripts
|
|
263
|
+
- hot-reload
|
|
264
|
+
- crash
|
|
265
|
+
- negative-result
|
|
266
|
+
detail: "Fire exactly one script-reload trigger. ModWright's reload apply writes only the
|
|
267
|
+
`.hot-scripts` sentinel for scripts. Still open: whether one clean reload with a save loaded
|
|
268
|
+
is stable, or whether script reloads belong at the main menu, since RHT rebinds every script
|
|
269
|
+
class over live gameplay objects. RELATED:
|
|
270
|
+
cp2077.redhottools.hotreload.triggers-are-sentinel-files and
|
|
271
|
+
cp2077.cet.sandbox.exec-func-vs-addmethod-reachability."
|