STUGPlay Free

Vehicle Data (tankData) Reference

Vehicle properties are defined in .tmx files under public/assets/vehicles/<name>/<name>.tmx. They are parsed by vehicle_data.js and stored on each vehicle entity as entity.tankData.

Gamemodes can override tankData values after createVehicle():

entity.tankData.reloadTime = 3000;
entity.tankData.armorMod = 0.3;

Properties

Identity

Property Type Description
name string Display name (e.g. “Grizzly Mk. I”)
type string Class: "light", "medium", or "heavy". Affects boost duration (light=10s, medium=12s, heavy=15s) and client rendering

Engine & Movement

Property Type Range Description
engineForce float 115–365 Forward acceleration force. Light 115–200, medium 260–320, heavy 260–365
engineForceWithTurn float 20–330 Reduced forward force while turning. Typically 70–90% of engineForce
engineBoostForce float 260–1000 Peak acceleration during boost. Light ~300, medium ~660, heavy 800–1000
engineBoostTime int (ms) — Custom boost duration override (replaces type-based default)
engineBoostAngularDamping float 0.1–0.8 Rotational drag during boost. Default 0.1; Haus uses 0.8 for stability
turnForce float 0.02–0.18 Rotation speed while stationary. Light 0.15–0.18, heavy 0.02–0.08
turnForceWithEngine float 0.02–0.15 Rotation speed while moving. Typically 60–80% of turnForce
mass float 0–35 Physics mass. Affects inertia, collisions, ram damage (25 + (mass-20)*0.75). Light 15–19, medium 20–22, heavy 21–35. Turret uses 0 (immovable)
reverseMod float 0.5–0.9 Multiplier on engineForce when reversing

Firepower

Property Type Range Description
reloadTime int (ms) 1500–10000 Cooldown between shots. Light 2100–3800, medium 4200–6800, heavy 7500–10000. Turret base: 1500
damageMod float 0.4–2.1 Damage multiplier on shells fired by this vehicle. Light 0.4–0.65, medium 1.0–1.2, heavy 1.55–2.1
damagePenMod float 0.5–1.5 Penetration angle modifier for shells fired. Higher = easier to penetrate targets
fireForce float 100–1000 Recoil force applied to hull when firing
barrelLength int (px) 26–85 Distance from turret center where shell spawns. Default ~45

Armor & Protection

Armor formula: damage *= 1 + (1 - armorMod). So armorMod=0.5 means 1.5x damage taken, armorMod=1.5 means 0.5x damage taken.

Property Type Range Description
armorMod float 0.2–1.6 Base armor multiplier for all hit directions. Light 0.2–0.4, medium 0.65–1.2, heavy 1.15–1.6
armorModSide float 0.24–1.25 Overrides armorMod for side hits. Typically weaker than front
armorModRear float — Overrides armorMod for rear hits. Haus uses 2.4 (strong rear, still one shot but ricochets better)
armorPenMod float 0.5–1.5 Multiplier on incoming penetration angle check. Higher = shells penetrate more easily (less bouncing). Useful for circular hitboxes where geometry causes excessive bouncing

Hit direction is determined by which face of the hitbox polygon the raycast hits (0=rear, 1/3=side, 2=front).

Turret

Property Type Range Description
turretSpeed float 0.013–0.25 Turret rotation speed in radians/frame. Light 0.08–0.12, heavy 0.013–0.04. Turret entity: 0.25
turretRotationLimit float (rad) 0.175–0.18 Max turret rotation from forward. Only tank destroyers use this (~10 degree arc)

Derived / Internal

Property Calculation Description
repairTime clamp(10000 * armorMod, 8000, 12000) Auto-repair duration. Heavier armor = faster repair

Special Flags

Property Type Description
disableCosmetics bool Skip cosmetic rendering (decals/skins)

Vehicle Classes at a Glance

Class armorMod damageMod mass reloadTime turretSpeed
Light 0.2–0.4 0.4–0.65 15–19 2100–3800 0.08–0.12
Medium 0.65–1.2 1.0–1.2 20–22 4200–6800 0.04–0.08
Heavy 1.15–1.6 1.55–2.1 21–35 6600–10000 0.013–0.04
Turret 0.6 1.4 0 1500 0.25

Weapon System

Vehicles can define multiple turrets, each with multiple weapons, each offering multiple selectable shell types. This is opt-in: a vehicle that declares none of the properties below behaves exactly as a classic single-gun tank (a single standard/ap weapon is synthesized from the flat reloadTime/barrelLength/damageMod/fireForce/damagePenMod properties).

Config is parsed once from the .tmx into vehicleInfo.weaponConfig by src-game/weapon_config.js and is shared by server and client (the client receives the same parsed data via the browserified bundle — nothing weapon-related is sent over the wire except runtime selection/fire events). Shell behaviors live in the src-game/weapon_shells.js registry. Firing/reload/selection runtime lives in src-game/weapon_system.js.

