Skip to content
This repository was archived by the owner on May 22, 2025. It is now read-only.

Commit 1df4100

Browse files
authored
footprints are now based on shoes and then legs, monkey legs make pawprints, fixed blood overlay leaking bug, added keep together helpers, renamed icon states in footprints.dmi (#21511)
1 parent bd9299a commit 1df4100

File tree

12 files changed

+109
-26
lines changed

12 files changed

+109
-26
lines changed

code/__DEFINES/cleaning.dm

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,8 @@
3434
#define CLEAN_SCRUB (CLEAN_WASH | CLEAN_TYPE_FINGERPRINTS | CLEAN_TYPE_FIBERS | CLEAN_TYPE_HARD_DECAL)
3535
#define CLEAN_RAD CLEAN_TYPE_RADIATION
3636
#define CLEAN_ALL (ALL & ~CLEAN_TYPE_WEAK)
37+
38+
// Footprint sprites to use when making footprints in blood, oil, etc.
39+
#define FOOTPRINT_SPRITE_SHOES "shoes"
40+
#define FOOTPRINT_SPRITE_PAWS "paws"
41+
#define FOOTPRINT_SPRITE_CLAWS "claws"

code/__DEFINES/flags.dm

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,21 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204
197197
#define AA_TARGET_SEE_APPEARANCE (1<<0)
198198
#define AA_MATCH_TARGET_OVERLAYS (1<<1)
199199

200+
#define KEEP_TOGETHER_ORIGINAL "keep_together_original"
201+
202+
//setter for KEEP_TOGETHER to allow for multiple sources to set and unset it
203+
#define ADD_KEEP_TOGETHER(x, source)\
204+
if ((x.appearance_flags & KEEP_TOGETHER) && !HAS_TRAIT(x, TRAIT_KEEP_TOGETHER)) ADD_TRAIT(x, TRAIT_KEEP_TOGETHER, KEEP_TOGETHER_ORIGINAL); \
205+
ADD_TRAIT(x, TRAIT_KEEP_TOGETHER, source);\
206+
x.appearance_flags |= KEEP_TOGETHER
207+
208+
#define REMOVE_KEEP_TOGETHER(x, source)\
209+
REMOVE_TRAIT(x, TRAIT_KEEP_TOGETHER, source);\
210+
if(HAS_TRAIT_FROM_ONLY(x, TRAIT_KEEP_TOGETHER, KEEP_TOGETHER_ORIGINAL))\
211+
REMOVE_TRAIT(x, TRAIT_KEEP_TOGETHER, KEEP_TOGETHER_ORIGINAL);\
212+
else if(!HAS_TRAIT(x, TRAIT_KEEP_TOGETHER))\
213+
x.appearance_flags &= ~KEEP_TOGETHER
214+
200215
//religious_tool flags
201216
#define RELIGION_TOOL_INVOKE (1<<0)
202217
#define RELIGION_TOOL_SACRIFICE (1<<1)

code/__HELPERS/type2type.dm

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,9 @@
143143
if(337.5 to 360)
144144
return NORTH
145145

146-
/proc/angle2dir_cardinal(angle)
147-
switch(round(angle, 0.1))
146+
/proc/angle2dir_cardinal(degree)
147+
degree = SIMPLIFY_DEGREES(degree)
148+
switch(round(degree, 0.1))
148149
if(315.5 to 360, 0 to 45.5)
149150
return NORTH
150151
if(45.6 to 135.5)

code/datums/components/bloodysoles.dm

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
/// The world.time when we last picked up blood
2222
var/last_pickup
2323

24+
var/footprint_sprite = FOOTPRINT_SPRITE_SHOES
25+
2426
/datum/component/bloodysoles/Initialize()
2527
if(!isclothing(parent))
2628
return COMPONENT_INCOMPATIBLE
@@ -69,9 +71,9 @@
6971

7072
//Find a blood decal on a turf that matches our last_blood_state
7173

72-
/datum/component/bloodysoles/proc/find_pool_by_blood_state(turf/turfLoc, typeFilter = null)
74+
/datum/component/bloodysoles/proc/find_pool_by_blood_state(turf/turfLoc, typeFilter = null, footprint_sprite)
7375
for(var/obj/effect/decal/cleanable/blood/pool in turfLoc)
74-
if(pool.blood_state == last_blood_state && (!typeFilter || istype(pool, typeFilter)))
76+
if(pool.blood_state == last_blood_state && pool.footprint_sprite == footprint_sprite && (!typeFilter || istype(pool, typeFilter)))
7577
return pool
7678

7779

@@ -123,24 +125,24 @@ Used to make bloody footprints on the ground
123125
return
124126

125127
var/half_our_blood = bloody_shoes[last_blood_state] / 2
126-
128+
var/footprint_sprite = wielder.get_footprint_sprite()
127129
// Add footprints in old loc if we have enough cream
128130
if(half_our_blood >= BLOOD_FOOTPRINTS_MIN)
129131
var/turf/oldLocTurf = get_turf(OldLoc)
130-
var/obj/effect/decal/cleanable/blood/footprints/oldLocFP = find_pool_by_blood_state(oldLocTurf, /obj/effect/decal/cleanable/blood/footprints)
132+
var/obj/effect/decal/cleanable/blood/footprints/oldLocFP = find_pool_by_blood_state(oldLocTurf, /obj/effect/decal/cleanable/blood/footprints, footprint_sprite)
131133
if(oldLocFP)
132134
// Footprints found in the tile we left, add us to it
133135
add_parent_to_footprint(oldLocFP)
134136
if (!(oldLocFP.exited_dirs & wielder.dir))
135137
oldLocFP.exited_dirs |= wielder.dir
136138
oldLocFP.update_icon()
137-
else if(find_pool_by_blood_state(oldLocTurf))
139+
else if(find_pool_by_blood_state(oldLocTurf, footprint_sprite = footprint_sprite))
138140
// No footprints in the tile we left, but there was some other blood pool there. Add exit footprints on it
139141
bloody_shoes[last_blood_state] -= half_our_blood
140142
update_icon()
141143

142144

143-
oldLocFP = new(oldLocTurf)
145+
oldLocFP = new(oldLocTurf, footprint_sprite)
144146
if(!QDELETED(oldLocFP)) ///prints merged
145147
oldLocFP.blood_state = last_blood_state
146148
oldLocFP.exited_dirs |= wielder.dir
@@ -160,7 +162,7 @@ Used to make bloody footprints on the ground
160162
bloody_shoes[last_blood_state] -= half_our_blood
161163
update_icon()
162164

163-
var/obj/effect/decal/cleanable/blood/footprints/FP = new(get_turf(parent_atom))
165+
var/obj/effect/decal/cleanable/blood/footprints/FP = new(get_turf(parent_atom), footprint_sprite)
164166
if(!QDELETED(FP)) ///prints merged
165167
FP.blood_state = last_blood_state
166168
FP.entered_dirs |= wielder.dir
@@ -220,7 +222,8 @@ Like its parent but can be applied to carbon mobs instead of clothing items
220222
return COMPONENT_INCOMPATIBLE
221223
parent_atom = parent
222224
wielder = parent
223-
225+
if(footprint_sprite)
226+
src.footprint_sprite = footprint_sprite
224227
if(!bloody_feet)
225228
bloody_feet = mutable_appearance('icons/effects/blood.dmi', "shoeblood", SHOES_LAYER)
226229

code/datums/elements/decals/blood.dm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
/datum/element/decal/blood/generate_appearance(_icon, _icon_state, _dir, _plane, _layer, _color, _alpha, _smoothing, source)
1515
var/obj/item/I = source
16+
ADD_KEEP_TOGETHER(I, "item_blood_overlay")
1617
if(!_color)
1718
_color = COLOR_BLOOD
1819
var/icon = I.icon

code/game/objects/effects/decals/cleanable/humans.dm

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
var/dryname = "dried blood" //when the blood lasts long enough, it becomes dry and gets a new name
1212
var/drydesc = "Looks like it's been here a while. Eew." //as above
1313
var/drytime = 0
14+
var/footprint_sprite = null
1415

1516
/obj/effect/decal/cleanable/blood/Initialize(mapload)
1617
. = ..()
@@ -205,9 +206,8 @@
205206
/obj/effect/decal/cleanable/blood/footprints
206207
name = "footprints"
207208
icon = 'icons/effects/footprints.dmi'
208-
icon_state = "nothingwhatsoever"
209209
desc = "WHOSE FOOTPRINTS ARE THESE?"
210-
icon_state = "blood1"
210+
icon_state = "blood_shoes_enter"
211211
random_icon_states = null
212212
blood_state = BLOOD_STATE_HUMAN //the icon state to load images from
213213
var/entered_dirs = 0
@@ -220,28 +220,72 @@
220220
dryname = "dried footprints"
221221
drydesc = "HMM... SOMEONE WAS HERE!"
222222

223+
/obj/effect/decal/cleanable/blood/footprints/Initialize(mapload, footprint_sprite)
224+
src.footprint_sprite = footprint_sprite
225+
. = ..()
226+
icon_state = "" //All of the footprint visuals come from overlays
227+
if(mapload)
228+
entered_dirs |= dir //Keep the same appearance as in the map editor
229+
update_appearance(mapload ? (ALL) : (UPDATE_NAME | UPDATE_DESC))
230+
231+
//Rotate all of the footprint directions too
232+
/obj/effect/decal/cleanable/blood/footprints/setDir(newdir)
233+
if(dir == newdir)
234+
return ..()
235+
236+
var/ang_change = dir2angle(newdir) - dir2angle(dir)
237+
var/old_entered_dirs = entered_dirs
238+
var/old_exited_dirs = exited_dirs
239+
entered_dirs = 0
240+
exited_dirs = 0
241+
242+
for(var/Ddir in GLOB.cardinals)
243+
if(old_entered_dirs & Ddir)
244+
entered_dirs |= angle2dir_cardinal(dir2angle(Ddir) + ang_change)
245+
if(old_exited_dirs & Ddir)
246+
exited_dirs |= angle2dir_cardinal(dir2angle(Ddir) + ang_change)
247+
248+
update_appearance()
249+
return ..()
250+
251+
/obj/effect/decal/cleanable/blood/footprints/update_name(updates)
252+
switch(footprint_sprite)
253+
if(FOOTPRINT_SPRITE_CLAWS)
254+
name = "clawprints"
255+
if(FOOTPRINT_SPRITE_SHOES)
256+
name = "footprints"
257+
if(FOOTPRINT_SPRITE_PAWS)
258+
name = "pawprints"
259+
dryname = "dried [name]"
260+
return ..()
261+
262+
/obj/effect/decal/cleanable/blood/footprints/update_desc(updates)
263+
desc = "WHOSE [uppertext(name)] ARE THESE?"
264+
return ..()
265+
266+
/obj/effect/decal/cleanable/blood/footprints/update_icon()
267+
. = ..()
268+
alpha = min(BLOODY_FOOTPRINT_BASE_ALPHA + (255 - BLOODY_FOOTPRINT_BASE_ALPHA) * bloodiness / (BLOOD_ITEM_MAX / 2), 255)
269+
223270
/obj/effect/decal/cleanable/blood/footprints/update_overlays()
224271
. = ..()
225272

226273
for(var/Ddir in GLOB.cardinals)
227274
if(entered_dirs & Ddir)
228-
var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["entered-[blood_state]-[Ddir]"]
275+
var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["entered-[footprint_sprite]-[blood_state]-[Ddir]"]
229276
if(!bloodstep_overlay)
230-
GLOB.bloody_footprints_cache["entered-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]1", dir = Ddir)
277+
GLOB.bloody_footprints_cache["entered-[footprint_sprite]-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]_[footprint_sprite]_enter", dir = Ddir)
231278
. += bloodstep_overlay
232279
if(exited_dirs & Ddir)
233-
var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["exited-[blood_state]-[Ddir]"]
280+
var/image/bloodstep_overlay = GLOB.bloody_footprints_cache["exited-[footprint_sprite]-[blood_state]-[Ddir]"]
234281
if(!bloodstep_overlay)
235-
GLOB.bloody_footprints_cache["exited-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]2", dir = Ddir)
282+
GLOB.bloody_footprints_cache["exited-[footprint_sprite]-[blood_state]-[Ddir]"] = bloodstep_overlay = image(icon, "[blood_state]_[footprint_sprite]_exit", dir = Ddir)
236283
. += bloodstep_overlay
237284

238-
alpha = min(BLOODY_FOOTPRINT_BASE_ALPHA + (255 - BLOODY_FOOTPRINT_BASE_ALPHA) * bloodiness / (BLOOD_ITEM_MAX / 2), 255)
239-
240-
241285
/obj/effect/decal/cleanable/blood/footprints/examine(mob/user)
242286
. = ..()
243287
if((shoe_types.len + species_types.len) > 0)
244-
. += "You recognise the footprints as belonging to:"
288+
. += "You recognise the [name] as belonging to:"
245289
for(var/sole in shoe_types)
246290
var/obj/item/clothing/item = sole
247291
var/article = initial(item.gender) == PLURAL ? "Some" : "A"
@@ -251,14 +295,14 @@
251295
if(species == "unknown")
252296
. += "Some <B>feet</B>."
253297
else if(species == "monkey")
254-
. += "[icon2html('icons/mob/monkey.dmi', user, "monkey1")] Some <B>monkey feet</B>."
298+
. += "[icon2html('icons/mob/monkey.dmi', user, "monkey1")] Some <B>monkey paws</B>."
255299
else if(species == "human")
256300
. += "[icon2html('icons/mob/human_parts.dmi', user, "default_human_l_leg")] Some <B>human feet</B>."
257301
else
258302
. += "[icon2html('icons/mob/human_parts.dmi', user, "[species]_l_leg")] Some <B>[species] feet</B>."
259303

260-
/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/C)
261-
if(blood_state != C.blood_state) //We only replace footprints of the same type as us
304+
/obj/effect/decal/cleanable/blood/footprints/replace_decal(obj/effect/decal/cleanable/blood/blood_decal)
305+
if(blood_state != blood_decal.blood_state || footprint_sprite != blood_decal.footprint_sprite) //We only replace footprints of the same type as us
262306
return FALSE
263307
return ..()
264308

