From 8b77ee159fcf7b32cf0a9a4bd2e0b6b265ac56af Mon Sep 17 00:00:00 2001
From: Solaris-Shade <73904284+Solaris-Shade@users.noreply.github.com>
Date: Tue, 22 Feb 2022 14:57:08 -0500
Subject: [PATCH 1/6] Update projectile.dm
Delete redundant list
---
code/modules/projectiles/projectile.dm | 1 -
1 file changed, 1 deletion(-)
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 8d467c9901..ca07bde239 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -31,7 +31,6 @@
var/xo = null
var/atom/original = null // the original target clicked
var/turf/starting = null // the projectile's starting turf
- var/list/permutated = list() // we've passed through these atoms, don't try to hit them again
var/p_x = 16
var/p_y = 16 // the pixel location of the tile that the player clicked. Default is the center
From 2fdb70b2b9f955ee8d5181b2d698fe5a8cabaf87 Mon Sep 17 00:00:00 2001
From: Solaris-Shade <73904284+Solaris-Shade@users.noreply.github.com>
Date: Sun, 6 Mar 2022 15:20:23 -0500
Subject: [PATCH 2/6] [DNM][DNM][WIP] Projectile backend code port and update
Ports#54924, #65061, #59804 from /tg.
adds auxiliary code from /tg to make code work.
---
code/__DEFINES/_flags/_flags.dm | 5 +-
code/__DEFINES/projectiles.dm | 11 +
code/_globalvars/bitfields.dm | 2 +-
code/_onclick/adjacent.dm | 2 +-
code/controllers/subsystem/throwing.dm | 2 +-
code/datums/components/mirv.dm | 2 +-
code/datums/components/pellet_cloud.dm | 2 +-
code/game/atoms.dm | 34 +-
code/game/atoms_movable.dm | 14 +-
code/game/machinery/_machinery.dm | 1 +
code/game/machinery/deployable.dm | 25 +-
code/game/machinery/doors/door.dm | 6 +-
code/game/machinery/doors/firedoor.dm | 14 +-
code/game/machinery/doors/windowdoor.dm | 21 +-
code/game/machinery/recycler.dm | 2 +-
code/game/machinery/shieldgen.dm | 5 +-
code/game/machinery/transformer.dm | 10 +-
.../effects/effect_system/effects_foam.dm | 12 +-
.../effects/effect_system/effects_smoke.dm | 10 +-
code/game/objects/effects/spiders.dm | 4 +-
code/game/objects/items/cardboard_cutouts.dm | 4 +-
.../items/devices/forcefieldprojector.dm | 6 +-
code/game/objects/objs.dm | 6 +-
code/game/objects/structures.dm | 4 +-
code/game/objects/structures/aliens.dm | 5 -
.../structures/crates_lockers/closets.dm | 4 +-
.../structures/crates_lockers/crates.dm | 8 +-
code/game/objects/structures/girders.dm | 10 +-
code/game/objects/structures/grille.dm | 13 +-
code/game/objects/structures/holosign.dm | 44 +-
code/game/objects/structures/mineral_doors.dm | 4 +-
code/game/objects/structures/morgue.dm | 20 +-
code/game/objects/structures/plasticflaps.dm | 5 +-
code/game/objects/structures/railings.dm | 2 +-
code/game/objects/structures/tables_racks.dm | 23 +-
.../structures/transit_tubes/transit_tube.dm | 6 +-
.../objects/structures/windoor_assembly.dm | 16 +-
code/game/objects/structures/window.dm | 20 +-
code/game/turfs/closed.dm | 6 +-
code/game/turfs/simulated/chasm.dm | 3 -
code/game/turfs/turf.dm | 23 +-
.../antagonists/blob/blob/blobs/blob_mobs.dm | 6 +-
code/modules/antagonists/blob/blob/theblob.dm | 12 +-
code/modules/antagonists/swarmer/swarmer.dm | 11 +-
code/modules/assembly/infrared.dm | 3 +-
code/modules/awaymissions/away_props.dm | 5 +-
code/modules/awaymissions/capture_the_flag.dm | 8 +-
code/modules/events/spacevine.dm | 2 +-
code/modules/fields/turf_objects.dm | 4 +-
code/modules/flufftext/Hallucination.dm | 4 +-
code/modules/holiday/halloween/halloween.dm | 5 +-
code/modules/hydroponics/grown/towercap.dm | 8 +-
code/modules/mining/minebot.dm | 4 +-
code/modules/mob/dead/observer/observer.dm | 3 -
.../mob/living/carbon/human/human_defense.dm | 4 +-
code/modules/mob/living/living_defense.dm | 4 +-
code/modules/mob/living/living_movement.dm | 12 +-
.../mob/living/silicon/silicon_defense.dm | 4 +-
.../living/simple_animal/animal_defense.dm | 4 +-
.../simple_animal/hostile/jungle/mook.dm | 4 +-
.../hostile/megafauna/bubblegum.dm | 12 +-
.../hostile/megafauna/hierophant.dm | 4 +-
.../simple_animal/hostile/megafauna/legion.dm | 2 +-
.../hostile/mining_mobs/curse_blob.dm | 4 +-
.../hostile/mining_mobs/elites/elite.dm | 5 +-
.../mob/living/simple_animal/slime/slime.dm | 4 +-
code/modules/mob/mob_defines.dm | 2 +-
.../plumbing/plumbers/grinder_chemical.dm | 2 +-
.../power/singularity/containment_field.dm | 4 +-
.../guns/energy/kinetic_accelerator.dm | 4 +-
.../projectiles/guns/misc/beam_rifle.dm | 76 ++--
.../projectiles/guns/misc/blastcannon.dm | 3 +-
code/modules/projectiles/projectile.dm | 396 ++++++++++++------
code/modules/projectiles/projectile/beams.dm | 2 +-
.../projectile/bullets/ferromagnetic.dm | 4 +-
.../projectiles/projectile/bullets/sniper.dm | 3 +-
.../projectiles/projectile/bullets/special.dm | 3 +-
code/modules/projectiles/projectile/magic.dm | 13 +-
.../projectiles/projectile/special/curse.dm | 11 +-
.../ruins/objects_and_mobs/necropolis_gate.dm | 8 +-
.../ruins/objects_and_mobs/sin_ruins.dm | 5 +-
code/modules/shuttle/special.dm | 5 +-
code/modules/spells/spell_types/forcewall.dm | 4 +-
code/modules/vehicles/ridden.dm | 1 +
84 files changed, 597 insertions(+), 503 deletions(-)
diff --git a/code/__DEFINES/_flags/_flags.dm b/code/__DEFINES/_flags/_flags.dm
index 5f591b429b..99c9b293fb 100644
--- a/code/__DEFINES/_flags/_flags.dm
+++ b/code/__DEFINES/_flags/_flags.dm
@@ -104,6 +104,7 @@ GLOBAL_LIST_INIT(bitflags, list(
#define PASSBLOB (1<<3)
#define PASSMOB (1<<4)
#define PASSCLOSEDTURF (1<<5)
+/// Let thrown things past us. **ONLY MEANINGFUL ON pass_flags_self!**
#define LETPASSTHROW (1<<6)
//Movement Types
@@ -111,8 +112,8 @@ GLOBAL_LIST_INIT(bitflags, list(
#define FLYING (1<<1)
#define VENTCRAWLING (1<<2)
#define FLOATING (1<<3)
-///When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped.
-#define UNSTOPPABLE (1<<4)
+///When moving, will Bump()/Cross()/Uncross() everything, but won't stop or Bump() anything.
+#define PHASING (1<<4)
///Applied if you're crawling around on the ground/resting.
#define CRAWLING (1<<5)
diff --git a/code/__DEFINES/projectiles.dm b/code/__DEFINES/projectiles.dm
index 1bd67fbe02..70a2d611ab 100644
--- a/code/__DEFINES/projectiles.dm
+++ b/code/__DEFINES/projectiles.dm
@@ -1,3 +1,14 @@
+
+// check_pierce() return values
+/// Default behavior: hit and delete self
+#define PROJECTILE_PIERCE_NONE 0
+/// Hit the thing but go through without deleting. Causes on_hit to be called with pierced = TRUE
+#define PROJECTILE_PIERCE_HIT 1
+/// Entirely phase through the thing without ever hitting.
+#define PROJECTILE_PIERCE_PHASE 2
+// Delete self without hitting
+#define PROJECTILE_DELETE_WITHOUT_HITTING 3
+
/// This atom should be ricocheted off of from its inherent properties using standard % chance handling.
#define PROJECTILE_RICOCHET_YES 1
/// This atom should not be ricocheted off of from its inherent properties.
diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm
index df3b6e5334..e3675a53f5 100644
--- a/code/_globalvars/bitfields.dm
+++ b/code/_globalvars/bitfields.dm
@@ -130,7 +130,7 @@ GLOBAL_LIST_INIT(bitfields, list(
"FLYING" = FLYING,
"VENTCRAWLING" = VENTCRAWLING,
"FLOATING" = FLOATING,
- "UNSTOPPABLE" = UNSTOPPABLE
+ "PHASING" = PHASING
),
"resistance_flags" = list(
"LAVA_PROOF" = LAVA_PROOF,
diff --git a/code/_onclick/adjacent.dm b/code/_onclick/adjacent.dm
index 3f3eecb676..e629a6eb57 100644
--- a/code/_onclick/adjacent.dm
+++ b/code/_onclick/adjacent.dm
@@ -94,7 +94,7 @@
for(var/obj/O in src)
if((mover && O.CanPass(mover,get_step(src,target_dir))) || (!mover && !O.density))
continue
- if(O == target_atom || O == mover || (O.pass_flags & LETPASSTHROW)) //check if there's a dense object present on the turf
+ if(O == target_atom || O == mover || (O.pass_flags_self & LETPASSTHROW)) //check if there's a dense object present on the turf
continue // LETPASSTHROW is used for anything you can click through (or the firedoor special case, see above)
if( O.flags_1&ON_BORDER_1) // windows are on border, check them first
diff --git a/code/controllers/subsystem/throwing.dm b/code/controllers/subsystem/throwing.dm
index 0fa8035d72..2ff1e284d0 100644
--- a/code/controllers/subsystem/throwing.dm
+++ b/code/controllers/subsystem/throwing.dm
@@ -200,6 +200,6 @@ SUBSYSTEM_DEF(throwing)
var/atom/movable/AM = thing
if (AM == thrownthing || (AM == thrower && !ismob(thrownthing)))
continue
- if (AM.density && !(AM.pass_flags & LETPASSTHROW) && !(AM.flags_1 & ON_BORDER_1))
+ if (AM.density && !(AM.pass_flags_self & LETPASSTHROW) && !(AM.flags_1 & ON_BORDER_1))
finalize(hit=TRUE, target=AM)
return TRUE
diff --git a/code/datums/components/mirv.dm b/code/datums/components/mirv.dm
index 2a1663776c..77c47bcb1d 100644
--- a/code/datums/components/mirv.dm
+++ b/code/datums/components/mirv.dm
@@ -38,5 +38,5 @@
P.range = override_projectile_range
P.preparePixelProjectile(shootat_turf, target)
P.firer = firer // don't hit ourself that would be really annoying
- P.permutated += target // don't hit the target we hit already with the flak
+ P.impacted = list(target = TRUE) // don't hit the target we hit already with the flak
P.fire()
diff --git a/code/datums/components/pellet_cloud.dm b/code/datums/components/pellet_cloud.dm
index dcc806d991..a06242962f 100644
--- a/code/datums/components/pellet_cloud.dm
+++ b/code/datums/components/pellet_cloud.dm
@@ -242,7 +242,7 @@
P.original = target
P.fired_from = parent
P.firer = parent // don't hit ourself that would be really annoying
- P.permutated += parent // don't hit the target we hit already with the flak
+ P.impacted = list(parent = TRUE) // don't hit the target we hit already with the flak
P.suppressed = SUPPRESSED_VERY // set the projectiles to make no message so we can do our own aggregate message
P.preparePixelProjectile(target, parent)
RegisterSignal(P, COMSIG_PROJECTILE_SELF_ON_HIT, .proc/pellet_hit)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 40162a6c9b..e4b7507560 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -9,6 +9,9 @@
plane = GAME_PLANE
appearance_flags = TILE_BOUND
+ /// pass_flags that we are. If any of this matches a pass_flag on a moving thing, by default, we let them through.
+ var/pass_flags_self = NONE
+
var/level = 2
///If non-null, overrides a/an/some in all cases
var/article
@@ -269,12 +272,27 @@
return FALSE
if((P.flag in list("bullet", "bomb")) && P.ricochet_incidence_leeway)
if((a_incidence_s < 90 && a_incidence_s < 90 - P.ricochet_incidence_leeway) || (a_incidence_s > 270 && a_incidence_s -270 > P.ricochet_incidence_leeway))
- return
+ return FALSE
var/new_angle_s = SIMPLIFY_DEGREES(face_angle + incidence_s)
P.setAngle(new_angle_s)
return TRUE
/atom/proc/CanPass(atom/movable/mover, turf/target)
+ SHOULD_CALL_PARENT(TRUE)
+ if(mover.movement_type & PHASING)
+ return TRUE
+ . = CanAllowThrough(mover, target)
+ // This is cheaper than calling the proc every time since most things dont override CanPassThrough
+ if(!mover.generic_canpass)
+ return mover.CanPassThrough(src, target, .)
+
+/// Returns true or false to allow the mover to move through src
+/atom/proc/CanAllowThrough(atom/movable/mover, turf/target)
+ SHOULD_CALL_PARENT(TRUE)
+ if(mover.pass_flags & pass_flags_self)
+ return TRUE
+ if(mover.throwing && (pass_flags_self & LETPASSTHROW))
+ return TRUE
return !density
/**
@@ -445,9 +463,19 @@
wires.emp_pulse(severity)
return protection // Pass the protection value collected here upwards
-/atom/proc/bullet_act(obj/item/projectile/P, def_zone)
+/**
+ * React to a hit by a projectile object
+ *
+ * Default behaviour is to send the [COMSIG_ATOM_BULLET_ACT] and then call [on_hit][/obj/item/projectile/proc/on_hit] on the projectile
+ *
+ * @params
+ * P - projectile
+ * def_zone - zone hit
+ * piercing_hit - is this hit piercing or normal?
+ */
+/atom/proc/bullet_act(obj/item/projectile/P, def_zone, piercing_hit = FALSE)
SEND_SIGNAL(src, COMSIG_ATOM_BULLET_ACT, P, def_zone)
- . = P.on_hit(src, 0, def_zone)
+ . = P.on_hit(src, 0, def_zone, piercing_hit)
//used on altdisarm() for special interactions between the shoved victim (target) and the src, with user being the one shoving the target on it.
// IMPORTANT: if you wish to add a new own shove_act() to a certain object, remember to add SHOVABLE_ONTO to its obj_flags bitfied var first.
diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm
index 5da389fbb8..56c668a24b 100644
--- a/code/game/atoms_movable.dm
+++ b/code/game/atoms_movable.dm
@@ -25,7 +25,10 @@
var/inertia_moving = 0
var/inertia_next_move = 0
var/inertia_move_delay = 5
- var/pass_flags = 0
+ /// Things we can pass through while moving. If any of this matches the thing we're trying to pass's [pass_flags_self], then we can pass through.
+ var/pass_flags = NONE
+ /// If false makes CanPass call CanPassThrough on this type instead of using default behaviour
+ var/generic_canpass = TRUE
var/moving_diagonally = 0 //0: not doing a diagonal move. 1 and 2: doing the first/second step of the diagonal move
var/atom/movable/moving_from_pull //attempt to resume grab after moving instead of before.
var/list/acted_explosions //for explosion dodging
@@ -473,10 +476,15 @@
/atom/movable/proc/move_crushed(atom/movable/pusher, force = MOVE_FORCE_DEFAULT, direction)
return FALSE
-/atom/movable/CanPass(atom/movable/mover, turf/target)
+/atom/movable/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(mover in buckled_mobs)
return TRUE
- return ..()
+
+/// Returns true or false to allow src to move through the blocker, mover has final say
+/atom/movable/proc/CanPassThrough(atom/blocker, turf/target, blocker_opinion)
+ SHOULD_CALL_PARENT(TRUE)
+ return blocker_opinion
/// called when this atom is removed from a storage item, which is passed on as S. The loc variable is already set to the new destination before this is called.
/atom/movable/proc/on_exit_storage(datum/component/storage/concrete/S) // rename S to master_storage
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index f40adcd00b..675d54ef22 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -90,6 +90,7 @@ Class Procs:
verb_say = "beeps"
verb_yell = "blares"
pressure_resistance = 15
+ pass_flags_self = PASSMACHINE
max_integrity = 200
layer = BELOW_OBJ_LAYER //keeps shit coming out of the machine from ending up underneath it.
flags_1 = DEFAULT_RICOCHET_1
diff --git a/code/game/machinery/deployable.dm b/code/game/machinery/deployable.dm
index ca4b392efa..b720a92402 100644
--- a/code/game/machinery/deployable.dm
+++ b/code/game/machinery/deployable.dm
@@ -37,22 +37,19 @@
else
return ..()
-/obj/structure/barricade/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff.
+/obj/structure/barricade/CanAllowThrough(atom/movable/mover, turf/target)//So bullets will fly over and stuff.
+ . = ..()
if(locate(/obj/structure/barricade) in get_turf(mover))
- return 1
+ return TRUE
else if(istype(mover, /obj/item/projectile))
if(!anchored)
- return 1
+ return TRUE
var/obj/item/projectile/proj = mover
if(proj.firer && Adjacent(proj.firer))
- return 1
+ return TRUE
if(prob(proj_pass_rate))
- return 1
- return 0
- else
- return !density
-
-
+ return TRUE
+ return FALSE
/////BARRICADE TYPES///////
@@ -79,7 +76,6 @@
return
return ..()
-
/obj/structure/barricade/wooden/crude
name = "crude plank barricade"
desc = "This space is blocked off by a crude assortment of planks."
@@ -96,7 +92,6 @@
/obj/structure/barricade/wooden/make_debris()
new /obj/item/stack/sheet/mineral/wood(get_turf(src), drop_amount)
-
/obj/structure/barricade/sandbags
name = "sandbags"
desc = "Bags of sand. Self explanatory."
@@ -104,13 +99,12 @@
icon_state = "sandbags"
max_integrity = 280
proj_pass_rate = 20
- pass_flags = LETPASSTHROW
+ pass_flags_self = LETPASSTHROW
bar_material = SAND
climbable = TRUE
smooth = SMOOTH_TRUE
canSmoothWith = list(/obj/structure/barricade/sandbags, /turf/closed/wall, /turf/closed/wall/r_wall, /obj/structure/falsewall, /obj/structure/falsewall/reinforced, /turf/closed/wall/rust, /turf/closed/wall/r_wall/rust, /obj/structure/barricade/security)
-
/obj/structure/barricade/security
name = "security barrier"
desc = "A deployable barrier. Provides good cover in fire fights."
@@ -125,7 +119,6 @@
var/deploy_time = 40
var/deploy_message = TRUE
-
/obj/structure/barricade/security/Initialize()
. = ..()
addtimer(CALLBACK(src, .proc/deploy), deploy_time)
@@ -137,7 +130,6 @@
if(deploy_message)
visible_message("[src] deploys!")
-
/obj/item/grenade/barrier
name = "barrier grenade"
desc = "Instant cover."
@@ -194,7 +186,6 @@
/obj/item/grenade/barrier/ui_action_click(mob/user)
toggle_mode(user)
-
#undef SINGLE
#undef VERTICAL
#undef HORIZONTAL
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index d1781d9477..71df6affb7 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -127,10 +127,12 @@
. = ..()
move_update_air(T)
-/obj/machinery/door/CanPass(atom/movable/mover, turf/target)
+/obj/machinery/door/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+
+ // Snowflake handling for PASSGLASS.
if(istype(mover) && (mover.pass_flags & PASSGLASS))
return !opacity
- return !density
/obj/machinery/door/proc/bumpopen(mob/user)
if(operating)
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index d84b994b92..62eb08735f 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -347,21 +347,15 @@
return 0 // not big enough to matter
return start_point.air.return_pressure() < 20 ? -1 : 1
-/obj/machinery/door/firedoor/border_only/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return TRUE
- if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
- return !density
- else
+/obj/machinery/door/firedoor/border_only/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(!(get_dir(loc, target) == dir)) //Make sure looking at appropriate border
return TRUE
/obj/machinery/door/firedoor/border_only/CheckExit(atom/movable/mover as mob|obj, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return TRUE
if(get_dir(loc, target) == dir)
return !density
- else
- return TRUE
+ return TRUE
/obj/machinery/door/firedoor/border_only/CanAtmosPass(turf/T)
if(get_dir(loc, T) == dir)
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index af7545d3c9..5027e46aa0 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -12,6 +12,7 @@
armor = list("melee" = 20, "bullet" = 50, "laser" = 50, "energy" = 50, "bomb" = 10, "bio" = 100, "rad" = 100, "fire" = 70, "acid" = 100)
visible = FALSE
flags_1 = ON_BORDER_1|DEFAULT_RICOCHET_1
+ pass_flags_self = PASSGLASS
opacity = 0
CanAtmosPass = ATMOS_PASS_PROC
interaction_flags_machine = INTERACT_MACHINE_WIRES_IF_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OPEN_SILICON | INTERACT_MACHINE_REQUIRES_SILICON | INTERACT_MACHINE_OPEN
@@ -103,11 +104,12 @@
do_animate("deny")
return
-/obj/machinery/door/window/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return 1
+/obj/machinery/door/window/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(.)
+ return
if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
- return !density
+ return
if(istype(mover, /obj/structure/window))
var/obj/structure/window/W = mover
if(!valid_window_location(loc, W.ini_dir))
@@ -119,7 +121,7 @@
else if(istype(mover, /obj/machinery/door/window) && !valid_window_location(loc, mover.dir))
return FALSE
else
- return 1
+ return TRUE
/obj/machinery/door/window/CanAtmosPass(turf/T)
if(get_dir(loc, T) == dir)
@@ -131,13 +133,12 @@
/obj/machinery/door/window/CanAStarPass(obj/item/card/id/ID, to_dir)
return !density || (dir != to_dir) || (check_access(ID) && hasPower())
-/obj/machinery/door/window/CheckExit(atom/movable/mover as mob|obj, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return 1
+/obj/machinery/door/window/CheckExit(atom/movable/mover, turf/target)
+ if((pass_flags_self & mover.pass_flags)) || ((pass_flags_self & LETPASSTHROW) && mover.throwing))
+ return TRUE
if(get_dir(loc, target) == dir)
return !density
- else
- return 1
+ return TRUE
/obj/machinery/door/window/open(forced=0)
if (src.operating == 1) //doors can still open when emag-disabled
diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm
index 21ef8e2dcf..7129b6fe57 100644
--- a/code/game/machinery/recycler.dm
+++ b/code/game/machinery/recycler.dm
@@ -87,7 +87,7 @@
is_powered = FALSE
icon_state = icon_name + "[is_powered]" + "[(blood ? "bld" : "")]" // add the blood tag at the end
-/obj/machinery/recycler/CanPass(atom/movable/AM)
+/obj/machinery/recycler/CanAllowThrough(atom/movable/AM)
. = ..()
if(!anchored)
return
diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm
index 2ebb137839..51f16c3425 100644
--- a/code/game/machinery/shieldgen.dm
+++ b/code/game/machinery/shieldgen.dm
@@ -454,11 +454,10 @@
if(gen_secondary) //using power may cause us to be destroyed
gen_secondary.use_stored_power(drain_amount*0.5)
-/obj/machinery/shieldwall/CanPass(atom/movable/mover, turf/target)
+/obj/machinery/shieldwall/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(istype(mover) && (mover.pass_flags & PASSGLASS))
return prob(20)
else
if(istype(mover, /obj/item/projectile))
return prob(10)
- else
- return !density
diff --git a/code/game/machinery/transformer.dm b/code/game/machinery/transformer.dm
index 8bca58a7de..afaf617cbc 100644
--- a/code/game/machinery/transformer.dm
+++ b/code/game/machinery/transformer.dm
@@ -57,14 +57,14 @@
AM.forceMove(drop_location())
do_transform(AM)
-/obj/machinery/transformer/CanPass(atom/movable/mover, turf/target)
+/obj/machinery/transformer/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
// Allows items to go through,
// to stop them from blocking the conveyor belt.
if(!ishuman(mover))
- var/dir = get_dir(src, mover)
- if(dir == EAST)
- return ..()
- return 0
+ if(get_dir(src, mover) == EAST)
+ return
+ return FALSE
/obj/machinery/transformer/process()
if(cooldown && (cooldown_timer <= world.time))
diff --git a/code/game/objects/effects/effect_system/effects_foam.dm b/code/game/objects/effects/effect_system/effects_foam.dm
index a0f53ceab7..d4a198a5b0 100644
--- a/code/game/objects/effects/effect_system/effects_foam.dm
+++ b/code/game/objects/effects/effect_system/effects_foam.dm
@@ -291,9 +291,6 @@
to_chat(user, "You hit [src] but bounce off it!")
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
-/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target)
- return !density
-
/obj/structure/foamedmetal/iron
max_integrity = 50
icon_state = "ironfoam"
@@ -306,6 +303,7 @@
icon_state = "atmos_resin"
alpha = 120
max_integrity = 10
+ pass_flags_self = PASSGLASS
/obj/structure/foamedmetal/resin/Initialize()
. = ..()
@@ -336,14 +334,6 @@
for(var/obj/item/Item in O)
Item.extinguish()
-/obj/structure/foamedmetal/resin/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return TRUE
- . = ..()
-
-/obj/structure/foamedmetal/resin/BlockThermalConductivity()
- return TRUE
-
#undef ALUMINUM_FOAM
#undef IRON_FOAM
#undef RESIN_FOAM
diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm
index 3e80ade0ce..db1b9d5b2b 100644
--- a/code/game/objects/effects/effect_system/effects_smoke.dm
+++ b/code/game/objects/effects/effect_system/effects_smoke.dm
@@ -133,13 +133,11 @@
M.emote("cough")
return 1
-/obj/effect/particle_effect/smoke/bad/CanPass(atom/movable/mover, turf/target)
- if(istype(mover, /obj/item/projectile/beam))
- var/obj/item/projectile/beam/B = mover
+/obj/effect/particle_effect/smoke/bad/Crossed(atom/movable/AM, oldloc)
+ . = ..()
+ if(istype(AM, /obj/projectile/beam))
+ var/obj/projectile/beam/B = AM
B.damage = (B.damage/2)
- return 1
-
-
/datum/effect_system/smoke_spread/bad
effect_type = /obj/effect/particle_effect/smoke/bad
diff --git a/code/game/objects/effects/spiders.dm b/code/game/objects/effects/spiders.dm
index 4b04606401..1c8df008fd 100644
--- a/code/game/objects/effects/spiders.dm
+++ b/code/game/objects/effects/spiders.dm
@@ -36,7 +36,8 @@
icon_state = "stickyweb2"
. = ..()
-/obj/structure/spider/stickyweb/CanPass(atom/movable/mover, turf/target)
+/obj/structure/spider/stickyweb/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if (genetic)
return
if(istype(mover, /mob/living/simple_animal/hostile/poison/giant_spider))
@@ -49,7 +50,6 @@
return FALSE
else if(istype(mover, /obj/item/projectile))
return prob(30)
- return TRUE
/obj/structure/spider/stickyweb/genetic //for the spider genes in genetics
genetic = TRUE
diff --git a/code/game/objects/items/cardboard_cutouts.dm b/code/game/objects/items/cardboard_cutouts.dm
index a8ff7b9004..4a59118c8a 100644
--- a/code/game/objects/items/cardboard_cutouts.dm
+++ b/code/game/objects/items/cardboard_cutouts.dm
@@ -92,9 +92,9 @@
if(prob(I.force))
push_over()
-/obj/item/cardboard_cutout/bullet_act(obj/item/projectile/P)
+/obj/item/cardboard_cutout/bullet_act(obj/item/projectile/P, def_zone, piercing_hit = FALSE)
if(istype(P, /obj/item/projectile/bullet/reusable))
- P.on_hit(src, 0)
+ P.on_hit(src, 0, piercing_hit)
visible_message("[src] has been hit by [P]!")
playsound(src, 'sound/weapons/slice.ogg', 50, 1)
if(prob(P.damage))
diff --git a/code/game/objects/items/devices/forcefieldprojector.dm b/code/game/objects/items/devices/forcefieldprojector.dm
index 9ef9d73705..71f69a5c93 100644
--- a/code/game/objects/items/devices/forcefieldprojector.dm
+++ b/code/game/objects/items/devices/forcefieldprojector.dm
@@ -84,6 +84,7 @@
layer = ABOVE_ALL_MOB_LAYER
anchored = TRUE
density = TRUE
+ pass_flags_self = PASSGLASS
mouse_opacity = MOUSE_OPACITY_OPAQUE
resistance_flags = INDESTRUCTIBLE
CanAtmosPass = ATMOS_PASS_DENSITY
@@ -101,11 +102,6 @@
generator = null
return ..()
-/obj/structure/projected_forcefield/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return 1
- return !density
-
/obj/structure/projected_forcefield/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
playsound(loc, 'sound/weapons/egloves.ogg', 80, 1)
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index e263678943..0651891421 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -238,7 +238,11 @@
/obj/get_dumping_location(datum/component/storage/source,mob/user)
return get_turf(src)
-/obj/proc/CanAStarPass()
+/obj/proc/CanAStarPass(ID, dir, caller)
+ if(ismovable(caller))
+ var/atom/movable/AM = caller
+ if(AM.pass_flags & pass_flags_self)
+ return TRUE
. = !density
/obj/proc/check_uplink_validity()
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index 52036427c8..a8f0739bed 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -10,9 +10,11 @@
var/broken = 0 //similar to machinery's stat BROKEN
layer = BELOW_OBJ_LAYER
//ricochets on structures commented out for now because there's a lot of structures that /shouldnt/ be ricocheting and those need to be reviewed first
+ //With the addition of [pass_flags_self] the ricocheting of structures /shouldnt/ happen by default thus the existing code could be uncommented out - Solaris-Shade
//flags_1 = DEFAULT_RICOCHET_1
//flags_ricochet = RICOCHET_HARD
//ricochet_chance_mod = 0.5
+ pass_flags_self = PASSSTRUCTURE
/obj/structure/Initialize()
if (!armor)
@@ -114,4 +116,4 @@
return "It's falling apart!"
/obj/structure/rust_heretic_act()
- take_damage(500, BRUTE, "melee", 1)
+ take_damage(500, BRUTE, "melee", 1)
diff --git a/code/game/objects/structures/aliens.dm b/code/game/objects/structures/aliens.dm
index bc7ce8c36e..bd90db9c12 100644
--- a/code/game/objects/structures/aliens.dm
+++ b/code/game/objects/structures/aliens.dm
@@ -97,11 +97,6 @@
/obj/structure/alien/resin/attack_paw(mob/user)
return attack_hand(user)
-
-/obj/structure/alien/resin/CanPass(atom/movable/mover, turf/target)
- return !density
-
-
/*
* Weeds
*/
diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm
index af4d098157..b511ed7e2d 100644
--- a/code/game/objects/structures/crates_lockers/closets.dm
+++ b/code/game/objects/structures/crates_lockers/closets.dm
@@ -110,10 +110,10 @@
if(HAS_TRAIT(user, TRAIT_SKITTISH))
. += "If you bump into [p_them()] while running, you will jump inside."
-/obj/structure/closet/CanPass(atom/movable/mover, turf/target)
+/obj/structure/closet/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(wall_mounted)
return TRUE
- return !density
/obj/structure/closet/proc/can_open(mob/living/user, force = FALSE)
if(force)
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index f6153330e4..ec97dad72c 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -26,15 +26,15 @@
// AddElement(/datum/element/climbable, climb_time = crate_climb_time, climb_stun = 0)
update_icon()
-/obj/structure/closet/crate/CanPass(atom/movable/mover, turf/target)
+/obj/structure/closet/crate/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(!istype(mover, /obj/structure/closet))
var/obj/structure/closet/crate/locatedcrate = locate(/obj/structure/closet/crate) in get_turf(mover)
if(locatedcrate) //you can walk on it like tables, if you're not in an open crate trying to move to a closed crate
if(opened) //if we're open, allow entering regardless of located crate openness
- return 1
+ return TRUE
if(!locatedcrate.opened) //otherwise, if the located crate is closed, allow entering
- return 1
- return !density
+ return TRUE
/obj/structure/closet/crate/update_icon_state()
icon_state = "[initial(icon_state)][opened ? "open" : ""]"
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index 50240aabb3..3e6884613e 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -296,14 +296,10 @@
qdel(src)
return TRUE
-/obj/structure/girder/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGRILLE))
+/obj/structure/girder/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if((mover.pass_flags & PASSGRILLE) || istype(mover, /obj/projectile))
return prob(girderpasschance)
- else
- if(istype(mover, /obj/item/projectile))
- return prob(girderpasschance)
- else
- return 0
/obj/structure/girder/CanAStarPass(ID, dir, caller)
. = !density
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 2ac85f79dc..54dce18d44 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -5,6 +5,7 @@
icon_state = "grille"
density = TRUE
anchored = TRUE
+ pass_flags_self = PASSGRILLE
flags_1 = CONDUCT_1
pressure_resistance = 5*ONE_ATMOSPHERE
layer = BELOW_OBJ_LAYER
@@ -124,14 +125,10 @@
if(!shock(user, 70))
take_damage(20, BRUTE, "melee", 1)
-/obj/structure/grille/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGRILLE))
- return TRUE
- else
- if(istype(mover, /obj/item/projectile) && density)
- return prob(30)
- else
- return !density
+/obj/structure/grille/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(!. && istype(mover, /obj/projectile))
+ return prob(30)
/obj/structure/grille/CanAStarPass(ID, dir, caller)
. = !density
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index cb9309c4c4..26dedf3b62 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -51,20 +51,19 @@
name = "holo barrier"
desc = "A short holographic barrier which can only be passed by walking."
icon_state = "holosign_sec"
- pass_flags = LETPASSTHROW
+ pass_flags_self = PASSTABLE | PASSGRILLE | PASSGLASS | LETPASSTHROW
density = TRUE
max_integrity = 20
var/allow_walk = 1 //can we pass through it on walk intent
-/obj/structure/holosign/barrier/CanPass(atom/movable/mover, turf/target)
- if(!density)
- return 1
- if(mover.pass_flags & (PASSGLASS|PASSTABLE|PASSGRILLE))
- return 1
+/obj/structure/holosign/barrier/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(.)
+ return
if(iscarbon(mover))
var/mob/living/carbon/C = mover
if(allow_walk && C.m_intent == MOVE_INTENT_WALK)
- return 1
+ return TRUE
/obj/structure/holosign/barrier/engineering
icon_state = "holosign_engi"
@@ -149,22 +148,27 @@
. = ..()
. += "The biometric scanners are [force_allaccess ? "off" : "on"]."
-/obj/structure/holosign/barrier/medical/CanPass(atom/movable/mover, turf/target)
- icon_state = "holo_medical"
+/obj/structure/holosign/barrier/medical/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(force_allaccess)
return TRUE
if(ishuman(mover))
- var/mob/living/carbon/human/sickboi = mover
- var/threat = sickboi.check_virus()
- switch(threat)
- if(DISEASE_SEVERITY_MINOR, DISEASE_SEVERITY_MEDIUM, DISEASE_SEVERITY_HARMFUL, DISEASE_SEVERITY_DANGEROUS, DISEASE_SEVERITY_BIOHAZARD)
- if(buzzcd < world.time)
- playsound(get_turf(src),'sound/machines/buzz-sigh.ogg',65,1,4)
- buzzcd = (world.time + 60)
- icon_state = "holo_medical-deny"
- return FALSE
- else
- return TRUE //nice or benign diseases!
+
+ return CheckHuman(mover)
+
+/obj/structure/holosign/barrier/medical/Bumped(atom/movable/AM)
+ . = ..()
+ icon_state = "holo_medical"
+ if(ishuman(AM) && !CheckHuman(AM))
+ if(buzzcd < world.time)
+ playsound(get_turf(src),'sound/machines/buzz-sigh.ogg',65,TRUE,4)
+ buzzcd = (world.time + 60)
+ icon_state = "holo_medical-deny"
+
+/obj/structure/holosign/barrier/medical/proc/CheckHuman(mob/living/carbon/human/sickboi)
+ var/threat = sickboi.check_virus()
+ if(get_disease_severity_value(threat) > get_disease_severity_value(DISEASE_SEVERITY_MINOR))
+ return FALSE
return TRUE
/obj/structure/holosign/barrier/medical/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm
index b2f1de8750..ecd7c1a03e 100644
--- a/code/game/objects/structures/mineral_doors.dm
+++ b/code/game/objects/structures/mineral_doors.dm
@@ -53,10 +53,10 @@
/obj/structure/mineral_door/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
return TryToSwitchState(user)
-/obj/structure/mineral_door/CanPass(atom/movable/mover, turf/target)
+/obj/structure/mineral_door/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(istype(mover, /obj/effect/beam))
return !opacity
- return !density
/obj/structure/mineral_door/proc/TryToSwitchState(atom/user)
if(isSwitchingStates)
diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm
index 73268009ce..f98151e76a 100644
--- a/code/game/objects/structures/morgue.dm
+++ b/code/game/objects/structures/morgue.dm
@@ -306,7 +306,7 @@ GLOBAL_LIST_EMPTY(crematoriums)
layer = TRAY_LAYER
var/obj/structure/bodycontainer/connected = null
anchored = TRUE
- pass_flags = LETPASSTHROW
+ pass_flags_self = LETPASSTHROW
max_integrity = 350
/obj/structure/tray/Destroy()
@@ -362,17 +362,11 @@ GLOBAL_LIST_EMPTY(crematoriums)
name = "morgue tray"
desc = "Apply corpse before closing."
icon_state = "morguet"
+ pass_flags_self = PASSTABLE
-/obj/structure/tray/m_tray/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSTABLE))
- return 1
+/obj/structure/tray/m_tray/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(.)
+ return
if(locate(/obj/structure/table) in get_turf(mover))
- return 1
- else
- return 0
-
-/obj/structure/tray/m_tray/CanAStarPass(ID, dir, caller)
- . = !density
- if(ismovable(caller))
- var/atom/movable/mover = caller
- . = . || (mover.pass_flags & PASSTABLE)
+ return TRUE
diff --git a/code/game/objects/structures/plasticflaps.dm b/code/game/objects/structures/plasticflaps.dm
index ff8287d77b..4e916d57a6 100644
--- a/code/game/objects/structures/plasticflaps.dm
+++ b/code/game/objects/structures/plasticflaps.dm
@@ -69,7 +69,9 @@
return CanAStarPass(ID, to_dir, M.pulling)
return 1 //diseases, stings, etc can pass
-/obj/structure/plasticflaps/CanPass(atom/movable/A, turf/T)
+/obj/structure/plasticflaps/CanAllowThrough(atom/movable/A, turf/T)
+ . = ..()
+
if(istype(A) && (A.pass_flags & PASSGLASS))
return prob(60)
@@ -93,7 +95,6 @@
return 1
if(!M.lying && !(SEND_SIGNAL(M, COMSIG_CHECK_VENTCRAWL)) && M.mob_size != MOB_SIZE_TINY) //If your not laying down, or a ventcrawler or a small creature, no pass.
return 0
- return ..()
/obj/structure/plasticflaps/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
diff --git a/code/game/objects/structures/railings.dm b/code/game/objects/structures/railings.dm
index 21cf97ba70..13bc676239 100644
--- a/code/game/objects/structures/railings.dm
+++ b/code/game/objects/structures/railings.dm
@@ -78,7 +78,7 @@
/obj/structure/railing/CheckExit(atom/movable/mover, turf/target)
..()
if(get_dir(loc, target) & dir)
- var/checking = UNSTOPPABLE | FLYING | FLOATING
+ var/checking = PHASING | FLYING | FLOATING
return !density || mover.throwing || mover.movement_type & checking || mover.move_force >= MOVE_FORCE_EXTREMELY_STRONG
return TRUE
diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm
index 065c0d2f28..2435e9a5f6 100644
--- a/code/game/objects/structures/tables_racks.dm
+++ b/code/game/objects/structures/tables_racks.dm
@@ -19,10 +19,10 @@
icon_state = "table"
density = TRUE
anchored = TRUE
+ pass_flags_self = PASSTABLE | LETPASSTHROW
layer = TABLE_LAYER
climbable = TRUE
obj_flags = CAN_BE_HIT|SHOVABLE_ONTO
- pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density.")
attack_hand_speed = CLICK_CD_MELEE
attack_hand_is_action = TRUE
var/frame = /obj/structure/table_frame
@@ -99,15 +99,14 @@
/obj/structure/table/attack_tk()
return FALSE
-/obj/structure/table/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSTABLE))
- return 1
+/obj/structure/table/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(.)
+ return
if(mover.throwing)
- return 1
+ return TRUE
if(locate(/obj/structure/table) in get_turf(mover))
- return 1
- else
- return !density
+ return TRUE
/obj/structure/table/CanAStarPass(ID, dir, caller)
. = !density
@@ -685,7 +684,7 @@
layer = TABLE_LAYER
density = TRUE
anchored = TRUE
- pass_flags = LETPASSTHROW //You can throw objects over this, despite it's density.
+ pass_flags_self = LETPASSTHROW //You can throw objects over this, despite it's density.
max_integrity = 20
attack_hand_speed = CLICK_CD_MELEE
attack_hand_is_action = TRUE
@@ -702,12 +701,6 @@
else
return 0
-/obj/structure/rack/CanAStarPass(ID, dir, caller)
- . = !density
- if(ismovable(caller))
- var/atom/movable/mover = caller
- . = . || (mover.pass_flags & PASSTABLE)
-
/obj/structure/rack/MouseDrop_T(obj/O, mob/user)
. = ..()
if ((!( istype(O, /obj/item) ) || user.get_active_held_item() != O))
diff --git a/code/game/objects/structures/transit_tubes/transit_tube.dm b/code/game/objects/structures/transit_tubes/transit_tube.dm
index 7e3684ad32..c8341c8834 100644
--- a/code/game/objects/structures/transit_tubes/transit_tube.dm
+++ b/code/game/objects/structures/transit_tubes/transit_tube.dm
@@ -8,17 +8,13 @@
layer = LOW_ITEM_LAYER
anchored = TRUE
climbable = 1
+ pass_flags_self = PASSGLASS
var/tube_construction = /obj/structure/c_transit_tube
var/list/tube_dirs //list of directions this tube section can connect to.
var/exit_delay = 1
var/enter_delay = 0
var/const/time_to_unwrench = 2 SECONDS
-/obj/structure/transit_tube/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return 1
- return !density
-
/obj/structure/transit_tube/New(loc, newdirection)
..(loc)
if(newdirection)
diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm
index ef1ca6720a..4f1de6432a 100644
--- a/code/game/objects/structures/windoor_assembly.dm
+++ b/code/game/objects/structures/windoor_assembly.dm
@@ -50,11 +50,10 @@
/obj/structure/windoor_assembly/update_icon_state()
icon_state = "[facing]_[secure ? "secure_" : ""]windoor_assembly[state]"
-/obj/structure/windoor_assembly/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return 1
+/obj/structure/windoor_assembly/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(get_dir(loc, target) == dir) //Make sure looking at appropriate border
- return !density
+ return
if(istype(mover, /obj/structure/window))
var/obj/structure/window/W = mover
if(!valid_window_location(loc, W.ini_dir))
@@ -65,7 +64,6 @@
return FALSE
else if(istype(mover, /obj/machinery/door/window) && !valid_window_location(loc, mover.dir))
return FALSE
- return 1
/obj/structure/windoor_assembly/CanAtmosPass(turf/T)
if(get_dir(loc, T) == dir)
@@ -73,13 +71,13 @@
else
return 1
-/obj/structure/windoor_assembly/CheckExit(atom/movable/mover as mob|obj, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return 1
+/obj/structure/windoor_assembly/CheckExit(atom/movable/mover, turf/target)
+ if(mover.pass_flags & pass_flags_self)
+ return TRUE
if(get_dir(loc, target) == dir)
return !density
else
- return 1
+ return TRUE
/obj/structure/windoor_assembly/attackby(obj/item/W, mob/user, params)
diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm
index 4853d553dc..a73de2d367 100644
--- a/code/game/objects/structures/window.dm
+++ b/code/game/objects/structures/window.dm
@@ -18,6 +18,7 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
pressure_resistance = 4*ONE_ATMOSPHERE
anchored = TRUE //initially is 0 for tile smoothing
max_integrity = 25
+ pass_flags_self = PASSGLASS
var/ini_dir = null
var/state = WINDOW_OUT_OF_FRAME
var/reinf = FALSE
@@ -90,13 +91,13 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
. = ..()
if(direct)
setDir(direct)
-
+
if(extra_reinforced && anchored)
state = PRWINDOW_SECURE
else if(reinf && anchored)
state = WINDOW_SCREWED_TO_FRAME
-
+
if(mapload && electrochromatic_id && electrochromatic_id[1] == "!")
electrochromatic_id = SSmapping.get_obfuscated_id(electrochromatic_id)
@@ -159,13 +160,15 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
else
..(FULLTILE_WINDOW_DIR)
-/obj/structure/window/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSGLASS))
- return 1
+/obj/structure/window/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(.)
+ return
if(dir == FULLTILE_WINDOW_DIR)
return 0 //full tile window, you can't move into it!
- if(get_dir(loc, target) == dir)
- return !density
+ var/attempted_dir = get_dir(loc, target)
+ if(attempted_dir == dir)
+ return
if(istype(mover, /obj/structure/window))
var/obj/structure/window/W = mover
if(!valid_window_location(loc, W.ini_dir))
@@ -176,7 +179,8 @@ GLOBAL_LIST_EMPTY(electrochromatic_window_lookup)
return FALSE
else if(istype(mover, /obj/machinery/door/window) && !valid_window_location(loc, mover.dir))
return FALSE
- return 1
+ else if(attempted_dir != dir)
+ return TRUE
/obj/structure/window/CheckExit(atom/movable/O, turf/target)
if(istype(O) && (O.pass_flags & PASSGLASS))
diff --git a/code/game/turfs/closed.dm b/code/game/turfs/closed.dm
index ccfb5dc238..3c2f38e872 100644
--- a/code/game/turfs/closed.dm
+++ b/code/game/turfs/closed.dm
@@ -6,6 +6,7 @@
blocks_air = 1
rad_flags = RAD_PROTECT_CONTENTS | RAD_NO_CONTAMINATE
rad_insulation = RAD_MEDIUM_INSULATION
+ pass_flags_self = PASSCLOSEDTURF
wave_explosion_block = 10
wave_explosion_multiply = 0.75
/// How much we block yelling
@@ -23,11 +24,6 @@
/turf/closed/get_smooth_underlay_icon(mutable_appearance/underlay_appearance, turf/asking_turf, adjacency_dir)
return FALSE
-/turf/closed/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSCLOSEDTURF))
- return TRUE
- return ..()
-
/turf/closed/indestructible
name = "wall"
icon = 'icons/turf/walls.dmi'
diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm
index 9490d728fe..40b96dbcc8 100644
--- a/code/game/turfs/simulated/chasm.dm
+++ b/code/game/turfs/simulated/chasm.dm
@@ -77,9 +77,6 @@
else
to_chat(user, "The plating is going to need some support! Place metal rods first.")
-/turf/open/chasm/CanPass(atom/movable/mover, turf/target)
- return 1
-
// Chasms for Lavaland, with planetary atmos and lava glow
/turf/open/chasm/lavaland
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index 85de964463..c87d386b5f 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -225,16 +225,6 @@ GLOBAL_LIST_EMPTY(station_turfs)
return FALSE
-/turf/CanPass(atom/movable/mover, turf/target)
- if(!target)
- return FALSE
-
- if(istype(mover)) // turf/Enter(...) will perform more advanced checks
- return !density
-
- stack_trace("Non movable passed to turf CanPass : [mover]")
- return FALSE
-
//There's a lot of QDELETED() calls here if someone can figure out how to optimize this but not runtime when something gets deleted by a Bump/CanPass/Cross call, lemme know or go ahead and fix this mess - kevinz000
/turf/Enter(atom/movable/mover, atom/oldloc)
// Do not call ..()
@@ -243,7 +233,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
// Here's hoping it doesn't stay like this for years before we finish conversion to step_
var/atom/firstbump
var/canPassSelf = CanPass(mover, src)
- if(canPassSelf || (mover.movement_type & UNSTOPPABLE))
+ if(canPassSelf || (mover.movement_type & PHASING))
for(var/i in contents)
if(QDELETED(mover))
return FALSE //We were deleted, do not attempt to proceed with movement.
@@ -253,7 +243,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
if(!thing.Cross(mover))
if(QDELETED(mover)) //Mover deleted from Cross/CanPass, do not proceed.
return FALSE
- if((mover.movement_type & UNSTOPPABLE))
+ if((mover.movement_type & PHASING))
mover.Bump(thing)
continue
else
@@ -265,7 +255,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
firstbump = src
if(firstbump)
mover.Bump(firstbump)
- return (mover.movement_type & UNSTOPPABLE)
+ return (mover.movement_type & PHASING)
return TRUE
/turf/Exit(atom/movable/mover, atom/newloc)
@@ -279,7 +269,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
if(!thing.Uncross(mover, newloc))
if(thing.flags_1 & ON_BORDER_1)
mover.Bump(thing)
- if(!(mover.movement_type & UNSTOPPABLE))
+ if(!(mover.movement_type & PHASING))
return FALSE
if(QDELETED(mover))
return FALSE //We were deleted.
@@ -621,11 +611,6 @@ GLOBAL_LIST_EMPTY(station_turfs)
/turf/proc/Melt()
return ScrapeAway(flags = CHANGETURF_INHERIT_AIR)
-/turf/bullet_act(obj/item/projectile/P)
- . = ..()
- if(. != BULLET_ACT_FORCE_PIERCE)
- . = BULLET_ACT_TURF
-
/turf/proc/get_yelling_resistance(power)
. = 0
// don't bother checking fulltile, we don't need accuracy
diff --git a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
index f9763b92fd..3caaff4a53 100644
--- a/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
+++ b/code/modules/antagonists/blob/blob/blobs/blob_mobs.dm
@@ -46,10 +46,10 @@
else
adjustFireLoss(5)
-/mob/living/simple_animal/hostile/blob/CanPass(atom/movable/mover, turf/target)
+/mob/living/simple_animal/hostile/blob/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(istype(mover, /obj/structure/blob))
- return 1
- return ..()
+ return TRUE
/mob/living/simple_animal/hostile/blob/Process_Spacemove(movement_dir = 0)
for(var/obj/structure/blob/B in range(1, src))
diff --git a/code/modules/antagonists/blob/blob/theblob.dm b/code/modules/antagonists/blob/blob/theblob.dm
index a95f73f90d..7651093ea1 100644
--- a/code/modules/antagonists/blob/blob/theblob.dm
+++ b/code/modules/antagonists/blob/blob/theblob.dm
@@ -8,6 +8,7 @@
opacity = 0
anchored = TRUE
layer = BELOW_MOB_LAYER
+ pass_flags_self = PASSBLOB
CanAtmosPass = ATMOS_PASS_PROC
var/point_return = 0 //How many points the blob gets back when it removes a blob of that type. If less than 0, blob cannot be removed.
max_integrity = 30
@@ -67,20 +68,9 @@
/obj/structure/blob/BlockThermalConductivity()
return atmosblock
-/obj/structure/blob/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSBLOB))
- return 1
- return 0
-
/obj/structure/blob/CanAtmosPass(turf/T)
return !atmosblock
-/obj/structure/blob/CanAStarPass(ID, dir, caller)
- . = 0
- if(ismovable(caller))
- var/atom/movable/mover = caller
- . = . || (mover.pass_flags & PASSBLOB)
-
/obj/structure/blob/update_icon() //Updates color based on overmind color if we have an overmind.
if(overmind)
add_atom_colour(overmind.blobstrain.color, FIXED_COLOUR_PRIORITY)
diff --git a/code/modules/antagonists/swarmer/swarmer.dm b/code/modules/antagonists/swarmer/swarmer.dm
index 2d4ac88656..a572238877 100644
--- a/code/modules/antagonists/swarmer/swarmer.dm
+++ b/code/modules/antagonists/swarmer/swarmer.dm
@@ -139,12 +139,12 @@
else
death()
-/mob/living/simple_animal/hostile/swarmer/CanPass(atom/movable/O)
+/mob/living/simple_animal/hostile/swarmer/CanAllowThrough(atom/movable/O)
+ . = ..()
if(istype(O, /obj/item/projectile/beam/disabler))//Allows for swarmers to fight as a group without wasting their shots hitting each other
return 1
if(isswarmer(O))
return 1
- ..()
////CTRL CLICK FOR SWARMERS AND SWARMER_ACT()'S////
/mob/living/simple_animal/hostile/swarmer/AttackingTarget()
@@ -698,11 +698,12 @@
light_range = MINIMUM_USEFUL_LIGHT_RANGE
max_integrity = 50
-/obj/structure/swarmer/blockade/CanPass(atom/movable/O)
+/obj/structure/swarmer/blockade/CanAllowThrough(atom/movable/O)
+ . = ..()
if(isswarmer(O))
- return 1
+ return TRUE
if(istype(O, /obj/item/projectile/beam/disabler))
- return 1
+ return TRUE
/mob/living/simple_animal/hostile/swarmer/proc/CreateSwarmer()
set name = "Replicate"
diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm
index d0ed0f2436..94f7409cc9 100644
--- a/code/modules/assembly/infrared.dm
+++ b/code/modules/assembly/infrared.dm
@@ -220,7 +220,8 @@
icon_state = "ibeam"
anchored = TRUE
density = FALSE
- pass_flags = PASSTABLE|PASSGLASS|PASSGRILLE|LETPASSTHROW
+ pass_flags = PASSTABLE|PASSGLASS|PASSGRILLE
+ pass_flags_self = LETPASSTHROW
var/obj/item/assembly/infra/master
/obj/effect/beam/i_beam/Crossed(atom/movable/AM as mob|obj)
diff --git a/code/modules/awaymissions/away_props.dm b/code/modules/awaymissions/away_props.dm
index 36ed9b6ba3..d5d94b2a92 100644
--- a/code/modules/awaymissions/away_props.dm
+++ b/code/modules/awaymissions/away_props.dm
@@ -6,10 +6,11 @@
invisibility = INVISIBILITY_MAXIMUM
anchored = TRUE
-/obj/effect/oneway/CanPass(atom/movable/mover, turf/target)
+/obj/effect/oneway/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
var/turf/T = get_turf(src)
var/turf/MT = get_turf(mover)
- return ..() && (T == MT || get_dir(MT,T) == dir)
+ return . && (T == MT || get_dir(MT,T) == dir)
/obj/effect/wind
diff --git a/code/modules/awaymissions/capture_the_flag.dm b/code/modules/awaymissions/capture_the_flag.dm
index d32905e007..c6cd2e4d77 100644
--- a/code/modules/awaymissions/capture_the_flag.dm
+++ b/code/modules/awaymissions/capture_the_flag.dm
@@ -405,10 +405,10 @@
/obj/item/projectile/bullet/ctf
damage = 0
-/obj/item/projectile/bullet/ctf/prehit(atom/target)
+/obj/item/projectile/bullet/ctf/prehit_pierce(atom/target)
if(is_ctf_target(target))
damage = 60
- return //PROJECTILE_PIERCE_NONE /// hey uhh don't hit anyone behind them
+ return PROJECTILE_PIERCE_NONE /// hey uhh don't hit anyone behind them
. = ..()
/obj/item/gun/ballistic/automatic/laser/ctf
@@ -442,10 +442,10 @@
damage = 0
icon_state = "omnilaser"
-/obj/item/projectile/beam/ctf/prehit(atom/target)
+/obj/item/projectile/beam/ctf/prehit_pierce(atom/target)
if(is_ctf_target(target))
damage = 150
- return //PROJECTILE_PIERCE_NONE /// hey uhhh don't hit anyone behind them
+ return PROJECTILE_PIERCE_NONE /// hey uhhh don't hit anyone behind them
. = ..()
/proc/is_ctf_target(atom/target)
diff --git a/code/modules/events/spacevine.dm b/code/modules/events/spacevine.dm
index ed6a087cd9..8cbe7f50e1 100644
--- a/code/modules/events/spacevine.dm
+++ b/code/modules/events/spacevine.dm
@@ -523,7 +523,7 @@
if(!override)
qdel(src)
-/obj/structure/spacevine/CanPass(atom/movable/mover, turf/target)
+/obj/structure/spacevine/CanAllowThrough(atom/movable/mover, turf/target)
. = ..()
if(isvineimmune(mover))
return TRUE
diff --git a/code/modules/fields/turf_objects.dm b/code/modules/fields/turf_objects.dm
index 1af924294a..f8d139a45d 100644
--- a/code/modules/fields/turf_objects.dm
+++ b/code/modules/fields/turf_objects.dm
@@ -23,7 +23,7 @@
name = "energy field"
desc = "Get off my turf!"
-/obj/effect/abstract/proximity_checker/advanced/field_turf/CanPass(atom/movable/AM, turf/target)
+/obj/effect/abstract/proximity_checker/advanced/field_turf/CanAllowThrough(atom/movable/AM, turf/target)
. = ..()
if(parent)
return parent.field_turf_canpass(AM, src, target)
@@ -48,7 +48,7 @@
name = "energy field edge"
desc = "Edgy description here."
-/obj/effect/abstract/proximity_checker/advanced/field_edge/CanPass(atom/movable/AM, turf/target)
+/obj/effect/abstract/proximity_checker/advanced/field_edge/CanAllowThrough(atom/movable/AM, turf/target)
. = ..()
if(parent)
return parent.field_edge_canpass(AM, src, target)
diff --git a/code/modules/flufftext/Hallucination.dm b/code/modules/flufftext/Hallucination.dm
index 5d84901e7f..a43bb0cff5 100644
--- a/code/modules/flufftext/Hallucination.dm
+++ b/code/modules/flufftext/Hallucination.dm
@@ -647,10 +647,10 @@ GLOBAL_LIST_INIT(hallucination_list, list(
target.playsound_local(get_turf(airlock), 'sound/machines/boltsup.ogg',30,0,3)
qdel(src)
-/obj/effect/hallucination/fake_door_lock/CanPass(atom/movable/mover, turf/_target)
+/obj/effect/hallucination/fake_door_lock/CanAllowThrough(atom/movable/mover, turf/_target)
+ . = ..()
if(mover == target && airlock.density)
return FALSE
- return TRUE
/datum/hallucination/chat
diff --git a/code/modules/holiday/halloween/halloween.dm b/code/modules/holiday/halloween/halloween.dm
index 0c9987fc00..1e5f4b4502 100644
--- a/code/modules/holiday/halloween/halloween.dm
+++ b/code/modules/holiday/halloween/halloween.dm
@@ -175,9 +175,6 @@
step(I,direction)
return
-/mob/living/simple_animal/hostile/construct/shade/howling_ghost/CanPass(atom/movable/mover, turf/target)
- return 1
-
///////////////////////////
//Spookoween Insane Clown//
///////////////////////////
@@ -233,7 +230,7 @@
return
/mob/living/simple_animal/hostile/retaliate/clown/insane/adjustHealth()
- . = ..()
+ . = ..()
if(prob(5))
playsound(loc, 'sound/spookoween/insane_low_laugh.ogg', 300, 1)
diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm
index 38e4fcc6ff..a314210570 100644
--- a/code/modules/hydroponics/grown/towercap.dm
+++ b/code/modules/hydroponics/grown/towercap.dm
@@ -151,6 +151,7 @@
density = FALSE
anchored = TRUE
buckle_lying = 0
+ pass_flags_self = PASSTABLE | LETPASSTHROW
var/burning = 0
var/burn_icon = "bonfire_on_fire" //for a softer more burning embers icon, use "bonfire_warm"
var/grill = FALSE
@@ -163,13 +164,6 @@
. = ..()
StartBurning()
-/obj/structure/bonfire/CanPass(atom/movable/mover, turf/target)
- if(istype(mover) && (mover.pass_flags & PASSTABLE))
- return TRUE
- if(mover.throwing)
- return TRUE
- return ..()
-
/obj/structure/bonfire/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stack/rods) && !can_buckle && !grill)
var/obj/item/stack/rods/R = W
diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm
index 8037a22a52..50c91378ec 100644
--- a/code/modules/mining/minebot.dm
+++ b/code/modules/mining/minebot.dm
@@ -131,7 +131,8 @@
to_chat(M, "[src] has been set to attack hostile wildlife.")
return
-/mob/living/simple_animal/hostile/mining_drone/CanPass(atom/movable/O)
+/mob/living/simple_animal/hostile/mining_drone/CanAllowThrough(atom/movable/O)
+ . = ..()
if(istype(O, /obj/item/projectile/kinetic))
var/obj/item/projectile/kinetic/K = O
if(K.kinetic_gun)
@@ -141,7 +142,6 @@
return TRUE
if(istype(O, /obj/item/projectile/destabilizer))
return TRUE
- return ..()
/mob/living/simple_animal/hostile/mining_drone/proc/SetCollectBehavior()
mode = MINEDRONE_COLLECT
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index 624db8caf5..4b228e1eb3 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -166,9 +166,6 @@ GLOBAL_VAR_INIT(observer_default_invisibility, INVISIBILITY_OBSERVER)
QDEL_NULL(spawners_menu)
return ..()
-/mob/dead/CanPass(atom/movable/mover, turf/target)
- return 1
-
/*
* This proc will update the icon of the ghost itself, with hair overlays, as well as the ghost image.
* Please call update_icon(icon_state) from now on when you want to update the icon_state of the ghost,
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index 71573abc90..b65155f086 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -53,7 +53,7 @@
dna.species.on_hit(P, src)
-/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone)
+/mob/living/carbon/human/bullet_act(obj/item/projectile/P, def_zone, piercing_hit = FALSE)
if(dna && dna.species)
var/spec_return = dna.species.bullet_act(P, src)
if(spec_return)
@@ -61,7 +61,7 @@
if(mind) //martial art stuff
if(mind.martial_art && mind.martial_art.can_use(src)) //Some martial arts users can deflect projectiles!
- var/martial_art_result = mind.martial_art.on_projectile_hit(src, P, def_zone)
+ var/martial_art_result = mind.martial_art.on_projectile_hit(src, P, def_zone, piercing_hit)
if(!(martial_art_result == BULLET_ACT_HIT))
return martial_art_result
return ..()
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 5ce80c5575..2aaedb22a5 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -68,7 +68,7 @@
else
CRASH("Invalid rediretion mode [redirection_mode]")
-/mob/living/bullet_act(obj/item/projectile/P, def_zone)
+/mob/living/bullet_act(obj/item/projectile/P, def_zone, piercing_hit = FALSE)
var/totaldamage = P.damage
var/final_percent = 0
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
@@ -81,7 +81,7 @@
if(returned & BLOCK_REDIRECTED)
return BULLET_ACT_FORCE_PIERCE
if(returned & BLOCK_SUCCESS)
- P.on_hit(src, final_percent, def_zone)
+ P.on_hit(src, final_percent, def_zone, piercing_hit)
return BULLET_ACT_BLOCK
totaldamage = block_calculate_resultant_damage(totaldamage, returnlist)
var/armor = run_armor_check(def_zone, P.flag, null, null, P.armour_penetration, null)
diff --git a/code/modules/mob/living/living_movement.dm b/code/modules/mob/living/living_movement.dm
index a35558884b..fcab9344d9 100644
--- a/code/modules/mob/living/living_movement.dm
+++ b/code/modules/mob/living/living_movement.dm
@@ -20,12 +20,10 @@
/mob/living/proc/update_density()
density = !lying && !HAS_TRAIT(src, TRAIT_LIVING_NO_DENSITY)
-/mob/living/CanPass(atom/movable/mover, turf/target)
- if((mover.pass_flags & PASSMOB))
- return TRUE
- if(istype(mover, /obj/item/projectile))
- var/obj/item/projectile/P = mover
- return !P.can_hit_target(src, P.permutated, src == P.original, TRUE)
+/mob/living/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(.)
+ return
if(mover.throwing)
return (!density || lying)
if(buckled == mover)
@@ -41,7 +39,7 @@
var/mob/living/L = mover //typecast first, check isliving and only check this if living using short circuit
if(isliving(L) && lying && L.lying) //if we're both lying down and aren't already being thrown/shipped around, don't pass
return FALSE
- return (!density || (isliving(mover)? L.can_move_under_living(src) : !mover.density))
+ return (isliving(mover)? L.can_move_under_living(src) : !mover.density)
/mob/living/toggle_move_intent()
. = ..()
diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm
index 55d0336671..a87c0a81ab 100644
--- a/code/modules/mob/living/silicon/silicon_defense.dm
+++ b/code/modules/mob/living/silicon/silicon_defense.dm
@@ -120,7 +120,7 @@
"You are thrown off of [src]!")
flash_act(affect_silicon = 1)
-/mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone)
+/mob/living/silicon/bullet_act(obj/item/projectile/P, def_zone, piercing_hit = FALSE)
var/totaldamage = P.damage
if(P.original != src || P.firer != src) //try to block or reflect the bullet, can't do so when shooting oneself
var/list/returnlist = list()
@@ -141,7 +141,7 @@
"You are knocked off of [src] by the [P]!")
unbuckle_mob(M)
M.DefaultCombatKnockdown(40)
- P.on_hit(src, 0, def_zone)
+ P.on_hit(src, 0, def_zone, 0, piercing_hit)
return BULLET_ACT_HIT
/mob/living/silicon/flash_act(intensity = 1, override_blindness_check = 0, affect_silicon = 0, visual = 0, type = /atom/movable/screen/fullscreen/tiled/flash/static)
diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm
index b003e066ef..df8ef44845 100644
--- a/code/modules/mob/living/simple_animal/animal_defense.dm
+++ b/code/modules/mob/living/simple_animal/animal_defense.dm
@@ -124,10 +124,10 @@
apply_damage(damage, damagetype, null, getarmor(null, armorcheck))
return TRUE
-/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj)
+/mob/living/simple_animal/bullet_act(obj/item/projectile/Proj, def_zone, piercing_hit = FALSE)
if(!Proj)
return
- apply_damage(Proj.damage, Proj.damage_type)
+ apply_damage(Proj.damage, Proj.damage_type, 0, piercing_hit)
Proj.on_hit(src)
return BULLET_ACT_HIT
diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
index 2d964f5721..baa0fe4649 100644
--- a/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
+++ b/code/modules/mob/living/simple_animal/hostile/jungle/mook.dm
@@ -33,12 +33,12 @@
footstep_type = FOOTSTEP_MOB_BAREFOOT
-/mob/living/simple_animal/hostile/jungle/mook/CanPass(atom/movable/O)
+/mob/living/simple_animal/hostile/jungle/mook/CanAllowThrough(atom/movable/O)
+ . = ..()
if(istype(O, /mob/living/simple_animal/hostile/jungle/mook))
var/mob/living/simple_animal/hostile/jungle/mook/M = O
if(M.attack_state == MOOK_ATTACK_ACTIVE && M.throwing)
return TRUE
- return ..()
/mob/living/simple_animal/hostile/jungle/mook/death()
desc = "A deceased primitive. Upon closer inspection, it was suffering from severe cellular degeneration and its garments are machine made..."//Can you guess the twist
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
index 9bcc21efa6..ab6c9fa301 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/bubblegum.dm
@@ -160,10 +160,10 @@ Difficulty: Hard
severity = EXPLODE_LIGHT // puny mortals
return ..()
-/mob/living/simple_animal/hostile/megafauna/bubblegum/CanPass(atom/movable/mover, turf/target)
+/mob/living/simple_animal/hostile/megafauna/bubblegum/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination))
- return 1
- return ..()
+ return TRUE
/mob/living/simple_animal/hostile/megafauna/bubblegum/Goto(target, delay, minimum_distance)
if(!charging)
@@ -466,10 +466,10 @@ Difficulty: Hard
new /obj/effect/decal/cleanable/blood(get_turf(src))
. = ..()
-/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/CanPass(atom/movable/mover, turf/target)
+/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(istype(mover, /mob/living/simple_animal/hostile/megafauna/bubblegum)) // hallucinations should not be stopping bubblegum or eachother
- return 1
- return ..()
+ return TRUE
/mob/living/simple_animal/hostile/megafauna/bubblegum/hallucination/Life()
return
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
index c1aea8db9d..a4620cd781 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm
@@ -490,7 +490,8 @@ Difficulty: Normal
queue_smooth_neighbors(src)
return ..()
-/obj/effect/temp_visual/hierophant/wall/CanPass(atom/movable/mover, turf/target)
+/obj/effect/temp_visual/hierophant/wall/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(QDELETED(caster))
return FALSE
if(mover == caster.pulledby)
@@ -501,7 +502,6 @@ Difficulty: Normal
return TRUE
if(mover == caster)
return TRUE
- return FALSE
/obj/effect/temp_visual/hierophant/chaser //a hierophant's chaser. follows target around, moving and producing a blast every speed deciseconds.
duration = 98
diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
index 15bfe2b7f7..f0f978c03f 100644
--- a/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
+++ b/code/modules/mob/living/simple_animal/hostile/megafauna/legion.dm
@@ -394,7 +394,7 @@ SHITCODE AHEAD. BE ADVISED. Also comment extravaganza
muzzle_type = /obj/effect/projectile/tracer/legion
impact_type = /obj/effect/projectile/tracer/legion
hitscan = TRUE
- movement_type = UNSTOPPABLE
+ projectile_piercing = ALL
///Used for the legion turret tracer.
/obj/effect/projectile/tracer/legion/tracer
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
index ed056c2ad9..04b003b315 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/curse_blob.dm
@@ -72,14 +72,14 @@
return
//if it's not our target, we ignore it
-/mob/living/simple_animal/hostile/asteroid/curseblob/CanPass(atom/movable/mover, turf/target)
+/mob/living/simple_animal/hostile/asteroid/curseblob/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(mover == set_target)
return FALSE
if(istype(mover, /obj/item/projectile))
var/obj/item/projectile/P = mover
if(P.firer == set_target)
return FALSE
- return TRUE
#define IGNORE_PROC_IF_NOT_TARGET(X) /mob/living/simple_animal/hostile/asteroid/curseblob/##X(AM) { if (AM == set_target) return ..(); }
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
index be596b0292..b92f429c8c 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/elite.dm
@@ -383,8 +383,7 @@ While using this makes the system rely on OnFire, it still gives options for tim
ourelite = null
return ..()
-/obj/effect/temp_visual/elite_tumor_wall/CanPass(atom/movable/mover, turf/target)
+/obj/effect/temp_visual/elite_tumor_wall/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(mover == ourelite || mover == activator)
return FALSE
- else
- return TRUE
diff --git a/code/modules/mob/living/simple_animal/slime/slime.dm b/code/modules/mob/living/simple_animal/slime/slime.dm
index 38149494bc..9812307300 100644
--- a/code/modules/mob/living/simple_animal/slime/slime.dm
+++ b/code/modules/mob/living/simple_animal/slime/slime.dm
@@ -231,11 +231,11 @@
amount = -abs(amount)
return ..() //Heals them
-/mob/living/simple_animal/slime/bullet_act(obj/item/projectile/Proj)
+/mob/living/simple_animal/slime/bullet_act(obj/item/projectile/Proj, def_zone, piercing_hit = FALSE)
attacked += 10
if((Proj.damage_type == BURN))
adjustBruteLoss(-abs(Proj.damage)) //fire projectiles heals slimes.
- Proj.on_hit(src)
+ Proj.on_hit(src, 0, piercing_hit)
return BULLET_ACT_BLOCK
return ..()
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 527b0c0917..138a3b9662 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -9,7 +9,7 @@
mouse_drag_pointer = MOUSE_ACTIVE_POINTER
throwforce = 10
blocks_emissive = EMISSIVE_BLOCK_GENERIC
-
+ pass_flags_self = PASSMOB
vis_flags = VIS_INHERIT_PLANE //when this be added to vis_contents of something it inherit something.plane, important for visualisation of mob in openspace.
attack_hand_is_action = TRUE
diff --git a/code/modules/plumbing/plumbers/grinder_chemical.dm b/code/modules/plumbing/plumbers/grinder_chemical.dm
index f39c79f906..1d216046e4 100644
--- a/code/modules/plumbing/plumbers/grinder_chemical.dm
+++ b/code/modules/plumbing/plumbers/grinder_chemical.dm
@@ -31,7 +31,7 @@
eat_dir = WEST
return TRUE
-/obj/machinery/plumbing/grinder_chemical/CanPass(atom/movable/AM)
+/obj/machinery/plumbing/grinder_chemical/CanAllowThrough(atom/movable/AM)
. = ..()
if(!anchored)
return
diff --git a/code/modules/power/singularity/containment_field.dm b/code/modules/power/singularity/containment_field.dm
index ff6cf99411..7c6b1cc922 100644
--- a/code/modules/power/singularity/containment_field.dm
+++ b/code/modules/power/singularity/containment_field.dm
@@ -100,10 +100,10 @@
return
-/obj/machinery/field/CanPass(atom/movable/mover, turf/target)
+/obj/machinery/field/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(hasShocked || isliving(mover) || ismachinery(mover) || isstructure(mover) || ismecha(mover))
return FALSE
- return ..()
/obj/machinery/field/proc/shock(mob/living/user)
var/shock_damage = min(rand(30,40),rand(30,40))
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 4d394401c4..7516092149 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -232,14 +232,14 @@
kinetic_gun = null
return ..()
-/obj/item/projectile/kinetic/prehit(atom/target)
+/obj/item/projectile/kinetic/prehit_pierce(atom/target)
. = ..()
if(.)
if(kinetic_gun)
var/list/mods = kinetic_gun.get_modkits()
for(var/obj/item/borg/upgrade/modkit/M in mods)
M.projectile_prehit(src, target, kinetic_gun)
- if(!lavaland_equipment_pressure_check(get_turf(target)))
+ if(!pressure_decrease_active && !lavaland_equipment_pressure_check(get_turf(target)))
name = "weakened [name]"
damage = damage * pressure_decrease
pressure_decrease_active = TRUE
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index 2ef974a450..ebc388a965 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -427,11 +427,9 @@
var/aoe_mob_damage = 30
var/impact_structure_damage = 0
var/impact_direct_damage = 0
- var/turf/cached
var/list/pierced = list()
/obj/item/projectile/beam/beam_rifle/proc/AOE(turf/epicenter)
- set waitfor = FALSE
if(!epicenter)
return
new /obj/effect/temp_visual/explosion/fast(epicenter)
@@ -447,31 +445,22 @@
continue
O.take_damage(aoe_structure_damage * get_damage_coeff(O), BURN, "laser", FALSE)
-/obj/item/projectile/beam/beam_rifle/proc/check_pierce(atom/target)
- if(!do_pierce)
- return FALSE
- if(pierced[target]) //we already pierced them go away
- return TRUE
- if(isclosedturf(target))
- if(wall_pierce++ < wall_pierce_amount)
- if(prob(wall_devastate))
- if(iswallturf(target))
- var/turf/closed/wall/W = target
- W.dismantle_wall(TRUE, TRUE)
- else
- target.ex_act(EXPLODE_HEAVY)
- return TRUE
- if(ismovable(target))
- var/atom/movable/AM = target
- if(AM.density && !AM.CanPass(src, get_turf(target)) && !ismob(AM))
- if(structure_pierce < structure_pierce_amount)
- if(isobj(AM))
- var/obj/O = AM
- O.take_damage((impact_structure_damage + aoe_structure_damage) * structure_bleed_coeff * get_damage_coeff(AM), BURN, "energy", FALSE)
- pierced[AM] = TRUE
- structure_pierce++
- return TRUE
- return FALSE
+/obj/item/projectile/beam/beam_rifle/proc/check_pierce(atom/A)
+ if(isclosedturf(A) && (wall_pierce < wall_pierce_amount))
+ if(prob(wall_devastate))
+ if(iswallturf(A))
+ var/turf/closed/wall/W = A
+ W.dismantle_wall(TRUE, TRUE)
+ else
+ target.ex_act(EXPLODE_HEAVY)
+ ++wall_pierce
+ return PROJECTILE_PIERCE_PHASE // yeah this gun is a snowflakey piece of garbage - Silly-Cons
+ if(isobj(A) && (structure_pierce < structure_pierce_amount))
+ ++structure_pierce
+ var/obj/O = A
+ O.take_damage((impact_structure_damage + aoe_structure_damage) * structure_bleed_coeff * get_damage_coeff(A), BURN, ENERGY, FALSE)
+ return PROJECTILE_PIERCE_PHASE // ditto and this could be refactored to on_hit honestly - Silly-Cons
+ return ..()
/obj/item/projectile/beam/beam_rifle/proc/get_damage_coeff(atom/target)
if(istype(target, /obj/machinery/door))
@@ -491,32 +480,18 @@
L.adjustFireLoss(impact_direct_damage)
L.emote("scream")
-/obj/item/projectile/beam/beam_rifle/proc/handle_hit(atom/target)
+/obj/item/projectile/beam/beam_rifle/proc/handle_hit(atom/target, piercing_hit = FALSE)
set waitfor = FALSE
- if(!cached && !QDELETED(target))
- cached = get_turf(target)
if(nodamage)
return FALSE
- playsound(cached, 'sound/effects/explosion3.ogg', 100, 1)
- AOE(cached)
+ playsound(src, 'sound/effects/explosion3.ogg', 100, TRUE)
+ if(!piercing_hit)
+ AOE(get_turf(target) || get_turf(src))
if(!QDELETED(target))
handle_impact(target)
-/obj/item/projectile/beam/beam_rifle/Bump(atom/target)
- if(check_pierce(target))
- permutated += target
- trajectory_ignore_forcemove = TRUE
- forceMove(target.loc)
- trajectory_ignore_forcemove = FALSE
- return FALSE
- if(!QDELETED(target))
- cached = get_turf(target)
- . = ..()
-
-/obj/item/projectile/beam/beam_rifle/on_hit(atom/target, blocked = FALSE)
- if(!QDELETED(target))
- cached = get_turf(target)
- handle_hit(target)
+/obj/projectile/beam/beam_rifle/on_hit(atom/target, blocked = FALSE, piercing_hit = FALSE)
+ handle_hit(target, piercing_hit)
. = ..()
/obj/item/projectile/beam/beam_rifle/hitscan
@@ -547,6 +522,9 @@
hitscan_light_intensity = 0
hitscan_light_color_override = "#99ff99"
-/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit(atom/target)
+/obj/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit_pierce(atom/target)
+ return PROJECTILE_DELETE_WITHOUT_HITTING
+
+/obj/projectile/beam/beam_rifle/hitscan/aiming_beam/on_hit()
qdel(src)
- return FALSE
+ return BULLET_ACT_BLOCK
diff --git a/code/modules/projectiles/guns/misc/blastcannon.dm b/code/modules/projectiles/guns/misc/blastcannon.dm
index 64cffe52e7..b28c06a2c2 100644
--- a/code/modules/projectiles/guns/misc/blastcannon.dm
+++ b/code/modules/projectiles/guns/misc/blastcannon.dm
@@ -114,7 +114,8 @@
icon_state = "blastwave"
damage = 0
nodamage = FALSE
- movement_type = FLYING | UNSTOPPABLE
+ movement_type = FLYING
+ projectile_phasing = ALL // just blows up the turfs lmao - Silly-Cons
var/heavyr = 0
var/mediumr = 0
var/lightr = 0
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index ca07bde239..3fd1bce1ca 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -13,9 +13,9 @@
density = FALSE
anchored = TRUE
item_flags = ABSTRACT
- pass_flags = PASSTABLE
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
movement_type = FLYING
+ generic_canpass = FALSE
animate_movement = NO_STEPS
hitsound = 'sound/weapons/pierce.ogg'
appearance_flags = PIXEL_SCALE
@@ -40,6 +40,35 @@
var/time_offset = 0
var/datum/point/vector/trajectory
var/trajectory_ignore_forcemove = FALSE //instructs forceMove to NOT reset our trajectory to the new location!
+ /// 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.
+ var/list/impacted
+ /// If TRUE, we can hit our firer.
+ var/ignore_source_check = FALSE
+ /// We are flagged PHASING temporarily to not stop moving when we Bump something but want to keep going anyways.
+ var/temporary_unstoppable_movement = FALSE
+
+ /** PROJECTILE PIERCING
+ * WARNING:
+ * Projectile piercing MUST be done using these variables.
+ * Ordinary passflags will be **IGNORED**.
+ * The two flag variables below both use pass flags.
+ * In the context of LETPASStHROW, it means the projectile will ignore things that are currently "in the air" from a throw.
+ *
+ * Also, projectiles sense hits using Bump(), and then pierce them if necessary.
+ * They simply do not follow conventional movement rules.
+ * NEVER flag a projectile as PHASING movement type.
+ * If you so badly need to make one go through *everything*, override check_pierce() for your projectile to always return PROJECTILE_PIERCE_PHASE/HIT.
+ */
+ /// 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.
+ pass_flags = PASSTABLE
+ /// If FALSE, allow us to hit something directly targeted/clicked/whatnot even if we're able to phase through it
+ var/phasing_ignore_direct_target = FALSE
+ /// 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.
+ var/projectile_phasing = NONE
+ /// Bitflag for things the projectile should hit, but pierce through without deleting itself. Defers to projectile_phasing. Uses pass_flags flags.
+ var/projectile_piercing = NONE
+ /// number of times we've pierced something. Incremented BEFORE bullet_act and on_hit proc!
+ var/pierces = 0
/// "leftover" pixels for Range() calculation as pixel_move() was moved to simulated semi-pixel movement and Range() is in tiles.
var/pixels_range_leftover = 0
/// "leftover" tick pixels and stuff yeah, so we don't round off things and introducing tracing inaccuracy.
@@ -117,8 +146,6 @@
/// How many deciseconds are each hitscan movement considered. Used for homing and other things that use seconds for timing rather than ticks.
var/hitscan_movement_decisecond_equivalency = 0.1
- var/ignore_source_check = FALSE
-
var/damage = 10
var/damage_type = BRUTE //BRUTE, BURN, TOX, OXY, CLONE are the only things that should be in here
var/nodamage = 0 //Determines if the projectile will skip any damage inflictions
@@ -150,8 +177,6 @@
var/impact_effect_type //what type of impact effect to show when hitting something
var/log_override = FALSE //is this type spammed enough to not log? (KAs)
- var/temporary_unstoppable_movement = FALSE
-
///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
var/shrapnel_type
///If TRUE, hit mobs even if they're on the floor and not our target
@@ -167,7 +192,6 @@
/obj/item/projectile/Initialize()
. = ..()
- permutated = list()
decayedRange = range
if(embedding)
updateEmbedding()
@@ -201,10 +225,7 @@
else //when a limb is missing the damage is actually passed to the chest
return BODY_ZONE_CHEST
-/obj/item/projectile/proc/prehit(atom/target)
- return TRUE
-
-/obj/item/projectile/proc/on_hit(atom/target, blocked = FALSE)
+/obj/item/projectile/proc/on_hit(atom/target, blocked = FALSE, pierce_hit)
if(fired_from)
SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_ON_HIT, firer, target, Angle)
@@ -238,6 +259,11 @@
if(!isliving(target))
if(impact_effect_type && !hitscan)
new impact_effect_type(target_loca, hitx, hity)
+ if(isturf(target) && hitsound_wall)
+ var/volume = clamp(vol_by_damage() + 20, 0, 100)
+ if(suppressed)
+ volume = 5
+ playsound(loc, hitsound_wall, volume, TRUE, -1)
return BULLET_ACT_HIT
var/mob/living/L = target
@@ -278,7 +304,7 @@
else
if(hitsound)
var/volume = vol_by_damage()
- playsound(loc, hitsound, volume, 1, -1)
+ playsound(src, hitsound, volume, 1, -1)
L.visible_message("[L] is hit by \a [src][organ_hit_text]!", \
"[L] is hit by \a [src][organ_hit_text]!", null, COMBAT_MESSAGE_RANGE)
if(candink && def_zone == BODY_ZONE_HEAD)
@@ -298,7 +324,7 @@
/obj/item/projectile/proc/vol_by_damage()
if(src.damage)
- return clamp((src.damage) * 0.67, 30, 100)// Multiply projectile damage by 0.67, then CLAMP the value between 30 and 100
+ return clamp((src.damage) * 0.67, 30, 100) // Multiply projectile damage by 0.67, then CLAMP the value between 30 and 100
else
return 50 //if the projectile doesn't do damage, play its hitsound at 50% volume
@@ -327,95 +353,267 @@
beam_segments[beam_index] = null
/obj/item/projectile/Bump(atom/A)
- if(!trajectory)
+ SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
+ if(!can_hit_target(A, A == original, TRUE))
return
+ Impact(A)
+
+/**
+ * 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.
+ */
+/obj/projectile/proc/Impact(atom/A)
+ if(!trajectory)
+ qdel(src)
+ return FALSE
+ if(impacted[A]) // NEVER doublehit - Silly-Cons
+ return FALSE
+ var/datum/point/pcache = trajectory.copy_to()
var/turf/T = get_turf(A)
if(check_ricochet_flag(A) && check_ricochet(A)) //if you can ricochet, attempt to ricochet off the object
ricochets++
if(A.handle_ricochet(src))
on_ricochet(A) //if allowed, use autoaim to ricochet into someone, otherwise default to ricocheting off the object from above
- var/datum/point/pcache = trajectory.copy_to()
- if(hitscan)
- store_hitscan_collision(pcache)
+ impacted = list() // Shoot a x-ray laser at a pair of mirrors I dare you
+ ignore_source_check = TRUE // Firer is no longer immune
decayedRange = max(0, decayedRange - reflect_range_decrease)
ricochet_chance *= ricochet_decay_chance
damage *= ricochet_decay_damage
range = decayedRange
+ if(hitscan)
+ store_hitscan_collision(pcache)
return TRUE
var/distance = get_dist(T, starting) // Get the distance between the turf shot from and the mob we hit and use that for the calculations.
if(def_zone && check_zone(def_zone) != BODY_ZONE_CHEST)
def_zone = ran_zone(def_zone, max(100-(7*distance), 5) * zone_accuracy_factor) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use.
- if(isturf(A) && hitsound_wall)
- var/volume = clamp(vol_by_damage() + 20, 0, 100)
- if(suppressed)
- volume = 5
- playsound(loc, hitsound_wall, volume, 1, -1)
+ return process_hit(T, select_target(T, A)) // SELECT TARGET FIRST!
- return process_hit(T, select_target(T, A))
-
-#define QDEL_SELF 1 //Delete if we're not UNSTOPPABLE flagged non-temporarily
-#define DO_NOT_QDEL 2 //Pass through.
-#define FORCE_QDEL 3 //Force deletion.
-
-/obj/item/projectile/proc/process_hit(turf/T, atom/target, qdel_self, hit_something = FALSE) //probably needs to be reworked entirely when pixel movement is done.
- if(QDELETED(src) || !T || !target) //We're done, nothing's left.
- if((qdel_self == FORCE_QDEL) || ((qdel_self == QDEL_SELF) && !temporary_unstoppable_movement && !(movement_type & UNSTOPPABLE)))
- qdel(src)
+/**
+ * The primary workhorse proc of projectile impacts.
+ * This is a RECURSIVE call - process_hit is called on the first selected target, and then repeatedly called if the projectile still hasn't been deleted.
+ *
+ * Order of operations:
+ * 1. Checks if we are deleted, or if we're somehow trying to hit a null, in which case, bail out
+ * 2. Adds the thing we're hitting to impacted so we can make sure we don't doublehit
+ * 3. Checks piercing - stores this.
+ * Afterwards:
+ * Hit and delete, hit without deleting and pass through, pass through without hitting, or delete without hitting depending on result
+ * If we're going through without hitting, find something else to hit if possible and recurse, set unstoppable movement to true
+ * If we're deleting without hitting, delete and return
+ * Otherwise, send signal of COMSIG_PROJECTILE_PREHIT to target
+ * Then, hit, deleting ourselves if necessary.
+ * @params
+ * T - Turf we're on/supposedly hitting
+ * target - target we're hitting
+ * hit_something - only should be set by recursive calling by this proc - tracks if we hit something already
+ *
+ * Returns if we hit something.
+ * - Silly-Cons
+ */
+/obj/item/projectile/proc/process_hit(turf/T, atom/target, hit_something = FALSE)
+ // 1.
+ if(QDELETED(src) || !T || !target)
+ return
+ // 2.
+ impacted[target] = TRUE //hash lookup > in for performance in hit-checking
+ // 3.
+ var/mode = prehit_pierce(target)
+ if(mode == PROJECTILE_DELETE_WITHOUT_HITTING)
+ qdel(src)
return hit_something
- permutated |= target //Make sure we're never hitting it again. If we ever run into weirdness with piercing projectiles needing to hit something multiple times.. well.. that's a to-do.
- if(!prehit(target))
- return process_hit(T, select_target(T), qdel_self, hit_something) //Hit whatever else we can since that didn't work.
- var/result = target.bullet_act(src, def_zone)
- if(result == BULLET_ACT_FORCE_PIERCE)
- if(!(movement_type & UNSTOPPABLE))
+ else if(mode == PROJECTILE_PIERCE_PHASE)
+ if(!(movement_type & PHASING))
temporary_unstoppable_movement = TRUE
- movement_type |= UNSTOPPABLE
- return process_hit(T, select_target(T), qdel_self, TRUE) //Hit whatever else we can since we're piercing through but we're still on the same tile.
- else if(result == BULLET_ACT_TURF) //We hit the turf but instead we're going to also hit something else on it.
- return process_hit(T, select_target(T), QDEL_SELF, TRUE)
- else //Whether it hit or blocked, we're done!
- qdel_self = QDEL_SELF
- hit_something = TRUE
- if((qdel_self == FORCE_QDEL) || ((qdel_self == QDEL_SELF) && !temporary_unstoppable_movement && !(movement_type & UNSTOPPABLE)))
+ movement_type |= PHASING
+ return process_hit(T, select_target(T, target), hit_something) // try to hit something else
+ // at this point we are going to hit the thing
+ // in which case send signal to it
+ SEND_SIGNAL(target, COMSIG_PROJECTILE_PREHIT, args)
+ if(mode == PROJECTILE_PIERCE_HIT)
+ ++pierces
+ hit_something = TRUE
+ var/result = target.bullet_act(src, def_zone, mode == PROJECTILE_PIERCE_HIT)
+ if((result == BULLET_ACT_FORCE_PIERCE) || (mode == PROJECTILE_PIERCE_HIT))
+ if(!(movement_type & PHASING))
+ temporary_unstoppable_movement = TRUE
+ movement_type |= PHASING
+ return process_hit(T, select_target(T, target), TRUE)
qdel(src)
return hit_something
-#undef QDEL_SELF
-#undef DO_NOT_QDEL
-#undef FORCE_QDEL
-
-/obj/item/projectile/proc/select_target(turf/T, atom/target) //Select a target from a turf.
- if((original in T) && can_hit_target(original, permutated, TRUE, TRUE))
+/**
+ * Selects a target to hit from a turf
+ *
+ * @params
+ * T - The turf
+ * target - The "preferred" atom to hit, usually what we Bumped() first.
+ *
+ * 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. The thing originally aimed at/clicked on
+ * 2. Mobs - picks lowest buckled mob to prevent scarp piggybacking memes
+ * 3. Objs
+ * 4. Turf
+ * 5. Nothing
+ */
+/obj/projectile/proc/select_target(turf/T, atom/target)
+ // 1. original
+ if(can_hit_target(original, TRUE, FALSE))
return original
- if(target && can_hit_target(target, permutated, target == original, TRUE))
- return target
- var/list/mob/living/possible_mobs = typecache_filter_list(T, GLOB.typecache_mob)
- var/list/mob/mobs = list()
- for(var/mob/living/M in possible_mobs)
- if(!can_hit_target(M, permutated, M == original, TRUE))
+ var/list/atom/possible = list() // let's define these ONCE
+ var/list/atom/considering = list()
+ // 2. mobs
+ possible = typecache_filter_list(T, GLOB.typecache_living) // living only
+ for(var/i in possible)
+ if(!can_hit_target(i, i == original, TRUE))
continue
- mobs += M
- var/mob/M = safepick(mobs)
- if(M)
+ considering += i
+ if(considering.len)
+ var/mob/living/M = pick(considering)
return M.lowest_buckled_mob()
- var/list/obj/possible_objs = typecache_filter_list(T, GLOB.typecache_machine_or_structure)
- var/list/obj/objs = list()
- for(var/obj/O in possible_objs)
- if(!can_hit_target(O, permutated, O == original, TRUE))
+ considering.len = 0
+ // 3. objs
+ possible = typecache_filter_list(T, GLOB.typecache_machine_or_structure) // because why are items ever dense?
+ for(var/i in possible)
+ if(!can_hit_target(i, i == original, TRUE))
continue
- objs += O
- var/obj/O = safepick(objs)
- if(O)
- if(length(O.buckled_mobs))
- return pick(O.buckled_mobs)
- return O
- //Nothing else is here that we can hit, hit the turf if we haven't.
- if(!(T in permutated) && can_hit_target(T, permutated, T == original, TRUE))
+ considering += i
+ if(considering.len)
+ return pick(considering)
+ // 4. turf
+ if(can_hit_target(T, T == original, TRUE))
return T
- //Returns null if nothing at all was found.
+ // 5. nothing
+ // (returns null)
+//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.
+/obj/projectile/proc/can_hit_target(atom/target, direct_target = FALSE, ignore_loc = FALSE)
+ if(QDELETED(target) || impacted[target])
+ return FALSE
+ if(!ignore_loc && (loc != target.loc))
+ return FALSE
+ // if pass_flags match, pass through entirely
+ if(target.pass_flags_self & pass_flags) // phasing
+ return FALSE
+ if(!ignore_source_check && firer)
+ var/mob/M = firer
+ if((target == firer) || ((target == firer.loc) && ismecha(firer.loc)) || (target in firer.buckled_mobs) || (istype(M) && (M.buckled == target)))
+ return FALSE
+ if(target.density) //This thing blocks projectiles, hit it regardless of layer/mob stuns/etc.
+ return TRUE
+ if(!isliving(target))
+ if(isturf(target)) // non dense turfs
+ return FALSE
+ if(target.layer < PROJECTILE_HIT_THRESHHOLD_LAYER)
+ return FALSE
+ else if(!direct_target) // non dense objects do not get hit unless specifically clicked
+ return FALSE
+ else
+ var/mob/living/L = target
+ if(direct_target)
+ return TRUE
+ // If target not able to use items, move and stand - or if they're just dead, pass over.
+ if(L.stat == DEAD || (!hit_stunned_targets && HAS_TRAIT(L, TRAIT_IMMOBILIZED) && HAS_TRAIT(L, TRAIT_FLOORED) && HAS_TRAIT(L, TRAIT_HANDS_BLOCKED)))
+ return FALSE
+ return TRUE
+
+/**
+ * Scan if we should hit something and hit it if we need to
+ * The difference between this and handling in Impact is
+ * In this we strictly check if we need to Impact() something in specific
+ * If we do, we do
+ * We don't even check if it got hit already - Impact() does that
+ * In impact there's more code for selecting WHAT to hit
+ * So this proc is more of checking if we should hit something at all BY having an atom cross us.
+ */
+/obj/projectile/proc/scan_crossed_hit(atom/movable/A)
+ if(can_hit_target(A, direct_target = (A == original)))
+ Impact(A)
+
+/**
+ * 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.
+ */
+/obj/projectile/proc/scan_moved_turf()
+ // Optimally, we scan: mobs --> objs --> turf for impact
+ // but, overhead is a thing and 2 for loops every time it moves is a no-go.
+ // realistically, since we already do select_target in impact, we can not do that
+ // and hope projectiles get refactored again in the future to have a less stupid impact detection system
+ // that hopefully won't also involve a ton of overhead
+ if(can_hit_target(original, TRUE, FALSE))
+ Impact(original) // try to hit thing clicked on
+ // else, try to hit mobs
+ else // because if we impacted original and pierced we'll already have select target'd and hit everything else we should be hitting
+ for(var/mob/M in loc) // so I guess we're STILL doing a for loop of mobs because living movement would otherwise have snowflake code for projectile CanPass
+ // so the snowflake vs performance is pretty arguable here
+ if(can_hit_target(M, M == original, TRUE))
+ Impact(M)
+ break
+
+/**
+ * Projectile crossed: When something enters a projectile's tile, make sure the projectile hits it if it should be hitting it.
+ */
+/obj/projectile/Crossed(atom/movable/AM)
+ . = ..()
+ scan_crossed_hit(AM)
+
+/**
+ * Projectile can pass through
+ * Used to not even attempt to Bump() or fail to Cross() anything we already hit.
+ */
+/obj/projectile/CanPassThrough(atom/blocker, turf/target, blocker_opinion)
+ return impacted[blocker]? TRUE : ..()
+
+/**
+ * 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().
+ */
+/obj/projectile/Moved(atom/OldLoc, Dir)
+ . = ..()
+ if(!fired)
+ return
+ if(temporary_unstoppable_movement)
+ temporary_unstoppable_movement = FALSE
+ movement_type &= ~PHASING
+ scan_moved_turf() //mostly used for making sure we can hit a non-dense object the user directly clicked on, and for penetrating projectiles that don't bump
+
+/**
+ * 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!
+ */
+/obj/projectile/proc/prehit_pierce(atom/A)
+ if(projectile_phasing & A.pass_flags_self)
+ return PROJECTILE_PIERCE_PHASE
+ if(projectile_piercing & A.pass_flags_self)
+ return PROJECTILE_PIERCE_HIT
+ if(ismovable(A))
+ var/atom/movable/AM = A
+ if(AM.throwing)
+ return (projectile_phasing & LETPASSTHROW)? PROJECTILE_PIERCE_PHASE : ((projectile_piercing & LETPASSTHROW)? PROJECTILE_PIERCE_HIT : PROJECTILE_PIERCE_NONE)
+ return PROJECTILE_PIERCE_NONE
+
+/**INeedAnAdult I am unsure what the fuck is going on in here and I'll have to get clairification on this shit.
+ */
/obj/item/projectile/proc/check_ricochet(atom/A)
if(ricochets > ricochets_max) //safety thing, we don't care about what the other thing says about this.
return FALSE
@@ -484,11 +682,10 @@
AddElement(/datum/element/embed, projectile_payload = shrapnel_type)
if(!log_override && firer && original)
log_combat(firer, original, "fired at", src, "from [get_area_name(src, TRUE)]")
- if(direct_target)
- if(prehit(direct_target))
- direct_target.bullet_act(src, def_zone)
- qdel(src)
- return
+ if(direct_target && (get_dist(direct_target, get_turf(src)) <= 1)) // point blank shots
+ process_hit(get_turf(direct_target), direct_target)
+ if(QDELETED(src))
+ return
if(isnum(angle))
setAngle(angle)
if(spread)
@@ -506,6 +703,7 @@
var/matrix/M = new
M.Turn(Angle)
transform = M
+ LAZYINITLIST(impacted)
trajectory_ignore_forcemove = TRUE
forceMove(starting)
set_light(fired_light_range, fired_light_intensity, fired_light_color)
@@ -544,6 +742,8 @@
if(zc)
before_z_change(old, target)
. = ..()
+ if(QDELETED(src)) // we coulda bumped something
+ return
if(trajectory && !trajectory_ignore_forcemove && isturf(target))
if(hitscan)
finalize_hitscan_and_generate_tracers(FALSE)
@@ -678,30 +878,6 @@
if(prob(50))
homing_offset_y = -homing_offset_y
-//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.
-/obj/item/projectile/proc/can_hit_target(atom/target, list/passthrough, direct_target = FALSE, ignore_loc = FALSE)
- if(QDELETED(target))
- return FALSE
- if(!ignore_source_check && firer)
- var/mob/M = firer
- if((target == firer) || ((target == firer.loc) && ismecha(firer.loc)) || (target in firer.buckled_mobs) || (istype(M) && (M.buckled == target)))
- if(!ricochets) //if it has ricocheted, it can hit the firer.
- return FALSE
- if(!ignore_loc && (loc != target.loc))
- return FALSE
- if(target in passthrough)
- return FALSE
- if(target.density) //This thing blocks projectiles, hit it regardless of layer/mob stuns/etc.
- return TRUE
- if(!isliving(target))
- if(target.layer < PROJECTILE_HIT_THRESHHOLD_LAYER)
- return FALSE
- else
- var/mob/living/L = target
- if(!direct_target && !L.density)
- return FALSE
- return TRUE
//Spread is FORCED!
/obj/item/projectile/proc/preparePixelProjectile(atom/target, atom/source, params, spread = 0)
@@ -762,22 +938,6 @@
angle = arctan(y - oy, x - ox)
return list(angle, p_x, p_y)
-/obj/item/projectile/Crossed(atom/movable/AM) //A mob moving on a tile with a projectile is hit by it.
- . = ..()
- if(isliving(AM) && !(pass_flags & PASSMOB))
- var/mob/living/L = AM
- if(can_hit_target(L, permutated, (AM == original)))
- Bump(AM)
-
-/obj/item/projectile/Move(atom/newloc, dir = NONE)
- . = ..()
- if(.)
- if(temporary_unstoppable_movement)
- temporary_unstoppable_movement = FALSE
- movement_type &= ~(UNSTOPPABLE)
- if(fired && can_hit_target(original, permutated, TRUE))
- Bump(original)
-
/obj/item/projectile/Destroy()
STOP_PROCESSING(SSprojectiles, src)
if(hitscan)
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index 79e9ab8b4b..a74a71d141 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -166,7 +166,7 @@
/obj/item/projectile/beam/lasertag/mag //the projectile, compatible with regular laser tag armor
icon_state = "magjectile-toy"
name = "lasertag magbolt"
- movement_type = FLYING | UNSTOPPABLE //for penetration memes
+ movement_type = FLYING | PHASING //for penetration memes
range = 5 //so it isn't super annoying
light_range = 2
light_color = LIGHT_COLOR_YELLOW
diff --git a/code/modules/projectiles/projectile/bullets/ferromagnetic.dm b/code/modules/projectiles/projectile/bullets/ferromagnetic.dm
index 03482e2a9d..1ba6ba7b79 100644
--- a/code/modules/projectiles/projectile/bullets/ferromagnetic.dm
+++ b/code/modules/projectiles/projectile/bullets/ferromagnetic.dm
@@ -28,7 +28,7 @@
damage = 10
armour_penetration = 20
stamina = 10
- movement_type = FLYING | UNSTOPPABLE
+ movement_type = FLYING | PHASING
range = 6
fired_light_range = 1
fired_light_color = LIGHT_COLOR_RED
@@ -37,7 +37,7 @@
icon_state = "magjectile-large"
damage = 10
armour_penetration = 20
- movement_type = FLYING | UNSTOPPABLE
+ movement_type = FLYING | PHASING
range = 20
pixels_per_second = TILES_TO_PIXELS(12.5)
fired_light_range = 4
diff --git a/code/modules/projectiles/projectile/bullets/sniper.dm b/code/modules/projectiles/projectile/bullets/sniper.dm
index f69b62a149..80edd716b5 100644
--- a/code/modules/projectiles/projectile/bullets/sniper.dm
+++ b/code/modules/projectiles/projectile/bullets/sniper.dm
@@ -35,7 +35,8 @@
icon_state = "gauss"
name = "penetrator round"
damage = 60
- movement_type = FLYING | UNSTOPPABLE
+ projectile_piercing = PASSMOB
+ projectile_phasing = (ALL & (~PASSMOB))
dismemberment = 0 //It goes through you cleanly.
knockdown = 0
breakthings = FALSE
diff --git a/code/modules/projectiles/projectile/bullets/special.dm b/code/modules/projectiles/projectile/bullets/special.dm
index a0414d8a9c..76ba76fbfe 100644
--- a/code/modules/projectiles/projectile/bullets/special.dm
+++ b/code/modules/projectiles/projectile/bullets/special.dm
@@ -3,7 +3,8 @@
/obj/item/projectile/bullet/honker
damage = 0
knockdown = 60
- movement_type = FLYING | UNSTOPPABLE
+ movement_type = FLYING
+ projectile_piercing = ALL
nodamage = TRUE
candink = FALSE
hitsound = 'sound/items/bikehorn.ogg'
diff --git a/code/modules/projectiles/projectile/magic.dm b/code/modules/projectiles/projectile/magic.dm
index 76cd1a6bc5..21af43478a 100644
--- a/code/modules/projectiles/projectile/magic.dm
+++ b/code/modules/projectiles/projectile/magic.dm
@@ -344,18 +344,17 @@
var/created = FALSE //prevents creation of more then one locker if it has multiple hits
var/locker_suck = TRUE
-/obj/item/projectile/magic/locker/prehit(atom/A)
+/obj/item/projectile/magic/locker/prehit_pierce(atom/A)
+ . = ..()
if(ismob(A) && locker_suck)
var/mob/M = A
- if(M.anti_magic_check())
+ if(M.anti_magic_check()) // no this doesn't check if ..() returned to phase through do I care no it's magic ain't gotta explain shit - Silly-Cons
M.visible_message("[src] vanishes on contact with [A]!")
- qdel(src)
- return
+ return PROJECTILE_DELETE_WITHOUT_HITTING
if(M.anchored)
- return ..()
+ return
M.forceMove(src)
- return FALSE
- return ..()
+ return PROJECTILE_PIERCE_PHASE
/obj/item/projectile/magic/locker/on_hit(target)
if(created)
diff --git a/code/modules/projectiles/projectile/special/curse.dm b/code/modules/projectiles/projectile/special/curse.dm
index 6c682763ae..36c27ac0e1 100644
--- a/code/modules/projectiles/projectile/special/curse.dm
+++ b/code/modules/projectiles/projectile/special/curse.dm
@@ -12,7 +12,6 @@
knockdown = 20
pixels_per_second = TILES_TO_PIXELS(5)
range = 16
- movement_type = FLYING | UNSTOPPABLE
var/datum/beam/arm
var/handedness = 0
@@ -29,18 +28,14 @@
arm = starting.Beam(src, icon_state = "curse[handedness]", time = INFINITY, maxdistance = INFINITY, beam_type=/obj/effect/ebeam/curse_arm)
..()
-/obj/item/projectile/curse_hand/prehit(atom/target)
- if(target == original)
- movement_type &= ~(UNSTOPPABLE)
- else if(!isturf(target))
- return FALSE
- return ..()
+/obj/projectile/curse_hand/prehit_pierce(atom/target)
+ return (target == original)? PROJECTILE_PIERCE_NONE : PROJECTILE_PIERCE_PHASE
/obj/item/projectile/curse_hand/Destroy()
if(arm)
arm.End()
arm = null
- if((movement_type & UNSTOPPABLE))
+ if((movement_type & PHASING))
playsound(src, 'sound/effects/curse3.ogg', 25, 1, -1)
var/turf/T = get_step(src, dir)
var/obj/effect/temp_visual/dir_setting/curse/hand/leftover = new(T, dir)
diff --git a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
index d62b3c2611..54e07d24e5 100644
--- a/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
+++ b/code/modules/ruins/objects_and_mobs/necropolis_gate.dm
@@ -59,10 +59,10 @@
/obj/structure/necropolis_gate/singularity_pull()
return 0
-/obj/structure/necropolis_gate/CanPass(atom/movable/mover, turf/target)
- if(get_dir(loc, target) == dir)
- return !density
- return 1
+/obj/structure/necropolis_gate/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+ if(!(get_dir(loc, target) == dir))
+ return TRUE
/obj/structure/necropolis_gate/CheckExit(atom/movable/O, target)
if(get_dir(O.loc, target) == dir)
diff --git a/code/modules/ruins/objects_and_mobs/sin_ruins.dm b/code/modules/ruins/objects_and_mobs/sin_ruins.dm
index 5e2fc3d7e4..da6179197c 100644
--- a/code/modules/ruins/objects_and_mobs/sin_ruins.dm
+++ b/code/modules/ruins/objects_and_mobs/sin_ruins.dm
@@ -80,7 +80,8 @@
icon = 'icons/mob/blob.dmi'
color = rgb(145, 150, 0)
-/obj/effect/gluttony/CanPass(atom/movable/mover, turf/target)//So bullets will fly over and stuff.
+/obj/effect/gluttony/CanAllowThrough(atom/movable/mover, turf/target)//So bullets will fly over and stuff.
+ . = ..()
if(ishuman(mover))
var/mob/living/carbon/human/H = mover
if(H.nutrition >= NUTRITION_LEVEL_FAT)
@@ -90,8 +91,6 @@
to_chat(H, "You're repulsed by even looking at [src]. Only a pig could force themselves to go through it.")
if(istype(mover, /mob/living/simple_animal/hostile/morph))
return TRUE
- else
- return FALSE
/obj/structure/mirror/magic/pride //Pride's mirror: Used in the Pride ruin.
name = "pride's mirror"
diff --git a/code/modules/shuttle/special.dm b/code/modules/shuttle/special.dm
index 05450fd7c2..274efcda5a 100644
--- a/code/modules/shuttle/special.dm
+++ b/code/modules/shuttle/special.dm
@@ -212,15 +212,14 @@
var/static/list/check_times = list()
-/obj/effect/forcefield/luxury_shuttle/CanPass(atom/movable/mover, turf/target)
+/obj/effect/forcefield/luxury_shuttle/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(mover in approved_passengers)
return TRUE
if(!isliving(mover)) //No stowaways
return FALSE
- return FALSE
-
#define LUXURY_MESSAGE_COOLDOWN 100
/obj/effect/forcefield/luxury_shuttle/Bumped(atom/movable/AM)
diff --git a/code/modules/spells/spell_types/forcewall.dm b/code/modules/spells/spell_types/forcewall.dm
index e0c21066cf..be7bb4cbd3 100644
--- a/code/modules/spells/spell_types/forcewall.dm
+++ b/code/modules/spells/spell_types/forcewall.dm
@@ -30,11 +30,11 @@
. = ..()
wizard = summoner
-/obj/effect/forcefield/wizard/CanPass(atom/movable/mover, turf/target)
+/obj/effect/forcefield/wizard/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
if(mover == wizard)
return TRUE
if(ismob(mover))
var/mob/M = mover
if(M.anti_magic_check(chargecost = 0))
return TRUE
- return FALSE
diff --git a/code/modules/vehicles/ridden.dm b/code/modules/vehicles/ridden.dm
index f71d9367d3..28b79a1599 100644
--- a/code/modules/vehicles/ridden.dm
+++ b/code/modules/vehicles/ridden.dm
@@ -4,6 +4,7 @@
max_buckled_mobs = 1
buckle_lying = FALSE
default_driver_move = FALSE
+ pass_flags_self = PASSTABLE
var/legs_required = 1
var/arms_required = 0 //why not?
From c5be81c589a16ff0f5af9a3635e69af466e074fb Mon Sep 17 00:00:00 2001
From: Solaris-Shade <73904284+Solaris-Shade@users.noreply.github.com>
Date: Sun, 6 Mar 2022 16:29:58 -0500
Subject: [PATCH 3/6] tg moved projectiles out of /item, added '/item' back
---
.../effects/effect_system/effects_smoke.dm | 4 ++--
code/game/objects/structures/girders.dm | 2 +-
code/game/objects/structures/grille.dm | 2 +-
.../projectiles/guns/misc/beam_rifle.dm | 6 +++---
code/modules/projectiles/projectile.dm | 18 +++++++++---------
.../projectiles/projectile/special/curse.dm | 2 +-
code/modules/unit_tests/projectiles.dm | 2 +-
7 files changed, 18 insertions(+), 18 deletions(-)
diff --git a/code/game/objects/effects/effect_system/effects_smoke.dm b/code/game/objects/effects/effect_system/effects_smoke.dm
index db1b9d5b2b..43d55a5756 100644
--- a/code/game/objects/effects/effect_system/effects_smoke.dm
+++ b/code/game/objects/effects/effect_system/effects_smoke.dm
@@ -135,8 +135,8 @@
/obj/effect/particle_effect/smoke/bad/Crossed(atom/movable/AM, oldloc)
. = ..()
- if(istype(AM, /obj/projectile/beam))
- var/obj/projectile/beam/B = AM
+ if(istype(AM, /obj/item/projectile/beam))
+ var/obj/item/projectile/beam/B = AM
B.damage = (B.damage/2)
/datum/effect_system/smoke_spread/bad
diff --git a/code/game/objects/structures/girders.dm b/code/game/objects/structures/girders.dm
index 3e6884613e..7e3d0262e1 100644
--- a/code/game/objects/structures/girders.dm
+++ b/code/game/objects/structures/girders.dm
@@ -298,7 +298,7 @@
/obj/structure/girder/CanAllowThrough(atom/movable/mover, turf/target)
. = ..()
- if((mover.pass_flags & PASSGRILLE) || istype(mover, /obj/projectile))
+ if((mover.pass_flags & PASSGRILLE) || istype(mover, /obj/item/projectile))
return prob(girderpasschance)
/obj/structure/girder/CanAStarPass(ID, dir, caller)
diff --git a/code/game/objects/structures/grille.dm b/code/game/objects/structures/grille.dm
index 54dce18d44..29817e3d58 100644
--- a/code/game/objects/structures/grille.dm
+++ b/code/game/objects/structures/grille.dm
@@ -127,7 +127,7 @@
/obj/structure/grille/CanAllowThrough(atom/movable/mover, turf/target)
. = ..()
- if(!. && istype(mover, /obj/projectile))
+ if(!. && istype(mover, /obj/item/projectile))
return prob(30)
/obj/structure/grille/CanAStarPass(ID, dir, caller)
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index ebc388a965..cf64ae364e 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -490,7 +490,7 @@
if(!QDELETED(target))
handle_impact(target)
-/obj/projectile/beam/beam_rifle/on_hit(atom/target, blocked = FALSE, piercing_hit = FALSE)
+/obj/item/projectile/beam/beam_rifle/on_hit(atom/target, blocked = FALSE, piercing_hit = FALSE)
handle_hit(target, piercing_hit)
. = ..()
@@ -522,9 +522,9 @@
hitscan_light_intensity = 0
hitscan_light_color_override = "#99ff99"
-/obj/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit_pierce(atom/target)
+/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/prehit_pierce(atom/target)
return PROJECTILE_DELETE_WITHOUT_HITTING
-/obj/projectile/beam/beam_rifle/hitscan/aiming_beam/on_hit()
+/obj/item/projectile/beam/beam_rifle/hitscan/aiming_beam/on_hit()
qdel(src)
return BULLET_ACT_BLOCK
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 3fd1bce1ca..4d567e8767 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -369,7 +369,7 @@
* 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.
*/
-/obj/projectile/proc/Impact(atom/A)
+/obj/item/projectile/proc/Impact(atom/A)
if(!trajectory)
qdel(src)
return FALSE
@@ -467,7 +467,7 @@
* 4. Turf
* 5. Nothing
*/
-/obj/projectile/proc/select_target(turf/T, atom/target)
+/obj/item/projectile/proc/select_target(turf/T, atom/target)
// 1. original
if(can_hit_target(original, TRUE, FALSE))
return original
@@ -499,7 +499,7 @@
//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.
-/obj/projectile/proc/can_hit_target(atom/target, direct_target = FALSE, ignore_loc = FALSE)
+/obj/item/projectile/proc/can_hit_target(atom/target, direct_target = FALSE, ignore_loc = FALSE)
if(QDELETED(target) || impacted[target])
return FALSE
if(!ignore_loc && (loc != target.loc))
@@ -538,7 +538,7 @@
* In impact there's more code for selecting WHAT to hit
* So this proc is more of checking if we should hit something at all BY having an atom cross us.
*/
-/obj/projectile/proc/scan_crossed_hit(atom/movable/A)
+/obj/item/projectile/proc/scan_crossed_hit(atom/movable/A)
if(can_hit_target(A, direct_target = (A == original)))
Impact(A)
@@ -547,7 +547,7 @@
*
* This proc is a little high in overhead but allows us to not snowflake CanPass in living and other things.
*/
-/obj/projectile/proc/scan_moved_turf()
+/obj/item/projectile/proc/scan_moved_turf()
// Optimally, we scan: mobs --> objs --> turf for impact
// but, overhead is a thing and 2 for loops every time it moves is a no-go.
// realistically, since we already do select_target in impact, we can not do that
@@ -566,7 +566,7 @@
/**
* Projectile crossed: When something enters a projectile's tile, make sure the projectile hits it if it should be hitting it.
*/
-/obj/projectile/Crossed(atom/movable/AM)
+/obj/item/projectile/Crossed(atom/movable/AM)
. = ..()
scan_crossed_hit(AM)
@@ -574,7 +574,7 @@
* Projectile can pass through
* Used to not even attempt to Bump() or fail to Cross() anything we already hit.
*/
-/obj/projectile/CanPassThrough(atom/blocker, turf/target, blocker_opinion)
+/obj/item/projectile/CanPassThrough(atom/blocker, turf/target, blocker_opinion)
return impacted[blocker]? TRUE : ..()
/**
@@ -586,7 +586,7 @@
* 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().
*/
-/obj/projectile/Moved(atom/OldLoc, Dir)
+/obj/item/projectile/Moved(atom/OldLoc, Dir)
. = ..()
if(!fired)
return
@@ -601,7 +601,7 @@
* 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!
*/
-/obj/projectile/proc/prehit_pierce(atom/A)
+/obj/item/projectile/proc/prehit_pierce(atom/A)
if(projectile_phasing & A.pass_flags_self)
return PROJECTILE_PIERCE_PHASE
if(projectile_piercing & A.pass_flags_self)
diff --git a/code/modules/projectiles/projectile/special/curse.dm b/code/modules/projectiles/projectile/special/curse.dm
index 36c27ac0e1..89b1ecba4c 100644
--- a/code/modules/projectiles/projectile/special/curse.dm
+++ b/code/modules/projectiles/projectile/special/curse.dm
@@ -28,7 +28,7 @@
arm = starting.Beam(src, icon_state = "curse[handedness]", time = INFINITY, maxdistance = INFINITY, beam_type=/obj/effect/ebeam/curse_arm)
..()
-/obj/projectile/curse_hand/prehit_pierce(atom/target)
+/obj/item/projectile/curse_hand/prehit_pierce(atom/target)
return (target == original)? PROJECTILE_PIERCE_NONE : PROJECTILE_PIERCE_PHASE
/obj/item/projectile/curse_hand/Destroy()
diff --git a/code/modules/unit_tests/projectiles.dm b/code/modules/unit_tests/projectiles.dm
index 53ceef01d6..f1a2391c07 100644
--- a/code/modules/unit_tests/projectiles.dm
+++ b/code/modules/unit_tests/projectiles.dm
@@ -1,5 +1,5 @@
/datum/unit_test/projectile_movetypes/Run()
for(var/path in typesof(/obj/item/projectile))
- var/obj/projectile/projectile = path
+ var/obj/item/projectile/projectile = path
if(initial(projectile.movement_type) & PHASING)
Fail("[path] has default movement type PHASING. Piercing projectiles should be done using the projectile piercing system, not movement_types!")
From 171bd18c8ab35c468e203e330b429b5dea5aa74f Mon Sep 17 00:00:00 2001
From: Solaris-Shade <73904284+Solaris-Shade@users.noreply.github.com>
Date: Fri, 11 Mar 2022 22:23:01 -0500
Subject: [PATCH 4/6] Updated Projectile code some more.
---
code/__DEFINES/_flags/_flags.dm | 2 +
code/game/atoms.dm | 4 +-
code/game/machinery/_machinery.dm | 8 ++-
code/game/machinery/doors/door.dm | 2 +
code/game/machinery/doors/windowdoor.dm | 2 +-
code/game/objects/structures.dm | 6 ++
code/game/objects/structures/holosign.dm | 29 ++++-----
code/modules/antagonists/blob/blob/theblob.dm | 2 +-
.../guns/energy/kinetic_accelerator.dm | 19 +++---
.../projectiles/guns/misc/beam_rifle.dm | 8 +--
code/modules/projectiles/projectile.dm | 62 +++++++++++--------
code/modules/projectiles/projectile/beams.dm | 2 +-
12 files changed, 83 insertions(+), 63 deletions(-)
diff --git a/code/__DEFINES/_flags/_flags.dm b/code/__DEFINES/_flags/_flags.dm
index 99c9b293fb..c1d997eaa0 100644
--- a/code/__DEFINES/_flags/_flags.dm
+++ b/code/__DEFINES/_flags/_flags.dm
@@ -106,6 +106,8 @@ GLOBAL_LIST_INIT(bitflags, list(
#define PASSCLOSEDTURF (1<<5)
/// Let thrown things past us. **ONLY MEANINGFUL ON pass_flags_self!**
#define LETPASSTHROW (1<<6)
+#define PASSMACHINE (1<<7)
+#define PASSSTRUCTURE (1<<8)
//Movement Types
#define GROUND (1<<0)
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index e4b7507560..f49dae2bb4 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -278,7 +278,7 @@
return TRUE
/atom/proc/CanPass(atom/movable/mover, turf/target)
- SHOULD_CALL_PARENT(TRUE)
+ //SHOULD_CALL_PARENT(TRUE)
if(mover.movement_type & PHASING)
return TRUE
. = CanAllowThrough(mover, target)
@@ -288,7 +288,7 @@
/// Returns true or false to allow the mover to move through src
/atom/proc/CanAllowThrough(atom/movable/mover, turf/target)
- SHOULD_CALL_PARENT(TRUE)
+ //SHOULD_CALL_PARENT(TRUE)
if(mover.pass_flags & pass_flags_self)
return TRUE
if(mover.throwing && (pass_flags_self & LETPASSTHROW))
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index 675d54ef22..70794915bc 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -90,7 +90,7 @@ Class Procs:
verb_say = "beeps"
verb_yell = "blares"
pressure_resistance = 15
- pass_flags_self = PASSMACHINE
+ pass_flags_self = PASSMACHINE
max_integrity = 200
layer = BELOW_OBJ_LAYER //keeps shit coming out of the machine from ending up underneath it.
flags_1 = DEFAULT_RICOCHET_1
@@ -449,6 +449,12 @@ Class Procs:
update_icon()
updateUsrDialog()
+/obj/machinery/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+
+ if(mover.pass_flags & PASSMACHINE)
+ return TRUE
+
/obj/machinery/proc/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/I)
if(!(flags_1 & NODECONSTRUCT_1) && I.tool_behaviour == TOOL_SCREWDRIVER)
I.play_tool_sound(src, 50)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 71df6affb7..ce84b8e8c6 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -129,6 +129,8 @@
/obj/machinery/door/CanAllowThrough(atom/movable/mover, turf/target)
. = ..()
+ if(.)
+ return
// Snowflake handling for PASSGLASS.
if(istype(mover) && (mover.pass_flags & PASSGLASS))
diff --git a/code/game/machinery/doors/windowdoor.dm b/code/game/machinery/doors/windowdoor.dm
index 5027e46aa0..3fc5363459 100644
--- a/code/game/machinery/doors/windowdoor.dm
+++ b/code/game/machinery/doors/windowdoor.dm
@@ -134,7 +134,7 @@
return !density || (dir != to_dir) || (check_access(ID) && hasPower())
/obj/machinery/door/window/CheckExit(atom/movable/mover, turf/target)
- if((pass_flags_self & mover.pass_flags)) || ((pass_flags_self & LETPASSTHROW) && mover.throwing))
+ if((pass_flags_self & mover.pass_flags) || ((pass_flags_self & LETPASSTHROW) && mover.throwing))
return TRUE
if(get_dir(loc, target) == dir)
return !density
diff --git a/code/game/objects/structures.dm b/code/game/objects/structures.dm
index a8f0739bed..8cfb1068d4 100644
--- a/code/game/objects/structures.dm
+++ b/code/game/objects/structures.dm
@@ -104,6 +104,12 @@
if(examine_status)
. += examine_status
+/obj/structure/CanAllowThrough(atom/movable/mover, turf/target)
+ . = ..()
+
+ if(mover.pass_flags & PASSSTRUCTURE)
+ return TRUE
+
/obj/structure/proc/examine_status(mob/user) //An overridable proc, mostly for falsewalls.
var/healthpercent = (obj_integrity/max_integrity) * 100
switch(healthpercent)
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index 26dedf3b62..95970f369d 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -149,26 +149,21 @@
. += "The biometric scanners are [force_allaccess ? "off" : "on"]."
/obj/structure/holosign/barrier/medical/CanAllowThrough(atom/movable/mover, turf/target)
- . = ..()
+ icon_state = "holo_medical"
if(force_allaccess)
return TRUE
if(ishuman(mover))
-
- return CheckHuman(mover)
-
-/obj/structure/holosign/barrier/medical/Bumped(atom/movable/AM)
- . = ..()
- icon_state = "holo_medical"
- if(ishuman(AM) && !CheckHuman(AM))
- if(buzzcd < world.time)
- playsound(get_turf(src),'sound/machines/buzz-sigh.ogg',65,TRUE,4)
- buzzcd = (world.time + 60)
- icon_state = "holo_medical-deny"
-
-/obj/structure/holosign/barrier/medical/proc/CheckHuman(mob/living/carbon/human/sickboi)
- var/threat = sickboi.check_virus()
- if(get_disease_severity_value(threat) > get_disease_severity_value(DISEASE_SEVERITY_MINOR))
- return FALSE
+ var/mob/living/carbon/human/sickboi = mover
+ var/threat = sickboi.check_virus()
+ switch(threat)
+ if(DISEASE_SEVERITY_MINOR, DISEASE_SEVERITY_MEDIUM, DISEASE_SEVERITY_HARMFUL, DISEASE_SEVERITY_DANGEROUS, DISEASE_SEVERITY_BIOHAZARD)
+ if(buzzcd < world.time)
+ playsound(get_turf(src),'sound/machines/buzz-sigh.ogg',65,TRUE,4)
+ buzzcd = (world.time + 60)
+ icon_state = "holo_medical-deny"
+ return FALSE
+ else
+ return TRUE //nice or benign diseases!
return TRUE
/obj/structure/holosign/barrier/medical/on_attack_hand(mob/living/user, act_intent = user.a_intent, unarmed_attack_flags)
diff --git a/code/modules/antagonists/blob/blob/theblob.dm b/code/modules/antagonists/blob/blob/theblob.dm
index 7651093ea1..5d8086816a 100644
--- a/code/modules/antagonists/blob/blob/theblob.dm
+++ b/code/modules/antagonists/blob/blob/theblob.dm
@@ -4,7 +4,7 @@
icon = 'icons/mob/blob.dmi'
light_range = 2
desc = "A thick wall of writhing tendrils."
- density = FALSE //this being false causes two bugs, being able to attack blob tiles behind other blobs and being unable to move on blob tiles in no gravity, but turning it to 1 causes the blob mobs to be unable to path through blobs, which is probably worse.
+ density = TRUE
opacity = 0
anchored = TRUE
layer = BELOW_MOB_LAYER
diff --git a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
index 7516092149..4d6d9bd6c7 100644
--- a/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
+++ b/code/modules/projectiles/guns/energy/kinetic_accelerator.dm
@@ -234,15 +234,16 @@
/obj/item/projectile/kinetic/prehit_pierce(atom/target)
. = ..()
- if(.)
- if(kinetic_gun)
- var/list/mods = kinetic_gun.get_modkits()
- for(var/obj/item/borg/upgrade/modkit/M in mods)
- M.projectile_prehit(src, target, kinetic_gun)
- if(!pressure_decrease_active && !lavaland_equipment_pressure_check(get_turf(target)))
- name = "weakened [name]"
- damage = damage * pressure_decrease
- pressure_decrease_active = TRUE
+ if(. == PROJECTILE_PIERCE_PHASE)
+ return
+ if(kinetic_gun)
+ var/list/mods = kinetic_gun.modkits
+ for(var/obj/item/borg/upgrade/modkit/modkit in mods)
+ modkit.projectile_prehit(src, target, kinetic_gun)
+ if(!pressure_decrease_active && !lavaland_equipment_pressure_check(get_turf(target)))
+ name = "weakened [name]"
+ damage = damage * pressure_decrease
+ pressure_decrease_active = TRUE
/obj/item/projectile/kinetic/on_range()
strike_thing()
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index cf64ae364e..182e479bbb 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -445,22 +445,22 @@
continue
O.take_damage(aoe_structure_damage * get_damage_coeff(O), BURN, "laser", FALSE)
-/obj/item/projectile/beam/beam_rifle/proc/check_pierce(atom/A)
+/obj/item/projectile/beam/beam_rifle/prehit_pierce(atom/A)
if(isclosedturf(A) && (wall_pierce < wall_pierce_amount))
if(prob(wall_devastate))
if(iswallturf(A))
var/turf/closed/wall/W = A
W.dismantle_wall(TRUE, TRUE)
else
- target.ex_act(EXPLODE_HEAVY)
+ A.ex_act(EXPLODE_HEAVY)
++wall_pierce
return PROJECTILE_PIERCE_PHASE // yeah this gun is a snowflakey piece of garbage - Silly-Cons
if(isobj(A) && (structure_pierce < structure_pierce_amount))
++structure_pierce
var/obj/O = A
- O.take_damage((impact_structure_damage + aoe_structure_damage) * structure_bleed_coeff * get_damage_coeff(A), BURN, ENERGY, FALSE)
+ O.take_damage((impact_structure_damage + aoe_structure_damage) * structure_bleed_coeff * get_damage_coeff(A), BURN, "energy", FALSE)
return PROJECTILE_PIERCE_PHASE // ditto and this could be refactored to on_hit honestly - Silly-Cons
- return ..()
+ return ..()
/obj/item/projectile/beam/beam_rifle/proc/get_damage_coeff(atom/target)
if(istype(target, /obj/machinery/door))
diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm
index 4d567e8767..f0db597b27 100644
--- a/code/modules/projectiles/projectile.dm
+++ b/code/modules/projectiles/projectile.dm
@@ -50,7 +50,7 @@
/** PROJECTILE PIERCING
* WARNING:
* Projectile piercing MUST be done using these variables.
- * Ordinary passflags will be **IGNORED**.
+ * Ordinary passflags will result in can_hit_target being false unless directly clicked on - similar to projectile_phasing but without even going to process_hit.
* The two flag variables below both use pass flags.
* In the context of LETPASStHROW, it means the projectile will ignore things that are currently "in the air" from a throw.
*
@@ -354,7 +354,7 @@
/obj/item/projectile/Bump(atom/A)
SEND_SIGNAL(src, COMSIG_MOVABLE_BUMP, A)
- if(!can_hit_target(A, A == original, TRUE))
+ if(!can_hit_target(A, A == original, TRUE, TRUE))
return
Impact(A)
@@ -395,7 +395,7 @@
if(def_zone && check_zone(def_zone) != BODY_ZONE_CHEST)
def_zone = ran_zone(def_zone, max(100-(7*distance), 5) * zone_accuracy_factor) //Lower accurancy/longer range tradeoff. 7 is a balanced number to use.
- return process_hit(T, select_target(T, A)) // SELECT TARGET FIRST!
+ return process_hit(T, select_target(T, A, A), A) // SELECT TARGET FIRST!
/**
* The primary workhorse proc of projectile impacts.
@@ -414,12 +414,14 @@
* @params
* T - Turf we're on/supposedly hitting
* target - target we're hitting
+ * bumped - target we originally bumped. it's here to ensure that if something blocks our projectile by means of Cross() failure, we hit it
+ * even if it is not dense.
* hit_something - only should be set by recursive calling by this proc - tracks if we hit something already
*
* Returns if we hit something.
* - Silly-Cons
*/
-/obj/item/projectile/proc/process_hit(turf/T, atom/target, hit_something = FALSE)
+/obj/item/projectile/proc/process_hit(turf/T, atom/target, atom/bumped, hit_something = FALSE)
// 1.
if(QDELETED(src) || !T || !target)
return
@@ -434,7 +436,7 @@
if(!(movement_type & PHASING))
temporary_unstoppable_movement = TRUE
movement_type |= PHASING
- return process_hit(T, select_target(T, target), hit_something) // try to hit something else
+ return process_hit(T, select_target(T, target, bumped), bumped, hit_something) // try to hit something else
// at this point we are going to hit the thing
// in which case send signal to it
SEND_SIGNAL(target, COMSIG_PROJECTILE_PREHIT, args)
@@ -446,8 +448,8 @@
if(!(movement_type & PHASING))
temporary_unstoppable_movement = TRUE
movement_type |= PHASING
- return process_hit(T, select_target(T, target), TRUE)
- qdel(src)
+ return process_hit(T, select_target(T, target, bumped), bumped, TRUE)
+ qdel(src)
return hit_something
/**
@@ -456,7 +458,9 @@
* @params
* T - The turf
* target - The "preferred" atom to hit, usually what we Bumped() first.
- *
+ * bumped - used to track if something is the reason we impacted 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.
@@ -467,51 +471,50 @@
* 4. Turf
* 5. Nothing
*/
-/obj/item/projectile/proc/select_target(turf/T, atom/target)
+/obj/item/projectile/proc/select_target(turf/T, atom/target, atom/bumped)
// 1. original
- if(can_hit_target(original, TRUE, FALSE))
+ if(can_hit_target(original, TRUE, FALSE, original == bumped))
return original
var/list/atom/possible = list() // let's define these ONCE
var/list/atom/considering = list()
// 2. mobs
possible = typecache_filter_list(T, GLOB.typecache_living) // living only
for(var/i in possible)
- if(!can_hit_target(i, i == original, TRUE))
+ if(!can_hit_target(i, i == original, TRUE, i == bumped))
continue
considering += i
if(considering.len)
var/mob/living/M = pick(considering)
return M.lowest_buckled_mob()
considering.len = 0
- // 3. objs
- possible = typecache_filter_list(T, GLOB.typecache_machine_or_structure) // because why are items ever dense?
- for(var/i in possible)
- if(!can_hit_target(i, i == original, TRUE))
+ // 3. objs and other dense things
+ for(var/i in T.contents)
+ if(!can_hit_target(i, i == original, TRUE, i == bumped))
continue
considering += i
if(considering.len)
return pick(considering)
// 4. turf
- if(can_hit_target(T, T == original, TRUE))
+ if(can_hit_target(T, T == original, TRUE, T == bumped))
return T
// 5. nothing
// (returns null)
//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.
-/obj/item/projectile/proc/can_hit_target(atom/target, direct_target = FALSE, ignore_loc = FALSE)
+/obj/item/projectile/proc/can_hit_target(atom/target, direct_target = FALSE, ignore_loc = FALSE,cross_failed = FALSE)
if(QDELETED(target) || impacted[target])
return FALSE
if(!ignore_loc && (loc != target.loc))
return FALSE
- // if pass_flags match, pass through entirely
- if(target.pass_flags_self & pass_flags) // phasing
+ // if pass_flags match, pass through entirely - unless direct target is set.
+ if((target.pass_flags_self & pass_flags) && !direct_target)
return FALSE
if(!ignore_source_check && firer)
var/mob/M = firer
if((target == firer) || ((target == firer.loc) && ismecha(firer.loc)) || (target in firer.buckled_mobs) || (istype(M) && (M.buckled == target)))
return FALSE
- if(target.density) //This thing blocks projectiles, hit it regardless of layer/mob stuns/etc.
+ if(target.density || cross_failed) //This thing blocks projectiles, hit it regardless of layer/mob stuns/etc.
return TRUE
if(!isliving(target))
if(isturf(target)) // non dense turfs
@@ -525,8 +528,14 @@
if(direct_target)
return TRUE
// If target not able to use items, move and stand - or if they're just dead, pass over.
- if(L.stat == DEAD || (!hit_stunned_targets && HAS_TRAIT(L, TRAIT_IMMOBILIZED) && HAS_TRAIT(L, TRAIT_FLOORED) && HAS_TRAIT(L, TRAIT_HANDS_BLOCKED)))
+ if(L.stat == DEAD)
return FALSE
+ if(!L.density)
+ return FALSE
+ if(L.resting)
+ return TRUE
+ var/stunned = HAS_TRAIT(L, TRAIT_MOBILITY_NOMOVE) && HAS_TRAIT(L, TRAIT_MOBILITY_NOREST) && HAS_TRAIT(L, TRAIT_MOBILITY_NOPICKUP)
+ return !stunned || hit_stunned_targets
return TRUE
/**
@@ -601,8 +610,9 @@
* 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!
*/
+
/obj/item/projectile/proc/prehit_pierce(atom/A)
- if(projectile_phasing & A.pass_flags_self)
+ if((projectile_phasing & A.pass_flags_self) && (phasing_ignore_direct_target || original != A))
return PROJECTILE_PIERCE_PHASE
if(projectile_piercing & A.pass_flags_self)
return PROJECTILE_PIERCE_HIT
@@ -612,8 +622,6 @@
return (projectile_phasing & LETPASSTHROW)? PROJECTILE_PIERCE_PHASE : ((projectile_piercing & LETPASSTHROW)? PROJECTILE_PIERCE_HIT : PROJECTILE_PIERCE_NONE)
return PROJECTILE_PIERCE_NONE
-/**INeedAnAdult I am unsure what the fuck is going on in here and I'll have to get clairification on this shit.
- */
/obj/item/projectile/proc/check_ricochet(atom/A)
if(ricochets > ricochets_max) //safety thing, we don't care about what the other thing says about this.
return FALSE
@@ -676,16 +684,17 @@
pixels_tick_leftover = required_pixels
/obj/item/projectile/proc/fire(angle, atom/direct_target)
+ LAZYINITLIST(impacted)
if(fired_from)
SEND_SIGNAL(fired_from, COMSIG_PROJECTILE_BEFORE_FIRE, src, original) //If no angle needs to resolve it from xo/yo!
if(shrapnel_type)
AddElement(/datum/element/embed, projectile_payload = shrapnel_type)
if(!log_override && firer && original)
log_combat(firer, original, "fired at", src, "from [get_area_name(src, TRUE)]")
- if(direct_target && (get_dist(direct_target, get_turf(src)) <= 1)) // point blank shots
+ if(direct_target && (get_dist(direct_target, get_turf(src)) <= 1)) // point blank shots
process_hit(get_turf(direct_target), direct_target)
if(QDELETED(src))
- return
+ return
if(isnum(angle))
setAngle(angle)
if(spread)
@@ -703,7 +712,6 @@
var/matrix/M = new
M.Turn(Angle)
transform = M
- LAZYINITLIST(impacted)
trajectory_ignore_forcemove = TRUE
forceMove(starting)
set_light(fired_light_range, fired_light_intensity, fired_light_color)
diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm
index a74a71d141..0d196ef0e3 100644
--- a/code/modules/projectiles/projectile/beams.dm
+++ b/code/modules/projectiles/projectile/beams.dm
@@ -72,7 +72,7 @@
damage = 15
irradiate = 100
range = 15
- pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF
+ pass_flags = PASSTABLE | PASSGLASS | PASSGRILLE | PASSCLOSEDTURF | PASSMACHINE | PASSSTRUCTURE
impact_effect_type = /obj/effect/temp_visual/impact_effect/green_laser
light_color = LIGHT_COLOR_GREEN
From a478945424f1803ce35cf7b32214fc99386684b6 Mon Sep 17 00:00:00 2001
From: Solaris-Shade <73904284+Solaris-Shade@users.noreply.github.com>
Date: Fri, 11 Mar 2022 22:49:16 -0500
Subject: [PATCH 5/6] Merge conflict one
---
code/game/objects/objs.dm | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm
index 0651891421..307307df61 100644
--- a/code/game/objects/objs.dm
+++ b/code/game/objects/objs.dm
@@ -238,7 +238,18 @@
/obj/get_dumping_location(datum/component/storage/source,mob/user)
return get_turf(src)
-/obj/proc/CanAStarPass(ID, dir, caller)
+/**
+ * This proc is used for telling whether something can pass by this object in a given direction, for use by the pathfinding system.
+ *
+ * Trying to generate one long path across the station will call this proc on every single object on every single tile that we're seeing if we can move through, likely
+ * multiple times per tile since we're likely checking if we can access said tile from multiple directions, so keep these as lightweight as possible.
+ *
+ * Arguments:
+ * * ID- An ID card representing what access we have (and thus if we can open things like airlocks or windows to pass through them). The ID card's physical location does not matter, just the reference
+ * * to_dir- What direction we're trying to move in, relevant for things like directional windows that only block movement in certain directions
+ * * caller- The movable we're checking pass flags for, if we're making any such checks
+ **/
+/obj/proc/CanAStarPass(obj/item/card/id/ID, to_dir, atom/movable/caller)
if(ismovable(caller))
var/atom/movable/AM = caller
if(AM.pass_flags & pass_flags_self)
From a4f8789d68b54986a566fd1606ec0ed3b3e14620 Mon Sep 17 00:00:00 2001
From: Solaris-Shade <73904284+Solaris-Shade@users.noreply.github.com>
Date: Thu, 24 Mar 2022 22:43:17 -0400
Subject: [PATCH 6/6] DO it not HIT it!
https://github.com/tgstation/tgstation/pull/65061
---
code/modules/projectiles/guns/misc/beam_rifle.dm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm
index 182e479bbb..decf2d1aa9 100644
--- a/code/modules/projectiles/guns/misc/beam_rifle.dm
+++ b/code/modules/projectiles/guns/misc/beam_rifle.dm
@@ -485,7 +485,7 @@
if(nodamage)
return FALSE
playsound(src, 'sound/effects/explosion3.ogg', 100, TRUE)
- if(!piercing_hit)
+ if(!do_pierce)
AOE(get_turf(target) || get_turf(src))
if(!QDELETED(target))
handle_impact(target)