diff --git a/code/datums/elements/squish.dm b/code/datums/elements/squish.dm
new file mode 100644
index 00000000..823d391e
--- /dev/null
+++ b/code/datums/elements/squish.dm
@@ -0,0 +1,28 @@
+#define SHORT 5/7
+#define TALL 7/5
+
+/datum/element/squish
+ element_flags = ELEMENT_DETACH
+
+/datum/element/squish/Attach(datum/target, duration)
+ . = ..()
+ if(!iscarbon(target))
+ return ELEMENT_INCOMPATIBLE
+
+ var/mob/living/carbon/C = target
+ var/was_lying = (C.lying != 0)
+ addtimer(CALLBACK(src, .proc/Detach, C, was_lying), duration)
+
+ C.transform = C.transform.Scale(TALL, SHORT)
+
+/datum/element/squish/Detach(mob/living/carbon/C, was_lying)
+ . = ..()
+ if(istype(C))
+ var/is_lying = (C.lying != 0)
+ if(was_lying == is_lying)
+ C.transform = C.transform.Scale(SHORT, TALL)
+ else
+ C.transform = C.transform.Scale(TALL, SHORT)
+
+#undef SHORT
+#undef TALL
diff --git a/code/modules/vending/_vending.dm b/code/modules/vending/_vending.dm
index a49efde2..b256d861 100644
--- a/code/modules/vending/_vending.dm
+++ b/code/modules/vending/_vending.dm
@@ -74,6 +74,14 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
var/obj/item/vending_refill/refill_canister = null //The type of refill canisters used by this machine
+ //tilting stuff
+ var/tilted = FALSE
+ var/tiltable = TRUE
+ var/squish_damage = 75
+ var/forcecrit = 0
+ var/num_shards = 7
+ var/list/pinned_mobs = list()
+
//hyper economy stuff
var/credits = 0
var/baseprice = 0
@@ -102,6 +110,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
power_change()
/obj/machinery/vending/Destroy()
+ unbuckle_all_mobs(TRUE)
QDEL_NULL(wires)
QDEL_NULL(coin)
QDEL_NULL(bill)
@@ -230,6 +239,7 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
/obj/machinery/vending/wrench_act(mob/living/user, obj/item/I)
if(panel_open)
default_unfasten_wrench(user, I, time = 60)
+ unbuckle_all_mobs(TRUE)
return TRUE
/obj/machinery/vending/screwdriver_act(mob/living/user, obj/item/I)
@@ -307,7 +317,133 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
to_chat(user, "There's nothing to restock!")
return
else
- return ..()
+ . = ..()
+ if(tiltable && !tilted && I.force)
+ switch(rand(1, 100))
+ if(1 to 5)
+ freebie(user, 3)
+ if(6 to 15)
+ freebie(user, 2)
+ if(16 to 25)
+ freebie(user, 1)
+ if(76 to 90)
+ tilt(user)
+ if(91 to 100)
+ tilt(user, crit=TRUE)
+
+/obj/machinery/vending/proc/freebie(mob/fatty, freebies)
+ visible_message("[src] yields [freebies > 1 ? "several free goodies" : "a free goody"]!")
+
+ for(var/i in 1 to freebies)
+ playsound(src, 'sound/items/vending.ogg', 50, TRUE, extrarange = -3)
+ for(var/datum/data/vending_product/R in shuffle(product_records))
+
+ if(R.amount <= 0) //Try to use a record that actually has something to dump.
+ continue
+ var/dump_path = R.product_path
+ if(!dump_path)
+ continue
+
+ R.amount--
+ new dump_path(get_turf(src))
+ break
+
+/obj/machinery/vending/proc/tilt(mob/fatty, crit=FALSE)
+ visible_message("[src] tips over!")
+ tilted = TRUE
+ layer = ABOVE_MOB_LAYER
+
+ var/crit_case
+ if(crit)
+ crit_case = rand(1,5)
+
+ if(forcecrit)
+ crit_case = forcecrit
+
+ if(in_range(fatty, src))
+ for(var/mob/living/L in get_turf(fatty))
+ var/mob/living/carbon/C = L
+
+ if(istype(C))
+ var/crit_rebate = 0 // lessen the normal damage we deal for some of the crits
+
+ if(crit_case != 5) // the head asplode case has its own description
+ C.visible_message("[C] is crushed by [src]!", \
+ "You are crushed by [src]!")
+
+ switch(crit_case) // only carbons can have the fun crits
+ if(1) // shatter their legs and bleed 'em
+ crit_rebate = 60
+ C.bleed(150)
+ var/obj/item/bodypart/l_leg/l = C.get_bodypart(BODY_ZONE_L_LEG)
+ if(l)
+ l.receive_damage(brute=200, updating_health=TRUE)
+ var/obj/item/bodypart/r_leg/r = C.get_bodypart(BODY_ZONE_R_LEG)
+ if(r)
+ r.receive_damage(brute=200, updating_health=TRUE)
+ if(l || r)
+ C.visible_message("[C]'s legs shatter with a sickening crunch!", \
+ "Your legs shatter with a sickening crunch!")
+ if(2) // pin them beneath the machine until someone untilts it
+ forceMove(get_turf(C))
+ buckle_mob(C, force=TRUE)
+ C.visible_message("[C] is pinned underneath [src]!", \
+ "You are pinned down by [src]!")
+ if(3) // glass candy
+ crit_rebate = 50
+ for(var/i = 0, i < num_shards, i++)
+ var/obj/item/shard/shard = new /obj/item/shard(get_turf(C))
+ shard.embedding = shard.embedding.setRating(embed_chance = 100)
+ C.hitby(shard, skipcatch = TRUE, hitpush = FALSE)
+ shard.embedding = shard.embedding.setRating(embed_chance = EMBED_CHANCE)
+ if(4) // paralyze this binch
+ // the new paraplegic gets like 4 lines of losing their legs so skip them
+ visible_message("[C]'s spinal cord is obliterated with a sickening crunch!", ignored_mobs = list(C))
+ C.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic)
+ if(5) // skull squish!
+ var/obj/item/bodypart/head/O = C.get_bodypart(BODY_ZONE_HEAD)
+ if(O)
+ C.visible_message("[O] explodes in a shower of gore beneath [src]!", \
+ "Oh f-")
+ O.dismember()
+ O.drop_organs()
+ qdel(O)
+ new /obj/effect/gibspawner/human/bodypartless(get_turf(C))
+ C.apply_damage(max(0, squish_damage - crit_rebate), BRUTE)
+ C.AddElement(/datum/element/squish, 60 SECONDS)
+ else
+ L.visible_message("[L] is crushed by [src]!", \
+ "You are crushed by [src]!")
+ L.apply_damage(squish_damage, BRUTE)
+ if(crit_case)
+ L.apply_damage(squish_damage, BRUTE)
+
+ //L.Paralyze(60) We don't have paralyze, too bad.
+ L.Stun(60, TRUE, TRUE)
+ L.Knockdown(60)
+ L.emote("scream")
+ playsound(L, 'sound/effects/blobattack.ogg', 40, TRUE)
+ playsound(L, 'sound/effects/splat.ogg', 50, TRUE)
+
+ var/matrix/M = matrix()
+ M.Turn(pick(90, 270))
+ transform = M
+
+ if(get_turf(fatty) != get_turf(src))
+ throw_at(get_turf(fatty), 1, 1, spin=FALSE)
+
+/obj/machinery/vending/proc/untilt(mob/user)
+ user.visible_message("[user] rights [src].", \
+ "You right [src].")
+
+ unbuckle_all_mobs(TRUE)
+
+ tilted = FALSE
+ layer = initial(layer)
+
+ var/matrix/M = matrix()
+ M.Turn(0)
+ transform = M
/obj/machinery/vending/exchange_parts(mob/user, obj/item/storage/part_replacer/W)
if(!istype(W))
@@ -345,6 +481,11 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C
if(seconds_electrified && !(stat & NOPOWER))
if(shock(user, 100))
return
+ if(tilted && !user.buckled)
+ to_chat(user, "You begin righting \the [src].")
+ if(do_after(user, 50, target=src))
+ untilt(user)
+ return
return ..()
/obj/machinery/vending/ui_interact(mob/user)
diff --git a/code/modules/vending/medical_wall.dm b/code/modules/vending/medical_wall.dm
index 514bbd87..cc345016 100644
--- a/code/modules/vending/medical_wall.dm
+++ b/code/modules/vending/medical_wall.dm
@@ -18,6 +18,7 @@
armor = list("melee" = 100, "bullet" = 100, "laser" = 100, "energy" = 100, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 100, "acid" = 50)
resistance_flags = FIRE_PROOF
refill_canister = /obj/item/vending_refill/wallmed
+ tiltable = FALSE
/obj/item/vending_refill/wallmed
machine_name = "NanoMed"
diff --git a/tgstation.dme b/tgstation.dme
index 3dc26428..855cf5a3 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -468,6 +468,7 @@
#include "code\datums\elements\flavor_text.dm"
#include "code\datums\elements\ghost_role_eligibility.dm"
#include "code\datums\elements\mob_holder.dm"
+#include "code\datums\elements\squish.dm"
#include "code\datums\elements\swimming.dm"
#include "code\datums\elements\wuv.dm"
#include "code\datums\helper_datums\events.dm"