diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index 745e719112c..db3503a2f95 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -184,13 +184,14 @@ assemblies[color] = S S.forceMove(holder) S.connected = src + S.on_attach() // Notify assembly that it is attached return S /datum/wires/proc/detach_assembly(color) var/obj/item/assembly/S = get_attached(color) if(S && istype(S)) assemblies -= color - S.connected = null + S.on_detach() // Notify the assembly. This should remove the reference to our holder S.forceMove(holder.drop_location()) return S diff --git a/code/game/communications.dm b/code/game/communications.dm index e4517f4f644..ba8c29ed250 100644 --- a/code/game/communications.dm +++ b/code/game/communications.dm @@ -180,11 +180,13 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( if (!filter) filter = "_default" + var/datum/weakref/new_listener = WEAKREF(device) + if(isnull(new_listener)) + return stack_trace("null, non-datum, or qdeleted device") var/list/devices_line = devices[filter] if(!devices_line) devices[filter] = devices_line = list() - devices_line += WEAKREF(device) - + devices_line += new_listener /datum/radio_frequency/proc/remove_listener(obj/device) for(var/devices_filter in devices) @@ -195,7 +197,6 @@ GLOBAL_LIST_INIT(reverseradiochannels, list( if(!devices_line.len) devices -= devices_filter - /obj/proc/receive_signal(datum/signal/signal) return diff --git a/code/game/objects/items/devices/transfer_valve.dm b/code/game/objects/items/devices/transfer_valve.dm index a188b07f764..8d5477aafb9 100644 --- a/code/game/objects/items/devices/transfer_valve.dm +++ b/code/game/objects/items/devices/transfer_valve.dm @@ -65,8 +65,8 @@ return attached_device = A to_chat(user, span_notice("You attach the [item] to the valve controls and secure it.")) - A.on_attach() A.holder = src + A.on_attach() A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb). log_bomber(user, "attached a [item.name] to a ttv -", src, null, FALSE) attacher = user diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index c8a529a8d51..0b9becc8c86 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -39,17 +39,30 @@ /obj/item/assembly/get_part_rating() return 1 +/** + * on_attach: Called when attached to a holder, wiring datum, or other special assembly + * + * Will also be called if the assembly holder is attached to a plasma (internals) tank or welding fuel (dispenser) tank. + */ /obj/item/assembly/proc/on_attach() + if(!holder && connected) + holder = connected.holder -//Call this when detaching it from a device. handles any special functions that need to be updated ex post facto +/** + * on_detach: Called when removed from an assembly holder or wiring datum + */ /obj/item/assembly/proc/on_detach() + if(connected) + connected = null if(!holder) return FALSE forceMove(holder.drop_location()) holder = null return TRUE -//Called when the holder is moved +/** + * holder_movement: Called when the assembly's holder detects movement + */ /obj/item/assembly/proc/holder_movement() if(!holder) return FALSE @@ -94,6 +107,15 @@ update_appearance() return secured +// This is overwritten so that clumsy people can set off mousetraps even when in a holder. +// We are not going deeper than that however (won't set off if in a tank bomb or anything with wires) +// That would need to be added to all parent objects, or a signal created, whatever. +// Anyway this return check prevents you from picking up every assembly inside the holder at once. +/obj/item/assembly/attack_hand(mob/living/user, list/modifiers) + if(holder || connected) + return + . = ..() + /obj/item/assembly/attackby(obj/item/W, mob/user, params) if(isassembly(W)) var/obj/item/assembly/A = W @@ -135,9 +157,12 @@ return ui_interact(user) /obj/item/assembly/ui_host(mob/user) - if(holder) - return holder - return src + // In order, return: + // - The conencted wiring datum's owner, or + // - The thing your assembly holder is attached to, or + // - the assembly holder itself, or + // - us + return connected?.holder || holder?.master || holder || src /obj/item/assembly/ui_state(mob/user) return GLOB.hands_state diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index 9ef44fc61ae..887f8e973b9 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -136,6 +136,7 @@ bomb.bombassembly = assembly //Tell the bomb about its assembly part assembly.master = bomb //Tell the assembly about its new owner + assembly.on_attach() bomb.bombtank = src //Same for tank master = bomb diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index fb551a44e41..004315f7c21 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -28,7 +28,6 @@ /obj/item/assembly_holder/IsAssemblyHolder() return TRUE - /obj/item/assembly_holder/proc/assemble(obj/item/assembly/A, obj/item/assembly/A2, mob/user) attach(A,user) attach(A2,user) @@ -36,6 +35,17 @@ update_appearance() SSblackbox.record_feedback("tally", "assembly_made", 1, "[initial(A.name)]-[initial(A2.name)]") +/** + * on_attach: Pass on_attach message to child assemblies + * + */ +/obj/item/assembly_holder/proc/on_attach() + var/obj/item/newloc = loc + if(!newloc.IsSpecialAssembly() && !newloc.IsAssemblyHolder()) + return + for(var/obj/item/assembly/assembly in assemblies) + assembly.on_attach() + /** * Adds an assembly to the assembly holder * @@ -104,7 +114,7 @@ if(.) return for(var/obj/item/assembly/assembly as anything in assemblies) - assembly.attack_hand() + assembly.attack_hand(user, modifiers) // Note override in assembly.dm to prevent side effects here /obj/item/assembly_holder/attackby(obj/item/weapon, mob/user, params) if(isassembly(weapon)) @@ -151,7 +161,7 @@ return FALSE if(normal && LAZYLEN(assemblies) >= 2) for(var/obj/item/assembly/assembly as anything in assemblies) - if(LAZYACCESS(assemblies, assembly) != device) + if(assembly != device) assembly.pulsed(FALSE) if(master) master.receive_signal() diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index 580b17ab374..9c0b3e081e8 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -8,18 +8,72 @@ var/armed = FALSE drop_sound = 'sound/items/handling/component_drop.ogg' pickup_sound = 'sound/items/handling/component_pickup.ogg' + var/obj/item/host = null + var/turf/host_turf = null - ///if we are attached to an assembly holder, we attach a connect_loc element to ourselves that listens to this from the holder - var/static/list/holder_connections = list( - COMSIG_ATOM_ENTERED = .proc/on_entered, - ) +/** + * update_host: automatically setup host and host_turf + * + * Arguments: + * * force: Re-register signals even if the host or loc is unchanged + */ +/obj/item/assembly/mousetrap/proc/update_host(force = FALSE) + var/obj/item/newhost + // Pick the first valid object in this list: + // Wiring datum's owner + // assembly holder's attached object + // assembly holder itself + // us + newhost = connected?.holder || holder?.master || holder || src + + // ok look + // previously this wasn't working and thus no concern, but I made mousetraps work with wires + // specifically in step-on-the-mousetrap mode, ie, when you enter its turf + // and as a consequence, you can put a mousetrap in door wires and it will be set off + // the first time someone walks through a door (enters the door's loc) + // that's an interesting mechanic (bolt open a door for example) but it's not appropriate for a mousetrap + // similarly if used on say an apc's wires it would go into effect when someone walked by it. Not appropriate. + // other assemblies could be made to do something similar instead. + // mousetrap assemblies will still receive on-found notifications when you open a wiring panel + // and (whether reasonable or not) mousetraps that do this do still trigger wires + // the point is for now step-on-mousetrap mode should only work on items + // maybe it should never have been an assembly in the first place. + + // tl;dr only trigger step-on mode if the host is an item + if(!istype(newhost,/obj/item)) + if(host) + UnregisterSignal(host,COMSIG_MOVABLE_MOVED) + host = src + if(isturf(host_turf)) + UnregisterSignal(host_turf,COMSIG_ATOM_ENTERED) + host_turf = null + return + + // If host changed + if((newhost != host) || force) + if(host) + UnregisterSignal(host,COMSIG_MOVABLE_MOVED) + host = newhost + RegisterSignal(host,COMSIG_MOVABLE_MOVED,.proc/holder_movement) + + // If host moved + if((host_turf != host.loc) || force) + if(isturf(host_turf)) + UnregisterSignal(host_turf,COMSIG_ATOM_ENTERED) + host_turf = null + if(isturf(host.loc)) + host_turf = host.loc + RegisterSignal(host_turf,COMSIG_ATOM_ENTERED,.proc/on_entered) + else + host_turf = null + +/obj/item/assembly/mousetrap/holder_movement() + . = ..() + update_host() /obj/item/assembly/mousetrap/Initialize(mapload) . = ..() - var/static/list/loc_connections = list( - COMSIG_ATOM_ENTERED = .proc/on_entered, - ) - AddElement(/datum/element/connect_loc, loc_connections) + update_host(force = TRUE) /obj/item/assembly/mousetrap/examine(mob/user) . = ..() @@ -47,22 +101,22 @@ /obj/item/assembly/mousetrap/on_attach() . = ..() - AddComponent(/datum/component/connect_loc_behalf, holder, holder_connections) + update_host() /obj/item/assembly/mousetrap/on_detach() . = ..() - qdel(GetComponent(/datum/component/connect_loc_behalf)) + update_host() /obj/item/assembly/mousetrap/proc/triggered(mob/target, type = "feet") if(!armed) return + armed = FALSE // moved to the top because you could trigger it more than once under some circumstances + update_appearance() var/obj/item/bodypart/affecting = null if(ishuman(target)) var/mob/living/carbon/human/H = target if(HAS_TRAIT(H, TRAIT_PIERCEIMMUNE)) playsound(src, 'sound/effects/snap.ogg', 50, TRUE) - armed = FALSE - update_appearance() pulse(FALSE) return FALSE switch(type) @@ -89,22 +143,32 @@ else if(isregalrat(target)) visible_message(span_boldannounce("Skreeeee!")) //He's simply too large to be affected by a tiny mouse trap. playsound(src, 'sound/effects/snap.ogg', 50, TRUE) - armed = FALSE - update_appearance() pulse(FALSE) +/** + * clumsy_check: Sets off the mousetrap if handled by a clown (with some probability) + * + * Arguments: + * * user: The mob handling the trap + */ +/obj/item/assembly/mousetrap/proc/clumsy_check(mob/living/carbon/human/user) + if(!armed) + return FALSE + if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50)) + var/which_hand = BODY_ZONE_PRECISE_L_HAND + if(!(user.active_hand_index % 2)) + which_hand = BODY_ZONE_PRECISE_R_HAND + triggered(user, which_hand) + user.visible_message(span_warning("[user] accidentally sets off [src], breaking their fingers."), \ + span_warning("You accidentally trigger [src]!")) + return TRUE + return FALSE /obj/item/assembly/mousetrap/attack_self(mob/living/carbon/human/user) if(!armed) to_chat(user, span_notice("You arm [src].")) else - if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50)) - var/which_hand = BODY_ZONE_PRECISE_L_HAND - if(!(user.active_hand_index % 2)) - which_hand = BODY_ZONE_PRECISE_R_HAND - triggered(user, which_hand) - user.visible_message(span_warning("[user] accidentally sets off [src], breaking their fingers."), \ - span_warning("You accidentally trigger [src]!")) + if(clumsy_check(user)) return to_chat(user, span_notice("You disarm [src].")) armed = !armed @@ -112,17 +176,10 @@ playsound(src, 'sound/weapons/handcuffs.ogg', 30, TRUE, -3) -//ATTACK HAND IGNORING PARENT RETURN VALUE +// Clumsy check only /obj/item/assembly/mousetrap/attack_hand(mob/living/carbon/human/user, list/modifiers) - if(armed) - if((HAS_TRAIT(user, TRAIT_DUMB) || HAS_TRAIT(user, TRAIT_CLUMSY)) && prob(50)) - var/which_hand = BODY_ZONE_PRECISE_L_HAND - if(!(user.active_hand_index % 2)) - which_hand = BODY_ZONE_PRECISE_R_HAND - triggered(user, which_hand) - user.visible_message(span_warning("[user] accidentally sets off [src], breaking their fingers."), \ - span_warning("You accidentally trigger [src]!")) - return + if(clumsy_check(user)) + return return ..() @@ -164,6 +221,15 @@ triggered(null) +/obj/item/assembly/mousetrap/Destroy() + if(host) + UnregisterSignal(host,COMSIG_MOVABLE_MOVED) + host = null + if(isturf(host_turf)) + UnregisterSignal(host_turf,COMSIG_ATOM_ENTERED) + host_turf = null + return ..() + /obj/item/assembly/mousetrap/armed icon_state = "mousetraparmed" armed = TRUE diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm index c1c4cecaffd..210cc4ec0e3 100644 --- a/code/modules/assembly/proximity.dm +++ b/code/modules/assembly/proximity.dm @@ -37,12 +37,35 @@ update_appearance() return TRUE +/obj/item/assembly/prox_sensor/dropped() + . = ..() + // Pick the first valid object in this list: + // Wiring datum's owner + // assembly holder's attached object + // assembly holder itself + // us + proximity_monitor.set_host(connected?.holder || holder?.master || holder || src, src) + +/obj/item/assembly/prox_sensor/on_attach() + . = ..() + // Pick the first valid object in this list: + // Wiring datum's owner + // assembly holder's attached object + // assembly holder itself + // us + proximity_monitor.set_host(connected?.holder || holder?.master || holder || src, src) + /obj/item/assembly/prox_sensor/on_detach() . = ..() if(!.) return else - proximity_monitor.set_host(src, src) + // Pick the first valid object in this list: + // Wiring datum's owner + // assembly holder's attached object + // assembly holder itself + // us + proximity_monitor.set_host(connected?.holder || holder?.master || holder || src, src) /obj/item/assembly/prox_sensor/toggle_secure() secured = !secured diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm index d2312056c2e..d47c6f8fb88 100644 --- a/code/modules/assembly/timer.dm +++ b/code/modules/assembly/timer.dm @@ -54,12 +54,11 @@ return secured /obj/item/assembly/timer/proc/timer_end() - if(!secured || next_activate > world.time) - return FALSE - pulse(FALSE) - audible_message("[icon2html(src, hearers(src))] *beep* *beep* *beep*", null, hearing_range) - for(var/mob/hearing_mob in get_hearers_in_view(hearing_range, src)) - hearing_mob.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE) + if(secured && next_activate <= world.time) + pulse(FALSE) + audible_message(span_infoplain("[icon2html(src, hearers(src))] *beep* *beep* *beep*"), null, hearing_range) + for(var/mob/hearing_mob in get_hearers_in_view(hearing_range, src)) + hearing_mob.playsound_local(get_turf(src), 'sound/machines/triple_beep.ogg', ASSEMBLY_BEEP_VOLUME, TRUE) if(loop) timing = TRUE update_appearance() diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 623e6783504..a22c18aaf86 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -7,20 +7,44 @@ anchored = FALSE pressure_resistance = 2*ONE_ATMOSPHERE max_integrity = 300 - ///In units, how much the dispenser can hold + /// In units, how much the dispenser can hold var/tank_volume = 1000 - ///The ID of the reagent that the dispenser uses + /// The ID of the reagent that the dispenser uses var/reagent_id = /datum/reagent/water - ///Can you turn this into a plumbing tank? + /// Can you turn this into a plumbing tank? var/can_be_tanked = TRUE - ///Is this source self-replenishing? + /// Is this source self-replenishing? var/refilling = FALSE - ///Can this dispenser be opened using a wrench? + /// Can this dispenser be opened using a wrench? var/openable = FALSE - ///Is this dispenser slowly leaking its reagent? + /// Is this dispenser slowly leaking its reagent? var/leaking = FALSE - ///How much reagent to leak + /// How much reagent to leak var/amount_to_leak = 10 + /// An assembly attached to the tank - if this dispenser accepts_rig + var/obj/item/assembly_holder/rig = null + /// Whether this dispenser can be rigged with an assembly (and blown up with an igniter) + var/accepts_rig = FALSE + //overlay of attached assemblies + var/mutable_appearance/assembliesoverlay + /// The person who attached an assembly to this dispenser, for bomb logging purposes + var/last_rigger = "" + +// This check is necessary for assemblies to automatically detect that we are compatible +/obj/structure/reagent_dispensers/IsSpecialAssembly() + return accepts_rig + +/obj/structure/reagent_dispensers/Destroy() + QDEL_NULL(rig) + return ..() + +/** + * rig_boom: Wrapper to log when a reagent_dispenser is set off by an assembly + * + */ +/obj/structure/reagent_dispensers/proc/rig_boom() + log_bomber(last_rigger, "rigged [src] exploded", src) + boom() /obj/structure/reagent_dispensers/Initialize(mapload) . = ..() @@ -37,6 +61,12 @@ . += span_notice("Its tap looks like it could be wrenched open.") else . += span_warning("Its tap is wrenched open!") + if(accepts_rig && get_dist(user, src) <= 2) + if(rig) + . += span_warning("There is some kind of device rigged to the tank!") + else + . += span_notice("It looks like you could rig a device to the tank.") + /obj/structure/reagent_dispensers/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) . = ..() @@ -47,6 +77,30 @@ /obj/structure/reagent_dispensers/attackby(obj/item/W, mob/user, params) if(W.is_refillable()) return FALSE //so we can refill them via their afterattack. + if(istype(W, /obj/item/assembly_holder) && accepts_rig) + if(rig) + user.balloon_alert("another device is in the way!") + return ..() + var/obj/item/assembly_holder/holder = W + if(!(locate(/obj/item/assembly/igniter) in holder.assemblies)) + return ..() + + user.balloon_alert_to_viewers("attaching rig...") + add_fingerprint(user) + if(!do_after(user, 2 SECONDS, target = src) || !user.transferItemToLoc(holder, src)) + return + rig = holder + holder.master = src + holder.on_attach() + assembliesoverlay = holder + assembliesoverlay.pixel_x += 6 + assembliesoverlay.pixel_y += 1 + add_overlay(assembliesoverlay) + RegisterSignal(src, COMSIG_IGNITER_ACTIVATE, .proc/rig_boom) + log_bomber(user, "attached [holder.name] to ", src) + last_rigger = user + user.balloon_alert_to_viewers("attached rig") + return if(istype(W, /obj/item/stack/sheet/iron) && can_be_tanked) var/obj/item/stack/sheet/iron/metal_stack = W @@ -62,15 +116,75 @@ return ..() +/obj/structure/reagent_dispensers/Exited(atom/movable/gone, direction) + . = ..() + if(gone == rig) + rig = null + +/obj/structure/reagent_dispensers/attack_hand(mob/user, list/modifiers) + . = ..() + if(. || !rig) + return + // mousetrap rigs only make sense if you can set them off, can't step on them + // If you see a mousetrap-rigged fuel tank, just leave it alone + rig.on_found() + if(QDELETED(src)) + return + user.balloon_alert_to_viewers("detaching rig...") + if(!do_after(user, 2 SECONDS, target = src)) + return + user.balloon_alert_to_viewers("detached rig") + user.log_message("detached [rig] from [src].", LOG_GAME) + if(!user.put_in_hands(rig)) + rig.forceMove(get_turf(user)) + rig = null + last_rigger = null + cut_overlays(assembliesoverlay) + UnregisterSignal(src, COMSIG_IGNITER_ACTIVATE) + /obj/structure/reagent_dispensers/Initialize(mapload) create_reagents(tank_volume, DRAINABLE | AMOUNT_VISIBLE) if(reagent_id) reagents.add_reagent(reagent_id, tank_volume) . = ..() +/** + * boom: Detonate a reagent dispenser. + * + * This is most dangerous for fuel tanks, which will explosion(). + * Other dispensers will scatter their contents within range. + */ /obj/structure/reagent_dispensers/proc/boom() - visible_message(span_danger("\The [src] ruptures!")) - chem_splash(loc, null, 5, list(reagents)) + var/datum/reagent/fuel/volatiles = reagents.has_reagent(/datum/reagent/fuel) + var/fuel_amt = 0 + if(istype(volatiles) && volatiles.volume >= 25) + fuel_amt = volatiles.volume + reagents.del_reagent(/datum/reagent/fuel) // not actually used for the explosion + if(reagents.total_volume) + if(!fuel_amt) + visible_message(span_danger("\The [src] ruptures!")) + // Leave it up to future terrorists to figure out the best way to mix reagents with fuel for a useful boom here + chem_splash(loc, null, 2 + (reagents.total_volume + fuel_amt) / 1000, list(reagents), extra_heat=(fuel_amt / 50),adminlog=(fuel_amt<25)) + + if(fuel_amt) // with that done, actually explode + visible_message(span_danger("\The [src] explodes!")) + // old code for reference: + // standard fuel tank = 1000 units = heavy_impact_range = 1, light_impact_range = 5, flame_range = 5 + // big fuel tank = 5000 units = devastation_range = 1, heavy_impact_range = 2, light_impact_range = 7, flame_range = 12 + // It did not account for how much fuel was actually in the tank at all, just the size of the tank. + // I encourage others to better scale these numbers in the future. + // As it stands this is a minor nerf in exchange for an easy bombing technique working that has been broken for a while. + switch(volatiles.volume) + if(25 to 150) + explosion(src, light_impact_range = 1, flame_range = 2) + if(150 to 300) + explosion(src, light_impact_range = 2, flame_range = 3) + if(300 to 750) + explosion(src, heavy_impact_range = 1, light_impact_range = 3, flame_range = 5) + if(750 to 1500) + explosion(src, heavy_impact_range = 1, light_impact_range = 4, flame_range = 6) + if(1500 to INFINITY) + explosion(src, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 6, flame_range = 8) qdel(src) /obj/structure/reagent_dispensers/deconstruct(disassembled = TRUE) @@ -127,14 +241,7 @@ icon_state = "fuel" reagent_id = /datum/reagent/fuel openable = TRUE - //an assembly attached to the tank - var/obj/item/assembly_holder/rig = null - //whether it accepts assemblies or not - var/accepts_rig = TRUE - //overlay of attached assemblies - var/mutable_appearance/assembliesoverlay - /// The last person to rig this fuel tank - Stored with the object. Only the last person matters for investigation - var/last_rigger = "" + accepts_rig = TRUE /obj/structure/reagent_dispensers/fueltank/Initialize(mapload) . = ..() @@ -142,49 +249,6 @@ if(SSevents.holidays?[APRIL_FOOLS]) icon_state = "fuel_fools" -/obj/structure/reagent_dispensers/fueltank/Destroy() - QDEL_NULL(rig) - return ..() - -/obj/structure/reagent_dispensers/fueltank/Exited(atom/movable/gone, direction) - . = ..() - if(gone == rig) - rig = null - -/obj/structure/reagent_dispensers/fueltank/examine(mob/user) - . = ..() - if(get_dist(user, src) <= 2) - if(rig) - . += span_warning("There is some kind of device rigged to the tank!") - else - . += span_notice("It looks like you could rig a device to the tank.") - -/obj/structure/reagent_dispensers/fueltank/attack_hand(mob/user, list/modifiers) - . = ..() - if(.) - return - if(!rig) - return - user.balloon_alert_to_viewers("detaching rig...") - if(!do_after(user, 2 SECONDS, target = src)) - return - user.balloon_alert_to_viewers("detached rig") - user.log_message("detached [rig] from [src].", LOG_GAME) - if(!user.put_in_hands(rig)) - rig.forceMove(get_turf(user)) - rig = null - last_rigger = null - cut_overlays(assembliesoverlay) - UnregisterSignal(src, COMSIG_IGNITER_ACTIVATE) - -/obj/structure/reagent_dispensers/fueltank/boom() - explosion(src, heavy_impact_range = 1, light_impact_range = 5, flame_range = 5) - qdel(src) - -/obj/structure/reagent_dispensers/fueltank/proc/rig_boom() - log_bomber(last_rigger, "rigged fuel tank exploded", src) - boom() - /obj/structure/reagent_dispensers/fueltank/blob_act(obj/structure/blob/B) boom() @@ -225,27 +289,7 @@ log_bomber(user, "detonated a", src, "via welding tool") boom() return - if(istype(I, /obj/item/assembly_holder) && accepts_rig) - if(rig) - user.balloon_alert("another device is in the way!") - return ..() - user.balloon_alert_to_viewers("attaching rig...") - if(!do_after(user, 2 SECONDS, target = src)) - return - user.balloon_alert_to_viewers("attached rig") - var/obj/item/assembly_holder/holder = I - if(locate(/obj/item/assembly/igniter) in holder.assemblies) - rig = holder - if(!user.transferItemToLoc(holder, src)) - return - log_bomber(user, "rigged [name] with [holder.name] for explosion", src) - last_rigger = user - assembliesoverlay = holder - assembliesoverlay.pixel_x += 6 - assembliesoverlay.pixel_y += 1 - add_overlay(assembliesoverlay) - RegisterSignal(src, COMSIG_IGNITER_ACTIVATE, .proc/rig_boom) - return + return ..() /obj/structure/reagent_dispensers/fueltank/large @@ -254,10 +298,6 @@ icon_state = "fuel_high" tank_volume = 5000 -/obj/structure/reagent_dispensers/fueltank/large/boom() - explosion(src, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 7, flame_range = 12) - qdel(src) - /// Wall mounted dispeners, like pepper spray or virus food. Not a normal tank, and shouldn't be able to be turned into a plumbed stationary one. /obj/structure/reagent_dispensers/wall anchored = TRUE @@ -388,3 +428,4 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/reagent_dispensers/wall/virusfood, 30 icon_state = "fuel_stationary" desc = "A stationary, plumbed, fuel tank." reagent_id = /datum/reagent/fuel + accepts_rig = TRUE