Refactors MODsuit module rendering and allows overslotted parts to show items they overslot when unsealed (#90414)

MODsuit modules now render on the part they're attached to, that being
first part if required_slots is set, otherwise defaulting to the control
module. Instead of using icon ops and a cache, module masking (used by
armor boosters and insignias) will instead render the module on all
parts, each overlay alpha filtered using the worn piece as the mask. To
do this we also migrate modules to separate_worn_overlays, which fixes
the issue where they'd always get painted the same color as the back
piece, ignoring use_mod_colors's value (which is FALSE by default). So
now modules that inherit MOD's color like armor booster will be painted
accordingly to their piece.
This also means that modules actually layer properly, and don't go ontop
of items that they should be under.

Additionally, whenever gloves or boots overslot an item, the overslotted
item will still render underneath them if they're unsealed. Because it
looks weird when your gloves disappear when you extend your MODsuit
ones.

![dreamseeker_BaWjJBcMVO](https://github.com/user-attachments/assets/2b374913-7761-4b54-9bbd-cbd57d343fd6)

Look at that hip look, she'd have bare hands and ankles without this PR.

Closes #90370

Fixes a bunch of visual jank that looks weird, and overslotting
displaying overslotted item is just behavior you'd expect normally.

🆑
add: When a MODsuit piece overslots an item, it will now render beneath
that piece as long as its unsealed.
refactor: Refactored how MODsuit modules are rendered, report any bugs
on GitHub!
/🆑
This commit is contained in:
SmArtKar
2025-04-15 10:21:10 +02:00
committed by Shadow-Quill
parent 711b8c215e
commit 8e0750a6c3
19 changed files with 234 additions and 147 deletions

View File

@@ -57,9 +57,5 @@
/// Global list of all /datum/mod_theme /// Global list of all /datum/mod_theme
GLOBAL_LIST_INIT(mod_themes, setup_mod_themes()) GLOBAL_LIST_INIT(mod_themes, setup_mod_themes())
/// Global cache of mod skins to masks per different configuration of pulled out parts.
GLOBAL_LIST_EMPTY(mod_masks)
/// Global cache of mod skins to deployed parts to module icon states
GLOBAL_LIST_EMPTY(mod_module_overlays)
/// Global list of all ids associated to a /datum/mod_link instance /// Global list of all ids associated to a /datum/mod_link instance
GLOBAL_LIST_EMPTY(mod_link_ids) GLOBAL_LIST_EMPTY(mod_link_ids)

View File

@@ -119,49 +119,12 @@
var/obj/item/worn_item = worn_items[slot_flag] var/obj/item/worn_item = worn_items[slot_flag]
if(!worn_item) if(!worn_item)
continue continue
var/default_layer = 0 var/default_icon = get_default_icon_by_slot(text2num(slot_flag))
var/default_icon = null var/default_layer = get_default_layer_by_slot(text2num(slot_flag))
var/female_icon = NO_FEMALE_UNIFORM var/female_icon = NO_FEMALE_UNIFORM
switch(text2num(slot_flag)) //this kinda sucks because build worn icon kinda sucks if(body_type == FEMALE && istype(worn_item, /obj/item/clothing/under))
if(ITEM_SLOT_HEAD) var/obj/item/clothing/under/worn_jumpsuit = worn_item
default_layer = HEAD_LAYER female_icon = worn_jumpsuit.female_sprite_flags
default_icon = 'icons/mob/clothing/head/default.dmi'
if(ITEM_SLOT_EYES)
default_layer = GLASSES_LAYER
default_icon = 'icons/mob/clothing/eyes.dmi'
if(ITEM_SLOT_EARS)
default_layer = EARS_LAYER
default_icon = 'icons/mob/clothing/ears.dmi'
if(ITEM_SLOT_MASK)
default_layer = FACEMASK_LAYER
default_icon = 'icons/mob/clothing/mask.dmi'
if(ITEM_SLOT_NECK)
default_layer = NECK_LAYER
default_icon = 'icons/mob/clothing/neck.dmi'
if(ITEM_SLOT_BACK)
default_layer = BACK_LAYER
default_icon = 'icons/mob/clothing/back.dmi'
if(ITEM_SLOT_BELT)
default_layer = BELT_LAYER
default_icon = 'icons/mob/clothing/belt.dmi'
if(ITEM_SLOT_ID)
default_layer = ID_LAYER
default_icon = 'icons/mob/clothing/id.dmi'
if(ITEM_SLOT_ICLOTHING)
default_layer = UNIFORM_LAYER
default_icon = DEFAULT_UNIFORM_FILE
if(body_type == FEMALE && istype(worn_item, /obj/item/clothing/under))
var/obj/item/clothing/under/worn_jumpsuit = worn_item
female_icon = worn_jumpsuit.female_sprite_flags
if(ITEM_SLOT_OCLOTHING)
default_layer = SUIT_LAYER
default_icon = DEFAULT_SUIT_FILE
if(ITEM_SLOT_GLOVES)
default_layer = GLOVES_LAYER
default_icon = 'icons/mob/clothing/hands.dmi'
if(ITEM_SLOT_FEET)
default_layer = SHOES_LAYER
default_icon = DEFAULT_SHOES_FILE
. += worn_item.build_worn_icon(default_layer, default_icon, female_uniform = female_icon) . += worn_item.build_worn_icon(default_layer, default_icon, female_uniform = female_icon)
/obj/structure/mannequin/attack_hand_secondary(mob/user, list/modifiers) /obj/structure/mannequin/attack_hand_secondary(mob/user, list/modifiers)

View File

@@ -78,8 +78,7 @@
/datum/outfit/clown_operative/post_equip(mob/living/carbon/human/H, visuals_only) /datum/outfit/clown_operative/post_equip(mob/living/carbon/human/H, visuals_only)
var/obj/item/mod/module/armor_booster/booster = locate() in H.back var/obj/item/mod/module/armor_booster/booster = locate() in H.back
booster.active = TRUE booster.activate()
H.update_worn_back()
/datum/outfit/clown_operative_elite /datum/outfit/clown_operative_elite
name = "Clown Operative (Elite, Preview only)" name = "Clown Operative (Elite, Preview only)"
@@ -89,5 +88,4 @@
/datum/outfit/clown_operative_elite/post_equip(mob/living/carbon/human/H, visuals_only) /datum/outfit/clown_operative_elite/post_equip(mob/living/carbon/human/H, visuals_only)
var/obj/item/mod/module/armor_booster/booster = locate() in H.back var/obj/item/mod/module/armor_booster/booster = locate() in H.back
booster.active = TRUE booster.activate()
H.update_worn_back()

View File

@@ -188,8 +188,7 @@
/datum/outfit/nuclear_operative/post_equip(mob/living/carbon/human/H, visuals_only) /datum/outfit/nuclear_operative/post_equip(mob/living/carbon/human/H, visuals_only)
var/obj/item/mod/module/armor_booster/booster = locate() in H.back var/obj/item/mod/module/armor_booster/booster = locate() in H.back
booster.active = TRUE booster.activate()
H.update_worn_back()
/datum/outfit/nuclear_operative_elite /datum/outfit/nuclear_operative_elite
name = "Nuclear Operative (Elite, Preview only)" name = "Nuclear Operative (Elite, Preview only)"
@@ -201,8 +200,7 @@
/datum/outfit/nuclear_operative_elite/post_equip(mob/living/carbon/human/H, visuals_only) /datum/outfit/nuclear_operative_elite/post_equip(mob/living/carbon/human/H, visuals_only)
var/obj/item/mod/module/armor_booster/booster = locate() in H.back var/obj/item/mod/module/armor_booster/booster = locate() in H.back
booster.active = TRUE booster.activate()
H.update_worn_back()
var/obj/item/shield/energy/shield = locate() in H.held_items var/obj/item/shield/energy/shield = locate() in H.held_items
shield.icon_state = "[shield.base_icon_state]1" shield.icon_state = "[shield.base_icon_state]1"
H.update_held_items() H.update_held_items()

View File

@@ -658,3 +658,57 @@ GLOBAL_LIST_EMPTY(masked_leg_icons_cache)
new_leg_appearance_lower.layer = -BODYPARTS_LOW_LAYER new_leg_appearance_lower.layer = -BODYPARTS_LOW_LAYER
. += new_leg_appearance_lower . += new_leg_appearance_lower
return . return .
/proc/get_default_icon_by_slot(slot_flag)
switch(slot_flag)
if(ITEM_SLOT_HEAD)
return 'icons/mob/clothing/head/default.dmi'
if(ITEM_SLOT_EYES)
return 'icons/mob/clothing/eyes.dmi'
if(ITEM_SLOT_EARS)
return 'icons/mob/clothing/ears.dmi'
if(ITEM_SLOT_MASK)
return 'icons/mob/clothing/mask.dmi'
if(ITEM_SLOT_NECK)
return 'icons/mob/clothing/neck.dmi'
if(ITEM_SLOT_BACK)
return 'icons/mob/clothing/back.dmi'
if(ITEM_SLOT_BELT)
return 'icons/mob/clothing/belt.dmi'
if(ITEM_SLOT_ID)
return 'icons/mob/clothing/id.dmi'
if(ITEM_SLOT_ICLOTHING)
return DEFAULT_UNIFORM_FILE
if(ITEM_SLOT_OCLOTHING)
return DEFAULT_SUIT_FILE
if(ITEM_SLOT_GLOVES)
return 'icons/mob/clothing/hands.dmi'
if(ITEM_SLOT_FEET)
return DEFAULT_SHOES_FILE
/proc/get_default_layer_by_slot(slot_flag)
switch(text2num(slot_flag))
if(ITEM_SLOT_HEAD)
return HEAD_LAYER
if(ITEM_SLOT_EYES)
return GLASSES_LAYER
if(ITEM_SLOT_EARS)
return EARS_LAYER
if(ITEM_SLOT_MASK)
return FACEMASK_LAYER
if(ITEM_SLOT_NECK)
return NECK_LAYER
if(ITEM_SLOT_BACK)
return BACK_LAYER
if(ITEM_SLOT_BELT)
return BELT_LAYER
if(ITEM_SLOT_ID)
return ID_LAYER
if(ITEM_SLOT_ICLOTHING)
return UNIFORM_LAYER
if(ITEM_SLOT_OCLOTHING)
return SUIT_LAYER
if(ITEM_SLOT_GLOVES)
return GLOVES_LAYER
if(ITEM_SLOT_FEET)
return SHOES_LAYER

View File

@@ -93,7 +93,7 @@
RegisterSignal(part, COMSIG_ATOM_EXITED, PROC_REF(on_overslot_exit)) 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)) 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) ADD_TRAIT(part, TRAIT_NODROP, MOD_TRAIT)
wearer.update_clothing(slot_flags) wearer.update_clothing(slot_flags|part.slot_flags)
SEND_SIGNAL(src, COMSIG_MOD_PART_DEPLOYED, user, part_datum) SEND_SIGNAL(src, COMSIG_MOD_PART_DEPLOYED, user, part_datum)
if(user) if(user)
wearer.visible_message(span_notice("[wearer]'s [part.name] deploy[part.p_s()] with a mechanical hiss."), wearer.visible_message(span_notice("[wearer]'s [part.name] deploy[part.p_s()] with a mechanical hiss."),
@@ -131,7 +131,9 @@
return FALSE return FALSE
if(SEND_SIGNAL(src, COMSIG_MOD_PART_RETRACTING, user, part_datum) & MOD_CANCEL_RETRACTION) if(SEND_SIGNAL(src, COMSIG_MOD_PART_RETRACTING, user, part_datum) & MOD_CANCEL_RETRACTION)
return FALSE return FALSE
var/unsealing = FALSE
if(active && part_datum.sealed) if(active && part_datum.sealed)
unsealing = TRUE
if(instant) if(instant)
seal_part(part, is_sealed = FALSE) seal_part(part, is_sealed = FALSE)
else if(!delayed_seal_part(part)) else if(!delayed_seal_part(part))
@@ -144,13 +146,14 @@
var/obj/item/overslot = part_datum.overslotting 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)) 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) wearer.dropItemToGround(overslot, force = TRUE, silent = TRUE)
wearer.update_clothing(slot_flags) wearer.update_clothing(slot_flags|part.slot_flags)
if(!user) if(!user)
return TRUE return TRUE
wearer.visible_message(span_notice("[wearer]'s [part.name] retract[part.p_s()] back into [src] with a mechanical hiss."), 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_notice("[part] retract[part.p_s()] back into [src] with a mechanical hiss."),
span_hear("You hear a mechanical hiss.")) span_hear("You hear a mechanical hiss."))
playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) if (!unsealing)
playsound(src, 'sound/vehicles/mecha/mechmove03.ogg', 25, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
return TRUE return TRUE
/// Starts the activation sequence, where parts of the suit activate one by one until the whole suit is on. /// Starts the activation sequence, where parts of the suit activate one by one until the whole suit is on.
@@ -268,7 +271,6 @@
part.heat_protection = NONE part.heat_protection = NONE
part.cold_protection = NONE part.cold_protection = NONE
part.alternate_worn_layer = part_datum.unsealed_layer part.alternate_worn_layer = part_datum.unsealed_layer
generate_suit_mask()
update_speed() update_speed()
wearer.update_clothing(part.slot_flags | slot_flags) wearer.update_clothing(part.slot_flags | slot_flags)
wearer.update_obscured_slots(part.visor_flags_inv) wearer.update_obscured_slots(part.visor_flags_inv)
@@ -281,7 +283,7 @@
for(var/obj/item/mod/module/module as anything in modules) for(var/obj/item/mod/module/module as anything in modules)
if(module.part_activated || !module.has_required_parts(mod_parts, need_active = TRUE)) if(module.part_activated || !module.has_required_parts(mod_parts, need_active = TRUE))
continue continue
module.on_part_activation() module.on_part_activation()
module.part_activated = TRUE module.part_activated = TRUE
else else
for(var/obj/item/mod/module/module as anything in modules) for(var/obj/item/mod/module/module as anything in modules)
@@ -300,23 +302,16 @@
active = is_on active = is_on
if(active) if(active)
for(var/obj/item/mod/module/module as anything in modules) for(var/obj/item/mod/module/module as anything in modules)
if(module.part_activated || !module.has_required_parts(mod_parts, need_active = TRUE)) if(!module.part_activated && module.has_required_parts(mod_parts, need_active = TRUE))
continue module.on_part_activation()
module.on_part_activation()
module.part_activated = TRUE
else else
for(var/obj/item/mod/module/module as anything in modules) for(var/obj/item/mod/module/module as anything in modules)
if(!module.part_activated) if(!module.part_activated)
continue continue
module.on_part_deactivation() module.on_part_deactivation()
module.part_activated = FALSE
if(!module.active || (module.allow_flags & MODULE_ALLOW_INACTIVE))
continue
module.deactivate(display_message = FALSE)
update_charge_alert() update_charge_alert()
update_appearance(UPDATE_ICON_STATE) update_appearance(UPDATE_ICON_STATE)
generate_suit_mask() wearer.update_clothing()
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. /// 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() /obj/item/mod/control/proc/quick_activation()

View File

@@ -115,13 +115,10 @@
if(core) if(core)
QDEL_NULL(core) QDEL_NULL(core)
QDEL_NULL(mod_link) QDEL_NULL(mod_link)
for(var/datum/mod_part/part_datum as anything in get_part_datums(all = TRUE)) for(var/part_key in mod_parts)
var/obj/item/part_item = part_datum.part_item var/datum/mod_part/part_datum = mod_parts[part_key]
part_datum.part_item = null mod_parts -= part_key
part_datum.overslotting = null qdel(part_datum)
mod_parts -= part_datum
if(!QDELING(part_item))
qdel(part_item)
return ..() return ..()
/obj/item/mod/control/atom_destruction(damage_flag) /obj/item/mod/control/atom_destruction(damage_flag)
@@ -454,11 +451,14 @@
CRASH("get_part_datum called with incorrect item [part] passed.") CRASH("get_part_datum called with incorrect item [part] passed.")
/obj/item/mod/control/proc/get_part_from_slot(slot) /obj/item/mod/control/proc/get_part_from_slot(slot)
var/datum/mod_part/part = mod_parts["[slot]"] RETURN_TYPE(/obj/item)
return part?.part_item return get_part_datum_from_slot(slot)?.part_item
/obj/item/mod/control/proc/get_part_datum_from_slot(slot) /obj/item/mod/control/proc/get_part_datum_from_slot(slot)
return mod_parts["[slot]"] RETURN_TYPE(/datum/mod_part)
for (var/part_key in mod_parts)
if (text2num(part_key) & slot)
return mod_parts[part_key]
/obj/item/mod/control/proc/set_wearer(mob/living/carbon/human/user) /obj/item/mod/control/proc/set_wearer(mob/living/carbon/human/user)
if(wearer == user) if(wearer == user)
@@ -492,21 +492,6 @@
covered_slots |= part.slot_flags covered_slots |= part.slot_flags
return covered_slots return covered_slots
/obj/item/mod/control/proc/generate_suit_mask()
var/list/parts = get_parts(all = TRUE)
var/covered_slots = get_sealed_slots(parts)
if(GLOB.mod_masks[skin])
if(GLOB.mod_masks[skin]["[covered_slots]"])
return GLOB.mod_masks[skin]["[covered_slots]"]
else
GLOB.mod_masks[skin] = list()
var/icon/slot_mask = icon('icons/blanks/32x32.dmi', "nothing")
for(var/obj/item/part as anything in parts)
slot_mask.Blend(icon(part.worn_icon, part.icon_state), ICON_OVERLAY)
slot_mask.Blend("#fff", ICON_ADD)
GLOB.mod_masks[skin]["[covered_slots]"] = slot_mask
return GLOB.mod_masks[skin]["[covered_slots]"]
/obj/item/mod/control/proc/clean_up() /obj/item/mod/control/proc/clean_up()
if(QDELING(src)) if(QDELING(src))
unset_wearer() unset_wearer()
@@ -613,7 +598,6 @@
modules += new_module modules += new_module
complexity += new_module.complexity complexity += new_module.complexity
new_module.mod = src new_module.mod = src
new_module.RegisterSignal(src, COMSIG_ITEM_GET_WORN_OVERLAYS, TYPE_PROC_REF(/obj/item/mod/module, add_module_overlay))
new_module.on_install() new_module.on_install()
if(wearer) if(wearer)
new_module.on_equip() new_module.on_equip()
@@ -633,7 +617,6 @@
old_module.on_part_deactivation(deleting = deleting) old_module.on_part_deactivation(deleting = deleting)
if(old_module.active) if(old_module.active)
old_module.deactivate(display_message = !deleting, deleting = deleting) old_module.deactivate(display_message = !deleting, deleting = deleting)
old_module.UnregisterSignal(src, COMSIG_ITEM_GET_WORN_OVERLAYS)
old_module.on_uninstall(deleting = deleting) old_module.on_uninstall(deleting = deleting)
QDEL_LIST_ASSOC_VAL(old_module.pinned_to) QDEL_LIST_ASSOC_VAL(old_module.pinned_to)
old_module.mod = null old_module.mod = null

View File

@@ -18,5 +18,29 @@
var/obj/item/overslotting = null var/obj/item/overslotting = null
/datum/mod_part/Destroy() /datum/mod_part/Destroy()
// To avoid qdel loops in MOD control units, since they're also a part
if (!QDELING(part_item))
qdel(part_item)
part_item = null part_item = null
overslotting = null
return ..() return ..()
/datum/mod_part/proc/set_item(obj/item/new_part)
part_item = new_part
RegisterSignal(part_item, COMSIG_ITEM_GET_SEPARATE_WORN_OVERLAYS, PROC_REF(get_separate_worn_overlays))
// If we're overslotting an item, add its visual as an underlay
/datum/mod_part/proc/get_separate_worn_overlays(obj/item/source, list/overlays, mutable_appearance/standing, mutable_appearance/draw_target, isinhands, icon_file)
SIGNAL_HANDLER
if (!overslotting || sealed)
return
var/checked_slot = source.slot_flags
if (ismob(source.loc))
var/mob/as_mob = source.loc
checked_slot = as_mob.get_slot_by_item(source)
var/mutable_appearance/worn_overlay = overslotting.build_worn_icon(default_layer = -draw_target.layer + 0.1, default_icon_file = get_default_icon_by_slot(checked_slot))
for (var/mutable_appearance/overlay in worn_overlay.overlays)
overlay.layer = draw_target.layer + 0.1
overlays += worn_overlay

View File

@@ -108,7 +108,7 @@
mod.ui_theme = ui_theme mod.ui_theme = ui_theme
mod.charge_drain = charge_drain mod.charge_drain = charge_drain
var/datum/mod_part/control_part_datum = new() var/datum/mod_part/control_part_datum = new()
control_part_datum.part_item = mod control_part_datum.set_item(mod)
mod.mod_parts["[mod.slot_flags]"] = control_part_datum mod.mod_parts["[mod.slot_flags]"] = control_part_datum
for(var/path in variants[default_skin]) for(var/path in variants[default_skin])
if(!ispath(path)) if(!ispath(path))
@@ -118,7 +118,7 @@
var/obj/item/clothing/chestplate = mod_part var/obj/item/clothing/chestplate = mod_part
chestplate.allowed |= allowed_suit_storage chestplate.allowed |= allowed_suit_storage
var/datum/mod_part/part_datum = new() var/datum/mod_part/part_datum = new()
part_datum.part_item = mod_part part_datum.set_item(mod_part)
mod.mod_parts["[mod_part.slot_flags]"] = part_datum mod.mod_parts["[mod_part.slot_flags]"] = part_datum
parts += mod_part parts += mod_part

View File

@@ -180,9 +180,9 @@
update_signal(used_button) update_signal(used_button)
balloon_alert(mod.wearer, "[src] activated, [used_button]-click to use") balloon_alert(mod.wearer, "[src] activated, [used_button]-click to use")
active = TRUE active = TRUE
mod.wearer.update_clothing(mod.slot_flags)
SEND_SIGNAL(src, COMSIG_MODULE_ACTIVATED) SEND_SIGNAL(src, COMSIG_MODULE_ACTIVATED)
on_activation() on_activation()
update_clothing_slots()
return TRUE return TRUE
/// Called when the module is deactivated /// Called when the module is deactivated
@@ -199,11 +199,22 @@
else else
UnregisterSignal(mod.wearer, used_signal) UnregisterSignal(mod.wearer, used_signal)
used_signal = null used_signal = null
mod.wearer.update_clothing(mod.slot_flags)
SEND_SIGNAL(src, COMSIG_MODULE_DEACTIVATED, mod.wearer) SEND_SIGNAL(src, COMSIG_MODULE_DEACTIVATED, mod.wearer)
on_deactivation(display_message = TRUE, deleting = FALSE) on_deactivation(display_message = TRUE, deleting = FALSE)
update_clothing_slots()
return TRUE return TRUE
/// Call to update all slots visually affected by this module
/obj/item/mod/module/proc/update_clothing_slots()
var/updated_slots = mod.slot_flags
if (mask_worn_overlay)
for (var/obj/item/part as anything in mod.get_parts())
updated_slots |= part.slot_flags
else if (length(required_slots))
for (var/slot in required_slots)
updated_slots |= slot
mod.wearer.update_clothing(updated_slots)
/// Called when the module is used /// Called when the module is used
/obj/item/mod/module/proc/used() /obj/item/mod/module/proc/used()
if(!COOLDOWN_FINISHED(src, cooldown_timer)) if(!COOLDOWN_FINISHED(src, cooldown_timer))
@@ -220,7 +231,7 @@
return FALSE return FALSE
start_cooldown() start_cooldown()
addtimer(CALLBACK(mod.wearer, TYPE_PROC_REF(/mob, update_clothing), mod.slot_flags), cooldown_time+1) //need to run it a bit after the cooldown starts to avoid conflicts addtimer(CALLBACK(mod.wearer, TYPE_PROC_REF(/mob, update_clothing), mod.slot_flags), cooldown_time+1) //need to run it a bit after the cooldown starts to avoid conflicts
mod.wearer.update_clothing(mod.slot_flags) update_clothing_slots()
SEND_SIGNAL(src, COMSIG_MODULE_USED) SEND_SIGNAL(src, COMSIG_MODULE_USED)
on_use() on_use()
return TRUE return TRUE
@@ -271,11 +282,38 @@
/// Called from MODsuit's install() proc, so when the module is installed /// Called from MODsuit's install() proc, so when the module is installed
/obj/item/mod/module/proc/on_install() /obj/item/mod/module/proc/on_install()
return SHOULD_CALL_PARENT(TRUE)
if (mask_worn_overlay)
for (var/obj/item/part as anything in mod.get_parts(all = TRUE))
RegisterSignal(part, COMSIG_ITEM_GET_SEPARATE_WORN_OVERLAYS, PROC_REF(add_module_overlay))
return
if (!length(required_slots))
RegisterSignal(mod, COMSIG_ITEM_GET_SEPARATE_WORN_OVERLAYS, PROC_REF(add_module_overlay))
return
var/obj/item/part = mod.get_part_from_slot(required_slots[1])
RegisterSignal(part, COMSIG_ITEM_GET_SEPARATE_WORN_OVERLAYS, PROC_REF(add_module_overlay))
/// Called from MODsuit's uninstall() proc, so when the module is uninstalled /// Called from MODsuit's uninstall() proc, so when the module is uninstalled
/obj/item/mod/module/proc/on_uninstall(deleting = FALSE) /obj/item/mod/module/proc/on_uninstall(deleting = FALSE)
return SHOULD_CALL_PARENT(TRUE)
if (deleting)
return
if (mask_worn_overlay)
for (var/obj/item/part as anything in mod.get_parts(all = TRUE))
UnregisterSignal(part, COMSIG_ITEM_GET_SEPARATE_WORN_OVERLAYS)
return
if (!length(required_slots))
UnregisterSignal(mod, COMSIG_ITEM_GET_SEPARATE_WORN_OVERLAYS)
return
var/obj/item/part = mod.get_part_from_slot(required_slots[1])
UnregisterSignal(part, COMSIG_ITEM_GET_SEPARATE_WORN_OVERLAYS)
/// Called when the MODsuit is activated /// Called when the MODsuit is activated
/obj/item/mod/module/proc/on_part_activation() /obj/item/mod/module/proc/on_part_activation()
@@ -343,27 +381,45 @@
qdel(src) qdel(src)
/// Adds the worn overlays to the suit. /// Adds the worn overlays to the suit.
/obj/item/mod/module/proc/add_module_overlay(obj/item/source, list/overlays, mutable_appearance/standing, isinhands, icon_file) /obj/item/mod/module/proc/add_module_overlay(obj/item/source, list/overlays, mutable_appearance/standing, mutable_appearance/draw_target, isinhands, icon_file)
SIGNAL_HANDLER SIGNAL_HANDLER
overlays += generate_worn_overlay(standing) if (isinhands)
return
var/list/added_overlays = generate_worn_overlay(source, standing)
if (!added_overlays)
return
if (!mask_worn_overlay)
overlays += added_overlays
return
for (var/mutable_appearance/overlay as anything in added_overlays)
overlay.add_filter("mod_mask_overlay", 1, alpha_mask_filter(icon = icon(draw_target.icon, draw_target.icon_state)))
overlays += overlay
/// Generates an icon to be used for the suit's worn overlays /// Generates an icon to be used for the suit's worn overlays
/obj/item/mod/module/proc/generate_worn_overlay(mutable_appearance/standing) /obj/item/mod/module/proc/generate_worn_overlay(obj/item/source, mutable_appearance/standing)
if(!mask_worn_overlay)
if(!has_required_parts(mod.mod_parts, need_active = TRUE))
return
else
var/datum/mod_part/part_datum = mod.get_part_datum(source)
if (!part_datum?.sealed)
return
. = list() . = list()
if(!mod.active || !has_required_parts(mod.mod_parts, need_active = TRUE))
return
var/used_overlay = get_current_overlay_state() var/used_overlay = get_current_overlay_state()
if (!used_overlay) if (!used_overlay)
return return
/* BUBBER EDIT START - Making MODsuits mutant-compatible - ORIGINAL: /* BUBBER EDIT START - Making MODsuits mutant-compatible - ORIGINAL:
var/mutable_appearance/module_icon var/mutable_appearance/module_icon = mutable_appearance(overlay_icon_file, used_overlay, layer = standing.layer + 0.1)
if(mask_worn_overlay) if(use_mod_colors)
module_icon = mutable_appearance(get_module_icon_cache(used_overlay), layer = standing.layer + 0.1) module_icon.color = mod.color
else if (mod.cached_color_filter)
module_icon = mutable_appearance(overlay_icon_file, used_overlay, layer = standing.layer + 0.1) module_icon = filter_appearance_recursive(module_icon, mod.cached_color_filter)
if(!use_mod_colors)
module_icon.appearance_flags |= RESET_COLOR
. += module_icon . += module_icon
*/ */
@@ -380,22 +436,6 @@
return overlay_state_inactive return overlay_state_inactive
return null return null
/obj/item/mod/module/proc/get_module_icon_cache(used_overlay)
var/covered_slots = mod.get_sealed_slots(mod.get_parts(all = TRUE))
if (GLOB.mod_module_overlays[mod.skin])
if (GLOB.mod_module_overlays[mod.skin]["[covered_slots]"])
if (GLOB.mod_module_overlays[mod.skin]["[covered_slots]"][used_overlay])
return GLOB.mod_module_overlays[mod.skin]["[covered_slots]"][used_overlay]
else
GLOB.mod_module_overlays[mod.skin]["[covered_slots]"] = list()
else
GLOB.mod_module_overlays[mod.skin] = list()
GLOB.mod_module_overlays[mod.skin]["[covered_slots]"] = list()
var/icon/mod_mask = icon(mod.generate_suit_mask())
mod_mask.Blend(icon(overlay_icon_file, used_overlay), ICON_MULTIPLY)
GLOB.mod_module_overlays[mod.skin]["[covered_slots]"][used_overlay] = mod_mask
return GLOB.mod_module_overlays[mod.skin]["[covered_slots]"][used_overlay]
/// Updates the signal used by active modules to be activated /// Updates the signal used by active modules to be activated
/obj/item/mod/module/proc/update_signal(value) /obj/item/mod/module/proc/update_signal(value)
switch(value) switch(value)

View File

@@ -90,7 +90,7 @@
if (!active) if (!active)
module_slowdowns += space_slowdown module_slowdowns += space_slowdown
/obj/item/mod/module/armor_booster/generate_worn_overlay(mutable_appearance/standing) /obj/item/mod/module/armor_booster/generate_worn_overlay(obj/item/source, mutable_appearance/standing)
overlay_state_inactive = "[initial(overlay_state_inactive)]-[mod.skin]" overlay_state_inactive = "[initial(overlay_state_inactive)]-[mod.skin]"
overlay_state_active = "[initial(overlay_state_active)]-[mod.skin]" overlay_state_active = "[initial(overlay_state_active)]-[mod.skin]"
return ..() return ..()
@@ -105,9 +105,11 @@
REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, REF(src)) REMOVE_TRAIT(mod.wearer, TRAIT_HEAD_INJURY_BLOCKED, REF(src))
/obj/item/mod/module/armor_booster/on_install() /obj/item/mod/module/armor_booster/on_install()
. = ..()
RegisterSignal(mod, COMSIG_MOD_GET_VISOR_OVERLAY, PROC_REF(on_visor_overlay)) RegisterSignal(mod, COMSIG_MOD_GET_VISOR_OVERLAY, PROC_REF(on_visor_overlay))
/obj/item/mod/module/armor_booster/on_uninstall(deleting) /obj/item/mod/module/armor_booster/on_uninstall(deleting = FALSE)
. = ..()
UnregisterSignal(mod, COMSIG_MOD_GET_VISOR_OVERLAY) UnregisterSignal(mod, COMSIG_MOD_GET_VISOR_OVERLAY)
/obj/item/mod/module/armor_booster/proc/on_visor_overlay(datum/source, mutable_appearance/standing, list/overrides) /obj/item/mod/module/armor_booster/proc/on_visor_overlay(datum/source, mutable_appearance/standing, list/overrides)
@@ -241,7 +243,7 @@
overlay_state_inactive = "module_insignia" overlay_state_inactive = "module_insignia"
mask_worn_overlay = TRUE mask_worn_overlay = TRUE
/obj/item/mod/module/insignia/generate_worn_overlay(mutable_appearance/standing) /obj/item/mod/module/insignia/generate_worn_overlay(obj/item/source, mutable_appearance/standing)
overlay_state_inactive = "[initial(overlay_state_inactive)]-[mod.skin]" overlay_state_inactive = "[initial(overlay_state_inactive)]-[mod.skin]"
. = ..() . = ..()
for(var/mutable_appearance/appearance as anything in .) for(var/mutable_appearance/appearance as anything in .)
@@ -409,6 +411,7 @@
var/obj/item/current_disguise var/obj/item/current_disguise
/obj/item/mod/module/chameleon/on_install() /obj/item/mod/module/chameleon/on_install()
. = ..()
var/list/all_disguises = sort_list(subtypesof(get_path_by_slot(mod.slot_flags)), GLOBAL_PROC_REF(cmp_typepaths_asc)) var/list/all_disguises = sort_list(subtypesof(get_path_by_slot(mod.slot_flags)), GLOBAL_PROC_REF(cmp_typepaths_asc))
for(var/clothing_path in all_disguises) for(var/clothing_path in all_disguises)
var/obj/item/clothing = clothing_path var/obj/item/clothing = clothing_path
@@ -418,6 +421,7 @@
possible_disguises[chameleon_item_name] = clothing_path possible_disguises[chameleon_item_name] = clothing_path
/obj/item/mod/module/chameleon/on_uninstall(deleting = FALSE) /obj/item/mod/module/chameleon/on_uninstall(deleting = FALSE)
. = ..()
if(current_disguise) if(current_disguise)
return_look() return_look()
possible_disguises = null possible_disguises = null
@@ -449,7 +453,7 @@
mod.righthand_file = initial(current_disguise.righthand_file) mod.righthand_file = initial(current_disguise.righthand_file)
mod.worn_icon_state = initial(current_disguise.worn_icon_state) mod.worn_icon_state = initial(current_disguise.worn_icon_state)
mod.inhand_icon_state = initial(current_disguise.inhand_icon_state) mod.inhand_icon_state = initial(current_disguise.inhand_icon_state)
mod.wearer.update_clothing(mod.slot_flags) update_clothing_slots()
RegisterSignal(mod, COMSIG_MOD_ACTIVATE, PROC_REF(return_look)) RegisterSignal(mod, COMSIG_MOD_ACTIVATE, PROC_REF(return_look))
/obj/item/mod/module/chameleon/proc/return_look() /obj/item/mod/module/chameleon/proc/return_look()
@@ -463,7 +467,7 @@
mod.righthand_file = initial(mod.righthand_file) mod.righthand_file = initial(mod.righthand_file)
mod.worn_icon_state = null mod.worn_icon_state = null
mod.inhand_icon_state = null mod.inhand_icon_state = null
mod.wearer.update_clothing(mod.slot_flags) update_clothing_slots()
current_disguise = null current_disguise = null
UnregisterSignal(mod, COMSIG_MOD_ACTIVATE) UnregisterSignal(mod, COMSIG_MOD_ACTIVATE)
@@ -481,10 +485,12 @@
var/old_size var/old_size
/obj/item/mod/module/plate_compression/on_install() /obj/item/mod/module/plate_compression/on_install()
. = ..()
old_size = mod.w_class old_size = mod.w_class
mod.update_weight_class(new_size) mod.update_weight_class(new_size)
/obj/item/mod/module/plate_compression/on_uninstall(deleting = FALSE) /obj/item/mod/module/plate_compression/on_uninstall(deleting = FALSE)
. = ..()
mod.update_weight_class(old_size) mod.update_weight_class(old_size)
old_size = null old_size = null
if(!mod.loc) if(!mod.loc)
@@ -528,9 +534,11 @@
var/list/traits_to_add = list(TRAIT_SILENT_FOOTSTEPS, TRAIT_UNKNOWN, TRAIT_HEAD_INJURY_BLOCKED) var/list/traits_to_add = list(TRAIT_SILENT_FOOTSTEPS, TRAIT_UNKNOWN, TRAIT_HEAD_INJURY_BLOCKED)
/obj/item/mod/module/infiltrator/on_install() /obj/item/mod/module/infiltrator/on_install()
. = ..()
ADD_TRAIT(mod, TRAIT_EXAMINE_SKIP, REF(src)) ADD_TRAIT(mod, TRAIT_EXAMINE_SKIP, REF(src))
/obj/item/mod/module/infiltrator/on_uninstall(deleting = FALSE) /obj/item/mod/module/infiltrator/on_uninstall(deleting = FALSE)
. = ..()
REMOVE_TRAIT(mod, TRAIT_EXAMINE_SKIP, REF(src)) REMOVE_TRAIT(mod, TRAIT_EXAMINE_SKIP, REF(src))
/obj/item/mod/module/infiltrator/on_part_activation() /obj/item/mod/module/infiltrator/on_part_activation()

