diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm index 3b8649e26a5..b03a5d10fdf 100644 --- a/code/game/gamemodes/nuclear/nuclearbomb.dm +++ b/code/game/gamemodes/nuclear/nuclearbomb.dm @@ -4,6 +4,10 @@ #define NUKE_SEALANT_OPEN 3 #define NUKE_UNWRENCHED 4 #define NUKE_MOBILE 5 +#define NUKE_CORE_EVERYTHING_FINE 6 +#define NUKE_CORE_PANEL_EXPOSED 7 +#define NUKE_CORE_PANEL_UNWELDED 8 +#define NUKE_CORE_FULLY_EXPOSED 9 GLOBAL_VAR(bomb_set) @@ -25,12 +29,17 @@ GLOBAL_VAR(bomb_set) var/yes_code = FALSE var/safety = TRUE var/obj/item/disk/nuclear/auth = null - var/removal_stage = NUKE_INTACT + var/obj/item/nuke_core/plutonium/core = null var/lastentered var/is_syndicate = FALSE use_power = NO_POWER_USE var/previous_level = "" var/datum/wires/nuclearbomb/wires = null + var/removal_stage = NUKE_INTACT + ///The same state removal stage is, until someone opens the panel of the nuke. This way we can have someone open the front of the nuke, while keeping track of where in the world we are on the anchoring bolts. + var/anchor_stage = NUKE_INTACT + ///This is so that we can check if the internal components are sealed up properly when the outer hatch is closed. + var/core_stage = NUKE_CORE_EVERYTHING_FINE /obj/machinery/nuclearbomb/syndicate is_syndicate = TRUE @@ -39,16 +48,19 @@ GLOBAL_VAR(bomb_set) extended = FALSE anchored = FALSE -/obj/machinery/nuclearbomb/New() - ..() - r_code = rand(10000, 99999.0) // Creates a random code upon object spawn. +/obj/machinery/nuclearbomb/Initialize() + . = ..() + r_code = rand(10000, 99999) // Creates a random code upon object spawn. wires = new/datum/wires/nuclearbomb(src) previous_level = get_security_level() GLOB.poi_list |= src + core = new /obj/item/nuke_core/plutonium(src) + STOP_PROCESSING(SSobj, core) //Let us not irradiate the vault by default. /obj/machinery/nuclearbomb/Destroy() SStgui.close_uis(wires) QDEL_NULL(wires) + QDEL_NULL(core) GLOB.poi_list.Remove(src) return ..() @@ -73,16 +85,41 @@ GLOBAL_VAR(bomb_set) else to_chat(user, "You need to deploy [src] first.") return + if(istype(O, /obj/item/stack/sheet/mineral/titanium) && removal_stage == NUKE_CORE_FULLY_EXPOSED) + if(do_after(user, 2 SECONDS, target = src)) + var/obj/item/stack/S = O + if(!loc || !S || S.get_amount() < 5) + return + S.use(5) + user.visible_message("[user] repairs [src]'s inner core plate.", "You repair [src]'s inner core plate. The radiation is contained.") + removal_stage = NUKE_CORE_PANEL_UNWELDED + if(core) + STOP_PROCESSING(SSobj, core) + return + if(istype(O, /obj/item/stack/sheet/metal) && removal_stage == NUKE_CORE_PANEL_EXPOSED) + var/obj/item/stack/S = O + if(do_after(user, 2 SECONDS, target = src)) + if(!loc || !S || S.get_amount() < 5) + return + S.use(5) + user.visible_message("[user] repairs [src]'s outer core plate.", "You repair [src]'s outer core plate.") + removal_stage = NUKE_CORE_EVERYTHING_FINE + return + if(istype(O, /obj/item/nuke_core/plutonium) && removal_stage == NUKE_CORE_FULLY_EXPOSED) + if(do_after(user, 2 SECONDS, target = src)) + if(!user.unEquip(O)) + to_chat(user, "The [O] is stuck to your hand!") + return + user.visible_message("[user] puts [O] back in [src].", "You put [O] back in [src].") + O.forceMove(src) + core = O + else if(istype(O, /obj/item/disk/plantgene)) to_chat(user, "You try to plant the disk, but despite rooting around, it won't fit! After you branch out to read the instructions, you find out where the problem stems from. You've been bamboo-zled, this isn't a nuclear disk at all!") return return ..() /obj/machinery/nuclearbomb/crowbar_act(mob/user, obj/item/I) - if(!anchored) - return - if(removal_stage != NUKE_UNWRENCHED && removal_stage != NUKE_COVER_OFF) - return . = TRUE if(!I.tool_use_check(user, 0)) return @@ -92,9 +129,26 @@ GLOBAL_VAR(bomb_set) return user.visible_message("[user] forces open the bolt covers on [src].", "You force open the bolt covers.") removal_stage = NUKE_COVER_OPEN - else + if(removal_stage == NUKE_CORE_EVERYTHING_FINE) + user.visible_message("[user] starts removing [src]'s outer core plate...", "You start removing [src]'s outer core plate...") + if(!I.use_tool(src, user, 4 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_CORE_EVERYTHING_FINE) + return + user.visible_message("[user] finishes removing [src]'s outer core plate.", "You finish removing [src]'s outer core plate.") + new /obj/item/stack/sheet/metal(loc, 5) + removal_stage = NUKE_CORE_PANEL_EXPOSED + + if(removal_stage == NUKE_CORE_PANEL_UNWELDED) + user.visible_message("[user] starts removing [src]'s inner core plate...", "You start removing [src]'s inner core plate...") + if(!I.use_tool(src, user, 8 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_CORE_PANEL_UNWELDED) + return + user.visible_message("[user] finishes removing [src]'s inner core plate.", "You remove [src]'s inner core plate. You can see the core's green glow!") + removal_stage = NUKE_CORE_FULLY_EXPOSED + new /obj/item/stack/sheet/mineral/titanium(loc, 5) + if(core) + START_PROCESSING(SSobj, core) + if(removal_stage == NUKE_UNWRENCHED) user.visible_message("[user] begins lifting [src] off of the anchors.", "You begin lifting the device off the anchors...") - if(!I.use_tool(src, user, 80, volume = I.tool_volume) || removal_stage != NUKE_UNWRENCHED) + if(!I.use_tool(src, user, 8 SECONDS, volume = I.tool_volume) || removal_stage != NUKE_UNWRENCHED) return user.visible_message("[user] crowbars [src] off of the anchors. It can now be moved.", "You jam the crowbar under the nuclear device and lift it off its anchors. You can now move it!") anchored = FALSE @@ -126,15 +180,19 @@ GLOBAL_VAR(bomb_set) . = TRUE if(!I.use_tool(src, user, 0, volume = I.tool_volume)) return - if(auth) + if(auth || (istype(I, /obj/item/screwdriver/nuke))) if(!panel_open) panel_open = TRUE overlays += image(icon, "npanel_open") to_chat(user, "You unscrew the control panel of [src].") + anchor_stage = removal_stage + removal_stage = core_stage else panel_open = FALSE overlays -= image(icon, "npanel_open") to_chat(user, "You screw the control panel of [src] back on.") + core_stage = removal_stage + removal_stage = anchor_stage else if(!panel_open) to_chat(user, "[src] emits a buzzing noise, the panel staying locked in.") @@ -142,6 +200,8 @@ GLOBAL_VAR(bomb_set) panel_open = FALSE overlays -= image(icon, "npanel_open") to_chat(user, "You screw the control panel of [src] back on.") + core_stage = removal_stage + removal_stage = anchor_stage flick("nuclearbombc", src) /obj/machinery/nuclearbomb/wirecutter_act(mob/user, obj/item/I) @@ -154,8 +214,6 @@ GLOBAL_VAR(bomb_set) /obj/machinery/nuclearbomb/welder_act(mob/user, obj/item/I) . = TRUE - if(removal_stage != NUKE_INTACT && removal_stage != NUKE_COVER_OPEN) - return if(!I.tool_use_check(user, 0)) return if(removal_stage == NUKE_INTACT) @@ -167,7 +225,20 @@ GLOBAL_VAR(bomb_set) visible_message("[user] cuts through the bolt covers on [src].",\ "You cut through the bolt cover.") removal_stage = NUKE_COVER_OFF - else if(removal_stage == NUKE_COVER_OPEN) + if(removal_stage == NUKE_CORE_PANEL_UNWELDED) + user.visible_message("[user] starts welding [src]'s inner core plate...", "You start welding [src]'s inner core plate...") + if(!I.use_tool(src, user, 4 SECONDS, 5, volume = I.tool_volume) || removal_stage != NUKE_CORE_PANEL_UNWELDED) + return + user.visible_message("[user] finishes welding [src]'s inner core plate...", "You finish welding [src]'s inner core plate...") + removal_stage = NUKE_CORE_PANEL_EXPOSED + + else if(removal_stage == NUKE_CORE_PANEL_EXPOSED) + user.visible_message("[user] starts unwelding [src]'s inner core plate...", "You start unwelding [src]'s inner core plate...") + if(!I.use_tool(src, user, 4 SECONDS, 5, volume = I.tool_volume) || removal_stage != NUKE_CORE_PANEL_EXPOSED) + return + user.visible_message("[user] finishes unwelding [src]'s inner core plate...", "You finish unwelding [src]'s inner core plate...") + removal_stage = NUKE_CORE_PANEL_UNWELDED + if(removal_stage == NUKE_COVER_OPEN) visible_message("[user] starts cutting apart the anchoring system sealant on [src].",\ "You start cutting apart the anchoring system's sealant with [I]...",\ "You hear welding.") @@ -181,10 +252,18 @@ GLOBAL_VAR(bomb_set) attack_hand(user) /obj/machinery/nuclearbomb/attack_hand(mob/user as mob) - if(panel_open) - wires.Interact(user) - else - ui_interact(user) + if(!panel_open) + return ui_interact(user) + if(removal_stage != NUKE_CORE_FULLY_EXPOSED || !core) + return wires.Interact(user) + if(timing) //removing the core is less risk then cutting wires, and doesnt take long, so we should not let crew do it while the nuke is armed. You can however get to it, without the special screwdriver, if you put the NAD in. + to_chat(user, "[core] won't budge, metal clamps keep it in!") + return + user.visible_message("[user] starts to pull [core] out of [src]!", "You start to pull [core] out of [src]!") + if(do_after(user, 5 SECONDS, target = src)) + user.visible_message("[user] pulls [core] out of [src]!", "You pull [core] out of [src]! Might want to put it somewhere safe.") + core.forceMove(loc) + core = null /obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = TRUE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state) ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) @@ -308,6 +387,9 @@ GLOBAL_VAR(bomb_set) if(safety) to_chat(usr, "The safety is still on.") return + if(!core) + to_chat(usr, "[src]'s screen blinks red! There is no plutonium core in [src]!") + return timing = !(timing) if(timing) if(!lighthack) @@ -471,3 +553,7 @@ GLOBAL_VAR(bomb_set) #undef NUKE_SEALANT_OPEN #undef NUKE_UNWRENCHED #undef NUKE_MOBILE +#undef NUKE_CORE_EVERYTHING_FINE +#undef NUKE_CORE_PANEL_EXPOSED +#undef NUKE_CORE_PANEL_UNWELDED +#undef NUKE_CORE_FULLY_EXPOSED diff --git a/code/game/gamemodes/objective.dm b/code/game/gamemodes/objective.dm index b7ff2d7992e..b5bb07ff234 100644 --- a/code/game/gamemodes/objective.dm +++ b/code/game/gamemodes/objective.dm @@ -391,6 +391,8 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective) explanation_text = "Steal [steal_target]. One was last seen in [get_location()]. " if(length(O.protected_jobs)) explanation_text += "It may also be in the possession of the [english_list(O.protected_jobs, and_text = " or ")]." + if(steal_target.special_equipment) + give_kit(steal_target.special_equipment) return explanation_text = "Free Objective." @@ -412,6 +414,8 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective) else steal_target = new new_target explanation_text = "Steal [steal_target.name]." + if(steal_target.special_equipment) + give_kit(steal_target.special_equipment) return steal_target /datum/objective/steal/check_completion() @@ -429,6 +433,23 @@ GLOBAL_LIST_INIT(potential_theft_objectives, (subtypesof(/datum/theft_objective) if(I.type in steal_target.altitems) return steal_target.check_special_completion(I) +/datum/objective/steal/proc/give_kit(obj/item/item_path) + var/mob/living/carbon/human/mob = owner.current + var/I = new item_path + var/list/slots = list( + "backpack" = slot_in_backpack, + "left pocket" = slot_l_store, + "right pocket" = slot_r_store, + "left hand" = slot_l_hand, + "right hand" = slot_r_hand, + ) + var/where = mob.equip_in_one_of_slots(I, slots) + if(where) + to_chat(mob, "

