-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathvehicles.json
More file actions
241 lines (241 loc) · 11.8 KB
/
Copy pathvehicles.json
File metadata and controls
241 lines (241 loc) · 11.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
{
"_README": [
"Define NEW vehicles as modifications of existing ones.",
"",
" base DataTable ROW name to start from \u2014 what the game calls it,",
" the same name Spawn_<Row> placeholders use.",
" `python unlock_vehicles.py` lists every row.",
" new_id row name for the new vehicle. Spawn_<new_id> places it.",
" display_name name shown in game.",
" modifications list of {type: ..., ...}, applied in order.",
"",
"Inspect any row's real fields with:",
" MTBPInjector dump-table --uasset <Vehicles.uasset> --mappings <usmap> --row Vista",
"Vehicles.uasset is the aggregate \u2014 it carries ParentTables for the 12",
"others, so a row resolves through it even when defined elsewhere.",
"",
"MODIFICATION: all_wheel_drive",
" (no flags) spool \u2014 every wheel on one differential.",
" each_set_awd: true front and rear each get their own differential.",
" enable_center_diff: true adds the centre differential they both feed.",
" This is vanilla's shape (see Neo).",
"MODIFICATION: row_field {field, value} \u2014 any scalar on the vehicle row.",
"MODIFICATION: display_name is a top-level key, not a modification.",
"",
" row the existing DataTable row. Keeps its name and class path,",
" so the mod's copy overrides vanilla and every one already",
" in the world gains the change \u2014 no second vehicle to buy.",
" Adds MTTankerFuelPumpComponent, which is what actually makes a vehicle",
" usable as a refuelling station. bHasFuelPump on the row only ADVERTISES",
" that component \u2014 setting the flag alone does nothing at all.",
" One slot per fuel type. EMTFuelType has exactly two members, Gasoline",
" and Diesel; water is not one of them, so a water tanker is not possible",
" this way even though the fire engine carries water as cargo.",
" rel_x/y/z move the interaction point; omitted leaves the class default,",
" which is what the Brutus fire engine itself uses.",
"",
"The `modify` section lives in vehicles_tankers.json now, not here. The",
"tanker fuel pumps ship as their own mod; this file is the ISLAND's, so",
"anything in it goes into the Arini pak. Vista_GTR belongs here."
],
"_STATUS": [
"The drivetrain analysis is DONE and recorded below. The injector work to",
"clone a vehicle class and restructure its differentials is NOT done, so",
"nothing in `vehicles` ships yet. Recorded so the analysis is not repeated.",
"",
"Cloning the class itself is tractable: the same byte-rename that produces",
"the Mod* delivery point classes works on a vehicle asset, and cloning the",
"DataTable row is the same mutate pattern used for cargo. That much gives a",
"new vehicle that exists, spawns and is buyable.",
"",
"The hard part is AWD, which is not a property change. It means ADDING",
"components to a cooked Blueprint's construction script, which this",
"framework has never done \u2014 every actor so far has been cloned whole or had",
"existing properties overwritten."
],
"_DRIVETRAIN_ANALYSIS": {
"_": "How Motor Town expresses drivetrain, read from the cooked classes.",
"rwd_example_Vista": {
"Wheel0": "no DifferentialComponentName (front, undriven)",
"Wheel1": "no DifferentialComponentName (front, undriven)",
"Wheel2": "DifferentialComponentName = Differential",
"Wheel3": "DifferentialComponentName = Differential",
"components": [
"Differential"
]
},
"awd_example_Neo": {
"Wheel0": "DifferentialComponentName = DifferentialF",
"Wheel1": "DifferentialComponentName = DifferentialF",
"Wheel2": "DifferentialComponentName = DifferentialR",
"Wheel3": "DifferentialComponentName = DifferentialR",
"DifferentialF": "DifferentialComponentName = DifferentialC",
"DifferentialR": "DifferentialComponentName = DifferentialC",
"components": [
"DifferentialC",
"DifferentialF",
"DifferentialR"
]
},
"awd_example_EnfoGT": "same three-differential shape; the centre one is spelled DiffernetialC, a typo in the game's own data \u2014 match it exactly if cloning EnfoGT rather than Neo",
"conclusion": [
"AWD is a three-differential tree: front and rear differentials each",
"feed a centre differential, and all four wheels name their end.",
"Converting RWD -> AWD therefore requires renaming Differential to",
"DifferentialR, ADDING DifferentialF and DifferentialC components, and",
"repointing Wheel0/Wheel1. Neo is the reference to copy: it is a road",
"car like the Vista, where EnfoGT is a GT with its own quirks."
]
},
"_PLANNED": {
"row_field": "DONE. Any scalar field on the row \u2014 Cost, bIsRaceCar, bTrailerHauling, DeliveryPaymentMultiplier, CurbWeight.",
"display_name": "DONE. VehicleName is a TextProperty into a StringTable, so a cloned row shows the BASE car's name. Written as CultureInvariant inline text instead, on both VehicleName and VehicleName2 \u2014 the two UI screens read different ones.",
"all_wheel_drive": "DONE, but as a SPOOL not a centre diff. All four wheels point at the differential the rear pair used. Vanilla AWD (Neo) is three differentials \u2014 F and R each feeding a centre C \u2014 which needs new components in a cooked Blueprint and is still out of reach.",
"fuel_tank_capacity": "NOT a vehicle property at all. It is a PART: UtilityParts has a row FuelTank_01 carrying FuelTank.FuelLiter (100 L, 1000c, 20kg) plus a mesh on Aero.Mesh. So a bigger tank means cloning that row with a larger FuelLiter and making the vehicle accept it, not editing the car. Reference implementation: D:/MT/MoreTuning/FuelTanks/run.py"
},
"vehicles": [
{
"base": "Vista",
"new_id": "Vista_GTR",
"display_name": "Vista GTR",
"_": "Placeholder Spawn_Vista_GTR is already placed in the scene at editor (-184975,-798940,865). It resolves to nothing until this ships, and the build logs `spawner: vehicle 'Vista_GTR' not found` every run \u2014 that warning is expected until then.",
"modifications": [
{
"type": "row_field",
"field": "Cost",
"value": 95000
},
{
"type": "all_wheel_drive",
"each_set_awd": true,
"enable_center_diff": true,
"_": "Full three-differential tree, the same shape Neo uses."
}
]
}
],
"_ROW_FIELDS_Vista": {
"_": "All 38 fields on the Vista row, from dump-table --row. NOTE: there is NO fuel tank field here. Anything not in this list is not a row-level knob.",
"identity": [
"VehicleName",
"VehicleName2",
"VehicleType",
"VehicleClass",
"TruckClass",
"VehicleTypeFlags"
],
"economy": [
"Cost",
"DeliveryBasePayment",
"DeliveryPaymentMultiplier",
"CompanyAIRunningCostMultiplier",
"CompanyAIConditionUsageMultiplier",
"CompanyAIConditionUsageMultiplierOffroad"
],
"roles": [
"bIsTaxiable",
"bIsLimoable",
"bIsBusable",
"bIsRaceCar",
"bTrailerHauling",
"bHasFuelPump"
],
"availability": [
"bHidden",
"bDisabled",
"bShowRequirementsNotMet",
"LevelRequirementToDrive",
"GameplayTags",
"GarageGameplayTagQuery",
"NPCSpawnPrabability"
],
"parts": [
"Parts",
"PartValues",
"NotOptionalPartTypes",
"OptionalPartTypes",
"NotOptionalPartSlots",
"NotSupportedPartTypes",
"SlotSupportedPartsQueries"
],
"physical": [
"CurbWeight",
"BodyDamageThreshold",
"Comport",
"ExhaustBlackSmokeDensity",
"ExhaustTone",
"bShowCargoSpaceAtTheGarage"
]
},
"_RENAME_TRAP": [
"Cloning a vehicle class is a byte-rename, which is only valid at equal",
"length \u2014 hence generated names like Vista -> V8C52. What matters more is",
"WHICH occurrences get renamed.",
"",
"A blind replace of the base name breaks the car in two ways at once:",
" /Game/Cars/Models/Vista/Body the FOLDER is also called Vista",
" /Game/Cars/Parts/Wheels/Vista_L the wheels are separate assets",
"Rename either and the clone points at packages that do not exist \u2014 the",
"car spawns with no body and no wheels. Only three self-references may",
"move: the package self-path, Default__<name>_C, and <name>_C.",
"",
"Delivery point classes never hit this because their folder is not named",
"after the class."
],
"modify": [
{
"row": "Crany",
"_": "Crany's rope has no tension because MTCraneComponent.Winch is null, and it is null because a winch is spawned at runtime from a PART fitted to a SLOT -- not authored as a component. Crany declares no slots at all, so there is nowhere for one to go. Crane0 ONLY: Pulio also carries Utility0 and Utility1, but those are a tow truck's business and would offer Crany equipment it has no arm for.",
"modifications": [
{
"type": "crane_winch",
"name": "MTWinch",
"crane": "MTCrane_GEN_VARIABLE",
"_": "The rope's tension refreshes the moment the controller is picked up and never changes in between -- so tension IS computed, on discrete interaction events, and nothing updates it per-frame. MTCraneComponent.Winch is null, so the crane has nothing to tick. MTWinchComponent is a real class, so this adds one and points the crane at it rather than waiting for a spawn the Blueprint never does."
},
{
"type": "part_slots",
"field": "NotOptionalPartSlots",
"add": [
"EMTVehiclePartSlot::Crane0"
]
},
{
"type": "interactable",
"name": "CraneWinchControl",
"types": [
"Crane0_In",
"Crane0_Out"
],
"_": "Crany has a crane SEAT and no crane INTERACTION. GolimaRotator, whose crane works, carries CraneInteraction_L and _R as dedicated components; Crany's only interactables are for the driver and passenger seats. EMotorTownInteractableType has Crane0_In (50) and Crane0_Out (51) -- the winch in/out for the crane slot Crany now declares -- and nothing on the vehicle exposed them."
},
{
"type": "all_wheel_drive",
"each_set_awd": true,
"enable_center_diff": true,
"_": "Front and rear each get a differential, with a centre one they both feed -- the shape vanilla AWD vehicles actually use. A crane truck spends its life on soft ground and outriggers."
}
]
}
],
"_crany_finding": [
"CRANY CRANE: the constraint approach CRASHES. Do not re-add without a new idea.",
"",
"Constraint_Boom1 (Boom1 <-> CraneTop, hydraulic, angular) applied cleanly and",
"the vehicle drove, but stepping OUT of it crashed with an access violation",
"reading 0x10 -- a null dereference as the physics state is released.",
"",
"Why, most likely: a constraint joins two SIMULATED bodies. Crany's booms are",
"driven kinematically by MTCraneComponent every tick and have no authored",
"transforms at all, so there is no body for the constraint to hold, and the",
"null shows up when something walks the constraint list on exit.",
"",
"This is the answer to the question the build was designed to ask, and it is a",
"no: the two systems do not coexist. Brutus_Wrecker and GolimaRotator have",
"constraints and NO MTCraneComponent -- they are alternatives, not layers.",
"",
"A real fix means replacing MTCraneComponent with a constraint-driven arm, which",
"also replaces what CraneSeat currently talks to. That is a vehicle rebuild, not",
"a patch."
]
}