Elevates (almost all) inventory variables from /carbon to /human (#96955)

## About The Pull Request

Moves all inventory slots but handcuffs/legcuffs (as those can be used
by xenos) from ``/carbon`` onto ``/human``, as xenos do not use any of
those inventory slots, only leaving them in use by humans. Their
presence on ``/carbon`` is an artifact of times when monkeys weren't
humans, and some of the slots had to be shared by all carbons.
In some places I've used ``get_item_by_slot`` rather than swapping
checks to ``ishuman`` for simplicity's sake, in some places it might not
be the most optimal solution but in cases like help act any other
solution would require a refactor of the whole (massive) proc.

## Why It's Good For The Game

Cleaner/more sensible code, one step closer to fully datumized
inventories.

## Changelog
🆑
refactor: Moved a lot of human-specific inventory code onto human mobs,
report if inventories break!
/🆑
This commit is contained in:
SmArtKar
2026-07-16 03:03:50 -07:00
committed by GitHub
parent 156beffc62
commit 677f070995
43 changed files with 288 additions and 412 deletions
+4 -4
View File
@@ -1162,13 +1162,13 @@
if(!.)
return
var/mob/living/carbon/carbon_owner = owner
var/mob/living/carbon/human/human_owner = owner
if(!carbon_owner.can_resist() || !carbon_owner.shoes)
if(!human_owner.can_resist() || !human_owner.shoes)
return
carbon_owner.changeNext_move(CLICK_CD_RESIST)
carbon_owner.shoes.handle_tying(carbon_owner)
human_owner.changeNext_move(CLICK_CD_RESIST)
human_owner.shoes.handle_tying(human_owner)
/atom/movable/screen/alert/shoes/untied
name = "Untied Shoes"
+2 -2
View File
@@ -56,7 +56,7 @@
if(!(equipped_slot & ITEM_SLOT_ICLOTHING))
return FALSE
return !isnull(wielder.shoes)
return !isnull(wielder.get_item_by_slot(ITEM_SLOT_FEET))
/**
* Run to update the icon of the parent
@@ -331,7 +331,7 @@
LAZYSET(footprint.species_types, affecting.limb_id, TRUE)
/datum/component/bloodysoles/feet/is_under_feet_covered()
return !isnull(wielder.shoes)
return !isnull(wielder.get_item_by_slot(ITEM_SLOT_FEET))
/datum/component/bloodysoles/feet/on_moved(datum/source, OldLoc, Dir, Forced)
if(wielder.num_legs >= 2)
+2 -1
View File
@@ -127,7 +127,8 @@
apply_tint(TRUE)
/datum/component/clothing_dirt/proc/is_protected(mob/living/carbon/wearer)
return wearer.head && wearer.head != parent && (wearer.head.flags_cover & PEPPERPROOF)
var/obj/item/head_cover = wearer.get_item_by_slot(ITEM_SLOT_HEAD)
return istype(head_cover) && head_cover != parent && (head_cover.flags_cover & PEPPERPROOF)
/datum/component/clothing_dirt/proc/remove_tint(updates = TRUE)
if(!tint_applied)
+7 -7
View File
@@ -45,14 +45,14 @@
RegisterSignal(interacting_with, COMSIG_ATOM_TOOL_ACT(TOOL_MULTITOOL), PROC_REF(redirect_multitool))
balloon_alert(user, "style meter attached")
playsound(src, 'sound/machines/click.ogg', 30, TRUE)
if(!iscarbon(interacting_with.loc))
if(!ishuman(interacting_with.loc))
return .
var/mob/living/carbon/carbon_wearer = interacting_with.loc
if(carbon_wearer.glasses != interacting_with)
var/mob/living/carbon/human/human_wearer = interacting_with.loc
if(human_wearer.glasses != interacting_with)
return .
start_meter(carbon_wearer)
start_meter(human_wearer)
return .
/obj/item/style_meter/Moved(atom/old_loc, Dir, momentum_change)
@@ -126,10 +126,10 @@
QDEL_NULL(style_meter)
/// Create the style meter component, attach it to our wearer, register other things onto the component.
/obj/item/style_meter/proc/start_meter(mob/living/carbon/carbon_wearer)
style_meter = carbon_wearer.AddComponent(/datum/component/style, multitooled, stored_permanent_multiplier)
/obj/item/style_meter/proc/start_meter(mob/living/carbon/human/human_wearer)
style_meter = human_wearer.AddComponent(/datum/component/style, multitooled, stored_permanent_multiplier)
RegisterSignal(SSdcs, COMSIG_GLOB_MOB_DEATH, PROC_REF(on_death))
RegisterSignal(carbon_wearer, COMSIG_LIVING_ON_VENT_WIN, PROC_REF(on_vent_win))
RegisterSignal(human_wearer, COMSIG_LIVING_ON_VENT_WIN, PROC_REF(on_vent_win))
/// On a successful vent tap, adjust permanent multiplier, scaling with vent value.
/obj/item/style_meter/proc/on_vent_win(datum/source, obj/structure/ore_vent/vent)
+1 -1
View File
@@ -72,7 +72,7 @@
attacker.apply_damage(rand(5, 10), attacker.get_attack_type(), BODY_ZONE_HEAD)
if(iscarbon(defender))
var/mob/living/carbon/carbon_defender = defender
if(!istype(carbon_defender.head, /obj/item/clothing/head/helmet/) && !istype(carbon_defender.head, /obj/item/clothing/head/utility/hardhat))
if(!istype(carbon_defender.get_item_by_slot(ITEM_SLOT_HEAD), /obj/item/clothing/head/helmet) && !istype(carbon_defender.get_item_by_slot(ITEM_SLOT_HEAD), /obj/item/clothing/head/utility/hardhat))
carbon_defender.adjust_organ_loss(ORGAN_SLOT_BRAIN, 5)
attacker.Stun(rand(1 SECONDS, 4.5 SECONDS))
defender.Stun(rand(0.5 SECONDS, 3 SECONDS))
+8 -9
View File
@@ -305,11 +305,10 @@ CIGARETTE PACKETS ARE IN FANCY.DM
/obj/item/cigarette/dropped(mob/dropee)
. = ..()
// Moving the cigarette from mask to hands (or pocket I guess) will emit a larger puff of smoke
if(!QDELETED(src) && !QDELETED(dropee) && how_long_have_we_been_smokin >= 4 SECONDS && iscarbon(dropee) && iscarbon(loc))
var/mob/living/carbon/smoker = dropee
if(!QDELETED(src) && !QDELETED(dropee) && how_long_have_we_been_smokin >= 4 SECONDS && dropee == loc && iscarbon(dropee))
// This relies on the fact that dropped is called before slot is nulled
if(src == smoker.wear_mask && !smoker.incapacitated)
long_exhale(smoker)
if(dropee.get_item_by_slot(ITEM_SLOT_MASK) == src && !dropee.incapacitated)
long_exhale(dropee)
UnregisterSignal(dropee, list(COMSIG_HUMAN_FORCESAY, COMSIG_ATOM_DIR_CHANGE))
QDEL_NULL(mob_smoke)
@@ -373,9 +372,9 @@ CIGARETTE PACKETS ARE IN FANCY.DM
var/datum/gas_mixture/air = return_air()
if (!isnull(air) && air.has_gas(/datum/gas/oxygen, 1))
return TRUE
if (!iscarbon(user))
if (!ishuman(user))
return FALSE
var/mob/living/carbon/the_smoker = user
var/mob/living/carbon/human/the_smoker = user
return the_smoker.can_breathe_helmet()
/obj/item/cigarette/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers)
@@ -466,7 +465,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
if(iscarbon(loc))
var/mob/living/carbon/smoker = loc
if(src == smoker.wear_mask)
if(smoker.get_item_by_slot(ITEM_SLOT_MASK) == src)
make_mob_smoke(smoker)
/obj/item/cigarette/extinguish()
@@ -563,7 +562,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
reagents.remove_all(to_smoke)
return
else
if(src != smoker.wear_mask)
if(smoker.get_item_by_slot(ITEM_SLOT_MASK) != src)
reagents.remove_all(to_smoke)
return
@@ -1181,7 +1180,7 @@ CIGARETTE PACKETS ARE IN FANCY.DM
return
var/mob/living/carbon/vaper = loc
if(!iscarbon(vaper) || src != vaper.wear_mask)
if(!iscarbon(vaper) || vaper.get_item_by_slot(ITEM_SLOT_MASK) != src)
reagents.remove_all(REAGENTS_METABOLISM)
return
@@ -237,7 +237,7 @@
//Intensity of the laser dot to pass to flash_act
var/severity = pick(0, 1, 2)
var/always_fail = FALSE
if(istype(target_humanoid.glasses, /obj/item/clothing/glasses/eyepatch) && prob(50))
if(istype(target_humanoid.get_item_by_slot(ITEM_SLOT_EYES), /obj/item/clothing/glasses/eyepatch) && prob(50))
always_fail = TRUE
//chance to actually hit the eyes depends on internal component
@@ -33,11 +33,9 @@
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/electropack/attack_hand(mob/user, list/modifiers)
if(iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.back)
to_chat(user, span_warning("You need help taking this off!"))
return
if(user.get_item_by_slot(ITEM_SLOT_BACK) == src)
to_chat(user, span_warning("You need help taking this off!"))
return
return ..()
/obj/item/electropack/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
@@ -33,7 +33,7 @@
uses--
carbon_imp_in.uncuff()
var/obj/item/clothing/shoes/shoes = carbon_imp_in.shoes
var/obj/item/clothing/shoes/shoes = carbon_imp_in.get_item_by_slot(ITEM_SLOT_FEET)
if(istype(shoes) && shoes.tied == SHOES_KNOTTED)
shoes.adjust_laces(SHOES_TIED, carbon_imp_in)
@@ -45,7 +45,7 @@
if(implanted_in.handcuffed || implanted_in.legcuffed)
return TRUE
var/obj/item/clothing/shoes/shoes = implanted_in.shoes
var/obj/item/clothing/shoes/shoes = implanted_in.get_item_by_slot(ITEM_SLOT_FEET)
if(istype(shoes) && shoes.tied == SHOES_KNOTTED)
return TRUE
@@ -192,10 +192,8 @@
if(!HAS_TRAIT(src, TRAIT_WIELDED))
return ""
var/in_mouth = ""
if(iscarbon(user))
var/mob/living/carbon/C = user
if(C.wear_mask)
in_mouth = ", barely missing [user.p_their()] nose"
if(iscarbon(user) && user.get_item_by_slot(ITEM_SLOT_MASK))
in_mouth = ", barely missing [user.p_their()] nose"
. = span_rose("[user] swings [user.p_their()] [name][in_mouth]. [user.p_They()] light[user.p_s()] [A.loc == user ? "[user.p_their()] [A.name]" : A] in the process.")
playsound(loc, hitsound, get_clamped_volume(), TRUE, -1)
add_fingerprint(user)
@@ -87,10 +87,8 @@
return ""
var/in_mouth = ""
if(iscarbon(user))
var/mob/living/carbon/carbon_user = user
if(carbon_user.wear_mask)
in_mouth = ", barely missing [carbon_user.p_their()] nose"
if(ishuman(user) && user.get_item_by_slot(ITEM_SLOT_MASK))
in_mouth = ", barely missing [user.p_their()] nose"
. = span_rose("[user] swings [user.p_their()] [name][in_mouth]. [user.p_They()] light[user.p_s()] [user.p_their()] [atom.name] in the process.")
playsound(loc, hitsound, get_clamped_volume(), TRUE, -1)
add_fingerprint(user)
@@ -162,10 +162,9 @@
if(tt.target_zone != BODY_ZONE_HEAD)
return
if(iscarbon(hit_atom))
var/mob/living/carbon/H = hit_atom
if(!H.wear_mask)
H.equip_to_slot_if_possible(src, ITEM_SLOT_MASK)
H.visible_message(span_warning("The plunger slams into [H]'s face!"), span_warning("The plunger suctions to your face!"))
var/mob/living/carbon/victim = hit_atom
if(victim.equip_to_slot_if_possible(src, ITEM_SLOT_MASK, disable_warning = TRUE))
victim.visible_message(span_warning("The plunger slams into [victim]'s face!"), span_warning("The plunger suctions to your face!"))
/obj/item/plunger/attack_self(mob/user)
. = ..()
+3 -3
View File
@@ -4,10 +4,10 @@
/datum/smite/knot_shoes/effect(client/user, mob/living/target)
. = ..()
if (!iscarbon(target))
to_chat(user, span_warning("This must be used on a carbon mob."), confidential = TRUE)
if (!ishuman(target))
to_chat(user, span_warning("This must be used on a human mob."), confidential = TRUE)
return
var/mob/living/carbon/dude = target
var/mob/living/carbon/human/dude = target
var/obj/item/clothing/shoes/sick_kicks = dude.shoes
if (!sick_kicks || sick_kicks.fastening_type == SHOES_SLIPON)
to_chat(user, span_warning("[dude] does not have knottable shoes!"), confidential = TRUE)
@@ -658,9 +658,9 @@
if(!istype(tool, /obj/item/organ/monster_core/regenerative_core/legion) || !holds_reagents)
return NONE
visible_message(span_boldwarning("As [user] shoves [tool] into [src], [src] begins to mutate."))
var/mob/living/carbon/wearer = loc
var/mob/living/carbon/human/wearer = loc
playsound(wearer, 'sound/effects/blob/attackblob.ogg', 60, TRUE)
wearer.temporarilyRemoveItemFromInventory(wearer.head, TRUE)
wearer.temporarilyRemoveItemFromInventory(src, TRUE)
wearer.equip_to_slot_if_possible(new /obj/item/clothing/head/helmet/changeling_hivehead/legion(wearer), ITEM_SLOT_HEAD, 1, 1, 1)
qdel(tool)
return ITEM_INTERACT_SUCCESS
@@ -704,9 +704,9 @@
///Stuff we want to do to our minions. This is in its own proc so subtypes can override this behaviour.
/datum/action/cooldown/hivehead_spawn_minions/proc/minion_additional_changes(mob/living/basic/minion)
var/mob/living/basic/bee/summoned_bee = minion
var/mob/living/carbon/wearer = owner
if(istype(summoned_bee) && length(wearer.head.reagents.reagent_list))
summoned_bee.assign_reagent(pick(wearer.head.reagents.reagent_list))
var/obj/item/clothing/head/helmet/changeling_hivehead/hivehead = owner.get_item_by_slot(ITEM_SLOT_HEAD)
if(istype(summoned_bee) && istype(hivehead) && length(hivehead.reagents.reagent_list))
summoned_bee.assign_reagent(pick(hivehead.reagents.reagent_list))
/obj/item/clothing/head/helmet/changeling_hivehead/legion
name = "legion hive head"
@@ -197,11 +197,11 @@
if(!.)
return
for(var/mob/living/carbon/M in view(6, myloc))
if(!istype(M.wear_mask, /obj/item/clothing/mask/gas/clown_hat) && !istype(M.wear_mask, /obj/item/clothing/mask/gas/mime) )
if(!M.wear_mask || M.dropItemToGround(M.wear_mask))
for(var/mob/living/carbon/human/victim in view(6, myloc))
if(!istype(victim.wear_mask, /obj/item/clothing/mask/gas/clown_hat) && !istype(victim.wear_mask, /obj/item/clothing/mask/gas/mime))
if(!victim.wear_mask || victim.dropItemToGround(victim.wear_mask))
var/obj/item/clothing/mask/fakemoustache/sticky/the_stash = new /obj/item/clothing/mask/fakemoustache/sticky()
M.equip_to_slot_or_del(the_stash, ITEM_SLOT_MASK, TRUE, TRUE, TRUE, TRUE)
victim.equip_to_slot_or_del(the_stash, ITEM_SLOT_MASK, TRUE, TRUE, TRUE, TRUE)
/obj/item/clothing/mask/fakemoustache/sticky
var/unstick_time = 600
@@ -64,7 +64,7 @@
human_owner.SetAllImmobility(0)
var/mob/living/carbon/carbon_owner = owner
carbon_owner.uncuff()
var/obj/item/clothing/shoes/shoes = carbon_owner.shoes
var/obj/item/clothing/shoes/shoes = carbon_owner.get_item_by_slot(ITEM_SLOT_FEET)
if(istype(shoes) && shoes.tied == SHOES_KNOTTED)
shoes.adjust_laces(SHOES_TIED, carbon_owner)
+2 -2
View File
@@ -22,8 +22,8 @@
return
if(iscarbon(hit_atom))
var/mob/living/carbon/H = hit_atom
if(istype(H.head, /obj/item))
var/obj/item/WH = H.head
var/obj/item/WH = H.get_item_by_slot(ITEM_SLOT_HEAD)
if(istype(WH))
///check if the item has NODROP
if(HAS_TRAIT(WH, TRAIT_NODROP))
H.visible_message(span_warning("[src] bounces off [H]'s [WH.name]!"), span_warning("[src] bounces off your [WH.name], falling to the floor."))
+6 -10
View File
@@ -47,11 +47,9 @@
/obj/item/clothing/head/costume/foilhat/mouse_drop_dragged(atom/over_object, mob/user)
//God Im sorry
if(!warped && iscarbon(user))
var/mob/living/carbon/C = user
if(src == C.head)
to_chat(C, span_userdanger("Why would you want to take this off? Do you want them to get into your mind?!"))
return
if(!warped && user.get_item_by_slot(ITEM_SLOT_HEAD) == src)
to_chat(user, span_userdanger("Why would you want to take this off? Do you want them to get into your mind?!"))
return
return ..()
/obj/item/clothing/head/costume/foilhat/dropped(mob/user)
@@ -80,11 +78,9 @@
to_chat(target, span_warning("Your zealous conspirationism rapidly dissipates as the donned hat warps up into a ruined mess. All those theories starting to sound like nothing but a ridicolous fanfare."))
/obj/item/clothing/head/costume/foilhat/attack_hand(mob/user, list/modifiers)
if(!warped && iscarbon(user))
var/mob/living/carbon/wearer = user
if(src == wearer.head)
to_chat(user, span_userdanger("Why would you want to take this off? Do you want them to get into your mind?!"))
return
if(!warped && user.get_item_by_slot(ITEM_SLOT_HEAD) == src)
to_chat(user, span_userdanger("Why would you want to take this off? Do you want them to get into your mind?!"))
return
return ..()
/obj/item/clothing/head/costume/foilhat/microwave_act(obj/machinery/microwave/microwave_source, mob/microwaver, randomize_pixel_offset)
+3 -5
View File
@@ -68,11 +68,9 @@
AddElement(/datum/element/muffles_speech)
/obj/item/clothing/mask/breath/muzzle/attack_paw(mob/user, list/modifiers)
if(iscarbon(user))
var/mob/living/carbon/carbon_user = user
if(src == carbon_user.wear_mask)
to_chat(user, span_warning("You need help taking this off!"))
return
if(user.get_item_by_slot(ITEM_SLOT_MASK) == src)
to_chat(user, span_warning("You need help taking this off!"))
return
return ..()
/obj/item/clothing/mask/breath/muzzle/examine_tags(mob/user)
+3 -5
View File
@@ -14,11 +14,9 @@
AddElement(/datum/element/muffles_speech)
/obj/item/clothing/mask/muzzle/attack_paw(mob/user, list/modifiers)
if(iscarbon(user))
var/mob/living/carbon/carbon_user = user
if(src == carbon_user.wear_mask)
to_chat(user, span_warning("You need help taking this off!"))
return
if(user.get_item_by_slot(ITEM_SLOT_MASK) == src)
to_chat(user, span_warning("You need help taking this off!"))
return
return ..()
/obj/item/clothing/mask/muzzle/tape
@@ -44,7 +44,7 @@
/datum/custom_order/moth_clothing/New(mob/living/basic/robot_customer/customer, datum/venue/our_venue)
var/datum/weakref/portal_ref = our_venue.current_visitors[customer]
var/obj/machinery/restaurant_portal/portal = portal_ref.resolve()
var/mob/living/carbon/buffet = portal?.turned_on_portal?.resolve()
var/mob/living/carbon/human/buffet = portal?.turned_on_portal?.resolve()
if (!istype(buffet)) // Always asks for the clothes that you have on, but this is a fallback.
wanted_clothing_type = pick_weight(list(
/obj/item/clothing/head/utility/chefhat = 3,
@@ -306,7 +306,7 @@
// If it takes any more effort, it loses a bit of the comedy.
// Therefore, only show up if it's reasonable for that gag to happen.
/datum/customer_data/moth/can_use(datum/venue/venue, obj/machinery/restaurant_portal/portal)
var/mob/living/carbon/buffet = portal.turned_on_portal?.resolve()
var/mob/living/carbon/human/buffet = portal.turned_on_portal?.resolve()
if (!istype(buffet))
return FALSE
if(QDELETED(buffet.head) && QDELETED(buffet.gloves) && QDELETED(buffet.shoes))
+5 -5
View File
@@ -274,11 +274,11 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
SEND_SIGNAL(target_mob, COMSIG_LIVING_BLESSED, user, src, bless_result)
return
if(iscarbon(target_mob))
var/mob/living/carbon/carbon_target = target_mob
if(!istype(carbon_target.head, /obj/item/clothing/head/helmet))
carbon_target.adjust_organ_loss(ORGAN_SLOT_BRAIN, 5, 60)
carbon_target.balloon_alert(carbon_target, "you feel dumber!")
if(ishuman(target_mob))
var/mob/living/carbon/human/human_target = target_mob
if(!istype(human_target.head, /obj/item/clothing/head/helmet))
human_target.adjust_organ_loss(ORGAN_SLOT_BRAIN, 5, 60)
human_target.balloon_alert(human_target, "you feel dumber!")
target_mob.visible_message(span_danger("[user] beats [target_mob] over the head with [src]!"), \
span_userdanger("[user] beats [target_mob] over the head with [src]!"))
playsound(target_mob, SFX_PUNCH, 25, TRUE, -1)
@@ -130,12 +130,9 @@
return FALSE
if(attached)
return FALSE
if(!iscarbon(hit_mob))
if(!ishuman(hit_mob))
return FALSE
// disallowed carbons
if(isalien(hit_mob))
return FALSE
var/mob/living/carbon/target = hit_mob
var/mob/living/carbon/human/target = hit_mob
// gotta have a head to be implanted (no changelings or sentient plants)
if(!target.get_bodypart(BODY_ZONE_HEAD))
return FALSE
@@ -149,8 +146,8 @@
//check if not carbon/alien/has facehugger already/ect.
if(!valid_to_attach(hit_mob))
return FALSE
var/mob/living/carbon/target = hit_mob
if(target.wear_mask && istype(target.wear_mask, /obj/item/clothing/mask/facehugger))
var/mob/living/carbon/human/target = hit_mob
if(istype(target.wear_mask, /obj/item/clothing/mask/facehugger))
return FALSE
// passed initial checks - time to leap!
target.visible_message(span_danger("[src] leaps at [target]'s face!"), \
@@ -201,14 +198,9 @@
attached = 0
/obj/item/clothing/mask/facehugger/proc/impregnate_target(mob/living/target)
if(!target || target.stat == DEAD) //was taken off or something
if(!target || target.stat == DEAD || target.get_item_by_slot(ITEM_SLOT_MASK) != src) //was taken off or something
return
if(iscarbon(target))
var/mob/living/carbon/C = target
if(C.wear_mask != src)
return
if(!sterile)
target.visible_message(span_danger("[src] falls limp after violating [target]'s face!"), \
span_userdanger("[src] falls limp after violating your face!"))
+25 -43
View File
@@ -476,38 +476,7 @@
if(A.update_remote_sight(src)) //returns 1 if we override all other sight updates.
return
if(glasses)
new_sight |= glasses.vision_flags
if(glasses.invis_override)
set_invis_see(glasses.invis_override)
else
set_invis_see(min(glasses.invis_view, see_invisible))
if(!isnull(glasses.lighting_cutoff))
lighting_cutoff = max(lighting_cutoff, glasses.lighting_cutoff)
if(length(glasses.color_cutoffs))
lighting_color_cutoffs = blend_cutoff_colors(lighting_color_cutoffs, glasses.color_cutoffs)
if(HAS_TRAIT(src, TRAIT_TRUE_NIGHT_VISION))
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_HIGH)
if(HAS_TRAIT(src, TRAIT_MESON_VISION))
new_sight |= SEE_TURFS
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_MEDIUM)
if(HAS_TRAIT(src, TRAIT_THERMAL_VISION))
new_sight |= SEE_MOBS
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_MEDIUM)
if (HAS_TRAIT(src, TRAIT_MINOR_NIGHT_VISION))
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_LOW)
if(HAS_TRAIT(src, TRAIT_XRAY_VISION))
new_sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS
if(HAS_TRAIT(src, TRAIT_ECHOLOCATOR))
new_sight |= SEE_MOBS|SEE_TURFS
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_FULLBRIGHT)
new_sight |= get_sight_and_cutoffs()
if(SSmapping.level_trait(z, ZTRAIT_NOXRAY))
new_sight = NONE
@@ -515,6 +484,30 @@
set_sight(new_sight)
return ..()
/// Modifies lighting_cutoff/lighting_color_cutoffs/see_invisible and returns additional sight flags to apply
/mob/living/carbon/proc/get_sight_and_cutoffs()
. = NONE
if(HAS_TRAIT(src, TRAIT_TRUE_NIGHT_VISION))
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_HIGH)
if(HAS_TRAIT(src, TRAIT_MESON_VISION))
. |= SEE_TURFS
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_MEDIUM)
if(HAS_TRAIT(src, TRAIT_THERMAL_VISION))
. |= SEE_MOBS
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_MEDIUM)
if (HAS_TRAIT(src, TRAIT_MINOR_NIGHT_VISION))
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_LOW)
if(HAS_TRAIT(src, TRAIT_XRAY_VISION))
. |= SEE_TURFS|SEE_MOBS|SEE_OBJS
if(HAS_TRAIT(src, TRAIT_ECHOLOCATOR))
. |= SEE_MOBS|SEE_TURFS
lighting_cutoff = max(lighting_cutoff, LIGHTING_CUTOFF_FULLBRIGHT)
/**
* Calculates how visually impaired the mob is by their equipment and other factors
*
@@ -1169,9 +1162,6 @@
if (ismecha(loc))
return FALSE
if (wearing_shock_proof_gloves())
return FALSE
if(!get_powernet_info_from_source(power_source))
return FALSE
@@ -1180,10 +1170,6 @@
return TRUE
/// Returns if the carbon is wearing shock proof gloves
/mob/living/carbon/proc/wearing_shock_proof_gloves()
return gloves?.siemens_coefficient == 0
/// Modifies max_skillchip_count and updates active skillchips
/mob/living/carbon/proc/adjust_skillchip_complexity_modifier(delta)
skillchip_complexity_modifier += delta
@@ -1268,8 +1254,6 @@
return TRUE
if((acid_power * acid_volume) < ACID_LEVEL_HANDBURN)
return TRUE
if(gloves?.resistance_flags & (UNACIDABLE | ACID_PROOF))
return TRUE
return FALSE
/**
@@ -1281,8 +1265,6 @@
return TRUE
if(HAS_TRAIT(src, TRAIT_RESISTHEAT) || HAS_TRAIT(src, TRAIT_RESISTHEATHANDS))
return TRUE
if(gloves?.max_heat_protection_temperature >= BURNING_ITEM_MINIMUM_TEMPERATURE)
return TRUE
return FALSE
/// Goes through the organs and bodyparts of the mob and updates their blood_dna_info, in case their blood type has changed (via set_species() or otherwise)
@@ -5,17 +5,9 @@
if(is_blind() && !is_blind_from(list(UNCONSCIOUS_TRAIT, HYPNOCHAIR_TRAIT)))
return INFINITY //For all my homies that can not see in the world
var/obj/item/organ/eyes/eyes = get_organ_slot(ORGAN_SLOT_EYES)
if(eyes)
. += eyes.flash_protect
else
if(!eyes)
return INFINITY //Can't get flashed without eyes
if(isclothing(head)) //Adds head protection
var/obj/item/clothing/helmet = head
. += helmet.flash_protect
if(isclothing(glasses)) //Glasses
. += glasses.flash_protect
if(isclothing(wear_mask)) //Mask
. += wear_mask.flash_protect
. += eyes.flash_protect
/mob/living/carbon/sound_damage(damage, deafen)
if(HAS_TRAIT(src, TRAIT_GODMODE))
@@ -32,42 +24,16 @@
var/obj/item/organ/ears/ears = get_organ_slot(ORGAN_SLOT_EARS)
return ..() + ears?.bang_protect
/mob/living/carbon/is_mouth_covered(check_flags = ALL)
if((check_flags & ITEM_SLOT_HEAD) && head && (head.flags_cover & HEADCOVERSMOUTH))
return head
if((check_flags & ITEM_SLOT_MASK) && wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH))
return wear_mask
return null
/mob/living/carbon/is_eyes_covered(check_flags = ALL)
if((check_flags & ITEM_SLOT_HEAD) && head && (head.flags_cover & HEADCOVERSEYES))
return head
if((check_flags & ITEM_SLOT_MASK) && wear_mask && (wear_mask.flags_cover & MASKCOVERSEYES))
return wear_mask
if((check_flags & ITEM_SLOT_EYES) && glasses && (glasses.flags_cover & GLASSESCOVERSEYES))
return glasses
return null
/mob/living/carbon/is_pepper_proof(check_flags = ALL)
var/obj/item/organ/eyes/eyes = get_organ_by_type(/obj/item/organ/eyes)
if(eyes && eyes.pepperspray_protect)
return eyes
if((check_flags & ITEM_SLOT_HEAD) && head && (head.flags_cover & PEPPERPROOF))
return head
if((check_flags & ITEM_SLOT_MASK) && wear_mask && (wear_mask.flags_cover & PEPPERPROOF))
return wear_mask
return null
/mob/living/carbon/is_ears_covered()
for(var/obj/item/worn_thing as anything in get_equipped_items(INCLUDE_ABSTRACT))
if(worn_thing.flags_cover & EARS_COVERED)
return worn_thing
return null
/mob/living/carbon/check_projectile_dismemberment(obj/projectile/proj, def_zone)
var/obj/item/bodypart/affecting = get_bodypart(def_zone)
if(affecting && affecting.can_dismember() && !(affecting.bodypart_flags & BODYPART_UNREMOVABLE) && affecting.get_damage() >= (affecting.max_damage - proj.dismemberment))
@@ -364,8 +330,8 @@
else
add_mood_event("tailpulled", /datum/mood_event/tailpulled)
else if ((helper.zone_selected == BODY_ZONE_PRECISE_GROIN) && (istype(head, /obj/item/clothing/head/costume/kitty) || istype(head, /obj/item/clothing/head/collectable/kitty)))
var/obj/item/clothing/head/faketail = head
else if ((helper.zone_selected == BODY_ZONE_PRECISE_GROIN) && (istype(get_item_by_slot(ITEM_SLOT_HEAD), /obj/item/clothing/head/costume/kitty) || istype(get_item_by_slot(ITEM_SLOT_HEAD), /obj/item/clothing/head/collectable/kitty)))
var/obj/item/clothing/head/faketail = get_item_by_slot(ITEM_SLOT_HEAD) // Should probably be COMSIG_CARBON_PRE_MISC_HELP
helper.visible_message(span_danger("[helper] pulls on [src]'s tail... and it rips off!"), \
null, span_hear("You hear a ripping sound."), DEFAULT_MESSAGE_RANGE, list(helper, src))
to_chat(helper, span_danger("You pull on [src]'s tail... and it rips off!"))
@@ -518,21 +484,6 @@
else if(damage == 0 && prob(20)) // just enough protection
to_chat(src, span_notice("Something bright flashes in the corner of your vision!"))
/mob/living/carbon/damage_clothes(damage_amount, damage_type = BRUTE, damage_flag = 0, def_zone)
if(damage_type != BRUTE && damage_type != BURN)
return
damage_amount *= 0.5 //0.5 multiplier for balance reason, we don't want clothes to be too easily destroyed
if(!def_zone || def_zone == BODY_ZONE_HEAD)
var/obj/item/clothing/hit_clothes
if(wear_mask)
hit_clothes = wear_mask
if(wear_neck)
hit_clothes = wear_neck
if(head)
hit_clothes = head
if(hit_clothes)
hit_clothes.take_damage(damage_amount, damage_type, damage_flag, 0)
/mob/living/carbon/adjust_oxy_loss(amount, updating_health = TRUE, forced, required_biotype)
if(!forced && HAS_TRAIT(src, TRAIT_NOBREATH))
amount = min(amount, 0) //Prevents oxy damage but not healing
@@ -31,23 +31,10 @@
var/old_disgust = 0
//inventory slots
var/obj/item/back = null
var/obj/item/clothing/mask/wear_mask = null
var/obj/item/clothing/neck/wear_neck = null
/// Equipped air tank. Never set this manually.
var/obj/item/tank/internal = null
/// "External" air tank. Never set this manually. Not required to stay directly equipped on the mob (i.e. could be a machine or MOD suit module).
var/obj/item/tank/external = null
var/obj/item/head = null
///only used by humans
var/obj/item/clothing/gloves = null
///only used by humans.
var/obj/item/clothing/shoes/shoes = null
///only used by humans.
var/obj/item/clothing/glasses/glasses = null
///only used by humans.
var/obj/item/clothing/ears = null
/// DNA is carbon-only, and ideally you should be accessing it through has_dna(), but you can access it directly if you know you're working with a carbon mob
var/datum/dna/dna = null
@@ -329,35 +329,6 @@
overlays_standing[WOUND_LAYER] = wound_overlay
apply_overlay(WOUND_LAYER)
/mob/living/carbon/update_worn_mask()
remove_overlay(FACEMASK_LAYER)
hud_used?.update_inventory_slot(ITEM_SLOT_MASK)
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(wear_mask && !(obscured_slots & HIDEMASK))
overlays_standing[FACEMASK_LAYER] = wear_mask.build_worn_icon(default_layer = FACEMASK_LAYER, default_icon_file = 'icons/mob/clothing/mask.dmi', bodyshape = bodyshape)
apply_overlay(FACEMASK_LAYER)
/mob/living/carbon/update_worn_neck()
remove_overlay(NECK_LAYER)
hud_used?.update_inventory_slot(ITEM_SLOT_NECK)
if(wear_neck && !(obscured_slots & HIDENECK))
overlays_standing[NECK_LAYER] = wear_neck.build_worn_icon(default_layer = NECK_LAYER, default_icon_file = 'icons/mob/clothing/neck.dmi', bodyshape = bodyshape)
apply_overlay(NECK_LAYER)
/mob/living/carbon/update_worn_back()
remove_overlay(BACK_LAYER)
hud_used?.update_inventory_slot(ITEM_SLOT_BACK)
if(back)
overlays_standing[BACK_LAYER] = back.build_worn_icon(default_layer = BACK_LAYER, default_icon_file = 'icons/mob/clothing/back.dmi', bodyshape = bodyshape)
apply_overlay(BACK_LAYER)
/mob/living/carbon/update_worn_legcuffs()
remove_overlay(LEGCUFF_LAYER)
clear_alert("legcuffed")
@@ -369,19 +340,6 @@
apply_overlay(LEGCUFF_LAYER)
throw_alert("legcuffed", /atom/movable/screen/alert/restrained/legcuffed, new_master = src.legcuffed)
/mob/living/carbon/update_worn_head()
remove_overlay(HEAD_LAYER)
hud_used?.update_inventory_slot(ITEM_SLOT_HEAD)
if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated
return
if(head && !(obscured_slots & HIDEHEADGEAR))
overlays_standing[HEAD_LAYER] = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = 'icons/mob/clothing/head/default.dmi', bodyshape = bodyshape)
apply_overlay(HEAD_LAYER)
/mob/living/carbon/update_worn_handcuffs()
remove_overlay(HANDCUFF_LAYER)
hud_used?.update_inventory_slot(ITEM_SLOT_HANDS)
+10 -33
View File
@@ -362,12 +362,6 @@
var/t_his = p_their()
var/t_has = p_have()
var/t_is = p_are()
//head
if(head && !(obscured_slots & HIDEHEADGEAR) && !HAS_TRAIT(head, TRAIT_EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [head.examine_title(user)] on [t_his] head."
//back
if(back && !HAS_TRAIT(back, TRAIT_EXAMINE_SKIP))
. += "[t_He] [t_has] [back.examine_title(user)] on [t_his] back."
//Hands
for(var/obj/item/held_thing in held_items)
if((held_thing.item_flags & (ABSTRACT|HAND_ITEM)) || HAS_TRAIT(held_thing, TRAIT_EXAMINE_SKIP))
@@ -378,39 +372,16 @@
continue
var/obj/item/corresponding_item = get_item_for_held_index(part.held_index) || part
. += "[t_He] [t_has] a [corresponding_item.examine_title(user)] in place of [t_his] [initial(part.plaintext_zone)]."
//gloves
if(gloves && !(obscured_slots & HIDEGLOVES) && !HAS_TRAIT(gloves, TRAIT_EXAMINE_SKIP))
. += "[t_He] [t_has] [gloves.examine_title(user)] on [t_his] hands."
else if(GET_ATOM_BLOOD_DECAL_LENGTH(src) && num_hands)
var/list/blood_stains = GET_ATOM_BLOOD_DECALS(src)
var/datum/blood_type/blood_type = blood_stains[blood_stains[length(blood_stains)]]
var/blood_descriptior = "blood"
if(istype(blood_type))
blood_descriptior = LOWER_TEXT(blood_type.get_blood_name())
. += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "][blood_descriptior]-stained hand[num_hands > 1 ? "s" : ""]!")
//handcuffed?
if(handcuffed)
var/cables_or_cuffs = istype(handcuffed, /obj/item/restraints/handcuffs/cable) ? "restrained with cable" : "handcuffed"
. += span_warning("[t_He] [t_is] [icon2html(handcuffed, user)] [cables_or_cuffs]!")
//shoes
if(shoes && !(obscured_slots & HIDESHOES) && !HAS_TRAIT(shoes, TRAIT_EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [shoes.examine_title(user)] on [t_his] feet."
//mask
if(wear_mask && !(obscured_slots & HIDEMASK) && !HAS_TRAIT(wear_mask, TRAIT_EXAMINE_SKIP))
. += "[t_He] [t_has] [wear_mask.examine_title(user)] on [t_his] face."
if(wear_neck && !(obscured_slots & HIDENECK) && !HAS_TRAIT(wear_neck, TRAIT_EXAMINE_SKIP))
. += "[t_He] [t_is] wearing [wear_neck.examine_title(user)] around [t_his] neck."
//eyes
if(!(obscured_slots & HIDEEYES))
if(glasses && !HAS_TRAIT(glasses, TRAIT_EXAMINE_SKIP))
. += "[t_He] [t_has] [glasses.examine_title(user)] covering [t_his] eyes."
else if(HAS_TRAIT(src, TRAIT_UNNATURAL_RED_GLOWY_EYES))
if(HAS_TRAIT(src, TRAIT_UNNATURAL_RED_GLOWY_EYES))
. += span_warning("<B>[t_His] eyes are glowing with an unnatural red aura!</B>")
else if(HAS_TRAIT(src, TRAIT_BLOODSHOT_EYES))
. += span_warning("<B>[t_His] eyes are bloodshot!</B>")
//ears
if(ears && !(obscured_slots & HIDEEARS) && !HAS_TRAIT(ears, TRAIT_EXAMINE_SKIP))
. += "[t_He] [t_has] [ears.examine_title(user)] on [t_his] ears."
// Yes there's a lot of copypasta here, we can improve this later when carbons are less dumb in general
/mob/living/carbon/human/get_clothing_examine_info(mob/living/user)
@@ -483,9 +454,15 @@
//gloves
if(gloves && !(obscured_slots & HIDEGLOVES) && !HAS_TRAIT(gloves, TRAIT_EXAMINE_SKIP))
. += "[t_He] [t_has] [gloves.examine_title(user)] on [t_his] hands."
else if(GET_ATOM_BLOOD_DECAL_LENGTH(src) || blood_in_hands)
if(num_hands)
. += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "]blood-stained hand[num_hands > 1 ? "s" : ""]!")
else if(GET_ATOM_BLOOD_DECAL_LENGTH(src) && num_hands)
var/list/blood_stains = GET_ATOM_BLOOD_DECALS(src)
var/datum/blood_type/blood_type = blood_stains[blood_stains[length(blood_stains)]]
var/blood_descriptior = "blood"
if(istype(blood_type))
blood_descriptior = LOWER_TEXT(blood_type.get_blood_name())
. += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "][blood_descriptior]-stained hand[num_hands > 1 ? "s" : ""]!")
else if (blood_in_hands && num_hands)
. += span_warning("[t_He] [t_has] [num_hands > 1 ? "" : "a "]blood-stained hand[num_hands > 1 ? "s" : ""]!")
//handcuffed?
if(handcuffed)
var/cables_or_cuffs = istype(handcuffed, /obj/item/restraints/handcuffs/cable) ? "restrained with cable" : "handcuffed"
@@ -1075,6 +1075,35 @@
return FALSE
return head_covered || HAS_TRAIT(src, TRAIT_HEAD_ATMOS_SEALED)
/mob/living/carbon/human/should_electrocute(power_source)
if (gloves?.siemens_coefficient == 0)
return FALSE
return ..()
/mob/living/carbon/human/can_touch_acid(atom/acided_atom, acid_power, acid_volume)
if(gloves?.resistance_flags & (UNACIDABLE | ACID_PROOF))
return TRUE
return ..()
/mob/living/carbon/human/can_touch_burning(atom/burning_atom, acid_power, acid_volume)
if(gloves?.max_heat_protection_temperature >= BURNING_ITEM_MINIMUM_TEMPERATURE)
return TRUE
return ..()
/mob/living/carbon/human/get_sight_and_cutoffs()
. = ..()
if(!istype(glasses))
return
. |= glasses.vision_flags
if(glasses.invis_override)
set_invis_see(glasses.invis_override)
else
set_invis_see(min(glasses.invis_view, see_invisible))
if(!isnull(glasses.lighting_cutoff))
lighting_cutoff = max(lighting_cutoff, glasses.lighting_cutoff)
if(length(glasses.color_cutoffs))
lighting_color_cutoffs = blend_cutoff_colors(lighting_color_cutoffs, glasses.color_cutoffs)
/mob/living/carbon/human/species/abductor
race = /datum/species/abductor
@@ -18,7 +18,6 @@
organnum++
return (armorval/max(organnum, 1))
/mob/living/carbon/human/proc/check_armor(obj/item/bodypart/def_zone, damage_type)
if(!damage_type)
return 0
@@ -728,3 +727,39 @@
if(methods == NONE)
return
return ..()
/mob/living/carbon/human/is_mouth_covered(check_flags = ALL)
if((check_flags & ITEM_SLOT_HEAD) && head && (head.flags_cover & HEADCOVERSMOUTH))
return head
if((check_flags & ITEM_SLOT_MASK) && wear_mask && (wear_mask.flags_cover & MASKCOVERSMOUTH))
return wear_mask
return null
/mob/living/carbon/human/is_eyes_covered(check_flags = ALL)
if((check_flags & ITEM_SLOT_HEAD) && head && (head.flags_cover & HEADCOVERSEYES))
return head
if((check_flags & ITEM_SLOT_MASK) && wear_mask && (wear_mask.flags_cover & MASKCOVERSEYES))
return wear_mask
if((check_flags & ITEM_SLOT_EYES) && glasses && (glasses.flags_cover & GLASSESCOVERSEYES))
return glasses
return null
/mob/living/carbon/human/is_pepper_proof(check_flags = ALL)
. = ..()
if (.)
return
if((check_flags & ITEM_SLOT_HEAD) && head && (head.flags_cover & PEPPERPROOF))
return head
if((check_flags & ITEM_SLOT_MASK) && wear_mask && (wear_mask.flags_cover & PEPPERPROOF))
return wear_mask
/mob/living/carbon/human/get_eye_protection()
. = ..()
if(isclothing(head)) // Adds head protection
var/obj/item/clothing/helmet = head
. += helmet.flash_protect
if(isclothing(glasses)) // Glasses
. += glasses.flash_protect
if(isclothing(wear_mask)) // Mask
. += wear_mask.flash_protect
@@ -57,6 +57,14 @@
var/jumpsuit_style = PREF_SUIT //suit/skirt
//Equipment slots
var/obj/item/back = null
var/obj/item/head = null
var/obj/item/clothing/gloves = null
var/obj/item/clothing/ears = null
var/obj/item/clothing/glasses/glasses = null
var/obj/item/clothing/shoes/shoes = null
var/obj/item/clothing/neck/wear_neck = null
var/obj/item/clothing/mask/wear_mask = null
var/obj/item/clothing/wear_suit = null
var/obj/item/clothing/w_uniform = null
var/obj/item/belt = null
@@ -26,6 +26,8 @@
/mob/living/carbon/human/get_item_by_slot(slot_id)
switch(slot_id)
if(ITEM_SLOT_BACK)
return back
if(ITEM_SLOT_BELT)
return belt
if(ITEM_SLOT_ID)
@@ -38,6 +40,12 @@
return gloves
if(ITEM_SLOT_FEET)
return shoes
if(ITEM_SLOT_MASK)
return wear_mask
if(ITEM_SLOT_NECK)
return wear_neck
if(ITEM_SLOT_HEAD)
return head
if(ITEM_SLOT_OCLOTHING)
return wear_suit
if(ITEM_SLOT_ICLOTHING)
@@ -52,6 +60,9 @@
return ..()
/mob/living/carbon/human/get_slot_by_item(obj/item/looking_for)
if(looking_for == back)
return ITEM_SLOT_BACK
if(looking_for == belt)
return ITEM_SLOT_BELT
@@ -70,6 +81,15 @@
if(looking_for == head)
return ITEM_SLOT_HEAD
if(looking_for == wear_mask)
return ITEM_SLOT_MASK
if(looking_for == wear_neck)
return ITEM_SLOT_NECK
if(looking_for == head)
return ITEM_SLOT_HEAD
if(looking_for == shoes)
return ITEM_SLOT_FEET
@@ -90,40 +110,6 @@
return ..()
/mob/living/carbon/human/proc/get_body_slots()
return list(
back,
s_store,
handcuffed,
legcuffed,
wear_suit,
gloves,
shoes,
belt,
wear_id,
l_store,
r_store,
w_uniform
)
/mob/living/carbon/human/proc/get_head_slots()
return list(
head,
wear_mask,
wear_neck,
glasses,
ears,
)
/mob/living/carbon/human/proc/get_storage_slots()
return list(
back,
belt,
l_store,
r_store,
s_store,
)
/mob/living/carbon/human/get_visible_items()
var/list/visible_items = ..()
var/obj/item/clothing/under/under = w_uniform
@@ -139,6 +125,11 @@
var/not_handled = FALSE //Added in case we make this type path deeper one day
switch(slot)
if(ITEM_SLOT_BACK)
if(back)
return
back = equipping
update_worn_back()
if(ITEM_SLOT_BELT)
if(belt)
return
@@ -181,6 +172,21 @@
stop_pulling() //can't pull if restrained
update_mob_action_buttons() //certain action buttons will no longer be usable.
update_worn_oversuit()
if(ITEM_SLOT_MASK)
if(wear_mask)
return
wear_mask = equipping
update_worn_mask()
if(ITEM_SLOT_HEAD)
if(head)
return
head = equipping
update_worn_head()
if(ITEM_SLOT_NECK)
if(wear_neck)
return
wear_neck = equipping
update_worn_neck(equipping)
if(ITEM_SLOT_ICLOTHING)
if(w_uniform)
return
@@ -234,6 +240,22 @@
dropItemToGround(wear_id)
if(belt && !can_equip(belt, ITEM_SLOT_BELT, TRUE, ignore_equipped = TRUE))
dropItemToGround(belt)
else if(item_dropping == back)
back = null
if(!QDELETED(src))
update_worn_back()
else if(item_dropping == head)
head = null
if(!QDELETED(src))
update_worn_head()
else if(item_dropping == wear_mask)
wear_mask = null
if(!QDELETED(src))
update_worn_mask()
else if(item_dropping == wear_neck)
wear_neck = null
if(!QDELETED(src))
update_worn_neck(item_dropping)
else if(item_dropping == gloves)
gloves = null
if(!QDELETED(src))
@@ -429,3 +451,17 @@
new_bodypart.try_attach_limb(src, TRUE)
hand_bodyparts[i] = new_bodypart
..() //Don't redraw hands until we have organs for them
/// Returns the helmet if an air tank compatible helmet is equipped.
/mob/living/carbon/human/proc/can_breathe_helmet()
if (astype(head, /obj/item/clothing)?.clothing_flags & HEADINTERNALS)
return head
/// Returns the mask if an air tank compatible mask is equipped.
/mob/living/carbon/human/proc/can_breathe_mask()
if (astype(wear_mask, /obj/item/clothing)?.clothing_flags & MASKINTERNALS)
return wear_mask
/// Returns the object that allows us to breathe internals - tube implant, mask or helmet
/mob/living/carbon/human/can_breathe_internals()
return can_breathe_tube() || can_breathe_mask() || can_breathe_helmet()
+2 -68
View File
@@ -25,14 +25,6 @@
/mob/living/carbon/get_item_by_slot(slot_id)
switch(slot_id)
if(ITEM_SLOT_BACK)
return back
if(ITEM_SLOT_MASK)
return wear_mask
if(ITEM_SLOT_NECK)
return wear_neck
if(ITEM_SLOT_HEAD)
return head
if(ITEM_SLOT_HANDCUFFED)
return handcuffed
if(ITEM_SLOT_LEGCUFFED)
@@ -41,18 +33,6 @@
return ..()
/mob/living/carbon/get_slot_by_item(obj/item/looking_for)
if(looking_for == back)
return ITEM_SLOT_BACK
if(looking_for == wear_mask)
return ITEM_SLOT_MASK
if(looking_for == wear_neck)
return ITEM_SLOT_NECK
if(looking_for == head)
return ITEM_SLOT_HEAD
if(looking_for == handcuffed)
return ITEM_SLOT_HANDCUFFED
@@ -123,26 +103,6 @@
var/not_handled = FALSE
switch(slot)
if(ITEM_SLOT_BACK)
if(back)
return
back = equipping
update_worn_back()
if(ITEM_SLOT_MASK)
if(wear_mask)
return
wear_mask = equipping
update_worn_mask()
if(ITEM_SLOT_HEAD)
if(head)
return
head = equipping
update_worn_head()
if(ITEM_SLOT_NECK)
if(wear_neck)
return
wear_neck = equipping
update_worn_neck(equipping)
if(ITEM_SLOT_HANDCUFFED)
set_handcuffed(equipping)
if(ITEM_SLOT_LEGCUFFED)
@@ -193,23 +153,7 @@
if(!. || !item_dropping) //We don't want to set anything to null if the parent returned 0.
return
if(item_dropping == head)
head = null
if(!QDELETED(src))
update_worn_head()
else if(item_dropping == back)
back = null
if(!QDELETED(src))
update_worn_back()
else if(item_dropping == wear_mask)
wear_mask = null
if(!QDELETED(src))
update_worn_mask()
else if(item_dropping == wear_neck)
wear_neck = null
if(!QDELETED(src))
update_worn_neck(item_dropping)
else if(item_dropping == handcuffed)
if(item_dropping == handcuffed)
set_handcuffed(null)
if(buckled?.buckle_requires_restraints)
buckled.unbuckle_mob(src)
@@ -272,23 +216,13 @@
if((added_slots|removed_slots) & (HIDEJUMPSUIT|HIDEEARS|HIDEHAIR|HIDESNOUT|HIDEMUTWINGS|HIDEANTENNAE))
update_body()
/// Returns the helmet if an air tank compatible helmet is equipped.
/mob/living/carbon/proc/can_breathe_helmet()
if (astype(head, /obj/item/clothing)?.clothing_flags & HEADINTERNALS)
return head
/// Returns the mask if an air tank compatible mask is equipped.
/mob/living/carbon/proc/can_breathe_mask()
if (astype(wear_mask, /obj/item/clothing)?.clothing_flags & MASKINTERNALS)
return wear_mask
/// Returns the tube if a breathing tube is equipped.
/mob/living/carbon/proc/can_breathe_tube()
return get_organ_slot(ORGAN_SLOT_BREATHING_TUBE)
/// Returns the object that allows us to breathe internals - tube implant, mask or helmet
/mob/living/carbon/proc/can_breathe_internals()
return can_breathe_tube() || can_breathe_mask() || can_breathe_helmet()
return can_breathe_tube()
/// Returns truthy if air tank is open and mob lacks apparatus, or if the tank moved away from the mob.
/mob/living/carbon/proc/invalid_internals()
+4 -5
View File
@@ -121,12 +121,11 @@
message_animal_or_basic = initial(message_animal_or_basic)
if(!user.can_speak() || user.get_oxy_loss() >= 50)
return //stop the sound if oxyloss too high/cant speak
var/mob/living/carbon/carbon_user = user
// For masks that give unique death sounds
if(istype(carbon_user) && isclothing(carbon_user.wear_mask) && carbon_user.wear_mask.unique_death)
playsound(carbon_user, carbon_user.wear_mask.unique_death, 200, TRUE, TRUE)
return
if(user.death_sound)
var/obj/item/clothing/mask/mask = astype(user.get_item_by_slot(ITEM_SLOT_MASK), /obj/item/clothing/mask)
if(mask?.unique_death)
playsound(user, mask.unique_death, 200, TRUE, TRUE)
else if(user.death_sound)
playsound(user, user.death_sound, 200, TRUE, TRUE)
/datum/emote/living/drool
+5
View File
@@ -446,6 +446,11 @@ GAME_VERB_PROC(/mob, Cell, "Cell", "Admin")
/mob/proc/get_item_by_slot(slot_id) as /obj/item
return null
/mob/proc/get_items_by_slots(slot_ids)
. = list()
for (var/slot_id in bitfield_to_list(slot_ids))
. += get_item_by_slot(slot_id)
/// Gets what slot the item on the mob is held in.
/// Returns null if the item isn't in any slots on our mob.
/// Does not check if the passed item is null, which may result in unexpected outcoms.
+2 -2
View File
@@ -277,8 +277,8 @@
call_link(user, mod_link)
/obj/item/clothing/neck/link_scryer/proc/get_user()
var/mob/living/carbon/user = loc
return istype(user) && user.wear_neck == src ? user : null
var/mob/living/user = loc
return istype(user) && user.get_item_by_slot(ITEM_SLOT_NECK) == src ? user : null
/obj/item/clothing/neck/link_scryer/proc/can_call()
var/mob/living/user = loc
+1 -1
View File
@@ -483,7 +483,7 @@
if(!in_range(source, victim))
return FALSE
if(victim.wearing_shock_proof_gloves())
if(victim.get_item_by_slot(ITEM_SLOT_GLOVES)?.siemens_coefficient == 0)
SEND_SIGNAL(victim, COMSIG_LIVING_SHOCK_PREVENTED, power_source, source, siemens_coeff, dist_check)
return FALSE //to avoid spamming with insulated gloves on
@@ -496,12 +496,12 @@
if(exposed_mob.adjust_tox_loss(damage * 20, required_biotype = affected_biotype))
return
if(!(methods & VAPOR) || !iscarbon(exposed_mob))
if(!(methods & VAPOR) || !ishuman(exposed_mob))
return
var/mob/living/carbon/exposed_carbon = exposed_mob
if(!exposed_carbon.wear_mask)
exposed_carbon.adjust_tox_loss(damage, required_biotype = affected_biotype)
var/mob/living/carbon/human/exposed_human = exposed_mob
if(!exposed_human.wear_mask)
exposed_human.adjust_tox_loss(damage, required_biotype = affected_biotype)
/datum/reagent/toxin/plantbgone/weedkiller
name = "Weed Killer"
+6 -8
View File
@@ -401,17 +401,15 @@
playsound(user, SFX_SPARKS, rand(25,50), TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
throw_smoke(user)
// carbons always get a hat at least
var/mob/living/carbon/carbonius = user
//hat
var/obj/item/clothing/head/costume/disguise_hat = roll_costume(ITEM_SLOT_HEAD, HIDEMASK)
carbonius.dropItemToGround(carbonius.head)
carbonius.equip_to_slot_or_del(disguise_hat, ITEM_SLOT_HEAD)
if(!ishuman(carbonius))
if(!ishuman(user))
to_chat(user, span_notice("You have a peculiar feeling for a moment, but then it passes."))
return
var/mob/living/carbon/human/humerus = carbonius
var/mob/living/carbon/human/humerus = user
//hat
var/obj/item/clothing/head/costume/disguise_hat = roll_costume(ITEM_SLOT_HEAD, HIDEMASK)
humerus.dropItemToGround(humerus.head)
humerus.equip_to_slot_or_del(disguise_hat, ITEM_SLOT_HEAD)
// uniform
var/obj/item/clothing/under/costume/disguise_uniform = roll_costume(ITEM_SLOT_ICLOTHING)
humerus.dropItemToGround(humerus.w_uniform)
@@ -73,7 +73,7 @@
if(HAS_TRAIT(owner, TRAIT_SPLATTERCASTER))
shoe_to_cast = /obj/item/clothing/shoes/laceup
var/obj/item/clothing/shoes/shoes_to_tie = cast_on.shoes
var/obj/item/clothing/shoes/shoes_to_tie = cast_on.get_item_by_slot(ITEM_SLOT_FEET)
if(isnull(shoes_to_tie))
if(!summons_shoes)
@@ -41,7 +41,7 @@
victim.Knockdown(5 SECONDS)
// If someone's already cursed, don't try to give them another
if(istype(victim.back, /obj/item/storage/backpack/duffelbag/cursed))
if(istype(victim.get_item_by_slot(ITEM_SLOT_BACK), /obj/item/storage/backpack/duffelbag/cursed))
to_chat(caster, span_warning("The burden of [victim]'s duffel bag becomes too much, shoving them to the floor!"))
to_chat(victim, span_warning("The weight of this bag becomes overburdening!"))
return TRUE
@@ -57,7 +57,7 @@
conjured_duffel.forceMove(victim)
// Put it on their back first
if(victim.dropItemToGround(victim.back))
if(victim.dropItemToGround(victim.get_item_by_slot(ITEM_SLOT_BACK)))
victim.equip_to_slot_if_possible(conjured_duffel, ITEM_SLOT_BACK, TRUE, TRUE)
return TRUE
@@ -200,7 +200,7 @@
arm_owner.dropItemToGround(lost_cuffs, force = TRUE)
arm_owner.hud_used?.update_inventory_slot(ITEM_SLOT_HANDS, held_index)
if(arm_owner.num_hands == 0)
arm_owner.dropItemToGround(arm_owner.gloves, force = TRUE)
arm_owner.dropItemToGround(arm_owner.get_item_by_slot(ITEM_SLOT_GLOVES), force = TRUE)
arm_owner.update_worn_gloves() //to remove the bloody hands overlay
/obj/item/bodypart/leg/drop_limb(special, dismembered, move_to_floor = TRUE)
@@ -209,12 +209,12 @@
if(special || !leg_owner)
return
leg_owner.dropItemToGround(leg_owner.legcuffed, force = TRUE)
leg_owner.dropItemToGround(leg_owner.shoes, force = TRUE)
leg_owner.dropItemToGround(leg_owner.get_item_by_slot(ITEM_SLOT_FEET), force = TRUE)
/obj/item/bodypart/head/drop_limb(special, dismembered, move_to_floor = TRUE)
if(!special)
//Drop all worn head items
for(var/obj/item/head_item as anything in list(owner.glasses, owner.ears, owner.wear_mask, owner.head))
for(var/obj/item/head_item as anything in owner.get_items_by_slots(ITEM_SLOT_EYES | ITEM_SLOT_EARS | ITEM_SLOT_MASK | ITEM_SLOT_HEAD))
owner.dropItemToGround(head_item, force = TRUE)
//Handle dental implants