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