diff --git a/code/modules/food_and_drinks/food/snacks_burgers.dm b/code/modules/food_and_drinks/food/snacks_burgers.dm
index 814875d2..f9169ca3 100644
--- a/code/modules/food_and_drinks/food/snacks_burgers.dm
+++ b/code/modules/food_and_drinks/food/snacks_burgers.dm
@@ -281,3 +281,11 @@
bonus_reagents = list("nutriment" = 8, "vitamin" = 1)
tastes = list("bun" = 4, "bacon" = 2)
foodtype = GRAIN | MEAT
+
+/obj/item/reagent_containers/food/snacks/burger/cumburger
+ name = "Cumburger"
+ desc = "A sticky and salty burger."
+ icon_state = "cumburger"
+ tastes = list("bun" = 4, "salt" = 5)
+ bonus_reagents = list("nutriment" = 3, "vitamin" = 10, "semen" = 10, "aphro" = 5)
+ foodtype = GRAIN
\ No newline at end of file
diff --git a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
index d7beebf4..733c6c48 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
@@ -176,7 +176,7 @@
)
result = /obj/item/reagent_containers/food/snacks/burger/purple
subcategory = CAT_BURGER
-
+
/datum/crafting_recipe/food/blackburger
name = "Black burger"
reqs = list(
@@ -186,7 +186,7 @@
)
result = /obj/item/reagent_containers/food/snacks/burger/black
subcategory = CAT_BURGER
-
+
/datum/crafting_recipe/food/whiteburger
name = "White burger"
reqs = list(
@@ -293,3 +293,12 @@
result = /obj/item/reagent_containers/food/snacks/burger/baconburger
subcategory = CAT_BURGER
+
+/datum/crafting_recipe/food/burger
+ name = "Cumburger"
+ reqs = list(
+ /datum/reagent/consumable/semen = 10,
+ /obj/item/reagent_containers/food/snacks/bun = 1
+ )
+ result = /obj/item/reagent_containers/food/snacks/burger/cumburger
+ subcategory = CAT_BURGER
\ No newline at end of file
diff --git a/hyperstation/code/obj/leash.dm b/hyperstation/code/obj/leash.dm
index a4f94c98..75ce8c00 100644
--- a/hyperstation/code/obj/leash.dm
+++ b/hyperstation/code/obj/leash.dm
@@ -1,403 +1,403 @@
-//Jay Sparrow
-//TODO
-/*
-Icons, maybe?
-*/
-
-#define STATUS_EFFECT_LEASH_PET /datum/status_effect/leash_pet
-#define STATUS_EFFECT_LEASH_DOM /datum/status_effect/leash_dom
-#define STATUS_EFFECT_LEASH_FREEPET /datum/status_effect/leash_freepet
-#define MOVESPEED_ID_LEASH "LEASH"
-
-/////STATUS EFFECTS/////
-//These are mostly used as flags for the states each member can be in
-
-/datum/status_effect/leash_dom
- status_type = STATUS_EFFECT_UNIQUE
- alert_type = /obj/screen/alert/status_effect/leash_dom
-
-/obj/screen/alert/status_effect/leash_dom
- name = "Leash Master"
- desc = "You've got a leash, and a cute pet on the other end."
- icon_state = "leash_master" //These call icons that don't exist, so no icon comes up. Which is good.
- //As a result, the descriptions also don't proc, which is fine.
-
-/datum/status_effect/leash_freepet
- status_type = STATUS_EFFECT_UNIQUE
- alert_type = /obj/screen/alert/status_effect/leash_freepet
-
-/obj/screen/alert/status_effect/leash_freepet
- name = "Escaped Pet"
- desc = "You're on a leash, but you've no master. If anyone grabs the leash they'll gain control!"
- icon_state = "leash_freepet"
-
-
-/datum/status_effect/leash_pet
- id = "leashed"
- status_type = STATUS_EFFECT_UNIQUE
- var/datum/weakref/redirect_component
- alert_type = /obj/screen/alert/status_effect/leash_pet
-
-/obj/screen/alert/status_effect/leash_pet
- name = "Leashed Pet"
- desc = "You're on the hook now! Be good for your master."
- icon_state = "leash_pet"
-
-
-/datum/status_effect/leash_pet/on_apply()
- redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/owner_resist))))
- if(!owner.stat)
- to_chat(owner, "You have been leashed!")
- return ..()
-
-//This lets the pet resist their leash
-/datum/status_effect/leash_pet/proc/owner_resist()
- to_chat(owner, "You reach for the hook on your collar...")
- //Determine how long it takes to remove the leash
- var/deleash = 15
- //if(owner.get_item_by_slot(SLOT_HANDCUFFED)) //Commented out because there is no clear way to make this proc BEFORE decuff on resist.
- //deleash = 100
- if(do_mob(owner, owner, deleash))//do_mob creates a progress bar and then enacts the code after. Owner, owner, because it's an act on themself
- if(!QDELETED(src))
- to_chat(owner, "[owner] has removed their leash!")
- owner.remove_status_effect(/datum/status_effect/leash_pet)
-
-///// OBJECT /////
-//The leash object itself
-//The component variables are used for hooks, used later.
-
-/obj/item/leash
- name = "leash"
- desc = "A simple tether that can easily be hooked onto a collar. Perfect for your pet."
- icon = 'hyperstation/icons/obj/leash.dmi'
- icon_state = "leash"
- item_state = "leash"
- throw_range = 4
- slot_flags = ITEM_SLOT_BELT
- force = 1
- throwforce = 1
- w_class = WEIGHT_CLASS_SMALL
- var/leash_used = 0 //A flag to see if the leash has been used yet, because for some reason picking up an unused leash is weird
- var/mob/living/leash_pet = "null" //Variable to store our pet later
- var/mob/living/leash_master = "null" //And our master too
- var/datum/component/mobhook_leash_pet
- var/datum/component/mobhook_leash_master //Needed to watch for these entities to move
- var/datum/component/mobhook_leash_freepet
- var/leash_location[3] //Three digit list for us to store coordinates later
-
-//Called when someone is clicked with the leash
-/obj/item/leash/attack(mob/living/carbon/C, mob/living/user) //C is the target, user is the one with the leash
- if(istype(C.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/petcollar) || istype(C.get_item_by_slot(SLOT_NECK), /obj/item/electropack/shockcollar))
- var/leashtime = 50
- if(C.handcuffed)
- leashtime = 5
- if(do_mob(user, C, leashtime)) //do_mob adds a progress bar, but then we also check to see if they have a collar
- log_combat(user, C, "leashed", addition="playfully")
- //TODO: Figure out how to make an easy breakout for leashed leash_pets
- C.apply_status_effect(/datum/status_effect/leash_pet)//Has now been leashed
- user.apply_status_effect(/datum/status_effect/leash_dom) //Is the leasher
- leash_pet = C //Save pet reference for later
- leash_master = user //Save dom reference for later
- mobhook_leash_pet = leash_pet.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_pet_move)))
- mobhook_leash_master = leash_master.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_master_move)))
- leash_used = 1
- if(!leash_pet.has_status_effect(/datum/status_effect/leash_dom)) //Add slowdown if the pet didn't leash themselves
- leash_pet.add_movespeed_modifier(MOVESPEED_ID_LEASH, multiplicative_slowdown = 5)
- for(var/mob/viewing in viewers(user, null))
- if(viewing == leash_master)
- to_chat(leash_master, "You have hooked a leash onto [leash_pet]!")
- else
- viewing.show_message("[leash_pet] has been leashed by [leash_master]!", 1)
- if(leash_pet.has_status_effect(/datum/status_effect/leash_dom)) //Pet leashed themself. They are not the dom
- leash_pet.apply_status_effect(/datum/status_effect/leash_freepet)
- leash_pet.remove_status_effect(/datum/status_effect/leash_dom)
- while(1) //While true loop. The mark of a genius coder. ##MAINLOOP START
- sleep(2) //Check every other tick
- if(leash_pet == "null") //No pet, break loop
- return
- if(!(leash_pet.get_item_by_slot(SLOT_NECK))) //The pet has slipped their collar and is not the pet anymore.
- for(var/mob/viewing in viewers(user, null))
- viewing.show_message("[leash_pet] has slipped out of their collar!!", 1)
- to_chat(leash_pet, "You have slipped out of your collar!")
- to_chat(loc, "[leash_pet] has slipped out of their collar!")
- leash_pet.remove_status_effect(/datum/status_effect/leash_pet)
-
- if(!leash_pet.has_status_effect(/datum/status_effect/leash_pet)) //If there is no pet, there is no dom. Loop breaks.
- QDEL_NULL(mobhook_leash_master)
- QDEL_NULL(mobhook_leash_pet)
- QDEL_NULL(mobhook_leash_freepet)
- if(leash_pet.has_status_effect(/datum/status_effect/leash_freepet))
- leash_pet.remove_status_effect(/datum/status_effect/leash_freepet)
- if(leash_pet.has_movespeed_modifier(MOVESPEED_ID_LEASH))
- leash_pet.remove_movespeed_modifier(MOVESPEED_ID_LEASH)
- if(!leash_master == "null")
- leash_master.remove_status_effect(/datum/status_effect/leash_dom)
- leash_used = 0 //reset the leash to neutral
- leash_pet = "null"
- return
-
- else //No collar, no fun
- var/leash_message = pick("Your pet needs a collar")
- to_chat(user, "[leash_message]")
-
-//Called when the leash is used in hand
-//Tugs the pet closer
-/obj/item/leash/attack_self(mob/living/user)
- if(!leash_pet == "null") //No pet, no tug.
- return
- //Yank the pet. Yank em in close.
- if(leash_pet.x > leash_master.x + 1)
- step(leash_pet, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
- if(leash_pet.y > leash_master.y)//Check the other axis, and tug them into alignment so they are behind the master
- step(leash_pet, SOUTH, 1)
- if(leash_pet.y < leash_master.y)
- step(leash_pet, NORTH, 1)
- if(leash_pet.x < leash_master.x - 1)
- step(leash_pet, EAST, 1)
- if(leash_pet.y > leash_master.y)//Check the other axis, and tug them into alignment so they are behind the master
- step(leash_pet, SOUTH, 1)
- if(leash_pet.y < leash_master.y)
- step(leash_pet, NORTH, 1)
- if(leash_pet.y > leash_master.y + 1)
- step(leash_pet, SOUTH, 1)
- if(leash_pet.x > leash_master.x)//Check the other axis, and tug them into alignment so they are behind the master
- step(leash_pet, WEST, 1)
- if(leash_pet.x < leash_master.x)
- step(leash_pet, EAST, 1)
- if(leash_pet.y < leash_master.y - 1)
- step(leash_pet, NORTH, 1)
- if(leash_pet.x > leash_master.x)//Check the other axis, and tug them into alignment so they are behind the master
- step(leash_pet, WEST, 1)
- if(leash_pet.x < leash_master.x)
- step(leash_pet, EAST, 1)
-
-/obj/item/leash/proc/on_master_move()
- //Make sure the dom still has a pet
- if(leash_master == "null") //There must be a master
- return
- if(leash_pet == "null") //There must be a pet
- return
- if(leash_pet == leash_master) //Pet is the master
- return
- if(!leash_pet.has_status_effect(/datum/status_effect/leash_pet))
- QDEL_NULL(mobhook_leash_master) //Probably redundant, but it's nice to be safe
- leash_master.remove_status_effect(/datum/status_effect/leash_dom)
- return
-
- //If the master moves, pull the pet in behind
- sleep(2) //A small sleep so the pet kind of bounces back after they make the step
- //Also, the sleep means that the distance check for master happens before the pet, to prevent both from proccing.
-
- if(leash_master == "null") //Just to stop error messages
- return
- if(leash_pet == "null")
- return
- if(leash_pet.x > leash_master.x + 2)
- step(leash_pet, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
- if(leash_pet.y > leash_master.y)//Check the other axis, and tug them into alignment so they are behind the master
- step(leash_pet, SOUTH, 1)
- if(leash_pet.y < leash_master.y)
- step(leash_pet, NORTH, 1)
- if(leash_pet.x < leash_master.x - 2)
- step(leash_pet, EAST, 1)
- if(leash_pet.y > leash_master.y)
- step(leash_pet, SOUTH, 1)
- if(leash_pet.y < leash_master.y)
- step(leash_pet, NORTH, 1)
- if(leash_pet.y > leash_master.y + 2)
- step(leash_pet, SOUTH, 1)
- if(leash_pet.x > leash_master.x)
- step(leash_pet, WEST, 1)
- if(leash_pet.x < leash_master.x)
- step(leash_pet, EAST, 1)
- if(leash_pet.y < leash_master.y - 2)
- step(leash_pet, NORTH, 1)
- if(leash_pet.x > leash_master.x)
- step(leash_pet, WEST, 1)
- if(leash_pet.x < leash_master.x)
- step(leash_pet, EAST, 1)
-
- //Knock the pet over if they get further behind. Shouldn't happen too often.
- sleep(3) //This way running normally won't just yank the pet to the ground.
- if(leash_master == "null") //Just to stop error messages. Break the loop early if something removed the master
- return
- if(leash_pet == "null")
- return
- if(leash_pet.x > leash_master.x + 3 || leash_pet.x < leash_master.x - 3 || leash_pet.y > leash_master.y + 3 || leash_pet.y < leash_master.y - 3)
- //var/leash_knockdown_message = "[leash_pet] got pulled to the ground by their leash!"
- //to_chat(leash_master, "[leash_knockdown_message]")
- //to_chat(leash_pet, "[leash_knockdown_message]")
- leash_pet.apply_effect(20, EFFECT_KNOCKDOWN, 0)
-
- //This code is to check if the pet has gotten too far away, and then break the leash.
- sleep(3) //Wait to snap the leash
- if(leash_master == "null") //Just to stop error messages
- return
- if(leash_pet == "null")
- return
- if(leash_pet.x > leash_master.x + 5 || leash_pet.x < leash_master.x - 5 || leash_pet.y > leash_master.y + 5 || leash_pet.y < leash_master.y - 5)
- var/leash_break_message = "The leash snapped free from [leash_pet]!"
- for(var/mob/viewing in viewers(leash_pet, null))
- if(viewing == leash_master)
- to_chat(leash_master, "The leash snapped free from your pet!")
- if(viewing == leash_pet)
- to_chat(leash_pet, "Your leash has popped from your collar!")
- else
- viewing.show_message("[leash_break_message]", 1)
- leash_pet.apply_effect(20, EFFECT_KNOCKDOWN, 0)
- leash_pet.adjustOxyLoss(5)
- leash_pet.remove_status_effect(/datum/status_effect/leash_pet)
- leash_pet.remove_movespeed_modifier(MOVESPEED_ID_LEASH)
- leash_master.remove_status_effect(/datum/status_effect/leash_dom)
- QDEL_NULL(mobhook_leash_master)
- QDEL_NULL(mobhook_leash_pet)
- leash_pet = "null"
- leash_master = "null"
- leash_used = 0
-
-/obj/item/leash/proc/on_pet_move()
- //This should only work if there is a pet and a master.
- //This is here pretty much just to stop the console from flooding with errors
- if(leash_master == "null")
- return
- if(leash_pet == "null")
- return
- //Make sure the pet is still a pet
- if(!leash_pet.has_status_effect(/datum/status_effect/leash_pet))
- QDEL_NULL(mobhook_leash_pet) //Probably redundant, but it's nice to be safe
- return
-
- //The pet has escaped. There is no DOM. GO PET RUN.
- if(leash_pet.has_status_effect(/datum/status_effect/leash_freepet))//If the pet is free, break
- return
-
- //If the pet gets too far away, they get tugged back
- sleep(3)//A small sleep so the pet kind of bounces back after they make the step
- if(leash_master == "null")
- return
- if(leash_pet == "null")
- return
- //West tug
- if(leash_pet.x > leash_master.x + 2)
- step(leash_pet, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
- //East tug
- if(leash_pet.x < leash_master.x - 2)
- step(leash_pet, EAST, 1)
- //South tug
- if(leash_pet.y > leash_master.y + 2)
- step(leash_pet, SOUTH, 1)
- //North tug
- if(leash_pet.y < leash_master.y - 2)
- step(leash_pet, NORTH, 1)
-
-/obj/item/leash/proc/on_freepet_move()
- . = ..()
- //Pet is on the run. Let's drag the leash behind them.
- if(!leash_master == "null") //If there is a master, don't do this
- return
- if(leash_pet == "null") //If there is no pet, don't do this
- return
- if(leash_pet.is_holding_item_of_type(/obj/item/leash)) //If the pet is holding the leash, don't do this
- return
-
- sleep(2)
- if(leash_pet == "null")
- return
- //Double move to catch the leash up to the pet
- if(src.x > leash_pet.x + 2)
- . = step(src, WEST, 1)
- if(src.x < leash_pet.x - 2)
- . = step(src, EAST, 1)
- if(src.y > leash_pet.y + 2)
- . = step(src, SOUTH, 1)
- if(src.y < leash_pet.y - 2)
- . = step(src, NORTH, 1)
- //Primary dragging code
- if(src.x > leash_pet.x + 1)
- . = step(src, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
- if(src.y > leash_pet.y)//Check the other axis, and tug them into alignment so they are behind the pet
- . = step(src, SOUTH, 1)
- if(src.y < leash_pet.y)
- . = step(src, NORTH, 1)
- if(src.x < leash_pet.x - 1)
- . = step(src, EAST, 1)
- if(src.y > leash_pet.y)
- . = step(src, SOUTH, 1)
- if(src.y < leash_pet.y)
- . = step(src, NORTH, 1)
- if(src.y > leash_pet.y + 1)
- . = step(src, SOUTH, 1)
- if(src.x > leash_pet.x)
- . = step(src, WEST, 1)
- if(src.x < leash_pet.x)
- . = step(src, EAST, 1)
- if(src.y < leash_pet.y - 1)
- . = step(src, NORTH, 1)
- if(src.x > leash_pet.x)
- . = step(src, WEST, 1)
- if(src.x < leash_pet.x)
- . = step(src, EAST, 1)
-
- sleep(1)
- //Just to prevent error messages
- if(leash_pet == "null")
- return
- if(src.x > leash_pet.x + 5 || src.x < leash_pet.x - 5 || src.y > leash_pet.y + 5 || src.y < leash_pet.y - 5)
- var/leash_break_message = "The leash snapped free from [leash_pet]!"
- for(var/mob/viewing in viewers(leash_pet, null))
- if(viewing == leash_pet)
- to_chat(leash_pet, "Your leash has popped from your collar!")
- else
- viewing.show_message("[leash_break_message]", 1)
- leash_pet.apply_effect(20, EFFECT_KNOCKDOWN, 0)
- leash_pet.adjustOxyLoss(5)
- leash_pet.remove_status_effect(/datum/status_effect/leash_pet)
- leash_pet.remove_status_effect(/datum/status_effect/leash_freepet)
- QDEL_NULL(mobhook_leash_pet)
- QDEL_NULL(mobhook_leash_freepet)
- leash_pet = "null"
- leash_used = 0
-
-/obj/item/leash/dropped() //Drop the leash, and the leash effects stop
- . = ..()
- if(leash_pet == "null") //There is no pet. Stop this silliness
- return
- if(leash_master == "null")
- return
- //Dropping procs any time the leash changes slots. So, we will wait a tick and see if the leash was actually dropped
- sleep(1)
- if(leash_master.is_holding_item_of_type(/obj/item/leash) || istype(leash_master.get_item_by_slot(SLOT_BELT), /obj/item/leash))
- return //Dom still has the leash as it turns out. Cancel the proc.
- for(var/mob/viewing in viewers(leash_master, null))
- viewing.show_message("[leash_master] has dropped the leash.", 1)
- //DOM HAS DROPPED LEASH. PET IS FREE. SCP HAS BREACHED CONTAINMENT.
- leash_pet.remove_movespeed_modifier(MOVESPEED_ID_LEASH)
- mobhook_leash_freepet = leash_pet.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_freepet_move)))
- leash_master.remove_status_effect(/datum/status_effect/leash_dom) //No dom with no leash. We will get a new dom if the leash is picked back up.
- leash_master = "null"
- QDEL_NULL(mobhook_leash_master)
-
-/obj/item/leash/equipped(mob/user)
- . = ..()
- if(leash_used == 0) //Don't apply statuses with a fresh leash. Keeps things clean on the backend.
- return
- sleep(2)
- if(leash_pet == "null")
- return
- leash_master = user
- if(leash_master.has_status_effect(/datum/status_effect/leash_freepet) || leash_master.has_status_effect(/datum/status_effect/leash_pet)) //Pet picked up their own leash.
- leash_master = "null"
- return
- leash_master.apply_status_effect(/datum/status_effect/leash_dom)
- mobhook_leash_master = leash_master.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_master_move)))
- leash_pet.remove_status_effect(/datum/status_effect/leash_freepet)
- QDEL_NULL(mobhook_leash_freepet)
- leash_pet.add_movespeed_modifier(MOVESPEED_ID_LEASH, multiplicative_slowdown = 5)
-
-/datum/crafting_recipe/leash
- name = "Leash"
- result = /obj/item/leash
- time = 40
- reqs = list(/obj/item/stack/sheet/metal = 1,
- /obj/item/stack/sheet/cloth = 3)
+//Jay Sparrow
+//TODO
+/*
+Icons, maybe?
+*/
+
+#define STATUS_EFFECT_LEASH_PET /datum/status_effect/leash_pet
+#define STATUS_EFFECT_LEASH_DOM /datum/status_effect/leash_dom
+#define STATUS_EFFECT_LEASH_FREEPET /datum/status_effect/leash_freepet
+#define MOVESPEED_ID_LEASH "LEASH"
+
+/////STATUS EFFECTS/////
+//These are mostly used as flags for the states each member can be in
+
+/datum/status_effect/leash_dom
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = /obj/screen/alert/status_effect/leash_dom
+
+/obj/screen/alert/status_effect/leash_dom
+ name = "Leash Master"
+ desc = "You've got a leash, and a cute pet on the other end."
+ icon_state = "leash_master" //These call icons that don't exist, so no icon comes up. Which is good.
+ //As a result, the descriptions also don't proc, which is fine.
+
+/datum/status_effect/leash_freepet
+ status_type = STATUS_EFFECT_UNIQUE
+ alert_type = /obj/screen/alert/status_effect/leash_freepet
+
+/obj/screen/alert/status_effect/leash_freepet
+ name = "Escaped Pet"
+ desc = "You're on a leash, but you've no master. If anyone grabs the leash they'll gain control!"
+ icon_state = "leash_freepet"
+
+
+/datum/status_effect/leash_pet
+ id = "leashed"
+ status_type = STATUS_EFFECT_UNIQUE
+ var/datum/weakref/redirect_component
+ alert_type = /obj/screen/alert/status_effect/leash_pet
+
+/obj/screen/alert/status_effect/leash_pet
+ name = "Leashed Pet"
+ desc = "You're on the hook now! Be good for your master."
+ icon_state = "leash_pet"
+
+
+/datum/status_effect/leash_pet/on_apply()
+ redirect_component = WEAKREF(owner.AddComponent(/datum/component/redirect, list(COMSIG_LIVING_RESIST = CALLBACK(src, .proc/owner_resist))))
+ if(!owner.stat)
+ to_chat(owner, "You have been leashed!")
+ return ..()
+
+//This lets the pet resist their leash
+/datum/status_effect/leash_pet/proc/owner_resist()
+ to_chat(owner, "You reach for the hook on your collar...")
+ //Determine how long it takes to remove the leash
+ var/deleash = 15
+ //if(owner.get_item_by_slot(SLOT_HANDCUFFED)) //Commented out because there is no clear way to make this proc BEFORE decuff on resist.
+ //deleash = 100
+ if(do_mob(owner, owner, deleash))//do_mob creates a progress bar and then enacts the code after. Owner, owner, because it's an act on themself
+ if(!QDELETED(src))
+ to_chat(owner, "[owner] has removed their leash!")
+ owner.remove_status_effect(/datum/status_effect/leash_pet)
+
+///// OBJECT /////
+//The leash object itself
+//The component variables are used for hooks, used later.
+
+/obj/item/leash
+ name = "leash"
+ desc = "A simple tether that can easily be hooked onto a collar. Perfect for your pet."
+ icon = 'hyperstation/icons/obj/leash.dmi'
+ icon_state = "leash"
+ item_state = "leash"
+ throw_range = 4
+ slot_flags = ITEM_SLOT_BELT
+ force = 1
+ throwforce = 1
+ w_class = WEIGHT_CLASS_SMALL
+ var/leash_used = 0 //A flag to see if the leash has been used yet, because for some reason picking up an unused leash is weird
+ var/mob/living/leash_pet = "null" //Variable to store our pet later
+ var/mob/living/leash_master = "null" //And our master too
+ var/datum/component/mobhook_leash_pet
+ var/datum/component/mobhook_leash_master //Needed to watch for these entities to move
+ var/datum/component/mobhook_leash_freepet
+ var/leash_location[3] //Three digit list for us to store coordinates later
+
+//Called when someone is clicked with the leash
+/obj/item/leash/attack(mob/living/carbon/C, mob/living/user) //C is the target, user is the one with the leash
+ if(istype(C.get_item_by_slot(SLOT_NECK), /obj/item/clothing/neck/petcollar) || istype(C.get_item_by_slot(SLOT_NECK), /obj/item/electropack/shockcollar))
+ var/leashtime = 50
+ if(C.handcuffed)
+ leashtime = 5
+ if(do_mob(user, C, leashtime)) //do_mob adds a progress bar, but then we also check to see if they have a collar
+ log_combat(user, C, "leashed", addition="playfully")
+ //TODO: Figure out how to make an easy breakout for leashed leash_pets
+ C.apply_status_effect(/datum/status_effect/leash_pet)//Has now been leashed
+ user.apply_status_effect(/datum/status_effect/leash_dom) //Is the leasher
+ leash_pet = C //Save pet reference for later
+ leash_master = user //Save dom reference for later
+ mobhook_leash_pet = leash_pet.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_pet_move)))
+ mobhook_leash_master = leash_master.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_master_move)))
+ leash_used = 1
+ if(!leash_pet.has_status_effect(/datum/status_effect/leash_dom)) //Add slowdown if the pet didn't leash themselves
+ leash_pet.add_movespeed_modifier(MOVESPEED_ID_LEASH, multiplicative_slowdown = 5)
+ for(var/mob/viewing in viewers(user, null))
+ if(viewing == leash_master)
+ to_chat(leash_master, "You have hooked a leash onto [leash_pet]!")
+ else
+ viewing.show_message("[leash_pet] has been leashed by [leash_master]!", 1)
+ if(leash_pet.has_status_effect(/datum/status_effect/leash_dom)) //Pet leashed themself. They are not the dom
+ leash_pet.apply_status_effect(/datum/status_effect/leash_freepet)
+ leash_pet.remove_status_effect(/datum/status_effect/leash_dom)
+ while(1) //While true loop. The mark of a genius coder. ##MAINLOOP START
+ sleep(2) //Check every other tick
+ if(leash_pet == "null") //No pet, break loop
+ return
+ if(!(leash_pet.get_item_by_slot(SLOT_NECK))) //The pet has slipped their collar and is not the pet anymore.
+ for(var/mob/viewing in viewers(user, null))
+ viewing.show_message("[leash_pet] has slipped out of their collar!!", 1)
+ to_chat(leash_pet, "You have slipped out of your collar!")
+ to_chat(loc, "[leash_pet] has slipped out of their collar!")
+ leash_pet.remove_status_effect(/datum/status_effect/leash_pet)
+
+ if(!leash_pet.has_status_effect(/datum/status_effect/leash_pet)) //If there is no pet, there is no dom. Loop breaks.
+ QDEL_NULL(mobhook_leash_master)
+ QDEL_NULL(mobhook_leash_pet)
+ QDEL_NULL(mobhook_leash_freepet)
+ if(leash_pet.has_status_effect(/datum/status_effect/leash_freepet))
+ leash_pet.remove_status_effect(/datum/status_effect/leash_freepet)
+ if(leash_pet.has_movespeed_modifier(MOVESPEED_ID_LEASH))
+ leash_pet.remove_movespeed_modifier(MOVESPEED_ID_LEASH)
+ if(!leash_master == "null")
+ leash_master.remove_status_effect(/datum/status_effect/leash_dom)
+ leash_used = 0 //reset the leash to neutral
+ leash_pet = "null"
+ return
+
+ else //No collar, no fun
+ var/leash_message = pick("Your pet needs a collar")
+ to_chat(user, "[leash_message]")
+
+//Called when the leash is used in hand
+//Tugs the pet closer
+/obj/item/leash/attack_self(mob/living/user)
+ if(!leash_pet == "null") //No pet, no tug.
+ return
+ //Yank the pet. Yank em in close.
+ if(leash_pet.x > leash_master.x + 1)
+ step(leash_pet, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
+ if(leash_pet.y > leash_master.y)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.y < leash_master.y)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.x < leash_master.x - 1)
+ step(leash_pet, EAST, 1)
+ if(leash_pet.y > leash_master.y)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.y < leash_master.y)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.y > leash_master.y + 1)
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.x > leash_master.x)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, WEST, 1)
+ if(leash_pet.x < leash_master.x)
+ step(leash_pet, EAST, 1)
+ if(leash_pet.y < leash_master.y - 1)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.x > leash_master.x)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, WEST, 1)
+ if(leash_pet.x < leash_master.x)
+ step(leash_pet, EAST, 1)
+
+/obj/item/leash/proc/on_master_move()
+ //Make sure the dom still has a pet
+ if(leash_master == "null") //There must be a master
+ return
+ if(leash_pet == "null") //There must be a pet
+ return
+ if(leash_pet == leash_master) //Pet is the master
+ return
+ if(!leash_pet.has_status_effect(/datum/status_effect/leash_pet))
+ QDEL_NULL(mobhook_leash_master) //Probably redundant, but it's nice to be safe
+ leash_master.remove_status_effect(/datum/status_effect/leash_dom)
+ return
+
+ //If the master moves, pull the pet in behind
+ sleep(2) //A small sleep so the pet kind of bounces back after they make the step
+ //Also, the sleep means that the distance check for master happens before the pet, to prevent both from proccing.
+
+ if(leash_master == "null") //Just to stop error messages
+ return
+ if(leash_pet == "null")
+ return
+ if(leash_pet.x > leash_master.x + 2)
+ step(leash_pet, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
+ if(leash_pet.y > leash_master.y)//Check the other axis, and tug them into alignment so they are behind the master
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.y < leash_master.y)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.x < leash_master.x - 2)
+ step(leash_pet, EAST, 1)
+ if(leash_pet.y > leash_master.y)
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.y < leash_master.y)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.y > leash_master.y + 2)
+ step(leash_pet, SOUTH, 1)
+ if(leash_pet.x > leash_master.x)
+ step(leash_pet, WEST, 1)
+ if(leash_pet.x < leash_master.x)
+ step(leash_pet, EAST, 1)
+ if(leash_pet.y < leash_master.y - 2)
+ step(leash_pet, NORTH, 1)
+ if(leash_pet.x > leash_master.x)
+ step(leash_pet, WEST, 1)
+ if(leash_pet.x < leash_master.x)
+ step(leash_pet, EAST, 1)
+
+ //Knock the pet over if they get further behind. Shouldn't happen too often.
+ sleep(3) //This way running normally won't just yank the pet to the ground.
+ if(leash_master == "null") //Just to stop error messages. Break the loop early if something removed the master
+ return
+ if(leash_pet == "null")
+ return
+ if(leash_pet.x > leash_master.x + 3 || leash_pet.x < leash_master.x - 3 || leash_pet.y > leash_master.y + 3 || leash_pet.y < leash_master.y - 3)
+ //var/leash_knockdown_message = "[leash_pet] got pulled to the ground by their leash!"
+ //to_chat(leash_master, "[leash_knockdown_message]")
+ //to_chat(leash_pet, "[leash_knockdown_message]")
+ leash_pet.apply_effect(20, EFFECT_KNOCKDOWN, 0)
+
+ //This code is to check if the pet has gotten too far away, and then break the leash.
+ sleep(3) //Wait to snap the leash
+ if(leash_master == "null") //Just to stop error messages
+ return
+ if(leash_pet == "null")
+ return
+ if(leash_pet.x > leash_master.x + 5 || leash_pet.x < leash_master.x - 5 || leash_pet.y > leash_master.y + 5 || leash_pet.y < leash_master.y - 5)
+ var/leash_break_message = "The leash snapped free from [leash_pet]!"
+ for(var/mob/viewing in viewers(leash_pet, null))
+ if(viewing == leash_master)
+ to_chat(leash_master, "The leash snapped free from your pet!")
+ if(viewing == leash_pet)
+ to_chat(leash_pet, "Your leash has popped from your collar!")
+ else
+ viewing.show_message("[leash_break_message]", 1)
+ leash_pet.apply_effect(20, EFFECT_KNOCKDOWN, 0)
+ leash_pet.adjustOxyLoss(5)
+ leash_pet.remove_status_effect(/datum/status_effect/leash_pet)
+ leash_pet.remove_movespeed_modifier(MOVESPEED_ID_LEASH)
+ leash_master.remove_status_effect(/datum/status_effect/leash_dom)
+ QDEL_NULL(mobhook_leash_master)
+ QDEL_NULL(mobhook_leash_pet)
+ leash_pet = "null"
+ leash_master = "null"
+ leash_used = 0
+
+/obj/item/leash/proc/on_pet_move()
+ //This should only work if there is a pet and a master.
+ //This is here pretty much just to stop the console from flooding with errors
+ if(leash_master == "null")
+ return
+ if(leash_pet == "null")
+ return
+ //Make sure the pet is still a pet
+ if(!leash_pet.has_status_effect(/datum/status_effect/leash_pet))
+ QDEL_NULL(mobhook_leash_pet) //Probably redundant, but it's nice to be safe
+ return
+
+ //The pet has escaped. There is no DOM. GO PET RUN.
+ if(leash_pet.has_status_effect(/datum/status_effect/leash_freepet))//If the pet is free, break
+ return
+
+ //If the pet gets too far away, they get tugged back
+ sleep(3)//A small sleep so the pet kind of bounces back after they make the step
+ if(leash_master == "null")
+ return
+ if(leash_pet == "null")
+ return
+ //West tug
+ if(leash_pet.x > leash_master.x + 2)
+ step(leash_pet, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
+ //East tug
+ if(leash_pet.x < leash_master.x - 2)
+ step(leash_pet, EAST, 1)
+ //South tug
+ if(leash_pet.y > leash_master.y + 2)
+ step(leash_pet, SOUTH, 1)
+ //North tug
+ if(leash_pet.y < leash_master.y - 2)
+ step(leash_pet, NORTH, 1)
+
+/obj/item/leash/proc/on_freepet_move()
+ . = ..()
+ //Pet is on the run. Let's drag the leash behind them.
+ if(!leash_master == "null") //If there is a master, don't do this
+ return
+ if(leash_pet == "null") //If there is no pet, don't do this
+ return
+ if(leash_pet.is_holding_item_of_type(/obj/item/leash)) //If the pet is holding the leash, don't do this
+ return
+
+ sleep(2)
+ if(leash_pet == "null")
+ return
+ //Double move to catch the leash up to the pet
+ if(src.x > leash_pet.x + 2)
+ . = step(src, WEST, 1)
+ if(src.x < leash_pet.x - 2)
+ . = step(src, EAST, 1)
+ if(src.y > leash_pet.y + 2)
+ . = step(src, SOUTH, 1)
+ if(src.y < leash_pet.y - 2)
+ . = step(src, NORTH, 1)
+ //Primary dragging code
+ if(src.x > leash_pet.x + 1)
+ . = step(src, WEST, 1) //"1" is the speed of movement. We want the tug to be faster than their slow current walk speed.
+ if(src.y > leash_pet.y)//Check the other axis, and tug them into alignment so they are behind the pet
+ . = step(src, SOUTH, 1)
+ if(src.y < leash_pet.y)
+ . = step(src, NORTH, 1)
+ if(src.x < leash_pet.x - 1)
+ . = step(src, EAST, 1)
+ if(src.y > leash_pet.y)
+ . = step(src, SOUTH, 1)
+ if(src.y < leash_pet.y)
+ . = step(src, NORTH, 1)
+ if(src.y > leash_pet.y + 1)
+ . = step(src, SOUTH, 1)
+ if(src.x > leash_pet.x)
+ . = step(src, WEST, 1)
+ if(src.x < leash_pet.x)
+ . = step(src, EAST, 1)
+ if(src.y < leash_pet.y - 1)
+ . = step(src, NORTH, 1)
+ if(src.x > leash_pet.x)
+ . = step(src, WEST, 1)
+ if(src.x < leash_pet.x)
+ . = step(src, EAST, 1)
+
+ sleep(1)
+ //Just to prevent error messages
+ if(leash_pet == "null")
+ return
+ if(src.x > leash_pet.x + 5 || src.x < leash_pet.x - 5 || src.y > leash_pet.y + 5 || src.y < leash_pet.y - 5)
+ var/leash_break_message = "The leash snapped free from [leash_pet]!"
+ for(var/mob/viewing in viewers(leash_pet, null))
+ if(viewing == leash_pet)
+ to_chat(leash_pet, "Your leash has popped from your collar!")
+ else
+ viewing.show_message("[leash_break_message]", 1)
+ leash_pet.apply_effect(20, EFFECT_KNOCKDOWN, 0)
+ leash_pet.adjustOxyLoss(5)
+ leash_pet.remove_status_effect(/datum/status_effect/leash_pet)
+ leash_pet.remove_status_effect(/datum/status_effect/leash_freepet)
+ QDEL_NULL(mobhook_leash_pet)
+ QDEL_NULL(mobhook_leash_freepet)
+ leash_pet = "null"
+ leash_used = 0
+
+/obj/item/leash/dropped() //Drop the leash, and the leash effects stop
+ . = ..()
+ if(leash_pet == "null") //There is no pet. Stop this silliness
+ return
+ if(leash_master == "null")
+ return
+ //Dropping procs any time the leash changes slots. So, we will wait a tick and see if the leash was actually dropped
+ sleep(1)
+ if(leash_master.is_holding_item_of_type(/obj/item/leash) || istype(leash_master.get_item_by_slot(SLOT_BELT), /obj/item/leash))
+ return //Dom still has the leash as it turns out. Cancel the proc.
+ for(var/mob/viewing in viewers(leash_master, null))
+ viewing.show_message("[leash_master] has dropped the leash.", 1)
+ //DOM HAS DROPPED LEASH. PET IS FREE. SCP HAS BREACHED CONTAINMENT.
+ leash_pet.remove_movespeed_modifier(MOVESPEED_ID_LEASH)
+ mobhook_leash_freepet = leash_pet.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_freepet_move)))
+ leash_master.remove_status_effect(/datum/status_effect/leash_dom) //No dom with no leash. We will get a new dom if the leash is picked back up.
+ leash_master = "null"
+ QDEL_NULL(mobhook_leash_master)
+
+/obj/item/leash/equipped(mob/user)
+ . = ..()
+ if(leash_used == 0) //Don't apply statuses with a fresh leash. Keeps things clean on the backend.
+ return
+ sleep(2)
+ if(leash_pet == "null")
+ return
+ leash_master = user
+ if(leash_master.has_status_effect(/datum/status_effect/leash_freepet) || leash_master.has_status_effect(/datum/status_effect/leash_pet)) //Pet picked up their own leash.
+ leash_master = "null"
+ return
+ leash_master.apply_status_effect(/datum/status_effect/leash_dom)
+ mobhook_leash_master = leash_master.AddComponent(/datum/component/redirect, list(COMSIG_MOVABLE_MOVED = CALLBACK(src, .proc/on_master_move)))
+ leash_pet.remove_status_effect(/datum/status_effect/leash_freepet)
+ QDEL_NULL(mobhook_leash_freepet)
+ leash_pet.add_movespeed_modifier(MOVESPEED_ID_LEASH, multiplicative_slowdown = 5)
+
+/datum/crafting_recipe/leash
+ name = "Leash"
+ result = /obj/item/leash
+ time = 40
+ reqs = list(/obj/item/stack/sheet/metal = 1,
+ /obj/item/stack/sheet/cloth = 3)
category = CAT_MISC
\ No newline at end of file
diff --git a/icons/obj/food/burgerbread.dmi b/icons/obj/food/burgerbread.dmi
index 9eafd6c2..6e6d9555 100644
Binary files a/icons/obj/food/burgerbread.dmi and b/icons/obj/food/burgerbread.dmi differ