Projectiles are a type of object that can be fired from weapon triggers and thrown as grenades. They can have render models and various attachments, and are capable of bouncing, detonations, different responses by impacted material, ballistic trajectories, and various other settings.

Movement

Projectile movement is simulated during each game tick (smallest unit of simulated time). According to the projectile's velocity and gravity scale, its next position is calculated by the engine and a "trace" ray between the two points is tested for collisions.

The trace collision test takes advantage of other objects' bounding radii and the collision BSP structures found in model_collision_geometry and scenario_structure_bsp. If any collision is detected, it is handled accordingly (e.g. applying effects or playing sounds).

If a collision radius is set then and the game uses an additional 2 offset rays to check for collisions with objects.

If no collision is detected, the projectile is moved to its next position at the end of the trace line. The process continues, tick by tick, until the projectile collides, detonates at its maximum range, or is removed at its maximum air or water damage range.

A sufficiently high velocity projectile is effectively hitscan if it can cross a playable space within a single tick, with the game being simulated at 30 ticks per second. Otherwise, ballistic leading will be required to hit a moving target.

Related HaloScript

Function/global

Type

(ai_debug_ballistic_lineoffire_freeze [boolean])

If enabled, the ballistic arc drawn by ai_render_ballistic_lineoffire will not update when new grenades are thrown.

Global
(ai_render_ballistic_lineoffire [boolean])

Toggles the rendering of ballistic aiming arcs when AI throw grenades only (does not include hunter guns, wraiths, or other ballistic weapons). The arc is shown in green when unobstructed and orange when obstructed by an object or the BSP. Its origin point and vector are shown in yellow. Only a single arc is shown at a time and updates whenever a new grenade is thrown. This can be paused with ai_debug_ballistic_lineoffire_freeze.

Global

Structure and fields

FieldTypeComments
projectile flagsbitfield
FlagMaskComments
oriented along velocity0x1

Projectile will always face in the direction it's moving in.

ai must use ballistic aiming0x2

AI will try to arc their shots to hit their targets rather than firing directly at them. Useful if the projectile has a strong arc or long travel time, throws off AI aim if not.

detonation max time if attached0x4
has super combining explosion0x8

If seven of this projectile are attached to the same biped, this projectile's super detonation effect will be triggered. This number is hardcoded and cannot be changed.

combine initial velocity with parent velocity0x10

When off, projectiles add the component of the shooter's velocity in the direction of travel when firing. When on, the shooter's unmodified velocity is added to the projectile's when firing.

random attached detonation time0x20
minimum unattached detonation time0x40
detonation timer startsenum
OptionValueComments
immediately0x0

The detonation timer begins immediately after the projectile is created, causing it to explode after a fixed length of time.

after first bounce0x1

Treated identically to when at rest by the game (same code path).

when at rest0x2

Once the projectile comes to rest, its detonation timer begins. If it becomes in motion again, the timer is not interrupted.

impact noiseenum

How loudly AI will perceive this impact.

OptionValueComments
silent0x0

The sound is not perceived at all.

medium0x1

This is the volume of the sniper rifle. The exact radius is unknown.

loud0x2
shout0x3

Every AI in the BSP can hear this.

quiet0x4
projectile a inenum
OptionValueComments
none0x0
range remaining0x1
time remaining0x2
tracer0x3
projectile b inenum?
projectile c inenum?
projectile d inenum?
super detonationTagDependency: effect
ai perception radiusfloat
  • Unit: world units
collision radiusfloat
  • Unit: world units

Setting this to a non-zero value causes the game to test for projectile collisions using 3 horizontal rays. In addition to the normal central ray, two additional rays are added to the left and right offset by this distance (like Quake's lightning gun). The side rays can only collide with objects and not BSP. When the side rays detect a collision then the projectile will be snapped to that location. The projectile's bounding radius does not affect this.

arming timefloat
  • Unit: seconds
danger radiusfloat
  • Unit: world units

Actors within this distance of the projectile may attempt to avoid it, such as by diving away, depending on actor settings.

effectTagDependency: effect
timerBounds
  • Unit: seconds
FieldTypeComments
minfloat
maxfloat
minimum velocityfloat
  • Unit: world units per second
maximum rangefloat
  • Unit: world units
air gravity scalefloat
air damage rangeBounds?
  • Unit: world units

Determines the maximum range that the projectile travels in the air and scales impact damage between its lower and upper bound. When the projectile reaches the maximum range, it disappears (and does not detonate). If detonation at a max range is desired, used the maximum range field above. See the impact damage formula for more information. If these values are set to 0, maximum damage is applied and the projectile continues traveling until colliding or detonating.

water gravity scalefloat
water damage rangeBounds?
  • Unit: world units

Like air damage range, but for underwater environments (determined by the is water flag of fog tags).

initial velocityfloat
  • Unit: world units per second

Sets the velocity of the projectile upon creation. For grenades thrown by AI, see actor_variant grenade velocity. For player-thrown grenades, see unit grenade velocity.

final velocityfloat
  • Unit: world units per second
guided angular velocityfloat
  • Unit: degrees per second
detonation noiseenum?

How loudly AI will perceive this detonation.

detonation startedTagDependency: effect
flyby soundTagDependency: sound
attached detonation damageTagDependency: damage_effect
impact damageTagDependency: damage_effect
projectile material responseBlock
  • HEK max count: 33
FieldTypeComments
flagsbitfield
FlagMaskComments
cannot be overpenetrated0x1
default responseenum
OptionValueComments
disappear0x0
detonate0x1
reflect0x2
overpenetrate0x3
attach0x4
default effectTagDependency: effect
potential responseenum?
potential flagsbitfield
FlagMaskComments
only against units0x1
never against units0x2
  • H1A only
potential skip fractionfloat
  • Min: 0
  • Max: 1
potential betweenBounds?
potential andBounds?
  • Unit: world units per second
potential effectTagDependency: effect
scale effects byenum
OptionValueComments
damage0x0
angle0x1
angular noisefloat
velocity noisefloat
  • Unit: world units per second
detonation effectTagDependency: effect
initial frictionfloat
maximum distancefloat
parallel frictionfloat
perpendicular frictionfloat

Acknowledgements

Thanks to the following individuals for their research or contributions to this topic:

  • Conscars (Testing collision radius)
  • FD (Explaining "combine initial velocity with parent velocity")
  • gbMichelle (Movement)
  • Kavawuvi (Invader tag definitions)
  • Mimickal (Explaining bounce timer)
  • MosesOfEgypt (Tag structure research)
  • Vennobennu (Field documentation)
  • xScruffyDaSasquatchx (Explaining noise volumes for AI perception)