From 4d32fa90616b33e242c8c095812191f9a1b1aca6 Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Sat, 13 Jul 2024 14:55:43 -0500 Subject: [PATCH] Scratches random things off the TODO list (#529) --- _maps/shuttles/emergency_lima.dmm | 2 +- .../signals/signals_mob/signals_mob_living.dm | 2 - code/__HELPERS/radiation.dm | 2 + .../mood_events/generic_negative_events.dm | 4 +- code/datums/mutations/hulk.dm | 2 +- code/game/objects/items/cards_ids.dm | 14 ++-- code/game/objects/items/cigs_lighters.dm | 9 ++- code/game/objects/items/hand_items.dm | 6 +- .../crates_lockers/closets/bodybag.dm | 21 ++++- code/game/objects/structures/morgue.dm | 25 ++++++ code/modules/mob/living/carbon/carbon.dm | 17 ++++ .../mob/living/carbon/human/_species.dm | 2 +- code/modules/mob/living/carbon/human/emote.dm | 37 ++++++++- code/modules/surgery/organs/external/tails.dm | 80 +++++++++++-------- code/modules/unit_tests/tail_wag.dm | 31 ++++--- .../code/datums/components/knockoff_move.dm | 11 +-- .../code/datums/id_trim/jobs.dm | 21 ++--- .../objects/structures/item_dispensers.dm | 12 ++- .../code/modules/jobs/job_types/_job.dm | 4 +- .../jobs/job_types/asset_protection.dm | 2 +- .../modules/jobs/job_types/bridge_officer.dm | 4 +- .../jobs/job_types/noble_ambassador.dm | 2 + .../modules/jobs/job_types/ordnance_tech.dm | 2 +- .../modules/jobs/job_types/xenobiologist.dm | 2 +- .../loadout_items/loadout_datum_belts.dm | 24 +++++- .../research/designs/autolathe_designs.dm | 12 +++ .../modules/research/techweb/all_nodes.dm | 1 + .../prince_equipment/code/clothing.dm | 4 +- 28 files changed, 252 insertions(+), 103 deletions(-) diff --git a/_maps/shuttles/emergency_lima.dmm b/_maps/shuttles/emergency_lima.dmm index 788949b77b9f..a66b5238e722 100644 --- a/_maps/shuttles/emergency_lima.dmm +++ b/_maps/shuttles/emergency_lima.dmm @@ -743,7 +743,7 @@ /area/shuttle/escape) "VZ" = ( /obj/structure/table/reinforced, -/obj/item/clothing/gloves/color/latex, +/obj/item/clothing/gloves/latex, /obj/item/clothing/mask/surgical, /obj/item/healthanalyzer, /turf/open/floor/mineral/titanium/white, diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm index 7ac77efcaa7f..c4acf3988b23 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_living.dm @@ -12,8 +12,6 @@ #define COMSIG_ORGAN_BEING_REPLACED "organ_being_replaced" /// Called when an organ gets surgically removed (mob/living/user, mob/living/carbon/old_owner, target_zone, obj/item/tool) #define COMSIG_ORGAN_SURGICALLY_REMOVED "organ_surgically_removed" -/// Called when using the *wag emote -#define COMSIG_ORGAN_WAG_TAIL "wag_tail" ///from base of mob/update_transform() #define COMSIG_LIVING_POST_UPDATE_TRANSFORM "living_post_update_transform" diff --git a/code/__HELPERS/radiation.dm b/code/__HELPERS/radiation.dm index eb1abb9fcc4e..5722ac1574d1 100644 --- a/code/__HELPERS/radiation.dm +++ b/code/__HELPERS/radiation.dm @@ -85,6 +85,8 @@ return /obj/item/make_irradiated(can_propogate) + if(anchored) + return AddElement(/datum/element/simple_rad) /mob/living/carbon/human/make_irradiated(can_propogate) diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index cc3af071eef3..afcb5d688ed6 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -112,8 +112,8 @@ /datum/mood_event/table/add_effects() if(isfelinid(owner)) //Holy snowflake batman! - var/mob/living/carbon/human/H = owner - SEND_SIGNAL(H, COMSIG_ORGAN_WAG_TAIL, TRUE, 3 SECONDS) + var/mob/living/carbon/human/feline = owner + feline.wag_tail(3 SECONDS) description = "They want to play on the table!" mood_change = 2 diff --git a/code/datums/mutations/hulk.dm b/code/datums/mutations/hulk.dm index bb4b55f0cac8..36fd1ebd6712 100644 --- a/code/datums/mutations/hulk.dm +++ b/code/datums/mutations/hulk.dm @@ -52,7 +52,7 @@ return COMPONENT_CANCEL_ATTACK_CHAIN /datum/mutation/human/hulk/proc/scream_attack(mob/living/carbon/human/source) - source.say("WAAAAAAAAAAAAAAGH!", forced="hulk") + source.say(pick(";RAAAAAAAARGH!", ";HNNNNNNNNNGGGGGGH!", ";GWAAAAAAAARRRHHH!", "NNNNNNNNGGGGGGGGHH!", ";AAAAAAARRRGH!" ), forced = "hulk") /** *Checks damage of a hulk's arm and applies bone wounds as necessary. diff --git a/code/game/objects/items/cards_ids.dm b/code/game/objects/items/cards_ids.dm index da6e70e0fcb6..dbf1fcfb5b95 100644 --- a/code/game/objects/items/cards_ids.dm +++ b/code/game/objects/items/cards_ids.dm @@ -1023,21 +1023,21 @@ if(registered_name && registered_name != "Captain") . += mutable_appearance(icon, assigned_icon_state) - var/trim_icon_file = trim_icon_override ? trim_icon_override : trim?.trim_icon - var/trim_icon_state = trim_state_override ? trim_state_override : trim?.trim_state - var/trim_department_color = department_color_override ? department_color_override : trim?.department_color - var/trim_department_state = department_state_override ? department_state_override : trim?.department_state - var/trim_subdepartment_color = subdepartment_color_override ? subdepartment_color_override : trim?.subdepartment_color + var/trim_icon_file = trim_icon_override || trim?.trim_icon + var/trim_icon_state = trim_state_override || trim?.trim_state + var/trim_department_color = department_color_override || trim?.department_color + var/trim_department_state = department_state_override || trim?.department_state + var/trim_subdepartment_color = subdepartment_color_override || trim?.subdepartment_color if(!trim_icon_file || !trim_icon_state || !trim_department_color || !trim_subdepartment_color || !trim_department_state) return /// We handle department and subdepartment overlays first, so the job icon is always on top. - var/mutable_appearance/department_overlay = mutable_appearance(trim_icon_file, trim_department_state) + var/mutable_appearance/department_overlay = mutable_appearance('icons/obj/card.dmi', trim_department_state) department_overlay.color = trim_department_color . += department_overlay - var/mutable_appearance/subdepartment_overlay = mutable_appearance(trim_icon_file, "subdepartment") + var/mutable_appearance/subdepartment_overlay = mutable_appearance('icons/obj/card.dmi', "subdepartment") subdepartment_overlay.color = trim_subdepartment_color . += subdepartment_overlay diff --git a/code/game/objects/items/cigs_lighters.dm b/code/game/objects/items/cigs_lighters.dm index 86c8e3622d09..3c64fde9810d 100644 --- a/code/game/objects/items/cigs_lighters.dm +++ b/code/game/objects/items/cigs_lighters.dm @@ -717,9 +717,16 @@ CIGARETTE PACKETS ARE IN FANCY.DM /obj/item/cigbutt/equipped(mob/user, slot, initial) // Lazily initing these components because there's no need to do it for every single cigarette butt AddComponent(/datum/component/knockoff, 90, list(BODY_ZONE_PRECISE_MOUTH, BODY_ZONE_HEAD, BODY_ZONE_CHEST), slot_flags) - AddComponent(/datum/component/wearertargeting/knockoff_move, 1, list(slot_flags), "falls out of your mouth!") + AddComponent(/datum/component/wearertargeting/knockoff_move, 1, list(slot_flags), CALLBACK(src, PROC_REF(on_fall))) return ..() +/obj/item/cigbutt/proc/on_fall(mob/living/guy) + guy.visible_message( + span_warning("[src] falls out [guy]'s mouth."), + span_warning("[src] falls out of your mouth."), + visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE, + ) + /obj/item/cigbutt/cigarbutt name = "cigar butt" desc = "A manky old cigar butt." diff --git a/code/game/objects/items/hand_items.dm b/code/game/objects/items/hand_items.dm index c6dc9cb7a2f1..2255afe10541 100644 --- a/code/game/objects/items/hand_items.dm +++ b/code/game/objects/items/hand_items.dm @@ -219,9 +219,9 @@ /obj/item/hand_item/slapper/attack(mob/living/slapped, mob/living/carbon/human/user) SEND_SIGNAL(user, COMSIG_LIVING_SLAP_MOB, slapped) - if(ishuman(slapped)) - var/mob/living/carbon/human/human_slapped = slapped - SEND_SIGNAL(human_slapped, COMSIG_ORGAN_WAG_TAIL, FALSE) + if(iscarbon(slapped)) + var/mob/living/carbon/potential_tailed = slapped + potential_tailed.unwag_tail() user.do_attack_animation(slapped) var/slap_volume = 50 diff --git a/code/game/objects/structures/crates_lockers/closets/bodybag.dm b/code/game/objects/structures/crates_lockers/closets/bodybag.dm index d8e7435ece50..67295ad712b8 100644 --- a/code/game/objects/structures/crates_lockers/closets/bodybag.dm +++ b/code/game/objects/structures/crates_lockers/closets/bodybag.dm @@ -48,7 +48,7 @@ QDEL_NULL(foldedbag_instance) return ..() -/obj/structure/closet/body_bag/attackby(obj/item/interact_tool, mob/user, params) +/obj/structure/closet/body_bag/attackby(obj/item/interact_tool, mob/living/user, params) if (istype(interact_tool, /obj/item/pen) || istype(interact_tool, /obj/item/toy/crayon)) if(!user.can_write(interact_tool)) return @@ -59,11 +59,14 @@ return handle_tag("[t ? t : initial(name)]") return + else if(!user.combat_mode && !(interact_tool.item_flags & (ABSTRACT|HAND_ITEM)) && user.transferItemToLoc(interact_tool, loc, silent = FALSE)) + return if(!tag_name) return if(interact_tool.tool_behaviour == TOOL_WIRECUTTER || interact_tool.get_sharpness()) to_chat(user, span_notice("You cut the tag off [src].")) handle_tag() + return ///Handles renaming of the bodybag's examine tag. /obj/structure/closet/body_bag/proc/handle_tag(new_name) @@ -487,6 +490,14 @@ /obj/structure/closet/body_bag/environmental/stasis/Entered(atom/movable/arrived, atom/old_loc, list/atom/old_locs) . = ..() + if(isinternalorgan(arrived)) + var/obj/item/organ/organ_arrived = arrived + organ_arrived.organ_flags |= ORGAN_FROZEN + return + if(isbodypart(arrived)) + for(var/obj/item/organ/internal/organ in arrived) + organ.organ_flags |= ORGAN_FROZEN + return if(!isliving(arrived)) return if(seconds_freezing != -1) @@ -495,6 +506,14 @@ /obj/structure/closet/body_bag/environmental/stasis/Exited(atom/movable/gone, direction) . = ..() + if(isinternalorgan(gone)) + var/obj/item/organ/organ_gone = gone + organ_gone.organ_flags &= ~ORGAN_FROZEN + return + if(isbodypart(gone)) + for(var/obj/item/organ/internal/organ in gone) + organ.organ_flags &= ~ORGAN_FROZEN + return if(!isliving(gone)) return seconds_freezing = -1 diff --git a/code/game/objects/structures/morgue.dm b/code/game/objects/structures/morgue.dm index 3e45232fbaea..95e04c11f3d3 100644 --- a/code/game/objects/structures/morgue.dm +++ b/code/game/objects/structures/morgue.dm @@ -53,6 +53,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an if(connected) connected = new connected(src) connected.connected = src + connected.RegisterSignal(src, COMSIG_CLICK, TYPE_PROC_REF(/obj/structure/tray, redirect_click)) GLOB.bodycontainers += src register_context() @@ -559,6 +560,20 @@ GLOBAL_LIST_EMPTY(crematoriums) to_chat(user, span_warning("That's not connected to anything!")) add_fingerprint(user) +// Registered on our connected bodycontainer, so if we click it we redirect to click this +/obj/structure/tray/proc/redirect_click(datum/source, location, control, params, mob/clicker) + SIGNAL_HANDLER + ASSERT(source == connected) + if(!isliving(clicker) \ + || loc == connected \ + || clicker.get_active_held_item() \ + || !clicker.CanReach(src) \ + || clicker.CanReach(connected) \ + ) + return + + INVOKE_ASYNC(clicker, TYPE_PROC_REF(/mob, ClickOn), src, params) + /obj/structure/tray/attackby(obj/P, mob/user, params) if(!istype(P, /obj/item/riding_offhand)) return ..() @@ -618,5 +633,15 @@ GLOBAL_LIST_EMPTY(crematoriums) if(locate(/obj/structure/table) in get_turf(mover)) return TRUE +/obj/structure/tray/m_tray/item_interaction(mob/living/user, obj/item/tool, list/modifiers, is_right_clicking) + . = ..() + if(. & ITEM_INTERACT_ANY_BLOCKER) + return + if(user.combat_mode) + return + if(tool.item_flags & (ABSTRACT|HAND_ITEM)) + return + return user.transferItemToLoc(tool, loc, silent = FALSE) ? ITEM_INTERACT_SUCCESS : ITEM_INTERACT_BLOCKING + #undef BREAKOUT_COOLDOWN #undef BREAKDOWN_TIME diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 209789b8fb15..e1f2fc05c99b 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1446,3 +1446,20 @@ if(item && ((item in organs) || (item in bodyparts))) //let's not do this, aight? return FALSE return ..() + +/// Helper to cleanly trigger tail wagging +/// Accepts an optional timeout after which we remove the tail wagging +/// Returns true if successful, false otherwise +/mob/living/carbon/proc/wag_tail(timeout = INFINITY) + var/obj/item/organ/external/tail/wagged = get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + if(!wagged) + return FALSE + return wagged.start_wag(src, timeout) + +/// Helper to cleanly stop all tail wagging +/// Returns true if successful, false otherwise +/mob/living/carbon/proc/unwag_tail() // can't unwag a tail + var/obj/item/organ/external/tail/unwagged = get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + if(!unwagged) + return FALSE + return unwagged.stop_wag(src) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 4c4d09f102ac..b31169401098 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -1612,7 +1612,7 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/clear_tail_moodlets(mob/living/carbon/human/former_tail_owner) former_tail_owner.clear_mood_event("tail_lost") former_tail_owner.clear_mood_event("tail_balance_lost") - former_tail_owner.clear_mood_event("wrong_tail_regained") + former_tail_owner.clear_mood_event("tail_regained") /// Returns a list of strings representing features this species has. /// Used by the preferences UI to know what buttons to show. diff --git a/code/modules/mob/living/carbon/human/emote.dm b/code/modules/mob/living/carbon/human/emote.dm index 4b6734ebdf91..3a086be09583 100644 --- a/code/modules/mob/living/carbon/human/emote.dm +++ b/code/modules/mob/living/carbon/human/emote.dm @@ -122,10 +122,12 @@ if(!.) return var/obj/item/organ/external/tail/oranges_accessory = user.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + //I am so sorry my son + //We bypass helpers here cause we already have the tail if(oranges_accessory.wag_flags & WAG_WAGGING) //We verified the tail exists in can_run_emote() - SEND_SIGNAL(user, COMSIG_ORGAN_WAG_TAIL, FALSE) + oranges_accessory.stop_wag(user) else - SEND_SIGNAL(user, COMSIG_ORGAN_WAG_TAIL, TRUE) + oranges_accessory.start_wag(user) /datum/emote/living/carbon/human/wag/select_message_type(mob/user, intentional) . = ..() @@ -141,6 +143,25 @@ return ..() return FALSE +/datum/emote/living/carbon/human/wag_swish + key = "swish" + key_third_person = "swishes" + message = "swishes their tail." + +/datum/emote/living/carbon/human/wag_swish/run_emote(mob/user, params, type_override, intentional) + . = ..() + if(!.) + return + var/obj/item/organ/external/tail/tail = user.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + if(tail?.wag_flags & WAG_ABLE) + tail.start_wag(user, 1 SECONDS) + +/datum/emote/living/carbon/human/wag_swish/can_run_emote(mob/user, status_check, intentional) + var/obj/item/organ/external/tail/tail = user.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + if(tail?.wag_flags & WAG_ABLE) + return ..() + return FALSE + /datum/emote/living/carbon/human/wing key = "wing" key_third_person = "wings" @@ -173,6 +194,18 @@ key_third_person = "clears throat" message = "clears their throat." +/datum/emote/living/carbon/human/hiss + key = "hiss" + key_third_person = "hisses" + message = "hisses." + message_mime = "hisses silently." + emote_type = EMOTE_AUDIBLE + +/datum/emote/living/carbon/human/hiss/get_sound(mob/user) + if(islizard(user)) + return pick(user.get_speech_sounds()) + return null + ///Snowflake emotes only for le epic chimp /datum/emote/living/carbon/human/monkey diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index 5c1ec393d5d2..9fda5a87f1b8 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -15,24 +15,28 @@ ///Does this tail have a wagging sprite, and is it currently wagging? var/wag_flags = NONE - ///The original owner of this tail - var/original_owner //Yay, snowflake code! ///The overlay for tail spines, if any var/datum/bodypart_overlay/mutant/tail_spines/tail_spines_overlay -/obj/item/organ/external/tail/Insert(mob/living/carbon/receiver, special, movement_flags) +/obj/item/organ/external/tail/proc/is_tailed_species(mob/living/carbon/who) + for(var/tail_type in who.dna.species.external_organs) + if(ispath(tail_type, /obj/item/organ/external/tail)) + return TRUE + return FALSE + +/obj/item/organ/external/tail/on_mob_insert(mob/living/carbon/organ_owner, special, movement_flags) . = ..() - if(.) - RegisterSignal(receiver, COMSIG_ORGAN_WAG_TAIL, PROC_REF(wag)) - original_owner ||= WEAKREF(receiver) + organ_owner.clear_mood_event("tail_lost") + organ_owner.clear_mood_event("tail_balance_lost") - receiver.clear_mood_event("tail_lost") - receiver.clear_mood_event("tail_balance_lost") + if(!is_tailed_species(organ_owner)) + wag_flags &= ~WAG_ABLE + return + if(special) + return - if(IS_WEAKREF_OF(receiver, original_owner)) - receiver.clear_mood_event("wrong_tail_regained") - else if(type in receiver.dna.species.external_organs) - receiver.add_mood_event("wrong_tail_regained", /datum/mood_event/tail_regained_wrong) + var/moodlet_type = is_type_in_list(src, organ_owner.dna.species.external_organs) ? /datum/mood_event/tail_regained_right : /datum/mood_event/tail_regained_wrong + organ_owner.add_mood_event("tail_regained", moodlet_type) /obj/item/organ/external/tail/on_bodypart_insert(obj/item/bodypart/bodypart) var/obj/item/organ/external/spines/our_spines = bodypart.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_SPINES) @@ -72,56 +76,64 @@ /obj/item/organ/external/tail/on_mob_remove(mob/living/carbon/organ_owner, special) . = ..() + organ_owner.clear_mood_event("tail_regained") - if(wag_flags & WAG_WAGGING) - wag(organ_owner, start = FALSE) + if(initial(wag_flags) & WAG_ABLE) + wag_flags |= WAG_ABLE - UnregisterSignal(organ_owner, COMSIG_ORGAN_WAG_TAIL) + if(wag_flags & WAG_WAGGING) + stop_wag(organ_owner) - if(type in organ_owner.dna.species.external_organs) + if(is_type_in_list(src, organ_owner.dna.species.external_organs)) organ_owner.add_mood_event("tail_lost", /datum/mood_event/tail_lost) organ_owner.add_mood_event("tail_balance_lost", /datum/mood_event/tail_balance_lost) -/obj/item/organ/external/tail/proc/wag(mob/living/carbon/organ_owner, start = TRUE, stop_after = 0) - if(!(wag_flags & WAG_ABLE)) - return - - if(start) - if(start_wag(organ_owner) && stop_after) - addtimer(CALLBACK(src, PROC_REF(wag), organ_owner, FALSE), stop_after, TIMER_STOPPABLE|TIMER_DELETE_ME) - else - stop_wag(organ_owner) - ///We need some special behaviour for accessories, wrapped here so we can easily add more interactions later -/obj/item/organ/external/tail/proc/start_wag(mob/living/carbon/organ_owner) - if(wag_flags & WAG_WAGGING) // we are already wagging +///Accepts an optional timeout after which we remove the tail wagging +///Returns false if the wag worked, true otherwise +/obj/item/organ/external/tail/proc/start_wag(mob/living/carbon/organ_owner, stop_after = INFINITY) + if(wag_flags & WAG_WAGGING || !(wag_flags & WAG_ABLE)) // we are already wagging return FALSE if(organ_owner.stat == DEAD || organ_owner != owner) // no wagging when owner is dead or tail has been disembodied return FALSE + if(stop_after != INFINITY) + addtimer(CALLBACK(src, PROC_REF(stop_wag), organ_owner), stop_after, TIMER_STOPPABLE|TIMER_DELETE_ME) + var/datum/bodypart_overlay/mutant/tail/accessory = bodypart_overlay wag_flags |= WAG_WAGGING accessory.wagging = TRUE if(tail_spines_overlay) //if there are spines, they should wag with the tail tail_spines_overlay.wagging = TRUE organ_owner.update_body_parts() - RegisterSignal(organ_owner, COMSIG_LIVING_DEATH, PROC_REF(stop_wag)) + RegisterSignal(organ_owner, COMSIG_LIVING_DEATH, PROC_REF(owner_died)) return TRUE +/obj/item/organ/external/tail/proc/owner_died(mob/living/carbon/organ_owner) // Resisting the urge to replace owner with daddy + SIGNAL_HANDLER + stop_wag(organ_owner) + ///We need some special behaviour for accessories, wrapped here so we can easily add more interactions later +///Returns false if the wag stopping worked, true otherwise /obj/item/organ/external/tail/proc/stop_wag(mob/living/carbon/organ_owner) - SIGNAL_HANDLER + if(!(wag_flags & WAG_ABLE)) + return FALSE - var/datum/bodypart_overlay/mutant/tail/accessory = bodypart_overlay - wag_flags &= ~WAG_WAGGING - accessory.wagging = FALSE + var/succeeded = FALSE + if(wag_flags & WAG_WAGGING) + wag_flags &= ~WAG_WAGGING + succeeded = TRUE + + var/datum/bodypart_overlay/mutant/tail/tail_overlay = bodypart_overlay + tail_overlay.wagging = FALSE if(tail_spines_overlay) //if there are spines, they should stop wagging with the tail tail_spines_overlay.wagging = FALSE if(isnull(organ_owner)) - return + return succeeded organ_owner.update_body_parts() UnregisterSignal(organ_owner, COMSIG_LIVING_DEATH) + return succeeded ///Tail parent type, with wagging functionality /datum/bodypart_overlay/mutant/tail diff --git a/code/modules/unit_tests/tail_wag.dm b/code/modules/unit_tests/tail_wag.dm index ceb82e98c0d6..34495f302be8 100644 --- a/code/modules/unit_tests/tail_wag.dm +++ b/code/modules/unit_tests/tail_wag.dm @@ -5,28 +5,41 @@ /datum/unit_test/tail_wag/Run() var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent) + dummy.dna.species.external_organs[/obj/item/organ/external/tail/cat] = "Cat" // so we can actually wag var/obj/item/organ/external/tail/cat/dummy_tail = allocate(/obj/item/organ/external/tail/cat) dummy_tail.Insert(dummy, special = TRUE, movement_flags = DELETE_IF_REPLACED) // SANITY TEST // start wagging - SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, TRUE) + dummy.wag_tail() if(!(dummy_tail.wag_flags & WAG_WAGGING)) TEST_FAIL("Tail did not start wagging when it should have!") // stop wagging - SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, FALSE) + dummy.unwag_tail() if(dummy_tail.wag_flags & WAG_WAGGING) TEST_FAIL("Tail did not stop wagging when it should have!") + // TESTING WAG EMOTE + + // start wagging + dummy.emote("wag") + if(!(dummy_tail.wag_flags & WAG_WAGGING)) + TEST_FAIL("Tail did not start wagging after using the *wag emote!") + + // stop wagging + dummy.emote("wag") + if(dummy_tail.wag_flags & WAG_WAGGING) + TEST_FAIL("Tail did not stop wagging after using the *wag emote!") + // TESTING WAG_ABLE FLAG // flip the wag flag to unwaggable dummy_tail.wag_flags &= ~WAG_ABLE // try to wag it again - SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, TRUE) + dummy.wag_tail() if(dummy_tail.wag_flags & WAG_WAGGING) TEST_FAIL("Tail should not have the ability to wag, yet it did!") @@ -34,19 +47,19 @@ dummy_tail.wag_flags |= WAG_ABLE // start wagging again - SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, TRUE) + dummy.wag_tail() if(!(dummy_tail.wag_flags & WAG_WAGGING)) TEST_FAIL("Tail did not start wagging when it should have!") // TESTING STOP_AFTER // stop wagging - SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, FALSE) + dummy.unwag_tail() if(dummy_tail.wag_flags & WAG_WAGGING) TEST_FAIL("Tail did not stop wagging when it should have!") // start wagging, stop after 0.1 seconds - SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, TRUE, 0.1 SECONDS) + dummy.wag_tail(0.1 SECONDS) // because timers are a pain addtimer(VARSET_CALLBACK(src, timer_finished, TRUE), 0.2 SECONDS) if(!(dummy_tail.wag_flags & WAG_WAGGING)) @@ -67,7 +80,7 @@ TEST_FAIL("Tail was still wagging after being removed!") // try to wag the removed tail - SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, TRUE) + dummy.wag_tail() if(dummy_tail.wag_flags & WAG_WAGGING) TEST_FAIL("A disembodied tail was able to start wagging!") @@ -75,7 +88,7 @@ // put it back and start wagging again dummy_tail.Insert(dummy, special = TRUE, movement_flags = DELETE_IF_REPLACED) - SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, TRUE) + dummy.wag_tail() if(!(dummy_tail.wag_flags & WAG_WAGGING)) TEST_FAIL("Tail did not start wagging when it should have!") @@ -85,6 +98,6 @@ TEST_FAIL("A mob's tail was still wagging after being killed!") // check if we are still able to wag the tail after death - SEND_SIGNAL(dummy, COMSIG_ORGAN_WAG_TAIL, TRUE) + dummy.wag_tail() if(dummy_tail.wag_flags & WAG_WAGGING) TEST_FAIL("A dead mob was able to wag their tail!") diff --git a/maplestation_modules/code/datums/components/knockoff_move.dm b/maplestation_modules/code/datums/components/knockoff_move.dm index 5c0697bc4bb7..472a7ee845be 100644 --- a/maplestation_modules/code/datums/components/knockoff_move.dm +++ b/maplestation_modules/code/datums/components/knockoff_move.dm @@ -2,12 +2,12 @@ signals = list(COMSIG_MOVABLE_MOVED) proctype = PROC_REF(check_fall) var/fall_chance = 100 - var/how_fall + var/datum/callback/fall_callback -/datum/component/wearertargeting/knockoff_move/Initialize(chance = 10, list/slots, how_fall = "falls!") +/datum/component/wearertargeting/knockoff_move/Initialize(chance = 10, list/slots, datum/callback/fall_callback) src.valid_slots = slots src.fall_chance = chance - src.how_fall = how_fall + src.fall_callback = fall_callback return ..() /datum/component/wearertargeting/knockoff_move/proc/check_fall(mob/living/source, atom/old_loc, dir, forced) @@ -32,7 +32,4 @@ if(!source.dropItemToGround(item_parent)) return - source.visible_message( - span_warning("[source]'s [item_parent.name] [how_fall]"), - span_warning("[item_parent] [how_fall]"), - ) + fall_callback?.Invoke(source) diff --git a/maplestation_modules/code/datums/id_trim/jobs.dm b/maplestation_modules/code/datums/id_trim/jobs.dm index f4aaa432c7d9..a87e3822e5aa 100644 --- a/maplestation_modules/code/datums/id_trim/jobs.dm +++ b/maplestation_modules/code/datums/id_trim/jobs.dm @@ -67,6 +67,8 @@ trim_state = "trim_ordnance_tech" sechud_icon = 'maplestation_modules/icons/mob/huds/hud.dmi' sechud_icon_state = "hudordnancetechnician" + department_color = COLOR_SCIENCE_PINK + subdepartment_color = COLOR_SCIENCE_PINK extra_access = list(ACCESS_GENETICS, ACCESS_ROBOTICS, ACCESS_XENOBIOLOGY) minimal_access = list(ACCESS_AUX_BASE, ACCESS_MECH_SCIENCE, ACCESS_MINERAL_STOREROOM, ACCESS_ORDNANCE, ACCESS_ORDNANCE_STORAGE, ACCESS_RESEARCH, ACCESS_SCIENCE) @@ -80,26 +82,13 @@ trim_state = "trim_xenobiologist" sechud_icon = 'maplestation_modules/icons/mob/huds/hud.dmi' sechud_icon_state = "hudxenobiologist" + department_color = COLOR_SCIENCE_PINK + subdepartment_color = COLOR_SCIENCE_PINK extra_access = list(ACCESS_GENETICS, ACCESS_ROBOTICS, ACCESS_ORDNANCE, ACCESS_ORDNANCE_STORAGE) minimal_access = list(ACCESS_AUX_BASE, ACCESS_MECH_SCIENCE, ACCESS_MINERAL_STOREROOM, ACCESS_RESEARCH, ACCESS_SCIENCE, ACCESS_XENOBIOLOGY) template_access = list(ACCESS_CAPTAIN, ACCESS_RD, ACCESS_CHANGE_IDS) job = /datum/job/xenobiologist -/datum/id_trim/job/noble_ambassador - assignment = "Noble Ambassador" - trim_icon = 'maplestation_modules/icons/obj/card.dmi' - trim_state = "trim_noble" - sechud_icon = 'maplestation_modules/icons/mob/huds/hud.dmi' - sechud_icon_state = "hudnoble" - extra_access = list(ACCESS_RESEARCH, ACCESS_SCIENCE) - extra_wildcard_access = list(ACCESS_ARMORY) - minimal_access = list(ACCESS_BRIG, ACCESS_CARGO, ACCESS_CONSTRUCTION, ACCESS_COURT, ACCESS_COMMAND, - ACCESS_KEYCARD_AUTH, ACCESS_LAWYER, ACCESS_SHIPPING, ACCESS_MAINT_TUNNELS, ACCESS_MEDICAL, - ACCESS_MINERAL_STOREROOM, ACCESS_RC_ANNOUNCE, ACCESS_BRIG_ENTRANCE, ACCESS_SECURITY, ACCESS_WEAPONS) - minimal_wildcard_access = list(ACCESS_VAULT) - template_access = list(ACCESS_CAPTAIN, ACCESS_HOP, ACCESS_CHANGE_IDS) - job = /datum/job/noble_ambassador - /datum/id_trim/job/noble_ambassador assignment = "Noble Ambassador" intern_alt_name = "Noble Squire" @@ -107,6 +96,8 @@ trim_state = "trim_noble" sechud_icon = 'maplestation_modules/icons/mob/huds/hud.dmi' sechud_icon_state = "hudnoble" + department_color = COLOR_COMMAND_BLUE + subdepartment_color = COLOR_COMMAND_BLUE minimal_access = list( ACCESS_AUX_BASE, ACCESS_BAR, diff --git a/maplestation_modules/code/game/objects/structures/item_dispensers.dm b/maplestation_modules/code/game/objects/structures/item_dispensers.dm index b33cdb8305c8..7e6e01bef730 100644 --- a/maplestation_modules/code/game/objects/structures/item_dispensers.dm +++ b/maplestation_modules/code/game/objects/structures/item_dispensers.dm @@ -102,7 +102,7 @@ curr_charges -= things_to_drop return ..() -/obj/structure/item_dispenser/proc/dispense_item(atom/drop_loc) +/obj/structure/item_dispenser/proc/dispense_item(atom/drop_loc = drop_location()) var/obj/item/dropped = LAZYLEN(stored_things) ? stored_things[1] : new stock() LAZYREMOVE(stored_things, dropped) dropped.forceMove(drop_loc) @@ -151,8 +151,7 @@ return ITEM_INTERACT_BLOCKING balloon_alert(user, "unsecuring...") - tool.play_tool_sound(src) - if(!tool.use_tool(src, user, 1 SECONDS)) + if(!tool.use_tool(src, user, 1 SECONDS, volume = 50)) balloon_alert(user, "interrupted!") return ITEM_INTERACT_BLOCKING @@ -174,8 +173,7 @@ return ITEM_INTERACT_BLOCKING balloon_alert(user, "adjusting spring...") - tool.play_tool_sound(src) - if(!tool.use_tool(src, user, 1 SECONDS)) + if(!tool.use_tool(src, user, 1 SECONDS, volume = 50)) balloon_alert(user, "interrupted!") return ITEM_INTERACT_BLOCKING @@ -197,7 +195,7 @@ balloon_alert(user, "no items left!") return - var/obj/item/grabbies = dispense_item(drop_location()) + var/obj/item/grabbies = dispense_item() var/hand_result = user.put_in_hands(grabbies) balloon_alert(user, "[hand_result ? "took" : "dispensed"] [item_name]") playsound(src, 'sound/machines/click.ogg', 15, TRUE, -3) @@ -217,7 +215,7 @@ /obj/structure/item_dispenser/latex icon_state = "dispenser_gloves" - stock = /obj/item/clothing/gloves/color/latex + stock = /obj/item/clothing/gloves/latex start_stocked = TRUE /obj/structure/item_dispenser/mask diff --git a/maplestation_modules/code/modules/jobs/job_types/_job.dm b/maplestation_modules/code/modules/jobs/job_types/_job.dm index 3398a83bc3fd..060e67943521 100644 --- a/maplestation_modules/code/modules/jobs/job_types/_job.dm +++ b/maplestation_modules/code/modules/jobs/job_types/_job.dm @@ -9,7 +9,9 @@ // Update crew monitor with new jobs /datum/crewmonitor/New() . = ..() - for(var/datum/job/jobtype as anything in SSjob.joinable_occupations) + for(var/datum/job/jobtype as anything in subtypesof(/datum/job)) + if(!(initial(jobtype.job_flags) & JOB_NEW_PLAYER_JOINABLE)) + continue if(jobtype.crewmonitor_priority < 0) continue jobs[jobtype.title] = jobtype.crewmonitor_priority diff --git a/maplestation_modules/code/modules/jobs/job_types/asset_protection.dm b/maplestation_modules/code/modules/jobs/job_types/asset_protection.dm index 9c780f616022..43aa080aedb1 100644 --- a/maplestation_modules/code/modules/jobs/job_types/asset_protection.dm +++ b/maplestation_modules/code/modules/jobs/job_types/asset_protection.dm @@ -48,7 +48,7 @@ job_flags = STATION_JOB_FLAGS | JOB_BOLD_SELECT_TEXT | JOB_CANNOT_OPEN_SLOTS voice_of_god_power = 1.2 // Not quite command staff. rpg_title = "Royal Guard" - crewmonitor_priority = 9 + crewmonitor_priority = 9 // after cap, right before sec /datum/outfit/job/asset_protection name = "Asset Protection" diff --git a/maplestation_modules/code/modules/jobs/job_types/bridge_officer.dm b/maplestation_modules/code/modules/jobs/job_types/bridge_officer.dm index f65f4144bd40..fd4bcabb10e3 100644 --- a/maplestation_modules/code/modules/jobs/job_types/bridge_officer.dm +++ b/maplestation_modules/code/modules/jobs/job_types/bridge_officer.dm @@ -57,9 +57,9 @@ /obj/item/storage/fancy/cigarettes = 1, ) - job_flags = STATION_JOB_FLAGS | JOB_CANNOT_OPEN_SLOTS + job_flags = STATION_JOB_FLAGS rpg_title = "Guildperson" - crewmonitor_priority = 59 + crewmonitor_priority = 60.1 // after HOP, before rest of service /datum/outfit/job/bridge_officer name = "Bridge Officer" diff --git a/maplestation_modules/code/modules/jobs/job_types/noble_ambassador.dm b/maplestation_modules/code/modules/jobs/job_types/noble_ambassador.dm index d388a16fd3ca..f1969ddaed5c 100644 --- a/maplestation_modules/code/modules/jobs/job_types/noble_ambassador.dm +++ b/maplestation_modules/code/modules/jobs/job_types/noble_ambassador.dm @@ -50,6 +50,8 @@ voice_of_god_power = 1.4 // Captain-level VoG. rpg_title = "Noble" //you already sound like an RPG character + crewmonitor_priority = 8 // after captain, before sec - though NT rep (if added) would be higher (7) + /datum/outfit/job/noble_ambassador name = "Noble Ambassador" jobtype = /datum/job/noble_ambassador diff --git a/maplestation_modules/code/modules/jobs/job_types/ordnance_tech.dm b/maplestation_modules/code/modules/jobs/job_types/ordnance_tech.dm index 7efa18e22a4e..84403a34afd0 100644 --- a/maplestation_modules/code/modules/jobs/job_types/ordnance_tech.dm +++ b/maplestation_modules/code/modules/jobs/job_types/ordnance_tech.dm @@ -44,7 +44,7 @@ job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN rpg_title = "Dwarven Miner" - crewmonitor_priority = 34 + crewmonitor_priority = 35 /datum/outfit/job/scientist/ordnance_tech name = "Ordnance Technician" diff --git a/maplestation_modules/code/modules/jobs/job_types/xenobiologist.dm b/maplestation_modules/code/modules/jobs/job_types/xenobiologist.dm index d137d8338370..a0fbd5e32a8b 100644 --- a/maplestation_modules/code/modules/jobs/job_types/xenobiologist.dm +++ b/maplestation_modules/code/modules/jobs/job_types/xenobiologist.dm @@ -44,7 +44,7 @@ job_flags = JOB_ANNOUNCE_ARRIVAL | JOB_CREW_MANIFEST | JOB_EQUIP_RANK | JOB_CREW_MEMBER | JOB_NEW_PLAYER_JOINABLE | JOB_REOPEN_ON_ROUNDSTART_LOSS | JOB_ASSIGN_QUIRKS | JOB_CAN_BE_INTERN rpg_title = "Beast Tamer" - crewmonitor_priority = 35 + crewmonitor_priority = 34 /datum/outfit/job/scientist/xenobiologist name = "Xenobiologist" diff --git a/maplestation_modules/code/modules/loadouts/loadout_items/loadout_datum_belts.dm b/maplestation_modules/code/modules/loadouts/loadout_items/loadout_datum_belts.dm index d550cecdb71b..f8404c0e14ce 100644 --- a/maplestation_modules/code/modules/loadouts/loadout_items/loadout_datum_belts.dm +++ b/maplestation_modules/code/modules/loadouts/loadout_items/loadout_datum_belts.dm @@ -10,9 +10,29 @@ abstract_type = /datum/loadout_item/belts /datum/loadout_item/belts/insert_path_into_outfit(datum/outfit/outfit, mob/living/carbon/human/equipper, visuals_only = FALSE, job_equipping_step = FALSE) - if(outfit.belt) + if(!outfit.belt) + outfit.belt = item_path + return + // try to move the existing belt to the backpack + var/obj/item/move_belt = outfit.belt + if(outfit.l_hand && outfit.r_hand && initial(move_belt.w_class) <= WEIGHT_CLASS_NORMAL) LAZYADD(outfit.backpack_contents, outfit.belt) - outfit.belt = item_path + outfit.belt = item_path + return + // try to carry the existing belt in a hand + if(!outfit.l_hand) + outfit.l_hand = outfit.belt + outfit.belt = item_path + return + if(!outfit.r_hand) + outfit.r_hand = outfit.belt + outfit.belt = item_path + return + // failed to put it on, put it in the backpack + if(initial(item_path.w_class) <= WEIGHT_CLASS_NORMAL) + LAZYADD(outfit.backpack_contents, item_path) + return + to_chat(equipper, span_notice("Your loadout belt was not equipped to preserve your job's equipment.")) /datum/loadout_item/belts/fanny_pack_black name = "Fannypack (Black)" diff --git a/maplestation_modules/code/modules/research/designs/autolathe_designs.dm b/maplestation_modules/code/modules/research/designs/autolathe_designs.dm index a96941ab0512..fb78d6f82ea3 100644 --- a/maplestation_modules/code/modules/research/designs/autolathe_designs.dm +++ b/maplestation_modules/code/modules/research/designs/autolathe_designs.dm @@ -32,3 +32,15 @@ RND_CATEGORY_WEAPONS + RND_SUBCATEGORY_WEAPONS_AMMO ) departmental_flags = DEPARTMENT_BITFLAG_SECURITY + +/datum/design/ashtray + name = "Ashtray" + id = "ashtray" + build_type = AUTOLATHE | PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/glass = SHEET_MATERIAL_AMOUNT * 0.25) + build_path = /obj/item/ashtray + category = list( + RND_CATEGORY_INITIAL, + RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_KITCHEN, + ) + departmental_flags = DEPARTMENT_BITFLAG_SERVICE diff --git a/maplestation_modules/code/modules/research/techweb/all_nodes.dm b/maplestation_modules/code/modules/research/techweb/all_nodes.dm index a928d19c7120..dc0d3dfe9a81 100644 --- a/maplestation_modules/code/modules/research/techweb/all_nodes.dm +++ b/maplestation_modules/code/modules/research/techweb/all_nodes.dm @@ -13,6 +13,7 @@ /datum/techweb_node/base id_additions = list( + "ashtray", "fax_machine_deluxe", ) diff --git a/maplestation_modules/story_content/prince_equipment/code/clothing.dm b/maplestation_modules/story_content/prince_equipment/code/clothing.dm index 207c310b6e92..6b85cb42d0db 100644 --- a/maplestation_modules/story_content/prince_equipment/code/clothing.dm +++ b/maplestation_modules/story_content/prince_equipment/code/clothing.dm @@ -33,7 +33,7 @@ /datum/armor/medical_boots bio = 95 -/obj/item/clothing/gloves/color/latex/nitrile/special +/obj/item/clothing/gloves/latex/nitrile/special name = "high grade nitriles" desc = "Medical grade gloves made from thicker material. These are more resistant to tearing and cuts." icon = 'maplestation_modules/story_content/prince_equipment/icons/doctor_item.dmi' @@ -84,7 +84,7 @@ . = ..() new /obj/item/clothing/under/rank/medical/chief_medical_officer/special(src) new /obj/item/clothing/shoes/jackboots/medical(src) - new /obj/item/clothing/gloves/color/latex/nitrile/special(src) + new /obj/item/clothing/gloves/latex/nitrile/special(src) new /obj/item/clothing/suit/toggle/labcoat/cmo/special(src) // Belt to the locker