Hidden SBC tags features - THDigi/SE-ModScript-Examples GitHub Wiki

Not all SBC tags are declared in vanilla files, this list has the ones I found/remembered.

NOTE: All numbers are float (can have decimal points) unless otherwise specified in the comment next to it.

NOTE: Boolean values should always be lower case, a False or True will throw XML errors.

Contents


Referencing assets from other mods

(Back to top)

Paths inside SBCs that lead to an asset can take advantage of ..\ to go back one folder into the workshop, from there you can go into anoher mod's folder and reference one of its models, icons, sounds, etc, this works because mods are stored there under their workshopId as their folder name.

An example: <Model>..\WorkshopId\Models\SomeThing.mwm</Model> where WorkshopId is the id (from the link) of the mod you're relying on.

This is very useful if you want to make small tweaks to a mod without having to reupload any of its assets, but instead adding it as a dependency.

To test this locally you will have to temporarily copy the other mod's folder to your %appdata%/SpaceEngineers/Mods/, without renaming it!

A more real example, if one were to change volume of my PaintGun item, it would have:

<Icon>Textures\UI\PaintGun.dds</Icon>
<Model>Models\PaintGun.mwm</Model>

that would look inside the new mod, but one can change those to:

<Icon>..\500818376\Textures\UI\PaintGun.dds</Icon>
<Model>..\500818376\Models\PaintGun.mwm</Model>

(see the id=500818376 in the mod link) So that they're still looking for them in the original mod.

This of course requires the PaintGun mod to be added as a dependency so it's automatically used whenever the item sbc mod is.

NOTE: this is for Steam workshop, I don't know if this works for mod.io ones, I've been told they're as .zip in %appdata%/SpaceEngineers/cache/ so it might work, experiment and tell me so I can update this notice.


Multiple Icons (stacked)

(Back to top)

You can stack multiple icons for the same block, item, etc. This should work on anything that has the <Icon> tag (which is all definitions, but not all of them actually use it). To do it, simply declare <Icon> multiple times, no wrapping tag or anything, example:

<Icon>Textures\Icons\SomeIcon.dds</Icon>
<Icon>Textures\Icons\SomeOverlayedIcon.dds</Icon>

Remove definition

(Back to top)

Mind that this might not always work or it can cause crashes because other things refer to the definition you've removed. It can work in some cases, like respawn ships.

Using it is simply adding Enabled="false" inside the opening tag of the definition.

Here's an example:

    <Ship Enabled="false">
      <Id>
        <TypeId>RespawnShipDefinition</TypeId>
        <SubtypeId>RespawnSpacePod</SubtypeId>
      </Id>
...

NOTE: do not strip the definition of other tags, they still have to be validly processed and loaded before they're getting removed =) I know, it's weird.


Random model for a droppable item

(Back to top)

Only works for items.
The game itself uses it for ores too (in combination with DebrisModels.sbc), although declaring these manually should override their behavior.

Usage example:

<Models>
    <Model>Models\SomeModel1.mwm</Model>
    <Model>Models\SomeModel2.mwm</Model>
    <Model>Models\SomeModelWhatever.mwm</Model>
</Models>

If this list is declared, <Model> tag gets ignored.


Undeclared tags on Radio Antenna

(Back to top)

and their defaults:

<MaxBroadcastRadius>50000</MaxBroadcastRadius>
<LightningRodRadiusLarge>10</LightningRodRadiusLarge>
<LightningRodRadiusSmall>2</LightningRodRadiusSmall>

The way LightningRod ones work is it simply chooses the one that matches the grid size, there's nothing fancy about it.


Undeclared tags on Decoy

(Back to top)

<LightningRodRadiusLarge>50</LightningRodRadiusLarge>
<LightningRodRadiusSmall>10</LightningRodRadiusSmall>

The way LightningRod ones work is it simply chooses the one that matches the grid size, there's nothing fancy about it.


Undeclared tags on ship welder & grinder

(Back to top)

<SensorOffset>0</SensorOffset> <!-- shifts center of welding/grinding sphere forwards/backwards; if model's detector_shiptool is scaled this will get affected by it (making it no longer in meters) -->

Undeclared tags on Ammo (Ammos.sbc)

(Back to top)

Straightforward, here's all the tags available to ammo.

Projectile ammo:

<ProjectileCount>1</ProjectileCount> <!-- integer value. amount of projectiles to spawn, each will be subject to gun's DeviateShotAngle allowing for shotguns -->
<ProjectileHealthDamage>0</ProjectileHealthDamage> <!-- damage to characters -->
<HeadShot>false</HeadShot>
<ProjectileHeadShotDamage>120</ProjectileHeadShotDamage> <!-- replaced damage if it hits a character's head, only used if HeadShot is true -->
<ProjectileMassDamage>0</ProjectileMassDamage> <!-- damage to everything else -->
<ProjectileExplosionDamage>0</ProjectileExplosionDamage>
<ProjectileExplosionRadius>0</ProjectileExplosionRadius> <!-- meters -->
<ProjectileHitImpulse>0</ProjectileHitImpulse> <!-- in newton-seconds; half to everythong except characters which get x50. just keen things -->
<ProjectileOnHitEffectName>Hit_BasicAmmoSmall</ProjectileOnHitEffectName> <!-- particle subtypeId -->
<ProjectileTrailColor x="1" y="1" z="1" /> <!-- X/Y/Z == R/G/B, can go past 1 to create glow/bloom -->
<ProjectileTrailMaterial></ProjectileTrailMaterial> <!-- transparent material subtypeId, if empty then uses ProjectileTrailLine -->
<ProjectileTrailProbability>1.0</ProjectileTrailProbability> <!-- 0.0 to 1.0 as chance percentage -->
<ProjectileTrailScale>0.1</ProjectileTrailScale> <!-- has a small random and scales with FOV a bit too, it does not have a unit, eyeball it -->

Missile ammo:

<MissileSkipAcceleration>false</MissileSkipAcceleration> <!-- if true, uses ammo's DesiredSpeed as the constant speed -->
<MissileAcceleration>0</MissileAcceleration> <!-- m/s/s, only works if MissileSkipAcceleration is false; max speed is DesiredSpeed, capped spherically -->
<MissileExplosionDamage>0</MissileExplosionDamage>
<MissileExplosionRadius>0</MissileExplosionRadius> <!-- meters -->
<MissileGravityEnabled>false</MissileGravityEnabled> <!-- whether missile is affected by natural gravity. artificial is always ignored. NOTE: gravity is retrieved only once on missile spawn. -->
<MissileHealthPool>0</MissileHealthPool> <!-- block health it can penetrate -->
<MissileInitialSpeed>0</MissileInitialSpeed> <!-- m/s -->
<MissileMass>0</MissileMass> <!-- in kg like everywhere else -->
<MissileModelName></MissileModelName> <!-- path to model .mwm, defaults null but should probably not be left as such -->
<MissileTrailEffect>Smoke_Missile</MissileTrailEffect> <!-- particle subtypeId -->

Undeclared tags on TargetLockingComponent (EntityComponents.sbc)

(Back to top)

This for some unknown reason has no tags declared in the SBC, but the definition actually has 4 tags that one can edit:

<LockingModifierSmallGrid>2</LockingModifierSmallGrid>
<LockingModifierLargeGrid>1</LockingModifierLargeGrid>
<LockingTimeMin>1</LockingTimeMin> <!-- seconds -->
<LockingTimeMax>10</LockingTimeMax>
<LockingModifierDistance>10</LockingModifierDistance>

The other component, TargetFocusComponent, does have both its tags mentioned in that file.

The way these are used, pseudocode:

DistanceRatio = DistanceBetweenShips / TargetFocusComponent.FocusSearchMaxDistance
SizeModifier = LockingModifierSmallGrid or LockingModifierSmallGrid depending on target grid size

TimeToLock = (DistanceRatio * LockingModifierDistance * SizeModifier) and limited between LockingTimeMin and LockingTimeMax, inclusive

Undeclared Ratio for reactor

(Back to top)

In reactors' <FuelInfo> tag you can also have a <Ratio> tag:

<FuelInfos>
    <FuelInfo>
        <Id>
            <TypeId>Ingot</TypeId>
            <SubtypeId>Uranium</SubtypeId>
        </Id>
        <Ratio>1</Ratio>
    </FuelInfo>
</FuelInfos>

There's also <FuelProductionToCapacityMultiplier> that is default 3600 if undeclared (which is not declared for reactor).

And while we're here... Reactor fuel formula:

MaxFuelPerSecond = ((MaxPowerOutput / FuelProductionToCapacityMultiplier * Fuel_Ratio) / Fuel_Mass)

Hydrogen engine fuel formula:

MaxFuelPerSecond = MaxPowerOutput / FuelProductionToCapacityMultiplier

Both of these scale with current power output percentage.

Also NOTE: even though <FuelInfos> supports more than one fuel, hydrogen engine only uses the first declared.


Thrusters can only use one resource

(Back to top)

For example, hydrogen thrusters only consume hydrogen, they do not (and cannot) consume electricity.

Here's the formula used by thrusters:

FuelPerSec = Thruster_MaxPowerConsumption / (Fuel_EnergyDensity * Thruster_Efficiency)

The EnergyDensity is in GasProperties.sbc for the chosen fuel.

For electric thrusters, it will just be the Min/MaxPowerConsumption tags in MW.


Inventory size? Railgun charge? EntityComponents.sbc!

(Back to top)

EntityComponents.sbc is just a declaration of components, the EntityContainers.sbc is what links entities (blocks, characters, etc) to entity components.

Some vanilla cargo containers have their inventory volume declared there aswell as railguns' charge and capacity.

For inventories the <Size x="0.4" y="1" z="1" /> tag is simply 3D volume, it will get the final volume from X * Y * Z which in this case is 0.4 m3.

And here's all the tags supported by MyObjectBuilder_InventoryComponentDefinition:

<Size x="1" y="1" z="1" /> <!-- nullable Vector3, defaults to null -->
<Volume>3.40282347e+38</Volume> <!-- default is float.MaxValue; if Size is declared then it will override this -->
<Mass>3.40282347e+38</Mass> <!-- default is float.MaxValue -->
<RemoveEntityOnEmpty>false</RemoveEntityOnEmpty> <!-- used by temporary inventories like dead character's backpack -->
<MultiplierEnabled>true</MultiplierEnabled> <!-- turning this off *should* prevent volume and mass from being affected by multiplier (ship or character, depending on which it's applied to) -->
<MaxItemCount>2147483647</MaxItemCount> <!-- default is int.MaxValue -->

<!-- this defaults to null which means allow all items. instead I'll just show all the possible options: -->
<InputConstraint Whitelist="true" Description="Tooltip here" Icon="Texture\SomeIcon.dds">
    <!-- example of all magazines regardless of subtypes -->
    <Entry Type="AmmoMagazine" />

    <!-- example of a specific type+subtype -->
    <Entry>
        <TypeId>Component</TypeId>
        <SubtypeId>SteelPlate</SubtypeId>
    </Entry>
</InputConstraint>

The railgun component (MyObjectBuilder_EntityCapacitorComponentDefinition) already shows both its tags in vanilla sbc.

Speaking of railguns, here's some handy formulas to calculate one of Capacity/RechargeDraw/Time by inputting the other 2:

Time = (Capacity * 60 * 60) / (RechargeDraw * 0.8)
Capacity = (RechargeDraw * 0.8) * (Time / 60 / 60)
RechargeDraw = ((Capacity * 60 * 60) / Time) * (1 / 0.8)

The 0.8 being the charge loss which is hardcoded.


Conveyor network support

(Back to top)

Only specific block types can connect to conveyor network, as of SE v201 those are:

Click to see list

AirVent
Assembler
CargoContainer
Cockpit
Collector
ContractBlock
Conveyor
ConveyorConnector
ConveyorSorter
CryoChamber
Drill
ExtendedPistonBase
HydrogenEngine
LargeGatlingTurret
LargeMissileTurret
MedicalRoom
MotorAdvancedRotor
MotorAdvancedStator
MotorStator
OxygenFarm
OxygenGenerator
OxygenTank
Parachute
PistonTop
Reactor
Refinery
SafeZoneBlock
ShipConnector
ShipGrinder
ShipWelder
SmallMissileLauncher
SmallMissileLauncherReload
StoreBlock
SurvivalKit
TargetDummyBlock
Thrust

Undeclared tags for Medical Room

(Back to top)

The self-explanatory ones along with their defaults:

<RespawnAllowed>true</RespawnAllowed>
<HealingAllowed>true</HealingAllowed>
<RefuelAllowed>true</RefuelAllowed>
<SuitChangeAllowed>true</SuitChangeAllowed>
<ForceSuitChangeOnRespawn>false</ForceSuitChangeOnRespawn>
<SpawnWithoutOxygenEnabled>true</SpawnWithoutOxygenEnabled>

You can also define what "suits" (characters) can be equipped using this block:

<CustomWardrobesEnabled>true</CustomWardrobesEnabled> <!-- this is default false, true enables the below list filter -->
<CustomWardRobeNames>
  <Name>SomeCharacterName</Name> <!-- from character's <Name> tag, not SubTypeId -->
  <Name>AndMore...</Name>
</CustomWardRobeNames>

Now for the mess that is this offset... first this is the tag and defaults:

<WardrobeCharacterOffset>
  <X>-1.35</X>
  <Y>-0.9</Y>
  <Z>1.7</Z>
</WardrobeCharacterOffset>

If detector_wardrobe exists in the model it will be used for the player position, it however needs to be 0.98m above the floor where the character's feet would be.
Otherwise without the dummy the <WardrobeCharacterOffset> is the position of the character but Z is flipped, it's right/up/forwards instead of right/up/back as everything else is in this engine.

Then it will calculate this continuously:
dist = Distance(PlayerFeetPosition, BlockCenterPosition) - WardrobeCharacterOffset.Length
Length of WardrobeCharacterOffset is basically distance from 0,0,0 that the vector represents.
If this dist gets higher than 0.5 for a second or so, it'll kick you off the wardrobe, pretty nasty.

Then the camera is placed relative to <WardrobeCharacterOffset> aswell, again with Z flipped, and they're adding -1.15, 0.7, 1.5 to each axis, then the final Z is multiplied by 70 / ClientFieldOfView.

Then the problem is with leaving the wardrobe, if <RespawnAllowed> is true it will use the same logic as respawning for placing the player, but if that is false it will do bad math and place you, from block center (character's feet are their position, so already we're starting head-first in the ceiling) it offsets towards block's forward by <Size> tag's highest number. So for a 1x1x1 largegrid, 1m, for a 5x2x3 smallgrid, 5m (the grid size does not matter, which is the issue with that math).

TL;DR, the math is all weird and wrong in places, what I suggest is:

  • Have a detector_wardrobe where the player's feet are supposed to be placed, then move it 0.98m upwards.
  • Set <WardrobeCharacterOffset> to the same coordinates as the detector_wardrobe, flip Z then add 0.45 to Y, this is so that the camera isn't in the floor (you can freely tweak Z within the regular value and the flipped value, as long as you don't go over those to make the Length larger causing it to kick you off the wardrobe).
  • If respawn is turned off, unfortunately there's no solution for the bad exit position.