View File

@@ -62,9 +62,11 @@
var/list/active_traits = list(TRAIT_NO_SLIP_WATER, TRAIT_NO_SLIP_ICE, TRAIT_NO_SLIP_SLIDE, TRAIT_NEGATES_GRAVITY) var/list/active_traits = list(TRAIT_NO_SLIP_WATER, TRAIT_NO_SLIP_ICE, TRAIT_NO_SLIP_SLIDE, TRAIT_NEGATES_GRAVITY)
/obj/item/mod/module/magboot/on_install() /obj/item/mod/module/magboot/on_install()
. = ..()
RegisterSignal(mod, COMSIG_MOD_UPDATE_SPEED, PROC_REF(on_update_speed)) RegisterSignal(mod, COMSIG_MOD_UPDATE_SPEED, PROC_REF(on_update_speed))
/obj/item/mod/module/magboot/on_uninstall(deleting) /obj/item/mod/module/magboot/on_uninstall(deleting = FALSE)
. = ..()
UnregisterSignal(mod, COMSIG_MOD_UPDATE_SPEED) UnregisterSignal(mod, COMSIG_MOD_UPDATE_SPEED)
/obj/item/mod/module/magboot/on_activation() /obj/item/mod/module/magboot/on_activation()

View File

@@ -25,6 +25,7 @@
atom_storage.set_locked(STORAGE_FULLY_LOCKED) atom_storage.set_locked(STORAGE_FULLY_LOCKED)
/obj/item/mod/module/storage/on_install() /obj/item/mod/module/storage/on_install()
. = ..()
var/datum/storage/modstorage = mod.create_storage(max_specific_storage = max_w_class, max_total_storage = max_combined_w_class, max_slots = max_items) var/datum/storage/modstorage = mod.create_storage(max_specific_storage = max_w_class, max_total_storage = max_combined_w_class, max_slots = max_items)
modstorage.set_real_location(src) modstorage.set_real_location(src)
modstorage.allow_big_nesting = big_nesting modstorage.allow_big_nesting = big_nesting
@@ -34,6 +35,7 @@
RegisterSignal(suit, COMSIG_ITEM_PRE_UNEQUIP, PROC_REF(on_suit_unequip)) RegisterSignal(suit, COMSIG_ITEM_PRE_UNEQUIP, PROC_REF(on_suit_unequip))
/obj/item/mod/module/storage/on_uninstall(deleting = FALSE) /obj/item/mod/module/storage/on_uninstall(deleting = FALSE)
. = ..()
atom_storage.set_locked(STORAGE_FULLY_LOCKED) atom_storage.set_locked(STORAGE_FULLY_LOCKED)
QDEL_NULL(mod.atom_storage) QDEL_NULL(mod.atom_storage)
if(!deleting) if(!deleting)
@@ -328,6 +330,7 @@
var/former_visor_mask_flags = NONE var/former_visor_mask_flags = NONE
/obj/item/mod/module/mouthhole/on_install() /obj/item/mod/module/mouthhole/on_install()
. = ..()
var/obj/item/clothing/helmet = mod.get_part_from_slot(ITEM_SLOT_HEAD) var/obj/item/clothing/helmet = mod.get_part_from_slot(ITEM_SLOT_HEAD)
if(istype(helmet)) if(istype(helmet))
former_helmet_flags = helmet.flags_cover former_helmet_flags = helmet.flags_cover
@@ -351,6 +354,7 @@
return FALSE return FALSE
/obj/item/mod/module/mouthhole/on_uninstall(deleting = FALSE) /obj/item/mod/module/mouthhole/on_uninstall(deleting = FALSE)
. = ..()
if(deleting) if(deleting)
return return
var/obj/item/clothing/helmet = mod.get_part_from_slot(ITEM_SLOT_HEAD) var/obj/item/clothing/helmet = mod.get_part_from_slot(ITEM_SLOT_HEAD)
@@ -375,9 +379,11 @@
required_slots = list(ITEM_SLOT_BACK|ITEM_SLOT_BELT) required_slots = list(ITEM_SLOT_BACK|ITEM_SLOT_BELT)
/obj/item/mod/module/emp_shield/on_install() /obj/item/mod/module/emp_shield/on_install()
. = ..()
mod.AddElement(/datum/element/empprotection, EMP_PROTECT_ALL) mod.AddElement(/datum/element/empprotection, EMP_PROTECT_ALL)
/obj/item/mod/module/emp_shield/on_uninstall(deleting = FALSE) /obj/item/mod/module/emp_shield/on_uninstall(deleting = FALSE)
. = ..()
mod.RemoveElement(/datum/element/empprotection, EMP_PROTECT_ALL) mod.RemoveElement(/datum/element/empprotection, EMP_PROTECT_ALL)
/obj/item/mod/module/emp_shield/advanced /obj/item/mod/module/emp_shield/advanced
@@ -437,7 +443,7 @@
active_power_cost = base_power * light_range active_power_cost = base_power * light_range
return ..() return ..()
/obj/item/mod/module/flashlight/generate_worn_overlay(mutable_appearance/standing) /obj/item/mod/module/flashlight/generate_worn_overlay(obj/item/source, mutable_appearance/standing)
. = ..() . = ..()
if(!active) if(!active)
return return
@@ -460,7 +466,7 @@
balloon_alert(mod.wearer, "too dark!") balloon_alert(mod.wearer, "too dark!")
return return
set_light_color(value) set_light_color(value)
mod.wearer.update_clothing(mod.slot_flags) update_clothing_slots()
if("light_range") if("light_range")
set_light_range(clamp(value, min_range, max_range)) set_light_range(clamp(value, min_range, max_range))
@@ -594,12 +600,14 @@
var/dna = null var/dna = null
/obj/item/mod/module/dna_lock/on_install() /obj/item/mod/module/dna_lock/on_install()
. = ..()
RegisterSignal(mod, COMSIG_MOD_ACTIVATE, PROC_REF(on_mod_activation)) RegisterSignal(mod, COMSIG_MOD_ACTIVATE, PROC_REF(on_mod_activation))
RegisterSignal(mod, COMSIG_MOD_MODULE_REMOVAL, PROC_REF(on_mod_removal)) RegisterSignal(mod, COMSIG_MOD_MODULE_REMOVAL, PROC_REF(on_mod_removal))
RegisterSignal(mod, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp)) RegisterSignal(mod, COMSIG_ATOM_EMP_ACT, PROC_REF(on_emp))
RegisterSignal(mod, COMSIG_ATOM_EMAG_ACT, PROC_REF(on_emag)) RegisterSignal(mod, COMSIG_ATOM_EMAG_ACT, PROC_REF(on_emag))
/obj/item/mod/module/dna_lock/on_uninstall(deleting = FALSE) /obj/item/mod/module/dna_lock/on_uninstall(deleting = FALSE)
. = ..()
UnregisterSignal(mod, COMSIG_MOD_ACTIVATE) UnregisterSignal(mod, COMSIG_MOD_ACTIVATE)
UnregisterSignal(mod, COMSIG_MOD_MODULE_REMOVAL) UnregisterSignal(mod, COMSIG_MOD_MODULE_REMOVAL)
UnregisterSignal(mod, COMSIG_ATOM_EMP_ACT) UnregisterSignal(mod, COMSIG_ATOM_EMP_ACT)
@@ -665,11 +673,15 @@
incompatible_modules = list(/obj/item/mod/module/plasma_stabilizer) incompatible_modules = list(/obj/item/mod/module/plasma_stabilizer)
required_slots = list(ITEM_SLOT_HEAD) required_slots = list(ITEM_SLOT_HEAD)
/obj/item/mod/module/plasma_stabilizer/generate_worn_overlay(mutable_appearance/standing) /obj/item/mod/module/plasma_stabilizer/generate_worn_overlay(obj/item/source, mutable_appearance/standing)
. = ..()
if (!.)
return
var/mutable_appearance/visor_overlay = mod.get_visor_overlay(standing) var/mutable_appearance/visor_overlay = mod.get_visor_overlay(standing)
visor_overlay.appearance_flags |= RESET_COLOR visor_overlay.appearance_flags |= RESET_COLOR
visor_overlay.color = COLOR_VIOLET visor_overlay.color = COLOR_VIOLET
return list(visor_overlay) . += visor_overlay
/obj/item/mod/module/plasma_stabilizer/on_equip() /obj/item/mod/module/plasma_stabilizer/on_equip()
ADD_TRAIT(mod.wearer, TRAIT_HEAD_ATMOS_SEALED, REF(src)) ADD_TRAIT(mod.wearer, TRAIT_HEAD_ATMOS_SEALED, REF(src))

