Files
Bubberstation/code/modules/mod/mod_activation.dm
SkyratBot 9e30f1befd [MIRROR] MODsuit module update: new stuff and improved old stuff [MDB IGNORE] (#13685)
* 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.

* MODsuit module update: new stuff and improved old stuff

* should be all

Co-authored-by: Fikou <23585223+Fikou@users.noreply.github.com>
Co-authored-by: John Doe <gamingskeleton3@gmail.com>
2022-05-19 07:29:57 -07:00

254 lines
11 KiB
Plaintext

#define MOD_ACTIVATION_STEP_FLAGS IGNORE_USER_LOC_CHANGE|IGNORE_TARGET_LOC_CHANGE|IGNORE_HELD_ITEM|IGNORE_INCAPACITATED|IGNORE_SLOWDOWNS
/// Creates a radial menu from which the user chooses parts of the suit to deploy/retract. Repeats until all parts are extended or retracted.
/obj/item/mod/control/proc/choose_deploy(mob/user)
if(!length(mod_parts))
return
var/list/display_names = list()
var/list/items = list()
for(var/obj/item/part as anything in mod_parts)
display_names[part.name] = REF(part)
var/image/part_image = image(icon = part.icon, icon_state = part.icon_state)
if(part.loc != src)
part_image.underlays += image(icon = 'icons/hud/radial.dmi', icon_state = "module_active")
items += list(part.name = part_image)
var/pick = show_radial_menu(user, src, items, custom_check = FALSE, require_near = TRUE, tooltips = TRUE)
if(!pick)
return
var/part_reference = display_names[pick]
var/obj/item/part = locate(part_reference) in mod_parts
if(!istype(part) || user.incapacitated())
return
if(activating) // SKYRAT EDIT - RETRACTABLE EVERYTHING
balloon_alert(user, "deactivate the suit first!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return
var/parts_to_check = mod_parts - part
if(part.loc == src)
deploy(user, part)
for(var/obj/item/checking_part as anything in parts_to_check)
if(checking_part.loc != src)
continue
choose_deploy(user)
break
else
retract(user, part)
for(var/obj/item/checking_part as anything in parts_to_check)
if(checking_part.loc == src)
continue
choose_deploy(user)
break
/// Quickly deploys all parts (or retracts if all are on the wearer)
/obj/item/mod/control/proc/quick_deploy(mob/user)
if(activating) // SKYRAT EDIT - RETRACTABLE EVERYTHING
balloon_alert(user, "deactivate the suit first!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
var/deploy = FALSE
for(var/obj/item/part as anything in mod_parts)
if(part.loc != src)
continue
deploy = TRUE
for(var/obj/item/part as anything in mod_parts)
if(deploy && part.loc == src)
deploy(null, part)
else if(!deploy && part.loc != src)
retract(null, part)
wearer.visible_message(span_notice("[wearer]'s [src] [deploy ? "deploys" : "retracts"] its' parts with a mechanical hiss."),
span_notice("[src] [deploy ? "deploys" : "retracts"] its' parts with a mechanical hiss."),
span_hear("You hear a mechanical hiss."))
playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
return TRUE
/// Deploys a part of the suit onto the user.
/obj/item/mod/control/proc/deploy(mob/user, obj/item/part)
if(part.loc != src)
if(!user)
return FALSE
balloon_alert(user, "[part.name] already deployed!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
if(part in overslotting_parts)
var/obj/item/overslot = wearer.get_item_by_slot(part.slot_flags)
if(overslot)
overslotting_parts[part] = overslot
wearer.transferItemToLoc(overslot, part, force = TRUE)
RegisterSignal(part, COMSIG_ATOM_EXITED, .proc/on_overslot_exit)
if(wearer.equip_to_slot_if_possible(part, part.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE))
ADD_TRAIT(part, TRAIT_NODROP, MOD_TRAIT)
if(!user)
return TRUE
wearer.visible_message(span_notice("[wearer]'s [part.name] deploy[part.p_s()] with a mechanical hiss."),
span_notice("[part] deploy[part.p_s()] with a mechanical hiss."),
span_hear("You hear a mechanical hiss."))
playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
return TRUE
else
if(!user)
return FALSE
balloon_alert(user, "bodypart clothed!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
/// Retract a part of the suit from the user.
/obj/item/mod/control/proc/retract(mob/user, obj/item/part)
if(part.loc == src)
if(!user)
return FALSE
balloon_alert(user, "[part.name] already retracted!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
REMOVE_TRAIT(part, TRAIT_NODROP, MOD_TRAIT)
wearer.transferItemToLoc(part, src, force = TRUE)
if(overslotting_parts[part])
UnregisterSignal(part, COMSIG_ATOM_EXITED)
var/obj/item/overslot = overslotting_parts[part]
if(!wearer.equip_to_slot_if_possible(overslot, overslot.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE))
wearer.dropItemToGround(overslot, force = TRUE, silent = TRUE)
overslotting_parts[part] = null
if(!user)
return
wearer.visible_message(span_notice("[wearer]'s [part.name] retract[part.p_s()] back into [src] with a mechanical hiss."),
span_notice("[part] retract[part.p_s()] back into [src] with a mechanical hiss."),
span_hear("You hear a mechanical hiss."))
playsound(src, 'sound/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
/// Starts the activation sequence, where parts of the suit activate one by one until the whole suit is on
/obj/item/mod/control/proc/toggle_activate(mob/user, force_deactivate = FALSE)
if(!wearer)
if(!force_deactivate)
balloon_alert(user, "equip suit first!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
if(!force_deactivate && (SEND_SIGNAL(src, COMSIG_MOD_ACTIVATE, user) & MOD_CANCEL_ACTIVATE))
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
for(var/obj/item/part as anything in mod_parts)
if(!force_deactivate && part.loc == src)
balloon_alert(user, "deploy all parts first!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
if(locked && !active && !allowed(user) && !force_deactivate)
balloon_alert(user, "access insufficient!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
if(!get_charge() && !force_deactivate)
balloon_alert(user, "suit not powered!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
if(open && !force_deactivate)
balloon_alert(user, "close the suit panel!")
playsound(src, 'sound/machines/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
if(activating)
if(!force_deactivate)
balloon_alert(user, "suit already [active ? "shutting down" : "starting up"]!")
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 || module.allowed_inactive)
continue
module.on_deactivation(display_message = FALSE)
activating = TRUE
to_chat(wearer, span_notice("MODsuit [active ? "shutting down" : "starting up"]."))
// SKYRAT EDIT START - pAIs in MODsuits
if(mod_pai)
to_chat(mod_pai, span_notice("MODsuit [active ? "shutting down" : "starting up"]."))
// SKYRAT EDIT END
if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, .proc/has_wearer)))
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, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, .proc/has_wearer)))
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, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, .proc/has_wearer)))
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, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, .proc/has_wearer)))
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, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, .proc/has_wearer)))
to_chat(wearer, span_notice("Systems [active ? "shut down. Parts unsealed. Goodbye" : "started up. Parts sealed. Welcome"], [wearer]."))
// SKYRAT EDIT START - pAIs in MODsuits
if(mod_pai)
to_chat(mod_pai, span_notice("<b>SYSTEMS [active ? "DEACTIVATED. GOODBYE" : "ACTIVATED. WELCOME"]: \"[mod_pai]\"</b>"))
// SKYRAT EDIT END
finish_activation(on = !active)
if(active)
playsound(src, 'sound/machines/synth_yes.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 6000)
if(!malfunctioning)
wearer.playsound_local(get_turf(src), 'sound/mecha/nominal.ogg', 50)
else
playsound(src, 'sound/machines/synth_no.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 6000)
activating = FALSE
return TRUE
///Seals or unseals the given part
/obj/item/mod/control/proc/seal_part(obj/item/clothing/part, seal)
if(seal)
part.clothing_flags |= part.visor_flags
part.flags_inv |= part.visor_flags_inv
part.flags_cover |= part.visor_flags_cover
part.heat_protection = initial(part.heat_protection)
part.cold_protection = initial(part.cold_protection)
part.alternate_worn_layer = null
else
part.flags_cover &= ~part.visor_flags_cover
part.flags_inv &= ~part.visor_flags_inv + HIDESPINE // SKYRAT EDIT - Hiding the tail spines from MODsuits
part.clothing_flags &= ~part.visor_flags
part.heat_protection = NONE
part.cold_protection = NONE
part.alternate_worn_layer = mod_parts[part]
if(part == boots)
boots.icon_state = "[skin]-boots[seal ? "-sealed" : ""]"
wearer.update_inv_shoes()
if(part == gauntlets)
gauntlets.icon_state = "[skin]-gauntlets[seal ? "-sealed" : ""]"
wearer.update_inv_gloves()
if(part == chestplate)
chestplate.icon_state = "[skin]-chestplate[seal ? "-sealed" : ""]"
wearer.update_inv_wear_suit()
wearer.update_inv_w_uniform()
if(part == helmet)
helmet.icon_state = "[skin]-helmet[seal ? "-sealed" : ""]"
wearer.update_inv_head()
wearer.update_inv_wear_mask()
wearer.update_inv_glasses()
wearer.update_hair()
/// Finishes the suit's activation, starts processing
/obj/item/mod/control/proc/finish_activation(on)
active = on
if(active)
for(var/obj/item/mod/module/module as anything in modules)
module.on_suit_activation()
START_PROCESSING(SSobj, src)
else
for(var/obj/item/mod/module/module as anything in modules)
module.on_suit_deactivation()
STOP_PROCESSING(SSobj, src)
update_speed()
update_icon_state()
wearer.update_clothing(slot_flags)
/// Quickly deploys all the suit parts and if successful, seals them and turns on the suit. Intended mostly for outfits.
/obj/item/mod/control/proc/quick_activation()
var/seal = TRUE
for(var/obj/item/part as anything in mod_parts)
if(!deploy(null, part))
seal = FALSE
if(!seal)
return
for(var/obj/item/part as anything in mod_parts)
seal_part(part, seal = TRUE)
finish_activation(on = TRUE)
/obj/item/mod/control/proc/has_wearer()
return wearer
#undef MOD_ACTIVATION_STEP_FLAGS