diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm
index a67384f2186..f80f30578d2 100644
--- a/code/__DEFINES/DNA.dm
+++ b/code/__DEFINES/DNA.dm
@@ -64,6 +64,8 @@
#define BURDENED /datum/mutation/human/burdened
#define HONORBOUND /datum/mutation/human/honorbound
+#define TK_MOD /datum/mutation/human/telekinesis/mod
+
#define UE_CHANGED "ue changed"
#define UI_CHANGED "ui changed"
#define UF_CHANGED "uf changed"
diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm
index 91c57847f8b..b10a140f9ad 100644
--- a/code/__DEFINES/misc.dm
+++ b/code/__DEFINES/misc.dm
@@ -446,7 +446,26 @@ GLOBAL_LIST_INIT(pda_styles, sort_list(list(MONO, VT, ORBITRON, SHARE)))
#define AMBIENT_OCCLUSION filter(type="drop_shadow", x=0, y=-2, size=4, color="#04080FAA")
#define GAUSSIAN_BLUR(filter_size) filter(type="blur", size=filter_size)
-#define STANDARD_GRAVITY 1 //Anything above this is high gravity, anything below no grav
+///range of values where you suffer from negative gravity
+#define NEGATIVE_GRAVITY_RANGE -INFINITY to NEGATIVE_GRAVITY
+///range of values where you have no gravity
+#define WEIGHTLESS_RANGE NEGATIVE_GRAVITY + 0.01 to 0
+///range of values where you have normal gravity
+#define STANDRARD_GRAVITY_RANGE 0.01 to STANDARD_GRAVITY
+///range of values where you have heavy gravity
+#define HIGH_GRAVITY_RANGE STANDARD_GRAVITY + 0.01 to GRAVITY_DAMAGE_THRESHOLD - 0.01
+///range of values where you suffer from crushing gravity
+#define CRUSHING_GRAVITY_RANGE GRAVITY_DAMAGE_THRESHOLD to INFINITY
+
+/**
+ * The point where gravity is negative enough to pull you upwards.
+ * That means walking checks for a ceiling instead of a floor, and you can fall "upwards"
+ *
+ * This should only be possible on multi-z maps because it works like shit on maps that aren't.
+ */
+#define NEGATIVE_GRAVITY -1
+
+#define STANDARD_GRAVITY 1 //Anything above this is high gravity, anything below no grav until negative gravity
/// The gravity strength threshold for high gravity damage.
#define GRAVITY_DAMAGE_THRESHOLD 3
/// The scaling factor for high gravity damage.
diff --git a/code/__DEFINES/mod.dm b/code/__DEFINES/mod.dm
index 03163497d42..d92cfdc212e 100644
--- a/code/__DEFINES/mod.dm
+++ b/code/__DEFINES/mod.dm
@@ -4,6 +4,9 @@
/// Default cell drain per process on MODsuits
#define DEFAULT_CELL_DRAIN 5
+/// Default time for a part to seal
+#define MOD_ACTIVATION_STEP_TIME 2 SECONDS
+
/// Passive module, just acts when put in naturally.
#define MODULE_PASSIVE 0
/// Usable module, does something when you press a button.
diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm
index b20cae5f00f..25721335cb4 100644
--- a/code/_globalvars/lists/maintenance_loot.dm
+++ b/code/_globalvars/lists/maintenance_loot.dm
@@ -202,7 +202,6 @@ GLOBAL_LIST_INIT(uncommon_loot, list(//uncommon: useful items
/obj/item/storage/box/clown = 1,
/obj/item/seeds/kronkus = 1,
/obj/item/seeds/odious_puffball = 1,
- /obj/item/mod/construction/broken_core = 1,
) = 8,
list(//medical and chemicals
@@ -247,6 +246,11 @@ GLOBAL_LIST_INIT(uncommon_loot, list(//uncommon: useful items
/obj/item/food/monkeycube = 1,
) = 8,
+ list(//modsuits
+ /obj/item/mod/construction/broken_core = 1,
+ /obj/effect/spawner/random/mod/maint = 3,
+ ) = 4,
+
list(//music
/obj/item/instrument/violin = 5,
/obj/item/instrument/banjo = 5,
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index 2e22c3d4edd..07e044ecd3a 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -269,6 +269,11 @@ If you're feeling frisky, examine yourself and click the underlined item to pull
return carbon_owner.help_shake_act(carbon_owner)
+/atom/movable/screen/alert/negative
+ name = "Negative Gravity"
+ desc = "You're getting pulled upwards. While you won't have to worry about falling down anymore, you may accidentally fall upwards!"
+ icon_state = "negative"
+
/atom/movable/screen/alert/weightless
name = "Weightless"
desc = "Gravity has ceased affecting you, and you're floating around aimlessly. You'll need something large and heavy, like a \
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 16498840c9f..d319a8c34c7 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -201,7 +201,7 @@
return TRUE
/obj/item/tk_grab/proc/check_if_focusable(obj/target)
- if(!tk_user || !istype(tk_user) || QDELETED(target) || !istype(target) || !tk_user.dna.check_mutation(TK))
+ if(!tk_user || !istype(tk_user) || QDELETED(target) || !istype(target) || !(tk_user.dna.check_mutation(TK) || tk_user.dna.check_mutation(TK_MOD)))
qdel(src)
return
if(!tkMaxRangeCheck(tk_user, target) || target.anchored || !isturf(target.loc))
diff --git a/code/datums/mutations/telekinesis.dm b/code/datums/mutations/telekinesis.dm
index 108fc98854e..a28ec3d437a 100644
--- a/code/datums/mutations/telekinesis.dm
+++ b/code/datums/mutations/telekinesis.dm
@@ -35,3 +35,14 @@
source.balloon_alert(source, "can't TK, too far!")
return
return target.attack_tk(source)
+
+/datum/mutation/human/telekinesis/mod
+ name = "Kinesis"
+ desc = "A modification that allows the wearer of a MODsuit to interact with objects through thought with the kinesis module."
+ locked = TRUE
+ text_gain_indication = null
+ limb_req = null
+ instability = 0
+
+/datum/mutation/human/telekinesis/mod/get_visual_indicator()
+ return
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 18097023bd3..5534628d139 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -1940,7 +1940,7 @@
if(!forced_gravity.len)
SEND_SIGNAL(gravity_turf, COMSIG_TURF_HAS_GRAVITY, src, forced_gravity)
if(forced_gravity.len)
- var/max_grav
+ var/max_grav = forced_gravity[1]
for(var/i in forced_gravity)
max_grav = max(max_grav, i)
return max_grav
diff --git a/code/game/objects/effects/spawners/random/mod.dm b/code/game/objects/effects/spawners/random/mod.dm
new file mode 100644
index 00000000000..06b046811f9
--- /dev/null
+++ b/code/game/objects/effects/spawners/random/mod.dm
@@ -0,0 +1,18 @@
+/obj/effect/spawner/random/mod
+ name = "MOD module spawner"
+ desc = "Modularize this, please."
+ icon_state = "circuit"
+
+/obj/effect/spawner/random/mod/maint
+ name = "maint MOD module spawner"
+ loot = list(
+ /obj/item/mod/module/springlock,
+ /obj/item/mod/module/visor/rave,
+ /obj/item/mod/module/tanner,
+ /obj/item/mod/module/balloon,
+ )
+
+/obj/effect/spawner/random/mod/maint/Initialize(mapload)
+ if(SSmapping.level_trait(z, ZTRAIT_UP) || SSmapping.level_trait(z, ZTRAIT_DOWN))
+ loot += /obj/item/mod/module/atrocinator
+ return ..()
diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm
index a47c57342ca..e8d48825417 100755
--- a/code/game/turfs/turf.dm
+++ b/code/game/turfs/turf.dm
@@ -262,7 +262,10 @@ GLOBAL_LIST_EMPTY(station_turfs)
/// Precipitates a movable (plus whatever buckled to it) to lower z levels if possible and then calls zImpact()
/turf/proc/zFall(atom/movable/falling, levels = 1, force = FALSE, falling_from_move = FALSE)
- var/turf/target = get_step_multiz(src, DOWN)
+ var/direction = DOWN
+ if(falling.has_gravity() == NEGATIVE_GRAVITY)
+ direction = UP
+ var/turf/target = get_step_multiz(src, direction)
if(!target)
return FALSE
var/isliving = isliving(falling)
@@ -275,7 +278,7 @@ GLOBAL_LIST_EMPTY(station_turfs)
falling = falling_living.buckled
if(!falling_from_move && falling.currently_z_moving)
return
- if(!force && !falling.can_z_move(DOWN, src, target, ZMOVE_FALL_FLAGS))
+ if(!force && !falling.can_z_move(direction, src, target, ZMOVE_FALL_FLAGS))
falling.set_currently_z_moving(FALSE, TRUE)
return FALSE
diff --git a/code/modules/client/client_colour.dm b/code/modules/client/client_colour.dm
index fa68908999e..325b5d88955 100644
--- a/code/modules/client/client_colour.dm
+++ b/code/modules/client/client_colour.dm
@@ -207,6 +207,9 @@
..()
addtimer(CALLBACK(src, .proc/update_colour, list(1,0,0,0.8,0.2,0, 0.8,0,0.2,0.1,0,0), 10, SINE_EASING|EASE_OUT), 1)
+/datum/client_colour/rave
+ priority = PRIORITY_LOW
+
#undef PRIORITY_ABSOLUTE
#undef PRIORITY_HIGH
#undef PRIORITY_NORMAL
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index be2213b33df..1385de42e89 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -988,25 +988,39 @@
/mob/living/proc/get_visible_name()
return name
-/mob/living/update_gravity(has_gravity)
+/mob/living/update_gravity(gravity)
. = ..()
if(!SSticker.HasRoundStarted())
return
var/was_weightless = alerts["gravity"] && istype(alerts["gravity"], /atom/movable/screen/alert/weightless)
- if(has_gravity)
- if(has_gravity == 1)
+ var/was_negative = alerts["gravity"] && istype(alerts["gravity"], /atom/movable/screen/alert/negative)
+ switch(gravity)
+ if(NEGATIVE_GRAVITY_RANGE)
+ throw_alert("gravity", /atom/movable/screen/alert/negative)
+ if(!was_negative)
+ var/matrix/flipped_matrix = transform
+ flipped_matrix.b = -flipped_matrix.b
+ flipped_matrix.e = -flipped_matrix.e
+ animate(src, transform = flipped_matrix, pixel_y = pixel_y+4, time = 0.5 SECONDS, easing = EASE_OUT)
+ base_pixel_y += 4
+ if(WEIGHTLESS_RANGE)
+ throw_alert("gravity", /atom/movable/screen/alert/weightless)
+ if(!was_weightless)
+ ADD_TRAIT(src, TRAIT_MOVE_FLOATING, NO_GRAVITY_TRAIT)
+ if(STANDRARD_GRAVITY_RANGE)
clear_alert("gravity")
- else
- if(has_gravity >= GRAVITY_DAMAGE_THRESHOLD)
- throw_alert("gravity", /atom/movable/screen/alert/veryhighgravity)
- else
- throw_alert("gravity", /atom/movable/screen/alert/highgravity)
- if(was_weightless)
- REMOVE_TRAIT(src, TRAIT_MOVE_FLOATING, NO_GRAVITY_TRAIT)
- else
- throw_alert("gravity", /atom/movable/screen/alert/weightless)
- if(!was_weightless)
- ADD_TRAIT(src, TRAIT_MOVE_FLOATING, NO_GRAVITY_TRAIT)
+ if(HIGH_GRAVITY_RANGE)
+ throw_alert("gravity", /atom/movable/screen/alert/highgravity)
+ if(CRUSHING_GRAVITY_RANGE)
+ throw_alert("gravity", /atom/movable/screen/alert/veryhighgravity)
+ if(!(gravity in WEIGHTLESS_RANGE) && was_weightless)
+ REMOVE_TRAIT(src, TRAIT_MOVE_FLOATING, NO_GRAVITY_TRAIT)
+ if(!(gravity in NEGATIVE_GRAVITY_RANGE) && was_negative)
+ var/matrix/flipped_matrix = transform
+ flipped_matrix.b = -flipped_matrix.b
+ flipped_matrix.e = -flipped_matrix.e
+ animate(src, transform = flipped_matrix, pixel_y = pixel_y-4, time = 0.5 SECONDS, easing = EASE_OUT)
+ base_pixel_y -= 4
/mob/living/singularity_pull(S, current_size)
..()
diff --git a/code/modules/mod/mod_actions.dm b/code/modules/mod/mod_actions.dm
index f356a675771..e3d7ba6fc5d 100644
--- a/code/modules/mod/mod_actions.dm
+++ b/code/modules/mod/mod_actions.dm
@@ -97,7 +97,7 @@
var/mob/pinner
/datum/action/item_action/mod/pinned_module/New(Target, obj/item/mod/module/linked_module, mob/user)
- if(user == mod.ai)
+ if(isAI(user))
ai_action = TRUE
..()
module = linked_module
diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm
index c8fad5abec8..52a6897fec2 100644
--- a/code/modules/mod/mod_activation.dm
+++ b/code/modules/mod/mod_activation.dm
@@ -1,4 +1,3 @@
-#define MOD_ACTIVATION_STEP_TIME 2 SECONDS
#define MOD_ACTIVATION_STEP_FLAGS IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM|IGNORE_INCAPACITATED
/// Creates a radial menu from which the user chooses parts of the suit to deploy/retract. Repeats until all parts are extended or retracted.
@@ -122,30 +121,31 @@
module.on_deactivation()
activating = TRUE
to_chat(wearer, span_notice("MODsuit [active ? "shutting down" : "starting up"]."))
- if(do_after(wearer, MOD_ACTIVATION_STEP_TIME, wearer, MOD_ACTIVATION_STEP_FLAGS))
+ if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS))
to_chat(wearer, span_notice("[boots] [active ? "relax their grip on your legs" : "seal around your feet"]."))
playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
seal_part(boots, seal = !active)
- if(do_after(wearer, MOD_ACTIVATION_STEP_TIME, wearer, MOD_ACTIVATION_STEP_FLAGS))
+ if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS))
to_chat(wearer, span_notice("[gauntlets] [active ? "become loose around your fingers" : "tighten around your fingers and wrists"]."))
playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
seal_part(gauntlets, seal = !active)
- if(do_after(wearer, MOD_ACTIVATION_STEP_TIME, wearer, MOD_ACTIVATION_STEP_FLAGS))
+ if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS))
to_chat(wearer, span_notice("[chestplate] [active ? "releases your chest" : "cinches tightly against your chest"]."))
playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
seal_part(chestplate,seal = !active)
- if(do_after(wearer, MOD_ACTIVATION_STEP_TIME, wearer, MOD_ACTIVATION_STEP_FLAGS))
+ if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS))
to_chat(wearer, span_notice("[helmet] hisses [active ? "open" : "closed"]."))
playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
seal_part(helmet, seal = !active)
- if(do_after(wearer, MOD_ACTIVATION_STEP_TIME, wearer, MOD_ACTIVATION_STEP_FLAGS))
+ if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS))
to_chat(wearer, span_notice("Systems [active ? "shut down. Parts unsealed. Goodbye" : "started up. Parts sealed. Welcome"], [wearer]."))
if(ai)
to_chat(ai, span_notice("SYSTEMS [active ? "DEACTIVATED. GOODBYE" : "ACTIVATED. WELCOME"]: \"[ai]\""))
finish_activation(on = !active)
if(active)
playsound(src, 'sound/machines/synth_yes.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 6000)
- SEND_SOUND(wearer, sound('sound/mecha/nominal.ogg',volume=50))
+ if(!malfunctioning)
+ SEND_SOUND(wearer, sound('sound/mecha/nominal.ogg', volume = 50))
else
playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 6000)
activating = FALSE
@@ -217,5 +217,4 @@
seal_part(part, seal = TRUE)
finish_activation(on = TRUE)
-#undef MOD_ACTIVATION_STEP_TIME
#undef MOD_ACTIVATION_STEP_FLAGS
diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm
index 749706a0a53..ca6e614c425 100644
--- a/code/modules/mod/mod_control.dm
+++ b/code/modules/mod/mod_control.dm
@@ -61,6 +61,8 @@
var/slowdown_inactive = 1.25
/// Slowdown of the MOD when active.
var/slowdown_active = 0.75
+ /// How long this MOD takes each part to seal.
+ var/activation_step_time = MOD_ACTIVATION_STEP_TIME
/// Extended description of the theme.
var/extended_desc
/// MOD cell.
@@ -216,7 +218,7 @@
/obj/item/mod/control/examine_more(mob/user)
. = ..()
- . += extended_desc
+ . += "[extended_desc]"
/obj/item/mod/control/process(delta_time)
if(seconds_electrified > MACHINE_NOT_ELECTRIFIED)
@@ -424,8 +426,6 @@
/obj/item/mod/control/worn_overlays(mutable_appearance/standing, isinhands = FALSE, icon_file)
. = ..()
- if(!active)
- return
for(var/obj/item/mod/module/module as anything in modules)
var/list/module_icons = module.generate_worn_overlay(standing)
if(!length(module_icons))
diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm
index d8ecd760566..b69d7864eb0 100644
--- a/code/modules/mod/mod_theme.dm
+++ b/code/modules/mod/mod_theme.dm
@@ -101,7 +101,7 @@
desc = "An engineer-fit suit with heat and shock resistance. Nakamura Engineering's classic."
extended_desc = "A classic by Nakamura Engineering, and surely their claim to fame. This model is an \
improvement upon the first-generation prototype models from before the Void War, boasting an array of features. \
- The modular flexibility of the base design has been combined with an blast-dampening insulated inner layer and \
+ The modular flexibility of the base design has been combined with a blast-dampening insulated inner layer and \
a shock-resistant outer layer, making the suit nigh-invulnerable against even the extremes of high-voltage electricity. \
However, the capacity for modification remains the same as civilian-grade suits."
default_skin = "engineering"
@@ -156,7 +156,7 @@
HELMET_LAYER = NECK_LAYER,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT,
- SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDESNOUT,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR,
UNSEALED_COVER = HEADCOVERSMOUTH,
@@ -199,7 +199,7 @@
HELMET_LAYER = NECK_LAYER,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT,
- SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -281,7 +281,7 @@
HELMET_LAYER = NECK_LAYER,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT,
- SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -304,7 +304,7 @@
HELMET_LAYER = NECK_LAYER,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT,
- SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -347,7 +347,7 @@
HELMET_LAYER = NECK_LAYER,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT,
- SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -392,7 +392,7 @@
HELMET_LAYER = null,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
- SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
),
@@ -650,7 +650,7 @@
HELMET_LAYER = null,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT,
- SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -782,7 +782,7 @@
HELMET_LAYER = NECK_LAYER,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT,
- SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
@@ -805,7 +805,7 @@
HELMET_LAYER = null,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
- SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE|HIDEHAIR|HIDESNOUT,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
),
@@ -925,7 +925,7 @@
HELMET_LAYER = null,
HELMET_FLAGS = list(
UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL,
- SEALED_CLOTHING = STOPSPRESSUREDAMAGE,
+ SEALED_CLOTHING = STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEEARS|HIDEHAIR|HIDESNOUT,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE,
UNSEALED_COVER = HEADCOVERSMOUTH,
@@ -966,7 +966,7 @@
"debug" = list(
HELMET_LAYER = null,
HELMET_FLAGS = list(
- UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL|STOPSPRESSUREDAMAGE,
+ UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL|STOPSPRESSUREDAMAGE|BLOCK_GAS_SMOKE_EFFECT,
UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEEARS|HIDEHAIR|HIDESNOUT,
SEALED_INVISIBILITY = HIDEMASK|HIDEEARS|HIDEEYES|HIDEFACE,
UNSEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF,
diff --git a/code/modules/mod/modules/_module.dm b/code/modules/mod/modules/_module.dm
index e3cb516bd14..c86d7f17683 100644
--- a/code/modules/mod/modules/_module.dm
+++ b/code/modules/mod/modules/_module.dm
@@ -1,3 +1,4 @@
+///MOD module - A special device installed in a MODsuit allowing the suit to do new stuff.
/obj/item/mod/module
name = "MOD module"
icon_state = "module"
@@ -232,6 +233,8 @@
/// Generates an icon to be used for the suit's worn overlays
/obj/item/mod/module/proc/generate_worn_overlay(mutable_appearance/standing)
. = list()
+ if(!mod.active)
+ return
var/used_overlay
if(overlay_state_use && !COOLDOWN_FINISHED(src, cooldown_timer))
used_overlay = overlay_state_use
diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm
index 41166837096..870b13bf465 100644
--- a/code/modules/mod/modules/modules_antag.dm
+++ b/code/modules/mod/modules/modules_antag.dm
@@ -1,7 +1,6 @@
//Antag modules for MODsuits
-//Armor Booster
-
+///Armor Booster - Grants your suit more armor and speed in exchange for EVA protection.
/obj/item/mod/module/armor_booster
name = "MOD armor booster module"
desc = "A retrofitted series of retractable armor plates, allowing the suit to function as essentially power armor, \
@@ -16,9 +15,13 @@
cooldown_time = 0.5 SECONDS
overlay_state_inactive = "module_armorbooster_off"
overlay_state_active = "module_armorbooster_on"
+ /// Whether or not this module removes pressure protection.
var/remove_pressure_protection = TRUE
+ /// Slowdown added to the suit.
var/added_slowdown = -0.5
+ /// Armor values added to the suit parts.
var/list/armor_values = list(MELEE = 40, BULLET = 50, LASER = 30, ENERGY = 40)
+ /// List of parts of the suit that are spaceproofed, for giving them back the pressure protection.
var/list/spaceproofed = list()
/obj/item/mod/module/armor_booster/generate_worn_overlay(mutable_appearance/standing)
@@ -72,8 +75,7 @@
armor_values = list(MELEE = 60, BULLET = 60, LASER = 50, ENERGY = 60)
added_slowdown = -0.25
-//Energy Shield
-
+///Energy Shield - Gives you a rechargeable energy shield that nullifies attacks.
/obj/item/mod/module/energy_shield
name = "MOD energy shield module"
desc = "A personal, protective forcefield typically seen in military applications. \
@@ -85,14 +87,23 @@
idle_power_cost = DEFAULT_CELL_DRAIN * 0.5
use_power_cost = DEFAULT_CELL_DRAIN * 2
incompatible_modules = list(/obj/item/mod/module/energy_shield)
+ /// Max charges of the shield.
var/max_charges = 3
+ /// The time it takes for the first charge to recover.
var/recharge_start_delay = 20 SECONDS
+ /// How much time it takes for charges to recover after they started recharging.
var/charge_increment_delay = 1 SECONDS
+ /// How much charge is recovered per recovery.
var/charge_recovery = 1
+ /// Whether or not this shield can lose multiple charges.
var/lose_multiple_charges = FALSE
+ /// The item path to recharge this shielkd.
var/recharge_path = null
+ /// The icon file of the shield.
var/shield_icon_file = 'icons/effects/effects.dmi'
+ /// The icon_state of the shield.
var/shield_icon = "shield-red"
+ /// Charges the shield should start with.
var/charges
/obj/item/mod/module/energy_shield/Initialize(mapload)
@@ -132,8 +143,7 @@
shield_icon = "mageshield"
recharge_path = /obj/item/wizard_armour_charge
-//Magic Nullifier
-
+///Magic Nullifier - Protects you from magic.
/obj/item/mod/module/anti_magic
name = "MOD magic nullifier module"
desc = "A series of obsidian rods installed into critical points around the suit, \
@@ -167,8 +177,7 @@
/obj/item/mod/module/anti_magic/wizard/on_suit_deactivation()
REMOVE_TRAIT(mod.wearer, TRAIT_ANTIMAGIC_NO_SELFBLOCK, MOD_TRAIT)
-//Insignia
-
+///Insignia - Gives you a skin specific stripe.
/obj/item/mod/module/insignia
name = "MOD insignia module"
desc = "Despite the existence of IFF systems, radio communique, and modern methods of deductive reasoning involving \
@@ -178,7 +187,7 @@
icon_state = "insignia"
removable = FALSE
incompatible_modules = list(/obj/item/mod/module/insignia)
- overlay_state_inactive = "insignia"
+ overlay_state_inactive = "module_insignia"
/obj/item/mod/module/insignia/generate_worn_overlay(mutable_appearance/standing)
overlay_state_inactive = "[initial(overlay_state_inactive)]-[mod.skin]"
@@ -207,6 +216,7 @@
/obj/item/mod/module/insignia/chaplain
color = "#f0a00c"
+///Anti Slip - Prevents you from slipping on water.
/obj/item/mod/module/noslip
name = "MOD anti slip module"
desc = "These are a modified variant of standard magnetic boots, utilizing piezoelectric crystals on the soles. \
diff --git a/code/modules/mod/modules/modules_engineering.dm b/code/modules/mod/modules/modules_engineering.dm
index 5e79b43f0b3..0169caa0c0f 100644
--- a/code/modules/mod/modules/modules_engineering.dm
+++ b/code/modules/mod/modules/modules_engineering.dm
@@ -1,7 +1,6 @@
//Engineering modules for MODsuits
-//Welding Protection
-
+///Welding Protection - Makes the helmet protect from flashes and welding.
/obj/item/mod/module/welding
name = "MOD welding protection module"
desc = "A module installed into the visor of the suit, this projects a \
@@ -18,8 +17,7 @@
/obj/item/mod/module/welding/on_suit_deactivation()
mod.helmet.flash_protect = initial(mod.helmet.flash_protect)
-//T-Ray Scan
-
+///T-Ray Scan - Scans the terrain for undertile objects.
/obj/item/mod/module/t_ray
name = "MOD t-ray scan module"
desc = "A module installed into the visor of the suit, allowing the user to use a pulse of terahertz radiation \
@@ -31,13 +29,13 @@
active_power_cost = DEFAULT_CELL_DRAIN * 0.2
incompatible_modules = list(/obj/item/mod/module/t_ray)
cooldown_time = 0.5 SECONDS
+ /// T-ray scan range.
var/range = 2
/obj/item/mod/module/t_ray/on_active_process(delta_time)
- t_ray_scan(mod.wearer, 8, range)
-
-//Magnetic Stability
+ t_ray_scan(mod.wearer, 0.8 SECONDS, range)
+///Magnetic Stability - Gives the user a slowdown but makes them negate gravity and be immune to slips.
/obj/item/mod/module/magboot
name = "MOD magnetic stability module"
desc = "These are powerful electromagnets fitted into the suit's boots, allowing users both \
@@ -48,8 +46,9 @@
module_type = MODULE_TOGGLE
complexity = 2
active_power_cost = DEFAULT_CELL_DRAIN * 0.5
- incompatible_modules = list(/obj/item/mod/module/magboot)
+ incompatible_modules = list(/obj/item/mod/module/magboot, /obj/item/mod/module/atrocinator)
cooldown_time = 0.5 SECONDS
+ /// Slowdown added onto the suit.
var/slowdown_active = 0.5
/obj/item/mod/module/magboot/on_activation()
@@ -78,8 +77,7 @@
complexity = 0
slowdown_active = 0
-//Emergency Tether
-
+///Emergency Tether - Shoots a grappling hook projectile in 0g that throws the user towards it.
/obj/item/mod/module/tether
name = "MOD emergency tether module"
desc = "A custom-built grappling-hook powered by a winch capable of hauling the user. \
@@ -106,6 +104,7 @@
var/obj/projectile/tether = new /obj/projectile/tether(mod.wearer.loc)
tether.preparePixelProjectile(target, mod.wearer)
tether.firer = mod.wearer
+ playsound(src, 'sound/weapons/batonextend.ogg', 25, TRUE)
INVOKE_ASYNC(tether, /obj/projectile.proc/fire)
drain_power(use_power_cost)
@@ -137,8 +136,7 @@
QDEL_NULL(line)
return ..()
-//Radiation Protection
-
+///Radiation Protection - Protects the user from radiation, gives them a geiger counter and rad info in the panel.
/obj/item/mod/module/rad_protection
name = "MOD radiation protection module"
desc = "A module utilizing polymers and reflective shielding to protect the user against ionizing radiation; \
@@ -149,6 +147,7 @@
idle_power_cost = DEFAULT_CELL_DRAIN * 0.3
incompatible_modules = list(/obj/item/mod/module/rad_protection)
tgui_id = "rad_counter"
+ /// Radiation threat level being perceived.
var/perceived_threat_level
/obj/item/mod/module/rad_protection/on_suit_activation()
@@ -169,6 +168,7 @@
. = ..()
.["userradiated"] = mod.wearer ? HAS_TRAIT(mod.wearer, TRAIT_IRRADIATED) : 0
.["usertoxins"] = mod.wearer ? mod.wearer.getToxLoss() : 0
+ .["usermaxtoxins"] = mod.wearer ? mod.wearer.getMaxHealth() : 0
.["threatlevel"] = perceived_threat_level
/obj/item/mod/module/rad_protection/proc/on_pre_potential_irradiation(datum/source, datum/radiation_pulse_information/pulse_information, insulation_to_target)
@@ -177,8 +177,7 @@
perceived_threat_level = get_perceived_radiation_danger(pulse_information, insulation_to_target)
addtimer(VARSET_CALLBACK(src, perceived_threat_level, null), TIME_WITHOUT_RADIATION_BEFORE_RESET, TIMER_UNIQUE | TIMER_OVERRIDE)
-//Constructor
-
+///Constructor - Lets you build quicker and create RCD holograms.
/obj/item/mod/module/constructor
name = "MOD constructor module"
desc = "This module entirely occupies the wearer's forearm, notably causing conflict with \
@@ -205,3 +204,44 @@
return
rcd_scan(src, fade_time = 10 SECONDS)
drain_power(use_power_cost)
+
+///Kinesis - Gives you a special form of telekinesis.
+/obj/item/mod/module/kinesis //TODO POST-MERGE MAKE NOT SUCK ASS, MAKE BALLER AS FUCK
+ name = "MOD kinesis module"
+ desc = "A modular plug-in to the forearm, this module was presumed lost for many years, \
+ despite the suits it used to be mounted on still seeing some circulation. \
+ This piece of technology allows the user to generate precise anti-gravity fields, \
+ letting them move objects as small as a titanium rod to as large as industrial machinery. \
+ Oddly enough, it doesn't seem to work on living creatures."
+ icon_state = "kinesis"
+// module_type = MODULE_ACTIVE
+ module_type = MODULE_TOGGLE
+// complexity = 3
+ complexity = 0
+ active_power_cost = DEFAULT_CELL_DRAIN*0.75
+// use_power_cost = DEFAULT_CELL_DRAIN*3
+ removable = FALSE
+ incompatible_modules = list(/obj/item/mod/module/kinesis)
+ cooldown_time = 0.5 SECONDS
+ overlay_state_inactive = "module_kinesis"
+ overlay_state_active = "module_kinesis_on"
+ /// Whether the user had TK previously or not.
+ var/has_tk = FALSE
+
+/obj/item/mod/module/kinesis/on_activation()
+ . = ..()
+ if(!.)
+ return
+ if(mod.wearer.dna.check_mutation(TK))
+ has_tk = TRUE
+ return
+ mod.wearer.dna.add_mutation(TK_MOD)
+
+/obj/item/mod/module/kinesis/on_deactivation()
+ . = ..()
+ if(!.)
+ return
+ if(has_tk)
+ has_tk = FALSE
+ return
+ mod.wearer.dna.remove_mutation(TK_MOD)
diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm
index 1f4dd028f5b..35763ddd2b9 100644
--- a/code/modules/mod/modules/modules_general.dm
+++ b/code/modules/mod/modules/modules_general.dm
@@ -1,7 +1,6 @@
//General modules for MODsuits
-//Storage
-
+///Storage - Adds a storage component to the suit.
/obj/item/mod/module/storage
name = "MOD storage module"
desc = "What amounts to a series of integrated storage compartments and specialized pockets installed across \
@@ -9,9 +8,13 @@
icon_state = "storage"
complexity = 3
incompatible_modules = list(/obj/item/mod/module/storage)
+ /// The storage component of the module.
var/datum/component/storage/concrete/storage
+ /// Max weight class of items in the storage.
var/max_w_class = WEIGHT_CLASS_NORMAL
+ /// Max combined weight of all items in the storage.
var/max_combined_w_class = 15
+ /// Max amount of items in the storage.
var/max_items = 7
/obj/item/mod/module/storage/Initialize(mapload)
@@ -64,8 +67,7 @@
max_items = 21
-//Ion Jetpack
-
+///Ion Jetpack - Lets the user fly freely through space using battery charge.
/obj/item/mod/module/jetpack
name = "MOD ion jetpack module"
desc = "A series of electric thrusters installed across the suit, this is a module highly anticipated by trainee Engineers. \
@@ -80,8 +82,11 @@
cooldown_time = 0.5 SECONDS
overlay_state_inactive = "module_jetpack"
overlay_state_active = "module_jetpack_on"
+ /// Do we stop the wearer from gliding in space.
var/stabilizers = FALSE
+ /// Do we give the wearer a speed buff.
var/full_speed = FALSE
+ /// The ion trail particles left after the jetpack.
var/datum/effect_system/trail_follow/ion/ion_trail
/obj/item/mod/module/jetpack/Initialize(mapload)
@@ -158,25 +163,28 @@
ion_trail.generate_effect()
return TRUE
-//Eating Apparatus
-
+///Eating Apparatus - Lets the user eat/drink with the suit on.
/obj/item/mod/module/mouthhole
name = "MOD eating apparatus module"
desc = "A favorite by Miners, this modification to the helmet utilizes a nanotechnology barrier infront of the mouth \
- to allow eating and drinking while retaining protection and atmosphere. \
- However, it will do nothing to improve the taste of a goliath steak."
+ to allow eating and drinking while retaining protection and atmosphere. However, it won't free you from masks, \
+ and it will do nothing to improve the taste of a goliath steak."
icon_state = "apparatus"
complexity = 1
incompatible_modules = list(/obj/item/mod/module/mouthhole)
overlay_state_inactive = "module_apparatus"
+ /// Former flags of the helmet.
var/former_flags = NONE
+ /// Former visor flags of the helmet.
var/former_visor_flags = NONE
/obj/item/mod/module/mouthhole/on_install()
former_flags = mod.helmet.flags_cover
former_visor_flags = mod.helmet.visor_flags_cover
- mod.helmet.flags_cover &= ~HEADCOVERSMOUTH
- mod.helmet.visor_flags_cover &= ~HEADCOVERSMOUTH
+ if(!(former_flags & HEADCOVERSMOUTH))
+ mod.helmet.flags_cover &= ~HEADCOVERSMOUTH
+ if(!(former_visor_flags & HEADCOVERSMOUTH))
+ mod.helmet.visor_flags_cover &= ~HEADCOVERSMOUTH
/obj/item/mod/module/mouthhole/on_uninstall()
if(!(former_flags & HEADCOVERSMOUTH))
@@ -184,8 +192,7 @@
if(!(former_visor_flags & HEADCOVERSMOUTH))
mod.helmet.visor_flags_cover |= HEADCOVERSMOUTH
-//EMP Shield
-
+///EMP Shield - Protects the suit from EMPs.
/obj/item/mod/module/emp_shield
name = "MOD EMP shield module"
desc = "A field inhibitor installed into the suit, protecting it against feedback such as \
@@ -202,8 +209,7 @@
/obj/item/mod/module/emp_shield/on_uninstall()
mod.RemoveElement(/datum/element/empprotection, EMP_PROTECT_SELF|EMP_PROTECT_WIRES|EMP_PROTECT_CONTENTS)
-//Flashlight
-
+///Flashlight - Gives the suit a customizable flashlight.
/obj/item/mod/module/flashlight
name = "MOD flashlight module"
desc = "A simple pair of flashlights installed on the left and right sides of the helmet, \
@@ -221,8 +227,11 @@
light_range = 3
light_power = 1
light_on = FALSE
+ /// Cell drain per range amount.
var/base_power = DEFAULT_CELL_DRAIN * 0.1
+ /// Minimum range we can set.
var/min_range = 2
+ /// Maximum range we can set.
var/max_range = 5
/obj/item/mod/module/flashlight/on_activation()
@@ -274,8 +283,7 @@
if("light_range")
set_light_range(clamp(value, min_range, max_range))
-//Dispenser
-
+///Dispenser - Dispenses an item after a time passes.
/obj/item/mod/module/dispenser
name = "MOD burger dispenser module"
desc = "A rare piece of technology reverse-engineered from a prototype found in a Donk Corporation vessel. \
@@ -288,7 +296,9 @@
use_power_cost = DEFAULT_CELL_DRAIN * 2
incompatible_modules = list(/obj/item/mod/module/dispenser)
cooldown_time = 5 SECONDS
+ /// Path we dispense.
var/dispense_type = /obj/item/food/burger/plain
+ /// Time it takes for us to dispense.
var/dispense_time = 0 SECONDS
/obj/item/mod/module/dispenser/on_use()
@@ -297,15 +307,14 @@
return
if(dispense_time && !do_after(mod.wearer, dispense_time, target = mod))
balloon_alert(mod.wearer, "interrupted!")
- return
+ return FALSE
var/obj/item/dispensed = new dispense_type(mod.wearer.loc)
mod.wearer.put_in_hands(dispensed)
balloon_alert(mod.wearer, "[dispensed] dispensed")
playsound(src, 'sound/machines/click.ogg', 100, TRUE)
drain_power(use_power_cost)
-//Longfall
-
+///Longfall - Nullifies fall damage, removing charge instead.
/obj/item/mod/module/longfall
name = "MOD longfall module"
desc = "Useful for protecting both the suit and the wearer, \
@@ -331,8 +340,7 @@
to_chat(mod.wearer, span_notice("[src] protects you from the damage!"))
return NO_Z_IMPACT_DAMAGE
-//Thermal Regulator
-
+///Thermal Regulator - Regulates the wearer's core temperature.
/obj/item/mod/module/thermal_regulator
name = "MOD thermal regulator module"
desc = "Advanced climate control, using an inner body glove interwoven with thousands of tiny, \
@@ -344,8 +352,11 @@
active_power_cost = DEFAULT_CELL_DRAIN * 0.3
incompatible_modules = list(/obj/item/mod/module/thermal_regulator)
cooldown_time = 0.5 SECONDS
+ /// The temperature we are regulating to.
var/temperature_setting = BODYTEMP_NORMAL
+ /// Minimum temperature we can set.
var/min_temp = 293.15
+ /// Maximum temperature we can set.
var/max_temp = 318.15
/obj/item/mod/module/thermal_regulator/get_configuration()
@@ -360,8 +371,7 @@
/obj/item/mod/module/thermal_regulator/on_active_process(delta_time)
mod.wearer.adjust_bodytemperature(get_temp_change_amount((temperature_setting - mod.wearer.bodytemperature), 0.08 * delta_time))
-//Pathfinder
-
+///Pathfinder - Can fly the suit from a long distance to an implant installed in someone.
/obj/item/mod/module/pathfinder
name = "MOD pathfinder module"
desc = "This module, brought to you by Nakamura Engineering, has two components. \
@@ -376,6 +386,7 @@
complexity = 2
use_power_cost = DEFAULT_CELL_DRAIN * 10
incompatible_modules = list(/obj/item/mod/module/pathfinder)
+ /// The pathfinding implant.
var/obj/item/implant/mod/implant
/obj/item/mod/module/pathfinder/Initialize(mapload)
@@ -429,7 +440,9 @@
name = "MOD pathfinder implant"
desc = "Lets you recall a MODsuit to you at any time."
actions_types = list(/datum/action/item_action/mod_recall)
+ /// The pathfinder module we are linked to.
var/obj/item/mod/module/pathfinder/module
+ /// The jet icon we apply to the MOD.
var/image/jet_icon
/obj/item/implant/mod/Initialize(mapload)
@@ -509,7 +522,9 @@
background_icon_state = "bg_tech_blue"
icon_icon = 'icons/mob/actions/actions_mod.dmi'
button_icon_state = "recall"
+ /// The cooldown for the recall.
COOLDOWN_DECLARE(recall_cooldown)
+ /// The implant we are linked to.
var/obj/item/implant/mod/implant
/datum/action/item_action/mod_recall/New(Target)
@@ -526,8 +541,7 @@
if(implant.recall())
COOLDOWN_START(src, recall_cooldown, 15 SECONDS)
-//DNA Lock
-
+///DNA Lock - Prevents people without the set DNA from activating the suit.
/obj/item/mod/module/dna_lock
name = "MOD DNA lock module"
desc = "A module which engages with the various locks and seals tied to the suit's systems, \
@@ -539,6 +553,7 @@
use_power_cost = DEFAULT_CELL_DRAIN * 3
incompatible_modules = list(/obj/item/mod/module/dna_lock)
cooldown_time = 0.5 SECONDS
+ /// The DNA we lock with.
var/dna = null
/obj/item/mod/module/dna_lock/on_install()
@@ -599,8 +614,7 @@
if(!dna_check())
return MOD_CANCEL_REMOVAL
-//Plasma Stabilizer
-
+///Plasma Stabilizer - Prevents plasmamen from igniting in the suit
/obj/item/mod/module/plasma_stabilizer
name = "MOD plasma stabilizer module"
desc = "This system essentially forms an atmosphere of its' own inside the suit, \
@@ -619,42 +633,3 @@
/obj/item/mod/module/plasma_stabilizer/on_unequip()
REMOVE_TRAIT(mod.wearer, TRAIT_NOSELFIGNITION, MOD_TRAIT)
-
-//Kinesis
-
-/obj/item/mod/module/kinesis //TODO POST-MERGE MAKE NOT SUCK ASS, MAKE BALLER AS FUCK
- name = "MOD kinesis module"
- desc = "A modular plug-in to the forearm, this module was presumed lost for many years, \
- despite the suits it used to be mounted on still seeing some circulation. \
- This piece of technology allows the user to generate precise anti-gravity fields, \
- letting them move objects as small as a titanium rod to as large as industrial machinery. \
- Oddly enough, it doesn't seem to work on living creatures."
- icon_state = "kinesis"
-// module_type = MODULE_ACTIVE
- module_type = MODULE_TOGGLE
-// complexity = 3
- complexity = 0
- active_power_cost = DEFAULT_CELL_DRAIN*0.75
-// use_power_cost = DEFAULT_CELL_DRAIN*3
- removable = FALSE
- incompatible_modules = list(/obj/item/mod/module/kinesis)
- cooldown_time = 0.5 SECONDS
- var/has_tk = FALSE
-
-/obj/item/mod/module/kinesis/on_activation()
- . = ..()
- if(!.)
- return
- if(mod.wearer.dna.check_mutation(TK))
- has_tk = TRUE
- else
- mod.wearer.dna.add_mutation(TK)
-
-/obj/item/mod/module/kinesis/on_deactivation()
- . = ..()
- if(!.)
- return
- if(has_tk)
- has_tk = FALSE
- return
- mod.wearer.dna.remove_mutation(TK)
diff --git a/code/modules/mod/modules/modules_maint.dm b/code/modules/mod/modules/modules_maint.dm
new file mode 100644
index 00000000000..e4968d92e3b
--- /dev/null
+++ b/code/modules/mod/modules/modules_maint.dm
@@ -0,0 +1,254 @@
+//Maint modules for MODsuits
+
+///Springlock Mechanism - allows your modsuit to activate faster, but reagents are very dangerous.
+/obj/item/mod/module/springlock
+ name = "MOD springlock module"
+ desc = "A module that spans the entire size of the MOD unit, sitting under the outer shell. \
+ This mechanical exoskeleton pushes out of the way when the user enters and it helps in booting \
+ up, but was taken out of modern suits because of the springlock's tendency to \"snap\" back \
+ into place when exposed to humidity. You know what it's like to have an entire exoskeleton enter you?"
+ icon_state = "springlock"
+ complexity = 3 // it is inside every part of your suit, so
+ incompatible_modules = list(/obj/item/mod/module/springlock)
+
+/obj/item/mod/module/springlock/on_install()
+ mod.activation_step_time *= 0.75
+
+/obj/item/mod/module/springlock/on_uninstall()
+ mod.activation_step_time /= 0.75
+
+/obj/item/mod/module/springlock/on_suit_activation()
+ RegisterSignal(mod.wearer, COMSIG_ATOM_EXPOSE_REAGENTS, .proc/on_wearer_exposed)
+
+/obj/item/mod/module/springlock/on_suit_deactivation()
+ UnregisterSignal(mod.wearer, COMSIG_ATOM_EXPOSE_REAGENTS)
+
+///Signal fired when wearer is exposed to reagents
+/obj/item/mod/module/springlock/proc/on_wearer_exposed(atom/source, list/reagents, datum/reagents/source_reagents, methods, volume_modifier, show_message)
+ SIGNAL_HANDLER
+ if(!(methods & (VAPOR|PATCH|TOUCH)))
+ return //remove non-touch reagent exposure
+ to_chat(mod.wearer, span_danger("[src] makes an ominous click sound..."))
+ playsound(src, 'sound/items/springlock.ogg', 75, TRUE)
+ addtimer(CALLBACK(src, .proc/snap_shut), rand(3 SECONDS, 5 SECONDS))
+ RegisterSignal(mod, COMSIG_MOD_ACTIVATE, .proc/on_activate_spring_block)
+
+///Signal fired when wearer attempts to activate/deactivate suits
+/obj/item/mod/module/springlock/proc/on_activate_spring_block(datum/source, user)
+ SIGNAL_HANDLER
+ balloon_alert(user, "springlocks aren't responding...?")
+ return MOD_CANCEL_ACTIVATE
+
+///Delayed death proc of the suit after the wearer is exposed to reagents
+/obj/item/mod/module/springlock/proc/snap_shut()
+ UnregisterSignal(mod, COMSIG_MOD_ACTIVATE)
+ if(!mod.wearer) //while there is a guaranteed user when on_wearer_exposed() fires, that isn't the same case for this proc
+ return
+ mod.wearer.visible_message("[src] inside [mod.wearer]'s [mod.name] snaps shut, mutilating the user inside!", span_userdanger("*SNAP*"))
+ mod.wearer.emote("scream")
+ playsound(mod.wearer, 'sound/effects/snap.ogg', 75, TRUE, frequency = 0.5)
+ playsound(mod.wearer, 'sound/effects/splat.ogg', 50, TRUE, frequency = 0.5)
+ mod.wearer.apply_damage(500, BRUTE, sharpness = SHARP_POINTY, wound_bonus = -50) //boggers, bogchamp, etc
+ mod.wearer.death() //just in case, for some reason, they're still alive
+ flash_color(mod.wearer, flash_color = "#FF0000", flash_time = 10 SECONDS)
+
+///Rave Visor - Gives you a rainbow visor and plays jukebox music to you.
+/obj/item/mod/module/visor/rave
+ name = "MOD rave visor module"
+ desc = "A Super Cool Awesome Visor (SCAV), intended for modular suits."
+ icon_state = "rave_visor"
+ complexity = 1
+ overlay_state_inactive = "module_rave"
+ /// The client colors applied to the wearer.
+ var/datum/client_colour/rave_screen
+ /// The current element in the rainbow_order list we are on.
+ var/rave_number = 1
+ /// The track we selected to play.
+ var/datum/track/selection
+ /// A list of all the songs we can play.
+ var/list/songs = list()
+ /// A list of the colors the module can take.
+ var/static/list/rainbow_order = list(
+ "#FF6666",
+ "#FFAA66",
+ "#FFFF66",
+ "#66FF66",
+ "#66AAFF",
+ "#AA66FF",
+ )
+
+/obj/item/mod/module/visor/rave/Initialize(mapload)
+ . = ..()
+ var/list/tracks = flist("[global.config.directory]/jukebox_music/sounds/")
+ for(var/sound in tracks)
+ var/datum/track/track = new()
+ track.song_path = file("[global.config.directory]/jukebox_music/sounds/[sound]")
+ var/list/sound_params = splittext(sound,"+")
+ if(length(sound_params) != 3)
+ continue
+ track.song_name = sound_params[1]
+ track.song_length = text2num(sound_params[2])
+ track.song_beat = text2num(sound_params[3])
+ songs[track.song_name] = track
+ if(length(songs))
+ var/song_name = pick(songs)
+ selection = songs[song_name]
+
+/obj/item/mod/module/visor/rave/on_activation()
+ . = ..()
+ if(!.)
+ return
+ rave_screen = mod.wearer.add_client_colour(/datum/client_colour/rave)
+ rave_screen.update_colour(rainbow_order[rave_number])
+ if(selection)
+ mod.wearer.playsound_local(get_turf(src), null, 50, channel = CHANNEL_JUKEBOX, S = sound(selection.song_path), use_reverb = FALSE)
+
+/obj/item/mod/module/visor/rave/on_deactivation()
+ . = ..()
+ if(!.)
+ return
+ QDEL_NULL(rave_screen)
+ if(selection)
+ mod.wearer.stop_sound_channel(CHANNEL_JUKEBOX)
+
+/obj/item/mod/module/visor/rave/generate_worn_overlay(mutable_appearance/standing)
+ . = ..()
+ for(var/mutable_appearance/appearance as anything in .)
+ appearance.color = active ? rainbow_order[rave_number] : null
+
+/obj/item/mod/module/visor/rave/on_active_process(delta_time)
+ rave_number++
+ if(rave_number > length(rainbow_order))
+ rave_number = 1
+ mod.wearer.update_inv_back()
+ rave_screen.update_colour(rainbow_order[rave_number])
+
+/obj/item/mod/module/visor/rave/get_configuration()
+ . = ..()
+ if(length(songs))
+ .["selection"] = add_ui_configuration("Song", "list", selection.song_name, songs)
+
+/obj/item/mod/module/visor/rave/configure_edit(key, value)
+ switch(key)
+ if("selection")
+ if(active)
+ return
+ selection = songs[value]
+
+///Tanner - Tans you with spraytan.
+/obj/item/mod/module/tanner
+ name = "MOD tanning module"
+ desc = "A tanning module for modular suits. Skin cancer functionality has not been ever proven, \
+ although who knows with the rumors..."
+ icon_state = "tanning"
+ module_type = MODULE_USABLE
+ complexity = 1
+ use_power_cost = DEFAULT_CELL_DRAIN * 5
+ incompatible_modules = list(/obj/item/mod/module/tanner)
+ cooldown_time = 30 SECONDS
+
+/obj/item/mod/module/tanner/on_use()
+ . = ..()
+ if(!.)
+ return
+ playsound(src, 'sound/machines/microwave/microwave-end.ogg', 50, TRUE)
+ var/datum/reagents/holder = new()
+ holder.add_reagent(/datum/reagent/spraytan, 10)
+ holder.trans_to(mod.wearer, 10, methods = VAPOR)
+ if(prob(5))
+ SSradiation.irradiate(mod.wearer)
+ drain_power(use_power_cost)
+
+///Balloon Blower - Blows a balloon.
+/obj/item/mod/module/balloon
+ name = "MOD balloon blower module"
+ desc = "A strange module invented years ago by some ingenious mimes. It blows balloons."
+ icon_state = "bloon"
+ module_type = MODULE_USABLE
+ complexity = 1
+ use_power_cost = DEFAULT_CELL_DRAIN*0.5
+ incompatible_modules = list(/obj/item/mod/module/balloon)
+ cooldown_time = 15 SECONDS
+
+/obj/item/mod/module/balloon/on_use()
+ . = ..()
+ if(!.)
+ return
+ if(!do_after(mod.wearer, 10 SECONDS, target = mod))
+ return FALSE
+ mod.wearer.adjustOxyLoss(20)
+ playsound(src, 'sound/items/inflate_bloon.ogg', 50, TRUE)
+ var/obj/item/toy/balloon/balloon = new(get_turf(src))
+ mod.wearer.put_in_hands(balloon)
+ drain_power(use_power_cost)
+
+///Atrocinator - Flips your gravity.
+/obj/item/mod/module/atrocinator
+ name = "MOD atrocinator module"
+ desc = "A mysterious orb that has mysterious effects when inserted in a MODsuit."
+ icon_state = "atrocinator"
+ module_type = MODULE_TOGGLE
+ complexity = 2
+ active_power_cost = DEFAULT_CELL_DRAIN
+ incompatible_modules = list(/obj/item/mod/module/atrocinator, /obj/item/mod/module/magboot)
+ cooldown_time = 0.5 SECONDS
+ overlay_state_inactive = "module_atrocinator"
+ /// How many steps the user has taken since turning the suit on, used for footsteps.
+ var/step_count = 0
+ /// If you use the module on a planetary turf, you fly up. To the sky.
+ var/you_fucked_up = FALSE
+
+/obj/item/mod/module/atrocinator/on_activation()
+ . = ..()
+ if(!.)
+ return
+ playsound(src, 'sound/effects/curseattack.ogg', 50)
+ mod.wearer.AddElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY)
+ RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, .proc/check_upstairs)
+ mod.wearer.update_gravity(mod.wearer.has_gravity())
+ ADD_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT)
+ check_upstairs() //todo at some point flip your screen around
+
+/obj/item/mod/module/atrocinator/on_deactivation()
+ if(you_fucked_up)
+ to_chat(mod.wearer, span_danger("It's too late."))
+ return FALSE
+ . = ..()
+ if(!.)
+ return
+ playsound(src, 'sound/effects/curseattack.ogg', 50)
+ qdel(mod.wearer.RemoveElement(/datum/element/forced_gravity, NEGATIVE_GRAVITY))
+ UnregisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED)
+ step_count = 0
+ mod.wearer.update_gravity(mod.wearer.has_gravity())
+ REMOVE_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT)
+ var/turf/open/openspace/current_turf = get_turf(mod.wearer)
+ if(istype(current_turf))
+ current_turf.zFall(mod.wearer, falling_from_move = TRUE)
+
+/obj/item/mod/module/atrocinator/proc/check_upstairs()
+ SIGNAL_HANDLER
+
+ if(you_fucked_up || mod.wearer.has_gravity() != NEGATIVE_GRAVITY)
+ return
+ var/turf/open/current_turf = get_turf(mod.wearer)
+ var/turf/open/openspace/turf_above = get_step_multiz(mod.wearer, UP)
+ if(current_turf && istype(turf_above))
+ current_turf.zFall(mod.wearer)
+ else if(!turf_above && istype(current_turf) && current_turf.planetary_atmos) //nothing holding you down
+ INVOKE_ASYNC(src, .proc/fly_away)
+ else if(!(step_count % 2))
+ playsound(current_turf, 'sound/items/atrocinator_step.ogg', 50)
+ step_count++
+
+#define FLY_TIME 5 SECONDS
+
+/obj/item/mod/module/atrocinator/proc/fly_away()
+ you_fucked_up = TRUE
+ playsound(src, 'sound/effects/whirthunk.ogg', 75)
+ to_chat(mod.wearer, span_userdanger("That was stupid."))
+ mod.wearer.Stun(FLY_TIME, ignore_canstun = TRUE)
+ animate(mod.wearer, FLY_TIME, pixel_y = 256, alpha = 0)
+ QDEL_IN(mod.wearer, FLY_TIME)
+
+#undef FLY_TIME
diff --git a/code/modules/mod/modules/modules_medical.dm b/code/modules/mod/modules/modules_medical.dm
index bb1e353b7ce..e32d5ed0f4f 100644
--- a/code/modules/mod/modules/modules_medical.dm
+++ b/code/modules/mod/modules/modules_medical.dm
@@ -1,11 +1,10 @@
//Medical modules for MODsuits
-//Health Analyzer
-
#define HEALTH_SCAN "Health"
#define WOUND_SCAN "Wound"
#define CHEM_SCAN "Chemical"
+///Health Analyzer - Gives the user a ranged health analyzer and their health status in the panel.
/obj/item/mod/module/health_analyzer
name = "MOD health analyzer module"
desc = "A module installed into the glove of the suit. This is a high-tech biological scanning suite, \
@@ -18,9 +17,21 @@
use_power_cost = DEFAULT_CELL_DRAIN
incompatible_modules = list(/obj/item/mod/module/health_analyzer)
cooldown_time = 0.5 SECONDS
+ tgui_id = "health_analyzer"
+ /// Scanning mode, changes how we scan something.
var/mode = HEALTH_SCAN
+ /// List of all scanning modes.
var/static/list/modes = list(HEALTH_SCAN, WOUND_SCAN, CHEM_SCAN)
+/obj/item/mod/module/health_analyzer/add_ui_data()
+ . = ..()
+ .["userhealth"] = mod.wearer ? mod.wearer.health : 0
+ .["usermaxhealth"] = mod.wearer ? mod.wearer.getMaxHealth() : 0
+ .["userbrute"] = mod.wearer ? mod.wearer.getBruteLoss() : 0
+ .["userburn"] = mod.wearer ? mod.wearer.getFireLoss() : 0
+ .["usertoxin"] = mod.wearer ? mod.wearer.getToxLoss() : 0
+ .["useroxy"] = mod.wearer ? mod.wearer.getOxyLoss() : 0
+
/obj/item/mod/module/health_analyzer/on_select_use(atom/target)
. = ..()
if(!.)
@@ -49,8 +60,7 @@
#undef WOUND_SCAN
#undef CHEM_SCAN
-//Quick Carry
-
+///Quick Carry - Lets the user carry bodies quicker.
/obj/item/mod/module/quick_carry
name = "MOD quick carry module"
desc = "A suite of advanced servos, redirecting power from the suit's arms to help carry the wounded; \
@@ -79,8 +89,7 @@
REMOVE_TRAIT(mod.wearer, TRAIT_QUICKER_CARRY, MOD_TRAIT)
REMOVE_TRAIT(mod.wearer, TRAIT_FASTMED, MOD_TRAIT)
-//Injector
-
+///Injector - Gives the suit an extendable large-capacity piercing syringe.
/obj/item/mod/module/injector
name = "MOD injector module"
desc = "A module installed into the wrist of the suit, this functions as a high-capacity syringe, \
@@ -105,8 +114,7 @@
volume = 30
inject_flags = INJECT_CHECK_PENETRATE_THICK
-//Organ Thrower
-
+///Organ Thrower - Lets you shoot organs, immediately replacing them if the target has the organ manipulation surgery.
/obj/item/mod/module/organ_thrower
name = "MOD organ thrower module"
desc = "A device recovered from a crashed Interdyne Pharmaceuticals vessel, \
diff --git a/code/modules/mod/modules/modules_science.dm b/code/modules/mod/modules/modules_science.dm
index 62c86b81975..271e31ce416 100644
--- a/code/modules/mod/modules/modules_science.dm
+++ b/code/modules/mod/modules/modules_science.dm
@@ -1,7 +1,6 @@
//Science modules for MODsuits
-//Reagent Scanner
-
+///Reagent Scanner - Lets the user scan reagents.
/obj/item/mod/module/reagent_scanner
name = "MOD reagent scanner module"
desc = "A module based off research-oriented Nanotrasen HUDs, this is capable of scanning the contents of \
diff --git a/code/modules/mod/modules/modules_security.dm b/code/modules/mod/modules/modules_security.dm
index 8daa732ee81..b44a2857412 100644
--- a/code/modules/mod/modules/modules_security.dm
+++ b/code/modules/mod/modules/modules_security.dm
@@ -1,7 +1,6 @@
//Security modules for MODsuits
-//Cloaking
-
+///Cloaking - Lowers the user's visibility, can be interrupted by being touched or attacked.
/obj/item/mod/module/stealth
name = "MOD prototype cloaking module"
desc = "A complete retrofitting of the suit, this is a form of visual concealment tech employing esoteric technology \
@@ -14,7 +13,9 @@
use_power_cost = DEFAULT_CELL_DRAIN * 10
incompatible_modules = list(/obj/item/mod/module/stealth)
cooldown_time = 5 SECONDS
+ /// Whether or not the cloak turns off on bumping.
var/bumpoff = TRUE
+ /// The alpha applied when the cloak is on.
var/stealth_alpha = 50
/obj/item/mod/module/stealth/on_activation()
@@ -74,8 +75,7 @@
use_power_cost = DEFAULT_CELL_DRAIN * 5
cooldown_time = 3 SECONDS
-//Holster
-
+///Holster - Instantly holsters any not huge gun.
/obj/item/mod/module/holster
name = "MOD holster module"
desc = "Based off typical storage compartments, this system allows the suit to holster a \
@@ -88,6 +88,7 @@
use_power_cost = DEFAULT_CELL_DRAIN * 0.5
incompatible_modules = list(/obj/item/mod/module/holster)
cooldown_time = 0.5 SECONDS
+ /// Gun we have holstered.
var/obj/item/gun/holstered
/obj/item/mod/module/holster/on_use()
@@ -102,12 +103,12 @@
if(!istype(holding) || holding.w_class > WEIGHT_CLASS_BULKY)
balloon_alert(mod.wearer, "it doesn't fit!")
return
- if(mod.wearer.transferItemToLoc(holding, src, FALSE, FALSE))
+ if(mod.wearer.transferItemToLoc(holding, src, force = FALSE, silent = TRUE))
holstered = holding
balloon_alert(mod.wearer, "weapon holstered")
playsound(src, 'sound/weapons/gun/revolver/empty.ogg', 100, TRUE)
drain_power(use_power_cost)
- else if(mod.wearer.put_in_active_hand(holstered, FALSE, TRUE))
+ else if(mod.wearer.put_in_active_hand(holstered, forced = FALSE, ignore_animation = TRUE))
balloon_alert(mod.wearer, "weapon drawn")
holstered = null
playsound(src, 'sound/weapons/gun/revolver/empty.ogg', 100, TRUE)
diff --git a/code/modules/mod/modules/modules_service.dm b/code/modules/mod/modules/modules_service.dm
index 2f39492db75..f4f2a1fed41 100644
--- a/code/modules/mod/modules/modules_service.dm
+++ b/code/modules/mod/modules/modules_service.dm
@@ -1,7 +1,6 @@
//Service modules for MODsuits
-//Bike Horn
-
+///Bike Horn - Plays a bike horn sound.
/obj/item/mod/module/bikehorn
name = "MOD bike horn module"
desc = "A shoulder-mounted piece of heavy sonic artillery, this module uses the finest femto-manipulator technology to \
@@ -20,8 +19,7 @@
playsound(src, 'sound/items/bikehorn.ogg', 100, FALSE)
drain_power(use_power_cost)
-//Microwave Beam
-
+///Microwave Beam - Microwaves items instantly.
/obj/item/mod/module/microwave_beam
name = "MOD microwave beam module"
desc = "An oddly domestic device, this module is installed into the user's palm, \
@@ -57,12 +55,11 @@
spark_effect_two.start()
drain_power(use_power_cost)
-//Waddle
-
+//Waddle - Makes you waddle and squeak.
/obj/item/mod/module/waddle
name = "MOD waddle module"
desc = "Some of the most primitive technology in use by HonkCo. This module works off an automatic intention system, \
- utilizing its sensitivity to the pilot's often-limited brainwaves to directly read their next step, \
+ utilizing its' sensitivity to the pilot's often-limited brainwaves to directly read their next step, \
affecting the boots they're installed in. Employing a twin-linked gravitonic drive to create \
miniaturized etheric blasts of space-time beneath the user's feet, this enables them to... \
to waddle around, bouncing to and fro with a pep in their step."
diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm
index 5b6096b9d79..de64a6ba1d5 100644
--- a/code/modules/mod/modules/modules_supply.dm
+++ b/code/modules/mod/modules/modules_supply.dm
@@ -1,7 +1,6 @@
//Supply modules for MODsuits
-//Internal GPS
-
+///Internal GPS - Extends a GPS you can use.
/obj/item/mod/module/gps
name = "MOD internal GPS module"
desc = "This module uses common Nanotrasen technology to calculate the user's position anywhere in space, \
@@ -21,8 +20,7 @@
icon_state = "gps-b"
gpstag = "MOD0"
-//Hydraulic Clamp
-
+///Hydraulic Clamp - Lets you pick up and drop crates.
/obj/item/mod/module/clamp
name = "MOD hydraulic clamp module"
desc = "A series of actuators installed into both arms of the suit, boasting a lifting capacity of almost a ton. \
@@ -34,7 +32,9 @@
use_power_cost = DEFAULT_CELL_DRAIN
incompatible_modules = list(/obj/item/mod/module/clamp)
cooldown_time = 0.5 SECONDS
- var/max_crates = 5
+ /// The max amount of crates you can carry.
+ var/max_crates = 3
+ /// The crates stored in the module.
var/list/stored_crates = list()
/obj/item/mod/module/clamp/on_select_use(atom/target)
@@ -76,8 +76,7 @@
crate.forceMove(drop_location())
stored_crates -= crate
-//Drill
-
+///Drill - Lets you dig through rock and basalt.
/obj/item/mod/module/drill
name = "MOD drill module"
desc = "An integrated drill, typically extending over the user's hand. While useful for drilling through rock, \
@@ -111,6 +110,12 @@
var/turf/closed/mineral/mineral_turf = target
mineral_turf.gets_drilled(mod.wearer)
drain_power(use_power_cost)
+ else if(istype(target, /turf/open/floor/plating/asteroid))
+ var/turf/open/floor/plating/asteroid/sand_turf = target
+ if(!sand_turf.can_dig(mod.wearer))
+ return
+ sand_turf.getDug()
+ drain_power(use_power_cost)
/obj/item/mod/module/drill/proc/bump_mine(mob/living/carbon/human/bumper, atom/bumped_into, proximity)
SIGNAL_HANDLER
@@ -120,8 +125,7 @@
mineral_turf.gets_drilled(mod.wearer)
return COMPONENT_CANCEL_ATTACK_CHAIN
-//Ore Bag
-
+///Ore Bag - Lets you pick up ores and drop them from the suit.
/obj/item/mod/module/orebag
name = "MOD ore bag module"
desc = "An integrated ore storage system installed into the suit, \
@@ -133,6 +137,7 @@
use_power_cost = DEFAULT_CELL_DRAIN * 0.2
incompatible_modules = list(/obj/item/mod/module/orebag)
cooldown_time = 0.5 SECONDS
+ /// The ores stored in the bag.
var/list/ores = list()
/obj/item/mod/module/orebag/on_equip()
diff --git a/code/modules/mod/modules/modules_visor.dm b/code/modules/mod/modules/modules_visor.dm
index 858963cb45f..58bd179c732 100644
--- a/code/modules/mod/modules/modules_visor.dm
+++ b/code/modules/mod/modules/modules_visor.dm
@@ -1,7 +1,6 @@
//Visor modules for MODsuits
-//Base Visor
-
+///Base Visor - Adds a specific HUD and traits to you.
/obj/item/mod/module/visor
name = "MOD visor module"
desc = "A heads-up display installed into the visor of the suit. They say these also let you see behind you."
@@ -10,7 +9,9 @@
active_power_cost = DEFAULT_CELL_DRAIN*0.3
incompatible_modules = list(/obj/item/mod/module/visor)
cooldown_time = 0.5 SECONDS
+ /// The HUD type given by the visor.
var/hud_type
+ /// The traits given by the visor.
var/list/visor_traits = list()
/obj/item/mod/module/visor/on_activation()
@@ -36,7 +37,6 @@
mod.wearer.update_sight()
//Medical Visor
-
/obj/item/mod/module/visor/medhud
name = "MOD medical visor module"
desc = "A heads-up display installed into the visor of the suit. This cross-references suit sensor data with a modern \
@@ -47,7 +47,6 @@
visor_traits = list(TRAIT_MEDICAL_HUD)
//Diagnostic Visor
-
/obj/item/mod/module/visor/diaghud
name = "MOD diagnostic visor module"
desc = "A heads-up display installed into the visor of the suit. This uses a series of advanced sensors to access data \
@@ -58,7 +57,6 @@
visor_traits = list(TRAIT_DIAGNOSTIC_HUD)
//Security Visor
-
/obj/item/mod/module/visor/sechud
name = "MOD security visor module"
desc = "A heads-up display installed into the visor of the suit. This module is a heavily-retrofitted targeting system, \
@@ -69,7 +67,6 @@
visor_traits = list(TRAIT_SECURITY_HUD)
//Meson Visor
-
/obj/item/mod/module/visor/meson
name = "MOD meson visor module"
desc = "A heads-up display installed into the visor of the suit. This module is based off well-loved meson scanner \
@@ -79,7 +76,6 @@
visor_traits = list(TRAIT_MESON_VISION, TRAIT_SUPERMATTER_MADNESS_IMMUNE)
//Thermal Visor
-
/obj/item/mod/module/visor/thermal
name = "MOD thermal visor module"
desc = "A heads-up display installed into the visor of the suit. This uses a small IR scanner to detect and identify \
@@ -89,7 +85,6 @@
visor_traits = list(TRAIT_THERMAL_VISION)
//Night Visor
-
/obj/item/mod/module/visor/night
name = "MOD night visor module"
desc = "A heads-up display installed into the visor of the suit. Typical for both civilian and military applications, \
diff --git a/icons/hud/screen_alert.dmi b/icons/hud/screen_alert.dmi
index bc0a1883ef7..f183772b9d7 100755
Binary files a/icons/hud/screen_alert.dmi and b/icons/hud/screen_alert.dmi differ
diff --git a/icons/mob/mod.dmi b/icons/mob/mod.dmi
index 3781faaf80b..51657f3d425 100644
Binary files a/icons/mob/mod.dmi and b/icons/mob/mod.dmi differ
diff --git a/icons/obj/mod.dmi b/icons/obj/mod.dmi
index 555cf4fce7d..954b4ad1280 100644
Binary files a/icons/obj/mod.dmi and b/icons/obj/mod.dmi differ
diff --git a/sound/items/atrocinator_step.ogg b/sound/items/atrocinator_step.ogg
new file mode 100644
index 00000000000..deda85ac354
Binary files /dev/null and b/sound/items/atrocinator_step.ogg differ
diff --git a/sound/items/inflate_bloon.ogg b/sound/items/inflate_bloon.ogg
new file mode 100644
index 00000000000..9b030d66ced
Binary files /dev/null and b/sound/items/inflate_bloon.ogg differ
diff --git a/sound/items/springlock.ogg b/sound/items/springlock.ogg
new file mode 100644
index 00000000000..8d0013d2630
Binary files /dev/null and b/sound/items/springlock.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index ce43f4b01e6..7e32f96e890 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -1327,6 +1327,7 @@
#include "code\game\objects\effects\spawners\random\food_or_drink.dm"
#include "code\game\objects\effects\spawners\random\maintenance.dm"
#include "code\game\objects\effects\spawners\random\medical.dm"
+#include "code\game\objects\effects\spawners\random\mod.dm"
#include "code\game\objects\effects\spawners\random\random.dm"
#include "code\game\objects\effects\spawners\random\structure.dm"
#include "code\game\objects\effects\spawners\random\techstorage.dm"
@@ -3270,6 +3271,7 @@
#include "code\modules\mod\modules\modules_antag.dm"
#include "code\modules\mod\modules\modules_engineering.dm"
#include "code\modules\mod\modules\modules_general.dm"
+#include "code\modules\mod\modules\modules_maint.dm"
#include "code\modules\mod\modules\modules_medical.dm"
#include "code\modules\mod\modules\modules_science.dm"
#include "code\modules\mod\modules\modules_security.dm"
diff --git a/tgui/packages/tgui/interfaces/MODsuit.js b/tgui/packages/tgui/interfaces/MODsuit.js
index 5d67a4059fc..6224b0e7aa3 100644
--- a/tgui/packages/tgui/interfaces/MODsuit.js
+++ b/tgui/packages/tgui/interfaces/MODsuit.js
@@ -89,6 +89,7 @@ const RadCounter = (props, context) => {
active,
userradiated,
usertoxins,
+ usermaxtoxins,
threatlevel,
} = props;
return (
@@ -101,7 +102,7 @@ const RadCounter = (props, context) => {
{
);
};
+const HealthAnalyzer = (props, context) => {
+ const {
+ active,
+ userhealth,
+ usermaxhealth,
+ userbrute,
+ userburn,
+ usertoxin,
+ useroxy,
+ } = props;
+ return (
+ <>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ >
+ );
+};
+
const ID2MODULE = {
rad_counter: RadCounter,
+ health_analyzer: HealthAnalyzer,
};
const LockedInterface = () => (