diff --git a/code/game/gamemodes/gang/dominator.dm b/code/game/gamemodes/gang/dominator.dm
index d53fe91186a..5ad7dd3dc58 100644
--- a/code/game/gamemodes/gang/dominator.dm
+++ b/code/game/gamemodes/gang/dominator.dm
@@ -12,6 +12,7 @@
var/operating = 0 //0=standby or broken, 1=takeover
var/warned = 0 //if this device has set off the warning at <3 minutes yet
var/datum/effect_system/spark_spread/spark_system
+ var/obj/effect/countdown/dominator/countdown
/obj/machinery/dominator/tesla_act()
qdel(src)
@@ -22,6 +23,7 @@
poi_list |= src
spark_system = new
spark_system.set_up(5, 1, src)
+ countdown = new(src)
/obj/machinery/dominator/examine(mob/user)
..()
@@ -121,6 +123,9 @@
poi_list.Remove(src)
gang = null
qdel(spark_system)
+ qdel(countdown)
+ countdown = null
+ SSmachine.processing -= src
return ..()
/obj/machinery/dominator/emp_act(severity)
@@ -189,6 +194,10 @@
src.name = "[gang.name] Gang [src.name]"
operating = 1
icon_state = "dominator-[gang.color]"
+
+ countdown.text_color = gang.color_hex
+ countdown.start()
+
SetLuminosity(3)
SSmachine.processing += src
diff --git a/code/game/gamemodes/nuclear/nuclearbomb.dm b/code/game/gamemodes/nuclear/nuclearbomb.dm
index 27987aa8c26..be45083ed89 100644
--- a/code/game/gamemodes/nuclear/nuclearbomb.dm
+++ b/code/game/gamemodes/nuclear/nuclearbomb.dm
@@ -33,9 +33,11 @@ var/bomb_set
var/deconstruction_state = NUKESTATE_INTACT
var/image/lights = null
var/image/interior = null
+ var/obj/effect/countdown/nuclearbomb/countdown
/obj/machinery/nuclearbomb/New()
..()
+ countdown = new(src)
nuke_list += src
core = new /obj/item/nuke_core(src)
SSobj.processing -= core
@@ -45,6 +47,9 @@ var/bomb_set
/obj/machinery/nuclearbomb/Destroy()
poi_list -= src
+ nuke_list -= src
+ qdel(countdown)
+ countdown = null
. = ..()
/obj/machinery/nuclearbomb/selfdestruct
@@ -205,6 +210,7 @@ var/bomb_set
/obj/machinery/nuclearbomb/process()
if (timing > 0)
+ countdown.start()
bomb_set = 1 //So long as there is one nuke timing, it means one nuke is armed.
timeleft--
if (timeleft <= 0)
@@ -215,7 +221,8 @@ var/bomb_set
for(var/mob/M in viewers(1, src))
if ((M.client && M.machine == src))
attack_hand(M)
- return
+ else
+ countdown.stop()
/obj/machinery/nuclearbomb/attack_paw(mob/user)
return attack_hand(user)
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index cf2d63fbe67..4c66b5508aa 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -32,11 +32,15 @@
var/radio_key = /obj/item/device/encryptionkey/headset_med
var/radio_channel = "Medical"
+ var/obj/effect/countdown/clonepod/countdown
+
/obj/machinery/clonepod/New()
..()
var/obj/item/weapon/circuitboard/machine/B = new /obj/item/weapon/circuitboard/machine/clonepod(null)
B.apply_default_parts(src)
+ countdown = new(src)
+
radio = new(src)
radio.keyslot = new radio_key
radio.subspace_transmission = 1
@@ -45,6 +49,9 @@
/obj/machinery/clonepod/Destroy()
qdel(radio)
+ radio = null
+ qdel(countdown)
+ countdown = null
. = ..()
/obj/machinery/clonepod/RefreshParts()
@@ -115,12 +122,14 @@
if (isnull(occupant) || !is_operational())
return
if ((!isnull(occupant)) && (occupant.stat != DEAD))
- var/completion = (100 * ((occupant.health + 100) / (heal_level + 100)))
- user << "Current clone cycle is [round(completion)]% complete."
+ user << "Current clone cycle is [round(get_completion())]% complete."
else if(mess)
user << "It's filled with blood and vicerea. You swear you can see \
it moving..."
+/obj/machinery/clonepod/proc/get_completion()
+ . = (100 * ((occupant.health + 100) / (heal_level + 100)))
+
/obj/machinery/clonepod/attack_ai(mob/user)
return examine(user)
@@ -146,6 +155,7 @@
attempting = TRUE //One at a time!!
locked = TRUE
+ countdown.start()
eject_wait = TRUE
spawn(30)
@@ -306,6 +316,7 @@
/obj/machinery/clonepod/proc/go_out()
if (locked)
return
+ countdown.stop()
if (mess) //Clean that mess and dump those gibs!
mess = FALSE
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index c31202c2c1b..5764593fd20 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -18,6 +18,7 @@
var/beepsound = 'sound/items/timer.ogg'
var/delayedbig = FALSE //delay wire pulsed?
var/delayedlittle = FALSE //activation wire pulsed?
+ var/obj/effect/countdown/syndicatebomb/countdown
/obj/machinery/syndicatebomb/process()
if(active && !defused && (timer > 0)) //Tick Tock
@@ -41,6 +42,7 @@
if(src.payload)
payload = new payload(src)
update_icon()
+ countdown = new(src)
..()
/obj/machinery/syndicatebomb/Destroy()
diff --git a/code/modules/countdown/countdown.dm b/code/modules/countdown/countdown.dm
new file mode 100644
index 00000000000..cc28e5b6fef
--- /dev/null
+++ b/code/modules/countdown/countdown.dm
@@ -0,0 +1,108 @@
+/obj/effect/countdown
+ name = "countdown"
+ desc = "We're leaving together\n\
+ But still it's farewell\n\
+ And maybe we'll come back\n\
+ To earth, who can tell?"
+
+ var/displayed_text
+ var/atom/attached_to
+ var/text_color = "#ff0000"
+ var/text_size = 4
+ var/started = FALSE
+ invisibility = INVISIBILITY_OBSERVER
+ layer = GHOST_LAYER
+
+/obj/effect/countdown/New(atom/A)
+ . = ..()
+ attach(A)
+
+/obj/effect/countdown/proc/attach(atom/A)
+ attached_to = A
+ loc = get_turf(A)
+
+/obj/effect/countdown/proc/start()
+ if(!started)
+ SSfastprocess.processing |= src
+ started = TRUE
+
+/obj/effect/countdown/proc/stop()
+ if(started)
+ overlays.Cut()
+ SSfastprocess.processing -= src
+ started = FALSE
+
+/obj/effect/countdown/proc/get_value()
+ // Get the value from our atom
+ return
+
+/obj/effect/countdown/process()
+ if(!attached_to || qdeleted(attached_to))
+ qdel(src)
+ var/new_val = get_value()
+ if(new_val == displayed_text)
+ return
+ displayed_text = new_val
+
+ if(displayed_text)
+ var/image/text_image = new(loc = src)
+ //text_image.maptext = "[new_val]"
+ text_image.maptext = "[displayed_text]"
+ text_image.color = text_color
+
+ overlays.Cut()
+ overlays += text_image
+ else
+ overlays.Cut()
+
+/obj/effect/countdown/Destroy()
+ attached_to = null
+ SSfastprocess.processing -= src
+ . = ..()
+
+/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.timer
+
+/obj/effect/countdown/nuclearbomb
+ name = "nuclear bomb countdown"
+ text_color = "#81FF14"
+
+/obj/effect/countdown/nuclearbomb/get_value()
+ var/obj/machinery/nuclearbomb/N = attached_to
+ if(!istype(N))
+ return
+ else if(N.timing)
+ return N.timeleft
+
+/obj/effect/countdown/clonepod
+ name = "cloning pod countdown"
+ text_color = "#0C479D"
+ text_size = 1
+
+/obj/effect/countdown/clonepod/get_value()
+ var/obj/machinery/clonepod/C = attached_to
+ if(!istype(C))
+ return
+ else if(C.occupant)
+ var/completion = round(C.get_completion())
+ return completion
+
+/obj/effect/countdown/dominator
+ name = "dominator countdown"
+ text_size = 1
+ text_color = "#ff00ff" // Overwritten when the dominator starts
+
+/obj/effect/countdown/dominator/get_value()
+ var/obj/machinery/dominator/D = attached_to
+ if(!istype(D))
+ return
+ else if(D.gang && D.gang.dom_timer)
+ var/timer = D.gang.dom_timer
+ return timer
diff --git a/tgstation.dme b/tgstation.dme
index 2f3858e6137..4f09903bd39 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1022,6 +1022,7 @@
#include "code\modules\clothing\under\jobs\engineering.dm"
#include "code\modules\clothing\under\jobs\medsci.dm"
#include "code\modules\clothing\under\jobs\security.dm"
+#include "code\modules\countdown\countdown.dm"
#include "code\modules\crafting\craft.dm"
#include "code\modules\crafting\guncrafting.dm"
#include "code\modules\crafting\recipes.dm"
diff --git a/tools/linux_build.py b/tools/linux_build.py
index ef83210e217..13fc1a5dd3f 100755
--- a/tools/linux_build.py
+++ b/tools/linux_build.py
@@ -31,7 +31,7 @@ def stage2(map):
txt = "-M{}".format(map)
else:
txt = ''
- args = "bash dm.sh {} tgstation.dme".format(txt)
+ args = "bash tools/travis/dm.sh {} tgstation.dme".format(txt)
print(args)
p = subprocess.Popen(args, shell=True)
wait(p)