code/modules/clothing/shoes/_shoes.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
slot_flags = ITEM_SLOT_FEET
1010

1111
slowdown = SHOES_SLOWDOWN
12-
12+
var/footprint_sprite = FOOTPRINT_SPRITE_SHOES
1313
var/offset = 0
1414
var/equipped_before_drop = FALSE
1515
var/xenoshoe = NO_DIGIT // Check for if shoes can be worn by straight legs (NO_DIGIT) which is default, both / hybrid (EITHER_STYLE), or digitigrade only (YES_DIGIT)

code/modules/mob/living/carbon/carbon.dm

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -984,6 +984,9 @@
984984
var/obj/item/organ/I = X
985985
I.Insert(src)
986986

987+
/mob/living/carbon/proc/get_footprint_sprite()
988+
return FOOTPRINT_SPRITE_PAWS
989+
987990
/mob/living/carbon/vv_get_dropdown()
988991
. = ..()
989992
VV_DROPDOWN_SEPERATOR

code/modules/mob/living/carbon/carbon_defines.dm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
var/obj/item/clothing/head = null
4141

4242
var/obj/item/clothing/gloves = null //only used by humans
43-
var/obj/item/clothing/shoes = null //only used by humans.
43+
var/obj/item/clothing/shoes/shoes = null //only used by humans.
4444
var/obj/item/clothing/glasses/glasses = null //only used by humans.
4545
var/obj/item/clothing/ears = null //only used by humans.
4646

