Projectile refactoring madness (#19878)

Refactored the projectile code, mostly in line with TG's now.
Refactored various procs that are used or depends on it.
Projectiles can now ricochet if enabled to.
Damage falloffs with distance.
Homing projectiles can now have accuracy falloff with distance.
Projectiles have a maximum range.
Muzzle flash is configurable per projectile.
Impact effect of the projectile is configurable per projectile.
Accuracy decreases with distance.
Projectiles work with signals and emits them, for easy hooking up from
other parts of the code.
Meatshielding is now less effective .
Impact sound is now configurable per projectile.

High risk.
This commit is contained in:
Fluffy
2024-09-23 10:12:57 +00:00
committed by GitHub
parent 914f69dcc8
commit c24b4c7097
203 changed files with 2925 additions and 1590 deletions
+12 -6
View File
@@ -428,12 +428,13 @@
var/disp = dispersion[min(i, dispersion.len)]
P.accuracy = accuracy + acc
P.dispersion = disp
P.spread += disp
P.shot_from = src.name
P.suppressed = suppressed
P.launch_projectile(target)
P.preparePixelProjectile(target, get_turf(src))
P.fired_from = src
P.fire()
handle_post_fire() // should be safe to not include arguments here, as there are failsafes in effect (?)
@@ -539,7 +540,7 @@
//Accuracy modifiers
P.accuracy = accuracy + acc_mod
P.dispersion = dispersion
P.spread += dispersion
//Increasing accuracy across the board, ever so slightly
P.accuracy += 1
@@ -556,7 +557,7 @@
F = firemodes[sel_mode]
if(one_hand_fa_penalty > 2 && !wielded && F?.name == "full auto") // todo: make firemode names defines
P.accuracy -= one_hand_fa_penalty * 0.5
P.dispersion -= one_hand_fa_penalty * 0.5
P.spread -= one_hand_fa_penalty * 0.5
//does the actual launching of the projectile
/obj/item/gun/proc/process_projectile(obj/projectile, mob/user, atom/target, target_zone, params)
@@ -573,7 +574,12 @@
else if(mob.shock_stage > 70)
added_spread = 15
return !P.launch_from_gun(target, target_zone, user, params, null, added_spread, src)
P.preparePixelProjectile(target, src, deviation = added_spread)
P.firer = user
P.fired_from = src
P.def_zone = target_zone
return !P.fire()
//Suicide handling.
/obj/item/gun/var/mouthshoot = FALSE //To stop people from suiciding twice... >.>
@@ -80,19 +80,18 @@
muzzle_type = /obj/effect/projectile/muzzle/plasma_cutter
tracer_type = /obj/effect/projectile/tracer/plasma_cutter
impact_type = /obj/effect/projectile/impact/plasma_cutter
maiming = TRUE
maim_rate = 1
/obj/projectile/beam/plasmacutter/proc/pass_check(var/turf/simulated/mineral/mine_turf)
if(mineral_passes <= 0)
return list(null, FALSE) // the projectile stops
mineral_passes--
var/mineral_destroyed = on_impact(mine_turf)
return list(PROJECTILE_CONTINUE, mineral_destroyed) // the projectile tunnels deeper
var/mineral_destroyed = on_hit(mine_turf)
return list(BULLET_ACT_HIT, mineral_destroyed) // the projectile tunnels deeper
/obj/projectile/beam/plasmacutter/on_impact(var/atom/A)
if(istype(A, /turf/simulated/mineral))
var/turf/simulated/mineral/M = A
/obj/projectile/beam/plasmacutter/on_hit(atom/target, blocked, def_zone)
if(istype(target, /turf/simulated/mineral))
var/turf/simulated/mineral/M = target
if(prob(33))
M.GetDrilled(1)
return TRUE
@@ -13,7 +13,8 @@
reagents = new/datum/reagents(reagent_amount)
reagents.my_atom = src
/obj/projectile/bullet/chemdart/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null)
/obj/projectile/bullet/chemdart/on_hit(atom/target, blocked, def_zone)
. = ..()
if(blocked < 100 && ishuman(target))
var/mob/living/carbon/human/H = target
if(H.can_inject(target_zone=def_zone))
@@ -300,8 +300,8 @@
if(default_parry_check(user, attacker, damage_source) && prob(20))
user.visible_message(SPAN_DANGER("\The [user] parries [attack_text] with \the [src]!"))
playsound(user.loc, "punchmiss", 50, 1)
return PROJECTILE_STOPPED
return FALSE
return BULLET_ACT_BLOCK
return BULLET_ACT_HIT
/obj/item/gun/projectile/revolver/konyang/pirate
name = "reclaimed revolver"
File diff suppressed because it is too large Load Diff
@@ -3,7 +3,6 @@
icon_state = "ice_1"
damage = 0
damage_type = DAMAGE_BURN
nodamage = 1
check_armor = "energy"
/obj/projectile/animate/Collide(atom/change)
+28 -33
View File
@@ -130,10 +130,10 @@
damage = 45
armor_penetration = 40
/obj/projectile/beam/pulse/on_hit(var/atom/target, var/blocked = 0)
/obj/projectile/beam/pulse/on_hit(atom/target, blocked, def_zone)
if(isturf(target))
target.ex_act(2)
..()
. = ..()
/obj/projectile/beam/pulse/heavy
name = "heavy pulse laser"
@@ -168,7 +168,8 @@
tracer_type = /obj/effect/projectile/tracer/laser
impact_type = /obj/effect/projectile/impact/laser
/obj/projectile/beam/laser_tag/on_hit(var/atom/target, var/blocked = 0)
/obj/projectile/beam/laser_tag/on_hit(atom/target, blocked, def_zone)
. = ..()
if(ishuman(target))
var/mob/living/carbon/human/H = target
var/obj/item/clothing/suit/armor/riot/laser_tag/LT = H.wear_suit
@@ -234,7 +235,7 @@
tracer_type = /obj/effect/projectile/tracer/disabler
impact_type = /obj/effect/projectile/impact/disabler
/obj/projectile/beam/disorient/on_hit(var/atom/target, var/blocked = 0)
/obj/projectile/beam/disorient/on_hit(atom/target, blocked, def_zone)
if(ishuman(target) && blocked < 100 && !issilicon(target) && !isipc(target)) //Make them trip
var/mob/living/carbon/human/H = target
H.druggy = min(H.druggy + 15, 75)
@@ -268,9 +269,9 @@
tracer_type = /obj/effect/projectile/tracer/stun
impact_type = /obj/effect/projectile/impact/stun
/obj/projectile/beam/mousegun/on_impact(var/atom/A)
mousepulse(A, 1)
..()
/obj/projectile/beam/mousegun/on_hit(atom/target, blocked, def_zone)
mousepulse(target, 1)
. = ..()
/obj/projectile/beam/mousegun/proc/mousepulse(turf/epicenter, range, log=0)
if(!epicenter)
@@ -309,8 +310,6 @@
/obj/projectile/beam/mousegun/emag
name = "diffuse electrical arc"
nodamage = FALSE
damage_type = DAMAGE_BURN
damage = 15
agony = 30
@@ -349,7 +348,6 @@
return TRUE
/obj/projectile/beam/mousegun/xenofauna
nodamage = FALSE
damage = 10
/obj/projectile/beam/mousegun/xenofauna/mousepulse(atom/target, range, log)
@@ -376,22 +374,22 @@
tracer_type = /obj/effect/projectile/tracer/solar
impact_type = /obj/effect/projectile/impact/solar
/obj/projectile/beam/megaglaive/on_impact(var/atom/A)
if(isturf(A))
if(istype(A, /turf/simulated/mineral))
/obj/projectile/beam/megaglaive/on_hit(atom/target, blocked, def_zone)
if(isturf(target))
if(istype(target, /turf/simulated/mineral))
if(prob(75)) //likely because its a mining tool
var/turf/simulated/mineral/M = A
var/turf/simulated/mineral/M = target
if(prob(10))
M.GetDrilled(1)
else if(!M.emitter_blasts_taken)
M.emitter_blasts_taken += 1
else if(prob(33))
M.emitter_blasts_taken += 1
if(ismob(A))
var/mob/living/M = A
if(ismob(target))
var/mob/living/M = target
M.apply_effect(1, INCINERATE, 0)
explosion(A, -1, 0, 2)
..()
explosion(target, -1, 0, 2)
. = ..()
/obj/projectile/beam/thermaldrill
name = "thermal drill"
@@ -402,9 +400,9 @@
tracer_type = /obj/effect/projectile/tracer/solar
impact_type = /obj/effect/projectile/impact/solar
/obj/projectile/beam/thermaldrill/on_impact(var/atom/hit_atom)
if(istype(hit_atom, /turf/simulated/mineral))
var/turf/simulated/mineral/mineral = hit_atom
/obj/projectile/beam/thermaldrill/on_hit(atom/target, blocked, def_zone)
if(istype(target, /turf/simulated/mineral))
var/turf/simulated/mineral/mineral = target
mineral.GetDrilled(TRUE)
return ..()
@@ -426,11 +424,11 @@
tracer_type = /obj/effect/projectile/tracer/cult
impact_type = /obj/effect/projectile/impact/cult
/obj/projectile/beam/cult/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier=0)
/obj/projectile/beam/cult/on_hit(atom/target, blocked, def_zone)
//Harmlessly passes through cultists and constructs
if (target_mob == ignore)
if (target == ignore)
return 0
if (iscultist(target_mob))
if (iscultist(target))
return 0
return ..()
@@ -447,16 +445,16 @@
/obj/projectile/beam/energy_net
name = "energy net projection"
icon_state = "xray"
nodamage = 1
damage = 0
damage_type = DAMAGE_PAIN
muzzle_type = /obj/effect/projectile/muzzle/xray
tracer_type = /obj/effect/projectile/tracer/xray
impact_type = /obj/effect/projectile/impact/xray
/obj/projectile/beam/energy_net/on_hit(var/atom/netted)
do_net(netted)
..()
/obj/projectile/beam/energy_net/on_hit(atom/target, blocked, def_zone)
do_net(target)
. = ..()
/obj/projectile/beam/energy_net/proc/do_net(var/mob/M)
var/obj/item/energy_net/net = new (get_turf(M))
@@ -468,10 +466,7 @@
damage = 25
armor_penetration = 65
penetrating = 1
maiming = 1
maim_rate = 5
clean_cut = 1
maim_type = DROPLIMB_BURN
muzzle_type = /obj/effect/projectile/muzzle/tachyon
tracer_type = /obj/effect/projectile/tracer/tachyon
@@ -490,7 +485,7 @@
tracer_type = /obj/effect/projectile/tracer/tesla
impact_type = /obj/effect/projectile/impact/tesla
/obj/projectile/beam/tesla/on_impact(atom/target)
/obj/projectile/beam/tesla/on_hit(atom/target, blocked, def_zone)
. = ..()
if(isliving(target))
tesla_zap(target, 5, 5000)
@@ -507,7 +502,7 @@
tracer_type = /obj/effect/projectile/tracer/laser/blue
impact_type = /obj/effect/projectile/impact/laser/blue
/obj/projectile/beam/freezer/on_impact(atom/target)
/obj/projectile/beam/freezer/on_hit(atom/target, blocked, def_zone)
. = ..()
if(isliving(target))
var/mob/living/L = target
+57 -49
View File
@@ -4,7 +4,6 @@
damage = 60
damage_type = DAMAGE_BRUTE
impact_sounds = list(BULLET_IMPACT_MEAT = SOUNDS_BULLET_MEAT, BULLET_IMPACT_METAL = SOUNDS_BULLET_METAL)
nodamage = FALSE
check_armor = "bullet"
embed = TRUE
sharp = TRUE
@@ -13,12 +12,11 @@
muzzle_type = /obj/effect/projectile/muzzle/bullet
/obj/projectile/bullet/on_hit(var/atom/target, var/blocked = 0, var/def_zone = null)
if (..(target, blocked, def_zone))
/obj/projectile/bullet/on_hit(atom/target, blocked, def_zone)
if(isliving(target) && (..(target, blocked, def_zone) == BULLET_ACT_HIT))
var/mob/living/L = target
shake_camera(L, 3, 2)
/obj/projectile/bullet/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier)
if(penetrating > 0 && damage > 20 && prob(damage))
mob_passthrough_check = 1
else
@@ -88,9 +86,16 @@
var/pellet_loss = round((distance - 1)/range_step) //pellets lost due to distance
return max(pellets - pellet_loss, 1)
/obj/projectile/bullet/pellet/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier)
/obj/projectile/bullet/pellet/on_hit(atom/target, blocked, def_zone)
if(!isliving(target))
return ..()
var/mob/living/living_target = target
if (pellets < 0)
return TRUE
return BULLET_ACT_BLOCK
var/distance = get_dist(src.starting, get_turf(living_target))
var/total_pellets = get_pellets(distance)
var/spread = max(base_spread - (spread_step*distance), 0)
@@ -102,7 +107,7 @@
var/hits = 0
for (var/i in 1 to total_pellets)
if(target_mob.lying && target_mob != original && prob(prone_chance))
if(living_target.lying && living_target != original && prob(prone_chance))
continue
// pellet hits spread out across different zones, but 'aim at' the targeted zone with higher probability
@@ -112,20 +117,22 @@
// relatively hacky way of basing a shotgun pellet's likelihood of hitting on the first pellet of the burst while not affecting shrapnel explosions.
if (base_spread > 0)
if (i == 1)
if (..())
if (..() == BULLET_ACT_HIT)
hits++
else
return 0
else if (..(target_mob, distance, -100))
else if (..() == BULLET_ACT_HIT)
hits++
else if (..())
else if (..() == BULLET_ACT_HIT)
hits++
def_zone = old_zone //restore the original zone the projectile was aimed at
pellets -= hits //each hit reduces the number of pellets left
if (hits >= total_pellets || pellets <= 0)
return TRUE
return FALSE
// if (hits >= total_pellets || pellets <= 0)
// return TRUE
if(hits)
return BULLET_ACT_HIT //Technically not everything, but good enough
return BULLET_ACT_BLOCK //Nothing hit
/obj/projectile/bullet/pellet/get_structure_damage()
var/distance = get_dist(loc, starting)
@@ -157,7 +164,13 @@
var/ball_loss = round((distance - 1)/range_step)
return max(balls - ball_loss, 1)
/obj/projectile/bullet/rubberball/attack_mob(var/mob/living/target_mob, var/distance, var/miss_modifier)
/obj/projectile/bullet/rubberball/on_hit(atom/target, blocked, def_zone)
if(!isliving(target))
return ..()
var/mob/living/target_mob = target
var/distance = get_dist(src.starting, get_turf(target_mob))
if (balls < 0)
return TRUE
@@ -323,9 +336,7 @@
penetrating = 5
armor_penetration = 70
hitscan = 1 //so the PTR isn't useless as a sniper weapon
maiming = 1
maim_rate = 3
maim_type = DROPLIMB_BLUNT
anti_materiel_potential = 2
/obj/projectile/rifle/kumar_super
@@ -349,18 +360,15 @@
weaken = 3
penetrating = 5
armor_penetration = 10
maiming = TRUE
maim_rate = 3
maim_type = DROPLIMB_BLUNT
anti_materiel_potential = 2
/obj/projectile/bullet/rifle/slugger/on_hit(var/atom/movable/target, var/blocked = 0)
if(!istype(target))
return FALSE
var/throwdir = get_dir(firer, target)
target.throw_at(get_edge_target_turf(target, throwdir), 3, 3)
..()
return TRUE
/obj/projectile/bullet/rifle/slugger/on_hit(atom/target, blocked, def_zone)
var/atom/movable/movable_target = target
if(istype(movable_target))
var/throwdir = get_dir(firer, movable_target)
movable_target.throw_at(get_edge_target_turf(movable_target, throwdir), 3, 3)
. = ..()
/obj/projectile/bullet/rifle/tranq
name = "dart"
@@ -448,7 +456,6 @@
name = "cap"
damage_type = DAMAGE_PAIN
damage = 0
nodamage = 1
embed = 0
sharp = 0
@@ -493,17 +500,13 @@
damage = 10
armor_penetration = 30
/obj/projectile/bullet/gauss/highex/on_impact(var/atom/A)
explosion(A, -1, 0, 2)
..()
/obj/projectile/bullet/gauss/highex/on_hit(var/atom/target, var/blocked = 0)
/obj/projectile/bullet/gauss/highex/on_hit(atom/target, blocked, def_zone)
. = ..()
explosion(target, -1, 0, 2)
if(ismovable(target))
var/atom/movable/T = target
var/throwdir = get_dir(firer,target)
INVOKE_ASYNC(T, TYPE_PROC_REF(/atom/movable, throw_at), get_edge_target_turf(target, throwdir), 3, 3)
return TRUE
/obj/projectile/bullet/cannonball
name = "cannonball"
@@ -519,9 +522,9 @@
penetrating = 0
armor_penetration = 5
/obj/projectile/bullet/cannonball/explosive/on_impact(var/atom/A)
explosion(A, -1, 1, 2)
..()
/obj/projectile/bullet/cannonball/explosive/on_hit(atom/target, blocked, def_zone)
explosion(target, -1, 1, 2)
. = ..()
/obj/projectile/bullet/nuke
name = "miniaturized nuclear warhead"
@@ -529,15 +532,15 @@
damage = 25
anti_materiel_potential = 2
/obj/projectile/bullet/nuke/on_impact(var/atom/A)
/obj/projectile/bullet/nuke/on_hit(atom/target, blocked, def_zone)
for(var/mob/living/carbon/human/mob in GLOB.human_mob_list)
var/turf/T = get_turf(mob)
if(T && (loc.z == T.z))
if(ishuman(mob))
mob.apply_damage(250, DAMAGE_RADIATION, damage_flags = DAMAGE_FLAG_DISPERSED)
new /obj/effect/temp_visual/nuke(A.loc)
explosion(A,2,5,9)
..()
new /obj/effect/temp_visual/nuke(target.loc)
explosion(target,2,5,9)
. = ..()
/obj/projectile/bullet/shard
name = "shard"
@@ -559,9 +562,9 @@
penetrating = FALSE
var/heavy_impact_range = 1
/obj/projectile/bullet/recoilless_rifle/on_impact(var/atom/A)
explosion(A, -1, heavy_impact_range, 2)
..()
/obj/projectile/bullet/recoilless_rifle/on_hit(atom/target, blocked, def_zone)
explosion(target, -1, heavy_impact_range, 2)
. = ..()
/obj/projectile/bullet/peac
name = "anti-tank missile"
@@ -581,8 +584,10 @@
return FALSE
return ..()
/obj/projectile/bullet/peac/on_impact(var/atom/hit_atom)
explosion(hit_atom, devastation_range, heavy_impact_range, light_impact_range)
/obj/projectile/bullet/peac/on_hit(atom/target, blocked, def_zone)
. = ..()
explosion(target, devastation_range, heavy_impact_range, light_impact_range)
/obj/projectile/bullet/peac/he
name = "high-explosive missile"
@@ -600,12 +605,13 @@
light_impact_range = 1
/obj/projectile/bullet/peac/shrapnel/preparePixelProjectile()
/obj/projectile/bullet/peac/shrapnel/preparePixelProjectile(atom/target, atom/source, list/modifiers, deviation)
. = ..()
range = get_dist(firer, original)
/obj/projectile/bullet/peac/shrapnel/on_impact(var/atom/hit_atom)
..()
/obj/projectile/bullet/peac/shrapnel/on_hit(atom/target, blocked, def_zone)
. = ..()
spawn_shrapnel(starting ? get_dir(starting, original) : dir)
/obj/projectile/bullet/peac/shrapnel/proc/spawn_shrapnel(var/shrapnel_dir)
@@ -622,7 +628,9 @@
P.damage = 30
P.pellets = 4
P.range_step = 3
P.shot_from = src
P.range = 15
P.name = "shrapnel"
P.launch_projectile(T)
P.preparePixelProjectile(T, src)
P.firer = src
P.fired_from = src
P.fire()
@@ -3,11 +3,11 @@
icon_state = "ice_1"
damage = 0
damage_type = DAMAGE_BURN
nodamage = 1
check_armor = "energy"
/obj/projectile/change/on_hit(var/atom/change)
wabbajack(change)
/obj/projectile/change/on_hit(atom/target, blocked, def_zone)
. = ..()
wabbajack(target)
/obj/projectile/change/proc/wabbajack(var/mob/M)
if(istype(M, /mob/living) && M.stat != DEAD)
+26 -26
View File
@@ -16,8 +16,10 @@
var/brightness = 7
var/light_duration = 5
/obj/projectile/energy/flash/on_impact(var/atom/A, affected_limb)
var/turf/T = flash_range ? src.loc : get_turf(A)
/obj/projectile/energy/flash/on_hit(atom/target, blocked, def_zone)
. = ..()
var/turf/T = flash_range ? src.loc : get_turf(target)
if(!istype(T))
return
@@ -25,8 +27,6 @@
for(var/mob/living/M in viewers(T, flash_range))
if(M.flash_act(ignore_inherent = TRUE))
M.confused = rand(5, 15)
else if(affected_limb && M == A)
M.confused = rand(2, 7)
//snap pop
playsound(src, 'sound/effects/snap.ogg', 50, 1)
@@ -111,12 +111,12 @@
light_range = 4
light_color = "#b5ff5b"
/obj/projectile/energy/bfg/on_impact(var/atom/A)
if(ismob(A))
var/mob/M = A
/obj/projectile/energy/bfg/on_hit(atom/target, blocked, def_zone)
if(ismob(target))
var/mob/M = target
M.gib()
explosion(A, -1, 0, 5)
..()
explosion(target, -1, 0, 5)
. = ..()
/obj/projectile/energy/bfg/New()
var/matrix/M = matrix()
@@ -124,21 +124,21 @@
src.transform = M
..()
/obj/projectile/energy/bfg/after_move()
for(var/a in range(1, src))
if(isliving(a) && a != firer)
var/mob/living/M = a
if(M.stat == DEAD)
M.gib()
else
M.apply_damage(60, DAMAGE_BRUTE, BP_HEAD)
playsound(src, 'sound/magic/LightningShock.ogg', 75, 1)
else if(isturf(a) || isobj(a))
var/atom/A = a
if(!A.density)
continue
A.ex_act(2)
playsound(src, 'sound/magic/LightningShock.ogg', 75, 1)
// /obj/projectile/energy/bfg/after_move()
// for(var/a in range(1, src))
// if(isliving(a) && a != firer)
// var/mob/living/M = a
// if(M.stat == DEAD)
// M.gib()
// else
// M.apply_damage(60, DAMAGE_BRUTE, BP_HEAD)
// playsound(src, 'sound/magic/LightningShock.ogg', 75, 1)
// else if(isturf(a) || isobj(a))
// var/atom/A = a
// if(!A.density)
// continue
// A.ex_act(2)
// playsound(src, 'sound/magic/LightningShock.ogg', 75, 1)
/obj/projectile/energy/gravitydisabler
name = "gravity disabler"
@@ -153,7 +153,7 @@
light_range = 4
light_color = "#b5ff5b"
/obj/projectile/energy/gravitydisabler/on_impact(atom/target)
/obj/projectile/energy/gravitydisabler/on_hit(atom/target, blocked, def_zone)
. = ..()
var/area/A = get_area(target)
if(A && A.has_gravity())
@@ -176,7 +176,7 @@
damage_flags = DAMAGE_FLAG_LASER
pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE | PASSRAILING
muzzle_type = /obj/effect/projectile/muzzle/bolt
hit_effect = /obj/effect/temp_visual/blaster_effect
impact_effect_type = /obj/effect/temp_visual/blaster_effect
/obj/projectile/energy/blaster/disruptor
damage = 20
+7 -5
View File
@@ -10,13 +10,15 @@
name = "force bolt"
icon_state = "bluespace"
/obj/projectile/forcebolt/on_hit(var/atom/movable/target, var/blocked = 0)
if(istype(target))
/obj/projectile/forcebolt/on_hit(atom/target, blocked, def_zone)
. = ..()
if(ismovable(target))
var/atom/movable/M = target
var/throwdir = get_dir(firer,target)
target.throw_at(get_edge_target_turf(target, throwdir),10,10)
return 1
M.throw_at(get_edge_target_turf(target, throwdir),10,10)
return BULLET_ACT_HIT
/obj/projectile/forcebolt/strong/on_hit(var/atom/target, var/blocked = 0)
/obj/projectile/forcebolt/strong/on_hit(atom/target, blocked, def_zone)
for(var/mob/M in hearers(2, src))
if(M.loc != src.loc)
var/throwdir = get_dir(firer,target)
+40 -37
View File
@@ -7,12 +7,16 @@
check_armor = "energy"
var/pulse_range = 1
/obj/projectile/ion/on_impact(var/atom/A)
empulse(A, pulse_range, pulse_range)
/obj/projectile/ion/on_hit(atom/target, blocked, def_zone)
. = ..()
/obj/projectile/ion/stun/on_impact(var/atom/A)
if(isipc(A))
var/mob/living/carbon/human/H = A
empulse(target, pulse_range, pulse_range)
/obj/projectile/ion/stun/on_hit(atom/target, blocked, def_zone)
. = ..()
if(isipc(target))
var/mob/living/carbon/human/H = target
var/obj/item/organ/internal/surge/s = H.internal_organs_by_name["surge"]
if(!isnull(s))
if(s.surge_left >= 0.5)
@@ -28,8 +32,8 @@
return
else
to_chat(src, SPAN_DANGER("Warning: EMP detected, integrated surge prevention module is fried and unable to protect from EMP. Replacement recommended."))
if (isrobot(A))
var/mob/living/silicon/robot/R = A
if (isrobot(target))
var/mob/living/silicon/robot/R = target
var/datum/robot_component/surge/C = R.components["surge"]
if(C && C.installed)
if(C.surge_left >= 0.5)
@@ -48,7 +52,7 @@
R.emp_act(EMP_LIGHT) // Borgs emp_act is 1-2
else
A.emp_act(EMP_LIGHT)
target.emp_act(EMP_LIGHT)
return
/obj/projectile/ion/small
@@ -71,16 +75,18 @@
sharp = 1
edge = TRUE
/obj/projectile/bullet/gyro/on_impact(var/atom/A)
explosion(A, -1, 0, 2)
..()
/obj/projectile/bullet/gyro/on_hit(atom/target, blocked, def_zone)
explosion(target, -1, 0, 2)
. = ..()
/obj/projectile/bullet/gyro/law
name ="high-ex round"
icon_state= "bolter"
damage = 15
/obj/projectile/bullet/gyro/law/on_hit(var/atom/target, var/blocked = 0)
/obj/projectile/bullet/gyro/law/on_hit(atom/target, blocked, def_zone)
. = ..()
explosion(target, -1, 0, 2)
var/obj/T = target
var/throwdir = get_dir(firer,target)
@@ -92,12 +98,12 @@
icon_state = "ice_2"
damage = 0
damage_type = DAMAGE_BURN
nodamage = 1
check_armor = "energy"
//var/temperature = 300
/obj/projectile/temp/on_hit(var/atom/target, var/blocked = 0)//These two could likely check temp protection on the mob
/obj/projectile/temp/on_hit(atom/target, blocked, def_zone)//These two could likely check temp protection on the mob
. = ..()
if(istype(target, /mob/living))
var/mob/M = target
M.bodytemperature = -273
@@ -109,7 +115,6 @@
icon_state = "small1"
damage = 0
damage_type = DAMAGE_BRUTE
nodamage = 1
check_armor = "bullet"
/obj/projectile/meteor/Collide(atom/A)
@@ -136,7 +141,6 @@
icon_state = "energy"
damage = 0
damage_type = DAMAGE_TOXIN
nodamage = 1
check_armor = "energy"
/obj/projectile/energy/floramut/gene
@@ -144,10 +148,10 @@
icon_state = "energy2"
damage = 0
damage_type = DAMAGE_TOXIN
nodamage = TRUE
var/singleton/plantgene/gene = null
/obj/projectile/energy/floramut/on_hit(var/atom/target, var/blocked = 0)
/obj/projectile/energy/floramut/on_hit(atom/target, blocked, def_zone)
. = ..()
var/mob/living/M = target
if(ishuman(target))
var/mob/living/carbon/human/H = M
@@ -177,10 +181,10 @@
icon_state = "energy2"
damage = 0
damage_type = DAMAGE_TOXIN
nodamage = 1
check_armor = "energy"
/obj/projectile/energy/florayield/on_hit(var/atom/target, var/blocked = 0)
/obj/projectile/energy/florayield/on_hit(atom/target, blocked, def_zone)
. = ..()
var/mob/M = target
if(ishuman(target)) //These rays make plantmen fat.
var/mob/living/carbon/human/H = M
@@ -195,7 +199,8 @@
/obj/projectile/beam/mindflayer
name = "flayer ray"
/obj/projectile/beam/mindflayer/on_hit(var/atom/target, var/blocked = 0)
/obj/projectile/beam/mindflayer/on_hit(atom/target, blocked, def_zone)
. = ..()
if(ishuman(target))
var/mob/living/carbon/human/M = target
M.adjustBrainLoss(5)
@@ -209,16 +214,15 @@
sharp = 1
edge = TRUE
/obj/projectile/bullet/trod/on_impact(var/atom/A)
explosion(A, 0, 0, 4)
..()
/obj/projectile/bullet/trod/on_hit(atom/target, blocked, def_zone)
explosion(target, 0, 0, 4)
. = ..()
/obj/projectile/chameleon
name = "bullet"
icon_state = "bullet"
damage = 1 // stop trying to murderbone with a fake gun dumbass!!!
damage = 0 // stop trying to murderbone with a fake gun dumbass!!!
embed = 0 // nope
nodamage = 1
damage_type = DAMAGE_PAIN
muzzle_type = /obj/effect/projectile/muzzle/bullet
@@ -230,9 +234,9 @@
armor_penetration = 80
penetrating = 1
/obj/projectile/bullet/cannon/on_impact(var/atom/A)
explosion(A, 1, 2, 3, 3)
..()
/obj/projectile/bullet/cannon/on_hit(atom/target, blocked, def_zone)
explosion(target, 1, 2, 3, 3)
. = ..()
//magic
@@ -251,9 +255,9 @@
damage = 20
damage_type = DAMAGE_BURN
/obj/projectile/magic/fireball/on_impact(var/atom/A)
explosion(A, 0, 0, 4)
..()
/obj/projectile/magic/fireball/on_hit(atom/target, blocked, def_zone)
explosion(target, 0, 0, 4)
. = ..()
/obj/projectile/magic/teleport //literaly bluespace crystal code, because i am lazy and it seems to work
name = "bolt of teleportation"
@@ -261,12 +265,12 @@
icon_state = "energy2"
var/blink_range = 8
/obj/projectile/magic/teleport/on_hit(var/atom/hit_atom)
var/turf/T = get_turf(hit_atom)
/obj/projectile/magic/teleport/on_hit(atom/target, blocked, def_zone)
var/turf/T = get_turf(target)
single_spark(T)
playsound(src.loc, /singleton/sound_category/spark_sound, 50, 1)
if(isliving(hit_atom))
blink_mob(hit_atom)
if(isliving(target))
blink_mob(target)
return ..()
/obj/projectile/magic/teleport/proc/blink_mob(mob/living/L)
@@ -316,7 +320,6 @@
damage = 35
damage_type = DAMAGE_BRUTE
impact_sounds = list(BULLET_IMPACT_MEAT = SOUNDS_BULLET_MEAT, BULLET_IMPACT_METAL = SOUNDS_BULLET_METAL)
nodamage = FALSE
check_armor = "melee"
embed = TRUE
sharp = TRUE
+7 -6
View File
@@ -10,16 +10,16 @@
trace.obj_flags = obj_flags
trace.pass_flags = pass_flags
return trace.launch_projectile(target) //Test it!
trace.preparePixelProjectile(target, firer)
trace.firer = firer
/obj/projectile/proc/_check_fire(atom/target as mob, mob/living/user as mob) //Checks if you can hit them or not.
check_trajectory(target, user, pass_flags, obj_flags)
return trace.fire()
//"Tracing" projectile
/obj/projectile/test //Used to see if you can hit them.
invisibility = 101 //Nope! Can't see me!
invisibility = INVISIBILITY_ABSTRACT //Nope! Can't see me!
hitscan = TRUE
nodamage = TRUE
do_not_log = TRUE
damage = 0
var/list/hit = list()
@@ -34,5 +34,6 @@
hit |= A
return ..()
/obj/projectile/test/attack_mob()
/obj/projectile/test/on_hit(atom/target, blocked, def_zone)
SHOULD_CALL_PARENT(FALSE)
return