/tg/ Station 13 - Modules - TypesVar Details - Proc Details

projectile

Vars

accuracy_falloffHow much accuracy is lost for each tile travelled
accurate_rangeHow much accuracy before falloff starts to matter. Formula is range - falloff * tiles travelled
angleThe current angle of the projectile. Initially null, so if the arg is missing from [/fire()], we can calculate it from firer and target as fallback.
animate_movementGliding does not enjoy something getting moved multiple turfs in a tick, which is why we animate it manually
armor_flagDefines what armor to use when it hits things. Must be set to bullet, laser, energy, or bomb
armour_penetrationHow much armor this projectile pierces.
beam_pointsAssociated list of coordinate points in which we changed trajectories in order to calculate hitscan tracers Value points to the next point in the beam
can_hit_turfsIf true directly targeted turfs can be hit
catastropic_dismembermentIf TRUE, this projectile deals its damage to the chest if it dismembers a limb.
damage_falloff_tileHow much we want to drop damage per tile as it travels through the air
def_zoneZone at which the projectile is aimed at
deletion_queuedIn order to preserve animations, projectiles are only deleted the tick after they impact something. Same is applied to reaching the range limit
dismembermentDamage the limb must have for it to be dismembered upon getting hit. 0 will prevent dismembering altogether
do_not_logIf true, the projectile won't cause any logging whatsoever. Used for hallucinations and shit.
drowsyDrowsiness applied on projectile hit
embed_dataSaves embedding data
embed_falloff_tileHow much we want to drop the embed_chance value, if we can embed, per tile, for falloff purposes
embed_typeIf we have a shrapnel_type defined, these embedding stats will be passed to the spawned shrapnel type, which will roll for embedding on the target
entry_xX coordinate at which the projectile entered a new turf
entry_yY coordinate at which the projectile entered a new turf
eyeblurSeconds of blurry eyes applied on projectile hit
firedIf the projectile was fired already
fired_fromThe thing that the projectile was fired from (gun, turret, spell)
firerAtom who shot the projectile (Not the gun, the guy who shot the gun)
free_hitscan_forceMoveNext forceMove will not create tracer end/start effects
hit_prone_targetsIf TRUE, hit mobs, even if they are lying on the floor and are not our target within MAX_RANGE_HIT_PRONE_TARGETS tiles
hit_threshholdIf objects are below this layer, we pass through them
hitscanWherever this projectile is hitscan. Hitscan projectiles are processed until the end of their path instantly upon being fired and leave a tracer in their path
hitsoundThe sound this plays on impact.
hitsound_wallSound played when the projectile hits a wall
homingIf the projectile is homing. Warning - this changes projectile's processing logic, reverting it to segmented processing instead of new raymarching logic
homing_targetTarget the projectile is homing on
homing_turn_speedAngles per move segment, distance is based on SSprojectiles.pixels_per_decisecond With pixels_per_decisecond set to 16 and homing_turn_speed, the projectile can turn up to 20 pixels per turf passed
ignore_range_hit_prone_targetsIf TRUE, ignores the range of MAX_RANGE_HIT_PRONE_TARGETS tiles of hit_prone_targets
ignore_source_checkIf TRUE, we can hit our firer.
ignored_factionsWe ignore mobs with these factions.
impact_effect_typeImpact VFX created upon hitting something
impact_typeHitscan impact effect spawned on the target
impact_xX coordinate at which the projectile visually impacted the target
impact_yY coordinate at which the projectile visually impacted the target
impactedWe already impacted these things, do not impact them again. Used to make sure we can pierce things we want to pierce. Lazylist, typecache style (object = TRUE) for performance.
jitterJittering applied on projectile hit
last_impact_turfTurf of the last atom we've impacted
last_pointLast point in the beam
last_processLast time the projectile was processed, also used for lag compensation
last_projectile_moveLast time the projectile moved, used for lag compensation if SSprojectiles starts chugging
last_tick_turfTurf that we have registered connect_loc signal - this is done for performance, as we're moving ~a dozen turfs per tick and registering and unregistering signal for every single one of them is stupid. Unregistering the signal from the correct turf in case we get moved by smth else is important
log_overrideIf the act of firing this projectile does not create logs
max_piercesHow many times this projectile can pierce something before deleting
maximum_rangeOriginal range upon being fired/reflected
min_ricochetsHow many times we have to ricochet min (unless we hit an atom we can ricochet off)
movement_vectorProjectile's movement vector - this caches sine/cosine of our angle to cut down on trig calculations
muzzle_typeHitscan muzzle effect spawned on the firer
nondirectional_spriteSet TRUE to prevent projectiles from having their sprites rotated based on firing angle
originalOriginal clicked target
original_angleAngle at the moment of firing
overrunHow many pixels we missed last tick due to lag or speed cap
p_xpixel_x where the player clicked. Default is the center.
p_ypixel_y where the player clicked. Default is the center
pass_flags
pausedIf the projectile is suspended mid-air
phasing_ignore_direct_targetIf FALSE, allow us to hit something directly targeted/clicked/whatnot even if we're able to phase through it
piercesNumber of times we've pierced something. Incremented BEFORE bullet_act and on_hit proc!
pixels_moved_last_tileRemaining pixel movement last tick - used for precise range calculations
projectile_angleAdditional rotation for the projectile, in case it uses some object's sprite
projectile_phasingBitflag for things the projectile should just phase through entirely - No hitting unless direct target and [phasing_ignore_direct_target] is FALSE. Uses pass_flags flags.
projectile_piercingBitflag for things the projectile should hit, but pierce through without deleting itself. Defers to projectile_phasing. Uses pass_flags flags.
rangeThis will de-increment every step. When 0, it will delete the projectile.
reflect_range_decreaseAmount of original range that falls off when reflecting, so it doesn't go forever
reflectableIf this projectile can be reflected
ricochet_auto_aim_angleOn ricochet, if ricochet_auto_aim_range is nonzero, we'll consider any mobs within this range of the normal angle of incidence to home in on, higher = more auto aim
ricochet_auto_aim_rangeOn ricochet, if nonzero, we consider all mobs within this range of our projectile at the time of ricochet to home in on like Revolver Ocelot, as governed by ricochet_auto_aim_angle
ricochet_chance0-100 (or more, I guess), the base chance of ricocheting, before being modified by the atom we shoot and our chance decay
ricochet_decay_chance0-1 (or more, I guess) multiplier, the ricochet_chance is modified by multiplying this after each ricochet
ricochet_decay_damage0-1 (or more, I guess) multiplier, the projectile's damage is modified by multiplying this after each ricochet
ricochet_incidence_leewaythe angle of impact must be within this many degrees of the struck surface, set to 0 to allow any angle
ricochet_shoots_firerCan our ricochet autoaim hit our firer?
ricochetsHow many times we've ricochet'd so far (instance variable, not a stat)
ricochets_maxHow many times we can ricochet max
sharpnessFor what kind of brute wounds we're rolling for, if we're doing such a thing. Lasers obviously don't care since they do burn instead.
shrapnel_typeIf defined, on hit we create an item of this type then call hitby() on the hit target with this, mainly used for embedding items (bullets) in targets
slurSlurring applied on projectile hit
speedHow many tiles we pass in a single SSprojectiles tick
spreadRandom spread done projectile-side for convinience
staminaExtra stamina damage applied on projectile hit (in addition to the main damage)
stamina_falloff_tileHow much we want to drop stamina damage (defined by the stamina variable) per tile as it travels through the air
startingProjectile's starting turf
stutterStuttering applied on projectile hit
suppressedOne of three suppression states: NONE displays the hit message and produces a loud sound, QUIET makes a quiet sound and only lets the victim know they've been shot, and VERY only makes a very quiet sound with no messages
temporary_unstoppable_movementWe are flagged PHASING temporarily to not stop moving when we Bump something but want to keep going anyways.
ticks_to_deletionHow many ticks should we wait in queued deletion mode before qdeleting? Sometimes increased in animations
tracer_typeHitscan tracer effect left behind the projectile
weak_against_armourWhether or not our projectile doubles the value of affecting armour
wound_falloff_tileHow much we want to drop both wound_bonus and bare_wound_bonus (to a minimum of 0 for the latter) per tile, for falloff purposes
xoInitial target x coordinate offset of the projectile
yoInitial target y coordinate offset of the projectile

