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

Commit 27d7786

Browse files
authored
[FIX] Fixes a BUNCH of stepping things not working (#21477)
* fixes all of these yeah * invoke crush balls * fuck biome * we're not ready bees * squishums
1 parent 67a0ae0 commit 27d7786

File tree

11 files changed

+226
-22
lines changed

11 files changed

+226
-22
lines changed

code/__DEFINES/mobs.dm

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,3 +399,25 @@
399399

400400
/// Possible value of [/atom/movable/buckle_lying]. If set to a different (positive-or-zero) value than this, the buckling thing will force a lying angle on the buckled.
401401
#define NO_BUCKLE_LYING -1
402+
403+
/// Squashing will not occur if the mob is not lying down (bodyposition is LYING_DOWN)
404+
#define SQUASHED_SHOULD_BE_DOWN (1<<0)
405+
/// If present, outright gibs the squashed mob instead of just dealing damage
406+
#define SQUASHED_SHOULD_BE_GIBBED (1<<1)
407+
/// If squashing always passes if the mob is dead
408+
#define SQUASHED_ALWAYS_IF_DEAD (1<<2)
409+
/// Don't squash our mob if its not located in a turf
410+
#define SQUASHED_DONT_SQUASH_IN_CONTENTS (1<<3)
411+
412+
// Bitflags for mob dismemberment and gibbing
413+
/// Mobs will drop a brain
414+
#define DROP_BRAIN (1<<0)
415+
/// Mobs will drop organs
416+
#define DROP_ORGANS (1<<1)
417+
/// Mobs will drop bodyparts (arms, legs, etc.)
418+
#define DROP_BODYPARTS (1<<2)
419+
/// Mobs will drop items
420+
#define DROP_ITEMS (1<<3)
421+
422+
/// Mobs will drop everything
423+
#define DROP_ALL_REMAINS (DROP_BRAIN | DROP_ORGANS | DROP_BODYPARTS | DROP_ITEMS)

code/datums/components/squeak.dm

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@
1313
var/last_use = 0
1414
var/use_delay = 20
1515

16+
///what we set connect_loc to if parent is an item
17+
var/static/list/item_connections = list(
18+
COMSIG_ATOM_ENTERED = PROC_REF(play_squeak_crossed),
19+
)
20+
1621
/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override)
1722
if(!isatom(parent))
1823
return COMPONENT_INCOMPATIBLE
1924
RegisterSignals(parent, list(COMSIG_ATOM_ENTERED, COMSIG_ATOM_BLOB_ACT, COMSIG_ATOM_HULK_ATTACK, COMSIG_PARENT_ATTACKBY), PROC_REF(play_squeak))
2025
if(ismovable(parent))
2126
RegisterSignals(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT, COMSIG_PROJECTILE_BEFORE_FIRE), PROC_REF(play_squeak))
22-
RegisterSignal(parent, COMSIG_MOVABLE_CROSSED, PROC_REF(play_squeak_crossed))
27+
AddComponent(/datum/component/connect_loc_behalf, parent, item_connections)
2328
RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, PROC_REF(disposing_react))
2429
if(isitem(parent))
2530
RegisterSignals(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), PROC_REF(play_squeak))
@@ -41,6 +46,10 @@
4146
if(isnum(use_delay_override))
4247
use_delay = use_delay_override
4348

