diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm
index e0bdd54cae3..fa85efec9b2 100644
--- a/code/_onclick/item_attack.dm
+++ b/code/_onclick/item_attack.dm
@@ -39,6 +39,16 @@
visible_message("[attack_message]",
"[attack_message]")
+ if((butcher_results) && (stat == DEAD))
+ var/sharpness = is_sharp(I)
+ if(sharpness)
+ user.changeNext_move(CLICK_CD_MELEE)
+ user << "You begin to butcher [src]..."
+ playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
+ if(do_mob(user, src, 80/sharpness))
+ harvest(user)
+ return
+
/mob/living/simple_animal/attacked_by(var/obj/item/I, var/mob/living/user)
if(!I.force)
user.visible_message("[user] gently taps [src] with [I].",\
diff --git a/code/game/objects/structures/kitchen_spike.dm b/code/game/objects/structures/kitchen_spike.dm
index 2587f2db3f1..46979a3b380 100644
--- a/code/game/objects/structures/kitchen_spike.dm
+++ b/code/game/objects/structures/kitchen_spike.dm
@@ -1,13 +1,3 @@
-#define SKINTYPE_MONKEY /obj/item/stack/sheet/animalhide/monkey
-#define SKINTYPE_ALIEN /obj/item/stack/sheet/animalhide/xeno
-#define SKINTYPE_BEAR /obj/item/clothing/head/bearpelt
-#define SKINTYPE_CORGI /obj/item/stack/sheet/animalhide/corgi
-
-#define MEATTYPE_MONKEY /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey
-#define MEATTYPE_ALIEN /obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno
-#define MEATTYPE_BEAR /obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear
-#define MEATTYPE_CORGI /obj/item/weapon/reagent_containers/food/snacks/meat/slab/corgi
-
//////Kitchen Spike
/obj/structure/kitchenspike_frame
@@ -38,44 +28,17 @@
desc = "A spike for collecting meat from animals"
density = 1
anchored = 1
- var/meat = 0
- var/occupied = 0
- var/meattype = null
- var/skin = 0
- var/skintype = null
+ buckle_lying = 0
+ can_buckle = 1
- var/global/list/allowed_types = list( //ugh I know it's a whitelist but it's not as god-awful and hacky as before. at least this way it's sustainable. i don't think there's even a better way than this.
- /mob/living/carbon/monkey,
- /mob/living/carbon/alien,
- /mob/living/simple_animal/hostile/bear,
- /mob/living/simple_animal/pet/dog/corgi,
- )
-
- var/global/list/meatlist = list(
- "monkey" = MEATTYPE_MONKEY,
- "alien" = MEATTYPE_ALIEN,
- "bear" = MEATTYPE_BEAR,
- "corgi" = MEATTYPE_CORGI,
- )
- var/global/list/skinlist = list(
- "monkey" = SKINTYPE_MONKEY,
- "alien" = SKINTYPE_ALIEN,
- "bear" = SKINTYPE_BEAR,
- "corgi" = SKINTYPE_CORGI,
- )
/obj/structure/kitchenspike/attack_paw(mob/user)
return src.attack_hand(usr)
-/obj/structure/kitchenspike/proc/is_mob_allowed(var/obj/item/weapon/grab/G)
- for(var/I in allowed_types)
- if(istype(G.affecting, I))
- return I
- return 0
/obj/structure/kitchenspike/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/crowbar))
- if(!src.occupied)
+ if(!src.buckled_mob)
playsound(loc, 'sound/items/Crowbar.ogg', 100, 1)
if(do_after(user, 20, target = src))
user << "You pry the spikes out of the frame."
@@ -88,69 +51,71 @@
return
if(istype(I, /obj/item/weapon/grab))
var/obj/item/weapon/grab/G = I
- var/allowed_type = is_mob_allowed(G)
- if(allowed_type)
- if(!occupied)
- occupied = 1
- meat = 5
- skin = 1
-
- var/list/affecting_path = text2list("[allowed_type]", "/") //we want a specific part of the type path for this: the last part of the path in allowed_types
- var/affecting_type = affecting_path[affecting_path.len] //ex. 1 if affecting.type is /mob/living/carbon/monkey, this will set affecting_type to "monkey"
- //ex. 2 if affecting.type is /mob/living/carbon/alien/humanoid/queen, this will set affecting_type to "alien"
-
- //set these vars to the appropriate values based on type
- icon_state = "spikebloody[affecting_type]"
- meattype = meatlist["[affecting_type]"]
- skintype = skinlist["[affecting_type]"]
-
- var/mob/living/O = G.affecting
- O.visible_message(text("[user] has forced [G.affecting] onto the spike, killing them instantly!"))
- qdel(G.affecting)
- qdel(G)
- else
- user << "The spike already has something on it; finish collecting its meat first!"
- return
- if(istype(G.affecting, /mob/living/carbon/human))
- user.changeNext_move(CLICK_CD_MELEE)
- playsound(src.loc, "sound/effects/splat.ogg", 25, 1)
- var/mob/living/carbon/human/H = G.affecting
- H.visible_message("[user] slams [G.affecting] into the meat spike!", "[user] slams you into the meat spike!", "You hear a squishy wet noise.")
- H.adjustBruteLoss(20)
- return
+ if(istype(G.affecting, /mob/living/))
+ if(!buckled_mob)
+ if(do_mob(user, src, 120))
+ if(buckled_mob) //to prevent spam/queing up attacks
+ return
+ if(G.affecting.buckled)
+ return
+ var/mob/living/H = G.affecting
+ playsound(src.loc, "sound/effects/splat.ogg", 25, 1)
+ H.visible_message("[user] slams [G.affecting] onto the meat spike!", "[user] slams you onto the meat spike!", "You hear a squishy wet noise.")
+ H.loc = src.loc
+ H.emote("scream")
+ if(istype(H, /mob/living/carbon/human)) //So you don't get human blood when you spike a giant spidere
+ var/turf/pos = get_turf(H)
+ pos.add_blood_floor(H)
+ H.adjustBruteLoss(30)
+ H.buckled = src
+ H.dir = 2
+ buckled_mob = H
+ var/matrix/m120 = matrix(H.transform)
+ m120.Turn(180)
+ animate(H, transform = m120, time = 3)
+ H.pixel_y = H.get_standard_pixel_y_offset(180)
+ return
user << "You can't use that on the spike!"
return
..()
-///obj/structure/kitchenspike/MouseDrop_T(var/atom/movable/C, mob/user)
-// if(istype(C, /obj/mob/carbon/monkey)
-// else if(istype(C, /obj/mob/carbon/alien) && !istype(C, /mob/living/carbon/alien/larva/slime))
-// else if(istype(C, /obj/livestock/spesscarp
+/obj/structure/kitchenspike/user_buckle_mob(mob/living/M, mob/living/user) //Don't want them getting put on the rack other than by spiking
+ return
-/obj/structure/kitchenspike/attack_hand(mob/user)
- if(..())
- return
- if(occupied)
- if(meat >= 1)
- new meattype(src.loc)
- meat--
- if(meat > 1)
- usr << "You remove some meat from [src]."
+/obj/structure/kitchenspike/user_unbuckle_mob(mob/living/carbon/human/user)
+ if(buckled_mob && buckled_mob.buckled == src)
+ var/mob/living/M = buckled_mob
+ if(M != user)
+ M.visible_message(\
+ "[user.name] tries to pull [M.name] free of the [src]!",\
+ "[user.name] is trying to pull you off the [src], opening up fresh wounds!",\
+ "You hear a squishy wet noise.")
+ if(!do_after(user, 300, target = src))
+ if(M && M.buckled)
+ M.visible_message(\
+ "[user.name] fails to free [M.name]!",\
+ "[user.name] fails to pull you off of the [src].")
+ return
+
+ else
+ M.visible_message(\
+ "[M.name] struggles to break free from the [src]!",\
+ "You struggle to break free from the [src], exacerbating your wounds! (Stay still for two minutes.)",\
+ "You hear a wet squishing noise..")
+ M.adjustBruteLoss(30)
+ if(!do_after(M, 1200, target = src))
+ if(M && M.buckled)
+ M << "You fail to free yourself!"
+ return
+ if(!M.buckled)
return
- if(src.skin >=1)
- new skintype(src.loc)
- skin--
- usr << "You remove the hide from [src]."
- icon_state = "spike"
- occupied = 0
-
-
-#undef SKINTYPE_MONKEY
-#undef SKINTYPE_ALIEN
-#undef SKINTYPE_BEAR
-#undef SKINTYPE_CORGI
-
-#undef MEATTYPE_MONKEY
-#undef MEATTYPE_ALIEN
-#undef MEATTYPE_BEAR
-#undef MEATTYPE_CORGI
\ No newline at end of file
+ var/mob/living/L = buckled_mob
+ var/matrix/m120 = matrix(L.transform)
+ m120.Turn(360)
+ animate(L, transform = m120, time = 3)
+ L.pixel_y = L.get_standard_pixel_y_offset(360)
+ M.adjustBruteLoss(30)
+ src.visible_message(text("[M] falls free of the [src]!"))
+ unbuckle_mob()
+ L.emote("scream")
+ L.AdjustWeakened(10)
diff --git a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
index 4a190c27c7d..b5bbee5eb4c 100644
--- a/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
+++ b/code/modules/mob/living/carbon/alien/humanoid/humanoid.dm
@@ -2,6 +2,7 @@
name = "alien"
icon_state = "alien_s"
pass_flags = PASSTABLE
+ butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/xeno = 5, /obj/item/stack/sheet/animalhide/xeno = 1)
var/obj/item/r_store = null
var/obj/item/l_store = null
var/caste = ""
diff --git a/code/modules/mob/living/carbon/monkey/monkey.dm b/code/modules/mob/living/carbon/monkey/monkey.dm
index 64f73ca3980..844ebd793ae 100644
--- a/code/modules/mob/living/carbon/monkey/monkey.dm
+++ b/code/modules/mob/living/carbon/monkey/monkey.dm
@@ -8,6 +8,7 @@
pass_flags = PASSTABLE
languages = MONKEY
ventcrawler = 1
+ butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey = 5, /obj/item/stack/sheet/animalhide/monkey = 1)
type_of_meat = /obj/item/weapon/reagent_containers/food/snacks/meat/slab/monkey
gib_type = /obj/effect/decal/cleanable/blood/gibs
unique_name = 1
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 7d7b67a5d69..a2ef1cb8689 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -895,3 +895,14 @@ Sorry Giacom. Please don't be mad :(
//used in datum/reagents/reaction() proc
/mob/living/proc/get_permeability_protection()
return 0
+
+/mob/living/proc/harvest(mob/living/user)
+ if(qdeleted(src))
+ return
+ if(butcher_results)
+ for(var/path in butcher_results)
+ for(var/i = 1; i <= butcher_results[path];i++)
+ new path(src.loc)
+ butcher_results.Remove(path) //In case you want to have things like simple_animals drop their butcher results on gib, so it won't double up below.
+ visible_message("[user] butchers [src].")
+ gib()
\ No newline at end of file
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index b9f1cefa0f2..0c4d370dca7 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -53,3 +53,5 @@
var/last_bumped = 0
var/unique_name = 0 //if a mob's name should be appended with an id when created e.g. Mob (666)
+
+ var/list/butcher_results = null
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index b091ed92d39..6121354b335 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -14,7 +14,7 @@
taunt_chance = 25
turns_per_move = 5
see_in_dark = 6
- butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear = 5)
+ butcher_results = list(/obj/item/weapon/reagent_containers/food/snacks/meat/slab/bear = 5, /obj/item/clothing/head/bearpelt = 1)
response_help = "pets"
response_disarm = "gently pushes aside"
response_harm = "hits"
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index 36055b70011..fb57e9a55f5 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -18,7 +18,6 @@
var/turns_per_move = 1
var/turns_since_move = 0
- var/list/butcher_results = null
var/stop_automated_movement = 0 //Use this to temporarely stop random movement or to if you write special movement code for animals.
var/wander = 1 // Does the mob wander around when idle?
var/stop_automated_movement_when_pulled = 1 //When set to 1 this stops the animal from moving when someone is pulling it.
@@ -364,16 +363,6 @@
if(O.flags & NOBLUDGEON)
return
- if((butcher_results) && (stat == DEAD))
- user.changeNext_move(CLICK_CD_MELEE)
- var/sharpness = is_sharp(O)
- if(sharpness)
- user << "You begin to butcher [src]..."
- playsound(loc, 'sound/weapons/slice.ogg', 50, 1, -1)
- if(do_mob(user, src, 80/sharpness))
- harvest(user)
- return
-
..()
/mob/living/simple_animal/movement_delay()
@@ -468,11 +457,6 @@
if(alone && partner && children < 3)
new childtype(loc)
-// Harvest an animal's delicious byproducts
-/mob/living/simple_animal/proc/harvest(mob/living/user)
- visible_message("[user] butchers [src].")
- gib()
-
/mob/living/simple_animal/stripPanelUnequip(obj/item/what, mob/who, where, child_override)
if(!child_override)
src << "You don't have the dexterity to do this!"
diff --git a/html/changelogs/Kor-PR-Profligates.yml b/html/changelogs/Kor-PR-Profligates.yml
new file mode 100644
index 00000000000..c4acafd56fe
--- /dev/null
+++ b/html/changelogs/Kor-PR-Profligates.yml
@@ -0,0 +1,37 @@
+################################
+# Example Changelog File
+#
+# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
+#
+# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
+# When it is, any changes listed below will disappear.
+#
+# Valid Prefixes:
+# bugfix
+# wip (For works in progress)
+# tweak
+# soundadd
+# sounddel
+# rscadd (general adding of nice things)
+# rscdel (general deleting of nice things)
+# imageadd
+# imagedel
+# spellcheck (typo fixes)
+# experiment
+# tgs (TG-ported fixes?)
+#################################
+
+# Your name.
+author: Kor
+
+# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
+delete-after: True
+
+# Any changes you've made. See valid prefix list above.
+# INDENT WITH TWO SPACES. NOT TABS. SPACES.
+# SCREW THIS UP AND IT WON'T WORK.
+# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
+# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
+changes:
+ - rscadd: "You can now hang human mobs (dead or alive) from meatspikes. Escaping the meatspike will further damage the victim."
+ - rscdel: "You can no longer slam humans into the meatspike as an attack."