Fragments
When a bullet is destroyed, it can produce fragments. These fragments can also produce fragments when they are destroyed, creating one of the most versatile systems in Reassembly modding.
Fragments are nested within projectile code and have the same field types as base cannons except for those which wouldn't make sense.
Look at the code below and look at the similarities between the base cannon bullet and the fragment which is nested within it:
{ 17000
features=CANNON
cannon={
damage=100
roundsPerSec=5
muzzleVel=1000
range=1000
power=10
spread=0.1
color=0xFFFFFFFF
recoil=1
burstyness=1
roundsPerBurst=5
explosive=ENABLED
explodeRadius=50
fragment={
damage=50
-- Fragments don't have `roundsPerSec`.
muzzleVel=500
range=500
-- Fragments don't need `power`.
spread=0.1
color=0xFFFFFFFF
-- Fragments have no need to exert `recoil`.
-- Fragments also don't have `burstyness`.
roundsPerBurst=5
explosive=ENABLED
explodeRadius=25
}
}
}
In fragments, roundsPerBurst
is repurposed as the amount of fragments released when a bullet is destroyed.
In the code extract above, the base cannon bullet will split into 5 fragments, which are all identical. The fragments will also be created at a spread of 0.1 radians, or ~5.72°, as defined by the fragment's spread
field.
Fragment Chaining
As fragments can be nested within each other, we can create fragment chains. Below is an example of one using conventional one-line fragments for easy reading:
{ 17000
features=CANNON
cannon={
damage=100
roundsPerSec=1
muzzleVel=50
range=50
power=10
-- Some fields have been left out for ease of explaining.
fragment={ damage=100 muzzleVel=50 range=50 roundsPerBurst=1
fragment={ damage=100 muzzleVel=50 range=50 roundsPerBurst=1
fragment={ damage=100 muzzleVel=50 range=50 roundsPerBurst=1
fragment={ damage=100 muzzleVel=50 range=50 roundsPerBurst=1
}}}} -- Closing brackets are lined up at the end of the chain.
}
}
In this code extract, there will be 5 fragment projectiles that spawn after one another in a chain.
The Relationship of range
and muzzleVel
If you fire the cannon from the code extract above, you might notice something unexpected if you are unfamilier with fragment modding. Each new fragment is faster than the last by 50 units per second:
This is caused by each successive fragment inheriting the sum of the velocities of all the bullets that came before it.
To have uniform velocities on the bullets, one might expect the solution to be to make the muzzleVel
equal 0, but this does not work:
cannon={
damage=100
roundsPerSec=1
muzzleVel=50
range=50
power=10
fragment={ damage=100 muzzleVel=0 range=50 roundsPerBurst=1
-- None of the other fragments are reached.
fragment={ damage=100 muzzleVel=0 range=50 roundsPerBurst=1
fragment={ damage=100 muzzleVel=0 range=50 roundsPerBurst=1
fragment={ damage=100 muzzleVel=0 range=50 roundsPerBurst=1
}}}}
}
Although the second bullet has velocity, it is inherited from the first stage. Think back to how bullet duration is calculated based on only a bullet's muzzleVel
and range
, not its current velocity.
Now, understand that the second bullet will never transition to the third stage as the second bullet is "attempting" to travel a range
of 50 at a muzzleVel
of 0. The journey to travel 50 units at 0 units per second is uncompletable, the bullet will never enter the third stage.
To achieve uniform velocities, we must make the muzzleVel
unnoticably small as well setting its range
small enough that the fragments' duration is calculated to not be infinite.
If we want the fragments to last for one second, similar to the base bullet, then we can set range
to 1 and the muzzleVel
to 1. The bullet will travel 1 unit at 1 unit per second over a time of 1 second.
cannon={
damage=100
roundsPerSec=1
muzzleVel=50
range=50
power=10
fragment={ damage=100 muzzleVel=1 range=1 roundsPerBurst=1
fragment={ damage=100 muzzleVel=1 range=1 roundsPerBurst=1
fragment={ damage=100 muzzleVel=1 range=1 roundsPerBurst=1
fragment={ damage=100 muzzleVel=1 range=1 roundsPerBurst=1
-- All fragments occur. success!
}}}}
}
Strangely, a bullet trying to travel a range
of 0 at a muzzleVel
of 0 completes its journey.
Patterns
For more control over how bullets are spawned, you can select various pattern flags for the pattern
field of a bullet. They can be used in both base bullets and fragments.
Below is an example of a cannon using the RANDOM
pattern, which would be the same as having pattern
not defined.
cannon={
damage=100
roundsPerSec=1
muzzleVel=50
range=50
power=10
recoil=0
spread=pi*2
pattern=RANDOM
}
Below are all the bullet patterns, they can all be used on both base cannon bullets and fragments except for WAVE
, which can only be used on base cannon bullets.
Random
pattern=RANDOM
: default spread behaviour, choosing a random angle in the specified spread.
cannon={ spread=pi*2 pattern=RANDOM
damage=100 roundsPerSec=5 muzzleVel=50 range=50 recoil=0 }
Constant
pattern=CONSTANT
: bullet will angle exactly at the spread angle. Positive spread
angles bullet counterclockwise while negative spread
angles bullets clockwise.
Firing counterclockwise:
cannon={ spread=pi*0.5 pattern=CONSTANT
damage=100 roundsPerSec=5 muzzleVel=50 range=50 recoil=0 }
Firing clockwise:
cannon={ spread=pi*-0.5 pattern=CONSTANT
damage=100 roundsPerSec=5 muzzleVel=50 range=50 recoil=0 }
Spiral
pattern=SPIRAL
: bullets are evenly distributed within the spread angle. Needs roundsPerBurst
and burstyness
defined on base cannon bullets but only needs roundsPerBurst
defined on fragments.
cannon={ spread=pi*0.5 pattern=SPIRAL roundsPerBurst=5 burstyness=0.5
damage=100 roundsPerSec=5 muzzleVel=50 range=50 recoil=0 }
Wave
pattern=WAVE
: bullets are distributed according to a sine wave within the spread angle. Do not use on fragments.
cannon={ spread=pi*0.5 pattern=WAVE roundsPerBurst=20 burstyness=0.5
damage=100 roundsPerSec=5 muzzleVel=50 range=50 recoil=0 }
Absolute
pattern=ABSOLUTE
: bullets do not inherit velocity of ship or previous bullets. It can be mixed with any of the other pattern flags.
This is without ABSOLUTE
:
cannon={ spread=0
damage=100 roundsPerSec=5 muzzleVel=50 range=50 recoil=0 }
This is with ABSOLUTE
:
cannon={ spread=0 pattern=ABSOLUTE
damage=100 roundsPerSec=5 muzzleVel=50 range=50 recoil=0 }
Explosive Flags for Fragments
There are fragment specific alternatives for ENABLED
, FINAL
, and PROXIMITY
for the explosive field
. Respectively, they are:
FRAG_IMPACT
: bullet fragments when hitting a target but not when the bullet reaches the end of its range.FRAG_FINAL
: bullet fragments at either the end of its range or when the bullet's damage output is exhausted.FRAG_PROXIMITY
: bullet fragments when within proximity of an attackable block.
There is also FRAG_NOFLASH
, which makes bullets with this flag spawn without producing a frag spawn particle.