49+
/datum/component/squeak/UnregisterFromParent()
50+
. = ..()
51+
qdel(GetComponent(/datum/component/connect_loc_behalf))
52+
4453
/datum/component/squeak/proc/play_squeak()
4554
if(prob(squeak_chance))
4655
if(!override_squeak_sounds)
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
///This component allows something to be when crossed, for example for cockroaches.
2+
/datum/component/squashable
3+
///Chance on crossed to be squashed
4+
var/squash_chance = 50
5+
///How much brute is applied when mob is squashed
6+
var/squash_damage = 1
7+
///Squash flags, for extra checks etcetera.
8+
var/squash_flags = NONE
9+
///Special callback to call on squash instead, for things like hauberoach
10+
var/datum/callback/on_squash_callback
11+
///signal list given to connect_loc
12+
var/static/list/loc_connections = list(
13+
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
14+
)
15+
16+
17+
/datum/component/squashable/Initialize(squash_chance, squash_damage, squash_flags, squash_callback)
18+
. = ..()
19+
if(!isliving(parent))
20+
return COMPONENT_INCOMPATIBLE
21+
if(squash_chance)
22+
src.squash_chance = squash_chance
23+
if(squash_damage)
24+
src.squash_damage = squash_damage
25+
if(squash_flags)
26+
src.squash_flags = squash_flags
27+
if(!src.on_squash_callback && squash_callback)
28+
on_squash_callback = CALLBACK(parent, squash_callback)
29+
30+
AddComponent(/datum/component/connect_loc_behalf, parent, loc_connections)
31+
32+
/datum/component/squashable/Destroy(force)
33+
on_squash_callback = null
34+
return ..()
35+
36+
///Handles the squashing of the mob
37+
/datum/component/squashable/proc/on_entered(turf/source_turf, atom/movable/crossing_movable)
38+
// SIGNAL_HANDLER -- dont uncomment this
39+
40+
if(parent == crossing_movable)
41+
return
42+
43+
var/mob/living/parent_as_living = parent
44+
if((squash_flags & SQUASHED_DONT_SQUASH_IN_CONTENTS) && !isturf(parent_as_living.loc))
45+
return
46+
47+
if((squash_flags & SQUASHED_SHOULD_BE_DOWN) && parent_as_living.body_position != LYING_DOWN)
48+
return
49+
50+
var/should_squash = ((squash_flags & SQUASHED_ALWAYS_IF_DEAD) && parent_as_living.stat == DEAD) || prob(squash_chance)
51+
52+
if(should_squash && on_squash_callback)
53+
if(on_squash_callback.Invoke(parent_as_living, crossing_movable))
54+
return //Everything worked, we're done!
55+
if(isliving(crossing_movable))
56+
var/mob/living/crossing_mob = crossing_movable
57+
if(crossing_mob.mob_size > MOB_SIZE_SMALL && !(crossing_mob.movement_type & MOVETYPES_NOT_TOUCHING_GROUND))
58+
if(HAS_TRAIT(crossing_mob, TRAIT_PACIFISM))
59+
crossing_mob.visible_message(span_notice("[crossing_mob] carefully steps over [parent_as_living]."), span_notice("You carefully step over [parent_as_living] to avoid hurting it."))
60+
return
61+
if(should_squash)
62+
crossing_mob.visible_message(span_notice("[crossing_mob] squashed [parent_as_living]."), span_notice("You squashed [parent_as_living]."))
63+
Squish(parent_as_living)
64+
else
65+
parent_as_living.visible_message(span_notice("[parent_as_living] avoids getting crushed."))
66+
else if(isstructure(crossing_movable))
67+
if(should_squash)
68+
crossing_movable.visible_message(span_notice("[parent_as_living] is crushed under [crossing_movable]."))
69+
Squish(parent_as_living)
70+
else
71+
parent_as_living.visible_message(span_notice("[parent_as_living] avoids getting crushed."))
72+
73+
/datum/component/squashable/proc/Squish(mob/living/target)
74+
if(squash_flags & SQUASHED_SHOULD_BE_GIBBED)
75+
target.gib(DROP_ALL_REMAINS)
76+
else
77+
target.adjustBruteLoss(squash_damage)
78+
79+
/datum/component/squashable/UnregisterFromParent()
80+
. = ..()
81+
qdel(GetComponent(/datum/component/connect_loc_behalf))

code/game/objects/effects/mines.dm

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,23 @@
8686
icon_state = "uglymine"
8787
alpha = 30
8888
var/triggered = 0
89+
/// Can be set to FALSE if we want a short 'coming online' delay, then set to TRUE. Can still be set off by damage
90+
var/armed = TRUE
8991
var/smartmine = FALSE
9092
var/disarm_time = 12 SECONDS
9193
var/disarm_product = /obj/item/deployablemine // ie what drops when the mine is disarmed
94+
/// Who's got their foot on the mine's pressure plate
95+
/// Stepping on the mine will set this to the first mob who stepped over it
96+
/// The mine will not detonate via movement unless the first mob steps off of it
97+
var/datum/weakref/foot_on_mine
9298

9399
/obj/effect/mine/Initialize(mapload)
94100
. = ..()
95-
layer = ABOVE_MOB_LAYER
101+
var/static/list/loc_connections = list(
102+
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
103+
COMSIG_ATOM_EXITED = PROC_REF(on_exited),
104+
)
105+
AddElement(/datum/element/connect_loc, loc_connections)
96106

97107
/obj/effect/mine/attackby(obj/I, mob/user, params)
98108
if(istype(I, /obj/item/multitool))
@@ -107,18 +117,6 @@
107117
/obj/effect/mine/proc/mineEffect(mob/victim)
108118
to_chat(victim, span_danger("*click*"))
109119

