Ships Config Guidelines – Arma 3

From Bohemia Interactive Community
Jump to navigation Jump to search
Line 42: Line 42:
* Resolution LODs
* Resolution LODs
* ShadowVolume 0, 10, 1000, 1010
* ShadowVolume 0, 10, 1000, 1010
* Bouyancy LOD[[File:mkv_bouy_lod.PNG|right|frame|Buoyancy LOD|300px]]  
* Bouyancy LOD[[File:mkv_bouy_lod.PNG|frame|Buoyancy LOD|right|300px]]  
** bouy lods can contain more than one component (convex/closed/tris). but for components in the water (especially all the time), they really should be a single component with physx geometry in general, it's usually best to have no intersecting geometry. especially with the bouy lod. as it will double physx calcs in the water. Outside of that.. nothing really special about it. you want to keep the face count as low as possible. but honestly it can handle a lot before you actually see performance hits in a typical environment.  
** bouy lods can contain more than one component (convex/closed/tris). but for components in the water (especially all the time), they really should be a single component with physx geometry in general, it's usually best to have no intersecting geometry. especially with the bouy lod. as it will double physx calcs in the water. Outside of that.. nothing really special about it. you want to keep the face count as low as possible. but honestly it can handle a lot before you actually see performance hits in a typical environment.  
* A new PhysX LOD[[File:mkv_physx_lod.PNG|right|frame|PhysX LOD|300px]]  
* A new PhysX LOD[[File:mkv_physx_lod.PNG|frame|PhysX LOD|right|300px]]  
** There needs to be a lod (4e13) consisting of convex components as simple as possible.
** There needs to be a lod (4e13) consisting of convex components as simple as possible.
*** Requires the latest Arma 3 Tools to binarizE
*** Requires the latest Arma 3 Tools to binarizE

Revision as of 01:13, 11 November 2014

Intro

So you want to build a boat in Arma 3? Well lets start with some basics...

What's the difference between a boat and a ship?

- A ship is usually large enough to carry a boat. Subs are also called boats, regardless of size. :)

Creating boats in Arma 3 seems to be reasonably straight forward. They exist today (Speedboat, Inflatable boat etc). Creating ships in Arma 3 is a little more challenging.

Arma 3 has limitations when handling objects larger than 60m in any dimension. The main limitations from a boats/ships perspective is the inability for MAN class to stand on the object, so when getting out of a boat/vehicle onto a large object (ship), players will fall through the structure.

For Arma purposes, lets call boats anything shorter than 60m and ships over 60m. Small Subs (SDV) are those less than 60m, while Large Subs are greater than 60m (i.e. ship size).

There are 2 approaches to ships and boats in Arma 3. Typically boats are modelled and implemented as "vehicles" where as ships historically have been implemented as a single or multiple "static" objects stitched together (i.e. LHD, Fregata, Destroyer etc).

A few very brave modders have attempted to mix the two. USS Iowa (mod by AusSnipe73) - http://www.armaholic.com/page.php?id=27109 - defines a ship vehicle but then attaches many different static objects and turrets to the ship to build out a 270m long vessel (using an init script to attachto all the ship parts).

Similar efforts have been used to attempt to get a driveable LHD (from Arma 2).

Please be aware of the Arma 3 modding license: http://community.bistudio.com/wiki/Arma_3_Modding_License

Comparison to A2/OA ships

  • PhysX support (ShipX, SubmarineX)
  • Improved penetration materials
  • More detailed Fire Geometry LODs
  • Improved tweakability of HitPoints LODs

Model requirements {p3d}

General

The behavior of the ship in the water does not depend anymore on the LandContact points, but on the GEO and PHYSX LODs. The PHYSx LOD seems to represent the water displacement of the ship. If you put too much mass (a value over the displacement) the ship sinks. The PHYSx LOD must be similar in form and size, to the ship's hull. It must also follow the Geometry LOD rules (closed and convex) and must be composed of only one component (that's what BIS says in the VSB2 editing wiki)

GEO is very important. You must balance the mass in all axis (plural axes?) and keep the weight down so the ship doesn't turn and sinks. In subs it is specially important because it controls how it moves once submerged and how it maintains depth.