View File

@@ -17,9 +17,11 @@
var/step_change = 0.5 var/step_change = 0.5
/obj/item/mod/module/springlock/on_install() /obj/item/mod/module/springlock/on_install()
. = ..()
mod.activation_step_time *= step_change mod.activation_step_time *= step_change
/obj/item/mod/module/springlock/on_uninstall(deleting = FALSE) /obj/item/mod/module/springlock/on_uninstall(deleting = FALSE)
. = ..()
mod.activation_step_time /= step_change mod.activation_step_time /= step_change
/obj/item/mod/module/springlock/on_part_activation() /obj/item/mod/module/springlock/on_part_activation()
@@ -149,18 +151,22 @@
return return
SEND_SOUND(mod.wearer, sound('sound/machines/terminal/terminal_off.ogg', volume = 50, channel = CHANNEL_JUKEBOX)) SEND_SOUND(mod.wearer, sound('sound/machines/terminal/terminal_off.ogg', volume = 50, channel = CHANNEL_JUKEBOX))
/obj/item/mod/module/visor/rave/generate_worn_overlay(mutable_appearance/standing) /obj/item/mod/module/visor/rave/generate_worn_overlay(obj/item/source, mutable_appearance/standing)
. = ..()
if (!.)
return
var/mutable_appearance/visor_overlay = mod.get_visor_overlay(standing) var/mutable_appearance/visor_overlay = mod.get_visor_overlay(standing)
visor_overlay.appearance_flags |= RESET_COLOR visor_overlay.appearance_flags |= RESET_COLOR
if (!isnull(music_player.active_song_sound)) if (!isnull(music_player.active_song_sound))
visor_overlay.color = rainbow_order[rave_number] visor_overlay.color = rainbow_order[rave_number]
return list(visor_overlay) . += visor_overlay
/obj/item/mod/module/visor/rave/on_active_process(seconds_per_tick) /obj/item/mod/module/visor/rave/on_active_process(seconds_per_tick)
rave_number++ rave_number++
if(rave_number > length(rainbow_order)) if(rave_number > length(rainbow_order))
rave_number = 1 rave_number = 1
mod.wearer.update_clothing(mod.slot_flags) update_clothing_slots()
rave_screen.update_color(rainbow_order[rave_number]) rave_screen.update_color(rainbow_order[rave_number])
/obj/item/mod/module/visor/rave/get_configuration() /obj/item/mod/module/visor/rave/get_configuration()