Authoring in the .tmx

Turrets

A turret is an <objectgroup> named Turret, Turret2, Turret3, … (in order). The existing Turret group is turret 0. Group attributes/properties:

Property Where Description
offsetx / offsety group attribute Turret pivot offset from hull center (existing)
turretRotationLimit group property (float, rad) Firing arc half-width from the arc center. On a multi-turret vehicle, a turret whose gun can’t reach the aim (outside this arc) holds fire; only in-arc turrets shoot. Single-turret vehicles are never arc-gated.
turretArcCenter group property (float, rad) Offset of the firing-arc center from hull-forward. Positive = the tank’s right, negative = the tank’s left. Use for side-mounted sponson guns so the left/right turret each covers its side (default 0 = forward).
turretSpeed group property (float) Optional per-turret rotation speed override

Each turret aims at the player’s cursor from its own position (so side-by-side or fore/aft turrets get their own angle and parallax), rotates at turretSpeed, and is clamped to its arc; a turret whose arc can’t reach the target holds fire. The local player sees a separate aim line per turret.

Turret rotations are computed server-side (the client sends the world aim point) and synced in the snapshot, so every player sees each turret pointing correctly. Each turret also gets its own server raycast aim distance, so its aim line stops at the first obstacle. The snapshot is versioned (snapshotVersion: 3 = per-turret rotation + aim distance; v2 = rotation only; absent = neither): old replays that predate these still parse correctly (they just render all turrets at the primary angle).

Weapons

Each turret has one weapon, configured by properties on the turret <objectgroup> (alongside turretSpeed/turretRotationLimit/turretArcCenter). The Barrel objects inside a turret group are purely visual (rendered sprites) — they are not parsed for weapon stats. To give a vehicle multiple weapon types, give it multiple turrets. Each stat falls back to the vehicle-level value, then a default:

Property (on the turret group) Type Description
weaponType string standard (default), autoloader, charge, missile, or flamethrower
inaccuracy float (rad) Random per-shot angular deviation (± each shot). Defaults to 0.03 for autoloader (autocannon bursts walk around the aim point) and 0 for everything else; set explicitly per turret to override either way
reloadTime int (ms) Reload; for autoloader this is the long magazine reload after a burst
barrelLength, fireForce, damageMod, damagePenMod number Per-turret overrides of the vehicle stats
shells string CSV Selectable shell keys, e.g. "ap,he" (default "ap"). First entry is the default.
switchTime int (ms) Cooldown applied when the player switches shell/weapon. Defaults to the weapon’s reloadTime (swapping ammo takes a full reload); set explicitly for a faster/slower swap
burstCount int (autoloader) shots per magazine
burstInterval int (ms) (autoloader) delay between burst shots
chargeTime int (ms) (charge) time to reach full power
chargeMinPower / chargeMaxPower float (charge) power at tap / full hold; scales damage & recoil (default 0.4 / 1.0)
missileSpeed number (missile) projectile speed in px/tick (default 22)
missileRange int (px) (missile) max travel before it self-detonates (default 1500)
missileTurnRate float (rad/tick) (missile) TOW-style guidance: max steering per tick toward wherever the firer is aiming; 0 = dumb-fire (default 0)
missileGuidanceRange int (px) (missile) distance over which guidance is active before it flies straight (default 700)
missileAoeRadius / missileAoeDamage number (missile) warhead splash blast radius/damage to nearby tanks (default 120 / 70)
missileDamageMod float (missile) multiplier on the direct hit, which deals shell-style armor-face damage (front/side/rear) to the struck tank; that tank is excluded from the splash (default 1.4)
streamRange int (px) (flamethrower) length of the projected napalm string (default 300 — short)
streamSpeed int (px/s) (flamethrower) how fast the jet physically travels (default 1300). Damage/paint only reach as far as the stream has flown since fire-down, so it visibly extends from the barrel instead of appearing instantly
streamSpread float (rad) (flamethrower) half-angle of the spray (default 0.09 — a thin string; widen for a cone)
streamInterval int (ms) (flamethrower) time between stream ticks while held (default 90)
streamDamage float (flamethrower) small immediate flat damage per tick to every target the string touches (default 1.5). The sticky burn below is the real payload
streamStickDamage float (flamethrower) sticky napalm DOT per tick applied to any target the string touches (default 3)
streamStickDuration int (ms) (flamethrower) how long the burn keeps ticking after the target leaves the flames — the DOT follows them; re-contact refreshes it (default 3000)
streamStickInterval int (ms) (flamethrower) burn tick cadence (default 450)
streamFuel int (ms) (flamethrower) how long the tank sustains continuous fire before running dry (default 2600)
streamRegen float (flamethrower) passive refill rate (ms of fuel per ms) when not firing (default 0.5). Run the tank fully dry instead and it locks out for a full reloadTime refuel
streamFireRadius int (px) (flamethrower) optional lingering ground fire painted as a trail along the string (0 = off, default). Uses streamFireDamage/streamFireDuration/streamFireInterval