110-
/obj/effect/mine/Crossed(AM as mob|obj)
111-
. = ..()
112-
if(isturf(loc))
113-
if(ismob(AM))
114-
var/mob/MM = AM
115-
if(!(MM.movement_type & FLYING))
116-
checksmartmine(AM)
117-
else
118-
if(istype(AM, /obj/projectile))
119-
return
120-
triggermine(AM)
121-
122120
/obj/effect/mine/proc/checksmartmine(mob/target)
123121
if(smartmine && target && !HAS_TRAIT(target, TRAIT_MINDSHIELD))
124122
triggermine(target)
@@ -132,7 +130,7 @@
132130
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
133131
s.set_up(1, 0, src)
134132
s.start()
135-
mineEffect(victim)
133+
INVOKE_ASYNC(src, PROC_REF(mineEffect), victim)
136134
triggered = 1
137135
qdel(src)
138136

@@ -360,3 +358,45 @@
360358
/obj/effect/mine/creampie/mineEffect(mob/victim)
361359
var/obj/item/reagent_containers/food/snacks/pie/cream/P = new /obj/item/reagent_containers/food/snacks/pie/cream(src)
362360
P.splat(victim)
361+
362+
/// Can this mine trigger on the passed movable?
363+
/obj/effect/mine/proc/can_trigger(atom/movable/on_who)
364+
if(triggered || !isturf(loc) || iseffect(on_who))
365+
return FALSE
366+
367+
var/mob/living/living_mob
368+
if(ismob(on_who))
369+
if(!isliving(on_who)) //no ghosties.
370+
return FALSE
371+
living_mob = on_who
372+
373+
if(living_mob?.incorporeal_move || (on_who.movement_type & MOVETYPES_NOT_TOUCHING_GROUND))
374+
return foot_on_mine ? IS_WEAKREF_OF(on_who, foot_on_mine) : FALSE //Only go boom if their foot was on the mine PRIOR to flying/phasing. You fucked up, you live with the consequences.
375+
376+
return TRUE
377+
378+
379+
/obj/effect/mine/proc/on_entered(datum/source, atom/movable/arrived)
380+
SIGNAL_HANDLER
381+
382+
if(!can_trigger(arrived))
383+
return
384+
// Someone already on it
385+
if(foot_on_mine?.resolve())
386+
return
387+
388+
foot_on_mine = WEAKREF(arrived)
389+
visible_message(span_danger("[icon2html(src, viewers(src))] *click*"))
390+
playsound(src, 'sound/machines/click.ogg', 60, TRUE)
391+
392+
/obj/effect/mine/proc/on_exited(datum/source, atom/movable/gone)
393+
// SIGNAL_HANDLER we're not ready for this
394+
395+
if(!can_trigger(gone))
396+
return
397+
// Check that the guy who's on it is stepping off
398+
if(foot_on_mine && !IS_WEAKREF_OF(gone, foot_on_mine))
399+
return
400+
401+
triggermine(gone)
402+
foot_on_mine = null

code/game/objects/items/handcuffs.dm

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,29 @@
339339
ridden_vehicle.visible_message(span_danger("[ridden_vehicle] triggers \the [src]."))
340340
return
341341

