diff --git a/baystation12.dme b/baystation12.dme
index 97ffa020d64..a780bc568a6 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1021,6 +1021,7 @@
#include "code\WorkInProgress\SkyMarshal\traitoritems.dm"
#include "code\WorkInProgress\Tastyfish\Eliza.dm"
#include "code\WorkInProgress\Tastyfish\Eliza_Data.dm"
+#include "code\WorkInProgress\Tastyfish\livestock.dm"
#include "code\WorkInProgress\Tastyfish\paiLiza.dm"
#include "code\WorkInProgress\Tastyfish\Parser.dm"
#include "code\WorkInProgress\Tastyfish\wallmount_frame.dm"
diff --git a/code/WorkInProgress/Tastyfish/livestock.dm b/code/WorkInProgress/Tastyfish/livestock.dm
new file mode 100644
index 00000000000..dcabe381eca
--- /dev/null
+++ b/code/WorkInProgress/Tastyfish/livestock.dm
@@ -0,0 +1,185 @@
+// Base Class
+/mob/living/simple_animal/livestock
+ desc = "Tasty!"
+ icon = 'livestock.dmi'
+ emote_see = list("shakes its head", "kicks the ground")
+ speak_chance = 1
+ turns_per_move = 15
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat
+ response_help = "pets the"
+ response_disarm = "gently pushes aside the"
+ response_harm = "kicks the"
+ var/max_nutrition = 100 // different animals get hungry faster, basically number of 5-second steps from full to starving (60 == 5 minutes)
+ var/nutrition_step // cycle step in nutrition system
+ var/obj/movement_target // eating-ing target
+
+ New()
+ if(!nutrition)
+ nutrition = max_nutrition * 0.33 // at 1/3 nutrition
+
+ Life()
+ ..()
+
+ if(alive)
+ meat_amount = round(nutrition / 50)
+
+ nutrition_step--
+ if(nutrition_step <= 0)
+ // handle animal digesting
+ if(nutrition > 0)
+ nutrition--
+ else
+ health--
+ nutrition_step = 50 // only tick this every 5 seconds
+
+ // handle animal eating (borrowed from Ian code)
+
+ // not hungry if full
+ if(nutrition >= max_nutrition)
+ return
+
+ if((movement_target) && !(isturf(movement_target.loc) || ishuman(movement_target.loc) ))
+ movement_target = null
+ stop_automated_movement = 0
+ if( !movement_target || !(movement_target.loc in oview(src, 3)) )
+ movement_target = null
+ stop_automated_movement = 0
+ for(var/obj/item/weapon/reagent_containers/food/snacks/S in oview(src,3))
+ if(isturf(S.loc) || ishuman(S.loc))
+ movement_target = S
+ break
+ if(movement_target)
+ stop_automated_movement = 1
+ step_to(src,movement_target,1)
+ sleep(3)
+ step_to(src,movement_target,1)
+ sleep(3)
+ step_to(src,movement_target,1)
+
+ if(movement_target) //Not redundant due to sleeps, Item can be gone in 6 decisecomds
+ if (movement_target.loc.x < src.x)
+ dir = WEST
+ else if (movement_target.loc.x > src.x)
+ dir = EAST
+ else if (movement_target.loc.y < src.y)
+ dir = SOUTH
+ else if (movement_target.loc.y > src.y)
+ dir = NORTH
+ else
+ dir = SOUTH
+
+ if(isturf(movement_target.loc))
+ movement_target.attack_animal(src)
+ if(istype(movement_target, /obj/item/weapon/reagent_containers/food/snacks))
+ var/obj/item/I = movement_target
+ I.attack(src, src, "mouth") // eat it, if it's food
+
+ if(a_intent == "hurt") // to make raging critter harm, then disarm, then stop
+ a_intent = "disarm"
+ else if(a_intent == "disarm")
+ a_intent = "help"
+ movement_target = null
+ turns_per_move = initial(turns_per_move)
+ else if(ishuman(movement_target.loc))
+ if(prob(20))
+ emote("stares at the [movement_target] that [movement_target.loc] has with a longing expression.")
+
+ proc/rage_at(mob/living/M)
+ movement_target = M // pretty simple
+ turns_per_move = 1
+ emote("becomes enraged")
+ a_intent = "hurt"
+
+ attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(nutrition < max_nutrition && istype(O,/obj/item/weapon/reagent_containers/food/snacks))
+ O.attack_animal(src)
+ else
+ ..(O, user)
+
+// Cow
+/mob/living/simple_animal/livestock/cow
+ name = "cow"
+ icon_state = "cow"
+ icon_living = "cow"
+ icon_dead = "cow_d"
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/cow
+ meat_amount = 10
+ max_nutrition = 1000
+ speak = list("Moo.","Moooo!","Snort.")
+ speak_emote = list("moos")
+ emote_hear = list("moos", "snorts")
+
+ attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(istype(O,/obj/item/weapon/reagent_containers/glass))
+ var/datum/reagents/R = O:reagents
+
+ R.add_reagent("milk", 50)
+ nutrition -= 50
+ usr << "\blue You milk the cow."
+ else if(O.force > 0 && O.w_class >= 2)
+ rage_at(user)
+ else
+ ..(O, user)
+
+ attack_hand(var/mob/user as mob)
+ ..()
+ if(user.a_intent == "hurt")
+ rage_at(user)
+
+/obj/item/weapon/reagent_containers/food/snacks/meat/cow
+ name = "Beef"
+ desc = "It's what's for dinner!"
+
+// Chicken
+/mob/living/simple_animal/livestock/chicken
+ name = "chicken"
+ icon_state = "chick"
+ icon_living = "chick"
+ icon_dead = "chick_d"
+ meat_type = /obj/item/weapon/reagent_containers/food/snacks/meat/chicken
+ meat_amount = 3
+ max_nutrition = 200
+ speak = list("Bock bock!","Cl-cluck.","Click.")
+ speak_emote = list("bocks","clucks")
+ emote_hear = list("bocks", "clucks", "squacks")
+
+/mob/living/simple_animal/livestock/chicken/Life()
+ ..()
+
+ // go right before cycle elapses, and if animal isn't starving
+ if(alive && nutrition_step == 1 && nutrition > max_nutrition / 2)
+ // lay an egg with probability of 5% in 5 second time period
+ if(prob(33))
+ new/obj/item/weapon/reagent_containers/food/snacks/egg(src.loc) // lay an egg
+ nutrition -= 5
+
+/obj/item/weapon/reagent_containers/food/snacks/meat/chicken
+ name = "Chicken"
+ desc = "Tasty!"
+
+/obj/structure/closet/critter
+ desc = "A critter crate."
+ name = "Critter Crate"
+ icon = 'storage.dmi'
+ icon_state = "critter"
+ density = 1
+ icon_opened = "critteropen"
+ icon_closed = "critter"
+
+/datum/supply_packs/chicken
+ name = "Chicken crate"
+ contains = list("/mob/living/simple_animal/livestock/chicken",
+ "/obj/item/weapon/reagent_containers/food/snacks/grown/corn")
+ cost = 10
+ containertype = "/obj/structure/closet/critter"
+ containername = "Chicken crate"
+ group = "Hydroponics"
+
+/datum/supply_packs/cow
+ name = "Cow crate"
+ contains = list("/mob/living/simple_animal/livestock/cow",
+ "/obj/item/weapon/reagent_containers/food/snacks/grown/corn")
+ cost = 50
+ containertype = "/obj/structure/closet/critter"
+ containername = "Cow crate"
+ group = "Hydroponics"
diff --git a/code/WorkInProgress/filing.dm b/code/WorkInProgress/filing.dm
index 5bbfdf29ff9..5f6363dadc6 100644
--- a/code/WorkInProgress/filing.dm
+++ b/code/WorkInProgress/filing.dm
@@ -1,4 +1,4 @@
-/obj/filingcabinet
+/obj/structure/filingcabinet
name = "Filing Cabinet"
desc = "A large cabinet with drawers."
icon = 'computer.dmi'
@@ -6,7 +6,7 @@
density = 1
anchored = 1
-/obj/filingcabinet/attackby(obj/item/weapon/paper/P,mob/M)
+/obj/structure/filingcabinet/attackby(obj/item/weapon/paper/P,mob/M)
if(istype(P))
M << "You put the [P] in the [src]."
M.drop_item()
@@ -14,7 +14,7 @@
else
M << "You can't put a [P] in the [src]!"
-/obj/filingcabinet/attack_hand(mob/user)
+/obj/structure/filingcabinet/attack_hand(mob/user)
if(src.contents.len <= 0)
user << "The [src] is empty."
return
diff --git a/code/defines/mob/simple_animal/life.dm b/code/defines/mob/simple_animal/life.dm
index bf045bde534..cc8a746abb6 100644
--- a/code/defines/mob/simple_animal/life.dm
+++ b/code/defines/mob/simple_animal/life.dm
@@ -189,8 +189,11 @@
return "[emote], \"[text]\""
return "says, \"[text]\"";
-/mob/living/simple_animal/emote(var/act)
- if(act)
+/mob/living/simple_animal/emote(var/act,var/m_type=1,var/message = null)
+ if(act == "me")
+ for (var/mob/O in viewers(src, null))
+ O.show_message("[src] [message]")
+ else if(act)
for (var/mob/O in viewers(src, null))
O.show_message("[src] [act].")
diff --git a/code/defines/turf.dm b/code/defines/turf.dm
index 87c7f682868..ea30f6e5368 100644
--- a/code/defines/turf.dm
+++ b/code/defines/turf.dm
@@ -1,253 +1,259 @@
-/turf
- icon = 'floors.dmi'
- var/intact = 1 //for floors, use is_plating(), is_steel_floor() and is_light_floor()
-
- level = 1.0
-
- var
- //Properties for open tiles (/floor)
- oxygen = 0
- carbon_dioxide = 0
- nitrogen = 0
- toxins = 0
-
- //Properties for airtight tiles (/wall)
- thermal_conductivity = 0.05
- heat_capacity = 1
-
- //Properties for both
- temperature = T20C
-
- blocks_air = 0
- icon_old = null
- pathweight = 1
-
- proc/is_plating()
- return 0
- proc/is_asteroid_floor()
- return 0
- proc/is_steel_floor()
- return 0
- proc/is_light_floor()
- return 0
- proc/is_grass_floor()
- return 0
- proc/return_siding_icon_state()
- return 0
-
-/turf/space
- icon = 'space.dmi'
- name = "space"
- icon_state = "placeholder"
-
- temperature = TCMB
- thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
- heat_capacity = 700000
-
-/turf/space/New()
-// icon = 'space.dmi'
- icon_state = "[pick(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25)]"
-
-/turf/simulated
- name = "station"
- var/wet = 0
- var/image/wet_overlay = null
-
- var/thermite = 0
- oxygen = MOLES_O2STANDARD
- nitrogen = MOLES_N2STANDARD
- var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed
- var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to
-
-
-
-/turf/simulated/wall/r_wall
- name = "r wall"
- desc = "A huge chunk of reinforced metal used to seperate rooms."
- icon_state = "r_wall"
- opacity = 1
- density = 1
-
- walltype = "rwall"
-
- var/d_state = 0
-
-/turf/simulated/wall
- name = "wall"
- desc = "A huge chunk of metal used to seperate rooms."
- icon = 'walls.dmi'
- opacity = 1
- density = 1
- blocks_air = 1
-
- thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
- heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m steel wall
-
- var/walltype = "wall"
-
-/turf/simulated/shuttle
- name = "shuttle"
- icon = 'shuttle.dmi'
- thermal_conductivity = 0.05
- heat_capacity = 0
-
-/turf/simulated/shuttle/wall
- name = "wall"
- icon_state = "wall1"
- opacity = 1
- density = 1
- blocks_air = 1
-
-/turf/simulated/shuttle/floor
- name = "floor"
- icon_state = "floor"
-
-/turf/simulated/shuttle/floor4 // Added this floor tile so that I have a seperate turf to check in the shuttle -- Polymorph
- name = "Brig floor" // Also added it into the 2x3 brig area of the shuttle.
- icon_state = "floor4"
-
-/turf/unsimulated
- intact = 1
- name = "command"
- oxygen = MOLES_O2STANDARD
- nitrogen = MOLES_N2STANDARD
-
-/turf/unsimulated/floor
- name = "floor"
- icon = 'floors.dmi'
- icon_state = "Floor3"
-
-/turf/unsimulated/wall
- name = "wall"
- icon = 'walls.dmi'
- icon_state = "riveted"
- opacity = 1
- density = 1
-
-/turf/unsimulated/wall/other
- icon_state = "r_wall"
-
-/turf/proc
- AdjacentTurfs()
- var/L[] = new()
- for(var/turf/simulated/t in oview(src,1))
- if(!t.density)
- if(!LinkBlocked(src, t) && !TurfBlockedNonWindow(t))
- L.Add(t)
- return L
- Distance(turf/t)
- if(get_dist(src,t) == 1)
- var/cost = (src.x - t.x) * (src.x - t.x) + (src.y - t.y) * (src.y - t.y)
- cost *= (pathweight+t.pathweight)/2
- return cost
- else
- return get_dist(src,t)
- AdjacentTurfsSpace()
- var/L[] = new()
- for(var/turf/t in oview(src,1))
- if(!t.density)
- if(!LinkBlocked(src, t) && !TurfBlockedNonWindow(t))
- L.Add(t)
- return L
-
-
-
-/turf/simulated/wall/mineral
- icon = 'mineral_walls.dmi'
- walltype = "iron"
-
- var/oreAmount = 1
- var/hardness = 1
-
- New()
- ..()
- name = "[walltype] wall"
-
- dismantle_wall(devastated = 0)
- if(!devastated)
- var/ore = text2path("/obj/item/weapon/ore/[walltype]")
- for(var/i = 1, i <= oreAmount, i++)
- new ore(src)
- ReplaceWithFloor()
- else
- ReplaceWithSpace()
-
- attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W,/obj/item/weapon/pickaxe))
- var/obj/item/weapon/pickaxe/digTool = W
- user << "You start digging the [name]."
- if(do_after(user,digTool.digspeed*hardness) && src)
- user << "You finished digging."
- dismantle_wall()
- else if(istype(W,/obj/item/weapon)) //not sure, can't not just weapons get passed to this proc?
- hardness -= W.force/100
- user << "You hit the [name] with your [W.name]!"
- CheckHardness()
- else
- attack_hand(user)
- return
-
- proc/CheckHardness()
- if(hardness <= 0)
- dismantle_wall()
-
-/turf/simulated/wall/mineral/iron
- walltype = "iron"
- hardness = 3
-
-/turf/simulated/wall/mineral/silver
- walltype = "silver"
- hardness = 3
-
-/turf/simulated/wall/mineral/uranium
- walltype = "uranium"
- hardness = 3
-
- New()
- ..()
- sd_SetLuminosity(3)
-
-/turf/simulated/wall/mineral/gold
- walltype = "gold"
-
-/turf/simulated/wall/mineral/sand
- walltype = "sand"
- hardness = 0.5
-
-/turf/simulated/wall/mineral/transparent
- opacity = 0
-
-/turf/simulated/wall/mineral/transparent/diamond
- walltype = "diamond"
- hardness = 10
-
-/turf/simulated/wall/mineral/transparent/plasma
- walltype = "plasma"
-
- attackby(obj/item/weapon/W as obj, mob/user as mob)
- if(istype(W,/obj/item/weapon/weldingtool))
- if(W:welding)
- return TemperatureAct(100)
- ..()
-
- temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
- if(exposed_temperature > 300)
- TemperatureAct(exposed_temperature)
-
- proc/TemperatureAct(temperature)
- for(var/turf/simulated/floor/target_tile in range(2,loc))
- if(target_tile.parent && target_tile.parent.group_processing)
- target_tile.parent.suspend_group_processing()
-
- var/datum/gas_mixture/napalm = new
-
- var/toxinsToDeduce = temperature/10
-
- napalm.toxins = toxinsToDeduce
- napalm.temperature = 400+T0C
-
- target_tile.assume_air(napalm)
- spawn (0) target_tile.hotspot_expose(temperature, 400)
-
- hardness -= toxinsToDeduce/100
- CheckHardness()
+/turf
+ icon = 'floors.dmi'
+ var/intact = 1 //for floors, use is_plating(), is_steel_floor() and is_light_floor()
+
+ level = 1.0
+
+ var
+ //Properties for open tiles (/floor)
+ oxygen = 0
+ carbon_dioxide = 0
+ nitrogen = 0
+ toxins = 0
+
+ //Properties for airtight tiles (/wall)
+ thermal_conductivity = 0.05
+ heat_capacity = 1
+
+ //Properties for both
+ temperature = T20C
+
+ blocks_air = 0
+ icon_old = null
+ pathweight = 1
+
+ proc/is_plating()
+ return 0
+ proc/is_asteroid_floor()
+ return 0
+ proc/is_steel_floor()
+ return 0
+ proc/is_light_floor()
+ return 0
+ proc/is_grass_floor()
+ return 0
+ proc/return_siding_icon_state()
+ return 0
+
+/turf/space
+ icon = 'space.dmi'
+ name = "space"
+ icon_state = "placeholder"
+
+ temperature = TCMB
+ thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
+ heat_capacity = 700000
+
+/turf/space/New()
+// icon = 'space.dmi'
+ icon_state = "[pick(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25)]"
+
+/turf/simulated
+ name = "station"
+ var/wet = 0
+ var/image/wet_overlay = null
+
+ var/thermite = 0
+ oxygen = MOLES_O2STANDARD
+ nitrogen = MOLES_N2STANDARD
+ var/to_be_destroyed = 0 //Used for fire, if a melting temperature was reached, it will be destroyed
+ var/max_fire_temperature_sustained = 0 //The max temperature of the fire which it was subjected to
+
+
+
+/turf/simulated/wall/r_wall
+ name = "r wall"
+ desc = "A huge chunk of reinforced metal used to seperate rooms."
+ icon_state = "r_wall"
+ opacity = 1
+ density = 1
+
+ walltype = "rwall"
+
+ var/d_state = 0
+
+/turf/simulated/wall
+ name = "wall"
+ desc = "A huge chunk of metal used to seperate rooms."
+ icon = 'walls.dmi'
+ opacity = 1
+ density = 1
+ blocks_air = 1
+
+ thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
+ heat_capacity = 312500 //a little over 5 cm thick , 312500 for 1 m by 2.5 m by 0.25 m steel wall
+
+ var/walltype = "wall"
+
+/turf/simulated/shuttle
+ name = "shuttle"
+ icon = 'shuttle.dmi'
+ thermal_conductivity = 0.05
+ heat_capacity = 0
+
+/turf/simulated/shuttle/wall
+ name = "wall"
+ icon_state = "wall1"
+ opacity = 1
+ density = 1
+ blocks_air = 1
+
+/turf/simulated/shuttle/floor
+ name = "floor"
+ icon_state = "floor"
+
+/turf/simulated/shuttle/floor4 // Added this floor tile so that I have a seperate turf to check in the shuttle -- Polymorph
+ name = "Brig floor" // Also added it into the 2x3 brig area of the shuttle.
+ icon_state = "floor4"
+
+/turf/unsimulated
+ intact = 1
+ name = "command"
+ oxygen = MOLES_O2STANDARD
+ nitrogen = MOLES_N2STANDARD
+
+/turf/unsimulated/floor
+ name = "floor"
+ icon = 'floors.dmi'
+ icon_state = "Floor3"
+
+/turf/unsimulated/wall
+ name = "wall"
+ icon = 'walls.dmi'
+ icon_state = "riveted"
+ opacity = 1
+ density = 1
+
+/turf/unsimulated/wall/other
+ icon_state = "r_wall"
+
+/turf/proc
+ AdjacentTurfs()
+ var/L[] = new()
+ for(var/turf/simulated/t in oview(src,1))
+ if(!t.density)
+ if(!LinkBlocked(src, t) && !TurfBlockedNonWindow(t))
+ L.Add(t)
+ return L
+
+ Distance(turf/t)
+ if(get_dist(src,t) == 1)
+ var/cost = (src.x - t.x) * (src.x - t.x) + (src.y - t.y) * (src.y - t.y)
+ cost *= (pathweight+t.pathweight)/2
+ return cost
+
+ else
+ return get_dist(src,t)
+
+ Distance_ortho(turf/t)
+ return abs(src.x - t.x) + abs(src.y - t.y)
+
+ AdjacentTurfsSpace()
+ var/L[] = new()
+ for(var/turf/t in oview(src,1))
+ if(!t.density)
+ if(!LinkBlocked(src, t) && !TurfBlockedNonWindow(t))
+ L.Add(t)
+ return L
+
+
+
+/turf/simulated/wall/mineral
+ icon = 'mineral_walls.dmi'
+ walltype = "iron"
+
+ var/oreAmount = 1
+ var/hardness = 1
+
+ New()
+ ..()
+ name = "[walltype] wall"
+
+ dismantle_wall(devastated = 0)
+ if(!devastated)
+ var/ore = text2path("/obj/item/weapon/ore/[walltype]")
+ for(var/i = 1, i <= oreAmount, i++)
+ new ore(src)
+ ReplaceWithFloor()
+ else
+ ReplaceWithSpace()
+
+ attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/weapon/pickaxe))
+ var/obj/item/weapon/pickaxe/digTool = W
+ user << "You start digging the [name]."
+ if(do_after(user,digTool.digspeed*hardness) && src)
+ user << "You finished digging."
+ dismantle_wall()
+ else if(istype(W,/obj/item/weapon)) //not sure, can't not just weapons get passed to this proc?
+ hardness -= W.force/100
+ user << "You hit the [name] with your [W.name]!"
+ CheckHardness()
+ else
+ attack_hand(user)
+ return
+
+ proc/CheckHardness()
+ if(hardness <= 0)
+ dismantle_wall()
+
+/turf/simulated/wall/mineral/iron
+ walltype = "iron"
+ hardness = 3
+
+/turf/simulated/wall/mineral/silver
+ walltype = "silver"
+ hardness = 3
+
+/turf/simulated/wall/mineral/uranium
+ walltype = "uranium"
+ hardness = 3
+
+ New()
+ ..()
+ sd_SetLuminosity(3)
+
+/turf/simulated/wall/mineral/gold
+ walltype = "gold"
+
+/turf/simulated/wall/mineral/sand
+ walltype = "sand"
+ hardness = 0.5
+
+/turf/simulated/wall/mineral/transparent
+ opacity = 0
+
+/turf/simulated/wall/mineral/transparent/diamond
+ walltype = "diamond"
+ hardness = 10
+
+/turf/simulated/wall/mineral/transparent/plasma
+ walltype = "plasma"
+
+ attackby(obj/item/weapon/W as obj, mob/user as mob)
+ if(istype(W,/obj/item/weapon/weldingtool))
+ if(W:welding)
+ return TemperatureAct(100)
+ ..()
+
+ temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
+ if(exposed_temperature > 300)
+ TemperatureAct(exposed_temperature)
+
+ proc/TemperatureAct(temperature)
+ for(var/turf/simulated/floor/target_tile in range(2,loc))
+ if(target_tile.parent && target_tile.parent.group_processing)
+ target_tile.parent.suspend_group_processing()
+
+ var/datum/gas_mixture/napalm = new
+
+ var/toxinsToDeduce = temperature/10
+
+ napalm.toxins = toxinsToDeduce
+ napalm.temperature = 400+T0C
+
+ target_tile.assume_air(napalm)
+ spawn (0) target_tile.hotspot_expose(temperature, 400)
+
+ hardness -= toxinsToDeduce/100
+ CheckHardness()
diff --git a/code/game/machinery/bots/cleanbot.dm b/code/game/machinery/bots/cleanbot.dm
index 78b31ac8b69..1580c00c0aa 100644
--- a/code/game/machinery/bots/cleanbot.dm
+++ b/code/game/machinery/bots/cleanbot.dm
@@ -232,7 +232,7 @@ text("[src.oddbutton ? "Yes" : "No"
if (!next_dest_loc)
next_dest_loc = closest_loc
if (next_dest_loc)
- src.patrol_path = AStar(src.loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=null)
+ src.patrol_path = AStar(src.loc, next_dest_loc, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_ortho, 0, 120, id=botcard, exclude=null)
src.patrol_path = reverselist(src.patrol_path)
else
patrol_move()
diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm
index 4143f4e5de0..e588570cf95 100644
--- a/code/game/machinery/bots/ed209bot.dm
+++ b/code/game/machinery/bots/ed209bot.dm
@@ -563,7 +563,7 @@ Auto Patrol: []"},
// calculates a path to the current destination
// given an optional turf to avoid
/obj/machinery/bot/ed209/proc/calc_path(var/turf/avoid = null)
- src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid)
+ src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_ortho, 0, 120, id=botcard, exclude=avoid)
src.path = reverselist(src.path)
diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm
index 8e4381baf24..8c211975961 100644
--- a/code/game/machinery/bots/medbot.dm
+++ b/code/game/machinery/bots/medbot.dm
@@ -296,7 +296,7 @@
if(src.patient && src.path.len == 0 && (get_dist(src,src.patient) > 1))
spawn(0)
- src.path = AStar(src.loc, get_turf(src.patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 30,id=botcard)
+ src.path = AStar(src.loc, get_turf(src.patient), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_ortho, 0, 30,id=botcard)
src.path = reverselist(src.path)
if(src.path.len == 0)
src.oldpatient = src.patient
diff --git a/code/game/machinery/bots/mulebot.dm b/code/game/machinery/bots/mulebot.dm
index eec60faf6f0..909dcce3ded 100644
--- a/code/game/machinery/bots/mulebot.dm
+++ b/code/game/machinery/bots/mulebot.dm
@@ -694,7 +694,7 @@
// calculates a path to the current destination
// given an optional turf to avoid
/obj/machinery/bot/mulebot/proc/calc_path(var/turf/avoid = null)
- src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 250, id=botcard, exclude=avoid)
+ src.path = AStar(src.loc, src.target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_ortho, 0, 250, id=botcard, exclude=avoid)
src.path = reverselist(src.path)
diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm
index 03208420a67..e926bea08cb 100644
--- a/code/game/machinery/bots/secbot.dm
+++ b/code/game/machinery/bots/secbot.dm
@@ -543,7 +543,7 @@ Auto Patrol: []"},
// calculates a path to the current destination
// given an optional turf to avoid
/obj/machinery/bot/secbot/proc/calc_path(var/turf/avoid = null)
- src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, 120, id=botcard, exclude=avoid)
+ src.path = AStar(src.loc, patrol_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_ortho, 0, 120, id=botcard, exclude=avoid)
src.path = reverselist(src.path)
diff --git a/code/game/machinery/kitchen/gibber.dm b/code/game/machinery/kitchen/gibber.dm
index 7da11995c97..f22e963b133 100644
--- a/code/game/machinery/kitchen/gibber.dm
+++ b/code/game/machinery/kitchen/gibber.dm
@@ -13,7 +13,7 @@
use_power = 1
idle_power_usage = 2
active_power_usage = 500
-
+ var/emagged = 0
/obj/machinery/gibber/New()
..()
@@ -49,20 +49,36 @@
src.startgibbing(user)
/obj/machinery/gibber/attackby(obj/item/weapon/grab/G as obj, mob/user as mob)
- if(src.occupant)
- user << "\red The gibber is full, empty it first!"
- return
- if (!( istype(G, /obj/item/weapon/grab)) || !(istype(G.affecting, /mob/living/carbon/human)))
- user << "\red This item is not suitable for the gibber!"
- return
- if(G.affecting.abiotic(1))
- user << "\red Subject may not have abiotic items on."
+ if(istype(G,/obj/item/weapon/card/emag))
+ user.visible_message( \
+ "\red [user] swipes a strange card through \the [src]'s control panel!", \
+ "\red You swipe a strange card through \the [src]'s control panel!", \
+ "You hear a scratchy sound.")
+ emagged = 1
return
- user.visible_message("\red [user] starts to put [G.affecting] into the gibber!")
+ if(src.occupant)
+ user << "\red \The [src] is full, empty it first!"
+ return
+ if (!istype(G, /obj/item/weapon/grab))
+ user << "\red This item is not suitable for \the [src]!"
+ return
+ if(istype(G.affecting, /mob/living/carbon/human))
+ if(!emagged)
+ user << "\red \The [src] buzzes and spits [G.affecting] back out."
+ return
+ if(G.affecting.abiotic(1))
+ user << "\red Subject may not have abiotic items on."
+ return
+ else if(istype(G.affecting, /mob/living/carbon/monkey) || istype(G.affecting, /mob/living/carbon/alien) || istype(G.affecting, /mob/living/simple_animal))
+ // do nothing special
+ else
+ user << "\red This item is not suitable for \the [src]!"
+
+ user.visible_message("\red [user] starts to put [G.affecting] into \the [src]!")
src.add_fingerprint(user)
if(do_after(user, 30) && G && G.affecting && !occupant)
- user.visible_message("\red [user] stuffs [G.affecting] into the gibber!")
+ user.visible_message("\red [user] stuffs [G.affecting] into \the [src]!")
var/mob/M = G.affecting
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
@@ -109,21 +125,56 @@
M.show_message("\red You hear a loud squelchy grinding sound.", 1)
src.operating = 1
update_icon()
- var/sourcename = src.occupant.real_name
- var/sourcejob = src.occupant.job
- var/sourcenutriment = src.occupant.nutrition / 15
- var/sourcetotalreagents = src.occupant.reagents.total_volume
- var/totalslabs = 3
- var/obj/item/weapon/reagent_containers/food/snacks/meat/human/allmeat[totalslabs]
- for (var/i=1 to totalslabs)
- var/obj/item/weapon/reagent_containers/food/snacks/meat/human/newmeat = new
- newmeat.name = sourcename + newmeat.name
- newmeat.subjectname = sourcename
- newmeat.subjectjob = sourcejob
- newmeat.reagents.add_reagent ("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first
- src.occupant.reagents.trans_to (newmeat, round (sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the
- allmeat[i] = newmeat
+ var/list/obj/item/weapon/reagent_containers/food/snacks/allmeat = new()
+
+ if(istype(occupant,/mob/living/carbon/human))
+ var/sourcename = src.occupant.real_name
+ var/sourcejob = src.occupant.job
+ var/sourcenutriment = src.occupant.nutrition / 15
+ var/sourcetotalreagents = src.occupant.reagents.total_volume
+ var/totalslabs = 8
+
+ for (var/i=1 to totalslabs)
+ var/obj/item/weapon/reagent_containers/food/snacks/meat/human/newmeat = new()
+ newmeat.name = sourcename + newmeat.name
+ newmeat.subjectname = sourcename
+ newmeat.subjectjob = sourcejob
+ newmeat.reagents.add_reagent("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first
+ src.occupant.reagents.trans_to(newmeat, round(sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the
+ allmeat += newmeat
+ else if(istype(occupant,/mob/living/carbon/monkey))
+ var/sourcename = src.occupant.real_name
+ var/sourcenutriment = src.occupant.nutrition / 15
+ var/sourcetotalreagents = src.occupant.reagents.total_volume
+ var/totalslabs = 5
+
+ for (var/i=1 to totalslabs)
+ var/obj/item/weapon/reagent_containers/food/snacks/meat/monkey/newmeat = new()
+ newmeat.name = sourcename + newmeat.name
+ newmeat.reagents.add_reagent("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first
+ src.occupant.reagents.trans_to(newmeat, round(sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the
+ allmeat += newmeat
+ else if(istype(occupant,/mob/living/carbon/alien))
+ var/sourcename = src.occupant.real_name
+ var/sourcenutriment = src.occupant.nutrition / 15
+ var/sourcetotalreagents = src.occupant.reagents.total_volume
+ var/totalslabs = 5
+
+ for (var/i=1 to totalslabs)
+ var/obj/item/weapon/reagent_containers/food/snacks/xenomeat/newmeat = new()
+ newmeat.name = sourcename + newmeat.name
+ newmeat.reagents.add_reagent("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first
+ src.occupant.reagents.trans_to(newmeat, round(sourcetotalreagents / totalslabs, 1)) // Transfer all the reagents from the
+ allmeat += newmeat
+ else if(istype(occupant,/mob/living/simple_animal))
+ var/sourcenutriment = src.occupant.nutrition / 15
+ var/totalslabs = occupant:meat_amount
+
+ for (var/i=1 to totalslabs)
+ var/obj/item/weapon/reagent_containers/food/snacks/newmeat = new occupant:meat_type()
+ newmeat.reagents.add_reagent("nutriment", sourcenutriment / totalslabs) // Thehehe. Fat guys go first
+ allmeat += newmeat
src.occupant.death(1)
src.occupant.ghostize()
@@ -131,7 +182,7 @@
spawn(src.gibtime)
playsound(src.loc, 'splat.ogg', 50, 1)
operating = 0
- for (var/i=1 to totalslabs)
+ for (var/i=1 to allmeat.len)
var/obj/item/meatslab = allmeat[i]
var/turf/Tx = locate(src.x - i, src.y, src.z)
meatslab.loc = src.loc
@@ -140,5 +191,3 @@
new /obj/effect/decal/cleanable/blood/gibs(Tx,i)
src.operating = 0
update_icon()
-
-
diff --git a/code/game/supplyshuttle.dm b/code/game/supplyshuttle.dm
index e6153220bf6..f3fc7c70ff5 100644
--- a/code/game/supplyshuttle.dm
+++ b/code/game/supplyshuttle.dm
@@ -155,7 +155,8 @@ var/list/supply_groups = new()
if((locate(/mob/living) in T)) return 0
if((locate(/obj/item/device/radio/beacon) in T)) return 0
for(var/atom/ATM in T)
- if((locate(/mob/living) in ATM)) return 0
+ if((locate(/mob/living/carbon) in ATM)) return 0 // allow simple_animals to be transported in containers
+ if((locate(/mob/living/silicon) in ATM)) return 0
if((locate(/obj/item/device/radio/beacon) in ATM)) return 0
return 1
@@ -172,6 +173,10 @@ var/list/supply_groups = new()
/obj/item/weapon/paper/manifest
name = "Supply Manifest"
+ New()
+ ..()
+ overlays += "paper_words"
+
/proc/process_supply_order()
var/shuttleat = supply_shuttle_at_station ? SUPPLY_STATION_AREATYPE : SUPPLY_DOCK_AREATYPE
@@ -187,7 +192,7 @@ var/list/supply_groups = new()
var/pickedloc = 0
var/found = 0
for(var/C in markers)
- if (locate(/obj/structure/closet/crate) in get_turf(C)) continue
+ if (locate(/obj/structure/closet) in get_turf(C)) continue
found = 1
pickedloc = get_turf(C)
if (!found) pickedloc = get_turf(pick(markers))
@@ -305,6 +310,7 @@ var/list/supply_groups = new()
var/reason = input(usr,"Reason:","Why do you require this item?","")
reqform.name = "Requisition Form - [P.name]"
+ reqform.overlays += "paper_words"
reqform.info += "[station_name] Supply Requisition Form
"
if (istype(usr:wear_id, /obj/item/weapon/card/id))
diff --git a/code/modules/chemical/Chemistry-Tools.dm b/code/modules/chemical/Chemistry-Tools.dm
index 7526951920a..6363f943988 100644
--- a/code/modules/chemical/Chemistry-Tools.dm
+++ b/code/modules/chemical/Chemistry-Tools.dm
@@ -722,7 +722,8 @@
/obj/machinery/disposal,
/obj/machinery/disease2/incubator,
/obj/machinery/disease2/isolator,
- /obj/machinery/disease2/biodestroyer
+ /obj/machinery/disease2/biodestroyer,
+ /mob/living/simple_animal/livestock/cow
)
examine()
@@ -1339,7 +1340,60 @@
del(src)
playsound(M.loc,'eatfood.ogg', rand(10,50), 1)
return 1
+ else if(istype(M, /mob/living/simple_animal/livestock))
+ if(M == user) //If you're eating it yourself.
+ var/fullness = (M.nutrition + (M.reagents.get_reagent_amount("nutriment") * 25)) / M:max_nutrition
+ if (fullness <= 0.1)
+ M << "\red You hungrily chew out a piece of [src] and gobble it!"
+ if (fullness > 0.1 && fullness <= 0.27)
+ M << "\blue You hungrily begin to eat [src]."
+ if (fullness > 0.27 && fullness <= 0.64)
+ M << "\blue You take a bite of [src]."
+ if (fullness > 0.64 && fullness <= 1)
+ M << "\blue You unwillingly chew a bit of [src]."
+ if (fullness > 1)
+ M << "\red You cannot force any more of [src] to go down your throat."
+ return 0
+ else
+ var/fullness = (M.nutrition + (M.reagents.get_reagent_amount("nutriment") * 25)) / M:max_nutrition
+ if (fullness <= 1)
+ for(var/mob/O in viewers(world.view, user))
+ O.show_message("\red [user] attempts to feed [M] [src].", 1)
+ else
+ for(var/mob/O in viewers(world.view, user))
+ O.show_message("\red [user] cannot force anymore of [src] down [M]'s throat.", 1)
+ return 0
+ if(!do_mob(user, M)) return
+
+ M.attack_log += text("\[[time_stamp()]\] Has been fed [src.name] by [user.name] ([user.ckey]) Reagents: \ref[reagents]")
+ user.attack_log += text("\[[time_stamp()]\] Fed [M.name] by [M.name] ([M.ckey]) Reagents: \ref[reagents]")
+
+ for(var/mob/O in viewers(world.view, user))
+ O.show_message("\red [user] feeds [M] [src].", 1)
+
+ if(reagents) //Handle ingestion of the reagent.
+ if(reagents.total_volume)
+ reagents.reaction(M, INGEST)
+ spawn(5)
+ if(reagents.total_volume > bitesize)
+ /*
+ * I totally cannot understand what this code supposed to do.
+ * Right now every snack consumes in 2 bites, my popcorn does not work right, so I simplify it. -- rastaf0
+ var/temp_bitesize = max(reagents.total_volume /2, bitesize)
+ reagents.trans_to(M, temp_bitesize)
+ */
+ reagents.trans_to(M, bitesize)
+ else
+ reagents.trans_to(M, reagents.total_volume)
+ bitecount++
+ On_Consume()
+ if(!reagents.total_volume)
+ if(M == user) user << "\red You finish eating [src]."
+ else user << "\red [M] finishes eating [src]."
+ del(src)
+ playsound(M.loc,'eatfood.ogg', rand(10,50), 1)
+ return 1
return 0
attackby(obj/item/I as obj, mob/user as mob)
diff --git a/code/modules/food/food.dm b/code/modules/food/food.dm
index bb92d7f53ec..f4c354d07d0 100644
--- a/code/modules/food/food.dm
+++ b/code/modules/food/food.dm
@@ -40,13 +40,6 @@
else
if(bitecount == 0 || prob(50))
M.emote("nibbles away at the [src]")
- bitecount++
- if(bitecount >= 5)
- var/speak_emote = pick(M:speak_emote)
- var/sattisfaction_text = pick("[speak_emote] for more!", "[speak_emote] from enjoyment.", "looks at the area where the [src] was")
- if(sattisfaction_text)
- M.emote("[sattisfaction_text]")
- del(src)
/obj/item/weapon/reagent_containers/food/snacks/candy
name = "candy"
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 24a2083bf8f..65f228af505 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -165,7 +165,10 @@
return
/mob/living/proc/UpdateDamageIcon()
- return
+ return
+
+/mob/living/attack_animal(mob/M)
+ attack_paw(M) // treat it like a normal non-human attack
/mob/living/verb/change_flavor_text()
set name = "Change Flavor Text"
diff --git a/icons/obj/stationobjs.dmi b/icons/obj/stationobjs.dmi
index d244526134d..3653168102e 100644
Binary files a/icons/obj/stationobjs.dmi and b/icons/obj/stationobjs.dmi differ
diff --git a/icons/obj/storage.dmi b/icons/obj/storage.dmi
index c0dd32e8f36..8f25d7e0a0e 100644
Binary files a/icons/obj/storage.dmi and b/icons/obj/storage.dmi differ