LODs (included in Arma 3 boat p3ds)

  • Resolution LODs
  • ShadowVolume 0, 10, 1000, 1010
  • Bouyancy LOD
    Buoyancy LOD
    • bouy lods can contain more than one component (convex/closed/tris). but for components in the water (especially all the time), they really should be a single component with physx geometry in general, it's usually best to have no intersecting geometry. especially with the bouy lod. as it will double physx calcs in the water. Outside of that.. nothing really special about it. you want to keep the face count as low as possible. but honestly it can handle a lot before you actually see performance hits in a typical environment.
  • A new PhysX LOD
    PhysX LOD
    • There needs to be a lod (4e13) consisting of convex components as simple as possible.
      • Requires the latest Arma 3 Tools to binarizE

From VBS2 wiki... (assuming the displacement LOD in VBS2 = PhysX LOD in Arma 3)

Ensure that the geometry is accurate to the shape of the ship, with accurate mass distribution and realistic Center of Mass.
Create a simplified copy of the geometry, for use in the displacement LOD. 
The displacement LOD should adhere to these rules:
   * Have as few faces as possible - high face counts will have a negative impact on performance.
   * Convex components must not penetrate each other if possible (especially on permanently immersed parts). If they penetrate, then their volume and surface is calculated twice.
   * Convex components must not even touch each other. Merge them together if possible. (especially on permanently immersed parts). If they touch, then their surface is calculated twice. This is not that big a problem on not permanently immersed parts.
   * Inside areas must not be modeled. Volume is not calculated for this area and inside surface is then added, which we do not want.
   * Volume of the object represents what will generate buoyancy. Do not model parts which can instantly fill with the water.
   * Surface of the object represents what will generate resistance in water. Create only one convex component for permanently immersed part.
The ideal displacement LOD is built of a single component which matches (approximately) the shape of the hull. It is important that the volume be reasonably close to the real volume of the ship, as this is used for buoyancy calculations.
The displacement LOD adheres to the normal rules for geometry LODs.
  • Memory LOD
    • See Model.cfg for a list of memory points
    • Additionally the placement of the water effects is important. They must be below the waterline. Worth noting, if those memory points come out of the water in the simulation ... the engine will shut off (or wont turn on). These points are also where the 'thrust' is applied to the model. So there is a bit of a balancing act that can go on, depending on the speed/size of the vessel and relative weather conditions (eg.. 30 setWaves 1).
  • Geo
    • Regarding the GEO LOD, it is very important to remove the autocenter=0 property in the properties tab of the GEO LOD. Otherwise the ship will inmediately sink.
    • The basic concept/goal is to weight the vehicle accurately, the 'center of mass' should be about center vertically, and towards the rear of the vessel. This makes the vessel sit a little deeper aft when idle. What is important to note, is that the weighting is being applied to the Geometry LOD, but you need to balance the 'center of mass' around the shape of the PhysX GEO LOD.
    • What is also important to note is that the amount of weight you enter must counter the 'displacement' of the PhysX GEO LODs. I say LODs because I can't recall exactly if the Buoyancy LOD was actually responsible for that calculation. Either way, one of the PhysX LODs assumes a certain amount of displacement, and your total amount of mass must be balanced against that.
  • View Cargo
  • View Pilot
  • View Gunner
  • Fire Geo
  • View Geo
  • HitPoints

Model Config {model.cfg}

  • Example from the Armed Speed Boat in Arma 3:
class cfgSkeletons
{
	class Default
	{
		isDiscrete = 1;
		skeletonInherit = "";
		skeletonBones[] = {};
	};
	class Boat_Armed_01_hmg_F : default
	{
		SkeletonBones[]=
		{
			"damagehide",	"",
			"rearturret",	"damagehide",
			"reargun",	"damagehide",
			"drivewheel",	"damagehide",
			"otocvez",	"",
			"otochlaven",	"otocvez",
			"commanderview",	"otochlaven",
			"zasleh_gmg",	"otochlaven",
			"volant",	"",
			"radar",	"",
			"kompas",	"",
			"fuel",	"",
			"mph",	"",
			"rpm",	"",
			"amps",	"",
			"oil",	"",
			"trim",	"",
			"tmp",	"",
			"volt",	"",
			"otocvez2",	"",
			"otochlaven2",	"otocvez2",
			"otochlaven2_shake",	"otochlaven2",
			"z_gatlingr",	"otochlaven2_shake",
			"recoil",	"otochlaven2",
			"bolt",	"recoil",
			"gunnerview2",	"otochlaven2",
			"magazine",	"otochlaven2",
			"ammo_belt2",	"magazine",
			"bullet006",	"ammo_belt2",
			"bullet005",	"bullet006",
			"bullet004",	"bullet005",
			"bullet003",	"bullet004",
			"bullet002",	"bullet003",
			"bullet001",	"bullet002",
			"zasleh2",	"otochlaven2",
			"otochlaven2_static",	"otocvez2",
			"positionlights",	""
		};
	};
};

