Space Engineers

Space Engineers

27 ratings
WeaponCore Turret tips for modders WIP
By AutoMcDonough and 1 collaborators
*WIP* I started updating this since a lot is outdated. So currently it's half new and half old. Enjoy.

This guide focuses on getting the model structured properly in blender for making a turret using WeaponCore mod for Space Engineers.

WeaponCore can be found here:
https://steamcommunity.com/sharedfiles/filedetails/?id=1918681825&tscn=1581795378
   
Award
Favorite
Favorited
Unfavorite
Gatling Turret: Model Setup
First thing is first: This guide will assume existing fundamental knowledge of modding blocks into SE. It is my intention to run down the process of creating weapons and configuring them for WeaponCore, but I will not be going into detail about how to use Blender itself, SEUT, or how the game sbc files and directory structures work. If this is your first mod I would recommend to stop here and familiarize yourself with the process by creating a decorative block. Weapons are not easy.

Out first example is a gatling turret. This is a fairly basic baseline weapon to make, and includes animated barrels.
You'll want to set up a scene for each part. Base will be the main part, then we have subparts for the azimuth, elevation, and barrels.
On the base, place the subpart empty for the azimuth part. This will face the -Y direction.

You might have noticed that the subpart naming does not match the same convention as Keen's turrets. This blocktype will be a conveyor sorter, so the subparts can be named anything. A sorter type has many performance advantages, and a few other perks such as angled turrets. The only downside is lack of direct control. If sticking with gatling or missile turret type then use the keen names.
Some other things to consider when structuring your weapon:
-The Keen red/green emissive material only works on the base. Putting this on subpart is possible but will require some extra work on animation config (later).
-The control panel interactions don't move. Best to artistically work this into the base, or end up highlighting the entire azimuth subpart.
-The collisions don't move, and subpart collisions don't work. Often this means a turret with a large barrel sticking out will just not have collision mesh for the barrel.
-You can add additional subparts for animation purposes
-You can put azimuth part on a subpart. So many options!
-Subparts have their own LOD's, but aren't part of the build stages so copy those meshes into main scene there.

Example of angled turret.. just turn the subpart.

Subparts: Azimuth
For all subparts, you want the orientation to be +Y is forwards.
Remember that the origin of this part will be placed on the empty that called it, and we will place our subpart empty for elevation where the axis of rotation should be.
-For some weapons (such as my lasers which appear fixed but have 3º of gimbal) there is no visual need for azimuth and elevation subparts. Unfortunately it is still required structurally, so you will end up with a scene containing nothing more than another subpart empty and 1 little tiny poly just so it exports.
-Again, you may add more subparts to this.

Elevation:
This typically is the business end of the weapon. Since the gatling has animated barrels we will have more subparts, but the muzzles will be placed here. It would be the same for a cannon with a barrel that moves for recoil. Both barrel subpart empties are pointing to the same barrel mesh, since the muzzles are in this elevation scene with unique names, nothing about the barrels needs to be unique.
I have 2 muzzle empties here, shots will come from those. Again, facing +Y.
There is also an empty for the scope. (It is set to cone instead of axis here but same +Y forwards).
The scope is used to detect clear line of sight to fire. Make sure it is far enough out to clear any geometry and collisions.
I also have empties to place shell ejection particles. They aren't used yet but they don't hurt anything.

Barrels:

This subpart is purely decorative. In animation setup we will make it spin during firing.
There is also an emissive material which we will animate for heating effect.
This can be any emissive type material but the name must be "Heating". What I've done is the same as MexPex and set it up as a decal material that has a gradient.

That's about it. Once you got it all looking pretty go ahead and export it, set up your sbc, etc. I'm skipping ahead to in-game for this shot but this is how you check to make sure everything is rotated properly.
Hit Alt-F11 and turn on the model dummy info. Each model empty is shown with 3 colored lines to show orientation. This is usually difficult to read because they all overlap. The BLUE one needs to be facing forwards for all non-decorative subparts, muzzles, and scope. Decorative ones and stuff like terminals and conveyors not important which way they face.
SBC Setup
Cubeblocks SBC File:
Since this turret is using sorter for blocktype, start the turret entry with
<Definition xsi:type="MyObjectBuilder_ConveyorSorterDefinition">
and use <TypeId>ConveyorSorter</TypeId>

If you choose to use LargeMissileTurret then be sure to include the the following tag:
<AiEnabled>false</AiEnabled>

The rest of the turret settings don't matter, we will set those up in the WeaponCore config files.

Obviously set all the normal things here, mountpoints, mirroring, components cost, icon, grouping, etc. Most non-weapon related sbc settings related to the game are still valid and work normally here.

