mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-18 19:44:58 +01:00
Adds Maintenance MOD Modules! (#63791)
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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("<b>SYSTEMS [active ? "DEACTIVATED. GOODBYE" : "ACTIVATED. WELCOME"]: \"[ai]\"</b>"))
|
||||
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
|
||||
|
||||
@@ -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
|
||||
. += "<i>[extended_desc]</i>"
|
||||
|
||||
/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))
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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. \
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
@@ -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, \
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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, \
|
||||
|
||||
Reference in New Issue
Block a user