View File

@@ -93,11 +93,9 @@
required_slots = list(ITEM_SLOT_HEAD|ITEM_SLOT_EYES|ITEM_SLOT_MASK) required_slots = list(ITEM_SLOT_HEAD|ITEM_SLOT_EYES|ITEM_SLOT_MASK)
/obj/item/mod/module/welding/camera_vision/on_part_activation() /obj/item/mod/module/welding/camera_vision/on_part_activation()
. = ..()
RegisterSignal(mod.wearer, COMSIG_LIVING_CAN_TRACK, PROC_REF(can_track)) RegisterSignal(mod.wearer, COMSIG_LIVING_CAN_TRACK, PROC_REF(can_track))
/obj/item/mod/module/welding/camera_vision/on_part_deactivation(deleting = FALSE) /obj/item/mod/module/welding/camera_vision/on_part_deactivation(deleting = FALSE)
. = ..()
UnregisterSignal(mod.wearer, COMSIG_LIVING_CAN_TRACK) UnregisterSignal(mod.wearer, COMSIG_LIVING_CAN_TRACK)
/obj/item/mod/module/welding/camera_vision/proc/can_track(datum/source, mob/user) /obj/item/mod/module/welding/camera_vision/proc/can_track(datum/source, mob/user)
@@ -422,9 +420,11 @@
addtimer(CALLBACK(src, PROC_REF(boost_aftereffects), mod.wearer), 7 SECONDS) addtimer(CALLBACK(src, PROC_REF(boost_aftereffects), mod.wearer), 7 SECONDS)
/obj/item/mod/module/adrenaline_boost/on_install() /obj/item/mod/module/adrenaline_boost/on_install()
. = ..()
RegisterSignal(mod, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(try_boost)) RegisterSignal(mod, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(try_boost))
/obj/item/mod/module/adrenaline_boost/on_uninstall(deleting = FALSE) /obj/item/mod/module/adrenaline_boost/on_uninstall(deleting = FALSE)
. = ..()
UnregisterSignal(mod, COMSIG_ATOM_ITEM_INTERACTION) UnregisterSignal(mod, COMSIG_ATOM_ITEM_INTERACTION)
/obj/item/mod/module/adrenaline_boost/proc/try_boost(source, mob/user, obj/item/attacking_item) /obj/item/mod/module/adrenaline_boost/proc/try_boost(source, mob/user, obj/item/attacking_item)