Procs

CanPassThroughProjectile can pass through Used to not even attempt to Bump() or fail to Cross() anything we already hit.
MovedProjectile moved:
aim_projectileAims the projectile at a target.
can_embed_intoChecks if the projectile can embed into someone
can_hit_targetReturns true if the target atom is on our current turf and above the right layer If direct target is true it's the originally clicked target.
create_hitscan_pointCreates a new keypoint in which the tracer will split
get_embedFetches embedding data
impactCalled when the projectile hits something This can either be from it bumping something, or it passing over a turf/being crossed and scanning that there is infact a valid target it needs to hit. This target isn't however necessarily WHAT it hits that is determined by process_hit and select_target.
is_hostile_projectileIs this projectile considered "hostile"?
move_animateCalled every time projectile animates its movement, in case child wants to have custom animations. Returning TRUE cancels normal animation
on_enteredProjectile crossed: When something enters a projectile's tile, make sure the projectile hits it if it should be hitting it.
on_hitCalled when the projectile hits something
on_rangeCalled next tick after the projectile reaches its maximum range so the animation has time to fully play out
prehit_pierceChecks if we should pierce something.
process_hitscanAttempts to force the projectile to move until the subsystem runs out of processing time, the projectile impacts something or gets frozen by timestop
process_homingCalled every projectile loop for homing or alternatively, custom trajectory changes.
record_hitscan_startCreates (or wipes clean) list of tracer keypoints and creates a first point.
reduce_rangeCalled every time a projectile passes one tile worth of movement
reflectReflects the projectile off of something
scan_moved_turfScans if we should hit something on the turf we just moved to if we haven't already
select_targetSelects a target to hit from a turf
set_angle_centeredSame as set_angle, but the reflection continues from the center of the object that reflects it instead of the side
set_homing_targetMakes projectile home onto the passed target with minor inaccuracy

