mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-22 20:43:10 +01:00
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:
@@ -6,6 +6,15 @@ They should also be used for when you want to effect the ENTIRE mob, like having
|
||||
/obj/aura
|
||||
var/mob/living/user
|
||||
|
||||
/obj/aura/Initialize(mapload, ...)
|
||||
. = ..()
|
||||
RegisterSignal(src, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(handle_bullet_act))
|
||||
|
||||
/obj/aura/proc/handle_bullet_act(datum/source, obj/projectile/projectile)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
return COMPONENT_BULLET_BLOCKED
|
||||
|
||||
/obj/aura/Destroy()
|
||||
if(user)
|
||||
user.remove_aura(src)
|
||||
@@ -24,8 +33,5 @@ They should also be used for when you want to effect the ENTIRE mob, like having
|
||||
/obj/aura/attackby(obj/item/attacking_item, mob/user)
|
||||
return FALSE
|
||||
|
||||
/obj/aura/bullet_act(obj/projectile/P, def_zone)
|
||||
return FALSE
|
||||
|
||||
/obj/aura/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
return FALSE
|
||||
|
||||
@@ -3,13 +3,23 @@
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "shield"
|
||||
|
||||
/obj/aura/personal_shield/handle_bullet_act(datum/source, obj/projectile/projectile)
|
||||
user.visible_message(SPAN_WARNING("\The [user]'s [src.name] flashes before \the [projectile] can hit them!"))
|
||||
|
||||
flick("shield_impact", src)
|
||||
playsound(user, 'sound/effects/basscannon.ogg', 35, TRUE)
|
||||
|
||||
return COMPONENT_BULLET_BLOCKED
|
||||
|
||||
/obj/aura/personal_shield/added_to(mob/living/L)
|
||||
..()
|
||||
playsound(user, 'sound/weapons/flash.ogg', 35, 1)
|
||||
to_chat(user, SPAN_NOTICE("You feel your body prickle as \the [src] comes online."))
|
||||
|
||||
/obj/aura/personal_shield/bullet_act(obj/projectile/P, var/def_zone)
|
||||
user.visible_message(SPAN_WARNING("\The [user]'s [src.name] flashes before \the [P] can hit them!"))
|
||||
/obj/aura/personal_shield/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
SHOULD_CALL_PARENT(FALSE) //Ancient coders deserve the rope
|
||||
|
||||
user.visible_message(SPAN_WARNING("\The [user]'s [src.name] flashes before \the [hitting_projectile] can hit them!"))
|
||||
|
||||
flick("shield_impact", src)
|
||||
playsound(user, 'sound/effects/basscannon.ogg', 35, TRUE)
|
||||
|
||||
@@ -5,6 +5,11 @@
|
||||
alpha = 75
|
||||
layer = ABOVE_WINDOW_LAYER
|
||||
|
||||
/obj/aura/radiant_aura/handle_bullet_act(datum/source, obj/projectile/projectile)
|
||||
if(projectile.check_armor == LASER)
|
||||
user.visible_message(SPAN_WARNING("\The [projectile] refracts, bending into \the [user]'s aura."))
|
||||
return COMPONENT_BULLET_BLOCKED
|
||||
|
||||
/obj/aura/radiant_aura/added_to(mob/living/user)
|
||||
..()
|
||||
to_chat(user, SPAN_NOTICE("A bubble of light appears around you, exuding protection and warmth."))
|
||||
@@ -14,8 +19,10 @@
|
||||
to_chat(user, SPAN_WARNING("Your protective aura dissipates, leaving you feeling cold and unsafe."))
|
||||
return ..()
|
||||
|
||||
/obj/aura/radiant_aura/bullet_act(obj/projectile/P, var/def_zone)
|
||||
if(P.check_armor == LASER)
|
||||
user.visible_message(SPAN_WARNING("\The [P] refracts, bending into \the [user]'s aura."))
|
||||
/obj/aura/radiant_aura/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
SHOULD_CALL_PARENT(FALSE) //Ancient coders deserve the rope
|
||||
|
||||
if(hitting_projectile.check_armor == LASER)
|
||||
user.visible_message(SPAN_WARNING("\The [hitting_projectile] refracts, bending into \the [user]'s aura."))
|
||||
return AURA_FALSE
|
||||
return FALSE
|
||||
|
||||
@@ -170,7 +170,11 @@
|
||||
/obj/structure/foamedmetal/ex_act(severity)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/foamedmetal/bullet_act()
|
||||
/obj/structure/foamedmetal/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
if(metal == 1 || prob(50))
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -184,11 +184,17 @@ steam.start() -- spawns the effect
|
||||
M.coughedtime = 0
|
||||
|
||||
/obj/effect/effect/smoke/bad/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group || (height==0)) return 1
|
||||
if(air_group || (height==0))
|
||||
return TRUE
|
||||
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
|
||||
if(istype(mover, /obj/projectile/beam))
|
||||
var/obj/projectile/beam/B = mover
|
||||
B.damage = (B.damage/2)
|
||||
return 1
|
||||
|
||||
return TRUE
|
||||
/////////////////////////////////////////////
|
||||
// Sleep smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
light_range = 2
|
||||
light_color = "#00ffff"
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
appearance_flags = 0
|
||||
appearance_flags = LONG_GLIDE
|
||||
|
||||
/obj/effect/projectile/singularity_pull()
|
||||
return
|
||||
@@ -40,7 +40,7 @@
|
||||
apply_vars(angle_override, p_x, p_y, color_override, scaling)
|
||||
return ..()
|
||||
|
||||
/obj/effect/projectile/proc/apply_vars(angle_override, p_x = 0, p_y = 0, color_override, scaling = 1, new_loc, increment = 0)
|
||||
/obj/effect/projectile/proc/apply_vars(angle_override, p_x = 0, p_y = 0, color_override, scaling = 1, atom/new_loc, increment = 0)
|
||||
var/mutable_appearance/look = new(src)
|
||||
look.pixel_x = p_x
|
||||
look.pixel_y = p_y
|
||||
@@ -49,8 +49,16 @@
|
||||
appearance = look
|
||||
scale_to(1,scaling, FALSE)
|
||||
turn_to(angle_override, FALSE)
|
||||
if(!isnull(new_loc)) //If you want to null it just delete it...
|
||||
if(!isnull(new_loc)) //If you want to null it just delete it...
|
||||
forceMove(new_loc)
|
||||
for(var/i in 1 to increment)
|
||||
pixel_x += round((sin(angle_override)+16*sin(angle_override)*2), 1)
|
||||
pixel_y += round((cos(angle_override)+16*cos(angle_override)*2), 1)
|
||||
|
||||
/obj/effect/projectile_lighting
|
||||
var/owner
|
||||
|
||||
/obj/effect/projectile_lighting/Initialize(mapload, color, range, intensity, owner_key)
|
||||
. = ..()
|
||||
set_light(range, intensity, color)
|
||||
owner = owner_key
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
/proc/generate_tracer_between_points(datum/point/starting, datum/point/ending, beam_type, color, qdel_in = 5) //Do not pass z-crossing points as that will not be properly (and likely will never be properly until it's absolutely needed) supported!
|
||||
/proc/generate_tracer_between_points(datum/point/starting, datum/point/ending, beam_type, color, qdel_in = 5, light_range = 2, light_color_override, light_intensity = 1, instance_key) //Do not pass z-crossing points as that will not be properly (and likely will never be properly until it's absolutely needed) supported!
|
||||
if(!istype(starting) || !istype(ending) || !ispath(beam_type))
|
||||
return
|
||||
if(starting.z != ending.z)
|
||||
crash_with("Projectile tracer generation of cross-Z beam detected. This feature is not supported!") //Do it anyways though.
|
||||
var/datum/point/midpoint = point_midpoint_points(starting, ending)
|
||||
var/obj/effect/projectile/tracer/PB = new beam_type
|
||||
if(isnull(light_color_override))
|
||||
light_color_override = color
|
||||
PB.apply_vars(angle_between_points(starting, ending), midpoint.return_px(), midpoint.return_py(), color, pixel_length_between_points(starting, ending) / world.icon_size, midpoint.return_turf(), 0)
|
||||
. = PB
|
||||
if(light_range > 0 && light_intensity > 0)
|
||||
var/list/turf/line = get_line(starting.return_turf(), ending.return_turf())
|
||||
tracing_line:
|
||||
for(var/i in line)
|
||||
var/turf/T = i
|
||||
for(var/obj/effect/projectile_lighting/PL in T)
|
||||
if(PL.owner == instance_key)
|
||||
continue tracing_line
|
||||
QDEL_IN(new /obj/effect/projectile_lighting(T, light_color_override, light_range, light_intensity, instance_key), qdel_in > 0? qdel_in : 5)
|
||||
line = null
|
||||
if(qdel_in)
|
||||
QDEL_IN(PB, qdel_in)
|
||||
|
||||
|
||||
@@ -37,9 +37,12 @@
|
||||
health -= damage
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/spider/bullet_act(var/obj/projectile/Proj)
|
||||
..()
|
||||
health -= Proj.get_structure_damage()
|
||||
/obj/effect/spider/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
health -= hitting_projectile.get_structure_damage()
|
||||
healthcheck()
|
||||
|
||||
/obj/effect/spider/proc/healthcheck()
|
||||
@@ -69,6 +72,8 @@
|
||||
/obj/effect/spider/stickyweb/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group || height == 0)
|
||||
return TRUE
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover, /mob/living/simple_animal/hostile/giant_spider))
|
||||
return TRUE
|
||||
else if(istype(mover, /mob/living))
|
||||
|
||||
@@ -776,12 +776,17 @@ var/list/global/slot_flags_enumeration = list(
|
||||
/obj/item/proc/ui_action_click()
|
||||
attack_self(usr)
|
||||
|
||||
//RETURN VALUES
|
||||
//handle_shield
|
||||
//Return a negative value corresponding to the degree an attack is blocked. PROJECTILE_STOPPED stops the attack entirely, and is the default for projectile and non-projectile attacks
|
||||
//Otherwise should return 0 to indicate that the attack is not affected in any way.
|
||||
/**
|
||||
* Called when a mob is hit by a projectile, item or by an attack
|
||||
*
|
||||
* Return one of the `BULLET_ACT_*` defines
|
||||
*
|
||||
* BULLET_ACT_HIT will let the attack continue, BULLET_ACT_BLOCK will block the attack
|
||||
*/
|
||||
/obj/item/proc/handle_shield(mob/user, var/on_back, var/damage, atom/damage_source = null, mob/attacker = null, var/def_zone = null, var/attack_text = "the attack")
|
||||
return FALSE
|
||||
SHOULD_NOT_SLEEP(TRUE)
|
||||
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
/obj/item/proc/can_shield_back()
|
||||
return
|
||||
|
||||
@@ -291,8 +291,11 @@
|
||||
t_air.merge(inside_air)
|
||||
|
||||
// When we shoot bubble, make it rip.
|
||||
/obj/structure/closet/airbubble/bullet_act(var/obj/projectile/Proj)
|
||||
..()
|
||||
/obj/structure/closet/airbubble/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
ripped = TRUE
|
||||
update_icon()
|
||||
|
||||
|
||||
@@ -120,10 +120,13 @@
|
||||
to_chat(M, SPAN_WARNING("Your chameleon-projector deactivates."))
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/bullet_act()
|
||||
/obj/effect/dummy/chameleon/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
for(var/mob/M in src)
|
||||
to_chat(M, SPAN_WARNING("Your chameleon-projector deactivates."))
|
||||
..()
|
||||
master.disrupt()
|
||||
|
||||
/obj/effect/dummy/chameleon/relaymove(mob/living/user, direction)
|
||||
|
||||
@@ -107,9 +107,12 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/device/magnetic_lock/bullet_act(var/obj/projectile/Proj)
|
||||
takedamage(Proj.damage)
|
||||
..()
|
||||
/obj/item/device/magnetic_lock/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
takedamage(hitting_projectile.damage)
|
||||
|
||||
/obj/item/device/magnetic_lock/attackby(obj/item/attacking_item, mob/user)
|
||||
if (status == STATUS_BROKEN)
|
||||
|
||||
@@ -48,15 +48,17 @@
|
||||
desc = "A shooting target with a threatening silhouette."
|
||||
hp = 2350 // alium onest too kinda
|
||||
|
||||
/obj/item/target/bullet_act(var/obj/projectile/Proj)
|
||||
var/p_x = Proj.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!"
|
||||
var/p_y = Proj.p_y + pick(0,0,0,0,0,-1,1)
|
||||
var/decaltype = (Proj.damage_flags & DAMAGE_FLAG_BULLET) ? DECAL_BULLET : DECAL_SCORCH
|
||||
/obj/item/target/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
SHOULD_CALL_PARENT(FALSE) //Ancient coders deserve the rope
|
||||
|
||||
var/p_x = hitting_projectile.p_x + pick(0,0,0,0,0,-1,1) // really ugly way of coding "sometimes offset Proj.p_x!"
|
||||
var/p_y = hitting_projectile.p_y + pick(0,0,0,0,0,-1,1)
|
||||
var/decaltype = (hitting_projectile.damage_flags & DAMAGE_FLAG_BULLET) ? DECAL_BULLET : DECAL_SCORCH
|
||||
|
||||
virtual_icon = new(icon, icon_state)
|
||||
|
||||
if(virtual_icon.GetPixel(p_x, p_y)) // if the located pixel isn't blank (null)
|
||||
hp -= Proj.damage
|
||||
hp -= hitting_projectile.damage
|
||||
if(hp <= 0)
|
||||
visible_message(SPAN_WARNING("\The [src] breaks into tiny pieces and collapses!"))
|
||||
qdel(src)
|
||||
@@ -75,7 +77,7 @@
|
||||
bmark.pixel_x--
|
||||
bmark.pixel_y--
|
||||
|
||||
if(Proj.damage >= 20 || istype(Proj, /obj/projectile/beam/practice))
|
||||
if(hitting_projectile.damage >= 20 || istype(hitting_projectile, /obj/projectile/beam/practice))
|
||||
bmark.icon_state = "scorch"
|
||||
bmark.set_dir(pick(NORTH,SOUTH,EAST,WEST)) // random scorch design
|
||||
else
|
||||
@@ -83,12 +85,12 @@
|
||||
else // Bullets are hard. They make dents!
|
||||
bmark.icon_state = "dent"
|
||||
|
||||
if(Proj.damage >= 10 && length(bullet_holes) <= 35) // maximum of 35 bullet holes
|
||||
if(hitting_projectile.damage >= 10 && length(bullet_holes) <= 35) // maximum of 35 bullet holes
|
||||
if(decaltype == DECAL_BULLET)
|
||||
if(prob(Proj.damage+30)) // bullets make holes more commonly!
|
||||
if(prob(hitting_projectile.damage+30)) // bullets make holes more commonly!
|
||||
new /datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole
|
||||
else // Lasers!
|
||||
if(prob(Proj.damage-10)) // lasers make holes less commonly
|
||||
if(prob(hitting_projectile.damage-10)) // lasers make holes less commonly
|
||||
new /datum/bullethole(src, bmark.pixel_x, bmark.pixel_y) // create new bullet hole
|
||||
|
||||
// draw bullet holes
|
||||
@@ -101,7 +103,7 @@
|
||||
icon = virtual_icon // apply bullet_holes over decals
|
||||
return
|
||||
|
||||
return PROJECTILE_CONTINUE // the bullet/projectile goes through the target!
|
||||
return BULLET_ACT_HIT // the bullet/projectile goes through the target!
|
||||
|
||||
|
||||
// Small memory holder entity for transparent bullet holes
|
||||
|
||||
@@ -168,7 +168,11 @@
|
||||
if(prob(50))
|
||||
qdel(src)
|
||||
|
||||
/obj/item/toy/balloon/bullet_act()
|
||||
/obj/item/toy/balloon/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
burst()
|
||||
|
||||
/obj/item/toy/balloon/fire_act(temperature, volume)
|
||||
|
||||
@@ -12,20 +12,23 @@
|
||||
P.damage = p_dam
|
||||
P.pellets = fragments_per_projectile
|
||||
P.range_step = p_range
|
||||
P.shot_from = source
|
||||
P.range = shard_range
|
||||
P.name = "shrapnel"
|
||||
|
||||
P.launch_projectile(T)
|
||||
P.preparePixelProjectile(T, get_turf(source))
|
||||
P.firer = source
|
||||
P.fired_from = source
|
||||
P.fire()
|
||||
|
||||
if(can_cover)
|
||||
for(var/mob/living/M in O)
|
||||
//lying on a frag grenade while the grenade is on the ground causes you to absorb most of the shrapnel.
|
||||
//you will most likely be dead, but others nearby will be spared the fragments that hit you instead.
|
||||
if(M.lying && isturf(get_turf(source)))
|
||||
P.attack_mob(M, 0, 0)
|
||||
P.process_hit(get_turf(M), M)
|
||||
else
|
||||
P.attack_mob(M, 0, 100) //otherwise, allow a decent amount of fragments to pass
|
||||
if(prob(20))
|
||||
P.process_hit(get_turf(M), M)
|
||||
|
||||
//Fragmentation grenade projectile
|
||||
/obj/projectile/bullet/pellet/fragment
|
||||
|
||||
@@ -38,18 +38,21 @@
|
||||
P.damage = p_dam
|
||||
P.balls = fragments_per_projectile
|
||||
P.range_step = p_range
|
||||
P.shot_from = source
|
||||
P.range = shard_range
|
||||
P.name = "rubber ball"
|
||||
|
||||
P.launch_projectile(T)
|
||||
P.preparePixelProjectile(T, get_turf(source))
|
||||
P.firer = source
|
||||
P.fired_from = source
|
||||
P.fire()
|
||||
|
||||
if(can_cover)
|
||||
for(var/mob/living/M in O)
|
||||
if(M.lying && isturf(get_turf(source)))
|
||||
P.attack_mob(M, 0, 0)
|
||||
P.process_hit(get_turf(M), M)
|
||||
else
|
||||
P.attack_mob(M, 0, 100)
|
||||
if(prob(20))
|
||||
P.process_hit(get_turf(M), M)
|
||||
|
||||
/obj/item/grenade/stinger/prime()
|
||||
..()
|
||||
|
||||
@@ -176,7 +176,11 @@
|
||||
else if(attacking_item.force > 10 && deployed)
|
||||
trigger(user)
|
||||
|
||||
/obj/item/landmine/bullet_act()
|
||||
/obj/item/landmine/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
if(deployed)
|
||||
trigger()
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
if(default_parry_check(user, attacker, damage_source) && prob(parry_chance * parry_bonus))
|
||||
user.visible_message(SPAN_DANGER("\The [user] parries [attack_text] with \the [src]!"))
|
||||
playsound(user.loc, 'sound/weapons/bladeparry.ogg', 50, 1)
|
||||
return PROJECTILE_STOPPED
|
||||
return FALSE
|
||||
return BULLET_ACT_BLOCK
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
/obj/item/material/sword/perform_technique(var/mob/living/carbon/human/target, var/mob/living/carbon/human/user, var/target_zone)
|
||||
var/armor_reduction = target.get_blocked_ratio(target_zone, DAMAGE_BRUTE, DAMAGE_FLAG_EDGE|DAMAGE_FLAG_SHARP, damage = force)*100
|
||||
|
||||
@@ -97,8 +97,8 @@
|
||||
if(wielded && default_parry_check(user, attacker, damage_source) && prob(parry_chance))
|
||||
user.visible_message(SPAN_DANGER("\The [user] parries [attack_text] with \the [src]!"))
|
||||
playsound(user.loc, /singleton/sound_category/punchmiss_sound, 50, 1)
|
||||
return PROJECTILE_STOPPED
|
||||
return FALSE
|
||||
return BULLET_ACT_BLOCK
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
/obj/item/material/twohanded/update_icon()
|
||||
icon_state = "[base_icon][wielded]"
|
||||
|
||||
@@ -67,13 +67,13 @@
|
||||
user.visible_message(SPAN_DANGER("\The [user] parries [attack_text] with \the [src]!"))
|
||||
spark(src, 5)
|
||||
playsound(user.loc, 'sound/weapons/blade.ogg', 50, 1)
|
||||
return PROJECTILE_STOPPED
|
||||
return BULLET_ACT_BLOCK
|
||||
else
|
||||
if(!active)
|
||||
return FALSE //turn it on first!
|
||||
return BULLET_ACT_HIT //turn it on first!
|
||||
|
||||
if(user.incapacitated())
|
||||
return FALSE
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
//block as long as they are not directly behind us
|
||||
var/bad_arc = reverse_direction(user.dir) //arc of directions from which we cannot block
|
||||
@@ -87,7 +87,7 @@
|
||||
if(shield_power <= 0)
|
||||
to_chat(user, SPAN_DANGER("\The [src]'s integrated shield goes out! It will no longer assist in parrying."))
|
||||
shield_power = 0
|
||||
return FALSE
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
if(istype(damage_source, /obj/projectile/energy) || istype(damage_source, /obj/projectile/beam))
|
||||
var/obj/projectile/P = damage_source
|
||||
@@ -106,10 +106,10 @@
|
||||
P.firer = user
|
||||
P.old_style_target(locate(new_x, new_y, P.z))
|
||||
|
||||
return PROJECTILE_CONTINUE // complete projectile permutation
|
||||
return BULLET_ACT_FORCE_PIERCE // complete projectile permutation
|
||||
else
|
||||
user.visible_message(SPAN_DANGER("\The [user] blocks [attack_text] with \the [src]!"))
|
||||
return PROJECTILE_STOPPED
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
else if(istype(damage_source, /obj/projectile/bullet) && can_block_bullets)
|
||||
var/reflectchance = (base_reflectchance) - round(damage/3)
|
||||
@@ -117,7 +117,7 @@
|
||||
reflectchance /= 2
|
||||
if(prob(reflectchance))
|
||||
user.visible_message(SPAN_DANGER("\The [user] blocks [attack_text] with \the [src]!"))
|
||||
return PROJECTILE_STOPPED
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
/obj/item/melee/energy/get_print_info()
|
||||
. = ..()
|
||||
|
||||
@@ -43,12 +43,12 @@
|
||||
var/shield_dir = on_back ? user.dir : GLOB.reverse_dir[user.dir]
|
||||
|
||||
if(user.incapacitated() || !(check_shield_arc(user, shield_dir, damage_source, attacker)))
|
||||
return FALSE
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
if(prob(get_block_chance(user, damage, damage_source, attacker)))
|
||||
user.visible_message(SPAN_DANGER("\The [user] blocks [attack_text] with \the [src]!"))
|
||||
return PROJECTILE_STOPPED
|
||||
return FALSE
|
||||
return BULLET_ACT_BLOCK
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
/obj/item/shield/can_shield_back()
|
||||
return TRUE
|
||||
@@ -74,7 +74,8 @@
|
||||
|
||||
/obj/item/shield/riot/handle_shield(mob/user)
|
||||
. = ..()
|
||||
if(.) playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
if(. != BULLET_ACT_HIT)
|
||||
playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
|
||||
/obj/item/shield/riot/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null)
|
||||
if(istype(damage_source, /obj/projectile))
|
||||
@@ -113,7 +114,8 @@
|
||||
|
||||
/obj/item/shield/buckler/handle_shield(mob/user)
|
||||
. = ..()
|
||||
if(.) playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
if(. != BULLET_ACT_HIT)
|
||||
playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
|
||||
/obj/item/shield/buckler/get_block_chance(mob/user, var/damage, atom/damage_source = null, mob/attacker = null)
|
||||
if(istype(damage_source, /obj/projectile))
|
||||
@@ -178,9 +180,7 @@
|
||||
var/shield_dir = on_back ? user.dir : GLOB.reverse_dir[user.dir]
|
||||
|
||||
if(!active || user.incapacitated() || !(check_shield_arc(user, shield_dir, damage_source, attacker)))
|
||||
return FALSE
|
||||
if(.)
|
||||
spark(user.loc, 5)
|
||||
return BULLET_ACT_HIT
|
||||
|
||||
if(prob(get_block_chance(user, damage, damage_source, attacker)))
|
||||
spark(user.loc, 5)
|
||||
@@ -214,13 +214,13 @@
|
||||
new_angle_s -= 360
|
||||
P.set_angle(new_angle_s)
|
||||
|
||||
return PROJECTILE_CONTINUE // complete projectile permutation
|
||||
return BULLET_ACT_FORCE_PIERCE // complete projectile permutation
|
||||
else
|
||||
user.visible_message(SPAN_DANGER("\The [user] blocks [attack_text] with \the [src]!"))
|
||||
return PROJECTILE_STOPPED
|
||||
return BULLET_ACT_BLOCK
|
||||
else
|
||||
user.visible_message(SPAN_DANGER("\The [user] blocks [attack_text] with \the [src]!"))
|
||||
return PROJECTILE_STOPPED
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
|
||||
/obj/item/shield/energy/get_block_chance(mob/user, damage, atom/damage_source = null, mob/attacker = null)
|
||||
@@ -323,11 +323,11 @@
|
||||
|
||||
/obj/item/shield/riot/tact/handle_shield(mob/user)
|
||||
if(!active)
|
||||
return FALSE //turn it on first!
|
||||
return BULLET_ACT_HIT //turn it on first!
|
||||
|
||||
. = ..()
|
||||
if(.)
|
||||
if(.) playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
if(. != BULLET_ACT_HIT)
|
||||
playsound(user.loc, 'sound/weapons/Genhit.ogg', 50, 1)
|
||||
|
||||
/obj/item/shield/riot/tact/attack_self(mob/living/user)
|
||||
active = !active
|
||||
|
||||
@@ -582,10 +582,14 @@
|
||||
new /obj/item/stack/material/steel(get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
/obj/item/trap/animal/bullet_act(var/obj/projectile/Proj)
|
||||
/obj/item/trap/animal/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
var/mob/living/captured_mob = captured ? captured.resolve() : null
|
||||
if(captured_mob)
|
||||
captured_mob.bullet_act(Proj)
|
||||
captured_mob.bullet_act(arglist(args))
|
||||
|
||||
/obj/item/trap/animal/proc/release(var/mob/user, var/turf/target)
|
||||
if(!target)
|
||||
@@ -846,6 +850,10 @@
|
||||
/obj/item/trap/animal/large/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(deployed)
|
||||
return TRUE
|
||||
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
|
||||
/obj/item/large_trap_foundation
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
if(!QDELETED(src))
|
||||
QDEL_IN(src, 1)
|
||||
|
||||
/obj/item/energy_net/throw_impact(atom/hit_atom)
|
||||
/obj/item/energy_net/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
..()
|
||||
|
||||
var/mob/living/M = hit_atom
|
||||
@@ -74,10 +74,13 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/effect/energy_net/bullet_act(var/obj/projectile/Proj)
|
||||
health -= Proj.get_structure_damage()
|
||||
/obj/effect/energy_net/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
health -= hitting_projectile.get_structure_damage()
|
||||
health_check()
|
||||
return FALSE
|
||||
|
||||
/obj/effect/energy_net/ex_act(var/severity = 2.0)
|
||||
health = 0
|
||||
|
||||
@@ -78,9 +78,12 @@
|
||||
dismantle_material.place_sheet(loc)
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/bullet_act(obj/projectile/P, def_zone)
|
||||
/obj/structure/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
bullet_ping(P)
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
bullet_ping(hitting_projectile)
|
||||
|
||||
/obj/structure/proc/climb_on()
|
||||
|
||||
|
||||
@@ -83,6 +83,8 @@
|
||||
return prob(max(30,(100.0*health)/maxhealth))
|
||||
|
||||
/obj/structure/barricade/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(air_group || (height==0))
|
||||
return TRUE
|
||||
if(istype(mover, /obj/projectile))
|
||||
@@ -197,11 +199,14 @@
|
||||
playsound(src, barricade_hitsound, 25, 1)
|
||||
hit_barricade(attacking_item, user)
|
||||
|
||||
/obj/structure/barricade/bullet_act(obj/projectile/P)
|
||||
bullet_ping(P)
|
||||
var/damage_to_take = P.damage * P.anti_materiel_potential
|
||||
/obj/structure/barricade/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
bullet_ping(hitting_projectile)
|
||||
var/damage_to_take = hitting_projectile.damage * hitting_projectile.anti_materiel_potential
|
||||
take_damage(damage_to_take)
|
||||
return TRUE
|
||||
|
||||
/obj/structure/barricade/proc/barricade_deconstruct(deconstruct)
|
||||
if(deconstruct && is_wired)
|
||||
|
||||
@@ -382,6 +382,8 @@ GLOBAL_LIST_EMPTY(total_active_bonfires)
|
||||
AddOverlays("fireplace_glow")
|
||||
|
||||
/obj/structure/bonfire/fireplace/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(get_dir(loc, target) == NORTH)
|
||||
return !density
|
||||
return TRUE
|
||||
|
||||
@@ -150,7 +150,8 @@
|
||||
return content_size
|
||||
|
||||
/obj/structure/closet/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group || (height==0 || wall_mounted)) return 1
|
||||
if(air_group || (height==0 || wall_mounted))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/structure/closet/proc/can_open()
|
||||
@@ -316,17 +317,19 @@
|
||||
new /obj/item/stack/material/steel(get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/closet/bullet_act(var/obj/projectile/Proj)
|
||||
var/proj_damage = Proj.get_structure_damage()
|
||||
/obj/structure/closet/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
var/proj_damage = hitting_projectile.get_structure_damage()
|
||||
if(!proj_damage)
|
||||
return
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
if(Proj.penetrating || istype(Proj, /obj/projectile/bullet))
|
||||
var/distance = get_dist(Proj.starting, get_turf(loc))
|
||||
if(hitting_projectile.penetrating || istype(hitting_projectile, /obj/projectile/bullet))
|
||||
for(var/mob/living/L in contents)
|
||||
Proj.attack_mob(L, distance)
|
||||
hitting_projectile.Impact(L)
|
||||
|
||||
..()
|
||||
damage(proj_damage)
|
||||
|
||||
/obj/structure/closet/attackby(obj/item/attacking_item, mob/user)
|
||||
|
||||
@@ -124,11 +124,13 @@
|
||||
for(var/mob/M in src)
|
||||
shatter(M)
|
||||
|
||||
/obj/structure/closet/statue/bullet_act(var/obj/projectile/Proj)
|
||||
health -= Proj.get_structure_damage()
|
||||
check_health()
|
||||
/obj/structure/closet/statue/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
return
|
||||
health -= hitting_projectile.get_structure_damage()
|
||||
check_health()
|
||||
|
||||
/obj/structure/closet/statue/attack_generic(var/mob/user, damage, attacktext, environment_smash)
|
||||
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
||||
|
||||
@@ -97,6 +97,8 @@
|
||||
==========================
|
||||
*/
|
||||
/obj/structure/closet/crate/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if (istype(mover, /obj/structure/closet/crate))//Handle interaction with other crates
|
||||
var/obj/structure/closet/crate/C = mover
|
||||
if (tablestatus && tablestatus != C.tablestatus) // Crates can go under tables with crates on top of them, and vice versa
|
||||
|
||||
@@ -20,12 +20,14 @@
|
||||
layer = ABOVE_HUMAN_LAYER
|
||||
opacity = 0
|
||||
|
||||
/obj/structure/curtain/bullet_act(obj/projectile/P, def_zone)
|
||||
if(!P.nodamage)
|
||||
visible_message(SPAN_WARNING("[P] tears [src] down!"))
|
||||
/obj/structure/curtain/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
if(hitting_projectile.damage > 0)
|
||||
visible_message(SPAN_WARNING("[hitting_projectile] tears [src] down!"))
|
||||
qdel(src)
|
||||
else
|
||||
..(P, def_zone)
|
||||
|
||||
/obj/structure/curtain/attack_hand(mob/user)
|
||||
playsound(get_turf(loc), 'sound/effects/curtain.ogg', 15, 1, -5)
|
||||
|
||||
@@ -34,9 +34,12 @@
|
||||
health_check()
|
||||
|
||||
|
||||
/obj/structure/displaycase/bullet_act(var/obj/projectile/Proj)
|
||||
health -= Proj.get_structure_damage()
|
||||
..()
|
||||
/obj/structure/displaycase/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
health -= hitting_projectile.get_structure_damage()
|
||||
health_check()
|
||||
|
||||
/obj/structure/displaycase/proc/health_check()
|
||||
|
||||
@@ -48,6 +48,8 @@
|
||||
/obj/structure/window_frame/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group || (height == 0))
|
||||
return TRUE
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover, /obj/structure/closet/crate))
|
||||
return TRUE
|
||||
if(istype(mover) && mover.pass_flags & PASSTABLE)
|
||||
|
||||
@@ -41,16 +41,16 @@
|
||||
health = 50
|
||||
cover = 25
|
||||
|
||||
/obj/structure/girder/bullet_act(var/obj/projectile/Proj)
|
||||
/obj/structure/girder/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
//Girders only provide partial cover. There's a chance that the projectiles will just pass through. (unless you are trying to shoot the girder)
|
||||
if(Proj.original != src && !prob(cover))
|
||||
return PROJECTILE_CONTINUE //pass through
|
||||
if(hitting_projectile.original != src && !prob(cover))
|
||||
return BULLET_ACT_HIT //pass through
|
||||
|
||||
var/damage = Proj.get_structure_damage()
|
||||
var/damage = hitting_projectile.get_structure_damage()
|
||||
if(!damage)
|
||||
return
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
if(!istype(Proj, /obj/projectile/beam))
|
||||
if(!istype(hitting_projectile, /obj/projectile/beam))
|
||||
damage *= 0.4 //non beams do reduced damage
|
||||
|
||||
take_damage(damage)
|
||||
@@ -376,6 +376,8 @@
|
||||
/obj/structure/girder/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if (!mover)
|
||||
return 1
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover,/obj/projectile) && density)
|
||||
if (prob(50))
|
||||
return 1
|
||||
|
||||
@@ -31,10 +31,13 @@
|
||||
visible_message(SPAN_WARNING(final_message))
|
||||
qdel(src)
|
||||
|
||||
/obj/structure/gore/bullet_act(var/obj/projectile/Proj)
|
||||
health -= Proj.damage
|
||||
/obj/structure/gore/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
health -= hitting_projectile.damage
|
||||
healthcheck()
|
||||
return ..()
|
||||
|
||||
/obj/structure/gore/ex_act(severity)
|
||||
switch(severity)
|
||||
@@ -78,6 +81,8 @@
|
||||
/obj/structure/gore/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group)
|
||||
return FALSE
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover) && mover.pass_flags & PASSGLASS)
|
||||
return !opacity
|
||||
return !density
|
||||
|
||||
@@ -103,45 +103,54 @@
|
||||
attack_generic(user,damage_dealt,attack_message)
|
||||
|
||||
/obj/structure/grille/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group || (height==0)) return 1
|
||||
if(air_group || (height==0))
|
||||
return TRUE
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover) && mover.pass_flags & PASSGRILLE)
|
||||
return 1
|
||||
return TRUE
|
||||
else
|
||||
if(istype(mover, /obj/projectile))
|
||||
return prob(30)
|
||||
else
|
||||
return !density
|
||||
|
||||
/obj/structure/grille/bullet_act(var/obj/projectile/Proj)
|
||||
if(!Proj) return
|
||||
/obj/structure/grille/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
if(!hitting_projectile)
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
//Flimsy grilles aren't so great at stopping projectiles. However they can absorb some of the impact
|
||||
var/damage = Proj.get_structure_damage()
|
||||
var/damage = hitting_projectile.get_structure_damage()
|
||||
var/passthrough = 0
|
||||
|
||||
if(!damage) return
|
||||
if(!damage)
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
//20% chance that the grille provides a bit more cover than usual. Support structure for example might take up 20% of the grille's area.
|
||||
//If they click on the grille itself then we assume they are aiming at the grille itself and the extra cover behaviour is always used.
|
||||
switch(Proj.damage_type)
|
||||
switch(hitting_projectile.damage_type)
|
||||
if(DAMAGE_BRUTE)
|
||||
//bullets
|
||||
if(Proj.original == src || prob(20))
|
||||
Proj.damage *= between(0, Proj.damage/60, 0.5)
|
||||
if(hitting_projectile.original == src || prob(20))
|
||||
hitting_projectile.damage *= between(0, hitting_projectile.damage/60, 0.5)
|
||||
if(prob(max((damage-10)/25, 0))*100)
|
||||
passthrough = 1
|
||||
else
|
||||
Proj.damage *= between(0, Proj.damage/60, 1)
|
||||
hitting_projectile.damage *= between(0, hitting_projectile.damage/60, 1)
|
||||
passthrough = 1
|
||||
if(DAMAGE_BURN)
|
||||
//beams and other projectiles are either blocked completely by grilles or stop half the damage.
|
||||
if(!(Proj.original == src || prob(20)))
|
||||
Proj.damage *= 0.5
|
||||
if(!(hitting_projectile.original == src || prob(20)))
|
||||
hitting_projectile.damage *= 0.5
|
||||
passthrough = 1
|
||||
|
||||
if(passthrough)
|
||||
. = PROJECTILE_CONTINUE
|
||||
damage = between(0, (damage - Proj.damage)*(Proj.damage_type == DAMAGE_BRUTE? 0.4 : 1), 10) //if the bullet passes through then the grille avoids most of the damage
|
||||
. = BULLET_ACT_HIT
|
||||
damage = between(0, (damage - hitting_projectile.damage)*(hitting_projectile.damage_type == DAMAGE_BRUTE? 0.4 : 1), 10) //if the bullet passes through then the grille avoids most of the damage
|
||||
|
||||
src.health -= damage*0.2
|
||||
spawn(0) healthcheck() //spawn to make sure we return properly if the grille is deleted
|
||||
@@ -313,7 +322,7 @@
|
||||
/obj/structure/grille/cult/CanPass(atom/movable/mover, turf/target, height = 1.5, air_group = 0)
|
||||
if(air_group)
|
||||
return 0 //Make sure air doesn't drain
|
||||
..()
|
||||
. = ..()
|
||||
|
||||
/obj/structure/grille/crescent/attack_hand()
|
||||
return
|
||||
@@ -329,6 +338,3 @@
|
||||
|
||||
/obj/structure/grille/crescent/hitby(atom/movable/hitting_atom, skipcatch, hitpush, blocked, datum/thrownthing/throwingdatum)
|
||||
return
|
||||
|
||||
/obj/structure/grille/crescent/bullet_act()
|
||||
return
|
||||
|
||||
@@ -63,13 +63,18 @@
|
||||
if(health <= 0)
|
||||
topple()
|
||||
|
||||
/obj/structure/hadii_statue/bullet_act(var/obj/projectile/Proj)
|
||||
/obj/structure/hadii_statue/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
if(toppled)
|
||||
return
|
||||
if(!Proj)
|
||||
return
|
||||
if(!Proj.damage)
|
||||
visible_message(SPAN_WARNING("\The [Proj] bounces off \the [src]!"))
|
||||
return
|
||||
visible_message(SPAN_WARNING("\The [Proj] hits \the [src]!"))
|
||||
do_integrity_check(Proj.damage)
|
||||
return BULLET_ACT_BLOCK
|
||||
if(!hitting_projectile)
|
||||
return BULLET_ACT_BLOCK
|
||||
if(!hitting_projectile.damage)
|
||||
visible_message(SPAN_WARNING("\The [hitting_projectile] bounces off \the [src]!"))
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
visible_message(SPAN_WARNING("\The [hitting_projectile] hits \the [src]!"))
|
||||
do_integrity_check(hitting_projectile.damage)
|
||||
|
||||
@@ -60,21 +60,28 @@
|
||||
return ..()
|
||||
|
||||
/obj/structure/inflatable/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
|
||||
if(isprojectile(mover))
|
||||
visible_message(SPAN_DANGER("\The [src] rapidly deflates!"))
|
||||
deflate(TRUE)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/obj/structure/inflatable/bullet_act(var/obj/projectile/Proj)
|
||||
var/proj_damage = Proj.get_structure_damage()
|
||||
/obj/structure/inflatable/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
var/proj_damage = hitting_projectile.get_structure_damage()
|
||||
if(!proj_damage)
|
||||
return
|
||||
|
||||
bullet_ping(Proj)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
bullet_ping(hitting_projectile)
|
||||
|
||||
health -= proj_damage
|
||||
..()
|
||||
|
||||
if(health <= 0)
|
||||
deflate(TRUE)
|
||||
return
|
||||
@@ -203,6 +210,8 @@
|
||||
/obj/structure/inflatable/door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group)
|
||||
return state
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover, /obj/effect/beam))
|
||||
return !opacity
|
||||
if(isprojectile(mover))
|
||||
|
||||
@@ -423,11 +423,14 @@
|
||||
return
|
||||
|
||||
/obj/structure/janitorialcart/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group || (height==0)) return 1
|
||||
if(air_group || (height==0))
|
||||
return TRUE
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover) && mover.pass_flags & PASSTABLE)
|
||||
return 1
|
||||
return TRUE
|
||||
if(istype(mover, /mob/living) && mover == pulling)
|
||||
return 1
|
||||
return TRUE
|
||||
else
|
||||
if(istype(mover, /obj/projectile))
|
||||
return prob(30)
|
||||
|
||||
@@ -67,6 +67,9 @@
|
||||
if (!mover)
|
||||
return 1
|
||||
|
||||
if(mover.movement_type & PHASING)
|
||||
return TRUE
|
||||
|
||||
if(istype(mover,/obj/projectile) && density)
|
||||
if (!occupied && prob(80))
|
||||
//Wiry frame, usually wont be cover
|
||||
|
||||
@@ -57,13 +57,16 @@
|
||||
reflection.update_mirror_filters()
|
||||
|
||||
|
||||
/obj/structure/mirror/bullet_act(var/obj/projectile/Proj)
|
||||
if(prob(Proj.get_structure_damage() * 2))
|
||||
/obj/structure/mirror/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
if(prob(hitting_projectile.get_structure_damage() * 2))
|
||||
if(!shattered)
|
||||
shatter()
|
||||
else
|
||||
playsound(src, 'sound/effects/hit_on_shattered_glass.ogg', 70, 1)
|
||||
..()
|
||||
|
||||
/obj/structure/mirror/attackby(obj/item/attacking_item, mob/user)
|
||||
if(shattered)
|
||||
|
||||
@@ -56,27 +56,30 @@
|
||||
return AIR_BLOCKED
|
||||
return FALSE
|
||||
|
||||
/obj/structure/plasticflaps/CanPass(atom/A, turf/T)
|
||||
if(istype(A) && A.pass_flags & PASSGLASS)
|
||||
/obj/structure/plasticflaps/CanPass(atom/movable/mover, turf/target)
|
||||
if(istype(mover) && mover.pass_flags & PASSGLASS)
|
||||
return prob(60)
|
||||
|
||||
var/obj/structure/bed/B = A
|
||||
if (istype(A, /obj/structure/bed) && B.buckled)//if it's a bed/chair and someone is buckled, it will not pass
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
|
||||
var/obj/structure/bed/B = mover
|
||||
if (istype(mover, /obj/structure/bed) && B.buckled)//if it's a bed/chair and someone is buckled, it will not pass
|
||||
return 0
|
||||
|
||||
if(istype(A, /obj/vehicle)) //no vehicles
|
||||
if(istype(mover, /obj/vehicle)) //no vehicles
|
||||
return 0
|
||||
|
||||
//Bots can always pass
|
||||
if(isbot(A))
|
||||
if(isbot(mover))
|
||||
return TRUE
|
||||
|
||||
var/mob/living/M = A
|
||||
var/mob/living/M = mover
|
||||
if(istype(M))
|
||||
if(M.lying)
|
||||
return ..()
|
||||
for(var/mob_type in mobs_can_pass)
|
||||
if(istype(A, mob_type))
|
||||
if(istype(mover, mob_type))
|
||||
return ..()
|
||||
return issmall(M)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
climbable = TRUE
|
||||
layer = OBJ_LAYER
|
||||
anchored = FALSE
|
||||
pass_flags_self = LETPASSTHROW|PASSSTRUCTURE
|
||||
pass_flags_self = LETPASSTHROW|PASSSTRUCTURE|PASSRAILING
|
||||
|
||||
atom_flags = ATOM_FLAG_CHECKS_BORDER
|
||||
obj_flags = OBJ_FLAG_ROTATABLE|OBJ_FLAG_MOVES_UNSUPPORTED
|
||||
@@ -88,6 +88,8 @@
|
||||
. += FONT_SMALL(SPAN_NOTICE("\The [src] is <b>[anchored ? "" : "not"] screwed</b> to the floor."))
|
||||
|
||||
/obj/structure/railing/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover,/obj/projectile))
|
||||
return TRUE
|
||||
if(!istype(mover) || mover.pass_flags & PASSRAILING)
|
||||
|
||||
@@ -86,7 +86,10 @@
|
||||
return
|
||||
|
||||
/obj/structure/simple_door/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(air_group) return 0
|
||||
if(air_group)
|
||||
return FALSE
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover, /obj/effect/beam))
|
||||
return !opacity
|
||||
return !density
|
||||
@@ -193,9 +196,13 @@
|
||||
attack_hand(user)
|
||||
return
|
||||
|
||||
/obj/structure/simple_door/bullet_act(var/obj/projectile/Proj)
|
||||
health -= Proj.damage
|
||||
bullet_ping(Proj)
|
||||
/obj/structure/simple_door/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
health -= hitting_projectile.damage
|
||||
bullet_ping(hitting_projectile)
|
||||
CheckHealth()
|
||||
|
||||
/obj/structure/simple_door/proc/CheckHealth()
|
||||
|
||||
@@ -127,9 +127,6 @@
|
||||
if(buckled)
|
||||
buckled.forceMove(dest)
|
||||
|
||||
/obj/structure/bed/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
return ..()
|
||||
|
||||
/obj/structure/bed/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
|
||||
@@ -261,6 +261,8 @@ ABSTRACT_TYPE(/obj/structure/stairs/urban/road_ramp)
|
||||
anchored = TRUE
|
||||
|
||||
/obj/structure/rod_railing/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover,/obj/projectile))
|
||||
return TRUE
|
||||
if(!istype(mover) || mover.pass_flags & PASSRAILING)
|
||||
@@ -313,6 +315,8 @@ ABSTRACT_TYPE(/obj/structure/stairs/urban/road_ramp)
|
||||
icon_state = "guard_top_end"
|
||||
|
||||
/obj/structure/road_barrier/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover,/obj/projectile))
|
||||
return TRUE
|
||||
if(!istype(mover) || mover.pass_flags & PASSRAILING)
|
||||
@@ -343,6 +347,8 @@ ABSTRACT_TYPE(/obj/structure/stairs/urban/road_ramp)
|
||||
can_be_unanchored = FALSE
|
||||
|
||||
/obj/structure/chainlink_fence/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)//So bullets will fly over and stuff.
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(air_group || (height==0))
|
||||
return TRUE
|
||||
if(istype(mover, /obj/projectile))
|
||||
@@ -378,6 +384,8 @@ ABSTRACT_TYPE(/obj/structure/stairs/urban/road_ramp)
|
||||
can_be_unanchored = FALSE
|
||||
|
||||
/obj/structure/rope_railing/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover,/obj/projectile))
|
||||
return TRUE
|
||||
if(!istype(mover) || mover.pass_flags & PASSRAILING)
|
||||
|
||||
@@ -49,6 +49,8 @@
|
||||
icon_state = "[facing]_[secure]windoor_assembly[state]"
|
||||
|
||||
/obj/structure/windoor_assembly/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover) && mover.pass_flags & PASSGLASS)
|
||||
return 1
|
||||
if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
|
||||
|
||||
@@ -138,12 +138,15 @@
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/structure/window/bullet_act(var/obj/projectile/Proj)
|
||||
var/proj_damage = Proj.get_structure_damage()
|
||||
/obj/structure/window/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
||||
var/proj_damage = hitting_projectile.get_structure_damage()
|
||||
if(!proj_damage)
|
||||
return
|
||||
return BULLET_ACT_BLOCK
|
||||
|
||||
. = ..()
|
||||
if(. != BULLET_ACT_HIT)
|
||||
return .
|
||||
|
||||
..()
|
||||
take_damage(proj_damage)
|
||||
return
|
||||
|
||||
@@ -167,6 +170,8 @@
|
||||
return (dir == SOUTHWEST || dir == SOUTHEAST || dir == NORTHWEST || dir == NORTHEAST)
|
||||
|
||||
/obj/structure/window/CanPass(atom/movable/mover, turf/target, height=0, air_group=0)
|
||||
if(mover?.movement_type & PHASING)
|
||||
return TRUE
|
||||
if(istype(mover) && mover.pass_flags & PASSGLASS)
|
||||
return 1
|
||||
if(is_full_window())
|
||||
|
||||
Reference in New Issue
Block a user