View File

@@ -22,6 +22,7 @@
guns_typecache = typecacheof(list(/obj/item/gun/ballistic, /obj/item/gun/energy, /obj/item/gun/grenadelauncher, /obj/item/gun/chem, /obj/item/gun/syringe, /obj/item/gun/microfusion)) //SKYRAT EDIT - MICROFUSION guns_typecache = typecacheof(list(/obj/item/gun/ballistic, /obj/item/gun/energy, /obj/item/gun/grenadelauncher, /obj/item/gun/chem, /obj/item/gun/syringe, /obj/item/gun/microfusion)) //SKYRAT EDIT - MICROFUSION
/obj/item/mod/module/magnetic_harness/on_install() /obj/item/mod/module/magnetic_harness/on_install()
. = ..()
var/obj/item/clothing/suit = mod.get_part_from_slot(ITEM_SLOT_OCLOTHING) var/obj/item/clothing/suit = mod.get_part_from_slot(ITEM_SLOT_OCLOTHING)
if(!istype(suit)) if(!istype(suit))
return return
@@ -29,6 +30,7 @@
suit.allowed |= guns_typecache suit.allowed |= guns_typecache
/obj/item/mod/module/magnetic_harness/on_uninstall(deleting = FALSE) /obj/item/mod/module/magnetic_harness/on_uninstall(deleting = FALSE)
. = ..()
if(deleting) if(deleting)
return return
var/obj/item/clothing/suit = mod.get_part_from_slot(ITEM_SLOT_OCLOTHING) var/obj/item/clothing/suit = mod.get_part_from_slot(ITEM_SLOT_OCLOTHING)
@@ -135,6 +137,7 @@
balloon_alert(mod.wearer, "holster full!") balloon_alert(mod.wearer, "holster full!")
/obj/item/mod/module/holster/on_uninstall(deleting = FALSE) /obj/item/mod/module/holster/on_uninstall(deleting = FALSE)
. = ..()
if(holstered) if(holstered)
holstered.forceMove(drop_location()) holstered.forceMove(drop_location())