Ammos and weapon sbcs: honestly I don't remember how I got thru it and I hope Ash fills this in.
Configuring Weapon.cs Part 1
First, grab the latest weaponthread config from github:
https://github.com/sstixrud/CoreParts/

Unzip to your mod\Data\Scripts\CoreParts

The files you see here are examples to get started. What you need for your weapon are the following:
1: MasterConfig.cs
2: X_Part.cs
3: X_Ammo.cs
4: X_Animation.cs

(where X is the name of your weapon obviously)

MasterConfig.cs
namespace Scripts { partial class Parts { internal Parts() { // naming convention: WeaponDefinition Name // // Enable your definitions using the follow syntax: // PartDefinitions(Your1stDefinition, Your2ndDefinition, Your3rdDefinition); // PartDefinitions includes both weapons and phantoms PartDefinitions(MA_Tiger, MA_Tiger_30_sm); //ArmorDefinitions(Armor1, Armor2); //SupportDefinitions(ArmorEnhancer1A); //UpgradeDefinitions(Upgrade75a, Upgrade75b); } } }

There is only one line to maintain here, list each weapon you config. I have 2 listed here. This goes by each weapon entry you config, it does not matter if each is in one big file or if each has it's own cs file.

Weapon.cs
The name of these files you can (and should) change to stay organized. For example I just call this one Tiger.cs
Now I will step thru it in small portions with explanation.
using static Scripts.Structure; using static Scripts.Structure.WeaponDefinition; using static Scripts.Structure.WeaponDefinition.ModelAssignmentsDef; using static Scripts.Structure.WeaponDefinition.HardPointDef; using static Scripts.Structure.WeaponDefinition.HardPointDef.Prediction; using static Scripts.Structure.WeaponDefinition.TargetingDef.BlockTypes; using static Scripts.Structure.WeaponDefinition.TargetingDef.Threat; using static Scripts.Structure.WeaponDefinition.HardPointDef.HardwareDef; using static Scripts.Structure.WeaponDefinition.HardPointDef.HardwareDef.HardwareType; namespace Scripts { partial class Parts { // Don't edit above this line WeaponDefinition MA_Tiger => new WeaponDefinition
MA_Tiger is the WC name for this weapon, what you put here must match the entry in MasterConfig.cs.

Assignments = new ModelAssignmentsDef { MountPoints = new[] { new MountPointDef { SubtypeId = "MA_Tiger", SpinPartId = "None", // For weapons with a spinning barrel such as Gatling Guns. MuzzlePartId = "barrel", // The subpart where your muzzle empties are located. AzimuthPartId = "az", ElevationPartId = "gimbal", DurabilityMod = 0.25f, // GeneralDamageMultiplier, 0.25f = 25% damage taken. IconName = "TestIcon.dds" // Overlay for block inventory slots, like reactors, refineries, etc. }, new MountPointDef { SubtypeId = "MA_Tiger_sm", SpinPartId = "None", MuzzlePartId = "barrel", AzimuthPartId = "az", ElevationPartId = "gimbal", DurabilityMod = 0.05f, IconName = "TestIcon.dds", }, }, Muzzles = new[] { "muzzle_01", "muzzle_02", "muzzle_03", "muzzle_04", }, Ejector = "", // Optional; empty from which to eject "shells" if specified. Scope = "camera", // Where line of sight checks are performed from. Must be clear of block collision. },
SubtypeId is the name you picked for this weapon in the SE sbc files.
The rest of the id's are the name of the subparts, as defined by the name of the model's subpart empty. for example, in the base model there is an empty named "subpart_az" which calls the az subpart. the "subpart_" prefix is not included in the name here.

I defined more than one weapon here, there is a small grid variant "MA_Tiger_sm". This will only work if all of the parameters and subpart names are identical.

The names of these parts can be anything you like, so long as it matches the entries here.
AzimuthPartId and ElevationPartId must be different for turrets, if it is a fixed weapon put "None".

fixed weapon example:
new MountPointDef { SubtypeId = "MA_Fixed_000", SpinPartId = "None", MuzzlePartId = "None", AzimuthPartId = "None", ElevationPartId = "None", DurabilityMod = 0.25f, IconName = "TestIcon.dds" },

Moving on to targeting.
Targeting = new TargetingDef { Threats = new[] { Meteors, Grids, Characters, // Types of threat to engage: Grids, Projectiles, Characters, Meteors, Neutrals }, SubSystems = new[] { Any, // Subsystem targeting priority: Offense, Utility, Power, Production, Thrust, Jumping, Steering, Any }, ClosestFirst = true, // Tries to pick closest targets first (blocks on grids, projectiles, etc...). IgnoreDumbProjectiles = false, // Don't fire at non-smart projectiles. LockedSmartOnly = false, // Only fire at smart projectiles that are locked on to parent grid. MinimumDiameter = 5, // Minimum radius of threat to engage. MaximumDiameter = 0, // Maximum radius of threat to engage; 0 = unlimited. MaxTargetDistance = 2500, // Maximum distance at which targets will be automatically shot at; 0 = unlimited. MinTargetDistance = 0, // Minimum distance at which targets will be automatically shot at. TopTargets = 0, // Maximum number of targets to randomize between; 0 = unlimited. TopBlocks = 0, // Maximum number of blocks to randomize between; 0 = unlimited. StopTrackingSpeed = 1000, // Do not track threats traveling faster than this speed; 0 = unlimited. },

This defines what the turret will shoot at. Most weapons just leave the full list, but each weapon has it's role so here is an opportunity to fine tune it. The PDT anti-missile turret lists only projectiles, so it will not target grids. Larger battle cannons can be made to ignore projectiles and fast moving targets.
Subsystems sets priority of subsystems (the list order matters) so here you can set priority if it targets power or offense first.
ClosestFirst should usually be true, when false it will pick random targets instead of the nearest threat. An example where I use ClosestFirst=false is PDT so that a group of them will pick separate random missiles to hit instead of all shooting the same one.
Min and Max diameter will filter out targets based on size. So for example instead of ignoring small grids with big cannon, can ignore anything less than 20m so that very large small-grid ships still get targeted but small fighters don't. Or perhaps a small anti-personell turret can ignore very large things.

Hardpoint def.. to be continued.
Configuring Weapon.cs Part 2
Hardpoint def.
HardPoint = new HardPointDef { PartName = "Tiger 150mm", // Name of the weapon in terminal, should be unique for each weapon definition that shares a SubtypeId (i.e. multiweapons). DeviateShotAngle = 0.1f, // Projectile inaccuracy in degrees. AimingTolerance = 0.5f, // How many degrees off target a turret can fire at. 0 - 180 firing angle. AimLeadingPrediction = Basic, // Level of turret aim prediction; Off, Basic, Accurate, Advanced DelayCeaseFire = 0, // Measured in game ticks (6 = 100ms, 60 = 1 second, etc..). Length of time the weapon continues firing after trigger is released. AddToleranceToTracking = false, // Allows turret to only track to the edge of the AimingTolerance cone instead of dead centre. CanShootSubmerged = false, // Whether the weapon can be fired underwater when using WaterMod.
WeaponName like it says, this is what players will see in game.
DeviateShotAngle is bullet spread, in degrees. I used 2º for the gatlings and they spray quite a bit.
AimingTolerance the barrel must be aligned within this tolerance to fire. For most weapons you will want 0.1f or less or the shot will miss at range, but a larger window will make the gun less finicky about getting shots off.
AimLeadingPrediction controls how well the turret will try to lead a moving target. For beam weapons just turn it off.
DelayCeaseFire is a delay from the time the AI says to stop firing to the time is actually stops. This is used mainly in beam weapons so that it seems to rake from target to target instead of stopping and starting again.
Ui = new UiDef { RateOfFire = false, // Enables terminal slider for changing rate of fire. DamageModifier = false, // Enables terminal slider for changing damage per shot. ToggleGuidance = false, // Enables terminal option to disable smart projectile guidance. EnableOverload = false, // Enables terminal option to turn on Overload; this allows energy weapons to double damage per shot, at the cost of quadrupled power draw and heat gain, and 2% self damage on overheat. },
These control what options you see in the turret's control panel. Set them to make sense for the type of weapon you are making. IE Ammo based weapons can't overload or adjust damage but energy ones can.
Ai = new AiDef { TrackTargets = true, // Whether this weapon tracks its own targets, or (for multiweapons) relies on the weapon with PrimaryTracking enabled for target designation. TurretAttached = true, // Whether this weapon is a turret and should have the UI and API options for such. TurretController = true, // Whether this weapon can physically control the turret's movement. PrimaryTracking = true, // For multiweapons: whether this weapon should designate targets for other weapons on the platform without their own tracking. LockOnFocus = false, // Whether this weapon should automatically fire at a target that has been locked onto via HUD. SuppressFire = false, // If enabled, weapon can only be fired manually. OverrideLeads = false, // Disable target leading on fixed weapons, or allow it for turrets. },
For a fixed weapon that is to be manually fired, set all of these to false.
LockOnFocus is for weapons which fire smart seeking ammo.

HardWare = new HardwareDef { RotateRate = 0.1f, // Max traversal speed of azimuth subpart in radians per tick (0.1 is approximately 360 degrees per second). ElevateRate = 0.1f, // Max traversal speed of elevation subpart in radians per tick. MinAzimuth = -3, MaxAzimuth = 3, MinElevation = -3, MaxElevation = 5, HomeAzimuth = 0, // Default resting rotation angle HomeElevation = 0, // Default resting elevation InventorySize = 1f, // Inventory capacity in kL. IdlePower = 0.1f, // Power draw in MW while not charging, or for non-energy weapons. Defaults to 0.001. FixedOffset = false, // Deprecated. Offset = Vector(x: 0, y: 0, z: 0), // Offsets the aiming/firing line of the weapon, in metres. Type = BlockWeapon, // What type of weapon this is; BlockWeapon, HandWeapon, Phantom CriticalReaction = new CriticalDef { Enable = false, // Enables Warhead behaviour. DefaultArmedTimer = 120, // Sets default countdown duration. PreArmed = false, // Whether the warhead is armed by default when placed. Best left as false. TerminalControls = true, // Whether the warhead should have terminal controls for arming and detonation. AmmoRound = "40m", // Optional. If specified, the warhead will always use this ammo on detonation rather than the currently selected ammo. }, }, Other = new OtherDef { ConstructPartCap = 0, // Maximum number of blocks with this weapon on a grid; 0 = unlimited. RotateBarrelAxis = 0, // For spinning barrels, which axis to spin the barrel around; 0 = none. EnergyPriority = 0, // Deprecated. MuzzleCheck = false, // Whether the weapon should check LOS from each individual muzzle in addition to the scope. Debug = false, // Force enables debug mode. RestrictionRadius = 0, // Prevents other blocks of this type from being placed within this distance of the centre of the block. CheckInflatedBox = false, // If true, the above distance check is performed from the edge of the block instead of the centre. CheckForAnyWeapon = false, // If true, the check will fail if ANY weapon is present, not just weapons of the same subtype. },
Hardware turn rates and angles are what they seem. For the Tiger I will turn these down to 3º.
Offset is to correct aiming to muzzle geometry error if you got extra creative with the shape of your weapon.
GridWeaponCap will limit how many of this weapon a player can place per grid.
MuzzleCheck will use raycast from the muzzles to target to verify clean shot, instead of checking from the scope. Mostly enable this if you have multiple widely space muzzles, where checking from the middle might not detect an obstruction. This can prevent firing if player tries to shroud the turret behind armor shapes.
Debug = true will give the colored debug lines.
Configuring Weapon.cs Part 3
Loading = new LoadingDef { RateOfFire = 720, // Set this to 3600 for beam weapons. BarrelsPerShot = 1, // How many muzzles will fire a projectile per fire event. TrajectilesPerBarrel = 1, // Number of projectiles per muzzle per fire event. SkipBarrels = 0, // Number of muzzles to skip after each fire event. ReloadTime = 660, // Measured in game ticks (6 = 100ms, 60 = 1 seconds, etc..). MagsToLoad = 1, // Number of physical magazines to consume on reload. DelayUntilFire = 0, // How long the weapon waits before shooting after being told to fire. Measured in game ticks (6 = 100ms, 60 = 1 seconds, etc..). HeatPerShot = 10, // Heat generated per shot. MaxHeat = 500, // Max heat before weapon enters cooldown (70% of max heat). Cooldown = .6f, // Percentage of max heat to be under to start firing again after overheat; accepts 0 - 0.95 HeatSinkRate = 3, // Amount of heat lost per second. DegradeRof = true, // Progressively lower rate of fire when over 80% heat threshold (80% of max heat). ShotsInBurst = 4, // Use this if you don't want the weapon to fire an entire physical magazine before stopping to reload. Should not be more than your magazine capacity. DelayAfterBurst = 30, // How long to spend "reloading" after each burst. Measured in game ticks (6 = 100ms, 60 = 1 seconds, etc..). FireFullBurst = true, // Whether the weapon should fire the full burst, even if the target is lost or player stops firing prematurely. GiveUpAfterBurst = false, // Whether the weapon should drop its current target and reacquire a new target after finishing its burst. BarrelSpinRate = 0, // Visual only, 0 disables and uses RateOfFire. DeterministicSpin = false, // Spin barrel position will always be relative to initial / starting positions (spin will not be as smooth). SpinFree = true, // Spin barrel while not firing. StayCharged = false, // Will start recharging whenever power cap is not full. },
Most of this should be obvious.
For beam weapons, use ROF of 3600.
GiveUpAfterBurst = true is a targeting tweak to make the weapon try to regularly reaquire target even if it is not destroyed. This originally was to try to make continuous laser rake over the ship.

Audio = new HardPointAudioDef { PreFiringSound = "", // Audio for warmup effect. FiringSound = "MA_Tiger_150shot", // Audio for firing. FiringSoundPerShot = true, // Whether to replay the sound for each shot, or just loop over the entire track while firing. ReloadSound = "MA_Tiger_reload", NoAmmoSound = "", HardPointRotationSound = "", // Audio played when turret is moving. BarrelRotationSound = "WepShipGatlingRotation", FireSoundEndDelay = 120, // How long the firing audio should keep playing after firing stops. Measured in game ticks(6 = 100ms, 60 = 1 seconds, etc..). },
Audio defs. These sound names, such as "MA_Tiger_reload" are defined in your mod's audio.sbc.

Graphics = new HardPointParticleDef { Effect1 = new ParticleDef { Name = "", // SubtypeId of muzzle particle effect. Color = Color(red: 0, green: 0, blue: 0, alpha: 1), // Deprecated, set color in particle sbc. Offset = Vector(x: 0, y: -1, z: 0), // Offsets the effect from the muzzle empty. Extras = new ParticleOptionDef { Loop = false, // Deprecated, set this in particle sbc. Restart = false, // Whether to end the previous effect early and spawn a new one. MaxDistance = 1500, // Max distance at which this effect should be visible. NOTE: This will use whichever MaxDistance value is higher across Effect1 and Effect2! MaxDuration = 5, // How many ticks the effect should be ended after, if it's still running. Scale = 1f, // Scale of effect. }, }, Effect2 = new ParticleDef { Name = "MA_Gatling_Flash", Color = Color(red: 1, green: 1, blue: 1, alpha: 0.5f), Offset = Vector(x: 0, y: 0, z: 0), Extras = new ParticleOptionDef { Restart = false, MaxDistance = 1500, MaxDuration = 6, Scale = 7f, }, }, },
Particles on shoot, particles are defined in particles sbc file. Even if using SE particle, you should still copy it over to your own local file (with unique name and ID of course).

Ammos = new[] { MA_150mm, // Must list all primary, shrapnel, and pattern ammos. },
What ammo it uses. This is set up in ammo.cs which we will go over in next section.
You may define multiple ammo types for a weapon.

Animations = MA_Tiger_Animation,
Animation defined in animation.cs, it will be covered in a later section.

You may add multiple WeaponDefinition entries to this file.
Configuring Ammo.cs Part 1
*There may be differences and updates to this as WC gets updated.
namespace Scripts { // Don't edit above this line partial class Parts { private AmmoDef MA_150mm => new AmmoDef
MA_150mm here is what WC will recognize as the ammo def a weapon can use.

AmmoMagazine = "MA_150mm", // SubtypeId of physical ammo magazine. Use "Energy" for weapons without physical ammo. AmmoRound = "150mm HE", // Name of ammo in terminal, should be different for each ammo type used by the same weapon. HybridRound = false, // Use both a physical ammo magazine and energy per shot. EnergyCost = 0.1f, // Scaler for energy per shot (EnergyCost * BaseDamage * (RateOfFire / 3600) * BarrelsPerShot * TrajectilesPerBarrel). Uses EffectStrength instead of BaseDamage if EWAR. BaseDamage = 3000f, // Direct damage; one steel plate is worth 100. Mass = 40f, // In kilograms; how much force the impact will apply to the target. Health = 0, // How much damage the projectile can take from other projectiles (base of 1 per hit) before dying; 0 disables this and makes the projectile untargetable. BackKickForce = 300f, // Recoil. DecayPerShot = 0f, // Damage to the firing weapon itself. HardPointUsable = true, // Whether this is a primary ammo type fired directly by the turret. Set to false if this is a shrapnel ammoType and you don't want the turret to be able to select it directly. EnergyMagazineSize = 0, // For energy weapons, how many shots to fire before reloading. IgnoreWater = false, // Whether the projectile should be able to penetrate water
AmmoMagazine as defined in your sbc files.
You still need to set up sbc files for weapons, ammo, ammo, blueprints, ammo magazines, and blueprintclasses so SE can handle your physical ammo item.
Large or slow projectiles which can be shot at such as drones or missiles should use a health value.

ObjectsHit = new ObjectsHitDef { MaxObjectsHit = 0, // Limits the number of entities (grids, players, projectiles) the projectile can penetrate; 0 = unlimited. CountBlocks = false, // Counts individual blocks, not just entities hit. },
This can be a way of limiting how much penetration a round does.
Fragment = new FragmentDef // Formerly known as Shrapnel. Spawns specified ammo fragments on projectile death (via hit or detonation). { AmmoRound = "", // AmmoRound field of the ammo to spawn. Fragments = 100, // Number of projectiles to spawn. Degrees = 15, // Cone in which to randomise direction of spawned projectiles. Reverse = false, // Spawn projectiles backward instead of forward. RandomizeDir = false, // Randomize between forward and backward directions. },
Fragments, aka shrapnel are another type of ammo which is spawned when this projectile is done. Define it with another ammo entry and put it's AmmoRound name in there. Probably should not make recursive shrapnel.

Pattern = new PatternDef { Patterns = new[] { // If enabled, set of multiple ammos to fire in order instead of the main ammo. "", }, Enable = false, TriggerChance = 1f, Random = false, RandomMin = 1, RandomMax = 1, SkipParent = false, PatternSteps = 1, // Number of Ammos activated per round, will progress in order and loop. Ignored if Random = true. },
Randomly fire different ammo. fun!

DamageScales: lets you modify how much damage to apply to characters, grids, shields, armor, and custom block types. Leave these as -1 if you don't want to enable them.

AreaEffect: Where to configure explosion effects and other area based effects such as EMP.

Beams = new BeamDef { Enable = false, // Enable beam behaviour. VirtualBeams = false, // Only one damaging beam, but with the effectiveness of the visual beams combined (better performance). ConvergeBeams = false, // When using virtual beams, converge the visual beams to the location of the real beam. RotateRealBeam = false, // The real beam is rotated between all visual beams, instead of centered between them. OneParticle = false, // Only spawn one particle hit per beam weapon. },
enable beams if this is a laser/beam weapon. VirtualBeams must be true to use ConvergeBeams or RotateRealBeam. It is to improve performance in situation where you have several laser barrels shooting simultaneously.

Configuring Ammo.cs Part 2
Trajectory = new TrajectoryDef { Guidance = None, // None, Remote, TravelTo, Smart, DetectTravelTo, DetectSmart, DetectFixed TargetLossDegree = 80f, TargetLossTime = 0, // 0 is disabled, Measured in game ticks (6 = 100ms, 60 = 1 seconds, etc..). MaxLifeTime = 240, // 0 is disabled, Measured in game ticks (6 = 100ms, 60 = 1 seconds, etc..). AccelPerSec = 0f, DesiredSpeed = 650, // voxel phasing if you go above 5100 MaxTrajectory = 2800f, FieldTime = 0, // 0 is disabled, a value causes the projectile to come to rest, spawn a field and remain for a time (Measured in game ticks, 60 = 1 second) GravityMultiplier = 0.7f, // Gravity multiplier, influences the trajectory of the projectile, value greater than 0 to enable. SpeedVariance = Random(start: 0, end: 0), // subtracts value from DesiredSpeed RangeVariance = Random(start: 0, end: 0), // subtracts value from MaxTrajectory MaxTrajectoryTime = 0, // How long the weapon must fire before it reaches MaxTrajectory.
Guidance, TargetLossDegree, and TargetLossTime are for guided projectiles such as homing missiles.
MaxLifeTime is how long the projectile lives for. Useful for mines and other things.
MaxTrajectory is the projectile's maximum range.

Smarts: Knobs to tweak for guided projectile.
Mines: If the ammo is mines.

AmmoGraphics = new GraphicDef { ModelName = "", VisualProbability = 1f, ShieldHitDraw = true,
Specifying a model here will use it for the projectile (such as a missile).

Particles: Can specify particles for the projectile appearance and the hit. Particle names come from sbc file.

Lines = new LineDef { ColorVariance = Random(start: 5f, end: 10f), // multiply the color by random values within range. WidthVariance = Random(start: 0f, end: 0.045f), // adds random value to default width (negatives shrinks width) Tracer = new TracerBaseDef { Enable = true, Length = 0.05f, Width = 0.15f, Color = Color(red: 3f, green: 3f, blue: 3f, alpha: 1f), VisualFadeStart = 0, // Number of ticks the weapon has been firing before projectiles begin to fade their color VisualFadeEnd = 0, // How many ticks after fade began before it will be invisible. Textures = new[] {// WeaponLaser, ProjectileTrailLine, WarpBubble, etc.. "ProjectileTrailLine", }, TextureMode = Normal, // Normal, Cycle, Chaos, Wave
This is the most common method for drawing bullets is to use small lines. This is also where to define what a laser beam looks like.
The color values are 0 to 1 and anything beyond that is for intensity. Low values are best, above 10 you will start getting a LOT of bloom effect. alpha you can also adjust to control intensity and transparency.
Trail = new TrailDef { Enable = true, Textures = new[] { "WeaponLaser", }, TextureMode = Normal, DecayTime = 15, Color = Color(red: 3, green: 3, blue: 1, alpha: .5f), Back = false, CustomWidth = 0, UseWidthVariance = false, UseColorFade = true, },
Trail is a fade effect for the projectile. Do not use this for high ROF beam weapon, it looks super trippy and will lag people.

AmmoAudio = new AmmoAudioDef { TravelSound = "", HitSound = "ArcImpMetalMetalCat0", ShieldHitSound = "", PlayerHitSound = "", VoxelHitSound = "", FloatingHitSound = "", HitPlayChance = 0.1f, HitPlayShield = true, },
Sound effects, as defined in audio sbc file.

This file may contain multiple AmmoDefs
Animation.cs
This file is where you would set up any custom part movement or emissives animations.

private AnimationDef MA_Tiger_Animation => new AnimationDef
This is the name which your weapon will reference.

HeatingEmissiveParts = new[] { "Barrel", },
Specify the subpart(s) which contain the "heating" material you want animated with overheating effect. If you want more control over the colors, you may define your own emissive section, this one is preconfigured for typical barrel heating.

Emissive: define any custom animation emissives you are using. For example, this is used on the Gladius laser for the internal beams that light up when it fires:
Emissive( EmissiveName: "LaserEmissive", Colors: new [] { Color(red: 3f, green: .25f, blue: 0.005f, alpha: 1f),//will transitions from one color to the next if more than one }, IntensityFrom:.2f, //starting intensity, can be 0.0-1.0 or 1.0-0.0, setting both from and to, to the same value will stay at that value IntensityTo:.3f, CycleEmissiveParts: false,//whether to cycle from one part to the next, while also following the Intensity Range, or set all parts at the same time to the same value LeavePreviousOn: false,//true will leave last part at the last setting until end of animation, used with cycleEmissiveParts EmissivePartNames: new [] { "Emissive_Beams" }),
"Emissive_Beams" is the name of the material on the subpart, "LaserEmissive" is the name to refer to this emissive entry as.




WeaponAnimationSets = new[] { new PartAnimationSetDef() { SubpartId = Names("barrel"), BarrelId = "muzzle_01", //only used for firing, use "Any" for all muzzles StartupFireDelay = 0, AnimationDelays = Delays(firingDelay : 0, reloadingDelay: 0, overheatedDelay: 0, trackingDelay: 0, lockedDelay: 0, onDelay: 0, offDelay: 0, burstReloadDelay: 0, outOfAmmoDelay: 0, preFireDelay: 0, stopFiringDelay: 0, stopTrackingDelay:0, initDelay:0),//Delay before animation starts Reverse = Events(), Loop = Events(), EventMoveSets = new Dictionary<PartAnimationSetDef.EventTriggers, RelMove[]> {

Each moving subpart will require it's own PartAnimationSetDef() entry.
AnimationDelays can be used to time the start of the part's movement.

// Reloading, Firing, Tracking, Overheated, TurnOn, TurnOff, BurstReload, NoMagsToLoad, PreFire, EmptyOnGameLoad, StopFiring, StopTracking, LockDelay, Init [Firing] = new[] { new RelMove { CenterEmpty = "", TicksToMove = 20, //number of ticks to complete motion, 60 = 1 second MovementType = ExpoDecay, //Linear,ExpoDecay,ExpoGrowth,Delay,Show, //instant or fade Hide, //instant or fade LinearPoints = new[] { Transformation(0, 0, 0.15), //linear movement }, Rotation = Transformation(0, 0, 0), //degrees RotAroundCenter = Transformation(0, 0, 0), //degrees }, new RelMove { CenterEmpty = "", TicksToMove = 2, //number of ticks to complete motion, 60 = 1 second MovementType = Delay, LinearPoints = new XYZ[0], Rotation = Transformation(0, 0, 0), //degrees RotAroundCenter = Transformation(0, 0, 0), //degrees }, new RelMove { CenterEmpty = "", TicksToMove = 15, //number of ticks to complete motion, 60 = 1 second MovementType = Linear, //Linear,ExpoDecay,ExpoGrowth,Delay,Show, //instant or fade Hide, //instant or fade LinearPoints = new[] { Transformation(0, 0, -0.15), //linear movement }, Rotation = Transformation(0, 0, 0), //degrees RotAroundCenter = Transformation(0, 0, 0), //degrees }, },

This is an entry for recoil animation. The subpart is the barrel.
The first line "[Firing]" defines the trigger for this animation sequence, in this case when the weapon fires. It will then step through each RelMove entry in order.
Here there are 3 of them.
1: Move of type ExpoDecay. TicksToMove is how much time the move takes, Transformation(0, 0, 0.15) defines the total movement, and "ExpoDecay" means it will start fast and slow down exponentially as it reaches the destination. As you might guess, ExpoGrowth starts moving slowly and accelerates, and linear is a constant speed movement. Show/Hide can be used to make the subpart appear or vanish (such as a missiles appears loaded then vanishes when the projectile is launched).
2: A delay for 2 ticks.
3: Linear move back to the original position.

For the reloading, I am using delay and rotation for mag subpart. Just keep adding entries as needed.

And for the Gladius emissive operation:
[Firing] = new[] { new RelMove { CenterEmpty = "", TicksToMove = 1, MovementType = Show, EmissiveName = "LaserEmissive", LinearPoints = new[] { Transformation(0, 0, 0), }, Rotation = Transformation(0, 0, 0), RotAroundCenter = Transformation(0, 0, 0), }, }, [StopFiring] = new[] { new RelMove { CenterEmpty = "", TicksToMove = 45, //number of ticks to complete motion, 60 = 1 second MovementType = Hide, LinearPoints = new[] { Transformation(0, 0, 0), }, Rotation = Transformation(0, 0, 0), RotAroundCenter = Transformation(0, 0, 0), }, },
You can see it sets the emissive color and also does show/hide on the subpart.
Troubleshooting.
This part is inevitable. Gun no shoot, wat do?

Gun looks ok in game but doesn't shoot
  • Is weaponcore active on it? Look at control menu for it, if you don't see DPS readouts and such then weaponcore is not active. Check logs for config errors, and check obvious setup things like maybe forgotten entry in masterconfig.
  • Try to manually shoot. Try to narrow it down to targeting or not.
  • check debug lines
  • ammo? power? test in creative first.
  • Are the muzzle empties inside the collision mesh area?

Can't even place weapon in game, error or crash
  • Check logs, first try to determine if this is a problem with your model or the configuration.
  • Coresystems debug log is found at \AppData\Roaming\SpaceEngineers\Storage\1918681825.sbm_CoreSystems\debug.log
  • Try placing model as a simple cubeblock, if you are not getting subparts or it crashes then you have a model issue. Naming errors on subpart empties can easily cause this.
  • The game looking for something that doesn't exist often can cause crash. Walk through the setup files making sure your names are consistent with what you say they are.

gun shoots backwards or aims in some random direction
  • This is almost certainly an error with the model, go back and check those debug axis lines, blue=forward.

Everything was great until the gun fired
  • Try it without particles and see, bad particle can cause WC to implode.
29 Comments
AutoMcDonough  [author] Aug 14, 2022 @ 5:04pm 
I highly recommend joining darkstar's discord server and asking there, there is almost always someone online to talk you through a problem.
IanShackleford Aug 14, 2022 @ 4:49pm 
So I am in the process of making my first weapon. But I am now incredibly confused once it comes to the whole .cs scripting part. That and particles. I'm rather fed up - would anyone be willing to help me out with it at all? I've got all the files and stuff required, just scripting is a pain (I also feel extremely dumb for asking...)
Dercaixr Feb 3, 2022 @ 6:46am 
Where can i find full list of required and optional SBCs and parameters for it
Dercaixr Feb 3, 2022 @ 5:29am 
Where is the SBC setup guide?
AutoMcDonough  [author] Jan 19, 2022 @ 2:08pm 
i don't understand
慕容夜 Jan 19, 2022 @ 12:02pm 
always ceushed,why
VladKΩB Apr 11, 2021 @ 9:35am 
How to create an explosion effect, simular to vanilla SE explosions? Shrapnel, Radiant and explosive effect seem to work different, and cause different damage to blocks(comparing with vanilla). (WC Wiki didnt't help) Are there any weapons with such an explosion effect as an example.
Kiithnaras Mar 30, 2021 @ 10:40am 
On the Smart guidance parameters, is TargetLossDegree a central-angle (0-180 range) or a total-width cone (0-360 range)?
Hello_There Mar 7, 2021 @ 3:52pm 
one of my guns randomly started throwing
03-07-21_23-33-17-180 - Exception in SessionDraw: System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.ThrowHelper.ThrowKeyNotFoundException()
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at WeaponCore.Hud.AddTextAndTextures()
at WeaponCore.Hud.DrawTextures()
at WeaponCore.Session.Draw()

into the log. it seems to be the model causing it, any idea if it could be something else?
AutoMcDonough  [author] Mar 2, 2021 @ 9:52am 
that section probably didn’t exist yet. i gotta update this guide.. some of the rotations are different now with SEUT as well.