class CfgModels
{
	class Default
	{
		sections[] = {};
		sectionsInherit="";
		skeletonName = "";
	};
	class Boat_Armed_01_hmg_F:Default
	{
		skeletonName="Boat_Armed_01_hmg_F";
		sections[]=
		{
			"otochlaven",
			"otochlaven2",
			"engine",
			"p svetlo",
			"camo",
			"camo2",
			"camo3",
			"zbytek"
		};
/* other potential axis=
otocvez2
magazine
recoil2
damagehide
otochlaven2_shake
karoserie
konec hlavne
usti hlavne
recoilhlaven_axis
osahlavne
osaveze2
konec hlavne2
usti hlavne2
eye2
osahlavne2
bolt_axis2
marker_light1
magazine2
gunnerview2
pilot2
ammo_belt_axis2
drivewheel_axis
watereffectl
watereffectr
engineeffectl
engineeffectr
pos driver
pos driver dir
pos cargo
pos cargo dir
pos gunner
pos gunner dir
commanderview
mph_axis
rpm_axis
tmp_axis
amps_axis
volt_axis
oil_axis
fuel_axis
trim_axis
marker_light2
pip0_pos
pip0_dir
pip3_pos
pip3_dir
pip2_pos
pip2_dir
konec p svetla
machinegun_eject_pos
machinegun_eject_dir
positionlight_red_1_pos
positionlight_green_1_pos
slingloadcargox
slingloadcargo1
slingloadcargo2
slingloadcargo3
slingloadcargo4
slingloadcargo5
slingloadcargo6
otocvez
drivewheel
mph
rpm
tmp
amps
volt
oil
fuel
trim
recoil
zasleh2
zasleh_gmg
positionlights
bolt
bullet001
bullet002
bullet003
bullet004
bullet005
bullet006
ammo_belt2
*/

