diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm index 110b70ab8c..956c3fe2d7 100644 --- a/code/game/machinery/computer/computer.dm +++ b/code/game/machinery/computer/computer.dm @@ -35,11 +35,11 @@ /obj/machinery/computer/ex_act(severity) switch(severity) if(1.0) - qdel(src) + fall_apart(severity) return if(2.0) if (prob(25)) - qdel(src) + fall_apart(severity) return if (prob(50)) for(var/x in verbs) diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index 28ea1c4816..610879f327 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -13,6 +13,10 @@ power_channel = ENVIRON explosion_resistance = 10 + + // Doors do their own stuff + bullet_vulnerability = 0 + blocks_emissive = EMISSIVE_BLOCK_GENERIC // Not quite as nice as /tg/'s custom masks. We should make those sometime var/aiControlDisabled = 0 //If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in. diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 1900811c8a..4ecc95b7c3 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -111,6 +111,11 @@ Class Procs: var/clickvol = 40 // volume var/interact_offline = 0 // Can the machine be interacted with while de-powered. var/obj/item/weapon/circuitboard/circuit = null + + // 0.0 - 1.0 multipler for prob() based on bullet structure damage + // So if this is 1.0 then a 100 damage bullet will always break this structure + // If this is 0.5 then a 50 damage bullet will break this structure 25% of the time + var/bullet_vulnerability = 0.25 var/speed_process = FALSE //If false, SSmachines. If true, SSfastprocess. @@ -181,15 +186,15 @@ Class Procs: /obj/machinery/ex_act(severity) switch(severity) if(1.0) - qdel(src) + fall_apart(severity) return if(2.0) if(prob(50)) - qdel(src) + fall_apart(severity) return if(3.0) if(prob(25)) - qdel(src) + fall_apart(severity) return else return @@ -476,6 +481,85 @@ Class Procs: qdel(src) return 1 +/obj/machinery/bullet_act(obj/item/projectile/P, def_zone) + . = ..() + if(prob(P.get_structure_damage() * bullet_vulnerability)) + fall_apart() + +/** + * Like an angrier dismantle, where it destroys some of the parts and doesn't give you a frame + ** severity: Same severities as ex_act (so lower is more destructive) + ** scatter: If you want the parts to slide around 1 turf in random directions + */ +/obj/machinery/proc/fall_apart(var/severity = 3, var/scatter = TRUE) + var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() + spark_system.set_up(5, 0, src) + spark_system.attach(src) + + var/atom/droploc = drop_location() + if(!droploc || !contents.len) // not even a circuit? + playsound(src, 'sound/machines/machine_die_short.ogg') + spark_system.start() + qdel(spark_system) + qdel(src) + return + + var/list/surviving_parts = list() + // Deleting IDs is lame, unless this is like nuclear severity + if(severity != 1) + for(var/obj/item/weapon/card/id/I in contents) + surviving_parts |= I + + // May populate some items to throw around + if(!LAZYLEN(component_parts) && circuit) + circuit.apply_default_parts(src) + + var/survivability + switch(severity) + // No survivors + if(1) + survivability = 0 + + // 1 part survives + if(2) + survivability = 0 + var/atom/movable/picked_part = pick(contents) + if(istype(picked_part)) + surviving_parts |= picked_part + + // 50% of parts destroyed on average + if(3) + survivability = 50 + + // No parts destroyed, but you lose the frame + else + survivability = 100 + + for(var/atom/movable/P in contents) + if(prob(survivability)) + surviving_parts |= P + + if(circuit && severity >= 2) + var/datum/frame/frame_types/FT = circuit.board_type + if(istype(FT)) + // Some steel from the frame, but about half + surviving_parts += new /obj/item/stack/material/steel(null, max(1,round(FT.frame_size/2))) + // Two bits of cable, but not the 5 required to rebuild + surviving_parts += new /obj/item/stack/cable_coil(null, 1) + surviving_parts += new /obj/item/stack/cable_coil(null, 1) + + for(var/a in surviving_parts) + var/atom/movable/A = a + A.forceMove(droploc) + if(scatter && isturf(droploc)) + var/turf/T = droploc + A.Move(get_step(T, pick(alldirs))) + + playsound(src, 'sound/machines/machine_die_short.ogg') + spark_system.start() + qdel(spark_system) + qdel(src) + /datum/proc/apply_visual(mob/M) M.sight = 0 //Just reset their mesons and stuff so they can't use them, by default. return diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index 365fda6b50..ac091a9fdb 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -460,8 +460,7 @@ GLOBAL_LIST_EMPTY(smeses) ..() /obj/machinery/power/smes/bullet_act(var/obj/item/projectile/Proj) - if(Proj.damage_type == BRUTE || Proj.damage_type == BURN) - take_damage(Proj.damage) + take_damage(Proj.get_structure_damage()) /obj/machinery/power/smes/ex_act(var/severity) // Two strong explosions will destroy a SMES. diff --git a/sound/machines/machine_die_short.ogg b/sound/machines/machine_die_short.ogg new file mode 100644 index 0000000000..6aac3e9356 Binary files /dev/null and b/sound/machines/machine_die_short.ogg differ