Shell types & per-shell overrides

shells="ap,he" references the registry in src-game/weapon_shells.js:

Shell Behavior
ap Armor-piercing — the classic shell. Penetrates, ricochets, full single-target damage.
he High-explosive — does not ricochet, deals reduced direct damage to the tank it hits (directDamageMod 0.6), and explodes for area damage on everything else nearby (aoeRadius/aoeDamage, linear falloff). The directly-hit target is excluded from its own blast. The blast is delayed by the shell’s travel time (tick-based — see delayedExplosions in vehicle.js).
heat Shaped charge — never ricochets and largely ignores armor thickness/angle (armorNormalize 0.6), so it reliably penetrates angled heavies AP would bounce off. Trade-off: no bounce/flank plays, only a small splash.
aphe Armor-piercing HE — penetrates and can still ricochet like AP, hits harder (directDamageMod 1.3) and does fairly consistent damage across armor classes (armorNormalize 0.4). Small internal-burst splash. The all-rounder.
hesh Squash head — cannot ricochet, big damage on flat plate but its damage falls off sharply on sloped/angled armor (angleDamageFalloff). Small spall splash.
canister Grapeshot/shotgun — fires a cone of pellets (pellets/spread), each weak, over a short range (maxRange). Devastating point-blank (especially on a rear), useless at distance.
incendiary Fire shell — modest direct hit, then leaves a burning zone (fireRadius/fireDamage/fireInterval/fireDuration) that deals tick-based damage-over-time to anything inside. Area denial. Fire zones are server-owned (they outlive the firer) and cleared on round reset.
shrapnel Fragmentation — a weak central burst that sprays fast fragment rays radially on detonation (shrapnelCount/shrapnelDamage/shrapnelRange), biased into a cone around the impact direction. Punishes clustered enemies.
smoke Concealment — negligible damage; lays down a smoke cloud (smokeRadius/smokeDuration). The cloud is a server-tracked circle that blocks the aim-distance raycast players see (but NOT actual shells — you can fire blind through it) and blocks team vision: tanks inside or behind it disappear from the enemy team’s screen (fog of war) and bots lose them as targets. If it hits nothing within smokeRange px it lays the cloud there, so you can screen open ground.

Registry fields (in src-game/weapon_shells.js): pierces, directDamageMod, penMod, armorNormalize (0..1, dampens the target’s armor at damage time), angleDamageFalloff (damage falls off on oblique hits), pellets/spread/maxRange (spread shells), aoeRadius/aoeDamage/aoeFalloff (explosive), fireRadius/fireDamage/fireInterval/fireDuration (incendiary zone), shrapnelCount/shrapnelDamage/shrapnelRange (fragments), smokeRadius/smokeDuration/smokeRange/smokeVisionRadius (concealment cloud; vision is blocked over smokeVisionRadius, default 70% of the cloud). A shell “detonates” (queues a delayed dispatch) if it has any of aoeRadius/fireRadius/shrapnelCount/smokeRadius > 0; the effects are fanned out by weaponSystem.detonate(). (missile is a separate weaponType, not a shell — it spawns a traveling projectile object; see the weapon table.)

Per-shell numeric params can be overridden per turret with <shellKey>_<param> properties, e.g. he_aoeRadius, heat_armorNormalize, canister_pellets, incendiary_fireDuration. Add a new shell type by adding a registry entry — no other code changes needed for the common cases.

Design intent — when to use what

The base game’s combat loop is AP vs armor angling: damage depends on which face you hit (front/side/rear) and shots ricochet off oblique plate, so the skill expression is positioning, flanking, and baiting bounces. Every weapon type and shell below is designed to bend that loop in one direction — never to replace it. When authoring a vehicle, pick the one bend that defines its identity and make the vehicle pay for it somewhere else (damage, reload, armor, or mobility — see the SFC “scrap tax” below).

Weapon types