		class Animations
		{
			class Damagehide
			{
				type="hide";
				source="damage";
				selection="damagehide";
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				hideValue = 1.0;
//				unHideValue = -1.0;//(default)
				animPeriod = 0.0;
				initPhase = 0.0;
			};
			class Barrel_recoil
			{
				type="translation";
				source="ReloadAnim";
				selection="recoil";
				axis="recoil_axis";//*probably*
				sourceAddress = mirror;
				minValue = 0.0;//rad 0.0
				maxValue = 0.5;//rad 28.64789
				offset0 = 0.0;
				offset1 = -0.05;
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class Bolt_recoil
			{
				type="translation";
				source="ReloadAnim";
				selection="bolt";
				axis="bolt_axis";//*probably*
				sourceAddress = mirror;
				minValue = 0.0;//rad 0.0
				maxValue = 0.5;//rad 28.64789
				offset0 = 0.0;
				offset1 = -0.25;
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class Turret_shake
			{
				type="translation";
				source="ReloadAnim";
				selection="otochlaven2_shake";
				axis="otochlaven2_shake_axis";//*probably*
				sourceAddress = mirror;
				minValue = 0.0;//rad 0.0
				maxValue = -0.2;//rad -11.459156
				offset0 = 0.0;
				offset1 = 0.2;
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class Turret_shake_aside
			{
				type="translation";
				source="ReloadAnim";
				selection="otochlaven2_shake";
				axis="otochlaven2_shake_axis";//*probably*
				sourceAddress = mirror;
				minValue = 0.0;//rad 0.0
				maxValue = 0.65;//rad 37.242256
				offset0 = 0.0;
				offset1 = 0.2;
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class Magazine_hide
			{
				type="hide";
				source="reloadMagazine";
				selection="magazine";
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				hideValue = 0.28;
				unHideValue = 0.72;
				animPeriod = 0.0;
				initPhase = 0.0;
			};
			class MainTurret
			{
				type="rotationY";
				source="mainTurret";
				selection="otocvez";
				axis="otocvez_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = -6.2831855;//rad -360.0
				maxValue = 6.2831855;//rad 360.0
				angle0 = -6.2831855;//rad -360.0;
				angle1 = 6.2831855;//rad 360.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class DamageHideOtocVez
			{
				type="hide";
				source="damage";
				selection="otocvez";
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				hideValue = 1.0;
//				unHideValue = -1.0;//(default)
				animPeriod = 0.0;
				initPhase = 0.0;
			};
			class MainGun
			{
				type="rotationX";
				source="mainGun";
				selection="otochlaven";
				axis="otochlaven_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = -6.2831855;//rad -360.0
				maxValue = 6.2831855;//rad 360.0
				angle0 = -6.2831855;//rad -360.0;
				angle1 = 6.2831855;//rad 360.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class DamageHideOtocHlaven
			{
				type="hide";
				source="damage";
				selection="otochlaven";
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				hideValue = 1.0;
//				unHideValue = -1.0;//(default)
				animPeriod = 0.0;
				initPhase = 0.0;
			};
			class RearTurret
			{
				type="rotationY";
				source="rearTurret";
				selection="otocvez2";
				axis="otocvez2_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = -6.2831855;//rad -360.0
				maxValue = 6.2831855;//rad 360.0
				angle0 = -6.2831855;//rad -360.0;
				angle1 = 6.2831855;//rad 360.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class RearGun
			{
				type="rotationX";
				source="RearGun";
				selection="otochlaven2";
				axis="otochlaven2_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = -6.2831855;//rad -360.0
				maxValue = 6.2831855;//rad 360.0
				angle0 = -6.2831855;//rad -360.0;
				angle1 = 6.2831855;//rad 360.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class muzzleFlash
			{
				type="hide";
				source="muzzle_source";
				selection="zasleh_gmg";
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				hideValue = 0.0;
				unHideValue = 0.1;
				animPeriod = 0.0;
				initPhase = 0.0;
			};
			class zaslehROT
			{
				type="rotationZ";
				source="muzzle_source_rot";
				selection="zasleh_gmg";
				axis="zasleh_gmg_axis";//*probably*
				sourceAddress = loop;
				minValue = 0.0;//rad 0.0
				maxValue = 4.0;//rad 229.18312
				angle0 = 0.0;//rad 0.0;
				angle1 = 6.2831855;//rad 360.0;
				animPeriod = 1.4013e-045/*#DEN*/;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class muzzleFlash2
			{
				type="hide";
				source="muzzle2_source";
				selection="zasleh2";
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				hideValue = 0.0;
				unHideValue = 0.8;
				animPeriod = 0.0;
				initPhase = 0.0;
			};
			class zasleh2ROT
			{
				type="rotationZ";
				source="muzzle2_source_rot";
				selection="zasleh2";
				axis="zasleh2_axis";//*probably*
				sourceAddress = loop;
				minValue = 0.0;//rad 0.0
				maxValue = 4.0;//rad 229.18312
				angle0 = 0.0;//rad 0.0;
				angle1 = 6.2831855;//rad 360.0;
				animPeriod = 1.4013e-045/*#DEN*/;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class fuel
			{
				type="rotation";
				source="fuel";
				selection="fuel";
				axis="fuel_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				angle0 = 0.5235988;//rad 30.0;
				angle1 = -0.5235988;//rad -30.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class mph
			{
				type="rotation";
				source="speed";
				selection="mph";
				axis="mph_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 2.0;//rad 114.59156
				maxValue = 25.0;//rad 1432.3945
				angle0 = 2.7925267;//rad 160.0;
				angle1 = -2.7925267;//rad -160.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class rpm
			{
				type="rotation";
				source="rpm";
				selection="rpm";
				axis="rpm_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				angle0 = 2.7925267;//rad 160.0;
				angle1 = -2.7925267;//rad -160.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class amps_random
			{
				type="rotation";
				source="rpm";
				selection="amps";
				axis="amps_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				angle0 = 0.17453292;//rad 10.0;
				angle1 = -0.17453292;//rad -10.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class oil_random
			{
				type="rotation";
				source="rpm";
				selection="oil";
				axis="oil_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				angle0 = -0.17453292;//rad -10.0;
				angle1 = 0.17453292;//rad 10.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class trim_random
			{
				type="rotation";
				source="speed";
				selection="trim";
				axis="trim_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				angle0 = 0.08726646;//rad 5.0;
				angle1 = -0.08726646;//rad -5.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class tmp_random
			{
				type="rotation";
				source="rpm";
				selection="tmp";
				axis="tmp_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				angle0 = -0.08726646;//rad -5.0;
				angle1 = 0.08726646;//rad 5.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class volt_random
			{
				type="rotation";
				source="speed";
				selection="volt";
				axis="volt_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				angle0 = 0.2617994;//rad 15.0;
				angle1 = -0.2617994;//rad -15.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class DrivingWheel
			{
				type="rotation";
				source="drivingWheel";
				selection="drivewheel";
				axis="drivewheel_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = -1.0;//rad -57.29578
				maxValue = 1.0;//rad 57.29578
				angle0 = 2.000147;//rad 114.59999;
				angle1 = -2.000147;//rad -114.59999;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class Ammo_Belt_2_Rotation_prep
			{
				type="translation";
				source="ReloadAnim";
				selection="ammo_belt2";
				axis="ammo_belt2_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 0.0001;//rad 0.005729578
				offset0 = -1.0;
				offset1 = 0.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class Ammo_Belt_2_Rotation_main
			{
				type="translation";
				source="ReloadAnim";
				selection="ammo_belt2";
				axis="ammo_belt2_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.3;//rad 17.188734
				maxValue = 0.999;//rad 57.238483
				offset0 = 0.0;
				offset1 = -1.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class Ammobelt_Hide
			{
				type="hide";
				source="reloadMagazine";
				selection="ammo_belt2";
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				hideValue = 0.09;
				unHideValue = 1.0;
				animPeriod = 0.0;
				initPhase = 0.0;
			};
			class Bullet001_2_Hide
			{
				type="hide";
				source="revolving";
				selection="bullet001";
				sourceAddress = mirror;
				minValue = -1.0;//rad -57.29578
				maxValue = 0.0;//rad 0.0
				hideValue = 0.975;
//				unHideValue = -1.0;//(default)
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
			};
			class Bullet002_2_Hide
			{
				type="hide";
				source="revolving";
				selection="bullet002";
				sourceAddress = mirror;
				minValue = -1.0;//rad -57.29578
				maxValue = 0.0;//rad 0.0
				hideValue = 0.98;
//				unHideValue = -1.0;//(default)
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
			};
			class Bullet003_2_Hide
			{
				type="hide";
				source="revolving";
				selection="bullet003";
				sourceAddress = mirror;
				minValue = -1.0;//rad -57.29578
				maxValue = 0.0;//rad 0.0
				hideValue = 0.985;
//				unHideValue = -1.0;//(default)
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
			};
			class Bullet004_2_Hide
			{
				type="hide";
				source="revolving";
				selection="bullet004";
				sourceAddress = mirror;
				minValue = -1.0;//rad -57.29578
				maxValue = 0.0;//rad 0.0
				hideValue = 0.99;
//				unHideValue = -1.0;//(default)
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
			};
			class Bullet005_2_Hide
			{
				type="hide";
				source="revolving";
				selection="bullet005";
				sourceAddress = mirror;
				minValue = -1.0;//rad -57.29578
				maxValue = 0.0;//rad 0.0
				hideValue = 0.995;
//				unHideValue = -1.0;//(default)
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
			};
			class Bullet006_2_Hide
			{
				type="hide";
				source="revolving";
				selection="bullet006";
				sourceAddress = mirror;
				minValue = -1.0;//rad -57.29578
				maxValue = 0.0;//rad 0.0
				hideValue = 1.0;
//				unHideValue = -1.0;//(default)
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
			};
			class Muzzle1_shake
			{
				type="translation";
				source="ReloadAnim";
				selection="recoil";
				axis="recoil_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.85;//rad 48.701412
				maxValue = 1.0;//rad 57.29578
				offset0 = -1.0;
				offset1 = 0.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class Muzzle1_shake_back
			{
				type="translation";
				source="ReloadAnim";
				selection="recoil";
				axis="recoil_axis";//*probably*
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 0.85;//rad 48.701412
				offset0 = 0.0;
				offset1 = -1.0;
				animPeriod = 0.0;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class Bolt_move_2
			{
				type="translation";
				source="ReloadAnim";
				selection="bolt";
				axis="bolt_axis";//*probably*
				sourceAddress = mirror;
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				offset0 = 0.0;
				offset1 = 0.5;
				animPeriod = 2.8026e-045/*#DEN*/;
				initPhase = 0.0;
//				memory = true;//(default assumed)
			};
			class PositionLights
			{
				type="hide";
				source="collisionLights";
				selection="positionlights";
//				sourceAddress = clamp;// (default)
				minValue = 0.0;//rad 0.0
				maxValue = 1.0;//rad 57.29578
				hideValue = 0.0;
				unHideValue = 1.0;
				animPeriod = 0.0;
				initPhase = 0.0;
			};
		};//Animations
	};//modelclass
};//CfgModels

Config (config.cpp)

Ship/Boat Config Classes in Arma 3

  • Base class is Ship (inherits AllVehicles) and uses simulation = "ship". There are 4 child classes:
    • SmallShip - not used
    • BigShip - not used
    • FloatingStructure_F
      • FloatingStructure_F uses simulation ShipX.
      • Submarine_01_F inherits from FloatingStructure_F but is defined as vehicleClass="submerged" and does not appear to be implemented as a "vehicle".
      • C_Boat_Civil_04_F inherits from FloatingStructure_F is defined as vehicleClass="submerged" and does appear to be implemented as a "vehicle" but you cannot interact with it (get in etc).
    • Ship_F
      • Boat_F is the basis of most of the "boats" in Arma 3.
        • Boat_Armed_01_base_F uses simulation shipX.
        • Boat_Civil_01_base_F uses simulation shipX.
        • Rubber_duck_base_F uses simulation shipX.
        • SDV_01_base_F uses simulation submarineX and is used as the basis for all SDVs in Arma 3.

Submarine and Ship Config Detail

Thanks to Mankyle for the following explanation and sample Sub.

airCapacity = 1209600;

Quite important for submarines. Determines the time the crew inside the ship can be below the surface before dying suffocated for lack of air. It seems that when using class submarinex, the engine sets the crew as if they were below the water

verticalTurnCoef = 20.2;

This line seems to control the speed for ascending/descending.

waterSpeedFactor = 3.0;

No idea of what this does. I have tried a couple of values and I haven't seen changes

periscopeDepth = 15.5;

This is the depth the sub mantains when you activate the "Mantain periscope Depth" Action. It is important to know that for big models (not a SDV sized submarine) that this depth DOES NOT coincide with the depth marker in the left upper corner of the screen

idleRpm = 1000;

Self explaining

redRpm = 4000;
thrustDelay = 2;

thrustDelay is the time the engine needs from 0 thrust to 1 thrust (or 0% to 100%). Time is in seconds.

simulation = "submarinex";
simulation = "shipx";

PHYSx simulation classes

overSpeedBrakeCoef = 0.8;

Brake effectivity. If you follow VBS 2 explanations, this value is (overSpeedBrakeCoef*enginePower). The higher the value, the better it brakes

enginePower = 3278;

Engine power in HPs. (according to VBS2 wiki - set the total engine power, in kW)

engineShiftY = 2;

This lines tells where the engine applies the force related to the origin of the model. Esentially what one mus calculate is the distance in the vertical axis between the Y value of center of mass of the model and the Y Value of the propeller, waterjet or whaterver moves the ship. Negative values tend to make the bow rise when you accelerate and positive values tend to make it dive. From vbs2 wiki - Adjust the height at which the engine force is applied to the hull, relative to the model origin, in m. Used for large ships, this will cause the ship to lean more/less in fast turns.

waterLeakiness = 1000;

This parameter determines the quantity of water (M^3 x S) that will fill the volume of the PHYSx LOD per second. Tipically lower vaues for boats, higher for bigger ships. Modifies the sinking rate of a ship when this suffers damage.

waterResistanceCoef = 0.01;

Represents the resistance if the hull. The higher the value the higher the resistance. This affects acceleration and maximum speed.

waterLinearDampingCoefX = 10.0;

This value represents lateral movements produced by waves. Higher values will make the ship corner better and slide less to the sides.

waterLinearDampingCoefY = 1.2;

This one represents vertical movements depending on the waves. Higher values will modify how much the ship sinks/goes down depending on the waves. It can also affect the flotation line maintaining the ame Ship mass. Higher values will also make a ship sink slower

waterAngularDampingCoef = 8.0;

Smooth the angular movement in all axis, higher values will reduce swinging/swaying, but may cause strange behavior in turns/rolling over waves.

rudderForceCoef = 12;

Set how effective the rudder is, small boats are typically 0.5 - 5, large ships are typically 100 - 200.

rudderForceCoefAtMaxSpeed = 15;

How the rudder works. The higher the value the more the ship will turn, BUT the more it will incline when turning. Values to high could even make a ship turn upside down (and sink) when turning. If you are transporting non scripted vehicles the can easily fall if this value is set too high.

There are two values. The first one is for low speed (usually ships turn better when sailing faster than a certain speed) and the second one when going at MEDIUM or FAST speed.

     memoryPointsLeftWaterEffect = "waterEffectR";
     memoryPointsRightWaterEffect = "waterEffectL";
     memoryPointsLeftEngineEffect = "EngineEffectL";
     memoryPointsRightEngineEffect = "EngineEffectR";

These are points in the memory LOD that represent the spawning points for water particle FX. The first ones represent bow FX, the last ones represent the foam generated by the engine propeller

Example Collins class submarine that uses submarinex simulation class:

http://www.freeuploadsite.com/uploads/13725721431.rar

Example Config for Armed Speedboat

Key noted items from Boat_Armed_01_base_F

		radarType = 8;
		steerAheadSimul = 0.5;
		steerAheadPlan = 0.35;
		predictTurnPlan = 0.8;
		predictTurnSimul = 0.6;
		brakeDistance = 5;
		acceleration = 15;
		turnCoef = 0.75;
		maxSpeed = 75;
		simulation = "shipx";
		waterLeakiness = 55.5;
		waterLinearDampingCoefY = 5;
		waterLinearDampingCoefX = 2;
		waterAngularDampingCoef = 1.2;
		waterResistanceCoef = 0.015;
		rudderForceCoef = 0.3;
		rudderForceCoefAtMaxSpeed = 0.02;
		waterEffectSpeed = 5;
		engineEffectSpeed = 5;
		waterFastEffectSpeed = 28;

Engine parameters

For indepth information about engine parameters see RedPhoenix's awesome BIF post http://forums.bistudio.com/showthread.php?165390-Tutorial-Creating-Custom-Engine-Gearbox-and-Suspension-Vehicle-config&p=2518019&viewfull=1#post2518019

Key noted items from Boat_Armed_01_base_F

		thrustDelay = 0.2;
		overSpeedBrakeCoef = 0.2;
		enginePower = 1085;
		engineShiftY = -0.1;
		idleRpm = 200;
		redRpm = 1200;
		class complexGearbox
		{
			GearboxRatios[] = {"R1",-0.782,"N",0,"D1",2,"D2",1.85,"D3",1.75};
			TransmissionRatios[] = {"High",1};
			gearBoxMode = "auto";
			moveOffGear = 1;
			driveString = "D";
			neutralString = "N";
			reverseString = "R";
		};

Config Comparison with USS Iowa (mod by AusSnipe73)

Inherits from Ship_F

		radarType = 4;
                simulation = "shipx";
		maxSpeed = 61;
		overSpeedBrakeCoef = 0.8;
		enginePower = 1580000;
		engineShiftY = 0.0;
		waterLeakiness = 1000.0;
		turnCoef = 1000.0;
		thrustDelay = 20;
		waterLinearDampingCoefY = 2;
		waterLinearDampingCoefX = 200.0;
		waterAngularDampingCoef = 1.2;
		waterResistanceCoef = 0.2;
		rudderForceCoef = 1000.0;
		rudderForceCoefAtMaxSpeed = 400.0;
		idleRpm = 500;
		redRpm = 1200;
		brakeDistance = 3;
		supplyRadius = 3;
		precision = 15;
		steerAheadSimul = 0.5;
		steerAheadPlan = 0.35;
		predictTurnPlan = 0.8;
		predictTurnSimul = 0.6;
		class complexGearbox
		{
			GearboxRatios[] = {"R1",-0.782,"N",0,"D1",2.0,"D2",1.85,"D3",1.75};
			TransmissionRatios[] = {"High",1.0};
			gearBoxMode = "auto";
			moveOffGear = 1;
			driveString = "D";
			neutralString = "N";
			reverseString = "R";
		};

Config for SDV in Arma 3

Inherits from Boat_F

		radarType = 8;
                verticalTurnCoef = 0.05;
		turnCoef = 0.5;
		steerAheadSimul = 0.5;
		steerAheadPlan = 0.35;
		predictTurnPlan = 0.8;
		predictTurnSimul = 0.6;
		brakeDistance = 25;
		acceleration = 15;
		maxSpeed = 30;
		waterSpeedFactor = 1;
		periscopeDepth = 1.2;
		idleRpm = 200;
		redRpm = 1200;
		thrustDelay = 2;
		formationX = 15;
		formationZ = 15;
		simulation = "submarinex";
		overSpeedBrakeCoef = 0.8;
		enginePower = 45;
		engineShiftY = 0.4;
		waterLeakiness = 0;
		waterResistanceCoef = 0.015;
		waterLinearDampingCoefX = 2;
		waterLinearDampingCoefY = 0.8;
		waterAngularDampingCoef = 1;
		rudderForceCoef = 0.2;
		rudderForceCoefAtMaxSpeed = 0.05;

Damage handling

Boats/Ships offer differing protection levels for themselves and crew inside, depending on place you hit them. Balancing damage is usually most time-consuming task for armored vehicles.

Basic config


		armor = 30;

		class Damage
		{
			tex[] = {};
			mat[] = {"A3\boat_F\Boat_Armed_01\data\Boat_Armed_01_ext.rvmat","A3\boat_F\Boat_Armed_01\data\Boat_Armed_01_ext_damage.rvmat","A3\boat_F\Boat_Armed_01\data\Boat_Armed_01_ext_destruct.rvmat","A3\boat_F\Boat_Armed_01\data\Boat_Armed_01_int.rvmat","A3\boat_F\Boat_Armed_01\data\Boat_Armed_01_int_damage.rvmat","A3\boat_F\Boat_Armed_01\data\Boat_Armed_01_int_destruct.rvmat","A3\boat_F\Boat_Armed_01\data\Boat_Armed_01_ctrls.rvmat","A3\boat_F\Boat_Armed_01\data\Boat_Armed_01_ctrls_damage.rvmat","A3\boat_F\Boat_Armed_01\data\Boat_Armed_01_ctrls_destruct.rvmat","A3\Static_F_Gamma\data\staticturret_01.rvmat","A3\Static_F_Gamma\data\StaticTurret_01_damage.rvmat","A3\Static_F_Gamma\data\StaticTurret_01_destruct.rvmat","A3\Static_F_Gamma\data\staticturret_02.rvmat","A3\Static_F_Gamma\data\StaticTurret_02_damage.rvmat","A3\Static_F_Gamma\data\StaticTurret_02_destruct.rvmat","a3\boat_f\Boat_Armed_01\data\Minigun.rvmat","A3\boat_f\Boat_Armed_01\data\Minigun_damage.rvmat","A3\boat_f\Boat_Armed_01\data\Minigun_destruct.rvmat","a3\boat_f\Boat_Armed_01\data\Minigun_Boat_Armed_01_add.rvmat","A3\boat_f\Boat_Armed_01\data\Minigun_Boat_Armed_01_add_damage.rvmat","A3\boat_f\Boat_Armed_01\data\Minigun_Boat_Armed_01_add_destruct.rvmat","a3\Data_F\Vehicles\Turret.rvmat","A3\Data_F\Vehicles\Turret_damage.rvmat","A3\Data_F\Vehicles\Turret_destruct.rvmat"};
		};

Hitpoints

Hitpoints represent weak points in structure of ships: turret servos, ammo storages, engine. They can also improve internal penetration handling.

Example from Boat_Armed_01_base_F

class HitPoints
		{
			class HitBody
			{
				armor = 0.7;
				material = 50;
				name = "karoserie";
				visual = "zbytek";
				passThrough = 1;
			};
			class HitEngine
			{
				armor = 0.12;
				material = -1;
				name = "Engine";
				visual = "";
				passThrough = 1;
			};
			class HitTurret
			{
				armor = 0.7;
				material = -1;
				name = "otochlaven";
				visual = "otochlaven";
				passThrough = 1;
			};
		};

Hitpoint categories

There are 3 common hitpoint categories in Arma 3's vehicles:

  • HitHull, handling internal penetration - when damaged over 0.9, vehicle will explode.
  • HitEngine, handling damage of engine

Turrets have their own class HitPoints, coontaining info about how easy it is to damage given turret:

  • HitTurret, horizontal rotation
  • HitGun, vertical rotation - this should handle any event that renders tank guns inoperable, f.e. hit to servos

New attributes

Hitpoints gained two important config attributes in Arma 3:

  • radius, defining size of “hitpoint sphere” around each vertice in Hit Points LOD assigned to given hitpoint’s selection
  • explosionShielding, multiplying damage inflicted by indirect damage. The smaller it is, the less damage hitpoint will receive.

Internal damage

Internal damage is handled by HitHull class. When KE round penetrates the armor plates, it passes the damage to HitHull hitpoints array as seen in example model. The hitpoint vertices are set up in such way that the nearest distance between them equals RADIUS attribute in HitHull class, and they cannot be activated by rounds that fail to penetrate armor.

During implementation of internal damage handling it is important to tweak following attributes:

  • armor
  • explosionShielding
  • radius

If the results of config tweaking are not satisfying, consider adding greater detail to Hit Points and Fire Geometry LODs.