code/modules/mob/living/carbon/human/human.dm

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
RegisterSignal(src, COMSIG_COMPONENT_CLEAN_FACE_ACT, PROC_REF(clean_face))
3636
AddComponent(/datum/component/personal_crafting)
3737
AddElement(/datum/element/footstep, FOOTSTEP_MOB_HUMAN, 1, -6)
38-
AddComponent(/datum/component/bloodysoles/feet)
38+
AddComponent(/datum/component/bloodysoles/feet, FOOTPRINT_SPRITE_SHOES)
3939

4040
/mob/living/carbon/human/proc/setup_human_dna()
4141
//initialize dna. for spawned humans; overwritten by other code
@@ -547,6 +547,11 @@
547547
// Might need re-wording.
548548
to_chat(user, span_alert("There is no exposed flesh or thin material [above_neck(target_zone) ? "on [p_their()] head" : "on [p_their()] body"]."))
549549

550+
/mob/living/carbon/human/get_footprint_sprite()
551+
var/obj/item/bodypart/l_leg/left_leg = get_bodypart(BODY_ZONE_L_LEG)
552+
var/obj/item/bodypart/r_leg/right_leg = get_bodypart(BODY_ZONE_R_LEG)
553+
return shoes?.footprint_sprite || left_leg?.footprint_sprite || right_leg?.footprint_sprite
554+
550555
/mob/living/carbon/human/assess_threat(judgement_criteria, lasercolor = "", datum/callback/weaponcheck=null)
551556
if(judgement_criteria & JUDGE_EMAGGED)
552557
return 10 //Everyone is a criminal!

0 commit comments

Comments
 (0)