From cb535cdfa694441e9cc688a026cc0c36a2efe70e Mon Sep 17 00:00:00 2001 From: san7890 Date: Mon, 13 Jul 2026 08:57:47 -0600 Subject: [PATCH] Refactor `var/can_be_held` to an element (#96917) ## About The Pull Request We were doing a lot of mental gymnastics in a bunch of other places, so let's change this wonky var to a streamlined element that will rely on the same signals that a lot of stuff was already using/accounting for in its own signal handling pathways, instead of being a weird coverage gap. This patch should also make the whole "checking if someone is attempting to pick a mob up" thing make a lot more sense and use a unified proc instead of spot-checking whatever random things it wants to spot-check. ## Why It's Good For The Game I didn't know this was a thing until I looked at #96873 and it made me sad because literally everything else involving mob drag-and-drop is already signal-based except this weird stinker that relied on proc overrides. Never mind that now, let's use nice traits to avoid typecasting and elements to avoid duplicating code. It should also be much cleaner to add holdability to a mob isntead of having to do `can_be_held = FALSE` as a weird behavior (at least one instance had this non-necessarily). All this really is is just middleware on the extant /mob/living code but still making it in proper lockstep with the other signalling procs. I did port over raptor code faithfully but I'm not 100% sure if it was meant to be like this? Regardless, that's how it is. ## Changelog :cl: refactor: Picking up mobs has been altered a bit, please report any bugs or glitches. /:cl: --- .../signals/signals_mob/signals_mob_main.dm | 3 ++ code/__DEFINES/dcs/signals/signals_storage.dm | 6 +++ code/datums/elements/can_be_held.dm | 50 +++++++++++++++++++ code/datums/elements/strippable.dm | 9 ++-- code/datums/storage/storage.dm | 8 ++- .../food_and_drinks/machinery/microwave.dm | 2 +- .../living/basic/bots/repairbot/repairbot.dm | 2 +- code/modules/mob/living/basic/drone/_drone.dm | 3 +- .../mob/living/basic/farm_animals/bee/_bee.dm | 2 +- .../mob/living/basic/farm_animals/rabbit.dm | 2 +- .../living/basic/lavaland/raptor/_raptor.dm | 18 +++++-- .../basic/lavaland/raptor/raptor_color.dm | 2 +- code/modules/mob/living/basic/pets/cat/cat.dm | 2 +- .../modules/mob/living/basic/pets/dog/_dog.dm | 2 +- code/modules/mob/living/basic/pets/fox.dm | 2 +- code/modules/mob/living/basic/pets/sloth.dm | 2 +- code/modules/mob/living/basic/snails/snail.dm | 8 ++- .../mob/living/basic/space_fauna/ant.dm | 1 - .../living/basic/space_fauna/spider/spider.dm | 2 +- code/modules/mob/living/basic/stoats/stoat.dm | 2 +- .../mob/living/basic/vermin/axolotl.dm | 2 +- .../basic/vermin/cockroach/cockroach.dm | 2 +- code/modules/mob/living/basic/vermin/frog.dm | 2 +- .../modules/mob/living/basic/vermin/lizard.dm | 2 +- .../basic/vermin/mothroach/mothroach.dm | 2 +- code/modules/mob/living/basic/vermin/mouse.dm | 2 +- code/modules/mob/living/living.dm | 19 ++----- code/modules/mob/living/living_defines.dm | 2 - code/modules/pai/pai.dm | 2 +- tgstation.dme | 1 + 30 files changed, 112 insertions(+), 52 deletions(-) create mode 100644 code/datums/elements/can_be_held.dm diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 8158a412cef..81697e545ee 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -188,6 +188,9 @@ ///Called on user, from base of /datum/strippable_item/try_(un)equip() (atom/target, obj/item/equipping?) #define COMSIG_TRY_STRIP "try_strip" #define COMPONENT_CANT_STRIP (1<<0) +///Called when a mob's strip menu is attempting to be opened,from base /datum/element/strippable/proc/mouse_drop_onto (datum/source, atom/over, mob/user) +#define COMSIG_MOB_STRIP_MENU_OPEN "mob_strip_menu_open" + #define COMPONENT_BLOCK_STRIP_MENU_OPEN (1<<0) ///From /datum/component/face_decal/splat/Initialize() #define COMSIG_MOB_HIT_BY_SPLAT "hit_by_splat" ///From /obj/item/gun/proc/check_botched() diff --git a/code/__DEFINES/dcs/signals/signals_storage.dm b/code/__DEFINES/dcs/signals/signals_storage.dm index 98fc7801850..6cd02dbd714 100644 --- a/code/__DEFINES/dcs/signals/signals_storage.dm +++ b/code/__DEFINES/dcs/signals/signals_storage.dm @@ -1,3 +1,8 @@ +/// Sent to the parent before even attempting to dump items, from base of /datum/storage/dump_content_at(): (datum/storage/storage, atom/over, mob/user) +#define COMSIG_STORAGE_DUMP_PRE_TRANSFER "storage_dump_pre_transfer" + /// Return to stop the dump before it even has a chance of starting + #define CANCEL_STORAGE_DUMP (1<<0) + /// Sent when /datum/storage/dump_content_at(): (obj/item/storage_source, mob/user) #define COMSIG_STORAGE_DUMP_CONTENT "storage_dump_contents" /// Return to stop the standard dump behavior. @@ -5,6 +10,7 @@ /// Sent after dumping into some other storage object: (atom/dest_object, mob/user) #define COMSIG_STORAGE_DUMP_POST_TRANSFER "storage_dump_into_storage" + /// Sent before storing an item (obj/item/being_stored, mob/user, force, messages) #define COMSIG_ATOM_PRE_STORED_ITEM "atom_pre_storing_item" /// Return to block the item from being stored. diff --git a/code/datums/elements/can_be_held.dm b/code/datums/elements/can_be_held.dm new file mode 100644 index 00000000000..8c08b54ef48 --- /dev/null +++ b/code/datums/elements/can_be_held.dm @@ -0,0 +1,50 @@ +/datum/element/can_be_held + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + +/datum/element/can_be_held/Attach(datum/source) + . = ..() + + if(!isliving(source)) + return ELEMENT_INCOMPATIBLE + + RegisterSignal(source, COMSIG_MOUSEDROP_ONTO, PROC_REF(on_mousedrop_onto)) + RegisterSignal(source, COMSIG_MOB_STRIP_MENU_OPEN, PROC_REF(on_strip_menu_open)) + RegisterSignal(source, COMSIG_STORAGE_DUMP_PRE_TRANSFER, PROC_REF(on_attempt_storage_dump)) + +/datum/element/can_be_held/Detach(datum/source) + UnregisterSignal(source, list(COMSIG_MOUSEDROP_ONTO, COMSIG_MOB_STRIP_MENU_OPEN, COMSIG_STORAGE_DUMP_PRE_TRANSFER)) + return ..() + +/// Used to determine the "intent" of the action that the user mob is trying to employ on the target. +/datum/element/can_be_held/proc/trying_to_hold_mob(mob/living/user, mob/living/target) + return isliving(user) && user.grab_state == GRAB_AGGRESSIVE && user.pulling == target + +/// Handles the mob being dropped onto the user mob. +/datum/element/can_be_held/proc/on_mousedrop_onto(datum/source, atom/over, mob/user) + SIGNAL_HANDLER + if(!trying_to_hold_mob(user, source)) + return + + INVOKE_ASYNC(source, TYPE_PROC_REF(/mob/living, mob_try_pickup), user) + return COMPONENT_CANCEL_MOUSEDROP_ONTO + +/datum/element/can_be_held/proc/on_strip_menu_open(datum/source, atom/over, mob/user) + SIGNAL_HANDLER + if(!trying_to_hold_mob(user, source)) + return + + INVOKE_ASYNC(source, TYPE_PROC_REF(/mob/living, mob_try_pickup), user) + return COMPONENT_BLOCK_STRIP_MENU_OPEN + + +/datum/element/can_be_held/proc/on_attempt_storage_dump(datum/source, atom/over, mob/user) + SIGNAL_HANDLER + if(!trying_to_hold_mob(user, source)) + return + + INVOKE_ASYNC(source, TYPE_PROC_REF(/mob/living, mob_try_pickup), user) + return CANCEL_STORAGE_DUMP + + + diff --git a/code/datums/elements/strippable.dm b/code/datums/elements/strippable.dm index 47e38079c72..e189ee58650 100644 --- a/code/datums/elements/strippable.dm +++ b/code/datums/elements/strippable.dm @@ -36,6 +36,9 @@ /datum/element/strippable/proc/mouse_drop_onto(datum/source, atom/over, mob/user) SIGNAL_HANDLER + if(SEND_SIGNAL(source, COMSIG_MOB_STRIP_MENU_OPEN, over, user) & COMPONENT_BLOCK_STRIP_MENU_OPEN) + return + if (user == source) return if (over != user) @@ -57,12 +60,6 @@ if (!isnull(should_strip_proc_path) && !call(source, should_strip_proc_path)(user)) return - // Snowflake for mob scooping - if (isliving(source)) - var/mob/living/mob = source - if (mob.can_be_held && (user.grab_state == GRAB_AGGRESSIVE) && (user.pulling == source)) - return - var/datum/strip_menu/strip_menu = LAZYACCESS(strip_menus, source) if (isnull(strip_menu)) diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index c478de045f5..01c4b3980ec 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -795,6 +795,9 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) /datum/storage/proc/on_mousedrop_onto(datum/source, atom/over_object, mob/user) SIGNAL_HANDLER + if(SEND_SIGNAL(parent, COMSIG_STORAGE_DUMP_PRE_TRANSFER, src, over_object, user) & CANCEL_STORAGE_DUMP) + return COMPONENT_CANCEL_MOUSEDROP_ONTO + if(ismecha(user.loc) || user.incapacitated || !user.canUseStorage()) return NONE @@ -816,11 +819,6 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) if(!user.can_perform_action(parent, FORBID_TELEKINESIS_REACH | ALLOW_RESTING)) return NONE - if(isliving(parent) && user.pulling == parent) - var/mob/living/as_living = parent - if(as_living.can_be_held) - return - parent.add_fingerprint(user) INVOKE_ASYNC(src, PROC_REF(open_storage), user) return COMPONENT_CANCEL_MOUSEDROP_ONTO diff --git a/code/modules/food_and_drinks/machinery/microwave.dm b/code/modules/food_and_drinks/machinery/microwave.dm index 0faf3ff4c84..f08922430f0 100644 --- a/code/modules/food_and_drinks/machinery/microwave.dm +++ b/code/modules/food_and_drinks/machinery/microwave.dm @@ -696,7 +696,7 @@ for(var/mob/living/victim in microwave_contents) if(victim.electrocute_act(shock_damage = 100, source = src, siemens_coeff = 1, flags = SHOCK_NOGLOVES)) successful_shock = TRUE - if(victim.stat == DEAD) //This is mostly so humans that can_be_held don't get gibbed from one microwave run alone, but mice become burnt messes + if(victim.stat == DEAD) //This is mostly so humans that have the can_be_held element don't get gibbed from one microwave run alone, but mice become burnt messes victim.gib() muck() if(successful_shock) //We only want to give feedback once, regardless of how many mobs got shocked diff --git a/code/modules/mob/living/basic/bots/repairbot/repairbot.dm b/code/modules/mob/living/basic/bots/repairbot/repairbot.dm index c7f9554102a..4bb584a3de5 100644 --- a/code/modules/mob/living/basic/bots/repairbot/repairbot.dm +++ b/code/modules/mob/living/basic/bots/repairbot/repairbot.dm @@ -9,7 +9,6 @@ layer = BELOW_MOB_LAYER anchored = FALSE health = 35 - can_be_held = TRUE maxHealth = 35 custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT * 7.8, /datum/material/glass = SMALL_MATERIAL_AMOUNT * 2) path_image_color = "#80dae7" @@ -93,6 +92,7 @@ our_screwdriver = new(src) our_rods = new(src, our_rods::max_amount) set_color(toolbox_color) + AddElement(/datum/element/can_be_held) START_PROCESSING(SSobj, src) /mob/living/basic/bot/repairbot/proc/set_color(new_color) diff --git a/code/modules/mob/living/basic/drone/_drone.dm b/code/modules/mob/living/basic/drone/_drone.dm index f7219599d40..36c60b175ab 100644 --- a/code/modules/mob/living/basic/drone/_drone.dm +++ b/code/modules/mob/living/basic/drone/_drone.dm @@ -46,7 +46,6 @@ lighting_cutoff_red = 30 lighting_cutoff_green = 35 lighting_cutoff_blue = 25 - can_be_held = TRUE worn_slot_flags = ITEM_SLOT_HEAD inhand_holder_type = /obj/item/mob_holder/drone /// `TRUE` if we have picked our visual appearance, `FALSE` otherwise (default) @@ -155,6 +154,8 @@ listener.RegisterSignal(src, COMSIG_LIVING_DEATH, TYPE_PROC_REF(/datum/alarm_listener, prevent_alarm_changes)) listener.RegisterSignal(src, COMSIG_LIVING_REVIVE, TYPE_PROC_REF(/datum/alarm_listener, allow_alarm_changes)) + AddElement(/datum/element/can_be_held) + /mob/living/basic/drone/med_hud_set_health() set_hud_image_state(DIAG_HUD, "huddiag[RoundDiagBar(health/maxHealth)]") diff --git a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm index c3a1c5d9139..409035c9683 100644 --- a/code/modules/mob/living/basic/farm_animals/bee/_bee.dm +++ b/code/modules/mob/living/basic/farm_animals/bee/_bee.dm @@ -36,7 +36,6 @@ mob_biotypes = MOB_ORGANIC|MOB_BUG density = FALSE gold_core_spawnable = FRIENDLY_SPAWN - can_be_held = TRUE held_w_class = WEIGHT_CLASS_TINY environment_smash = ENVIRONMENT_SMASH_NONE habitable_atmos = null @@ -71,6 +70,7 @@ AddComponent(/datum/component/obeys_commands, pet_commands) AddElement(/datum/element/swabable, CELL_LINE_TABLE_QUEEN_BEE, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) AddElement(/datum/element/basic_allergenic_attack, allergen = BUGS, allergen_chance = 33, histamine_add = 5) + AddElement(/datum/element/can_be_held) /mob/living/basic/bee/mob_pickup(mob/living/picker) if(flags_1 & HOLOGRAM_1) diff --git a/code/modules/mob/living/basic/farm_animals/rabbit.dm b/code/modules/mob/living/basic/farm_animals/rabbit.dm index 00b97458be9..42c3f083222 100644 --- a/code/modules/mob/living/basic/farm_animals/rabbit.dm +++ b/code/modules/mob/living/basic/farm_animals/rabbit.dm @@ -18,7 +18,6 @@ health = 15 maxHealth = 15 mob_size = MOB_SIZE_SMALL - can_be_held = TRUE density = FALSE gold_core_spawnable = FRIENDLY_SPAWN speak_emote = list("sniffles", "twitches") @@ -55,6 +54,7 @@ AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/pet_bonus, "hop") AddElement(/datum/element/animal_variety, icon_prefix, pick("brown", "black", "white"), TRUE) + AddElement(/datum/element/can_be_held) if(prob(20)) // bunny name = "bunny" diff --git a/code/modules/mob/living/basic/lavaland/raptor/_raptor.dm b/code/modules/mob/living/basic/lavaland/raptor/_raptor.dm index bad3e251182..6d14322145e 100644 --- a/code/modules/mob/living/basic/lavaland/raptor/_raptor.dm +++ b/code/modules/mob/living/basic/lavaland/raptor/_raptor.dm @@ -78,6 +78,8 @@ GLOBAL_LIST_EMPTY(raptor_population) var/datum/raptor_inheritance/inherited_stats = null /// Current happiness value of the raptor var/happiness_percentage = 0 + /// The ability for this raptor to be picked up and held. Defaults to FALSE as it's meant to be in lockstep with the element being added/removed. + var/could_be_held = FALSE /mob/living/basic/raptor/Initialize(mapload, datum/raptor_color/color_type, datum/raptor_inheritance/passed_stats) . = ..() @@ -283,6 +285,16 @@ GLOBAL_LIST_EMPTY(raptor_population) return pick_weight(prob_list) +/// Updates the presence of the can_be_held element based on what we want from the raptor +/mob/living/basic/raptor/proc/update_holdability(bool) + if(bool && !could_be_held) + AddElement(/datum/element/can_be_held) + could_be_held = TRUE + + if(!bool && could_be_held) + RemoveElement(/datum/element/can_be_held) + could_be_held = FALSE + /mob/living/basic/raptor/proc/on_picked_up(mob/living/basic/raptor/source, mob/living/user, obj/item/mob_holder/holder) SIGNAL_HANDLER // Our inventory code sucks so we have to do this @@ -364,16 +376,16 @@ GLOBAL_LIST_EMPTY(raptor_population) base_pixel_w = initial(base_pixel_w) mob_size = initial(mob_size) - can_be_held = initial(can_be_held) density = initial(density) move_resist = initial(move_resist) can_breed = initial(can_breed) + update_holdability(initial(could_be_held)) if (new_stage == RAPTOR_ADULT) // Adults need to be tamed with skill rather than snacks qdel(GetComponent(/datum/component/tameable)) else // Make us teeny-tiny - can_be_held = TRUE + update_holdability(TRUE) density = FALSE can_breed = FALSE move_resist = MOVE_RESIST_DEFAULT @@ -389,7 +401,7 @@ GLOBAL_LIST_EMPTY(raptor_population) var/obj/item/mob_holder/holder = null if (istype(loc, /obj/item/mob_holder)) holder = loc - if (!can_be_held) + if (!could_be_held) holder.release() holder = null diff --git a/code/modules/mob/living/basic/lavaland/raptor/raptor_color.dm b/code/modules/mob/living/basic/lavaland/raptor/raptor_color.dm index 8467589837f..25129736487 100644 --- a/code/modules/mob/living/basic/lavaland/raptor/raptor_color.dm +++ b/code/modules/mob/living/basic/lavaland/raptor/raptor_color.dm @@ -128,7 +128,7 @@ GLOBAL_LIST_INIT(raptor_colors, init_raptor_colors()) // Purple raptors never "fully" grow up, and remain usable as backpacks /datum/raptor_color/purple/setup_adult(mob/living/basic/raptor/raptor) - raptor.can_be_held = TRUE + raptor.update_holdability(TRUE) raptor.density = FALSE raptor.move_resist = MOVE_RESIST_DEFAULT raptor.held_w_class = WEIGHT_CLASS_BULKY diff --git a/code/modules/mob/living/basic/pets/cat/cat.dm b/code/modules/mob/living/basic/pets/cat/cat.dm index 30d36663698..abf7932978d 100644 --- a/code/modules/mob/living/basic/pets/cat/cat.dm +++ b/code/modules/mob/living/basic/pets/cat/cat.dm @@ -24,7 +24,6 @@ response_harm_simple = "kick" mobility_flags = MOBILITY_FLAGS_REST_CAPABLE_DEFAULT gold_core_spawnable = FRIENDLY_SPAWN - can_be_held = TRUE ai_controller = /datum/ai_controller/basic_controller/cat held_state = "cat2" attack_verb_continuous = "claws" @@ -91,6 +90,7 @@ AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/pet_bonus, "purr", /datum/mood_event/pet_animal) AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW) + AddElement(/datum/element/can_be_held) add_cell_sample() add_verb(src, /mob/living/proc/toggle_resting) add_traits(list(TRAIT_CATLIKE_GRACE, TRAIT_VENTCRAWLER_ALWAYS, TRAIT_WOUND_LICKER, TRAIT_COLORBLIND), INNATE_TRAIT) diff --git a/code/modules/mob/living/basic/pets/dog/_dog.dm b/code/modules/mob/living/basic/pets/dog/_dog.dm index 21f07026140..cd98fcf1f0a 100644 --- a/code/modules/mob/living/basic/pets/dog/_dog.dm +++ b/code/modules/mob/living/basic/pets/dog/_dog.dm @@ -27,7 +27,6 @@ response_harm_simple = "kick" speak_emote = list("barks", "woofs") faction = list(FACTION_NEUTRAL) - can_be_held = TRUE ai_controller = /datum/ai_controller/basic_controller/dog // The dog attack pet command can raise melee attack above 0 attack_verb_continuous = "bites" @@ -74,6 +73,7 @@ AddElement(/datum/element/pet_bonus, "woof") AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW) AddElement(/datum/element/unfriend_attacker, untamed_reaction = "%SOURCE% fixes %TARGET% with a look of betrayal.") + AddElement(/datum/element/can_be_held) var/static/list/food_types = list( /obj/item/food/meat/slab/human/mutant/skeleton, /obj/item/stack/sheet/bone, diff --git a/code/modules/mob/living/basic/pets/fox.dm b/code/modules/mob/living/basic/pets/fox.dm index 16b3b666217..e986d74259b 100644 --- a/code/modules/mob/living/basic/pets/fox.dm +++ b/code/modules/mob/living/basic/pets/fox.dm @@ -19,7 +19,6 @@ response_harm_continuous = "kicks" response_harm_simple = "kick" gold_core_spawnable = FRIENDLY_SPAWN - can_be_held = TRUE held_state = "fox" melee_damage_lower = 5 melee_damage_upper = 5 @@ -58,6 +57,7 @@ AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW) AddElement(/datum/element/tiny_mob_hunter, MOB_SIZE_SMALL) AddElement(/datum/element/ai_retaliate) + AddElement(/datum/element/can_be_held) /datum/ai_controller/basic_controller/fox blackboard = list( diff --git a/code/modules/mob/living/basic/pets/sloth.dm b/code/modules/mob/living/basic/pets/sloth.dm index a6d6b4f6a47..fd2d3f2827c 100644 --- a/code/modules/mob/living/basic/pets/sloth.dm +++ b/code/modules/mob/living/basic/pets/sloth.dm @@ -10,7 +10,6 @@ GLOBAL_DATUM(cargo_sloth, /mob/living/basic/sloth) speak_emote = list("yawns") - can_be_held = TRUE held_state = "sloth" response_help_continuous = "pets" @@ -53,6 +52,7 @@ GLOBAL_DATUM(cargo_sloth, /mob/living/basic/sloth) AddElement(/datum/element/pet_bonus, "ssmile") AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW) AddElement(/datum/element/ai_retaliate) + AddElement(/datum/element/can_be_held) AddComponent(/datum/component/tree_climber) if(!mapload || !isnull(GLOB.cargo_sloth) || !is_station_level(z)) diff --git a/code/modules/mob/living/basic/snails/snail.dm b/code/modules/mob/living/basic/snails/snail.dm index 5c8ea912ee4..e972f9937c2 100644 --- a/code/modules/mob/living/basic/snails/snail.dm +++ b/code/modules/mob/living/basic/snails/snail.dm @@ -19,7 +19,6 @@ speed = 6 verb_say = "gurgles" verb_ask = "gurgles curiously" - can_be_held = TRUE verb_exclaim = "gurgles loudly" verb_yell = "gurgles loudly" worn_slot_flags = ITEM_SLOT_HEAD @@ -28,6 +27,8 @@ ai_controller = /datum/ai_controller/basic_controller/snail /// What do we turn into if effected by a regal rat? var/minion_path = /mob/living/basic/snail/angry + /// Are we able to be held by a player? + var/should_be_holdable = TRUE /mob/living/basic/snail/Initialize(mapload) . = ..() @@ -53,6 +54,9 @@ if (minion_path) AddElement(/datum/element/regal_rat_minion, converted_path = minion_path, success_balloon = "gurgle", pet_commands = GLOB.regal_rat_minion_commands) + if(should_be_holdable) + AddElement(/datum/element/can_be_held) + /mob/living/basic/snail/proc/on_entered(datum/source, obj/effect/decal/cleanable/food/salt/potential_salt) SIGNAL_HANDLER if(istype(potential_salt)) @@ -105,7 +109,7 @@ melee_damage_lower = 5 melee_damage_upper = 8 obj_damage = 8 - can_be_held = FALSE + should_be_holdable = FALSE minion_path = null ai_controller = /datum/ai_controller/basic_controller/snail/trash diff --git a/code/modules/mob/living/basic/space_fauna/ant.dm b/code/modules/mob/living/basic/space_fauna/ant.dm index 5dc63c95d5a..97633a70580 100644 --- a/code/modules/mob/living/basic/space_fauna/ant.dm +++ b/code/modules/mob/living/basic/space_fauna/ant.dm @@ -26,7 +26,6 @@ response_harm_simple = "kick" gold_core_spawnable = FRIENDLY_SPAWN faction = list(FACTION_NEUTRAL) - can_be_held = FALSE health = 100 maxHealth = 100 light_range = 1.5 // Bioluminescence! diff --git a/code/modules/mob/living/basic/space_fauna/spider/spider.dm b/code/modules/mob/living/basic/space_fauna/spider/spider.dm index ce246e1e0e3..cde120b1c4c 100644 --- a/code/modules/mob/living/basic/space_fauna/spider/spider.dm +++ b/code/modules/mob/living/basic/space_fauna/spider/spider.dm @@ -200,7 +200,6 @@ icon_state = "maint_spider" icon_living = "maint_spider" icon_dead = "maint_spider_dead" - can_be_held = TRUE mob_size = MOB_SIZE_TINY held_w_class = WEIGHT_CLASS_TINY worn_slot_flags = ITEM_SLOT_HEAD @@ -234,3 +233,4 @@ AddElement(/datum/element/ai_retaliate) AddComponent(/datum/component/obeys_commands, pet_commands) AddElement(/datum/element/tiny_mob_hunter) + AddElement(/datum/element/can_be_held) diff --git a/code/modules/mob/living/basic/stoats/stoat.dm b/code/modules/mob/living/basic/stoats/stoat.dm index 0f5cfc82dd6..d9730e4c4f5 100644 --- a/code/modules/mob/living/basic/stoats/stoat.dm +++ b/code/modules/mob/living/basic/stoats/stoat.dm @@ -19,7 +19,6 @@ response_help_simple = "pet" verb_say = "chips" verb_ask = "chips curiously" - can_be_held = TRUE verb_exclaim = "chips loudly" verb_yell = "chips loudly" faction = list(FACTION_NEUTRAL) @@ -47,6 +46,7 @@ AddComponent(/datum/component/tameable, food_types = eatable_food, tame_chance = 70, bonus_tame_chance = 0) ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(eatable_food)) AddElement(/datum/element/wears_collar) + AddElement(/datum/element/can_be_held) AddComponent(/datum/component/obeys_commands, pet_commands) if(can_breed) add_breeding_component() diff --git a/code/modules/mob/living/basic/vermin/axolotl.dm b/code/modules/mob/living/basic/vermin/axolotl.dm index 278fc0eac69..730b22fb16d 100644 --- a/code/modules/mob/living/basic/vermin/axolotl.dm +++ b/code/modules/mob/living/basic/vermin/axolotl.dm @@ -22,7 +22,6 @@ response_harm_continuous = "splats" response_harm_simple = "splat" - can_be_held = TRUE held_w_class = WEIGHT_CLASS_TINY held_lh = 'icons/mob/inhands/animal_item_lefthand.dmi' held_rh = 'icons/mob/inhands/animal_item_righthand.dmi' @@ -35,6 +34,7 @@ . = ..() add_traits(list(TRAIT_NODROWN, TRAIT_SWIMMER, TRAIT_VENTCRAWLER_ALWAYS), INNATE_TRAIT) AddElement(/datum/element/swabable, CELL_LINE_TABLE_AXOLOTL, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) + AddElement(/datum/element/can_be_held) /datum/ai_controller/basic_controller/axolotl ai_traits = PASSIVE_AI_FLAGS diff --git a/code/modules/mob/living/basic/vermin/cockroach/cockroach.dm b/code/modules/mob/living/basic/vermin/cockroach/cockroach.dm index 76dee59ce35..393a612f1b1 100644 --- a/code/modules/mob/living/basic/vermin/cockroach/cockroach.dm +++ b/code/modules/mob/living/basic/vermin/cockroach/cockroach.dm @@ -10,7 +10,6 @@ health = 1 maxHealth = 1 speed = 1.25 - can_be_held = TRUE gold_core_spawnable = FRIENDLY_SPAWN pass_flags = PASSTABLE | PASSGRILLE | PASSMOB @@ -50,6 +49,7 @@ . = ..() AddElement(/datum/element/death_drops, /obj/effect/decal/cleanable/insectguts) AddElement(/datum/element/swabable, cockroach_cell_line, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 7) + AddElement(/datum/element/can_be_held) AddComponent( \ /datum/component/squashable, \ squash_chance = 50, \ diff --git a/code/modules/mob/living/basic/vermin/frog.dm b/code/modules/mob/living/basic/vermin/frog.dm index 0e4b7f2adc2..d7dbe3848f8 100644 --- a/code/modules/mob/living/basic/vermin/frog.dm +++ b/code/modules/mob/living/basic/vermin/frog.dm @@ -31,7 +31,6 @@ pass_flags = PASSTABLE | PASSGRILLE | PASSMOB mob_size = MOB_SIZE_TINY gold_core_spawnable = FRIENDLY_SPAWN - can_be_held = TRUE held_w_class = WEIGHT_CLASS_TINY worn_slot_flags = ITEM_SLOT_HEAD head_icon = 'icons/mob/clothing/head/pets_head.dmi' @@ -60,6 +59,7 @@ AddElement(/datum/element/venomous, poison_type, poison_per_bite) AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/swabable, CELL_LINE_TABLE_FROG, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5) + AddElement(/datum/element/can_be_held) if (minion_type) AddElement(/datum/element/regal_rat_minion, converted_path = minion_type, success_balloon = "ribbit", pet_commands = GLOB.regal_rat_minion_commands) diff --git a/code/modules/mob/living/basic/vermin/lizard.dm b/code/modules/mob/living/basic/vermin/lizard.dm index 3c585269901..a61b1604c54 100644 --- a/code/modules/mob/living/basic/vermin/lizard.dm +++ b/code/modules/mob/living/basic/vermin/lizard.dm @@ -32,7 +32,6 @@ gold_core_spawnable = FRIENDLY_SPAWN obj_damage = 0 environment_smash = ENVIRONMENT_SMASH_NONE - can_be_held = TRUE held_w_class = WEIGHT_CLASS_TINY held_lh = 'icons/mob/inhands/animal_item_lefthand.dmi' held_rh = 'icons/mob/inhands/animal_item_righthand.dmi' @@ -60,6 +59,7 @@ . = ..() ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT) AddElement(/datum/element/pet_bonus, "tongue") + AddElement(/datum/element/can_be_held) AddElement(/datum/element/basic_eating, heal_amt = 5, food_types = edibles) ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(edibles)) diff --git a/code/modules/mob/living/basic/vermin/mothroach/mothroach.dm b/code/modules/mob/living/basic/vermin/mothroach/mothroach.dm index 94acd65a3da..1e70c723a74 100644 --- a/code/modules/mob/living/basic/vermin/mothroach/mothroach.dm +++ b/code/modules/mob/living/basic/vermin/mothroach/mothroach.dm @@ -16,7 +16,6 @@ maxHealth = 25 speed = 1.25 gold_core_spawnable = FRIENDLY_SPAWN - can_be_held = TRUE worn_slot_flags = ITEM_SLOT_HEAD verb_say = "flutters" @@ -60,6 +59,7 @@ ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(food_types)) AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/pet_bonus, "squeak") + AddElement(/datum/element/can_be_held) add_verb(src, /mob/living/proc/toggle_resting) ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT) diff --git a/code/modules/mob/living/basic/vermin/mouse.dm b/code/modules/mob/living/basic/vermin/mouse.dm index b102fc8cf6c..3e92f78c8af 100644 --- a/code/modules/mob/living/basic/vermin/mouse.dm +++ b/code/modules/mob/living/basic/vermin/mouse.dm @@ -11,7 +11,6 @@ density = FALSE pass_flags = PASSTABLE|PASSGRILLE|PASSMOB mob_size = MOB_SIZE_TINY - can_be_held = TRUE held_w_class = WEIGHT_CLASS_TINY mob_biotypes = MOB_ORGANIC|MOB_BEAST gold_core_spawnable = FRIENDLY_SPAWN @@ -78,6 +77,7 @@ AddElement(/datum/element/connect_loc, loc_connections) make_tameable() AddComponent(/datum/component/swarming, 16, 16) //max_x, max_y + AddElement(/datum/element/can_be_held) /mob/living/basic/mouse/proc/make_tameable() if (HAS_TRAIT(src, TRAIT_TAMED)) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index eaf193e7b06..2d0a31982fc 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1984,14 +1984,11 @@ GLOBAL_LIST_EMPTY(fire_appearances) ..() update_z(new_turf?.z) -/mob/living/mouse_drop_receive(atom/dropping, atom/user, params) - var/mob/living/U = user - if(isliving(dropping)) - var/mob/living/M = dropping - if(M.can_be_held && U.pulling == M) - M.mob_try_pickup(U)//blame kevinz - return//dont open the mobs inventory if you are picking them up - return ..() +/mob/living/proc/set_name() + if(identifier == 0) + identifier = rand(1, 999) + name = "[name] ([identifier])" + real_name = name /mob/living/proc/mob_pickup(mob/living/user) var/obj/item/mob_holder/holder = new inhand_holder_type(get_turf(src), src, held_state, head_icon, held_lh, held_rh, worn_slot_flags) @@ -1999,12 +1996,6 @@ GLOBAL_LIST_EMPTY(fire_appearances) user.visible_message(span_warning("[user] scoops up [src]!")) user.put_in_hands(holder) -/mob/living/proc/set_name() - if(identifier == 0) - identifier = rand(1, 999) - name = "[name] ([identifier])" - real_name = name - /mob/living/proc/mob_try_pickup(mob/living/user, instant=FALSE) if(!ishuman(user) && (user.mob_size <= mob_size || user.num_hands == 0)) if (!user.num_hands) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index cc3aad0c129..f5e93fd5aa6 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -178,8 +178,6 @@ ///used for database logging var/last_words - ///whether this can be picked up and held. - var/can_be_held = FALSE /// The w_class of the holder when held. var/held_w_class = WEIGHT_CLASS_NORMAL ///if it can be held, can it be equipped to any slots? (think pAI's on head) diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm index 37c9e943deb..b5b1099aabe 100644 --- a/code/modules/pai/pai.dm +++ b/code/modules/pai/pai.dm @@ -1,5 +1,4 @@ /mob/living/silicon/pai - can_be_held = TRUE can_buckle_to = FALSE density = FALSE desc = "A generic pAI hard-light holographics emitter." @@ -203,6 +202,7 @@ /mob/living/silicon/pai/Initialize(mapload) . = ..() AddComponent(/datum/component/holographic_nature) + AddElement(/datum/element/can_be_held) if(istype(loc, /obj/item/modular_computer)) give_messenger_ability() START_PROCESSING(SSfastprocess, src) diff --git a/tgstation.dme b/tgstation.dme index 45c88b7d8b1..216aa39171b 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1576,6 +1576,7 @@ #include "code\datums\elements\bump_click.dm" #include "code\datums\elements\burn_when_item_ignition.dm" #include "code\datums\elements\can_barricade.dm" +#include "code\datums\elements\can_be_held.dm" #include "code\datums\elements\can_shatter.dm" #include "code\datums\elements\caseless.dm" #include "code\datums\elements\chain_lightning_attack.dm"