diff --git a/code/__DEFINES/cleaning.dm b/code/__DEFINES/cleaning.dm
index 7c954602215e3..79708cd152b62 100644
--- a/code/__DEFINES/cleaning.dm
+++ b/code/__DEFINES/cleaning.dm
@@ -29,3 +29,8 @@
#define CLEAN_SCRUB (CLEAN_WASH | CLEAN_TYPE_FINGERPRINTS | CLEAN_TYPE_FIBERS | CLEAN_TYPE_HARD_DECAL)
#define CLEAN_RAD CLEAN_TYPE_RADIATION
#define CLEAN_ALL ALL
+
+// Footprint sprites to use when making footprints in blood, oil, etc.
+#define FOOTPRINT_SPRITE_SHOES "shoes"
+#define FOOTPRINT_SPRITE_PAWS "paws"
+#define FOOTPRINT_SPRITE_CLAWS "claws"
diff --git a/code/__DEFINES/jobs.dm b/code/__DEFINES/jobs.dm
index 467b405f715e8..1d69d48e9d59f 100644
--- a/code/__DEFINES/jobs.dm
+++ b/code/__DEFINES/jobs.dm
@@ -84,6 +84,7 @@
#define JOB_BARTENDER "Bartender"
#define JOB_BOTANIST "Botanist"
#define JOB_COOK "Cook"
+#define JOB_CHEF "Chef" // Alternate cook title.
#define JOB_JANITOR "Janitor"
#define JOB_CLOWN "Clown"
#define JOB_MIME "Mime"
diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm
index 2e1eac6672d2a..d9514d735d0f1 100644
--- a/code/__DEFINES/mobs.dm
+++ b/code/__DEFINES/mobs.dm
@@ -120,7 +120,6 @@
#define SPECIES_NIGHTMARE "nightmare"
#define SPECIES_MONKEY "monkey"
#define SPECIES_MONKEY_FREAK "monkey_freak"
-#define SPECIES_MONKEY_HOLODECK "monkey_holodeck"
#define SPECIES_MONKEY_HUMAN_LEGGED "monkey_human_legged"
#define SPECIES_MOTH "moth"
#define SPECIES_MUSHROOM "mush"
diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm
index a79d4b385c20b..e1a60112c901f 100644
--- a/code/datums/components/bloodysoles.dm
+++ b/code/datums/components/bloodysoles.dm
@@ -21,6 +21,8 @@
/// The world.time when we last picked up blood
var/last_pickup
+ var/footprint_sprite = FOOTPRINT_SPRITE_SHOES
+
/datum/component/bloodysoles/Initialize()
if(!isclothing(parent))
return COMPONENT_INCOMPATIBLE
@@ -113,9 +115,9 @@
/**
* Find a blood decal on a turf that matches our last_blood_state
*/
-/datum/component/bloodysoles/proc/find_pool_by_blood_state(turf/turfLoc, typeFilter = null)
+/datum/component/bloodysoles/proc/find_pool_by_blood_state(turf/turfLoc, typeFilter = null, footprint_sprite)
for(var/obj/effect/decal/cleanable/blood/pool in turfLoc)
- if(pool.blood_state == last_blood_state && (!typeFilter || istype(pool, typeFilter)))
+ if(pool.blood_state == last_blood_state && pool.footprint_sprite == footprint_sprite && (!typeFilter || istype(pool, typeFilter)))
return pool
/**
@@ -171,23 +173,23 @@
return
var/half_our_blood = bloody_shoes[last_blood_state] / 2
-
+ var/footprint_sprite = wielder.get_footprint_sprite()
// Add footprints in old loc if we have enough cream
if(half_our_blood >= BLOOD_FOOTPRINTS_MIN)
var/turf/oldLocTurf = get_turf(OldLoc)
- var/obj/effect/decal/cleanable/blood/footprints/oldLocFP = find_pool_by_blood_state(oldLocTurf, /obj/effect/decal/cleanable/blood/footprints)
+ var/obj/effect/decal/cleanable/blood/footprints/oldLocFP = find_pool_by_blood_state(oldLocTurf, /obj/effect/decal/cleanable/blood/footprints, footprint_sprite)
if(oldLocFP)
// Footprints found in the tile we left, add us to it
add_parent_to_footprint(oldLocFP)
if (!(oldLocFP.exited_dirs & wielder.dir))
oldLocFP.exited_dirs |= wielder.dir
oldLocFP.update_appearance()
- else if(find_pool_by_blood_state(oldLocTurf))
+ else if(find_pool_by_blood_state(oldLocTurf, footprint_sprite = footprint_sprite))
// No footprints in the tile we left, but there was some other blood pool there. Add exit footprints on it
adjust_bloody_shoes(last_blood_state, half_our_blood)
update_icon()
- oldLocFP = new(oldLocTurf)
+ oldLocFP = new(oldLocTurf, footprint_sprite)
if(!QDELETED(oldLocFP)) ///prints merged
oldLocFP.blood_state = last_blood_state
oldLocFP.exited_dirs |= wielder.dir
@@ -207,7 +209,7 @@
adjust_bloody_shoes(last_blood_state, half_our_blood)
update_icon()
- var/obj/effect/decal/cleanable/blood/footprints/FP = new(get_turf(parent_atom))
+ var/obj/effect/decal/cleanable/blood/footprints/FP = new(get_turf(parent_atom), footprint_sprite)
if(!QDELETED(FP)) ///prints merged
FP.blood_state = last_blood_state
FP.entered_dirs |= wielder.dir
@@ -266,7 +268,8 @@
return COMPONENT_INCOMPATIBLE
parent_atom = parent
wielder = parent
-
+ if(footprint_sprite)
+ src.footprint_sprite = footprint_sprite
if(!bloody_feet)
bloody_feet = mutable_appearance('icons/effects/blood.dmi', "shoeblood", SHOES_LAYER)
diff --git a/code/datums/components/butchering.dm b/code/datums/components/butchering.dm
index 0cf6631f8074b..1f432efc73455 100644
--- a/code/datums/components/butchering.dm
+++ b/code/datums/components/butchering.dm
@@ -107,6 +107,12 @@
var/final_effectiveness = effectiveness - target.butcher_difficulty
var/bonus_chance = max(0, (final_effectiveness - 100) + bonus_modifier) //so 125 total effectiveness = 25% extra chance
+ if(target.flags_1 & HOLOGRAM_1)
+ butcher.visible_message(span_notice("[butcher] tries to butcher [target], but it vanishes."), \
+ span_notice("You try to butcher [target], but it vanishes."))
+ qdel(target)
+ return
+
for(var/result_typepath in target.butcher_results)
var/obj/remains = result_typepath
var/amount = target.butcher_results[remains]
diff --git a/code/datums/elements/decals/blood.dm b/code/datums/elements/decals/blood.dm
index 889ebb12904bd..ec09caed73d59 100644
--- a/code/datums/elements/decals/blood.dm
+++ b/code/datums/elements/decals/blood.dm
@@ -13,29 +13,20 @@
/datum/element/decal/blood/generate_appearance(_icon, _icon_state, _dir, _plane, _layer, _color, _alpha, _smoothing, source)
var/obj/item/I = source
- if(!_icon)
- _icon = 'icons/effects/blood.dmi'
- if(!_icon_state)
- _icon_state = "itemblood"
var/icon = I.icon
var/icon_state = I.icon_state
if(!icon || !icon_state)
// It's something which takes on the look of other items, probably
icon = I.icon
icon_state = I.icon_state
- var/static/list/blood_splatter_appearances = list()
- //try to find a pre-processed blood-splatter. otherwise, make a new one
- var/index = "[REF(icon)]-[icon_state]"
- pic = blood_splatter_appearances[index]
-
- if(!pic)
- var/icon/blood_splatter_icon = icon(I.icon, I.icon_state, , 1) //icon of the item that will become splattered
- var/icon/blood_icon = icon(_icon, _icon_state) //icon of the blood that we apply
- blood_icon.Scale(blood_splatter_icon.Width(), blood_splatter_icon.Height())
- blood_splatter_icon.Blend("#fff", ICON_ADD) //fills the icon_state with white (except where it's transparent)
- blood_splatter_icon.Blend(blood_icon, ICON_MULTIPLY) //adds blood and the remaining white areas become transparant
- pic = mutable_appearance(blood_splatter_icon, I.icon_state)
- blood_splatter_appearances[index] = pic
+ var/icon/icon_for_size = icon(icon, icon_state)
+ var/scale_factor_x = icon_for_size.Width()/world.icon_size
+ var/scale_factor_y = icon_for_size.Height()/world.icon_size
+ var/mutable_appearance/blood_splatter = mutable_appearance('icons/effects/blood.dmi', "itemblood", appearance_flags = RESET_COLOR) //MA of the blood that we apply
+ blood_splatter.transform = blood_splatter.transform.Scale(scale_factor_x, scale_factor_y)
+ blood_splatter.blend_mode = BLEND_INSET_OVERLAY
+ blood_splatter.color = _color
+ pic = blood_splatter
return TRUE
/datum/element/decal/blood/proc/get_examine_name(datum/source, mob/user, list/override)
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index d286f8ee6043d..a6e9936b1d9cf 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -129,15 +129,16 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
// 60+: Service
JOB_HEAD_OF_PERSONNEL = 60,
JOB_BARTENDER = 61,
- JOB_COOK = 62,
- JOB_BOTANIST = 63,
- JOB_CURATOR = 64,
- JOB_CHAPLAIN = 65,
- JOB_CLOWN = 66,
- JOB_MIME = 67,
- JOB_JANITOR = 68,
- JOB_LAWYER = 69,
- JOB_PSYCHOLOGIST = 71,
+ JOB_CHEF = 62,
+ JOB_COOK = 63,
+ JOB_BOTANIST = 64,
+ JOB_CURATOR = 65,
+ JOB_CHAPLAIN = 66,
+ JOB_CLOWN = 67,
+ JOB_MIME = 68,
+ JOB_JANITOR = 69,
+ JOB_LAWYER = 71,
+ JOB_PSYCHOLOGIST = 72,
// 200-229: Centcom
JOB_CENTCOM_ADMIRAL = 200,
JOB_CENTCOM = 201,
diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm
index f789da69cb52e..4a275199f3f55 100644
--- a/code/game/objects/effects/decals/cleanable/humans.dm
+++ b/code/game/objects/effects/decals/cleanable/humans.dm
@@ -12,6 +12,7 @@
var/dryname = "dried blood" //when the blood lasts long enough, it becomes dry and gets a new name
var/drydesc = "Looks like it's been here a while. Eew." //as above
var/drytime = 0
+ var/footprint_sprite = null
/obj/effect/decal/cleanable/blood/Initialize(mapload)
. = ..()
@@ -230,7 +231,7 @@
name = "footprints"
desc = "WHOSE FOOTPRINTS ARE THESE?"
icon = 'icons/effects/footprints.dmi'
- icon_state = "blood1"
+ icon_state = "blood_shoes_enter"
random_icon_states = null
blood_state = BLOOD_STATE_HUMAN //the icon state to load images from
var/entered_dirs = 0
@@ -245,12 +246,13 @@
dryname = "dried footprints"
drydesc = "HMM... SOMEONE WAS HERE!"
-/obj/effect/decal/cleanable/blood/footprints/Initialize(mapload)
+/obj/effect/decal/cleanable/blood/footprints/Initialize(mapload, footprint_sprite)
+ src.footprint_sprite = footprint_sprite
. = ..()
icon_state = "" //All of the footprint visuals come from overlays
if(mapload)
entered_dirs |= dir //Keep the same appearance as in the map editor
- update_appearance()
+ update_appearance(mapload ? (ALL) : (UPDATE_NAME | UPDATE_DESC))
//Rotate all of the footprint directions too
/obj/effect/decal/cleanable/blood/footprints/setDir(newdir)
@@ -272,6 +274,21 @@
update_appearance()
return ..()
+/obj/effect/decal/cleanable/blood/footprints/update_name(updates)
+ switch(footprint_sprite)
+ if(FOOTPRINT_SPRITE_CLAWS)
+ name = "clawprints"
+ if(FOOTPRINT_SPRITE_SHOES)
+ name = "footprints"
+ if(FOOTPRINT_SPRITE_PAWS)
+ name = "pawprints"
+ dryname = "dried [name]"
+ return ..()
+
+/obj/effect/decal/cleanable/blood/footprints/update_desc(updates)
+ desc = "WHOSE [uppertext(name)] ARE THESE?"
+ return ..()
+
/obj/effect/decal/cleanable/blood/footprints/update_icon()
. = ..()
alpha = min(BLOODY_FOOTPRINT_BASE_ALPHA + (255 - BLOODY_FOOTPRINT_BASE_ALPHA) * bloodiness / (BLOOD_ITEM_MAX / 2), 255)
@@ -286,22 +303,22 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
. = ..()
for(var/Ddir in GLOB.cardinals)
if(entered_dirs & Ddir)
- var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["entered-[blood_state]-[Ddir]"]
+ var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["entered-[footprint_sprite]-[blood_state]-[Ddir]"]
if(!bloodstep_overlay)
- GLOB.bloody_footprints_cache["entered-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]1", dir = Ddir)
+ GLOB.bloody_footprints_cache["entered-[footprint_sprite]-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]_[footprint_sprite]_enter", dir = Ddir)
. += bloodstep_overlay
if(exited_dirs & Ddir)
- var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["exited-[blood_state]-[Ddir]"]
+ var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["exited-[footprint_sprite]-[blood_state]-[Ddir]"]
if(!bloodstep_overlay)
- GLOB.bloody_footprints_cache["exited-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]2", dir = Ddir)
+ GLOB.bloody_footprints_cache["exited-[footprint_sprite]-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]_[footprint_sprite]_exit", dir = Ddir)
. += bloodstep_overlay
/obj/effect/decal/cleanable/blood/footprints/examine(mob/user)
. = ..()
if((shoe_types.len + species_types.len) > 0)
- . += "You recognise the footprints as belonging to:"
+ . += "You recognise the [name] as belonging to:"
for(var/sole in shoe_types)
var/obj/item/clothing/item = sole
var/article = initial(item.gender) == PLURAL ? "Some" : "A"
@@ -311,14 +328,14 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache)
if(species == "unknown")
. += "Some feet."
else if(species == SPECIES_MONKEY)
- . += "[icon2html('icons/mob/human/human.dmi', user, "monkey")] Some monkey feet."
+ . += "[icon2html('icons/mob/human/human.dmi', user, "monkey")] Some monkey paws."
else if(species == SPECIES_HUMAN)
. += "[icon2html('icons/mob/human/bodyparts.dmi', user, "default_human_l_leg")] Some human feet."
else
. += "[icon2html('icons/mob/human/bodyparts.dmi', user, "[species]_l_leg")] Some [species] feet."
-/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/C)
- if(blood_state != C.blood_state) //We only replace footprints of the same type as us
+/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/blood/blood_decal)
+ if(blood_state != blood_decal.blood_state || footprint_sprite != blood_decal.footprint_sprite) //We only replace footprints of the same type as us
return FALSE
return ..()
diff --git a/code/game/objects/effects/spawners/random/entertainment.dm b/code/game/objects/effects/spawners/random/entertainment.dm
index 0a61cd1ab1fbb..3ad477b0294f3 100644
--- a/code/game/objects/effects/spawners/random/entertainment.dm
+++ b/code/game/objects/effects/spawners/random/entertainment.dm
@@ -51,14 +51,13 @@
loot = list(
/obj/item/coin/iron = 5,
/obj/item/coin/plastic = 5,
- /obj/item/coin/silver = 3,
- /obj/item/coin/plasma = 3,
+ /obj/item/coin/silver = 4,
+ /obj/item/coin/plasma = 4,
/obj/item/coin/uranium = 3,
/obj/item/coin/titanium = 3,
/obj/item/coin/diamond = 2,
/obj/item/coin/bananium = 2,
/obj/item/coin/adamantine = 2,
- /obj/item/coin/mythril = 2,
/obj/item/coin/runite = 2,
/obj/item/food/chococoin = 2,
/obj/item/coin/twoheaded = 1,
diff --git a/code/game/objects/items/devices/scanners/health_analyzer.dm b/code/game/objects/items/devices/scanners/health_analyzer.dm
index a27faee2094bc..ef922ed3a7d3c 100644
--- a/code/game/objects/items/devices/scanners/health_analyzer.dm
+++ b/code/game/objects/items/devices/scanners/health_analyzer.dm
@@ -219,7 +219,7 @@
if(ears.damage)
render_list += "Subject has [ears.damage > ears.maxHealth ? "permanent ": "temporary "]hearing damage.\n"
if(ears.deaf)
- render_list += "Subject is [ears.damage > ears.maxHealth ? "permanently ": "temporarily "] deaf.\n"
+ render_list += "Subject is [ears.damage > ears.maxHealth ? "permanently": "temporarily"] deaf.\n"
// Eye status
var/obj/item/organ/internal/eyes/eyes = carbontarget.get_organ_slot(ORGAN_SLOT_EYES)
diff --git a/code/game/objects/structures/maintenance.dm b/code/game/objects/structures/maintenance.dm
index 78a67198fefdc..f9ed6d93c1e9f 100644
--- a/code/game/objects/structures/maintenance.dm
+++ b/code/game/objects/structures/maintenance.dm
@@ -24,9 +24,8 @@ at the cost of risking a vicious bite.**/
/obj/item/restraints/handcuffs/cable/green = 1,
/obj/item/restraints/handcuffs/cable/pink = 1,
/obj/item/restraints/handcuffs/alien = 2,
- /obj/item/coin/bananium = 9,
+ /obj/item/coin/bananium = 10,
/obj/item/knife/butcher = 5,
- /obj/item/coin/mythril = 1,
)
diff --git a/code/modules/clothing/shoes/_shoes.dm b/code/modules/clothing/shoes/_shoes.dm
index d74bbbe56553b..fcf0de64a5e47 100644
--- a/code/modules/clothing/shoes/_shoes.dm
+++ b/code/modules/clothing/shoes/_shoes.dm
@@ -22,6 +22,7 @@
var/lace_time = 5 SECONDS
///An active alert
var/datum/weakref/our_alert_ref
+ var/footprint_sprite = FOOTPRINT_SPRITE_SHOES
/datum/armor/clothing_shoes
bio = 50
diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm
index 5cdc2d2b8416f..c21579626fe28 100644
--- a/code/modules/fishing/sources/source_types.dm
+++ b/code/modules/fishing/sources/source_types.dm
@@ -233,12 +233,12 @@
/obj/item/stack/ore/plasma = 3,
/mob/living/basic/mining/lobstrosity = 1,
/obj/effect/decal/remains/plasma = 1,
- /obj/item/stack/sheet/mineral/mythril = 1,
+ /obj/item/stack/sheet/mineral/runite = 1,
/obj/item/stack/sheet/mineral/adamantine = 1,
)
fish_counts = list(
/obj/item/stack/sheet/mineral/adamantine = 3,
- /obj/item/stack/sheet/mineral/mythril = 2,
+ /obj/item/stack/sheet/mineral/runite = 2,
)
/datum/fish_source/moisture_trap
diff --git a/code/modules/food_and_drinks/machinery/gibber.dm b/code/modules/food_and_drinks/machinery/gibber.dm
index a774d0126a2ea..62157177bdcaf 100644
--- a/code/modules/food_and_drinks/machinery/gibber.dm
+++ b/code/modules/food_and_drinks/machinery/gibber.dm
@@ -147,6 +147,12 @@
if(!occupant)
audible_message(span_hear("You hear a loud metallic grinding sound."))
return
+ if(occupant.flags_1 & HOLOGRAM_1)
+ audible_message(span_hear("You hear a very short metallic grinding sound."))
+ playsound(loc, 'sound/machines/hiss.ogg', 20, TRUE)
+ qdel(occupant)
+ set_occupant(null)
+ return
use_power(active_power_usage)
audible_message(span_hear("You hear a loud squelchy grinding sound."))
diff --git a/code/modules/forensics/_forensics.dm b/code/modules/forensics/_forensics.dm
index 6a06e549d2635..40b480182537e 100644
--- a/code/modules/forensics/_forensics.dm
+++ b/code/modules/forensics/_forensics.dm
@@ -70,6 +70,7 @@
var/atom/parent_atom = parent.resolve()
if (!isnull(parent_atom))
UnregisterSignal(parent_atom, list(COMSIG_COMPONENT_CLEAN_ACT))
+ parent = null
return ..()
/// Empties the fingerprints list
@@ -147,7 +148,9 @@
/// Adds a single fiber
/datum/forensics/proc/add_fibers(mob/living/carbon/human/suspect)
var/fibertext
- var/atom/actual_parent = parent.resolve()
+ var/atom/actual_parent = parent?.resolve()
+ if(isnull(actual_parent))
+ parent = null
var/item_multiplier = isitem(actual_parent) ? ITEM_FIBER_MULTIPLIER : NON_ITEM_FIBER_MULTIPLIER
if(suspect.wear_suit)
fibertext = "Material from \a [suspect.wear_suit]."
@@ -214,8 +217,11 @@
if(last_stamp_pos)
LAZYSET(hiddenprints, suspect.key, copytext(hiddenprints[suspect.key], 1, last_stamp_pos))
hiddenprints[suspect.key] += "\nLast: \[[current_time]\] \"[suspect.real_name]\"[has_gloves]. Ckey: [suspect.ckey]" //made sure to be existing by if(!LAZYACCESS);else
- var/atom/parent_atom = parent.resolve()
- parent_atom.fingerprintslast = suspect.ckey
+ var/atom/parent_atom = parent?.resolve()
+ if(!isnull(parent_atom))
+ parent_atom.fingerprintslast = suspect.ckey
+ else
+ parent = null
return TRUE
/// Adds the given list into blood_DNA
@@ -230,7 +236,10 @@
/// Updates the blood displayed on parent
/datum/forensics/proc/check_blood()
- var/obj/item/the_thing = parent.resolve()
+ var/obj/item/the_thing = parent?.resolve()
+ if(isnull(the_thing))
+ parent = null
+ return
if(!istype(the_thing) || isorgan(the_thing)) // organs don't spawn with blood decals by default
return
if(!length(blood_DNA))
diff --git a/code/modules/holodeck/holo_effect.dm b/code/modules/holodeck/holo_effect.dm
index 1bbedefb2e0ef..afd4c2270388f 100644
--- a/code/modules/holodeck/holo_effect.dm
+++ b/code/modules/holodeck/holo_effect.dm
@@ -62,11 +62,9 @@
mobtype = pick(mobtype)
our_mob = new mobtype(loc)
our_mob.flags_1 |= HOLOGRAM_1
- ADD_TRAIT(our_mob, TRAIT_PERMANENTLY_MORTAL, INNATE_TRAIT)
// these vars are not really standardized but all would theoretically create stuff on death
- for(var/v in list("butcher_results","corpse","weapon1","weapon2","blood_volume") & our_mob.vars)
- our_mob.vars[v] = null
+ our_mob.add_traits(list(TRAIT_PERMANENTLY_MORTAL, TRAIT_NO_BLOOD_OVERLAY, TRAIT_NOBLOOD, TRAIT_NOHUNGER), INNATE_TRAIT)
RegisterSignal(our_mob, COMSIG_QDELETING, PROC_REF(handle_mob_delete))
return our_mob
@@ -103,7 +101,7 @@
mobtype = /mob/living/basic/bee/toxin
/obj/effect/holodeck_effect/mobspawner/monkey
- mobtype = /mob/living/carbon/human/species/monkey/holodeck
+ mobtype = /mob/living/carbon/human/species/monkey
/obj/effect/holodeck_effect/mobspawner/monkey/activate(obj/machinery/computer/holodeck/computer)
var/mob/living/carbon/human/monkey = ..()
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 729ef541adeba..7c036fe22390d 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -1064,6 +1064,9 @@
/proc/cmp_organ_slot_asc(slot_a, slot_b)
return GLOB.organ_process_order.Find(slot_a) - GLOB.organ_process_order.Find(slot_b)
+/mob/living/carbon/proc/get_footprint_sprite()
+ return FOOTPRINT_SPRITE_PAWS
+
/mob/living/carbon/vv_get_dropdown()
. = ..()
VV_DROPDOWN_OPTION("", "---------")
@@ -1344,7 +1347,6 @@
else
set_lying_angle(new_lying_angle)
-
/mob/living/carbon/vv_edit_var(var_name, var_value)
switch(var_name)
if(NAMEOF(src, disgust))
@@ -1360,17 +1362,18 @@
return ..()
-
/mob/living/carbon/get_attack_type()
if(has_active_hand())
var/obj/item/bodypart/arm/active_arm = get_active_hand()
return active_arm.attack_type
return ..()
-
/mob/living/carbon/proc/attach_rot()
- if(mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD))
- AddComponent(/datum/component/rot, 6 MINUTES, 10 MINUTES, 1)
+ if(flags_1 & HOLOGRAM_1)
+ return
+ if(!(mob_biotypes & (MOB_ORGANIC|MOB_UNDEAD)))
+ return
+ AddComponent(/datum/component/rot, 6 MINUTES, 10 MINUTES, 1)
/**
* This proc is used to determine whether or not the mob can handle touching an acid affected object.
diff --git a/code/modules/mob/living/carbon/human/death.dm b/code/modules/mob/living/carbon/human/death.dm
index 7d31dd5ff90de..6d15f696bed57 100644
--- a/code/modules/mob/living/carbon/human/death.dm
+++ b/code/modules/mob/living/carbon/human/death.dm
@@ -6,6 +6,8 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift)
new /obj/effect/temp_visual/dust_animation(loc, dna.species.dust_anim)
/mob/living/carbon/human/spawn_gibs(drop_bitflags=NONE)
+ if(flags_1 & HOLOGRAM_1)
+ return
if(drop_bitflags & DROP_BODYPARTS)
new /obj/effect/gibspawner/human(drop_location(), src, get_static_viruses())
else
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 4791c818e1aff..1860fd0dd0917 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -24,7 +24,7 @@
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_FACE_ACT, PROC_REF(clean_face))
AddComponent(/datum/component/personal_crafting)
AddElement(/datum/element/footstep, FOOTSTEP_MOB_HUMAN, 1, -6)
- AddComponent(/datum/component/bloodysoles/feet)
+ AddComponent(/datum/component/bloodysoles/feet, FOOTPRINT_SPRITE_SHOES)
AddElement(/datum/element/ridable, /datum/component/riding/creature/human)
AddElement(/datum/element/strippable, GLOB.strippable_human_items, TYPE_PROC_REF(/mob/living/carbon/human/, should_strip))
var/static/list/loc_connections = list(
@@ -347,6 +347,10 @@
var/obj/item/bodypart/the_part = isbodypart(target_zone) ? target_zone : get_bodypart(check_zone(target_zone)) //keep these synced
to_chat(user, span_alert("There is no exposed flesh or thin material on [p_their()] [the_part.name]."))
+/mob/living/carbon/human/get_footprint_sprite()
+ var/obj/item/bodypart/leg/L = get_bodypart(BODY_ZONE_R_LEG) || get_bodypart(BODY_ZONE_L_LEG)
+ return shoes?.footprint_sprite || L?.footprint_sprite
+
#define CHECK_PERMIT(item) (item && item.item_flags & NEEDS_PERMIT)
/mob/living/carbon/human/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
diff --git a/code/modules/mob/living/carbon/human/monkey.dm b/code/modules/mob/living/carbon/human/monkey.dm
index 88d46855a5e3d..d11e4f5208bc7 100644
--- a/code/modules/mob/living/carbon/human/monkey.dm
+++ b/code/modules/mob/living/carbon/human/monkey.dm
@@ -32,12 +32,6 @@
equip_to_slot_or_del(helmet, ITEM_SLOT_HEAD)
helmet.attack_self(src) // todo encapsulate toggle
-/mob/living/carbon/human/species/monkey/holodeck
- race = /datum/species/monkey/holodeck
-
-/mob/living/carbon/human/species/monkey/holodeck/spawn_gibs() // no blood and no gibs
- return
-
GLOBAL_DATUM(the_one_and_only_punpun, /mob/living/carbon/human/species/monkey/punpun)
/mob/living/carbon/human/species/monkey/punpun
diff --git a/code/modules/mob/living/carbon/human/species_types/monkeys.dm b/code/modules/mob/living/carbon/human/species_types/monkeys.dm
index 3c176ff4388c8..b67f3efb3ef17 100644
--- a/code/modules/mob/living/carbon/human/species_types/monkeys.dm
+++ b/code/modules/mob/living/carbon/human/species_types/monkeys.dm
@@ -191,23 +191,4 @@
/obj/item/organ/internal/brain/primate/get_attacking_limb(mob/living/carbon/human/target)
return owner.get_bodypart(BODY_ZONE_HEAD)
-/// Virtual monkeys that crave virtual bananas. Everything about them is ephemeral (except that bite).
-/datum/species/monkey/holodeck
- id = SPECIES_MONKEY_HOLODECK
- knife_butcher_results = list()
- meat = null
- skinned_type = null
- inherent_traits = list(
- TRAIT_GENELESS,
- TRAIT_GUN_NATURAL,
- TRAIT_NO_AUGMENTS,
- TRAIT_NO_BLOOD_OVERLAY,
- TRAIT_NO_DNA_COPY,
- TRAIT_NO_UNDERWEAR,
- TRAIT_NO_ZOMBIFY,
- TRAIT_NOBLOOD,
- TRAIT_NOHUNGER,
- TRAIT_VENTCRAWLER_NUDE,
- )
-
#undef MONKEY_SPEC_ATTACK_BITE_MISS_CHANCE
diff --git a/code/modules/mob/living/death.dm b/code/modules/mob/living/death.dm
index 4da845c11df43..0c228775662d8 100644
--- a/code/modules/mob/living/death.dm
+++ b/code/modules/mob/living/death.dm
@@ -37,6 +37,8 @@
* * DROP_BODYPARTS - Gibs will spawn with bodypart limbs present
**/
/mob/living/proc/spawn_gibs(drop_bitflags=NONE)
+ if(flags_1 & HOLOGRAM_1)
+ return
new /obj/effect/gibspawner/generic(drop_location(), src, get_static_viruses())
/**
diff --git a/code/modules/surgery/bodyparts/parts.dm b/code/modules/surgery/bodyparts/parts.dm
index 2031ea4c72309..be1a7828c2e99 100644
--- a/code/modules/surgery/bodyparts/parts.dm
+++ b/code/modules/surgery/bodyparts/parts.dm
@@ -383,7 +383,8 @@
unarmed_effectiveness = 15
/// Datum describing how to offset things worn on the foot of this leg, note that an x offset won't do anything here
var/datum/worn_feature_offset/worn_foot_offset
-
+ /// Used by the bloodysoles component to make footprints
+ var/footprint_sprite = FOOTPRINT_SPRITE_SHOES
biological_state = BIO_STANDARD_JOINTED
/obj/item/bodypart/leg/Destroy()
@@ -463,6 +464,7 @@
unarmed_damage_low = 2
unarmed_damage_high = 3
unarmed_effectiveness = 0
+ footprint_sprite = FOOTPRINT_SPRITE_PAWS
/obj/item/bodypart/leg/left/alien
icon = 'icons/mob/human/species/alien/bodyparts.dmi'
@@ -552,6 +554,7 @@
unarmed_damage_low = 2
unarmed_damage_high = 3
unarmed_effectiveness = 0
+ footprint_sprite = FOOTPRINT_SPRITE_PAWS
/obj/item/bodypart/leg/right/alien
icon = 'icons/mob/human/species/alien/bodyparts.dmi'
diff --git a/code/modules/surgery/lipoplasty.dm b/code/modules/surgery/lipoplasty.dm
index 1d2e6b6838167..031534b0723e3 100644
--- a/code/modules/surgery/lipoplasty.dm
+++ b/code/modules/surgery/lipoplasty.dm
@@ -87,14 +87,17 @@
var/mob/living/carbon/human/human = target
var/typeofmeat = /obj/item/food/meat/slab/human
- if(human.dna && human.dna.species)
+ if(target.flags_1 & HOLOGRAM_1)
+ typeofmeat = null
+ else if(human.dna && human.dna.species)
typeofmeat = human.dna.species.meat
- var/obj/item/food/meat/slab/human/newmeat = new typeofmeat
- newmeat.name = "fatty meat"
- newmeat.desc = "Extremely fatty tissue taken from a patient."
- newmeat.subjectname = human.real_name
- newmeat.subjectjob = human.job
- newmeat.reagents.add_reagent (/datum/reagent/consumable/nutriment, (removednutriment / 15)) //To balance with nutriment_factor of nutriment
- newmeat.forceMove(target.loc)
+ if(typeofmeat)
+ var/obj/item/food/meat/slab/human/newmeat = new typeofmeat
+ newmeat.name = "fatty meat"
+ newmeat.desc = "Extremely fatty tissue taken from a patient."
+ newmeat.subjectname = human.real_name
+ newmeat.subjectjob = human.job
+ newmeat.reagents.add_reagent (/datum/reagent/consumable/nutriment, (removednutriment / 15)) //To balance with nutriment_factor of nutriment
+ newmeat.forceMove(target.loc)
return ..()
diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_monkey_holodeck.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_monkey_holodeck.png
deleted file mode 100644
index e0d02f4302f43..0000000000000
Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_monkey_holodeck.png and /dev/null differ
diff --git a/html/changelogs/AutoChangeLog-pr-81477.yml b/html/changelogs/AutoChangeLog-pr-81477.yml
deleted file mode 100644
index afcfee6c41cb7..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-81477.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-author: "Melbert"
-delete-after: True
-changes:
- - refactor: "Frames have been refactored, you know the things you use to build computers and machines, report any oddities"
- - bugfix: "You can now smack (de)constructed computer and machine frames to break them, rather than doing nothing."
- - rscadd: "Machine frames can now be deconstructed with screwdrivers, and computer frames can now be deconstructed with welding torches. Welders are faster."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81541.yml b/html/changelogs/AutoChangeLog-pr-81541.yml
new file mode 100644
index 0000000000000..b152c6498dbdb
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-81541.yml
@@ -0,0 +1,4 @@
+author: "nevimer"
+delete-after: True
+changes:
+ - bugfix: "ForceEvent tgui panel search is more reliable."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81569.yml b/html/changelogs/AutoChangeLog-pr-81569.yml
deleted file mode 100644
index e0b2b2367dcd2..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-81569.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Ghommie"
-delete-after: True
-changes:
- - bugfix: "sec-hailers no longer apply filters on TTS when pushed out of the way."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81577.yml b/html/changelogs/AutoChangeLog-pr-81577.yml
new file mode 100644
index 0000000000000..16702f1297aa8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-81577.yml
@@ -0,0 +1,4 @@
+author: "13spacemen"
+delete-after: True
+changes:
+ - refactor: "Bloody item overlays no longer use icon procs to generate the overlay"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81584.yml b/html/changelogs/AutoChangeLog-pr-81584.yml
deleted file mode 100644
index 68115f1eef452..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-81584.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Melbert"
-delete-after: True
-changes:
- - bugfix: "Organs have the blood DNA of their owns on them again"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81585.yml b/html/changelogs/AutoChangeLog-pr-81585.yml
deleted file mode 100644
index ac9af0845bd41..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-81585.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Melbert"
-delete-after: True
-changes:
- - bugfix: "Chasms no longer break your verbs"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81587.yml b/html/changelogs/AutoChangeLog-pr-81587.yml
deleted file mode 100644
index 58ded0611baf5..0000000000000
--- a/html/changelogs/AutoChangeLog-pr-81587.yml
+++ /dev/null
@@ -1,4 +0,0 @@
-author: "Derpguy3"
-delete-after: True
-changes:
- - bugfix: "Adds a missing servo component into the MK1 Ripley Crate ordered from cargo."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81588.yml b/html/changelogs/AutoChangeLog-pr-81588.yml
new file mode 100644
index 0000000000000..fc9163ce3efcd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-81588.yml
@@ -0,0 +1,5 @@
+author: "13spacemen, Kapu1178"
+delete-after: True
+changes:
+ - refactor: "Footprint sprites are now based on your shoes and legs, shoes have priority"
+ - image: "Monkey legs now produce pawprints instead of footprints"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81589.yml b/html/changelogs/AutoChangeLog-pr-81589.yml
new file mode 100644
index 0000000000000..4cdcda2320ac0
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-81589.yml
@@ -0,0 +1,4 @@
+author: "JohnFulpWillard"
+delete-after: True
+changes:
+ - spellcheck: "Removed a double space in health analyzer's message telling you someone is deaf."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81595.yml b/html/changelogs/AutoChangeLog-pr-81595.yml
new file mode 100644
index 0000000000000..9a9db0f69a221
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-81595.yml
@@ -0,0 +1,5 @@
+author: "Melbert"
+delete-after: True
+changes:
+ - rscdel: "Deletes Mythril Coins from random coin spawners"
+ - rscdel: "Replaces Mythril sheets in icebox vent fishing with Runite sheets"
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81597.yml b/html/changelogs/AutoChangeLog-pr-81597.yml
new file mode 100644
index 0000000000000..87369c39be1f8
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-81597.yml
@@ -0,0 +1,4 @@
+author: "00-Steven"
+delete-after: True
+changes:
+ - bugfix: "Chefs (not to be confused with cooks) actually display as being a part of service on the crew monitor."
\ No newline at end of file
diff --git a/html/changelogs/AutoChangeLog-pr-81606.yml b/html/changelogs/AutoChangeLog-pr-81606.yml
new file mode 100644
index 0000000000000..02bee239288bd
--- /dev/null
+++ b/html/changelogs/AutoChangeLog-pr-81606.yml
@@ -0,0 +1,4 @@
+author: "JohnFulpWillard"
+delete-after: True
+changes:
+ - refactor: "Holographic mobs now gives better feedback to players and should more consistently not give any drops."
\ No newline at end of file
diff --git a/html/changelogs/archive/2024-02.yml b/html/changelogs/archive/2024-02.yml
index b949bfb3e41d1..de87de3d7f2b0 100644
--- a/html/changelogs/archive/2024-02.yml
+++ b/html/changelogs/archive/2024-02.yml
@@ -628,3 +628,18 @@
- bugfix: you may not teleport in or out of deathmatch arenas
- bugfix: if you died as a changeling/anyone that has cool mind spells you do not
get them in deathmatch
+2024-02-22:
+ Derpguy3:
+ - bugfix: Adds a missing servo component into the MK1 Ripley Crate ordered from
+ cargo.
+ Ghommie:
+ - bugfix: sec-hailers no longer apply filters on TTS when pushed out of the way.
+ Melbert:
+ - bugfix: Chasms no longer break your verbs
+ - refactor: Frames have been refactored, you know the things you use to build computers
+ and machines, report any oddities
+ - bugfix: You can now smack (de)constructed computer and machine frames to break
+ them, rather than doing nothing.
+ - rscadd: Machine frames can now be deconstructed with screwdrivers, and computer
+ frames can now be deconstructed with welding torches. Welders are faster.
+ - bugfix: Organs have the blood DNA of their owns on them again
diff --git a/icons/effects/footprints.dmi b/icons/effects/footprints.dmi
index a98344abe41ee..a00c6a0f780db 100644
Binary files a/icons/effects/footprints.dmi and b/icons/effects/footprints.dmi differ
diff --git a/tgui/packages/tgui/interfaces/ForceEvent.tsx b/tgui/packages/tgui/interfaces/ForceEvent.tsx
index a93ea6a5f430f..4811e2fc20f2c 100644
--- a/tgui/packages/tgui/interfaces/ForceEvent.tsx
+++ b/tgui/packages/tgui/interfaces/ForceEvent.tsx
@@ -21,13 +21,15 @@ const paginateEvents = (events: Event[], maxPerPage: number): Event[][] => {
let maxChars = EVENT_PAGE_MAXCHARS;
for (const event of events) {
- maxChars -= event.name.length;
- if (maxChars <= 0) {
- // would overflow the next line over
- itemsToAdd = maxPerPage;
- maxChars = EVENT_PAGE_MAXCHARS - event.name.length;
- pages.push(page);
- page = [];
+ if (event.name && typeof event.name === 'string') {
+ maxChars -= event.name.length;
+ if (maxChars <= 0) {
+ // would overflow the next line over
+ itemsToAdd = maxPerPage;
+ maxChars = EVENT_PAGE_MAXCHARS - event.name.length;
+ pages.push(page);
+ page = [];
+ }
}
page.push(event);
itemsToAdd--;
@@ -127,7 +129,14 @@ export const EventSection = (props) => {
return false;
}
// remove events not being searched for, if a search is active
- if (searchQuery && !event.name.toLowerCase().includes(searchQuery)) {
+ if (
+ searchQuery &&
+ event.name &&
+ typeof event.name === 'string' &&
+ searchQuery &&
+ typeof searchQuery === 'string' &&
+ !event.name.toLowerCase().includes(searchQuery.toLowerCase())
+ ) {
return false;
}
return true;