Var Details

accuracy_falloff

How much accuracy is lost for each tile travelled

accurate_range

How much accuracy before falloff starts to matter. Formula is range - falloff * tiles travelled

angle

The current angle of the projectile. Initially null, so if the arg is missing from [/fire()], we can calculate it from firer and target as fallback.

animate_movement

Gliding does not enjoy something getting moved multiple turfs in a tick, which is why we animate it manually

armor_flag

Defines what armor to use when it hits things. Must be set to bullet, laser, energy, or bomb

armour_penetration

How much armor this projectile pierces.

beam_points

Associated list of coordinate points in which we changed trajectories in order to calculate hitscan tracers Value points to the next point in the beam

can_hit_turfs

If true directly targeted turfs can be hit

catastropic_dismemberment

If TRUE, this projectile deals its damage to the chest if it dismembers a limb.

damage_falloff_tile

How much we want to drop damage per tile as it travels through the air

def_zone

Zone at which the projectile is aimed at

deletion_queued

In order to preserve animations, projectiles are only deleted the tick after they impact something. Same is applied to reaching the range limit

dismemberment

Damage the limb must have for it to be dismembered upon getting hit. 0 will prevent dismembering altogether

do_not_log

If true, the projectile won't cause any logging whatsoever. Used for hallucinations and shit.

drowsy

Drowsiness applied on projectile hit

embed_data

Saves embedding data

embed_falloff_tile

How much we want to drop the embed_chance value, if we can embed, per tile, for falloff purposes

embed_type

If we have a shrapnel_type defined, these embedding stats will be passed to the spawned shrapnel type, which will roll for embedding on the target

entry_x

X coordinate at which the projectile entered a new turf

entry_y

Y coordinate at which the projectile entered a new turf

eyeblur

Seconds of blurry eyes applied on projectile hit

fired

If the projectile was fired already

fired_from

The thing that the projectile was fired from (gun, turret, spell)

firer

Atom who shot the projectile (Not the gun, the guy who shot the gun)

free_hitscan_forceMove

Next forceMove will not create tracer end/start effects

hit_prone_targets

If TRUE, hit mobs, even if they are lying on the floor and are not our target within MAX_RANGE_HIT_PRONE_TARGETS tiles

hit_threshhold

If objects are below this layer, we pass through them

hitscan

Wherever this projectile is hitscan. Hitscan projectiles are processed until the end of their path instantly upon being fired and leave a tracer in their path

hitsound

The sound this plays on impact.

hitsound_wall

Sound played when the projectile hits a wall

homing

If the projectile is homing. Warning - this changes projectile's processing logic, reverting it to segmented processing instead of new raymarching logic

homing_target

Target the projectile is homing on

homing_turn_speed

Angles per move segment, distance is based on SSprojectiles.pixels_per_decisecond With pixels_per_decisecond set to 16 and homing_turn_speed, the projectile can turn up to 20 pixels per turf passed

ignore_range_hit_prone_targets

If TRUE, ignores the range of MAX_RANGE_HIT_PRONE_TARGETS tiles of hit_prone_targets

ignore_source_check

If TRUE, we can hit our firer.

ignored_factions

We ignore mobs with these factions.

impact_effect_type

Impact VFX created upon hitting something

impact_type

Hitscan impact effect spawned on the target

impact_x

X coordinate at which the projectile visually impacted the target

impact_y

Y coordinate at which the projectile visually impacted the target

impacted

We already impacted these things, do not impact them again. Used to make sure we can pierce things we want to pierce. Lazylist, typecache style (object = TRUE) for performance.

