diff --git a/.github/workflows/docker_publish.yml b/.github/workflows/docker_publish.yml index c6ae68fdfd9..48ef92c17f1 100644 --- a/.github/workflows/docker_publish.yml +++ b/.github/workflows/docker_publish.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v3 - name: Build and Publish Docker Image to Registry - uses: elgohr/Publish-Docker-Github-Action@master + uses: elgohr/Publish-Docker-Github-Action@v5 with: name: tgstation/tgstation username: ${{ secrets.DOCKER_USERNAME }} diff --git a/code/_globalvars/phobias.dm b/code/_globalvars/phobias.dm index d440f6ebb28..20ad6c1b70b 100644 --- a/code/_globalvars/phobias.dm +++ b/code/_globalvars/phobias.dm @@ -341,7 +341,6 @@ GLOBAL_LIST_INIT(phobia_objs, list( /obj/effect/heretic_rune, /obj/effect/rune, /obj/effect/visible_heretic_influence, - /obj/item/clothing/head/hooded/cult_hoodie, /obj/item/clothing/head/wizard, /obj/item/clothing/mask/madness_mask, /obj/item/clothing/neck/heretic_focus, diff --git a/code/controllers/subsystem/air.dm b/code/controllers/subsystem/air.dm index 39b9bcf18f9..bc6f802f2d5 100644 --- a/code/controllers/subsystem/air.dm +++ b/code/controllers/subsystem/air.dm @@ -603,10 +603,76 @@ SUBSYSTEM_DEF(air) EG.dismantle() CHECK_TICK + log_active_turfs() // invoke this here so we can count the time it takes to run this proc as "wasted time", quite simple honestly. + var/msg = "HEY! LISTEN! [DisplayTimeText(world.timeofday - timer, 0.00001)] were wasted processing [starting_ats] turf(s) (connected to [ending_ats - starting_ats] other turfs) with atmos differences at round start." to_chat(world, span_boldannounce("[msg]")) warning(msg) +/// Logs all active turfs at roundstart to the mapping log so it can be readily accessed. +/datum/controller/subsystem/air/proc/log_active_turfs() +// sadly this has to be here because we can't realistically expect that all active turfs will be resolved in every possible situation when running through CI. +// In an ideal world, we would have absolutely zero active turfs 99.99% of the time, but that's not the case. `log_mapping()` during world initialize triggers a CI fail. +#ifdef UNIT_TESTS + return +#endif + // Associated lists, left-hand-side is the z-level or z-trait, right-hand-side is the number of active turfs associated with that. + var/list/tally_by_level = list() + // Discriminate for certain z-traits, stuff like "Linkage" is not helpful. + var/list/tally_by_level_trait = list( + ZTRAIT_AWAY = 0, + ZTRAIT_CENTCOM = 0, + ZTRAIT_ICE_RUINS = 0, + ZTRAIT_ICE_RUINS_UNDERGROUND = 0, + ZTRAIT_ISOLATED_RUINS = 0, + ZTRAIT_LAVA_RUINS = 0, + ZTRAIT_MINING = 0, + ZTRAIT_RESERVED = 0, + ZTRAIT_SPACE_RUINS = 0, + ZTRAIT_STATION = 0, + ) + + var/list/message_to_log = list() + + message_to_log += "\nAll that follows is a turf with an active air difference at roundstart. To clear this, make sure that all of the turfs listed below are connected to a turf with the same air contents.\n\ + In an ideal world, this list should have enough information to help you locate the active turf(s) in question. Unfortunately, this might not be an ideal world.\n\ + If the round is still ongoing, you can use the \"Mapping -> Show roundstart AT list\" verb to see exactly what active turfs were detected. Otherwise, good luck." + + for(var/turf/active_turf as anything in GLOB.active_turfs_startlist) + var/turf_z = active_turf.z + var/datum/space_level/level = SSmapping.z_list[turf_z] + var/list/level_traits = list() + for(var/trait in level.traits) + if(!isnull(tally_by_level_trait[trait])) + level_traits += trait + tally_by_level_trait[trait]++ + + // so we can pass along the area type for the log, making it much easier to locate the active turf for a mapper assuming all area types are unique. This is only really a problem for stuff like ruin areas. + var/area/turf_area = get_area(active_turf) + message_to_log += "Active turf: [AREACOORD(active_turf)] ([turf_area.type]). Turf type: [active_turf.type]. Relevant Z-Trait(s): [english_list(level_traits)]." + + tally_by_level["[turf_z]"]++ + + // Following is so we can detect which rounds were "problematic" as far as active turfs go. + SSblackbox.record_feedback("amount", "overall_roundstart_active_turfs", length(GLOB.active_turfs_startlist)) + + for(var/z_level in tally_by_level) + var/level_turf_count = tally_by_level[z_level] + if(level_turf_count == 0) // no point logging it + continue + message_to_log += "Z-Level [z_level] has [level_turf_count] active turf(s)." + SSblackbox.record_feedback("tally", "roundstart_active_turfs_per_z", level_turf_count, z_level) + + for(var/z_trait in tally_by_level_trait) + var/trait_turf_count = tally_by_level_trait[z_trait] + if(trait_turf_count == 0) + continue + message_to_log += "Z-Level trait [z_trait] has [trait_turf_count] active turf(s)." + SSblackbox.record_feedback("amount", "roundstart_active_turfs_for_trait_[z_trait]", trait_turf_count) + + message_to_log += "End of active turf list." + log_mapping(message_to_log.Join("\n")) + /turf/open/proc/resolve_active_graph() . = list() var/datum/excited_group/EG = excited_group diff --git a/code/datums/brain_damage/phobia.dm b/code/datums/brain_damage/phobia.dm index 4746989c9e1..956c0759f9a 100644 --- a/code/datums/brain_damage/phobia.dm +++ b/code/datums/brain_damage/phobia.dm @@ -47,15 +47,14 @@ COOLDOWN_START(src, check_cooldown, 5 SECONDS) var/list/seen_atoms = view(7, owner) if(LAZYLEN(trigger_objs)) - for(var/obj/O in seen_atoms) - if(is_type_in_typecache(O, trigger_objs) || (phobia_type == "blood" && GET_ATOM_BLOOD_DNA_LENGTH(O))) - freak_out(O) + for(var/obj/seen_item in seen_atoms) + if(is_scary_item(seen_item)) + freak_out(seen_item) return - for(var/mob/living/carbon/human/HU in seen_atoms) //check equipment for trigger items - for(var/X in HU.get_all_worn_items() | HU.held_items) - var/obj/I = X - if(!QDELETED(I) && (is_type_in_typecache(I, trigger_objs) || (phobia_type == "blood" && GET_ATOM_BLOOD_DNA_LENGTH(I)))) - freak_out(I) + for(var/mob/living/carbon/human/nearby_guy in seen_atoms) //check equipment for trigger items + for(var/obj/item/equipped as anything in nearby_guy.get_visible_items()) + if(is_scary_item(equipped)) + freak_out(equipped) return if(LAZYLEN(trigger_turfs)) @@ -77,6 +76,15 @@ freak_out(H) return +/// Returns true if this item should be scary to us +/datum/brain_trauma/mild/phobia/proc/is_scary_item(obj/checked) + if (QDELETED(checked) || !is_type_in_typecache(checked, trigger_objs)) + return FALSE + if (!isitem(checked)) + return TRUE + var/obj/item/checked_item = checked + return !(checked_item.item_flags & EXAMINE_SKIP) + /datum/brain_trauma/mild/phobia/handle_hearing(datum/source, list/hearing_args) if(!owner.can_hear() || owner == hearing_args[HEARING_SPEAKER] || !owner.has_language(hearing_args[HEARING_LANGUAGE])) //words can't trigger you if you can't hear them *taps head* return @@ -217,3 +225,8 @@ /datum/brain_trauma/mild/phobia/blood phobia_type = "blood" random_gain = FALSE + +/datum/brain_trauma/mild/phobia/blood/is_scary_item(obj/checked) + if (GET_ATOM_BLOOD_DNA_LENGTH(checked)) + return TRUE + return ..() diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 6b9c0941a4a..f13d2bc51af 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -103,6 +103,39 @@ s_store, ) +/// Returns items which are currently visible on the mob +/mob/living/carbon/human/proc/get_visible_items() + var/static/list/visible_slots = list( + ITEM_SLOT_OCLOTHING, + ITEM_SLOT_ICLOTHING, + ITEM_SLOT_GLOVES, + ITEM_SLOT_EYES, + ITEM_SLOT_EARS, + ITEM_SLOT_MASK, + ITEM_SLOT_HEAD, + ITEM_SLOT_FEET, + ITEM_SLOT_ID, + ITEM_SLOT_BELT, + ITEM_SLOT_BACK, + ITEM_SLOT_NECK, + ITEM_SLOT_HANDS, + ITEM_SLOT_BACKPACK, + ITEM_SLOT_SUITSTORE, + ITEM_SLOT_HANDCUFFED, + ITEM_SLOT_LEGCUFFED, + ) + var/list/obscured = check_obscured_slots() + var/list/visible_items = list() + for (var/slot in visible_slots) + if (obscured & slot) + continue + var/obj/item/equipped = get_item_by_slot(slot) + if (equipped) + visible_items += equipped + for (var/obj/item/held in held_items) + visible_items += held + return visible_items + //This is an UNSAFE proc. Use mob_can_equip() before calling this one! Or rather use equip_to_slot_if_possible() or advanced_equip_to_slot_if_possible() // Initial is used to indicate whether or not this is the initial equipment (job datums etc) or just a player doing it /mob/living/carbon/human/equip_to_slot(obj/item/I, slot, initial = FALSE, redraw_mob = FALSE) diff --git a/code/modules/surgery/implant_removal.dm b/code/modules/surgery/implant_removal.dm index 4563d7a40f7..9370a4f719c 100644 --- a/code/modules/surgery/implant_removal.dm +++ b/code/modules/surgery/implant_removal.dm @@ -51,7 +51,7 @@ span_notice("[user] successfully removes [implant] from [target]'s [target_zone]!"), span_notice("[user] successfully removes something from [target]'s [target_zone]!"), ) - display_pain(target, "You can feel your [implant] pulled out of you!") + display_pain(target, "You can feel your [implant.name] pulled out of you!") implant.removed(target) var/obj/item/implantcase/case diff --git a/code/modules/surgery/lobectomy.dm b/code/modules/surgery/lobectomy.dm index 1b4eff0e85d..d3d90a90aeb 100644 --- a/code/modules/surgery/lobectomy.dm +++ b/code/modules/surgery/lobectomy.dm @@ -55,7 +55,7 @@ span_notice("Successfully removes a piece of [human_target]'s lungs."), "", ) - display_pain(target, "Your chest hurts like hell, but breathng becomes slightly easier.") + display_pain(target, "Your chest hurts like hell, but breathing becomes slightly easier.") return ..() /datum/surgery_step/lobectomy/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) diff --git a/code/modules/surgery/organ_manipulation.dm b/code/modules/surgery/organ_manipulation.dm index 19ee8cf2bf9..874e398cad3 100644 --- a/code/modules/surgery/organ_manipulation.dm +++ b/code/modules/surgery/organ_manipulation.dm @@ -206,7 +206,7 @@ span_notice("[user] begins to extract [target_organ] from [target]'s [parse_zone(target_zone)]."), span_notice("[user] begins to extract something from [target]'s [parse_zone(target_zone)]."), ) - display_pain(target, "You can feel your [target_organ] being removed from your [parse_zone(target_zone)]!") + display_pain(target, "You can feel your [target_organ.name] being removed from your [parse_zone(target_zone)]!") else return SURGERY_STEP_FAIL @@ -232,7 +232,7 @@ span_notice("[user] inserts [tool] into [target]'s [parse_zone(target_zone)]!"), span_notice("[user] inserts something into [target]'s [parse_zone(target_zone)]!"), ) - display_pain(target, "Your [parse_zone(target_zone)] throbs with pain as your new [tool] comes to life!") + display_pain(target, "Your [parse_zone(target_zone)] throbs with pain as your new [tool.name] comes to life!") else target_organ.forceMove(target.loc) @@ -245,7 +245,7 @@ span_notice("[user] successfully extracts [target_organ] from [target]'s [parse_zone(target_zone)]!"), span_notice("[user] successfully extracts something from [target]'s [parse_zone(target_zone)]!"), ) - display_pain(target, "Your [parse_zone(target_zone)] throbs with pain, you can't feel your [target_organ] anymore!") + display_pain(target, "Your [parse_zone(target_zone)] throbs with pain, you can't feel your [target_organ.name] anymore!") log_combat(user, target, "surgically removed [target_organ.name] from", addition="COMBAT MODE: [uppertext(user.combat_mode)]") target_organ.Remove(target) target_organ.forceMove(get_turf(target))