mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 04:30:44 +01:00
MODsuit module update: new stuff and improved old stuff (#67042)
Doubles the range of the MOD Pathfinder AI Fixes modules rendering below the suit. Adds the ability for modules to be used when inactive. Documents/cleans up some code. Updates some old descriptions and explains some concepts better. Armor Booster and Ash Accretion can no longer boost your speed over no slowdown at all. Makes flashlight module start with 4 instead of 3 range, so it's better for people that don't know about configuration. Doubles t-ray module range, from 2 to 4 (t-ray scanner is 3). Puts the noslip module lower in progression, lowers its' price to 2. New sprites for the magnetic harness module by Onule. Brings back the holster module, it can now be used when the suit is inactive, can be printed with security suit research. Adds the power kick module for the ERT Commander. It's a powerful kick.
This commit is contained in:
@@ -145,7 +145,7 @@
|
||||
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
|
||||
return FALSE
|
||||
for(var/obj/item/mod/module/module as anything in modules)
|
||||
if(!module.active)
|
||||
if(!module.active || module.allowed_inactive)
|
||||
continue
|
||||
module.on_deactivation(display_message = FALSE)
|
||||
activating = TRUE
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
heat_protection = HEAD
|
||||
cold_protection = HEAD
|
||||
obj_flags = IMMUTABLE_SLOW
|
||||
var/alternate_layer = NECK_LAYER
|
||||
|
||||
/obj/item/clothing/suit/mod
|
||||
name = "MOD chestplate"
|
||||
|
||||
@@ -622,13 +622,12 @@
|
||||
CRASH("[src] tried to set skin while active!")
|
||||
skin = new_skin
|
||||
var/list/used_skin = theme.skins[new_skin]
|
||||
alternate_worn_layer = used_skin[CONTROL_LAYER]
|
||||
if(used_skin[CONTROL_LAYER])
|
||||
alternate_worn_layer = used_skin[CONTROL_LAYER]
|
||||
var/list/skin_updating = mod_parts + src
|
||||
for(var/obj/item/part as anything in skin_updating)
|
||||
if(used_skin[MOD_ICON_OVERRIDE])
|
||||
part.icon = used_skin[MOD_ICON_OVERRIDE]
|
||||
if(used_skin[MOD_WORN_ICON_OVERRIDE])
|
||||
part.worn_icon = used_skin[MOD_WORN_ICON_OVERRIDE]
|
||||
part.icon = used_skin[MOD_ICON_OVERRIDE] || 'icons/obj/clothing/modsuit/mod_clothing.dmi'
|
||||
part.worn_icon = used_skin[MOD_WORN_ICON_OVERRIDE] || 'icons/mob/clothing/modsuit/mod_clothing.dmi'
|
||||
part.icon_state = "[skin]-[initial(part.icon_state)]"
|
||||
for(var/obj/item/clothing/part as anything in mod_parts)
|
||||
var/used_category
|
||||
|
||||
@@ -242,11 +242,11 @@
|
||||
|
||||
/obj/item/mod/control/pre_equipped/responsory/commander
|
||||
insignia_type = /obj/item/mod/module/insignia/commander
|
||||
additional_module = /obj/item/mod/module/noslip
|
||||
additional_module = /obj/item/mod/module/power_kick
|
||||
|
||||
/obj/item/mod/control/pre_equipped/responsory/security
|
||||
insignia_type = /obj/item/mod/module/insignia/security
|
||||
additional_module = /obj/item/mod/module/gps
|
||||
additional_module = /obj/item/mod/module/pepper_shoulders
|
||||
|
||||
/obj/item/mod/control/pre_equipped/responsory/engineer
|
||||
insignia_type = /obj/item/mod/module/insignia/engineer
|
||||
@@ -281,11 +281,11 @@
|
||||
|
||||
/obj/item/mod/control/pre_equipped/responsory/inquisitory/commander
|
||||
insignia_type = /obj/item/mod/module/insignia/commander
|
||||
additional_module = /obj/item/mod/module/noslip
|
||||
additional_module = /obj/item/mod/module/power_kick
|
||||
|
||||
/obj/item/mod/control/pre_equipped/responsory/inquisitory/security
|
||||
insignia_type = /obj/item/mod/module/insignia/security
|
||||
additional_module = /obj/item/mod/module/gps
|
||||
additional_module = /obj/item/mod/module/pepper_shoulders
|
||||
|
||||
/obj/item/mod/control/pre_equipped/responsory/inquisitory/medic
|
||||
insignia_type = /obj/item/mod/module/insignia/medic
|
||||
|
||||
@@ -43,6 +43,8 @@
|
||||
var/list/pinned_to = list()
|
||||
/// If we're allowed to use this module while phased out.
|
||||
var/allowed_in_phaseout = FALSE
|
||||
/// If we're allowed to use this module while the suit is disabled.
|
||||
var/allowed_inactive = FALSE
|
||||
/// Timer for the cooldown
|
||||
COOLDOWN_DECLARE(cooldown_timer)
|
||||
|
||||
@@ -68,33 +70,10 @@
|
||||
if(HAS_TRAIT(user, TRAIT_DIAGNOSTIC_HUD))
|
||||
. += span_notice("Complexity level: [complexity]")
|
||||
|
||||
/// Called from MODsuit's install() proc, so when the module is installed.
|
||||
/obj/item/mod/module/proc/on_install()
|
||||
return
|
||||
|
||||
/// Called from MODsuit's uninstall() proc, so when the module is uninstalled.
|
||||
/obj/item/mod/module/proc/on_uninstall(deleting = FALSE)
|
||||
return
|
||||
|
||||
/// Called when the MODsuit is activated
|
||||
/obj/item/mod/module/proc/on_suit_activation()
|
||||
return
|
||||
|
||||
/// Called when the MODsuit is deactivated
|
||||
/obj/item/mod/module/proc/on_suit_deactivation(deleting = FALSE)
|
||||
return
|
||||
|
||||
/// Called when the MODsuit is equipped
|
||||
/obj/item/mod/module/proc/on_equip()
|
||||
return
|
||||
|
||||
/// Called when the MODsuit is unequipped
|
||||
/obj/item/mod/module/proc/on_unequip()
|
||||
return
|
||||
|
||||
/// Called when the module is selected from the TGUI, radial or the action button
|
||||
/obj/item/mod/module/proc/on_select()
|
||||
if(!mod.active || mod.activating || module_type == MODULE_PASSIVE)
|
||||
if(((!mod.active || mod.activating) && !allowed_inactive) || module_type == MODULE_PASSIVE)
|
||||
if(mod.wearer)
|
||||
balloon_alert(mod.wearer, "not active!")
|
||||
return
|
||||
@@ -212,6 +191,30 @@
|
||||
/obj/item/mod/module/proc/on_active_process(delta_time)
|
||||
return
|
||||
|
||||
/// Called from MODsuit's install() proc, so when the module is installed.
|
||||
/obj/item/mod/module/proc/on_install()
|
||||
return
|
||||
|
||||
/// Called from MODsuit's uninstall() proc, so when the module is uninstalled.
|
||||
/obj/item/mod/module/proc/on_uninstall(deleting = FALSE)
|
||||
return
|
||||
|
||||
/// Called when the MODsuit is activated
|
||||
/obj/item/mod/module/proc/on_suit_activation()
|
||||
return
|
||||
|
||||
/// Called when the MODsuit is deactivated
|
||||
/obj/item/mod/module/proc/on_suit_deactivation(deleting = FALSE)
|
||||
return
|
||||
|
||||
/// Called when the MODsuit is equipped
|
||||
/obj/item/mod/module/proc/on_equip()
|
||||
return
|
||||
|
||||
/// Called when the MODsuit is unequipped
|
||||
/obj/item/mod/module/proc/on_unequip()
|
||||
return
|
||||
|
||||
/// Drains power from the suit charge
|
||||
/obj/item/mod/module/proc/drain_power(amount)
|
||||
if(!check_power(amount))
|
||||
|
||||
@@ -243,11 +243,11 @@
|
||||
var/list/view = getviewsize(kinesis_user.client.view)
|
||||
icon_x *= view[1]/FULLSCREEN_OVERLAY_RESOLUTION_X
|
||||
icon_y *= view[2]/FULLSCREEN_OVERLAY_RESOLUTION_Y
|
||||
var/our_x = round(icon_x / world.icon_size)
|
||||
var/our_y = round(icon_y / world.icon_size)
|
||||
var/our_x = round(icon_x / world.icon_size, 1)
|
||||
var/our_y = round(icon_y / world.icon_size, 1)
|
||||
var/mob_x = kinesis_user.x
|
||||
var/mob_y = kinesis_user.y
|
||||
var/mob_z = kinesis_user.z
|
||||
given_turf = locate(mob_x+our_x-round(view[1]/2),mob_y+our_y-round(view[2]/2),mob_z)
|
||||
given_x = round(icon_x - world.icon_size * our_x)
|
||||
given_y = round(icon_y - world.icon_size * our_y)
|
||||
given_x = round(icon_x - world.icon_size * our_x, 1)
|
||||
given_y = round(icon_y - world.icon_size * our_y, 1)
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
name = "MOD pathfinder module"
|
||||
desc = "This module, brought to you by Nakamura Engineering, has two components. \
|
||||
The first component is a series of thrusters and a computerized location subroutine installed into the \
|
||||
very control unit of the suit, allowing it flight at highway speeds, \
|
||||
and to be able to locate the second part of the system; \
|
||||
very control unit of the suit, allowing it flight at highway speeds using the suit's access locks \
|
||||
to navigate through the station, and to be able to locate the second part of the system; \
|
||||
a pathfinding implant installed into the base of the user's spine, \
|
||||
broadcasting their location to the suit and allowing them to recall it to their person at any time. \
|
||||
The implant is stored in the module and needs to be injected in a human to function. \
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
use_mod_colors = TRUE
|
||||
/// Whether or not this module removes pressure protection.
|
||||
var/remove_pressure_protection = TRUE
|
||||
/// Slowdown added to the suit.
|
||||
var/added_slowdown = -0.5
|
||||
/// Speed added to the control unit.
|
||||
var/speed_added = 0.5
|
||||
/// Speed that we actually added.
|
||||
var/actual_speed_added = 0
|
||||
/// Armor values added to the suit parts.
|
||||
var/list/armor_values = list(MELEE = 25, BULLET = 30, LASER = 15, ENERGY = 15)
|
||||
/// List of parts of the suit that are spaceproofed, for giving them back the pressure protection.
|
||||
@@ -38,7 +40,8 @@
|
||||
if(!.)
|
||||
return
|
||||
playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
mod.slowdown += added_slowdown
|
||||
actual_speed_added = max(0, min(mod.slowdown_active, speed_added))
|
||||
mod.slowdown -= actual_speed_added
|
||||
mod.wearer.update_equipment_speed_mods()
|
||||
var/list/parts = mod.mod_parts + mod
|
||||
for(var/obj/item/part as anything in parts)
|
||||
@@ -56,7 +59,7 @@
|
||||
return
|
||||
if(!deleting)
|
||||
playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
||||
mod.slowdown -= added_slowdown
|
||||
mod.slowdown += actual_speed_added
|
||||
mod.wearer.update_equipment_speed_mods()
|
||||
var/list/parts = mod.mod_parts + mod
|
||||
var/list/removed_armor = armor_values.Copy()
|
||||
@@ -288,3 +291,165 @@
|
||||
|
||||
/obj/projectile/bullet/incendiary/backblast/flamethrower
|
||||
range = 6
|
||||
|
||||
///Power kick - Lets the user launch themselves at someone to kick them.
|
||||
/obj/item/mod/module/power_kick
|
||||
name = "MOD power kick module"
|
||||
desc = "This module uses high-power myomer to generate an incredible amount of energy, transferred into the power of a kick."
|
||||
icon_state = "power_kick"
|
||||
module_type = MODULE_ACTIVE
|
||||
removable = FALSE
|
||||
use_power_cost = DEFAULT_CHARGE_DRAIN*5
|
||||
incompatible_modules = list(/obj/item/mod/module/power_kick)
|
||||
cooldown_time = 5 SECONDS
|
||||
/// Damage on kick.
|
||||
var/damage = 20
|
||||
/// The wound bonus of the kick.
|
||||
var/wounding_power = 35
|
||||
/// How long we knockdown for on the kick.
|
||||
var/knockdown_time = 2 SECONDS
|
||||
|
||||
/obj/item/mod/module/power_kick/on_select_use(atom/target)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
mod.wearer.visible_message(span_warning("[mod.wearer] starts charging a kick!"), \
|
||||
blind_message = span_hear("You hear a charging sound."))
|
||||
playsound(src, 'sound/items/modsuit/loader_charge.ogg', 75, TRUE)
|
||||
balloon_alert(mod.wearer, "you start charging...")
|
||||
animate(mod.wearer, 0.3 SECONDS, pixel_z = 16, flags = ANIMATION_RELATIVE|SINE_EASING|EASE_OUT)
|
||||
addtimer(CALLBACK(mod.wearer, /atom.proc/SpinAnimation, 3, 2), 0.3 SECONDS)
|
||||
if(!do_after(mod.wearer, 1 SECONDS, target = mod))
|
||||
animate(mod.wearer, 0.2 SECONDS, pixel_z = -16, flags = ANIMATION_RELATIVE|SINE_EASING|EASE_IN)
|
||||
return
|
||||
animate(mod.wearer)
|
||||
drain_power(use_power_cost)
|
||||
playsound(src, 'sound/items/modsuit/loader_launch.ogg', 75, TRUE)
|
||||
var/angle = get_angle(mod.wearer, target) + 180
|
||||
mod.wearer.transform = mod.wearer.transform.Turn(angle)
|
||||
RegisterSignal(mod.wearer, COMSIG_MOVABLE_IMPACT, .proc/on_throw_impact)
|
||||
mod.wearer.throw_at(target, range = 7, speed = 2, thrower = mod.wearer, spin = FALSE, gentle = TRUE, callback = CALLBACK(src, .proc/on_throw_end, mod.wearer, -angle))
|
||||
|
||||
/obj/item/mod/module/power_kick/proc/on_throw_end(mob/user, angle)
|
||||
if(!user)
|
||||
return
|
||||
user.transform = user.transform.Turn(angle)
|
||||
animate(user, 0.2 SECONDS, pixel_z = -16, flags = ANIMATION_RELATIVE|SINE_EASING|EASE_IN)
|
||||
|
||||
/obj/item/mod/module/power_kick/proc/on_throw_impact(mob/living/source, atom/target, datum/thrownthing/thrownthing)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
UnregisterSignal(source, COMSIG_MOVABLE_IMPACT)
|
||||
if(!mod?.wearer)
|
||||
return
|
||||
if(isliving(target))
|
||||
var/mob/living/living_target = target
|
||||
living_target.apply_damage(damage, BRUTE, mod.wearer.zone_selected, wound_bonus = wounding_power)
|
||||
living_target.Knockdown(knockdown_time)
|
||||
else if(target.uses_integrity)
|
||||
target.take_damage(damage, BRUTE, MELEE)
|
||||
else
|
||||
return
|
||||
mod.wearer.do_attack_animation(target, ATTACK_EFFECT_SMASH)
|
||||
|
||||
///Chameleon - lets the suit disguise as any item that would fit on that slot.
|
||||
/obj/item/mod/module/chameleon
|
||||
name = "MOD chameleon module"
|
||||
desc = "A module using chameleon technology to disguise the suit as another object."
|
||||
icon_state = "chameleon"
|
||||
module_type = MODULE_USABLE
|
||||
complexity = 2
|
||||
incompatible_modules = list(/obj/item/mod/module/chameleon)
|
||||
cooldown_time = 0.5 SECONDS
|
||||
allowed_inactive = TRUE
|
||||
/// A list of all the items the suit can disguise as.
|
||||
var/list/possible_disguises = list()
|
||||
/// The path of the item we're disguised as.
|
||||
var/obj/item/current_disguise
|
||||
|
||||
/obj/item/mod/module/chameleon/on_install()
|
||||
var/list/all_disguises = sort_list(subtypesof(get_path_by_slot(mod.slot_flags)), /proc/cmp_typepaths_asc)
|
||||
for(var/clothing_path in all_disguises)
|
||||
var/obj/item/clothing = clothing_path
|
||||
if(!initial(clothing.icon_state))
|
||||
continue
|
||||
var/chameleon_item_name = "[initial(clothing.name)] ([initial(clothing.icon_state)])"
|
||||
possible_disguises[chameleon_item_name] = clothing_path
|
||||
|
||||
/obj/item/mod/module/chameleon/on_uninstall(deleting = FALSE)
|
||||
if(current_disguise)
|
||||
return_look()
|
||||
possible_disguises = null
|
||||
|
||||
/obj/item/mod/module/chameleon/on_use()
|
||||
if(mod.active || mod.activating)
|
||||
balloon_alert(mod.wearer, "suit active!")
|
||||
return
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(current_disguise)
|
||||
return_look()
|
||||
return
|
||||
var/picked_name = tgui_input_list(mod.wearer, "Select look to change into", "Chameleon Settings", possible_disguises)
|
||||
if(!possible_disguises[picked_name] || mod.active || mod.activating)
|
||||
return
|
||||
current_disguise = possible_disguises[picked_name]
|
||||
update_look()
|
||||
|
||||
/obj/item/mod/module/chameleon/proc/update_look()
|
||||
mod.name = initial(current_disguise.name)
|
||||
mod.desc = initial(current_disguise.desc)
|
||||
mod.icon_state = initial(current_disguise.icon_state)
|
||||
mod.icon = initial(current_disguise.icon)
|
||||
mod.worn_icon = initial(current_disguise.worn_icon)
|
||||
mod.alternate_worn_layer = initial(current_disguise.alternate_worn_layer)
|
||||
mod.lefthand_file = initial(current_disguise.lefthand_file)
|
||||
mod.righthand_file = initial(current_disguise.righthand_file)
|
||||
mod.worn_icon_state = initial(current_disguise.worn_icon_state)
|
||||
mod.inhand_icon_state = initial(current_disguise.inhand_icon_state)
|
||||
mod.wearer.update_clothing(mod.slot_flags)
|
||||
RegisterSignal(mod, COMSIG_MOD_ACTIVATE, .proc/return_look)
|
||||
|
||||
/obj/item/mod/module/chameleon/proc/return_look()
|
||||
mod.name = "[mod.theme.name] [initial(mod.name)]"
|
||||
mod.desc = "[initial(mod.desc)] [mod.theme.desc]"
|
||||
mod.icon_state = "[mod.skin]-[initial(mod.icon_state)]"
|
||||
var/list/mod_skin = mod.theme.skins[mod.skin]
|
||||
mod.icon = mod_skin[MOD_ICON_OVERRIDE] || 'icons/obj/clothing/modsuit/mod_clothing.dmi'
|
||||
mod.worn_icon = mod_skin[MOD_WORN_ICON_OVERRIDE] || 'icons/mob/clothing/modsuit/mod_clothing.dmi'
|
||||
mod.alternate_worn_layer = mod_skin[CONTROL_LAYER]
|
||||
mod.lefthand_file = initial(mod.lefthand_file)
|
||||
mod.righthand_file = initial(mod.righthand_file)
|
||||
mod.worn_icon_state = null
|
||||
mod.inhand_icon_state = null
|
||||
mod.wearer.update_clothing(mod.slot_flags)
|
||||
current_disguise = null
|
||||
UnregisterSignal(mod, COMSIG_MOD_ACTIVATE)
|
||||
|
||||
///Plate Compression - Compresses the suit to normal size
|
||||
/obj/item/mod/module/plate_compression
|
||||
name = "MOD plate compression module"
|
||||
desc = "A module that keeps the suit in a very tightly fit state, lowering the overall size. \
|
||||
Due to the pressure on all the parts, typical storage modules do not fit."
|
||||
icon_state = "plate_compression"
|
||||
complexity = 2
|
||||
incompatible_modules = list(/obj/item/mod/module/plate_compression, /obj/item/mod/module/storage)
|
||||
/// The size we set the suit to.
|
||||
var/new_size = WEIGHT_CLASS_NORMAL
|
||||
/// The suit's size before the module is installed.
|
||||
var/old_size
|
||||
|
||||
/obj/item/mod/module/plate_compression/on_install()
|
||||
old_size = mod.w_class
|
||||
mod.w_class = new_size
|
||||
|
||||
/obj/item/mod/module/plate_compression/on_uninstall(deleting = FALSE)
|
||||
mod.w_class = old_size
|
||||
old_size = null
|
||||
if(!mod.loc)
|
||||
return
|
||||
var/datum/component/storage/holding_storage = mod.loc.GetComponent(/datum/component/storage)
|
||||
if(!holding_storage || holding_storage.max_w_class >= mod.w_class)
|
||||
return
|
||||
mod.forceMove(drop_location())
|
||||
|
||||
@@ -28,11 +28,11 @@
|
||||
icon_state = "tray"
|
||||
module_type = MODULE_TOGGLE
|
||||
complexity = 1
|
||||
active_power_cost = DEFAULT_CHARGE_DRAIN * 0.2
|
||||
active_power_cost = DEFAULT_CHARGE_DRAIN * 0.5
|
||||
incompatible_modules = list(/obj/item/mod/module/t_ray)
|
||||
cooldown_time = 0.5 SECONDS
|
||||
/// T-ray scan range.
|
||||
var/range = 2
|
||||
var/range = 4
|
||||
|
||||
/obj/item/mod/module/t_ray/on_active_process(delta_time)
|
||||
t_ray_scan(mod.wearer, 0.8 SECONDS, range)
|
||||
@@ -121,6 +121,7 @@
|
||||
hitsound_wall = 'sound/weapons/batonextend.ogg'
|
||||
suppressed = SUPPRESSED_VERY
|
||||
hit_threshhold = LATTICE_LAYER
|
||||
/// Reference to the beam following the projectile.
|
||||
var/line
|
||||
|
||||
/obj/projectile/tether/fire(setAngle)
|
||||
@@ -217,6 +218,7 @@
|
||||
device = /obj/item/reagent_containers/spray/mister
|
||||
incompatible_modules = list(/obj/item/mod/module/mister)
|
||||
cooldown_time = 0.5 SECONDS
|
||||
/// Volume of our reagent holder.
|
||||
var/volume = 500
|
||||
|
||||
/obj/item/mod/module/mister/Initialize(mapload)
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
the surface of the suit, useful for storing various bits, and or bobs."
|
||||
icon_state = "storage"
|
||||
complexity = 3
|
||||
incompatible_modules = list(/obj/item/mod/module/storage)
|
||||
incompatible_modules = list(/obj/item/mod/module/storage, /obj/item/mod/module/plate_compression)
|
||||
/// The storage component of the module.
|
||||
var/datum/component/storage/concrete/storage
|
||||
/// Max weight class of items in the storage.
|
||||
@@ -186,7 +186,7 @@
|
||||
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 won't free you from masks, \
|
||||
and it will do nothing to improve the taste of a goliath steak."
|
||||
lets pepper spray pass through 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)
|
||||
@@ -228,7 +228,7 @@
|
||||
///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, \
|
||||
desc = "A simple pair of configurable flashlights installed on the left and right sides of the helmet, \
|
||||
useful for providing light in a variety of ranges and colors. \
|
||||
Some survivalists prefer the color green for their illumination, for reasons unknown."
|
||||
icon_state = "flashlight"
|
||||
@@ -240,7 +240,7 @@
|
||||
overlay_state_inactive = "module_light"
|
||||
light_system = MOVABLE_LIGHT_DIRECTIONAL
|
||||
light_color = COLOR_WHITE
|
||||
light_range = 3
|
||||
light_range = 4
|
||||
light_power = 1
|
||||
light_on = FALSE
|
||||
/// Charge drain per range amount.
|
||||
@@ -266,10 +266,8 @@
|
||||
set_light_on(active)
|
||||
|
||||
/obj/item/mod/module/flashlight/on_process(delta_time)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
active_power_cost = base_power * light_range
|
||||
return ..()
|
||||
|
||||
/obj/item/mod/module/flashlight/generate_worn_overlay(mutable_appearance/standing)
|
||||
. = ..()
|
||||
|
||||
@@ -237,6 +237,8 @@
|
||||
drain_power(use_power_cost)
|
||||
num_sheets_dispensed++
|
||||
|
||||
|
||||
///Stamper - Extends a stamp that can switch between accept/deny modes.
|
||||
/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, \
|
||||
|
||||
@@ -128,7 +128,9 @@
|
||||
use_power_cost = DEFAULT_CHARGE_DRAIN
|
||||
incompatible_modules = list(/obj/item/mod/module/organ_thrower, /obj/item/mod/module/microwave_beam)
|
||||
cooldown_time = 0.5 SECONDS
|
||||
/// How many organs the module can hold.
|
||||
var/max_organs = 5
|
||||
/// A list of all our organs.
|
||||
var/organ_list = list()
|
||||
|
||||
/obj/item/mod/module/organ_thrower/on_select_use(atom/target)
|
||||
@@ -165,6 +167,7 @@
|
||||
nodamage = TRUE
|
||||
hitsound = 'sound/effects/attackblob.ogg'
|
||||
hitsound_wall = 'sound/effects/attackblob.ogg'
|
||||
/// A reference to the organ we "are".
|
||||
var/obj/item/organ/organ
|
||||
|
||||
/obj/projectile/organ/Initialize(mapload, obj/item/stored_organ)
|
||||
|
||||
@@ -168,3 +168,54 @@
|
||||
return
|
||||
mod.wearer.visible_message(span_warning("[src] reacts to the attack with a smoke of pepper spray!"), span_notice("Your [src] releases a cloud of pepper spray!"))
|
||||
on_use()
|
||||
|
||||
///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 \
|
||||
standard firearm across its surface and allow for extremely quick retrieval. \
|
||||
While some users prefer the chest, others the forearm for quick deployment, \
|
||||
some law enforcement prefer the holster to extend from the thigh."
|
||||
icon_state = "holster"
|
||||
module_type = MODULE_USABLE
|
||||
complexity = 2
|
||||
incompatible_modules = list(/obj/item/mod/module/holster)
|
||||
cooldown_time = 0.5 SECONDS
|
||||
allowed_inactive = TRUE
|
||||
/// Gun we have holstered.
|
||||
var/obj/item/gun/holstered
|
||||
|
||||
/obj/item/mod/module/holster/on_use()
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
if(!holstered)
|
||||
var/obj/item/gun/holding = mod.wearer.get_active_held_item()
|
||||
if(!holding)
|
||||
balloon_alert(mod.wearer, "nothing to holster!")
|
||||
return
|
||||
if(!istype(holding) || holding.w_class > WEIGHT_CLASS_BULKY)
|
||||
balloon_alert(mod.wearer, "it doesn't fit!")
|
||||
return
|
||||
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)
|
||||
else if(mod.wearer.put_in_active_hand(holstered, forced = FALSE, ignore_animation = TRUE))
|
||||
balloon_alert(mod.wearer, "weapon drawn")
|
||||
playsound(src, 'sound/weapons/gun/revolver/empty.ogg', 100, TRUE)
|
||||
else
|
||||
balloon_alert(mod.wearer, "holster full!")
|
||||
|
||||
/obj/item/mod/module/holster/on_uninstall(deleting = FALSE)
|
||||
if(holstered)
|
||||
holstered.forceMove(drop_location())
|
||||
|
||||
/obj/item/mod/module/holster/Exited(atom/movable/gone, direction)
|
||||
. = ..()
|
||||
if(gone == holstered)
|
||||
holstered = null
|
||||
|
||||
/obj/item/mod/module/holster/Destroy()
|
||||
QDEL_NULL(holstered)
|
||||
return ..()
|
||||
|
||||
@@ -253,12 +253,12 @@
|
||||
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))
|
||||
callback = CALLBACK(src, .proc/on_throw_end, mod.wearer, -angle))
|
||||
|
||||
/obj/item/mod/module/hydraulic/proc/on_throw_end(atom/target, angle)
|
||||
if(!mod?.wearer)
|
||||
/obj/item/mod/module/hydraulic/proc/on_throw_end(mob/user, angle)
|
||||
if(!user)
|
||||
return
|
||||
mod.wearer.transform = mod.wearer.transform.Turn(angle)
|
||||
user.transform = user.transform.Turn(angle)
|
||||
|
||||
/obj/item/mod/module/disposal_connector
|
||||
name = "MOD disposal selector module"
|
||||
@@ -370,6 +370,8 @@
|
||||
var/list/armor_values = list(MELEE = 4, BULLET = 1, LASER = 2, ENERGY = 2, BOMB = 4)
|
||||
/// Speed added when you're fully covered in ash.
|
||||
var/speed_added = 0.5
|
||||
/// Speed that we actually added.
|
||||
var/actual_speed_added = 0
|
||||
/// Turfs that let us accrete ash.
|
||||
var/static/list/accretion_turfs
|
||||
/// Turfs that let us keep ash.
|
||||
@@ -440,7 +442,8 @@
|
||||
mod.wearer.color = list(1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,3) //make them super light
|
||||
animate(mod.wearer, 1 SECONDS, color = null, flags = ANIMATION_PARALLEL)
|
||||
playsound(src, 'sound/effects/sparks1.ogg', 100, TRUE)
|
||||
mod.slowdown -= speed_added
|
||||
actual_speed_added = max(0, min(mod.slowdown_active, speed_added))
|
||||
mod.slowdown -= actual_speed_added
|
||||
mod.wearer.update_equipment_speed_mods()
|
||||
else if(is_type_in_typecache(mod.wearer.loc, keep_turfs))
|
||||
return
|
||||
@@ -448,7 +451,7 @@
|
||||
if(traveled_tiles <= 0)
|
||||
return
|
||||
if(traveled_tiles == max_traveled_tiles)
|
||||
mod.slowdown += speed_added
|
||||
mod.slowdown += actual_speed_added
|
||||
mod.wearer.update_equipment_speed_mods()
|
||||
traveled_tiles--
|
||||
var/list/parts = mod.mod_parts + mod
|
||||
@@ -481,7 +484,7 @@
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
playsound(src, 'sound/items/modsuit/ballin.ogg', 100)
|
||||
playsound(src, 'sound/items/modsuit/ballin.ogg', 100, TRUE)
|
||||
mod.wearer.add_filter("mod_ball", 1, alpha_mask_filter(icon = icon('icons/mob/clothing/modsuit/mod_modules.dmi', "ball_mask"), flags = MASK_INVERSE))
|
||||
mod.wearer.add_filter("mod_blur", 2, angular_blur_filter(size = 15))
|
||||
mod.wearer.add_filter("mod_outline", 3, outline_filter(color = "#000000AA"))
|
||||
@@ -503,7 +506,7 @@
|
||||
if(!.)
|
||||
return
|
||||
if(!deleting)
|
||||
playsound(src, 'sound/items/modsuit/ballout.ogg', 100)
|
||||
playsound(src, 'sound/items/modsuit/ballin.ogg', 100, TRUE, frequency = -1)
|
||||
mod.wearer.base_pixel_y = 0
|
||||
animate(mod.wearer, animate_time, pixel_y = mod.wearer.base_pixel_y)
|
||||
addtimer(CALLBACK(mod.wearer, /atom.proc/remove_filter, list("mod_ball", "mod_blur", "mod_outline")), animate_time)
|
||||
@@ -583,8 +586,6 @@
|
||||
var/damage = 15
|
||||
/// Damage multiplier on hostile fauna.
|
||||
var/fauna_boost = 4
|
||||
/// Damage multiplier on objects
|
||||
var/object_boost = 2
|
||||
/// Image overlaid on explosion.
|
||||
var/static/image/explosion_image
|
||||
|
||||
@@ -609,5 +610,5 @@
|
||||
for(var/mob/living/mob in range(1, src))
|
||||
mob.apply_damage(12 * (ishostile(mob) ? fauna_boost : 1), BRUTE, spread_damage = TRUE)
|
||||
for(var/obj/object in range(1, src))
|
||||
object.take_damage(damage * object_boost, BRUTE, BOMB)
|
||||
object.take_damage(damage, BRUTE, BOMB)
|
||||
qdel(src)
|
||||
|
||||
Reference in New Issue
Block a user