Undeclared tags for Respawn Ships

(Back to top)

I'm just gonna post all of them, with their types and default values:

<Prefab></Prefab> <!-- prefab SubTypeId (never file name), defaults to null -->
<CooldownSeconds>0</CooldownSeconds> <!-- integer value -->
<SpawnWithDefaultItems>true</SpawnWithDefaultItems>
<UseForSpace>false</UseForSpace>
<MinimalAirDensity>0.7</MinimalAirDensity>
<UseForPlanetsWithAtmosphere>false</UseForPlanetsWithAtmosphere>
<UseForPlanetsWithoutAtmosphere>false</UseForPlanetsWithoutAtmosphere>
<PlanetDeployAltitude>500</PlanetDeployAltitude> <!-- nullable float, can be set to null like: <PlanetDeployAltitude xsi:nil="true" />  -->

<InitialLinearVelocity x="0" y="0" z="0" />
<InitialAngularVelocity x="0" y="0" z="0" />

<HelpTextLocalizationId></HelpTextLocalizationId> <!-- string value, defaults null -->
<SpawnNearProceduralAsteroids>true</SpawnNearProceduralAsteroids>

<PlanetTypes> <!-- only spawns on these planets, defaults to all planets if undeclared -->
  <PlanetType>SomePlanetSubtype</PlanetType>
  <PlanetType>SomeOtherSubtype</PlanetType>
  <PlanetType>etc...</PlanetType>
</PlanetTypes>

<SpawnPosition x="0" y="0" z="0"> <!-- defaults to null, which you can achieve by removing the tag or using: <SpawnPosition xsi:nil="true" />  -->

<SpawnPositionDispersionMin>0</SpawnPositionDispersionMin>
<SpawnPositionDispersionMax>10000</SpawnPositionDispersionMax>

Disabling all mountpoints

(Back to top)

You cannot disable all mountpoints like keen does with an empty list, I've no idea why but they have a special check for it, if it's a modded one and empty tags, it will auto-generate it as if it's not declared at all.

To work around this you can declare a disabled mountpoint:

<MountPoints>
  <MountPoint Side="Back" StartX="0" StartY="0" EndX="0" EndY="0" Enabled="false" />
</MountPoints>

Which brings us to another tip, disabling mountpoints like above with Enabled="False" allows you to use that mountpoint as a purely airtight-contributing surface, so you can make an entire side that is airtight without it being mountable too.


<TieredUpdateTimes> explained

(Back to top)

You might've seen these tags on some blocks:

<TieredUpdateTimes>
    <unsignedInt>60</unsignedInt>
    <unsignedInt>120</unsignedInt>
    <unsignedInt>240</unsignedInt>
</TieredUpdateTimes>

What it affects is how frequent the block updates server-side depending on player-nearby-ness (in case server is also player) and if grid is streamed to any MP client. This of course impacts performance so if you're uncertain then don't change them.

