#define EARTHCRACKER_READY "ready" #define EARTHCRACKER_ACTIVE "active" #define EARTHCRACKER_SPENT "spent" /** * The E-2 Earthcracker, a traitor device that creates intentional weakpoints on the station after use, which can be triggered via explosions. * See weakpoint.dm for more specifics on their effects. */ /obj/item/earthcracker name = "E-2 Earthcracker" desc = "A nasty automated pilebunker can be used to create a massive weakpoint in flooring,\ which can be triggered afterwards by a sufficiently strong enough explosion." icon = 'icons/obj/devices/tool.dmi' icon_state = "earthcracker" base_icon_state = "earthcracker" /// Is the earthcracker ready to arm, arming, activating, or spent? var/status = EARTHCRACKER_READY /// What kind of weakpoint shall you spawn? var/obj/weakpoint_type = /obj/effect/weakpoint/big /// The timer for the strike_the_earth activation var/activation_timer /obj/item/earthcracker/Initialize(mapload) . = ..() if(!weakpoint_type) CRASH("An earthcracker spawned without a designated weakpoint!") register_context() /obj/item/earthcracker/attack_self(mob/user, modifiers) . = ..() if(status == EARTHCRACKER_READY) handle_arming(user) /obj/item/earthcracker/attack_hand(mob/user, list/modifiers) . = ..() if(!anchored) return NONE switch(status) if(EARTHCRACKER_ACTIVE) if(activation_timer) return FALSE var/response = tgui_alert(user, "Activate the earthcracker?", "Activate?", list("Yes", "No")) == "Yes" if(!response) return FALSE if(!user.Adjacent(src)) return FALSE flick("[base_icon_state]-active", src) if(is_mining_level(z)) activation_timer = addtimer(CALLBACK(src, PROC_REF(mining_act), user), 1.2 SECONDS) return TRUE activation_timer = addtimer(CALLBACK(src, PROC_REF(strike_the_earth)), 1.2 SECONDS) return TRUE if(EARTHCRACKER_SPENT) balloon_alert(user, "used up!") return FALSE /obj/item/earthcracker/update_icon_state() . = ..() switch(status) if(EARTHCRACKER_READY) icon_state = "[base_icon_state]" if(EARTHCRACKER_ACTIVE) icon_state = "[base_icon_state]-armed" if(EARTHCRACKER_SPENT) icon_state = "[base_icon_state]-spent" /obj/item/earthcracker/wrench_act(mob/living/user, obj/item/tool) if(anchored && status == EARTHCRACKER_SPENT) balloon_alert(user, "it falls apart") animate(src, 0.6 SECONDS, alpha = 0, easing = CIRCULAR_EASING|EASE_IN) addtimer(CALLBACK(src, PROC_REF(post_break)), 0.6 SECONDS) return ITEM_INTERACT_SUCCESS if(!anchored && status == EARTHCRACKER_READY) balloon_alert(user, "arm in hands first!") return ITEM_INTERACT_SUCCESS if(anchored && status == EARTHCRACKER_ACTIVE) balloon_alert(user, "unfastening from the floor...") if(!tool.use_tool(src, user, 8 SECONDS, volume = 50)) return ITEM_INTERACT_FAILURE anchored = FALSE status = EARTHCRACKER_READY update_appearance(UPDATE_ICON) return NONE /obj/item/earthcracker/add_context(atom/source, list/context, obj/item/held_item, mob/user) switch(status) if(EARTHCRACKER_ACTIVE) context[SCREENTIP_CONTEXT_LMB] = "Activate device" if(EARTHCRACKER_SPENT) if(held_item?.tool_behaviour == TOOL_WRENCH) context[SCREENTIP_CONTEXT_LMB] = "Disassemble device" return CONTEXTUAL_SCREENTIP_SET /obj/item/earthcracker/examine(mob/user) . = ..() if(status == EARTHCRACKER_SPENT) . += span_warning("This device is toast. You could disassemble the remains using a [EXAMINE_HINT("Wrench")].") else . += span_info("This device can be unanchored using a [EXAMINE_HINT("Wrench")].") /obj/item/earthcracker/proc/handle_arming(mob/user) var/turf/arm_location = get_turf(user) if(!arm_location) return FALSE if(isgroundlessturf(arm_location)) balloon_alert(user, "can't deploy here") return FALSE if(status == EARTHCRACKER_SPENT) balloon_alert(user, "used up!") return FALSE balloon_alert(user, "arming...") if(!do_after(user, 3 SECONDS, src)) balloon_alert(user, "failed to arm") return FALSE forceMove(arm_location) anchored = TRUE flick("[base_icon_state]-arm", src) playsound(src, 'sound/items/barcodebeep.ogg', 50, FALSE) status = EARTHCRACKER_ACTIVE update_appearance(UPDATE_ICON) return TRUE /// The fun part. We spawn a huge weakpoint here. /obj/item/earthcracker/proc/strike_the_earth() if(QDELETED(src)) return playsound(src, 'sound/items/weapons/earthcracker_bang.mp3', 75, FALSE, 3) var/turf/cracked_hull = drop_location() new weakpoint_type(cracked_hull) handle_after_activation(cracked_hull) /// Cleanup after an earthcracker is activated either for sabotage or mining. /obj/item/earthcracker/proc/handle_after_activation(turf/cracked_hull) do_sparks(2, FALSE, src) cracked_hull.levelupdate() status = EARTHCRACKER_SPENT update_appearance(UPDATE_ICON) particles = new /particles/smoke/burning/small activation_timer = null /// Called after the earthcracker activates. /obj/item/earthcracker/proc/post_break() deconstruct(TRUE) /// When this item is used on a mining Z, we perform an action that breaks all rocks in a radius around us, the same as starting an ore vent wave. /obj/item/earthcracker/proc/mining_act(mob/user) for(var/i in 1 to 5) for(var/turf/rock in oview(i)) // This collects a list of rings of turfs (in a growing radius of i) that we'll applying logic to "drill" below. if(istype(rock, /turf/closed/mineral)) if(prob(50 + (i * 8))) continue var/turf/closed/mineral/drillable = rock drillable.gets_drilled(user) if(prob(50)) new /obj/effect/decal/cleanable/rubble(rock) continue if(istype(rock, /turf/open/misc/asteroid) && prob(35)) new /obj/effect/decal/cleanable/rubble(rock) continue sleep(0.6 SECONDS) handle_after_activation() /// Small subtype for shenanigans. /obj/item/earthcracker/small name = "E-1 Earthcracker" desc = "A rusty automated pilebunker can be used to create a weakpoint in flooring,\ which can be triggered afterwards by a sufficiently strong enough explosion.\ You're pretty sure the mining company that used to make these got bought by Nanotrasen ages ago." weakpoint_type = /obj/effect/weakpoint #undef EARTHCRACKER_READY #undef EARTHCRACKER_ACTIVE #undef EARTHCRACKER_SPENT