The engine can load resources and expose native models, textures, materials and matrix providers to Python. These objects require explicit ownership discipline.

Background resource loading

The historical API documents BigWorld.loadResourceListBG(resourceList, callbackFn, priority). The callback runs when engine loading completes; it does not make arbitrary Python work asynchronous.

def on_resources_loaded(resource_refs):
    if not context_is_current():
        return
    create_visuals(resource_refs)

# Verify the current signature and callback payload first.
BigWorld.loadResourceListBG(resources, on_resources_loaded)

Models

Older references expose constructors and helpers such as BigWorld.Model, fetchModel, addModel and delModel. World of Tanks may wrap or replace parts of this flow.

Create

Resolve the resource, construct or fetch the model, and confirm the required space.

Attach

Use the engine-supported attachment or scene ownership path. Keep track of the exact model instance you added.

Remove

Detach or delete the model during arena exit and before discarding your Python reference.

Matrix providers

BigWorld includes many historical provider types for position, direction, tracking and animation. Providers are composable live transforms. They are powerful, but retaining one can indirectly retain or reference native objects that no longer belong to the current context.

Vehicle visual ownership patterns

Objects that appear attached to a vehicle can belong to very different engine paths. Choose the path whose ownership matches the visual instead of treating every effect as a node attachment.

PatternUseRequired cleanup
Descriptor-driven compound partsReplace chassis, hull, turret, or gun models while preserving native assembly.Copy descriptors, validate every path, preserve damage/model-set states, and compose the appearance hook.
Child model on a compound nodeRigid lamps, ornaments, beams, or animation sequences that follow a named bone.Retain the node and native animation owners; stop, unbind, and detach the exact child.
World model driven by a providerDebris, casings, or launched visuals that must leave the vehicle hierarchy.Bound count and lifetime, call delModel, and reject stale arena, space, vehicle, or avatar generations.
Embedded skinned mesh with a changed boneGeometry authored into the vehicle model that visually detaches or moves.Cache the base matrix per model instance and restore it on every valid exit path.

Procedural bone animation

Apply each procedural delta to an immutable base matrix for the current compound-model instance. Reapplying a delta to the previous frame accumulates drift. Invalidate cached nodes when the appearance or compound model changes, smooth frame-derived values, clamp authored ranges, cap large frame deltas, and restore the base before releasing ownership.

Battle ownership begins before the player vehicle and compound model necessarily exist. Handle delayed appearance, death, respawn or controlled-vehicle changes, model replacement, replay rewind, and ordinary arena exit. A stopped frame loop must either be reacquired by an explicit vehicle-change event or remain a bounded battle owner capable of finding the next eligible model.

Resources are contracts

A resource path is part of the client build contract. Before loading an asset, verify its virtual path, case, package location and expected type. Missing resources should disable only the optional visual feature. For virtual resource paths and section data, see ResMgr & Virtual Resources; for stale resource behavior, see Resource & Cache Invalidation.

try:
    model = load_optional_model(MODEL_PATH)
except Exception:
    LOG_CURRENT_EXCEPTION()
    model = None

if model is not None:
    install_visual(model)

A failed batch can leave partial work

Current public source; version-sensitive. The stock component-loading consumer checks each resource and attaches its component while iterating. If it encounters a failed ID later in that iteration, it returns before final assembly and the success callback. Components attached earlier are not rolled back by that function. Do not depend on dictionary iteration order to decide which component exists after failure.

For an all-or-nothing visual, validate every required result before changing the scene, and clean up owned objects if construction itself fails. For incremental loading, record each successful attachment and give failure, replacement and teardown a cleanup path. An absent success callback does not prove that nothing changed.

The same consumer rejects delivery when its weak owner is gone or its stop flag is set. Those checks control whether Python applies a result; they do not cancel the underlying load or clean up earlier attachments. Keep result admission, resource cancellation and object cleanup separate. The inspected caller does not establish callback threading, native allocation release or cancellation-race guarantees.

Keep each request description stable

In the same current client consumer, submission creates a list of resources, but its deferred handler retains the original mapping and rereads each loader's resource, arguments and keyword arguments at completion. Changing a shared descriptor can therefore make completion process a different request from the one submitted. Copying only the outer mapping still shares its loader objects.

Keep resource associations and factory parameters stable for the request's lifetime. On a new selection, create a new request description and reject obsolete results before mutation. Clearing a captured mapping is not cancellation: this consumer can still reach its success callback after iterating an empty mapping. Do not assume native loader objects can be safely deep-copied; preserve their documented ownership.

The consumer's foreground branch processes the result directly. When its success callback is reached, that callback runs before the wrapper returns. Initialize owner state before submitting work, and tolerate a completion that runs before the wrapper returns. This Python call order does not establish native background callback threading, timing or performance.

Cleanup checklist

  • Track every model, listener, texture feed and callback created by the feature.
  • Remove scene objects before their space is destroyed.
  • Reject completed loads from stale arena or view generations.
  • Do not assume a historical resource-loading signature is still valid.
  • Keep optional visuals separate from core mod behavior.

Resource results and request generations

Current native callers can submit compound/collision assemblers and animation loaders, not only path lists. Completion results have successful references and a separate failedIDs collection. Check failure identity before indexing; completion alone does not prove every asset loaded or an animator started.

Retain background task IDs and cancel owned loads on replacement/teardown. Source call sites demonstrate stopLoadResourceListBGTask usage, not that cancellation excludes every late callback. Space/node restrictions reject results for a missing player, changed space or dangling node, but cannot distinguish two requests within the same scene. Keep a build/request generation too.

Weak callback wrappers prevent some retention; they do not test logical destruction or current vehicle identity. A temporary weakly referenced lambda/partial can disappear before delivery, while captured arguments can accidentally retain an owner. Reused wrappers can also retain mutated keyword state. Prefer an explicit callback owner and generation check instead of relying on weak references as a cancellation abstraction.

Composite loads and effect lifetimes

CompositeLoaderMixin counts appendPiece calls rather than distinct successful resources. A failed child can leave the count pending; duplicate completion can reach zero early, and an old callback can decrement a newly prepared count. Preserve piece identity, failure handling and request generation when adapting this pattern.

Effect stages accumulate durations, while explicit timelines use named times and do not synthesize the same terminal marker. At the final keypoint, the inspected player completes/stops without running the ordinary attach/detach step for that key. Completion can run before isPlaying clears; an explicit forced stop can invoke the callback too. Do not treat it as an unconditional natural end or gameplay transition.

Release owned effect handles through their actual manager/descriptor lifecycle. Removing a Python element, receiving completion and releasing native assets are separate claims. Native loader cadence, rendering and decoder/allocator release still require runtime evidence.