View File

@@ -422,7 +422,7 @@
mod.update_speed() mod.update_speed()
traveled_tiles = 0 traveled_tiles = 0
/obj/item/mod/module/ash_accretion/generate_worn_overlay(mutable_appearance/standing) /obj/item/mod/module/ash_accretion/generate_worn_overlay(obj/item/source, mutable_appearance/standing)
overlay_state_inactive = "[initial(overlay_state_inactive)]-[mod.skin]" overlay_state_inactive = "[initial(overlay_state_inactive)]-[mod.skin]"
return ..() return ..()

View File

@@ -20,10 +20,12 @@
var/true_owner_ckey var/true_owner_ckey
/obj/item/mod/module/eradication_lock/on_install() /obj/item/mod/module/eradication_lock/on_install()
. = ..()
RegisterSignal(mod, COMSIG_MOD_ACTIVATE, PROC_REF(on_mod_activation)) RegisterSignal(mod, COMSIG_MOD_ACTIVATE, PROC_REF(on_mod_activation))
RegisterSignal(mod, COMSIG_MOD_MODULE_REMOVAL, PROC_REF(on_mod_removal)) RegisterSignal(mod, COMSIG_MOD_MODULE_REMOVAL, PROC_REF(on_mod_removal))
/obj/item/mod/module/eradication_lock/on_uninstall(deleting = FALSE) /obj/item/mod/module/eradication_lock/on_uninstall(deleting = FALSE)
. = ..()
UnregisterSignal(mod, COMSIG_MOD_ACTIVATE) UnregisterSignal(mod, COMSIG_MOD_ACTIVATE)
UnregisterSignal(mod, COMSIG_MOD_MODULE_REMOVAL) UnregisterSignal(mod, COMSIG_MOD_MODULE_REMOVAL)
@@ -228,6 +230,7 @@
INVOKE_ASYNC(chrono_beam, TYPE_PROC_REF(/obj/projectile, fire)) INVOKE_ASYNC(chrono_beam, TYPE_PROC_REF(/obj/projectile, fire))
/obj/item/mod/module/tem/on_uninstall(deleting = FALSE) /obj/item/mod/module/tem/on_uninstall(deleting = FALSE)
. = ..()
if(!field) if(!field)
return return
field_disconnect(field) field_disconnect(field)

View File

@@ -41,11 +41,13 @@
QDEL_LIST_ASSOC_VAL(action_comp.granted_to) QDEL_LIST_ASSOC_VAL(action_comp.granted_to)
/obj/item/mod/module/circuit/on_install() /obj/item/mod/module/circuit/on_install()
. = ..()
if(!shell?.attached_circuit) if(!shell?.attached_circuit)
return return
RegisterSignal(shell?.attached_circuit, COMSIG_CIRCUIT_PRE_POWER_USAGE, PROC_REF(override_power_usage)) RegisterSignal(shell?.attached_circuit, COMSIG_CIRCUIT_PRE_POWER_USAGE, PROC_REF(override_power_usage))
/obj/item/mod/module/circuit/on_uninstall(deleting = FALSE) /obj/item/mod/module/circuit/on_uninstall(deleting = FALSE)
. = ..()
if(!shell?.attached_circuit) if(!shell?.attached_circuit)
return return
for(var/obj/item/circuit_component/equipment_action/action_comp in action_comps) for(var/obj/item/circuit_component/equipment_action/action_comp in action_comps)