From f318dbe1b281c6fc6f37f40c51ebbb42c158400c Mon Sep 17 00:00:00 2001
From: kevinz000 <2003111+kevinz000@users.noreply.github.com>
Date: Thu, 6 Feb 2020 00:41:28 -0700
Subject: [PATCH] Merge pull request #10881 from Ghommie/Ghommie-cit552
---
code/__DEFINES/components.dm | 4 -
code/__DEFINES/dcs/signals.dm | 99 +++--
code/_onclick/click.dm | 5 +-
code/datums/elements/mob_holder.dm | 184 +++++++++
code/datums/elements/wuv.dm | 4 +
code/modules/mob/living/carbon/examine.dm | 6 +-
.../mob/living/carbon/human/examine.dm | 1 +
code/modules/mob/living/carbon/human/human.dm | 3 +-
.../mob/living/carbon/monkey/monkey.dm | 351 +++++++++---------
code/modules/mob/living/inhand_holder.dm | 129 -------
code/modules/mob/living/living.dm | 10 -
code/modules/mob/living/living_defines.dm | 2 +-
code/modules/mob/living/silicon/pai/pai.dm | 10 +-
.../mob/living/silicon/pai/pai_shell.dm | 19 +-
.../mob/living/simple_animal/friendly/cat.dm | 9 +-
.../mob/living/simple_animal/friendly/dog.dm | 23 +-
.../simple_animal/friendly/drone/_drone.dm | 12 +-
.../friendly/drone/interaction.dm | 6 -
.../mob/living/simple_animal/friendly/fox.dm | 5 +-
.../living/simple_animal/friendly/lizard.dm | 9 +-
.../living/simple_animal/friendly/mouse.dm | 12 +-
.../living/simple_animal/friendly/sloth.dm | 4 +-
code/modules/mob/mob.dm | 6 +-
hyperstation/code/modules/resize/resizing.dm | 4 +-
tgstation.dme | 4 +-
25 files changed, 469 insertions(+), 452 deletions(-)
create mode 100644 code/datums/elements/mob_holder.dm
delete mode 100644 code/modules/mob/living/inhand_holder.dm
diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index bab1e65d..c16c95e0 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -31,16 +31,12 @@
#define COMSIG_ATOM_RATVAR_ACT "atom_ratvar_act" //from base of atom/ratvar_act(): ()
/////////////////
-
-
// /area signals
// /turf signals
// /atom/movable signals
-// /mob signals
-
// /mob/living signals
// /mob/living/carbon signals
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index fbee222f..4036bab9 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -180,21 +180,17 @@
///from base of area/Exited(): (/area)
#define COMSIG_EXIT_AREA "exit_area"
///from base of atom/Click(): (location, control, params, mob/user)
-#define COMSIG_CLICK "atom_click"
-///from base of atom/ShiftClick(): (/mob)
-#define COMSIG_CLICK_SHIFT "shift_click"
- #define COMPONENT_ALLOW_EXAMINATE (1<<0) //Allows the user to examinate regardless of client.eye.
-///from base of atom/CtrlClickOn(): (/mob)
-#define COMSIG_CLICK_CTRL "ctrl_click"
-///from base of atom/AltClick(): (/mob)
-#define COMSIG_CLICK_ALT "alt_click"
-///from base of atom/CtrlShiftClick(/mob)
-#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click"
-///from base of atom/MouseDrop(): (/atom/over, /mob/user)
-#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto"
- #define COMPONENT_NO_MOUSEDROP (1<<0)
-///from base of atom/MouseDrop_T: (/atom/from, /mob/user)
-#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto"
+#define COMSIG_CLICK "atom_click" //from base of atom/Click(): (location, control, params, mob/user)
+#define COMSIG_CLICK_SHIFT "shift_click" //from base of atom/ShiftClick(): (/mob)
+ #define COMPONENT_ALLOW_EXAMINATE 1
+ #define COMPONENT_DENY_EXAMINATE 2 //Higher priority compared to the above one
+
+#define COMSIG_CLICK_CTRL "ctrl_click" //from base of atom/CtrlClickOn(): (/mob)
+#define COMSIG_CLICK_ALT "alt_click" //from base of atom/AltClick(): (/mob)
+#define COMSIG_CLICK_CTRL_SHIFT "ctrl_shift_click" //from base of atom/CtrlShiftClick(/mob)
+#define COMSIG_MOUSEDROP_ONTO "mousedrop_onto" //from base of atom/MouseDrop(): (/atom/over, /mob/user)
+ #define COMPONENT_NO_MOUSEDROP 1
+#define COMSIG_MOUSEDROPPED_ONTO "mousedropped_onto"
// /area signals
@@ -264,13 +260,42 @@
#define COMSIG_MOVABLE_TELEPORTED "movable_teleported" //from base of do_teleport(): (channel, turf/origin, turf/destination)
// /mob signals
+// /mob signals
+#define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A)
+#define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed)
+ #define COMPONENT_BLOCK_DEATH_BROADCAST 1 //stops the death from being broadcasted in deadchat.
+#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize(): (can_reenter_corpse, special, penalize)
+ #define COMPONENT_BLOCK_GHOSTING 1
+#define COMSIG_MOB_ALLOWED "mob_allowed" //from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
+#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic" //from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
+ #define COMPONENT_BLOCK_MAGIC 1
+#define COMSIG_MOB_HUD_CREATED "mob_hud_created" //from base of mob/create_mob_hud(): ()
+#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand" //from base of
+#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack" //from base of /obj/item/attack(): (mob/M, mob/user)
+ #define COMPONENT_ITEM_NO_ATTACK 1
+#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack" //from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
+#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged" //from base of mob/RangedAttack(): (atom/A, params)
+#define COMSIG_MOB_THROW "mob_throw" //from base of /mob/throw_item(): (atom/target)
+#define COMSIG_MOB_KEY_CHANGE "mob_key_change" //from base of /mob/transfer_ckey(): (new_character, old_character)
+#define COMSIG_MOB_PRE_PLAYER_CHANGE "mob_pre_player_change" //sent to the target mob from base of /mob/transfer_ckey() and /mind/transfer_to(): (our_character, their_character)
+// #define COMPONENT_STOP_MIND_TRANSFER 1
+#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight" //from base of /mob/update_sight(): ()
+#define COMSIG_MOB_ON_NEW_MIND "mob_on_new_mind" //called when a new mind is assigned to a mob: ()
+#define COMSIG_MOB_SAY "mob_say" // from /mob/living/say(): (proc args list)
+ #define COMPONENT_UPPERCASE_SPEECH 1
+ // used to access COMSIG_MOB_SAY argslist
+ #define SPEECH_MESSAGE 1
+ // #define SPEECH_BUBBLE_TYPE 2
+ #define SPEECH_SPANS 3
+ /* #define SPEECH_SANITIZE 4
+ #define SPEECH_LANGUAGE 5
+ #define SPEECH_IGNORE_SPAM 6
+ #define SPEECH_FORCED 7 */
///from base of /mob/Login(): ()
#define COMSIG_MOB_LOGIN "mob_login"
///from base of /mob/Logout(): ()
#define COMSIG_MOB_LOGOUT "mob_logout"
-///from base of mob/death(): (gibbed)
-#define COMSIG_MOB_DEATH "mob_death"
///from base of mob/set_stat(): (new_stat)
#define COMSIG_MOB_STATCHANGE "mob_statchange"
///from base of mob/clickon(): (atom/A, params)
@@ -280,50 +305,12 @@
///from base of mob/AltClickOn(): (atom/A)
#define COMSIG_MOB_ALTCLICKON "mob_altclickon"
#define COMSIG_MOB_CANCEL_CLICKON (1<<0)
-
-///from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
-#define COMSIG_MOB_ALLOWED "mob_allowed"
-///from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
-#define COMSIG_MOB_RECEIVE_MAGIC "mob_receive_magic"
- #define COMPONENT_BLOCK_MAGIC (1<<0)
-///from base of mob/create_mob_hud(): ()
-#define COMSIG_MOB_HUD_CREATED "mob_hud_created"
-///from base of atom/attack_hand(): (mob/user)
-#define COMSIG_MOB_ATTACK_HAND "mob_attack_hand"
-///from base of /obj/item/attack(): (mob/M, mob/user)
-#define COMSIG_MOB_ITEM_ATTACK "mob_item_attack"
- #define COMPONENT_ITEM_NO_ATTACK (1<<0)
///from base of /mob/living/proc/apply_damage(): (damage, damagetype, def_zone)
#define COMSIG_MOB_APPLY_DAMGE "mob_apply_damage"
-///from base of obj/item/afterattack(): (atom/target, mob/user, proximity_flag, click_parameters)
-#define COMSIG_MOB_ITEM_AFTERATTACK "mob_item_afterattack"
///from base of obj/item/attack_qdeleted(): (atom/target, mob/user, proxiumity_flag, click_parameters)
-#define COMSIG_MOB_ITEM_ATTACK_QDELETED "mob_item_attack_qdeleted"
-///from base of mob/RangedAttack(): (atom/A, params)
-#define COMSIG_MOB_ATTACK_RANGED "mob_attack_ranged"
-///from base of /mob/throw_item(): (atom/target)
-#define COMSIG_MOB_THROW "mob_throw"
-#define COMSIG_MOB_KEY_CHANGE "mob_key_change" //from base of /mob/transfer_ckey(): (new_character, old_character)
-#define COMSIG_MOB_PRE_PLAYER_CHANGE "mob_pre_player_change" //sent to the target mob from base of /mob/transfer_ckey() and /mind/transfer_to(): (our_character, their_character)
-#define COMSIG_MOB_GHOSTIZE "mob_ghostize" //from base of mob/Ghostize(): (can_reenter_corpse, special, penalize)
- #define COMPONENT_BLOCK_GHOSTING (1<<0)
+#define COMSIG_MOB_ITEM_ATTACK_QDELETED "mob_item_attack_qdeleted" //from base of /mob/transfer_ckey(): (new_character, old_character)
#define COMPONENT_DO_NOT_PENALIZE_GHOSTING (1<<1)
#define COMPONENT_FREE_GHOSTING (1<<2)
-///from base of /mob/verb/examinate(): (atom/target)
-#define COMSIG_MOB_EXAMINATE "mob_examinate"
-///from base of /mob/update_sight(): ()
-#define COMSIG_MOB_UPDATE_SIGHT "mob_update_sight"
-////from /mob/living/say(): ()
-#define COMSIG_MOB_SAY "mob_say"
- #define COMPONENT_UPPERCASE_SPEECH (1<<0)
- // used to access COMSIG_MOB_SAY argslist
- #define SPEECH_MESSAGE 1
- // #define SPEECH_BUBBLE_TYPE 2
- #define SPEECH_SPANS 3
- /* #define SPEECH_SANITIZE 4
- #define SPEECH_LANGUAGE 5
- #define SPEECH_IGNORE_SPAM 6
- #define SPEECH_FORCED 7 */
///from /mob/say_dead(): (mob/speaker, message)
#define COMSIG_MOB_DEADSAY "mob_deadsay"
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index e59aafda..8b5a754d 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -315,9 +315,10 @@
/mob/proc/ShiftClickOn(atom/A)
A.ShiftClick(src)
return
+
/atom/proc/ShiftClick(mob/user)
- SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user)
- if(user.client && user.client.eye == user || user.client.eye == user.loc)
+ var/flags = SEND_SIGNAL(src, COMSIG_CLICK_SHIFT, user)
+ if(!(flags & COMPONENT_DENY_EXAMINATE) && user.client && (user.client.eye == user || user.client.eye == user.loc || flags & COMPONENT_ALLOW_EXAMINATE))
user.examinate(src)
return
diff --git a/code/datums/elements/mob_holder.dm b/code/datums/elements/mob_holder.dm
new file mode 100644
index 00000000..a63be406
--- /dev/null
+++ b/code/datums/elements/mob_holder.dm
@@ -0,0 +1,184 @@
+/datum/element/mob_holder
+ element_flags = ELEMENT_BESPOKE
+ id_arg_index = 2
+ var/worn_state
+ var/alt_worn
+ var/right_hand
+ var/left_hand
+ var/inv_slots
+ var/proctype //if present, will be invoked on headwear generation.
+
+/datum/element/mob_holder/Attach(datum/target, _worn_state, _alt_worn, _right_hand, _left_hand, _inv_slots = NONE, _proctype)
+ . = ..()
+
+ if(!isliving(target))
+ return ELEMENT_INCOMPATIBLE
+
+ worn_state = _worn_state
+ alt_worn = _alt_worn
+ right_hand = _right_hand
+ left_hand = _left_hand
+ inv_slots = _inv_slots
+ proctype = _proctype
+
+ RegisterSignal(target, COMSIG_CLICK_ALT, .proc/mob_try_pickup)
+ RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_examine)
+
+/datum/element/mob_holder/Detach(datum/source, force)
+ . = ..()
+ UnregisterSignal(source, COMSIG_CLICK_ALT)
+ UnregisterSignal(source, COMSIG_PARENT_EXAMINE)
+
+/datum/element/mob_holder/proc/on_examine(mob/living/source, mob/user, list/examine_list)
+ if(ishuman(user) && !istype(source.loc, /obj/item/clothing/head/mob_holder))
+ examine_list += "Looks like [source.p_they(TRUE)] can be picked up with Alt+Click!"
+
+/datum/element/mob_holder/proc/mob_try_pickup(mob/living/source, mob/user)
+ if(!ishuman(user) || !user.Adjacent(source) || user.incapacitated())
+ return FALSE
+ if(user.get_active_held_item())
+ to_chat(user, "Your hands are full!")
+ return FALSE
+ if(source.buckled)
+ to_chat(user, "[src] is buckled to something!")
+ return FALSE
+ if(source == user)
+ to_chat(user, "You can't pick yourself up.")
+ return FALSE
+ source.visible_message("[user] starts picking up [source].", \
+ "[user] starts picking you up!")
+ if(!do_after(user, 20, target = source) || source.buckled)
+ return FALSE
+
+ source.visible_message("[user] picks up [source]!", \
+ "[user] picks you up!")
+ to_chat(user, "You pick [src] up.")
+ source.drop_all_held_items()
+ var/obj/item/clothing/head/mob_holder/holder = new(get_turf(source), source, worn_state, alt_worn, right_hand, left_hand, inv_slots)
+ if(proctype)
+ INVOKE_ASYNC(src, proctype, source, holder, user)
+ user.put_in_hands(holder)
+ return TRUE
+
+/datum/element/mob_holder/proc/drone_worn_icon(mob/living/simple_animal/drone/D, obj/item/clothing/head/mob_holder/holder, mob/user)
+ var/new_state = "[D.visualAppearence]_hat"
+ holder.item_state = new_state
+ holder.icon_state = new_state
+
+
+//The item itself,
+/obj/item/clothing/head/mob_holder
+ name = "bugged mob"
+ desc = "Yell at coderbrush."
+ icon = null
+ alternate_worn_icon = 'icons/mob/animals_held.dmi'
+ righthand_file = 'icons/mob/animals_held_rh.dmi'
+ lefthand_file = 'icons/mob/animals_held_lh.dmi'
+ icon_state = ""
+ w_class = WEIGHT_CLASS_BULKY
+ var/mob/living/held_mob
+
+/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/target, worn_state, alt_worn, right_hand, left_hand, slots = NONE)
+ . = ..()
+
+ if(target)
+ assimilate(target)
+
+ if(alt_worn)
+ alternate_worn_icon = alt_worn
+ if(worn_state)
+ item_state = worn_state
+ icon_state = worn_state
+ if(left_hand)
+ lefthand_file = left_hand
+ if(right_hand)
+ righthand_file = right_hand
+ slot_flags = slots
+
+/obj/item/clothing/head/mob_holder/proc/assimilate(mob/living/target)
+ target.setDir(SOUTH)
+ held_mob = target
+ target.forceMove(src)
+ var/image/I = new //work around to retain the same appearance to the mob idependently from inhands/worn states.
+ I.appearance = target.appearance
+ I.override = TRUE
+ add_overlay(I)
+ name = target.name
+ desc = target.desc
+ switch(target.mob_size)
+ if(MOB_SIZE_TINY)
+ w_class = WEIGHT_CLASS_TINY
+ if(MOB_SIZE_SMALL)
+ w_class = WEIGHT_CLASS_NORMAL
+ if(MOB_SIZE_LARGE)
+ w_class = WEIGHT_CLASS_HUGE
+ RegisterSignal(src, COMSIG_CLICK_SHIFT, .proc/examine_held_mob)
+
+/obj/item/clothing/head/mob_holder/Destroy()
+ if(held_mob)
+ release()
+ return ..()
+
+/obj/item/clothing/head/mob_holder/proc/examine_held_mob(datum/source, mob/user)
+ held_mob.ShiftClick(user)
+ return COMPONENT_DENY_EXAMINATE
+
+/obj/item/clothing/head/mob_holder/Exited(atom/movable/AM, atom/newloc)
+ . = ..()
+ if(AM == held_mob)
+ held_mob.reset_perspective()
+ held_mob = null
+ qdel(src)
+
+/obj/item/clothing/head/mob_holder/Entered(atom/movable/AM, atom/newloc)
+ . = ..()
+ if(AM != held_mob)
+ var/destination = loc
+ if(isliving(loc)) //the mob is held or worn, drop things on the floor
+ destination = get_turf(loc)
+ AM.forceMove(destination)
+
+/obj/item/clothing/head/mob_holder/dropped()
+ . = ..()
+ if(held_mob && isturf(loc))//don't release on soft-drops
+ release()
+
+/obj/item/clothing/head/mob_holder/proc/release()
+ if(held_mob)
+ var/mob/living/L = held_mob
+ held_mob = null
+ L.forceMove(get_turf(L))
+ L.reset_perspective()
+ L.setDir(SOUTH)
+ qdel(src)
+
+/obj/item/clothing/head/mob_holder/relaymove(mob/user)
+ return
+
+/obj/item/clothing/head/mob_holder/container_resist()
+ if(isliving(loc))
+ var/mob/living/L = loc
+ L.visible_message("[src] escapes from [L]!", "[src] escapes your grip!")
+ release()
+
+/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
+ var/atom/location = loc
+ if(!loc)
+ return //null
+ var/turf/T = get_turf(loc)
+ while(location != T)
+ location = location.loc
+ if(ismob(location))
+ return location.loc.assume_air(env)
+ return loc.assume_air(env)
+
+/obj/item/clothing/head/mob_holder/remove_air(amount)
+ var/atom/location = loc
+ if(!loc)
+ return //null
+ var/turf/T = get_turf(loc)
+ while(location != T)
+ location = location.loc
+ if(ismob(location))
+ return location.loc.remove_air(amount)
+ return loc.remove_air(amount)
diff --git a/code/datums/elements/wuv.dm b/code/datums/elements/wuv.dm
index bac7d1ff..55bc9baf 100644
--- a/code/datums/elements/wuv.dm
+++ b/code/datums/elements/wuv.dm
@@ -30,6 +30,10 @@
RegisterSignal(target, COMSIG_MOB_ATTACK_HAND, .proc/on_attack_hand)
+/datum/element/wuv/Detach(datum/source, force)
+ . = ..()
+ UnregisterSignal(source, COMSIG_MOB_ATTACK_HAND)
+
/datum/element/wuv/proc/on_attack_hand(datum/source, mob/user)
var/mob/living/L = source
diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm
index b05b796c..b36a2b95 100644
--- a/code/modules/mob/living/carbon/examine.dm
+++ b/code/modules/mob/living/carbon/examine.dm
@@ -16,10 +16,6 @@
msg += "[t_He] [t_is] wearing [wear_mask.get_examine_string(user)] on [t_his] face.\n"
if (wear_neck)
msg += "[t_He] [t_is] wearing [wear_neck.get_examine_string(user)] around [t_his] neck.\n"
- if(can_be_held)
- msg += "[t_He] might be able to be picked up with Alt+Click!\n"
-
-
for(var/obj/item/I in held_items)
if(!(I.item_flags & ABSTRACT))
@@ -111,7 +107,7 @@
msg += "[t_He] look[p_s()] very happy.\n"
if(MOOD_LEVEL_HAPPY4 to INFINITY)
msg += "[t_He] look[p_s()] ecstatic.\n"
+ SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, msg)
msg += "*---------*"
-
to_chat(user, msg)
return msg
diff --git a/code/modules/mob/living/carbon/human/examine.dm b/code/modules/mob/living/carbon/human/examine.dm
index e017ec34..03259bd2 100644
--- a/code/modules/mob/living/carbon/human/examine.dm
+++ b/code/modules/mob/living/carbon/human/examine.dm
@@ -399,6 +399,7 @@
msg += "...?
"
else
msg += "[print_flavor_text()]\n"
+ SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, msg)
msg += "*---------*"
to_chat(user, msg)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index fbbfe1bc..65259212 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1110,7 +1110,8 @@
race = /datum/species/krokodil_addict
//define holder_type on nerds we wanna commit scoop to
-/mob/living/carbon/human
+/* /mob/living/carbon/human
var/holder_type = /obj/item/clothing/head/mob_holder/micro
can_be_held = "micro"
+*/
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index 47a177f7..54fddea2 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -1,176 +1,175 @@
-/mob/living/carbon/monkey
- name = "monkey"
- verb_say = "chimpers"
- initial_language_holder = /datum/language_holder/monkey
- icon = 'icons/mob/monkey.dmi'
- icon_state = ""
- gender = NEUTER
- pass_flags = PASSTABLE
- ventcrawler = VENTCRAWLER_NUDE
- mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID)
- butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
- type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab/monkey
- gib_type = /obj/effect/decal/cleanable/blood/gibs
- unique_name = TRUE
- bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
- /obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
- hud_type = /datum/hud/monkey
- can_be_held = "monkey"
-
-/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
- verbs += /mob/living/proc/mob_sleep
- verbs += /mob/living/proc/lay_down
-
- if(unique_name) //used to exclude pun pun
- gender = pick(MALE, FEMALE)
- real_name = name
-
- //initialize limbs
- create_bodyparts()
- create_internal_organs()
-
- . = ..()
-
- if (cubespawned)
- var/cap = CONFIG_GET(number/monkeycap)
- if (LAZYLEN(SSmobs.cubemonkeys) > cap)
- if (spawner)
- to_chat(spawner, "Bluespace harmonics prevent the spawning of more than [cap] monkeys on the station at one time!")
- return INITIALIZE_HINT_QDEL
- SSmobs.cubemonkeys += src
-
- create_dna(src)
- dna.initialize_dna(random_blood_type())
-
-/mob/living/carbon/monkey/Destroy()
- SSmobs.cubemonkeys -= src
- return ..()
-
-/mob/living/carbon/monkey/generate_mob_holder()
- var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "monkey", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
- return holder
-
-/mob/living/carbon/monkey/create_internal_organs()
- internal_organs += new /obj/item/organ/appendix
- internal_organs += new /obj/item/organ/lungs
- internal_organs += new /obj/item/organ/heart
- internal_organs += new /obj/item/organ/brain
- internal_organs += new /obj/item/organ/tongue
- internal_organs += new /obj/item/organ/eyes
- internal_organs += new /obj/item/organ/ears
- internal_organs += new /obj/item/organ/liver
- internal_organs += new /obj/item/organ/stomach
- ..()
-
-/mob/living/carbon/monkey/on_reagent_change()
- . = ..()
- remove_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE)
- var/amount
- if(reagents.has_reagent("morphine"))
- amount = -1
- if(reagents.has_reagent("nuka_cola"))
- amount = -1
- if(amount)
- add_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
-
-/mob/living/carbon/monkey/updatehealth()
- . = ..()
- var/slow = 0
- var/health_deficiency = (100 - health)
- if(health_deficiency >= 45)
- slow += (health_deficiency / 25)
- add_movespeed_modifier(MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow)
-
-/mob/living/carbon/monkey/adjust_bodytemperature(amount)
- . = ..()
- var/slow = 0
- if (bodytemperature < 283.222)
- slow += (283.222 - bodytemperature) / 10 * 1.75
- if(slow <= 0)
- return
- add_movespeed_modifier(MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
-
-/mob/living/carbon/monkey/Stat()
- ..()
- if(statpanel("Status"))
- stat(null, "Intent: [a_intent]")
- stat(null, "Move Mode: [m_intent]")
- if(client && mind)
- var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
- if(changeling)
- stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]")
- stat("Absorbed DNA", changeling.absorbedcount)
- return
-
-
-/mob/living/carbon/monkey/verb/removeinternal()
- set name = "Remove Internals"
- set category = "IC"
- internal = null
- return
-
-
-/mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools
- if(mind && is_monkey(mind))
- return TRUE
- return FALSE
-
-/mob/living/carbon/monkey/reagent_check(datum/reagent/R) //can metabolize all reagents
- return FALSE
-
-/mob/living/carbon/monkey/canBeHandcuffed()
- return TRUE
-
-/mob/living/carbon/monkey/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
- if(judgement_criteria & JUDGE_EMAGGED)
- return 10 //Everyone is a criminal!
-
- var/threatcount = 0
-
- //Securitrons can't identify monkeys
- if( !(judgement_criteria & JUDGE_IGNOREMONKEYS) && (judgement_criteria & JUDGE_IDCHECK) )
- threatcount += 4
-
- //Lasertag bullshit
- if(lasercolor)
- if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
- if(is_holding_item_of_type(/obj/item/gun/energy/laser/redtag))
- threatcount += 4
-
- if(lasercolor == "r")
- if(is_holding_item_of_type(/obj/item/gun/energy/laser/bluetag))
- threatcount += 4
-
- return threatcount
-
- //Check for weapons
- if( (judgement_criteria & JUDGE_WEAPONCHECK) && weaponcheck )
- for(var/obj/item/I in held_items) //if they're holding a gun
- if(weaponcheck.Invoke(I))
- threatcount += 4
- if(weaponcheck.Invoke(back)) //if a weapon is present in the back slot
- threatcount += 4 //trigger look_for_perp() since they're nonhuman and very likely hostile
-
- //mindshield implants imply trustworthyness
- if(HAS_TRAIT(src, TRAIT_MINDSHIELD))
- threatcount -= 1
-
- return threatcount
-
-/mob/living/carbon/monkey/IsVocal()
- if(!getorganslot(ORGAN_SLOT_LUNGS))
- return 0
- return 1
-
-/mob/living/carbon/monkey/can_use_guns(obj/item/G)
- return TRUE
-
-/mob/living/carbon/monkey/angry
- aggressive = TRUE
-
-/mob/living/carbon/monkey/angry/Initialize()
- . = ..()
- if(prob(10))
- var/obj/item/clothing/head/helmet/justice/escape/helmet = new(src)
- equip_to_slot_or_del(helmet,SLOT_HEAD)
- helmet.attack_self(src) // todo encapsulate toggle
+/mob/living/carbon/monkey
+ name = "monkey"
+ verb_say = "chimpers"
+ initial_language_holder = /datum/language_holder/monkey
+ icon = 'icons/mob/monkey.dmi'
+ icon_state = ""
+ gender = NEUTER
+ pass_flags = PASSTABLE
+ ventcrawler = VENTCRAWLER_NUDE
+ mob_biotypes = list(MOB_ORGANIC, MOB_HUMANOID)
+ butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
+ type_of_meat = /obj/item/reagent_containers/food/snacks/meat/slab/monkey
+ gib_type = /obj/effect/decal/cleanable/blood/gibs
+ unique_name = TRUE
+ bodyparts = list(/obj/item/bodypart/chest/monkey, /obj/item/bodypart/head/monkey, /obj/item/bodypart/l_arm/monkey,
+ /obj/item/bodypart/r_arm/monkey, /obj/item/bodypart/r_leg/monkey, /obj/item/bodypart/l_leg/monkey)
+ hud_type = /datum/hud/monkey
+
+/mob/living/carbon/monkey/Initialize(mapload, cubespawned=FALSE, mob/spawner)
+ verbs += /mob/living/proc/mob_sleep
+ verbs += /mob/living/proc/lay_down
+
+ if(unique_name) //used to exclude pun pun
+ gender = pick(MALE, FEMALE)
+ real_name = name
+
+ //initialize limbs
+ create_bodyparts()
+ create_internal_organs()
+
+ . = ..()
+
+ if (cubespawned)
+ var/cap = CONFIG_GET(number/monkeycap)
+ if (LAZYLEN(SSmobs.cubemonkeys) > cap)
+ if (spawner)
+ to_chat(spawner, "Bluespace harmonics prevent the spawning of more than [cap] monkeys on the station at one time!")
+ return INITIALIZE_HINT_QDEL
+ SSmobs.cubemonkeys += src
+
+ create_dna(src)
+ dna.initialize_dna(random_blood_type())
+
+/mob/living/carbon/monkey/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/mob_holder, "monkey", null, null, null, SLOT_HEAD)
+
+/mob/living/carbon/monkey/Destroy()
+ SSmobs.cubemonkeys -= src
+ return ..()
+
+/mob/living/carbon/monkey/create_internal_organs()
+ internal_organs += new /obj/item/organ/appendix
+ internal_organs += new /obj/item/organ/lungs
+ internal_organs += new /obj/item/organ/heart
+ internal_organs += new /obj/item/organ/brain
+ internal_organs += new /obj/item/organ/tongue
+ internal_organs += new /obj/item/organ/eyes
+ internal_organs += new /obj/item/organ/ears
+ internal_organs += new /obj/item/organ/liver
+ internal_organs += new /obj/item/organ/stomach
+ ..()
+
+/mob/living/carbon/monkey/on_reagent_change()
+ . = ..()
+ remove_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE)
+ var/amount
+ if(reagents.has_reagent("morphine"))
+ amount = -1
+ if(reagents.has_reagent("nuka_cola"))
+ amount = -1
+ if(amount)
+ add_movespeed_modifier(MOVESPEED_ID_MONKEY_REAGENT_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
+
+/mob/living/carbon/monkey/updatehealth()
+ . = ..()
+ var/slow = 0
+ var/health_deficiency = (100 - health)
+ if(health_deficiency >= 45)
+ slow += (health_deficiency / 25)
+ add_movespeed_modifier(MOVESPEED_ID_MONKEY_HEALTH_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = slow)
+
+/mob/living/carbon/monkey/adjust_bodytemperature(amount)
+ . = ..()
+ var/slow = 0
+ if (bodytemperature < 283.222)
+ slow += (283.222 - bodytemperature) / 10 * 1.75
+ if(slow <= 0)
+ return
+ add_movespeed_modifier(MOVESPEED_ID_MONKEY_TEMPERATURE_SPEEDMOD, TRUE, 100, override = TRUE, multiplicative_slowdown = amount)
+
+/mob/living/carbon/monkey/Stat()
+ ..()
+ if(statpanel("Status"))
+ stat(null, "Intent: [a_intent]")
+ stat(null, "Move Mode: [m_intent]")
+ if(client && mind)
+ var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
+ if(changeling)
+ stat("Chemical Storage", "[changeling.chem_charges]/[changeling.chem_storage]")
+ stat("Absorbed DNA", changeling.absorbedcount)
+ return
+
+
+/mob/living/carbon/monkey/verb/removeinternal()
+ set name = "Remove Internals"
+ set category = "IC"
+ internal = null
+ return
+
+
+/mob/living/carbon/monkey/IsAdvancedToolUser()//Unless its monkey mode monkeys cant use advanced tools
+ if(mind && is_monkey(mind))
+ return TRUE
+ return FALSE
+
+/mob/living/carbon/monkey/reagent_check(datum/reagent/R) //can metabolize all reagents
+ return FALSE
+
+/mob/living/carbon/monkey/canBeHandcuffed()
+ return TRUE
+
+/mob/living/carbon/monkey/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
+ if(judgement_criteria & JUDGE_EMAGGED)
+ return 10 //Everyone is a criminal!
+
+ var/threatcount = 0
+
+ //Securitrons can't identify monkeys
+ if( !(judgement_criteria & JUDGE_IGNOREMONKEYS) && (judgement_criteria & JUDGE_IDCHECK) )
+ threatcount += 4
+
+ //Lasertag bullshit
+ if(lasercolor)
+ if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
+ if(is_holding_item_of_type(/obj/item/gun/energy/laser/redtag))
+ threatcount += 4
+
+ if(lasercolor == "r")
+ if(is_holding_item_of_type(/obj/item/gun/energy/laser/bluetag))
+ threatcount += 4
+
+ return threatcount
+
+ //Check for weapons
+ if( (judgement_criteria & JUDGE_WEAPONCHECK) && weaponcheck )
+ for(var/obj/item/I in held_items) //if they're holding a gun
+ if(weaponcheck.Invoke(I))
+ threatcount += 4
+ if(weaponcheck.Invoke(back)) //if a weapon is present in the back slot
+ threatcount += 4 //trigger look_for_perp() since they're nonhuman and very likely hostile
+
+ //mindshield implants imply trustworthyness
+ if(HAS_TRAIT(src, TRAIT_MINDSHIELD))
+ threatcount -= 1
+
+ return threatcount
+
+/mob/living/carbon/monkey/IsVocal()
+ if(!getorganslot(ORGAN_SLOT_LUNGS))
+ return 0
+ return 1
+
+/mob/living/carbon/monkey/can_use_guns(obj/item/G)
+ return TRUE
+
+/mob/living/carbon/monkey/angry
+ aggressive = TRUE
+
+/mob/living/carbon/monkey/angry/Initialize()
+ . = ..()
+ if(prob(10))
+ var/obj/item/clothing/head/helmet/justice/escape/helmet = new(src)
+ equip_to_slot_or_del(helmet,SLOT_HEAD)
+ helmet.attack_self(src) // todo encapsulate toggle
diff --git a/code/modules/mob/living/inhand_holder.dm b/code/modules/mob/living/inhand_holder.dm
deleted file mode 100644
index e68260de..00000000
--- a/code/modules/mob/living/inhand_holder.dm
+++ /dev/null
@@ -1,129 +0,0 @@
-//Generic system for picking up mobs.
-//Currently works for head and hands.
-/obj/item/clothing/head/mob_holder
- name = "bugged mob"
- desc = "Yell at coderbrush."
- icon = null
- icon_state = ""
- var/mob/living/held_mob
- var/can_head = FALSE
- w_class = WEIGHT_CLASS_BULKY
-
-/obj/item/clothing/head/mob_holder/Initialize(mapload, mob/living/M, _worn_state, alt_worn, lh_icon, rh_icon, _can_head_override = FALSE)
- . = ..()
-
- if(M)
- M.setDir(SOUTH)
- held_mob = M
- M.forceMove(src)
- appearance = M.appearance
- name = M.name
- desc = M.desc
-
- if(_can_head_override)
- can_head = _can_head_override
- if(alt_worn)
- alternate_worn_icon = alt_worn
- if(_worn_state)
- item_state = _worn_state
- icon_state = _worn_state
- if(lh_icon)
- lefthand_file = lh_icon
- if(rh_icon)
- righthand_file = rh_icon
- if(!can_head)
- slot_flags = NONE
-
-/obj/item/clothing/head/mob_holder/Destroy()
- if(held_mob)
- release()
- return ..()
-
-/obj/item/clothing/head/mob_holder/dropped()
- ..()
- if(isturf(loc))//don't release on soft-drops
- release()
-
-/obj/item/clothing/head/mob_holder/proc/release()
- if(isliving(loc))
- var/mob/living/L = loc
- L.dropItemToGround(src)
- if(held_mob)
- var/mob/living/m = held_mob
- m.forceMove(get_turf(m))
- m.reset_perspective()
- m.setDir(SOUTH)
- held_mob = null
- qdel(src)
-
-/obj/item/clothing/head/mob_holder/relaymove(mob/user)
- return
-
-/obj/item/clothing/head/mob_holder/container_resist()
- if(isliving(loc))
- var/mob/living/L = loc
- visible_message("[src] escapes [L]!")
- release()
-
-/mob/living/proc/mob_pickup(mob/living/L)
- var/obj/item/clothing/head/mob_holder/holder = generate_mob_holder()
- if(!holder)
- return
- drop_all_held_items()
- L.put_in_hands(holder)
- return
-
-/mob/living/proc/mob_try_pickup(mob/living/user)
- if(!ishuman(user) || !src.Adjacent(user) || user.incapacitated() || !can_be_held)
- return FALSE
- if(src.can_be_held == "micro")
- return FALSE
- if(user.get_active_held_item())
- to_chat(user, "Your hands are full!")
- return FALSE
- if(buckled)
- to_chat(user, "[src] is buckled to something!")
- return FALSE
- if(src == user)
- to_chat(user, "You can't pick yourself up.")
- return FALSE
- visible_message("[user] starts picking up [src].", \
- "[user] starts picking you up!")
- if(!do_after(user, 20, target = src))
- return FALSE
-
- if(user.get_active_held_item()||buckled)
- return FALSE
-
- visible_message("[user] picks up [src]!", \
- "[user] picks you up!")
- to_chat(user, "You pick [src] up.")
- mob_pickup(user)
- return TRUE
-
-/mob/living/AltClick(mob/user)
- . = ..()
- if(mob_try_pickup(user))
- return TRUE
-
-/obj/item/clothing/head/mob_holder/assume_air(datum/gas_mixture/env)
- var/atom/location = loc
- if(!loc)
- return //null
- var/turf/T = get_turf(loc)
- while(location != T)
- location = location.loc
- if(ismob(location))
- return location.loc.assume_air(env)
- return location.assume_air(env)
-
-/obj/item/clothing/head/mob_holder/remove_air(amount)
- var/atom/location = loc
- if(!loc)
- return //null
- var/turf/T = get_turf(loc)
- while(location != T)
- location = location.loc
- if(ismob(location))
- return location.loc.remove_air(amount)
- return location.remove_air(amount)
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 2ba4be99..4c400ee4 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -40,14 +40,6 @@
QDEL_LIST(diseases)
return ..()
-
-/mob/living/proc/generate_mob_holder()
- if(ishuman(src))
- var/obj/item/clothing/head/mob_holder/micro/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
- return holder
- var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
- return holder
-
/mob/living/onZImpact(turf/T, levels)
if(!isgroundlessturf(T))
ZImpactDamage(T, levels)
@@ -1153,8 +1145,6 @@
return
if(!over.Adjacent(src) || (user != src) || !canUseTopic(over))
return
- if(can_be_held)
- mob_try_pickup(over)
/mob/living/proc/get_static_viruses() //used when creating blood and other infective objects
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index d283a4fa..9d346a44 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -107,7 +107,7 @@
var/last_words //used for database logging
var/list/obj/effect/proc_holder/abilities = list()
-
+
var/can_be_held = FALSE
var/radiation = 0 //If the mob is irradiated.
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index 1601ccfe..c298d89c 100644
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -11,7 +11,7 @@
health = 500
maxHealth = 500
layer = BELOW_MOB_LAYER
- can_be_held = TRUE
+ var/datum/element/mob_holder/current_mob_holder //because only a few of their chassis can be actually held.
var/network = "ss13"
var/obj/machinery/camera/current = null
@@ -58,10 +58,12 @@
var/canholo = TRUE
var/obj/item/card/id/access_card = null
var/chassis = "repairbot"
+ var/dynamic_chassis
+ var/dynamic_chassis_sit = FALSE //whether we're sitting instead of resting spritewise
+ var/dynamic_chassis_bellyup = FALSE //whether we're lying down bellyup
var/list/possible_chassis = list("cat" = TRUE, "mouse" = TRUE, "monkey" = TRUE, "corgi" = FALSE, "fox" = FALSE, "repairbot" = TRUE, "rabbit" = TRUE, "operator" = TRUE) //assoc value is whether it can be picked up.
- var/static/item_head_icon = 'icons/mob/pai_item_head.dmi'
- var/static/item_lh_icon = 'icons/mob/pai_item_lh.dmi'
- var/static/item_rh_icon = 'icons/mob/pai_item_rh.dmi'
+ var/list/dynamic_chassis_icons //ditto.
+ var/list/chassis_pixel_offsets_x //stupid dogborgs
var/emitterhealth = 20
var/emittermaxhealth = 20
diff --git a/code/modules/mob/living/silicon/pai/pai_shell.dm b/code/modules/mob/living/silicon/pai/pai_shell.dm
index 164a3e73..bf625f67 100644
--- a/code/modules/mob/living/silicon/pai/pai_shell.dm
+++ b/code/modules/mob/living/silicon/pai/pai_shell.dm
@@ -86,6 +86,12 @@
if(resting)
icon_state = "[chassis]_rest"
to_chat(src, "You switch your holochassis projection composite to [chassis]")
+ if(possible_chassis[chassis])
+ current_mob_holder = AddElement(/datum/element/mob_holder, chassis, 'icons/mob/pai_item_head.dmi', 'icons/mob/pai_item_rh.dmi', 'icons/mob/pai_item_lh.dmi', SLOT_HEAD)
+ else
+ current_mob_holder?.Detach(src)
+ current_mob_holder = null
+ return
/mob/living/silicon/pai/lay_down()
..()
@@ -109,16 +115,3 @@
else
set_light(0)
to_chat(src, "You disable your integrated light.")
-
-/mob/living/silicon/pai/mob_pickup(mob/living/L)
- var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, chassis, item_head_icon, item_lh_icon, item_rh_icon)
- if(!L.put_in_hands(holder))
- qdel(holder)
- else
- L.visible_message("[L] scoops up [src]!")
-
-/mob/living/silicon/pai/mob_try_pickup(mob/living/user)
- if(!possible_chassis[chassis])
- to_chat(user, "[src]'s current form isn't able to be carried!")
- return FALSE
- return ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/cat.dm b/code/modules/mob/living/simple_animal/friendly/cat.dm
index b3cb4ec4..5ea3eed5 100644
--- a/code/modules/mob/living/simple_animal/friendly/cat.dm
+++ b/code/modules/mob/living/simple_animal/friendly/cat.dm
@@ -31,9 +31,9 @@
var/mob/living/simple_animal/mouse/movement_target
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "cat"
- can_be_held = "cat2"
size_multiplier = 0.5
+ var/held_icon = "cat2"
do_footstep = TRUE
/mob/living/simple_animal/pet/cat/Initialize()
@@ -43,6 +43,7 @@
/mob/living/simple_animal/pet/cat/ComponentInitialize()
. = ..()
AddElement(/datum/element/wuv, "purrs!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "hisses!", EMOTE_AUDIBLE)
+ AddElement(/datum/element/mob_holder, held_icon)
/mob/living/simple_animal/pet/cat/update_canmove()
..()
@@ -62,6 +63,7 @@
icon_state = "spacecat"
icon_living = "spacecat"
icon_dead = "spacecat_dead"
+ held_icon = "spacecat"
unsuitable_atmos_damage = 0
minbodytemp = TCMB
maxbodytemp = T0C + 40
@@ -73,6 +75,7 @@
icon_state = "original"
icon_living = "original"
icon_dead = "original_dead"
+ held_icon = "original"
collar_type = null
unique_pet = TRUE
@@ -86,7 +89,7 @@
pass_flags = PASSMOB
mob_size = MOB_SIZE_SMALL
collar_type = "kitten"
- can_be_held = "cat"
+ held_icon = "cat"
//RUNTIME IS ALIVE! SQUEEEEEEEE~
/mob/living/simple_animal/pet/cat/Runtime
@@ -251,7 +254,7 @@
attacked_sound = 'sound/items/eatfood.ogg'
deathmessage = "loses its false life and collapses!"
death_sound = "bodyfall"
- can_be_held = "cak"
+ held_icon = "cak"
/mob/living/simple_animal/pet/cat/cak/CheckParts(list/parts)
..()
diff --git a/code/modules/mob/living/simple_animal/friendly/dog.dm b/code/modules/mob/living/simple_animal/friendly/dog.dm
index 1979f9aa..bf7eb05f 100644
--- a/code/modules/mob/living/simple_animal/friendly/dog.dm
+++ b/code/modules/mob/living/simple_animal/friendly/dog.dm
@@ -14,13 +14,14 @@
speak_chance = 1
turns_per_move = 10
size_multiplier = 0.5
+ var/held_icon = "corgi"
do_footstep = TRUE
- can_be_held = TRUE
/mob/living/simple_animal/pet/dog/ComponentInitialize()
. = ..()
AddElement(/datum/element/wuv, "yaps_happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE)
+ AddElement(/datum/element/mob_holder, held_icon)
//Corgis and pugs are now under one dog subtype
@@ -35,13 +36,11 @@
childtype = list(/mob/living/simple_animal/pet/dog/corgi/puppy = 95, /mob/living/simple_animal/pet/dog/corgi/puppy/void = 5)
animal_species = /mob/living/simple_animal/pet/dog
gold_core_spawnable = FRIENDLY_SPAWN
- can_be_held = TRUE
collar_type = "corgi"
var/obj/item/inventory_head
var/obj/item/inventory_back
var/shaved = FALSE
var/nofur = FALSE //Corgis that have risen past the material plane of existence.
- can_be_held = "corgi"
/mob/living/simple_animal/pet/dog/corgi/Destroy()
QDEL_NULL(inventory_head)
@@ -70,7 +69,7 @@
butcher_results = list(/obj/item/reagent_containers/food/snacks/meat/slab/pug = 3)
gold_core_spawnable = FRIENDLY_SPAWN
collar_type = "pug"
- can_be_held = "pug"
+ held_icon = "pug"
/mob/living/simple_animal/pet/dog/corgi/exoticcorgi
name = "Exotic Corgi"
@@ -157,13 +156,6 @@
..()
update_corgi_fluff()
-/mob/living/simple_animal/pet/dog/corgi/mob_pickup(mob/living/L)
- var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "corgi", null, 'icons/mob/pets_held_lh.dmi', 'icons/mob/pets_held_rh.dmi', FALSE)
- if(!L.put_in_hands(holder))
- qdel(holder)
- else
- L.visible_message("[L] scoops up [src]!")
-
/mob/living/simple_animal/pet/dog/corgi/Topic(href, href_list)
if(!(iscarbon(usr) || iscyborg(usr)) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
usr << browse(null, "window=mob[REF(src)]")
@@ -368,7 +360,10 @@
icon_dead = "old_corgi_dead"
desc = "At a ripe old age of [record_age] Ian's not as spry as he used to be, but he'll always be the HoP's beloved corgi." //RIP
turns_per_move = 20
- can_be_held = "old_corgi"
+ var/datum/element/mob_holder/ele = SSdcs.GetElement(/datum/element/mob_holder, held_icon)
+ if(ele)
+ ele.Detach(src)
+ AddElement(/datum/element/mob_holder, "old_corgi")
/mob/living/simple_animal/pet/dog/corgi/Ian/Life()
if(!stat && SSticker.current_state == GAME_STATE_FINISHED && !memory_saved)
@@ -591,7 +586,7 @@
unsuitable_atmos_damage = 0
minbodytemp = TCMB
maxbodytemp = T0C + 40
- can_be_held = "void_puppy"
+ held_icon = "void_puppy"
/mob/living/simple_animal/pet/dog/corgi/puppy/void/Process_Spacemove(movement_dir = 0)
return 1 //Void puppies can navigate space.
@@ -613,7 +608,7 @@
response_harm = "kicks"
var/turns_since_scan = 0
var/puppies = 0
- can_be_held = "lisa"
+ held_icon = "lisa"
//Lisa already has a cute bow!
/mob/living/simple_animal/pet/dog/corgi/Lisa/Topic(href, href_list)
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
index f880adb7..c9ac7377 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/_drone.dm
@@ -50,7 +50,8 @@
dextrous_hud_type = /datum/hud/dextrous/drone
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
see_in_dark = 7
- can_be_held = TRUE
+ blood_volume = 0
+ can_be_held = TRUE //mob holder element.
held_items = list(null, null)
var/staticChoice = "static"
var/list/staticChoices = list("static", "blank", "letter", "animal")
@@ -100,6 +101,11 @@
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
+/mob/living/simple_animal/drone/ComponentInitialize()
+ . = ..()
+ if(can_be_held)
+ //icon/item state is defined in mob_holder/drone_worn_icon()
+ AddElement(/datum/element/mob_holder, null, 'icons/mob/head.dmi', 'icons/mob/inhands/clothing_righthand.dmi', 'icons/mob/inhands/clothing_lefthand.dmi', TRUE, /datum/element/mob_holder.proc/drone_worn_icon)
/mob/living/simple_animal/drone/med_hud_set_health()
var/image/holder = hud_list[DIAG_HUD]
@@ -274,7 +280,3 @@
/mob/living/simple_animal/drone/electrocute_act(shock_damage, obj/source, siemens_coeff = 1, safety = 0, tesla_shock = 0, illusion = 0, stun = TRUE)
return 0 //So they don't die trying to fix wiring
-
-/mob/living/simple_animal/drone/generate_mob_holder()
- var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "[visualAppearence]_hat", null, null, null, TRUE)
- return holder
diff --git a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
index c9207fcf..0f97a4c4 100644
--- a/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
+++ b/code/modules/mob/living/simple_animal/friendly/drone/interaction.dm
@@ -29,12 +29,6 @@
if("Nothing")
return
-//picky up the drone c:
-/mob/living/simple_animal/drone/attack_hand(mob/user)
- if(user.a_intent != INTENT_HELP)
- return ..() // TODO: convert picking up mobs into an element or component.
- mob_try_pickup(user)
-
/mob/living/simple_animal/drone/proc/try_reactivate(mob/living/user)
var/mob/dead/observer/G = get_ghost()
if(!client && (!G || !G.client))
diff --git a/code/modules/mob/living/simple_animal/friendly/fox.dm b/code/modules/mob/living/simple_animal/friendly/fox.dm
index 3f58ca59..95b082b7 100644
--- a/code/modules/mob/living/simple_animal/friendly/fox.dm
+++ b/code/modules/mob/living/simple_animal/friendly/fox.dm
@@ -18,9 +18,12 @@
response_disarm = "gently pushes aside"
response_harm = "kicks"
gold_core_spawnable = FRIENDLY_SPAWN
- can_be_held = "fox"
do_footstep = TRUE
+/mob/living/simple_animal/pet/fox/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/mob_holder, "fox")
+
//Captain fox
/mob/living/simple_animal/pet/fox/Renault
name = "Renault"
diff --git a/code/modules/mob/living/simple_animal/friendly/lizard.dm b/code/modules/mob/living/simple_animal/friendly/lizard.dm
index 6076e412..8d33d3a2 100644
--- a/code/modules/mob/living/simple_animal/friendly/lizard.dm
+++ b/code/modules/mob/living/simple_animal/friendly/lizard.dm
@@ -23,9 +23,12 @@
obj_damage = 0
environment_smash = ENVIRONMENT_SMASH_NONE
var/static/list/edibles = typecacheof(list(/mob/living/simple_animal/butterfly, /mob/living/simple_animal/cockroach)) //list of atoms, however turfs won't affect AI, but will affect consumption.
- can_be_held = "lizard"
size_multiplier = 0.5
+/mob/living/simple_animal/hostile/lizard/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/mob_holder, "lizard", null, null, null, SLOT_HEAD) //you can hold lizards now.
+
/mob/living/simple_animal/hostile/lizard/CanAttack(atom/the_target)//Can we actually attack a possible target?
if(see_invisible < the_target.invisibility)//Target's invisible to us, forget it
return FALSE
@@ -41,7 +44,3 @@
return TRUE
else
return ..()
-
-/mob/living/simple_animal/hostile/lizard/generate_mob_holder()
- var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, "lizard", 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi', TRUE)
- return holder
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index 028bada0..97db2047 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -25,18 +25,17 @@
var/body_color //brown, gray and white, leave blank for random
gold_core_spawnable = FRIENDLY_SPAWN
var/chew_probability = 1
- can_be_held = TRUE
size_multiplier = 0.5
/mob/living/simple_animal/mouse/Initialize()
. = ..()
AddComponent(/datum/component/squeak, list('sound/effects/mousesqueek.ogg'=1), 100)
if(!body_color)
- body_color = pick( list("brown","gray","white") )
+ body_color = pick(list("brown","gray","white"))
+ AddElement(/datum/element/mob_holder, "mouse_[body_color]")
icon_state = "mouse_[body_color]"
icon_living = "mouse_[body_color]"
icon_dead = "mouse_[body_color]_dead"
- can_be_held = "mouse_[body_color]"
/mob/living/simple_animal/mouse/proc/splat()
src.health = 0
@@ -89,17 +88,14 @@
/mob/living/simple_animal/mouse/white
body_color = "white"
icon_state = "mouse_white"
- can_be_held = "mouse_white"
/mob/living/simple_animal/mouse/gray
body_color = "gray"
icon_state = "mouse_gray"
- can_be_held = "mouse_gray"
/mob/living/simple_animal/mouse/brown
body_color = "brown"
icon_state = "mouse_brown"
- can_be_held = "mouse_brown"
//TOM IS ALIVE! SQUEEEEEEEE~K :)
/mob/living/simple_animal/mouse/brown/Tom
@@ -124,7 +120,3 @@
/obj/item/reagent_containers/food/snacks/deadmouse/on_grind()
reagents.clear_reagents()
-/mob/living/simple_animal/mouse/generate_mob_holder()
- var/obj/item/clothing/head/mob_holder/holder = new(get_turf(src), src, (istext(can_be_held) ? can_be_held : ""), 'icons/mob/animals_held.dmi', 'icons/mob/animals_held_lh.dmi', 'icons/mob/animals_held_rh.dmi')
- holder.w_class = WEIGHT_CLASS_TINY
- return holder
diff --git a/code/modules/mob/living/simple_animal/friendly/sloth.dm b/code/modules/mob/living/simple_animal/friendly/sloth.dm
index fb114ace..f488e5ee 100644
--- a/code/modules/mob/living/simple_animal/friendly/sloth.dm
+++ b/code/modules/mob/living/simple_animal/friendly/sloth.dm
@@ -22,10 +22,12 @@
maxHealth = 50
speed = 10
glide_size = 2
- can_be_held = "sloth" //finally oranges can be held
size_multiplier = 0.5
do_footstep = TRUE
+/mob/living/simple_animal/pet/fox/ComponentInitialize()
+ . = ..()
+ AddElement(/datum/element/mob_holder, "sloth") //finally oranges can be held
//Cargo Sloth
/mob/living/simple_animal/sloth/paperwork
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 4e50551f..c7ce6577 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -314,11 +314,13 @@
return
if(is_blind(src))
- to_chat(src, "Something is there but you can't see it.")
+ to_chat(src, "Something is there but you can't see it!")
return
face_atom(A)
- A.examine(src)
+ var/list/result = A.examine(src)
+ to_chat(src, result.Join("\n"))
+ SEND_SIGNAL(src, COMSIG_MOB_EXAMINATE, A)
//same as above
//note: ghosts can point, this is intended
diff --git a/hyperstation/code/modules/resize/resizing.dm b/hyperstation/code/modules/resize/resizing.dm
index 647de2c9..d889b77c 100644
--- a/hyperstation/code/modules/resize/resizing.dm
+++ b/hyperstation/code/modules/resize/resizing.dm
@@ -162,10 +162,10 @@ mob/living/get_effective_size()
else
if(istype(H) && H.dna.features["taur"] == "Naga" || H.dna.features["taur"] == "Tentacle")
tmob.visible_message("[src] snatches up [tmob] underneath their tail!", "[src]'s tail winds around you and snatches you in its coils!")
- tmob.mob_pickup_micro_feet(H)
+ //tmob.mob_pickup_micro_feet(H)
else
tmob.visible_message("[src] stomps down on [tmob], curling their toes and picking them up!", "[src]'s toes pin you down and curl around you, picking you up!")
- tmob.mob_pickup_micro_feet(H)
+ //tmob.mob_pickup_micro_feet(H)
return 1
if(abs(tmob.get_effective_size()/get_effective_size()) >= 2)
diff --git a/tgstation.dme b/tgstation.dme
index d48447f7..45b3be68 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -457,6 +457,7 @@
#include "code\datums\elements\cleaning.dm"
#include "code\datums\elements\earhealing.dm"
#include "code\datums\elements\ghost_role_eligibility.dm"
+#include "code\datums\elements\mob_holder.dm"
#include "code\datums\elements\wuv.dm"
#include "code\datums\helper_datums\events.dm"
#include "code\datums\helper_datums\getrev.dm"
@@ -1984,7 +1985,6 @@
#include "code\modules\mob\living\damage_procs.dm"
#include "code\modules\mob\living\death.dm"
#include "code\modules\mob\living\emote.dm"
-#include "code\modules\mob\living\inhand_holder.dm"
#include "code\modules\mob\living\life.dm"
#include "code\modules\mob\living\living.dm"
#include "code\modules\mob\living\living_defense.dm"
@@ -2931,7 +2931,7 @@
#include "hyperstation\code\modules\crafting\recipes.dm"
#include "hyperstation\code\modules\integrated_electronics\input.dm"
#include "hyperstation\code\modules\patreon\patreon.dm"
-#include "hyperstation\code\modules\resize\holder_micro.dm"
+// #include "hyperstation\code\modules\resize\holder_micro.dm"
#include "hyperstation\code\modules\resize\resizing.dm"
#include "hyperstation\code\modules\resize\sizechems.dm"
#include "hyperstation\code\modules\resize\sizegun.dm"