Configured vehicle versus preview copy
A preview object is presentation state, not automatically the player's configured garage setup.
In the current client, g_currentPreviewVehicle creates a vehicle copy. Descriptor-
backed preview construction can remove optional devices and replace the crew with a perfect
placeholder crew.
- When the selected compact descriptor belongs to an owned vehicle, resolve it through
IItemsCacheand use that inventoryVehicleas the authority for equipment, directives, consumables, field modifications, installed modules, and crew. - Use the preview copy when no owned account item exists, or when the question is explicitly about the preview rather than the configured loadout.
- Keep the visual preview and calculation authority separate even when they currently have the same compact descriptor.
Copy boundaries belong to individual fields
Reading a record does not guarantee an isolated snapshot. The current
comparison basket returns its actual
record from getVehicleAt(index), and that record's getters have different copy
contracts. Preserve the boundary of each field rather than treating every getter as equivalent.
| Getter | Inspected ownership boundary |
|---|---|
getCrewData() | Returns the retained skills mapping with its level value. |
getInventoryCrewData() | Deep-copies the inventory skills mapping. |
getEquipment() | Copies the selected list, then projects built-in equipment for a non-inventory record when item data is synchronized. |
getInvEquipment() | Returns the retained inventory layout. |
| Dynamic-slot and post-progression getters | Return retained objects. |
The configurator constructs a Vehicle from the string descriptor, then separately adopts crew, equipment, camouflage, booster, dynamic-slot, post-progression and selected-shell state. The descriptor alone is not the complete setup. Copying one equipment list also does not isolate the other fields.
Treat borrowed fields as read-only for observation. Direct mutation is not the basket's parameter-change notification path. These version-sensitive contracts were checked in current public source; live edits, complete clone isolation, persistence and rendered comparison behavior were not exercised.
Compose calculated parameters by producer
Garage statistics may combine descriptor mutations, vehicle attribute factors, crew-skill KPIs,
and native VehicleParams calculations. Trace the current producer before multiplying
layers: equipment or field modifications may already be represented in a descriptor or factor,
so applying the same KPI again can produce a plausible but incorrect value.
Units are part of that contract. For example, parsed engine power is stored in watts while the
current VehicleParams.enginePower property exposes horsepower. Convert only at a
verified boundary, and test an uncapped result because a later speed cap can hide a unit error.
Shell speed has its own verified boundary. Parsed shot descriptors contain a physics-scaled velocity; the native garage parameter divides by the common projectile-speed factor before showing metres per second. A custom row must perform the same conversion before applying live vehicle and crew coefficients. Displaying the descriptor value directly produces a consistent but inflated number.
Auto-shoot dispersion is a separate contract
For a gun tagged autoShoot, the ordinary
gun.shotDispersionFactors['afterShot'] value is not the mechanic's per-shot
auto-fire bloom. The current descriptor exposes that value separately as
gun.autoShoot.shotDispersionPerShot. Treat it as an additive dispersion increase
per shot, not as the conventional after-shot multiplier.
Use the configured vehicle descriptor when equipment, field modifications, or other descriptor
modifiers matter. The current client allows
autoShoot/shotDispersionPerShot to be modified at the descriptor layer, so routing
the resulting value through the conventional after-shot or generic additive-dispersion chain
can apply an adjustment twice. This contract is build-dependent: verify the gun tag, descriptor
field, modification path, and battle mechanic consumer in the target client.
Terrain, crew, and module boundaries
- Keep descriptor mutations,
getVehicleFactors, crew-skill KPIs, nativeVehicleParams, and detailed physics data as distinct producers. Combine only the layers current callers prove are independent. - Off-Road Driving changes medium and soft resistance differently and leaves firm resistance unchanged. Do not reuse an already perk-adjusted average in both the traverse numerator and per-ground denominator.
- Module health combines the relevant component health, matching miscellaneous factor, and only a supported crew KPI. Multi-track chassis require current track-pair data rather than an assumed legacy chassis field.
- Attribute breakdowns should remove bonuses from a vehicle copy in the client's order and refresh crew bonuses before recalculation. The resulting deltas are marginal effects, not independent additive promises.
Expensive breakdowns should be deferred and coalesced outside route constructors and hot preview callbacks. Cancel the pending refresh when the view closes and reuse one ordered calculation trace for rows with the same producer chain.
Hidden defaults can mean unavailable
Some formatted numbers are UI sentinels rather than usable characteristics. In the current client, the default artillery-warning delay and damaged-module detection time are hidden when the enabling perk or directive is absent. If a bonus-removal trace reaches one of those defaults, represent the baseline as unavailable and describe the source as enabling the characteristic. Showing the sentinel as a slow baseline falsely implies that the capability exists without its source.
Hypothetical loadouts are complete layouts
A safe configuration preview operates on isolated vehicle copies and accepts compact descriptor IDs only after Python validates the complete requested layout. An installed-bonus list is not a catalog and one item ID is not enough to prove a legal slot assignment.
- Equipment, consumables, and directives have separate vehicle, slot, duplicate, combination, and dependency contracts.
- Equipment specialization depends on the selected slot categories, including dynamic post-progression role slots.
- Field modifications and tier-XI vehicle skill trees are different systems and must not be exposed through one control.
- Crew layout comes from descriptor role slots even when the garage vehicle has no mounted crew. Validate primary and secondary skill groups on the Python side.
- A preview must never translate an arbitrary UI item identifier into an inventory or account command.
Publish catalog records once per family and keep per-slot payloads compact. Compatibility is combination-dependent, so cache it by vehicle, layout kind, and complete candidate layout—not by item ID alone. Rebuild the copied descriptor and crew bonuses before every authoritative calculation.
Multi-component values need component-level quality
One native parameter can mix directions: reload and intra-clip times are lower-is-better while rate-like components may be higher-is-better. Judge each keyed component before merging source rows. Summing tuple deltas first can label beneficial reload reductions as regressions.
Alternate vehicle mode snapshots
XML-backed alternate modes use a composite descriptor that keeps default and siege descriptors synchronized. Select the mode on a configured copy and keep that mode on every further copy used for attribution. Switching the inventory vehicle or calculating the baseline from the other descriptor half corrupts both ownership and comparison.
Not every mechanic is a second descriptor. Some expose persistent stance parameters, active modifier lists, or explicit vehicle-parameter blocks. Model only source-backed inactive and full-active snapshots; cooldown phases, charge counts, deployment animations, and progress meters do not imply intermediate stat sets. Apply each producer exactly once and preserve scalar and sequence components. These private mechanics and modifier paths are build-dependent and require representative client comparison after updates.