diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index df3ea6ba0f6..b2ab053870f 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -95836,10 +95836,10 @@ /area/command/bridge) "utp" = ( /obj/effect/decal/cleanable/dirt, -/obj/machinery/suit_storage_unit/mining/eva, /obj/effect/turf_decal/stripes/line{ dir = 5 }, +/obj/machinery/suit_storage_unit/industrial/loader, /turf/open/floor/iron, /area/cargo/qm) "uty" = ( @@ -98873,6 +98873,7 @@ /obj/machinery/light_switch/directional/north{ pixel_x = -10 }, +/obj/machinery/recharge_station, /turf/open/floor/iron, /area/cargo/storage) "viJ" = ( diff --git a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm index 7aaa6adb814..18972a15050 100644 --- a/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm +++ b/_maps/map_files/IceBoxStation/IcemoonUnderground_Above.dmm @@ -3262,6 +3262,7 @@ /area/service/hydroponics) "kU" = ( /obj/machinery/airalarm/directional/north, +/obj/machinery/suit_storage_unit/industrial/loader, /turf/open/floor/iron/smooth_large, /area/cargo/warehouse) "kV" = ( diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index 9c7c45977d8..ea645f26a51 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -16966,16 +16966,21 @@ /turf/open/floor/iron, /area/security/brig) "bTg" = ( -/obj/effect/turf_decal/bot, -/obj/structure/closet/crate, -/obj/item/clothing/shoes/jackboots{ - pixel_x = 4; - pixel_y = 4 +/obj/machinery/light/directional/south, +/obj/machinery/status_display/ai/directional/south, +/obj/effect/turf_decal/tile/neutral{ + dir = 4 }, -/obj/item/clothing/shoes/jackboots, -/obj/item/clothing/shoes/cowboy/black, -/turf/open/floor/plating, -/area/maintenance/starboard/aft) +/obj/effect/turf_decal/tile/neutral{ + dir = 1 + }, +/obj/effect/turf_decal/bot, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/machinery/suit_storage_unit/industrial/loader, +/turf/open/floor/iron/dark, +/area/cargo/drone_bay) "bTj" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/sign/warning/vacuum/external{ @@ -69010,8 +69015,6 @@ dir = 8 }, /obj/effect/turf_decal/tile/yellow, -/obj/machinery/light/directional/south, -/obj/machinery/status_display/ai/directional/south, /obj/effect/turf_decal/tile/brown, /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -77652,8 +77655,14 @@ /turf/open/floor/plating, /area/cargo/warehouse) "vWT" = ( -/obj/effect/decal/cleanable/dirt, -/obj/effect/spawner/random/structure/grille, +/obj/effect/turf_decal/bot, +/obj/structure/closet/crate, +/obj/item/clothing/shoes/jackboots{ + pixel_x = 4; + pixel_y = 4 + }, +/obj/item/clothing/shoes/jackboots, +/obj/item/clothing/shoes/cowboy/black, /turf/open/floor/plating, /area/maintenance/starboard/aft) "vXv" = ( @@ -79083,6 +79092,11 @@ /obj/machinery/firealarm/directional/east, /turf/open/floor/iron/dark, /area/medical/surgery/room_b) +"wzR" = ( +/obj/machinery/recharge_station, +/obj/effect/turf_decal/trimline/yellow, +/turf/open/floor/plating, +/area/cargo/drone_bay) "wAk" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -124958,7 +124972,7 @@ eZr sly jRU sEx -bEg +bTg bEg xVs mwi @@ -125215,8 +125229,8 @@ evh img jEq gaV -bOC -bTg +wzR +bEg vWT bEg sfF @@ -125472,8 +125486,8 @@ eCi sly qVZ qVZ +sly bEg -bUw bEg bEg bOc diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 4b697a54011..abcc33c180d 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -31306,9 +31306,8 @@ /turf/open/floor/iron/cafeteria, /area/commons/dorms) "iPC" = ( -/obj/effect/spawner/random/maintenance, -/obj/structure/closet/crate/internals, /obj/effect/decal/cleanable/dirt, +/obj/machinery/suit_storage_unit/industrial/loader, /turf/open/floor/iron, /area/cargo/warehouse) "iPD" = ( @@ -39579,6 +39578,7 @@ /obj/structure/rack, /obj/effect/spawner/random/maintenance, /obj/structure/cable, +/obj/effect/spawner/random/maintenance, /turf/open/floor/iron, /area/cargo/warehouse) "lTd" = ( @@ -60232,6 +60232,13 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron, /area/hallway/secondary/entry) +"tca" = ( +/obj/machinery/recharge_station, +/obj/effect/turf_decal/stripes/end{ + dir = 4 + }, +/turf/open/floor/plating, +/area/maintenance/port/fore) "tcf" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -64770,10 +64777,9 @@ /turf/open/floor/iron/dark, /area/command/teleporter) "uJq" = ( +/obj/effect/spawner/random/maintenance, +/obj/structure/closet/crate/internals, /obj/effect/decal/cleanable/dirt, -/obj/structure/rack, -/obj/effect/spawner/random/maintenance, -/obj/effect/spawner/random/maintenance, /turf/open/floor/iron, /area/cargo/warehouse) "uJY" = ( @@ -93502,7 +93508,7 @@ lZy dne hCI doJ -aRG +tca xZo hPP dne diff --git a/_maps/map_files/debug/runtimestation.dmm b/_maps/map_files/debug/runtimestation.dmm index d75f6a68d9e..ef5e244d0d7 100644 --- a/_maps/map_files/debug/runtimestation.dmm +++ b/_maps/map_files/debug/runtimestation.dmm @@ -154,6 +154,7 @@ /area/engineering/gravity_generator) "aH" = ( /obj/machinery/light/directional/east, +/obj/machinery/recharge_station, /turf/open/floor/iron, /area/engineering/main) "aI" = ( @@ -468,6 +469,7 @@ "bK" = ( /obj/structure/table, /obj/item/storage/backpack/holding, +/obj/item/storage/part_replacer/bluespace/tier4, /turf/open/floor/iron, /area/command/bridge) "bL" = ( diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index cece28d8053..b188a42948c 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -39269,7 +39269,7 @@ dir = 1 }, /obj/effect/decal/cleanable/dirt, -/obj/structure/ore_box, +/obj/machinery/recharge_station, /turf/open/floor/iron, /area/cargo/storage) "mIg" = ( @@ -45483,6 +45483,7 @@ /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 10 }, +/obj/structure/ore_box, /turf/open/floor/iron, /area/cargo/storage) "oQs" = ( @@ -57104,6 +57105,7 @@ }, /obj/machinery/airalarm/directional/north, /obj/machinery/light/small/directional/east, +/obj/machinery/suit_storage_unit/industrial/loader, /turf/open/floor/iron, /area/cargo/storage) "tew" = ( diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index ac4f9a0a220..0c7a99bd7b7 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -349,13 +349,12 @@ return TRUE stop_pulling() - SEND_SIGNAL(src, COMSIG_ATOM_START_PULL, pulled_atom, state, force) - if(pulled_atom.pulledby) log_combat(pulled_atom, pulled_atom.pulledby, "pulled from", src) pulled_atom.pulledby.stop_pulling() //an object can't be pulled by two mobs at once. pulling = pulled_atom pulled_atom.set_pulledby(src) + SEND_SIGNAL(src, COMSIG_ATOM_START_PULL, pulled_atom, state, force) setGrabState(state) if(ismob(pulled_atom)) var/mob/pulled_mob = pulled_atom diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm index eeee11af9d2..dd77536452c 100644 --- a/code/game/machinery/suit_storage_unit.dm +++ b/code/game/machinery/suit_storage_unit.dm @@ -136,6 +136,9 @@ icon_state = "industrial" base_icon_state = "industrial" +/obj/machinery/suit_storage_unit/industrial/loader + mod_type = /obj/item/mod/control/pre_equipped/loader + /obj/machinery/suit_storage_unit/Initialize(mapload) . = ..() wires = new /datum/wires/suit_storage_unit(src) diff --git a/code/game/objects/effects/spawners/random/mod.dm b/code/game/objects/effects/spawners/random/mod.dm index 53f10441777..7b5c3cc5852 100644 --- a/code/game/objects/effects/spawners/random/mod.dm +++ b/code/game/objects/effects/spawners/random/mod.dm @@ -6,15 +6,16 @@ /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/item/mod/module/paper_dispenser, - /obj/item/mod/module/hat_stabilizer, + /obj/item/mod/module/springlock = 2, + /obj/item/mod/module/visor/rave = 2, + /obj/item/mod/module/tanner = 1, + /obj/item/mod/module/balloon = 1, + /obj/item/mod/module/paper_dispenser = 1, + /obj/item/mod/module/hat_stabilizer = 2, + /obj/item/mod/module/stamp = 1 ) /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 + loot += list(/obj/item/mod/module/atrocinator = 3) return ..() diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index 41cabc0e899..60bb092d63c 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -62,7 +62,7 @@ contents_thermal_insulation = 0 /// Whether a skittish person can dive inside this closet. Disable if opening the closet causes "bad things" to happen or that it leads to a logical inconsistency. var/divable = TRUE - /// true whenever someone with the strong pull component is dragging this, preventing opening + /// true whenever someone with the strong pull component (or magnet modsuit module) is dragging this, preventing opening var/strong_grab = FALSE ///electronics for access var/obj/item/electronics/airlock/electronics diff --git a/code/modules/jobs/job_types/cargo_technician.dm b/code/modules/jobs/job_types/cargo_technician.dm index 00b2b3ed9b3..7865087e5b3 100644 --- a/code/modules/jobs/job_types/cargo_technician.dm +++ b/code/modules/jobs/job_types/cargo_technician.dm @@ -47,3 +47,8 @@ belt = /obj/item/pda/cargo ears = /obj/item/radio/headset/headset_cargo l_hand = /obj/item/export_scanner + +/datum/outfit/job/cargo_tech/mod + name = "Cargo Technician (MODsuit)" + + back = /obj/item/mod/control/pre_equipped/loader diff --git a/code/modules/jobs/job_types/research_director.dm b/code/modules/jobs/job_types/research_director.dm index e5f2dfe3b28..0f67c0452da 100644 --- a/code/modules/jobs/job_types/research_director.dm +++ b/code/modules/jobs/job_types/research_director.dm @@ -82,5 +82,4 @@ back = /obj/item/mod/control/pre_equipped/research suit = null mask = /obj/item/clothing/mask/breath - l_hand = null internals_slot = ITEM_SLOT_SUITSTORE diff --git a/code/modules/mod/mod_activation.dm b/code/modules/mod/mod_activation.dm index d3da5d9e2d9..426b07e422f 100644 --- a/code/modules/mod/mod_activation.dm +++ b/code/modules/mod/mod_activation.dm @@ -140,7 +140,7 @@ for(var/obj/item/mod/module/module as anything in modules) if(!module.active) continue - module.on_deactivation() + module.on_deactivation(display_message = FALSE) activating = TRUE to_chat(wearer, span_notice("MODsuit [active ? "shutting down" : "starting up"].")) if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS)) diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 6608f208afd..0dd1c923ff7 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -234,7 +234,7 @@ update_charge_alert() for(var/obj/item/mod/module/module as anything in modules) if(malfunctioning && module.active && DT_PROB(5, delta_time)) - module.on_deactivation() + module.on_deactivation(display_message = TRUE) module.on_process(delta_time) /obj/item/mod/control/equipped(mob/user, slot) @@ -410,7 +410,7 @@ to_chat(wearer, span_notice("[severity > 1 ? "Light" : "Strong"] electromagnetic pulse detected!")) if(. & EMP_PROTECT_CONTENTS) return - selected_module?.on_deactivation() + selected_module?.on_deactivation(display_message = TRUE) wearer.apply_damage(10 / severity, BURN, spread_damage=TRUE) to_chat(wearer, span_danger("You feel [src] heat up from the EMP, burning you slightly.")) if(wearer.stat < UNCONSCIOUS && prob(10)) @@ -584,7 +584,7 @@ if(active) old_module.on_suit_deactivation() if(old_module.active) - old_module.on_deactivation() + old_module.on_deactivation(display_message = TRUE) if(wearer) old_module.on_unequip() var/datum/action/item_action/mod/pinned_module/action = old_module.pinned_to[wearer] diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm index 1a7017193f7..23c84cb2a49 100644 --- a/code/modules/mod/mod_theme.dm +++ b/code/modules/mod/mod_theme.dm @@ -264,6 +264,49 @@ ), ) +/datum/mod_theme/loader + name = "loader" + desc = "An experimental powered harness manufactured by Scarborough Arms for quick and efficient munition supplies." + extended_desc = "This powered suit is an experimental spinoff of in-atmosphere Engineering suits. \ + This fully articulated titanium exoskeleton is Scarborough Arms' suit of choice for their munition delivery men, \ + and what it lacks in EVA protection, it makes up for in strength and flexibility. The primary feature of \ + this suit are the two manipulator arms, carefully synchronized with the user's thoughts and \ + duplicating their motions almost exactly. These are driven by myomer, an artificial analog of muscles, \ + requiring large amounts of voltage to function; occasionally sparking under load with the sheer power of a \ + suit capable of lifting 250 tons. Even the legs in the suit have been tuned to incredible capacity, \ + the user being able to run at greater speeds for much longer distances and times than an unsuited equivalent. \ + A lot of people would say loading cargo is a dull job. You could not disagree more." + default_skin = "loader" + armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 10, BIO = 10, FIRE = 25, ACID = 25, WOUND = 5) + max_heat_protection_temperature = ARMOR_MAX_TEMP_PROTECT + min_cold_protection_temperature = ARMOR_MIN_TEMP_PROTECT + permeability_coefficient = 0.5 + siemens_coefficient = 0.25 + complexity_max = DEFAULT_MAX_COMPLEXITY - 5 + slowdown_inactive = 0.5 + slowdown_active = 0 + inbuilt_modules = list(/obj/item/mod/module/hydraulic, /obj/item/mod/module/clamp/loader, /obj/item/mod/module/magnet) + skins = list( + "loader" = list( + HELMET_LAYER = null, + HELMET_FLAGS = list( + UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL, + UNSEALED_INVISIBILITY = HIDEEARS|HIDEHAIR, + SEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEMASK|HIDEEYES|HIDEFACE|HIDESNOUT, + SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF, + ), + CHESTPLATE_FLAGS = list( + UNSEALED_CLOTHING = THICKMATERIAL, + ), + GAUNTLETS_FLAGS = list( + SEALED_CLOTHING = THICKMATERIAL, + ), + BOOTS_FLAGS = list( + SEALED_CLOTHING = THICKMATERIAL, + ), + ), + ) + /datum/mod_theme/medical name = "medical" desc = "A lightweight suit by DeForest Medical Corporation, allows for easier movement." diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm index bf66e9cef77..91a994e5ba7 100644 --- a/code/modules/mod/mod_types.dm +++ b/code/modules/mod/mod_types.dm @@ -52,6 +52,16 @@ /obj/item/mod/module/jetpack, ) +/obj/item/mod/control/pre_equipped/loader + theme = /datum/mod_theme/loader + applied_cell = /obj/item/stock_parts/cell/high/plus + initial_modules = list( + /obj/item/mod/module/storage/large_capacity, + /obj/item/mod/module/flashlight, + /obj/item/mod/module/paper_dispenser, + /obj/item/mod/module/stamp, + ) + /obj/item/mod/control/pre_equipped/mining theme = /datum/mod_theme/mining applied_cell = /obj/item/stock_parts/cell/high/plus diff --git a/code/modules/mod/modules/_module.dm b/code/modules/mod/modules/_module.dm index cd6d3fd4c6b..6a4fbd15fcd 100644 --- a/code/modules/mod/modules/_module.dm +++ b/code/modules/mod/modules/_module.dm @@ -96,7 +96,7 @@ return if(module_type != MODULE_USABLE) if(active) - on_deactivation() + on_deactivation(display_message = TRUE) else on_activation() else @@ -118,7 +118,7 @@ if(SEND_SIGNAL(src, COMSIG_MODULE_TRIGGERED) & MOD_ABORT_USE) return FALSE if(module_type == MODULE_ACTIVE) - if(mod.selected_module && !mod.selected_module.on_deactivation()) + if(mod.selected_module && !mod.selected_module.on_deactivation(display_message = FALSE)) return mod.selected_module = src if(device) @@ -140,16 +140,16 @@ return TRUE /// Called when the module is deactivated -/obj/item/mod/module/proc/on_deactivation() +/obj/item/mod/module/proc/on_deactivation(display_message = TRUE) active = FALSE if(module_type == MODULE_ACTIVE) mod.selected_module = null + if(display_message) + balloon_alert(mod.wearer, device ? "[device] retracted" : "[src] deactivated") if(device) mod.wearer.transferItemToLoc(device, src, force = TRUE) - balloon_alert(mod.wearer, "[device] retracted") UnregisterSignal(mod.wearer, COMSIG_ATOM_EXITED) else - balloon_alert(mod.wearer, "[src] deactivated") UnregisterSignal(mod.wearer, used_signal) used_signal = null mod.wearer.update_inv_back() @@ -195,7 +195,7 @@ /obj/item/mod/module/proc/on_process(delta_time) if(active) if(!drain_power(active_power_cost * delta_time)) - on_deactivation() + on_deactivation(display_message = TRUE) return FALSE on_active_process(delta_time) else @@ -247,7 +247,7 @@ if(part.loc == mod.wearer) return if(part == device) - on_deactivation() + on_deactivation(display_message = TRUE) /// Called when the device gets deleted on active modules /obj/item/mod/module/proc/on_device_deletion(datum/source) diff --git a/code/modules/mod/modules/module_kinesis.dm b/code/modules/mod/modules/module_kinesis.dm index 2d66cb60744..cdc65a3f723 100644 --- a/code/modules/mod/modules/module_kinesis.dm +++ b/code/modules/mod/modules/module_kinesis.dm @@ -66,7 +66,7 @@ kinesis_catcher.RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, /atom/movable/screen/fullscreen/kinesis.proc/on_move) soundloop.start() -/obj/item/mod/module/anomaly_locked/kinesis/on_deactivation() +/obj/item/mod/module/anomaly_locked/kinesis/on_deactivation(display_message = TRUE) . = ..() if(!.) return diff --git a/code/modules/mod/modules/modules_antag.dm b/code/modules/mod/modules/modules_antag.dm index 9a24da8f0e6..7bc64049383 100644 --- a/code/modules/mod/modules/modules_antag.dm +++ b/code/modules/mod/modules/modules_antag.dm @@ -46,7 +46,7 @@ clothing_part.clothing_flags &= ~STOPSPRESSUREDAMAGE spaceproofed[clothing_part] = TRUE -/obj/item/mod/module/armor_booster/on_deactivation() +/obj/item/mod/module/armor_booster/on_deactivation(display_message = TRUE) . = ..() if(!.) return @@ -230,9 +230,9 @@ /obj/item/mod/module/noslip/on_suit_deactivation() REMOVE_TRAIT(mod.wearer, TRAIT_NOSLIPWATER, MOD_TRAIT) - + /obj/item/mod/module/springlock/bite_of_87 - + /obj/item/mod/module/springlock/bite_of_87/Initialize(mapload) . = ..() var/obj/item/mod/module/dna_lock/the_dna_lock_behind_the_slaughter = /obj/item/mod/module/dna_lock @@ -247,11 +247,11 @@ /obj/item/mod/module/springlock/bite_of_87/on_uninstall() mod.activation_step_time *= 10 - + /obj/item/mod/module/springlock/bite_of_87/on_suit_activation() ..() if(SSevents.holidays && SSevents.holidays[APRIL_FOOLS] || prob(1)) - var/list/all_parts = mod.mod_parts.Copy() + mod + var/list/all_parts = mod.mod_parts.Copy() + mod for(var/obj/item/part in all_parts) // turns the suit yellow part.remove_atom_colour(WASHABLE_COLOUR_PRIORITY) part.add_atom_colour("#b17f00", FIXED_COLOUR_PRIORITY) diff --git a/code/modules/mod/modules/modules_engineering.dm b/code/modules/mod/modules/modules_engineering.dm index 97c788ec70c..04639cb1eec 100644 --- a/code/modules/mod/modules/modules_engineering.dm +++ b/code/modules/mod/modules/modules_engineering.dm @@ -61,7 +61,7 @@ mod.wearer.update_gravity(mod.wearer.has_gravity()) mod.wearer.update_equipment_speed_mods() -/obj/item/mod/module/magboot/on_deactivation() +/obj/item/mod/module/magboot/on_deactivation(display_message = TRUE) . = ..() if(!.) return diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 89b4f8b9d53..9d8896261b4 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -118,7 +118,7 @@ if(full_speed) mod.wearer.add_movespeed_modifier(/datum/movespeed_modifier/jetpack/fullspeed) -/obj/item/mod/module/jetpack/on_deactivation(mob/user) +/obj/item/mod/module/jetpack/on_deactivation(display_message = TRUE) . = ..() if(!.) return @@ -259,7 +259,7 @@ set_light_on(active) active_power_cost = base_power * light_range -/obj/item/mod/module/flashlight/on_deactivation() +/obj/item/mod/module/flashlight/on_deactivation(display_message = TRUE) . = ..() if(!.) return diff --git a/code/modules/mod/modules/modules_maint.dm b/code/modules/mod/modules/modules_maint.dm index ef6921d4bde..61f676827d7 100644 --- a/code/modules/mod/modules/modules_maint.dm +++ b/code/modules/mod/modules/modules_maint.dm @@ -107,7 +107,7 @@ if(selection) SEND_SOUND(mod.wearer, sound(selection.song_path, volume = 50, channel = CHANNEL_JUKEBOX)) -/obj/item/mod/module/visor/rave/on_deactivation() +/obj/item/mod/module/visor/rave/on_deactivation(display_message = TRUE) . = ..() if(!.) return @@ -235,6 +235,30 @@ drain_power(use_power_cost) num_sheets_dispensed++ +/obj/item/mod/module/stamp + name = "MOD stamper module" + desc = "A module installed into the wrist of the suit, this functions as a high-power stamp, \ + able to switch between accept and deny modes." + icon_state = "stamp" + module_type = MODULE_ACTIVE + complexity = 1 + active_power_cost = DEFAULT_CHARGE_DRAIN * 0.3 + device = /obj/item/stamp/mod + incompatible_modules = list(/obj/item/mod/module/stamp) + cooldown_time = 0.5 SECONDS + +/obj/item/stamp/mod + name = "MOD electronic stamp" + desc = "A high-power stamp, able to switch between accept and deny mode when used." + +/obj/item/stamp/mod/attack_self(mob/user, modifiers) + . = ..() + if(icon_state == "stamp-ok") + icon_state = "stamp-deny" + else + icon_state = "stamp-ok" + balloon_alert(user, "switched mode") + ///Atrocinator - Flips your gravity. /obj/item/mod/module/atrocinator name = "MOD atrocinator module" @@ -262,7 +286,7 @@ 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() +/obj/item/mod/module/atrocinator/on_deactivation(display_message = TRUE) if(you_fucked_up) to_chat(mod.wearer, span_danger("It's too late.")) return FALSE diff --git a/code/modules/mod/modules/modules_science.dm b/code/modules/mod/modules/modules_science.dm index 5ef7ac34857..dfed572fe7c 100644 --- a/code/modules/mod/modules/modules_science.dm +++ b/code/modules/mod/modules/modules_science.dm @@ -19,7 +19,7 @@ return ADD_TRAIT(mod.wearer, TRAIT_REAGENT_SCANNER, MOD_TRAIT) -/obj/item/mod/module/reagent_scanner/on_deactivation() +/obj/item/mod/module/reagent_scanner/on_deactivation(display_message = TRUE) . = ..() if(!.) return @@ -38,7 +38,7 @@ mod.wearer.research_scanner++ RegisterSignal(SSdcs, COMSIG_GLOB_EXPLOSION, .proc/sense_explosion) -/obj/item/mod/module/reagent_scanner/advanced/on_deactivation() +/obj/item/mod/module/reagent_scanner/advanced/on_deactivation(display_message = TRUE) . = ..() if(!.) return @@ -77,7 +77,7 @@ mod.wearer.update_gravity(mod.wearer.has_gravity()) playsound(src, 'sound/effects/gravhit.ogg', 50) -/obj/item/mod/module/anomaly_locked/antigrav/on_deactivation() +/obj/item/mod/module/anomaly_locked/antigrav/on_deactivation(display_message = TRUE) . = ..() if(!.) return @@ -112,15 +112,16 @@ balloon_alert(mod.wearer, "invalid target!") return balloon_alert(mod.wearer, "teleporting...") - var/matrix/user_matrix = matrix(mod.wearer.transform) - animate(mod.wearer, teleport_time, color = COLOR_CYAN, transform = user_matrix.Scale(4, 0.25), easing = EASE_OUT) + var/matrix/pre_matrix = matrix() + pre_matrix.Scale(4, 0.25) + var/matrix/post_matrix = matrix() + post_matrix.Scale(0.25, 4) + animate(mod.wearer, teleport_time, color = COLOR_CYAN, transform = pre_matrix.Multiply(mod.wearer.transform), easing = EASE_OUT) if(!do_after(mod.wearer, teleport_time, target = mod)) balloon_alert(mod.wearer, "interrupted!") - var/matrix/post_matrix = matrix(mod.wearer.transform) - animate(mod.wearer, teleport_time, color = null, transform = post_matrix.Scale(0.25, 4), easing = EASE_IN) + animate(mod.wearer, teleport_time*0.1, color = null, transform = post_matrix.Multiply(mod.wearer.transform), easing = EASE_IN) return - var/matrix/post_matrix = matrix(mod.wearer.transform) - animate(mod.wearer, teleport_time*0.1, color = null, transform = post_matrix.Scale(0.25, 4), easing = EASE_IN) + animate(mod.wearer, teleport_time*0.1, color = null, transform = post_matrix.Multiply(mod.wearer.transform), easing = EASE_IN) if(!do_teleport(mod.wearer, target_turf, asoundin = 'sound/effects/phasein.ogg')) return drain_power(use_power_cost) diff --git a/code/modules/mod/modules/modules_security.dm b/code/modules/mod/modules/modules_security.dm index 4e7b1bb671c..d530936be34 100644 --- a/code/modules/mod/modules/modules_security.dm +++ b/code/modules/mod/modules/modules_security.dm @@ -30,7 +30,7 @@ animate(mod.wearer, alpha = stealth_alpha, time = 1.5 SECONDS) drain_power(use_power_cost) -/obj/item/mod/module/stealth/on_deactivation() +/obj/item/mod/module/stealth/on_deactivation(display_message = TRUE) . = ..() if(!.) return @@ -45,7 +45,7 @@ to_chat(mod.wearer, span_warning("[src] gets discharged from contact!")) do_sparks(2, TRUE, src) drain_power(use_power_cost) - on_deactivation() + on_deactivation(display_message = TRUE) /obj/item/mod/module/stealth/proc/on_unarmed_attack(datum/source, atom/target) SIGNAL_HANDLER diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm index 1a2d69e8989..047e1562ccf 100644 --- a/code/modules/mod/modules/modules_supply.dm +++ b/code/modules/mod/modules/modules_supply.dm @@ -34,6 +34,8 @@ cooldown_time = 0.5 SECONDS overlay_state_inactive = "module_clamp" overlay_state_active = "module_clamp_on" + /// Time it takes to load a crate. + var/load_time = 3 SECONDS /// The max amount of crates you can carry. var/max_crates = 3 /// The crates stored in the module. @@ -50,19 +52,20 @@ if(length(stored_crates) >= max_crates) balloon_alert(mod.wearer, "too many crates!") return - if(!do_after(mod.wearer, 1 SECONDS, target = target)) + playsound(src, 'sound/mecha/hydraulic.ogg', 25, TRUE) + if(!do_after(mod.wearer, load_time, target = target)) balloon_alert(mod.wearer, "interrupted!") return stored_crates += picked_crate picked_crate.forceMove(src) balloon_alert(mod.wearer, "picked up [picked_crate]") - playsound(src, 'sound/mecha/hydraulic.ogg', 25, TRUE) drain_power(use_power_cost) else if(length(stored_crates)) var/turf/target_turf = get_turf(target) if(target_turf.is_blocked_turf()) return - if(!do_after(mod.wearer, 1 SECONDS, target = target)) + playsound(src, 'sound/mecha/hydraulic.ogg', 25, TRUE) + if(!do_after(mod.wearer, load_time, target = target)) balloon_alert(mod.wearer, "interrupted!") return if(target_turf.is_blocked_turf()) @@ -70,14 +73,25 @@ var/atom/movable/dropped_crate = pop(stored_crates) dropped_crate.forceMove(target_turf) balloon_alert(mod.wearer, "dropped [dropped_crate]") - playsound(src, 'sound/mecha/hydraulic.ogg', 25, TRUE) drain_power(use_power_cost) + else + balloon_alert(mod.wearer, "invalid target!") /obj/item/mod/module/clamp/on_suit_deactivation() for(var/atom/movable/crate as anything in stored_crates) crate.forceMove(drop_location()) stored_crates -= crate +/obj/item/mod/module/clamp/loader + name = "MOD loader hydraulic clamp module" + icon_state = "clamp_loader" + complexity = 0 + removable = FALSE + overlay_state_inactive = null + overlay_state_active = "module_clamp_loader" + load_time = 1 SECONDS + max_crates = 5 + ///Drill - Lets you dig through rock and basalt. /obj/item/mod/module/drill name = "MOD drill module" @@ -96,7 +110,7 @@ return RegisterSignal(mod.wearer, COMSIG_MOVABLE_BUMP, .proc/bump_mine) -/obj/item/mod/module/drill/on_deactivation() +/obj/item/mod/module/drill/on_deactivation(display_message = TRUE) . = ..() if(!.) return @@ -174,3 +188,146 @@ ore.forceMove(drop_location()) ores -= ore drain_power(use_power_cost) + +/obj/item/mod/module/hydraulic + name = "MOD loader hydraulic arms module" + desc = "A pair of powerful hydraulic arms installed in a MODsuit." + icon_state = "launch_loader" + module_type = MODULE_ACTIVE + removable = FALSE + use_power_cost = DEFAULT_CHARGE_DRAIN*10 + incompatible_modules = list(/obj/item/mod/module/hydraulic) + cooldown_time = 4 SECONDS + overlay_state_inactive = "module_hydraulic" + overlay_state_active = "module_hydraulic_active" + /// Time it takes to launch + var/launch_time = 2 SECONDS + /// User overlay + var/mutable_appearance/lightning + +/obj/item/mod/module/hydraulic/on_select_use(atom/target) + . = ..() + if(!.) + return + var/atom/game_renderer = mod.wearer.hud_used.plane_masters["[RENDER_PLANE_GAME]"] + var/matrix/render_matrix = matrix(game_renderer.transform) + render_matrix.Scale(1.25, 1.25) + animate(game_renderer, launch_time, flags = SINE_EASING|EASE_IN, transform = render_matrix) + var/current_time = world.time + mod.wearer.visible_message(span_warning("[mod.wearer] starts whirring!"), \ + blind_message = span_hear("You hear a whirring sound.")) + playsound(src, 'sound/items/modsuit/loader_charge.ogg', 75, TRUE) + lightning = mutable_appearance('icons/effects/effects.dmi', "electricity3", plane = GAME_PLANE_FOV_HIDDEN) + mod.wearer.add_overlay(lightning) + balloon_alert(mod.wearer, "you start charging...") + var/power = launch_time + if(!do_after(mod.wearer, launch_time, target = mod)) + power = world.time - current_time + animate(game_renderer) + drain_power(use_power_cost) + new /obj/effect/temp_visual/mook_dust(get_turf(src)) + playsound(src, 'sound/items/modsuit/loader_launch.ogg', 75, TRUE) + game_renderer.transform = game_renderer.transform.Scale(0.8, 0.8) + mod.wearer.cut_overlay(lightning) + var/angle = get_angle(mod.wearer, target) + mod.wearer.transform = mod.wearer.transform.Turn(angle) + mod.wearer.throw_at(get_ranged_target_turf_direct(mod.wearer, target, power), \ + range = power, speed = max(round(0.2*power), 1), thrower = mod.wearer, spin = FALSE, \ + callback = CALLBACK(src, .proc/on_throw_end, target, -angle)) + +/obj/item/mod/module/hydraulic/proc/on_throw_end(atom/target, angle) + if(!mod?.wearer) + return + mod.wearer.transform = mod.wearer.transform.Turn(angle) + +/obj/item/mod/module/disposal_connector + name = "MOD disposal selector module" + desc = "A module that connects to the disposal pipeline, causing the user to go into their config selected disposal. \ + Only seems to work when the suit is on." + icon_state = "disposal" + complexity = 2 + idle_power_cost = DEFAULT_CHARGE_DRAIN * 0.3 + incompatible_modules = list(/obj/item/mod/module/disposal_connector) + var/disposal_tag = NONE + +/obj/item/mod/module/disposal_connector/Initialize(mapload) + . = ..() + disposal_tag = pick(GLOB.TAGGERLOCATIONS) + +/obj/item/mod/module/disposal_connector/on_suit_activation() + RegisterSignal(mod.wearer, COMSIG_MOVABLE_DISPOSING, .proc/disposal_handling) + +/obj/item/mod/module/disposal_connector/on_suit_deactivation() + UnregisterSignal(mod.wearer, COMSIG_MOVABLE_DISPOSING) + +/obj/item/mod/module/disposal_connector/get_configuration() + . = ..() + .["disposal_tag"] = add_ui_configuration("Disposal Tag", "list", GLOB.TAGGERLOCATIONS[disposal_tag], GLOB.TAGGERLOCATIONS) + +/obj/item/mod/module/disposal_connector/configure_edit(key, value) + switch(key) + if("disposal_tag") + for(var/tag in 1 to length(GLOB.TAGGERLOCATIONS)) + if(GLOB.TAGGERLOCATIONS[tag] == value) + disposal_tag = tag + break + +/obj/item/mod/module/disposal_connector/proc/disposal_handling(datum/disposal_source, obj/structure/disposalholder/disposal_holder, obj/machinery/disposal/disposal_machine, hasmob) + SIGNAL_HANDLER + + disposal_holder.destinationTag = disposal_tag + +/obj/item/mod/module/magnet + name = "MOD loader hydraulic magnet module" + desc = "A powerful hydraulic electromagnet able to launch crates and lockers towards the user, and keep 'em attached." + icon_state = "magnet_loader" + module_type = MODULE_ACTIVE + removable = FALSE + use_power_cost = DEFAULT_CHARGE_DRAIN*3 + incompatible_modules = list(/obj/item/mod/module/magnet) + cooldown_time = 1.5 SECONDS + overlay_state_active = "module_magnet" + +/obj/item/mod/module/magnet/on_select_use(atom/target) + . = ..() + if(!.) + return + if(istype(mod.wearer.pulling, /obj/structure/closet)) + var/obj/structure/closet/locker = mod.wearer.pulling + playsound(locker, 'sound/effects/gravhit.ogg', 75, TRUE) + locker.forceMove(mod.wearer.loc) + locker.throw_at(target, range = 7, speed = 4, thrower = mod.wearer) + return + if(!istype(target, /obj/structure/closet) || !(target in view(mod.wearer))) + balloon_alert(mod.wearer, "invalid target!") + return + var/obj/structure/closet/locker = target + if(locker.anchored || locker.move_resist >= MOVE_FORCE_OVERPOWERING) + balloon_alert(mod.wearer, "target anchored!") + return + new /obj/effect/temp_visual/mook_dust(get_turf(locker)) + playsound(locker, 'sound/effects/gravhit.ogg', 75, TRUE) + locker.throw_at(mod.wearer, range = 7, speed = 3, force = MOVE_FORCE_WEAK, \ + callback = CALLBACK(src, .proc/check_locker, locker)) + +/obj/item/mod/module/magnet/on_deactivation(display_message = TRUE) + . = ..() + if(!.) + return + if(istype(mod.wearer.pulling, /obj/structure/closet)) + mod.wearer.stop_pulling() + +/obj/item/mod/module/magnet/proc/check_locker(obj/structure/closet/locker) + if(!mod?.wearer) + return + if(!locker.Adjacent(mod.wearer) || !isturf(locker.loc) || !isturf(mod.wearer.loc)) + return + mod.wearer.start_pulling(locker) + locker.strong_grab = TRUE + RegisterSignal(locker, COMSIG_ATOM_NO_LONGER_PULLED, .proc/on_stop_pull) + +/obj/item/mod/module/magnet/proc/on_stop_pull(obj/structure/closet/locker, atom/movable/last_puller) + SIGNAL_HANDLER + + locker.strong_grab = FALSE + UnregisterSignal(locker, COMSIG_ATOM_NO_LONGER_PULLED) diff --git a/code/modules/mod/modules/modules_visor.dm b/code/modules/mod/modules/modules_visor.dm index 59473ae691b..82808568189 100644 --- a/code/modules/mod/modules/modules_visor.dm +++ b/code/modules/mod/modules/modules_visor.dm @@ -25,7 +25,7 @@ ADD_TRAIT(mod.wearer, trait, MOD_TRAIT) mod.wearer.update_sight() -/obj/item/mod/module/visor/on_deactivation() +/obj/item/mod/module/visor/on_deactivation(display_message = TRUE) . = ..() if(!.) return diff --git a/code/modules/research/designs/mechfabricator_designs.dm b/code/modules/research/designs/mechfabricator_designs.dm index 7988d2ce5b5..b93426b896f 100644 --- a/code/modules/research/designs/mechfabricator_designs.dm +++ b/code/modules/research/designs/mechfabricator_designs.dm @@ -970,7 +970,7 @@ build_path = /obj/item/assembly/flash/handheld category = list("Misc") -//MODsuit stuff +//MODsuit construction /datum/design/mod_shell name = "MOD shell" @@ -1086,6 +1086,8 @@ build_path = /obj/item/mod/paint category = list("Misc") +//MODsuit modules + /datum/design/module name = "MOD Module" build_type = MECHFAB @@ -1340,6 +1342,17 @@ materials = list(/datum/material/iron = 750, /datum/material/glass = 500) build_path = /obj/item/mod/module/signlang_radio +//MODsuit bepis modules + +/datum/design/module/disposal + name = "MOD Module: Disposal Connector" + id = "mod_disposal" + materials = list(/datum/material/iron = 2500, /datum/material/titanium = 1000) + build_path = /obj/item/mod/module/disposal_connector + department_type = MODULE_SUPPLY + +//MODsuit anomalock modules + /datum/design/module/mod_antigrav name = "MOD Module: Anti-Gravity" id = "mod_antigrav" diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index 463bf1d122e..ec868884ae2 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -2093,6 +2093,18 @@ hidden = TRUE experimental = TRUE +/datum/techweb_node/mod_experimental + id = "mod_experimental" + display_name = "Experimental Modular Suits" + description = "Applications of experimentality when creating MODsuits has created these..." + prereq_ids = list("base") + design_ids = list( + "mod_disposal", + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 2500) + hidden = TRUE + experimental = TRUE + //Helpers for debugging/balancing the techweb in its entirety! /proc/total_techweb_points() var/list/datum/techweb_node/processing = list() diff --git a/icons/mob/clothing/mod.dmi b/icons/mob/clothing/mod.dmi index 2f8b274016c..84c27858f49 100644 Binary files a/icons/mob/clothing/mod.dmi and b/icons/mob/clothing/mod.dmi differ diff --git a/icons/obj/clothing/modsuit/mod_clothing.dmi b/icons/obj/clothing/modsuit/mod_clothing.dmi index 6945f481349..6dbbeadc2df 100644 Binary files a/icons/obj/clothing/modsuit/mod_clothing.dmi and b/icons/obj/clothing/modsuit/mod_clothing.dmi differ diff --git a/icons/obj/clothing/modsuit/mod_modules.dmi b/icons/obj/clothing/modsuit/mod_modules.dmi index eb057fe31c3..579ff886f07 100644 Binary files a/icons/obj/clothing/modsuit/mod_modules.dmi and b/icons/obj/clothing/modsuit/mod_modules.dmi differ diff --git a/sound/items/modsuit/loader_charge.ogg b/sound/items/modsuit/loader_charge.ogg new file mode 100644 index 00000000000..61d5531f72e Binary files /dev/null and b/sound/items/modsuit/loader_charge.ogg differ diff --git a/sound/items/modsuit/loader_launch.ogg b/sound/items/modsuit/loader_launch.ogg new file mode 100644 index 00000000000..513118f3c68 Binary files /dev/null and b/sound/items/modsuit/loader_launch.ogg differ