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)