jitter

Jittering applied on projectile hit

last_impact_turf

Turf of the last atom we've impacted

last_point

Last point in the beam

last_process

Last time the projectile was processed, also used for lag compensation

last_projectile_move

Last time the projectile moved, used for lag compensation if SSprojectiles starts chugging

last_tick_turf

Turf that we have registered connect_loc signal - this is done for performance, as we're moving ~a dozen turfs per tick and registering and unregistering signal for every single one of them is stupid. Unregistering the signal from the correct turf in case we get moved by smth else is important

log_override

If the act of firing this projectile does not create logs

max_pierces

How many times this projectile can pierce something before deleting

maximum_range

Original range upon being fired/reflected

min_ricochets

How many times we have to ricochet min (unless we hit an atom we can ricochet off)

movement_vector

Projectile's movement vector - this caches sine/cosine of our angle to cut down on trig calculations

muzzle_type

Hitscan muzzle effect spawned on the firer

nondirectional_sprite

Set TRUE to prevent projectiles from having their sprites rotated based on firing angle

original

Original clicked target

original_angle

Angle at the moment of firing

overrun

How many pixels we missed last tick due to lag or speed cap

p_x

pixel_x where the player clicked. Default is the center.

p_y

pixel_y where the player clicked. Default is the center

pass_flags

The "usual" flags of pass_flags is used in that can_hit_target ignores these unless they're specifically targeted/clicked on. This behavior entirely bypasses process_hit if triggered, rather than phasing which uses prehit_pierce() to check.

paused

If the projectile is suspended mid-air

phasing_ignore_direct_target

If FALSE, allow us to hit something directly targeted/clicked/whatnot even if we're able to phase through it

pierces

Number of times we've pierced something. Incremented BEFORE bullet_act and on_hit proc!

pixels_moved_last_tile

Remaining pixel movement last tick - used for precise range calculations

projectile_angle

Additional rotation for the projectile, in case it uses some object's sprite

projectile_phasing

Bitflag for things the projectile should just phase through entirely - No hitting unless direct target and [phasing_ignore_direct_target] is FALSE. Uses pass_flags flags.

projectile_piercing

Bitflag for things the projectile should hit, but pierce through without deleting itself. Defers to projectile_phasing. Uses pass_flags flags.

range

This will de-increment every step. When 0, it will delete the projectile.

reflect_range_decrease

Amount of original range that falls off when reflecting, so it doesn't go forever

reflectable

If this projectile can be reflected

ricochet_auto_aim_angle

On ricochet, if ricochet_auto_aim_range is nonzero, we'll consider any mobs within this range of the normal angle of incidence to home in on, higher = more auto aim

ricochet_auto_aim_range

On ricochet, if nonzero, we consider all mobs within this range of our projectile at the time of ricochet to home in on like Revolver Ocelot, as governed by ricochet_auto_aim_angle

ricochet_chance

0-100 (or more, I guess), the base chance of ricocheting, before being modified by the atom we shoot and our chance decay

ricochet_decay_chance

0-1 (or more, I guess) multiplier, the ricochet_chance is modified by multiplying this after each ricochet

ricochet_decay_damage

0-1 (or more, I guess) multiplier, the projectile's damage is modified by multiplying this after each ricochet

ricochet_incidence_leeway

the angle of impact must be within this many degrees of the struck surface, set to 0 to allow any angle

ricochet_shoots_firer

Can our ricochet autoaim hit our firer?

ricochets

How many times we've ricochet'd so far (instance variable, not a stat)

ricochets_max

How many times we can ricochet max

sharpness

For what kind of brute wounds we're rolling for, if we're doing such a thing. Lasers obviously don't care since they do burn instead.

shrapnel_type

If defined, on hit we create an item of this type then call hitby() on the hit target with this, mainly used for embedding items (bullets) in targets

slur

Slurring applied on projectile hit

speed

How many tiles we pass in a single SSprojectiles tick

spread

Random spread done projectile-side for convinience

stamina

Extra stamina damage applied on projectile hit (in addition to the main damage)

stamina_falloff_tile

How much we want to drop stamina damage (defined by the stamina variable) per tile as it travels through the air

starting

Projectile's starting turf

stutter

Stuttering applied on projectile hit

suppressed

One of three suppression states: NONE displays the hit message and produces a loud sound, QUIET makes a quiet sound and only lets the victim know they've been shot, and VERY only makes a very quiet sound with no messages

temporary_unstoppable_movement

We are flagged PHASING temporarily to not stop moving when we Bump something but want to keep going anyways.