342+
//don't close the trap if they're as small as a mouse
343+
if(victim.mob_size <= MOB_SIZE_TINY)
344+
return
345+
if(!ignore_movetypes && (victim.movement_type & MOVETYPES_NOT_TOUCHING_GROUND))
346+
return
347+
348+
close_trap()
349+
if(ignore_movetypes)
350+
victim.visible_message(span_danger("\The [src] ensnares [victim]!"), \
351+
span_userdanger("\The [src] ensnares you!"))
352+
else
353+
victim.visible_message(span_danger("[victim] triggers \the [src]."), \
354+
span_userdanger("You trigger \the [src]!"))
355+
var/def_zone = BODY_ZONE_CHEST
356+
if(iscarbon(victim) && victim.body_position == STANDING_UP)
357+
var/mob/living/carbon/carbon_victim = victim
358+
def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
359+
if(!carbon_victim.legcuffed && carbon_victim.num_legs >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs.
360+
INVOKE_ASYNC(carbon_victim, TYPE_PROC_REF(/mob/living/carbon, equip_to_slot), src, ITEM_SLOT_LEGCUFFED)
361+
SSblackbox.record_feedback("tally", "handcuffs", 1, type)
362+
363+
victim.apply_damage(trap_damage, BRUTE, def_zone)
364+
342365

343366
/obj/item/restraints/legcuffs/beartrap/Crossed(AM as mob|obj)
344367
if(armed && isturf(loc))

code/game/objects/items/toys.dm

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,14 @@
456456
w_class = WEIGHT_CLASS_TINY
457457
var/ash_type = /obj/effect/decal/cleanable/ash
458458

459+
/obj/item/toy/snappop/Initialize(mapload)
460+
. = ..()
461+
var/static/list/loc_connections = list(
462+
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
463+
)
464+
AddElement(/datum/element/connect_loc, loc_connections)
465+
466+
459467
/obj/item/toy/snappop/proc/pop_burst(n=3, c=1)
460468
var/datum/effect_system/spark_spread/s = new()
461469
s.set_up(n, c, src)
@@ -473,8 +481,7 @@
473481
if(!..())
474482
pop_burst()
475483

476-
/obj/item/toy/snappop/Crossed(H as mob|obj)
477-
. = ..()
484+
/obj/item/toy/snappop/proc/on_entered(datum/source, atom/movable/H, ...)
478485
if(ishuman(H) || issilicon(H)) //i guess carp and shit shouldn't set them off
479486
var/mob/living/carbon/M = H
480487
if(issilicon(H) || M.m_intent == MOVE_INTENT_RUN)

code/modules/assembly/mousetrap.dm

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@
99
var/armed = FALSE
1010

1111

12+
/obj/item/assembly/mousetrap/Initialize(mapload)
13+
. = ..()
14+
var/static/list/loc_connections = list(
15+
COMSIG_ATOM_ENTERED = PROC_REF(trap_stepped_on),
16+
)
17+
AddElement(/datum/element/connect_loc, loc_connections)
18+
1219
/obj/item/assembly/mousetrap/examine(mob/user)
1320
. = ..()
1421
. += span_notice("The pressure plate is [armed?"primed":"safe"].")
@@ -109,7 +116,7 @@
109116
return ..()
110117

111118

112-
/obj/item/assembly/mousetrap/Crossed(atom/movable/AM as mob|obj)
119+
/obj/item/assembly/mousetrap/proc/trap_stepped_on(datum/source, atom/movable/AM, ...)
113120
if(armed)
114121
if(ismob(AM))
115122
var/mob/MM = AM
@@ -124,7 +131,7 @@
124131
triggered(MM)
125132
else if(AM.density) // For mousetrap grenades, set off by anything heavy
126133
triggered(AM)
127-
..()
134+
return
128135

129136

130137
/obj/item/assembly/mousetrap/on_found(mob/finder)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070
if(observe.client)
7171
observe.client.screen -= I
7272
I.forceMove(src)
73-
I.plane = ABOVE_HUD_PLANE
73+
SET_PLANE_EXPLICIT(I, ABOVE_HUD_PLANE, src)
7474
I.appearance_flags |= NO_CLIENT_COLOR
7575
var/not_handled = FALSE
7676
switch(slot)

code/modules/mob/living/simple_animal/friendly/cockroach.dm

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,16 @@
2828
var/squish_chance = 50
2929
del_on_death = 1
3030

31+
32+
/mob/living/simple_animal/cockroach/Initialize(mapload)
33+
. = ..()
34+
AddComponent( \
35+
/datum/component/squashable, \
36+
squash_chance = 50, \
37+
squash_damage = 1, \
38+
squash_flags = SQUASHED_SHOULD_BE_GIBBED|SQUASHED_ALWAYS_IF_DEAD|SQUASHED_DONT_SQUASH_IN_CONTENTS, \
39+
)
40+
3141
/mob/living/simple_animal/cockroach/death(gibbed)
3242
if(SSticker.mode && SSticker.mode.station_was_nuked) //If the nuke is going off, then cockroaches are invincible. Keeps the nuke from killing them, cause cockroaches are immune to nukes.
3343
return

code/modules/mob/living/simple_animal/hostile/retaliate/frog.dm

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,13 @@
3636
icon_living = "rare_frog"
3737
icon_dead = "rare_frog_dead"
3838
butcher_results = list(/obj/item/reagent_containers/food/snacks/nugget = 5)
39+
var/static/list/loc_connections = list(
40+
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
41+
)
42+
AddElement(/datum/element/connect_loc, loc_connections)
3943

40-
/mob/living/simple_animal/hostile/retaliate/frog/Crossed(AM as mob|obj)
41-
. = ..()
44+
45+
/mob/living/simple_animal/hostile/retaliate/frog/proc/on_entered(datum/source, atom/movable/AM, ...)
4246
if(!stat && isliving(AM))
4347
var/mob/living/L = AM
4448
if(L.mob_size > MOB_SIZE_TINY)

0 commit comments

Comments
 (0)