← Home SEEBIE90 DOCS
Download PDF
No copies or uploads of M.A.W.S. assetsExample code is free to useNo printed reproduction or modification of this documentationSuggestions: Discord to the authorLicense

Systems

Loadout & modules

Five hardpoints, dozens of modules, swappable in the field. The whole loadout replicates as a single integer – every machine builds the module meshes itself.

In plain wordsWhich weapon sits on which mount is stored as one number on the server. Every machine reads that number and attaches the matching weapon models itself.

Hardpoints and module definitions

HardpointClassHangs on
HP_Arm_L / HP_Arm_RARMarm parts
HP_Shoulder_L / HP_Shoulder_RSHOULDERlauncher parts
HP_BackBACKtorso

A module fits only a hardpoint of the same class. Each definition carries an id, label, class, weight in tonnes, swap time and the prefabs for the left and right side.

One int for the whole loadout

Example code – free to use
static const int BITS = 5;		// up to 31 modules per hardpoint, 0 = empty

[RplProp(onRplName: "OnLoadoutReplicated")]
protected int m_iLoadout;

int GetModuleAt(int hp)
{
	return (m_iLoadout >> (hp * BITS)) & 31;
}

void ServerSetModule(int hp, int module)
{
	int mask = 31 << (hp * BITS);
	m_iLoadout = (m_iLoadout & ~mask) | (module << (hp * BITS));
	Replication.BumpMe();
	Rebuild();				// onRplName does not fire on the server itself
}

protected void OnLoadoutReplicated()
{
	Rebuild();
}

Build locally on every machine

Module entities have no RplComponent. Each machine compares the replicated loadout with what it has mounted and spawns or deletes the difference itself. That keeps network entity count low and makes late joiners correct automatically.

Example code – free to use
protected void Rebuild()
{
	for (int hp = 0; hp < HardpointCount(); hp++)
	{
		int want = GetModuleAt(hp);
		if (m_aMounted[hp] == want)
			continue;

		if (m_aEntities[hp])
			SCR_EntityHelper.DeleteEntityAndChildren(m_aEntities[hp]);
		m_aEntities[hp] = null;
		m_aMounted[hp] = want;
		if (want == 0)
			continue;

		IEntity part = GetPartFor(hp);
		EntitySpawnParams sp = new EntitySpawnParams();
		sp.TransformMode = ETransformMode.WORLD;
		part.GetWorldTransform(sp.Transform);

		IEntity e = GetGame().SpawnEntityPrefab(Resource.Load(PrefabFor(hp, want)), part.GetWorld(), sp);
		part.AddChild(e, -1);
		e.SetLocalTransform(OffsetFor(hp));
		m_aEntities[hp] = e;

		// new children report garbage transforms in their first frame: re-scan weapons a bit later
		GetGame().GetCallqueue().CallLater(RescanWeapons, 400, false, hp);
	}
}

Weight and speed

Payload is the sum of the module weights. Top speed = 60 − 1 km/h per tonne (minimum 5), ×0.75 when overloaded above 20 t. The leg drive uses it as vmax, and a limiter on the physics owner clamps the horizontal velocity in case anything else (a jump, a push) exceeds it.

PitfallIf your drive has its own top-speed attribute, make sure it is not lower than the payload formula's maximum. Ours was 40 km/h – the payload limit then only mattered above 20 t, and an empty walker never got faster.

Swapping in the field

The commander requests a swap through the PlayerController. The server checks the seat, that the walker is parked and that a depot is near, then runs a swap timer. Each machine shows a progress bar from a small replicated start counter per hardpoint, so the bar restarts on every machine without sending times.

Example code on this site is free to use in your own projects (credit appreciated). The M.A.W.S. mods, their code and assets are covered by the M.A.W.S. License – no copies or uploads. This documentation may not be reproduced in print or modified. Suggestions: Discord. Arma Reforger / Enfusion are trademarks of Bohemia Interactive.
Impressum · Privacy Policy