fixes issues with the separate modsuit part activation (#87482)

## About The Pull Request

generally cleans up the code a bit. fixes the issue where if you had
clothing on yourself already and you tried extending when active it
still went through the sealing process even though it didnt extend the
part, causing weird desyncs. fixes the issues with part enabled modules
that would not activate, makes stealth and radproof modules require the
whole suit to be out cause thinking about it they wouldnt really work
without that i think
reverts quick activation to try put parts on you instead of removing
them as priority, i think that plays nicer with separate part activation

fixes #87413
This commit is contained in:
Fikou
2024-10-31 12:12:49 -05:00
committed by GitHub
parent 762a52ed83
commit 0f684bd7db
17 changed files with 225 additions and 244 deletions
+87 -55
View File
@@ -26,8 +26,7 @@
return
var/parts_to_check = parts - part
if(part.loc == src)
deploy(user, part)
if(active && !delayed_seal_part(part))
if(!deploy(user, part) || (active && !delayed_seal_part(part)))
return
SEND_SIGNAL(src, COMSIG_MOD_DEPLOYED, user)
for(var/obj/item/checking_part as anything in parts_to_check)
@@ -36,9 +35,8 @@
choose_deploy(user)
break
else
if(active && !delayed_seal_part(part))
if((active && !delayed_seal_part(part, silent = TRUE)) || !retract(user, part))
return
retract(user, part)
SEND_SIGNAL(src, COMSIG_MOD_RETRACTED, user)
for(var/obj/item/checking_part as anything in parts_to_check)
if(checking_part.loc == src)
@@ -49,28 +47,30 @@
/// Quickly deploys all parts (or retracts if all are on the wearer)
/obj/item/mod/control/proc/quick_deploy(mob/user)
if(activating)
balloon_alert(user, "currently sealing/unsealing!")
balloon_alert(user, "currently [active ? "unsealing" : "sealing"]!")
playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
var/deploy = TRUE
var/deploy = FALSE
for(var/obj/item/part as anything in get_parts())
if(part.loc == src)
if(part.loc != src)
continue
deploy = FALSE
deploy = TRUE
break
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/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
for(var/obj/item/part as anything in get_parts())
if(deploy && part.loc == src)
deploy(null, part)
if(!deploy(null, part))
continue
if(active && !delayed_seal_part(part))
retract(null, part)
return
else if(!deploy && part.loc != src)
if(active && !delayed_seal_part(part))
return
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/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
if(deploy)
SEND_SIGNAL(src, COMSIG_MOD_DEPLOYED, user)
else
@@ -96,6 +96,7 @@
RegisterSignal(part, COMSIG_ATOM_EXITED, PROC_REF(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)
wearer.update_clothing(slot_flags)
if(!user)
return TRUE
wearer.visible_message(span_notice("[wearer]'s [part.name] deploy[part.p_s()] with a mechanical hiss."),
@@ -105,6 +106,10 @@
SEND_SIGNAL(src, COMSIG_MOD_PART_DEPLOYED, user, part)
return TRUE
else
if(part_datum.overslotting)
var/obj/item/overslot = part_datum.overslotting
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)
if(!user)
return FALSE
balloon_alert(user, "bodypart clothed!")
@@ -119,21 +124,22 @@
return FALSE
balloon_alert(user, "[part.name] already retracted!")
playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return FALSE
REMOVE_TRAIT(part, TRAIT_NODROP, MOD_TRAIT)
wearer.transferItemToLoc(part, src, force = TRUE)
if(part_datum.overslotting)
UnregisterSignal(part, COMSIG_ATOM_EXITED)
var/obj/item/overslot = part_datum.overslotting
if(!QDELING(wearer) && !wearer.equip_to_slot_if_possible(overslot, overslot.slot_flags, qdel_on_fail = FALSE, disable_warning = TRUE))
wearer.dropItemToGround(overslot, force = TRUE, silent = TRUE)
part_datum.overslotting = null
wearer.update_clothing(slot_flags)
SEND_SIGNAL(src, COMSIG_MOD_PART_RETRACTED, user, part)
if(!user)
return
return TRUE
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/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
return TRUE
/// 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)
@@ -168,46 +174,71 @@
module.deactivate(display_message = FALSE)
activating = TRUE
mod_link.end_call()
var/original_active_status = active
to_chat(wearer, span_notice("MODsuit [active ? "shutting down" : "starting up"]."))
//deploy the control unit
if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(get_wearer)), hidden = TRUE))
playsound(src, active ? 'sound/machines/synth/synth_no.ogg' : 'sound/machines/synth/synth_yes.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 8000)
else
activating = FALSE
return
if(original_active_status)
if(delayed_activation())
playsound(src, 'sound/machines/synth/synth_no.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 6000)
to_chat(wearer, span_notice("Control unit offline. Module capability removed."))
else
activating = FALSE
return
var/list/sealed_parts = list()
for(var/obj/item/part as anything in get_parts()) //seals/unseals all deployed parts
if(part.loc == src)
continue
delayed_seal_part(part, no_activation = TRUE)
if(!delayed_seal_part(part)) //shit something broke, revert it all
activating = FALSE
for(var/obj/item/sealed_part as anything in sealed_parts)
seal_part(sealed_part, is_sealed = !get_part_datum(sealed_part).sealed)
if(original_active_status)
control_activation(is_on = TRUE)
to_chat(wearer, span_notice("Critical error in sealing systems. Reverting process."))
playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return
sealed_parts += part
//finish activation
to_chat(wearer, span_notice("Systems [active ? "shut down. Parts unsealed. Goodbye" : "started up. Parts sealed. Welcome"], [wearer]."))
if(!original_active_status)
if(delayed_activation())
playsound(src, 'sound/machines/synth/synth_yes.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 6000)
if(!malfunctioning)
wearer.playsound_local(get_turf(src), 'sound/vehicles/mecha/nominal.ogg', 50)
else
activating = FALSE
for(var/obj/item/sealed_part as anything in sealed_parts)
seal_part(sealed_part, is_sealed = !get_part_datum(sealed_part).sealed)
to_chat(wearer, span_notice("Critical error in sealing systems. Reverting process."))
playsound(src, 'sound/machines/scanner/scanbuzz.ogg', 25, TRUE, SILENCED_SOUND_EXTRARANGE)
return
to_chat(wearer, span_notice("Systems [active ? "started up. Parts sealed. Welcome" : "shut down. Parts unsealed. Goodbye"], [wearer]."))
if(ai_assistant)
to_chat(ai_assistant, span_notice("<b>SYSTEMS [active ? "DEACTIVATED. GOODBYE" : "ACTIVATED. WELCOME"]: \"[ai_assistant]\"</b>"))
finish_activation(is_on = !active)
if(active)
playsound(src, 'sound/machines/synth/synth_yes.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 6000)
if(!malfunctioning)
wearer.playsound_local(get_turf(src), 'sound/vehicles/mecha/nominal.ogg', 50)
else
playsound(src, 'sound/machines/synth/synth_no.ogg', 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE, frequency = 6000)
to_chat(ai_assistant, span_notice("<b>SYSTEMS [active ? "ACTIVATED. WELCOME" : "DEACTIVATED. GOODBYE"]: \"[ai_assistant]\"</b>"))
activating = FALSE
SEND_SIGNAL(src, COMSIG_MOD_TOGGLED, user)
return TRUE
/obj/item/mod/control/proc/delayed_seal_part(obj/item/clothing/part, no_activation = FALSE)
/obj/item/mod/control/proc/delayed_seal_part(obj/item/clothing/part, silent = FALSE)
. = FALSE
var/datum/mod_part/part_datum = get_part_datum(part)
if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(get_wearer)), hidden = TRUE))
to_chat(wearer, span_notice("[part] [!part_datum.sealed ? part_datum.sealed_message : part_datum.unsealed_message]."))
playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
seal_part(part, is_sealed = !part_datum.sealed, no_activation = no_activation)
if(!silent)
to_chat(wearer, span_notice("[part] [!part_datum.sealed ? part_datum.sealed_message : part_datum.unsealed_message]."))
playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
seal_part(part, is_sealed = !part_datum.sealed)
return TRUE
/obj/item/mod/control/proc/delayed_activation()
. = FALSE
if(do_after(wearer, activation_step_time, wearer, MOD_ACTIVATION_STEP_FLAGS, extra_checks = CALLBACK(src, PROC_REF(get_wearer)), hidden = TRUE))
control_activation(is_on = !active)
return TRUE
///Seals or unseals the given part.
/obj/item/mod/control/proc/seal_part(obj/item/clothing/part, is_sealed, no_activation = FALSE)
/obj/item/mod/control/proc/seal_part(obj/item/clothing/part, is_sealed)
var/datum/mod_part/part_datum = get_part_datum(part)
part_datum.sealed = is_sealed
if(part_datum.sealed)
@@ -231,38 +262,41 @@
wearer.update_obscured_slots(part.visor_flags_inv)
if((part.clothing_flags & (MASKINTERNALS|HEADINTERNALS)) && wearer.invalid_internals())
wearer.cutoff_internals()
if(!active || no_activation)
if(!active)
return
// these only matter during sealing and unsealing while active via deployment
if(is_sealed)
for(var/obj/item/mod/module/module as anything in modules)
if(!module.has_required_parts(list("[part.slot_flags]" = part_datum), need_extended = TRUE))
if(module.part_activated || !module.has_required_parts(mod_parts, need_active = TRUE))
continue
module.on_suit_activation()
module.on_part_activation()
module.part_activated = TRUE
else
for(var/obj/item/mod/module/module as anything in modules)
if(!module.has_required_parts(list("[part.slot_flags]" = part_datum), need_extended = TRUE))
if(!module.part_activated || module.has_required_parts(mod_parts, need_active = TRUE))
continue
module.on_suit_deactivation()
module.on_part_deactivation()
module.part_activated = FALSE
if(!module.active || (module.allow_flags & MODULE_ALLOW_INACTIVE))
continue
module.deactivate(display_message = FALSE)
/// Finishes the suit's activation
/obj/item/mod/control/proc/finish_activation(is_on)
/obj/item/mod/control/proc/control_activation(is_on)
var/datum/mod_part/part_datum = get_part_datum(src)
part_datum.sealed = is_on
active = is_on
if(active)
for(var/obj/item/mod/module/module as anything in modules)
if(!module.has_required_parts(mod_parts, need_extended = TRUE))
if(module.part_activated || !module.has_required_parts(mod_parts, need_active = TRUE))
continue
module.on_suit_activation()
module.on_part_activation()
module.part_activated = TRUE
else
for(var/obj/item/mod/module/module as anything in modules)
if(!module.has_required_parts(mod_parts, need_extended = TRUE)) //it probably will runtime if we dont do this
if(!module.part_activated || module.has_required_parts(mod_parts, need_active = TRUE))
continue
module.on_suit_deactivation()
module.on_part_deactivation()
module.part_activated = FALSE
update_speed()
update_charge_alert()
update_appearance(UPDATE_ICON_STATE)
@@ -271,14 +305,12 @@
/// 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 get_parts())
if(!deploy(null, part))
seal = FALSE
if(!seal)
return
deploy(null, part)
for(var/obj/item/part as anything in get_parts())
if(part.loc == src)
continue
seal_part(part, is_sealed = TRUE)
finish_activation(is_on = TRUE)
control_activation(is_on = TRUE)
#undef MOD_ACTIVATION_STEP_FLAGS