You also don't need to declare them, they have defaults per block type.

The <unsignedInt> tags in order are the tiers:

  1. Normal - local player is nearby or grid streamed to at least one player.
  2. Tier1 - local player not nearby and grid is not streamed to anyone.
  3. Tier2 - same as Tier1 but 10 minutes passed since that turned to Tier1.

Some block types will also care if any other grid is within 3km of its own grid, a few cases I found (SE v201):

  • Turrets: if a grid is nearby they use Normal instead
  • Thrusts: if they're on Tier2 and a grid is nearby, they'll use Tier1 instead
  • Connector: if a grid is nearby they use Normal instead

The values are ticks between updates (game runs at 60 ticks per game second), and 0 can be used to completely pause the block's update, only if it supports this system of course.

So for the above snippet, the refinery updates once per second if any player is within sync distance.

In SE v201 the following block types use this system:

  • 3 values: Reactor, Thrust, Refinery, Assembler, SurvivalKit, GasGenerator, Connector
  • 2 values: All Turrets
  • 1 value: Searchlight

Different mountpoints on build stages

(Back to top)

This feature is from Medieval Engineers where they prevent the top part of a block from being mountable until the block is more constructed or even fully built.

It seems to work in SE but as with all features not directly used by Keen in SE, they tend to be buggy(er) or could break in the future.

To use it you have to first open up the Model tag from <BuildProgressModels>, as in all definitions it's self-closing.

That is done by changing /> to > and then add a regular closing tag:

<Model BuildPercentUpperBound="0.33" File="Models\Cubes\Large\Armor\SquarePlateConstruction_1.mwm" />

to

<Model BuildPercentUpperBound="0.33" File="Models\Cubes\Large\Armor\SquarePlateConstruction_1.mwm">
</Model>

Very important to change the /> to > !

Then inside that model tag you can add <MountPointOverrides> which has the same exact layout as <MountPoints>.

However it works quite differently:

  • it starts off with a clone of the regular mountpoints.
  • declaring a Side in <MountPointOverrides> will first remove all mountpoints for that side then it adds yours.
  • any following build progresss models that have <MountPointOverrides> will inherit the previous one's changes.

Here's what I played around with, I added comments of what the result is:

<!-- for reference, the regular mountpoints -->
<MountPoints>
    <MountPoint Side="Back" StartX="0" StartY="0" EndX="2" EndY="4" />
    <MountPoint Side="Bottom" StartX="0" StartY="1" EndX="2" EndY="2" Default="true" />
    <MountPoint Side="Top" StartX="0" StartY="0" EndX="2" EndY="1" />
    <MountPoint Side="Left" StartX="1" StartY="0" EndX="2" EndY="4" />
    <MountPoint Side="Right" StartX="0" StartY="0" EndX="1" EndY="4" />
</MountPoints>

<BuildProgressModels>
    <Model BuildPercentUpperBound="0.16" File="Models\Cubes\Large\RefineryConstruction_1.mwm">
        <MountPointOverrides>
            <MountPoint Side="Back" Enabled="false" />
            <MountPoint Side="Top" Enabled="false" />
            <MountPoint Side="Left" Enabled="false" />
            <MountPoint Side="Right" Enabled="false" />
            <!-- results in only bottom side remaining -->
        </MountPointOverrides>
    </Model>
    
    <Model BuildPercentUpperBound="0.33" File="Models\Cubes\Large\RefineryConstruction_2.mwm">
        <MountPointOverrides>
            <!-- results in identical mountpoints as previous build stage -->
        </MountPointOverrides>
    </Model>
    
    <Model BuildPercentUpperBound="0.50" File="Models\Cubes\Large\RefineryConstruction_3.mwm">
        <MountPointOverrides>
            <MountPoint Side="Back" StartX="0" StartY="0" EndX="2" EndY="4" />
            <!-- results in bottom + back side -->
        </MountPointOverrides>
    </Model>
    
    <Model BuildPercentUpperBound="0.83" File="Models\Cubes\Large\RefineryConstruction_4.mwm">
        <MountPointOverrides>
            <!-- results in identical mountpoints as previous build stage -->
        </MountPointOverrides>
    </Model>
    
    <!-- this one has no override so it just uses the regular full mountpoints -->
    
    <Model BuildPercentUpperBound="1.00" File="Models\Cubes\Large\RefineryConstruction_5.mwm" />
</BuildProgressModels>

And here's the mountpoints in visual form, using my BuildInfo mod to show construction stages (alt R) and mountpoint overlays (ctrl +):

⚠️ **GitHub.com Fallback** ⚠️