In your [where] is a box containing items and instructions to help you with your steal objective.
") + else + to_chat(mob, "Unfortunately, you weren't able to get a stealing kit. This is very bad and you should adminhelp immediately (press F1).") + message_admins("[ADMIN_LOOKUPFLW(mob)] Failed to spawn with their [item_path] theft kit.") + qdel(I) /datum/objective/steal/exchange martyr_compatible = 0 diff --git a/code/game/gamemodes/steal_items.dm b/code/game/gamemodes/steal_items.dm index 780962045be..24ea05d786c 100644 --- a/code/game/gamemodes/steal_items.dm +++ b/code/game/gamemodes/steal_items.dm @@ -12,6 +12,8 @@ var/list/altitems = list() var/flags = 0 var/location_override + /// Do we have a special item we give to somewhen when they get this objective? + var/special_equipment = null /datum/theft_objective/proc/check_completion(datum/mind/owner) if(!owner.current) @@ -138,6 +140,19 @@ protected_jobs = list("Head Of Security", "Warden") location_override = "the Warden's Office" +/datum/theft_objective/supermatter_sliver + name = "a supermatter sliver" + typepath = /obj/item/nuke_core/supermatter_sliver + protected_jobs = list("Chief Engineer", "Engineer", "Atmospheric Technician") //Unlike other steal objectives, all jobs in the department have easy access, and would not be noticed at all stealing this + location_override = "Engineering. You can use the box and instructions provided to harvest the sliver." + special_equipment = /obj/item/storage/box/syndie_kit/supermatter + +/datum/theft_objective/plutonium_core + name = "the plutonium core from the stations nuclear device" + typepath = /obj/item/nuke_core/plutonium + location_override = "the Vault. You can use the box and instructions provided to remove the core, with some extra tools." + special_equipment = /obj/item/storage/box/syndie_kit/nuke + /datum/theft_objective/number var/min=0 var/max=0 diff --git a/code/game/objects/items/theft_items.dm b/code/game/objects/items/theft_items.dm new file mode 100644 index 00000000000..0a32cf90df7 --- /dev/null +++ b/code/game/objects/items/theft_items.dm @@ -0,0 +1,282 @@ +//Items for nuke theft, supermatter theft traitor objective + + +// STEALING THE NUKE + +//the nuke core, base item +/obj/item/nuke_core + name = "plutonium core" + desc = "Extremely radioactive. Wear goggles." + icon = 'icons/obj/nuke_tools.dmi' + icon_state = "plutonium_core" + item_state = "plutoniumcore" + resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF + flags_2 = RAD_NO_CONTAMINATE_2 //Don't have the item itself become irradiated when it makes radiation. + var/pulse = 0 + var/cooldown = 0 + var/pulseicon = "plutonium_core_pulse" + +/obj/item/nuke_core/Initialize() + . = ..() + START_PROCESSING(SSobj, src) + +/obj/item/nuke_core/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/nuke_core/attackby(obj/item/nuke_core_container/container, mob/user) + if(istype(container)) + container.load(src, user) + else + return ..() + +/obj/item/nuke_core/process() + if(cooldown < world.time - 6 SECONDS) + cooldown = world.time + flick(pulseicon, src) + radiation_pulse(src, 400, 2) + +/obj/item/nuke_core/suicide_act(mob/user) + user.visible_message("[user] is rubbing [src] against [user.p_them()]self! It looks like [user.p_theyre()] trying to commit suicide!") + return TOXLOSS + +/obj/item/nuke_core/plutonium //The steal objective, so it doesnt mess with the SM sliver on pinpointers and objectives + +//nuke core box, for carrying the core +/obj/item/nuke_core_container + name = "nuke core container" + desc = "A solid container for radioactive objects." + icon = 'icons/obj/nuke_tools.dmi' + icon_state = "core_container_empty" + item_state = "metal" + var/obj/item/nuke_core/plutonium/core + +/obj/item/nuke_core_container/Destroy() + QDEL_NULL(core) + return ..() + +/obj/item/nuke_core_container/proc/load(obj/item/nuke_core/plutonium/new_core, mob/user) + if(core || !istype(new_core)) + return + new_core.forceMove(src) + core = new_core + icon_state = "core_container_loaded" + to_chat(user, "Container is sealing...") + addtimer(CALLBACK(src, .proc/seal), 10 SECONDS) + +/obj/item/nuke_core_container/proc/seal() + if(!QDELETED(core)) + STOP_PROCESSING(SSobj, core) + icon_state = "core_container_sealed" + playsound(src, 'sound/items/deconstruct.ogg', 60, TRUE) + if(ismob(loc)) + to_chat(loc, "[src] is permanently sealed, [core]'s radiation is contained.") + +/obj/item/nuke_core_container/attackby(obj/item/nuke_core/plutonium/core, mob/user) + if(!istype(core)) + return ..() + + if(!user.drop_item()) + to_chat(user, "[core] is stuck to your hand!") + return + else + load(core, user) + +/obj/item/paper/guides/antag/nuke_instructions + info = "How to break into a Nanotrasen nuclear device and remove its plutonium core:
\ + " + +// STEALING SUPERMATTER. + +/obj/item/paper/guides/antag/supermatter_sliver + info = "How to safely extract a supermatter sliver:
\ + " + +/obj/item/nuke_core/supermatter_sliver + name = "supermatter sliver" + desc = "A tiny, highly volatile sliver of a supermatter crystal. Do not handle without protection!" + icon_state = "supermatter_sliver" + pulseicon = "supermatter_sliver_pulse" + +/obj/item/nuke_core/supermatter_sliver/attack_tk(mob/user) // no TK dusting memes + return + +/obj/item/nuke_core/supermatter_sliver/can_be_pulled(user) // no drag memes + return FALSE + +/obj/item/nuke_core/supermatter_sliver/attackby(obj/item/I, mob/living/user, params) + if(istype(I, /obj/item/retractor/supermatter)) + var/obj/item/retractor/supermatter/tongs = I + if(tongs.sliver) + to_chat(user, "[tongs] are already holding a supermatter sliver!") + return FALSE + forceMove(tongs) + tongs.sliver = src + tongs.icon_state = "supermatter_tongs_loaded" + tongs.item_state = "supermatter_tongs_loaded" + to_chat(user, "You carefully pick up [src] with [tongs].") + else if(istype(I, /obj/item/scalpel/supermatter) || istype(I, /obj/item/nuke_core_container/supermatter)) // we don't want it to dust + return + else + to_chat(user, "As it touches [src], both [src] and [I] burst into dust!") + radiation_pulse(user, 100) + playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE) + qdel(I) + qdel(src) + +/obj/item/nuke_core/supermatter_sliver/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) + if(!isliving(hit_atom)) + return ..() + var/mob/living/victim = hit_atom + if(victim.incorporeal_move || victim.status_flags & GODMODE) //try to keep this in sync with supermatter's consume fail conditions + return ..() + if(throwingdatum?.thrower) + var/mob/user = throwingdatum.thrower + add_attack_logs(user, victim, "[victim] consumed by [src] thrown by [user] ") + message_admins("[src] has consumed [key_name_admin(victim)] [ADMIN_JMP(src)], thrown by [key_name_admin(user)].") + investigate_log("has consumed [key_name(victim)], thrown by [key_name(user)]", "supermatter") + else + message_admins("[src] has consumed [key_name_admin(victim)] [ADMIN_JMP(src)] via throw impact.") + investigate_log("has consumed [key_name(victim)] via throw impact.", "supermatter") + victim.visible_message("As [victim] is hit by [src], both flash into dust and silence fills the room...", + "You're hit by [src] and everything suddenly goes silent.\n[src] flashes into dust, and soon as you can register this, you do as well.", + "Everything suddenly goes silent.") + victim.dust() + radiation_pulse(src, 500, 2) + playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE) + qdel(src) + +/obj/item/nuke_core/supermatter_sliver/pickup(mob/living/user) + ..() + if(!isliving(user) || user.status_flags & GODMODE) //try to keep this in sync with supermatter's consume fail conditions + return FALSE + user.visible_message("[user] reaches out and tries to pick up [src]. [user.p_their()] body starts to glow and bursts into flames before flashing into dust!", + "You reach for [src] with your hands. That was dumb.", + "Everything suddenly goes silent.") + radiation_pulse(user, 500, 2) + playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE) + user.dust() + +/obj/item/nuke_core_container/supermatter + name = "supermatter bin" + desc = "A tiny receptacle that releases an inert hyper-noblium mix upon sealing, allowing a sliver of a supermatter crystal to be safely stored." + var/obj/item/nuke_core/supermatter_sliver/sliver + +/obj/item/nuke_core_container/supermatter/Destroy() + QDEL_NULL(sliver) + return ..() + +/obj/item/nuke_core_container/supermatter/load(obj/item/retractor/supermatter/I, mob/user) + if(!istype(I) || !I.sliver) + return + I.sliver.forceMove(src) + sliver = I.sliver + I.sliver = null + I.icon_state = "supermatter_tongs" + I.item_state = "supermatter_tongs" + icon_state = "supermatter_container_loaded" + to_chat(user, "Container is sealing...") + addtimer(CALLBACK(src, .proc/seal), 10 SECONDS) + +/obj/item/nuke_core_container/supermatter/seal() + if(!QDELETED(sliver)) + STOP_PROCESSING(SSobj, sliver) + icon_state = "supermatter_container_sealed" + playsound(src, 'sound/items/deconstruct.ogg', 60, TRUE) + if(ismob(loc)) + to_chat(loc, "[src] is permanently sealed, [sliver] is safely contained.") + +/obj/item/nuke_core_container/supermatter/attackby(obj/item/retractor/supermatter/tongs, mob/user) + if(istype(tongs)) + //try to load shard into core + load(tongs, user) + else + return ..() + +/obj/item/scalpel/supermatter + name = "supermatter scalpel" + desc = "A scalpel with a fragile tip of condensed hyper-noblium gas, searingly cold to the touch, that can safely shave a sliver off a supermatter crystal." + icon = 'icons/obj/nuke_tools.dmi' + icon_state = "supermatter_scalpel" + toolspeed = 0.5 + damtype = BURN + usesound = 'sound/weapons/bladeslice.ogg' + var/uses_left + +/obj/item/scalpel/supermatter/Initialize() + . = ..() + uses_left = rand(2, 4) + +/obj/item/retractor/supermatter + name = "supermatter extraction tongs" + desc = "A pair of tongs made from condensed hyper-noblium gas, searingly cold to the touch, that can safely grip a supermatter sliver." + icon = 'icons/obj/nuke_tools.dmi' + icon_state = "supermatter_tongs" + lefthand_file = 'icons/mob/inhands/items_lefthand.dmi' + righthand_file = 'icons/mob/inhands/items_righthand.dmi' + item_state = "supermatter_tongs" + toolspeed = 0.75 + damtype = BURN + var/obj/item/nuke_core/supermatter_sliver/sliver + +/obj/item/retractor/supermatter/Destroy() + QDEL_NULL(sliver) + return ..() + +/obj/item/retractor/supermatter/afterattack(atom/O, mob/user, proximity) + . = ..() + if(!sliver) + return + if(proximity && ismovable(O) && O != sliver) + Consume(O, user) + +/obj/item/retractor/supermatter/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum) // no instakill supermatter javelins + if(sliver) + sliver.forceMove(loc) + visible_message("[sliver] falls out of [src] as it hits the ground.") + sliver = null + icon_state = "supermatter_tongs" + item_state = "supermatter_tongs" + return ..() + +/obj/item/retractor/supermatter/proc/Consume(atom/movable/AM, mob/living/user) + if(ismob(AM)) + if(!isliving(AM)) + return + var/mob/living/victim = AM + if(victim.incorporeal_move || victim.status_flags & GODMODE) //try to keep this in sync with supermatter's consume fail conditions + return + victim.dust() + message_admins("[src] has consumed [key_name_admin(victim)] [ADMIN_JMP(src)].") + investigate_log("has irradiated [key_name(victim)].", "supermatter") + else if(istype(AM, /obj/singularity)) + return + else + investigate_log("has consumed [AM].", "supermatter") + qdel(AM) + + if(user) + add_attack_logs(user, AM, "[AM] and [user] consumed by melee attack with [src] by [user]") + user.visible_message("As [user] touches [AM] with [src], both flash into dust and silence fills the room...", + "You touch [AM] with [src], and everything suddenly goes silent.\n[AM] and [sliver] flash into dust, and soon as you can register this, you do as well.", + "Everything suddenly goes silent.") + user.dust() + radiation_pulse(src, 500, 2) + playsound(src, 'sound/effects/supermatter.ogg', 50, TRUE) + QDEL_NULL(sliver) diff --git a/code/game/objects/items/tools/screwdriver.dm b/code/game/objects/items/tools/screwdriver.dm index 374b8ad66ca..c6b4aecd4f2 100644 --- a/code/game/objects/items/tools/screwdriver.dm +++ b/code/game/objects/items/tools/screwdriver.dm @@ -27,6 +27,7 @@ desc = "A screwdriver with an ultra thin tip." icon_state = "screwdriver_nuke" toolspeed = 0.5 + random_color = FALSE /obj/item/screwdriver/suicide_act(mob/user) user.visible_message("[user] is stabbing [src] into [user.p_their()] [pick("temple", "heart")]! It looks like [user.p_theyre()] trying to commit suicide!") diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 2747be43612..7f7bd427845 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -309,3 +309,24 @@ To apply, hold the injector a short distance away from the outer thigh before ap new /obj/item/reagent_containers/syringe/capulettium_plus(src) new /obj/item/reagent_containers/syringe/sarin(src) new /obj/item/reagent_containers/syringe/pancuronium(src) + +/obj/item/storage/box/syndie_kit/nuke + name = "box" //Bit of stealth, since you spawn with it + desc = "It's just an ordinary box." + icon_state = "box" + +/obj/item/storage/box/syndie_kit/nuke/populate_contents() + new /obj/item/screwdriver/nuke(src) + new /obj/item/nuke_core_container(src) + new /obj/item/paper/guides/antag/nuke_instructions(src) + +/obj/item/storage/box/syndie_kit/supermatter + name = "box" + desc = "It's just an ordinary box." + icon_state = "box" + +/obj/item/storage/box/syndie_kit/supermatter/populate_contents() + new /obj/item/scalpel/supermatter(src) + new /obj/item/retractor/supermatter(src) + new /obj/item/nuke_core_container/supermatter(src) + new /obj/item/paper/guides/antag/supermatter_sliver(src) diff --git a/code/modules/power/supermatter/supermatter.dm b/code/modules/power/supermatter/supermatter.dm index 11dc0f656ad..996817666ca 100644 --- a/code/modules/power/supermatter/supermatter.dm +++ b/code/modules/power/supermatter/supermatter.dm @@ -730,7 +730,20 @@ return if(moveable && default_unfasten_wrench(user, I, time = 20)) return - if(user.drop_item()) + if(istype(I, /obj/item/scalpel/supermatter)) + var/obj/item/scalpel/supermatter/scalpel = I + to_chat(user, "You carefully begin to scrape [src] with [I]...") + if(I.use_tool(src, user, 10 SECONDS, volume = 100)) + if(scalpel.uses_left) + to_chat(user, "You extract a sliver from [src], and it begins to react violently!") + new /obj/item/nuke_core/supermatter_sliver(drop_location()) + matter_power += 800 + scalpel.uses_left-- + if(!scalpel.uses_left) + to_chat(user, "A tiny piece of [I] falls off, rendering it useless!") + else + to_chat(user, "You fail to extract a sliver from [src]! [I] isn't sharp enough anymore.") + else if(user.drop_item()) user.visible_message("As [user] touches [src] with \a [I], silence fills the room...",\ "You touch [src] with [I], and everything suddenly goes silent.\n[I] flashes into dust as you flinch away from [src].",\ "Everything suddenly goes silent.") diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index aa632b9dad9..78506ad1890 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index 3e2a1ea5e2c..7e574384d62 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/obj/nuke_tools.dmi b/icons/obj/nuke_tools.dmi new file mode 100644 index 00000000000..1e06f1f89ea Binary files /dev/null and b/icons/obj/nuke_tools.dmi differ diff --git a/paradise.dme b/paradise.dme index f3ccd51b0b2..11176b1befe 100644 --- a/paradise.dme +++ b/paradise.dme @@ -853,6 +853,7 @@ #include "code\game\objects\items\mixing_bowl.dm" #include "code\game\objects\items\random_items.dm" #include "code\game\objects\items\shooting_range.dm" +#include "code\game\objects\items\theft_items.dm" #include "code\game\objects\items\toys.dm" #include "code\game\objects\items\trash.dm" #include "code\game\objects\items\devices\aicard.dm"