ticks_to_deletion

How many ticks should we wait in queued deletion mode before qdeleting? Sometimes increased in animations

tracer_type

Hitscan tracer effect left behind the projectile

weak_against_armour

Whether or not our projectile doubles the value of affecting armour

wound_falloff_tile

How much we want to drop both wound_bonus and bare_wound_bonus (to a minimum of 0 for the latter) per tile, for falloff purposes

xo

Initial target x coordinate offset of the projectile

yo

Initial target y coordinate offset of the projectile

Proc Details

CanPassThrough

Projectile can pass through Used to not even attempt to Bump() or fail to Cross() anything we already hit.

Moved

Projectile moved:

If not fired yet, do not do anything. Else,

If temporary unstoppable movement used for piercing through things we already hit (impacted list) is set, unset it. Scan turf we're now in for anything we can/should hit. This is useful for hitting non dense objects the user directly clicks on, as well as for PHASING projectiles to be able to hit things at all as they don't ever Bump().

aim_projectile

Aims the projectile at a target.

Must be passed at least one of a target or a list of click parameters. If only passed the click modifiers the source atom must be a mob with a client.

Arguments:

can_embed_into

Checks if the projectile can embed into someone

can_hit_target

Returns true if the target atom is on our current turf and above the right layer If direct target is true it's the originally clicked target.

create_hitscan_point

Creates a new keypoint in which the tracer will split

get_embed

Fetches embedding data

impact

Called when the projectile hits something This can either be from it bumping something, or it passing over a turf/being crossed and scanning that there is infact a valid target it needs to hit. This target isn't however necessarily WHAT it hits that is determined by process_hit and select_target.

Furthermore, this proc shouldn't check can_hit_target - this should only be called if can hit target is already checked. Also, we select_target to find what to process_hit first.

is_hostile_projectile

Is this projectile considered "hostile"?

By default all projectiles which deal damage or impart crowd control effects (including stamina) are hostile

This is NOT used for pacifist checks, that's handled by /obj/item/ammo_casing/var/harmful This is used in places such as AI responses to determine if they're being threatened or not (among other places)

move_animate

Called every time projectile animates its movement, in case child wants to have custom animations. Returning TRUE cancels normal animation

on_entered

Projectile crossed: When something enters a projectile's tile, make sure the projectile hits it if it should be hitting it.

on_hit

Called when the projectile hits something

By default parent call will always return [BULLET_ACT_HIT] (unless qdeleted) so it is save to assume a successful hit in children (though not necessarily successfully damaged - it could've been blocked)

Arguments

Returns

on_range

Called next tick after the projectile reaches its maximum range so the animation has time to fully play out

prehit_pierce

Checks if we should pierce something.

NOT meant to be a pure proc, since this replaces prehit() which was used to do things. Return PROJECTILE_DELETE_WITHOUT_HITTING to delete projectile without hitting at all!

process_hitscan

Attempts to force the projectile to move until the subsystem runs out of processing time, the projectile impacts something or gets frozen by timestop

process_homing

Called every projectile loop for homing or alternatively, custom trajectory changes.

record_hitscan_start

Creates (or wipes clean) list of tracer keypoints and creates a first point.

reduce_range

Called every time a projectile passes one tile worth of movement

reflect

Reflects the projectile off of something

scan_moved_turf

Scans if we should hit something on the turf we just moved to if we haven't already

This proc is a little high in overhead but allows us to not snowflake CanPass in living and other things.

select_target

Selects a target to hit from a turf

@params our_turf - Turf on which we hit the target bumped - What we've impacted and why this selection was called in the first place. If set, this atom is always treated as dense by can_hit_target.

Priority: 0. Anything that is already in impacted is ignored no matter what. Furthermore, in any bracket, if the target atom parameter is in it, that's hit first. Furthermore, can_hit_target is always checked. This (entire proc) is PERFORMANCE OVERHEAD!! But, it shouldn't be ""too"" bad and I frankly don't have a better generic non snowflakey way that I can think of right now at 3 AM. FURTHERMORE, mobs/objs have a density check from can_hit_target - to hit non dense objects over a turf, you must click on them, same for mobs that usually wouldn't get hit.

  1. Special check on what we bumped to see if it's a border object that intercepts hitting anything behind it
  2. The thing originally aimed at/clicked on
  3. Mobs - picks lowest buckled mob to prevent scarp piggybacking memes
  4. Objs
  5. Turf
  6. Nothing

set_angle_centered

Same as set_angle, but the reflection continues from the center of the object that reflects it instead of the side

set_homing_target

Makes projectile home onto the passed target with minor inaccuracy