Type Intent Trade-off / counterplay
standard The baseline rhythm: one shot, one reload. Skill is aim and reload discipline. Use unless the vehicle’s whole identity is its firing pattern. —
autoloader Front-loads a reload’s worth of damage into a short burst window — a flanker that darts in, dumps the magazine into a side/rear, and leaves. Bursts have slight inaccuracy by default (0.03 rad), so they hose an area rather than laser one pixel — get close to land the whole magazine. The long magazine reload is the counterplay window: a missed burst leaves the vehicle defenseless far longer than a missed single shot. The default wobble also makes range a soft counter. Keep burst-total damage ≈ what a standard gun of its tier deals over the same total cycle, or slightly less.
charge Risk/reward timing: damage scales with how long the player holds fire while exposed. Rewards ambush positions and siege play; the full-charge alpha should feel scary. Charging telegraphs (charge bar, exposure time). Tap-fire (chargeMinPower) must be clearly worse than a standard gun so holding is the point.
missile The only weapon whose projectile exists in the world: travel time, TOW steering (missileTurnRate toward the firer’s aim), and splash. Skill is curving shots around cover and leading targets; it trades hitscan certainty for reach and indirect angles. Travel time means it can be dodged or body-blocked; guidance ends after missileGuidanceRange, so long shots fly straight and are predictable. Direct hits still respect armor faces, so it doesn’t erase the angling game.
flamethrower Short-range sticky pressure: a held napalm string that lights everything it touches on fire — the burn follows the target for a few seconds even if they break away (streamStickDuration), and it paints a burning trail on the ground you can sweep to wall off space. Ignores the angling game entirely; the payload is the lingering DOT, not the direct hit. A resource weapon (fuel tank you feather or dump). Short reach (streamRange) and a thin string — anyone who keeps spacing takes little. The direct tick is tiny, so it’s weak burst; its damage arrives over time, which a target can partly outrun (kite the burn out, use cover). Dumping the whole tank overheats into a long reloadTime refuel. Give it low armor or mobility so closing the gap is the risk it pays for.

Shells

The first entry in shells is the default and should be the vehicle’s identity; extra entries are situational tools, not straight upgrades. switchTime defaults to a full reload, so switching is a commitment — a player who swaps to the wrong shell pays for it. Two shells is the sweet spot, three is the max before the choice stops being readable mid-fight.

Shell Intended role What it asks of the firer / counterplay
ap The reference shell. Full single-target damage, plays the complete ricochet/armor-face game. Firer must flank or catch flat plate; defender angles and baits bounces. Everything else is balanced against it.
aphe Comfort pick — AP that hits harder and cares less what it hits (armorNormalize 0.4). For players who want one shell that’s never wrong. Priced via the host vehicle (lower damageMod/slower reload than an AP peer), because a strictly-better AP kills the shell-choice game.
heat Anti-heavy specialist: ignores most of the armor/angle game (armorNormalize 0.6, never ricochets), so it opens up targets AP bounces off. Gives up the firer’s angle plays too — no bounce baiting, no oblique jackpots, tiny splash. Weak into light targets where armor wasn’t the problem.
hesh Punishes bad angling: big damage on flat plate, sharply worse on sloped (angleDamageFalloff). The mirror of heat — it deepens the angle game instead of removing it. Defender counterplay is simply angling well; a good opponent makes HESH feel terrible. Pair it with a backup shell.
he Anti-group / low-commitment poke: reduced direct damage but splash hits everyone near the impact. Good vs clusters, bad in duels. Choosing HE into a lone target is throwing damage away — that’s the decision it exists to create.
shrapnel Harder anti-cluster: weak center burst plus fragment rays that carry the blast outward. Punishes deathballs and choke stacking more than plain HE. Fragments are short-range rays — spread-out or single enemies mostly ignore it.
canister Range control: a pellet cone that shreds point-blank (especially rears) and does nothing at distance (maxRange). Defines brawlers and ambushers. The firer must close distance through the enemy’s effective range first; anyone who keeps spacing hard-counters it.
incendiary Area denial over time: the fire zone (not the direct hit) is the payload. Flushes campers off points, cuts off retreats, zones chokes. Weak direct damage — into a mobile target that just drives out of the fire, it’s the worst shell in the game. That’s intentional.
smoke Information denial, zero damage: blocks the aim raycast and hides tanks inside/behind it from the enemy team entirely (players and bots). Screens pushes, covers retreats, blinds sightlines. Note it does NOT stop shells — blind fire through it still hits. Firing smoke is a whole reload spent doing no damage; it’s only worth it when the team plays off it. Give it to support/scout vehicles, never as a main shell.

Pairing guide: good loadouts create a decision, not a fallback — canister,ap (brawl vs poke), aphe,heat (all-rounder vs angled heavies), shrapnel,hesh (groups vs flat singles), he,incendiary,smoke (dedicated support). Avoid pairing two shells that answer the same situation (e.g. he,shrapnel — both anti-cluster; one of them will never be selected).

Player controls (defaults, rebindable)

Action Default Notes
Cycle weapon X / mouse scroll Only active when the vehicle has >1 weapon
Cycle shell C Only active when the active weapon has >1 shell
Weapon wheel hold V Radial picker for weapons
Charge hold Fire Charge weapons charge while Fire is held; release to shoot (a charge bar shows progress)