diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index e453d748428..5e7fb5d0bd3 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -42,4 +42,4 @@ var/global/list/global_radios = list() //list of all radios, across all z-lev
var/global/list/meteor_list = list() //list of all meteors
var/global/list/poi_list = list() //list of points of interest for observe/follow
-
+var/global/list/active_jammers = list() // List of active radio jammers
diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index e969751e1dd..51afe833ea3 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -199,6 +199,11 @@
Topic(src, list("src" = UID(), "command"="lights", "activate" = "0"), 1)
return
+/obj/machinery/ai_slipper/AICtrlClick() //Turns liquid dispenser on or off
+ ToggleOn()
+
+/obj/machinery/ai_slipper/AIAltClick() //Dispenses liquid if on
+ Activate()
//
// Override AdjacentQuick for AltClicking
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index a15176af87c..a8de6127c41 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -169,6 +169,12 @@
/obj/machinery/turretid/BorgAltClick() //turret lethal on/off. Forwards to AI code.
AIAltClick()
+/obj/machinery/ai_slipper/BorgCtrlClick() //Turns liquid dispenser on or off
+ ToggleOn()
+
+/obj/machinery/ai_slipper/BorgAltClick() //Dispenses liquid if on
+ Activate()
+
/*
As with AI, these are not used in click code,
because the code for robots is specific, not generic.
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 260df783bf9..d184f765eac 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -108,11 +108,12 @@
icon_state = "internal0"
else
var/no_mask = FALSE
- if(!C.wear_mask || !(C.wear_mask.flags & AIRTIGHT))
- if(ishuman(C))
- var/mob/living/carbon/human/H = C
- if(!H.head || !(H.head.flags & AIRTIGHT))
- no_mask = TRUE
+ if(!C.get_organ_slot("breathing_tube"))
+ if(!C.wear_mask || !(C.wear_mask.flags & AIRTIGHT))
+ if(ishuman(C))
+ var/mob/living/carbon/human/H = C
+ if(!H.head || !(H.head.flags & AIRTIGHT))
+ no_mask = TRUE
if(no_mask)
to_chat(C, "You are not wearing a suitable mask or helmet.")
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 5475cd7d57e..14732318aab 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -332,7 +332,7 @@ var/list/uplink_items = list()
reference = "TPB"
item = /obj/item/weapon/reagent_containers/glass/bottle/traitor
cost = 2
- job = list("Research Director", "Chief Medical Officer", "Medical Doctor", "Psychiatrist", "Paramedic", "Virologist", "Bartender", "Chef")
+ job = list("Research Director", "Chief Medical Officer", "Medical Doctor", "Psychiatrist", "Chemist", "Paramedic", "Virologist", "Bartender", "Chef")
// Paper contact poison pen
@@ -1124,6 +1124,13 @@ var/list/uplink_items = list()
cost = 1
surplus = 0
+/datum/uplink_item/device_tools/jammer
+ name = "Radio Jammer"
+ desc = "This device will disrupt any nearby outgoing radio communication when activated."
+ reference = "RJ"
+ item = /obj/item/device/jammer
+ cost = 5
+
/datum/uplink_item/device_tools/teleporter
name = "Teleporter Circuit Board"
desc = "A printed circuit board that completes the teleporter onboard the mothership. Advise you test fire the teleporter before entering it, as malfunctions can occur."
diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm
index d1fe6217058..616429b8cd8 100644
--- a/code/datums/wires/syndicatebomb.dm
+++ b/code/datums/wires/syndicatebomb.dm
@@ -1,5 +1,5 @@
/datum/wires/syndicatebomb
- random = 1
+ random = TRUE
holder_type = /obj/machinery/syndicatebomb
wire_count = 5
@@ -13,83 +13,90 @@ var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if
switch(index)
if(WIRE_BOOM)
return "Explode"
-
+
if(WIRE_UNBOLT)
return "Unbolt"
-
+
if(WIRE_DELAY)
return "Delay"
-
+
if(WIRE_PROCEED)
return "Proceed"
-
+
if(WIRE_ACTIVATE)
return "Activate"
/datum/wires/syndicatebomb/CanUse(mob/living/L)
var/obj/machinery/syndicatebomb/P = holder
if(P.open_panel)
- return 1
- return 0
+ return TRUE
+ return FALSE
/datum/wires/syndicatebomb/UpdatePulsed(index)
- var/obj/machinery/syndicatebomb/P = holder
+ var/obj/machinery/syndicatebomb/B = holder
switch(index)
if(WIRE_BOOM)
- if(P.active)
- P.loc.visible_message("[bicon(holder)] An alarm sounds! It's go-")
- P.timer = 0
+ if(B.active)
+ holder.visible_message("[bicon(B)] An alarm sounds! It's go-")
+ B.explode_now = TRUE
if(WIRE_UNBOLT)
- P.loc.visible_message("[bicon(holder)] The bolts spin in place for a moment.")
+ holder.visible_message("[bicon(holder)] The bolts spin in place for a moment.")
if(WIRE_DELAY)
- playsound(P.loc, 'sound/machines/chime.ogg', 30, 1)
- P.loc.visible_message("[bicon(holder)] The bomb chirps.")
- P.timer += 10
- if(WIRE_PROCEED)
- playsound(P.loc, 'sound/machines/buzz-sigh.ogg', 30, 1)
- P.loc.visible_message("[bicon(holder)] The bomb buzzes ominously!")
- if(P.timer >= 61) //Long fuse bombs can suddenly become more dangerous if you tinker with them
- P.timer = 60
- if(P.timer >= 21)
- P.timer -= 10
- else if(P.timer >= 11) //both to prevent negative timers and to have a little mercy
- P.timer = 10
- if(WIRE_ACTIVATE)
- if(!P.active && !P.defused)
- playsound(P.loc, 'sound/machines/click.ogg', 30, 1)
- P.loc.visible_message("[bicon(holder)] You hear the bomb start ticking!")
- P.active = 1
- P.icon_state = "[initial(P.icon_state)]-active[P.open_panel ? "-wires" : ""]"
+ if(B.delayedbig)
+ holder.visible_message("[bicon(B)] The bomb has already been delayed.")
else
- P.loc.visible_message("[bicon(holder)] The bomb seems to hesitate for a moment.")
- P.timer += 5
+ holder.visible_message("[bicon(B)] The bomb chirps.")
+ playsound(B, 'sound/machines/chime.ogg', 30, 1)
+ B.detonation_timer += 300
+ B.delayedbig = TRUE
+ if(WIRE_PROCEED)
+ holder.visible_message("[bicon(B)] The bomb buzzes ominously!")
+ playsound(B, 'sound/machines/buzz-sigh.ogg', 30, 1)
+ var/seconds = B.seconds_remaining()
+ if(seconds >= 61) // Long fuse bombs can suddenly become more dangerous if you tinker with them.
+ B.detonation_timer = world.time + 600
+ else if(seconds >= 21)
+ B.detonation_timer -= 100
+ else if(seconds >= 11) // Both to prevent negative timers and to have a little mercy.
+ B.detonation_timer = world.time + 100
+ if(WIRE_ACTIVATE)
+ if(!B.active && !B.defused)
+ holder.visible_message("[bicon(B)] You hear the bomb start ticking!")
+ B.activate()
+ B.update_icon()
+ else if(B.delayedlittle)
+ holder.visible_message("[bicon(B)] Nothing happens.")
+ else
+ holder.visible_message("[bicon(B)] The bomb seems to hesitate for a moment.")
+ B.detonation_timer += 100
+ B.delayedlittle = TRUE
..()
/datum/wires/syndicatebomb/UpdateCut(index, mended)
- var/obj/machinery/syndicatebomb/P = holder
+ var/obj/machinery/syndicatebomb/B = holder
switch(index)
if(WIRE_EXPLODE)
- if(!mended)
- if(P.active)
- P.loc.visible_message("[bicon(holder)] An alarm sounds! It's go-")
- P.timer = 0
- else
- P.defused = 1
+ if(mended)
+ B.defused = FALSE // Cutting and mending all the wires of an inactive bomb will thus cure any sabotage.
else
- P.defused = 0 //cutting and mending all the wires of an inactive bomb will thus cure any sabotage
+ if(B.active)
+ holder.visible_message("[bicon(B)] An alarm sounds! It's go-")
+ B.explode_now = TRUE
+ else
+ B.defused = TRUE
if(WIRE_UNBOLT)
- if(!mended && P.anchored)
- playsound(P.loc, 'sound/effects/stealthoff.ogg', 30, 1)
- P.loc.visible_message("[bicon(holder)] The bolts lift out of the ground!")
- P.anchored = 0
+ if(!mended && B.anchored)
+ holder.visible_message("[bicon(B)] The bolts lift out of the ground!")
+ playsound(B, 'sound/effects/stealthoff.ogg', 30, 1)
+ B.anchored = FALSE
if(WIRE_PROCEED)
- if(!mended && P.active)
- P.loc.visible_message("[bicon(holder)] An alarm sounds! It's go-")
- P.timer = 0
+ if(!mended && B.active)
+ holder.visible_message("[bicon(B)] An alarm sounds! It's go-")
+ B.explode_now = TRUE
if(WIRE_ACTIVATE)
- if(!mended && P.active)
- P.loc.visible_message("[bicon(holder)] The timer stops! The bomb has been defused!")
- P.icon_state = "[initial(P.icon_state)]-inactive[P.open_panel ? "-wires" : ""]"
- P.active = 0
- P.defused = 1
+ if(!mended && B.active)
+ holder.visible_message("[bicon(B)] The timer stops! The bomb has been defused!")
+ B.active = FALSE
+ B.defused = TRUE
+ B.update_icon()
..()
\ No newline at end of file
diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm
index 2a6aa2b3a39..5d6b9da47bc 100644
--- a/code/game/data_huds.dm
+++ b/code/game/data_huds.dm
@@ -190,7 +190,7 @@
/mob/living/carbon/human/proc/sec_hud_set_security_status()
var/image/holder = hud_list[WANTED_HUD]
- var/perpname = get_face_name(get_id_name(""))
+ var/perpname = get_visible_name(TRUE) //gets the name of the perp, works if they have an id or if their face is uncovered
if(!ticker) return //wait till the game starts or the monkeys runtime....
if(perpname)
var/datum/data/record/R = find_record("name", perpname, data_core.security)
diff --git a/code/game/jobs/job/engineering.dm b/code/game/jobs/job/engineering.dm
index 50c8a06777b..ce410dea69e 100644
--- a/code/game/jobs/job/engineering.dm
+++ b/code/game/jobs/job/engineering.dm
@@ -112,6 +112,9 @@
id = /obj/item/weapon/card/id/engineering
pda = /obj/item/device/pda/atmos
+ backpack = /obj/item/weapon/storage/backpack/industrial
+ satchel = /obj/item/weapon/storage/backpack/satchel_eng
+ dufflebag = /obj/item/weapon/storage/backpack/duffel/engineering
box = /obj/item/weapon/storage/box/engineer
/datum/job/mechanic
diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm
index 4d059043329..63aeee28b2f 100644
--- a/code/game/machinery/ai_slipper.dm
+++ b/code/game/machinery/ai_slipper.dm
@@ -5,12 +5,12 @@
layer = 3
anchored = 1.0
var/uses = 20
- var/disabled = 1
+ var/disabled = TRUE
var/lethal = 0
- var/locked = 1
+ var/locked = TRUE
var/cooldown_time = 0
var/cooldown_timeleft = 0
- var/cooldown_on = 0
+ var/cooldown_on = FALSE
req_access = list(access_ai_upload)
/obj/machinery/ai_slipper/power_change()
@@ -22,6 +22,7 @@
else
icon_state = "motion0"
stat |= NOPOWER
+ disabled = TRUE
/obj/machinery/ai_slipper/proc/setState(var/enabled, var/uses)
disabled = disabled
@@ -49,6 +50,24 @@
return
return
+/obj/machinery/ai_slipper/proc/ToggleOn()
+ if(stat & (NOPOWER|BROKEN))
+ return
+ disabled = !disabled
+ icon_state = disabled? "motion0":"motion3"
+
+/obj/machinery/ai_slipper/proc/Activate()
+ if(stat & (NOPOWER|BROKEN))
+ return
+ if(cooldown_on || disabled)
+ return
+ else
+ new /obj/structure/foam(loc)
+ uses--
+ cooldown_on = TRUE
+ cooldown_time = world.timeofday + 100
+ slip_process()
+
/obj/machinery/ai_slipper/attack_ai(mob/user)
return attack_hand(user)
@@ -87,18 +106,10 @@
return 1
if(href_list["toggleOn"])
- disabled = !disabled
- icon_state = disabled? "motion0":"motion3"
+ ToggleOn()
+
if(href_list["toggleUse"])
- if(cooldown_on || disabled)
- return
- else
- new /obj/structure/foam(loc)
- uses--
- cooldown_on = 1
- cooldown_time = world.timeofday + 100
- slip_process()
- return
+ Activate()
attack_hand(usr)
@@ -115,5 +126,5 @@
if(uses <= 0)
return
if(uses >= 0)
- cooldown_on = 0
+ cooldown_on = FALSE
power_change()
\ No newline at end of file
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index 10f6fc1c8c5..153fc50bf91 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -1,3 +1,6 @@
+#define BUTTON_COOLDOWN 60 // cant delay the bomb forever
+#define BUTTON_DELAY 50 //five seconds
+
/obj/machinery/syndicatebomb
icon = 'icons/obj/assemblies.dmi'
name = "syndicate bomb"
@@ -6,71 +9,119 @@
anchored = 0
density = 0
- layer = MOB_LAYER - 0.1 //so people can't hide it and it's REALLY OBVIOUS
+ layer = BELOW_MOB_LAYER //so people can't hide it and it's REALLY OBVIOUS
unacidable = 1
var/datum/wires/syndicatebomb/wires = null
- var/timer = 120
- var/open_panel = 0 //are the wires exposed?
- var/active = 0 //is the bomb counting down?
- var/defused = 0 //is the bomb capable of exploding?
- var/obj/item/weapon/bombcore/payload = /obj/item/weapon/bombcore/
+ var/minimum_timer = 90
+ var/timer_set = 90
+ var/maximum_timer = 60000
+
+ var/can_unanchor = TRUE
+
+ var/open_panel = FALSE //are the wires exposed?
+ var/active = FALSE //is the bomb counting down?
+ var/defused = FALSE //is the bomb capable of exploding?
+ var/obj/item/weapon/bombcore/payload = /obj/item/weapon/bombcore
var/beepsound = 'sound/items/timer.ogg'
+ var/delayedbig = FALSE //delay wire pulsed?
+ var/delayedlittle = FALSE //activation wire pulsed?
+ var/obj/effect/countdown/syndicatebomb/countdown
+
+ var/next_beep
+ var/detonation_timer
+ var/explode_now = FALSE
+
+/obj/machinery/syndicatebomb/proc/try_detonate(ignore_active = FALSE)
+ . = (payload in src) && (active || ignore_active) && !defused
+ if(.)
+ payload.detonate()
/obj/machinery/syndicatebomb/process()
- if(active && !defused && (timer > 0)) //Tick Tock
- var/volume = (timer <= 20 ? 40 : 10) // Tick louder when the bomb is closer to being detonated.
- playsound(loc, beepsound, volume, 0)
- timer = max(timer - 2,0) // 2 seconds per process()
- if(active && !defused && (timer <= 0)) //Boom
- active = 0
- timer = 120
- update_icon()
- if(payload in src)
- payload.detonate()
+ if(!active)
+ fast_processing -= src
+ detonation_timer = null
+ next_beep = null
+ countdown.stop()
return
- if(!active || defused) //Counter terrorists win
+
+ if(!isnull(next_beep) && (next_beep <= world.time))
+ var/volume
+ switch(seconds_remaining())
+ if(0 to 5)
+ volume = 50
+ if(5 to 10)
+ volume = 40
+ if(10 to 15)
+ volume = 30
+ if(15 to 20)
+ volume = 20
+ if(20 to 25)
+ volume = 10
+ else
+ volume = 5
+ playsound(loc, beepsound, volume, 0)
+ next_beep = world.time + 10
+
+ if(active && !defused && ((detonation_timer <= world.time) || explode_now))
+ active = FALSE
+ timer_set = initial(timer_set)
+ update_icon()
+ try_detonate(TRUE)
+ //Counter terrorists win
+ else if(!active || defused)
if(defused && payload in src)
payload.defuse()
- return
+ countdown.stop()
+ fast_processing -= src
/obj/machinery/syndicatebomb/New()
wires = new(src)
- payload = new payload(src)
+ if(payload)
+ payload = new payload(src)
update_icon()
+ countdown = new(src)
..()
/obj/machinery/syndicatebomb/Destroy()
QDEL_NULL(wires)
+ QDEL_NULL(countdown)
+ fast_processing -= src
return ..()
/obj/machinery/syndicatebomb/examine(mob/user)
..(user)
- to_chat(user, "A digital display on it reads \"[timer]\".")
+ to_chat(user, "A digital display on it reads \"[seconds_remaining()]\".")
/obj/machinery/syndicatebomb/update_icon()
icon_state = "[initial(icon_state)][active ? "-active" : "-inactive"][open_panel ? "-wires" : ""]"
-/obj/machinery/syndicatebomb/attackby(var/obj/item/I, var/mob/user, params)
- if(istype(I, /obj/item/weapon/wrench))
+/obj/machinery/syndicatebomb/proc/seconds_remaining()
+ if(active)
+ . = max(0, round((detonation_timer - world.time) / 10))
+ else
+ . = timer_set
+
+/obj/machinery/syndicatebomb/attackby(obj/item/I, mob/user, params)
+ if(iswrench(I) && can_unanchor)
if(!anchored)
- if(!isturf(src.loc) || istype(src.loc, /turf/space))
- to_chat(user, "The bomb must be placed on solid ground to attach it")
+ if(!isturf(loc) || isspaceturf(loc))
+ to_chat(user, "The bomb must be placed on solid ground to attach it.")
else
- to_chat(user, "You firmly wrench the bomb to the floor")
+ to_chat(user, "You firmly wrench the bomb to the floor.")
playsound(loc, I.usesound, 50, 1)
anchored = 1
if(active)
- to_chat(user, "The bolts lock in place")
+ to_chat(user, "The bolts lock in place.")
else
if(!active)
- to_chat(user, "You wrench the bomb from the floor")
+ to_chat(user, "You wrench the bomb from the floor.")
playsound(loc, I.usesound, 50, 1)
anchored = 0
else
to_chat(user, "The bolts are locked down!")
- else if(istype(I, /obj/item/weapon/screwdriver))
+ else if(isscrewdriver(I))
open_panel = !open_panel
update_icon()
to_chat(user, "You [open_panel ? "open" : "close"] the wire panel.")
@@ -79,28 +130,47 @@
if(open_panel)
wires.Interact(user)
- else if(istype(I, /obj/item/weapon/crowbar))
- if(open_panel && isWireCut(WIRE_BOOM) && isWireCut(WIRE_UNBOLT) && isWireCut(WIRE_DELAY) && isWireCut(WIRE_PROCEED) && isWireCut(WIRE_ACTIVATE))
+ else if(iscrowbar(I))
+ if(open_panel && wires.IsAllCut())
if(payload)
to_chat(user, "You carefully pry out [payload].")
payload.loc = user.loc
payload = null
else
- to_chat(user, "There isn't anything in here to remove!")
+ to_chat(user, "There isn't anything in here to remove!")
else if(open_panel)
- to_chat(user, "The wires connecting the shell to the explosives are holding it down!")
+ to_chat(user, "The wires connecting the shell to the explosives are holding it down!")
else
- to_chat(user, "The cover is screwed on, it won't pry off!")
+ to_chat(user, "The cover is screwed on, it won't pry off!")
else if(istype(I, /obj/item/weapon/bombcore))
if(!payload)
+ if(!user.drop_item())
+ return
payload = I
to_chat(user, "You place [payload] into [src].")
- user.drop_item()
- payload.loc = src
+ payload.forceMove(src)
else
to_chat(user, "[payload] is already loaded into [src], you'll have to remove it first.")
+ else if(iswelder(I))
+ if(payload || !wires.IsAllCut() || !open_panel)
+ return
+ var/obj/item/weapon/weldingtool/WT = I
+ if(!WT.isOn())
+ return
+ if(WT.get_fuel() < 5) //uses up 5 fuel.
+ to_chat(user, "You need more fuel to complete this task!")
+ return
+
+ playsound(loc, WT.usesound, 50, 1)
+ to_chat(user, "You start to cut the [src] apart...")
+ if(do_after(user, 20*I.toolspeed, target = src))
+ if(!WT.isOn() || !WT.remove_fuel(5, user))
+ return
+ to_chat(user, "You cut the [src] apart.")
+ new /obj/item/stack/sheet/plasteel(loc, 5)
+ qdel(src)
else
- ..()
+ return ..()
/obj/machinery/syndicatebomb/attack_ghost(mob/user)
interact(user)
@@ -133,21 +203,27 @@
return FALSE
return TRUE
+/obj/machinery/syndicatebomb/proc/activate()
+ active = TRUE
+ fast_processing += src
+ countdown.start()
+ next_beep = world.time + 10
+ detonation_timer = world.time + (timer_set * 10)
+ playsound(loc, 'sound/machines/click.ogg', 30, 1)
+
/obj/machinery/syndicatebomb/proc/settings(mob/user)
- var/newtime = input(user, "Please set the timer.", "Timer", "[timer]") as num
- newtime = Clamp(newtime, 120, 60000)
+ var/new_timer = input(user, "Please set the timer.", "Timer", "[timer_set]") as num
if(can_interact(user)) //No running off and setting bombs from across the station
- timer = newtime
- loc.visible_message("[bicon(src)] timer set for [timer] seconds.")
+ timer_set = Clamp(new_timer, minimum_timer, maximum_timer)
+ loc.visible_message("[bicon(src)] timer set for [timer_set] seconds.")
if(alert(user,"Would you like to start the countdown now?",,"Yes","No") == "Yes" && can_interact(user))
if(defused || active)
if(defused)
loc.visible_message("[bicon(src)] Device error: User intervention required.")
return
else
- loc.visible_message("[bicon(src)] [timer] seconds until detonation, please clear the area.")
- playsound(loc, 'sound/machines/click.ogg', 30, 1)
- active = 1
+ loc.visible_message("[bicon(src)] [timer_set] seconds until detonation, please clear the area.")
+ activate()
update_icon()
add_fingerprint(user)
@@ -167,12 +243,12 @@
name = "training bomb"
icon_state = "training-bomb"
desc = "A salvaged syndicate device gutted of its explosives to be used as a training aid for aspiring bomb defusers."
- payload = /obj/item/weapon/bombcore/training/
+ payload = /obj/item/weapon/bombcore/training
/obj/machinery/syndicatebomb/badmin
name = "generic summoning badmin bomb"
desc = "Oh god what is in this thing?"
- payload = /obj/item/weapon/bombcore/badmin/summon/
+ payload = /obj/item/weapon/bombcore/badmin/summon
/obj/machinery/syndicatebomb/badmin/clown
name = "clown bomb"
@@ -181,8 +257,23 @@
payload = /obj/item/weapon/bombcore/badmin/summon/clown
beepsound = 'sound/items/bikehorn.ogg'
-/obj/machinery/syndicatebomb/badmin/varplosion
- payload = /obj/item/weapon/bombcore/badmin/explosion/
+/obj/machinery/syndicatebomb/empty
+ name = "bomb"
+ icon_state = "base-bomb"
+ desc = "An ominous looking device designed to detonate an explosive payload. Can be bolted down using a wrench."
+ payload = null
+ open_panel = TRUE
+ timer_set = 120
+
+/obj/machinery/syndicatebomb/empty/New()
+ ..()
+ wires.CutAll()
+
+/obj/machinery/syndicatebomb/self_destruct
+ name = "self destruct device"
+ desc = "Do not taunt. Warranty invalid if exposed to high temperature. Not suitable for agents under 3 years of age."
+ payload = /obj/item/weapon/bombcore/large
+ can_unanchor = FALSE
///Bomb Cores///
@@ -196,17 +287,26 @@
origin_tech = "syndicate=5;combat=6"
burn_state = FLAMMABLE //Burnable (but the casing isn't)
var/adminlog = null
+ var/range_heavy = 3
+ var/range_medium = 9
+ var/range_light = 17
+ var/range_flame = 17
/obj/item/weapon/bombcore/ex_act(severity) //Little boom can chain a big boom
- src.detonate()
+ detonate()
+
+
+/obj/item/weapon/bombcore/burn()
+ detonate()
+ ..()
/obj/item/weapon/bombcore/proc/detonate()
if(adminlog)
message_admins(adminlog)
log_game(adminlog)
- explosion(get_turf(src),3,9,17, flame_range = 17)
- if(src.loc && istype(src.loc,/obj/machinery/syndicatebomb/))
- qdel(src.loc)
+ explosion(get_turf(src), range_heavy, range_medium, range_light, flame_range = range_flame)
+ if(loc && istype(loc, /obj/machinery/syndicatebomb))
+ qdel(loc)
qdel(src)
/obj/item/weapon/bombcore/proc/defuse()
@@ -223,17 +323,20 @@
var/attempts = 0
/obj/item/weapon/bombcore/training/proc/reset()
- var/obj/machinery/syndicatebomb/holder = src.loc
+ var/obj/machinery/syndicatebomb/holder = loc
if(istype(holder))
if(holder.wires)
holder.wires.Shuffle()
holder.defused = 0
holder.open_panel = 0
+ holder.delayedbig = FALSE
+ holder.delayedlittle = FALSE
+ holder.explode_now = FALSE
holder.update_icon()
holder.updateDialog()
/obj/item/weapon/bombcore/training/detonate()
- var/obj/machinery/syndicatebomb/holder = src.loc
+ var/obj/machinery/syndicatebomb/holder = loc
if(istype(holder))
attempts++
holder.loc.visible_message("[bicon(holder)] Alert: Bomb has detonated. Your score is now [defusals] for [attempts]. Resetting wires...")
@@ -242,7 +345,7 @@
qdel(src)
/obj/item/weapon/bombcore/training/defuse()
- var/obj/machinery/syndicatebomb/holder = src.loc
+ var/obj/machinery/syndicatebomb/holder = loc
if(istype(holder))
attempts++
defusals++
@@ -257,11 +360,11 @@
origin_tech = null
/obj/item/weapon/bombcore/badmin/defuse() //because we wouldn't want them being harvested by players
- var/obj/machinery/syndicatebomb/B = src.loc
+ var/obj/machinery/syndicatebomb/B = loc
qdel(B)
qdel(src)
-/obj/item/weapon/bombcore/badmin/summon/
+/obj/item/weapon/bombcore/badmin/summon
var/summon_path = /obj/item/weapon/reagent_containers/food/snacks/cookie
var/amt_summon = 1
@@ -285,42 +388,165 @@
playsound(src.loc, 'sound/misc/sadtrombone.ogg', 50)
..()
-/obj/item/weapon/bombcore/badmin/explosion/
- var/HeavyExplosion = 2
- var/MediumExplosion = 5
- var/LightExplosion = 11
- var/Flames = 11
+/obj/item/weapon/bombcore/large
+ name = "large bomb payload"
+ range_heavy = 5
+ range_medium = 10
+ range_light = 20
+ range_flame = 20
-/obj/item/weapon/bombcore/badmin/explosion/detonate()
- explosion(get_turf(src),HeavyExplosion,MediumExplosion,LightExplosion, flame_range = Flames)
+/obj/item/weapon/bombcore/large/underwall
+ layer = ABOVE_OPEN_TURF_LAYER
/obj/item/weapon/bombcore/miniature
name = "small bomb core"
w_class = WEIGHT_CLASS_SMALL
+ range_heavy = 1
+ range_medium = 2
+ range_light = 4
+ range_flame = 2
-/obj/item/weapon/bombcore/miniature/detonate()
- explosion(src.loc,1,2,4,flame_range = 2) //Identical to a minibomb
+/obj/item/weapon/bombcore/chemical
+ name = "chemical payload"
+ desc = "An explosive payload designed to spread chemicals, dangerous or otherwise, across a large area. It is able to hold up to four chemical containers, and must be loaded before use."
+ origin_tech = "combat=4;materials=3"
+ icon_state = "chemcore"
+ var/list/beakers = list()
+ var/max_beakers = 1
+ var/spread_range = 5
+ var/temp_boost = 50
+ var/time_release = 0
+
+/obj/item/weapon/bombcore/chemical/detonate()
+
+ if(time_release > 0)
+ var/total_volume = 0
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ total_volume += RC.reagents.total_volume
+
+ if(total_volume < time_release) // If it's empty, the detonation is complete.
+ if(loc && istype(loc, /obj/machinery/syndicatebomb))
+ qdel(loc)
+ qdel(src)
+ return
+
+ var/fraction = time_release/total_volume
+ var/datum/reagents/reactants = new(time_release)
+ reactants.my_atom = src
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ RC.reagents.trans_to(reactants, RC.reagents.total_volume*fraction, 1, 1, 1)
+ chem_splash(get_turf(src), spread_range, list(reactants), temp_boost)
+
+ // Detonate it again in one second, until it's out of juice.
+ addtimer(src, "detonate", 10)
+
+ // If it's not a time release bomb, do normal explosion
+
+ var/list/reactants = list()
+
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ reactants += G.reagents
+
+ for(var/obj/item/slime_extract/S in beakers)
+ if(S.Uses)
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ G.reagents.trans_to(S, G.reagents.total_volume)
+
+ if(S && S.reagents && S.reagents.total_volume)
+ reactants += S.reagents
+
+ if(!chem_splash(get_turf(src), spread_range, reactants, temp_boost))
+ playsound(loc, 'sound/items/Screwdriver2.ogg', 50, 1)
+ return // The Explosion didn't do anything. No need to log, or disappear.
+
+ if(adminlog)
+ message_admins(adminlog)
+ log_game(adminlog)
+
+ playsound(loc, 'sound/effects/bamf.ogg', 75, 1, 5)
+
+ if(loc && istype(loc, /obj/machinery/syndicatebomb))
+ qdel(loc)
qdel(src)
+/obj/item/weapon/bombcore/chemical/attackby(obj/item/I, mob/user, params)
+ if(iscrowbar(I) && beakers.len > 0)
+ playsound(loc, I.usesound, 50, 1)
+ for (var/obj/item/B in beakers)
+ B.loc = get_turf(src)
+ beakers -= B
+ return
+ else if(istype(I, /obj/item/weapon/reagent_containers/glass/beaker) || istype(I, /obj/item/weapon/reagent_containers/glass/bottle))
+ if(beakers.len < max_beakers)
+ if(!user.drop_item())
+ return
+ beakers += I
+ to_chat(user, "You load [src] with [I].")
+ I.loc = src
+ else
+ to_chat(user, "The [I] wont fit! The [src] can only hold up to [max_beakers] containers.")
+ return
+ ..()
+
+/obj/item/weapon/bombcore/chemical/CheckParts(list/parts_list)
+ ..()
+ // Using different grenade casings, causes the payload to have different properties.
+ var/obj/item/weapon/stock_parts/matter_bin/MB = locate(/obj/item/weapon/stock_parts/matter_bin) in src
+ if(MB)
+ max_beakers += MB.rating // max beakers = 2-5.
+ qdel(MB)
+ for(var/obj/item/weapon/grenade/chem_grenade/G in src)
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/large))
+ var/obj/item/weapon/grenade/chem_grenade/large/LG = G
+ max_beakers += 1 // Adding two large grenades only allows for a maximum of 7 beakers.
+ spread_range += 2 // Extra range, reduced density.
+ temp_boost += 50 // maximum of +150K blast using only large beakers. Not enough to self ignite.
+ for(var/obj/item/slime_extract/S in LG.beakers) // And slime cores.
+ if(beakers.len < max_beakers)
+ beakers += S
+ S.loc = src
+ else
+ S.loc = get_turf(src)
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/cryo))
+ spread_range -= 1 // Reduced range, but increased density.
+ temp_boost -= 100 // minimum of -150K blast.
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/pyro))
+ temp_boost += 150 // maximum of +350K blast, which is enough to self ignite. Which means a self igniting bomb can't take advantage of other grenade casing properties. Sorry?
+
+ if(istype(G, /obj/item/weapon/grenade/chem_grenade/adv_release))
+ time_release += 50 // A typical bomb, using basic beakers, will explode over 2-4 seconds. Using two will make the reaction last for less time, but it will be more dangerous overall.
+
+ for(var/obj/item/weapon/reagent_containers/glass/B in G)
+ if(beakers.len < max_beakers)
+ beakers += B
+ B.loc = src
+ else
+ B.loc = get_turf(src)
+
+ qdel(G)
+
///Syndicate Detonator (aka the big red button)///
/obj/item/device/syndicatedetonator
name = "big red button"
- desc = "Nothing good can come of pressing a button this garish..."
+ desc = "Your standard issue bomb synchronizing button. Five second safety delay to prevent 'accidents'."
icon = 'icons/obj/assemblies.dmi'
icon_state = "bigred"
item_state = "electronic"
w_class = WEIGHT_CLASS_TINY
origin_tech = "syndicate=3"
- var/cooldown = 0
+ var/timer = 0
var/detonated = 0
var/existant = 0
-/obj/item/device/syndicatedetonator/attack_self(mob/user as mob)
- if(!cooldown)
+/obj/item/device/syndicatedetonator/attack_self(mob/user)
+ if(timer < world.time)
for(var/obj/machinery/syndicatebomb/B in machines)
if(B.active)
- B.timer = 0
+ B.detonation_timer = world.time + BUTTON_DELAY
detonated++
existant++
playsound(user, 'sound/machines/click.ogg', 20, 1)
@@ -334,5 +560,7 @@
log_game("[key_name(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] ([T.x],[T.y],[T.z])")
detonated = 0
existant = 0
- cooldown = 1
- spawn(30) cooldown = 0
+ timer = world.time + BUTTON_COOLDOWN
+
+#undef BUTTON_COOLDOWN
+#undef BUTTON_DELAY
\ No newline at end of file
diff --git a/code/game/objects/effects/mines.dm b/code/game/objects/effects/mines.dm
index 17029920dd3..d386fe07d0b 100644
--- a/code/game/objects/effects/mines.dm
+++ b/code/game/objects/effects/mines.dm
@@ -26,7 +26,7 @@
/obj/effect/mine/proc/triggermine(mob/living/victim)
if(triggered)
return
- visible_message("[victim] sets off \icon[src] [src]!")
+ visible_message("[victim] sets off [bicon(src)] [src]!")
var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
diff --git a/code/game/objects/items/devices/flash.dm b/code/game/objects/items/devices/flash.dm
index de82f0b8c34..1a1ed2b4c5e 100644
--- a/code/game/objects/items/devices/flash.dm
+++ b/code/game/objects/items/devices/flash.dm
@@ -201,4 +201,37 @@
icon_state = "memorizer"
item_state = "nullrod"
+/obj/item/device/flash/armimplant
+ name = "photon projector"
+ desc = "A high-powered photon projector implant normally used for lighting purposes, but also doubles as a flashbulb weapon. Self-repair protocals fix the flashbulb if it ever burns out."
+ var/flashcd = 20
+ var/overheat = 0
+ var/obj/item/organ/internal/cyberimp/arm/flash/I = null
+
+/obj/item/device/flash/armimplant/Destroy()
+ I = null
+ return ..()
+
+/obj/item/device/flash/armimplant/burn_out()
+ if(I && I.owner)
+ to_chat(I.owner, "Your photon projector implant overheats and deactivates!")
+ I.Retract()
+ overheat = FALSE
+ addtimer(src, "cooldown", flashcd * 2)
+
+/obj/item/device/flash/armimplant/try_use_flash(mob/user = null)
+ if(overheat)
+ if(I && I.owner)
+ to_chat(I.owner, "Your photon projector is running too hot to be used again so quickly!")
+ return FALSE
+ overheat = TRUE
+ addtimer(src, "cooldown", flashcd)
+ playsound(src.loc, 'sound/weapons/flash.ogg', 100, 1)
+ update_icon(1)
+ return TRUE
+
+/obj/item/device/flash/armimplant/proc/cooldown()
+ overheat = FALSE
+
+
/obj/item/device/flash/synthetic //just a regular flash now
diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm
index 3c9c0211663..3d1f1001b06 100644
--- a/code/game/objects/items/devices/radio/radio.dm
+++ b/code/game/objects/items/devices/radio/radio.dm
@@ -247,6 +247,13 @@ var/global/list/default_medbay_channels = list(
A.name = from
A.role = role
A.message = message
+ var/jammed = FALSE
+ for(var/obj/item/device/jammer/jammer in active_jammers)
+ if(get_dist(get_turf(src), get_turf(jammer)) < jammer.range)
+ jammed = TRUE
+ break
+ if(jammed)
+ message = Gibberish(message, 100)
Broadcast_Message(connection, A,
0, "*garbled automated announcement*", src,
message, from, "Automated Announcement", from, "synthesized voice",
@@ -332,6 +339,12 @@ var/global/list/default_medbay_channels = list(
var/datum/radio_frequency/connection = message_mode
var/turf/position = get_turf(src)
+ var/jammed = FALSE
+ for(var/obj/item/device/jammer/jammer in active_jammers)
+ if(get_dist(position, get_turf(jammer)) < jammer.range)
+ jammed = TRUE
+ break
+
//#### Tagging the signal with all appropriate identity values ####//
// ||-- The mob's name identity --||
@@ -345,6 +358,9 @@ var/global/list/default_medbay_channels = list(
var/jobname // the mob's "job"
+ if(jammed)
+ message = Gibberish(message, 100)
+
// --- Human: use their actual job ---
if(ishuman(M))
var/mob/living/carbon/human/H = M
diff --git a/code/game/objects/items/devices/traitordevices.dm b/code/game/objects/items/devices/traitordevices.dm
index 5f140f05d03..6b48dea1910 100644
--- a/code/game/objects/items/devices/traitordevices.dm
+++ b/code/game/objects/items/devices/traitordevices.dm
@@ -146,3 +146,22 @@ effective or pretty fucking useless.
attack_self(usr)
add_fingerprint(usr)
return
+
+/obj/item/device/jammer
+ name = "radio jammer"
+ desc = "Device used to disrupt nearby radio communication."
+ icon_state = "jammer"
+ var/active = FALSE
+ var/range = 12
+
+/obj/item/device/jammer/Destroy()
+ active_jammers -= src
+ return ..()
+
+/obj/item/device/jammer/attack_self(mob/user)
+ to_chat(user,"You [active ? "deactivate" : "activate"] the [src].")
+ active = !active
+ if(active)
+ active_jammers |= src
+ else
+ active_jammers -= src
\ No newline at end of file
diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm
index 67755655fe3..029cb8cd4a5 100644
--- a/code/game/objects/items/stacks/sheets/sheet_types.dm
+++ b/code/game/objects/items/stacks/sheets/sheet_types.dm
@@ -123,6 +123,7 @@ var/global/list/datum/stack_recipe/metal_recipes = list(
*/
var/global/list/datum/stack_recipe/plasteel_recipes = list(
new /datum/stack_recipe("AI core", /obj/structure/AIcore, 4, time = 50, one_per_turf = 1),
+ new /datum/stack_recipe("bomb assembly", /obj/machinery/syndicatebomb/empty, 10, time = 50),
new /datum/stack_recipe("Surgery Table", /obj/machinery/optable, 5, time = 50, one_per_turf = 1, on_floor = 1),
new /datum/stack_recipe("Metal crate", /obj/structure/closet/crate, 10, time = 50, one_per_turf = 1),
new /datum/stack_recipe("Mass Driver frame", /obj/machinery/mass_driver_frame, 3, time = 50, one_per_turf = 1)
diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm
index f21914a7c32..707eac2fbce 100644
--- a/code/game/objects/items/weapons/grenades/chem_grenade.dm
+++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm
@@ -19,6 +19,9 @@
var/obj/item/device/assembly_holder/nadeassembly = null
var/label = null
var/assemblyattacher
+ var/ignition_temp = 10 // The amount of heat added to the reagents when this grenade goes off.
+ var/threatscale = 1 // Used by advanced grenades to make them slightly more worthy.
+ var/no_splash = FALSE //If the grenade deletes even if it has no reagents to splash with. Used for slime core reactions.
/obj/item/weapon/grenade/chem_grenade/New()
create_reagents(1000)
@@ -99,6 +102,7 @@
log_game("[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])")
bombers += "[key_name(usr)] has primed a [name] for detonation at [A.name] ([bombturf.x],[bombturf.y],[bombturf.z])"
to_chat(user, "You prime the [name]! [det_time / 10] second\s!")
+ playsound(user.loc, 'sound/weapons/armbomb.ogg', 60, 1)
active = 1
update_icon()
if(iscarbon(user))
@@ -264,13 +268,18 @@
if(stage != READY)
return
- var/has_reagents = 0
+ var/list/datum/reagents/reactants = list()
for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- if(G.reagents.total_volume)
- has_reagents = 1
+ reactants += G.reagents
- if(!has_reagents)
- playsound(loc, usesound, 50, 1)
+ if(!chem_splash(get_turf(src), affected_area, reactants, ignition_temp, threatscale) && !no_splash)
+ playsound(loc, 'sound/items/Screwdriver2.ogg', 50, 1)
+ if(beakers.len)
+ for(var/obj/O in beakers)
+ O.forceMove(get_turf(src))
+ beakers = list()
+ stage = EMPTY
+ update_icon()
return
if(nadeassembly)
@@ -281,31 +290,9 @@
message_admins("grenade primed by an assembly, attached by [key_name_admin(M)](?) ([admin_jump_link(M)]) and last touched by [key_name_admin(last)](?) ([admin_jump_link(last)]) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP).")
log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
- playsound(loc, 'sound/effects/bamf.ogg', 50, 1)
-
update_mob()
- invisibility = INVISIBILITY_MAXIMUM //kaboom
- qdel(nadeassembly) // do this now to stop infrared beams
- var/end_temp = 0
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- G.reagents.trans_to(src, G.reagents.total_volume)
- end_temp += G.reagents.chem_temp
- reagents.chem_temp = end_temp
- if(reagents.total_volume) //The possible reactions didnt use up all reagents.
- var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread()
- steam.set_up(10, 0, get_turf(src))
- steam.attach(src)
- steam.start()
-
- for(var/atom/A in view(affected_area, loc))
- if(A == src)
- continue
- reagents.reaction(A, 1, 10)
-
-
- spawn(15) //Making sure all reagents can work
- qdel(src) //correctly before deleting the grenade.
+ qdel(src)
/obj/item/weapon/grenade/chem_grenade/proc/CreateDefaultTrigger(var/typekey)
if(ispath(typekey,/obj/item/device/assembly))
@@ -327,64 +314,37 @@
//Large chem grenades accept slime cores and use the appropriately.
/obj/item/weapon/grenade/chem_grenade/large
name = "large grenade casing"
- desc = "For oversized grenades; fits additional contents and affects a greater area."
+ desc = "A custom made large grenade. It affects a larger area."
icon_state = "large_grenade"
bomb_state = "largebomb"
allowed_containers = list(/obj/item/weapon/reagent_containers/glass,/obj/item/weapon/reagent_containers/food/condiment,
/obj/item/weapon/reagent_containers/food/drinks)
origin_tech = "combat=3;engineering=3"
- affected_area = 4
-
+ affected_area = 5
+ ignition_temp = 25 // Large grenades are slightly more effective at setting off heat-sensitive mixtures than smaller grenades.
+ threatscale = 1.1 // 10% more effective.
/obj/item/weapon/grenade/chem_grenade/large/prime()
if(stage != READY)
return
- var/has_reagents = 0
- var/obj/item/slime_extract/valid_core = null
+ for(var/obj/item/slime_extract/S in beakers)
+ if(S.Uses)
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ G.reagents.trans_to(S, G.reagents.total_volume)
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- if(!istype(G)) continue
- if(G.reagents.total_volume) has_reagents = 1
- for(var/obj/item/slime_extract/E in beakers)
- if(!istype(E)) continue
- if(E.Uses) valid_core = E
- if(E.reagents.total_volume) has_reagents = 1
+ //If there is still a core (sometimes it's used up)
+ //and there are reagents left, behave normally,
+ //otherwise drop it on the ground for timed reactions like gold.
- if(!has_reagents)
- playsound(loc, prime_sound, 50, 1)
- return
-
- playsound(loc, 'sound/effects/bamf.ogg', 50, 1)
-
- update_mob()
-
- if(valid_core)
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- G.reagents.trans_to(valid_core, G.reagents.total_volume)
-
- //If there is still a core (sometimes it's used up)
- //and there are reagents left, behave normally
-
- if(valid_core && valid_core.reagents && valid_core.reagents.total_volume)
- valid_core.reagents.trans_to(src,valid_core.reagents.total_volume)
- else
- for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
- G.reagents.trans_to(src, G.reagents.total_volume)
-
- if(reagents.total_volume) //The possible reactions didnt use up all reagents.
- var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread()
- steam.set_up(10, 0, get_turf(src))
- steam.attach(src)
- steam.start()
-
- for(var/atom/A in view(affected_area, loc))
- if( A == src ) continue
- reagents.reaction(A, 1, 10)
-
- invisibility = INVISIBILITY_MAXIMUM //Why am i doing this?
- spawn(50) //To make sure all reagents can work
- qdel(src) //correctly before deleting the grenade.
+ if(S)
+ if(S.reagents && S.reagents.total_volume)
+ for(var/obj/item/weapon/reagent_containers/glass/G in beakers)
+ S.reagents.trans_to(G, S.reagents.total_volume)
+ else
+ S.forceMove(get_turf(src))
+ no_splash = TRUE
+ ..()
//I tried to just put it in the allowed_containers list but
@@ -399,6 +359,71 @@
else
return ..()
+/obj/item/weapon/grenade/chem_grenade/cryo // Intended for rare cryogenic mixes. Cools the area moderately upon detonation.
+ name = "cryo grenade"
+ desc = "A custom made cryogenic grenade. It rapidly cools its contents upon detonation."
+ icon_state = "cryog"
+ affected_area = 2
+ ignition_temp = -100
+
+/obj/item/weapon/grenade/chem_grenade/pyro // Intended for pyrotechnical mixes. Produces a small fire upon detonation, igniting potentially flammable mixtures.
+ name = "pyro grenade"
+ desc = "A custom made pyrotechnical grenade. It heats up and ignites its contents upon detonation."
+ icon_state = "pyrog"
+ origin_tech = "combat=4;engineering=4"
+ affected_area = 3
+ ignition_temp = 500 // This is enough to expose a hotspot.
+
+/obj/item/weapon/grenade/chem_grenade/adv_release // Intended for weaker, but longer lasting effects. Could have some interesting uses.
+ name = "advanced release grenade"
+ desc = "A custom made advanced release grenade. It is able to be detonated more than once. Can be configured using a multitool."
+ icon_state = "timeg"
+ origin_tech = "combat=3;engineering=4"
+ var/unit_spread = 10 // Amount of units per repeat. Can be altered with a multitool.
+
+/obj/item/weapon/grenade/chem_grenade/adv_release/attackby(obj/item/I, mob/user, params)
+ if(ismultitool(I))
+ switch(unit_spread)
+ if(0 to 24)
+ unit_spread += 5
+ if(25 to 99)
+ unit_spread += 25
+ else
+ unit_spread = 5
+ to_chat(user, " You set the time release to [unit_spread] units per detonation.")
+ return
+ ..()
+
+/obj/item/weapon/grenade/chem_grenade/adv_release/prime()
+ if(stage != READY)
+ return
+
+ var/total_volume = 0
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ total_volume += RC.reagents.total_volume
+ if(!total_volume)
+ qdel(src)
+ qdel(nadeassembly)
+ return
+ var/fraction = unit_spread/total_volume
+ var/datum/reagents/reactants = new(unit_spread)
+ reactants.my_atom = src
+ for(var/obj/item/weapon/reagent_containers/RC in beakers)
+ RC.reagents.trans_to(reactants, RC.reagents.total_volume*fraction, threatscale, 1, 1)
+ chem_splash(get_turf(src), affected_area, list(reactants), ignition_temp, threatscale)
+
+ if(nadeassembly)
+ var/mob/M = get_mob_by_ckey(assemblyattacher)
+ var/mob/last = get_mob_by_ckey(nadeassembly.fingerprintslast)
+ var/turf/T = get_turf(src)
+ var/area/A = get_area(T)
+ message_admins("grenade primed by an assembly, attached by [key_name_admin(M)](?) (FLW) and last touched by [key_name_admin(last)](?) (FLW) ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] (JMP).")
+ log_game("grenade primed by an assembly, attached by [key_name(M)] and last touched by [key_name(last)] ([nadeassembly.a_left.name] and [nadeassembly.a_right.name]) at [A.name] ([T.x], [T.y], [T.z])")
+ else
+ addtimer(src, "prime", det_time)
+ var/turf/DT = get_turf(src)
+ var/area/DA = get_area(DT)
+ log_game("A grenade detonated at [DA.name] ([DT.x], [DT.y], [DT.z])")
/obj/item/weapon/grenade/chem_grenade/metalfoam
payload_name = "metal foam"
diff --git a/code/game/objects/items/weapons/implants/implant_death_alarm.dm b/code/game/objects/items/weapons/implants/implant_death_alarm.dm
index da9560122ad..d4807a18701 100644
--- a/code/game/objects/items/weapons/implants/implant_death_alarm.dm
+++ b/code/game/objects/items/weapons/implants/implant_death_alarm.dm
@@ -35,7 +35,7 @@
var/mob/M = imp_in
var/area/t = get_area(M)
- var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null)
+ var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(src)
a.follow_target = M
switch(cause)
@@ -52,7 +52,7 @@
else
a.autosay("[mobname] has died-zzzzt in-in-in...", "[mobname]'s Death Alarm")
qdel(src)
-
+
qdel(a)
/obj/item/weapon/implant/death_alarm/emp_act(severity) //for some reason alarms stop going off in case they are emp'd, even without this
diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm
index e61ca62831c..82c6b14f880 100644
--- a/code/game/objects/items/weapons/kitchen.dm
+++ b/code/game/objects/items/weapons/kitchen.dm
@@ -150,6 +150,13 @@
origin_tech = "materials=3;combat=4"
attack_verb = list("slashed", "stabbed", "sliced", "torn", "ripped", "cut")
+/obj/item/weapon/kitchen/knife/combat/cyborg
+ name = "cyborg knife"
+ icon = 'icons/obj/items_cyborg.dmi'
+ icon_state = "knife"
+ desc = "A cyborg-mounted plasteel knife. Extremely sharp and durable."
+ origin_tech = null
+
/obj/item/weapon/kitchen/knife/carrotshiv
name = "carrot shiv"
icon_state = "carrotshiv"
diff --git a/code/game/objects/items/weapons/melee/energy.dm b/code/game/objects/items/weapons/melee/energy.dm
index 6177c999393..810be365fa8 100644
--- a/code/game/objects/items/weapons/melee/energy.dm
+++ b/code/game/objects/items/weapons/melee/energy.dm
@@ -203,26 +203,29 @@
name = "energy blade"
desc = "A concentrated beam of energy in the shape of a blade. Very stylish... and lethal."
icon_state = "blade"
- force = 30
- sharp = 1
- edge = 1
+ force = 30 //Normal attacks deal esword damage
+ hitsound = 'sound/weapons/blade1.ogg'
+ active = 1
throwforce = 1//Throwing or dropping the item deletes it.
throw_speed = 3
throw_range = 1
w_class = WEIGHT_CLASS_BULKY //So you can't hide it in your pocket or some such.
- armour_penetration = 50
- attack_verb = list("attacked", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut")
var/datum/effect/system/spark_spread/spark_system
+ sharp = 1
+ edge = 1
//Most of the other special functions are handled in their own files. aka special snowflake code so kewl
/obj/item/weapon/melee/energy/blade/New()
+ ..()
spark_system = new /datum/effect/system/spark_spread()
spark_system.set_up(5, 0, src)
spark_system.attach(src)
-/obj/item/weapon/melee/energy/blade/dropped()
- ..()
- qdel(src)
-
/obj/item/weapon/melee/energy/blade/attack_self(mob/user)
return
+
+/obj/item/weapon/melee/energy/blade/hardlight
+ name = "hardlight blade"
+ desc = "An extremely sharp blade made out of hard light. Packs quite a punch."
+ icon_state = "lightblade"
+ item_state = "lightblade"
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/powerfist.dm b/code/game/objects/items/weapons/powerfist.dm
index 218fe47ed6b..ec6f285acd1 100644
--- a/code/game/objects/items/weapons/powerfist.dm
+++ b/code/game/objects/items/weapons/powerfist.dm
@@ -26,17 +26,17 @@
to_chat(user, "You'll need to get closer to see any more.")
return
if(tank)
- to_chat(user, "\icon [tank] It has \the [tank] mounted onto it.")
+ to_chat(user, "[bicon(tank)] It has [tank] mounted onto it.")
/obj/item/weapon/melee/powerfist/attackby(obj/item/weapon/W, mob/user, params)
if(istype(W, /obj/item/weapon/tank))
if(!tank)
var/obj/item/weapon/tank/IT = W
if(IT.volume <= 3)
- to_chat(user, "\The [IT] is too small for \the [src].")
+ to_chat(user, "[IT] is too small for [src].")
return
updateTank(W, 0, user)
- else if(istype(W, /obj/item/weapon/wrench))
+ else if(iswrench(W))
switch(fisto_setting)
if(1)
fisto_setting = 2
@@ -45,8 +45,8 @@
if(3)
fisto_setting = 1
playsound(loc, W.usesound, 50, 1)
- to_chat(user, "You tweak \the [src]'s piston valve to [fisto_setting].")
- else if(istype(W, /obj/item/weapon/screwdriver))
+ to_chat(user, "You tweak [src]'s piston valve to [fisto_setting].")
+ else if(isscrewdriver(W))
if(tank)
updateTank(tank, 1, user)
@@ -54,29 +54,29 @@
/obj/item/weapon/melee/powerfist/proc/updateTank(obj/item/weapon/tank/thetank, removing = 0, mob/living/carbon/human/user)
if(removing)
if(!tank)
- to_chat(user, "\The [src] currently has no tank attached to it.")
+ to_chat(user, "[src] currently has no tank attached to it.")
return
- to_chat(user, "You detach \the [thetank] from \the [src].")
+ to_chat(user, "You detach [thetank] from [src].")
tank.forceMove(get_turf(user))
user.put_in_hands(tank)
tank = null
if(!removing)
if(tank)
- to_chat(user, "\The [src] already has a tank.")
+ to_chat(user, "[src] already has a tank.")
return
if(!user.unEquip(thetank))
return
- to_chat(user, "You hook \the [thetank] up to \the [src].")
+ to_chat(user, "You hook [thetank] up to [src].")
tank = thetank
thetank.forceMove(src)
/obj/item/weapon/melee/powerfist/attack(mob/living/target, mob/living/user)
if(!tank)
- to_chat(user, "\The [src] can't operate without a source of gas!")
+ to_chat(user, "[src] can't operate without a source of gas!")
return
if(tank && !tank.air_contents.remove(gasperfist * fisto_setting))
- to_chat(user, "\The [src]'s piston-ram lets out a weak hiss, it needs more gas!")
+ to_chat(user, "[src]'s piston-ram lets out a weak hiss, it needs more gas!")
playsound(loc, 'sound/effects/refill.ogg', 50, 1)
return
@@ -90,8 +90,8 @@
playsound(loc, 'sound/weapons/genhit2.ogg', 50, 1)
var/atom/throw_target = get_edge_target_turf(target, get_dir(src, get_step_away(target, src)))
- spawn(0)
- target.throw_at(throw_target, 5 * fisto_setting, 0.2)
+
+ target.throw_at(throw_target, 5 * fisto_setting, 0.2)
add_logs(user, target, "power fisted", src)
diff --git a/code/game/objects/items/weapons/tanks/tanks.dm b/code/game/objects/items/weapons/tanks/tanks.dm
index 3b99936b0a8..27cbff53547 100644
--- a/code/game/objects/items/weapons/tanks/tanks.dm
+++ b/code/game/objects/items/weapons/tanks/tanks.dm
@@ -54,7 +54,9 @@
C.update_internals_hud_icon(0)
else
var/can_open_valve = 0
- if(C.wear_mask && C.wear_mask.flags & AIRTIGHT)
+ if(C.get_organ_slot("breathing_tube"))
+ can_open_valve = 1
+ else if(C.wear_mask && C.wear_mask.flags & AIRTIGHT)
can_open_valve = 1
else if(ishuman(C))
var/mob/living/carbon/human/H = C
diff --git a/code/game/objects/items/weapons/teleportation.dm b/code/game/objects/items/weapons/teleportation.dm
index c07c658a7bf..11da88ae680 100644
--- a/code/game/objects/items/weapons/teleportation.dm
+++ b/code/game/objects/items/weapons/teleportation.dm
@@ -128,7 +128,7 @@ Frequency:
if(turfs.len)
L["None (Dangerous)"] = pick(turfs)
var/t1 = input(user, "Please select a teleporter to lock in on.", "Hand Teleporter") as null|anything in L
- if(!t1 || (user.is_in_active_hand(src) || user.stat || user.restrained()))
+ if(!t1 || (!user.is_in_active_hand(src) || user.stat || user.restrained()))
return
if(active_portals >= 3)
user.show_message("\The [src] is recharging!")
diff --git a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
index d651ad55adb..e9d9781bf0e 100644
--- a/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
+++ b/code/game/objects/structures/crates_lockers/closets/wardrobe.dm
@@ -251,6 +251,10 @@
new /obj/item/clothing/under/rank/medical/skirt(src)
new /obj/item/clothing/under/rank/medical/skirt(src)
new /obj/item/clothing/head/surgery/purple(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
new /obj/item/clothing/shoes/black(src)
new /obj/item/clothing/shoes/black(src)
new /obj/item/clothing/shoes/black(src)
@@ -406,6 +410,10 @@
new /obj/item/clothing/suit/storage/labcoat(src)
new /obj/item/clothing/mask/surgical(src)
new /obj/item/clothing/mask/surgical(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
+ new /obj/item/clothing/under/medigown(src)
/obj/structure/closet/wardrobe/grey
diff --git a/code/game/response_team.dm b/code/game/response_team.dm
index 344a9b72054..ebfe10f71e0 100644
--- a/code/game/response_team.dm
+++ b/code/game/response_team.dm
@@ -387,12 +387,13 @@ var/ert_request_answered = 0
/obj/item/clothing/head/helmet/space/hardsuit/ert/commander = 1,
/obj/item/clothing/mask/gas/sechailer/swat = 1,
/obj/item/weapon/restraints/handcuffs = 1,
+ /obj/item/clothing/shoes/magboots = 1,
/obj/item/weapon/storage/lockbox/mindshield = 1
)
/datum/outfit/job/centcom/response_team/commander/gamma
name = "RT Commander (Gamma)"
- shoes = /obj/item/clothing/shoes/combat/swat
+ shoes = /obj/item/clothing/shoes/magboots/advance
gloves = /obj/item/clothing/gloves/combat
suit = /obj/item/clothing/suit/space/hardsuit/ert/commander
glasses = /obj/item/clothing/glasses/hud/security/night
@@ -457,6 +458,7 @@ var/ert_request_answered = 0
backpack_contents = list(
/obj/item/clothing/head/helmet/space/hardsuit/ert/security = 1,
/obj/item/clothing/mask/gas/sechailer = 1,
+ /obj/item/clothing/shoes/magboots = 1,
/obj/item/weapon/storage/box/handcuffs = 1,
/obj/item/weapon/gun/energy/ionrifle/carbine = 1
)
@@ -464,7 +466,7 @@ var/ert_request_answered = 0
/datum/outfit/job/centcom/response_team/security/gamma
name = "RT Security (Gamma)"
has_grenades = TRUE
- shoes = /obj/item/clothing/shoes/combat/swat
+ shoes = /obj/item/clothing/shoes/magboots/advance
gloves = /obj/item/clothing/gloves/combat
suit = /obj/item/clothing/suit/space/hardsuit/ert/security
suit_store = /obj/item/weapon/gun/energy/gun/nuclear
@@ -509,7 +511,7 @@ var/ert_request_answered = 0
/datum/outfit/job/centcom/response_team/engineer/red
name = "RT Engineer (Red)"
- shoes = /obj/item/clothing/shoes/magboots
+ shoes = /obj/item/clothing/shoes/magboots/advance
gloves = /obj/item/clothing/gloves/color/yellow
suit = /obj/item/clothing/suit/space/hardsuit/ert/engineer
suit_store = /obj/item/weapon/tank/emergency_oxygen/engi
@@ -594,12 +596,13 @@ var/ert_request_answered = 0
/obj/item/weapon/storage/firstaid/toxin = 1,
/obj/item/weapon/storage/firstaid/adv = 1,
/obj/item/weapon/storage/firstaid/surgery = 1,
- /obj/item/weapon/gun/energy/gun = 1
+ /obj/item/weapon/gun/energy/gun = 1,
+ /obj/item/clothing/shoes/magboots = 1
)
/datum/outfit/job/centcom/response_team/medic/gamma
name = "RT Medic (Gamma)"
- shoes = /obj/item/clothing/shoes/combat/swat
+ shoes = /obj/item/clothing/shoes/magboots/advance
gloves = /obj/item/clothing/gloves/combat
suit = /obj/item/clothing/suit/space/hardsuit/ert/medical
glasses = /obj/item/clothing/glasses/hud/health/night
diff --git a/code/modules/admin/verbs/gimmick_team.dm b/code/modules/admin/verbs/gimmick_team.dm
index 9aecae47d17..2ca1d3c27df 100644
--- a/code/modules/admin/verbs/gimmick_team.dm
+++ b/code/modules/admin/verbs/gimmick_team.dm
@@ -12,6 +12,7 @@
return
if(alert("Do you want to spawn a Gimmick Team at YOUR CURRENT LOCATION?",,"Yes","No")=="No")
return
+ var/turf/T = get_turf(mob)
var/pick_manually = 0
if(alert("Pick the team members manually? If you select yes, you pick from ghosts. If you select no, ghosts get offered the chance to join.",,"Yes","No")=="Yes")
pick_manually = 1
@@ -34,6 +35,9 @@
var/dresscode = input("Select Outfit", "Dress-a-mob") as null|anything in outfit_list
if(isnull(dresscode))
return
+ var/is_syndicate = 0
+ if(alert("Do you want these characters automatically classified as antagonists?",,"Yes","No")=="Yes")
+ is_syndicate = 1
var/list/players_to_spawn = list()
if(pick_manually)
@@ -55,7 +59,8 @@
return 0
var/datum/outfit/O = outfit_list[dresscode]
- var/turf/T = get_turf(mob)
+
+ var/players_spawned = 0
for(var/mob/thisplayer in players_to_spawn)
var/mob/living/carbon/human/H = new /mob/living/carbon/human(T)
H.name = random_name(pick(MALE,FEMALE))
@@ -67,13 +72,20 @@
H.mind_initialize()
H.mind.assigned_role = "MODE"
H.mind.special_role = "Event Character"
- ticker.mode.traitors |= H.mind //Adds them to extra antag list
H.key = thisplayer.key
H.equipOutfit(O, FALSE)
to_chat(H, "
[themission]")
+ H.mind.store_memory("[themission]
")
+
+ if(is_syndicate)
+ ticker.mode.traitors |= H.mind //Adds them to extra antag list
+
+ players_spawned++
+ if(players_spawned >= teamsize)
+ break
message_admins("[key_name_admin(src)] has spawned a Gimmick Team.", 1)
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index 3d11f40b1c9..596259b47da 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -332,7 +332,7 @@ BLIND // can't see anything
mask_adjusted = 1
if(adjusted_flags)
slot_flags = adjusted_flags
- if(ishuman(user) && H.internal && user.wear_mask == src) /*If the user was wearing the mask providing internals on their face at the time it was adjusted, turn off internals.
+ if(ishuman(user) && H.internal && !H.get_organ_slot("breathing_tube") && user.wear_mask == src) /*If the user was wearing the mask providing internals on their face at the time it was adjusted, turn off internals.
Otherwise, they adjusted it while it was in their hands or some such so we won't be needing to turn off internals.*/
H.update_internals_hud_icon(0)
H.internal = null
diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm
index c7c7c3afcb0..d120ef04528 100644
--- a/code/modules/clothing/glasses/glasses.dm
+++ b/code/modules/clothing/glasses/glasses.dm
@@ -90,7 +90,8 @@
scan_reagents = 1 //You can see reagents while wearing science goggles
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
actions_types = list(/datum/action/item_action/toggle_research_scanner)
@@ -138,7 +139,8 @@
item_state = "eyepatch"
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/monocle
@@ -150,7 +152,8 @@
species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/eyes.dmi',
- "Drask" = 'icons/mob/species/drask/eyes.dmi'
+ "Drask" = 'icons/mob/species/drask/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/material
@@ -163,7 +166,8 @@
species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/eyes.dmi',
- "Drask" = 'icons/mob/species/drask/eyes.dmi'
+ "Drask" = 'icons/mob/species/drask/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/material/cyber
@@ -182,7 +186,8 @@
prescription = 1
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/regular/hipster
@@ -198,7 +203,8 @@
item_state = "3d"
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/gglasses
@@ -208,7 +214,8 @@
item_state = "gglasses"
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
prescription_upgradable = 1
@@ -379,7 +386,8 @@
flash_protect = -1
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
emp_act(severity)
diff --git a/code/modules/clothing/glasses/hud.dm b/code/modules/clothing/glasses/hud.dm
index 818ed3f2f10..ff8de1a6a82 100644
--- a/code/modules/clothing/glasses/hud.dm
+++ b/code/modules/clothing/glasses/hud.dm
@@ -62,7 +62,8 @@
HUDType = DATA_HUD_DIAGNOSTIC
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/hud/diagnostic/night
@@ -85,7 +86,8 @@
species_fit = list("Vox")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/eyes.dmi',
- "Drask" = 'icons/mob/species/drask/eyes.dmi'
+ "Drask" = 'icons/mob/species/drask/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/hud/security/chameleon
@@ -138,7 +140,8 @@
HUDType = DATA_HUD_HYDROPONIC
species_fit = list("Vox")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/eyes.dmi'
+ "Vox" = 'icons/mob/species/vox/eyes.dmi',
+ "Grey" = 'icons/mob/species/grey/eyes.dmi'
)
/obj/item/clothing/glasses/hud/hydroponic/night
diff --git a/code/modules/clothing/head/hardhat.dm b/code/modules/clothing/head/hardhat.dm
index c73a6f21306..ae694f8edf2 100644
--- a/code/modules/clothing/head/hardhat.dm
+++ b/code/modules/clothing/head/hardhat.dm
@@ -70,4 +70,8 @@
heat_protection = HEAD
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
cold_protection = HEAD
- min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
\ No newline at end of file
+ min_cold_protection_temperature = FIRE_HELM_MIN_TEMP_PROTECT
+ species_fit = list("Grey")
+ sprite_sheets = list(
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
+ )
\ No newline at end of file
diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm
index 1bb6c1ec382..c3595288213 100644
--- a/code/modules/clothing/head/helmet.dm
+++ b/code/modules/clothing/head/helmet.dm
@@ -13,10 +13,11 @@
max_heat_protection_temperature = HELMET_MAX_TEMP_PROTECT
strip_delay = 60
burn_state = FIRE_PROOF
- species_fit = list("Vox", "Drask")
+ species_fit = list("Vox", "Drask", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/helmet.dmi',
- "Drask" = 'icons/mob/species/drask/helmet.dmi'
+ "Drask" = 'icons/mob/species/drask/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
/obj/item/clothing/head/helmet/attack_self(mob/user)
diff --git a/code/modules/clothing/head/misc_special.dm b/code/modules/clothing/head/misc_special.dm
index aa5a81c2063..ee0610471c8 100644
--- a/code/modules/clothing/head/misc_special.dm
+++ b/code/modules/clothing/head/misc_special.dm
@@ -24,12 +24,13 @@
flags_inv = (HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE)
actions_types = list(/datum/action/item_action/toggle)
burn_state = FIRE_PROOF
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/head.dmi',
"Unathi" = 'icons/mob/species/unathi/helmet.dmi',
"Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
/obj/item/clothing/head/welding/flamedecal
diff --git a/code/modules/clothing/masks/boxing.dm b/code/modules/clothing/masks/boxing.dm
index 59081cf3d00..d66daf59760 100644
--- a/code/modules/clothing/masks/boxing.dm
+++ b/code/modules/clothing/masks/boxing.dm
@@ -8,12 +8,13 @@
w_class = WEIGHT_CLASS_SMALL
actions_types = list(/datum/action/item_action/adjust)
adjusted_flags = SLOT_HEAD
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi',
"Drask" = 'icons/mob/species/drask/mask.dmi'
)
@@ -28,12 +29,13 @@
flags = BLOCKHAIR
flags_inv = HIDEFACE
w_class = WEIGHT_CLASS_SMALL
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi',
"Drask" = 'icons/mob/species/drask/mask.dmi'
)
diff --git a/code/modules/clothing/masks/breath.dm b/code/modules/clothing/masks/breath.dm
index 851c10db354..afefbbc93cc 100644
--- a/code/modules/clothing/masks/breath.dm
+++ b/code/modules/clothing/masks/breath.dm
@@ -10,13 +10,14 @@
permeability_coefficient = 0.50
actions_types = list(/datum/action/item_action/adjust)
burn_state = FIRE_PROOF
- species_fit = list("Vox", "Vox Armalis", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Vox Armalis", "Unathi", "Tajaran", "Vulpkanin", "Grey" )
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Vox Armalis" = 'icons/mob/species/armalis/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi',
"Drask" = 'icons/mob/species/drask/mask.dmi'
)
@@ -30,7 +31,7 @@
item_state = "medical"
permeability_coefficient = 0.01
put_on_delay = 10
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
/obj/item/clothing/mask/breath/vox
desc = "A weirdly-shaped breath mask."
diff --git a/code/modules/clothing/masks/miscellaneous.dm b/code/modules/clothing/masks/miscellaneous.dm
index d524d87e3d8..5ac05685079 100644
--- a/code/modules/clothing/masks/miscellaneous.dm
+++ b/code/modules/clothing/masks/miscellaneous.dm
@@ -34,12 +34,13 @@
w_class = WEIGHT_CLASS_TINY
resist_time = 150
mute = 0
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi'
)
/obj/item/clothing/mask/muzzle/tapegag/dropped(mob/living/carbon/human/user)
@@ -65,12 +66,13 @@
permeability_coefficient = 0.01
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 25, rad = 0)
actions_types = list(/datum/action/item_action/adjust)
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi'
)
@@ -83,12 +85,13 @@
icon_state = "fake-moustache"
flags_inv = HIDEFACE
actions_types = list(/datum/action/item_action/pontificate)
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi'
)
/obj/item/clothing/mask/fakemoustache/attack_self(mob/user)
@@ -267,12 +270,13 @@
slot_flags = SLOT_MASK
adjusted_flags = SLOT_HEAD
icon_state = "bandbotany"
- species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin")
+ species_fit = list("Vox", "Unathi", "Tajaran", "Vulpkanin", "Grey")
sprite_sheets = list(
"Vox" = 'icons/mob/species/vox/mask.dmi',
"Unathi" = 'icons/mob/species/unathi/mask.dmi',
"Tajaran" = 'icons/mob/species/tajaran/mask.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/mask.dmi',
+ "Grey" = 'icons/mob/species/grey/mask.dmi'
)
actions_types = list(/datum/action/item_action/adjust)
diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm
index 80257cda101..90d61fa0313 100644
--- a/code/modules/clothing/spacesuits/ert.dm
+++ b/code/modules/clothing/spacesuits/ert.dm
@@ -9,6 +9,10 @@
var/obj/machinery/camera/camera
var/has_camera = TRUE
strip_delay = 130
+ species_fit = list("Grey")
+ sprite_sheets = list(
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
+ )
/obj/item/clothing/head/helmet/space/hardsuit/ert/attack_self(mob/user)
if(camera || !has_camera)
diff --git a/code/modules/clothing/spacesuits/hardsuit.dm b/code/modules/clothing/spacesuits/hardsuit.dm
index 802f39ad361..5483ca65072 100644
--- a/code/modules/clothing/spacesuits/hardsuit.dm
+++ b/code/modules/clothing/spacesuits/hardsuit.dm
@@ -20,14 +20,15 @@
"Skrell" = 'icons/mob/species/skrell/helmet.dmi',
"Vox" = 'icons/mob/species/vox/helmet.dmi',
"Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi',
- "Drask" = 'icons/mob/species/drask/helmet.dmi'
+ "Drask" = 'icons/mob/species/drask/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
sprite_sheets_obj = list(
"Unathi" = 'icons/obj/clothing/species/unathi/hats.dmi',
"Tajaran" = 'icons/obj/clothing/species/tajaran/hats.dmi',
"Skrell" = 'icons/obj/clothing/species/skrell/hats.dmi',
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi',
- "Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/hats.dmi',
+ "Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/hats.dmi'
)
/obj/item/clothing/head/helmet/space/hardsuit/equip_to_best_slot(mob/M)
@@ -83,7 +84,7 @@
"Tajaran" = 'icons/obj/clothing/species/tajaran/suits.dmi',
"Skrell" = 'icons/obj/clothing/species/skrell/suits.dmi',
"Vox" = 'icons/obj/clothing/species/vox/suits.dmi',
- "Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/suits.dmi',
+ "Vulpkanin" = 'icons/obj/clothing/species/vulpkanin/suits.dmi'
)
//Breach thresholds, should ideally be inherited by most (if not all) hardsuits.
@@ -440,7 +441,10 @@
heat_protection = HEAD //Uncomment to enable firesuit protection
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
unacidable = 1
- sprite_sheets = null
+ species_fit = list("Grey")
+ sprite_sheets = list(
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
+ )
/obj/item/clothing/suit/space/hardsuit/wizard
icon_state = "hardsuit-wiz"
@@ -538,7 +542,6 @@
icon_state = "hardsuit0-hos"
item_color = "hos"
armor = list(melee = 45, bullet = 25, laser = 30,energy = 10, bomb = 25, bio = 100, rad = 50)
- sprite_sheets = null
/obj/item/clothing/suit/space/hardsuit/security/hos
diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm
index 20d9809f2b2..60e76418a53 100644
--- a/code/modules/clothing/spacesuits/miscellaneous.dm
+++ b/code/modules/clothing/spacesuits/miscellaneous.dm
@@ -8,9 +8,10 @@
permeability_coefficient = 0.01
armor = list(melee = 40, bullet = 50, laser = 50, energy = 25, bomb = 50, bio = 100, rad = 50)
species_restricted = list("exclude", "Diona", "Wryn")
- species_fit = list("Vox")
+ species_fit = list("Vox", "Grey")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/helmet.dmi'
+ "Vox" = 'icons/mob/species/vox/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
/obj/item/clothing/head/helmet/space/capspace/equipped(mob/living/carbon/human/user, slot)
@@ -136,9 +137,10 @@
desc = "A paramedic EVA helmet. Used in the recovery of bodies from space."
icon_state = "paramedic-eva-helmet"
item_state = "paramedic-eva-helmet"
- species_fit = list("Vox")
+ species_fit = list("Vox", "Grey")
sprite_sheets = list(
- "Vox" = 'icons/mob/species/vox/helmet.dmi'
+ "Vox" = 'icons/mob/species/vox/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
sprite_sheets_obj = list(
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi'
@@ -187,12 +189,13 @@
armor = list(melee = 0, bullet = 0, laser = 0, energy = 0, bomb = 0, bio = 100, rad = 20)
flash_protect = 0
species_restricted = list("exclude", "Diona", "Wryn")
- species_fit = list("Tajaran", "Unathi", "Vox", "Vulpkanin")
+ species_fit = list("Tajaran", "Unathi", "Vox", "Vulpkanin", "Grey")
sprite_sheets = list(
"Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
"Unathi" = 'icons/mob/species/unathi/helmet.dmi',
"Vox" = 'icons/mob/species/vox/helmet.dmi',
- "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi'
+ "Vulpkanin" = 'icons/mob/species/vulpkanin/helmet.dmi',
+ "Grey" = 'icons/mob/species/grey/helmet.dmi'
)
sprite_sheets_obj = list(
"Vox" = 'icons/obj/clothing/species/vox/hats.dmi',
diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm
index 273dab0c787..eda243a859a 100644
--- a/code/modules/clothing/spacesuits/plasmamen.dm
+++ b/code/modules/clothing/spacesuits/plasmamen.dm
@@ -116,7 +116,7 @@
armor = list(melee = 10, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 0)
max_heat_protection_temperature = FIRE_IMMUNITY_HELM_MAX_TEMP_PROTECT
flash_protect = 2
-
+
/obj/item/clothing/suit/space/eva/plasmaman/engineer
name = "plasmaman engineer suit"
icon_state = "plasmamanEngineer_suit"
@@ -128,7 +128,7 @@
base_state = "plasmamanEngineer_helmet"
armor = list(melee = 10, bullet = 5, laser = 10, energy = 5, bomb = 10, bio = 100, rad = 75)
flash_protect = 2
-
+
/obj/item/clothing/suit/space/eva/plasmaman/engineer/ce
name = "plasmaman chief engineer suit"
icon_state = "plasmaman_CE"
@@ -269,6 +269,24 @@
icon_state = "plasmaman_CMO_helmet0"
base_state = "plasmaman_CMO_helmet"
+/obj/item/clothing/suit/space/eva/plasmaman/medical/coroner
+ name = "plasmaman coroner suit"
+ icon_state = "plasmaman_Coroner"
+
+/obj/item/clothing/head/helmet/space/eva/plasmaman/medical/coroner
+ name = "plasmaman coroner helmet"
+ icon_state = "plasmaman_Coroner_helmet0"
+ base_state = "plasmaman_Coroner_helmet"
+
+/obj/item/clothing/suit/space/eva/plasmaman/medical/virologist
+ name = "plasmaman virologist suit"
+ icon_state = "plasmaman_Virologist"
+
+/obj/item/clothing/head/helmet/space/eva/plasmaman/medical/virologist
+ name = "plasmaman virologist helmet"
+ icon_state = "plasmaman_Virologist_helmet0"
+ base_state = "plasmaman_Virologist_helmet"
+
/obj/item/clothing/suit/space/eva/plasmaman/science
name = "plasmaman scientist suit"
icon_state = "plasmamanScience_suit"
@@ -278,6 +296,15 @@
icon_state = "plasmamanScience_helmet0"
base_state = "plasmamanScience_helmet"
+/obj/item/clothing/suit/space/eva/plasmaman/science/geneticist
+ name = "plasmaman geneticist suit"
+ icon_state = "plasmaman_Geneticist"
+
+/obj/item/clothing/head/helmet/space/eva/plasmaman/science/geneticist
+ name = "plasmaman geneticist helmet"
+ icon_state = "plasmaman_Geneticist_helmet0"
+ base_state = "plasmaman_Geneticist_helmet"
+
/obj/item/clothing/suit/space/eva/plasmaman/science/rd
name = "plasmaman research director suit"
icon_state = "plasmaman_RD"
diff --git a/code/modules/clothing/under/accessories/accessory.dm b/code/modules/clothing/under/accessories/accessory.dm
index 5f358ac58f4..8f4b65e6030 100644
--- a/code/modules/clothing/under/accessories/accessory.dm
+++ b/code/modules/clothing/under/accessories/accessory.dm
@@ -620,7 +620,7 @@
return
var/area/t = get_area(M)
- var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(null)
+ var/obj/item/device/radio/headset/a = new /obj/item/device/radio/headset(src)
if(istype(t, /area/syndicate_station) || istype(t, /area/syndicate_mothership) || istype(t, /area/shuttle/syndicate_elite) )
//give the syndicats a bit of stealth
a.autosay("[M] has been vandalized in Space!", "[M]'s Death Alarm")
diff --git a/code/modules/clothing/under/miscellaneous.dm b/code/modules/clothing/under/miscellaneous.dm
index 8066deb3074..6dc1e1f2991 100644
--- a/code/modules/clothing/under/miscellaneous.dm
+++ b/code/modules/clothing/under/miscellaneous.dm
@@ -822,3 +822,11 @@
icon_state = "victorianredvest"
item_state = "victorianredvest"
item_color = "victorianredvest"
+
+/obj/item/clothing/under/medigown
+ name = "medical gown"
+ desc = "a flimsy examination gown, the back ties never close."
+ icon_state = "medicalgown"
+ item_state = "medicalgown"
+ item_color = "medicalgown"
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO
diff --git a/code/modules/countdown/countdown.dm b/code/modules/countdown/countdown.dm
index 2ef85d6a9d7..7e651fb910f 100644
--- a/code/modules/countdown/countdown.dm
+++ b/code/modules/countdown/countdown.dm
@@ -9,15 +9,19 @@
var/atom/attached_to
color = "#ff0000"
var/text_size = 4
- var/started = 0
+ var/started = FALSE
invisibility = INVISIBILITY_OBSERVER
- anchored = 1
- layer = 5
+ anchored = TRUE
+ layer = GHOST_LAYER
/obj/effect/countdown/New(atom/A)
. = ..()
attach(A)
+/obj/effect/countdown/examine(mob/user)
+ . = ..()
+ to_chat(user, "This countdown is displaying: [displayed_text]")
+
/obj/effect/countdown/proc/attach(atom/A)
attached_to = A
loc = get_turf(A)
@@ -25,13 +29,13 @@
/obj/effect/countdown/proc/start()
if(!started)
fast_processing += src
- started = 1
+ started = TRUE
/obj/effect/countdown/proc/stop()
if(started)
maptext = null
fast_processing -= src
- started = 0
+ started = FALSE
/obj/effect/countdown/proc/get_value()
// Get the value from our atom
@@ -56,6 +60,19 @@
fast_processing -= src
return ..()
+/obj/effect/countdown/ex_act(severity) //immune to explosions
+ return
+
+/obj/effect/countdown/syndicatebomb
+ name = "syndicate bomb countdown"
+
+/obj/effect/countdown/syndicatebomb/get_value()
+ var/obj/machinery/syndicatebomb/S = attached_to
+ if(!istype(S))
+ return
+ else if(S.active)
+ return S.seconds_remaining()
+
/obj/effect/countdown/clonepod
name = "cloning pod countdown"
text_size = 1
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index 6f266c121e1..3fbcf39ed08 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -324,6 +324,30 @@
/obj/item/stack/rods = 1)
category = CAT_MISC
+/datum/crafting_recipe/chemical_payload
+ name = "Chemical Payload (C4)"
+ result = /obj/item/weapon/bombcore/chemical
+ reqs = list(
+ /obj/item/weapon/stock_parts/matter_bin = 1,
+ /obj/item/weapon/grenade/plastic/c4 = 1,
+ /obj/item/weapon/grenade/chem_grenade = 2
+ )
+ parts = list(/obj/item/weapon/stock_parts/matter_bin = 1, /obj/item/weapon/grenade/chem_grenade = 2)
+ time = 30
+ category = CAT_WEAPON
+
+/datum/crafting_recipe/chemical_payload2
+ name = "Chemical Payload (gibtonite)"
+ result = /obj/item/weapon/bombcore/chemical
+ reqs = list(
+ /obj/item/weapon/stock_parts/matter_bin = 1,
+ /obj/item/weapon/twohanded/required/gibtonite = 1,
+ /obj/item/weapon/grenade/chem_grenade = 2
+ )
+ parts = list(/obj/item/weapon/stock_parts/matter_bin = 1, /obj/item/weapon/grenade/chem_grenade = 2)
+ time = 50
+ category = CAT_WEAPON
+
/datum/crafting_recipe/bonfire
name = "Bonfire"
time = 60
diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm
index d591c8b4a1c..cc9ed1a27d6 100644
--- a/code/modules/mob/language.dm
+++ b/code/modules/mob/language.dm
@@ -296,13 +296,6 @@
flags = RESTRICTED | HIVEMIND
/datum/language/grey/broadcast(mob/living/speaker, message, speaker_mask)
- var/their = "their"
- if(speaker.gender == "female")
- their = "her"
- if(speaker.gender == "male")
- their = "his"
-
- speaker.visible_message("[speaker] touches [their] fingers to [their] temple.")
..(speaker,message,speaker.real_name)
/datum/language/grey/check_can_speak(mob/living/speaker)
@@ -316,6 +309,14 @@
if(speaker.incapacitated(ignore_lying = 1))
to_chat(speaker,"You can't communicate while unable to move your hands to your head!")
return FALSE
+
+ var/their = "their"
+ if(speaker.gender == "female")
+ their = "her"
+ if(speaker.gender == "male")
+ their = "his"
+ speaker.visible_message("[speaker] touches [their] fingers to [their] temple.") //If placed in grey/broadcast, it will happen regardless of the success of the action.
+
return TRUE
/datum/language/grey/check_special_condition(mob/living/carbon/human/other, mob/living/carbon/human/speaker)
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 708016df353..dd18495cc70 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -654,9 +654,10 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
"[usr] tries to [internal ? "close" : "open"] the valve on [src]'s [ITEM].")
var/no_mask
- if(!(wear_mask && wear_mask.flags & AIRTIGHT))
- if(!(head && head.flags & AIRTIGHT))
- no_mask = 1
+ if(!get_organ_slot("breathing_tube"))
+ if(!(wear_mask && wear_mask.flags & AIRTIGHT))
+ if(!(head && head.flags & AIRTIGHT))
+ no_mask = 1
if(no_mask)
to_chat(usr, "[src] is not wearing a suitable mask or helmet!")
return
@@ -667,9 +668,10 @@ var/list/ventcrawl_machinery = list(/obj/machinery/atmospherics/unary/vent_pump,
update_internals_hud_icon(0)
else
var/no_mask2
- if(!(wear_mask && wear_mask.flags & AIRTIGHT))
- if(!(head && head.flags & AIRTIGHT))
- no_mask2 = 1
+ if(!get_organ_slot("breathing_tube"))
+ if(!(wear_mask && wear_mask.flags & AIRTIGHT))
+ if(!(head && head.flags & AIRTIGHT))
+ no_mask2 = 1
if(no_mask2)
to_chat(usr, "[src] is not wearing a suitable mask or helmet!")
return
diff --git a/code/modules/mob/living/carbon/carbon_defines.dm b/code/modules/mob/living/carbon/carbon_defines.dm
index 6e34291caae..ab7a5f1d5a9 100644
--- a/code/modules/mob/living/carbon/carbon_defines.dm
+++ b/code/modules/mob/living/carbon/carbon_defines.dm
@@ -3,6 +3,7 @@
hud_possible = list(HEALTH_HUD,STATUS_HUD,SPECIALROLE_HUD)
var/list/stomach_contents = list()
var/list/internal_organs = list()
+ var/list/internal_organs_slot = list() //Same as above, but stores "slot ID" - "organ" pairs for easy access.
var/antibodies = 0
var/life_tick = 0 // The amount of life ticks that have processed on this mob.
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 59a679b1f63..8a39920cae1 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -427,7 +427,7 @@
/mob/living/carbon/human/show_inv(mob/user)
user.set_machine(src)
- var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask)
+ var/has_breathable_mask = istype(wear_mask, /obj/item/clothing/mask) || get_organ_slot("breathing_tube")
var/list/obscured = check_obscured_slots()
var/dat = {"