diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm
index dd0ed105efd..9fc5bfd10af 100644
--- a/_maps/map_files/Deltastation/DeltaStation2.dmm
+++ b/_maps/map_files/Deltastation/DeltaStation2.dmm
@@ -29135,8 +29135,6 @@
/turf/open/space,
/area/space/nearstation)
"cqu" = (
-/obj/structure/table/wood,
-/obj/item/clothing/mask/cigarette/pipe,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -29147,6 +29145,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/restaurant_portal/restaurant,
/turf/open/floor/iron/dark,
/area/service/bar/atrium)
"cqH" = (
@@ -69065,8 +69064,6 @@
/turf/open/floor/iron,
/area/engineering/main)
"hzj" = (
-/obj/structure/table/wood,
-/obj/item/clothing/head/fedora,
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
@@ -69077,6 +69074,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 8
},
+/obj/machinery/restaurant_portal/bar,
/turf/open/floor/iron/dark,
/area/service/bar/atrium)
"hzE" = (
@@ -73928,6 +73926,7 @@
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
+/obj/item/clothing/head/fedora,
/turf/open/floor/iron,
/area/service/bar/atrium)
"jqu" = (
@@ -88938,6 +88937,7 @@
/obj/item/reagent_containers/glass/bowl,
/obj/effect/turf_decal/bot,
/obj/item/food/dough,
+/obj/item/holosign_creator/robot_seat/restaurant,
/turf/open/floor/iron,
/area/service/kitchen)
"oJI" = (
@@ -103602,6 +103602,7 @@
},
/obj/item/clipboard,
/obj/item/toy/figure/bartender,
+/obj/item/holosign_creator/robot_seat/bar,
/turf/open/floor/iron/dark,
/area/service/bar)
"udl" = (
@@ -113574,6 +113575,7 @@
/obj/effect/turf_decal/tile/yellow{
dir = 8
},
+/obj/item/clothing/mask/cigarette/pipe,
/turf/open/floor/iron,
/area/service/bar/atrium)
"xRL" = (
diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
index ca185029ab0..097455881c4 100644
--- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm
+++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm
@@ -27315,7 +27315,9 @@
/turf/open/floor/iron/white,
/area/medical/virology)
"cXd" = (
-/obj/structure/chair/stool/bar,
+/obj/structure/chair/stool/bar{
+ dir = 4
+ },
/obj/effect/turf_decal/tile/bar,
/obj/effect/turf_decal/tile/bar{
dir = 1
@@ -40570,6 +40572,16 @@
/obj/item/clothing/suit/hooded/wintercoat,
/turf/open/floor/iron,
/area/commons/storage/mining)
+"mCN" = (
+/obj/effect/turf_decal/tile/bar,
+/obj/effect/turf_decal/tile/bar{
+ dir = 1
+ },
+/obj/structure/chair/stool/bar{
+ dir = 4
+ },
+/turf/open/floor/iron,
+/area/service/bar)
"mDf" = (
/obj/effect/mapping_helpers/airlock/cyclelink_helper,
/obj/machinery/door/airlock/engineering{
@@ -42945,6 +42957,12 @@
/obj/machinery/navbeacon/wayfinding,
/turf/open/floor/iron,
/area/commons/dorms)
+"opx" = (
+/obj/machinery/restaurant_portal/restaurant,
+/turf/open/floor/iron/white/corner{
+ dir = 1
+ },
+/area/hallway/primary/starboard)
"opE" = (
/obj/effect/turf_decal/tile/yellow{
dir = 4
@@ -43319,6 +43337,14 @@
},
/turf/closed/wall,
/area/commons/fitness)
+"oHO" = (
+/obj/structure/chair/stool/bar{
+ dir = 1
+ },
+/turf/open/floor/iron/white/corner{
+ dir = 1
+ },
+/area/hallway/primary/starboard)
"oHS" = (
/obj/effect/landmark/event_spawn,
/obj/structure/cable,
@@ -48821,6 +48847,7 @@
/obj/structure/closet/secure_closet/bar{
req_access_txt = "25"
},
+/obj/item/holosign_creator/robot_seat/bar,
/turf/open/floor/wood,
/area/service/bar)
"sCq" = (
@@ -49339,6 +49366,7 @@
/obj/structure/table,
/obj/effect/spawner/lootdrop/donkpockets,
/obj/item/reagent_containers/glass/beaker,
+/obj/item/holosign_creator/robot_seat/restaurant,
/turf/open/floor/iron/cafeteria,
/area/service/kitchen)
"sWw" = (
@@ -56104,6 +56132,14 @@
},
/turf/open/floor/iron,
/area/cargo/miningdock)
+"xzy" = (
+/obj/effect/turf_decal/tile/bar,
+/obj/effect/turf_decal/tile/bar{
+ dir = 1
+ },
+/obj/machinery/restaurant_portal/bar,
+/turf/open/floor/iron,
+/area/service/bar)
"xzA" = (
/obj/structure/table,
/obj/item/folder/white,
@@ -92629,7 +92665,7 @@ oHj
dSU
crr
iHa
-dLp
+xzy
jcA
hYS
jcA
@@ -93402,10 +93438,10 @@ gYp
dEb
jUE
cXd
-cXd
-cXd
-cXd
-cXd
+mCN
+mCN
+mCN
+mCN
dLp
wUq
wXj
@@ -94950,7 +94986,7 @@ nUo
nUo
tIN
mjA
-bbz
+opx
aYV
iKz
aYV
@@ -95464,7 +95500,7 @@ omc
nUo
xiq
xoj
-bbz
+oHO
aYV
iKz
aYV
@@ -95721,7 +95757,7 @@ sWv
nZu
xiq
pIM
-bbz
+oHO
aYV
iKz
aYV
@@ -95978,7 +96014,7 @@ rmK
nUo
myl
pIM
-bbz
+oHO
aYV
iKz
cBm
@@ -96235,7 +96271,7 @@ rmK
nUo
xiq
ewZ
-bbz
+oHO
aYV
iKz
bdc
diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm
index f65ed254639..63822f74d55 100644
--- a/_maps/map_files/KiloStation/KiloStation.dmm
+++ b/_maps/map_files/KiloStation/KiloStation.dmm
@@ -9553,10 +9553,8 @@
/obj/effect/turf_decal/tile/red{
dir = 1
},
-/obj/item/kirbyplants{
- icon_state = "plant-21"
- },
/obj/effect/turf_decal/stripes/corner,
+/obj/effect/spawner/randomcolavend,
/turf/open/floor/iron,
/area/hallway/primary/fore)
"auj" = (
@@ -57258,6 +57256,7 @@
pixel_y = 5
},
/obj/item/reagent_containers/glass/beaker,
+/obj/item/holosign_creator/robot_seat/restaurant,
/turf/open/floor/iron/dark,
/area/service/kitchen)
"eOX" = (
@@ -57348,14 +57347,10 @@
/turf/open/floor/iron/dark,
/area/service/chapel/office)
"eRD" = (
-/obj/structure/table/wood,
/obj/effect/turf_decal/tile/neutral{
dir = 4
},
/obj/effect/turf_decal/tile/neutral,
-/obj/machinery/computer/libraryconsole{
- pixel_y = 5
- },
/obj/effect/decal/cleanable/cobweb,
/obj/structure/extinguisher_cabinet{
pixel_x = -26
@@ -57363,6 +57358,7 @@
/obj/item/radio/intercom{
pixel_y = 22
},
+/obj/machinery/restaurant_portal/bar,
/turf/open/floor/iron/dark,
/area/service/bar)
"eRF" = (
@@ -82925,6 +82921,7 @@
/obj/machinery/light{
dir = 4
},
+/obj/item/holosign_creator/robot_seat/bar,
/turf/open/floor/iron/dark,
/area/service/bar)
"tfm" = (
@@ -87327,7 +87324,6 @@
/area/cargo/miningoffice)
"vyL" = (
/obj/effect/turf_decal/bot,
-/obj/effect/spawner/randomcolavend,
/obj/effect/turf_decal/tile/neutral,
/obj/effect/turf_decal/tile/neutral{
dir = 8
@@ -87335,6 +87331,7 @@
/obj/effect/turf_decal/tile/neutral{
dir = 1
},
+/obj/machinery/restaurant_portal/restaurant,
/turf/open/floor/iron/dark,
/area/service/bar/atrium)
"vyM" = (
diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm
index 4e6817ee34d..d107386632c 100644
--- a/_maps/map_files/MetaStation/MetaStation.dmm
+++ b/_maps/map_files/MetaStation/MetaStation.dmm
@@ -22819,7 +22819,11 @@
/turf/open/floor/iron/dark,
/area/security/office)
"ciV" = (
-/obj/item/kirbyplants/random,
+/obj/structure/disposalpipe/segment{
+ dir = 4
+ },
+/obj/structure/table/wood,
+/obj/effect/spawner/lootdrop/gambling,
/turf/open/floor/wood,
/area/service/bar)
"ciX" = (
@@ -25755,9 +25759,6 @@
/turf/open/floor/plating,
/area/science/mixing)
"cAS" = (
-/obj/structure/chair/stool{
- pixel_y = 8
- },
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer2{
dir = 9
},
@@ -42568,9 +42569,6 @@
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer2{
dir = 1
},
-/obj/structure/chair/stool{
- pixel_y = 8
- },
/turf/open/floor/wood,
/area/service/bar)
"hZZ" = (
@@ -50013,10 +50011,10 @@
/turf/open/floor/iron/white,
/area/medical/medbay/central)
"lgc" = (
-/obj/item/kirbyplants/random,
/obj/effect/turf_decal/siding/wood{
dir = 8
},
+/obj/machinery/restaurant_portal/bar,
/turf/open/floor/wood,
/area/service/bar)
"lgq" = (
@@ -58494,6 +58492,7 @@
/obj/machinery/light{
dir = 1
},
+/obj/machinery/restaurant_portal/restaurant,
/turf/open/floor/wood,
/area/service/bar)
"oFp" = (
@@ -59817,8 +59816,6 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden/layer2,
-/obj/structure/table/wood,
-/obj/effect/spawner/lootdrop/gambling,
/turf/open/floor/wood,
/area/service/bar)
"pds" = (
@@ -60286,6 +60283,7 @@
dir = 1
},
/obj/structure/table/reinforced,
+/obj/item/holosign_creator/robot_seat/bar,
/turf/open/floor/iron,
/area/service/bar)
"pod" = (
@@ -68883,6 +68881,9 @@
/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{
dir = 4
},
+/obj/structure/chair/stool{
+ pixel_y = 8
+ },
/turf/open/floor/wood,
/area/service/bar)
"sGh" = (
@@ -74850,6 +74851,9 @@
dir = 4
},
/obj/machinery/atmospherics/pipe/manifold/scrubbers/hidden/layer2,
+/obj/structure/chair/stool{
+ pixel_y = 8
+ },
/turf/open/floor/wood,
/area/service/bar)
"vih" = (
@@ -75238,6 +75242,7 @@
id = "kitchen_counter";
name = "Kitchen Counter Shutters"
},
+/obj/item/holosign_creator/robot_seat/restaurant,
/turf/open/floor/iron/cafeteria{
dir = 5
},
@@ -117069,7 +117074,7 @@ bhG
bjp
tFU
hkR
-ciV
+otW
otW
pTE
rNI
@@ -117588,7 +117593,7 @@ rXA
rSf
oNP
vic
-imL
+ciV
sFA
mio
vlj
diff --git a/code/__DEFINES/ai.dm b/code/__DEFINES/ai.dm
index a87781a40c0..73d5ed53dd3 100644
--- a/code/__DEFINES/ai.dm
+++ b/code/__DEFINES/ai.dm
@@ -60,3 +60,12 @@
#define BB_VENDING_UNTILT_COOLDOWN "BB_vending_untilt_cooldown"
#define BB_VENDING_BUSY_TILTING "BB_vending_busy_tilting"
#define BB_VENDING_LAST_HIT_SUCCESFUL "BB_vending_last_hit_succesful"
+
+///Robot customer AI controller blackboard keys
+#define BB_CUSTOMER_CURRENT_ORDER "BB_customer_current_order"
+#define BB_CUSTOMER_MY_SEAT "BB_customer_my_seat"
+#define BB_CUSTOMER_PATIENCE "BB_customer_patience"
+#define BB_CUSTOMER_CUSTOMERINFO "BB_customer_customerinfo"
+#define BB_CUSTOMER_EATING "BB_customer_eating"
+#define BB_CUSTOMER_ATTENDING_VENUE "BB_customer_attending_avenue"
+#define BB_CUSTOMER_LEAVING "BB_customer_leaving"
diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index 1e5f6703642..a9c9d34892b 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -909,6 +909,8 @@
///called on an object by its NTNET connection component on a port distruction (port, list/data))
#define COMSIG_COMPONENT_NTNET_PORT_UPDATED "ntnet_port_updated"
+///Restaurant
+#define COMSIG_ITEM_SOLD_TO_CUSTOMER "item_sold_to_customer"
//Nanites
diff --git a/code/__DEFINES/food.dm b/code/__DEFINES/food.dm
index f8694d882f2..b59162b943c 100644
--- a/code/__DEFINES/food.dm
+++ b/code/__DEFINES/food.dm
@@ -57,3 +57,21 @@
#define FOOD_LIKED 1
#define FOOD_DISLIKED 2
#define FOOD_TOXIC 3
+
+///Venue reagent requirement
+#define VENUE_BAR_MINIMUM_REAGENTS 10
+
+
+
+///Food price classes
+#define FOOD_PRICE_TRASH 10 //cheap and quick.
+#define FOOD_PRICE_CHEAP 40 //In line with prices of cheap snacks and foods you find in vending machine, practically disposable.
+#define FOOD_PRICE_NORMAL 100 //Half a crate of profit, selling 4 of these lets you buy a kitchen crate from cargo.
+#define FOOD_PRICE_EXOTIC 300 //Making one of these should be worth the time investment, solid chunk of profit.
+#define FOOD_PRICE_LEGENDARY 1000 //Large windfall for making something from this list.
+
+
+#define DRINK_PRICE_STOCK 20
+#define DRINK_PRICE_EASY 35
+#define DRINK_PRICE_MEDIUM 80
+#define DRINK_PRICE_HIGH 200
diff --git a/code/__DEFINES/footsteps.dm b/code/__DEFINES/footsteps.dm
index 02af15e40d2..1c6d639ebce 100644
--- a/code/__DEFINES/footsteps.dm
+++ b/code/__DEFINES/footsteps.dm
@@ -24,6 +24,7 @@
#define FOOTSTEP_MOB_HUMAN 5 //Warning: Only works on /mob/living/carbon/human
#define FOOTSTEP_MOB_SLIME 6
#define FOOTSTEP_OBJ_MACHINE 7
+#define FOOTSTEP_OBJ_ROBOT 8
/*
diff --git a/code/__DEFINES/subsystems.dm b/code/__DEFINES/subsystems.dm
index 5d945cf5d1c..cb002c68c1b 100644
--- a/code/__DEFINES/subsystems.dm
+++ b/code/__DEFINES/subsystems.dm
@@ -127,6 +127,7 @@
#define INIT_ORDER_NETWORKS 45
#define INIT_ORDER_ECONOMY 40
#define INIT_ORDER_OUTPUTS 35
+#define INIT_ORDER_RESTAURANT 34
#define INIT_ORDER_ATOMS 30
#define INIT_ORDER_LANGUAGE 25
#define INIT_ORDER_MACHINES 20
diff --git a/code/controllers/subsystem/restaurant.dm b/code/controllers/subsystem/restaurant.dm
new file mode 100644
index 00000000000..7917c0fc77e
--- /dev/null
+++ b/code/controllers/subsystem/restaurant.dm
@@ -0,0 +1,24 @@
+/*!
+This subsystem exists to serve as a holder for important info for the restaurant system for chef and bartender.
+*/
+
+SUBSYSTEM_DEF(restaurant)
+ name = "Restaurant"
+ wait = 20 SECONDS //Roll for new guests but don't do it too fast.
+ init_order = INIT_ORDER_RESTAURANT
+ flags = SS_NO_FIRE
+ ///All venues that exist, assoc list of type - reference
+ var/list/all_venues = list()
+ ///All customer data datums that exist, assoc list of type - reference
+ var/list/all_customers = list()
+ ///Seats claimed by robots. They want these. Don't be rude about it to them. assoc list of seat key and robot mob value
+ var/list/claimed_seats = list()
+ ///Caches appearances of food, assoc list where key is the type of food, and value is the appearance. Used so we don't have to keep creating new food. Gets filled whenever a new food that hasn't been ordered gets ordered for the first time.
+ var/list/food_appearance_cache = list()
+
+/datum/controller/subsystem/restaurant/Initialize(timeofday)
+ . = ..()
+ for(var/key in subtypesof(/datum/venue))
+ all_venues[key] = new key()
+ for(var/key in subtypesof(/datum/customer_data))
+ all_customers[key] = new key()
diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm
index abe43e515cd..635df1e8594 100644
--- a/code/datums/ai/_ai_controller.dm
+++ b/code/datums/ai/_ai_controller.dm
@@ -16,8 +16,6 @@ have ways of interacting with a specific atom and control it. They posses a blac
var/ai_status
///Current movement target of the AI, generally set by decision making.
var/atom/current_movement_target
- ///Delay between atom movements, if this is not a multiplication of the delay in
- var/move_delay
///This is a list of variables the AI uses and can be mutated by actions. When an action is performed you pass this list and any relevant keys for the variables it can mutate.
var/list/blackboard = list()
///Tracks recent pathing attempts, if we fail too many in a row we fail our current plans.
@@ -115,7 +113,7 @@ have ways of interacting with a specific atom and control it. They posses a blac
return
else if(ai_movement.moving_controllers[src] != current_movement_target) //We're too far, if we're not already moving start doing it.
- ai_movement.start_moving_towards(src, current_movement_target) //Then start moving
+ ai_movement.start_moving_towards(src, current_movement_target, current_behavior.required_distance) //Then start moving
if(current_behavior.behavior_flags & AI_BEHAVIOR_MOVE_AND_PERFORM) //If we can move and perform then do so.
current_behavior.perform(delta_time, src)
diff --git a/code/datums/ai/generic_actions.dm b/code/datums/ai/generic_actions.dm
index a3af839a568..99b75ae230a 100644
--- a/code/datums/ai/generic_actions.dm
+++ b/code/datums/ai/generic_actions.dm
@@ -14,3 +14,11 @@
var/mob/living/living_pawn = controller.pawn
INVOKE_ASYNC(living_pawn, /mob.proc/emote, pick(screeches))
finish_action(controller, TRUE)
+
+///Moves to target then finishes
+/datum/ai_behavior/move_to_target
+ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT
+
+/datum/ai_behavior/move_to_target/perform(delta_time, datum/ai_controller/controller)
+ . = ..()
+ finish_action(controller, TRUE)
diff --git a/code/datums/ai/movement/_ai_movement.dm b/code/datums/ai/movement/_ai_movement.dm
index 6b0eb02cfb9..495db7ae672 100644
--- a/code/datums/ai/movement/_ai_movement.dm
+++ b/code/datums/ai/movement/_ai_movement.dm
@@ -2,10 +2,12 @@
/datum/ai_movement
///Assoc list ist of controllers that are currently moving as key, and what they are moving to as value
var/list/moving_controllers = list()
+ ///Does this type require processing?
+ var/requires_processing = TRUE
/datum/ai_movement/proc/start_moving_towards(datum/ai_controller/controller, atom/current_movement_target)
controller.pathing_attempts = 0
- if(!moving_controllers.len)
+ if(!moving_controllers.len && requires_processing)
START_PROCESSING(SSai_movement, src)
moving_controllers[controller] = current_movement_target
@@ -13,6 +15,6 @@
controller.pathing_attempts = 0
moving_controllers -= controller
- if(!moving_controllers.len)
+ if(!moving_controllers.len && requires_processing)
STOP_PROCESSING(SSai_movement, src)
diff --git a/code/datums/ai/movement/ai_movement_basic_avoidance.dm b/code/datums/ai/movement/ai_movement_basic_avoidance.dm
new file mode 100644
index 00000000000..25b868d6f44
--- /dev/null
+++ b/code/datums/ai/movement/ai_movement_basic_avoidance.dm
@@ -0,0 +1,12 @@
+///Uses Byond's basic obstacle avoidance mvovement
+/datum/ai_movement/basic_avoidance
+ requires_processing = FALSE
+
+/datum/ai_movement/basic_avoidance/start_moving_towards(datum/ai_controller/controller, atom/current_movement_target, min_distance)
+ . = ..()
+ walk_to(controller.pawn, current_movement_target, min_distance, controller.movement_delay)
+
+
+/datum/ai_movement/basic_avoidance/stop_moving_towards(datum/ai_controller/controller)
+ . = ..()
+ walk_to(controller.pawn, src)
diff --git a/code/datums/ai/robot_customer/robot_customer_behaviors.dm b/code/datums/ai/robot_customer/robot_customer_behaviors.dm
new file mode 100644
index 00000000000..36608ff8101
--- /dev/null
+++ b/code/datums/ai/robot_customer/robot_customer_behaviors.dm
@@ -0,0 +1,111 @@
+/datum/ai_behavior/find_seat
+ action_cooldown = 8 SECONDS
+
+/datum/ai_behavior/find_seat/perform(delta_time, datum/ai_controller/controller)
+ . = ..()
+ var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn
+ var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO]
+
+ var/obj/structure/holosign/robot_seat/found_seat
+
+ for(var/obj/structure/holosign/robot_seat/potential_seat in oview(7, controller.pawn))
+
+ if(potential_seat.linked_venue != controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE]) //Incorrect venue
+ continue
+
+ if(SSrestaurant.claimed_seats[potential_seat]) //Someone called dibs
+ continue
+ var/turf/seat_turf = get_turf(potential_seat)
+
+ if(seat_turf.is_blocked_turf()) //Someone called dibsies
+ continue
+
+ found_seat = potential_seat
+ break
+
+ if(found_seat)
+ customer_pawn.say(pick(customer_data.found_seat_lines))
+ controller.blackboard[BB_CUSTOMER_MY_SEAT] = found_seat
+ SSrestaurant.claimed_seats[found_seat] = customer_pawn
+ finish_action(controller, TRUE)
+ else
+ customer_pawn.say(pick(customer_data.cant_find_seat_lines))
+ finish_action(controller, FALSE)
+
+
+/datum/ai_behavior/order_food
+ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT
+ required_distance = 0
+
+/datum/ai_behavior/order_food/perform(delta_time, datum/ai_controller/controller)
+ . = ..()
+ var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn
+ var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO]
+
+ if(get_turf(controller.blackboard[BB_CUSTOMER_MY_SEAT]) == get_turf(customer_pawn))
+ var/obj/structure/chair/my_seat = locate(/obj/structure/chair) in get_turf(customer_pawn)
+ if(my_seat)
+ controller.pawn.setDir(my_seat.dir) //Sit in your seat
+
+ var/datum/venue/attending_venue = controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE]
+
+ controller.blackboard[BB_CUSTOMER_CURRENT_ORDER] = attending_venue.order_food(customer_pawn, customer_data)
+
+ finish_action(controller, TRUE)
+
+/datum/ai_behavior/wait_for_food
+ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT | AI_BEHAVIOR_MOVE_AND_PERFORM
+ required_distance = 0
+
+/datum/ai_behavior/wait_for_food/perform(delta_time, datum/ai_controller/controller)
+ . = ..()
+ if(controller.blackboard[BB_CUSTOMER_EATING])
+ finish_action(controller, TRUE)
+ return
+
+ controller.blackboard[BB_CUSTOMER_PATIENCE] -= delta_time
+ if(controller.blackboard[BB_CUSTOMER_PATIENCE] < 0 || controller.blackboard[BB_CUSTOMER_LEAVING]) // Check if we're leaving because sometthing mightve forced us to
+ finish_action(controller, FALSE)
+ return
+
+ if(DT_PROB(1, delta_time))
+ var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn
+ var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO]
+ customer_pawn.say(pick(customer_data.wait_for_food_lines))
+
+ if(get_turf(controller.blackboard[BB_CUSTOMER_MY_SEAT]) == get_turf(controller.pawn))
+ var/obj/structure/chair/my_seat = locate(/obj/structure/chair) in get_turf(controller.pawn)
+ if(my_seat)
+ controller.pawn.setDir(my_seat.dir) //Sit in your seat
+
+
+ ///Now check if theres a meal infront of us.
+ var/datum/venue/attending_venue = controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE]
+
+ var/turf/infront_turf = get_step(controller.pawn, controller.pawn.dir)
+ for(var/obj/item/I in infront_turf.contents)
+ if(attending_venue.is_correct_order(I, controller.blackboard[BB_CUSTOMER_CURRENT_ORDER]))
+ var/datum/ai_controller/robot_customer/customer = controller
+ customer.eat_order(I, attending_venue)
+ break
+
+
+/datum/ai_behavior/wait_for_food/finish_action(datum/ai_controller/controller, succeeded)
+ . = ..()
+ var/mob/living/simple_animal/robot_customer/customer_pawn = controller.pawn
+ var/datum/customer_data/customer_data = controller.blackboard[BB_CUSTOMER_CUSTOMERINFO]
+ controller.blackboard[BB_CUSTOMER_LEAVING] = TRUE
+ customer_pawn.update_icon() //They might have a special leaving accesoiry (french flag)
+ if(succeeded)
+ customer_pawn.say(pick(customer_data.leave_happy_lines))
+ else
+ customer_pawn.say(pick(customer_data.leave_mad_lines))
+
+/datum/ai_behavior/leave_venue
+ behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT
+ required_distance = 1
+
+/datum/ai_behavior/leave_venue/perform(delta_time, datum/ai_controller/controller)
+ . = ..()
+ qdel(controller.pawn) //save the world, my final message, goodbye.
+ finish_action(controller, TRUE)
diff --git a/code/datums/ai/robot_customer/robot_customer_controller.dm b/code/datums/ai/robot_customer/robot_customer_controller.dm
new file mode 100644
index 00000000000..7f17974c171
--- /dev/null
+++ b/code/datums/ai/robot_customer/robot_customer_controller.dm
@@ -0,0 +1,60 @@
+/datum/ai_controller/robot_customer
+ ai_movement = /datum/ai_movement/basic_avoidance
+ movement_delay = 1 SECONDS
+ blackboard = list(BB_CUSTOMER_CURRENT_ORDER = null,
+ BB_CUSTOMER_MY_SEAT = null,
+ BB_CUSTOMER_PATIENCE = 999,
+ BB_CUSTOMER_CUSTOMERINFO = null,
+ BB_CUSTOMER_EATING = FALSE,
+ BB_CUSTOMER_LEAVING = FALSE,
+ BB_CUSTOMER_ATTENDING_VENUE = null)
+
+
+/datum/ai_controller/robot_customer/TryPossessPawn(atom/new_pawn)
+ if(!istype(new_pawn, /mob/living/simple_animal/robot_customer))
+ return AI_CONTROLLER_INCOMPATIBLE
+ RegisterSignal(new_pawn, COMSIG_PARENT_ATTACKBY, .proc/on_attackby)
+ return ..() //Run parent at end
+
+/datum/ai_controller/robot_customer/UnpossessPawn(destroy)
+ UnregisterSignal(pawn, list(COMSIG_PARENT_ATTACKBY))
+ return ..() //Run parent at end
+
+/datum/ai_controller/robot_customer/SelectBehaviors(delta_time)
+ current_behaviors = list()
+ if(blackboard[BB_CUSTOMER_LEAVING])
+ var/datum/venue/attending_venue = blackboard[BB_CUSTOMER_ATTENDING_VENUE]
+ current_movement_target = attending_venue.restaurant_portal
+ current_behaviors += GET_AI_BEHAVIOR(/datum/ai_behavior/leave_venue)
+ return
+
+ var/obj/my_seat = blackboard[BB_CUSTOMER_MY_SEAT]
+
+ if(!my_seat) //We havn't got a seat yet! find one!
+ current_behaviors += GET_AI_BEHAVIOR(/datum/ai_behavior/find_seat)
+ return
+
+ current_movement_target = my_seat
+
+ if(!blackboard[BB_CUSTOMER_CURRENT_ORDER]) //We havn't ordered yet even ordered yet. go on! go over there and go do it!
+ current_behaviors += GET_AI_BEHAVIOR(/datum/ai_behavior/order_food)
+ return
+ else
+ current_behaviors += GET_AI_BEHAVIOR(/datum/ai_behavior/wait_for_food)
+
+
+/datum/ai_controller/robot_customer/proc/on_attackby(datum/source, obj/item/I, mob/user)
+ SIGNAL_HANDLER
+ var/datum/venue/attending_venue = blackboard[BB_CUSTOMER_ATTENDING_VENUE]
+ if(attending_venue.is_correct_order(I, blackboard[BB_CUSTOMER_CURRENT_ORDER]))
+ to_chat(user, "You hand [I] to [pawn]")
+ eat_order(I, attending_venue)
+ return COMPONENT_NO_AFTERATTACK
+
+
+/datum/ai_controller/robot_customer/proc/eat_order(obj/item/order_item, datum/venue/attending_venue)
+ if(!blackboard[BB_CUSTOMER_EATING])
+ blackboard[BB_CUSTOMER_EATING] = TRUE
+ attending_venue.on_get_order(pawn, order_item)
+
+
diff --git a/code/datums/components/footstep.dm b/code/datums/components/footstep.dm
index 4f51e30e173..ff9a56a5e6a 100644
--- a/code/datums/components/footstep.dm
+++ b/code/datums/components/footstep.dm
@@ -40,6 +40,10 @@
footstep_sounds = 'sound/effects/bang.ogg'
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_simplestep_machine) //Note that this doesn't get called for humans.
return
+ if(FOOTSTEP_OBJ_ROBOT)
+ footstep_sounds = 'sound/effects/tank_treads.ogg'
+ RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_simplestep_machine) //Note that this doesn't get called for humans.
+ return
RegisterSignal(parent, list(COMSIG_MOVABLE_MOVED), .proc/play_simplestep) //Note that this doesn't get called for humans.
///Prepares a footstep. Determines if it should get played. Returns the turf it should get played on. Note that it is always a /turf/open
diff --git a/code/datums/elements/food/food_trash.dm b/code/datums/elements/food/food_trash.dm
index dccda8caaf1..1cfd5b22de4 100644
--- a/code/datums/elements/food/food_trash.dm
+++ b/code/datums/elements/food/food_trash.dm
@@ -25,6 +25,7 @@
RegisterSignal(target, COMSIG_ITEM_ON_GRIND, .proc/generate_trash)
RegisterSignal(target, COMSIG_ITEM_ON_JUICE, .proc/generate_trash)
RegisterSignal(target, COMSIG_ITEM_ON_COMPOSTED, .proc/generate_trash)
+ RegisterSignal(target, COMSIG_ITEM_SOLD_TO_CUSTOMER, .proc/generate_trash)
/datum/element/food_trash/Detach(datum/target)
. = ..()
diff --git a/code/datums/elements/food/venue_price.dm b/code/datums/elements/food/venue_price.dm
new file mode 100644
index 00000000000..76016deaf3b
--- /dev/null
+++ b/code/datums/elements/food/venue_price.dm
@@ -0,0 +1,23 @@
+///This component can be used to give something value for venues
+/datum/element/venue_price
+ element_flags = ELEMENT_BESPOKE
+ id_arg_index = 2
+ var/venue_price
+
+/datum/element/venue_price/Attach(datum/target, venue_price)
+ . = ..()
+ if(!venue_price)
+ stack_trace("A venue_price element was attached to something without specifying an actual price.")
+ return ELEMENT_INCOMPATIBLE
+ src.venue_price = venue_price
+ RegisterSignal(target, COMSIG_ITEM_SOLD_TO_CUSTOMER, .proc/item_sold)
+
+/datum/element/venue_price/Detach(datum/target)
+ . = ..()
+ UnregisterSignal(target, COMSIG_ITEM_SOLD_TO_CUSTOMER)
+
+/datum/element/venue_price/proc/item_sold(datum/source, obj/item/container)
+ SIGNAL_HANDLER
+
+ new /obj/item/holochip(get_turf(container), venue_price)
+ playsound(get_turf(container), 'sound/effects/cashregister.ogg', 60, TRUE)
diff --git a/code/game/alternate_appearance.dm b/code/game/alternate_appearance.dm
index 5ee152fed7c..48dffe0746c 100644
--- a/code/game/alternate_appearance.dm
+++ b/code/game/alternate_appearance.dm
@@ -186,3 +186,6 @@ GLOBAL_LIST_EMPTY(active_alternate_appearances)
..(key, I, FALSE)
seer = M
add_hud_to(seer)
+
+
+/datum/atom_hud/alternate_appearance/basic/food_demands
diff --git a/code/game/objects/items/circuitboards/machine_circuitboards.dm b/code/game/objects/items/circuitboards/machine_circuitboards.dm
index c2b356f8866..37b38b302f5 100644
--- a/code/game/objects/items/circuitboards/machine_circuitboards.dm
+++ b/code/game/objects/items/circuitboards/machine_circuitboards.dm
@@ -1192,6 +1192,12 @@
/obj/item/stock_parts/matter_bin = 2)
needs_anchored = FALSE
+/obj/item/circuitboard/machine/restaurant_portal
+ name = "Restaurant Portal"
+ icon_state = "service"
+ build_path = /obj/machinery/restaurant_portal
+ needs_anchored = TRUE
+
/obj/item/circuitboard/machine/abductor
name = "alien board (Report This)"
icon_state = "abductor_mod"
diff --git a/code/game/objects/items/food/_food.dm b/code/game/objects/items/food/_food.dm
index 77e0fe141a6..5c21b664d10 100644
--- a/code/game/objects/items/food/_food.dm
+++ b/code/game/objects/items/food/_food.dm
@@ -34,6 +34,8 @@
var/junkiness
///Will this food turn into badrecipe on a grill? Don't use this for everything; preferably mostly for food that is made on a grill to begin with so it burns after some time
var/burns_on_grill = FALSE
+ ///Price of this food if sold in a venue
+ var/venue_value
/obj/item/food/Initialize()
. = ..()
@@ -43,6 +45,8 @@
tastes = string_assoc_list(tastes)
if(eatverbs)
eatverbs = string_list(eatverbs)
+ if(venue_value)
+ AddElement(/datum/element/venue_price, venue_value)
MakeEdible()
MakeProcessable()
MakeLeaveTrash()
diff --git a/code/game/objects/items/food/bread.dm b/code/game/objects/items/food/bread.dm
index afc122f6a61..41510dba45f 100644
--- a/code/game/objects/items/food/bread.dm
+++ b/code/game/objects/items/food/bread.dm
@@ -30,6 +30,7 @@
tastes = list("bread" = 10)
foodtypes = GRAIN
w_class = WEIGHT_CLASS_SMALL
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/bread/plain/Initialize()
. = ..()
@@ -69,6 +70,8 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/vitamin = 10, /datum/reagent/consumable/nutriment/protein = 12)
tastes = list("bread" = 10, "meat" = 10)
foodtypes = GRAIN | MEAT
+ venue_value = FOOD_PRICE_CHEAP
+
/obj/item/food/bread/meat/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/breadslice/meat, 5, 30)
@@ -141,6 +144,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/vitamin = 10, /datum/reagent/consumable/nutriment/protein = 10)
tastes = list("bread" = 10, "tofu" = 10)
foodtypes = GRAIN | VEGETABLES
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/bread/tofu/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/breadslice/tofu, 5, 30)
@@ -221,6 +225,7 @@
attack_verb_simple = list("touche")
tastes = list("bread" = 1)
foodtypes = GRAIN
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/garlicbread
name = "garlic bread"
@@ -232,6 +237,7 @@
bite_consumption = 3
tastes = list("bread" = 1, "garlic" = 1, "butter" = 1)
foodtypes = GRAIN
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/deepfryholder
name = "Deep Fried Foods Holder Obj"
@@ -317,6 +323,7 @@
tastes = list("butter" = 1, "biscuit" = 1)
foodtypes = GRAIN | BREAKFAST
w_class = WEIGHT_CLASS_SMALL
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/butterdog
name = "butterdog"
diff --git a/code/game/objects/items/food/burgers.dm b/code/game/objects/items/food/burgers.dm
index 65e96a1a904..2e58e14a080 100644
--- a/code/game/objects/items/food/burgers.dm
+++ b/code/game/objects/items/food/burgers.dm
@@ -9,11 +9,12 @@
w_class = WEIGHT_CLASS_SMALL
/obj/item/food/burger/plain
- name = "burger"
+ name = "plain burger"
desc = "The cornerstone of every nutritious breakfast."
food_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/nutriment/vitamin = 1)
foodtypes = GRAIN | MEAT
custom_price = PAYCHECK_ASSISTANT * 0.8
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/burger/plain/Initialize()
. = ..()
@@ -35,6 +36,7 @@
foodtypes = MEAT | GRAIN | GROSS
var/subjectname = ""
var/subjectjob = null
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/burger/human/CheckParts(list/parts_list)
..()
@@ -54,6 +56,8 @@
desc = "You monster."
food_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/nutriment/vitamin = 6)
foodtypes = GRAIN | MEAT | GROSS
+ venue_value = FOOD_PRICE_EXOTIC
+
/obj/item/food/burger/appendix
name = "appendix burger"
@@ -62,6 +66,7 @@
icon_state = "appendixburger"
tastes = list("bun" = 4, "grass" = 2)
foodtypes = GRAIN | MEAT | GROSS
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/fish
name = "fillet -o- carp sandwich"
@@ -70,6 +75,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/nutriment/vitamin = 4)
tastes = list("bun" = 4, "fish" = 4)
foodtypes = GRAIN | MEAT
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/burger/tofu
name = "tofu burger"
@@ -78,6 +84,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/nutriment/vitamin = 3)
tastes = list("bun" = 4, "tofu" = 4)
foodtypes = GRAIN | VEGETABLES
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/burger/roburger
name = "roburger"
@@ -86,6 +93,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 8, /datum/reagent/nanomachines = 6, /datum/reagent/consumable/nutriment/vitamin = 6)
tastes = list("bun" = 4, "lettuce" = 2, "sludge" = 1)
foodtypes = GRAIN | TOXIC
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/burger/roburgerbig
name = "roburger"
@@ -103,6 +111,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/nutriment/vitamin = 5)
tastes = list("bun" = 4, "acid" = 4)
foodtypes = GRAIN | MEAT
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/burger/bearger
name = "bearger"
@@ -110,6 +119,7 @@
icon_state = "bearger"
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/nutriment/vitamin = 5)
foodtypes = GRAIN | MEAT
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/burger/clown
name = "clown burger"
@@ -117,6 +127,7 @@
icon_state = "clownburger"
food_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/medicine/mannitol = 6, /datum/reagent/consumable/nutriment/vitamin = 6)
foodtypes = GRAIN | FRUIT
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/mime
name = "mime burger"
@@ -124,6 +135,7 @@
icon_state = "mimeburger"
food_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/protein = 9, /datum/reagent/consumable/nutriment/vitamin = 4, /datum/reagent/consumable/nothing = 6)
foodtypes = GRAIN
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/brain
name = "brainburger"
@@ -132,6 +144,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/medicine/mannitol = 6, /datum/reagent/consumable/nutriment/vitamin = 5, /datum/reagent/consumable/nutriment/protein = 6)
tastes = list("bun" = 4, "brains" = 2)
foodtypes = GRAIN | MEAT | GROSS
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/burger/ghost
name = "ghost burger"
@@ -143,6 +156,7 @@
alpha = 170
verb_say = "moans"
verb_yell = "wails"
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/burger/ghost/Initialize()
. = ..()
@@ -251,6 +265,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/protein = 5, /datum/reagent/consumable/nutriment/vitamin = 10)
tastes = list("bun" = 4, "magic" = 2)
foodtypes = GRAIN | MEAT
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/bigbite
name = "big bite burger"
@@ -259,6 +274,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/protein = 10, /datum/reagent/consumable/nutriment/vitamin = 5)
w_class = WEIGHT_CLASS_NORMAL
foodtypes = GRAIN | MEAT | DAIRY
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/jelly
name = "jelly burger"
@@ -266,6 +282,7 @@
icon_state = "jellyburger"
tastes = list("bun" = 4, "jelly" = 2)
foodtypes = GRAIN | MEAT
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/burger/jelly/slime
food_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/toxin/slimejelly = 6, /datum/reagent/consumable/nutriment/vitamin = 6)
@@ -285,6 +302,7 @@
max_volume = 100
tastes = list("bun" = 4, "type two diabetes" = 10)
foodtypes = GRAIN | MEAT | DAIRY
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/burger/fivealarm
name = "five alarm burger"
@@ -292,6 +310,7 @@
icon_state = "fivealarmburger"
food_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/capsaicin = 5, /datum/reagent/consumable/condensedcapsaicin = 5, /datum/reagent/consumable/nutriment/vitamin = 6)
foodtypes = GRAIN | MEAT
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/rat
name = "rat burger"
@@ -299,6 +318,7 @@
icon_state = "ratburger"
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/nutriment/vitamin = 2)
foodtypes = GRAIN | MEAT | GROSS
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/burger/baseball
name = "home run baseball burger"
@@ -307,6 +327,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/protein = 5, /datum/reagent/consumable/nutriment/vitamin = 2)
foodtypes = GRAIN | GROSS
custom_price = PAYCHECK_ASSISTANT * 0.8
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/baconburger
name = "bacon burger"
@@ -316,6 +337,7 @@
tastes = list("bacon" = 4, "bun" = 2)
foodtypes = GRAIN | MEAT
custom_premium_price = PAYCHECK_ASSISTANT * 1.6
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/empoweredburger
name = "empowered burger"
@@ -324,6 +346,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/protein = 5, /datum/reagent/consumable/nutriment/vitamin = 1, /datum/reagent/consumable/liquidelectricity = 5)
tastes = list("bun" = 2, "pure electricity" = 4)
foodtypes = GRAIN | TOXIC
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/burger/crab
name = "crab burger"
@@ -332,6 +355,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/protein = 5, /datum/reagent/consumable/nutriment/vitamin = 4)
tastes = list("bun" = 2, "crab meat" = 4)
foodtypes = GRAIN | MEAT
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/soylent
name = "soylent burger"
@@ -340,6 +364,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/nutriment/vitamin = 4)
tastes = list("bun" = 2, "assistant" = 4)
foodtypes = GRAIN | MEAT | DAIRY
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/burger/rib
name = "mcrib"
@@ -348,6 +373,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/nutriment/protein = 7, /datum/reagent/consumable/nutriment/vitamin = 4, /datum/reagent/consumable/bbqsauce = 1)
tastes = list("bun" = 2, "pork patty" = 4)
foodtypes = GRAIN | MEAT
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/mcguffin
name = "mcguffin"
@@ -356,6 +382,7 @@
tastes = list("muffin" = 2, "bacon" = 3)
food_reagents = list(/datum/reagent/consumable/nutriment = 2, /datum/reagent/consumable/eggyolk = 3, /datum/reagent/consumable/nutriment/protein = 7, /datum/reagent/consumable/nutriment/vitamin = 1)
foodtypes = GRAIN | MEAT | BREAKFAST
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/chicken
name = "chicken sandwich" //Apparently the proud people of Americlapstan object to this thing being called a burger. Apparently McDonald's just calls it a burger in Europe as to not scare and confuse us.
@@ -364,6 +391,7 @@
tastes = list("bun" = 2, "chicken" = 4, "God's covenant" = 1)
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/mayonnaise = 3, /datum/reagent/consumable/nutriment/protein = 7, /datum/reagent/consumable/nutriment/vitamin = 1, /datum/reagent/consumable/cooking_oil = 2)
foodtypes = GRAIN | MEAT | FRIED
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/burger/cheese
name = "cheese burger"
@@ -372,6 +400,7 @@
tastes = list("bun" = 2, "beef patty" = 4, "cheese" = 3)
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/protein = 7, /datum/reagent/consumable/nutriment/vitamin = 2)
foodtypes = GRAIN | MEAT | DAIRY
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/burger/cheese/Initialize()
. = ..()
diff --git a/code/game/objects/items/food/cake.dm b/code/game/objects/items/food/cake.dm
index fffd8713c0d..a1b9a3225eb 100644
--- a/code/game/objects/items/food/cake.dm
+++ b/code/game/objects/items/food/cake.dm
@@ -43,6 +43,8 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/medicine/oculine = 10, /datum/reagent/consumable/nutriment/vitamin = 5)
tastes = list("cake" = 5, "sweetness" = 2, "carrot" = 1)
foodtypes = GRAIN | DAIRY | VEGETABLES | SUGAR
+ venue_value = FOOD_PRICE_CHEAP
+
/obj/item/food/cake/carrot/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/cakeslice/carrot, 5, 30)
@@ -81,6 +83,8 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/vitamin = 8, /datum/reagent/consumable/nutriment/protein = 5)
tastes = list("cake" = 4, "cream cheese" = 3)
foodtypes = GRAIN | DAIRY
+ venue_value = FOOD_PRICE_CHEAP
+
/obj/item/food/cake/cheese/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/cakeslice/cheese, 5, 30)
@@ -100,6 +104,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/vitamin = 10)
tastes = list("cake" = 5, "sweetness" = 2, "oranges" = 2)
foodtypes = GRAIN | DAIRY | FRUIT | SUGAR
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/cake/orange/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/cakeslice/orange, 5, 30)
@@ -118,6 +123,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/vitamin = 10)
tastes = list("cake" = 5, "sweetness" = 2, "unbearable sourness" = 2)
foodtypes = GRAIN | DAIRY | FRUIT | SUGAR
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/cake/lime/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/cakeslice/lime, 5, 30)
@@ -136,6 +142,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/vitamin = 10)
tastes = list("cake" = 5, "sweetness" = 2, "sourness" = 2)
foodtypes = GRAIN | DAIRY | FRUIT | SUGAR
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/cake/lemon/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/cakeslice/lemon, 5, 30)
@@ -154,6 +161,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/vitamin = 10)
tastes = list("cake" = 5, "sweetness" = 1, "chocolate" = 4)
foodtypes = GRAIN | DAIRY | JUNKFOOD | SUGAR
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/cake/chocolate/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/cakeslice/chocolate, 5, 30)
@@ -243,6 +251,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/vitamin = 10)
tastes = list("cake" = 5, "sweetness" = 1, "apple" = 1)
foodtypes = GRAIN | DAIRY | FRUIT | SUGAR
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/cake/apple/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/cakeslice/apple, 5, 30)
@@ -279,6 +288,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 20, /datum/reagent/consumable/nutriment/vitamin = 5)
tastes = list("cake" = 5, "sweetness" = 1, "pumpkin" = 1)
foodtypes = GRAIN | DAIRY | VEGETABLES | SUGAR
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/cake/pumpkinspice/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/cakeslice/pumpkinspice, 5, 30)
@@ -351,6 +361,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 60, /datum/reagent/consumable/nutriment/vitamin = 5)
tastes = list("cake" = 5, "sweetness" = 1, "batter" = 1)
foodtypes = GRAIN | DAIRY | SUGAR | JUNKFOOD
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/cake/pound_cake/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/cakeslice/pound_cake_slice, 7, 30)
diff --git a/code/game/objects/items/food/egg.dm b/code/game/objects/items/food/egg.dm
index f3534674ca5..a48a584cf83 100644
--- a/code/game/objects/items/food/egg.dm
+++ b/code/game/objects/items/food/egg.dm
@@ -113,6 +113,7 @@
w_class = WEIGHT_CLASS_SMALL
tastes = list("egg" = 1, "cheese" = 1)
foodtypes = MEAT | BREAKFAST | DAIRY
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/omelette/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/kitchen/fork))
diff --git a/code/game/objects/items/food/meat.dm b/code/game/objects/items/food/meat.dm
index 2bce1d3d662..65cea9a6e97 100644
--- a/code/game/objects/items/food/meat.dm
+++ b/code/game/objects/items/food/meat.dm
@@ -52,6 +52,7 @@
tastes = list("fish" = 1, "breadcrumbs" = 1)
foodtypes = MEAT
w_class = WEIGHT_CLASS_SMALL
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/fishandchips
name = "fish and chips"
@@ -60,6 +61,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/protein = 5, /datum/reagent/consumable/nutriment/vitamin = 2)
tastes = list("fish" = 1, "chips" = 1)
foodtypes = MEAT | VEGETABLES | FRIED
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/fishfry
name = "fish fry"
@@ -118,6 +120,7 @@
tastes = list("meat" = 1, "salmon" = 1)
foodtypes = MEAT | ALCOHOL
w_class = WEIGHT_CLASS_SMALL
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/raw_meatball
name = "raw meatball"
@@ -169,6 +172,7 @@
foodtypes = MEAT
w_class = WEIGHT_CLASS_SMALL
burns_on_grill = TRUE
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/meatball/human
name = "strange meatball"
@@ -281,6 +285,7 @@
var/roasted = FALSE
w_class = WEIGHT_CLASS_SMALL
burns_on_grill = TRUE
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/sausage/MakeProcessable()
AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/salami, 6, 30)
@@ -450,6 +455,7 @@
tastes = list("\"chicken\"" = 1)
foodtypes = MEAT
w_class = WEIGHT_CLASS_TINY
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/nugget/Initialize()
. = ..()
@@ -511,6 +517,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment/protein = 16, /datum/reagent/consumable/nutriment/vitamin = 6)
tastes = list("tender meat" = 3, "metal" = 1)
foodtypes = MEAT | GROSS
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/kebab/monkey
name = "meat-kebab"
@@ -518,6 +525,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment/protein = 16, /datum/reagent/consumable/nutriment/vitamin = 2)
tastes = list("meat" = 3, "metal" = 1)
foodtypes = MEAT
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/kebab/tofu
name = "tofu-kebab"
@@ -525,6 +533,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment/protein = 15)
tastes = list("tofu" = 3, "metal" = 1)
foodtypes = VEGETABLES
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/kebab/tail
name = "lizard-tail kebab"
@@ -541,6 +550,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment/protein = 10, /datum/reagent/consumable/nutriment/vitamin = 2)
tastes = list("rat meat" = 1, "metal" = 1)
foodtypes = MEAT | GROSS
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/kebab/rat/double
name = "double rat-kebab"
diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm
index 5ebd68d9d84..d86d56f9cc6 100644
--- a/code/game/objects/items/food/misc.dm
+++ b/code/game/objects/items/food/misc.dm
@@ -23,7 +23,7 @@
icon_state = "royalcheese"
food_reagents = list(/datum/reagent/consumable/nutriment = 15, /datum/reagent/consumable/nutriment/vitamin = 5, /datum/reagent/gold = 20, /datum/reagent/toxin/mutagen = 5)
w_class = WEIGHT_CLASS_BULKY
- tastes = list("cheese" = 4, "royalty" = 1)
+ tastes = list("cheese" = 4, "royalty" = 1)
rat_heal = 70
/obj/item/food/cheese
@@ -120,6 +120,7 @@
tastes = list("fries" = 3, "salt" = 1)
foodtypes = VEGETABLES | GRAIN | FRIED
w_class = WEIGHT_CLASS_SMALL
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/fries/Initialize()
. = ..()
@@ -157,6 +158,7 @@
tastes = list("fries" = 3, "cheese" = 1)
foodtypes = VEGETABLES | GRAIN | DAIRY
w_class = WEIGHT_CLASS_SMALL
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/cheesyfries/Initialize()
. = ..()
@@ -762,6 +764,7 @@
w_class = WEIGHT_CLASS_SMALL
tastes = list("cream cheese" = 4, "crab" = 3, "crispiness" = 2)
foodtypes = MEAT | DAIRY | GRAIN
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/cornchips
name = "boritos corn chips"
diff --git a/code/game/objects/items/food/pastries.dm b/code/game/objects/items/food/pastries.dm
index 81a4a21ece1..09f1cc1ba16 100644
--- a/code/game/objects/items/food/pastries.dm
+++ b/code/game/objects/items/food/pastries.dm
@@ -612,6 +612,7 @@
tastes = list("bun" = 3, "meat" = 2)
foodtypes = GRAIN | MEAT | VEGETABLES
w_class = WEIGHT_CLASS_SMALL
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/hotdog/debug
eat_time = 0
@@ -711,6 +712,7 @@
foodtypes = GRAIN | SUGAR | BREAKFAST
w_class = WEIGHT_CLASS_SMALL
burns_on_grill = TRUE
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/pancakes/raw
name = "goopy pancake"
diff --git a/code/game/objects/items/food/pie.dm b/code/game/objects/items/food/pie.dm
index 2b4fbe51b54..1636921a233 100644
--- a/code/game/objects/items/food/pie.dm
+++ b/code/game/objects/items/food/pie.dm
@@ -7,6 +7,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 10, /datum/reagent/consumable/nutriment/vitamin = 2)
tastes = list("pie" = 1)
foodtypes = GRAIN
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/pieslice
name = "pie slice"
@@ -68,6 +69,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 11, /datum/reagent/consumable/berryjuice = 5, /datum/reagent/consumable/nutriment/vitamin = 4)
tastes = list("pie" = 1, "blackberries" = 1)
foodtypes = GRAIN | FRUIT | SUGAR
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/pie/bearypie
name = "beary pie"
diff --git a/code/game/objects/items/food/pizza.dm b/code/game/objects/items/food/pizza.dm
index 6072923b769..c5487432916 100644
--- a/code/game/objects/items/food/pizza.dm
+++ b/code/game/objects/items/food/pizza.dm
@@ -6,6 +6,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 28, /datum/reagent/consumable/nutriment/protein = 3, /datum/reagent/consumable/tomatojuice = 6, /datum/reagent/consumable/nutriment/vitamin = 5)
tastes = list("crust" = 1, "tomato" = 1, "cheese" = 1)
foodtypes = GRAIN | DAIRY | VEGETABLES
+ venue_value = FOOD_PRICE_CHEAP
/// type is spawned 6 at a time and replaces this pizza when processed by cutting tool
var/obj/item/food/pizzaslice/slice_type
///What label pizza boxes use if this pizza spawns in them.
@@ -99,6 +100,7 @@
foodtypes = GRAIN | VEGETABLES | DAIRY
slice_type = /obj/item/food/pizzaslice/vegetable
boxtag = "Gourmet Vegetable"
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/pizzaslice/vegetable
name = "vegetable pizza slice"
diff --git a/code/game/objects/items/food/salad.dm b/code/game/objects/items/food/salad.dm
index e1c2519d88d..90b04b25f5d 100644
--- a/code/game/objects/items/food/salad.dm
+++ b/code/game/objects/items/food/salad.dm
@@ -9,6 +9,7 @@
tastes = list("leaves" = 1)
foodtypes = VEGETABLES
eatverbs = list("devour","nibble","gnaw","gobble","chomp") //who the fuck gnaws and devours on a salad
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/salad/aesirsalad
name = "\improper Aesir salad"
diff --git a/code/game/objects/items/food/soup.dm b/code/game/objects/items/food/soup.dm
index e48ebd0261c..b93129d336e 100644
--- a/code/game/objects/items/food/soup.dm
+++ b/code/game/objects/items/food/soup.dm
@@ -8,6 +8,7 @@
tastes = list("tasteless soup" = 1)
foodtypes = VEGETABLES
eatverbs = list("slurp","sip","inhale","drink")
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/soup/wish
name = "wish soup"
@@ -31,6 +32,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/nutriment/vitamin = 8, /datum/reagent/water = 5)
tastes = list("meat" = 1)
foodtypes = MEAT
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/soup/slime
name = "slime soup"
@@ -39,6 +41,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/toxin/slimejelly = 10, /datum/reagent/consumable/nutriment/vitamin = 9, /datum/reagent/water = 5)
tastes = list("slime" = 1)
foodtypes = TOXIC | SUGAR
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/soup/blood
name = "tomato soup"
@@ -72,6 +75,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 9, /datum/reagent/water = 5, /datum/reagent/consumable/nutriment/vitamin = 8)
tastes = list("vegetables" = 1)
foodtypes = VEGETABLES
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/soup/nettle
name = "nettle soup"
@@ -80,6 +84,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 5, /datum/reagent/consumable/nutriment/protein = 2, /datum/reagent/water = 5, /datum/reagent/consumable/nutriment/vitamin = 9, /datum/reagent/medicine/omnizine = 5)
tastes = list("nettles" = 1)
foodtypes = VEGETABLES
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/soup/mystery
name = "mystery soup"
@@ -102,7 +107,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 4, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/consumable/capsaicin = 3, /datum/reagent/consumable/tomatojuice = 4, /datum/reagent/consumable/nutriment/vitamin = 4)
tastes = list("hot peppers" = 1)
foodtypes = VEGETABLES | MEAT
-
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/soup/coldchili
name = "cold chili"
desc = "This slush is barely a liquid!"
@@ -126,6 +131,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 3, /datum/reagent/consumable/nutriment/protein = 9, /datum/reagent/consumable/banana = 5, /datum/reagent/consumable/nutriment/vitamin = 10)
tastes = list("the jungle" = 1, "banana" = 1)
foodtypes = FRUIT
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/soup/tomato
name = "tomato soup"
@@ -207,7 +213,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 12, /datum/reagent/water = 5, /datum/reagent/consumable/nutriment/vitamin = 6)
tastes = list("sweet potato" = 1)
foodtypes = VEGETABLES | SUGAR
-
+ venue_value = FOOD_PRICE_NORMAL
/obj/item/food/soup/beet/red
name = "red beet soup"
desc = "Quite a delicacy."
@@ -231,6 +237,7 @@
food_reagents = list(/datum/reagent/consumable/nutriment = 6, /datum/reagent/consumable/nutriment/protein = 6, /datum/reagent/water = 5, /datum/reagent/consumable/nutriment/vitamin = 6)
tastes = list("creamy texture" = 1, "crab" = 4)
foodtypes = MEAT
+ venue_value = FOOD_PRICE_EXOTIC
/obj/item/food/soup/electron
name = "electron soup"
diff --git a/code/game/objects/items/food/spaghetti.dm b/code/game/objects/items/food/spaghetti.dm
index e47e9775db7..525b7b7a5f1 100644
--- a/code/game/objects/items/food/spaghetti.dm
+++ b/code/game/objects/items/food/spaghetti.dm
@@ -8,6 +8,7 @@
microwaved_type = /obj/item/food/spaghetti/boiledspaghetti
tastes = list("pasta" = 1)
foodtypes = GRAIN
+ venue_value = FOOD_PRICE_CHEAP
/obj/item/food/spaghetti/Initialize()
. = ..()
diff --git a/code/game/objects/items/holosign_creator.dm b/code/game/objects/items/holosign_creator.dm
index 037316a108f..9dc243b69b2 100644
--- a/code/game/objects/items/holosign_creator.dm
+++ b/code/game/objects/items/holosign_creator.dm
@@ -20,6 +20,8 @@
/obj/item/holosign_creator/examine(mob/user)
. = ..()
+ if(!signs)
+ return
. += "It is currently maintaining [signs.len]/[max_signs] projections."
/obj/item/holosign_creator/afterattack(atom/target, mob/user, proximity_flag)
@@ -65,6 +67,13 @@
qdel(H)
to_chat(user, "You clear all active holograms.")
+/obj/item/holosign_creator/Destroy()
+ . = ..()
+ if(LAZYLEN(signs))
+ for(var/H in signs)
+ qdel(H)
+
+
/obj/item/holosign_creator/janibarrier
name = "custodial holobarrier projector"
desc = "A holographic projector that creates hard light wet floor barriers."
diff --git a/code/game/objects/structures/holosign.dm b/code/game/objects/structures/holosign.dm
index 1e8961819d7..f769d657330 100644
--- a/code/game/objects/structures/holosign.dm
+++ b/code/game/objects/structures/holosign.dm
@@ -8,11 +8,13 @@
max_integrity = 1
armor = list(MELEE = 0, BULLET = 50, LASER = 50, ENERGY = 50, BOMB = 0, BIO = 0, RAD = 0, FIRE = 20, ACID = 20)
var/obj/item/holosign_creator/projector
+ var/use_vis_overlay = TRUE
/obj/structure/holosign/Initialize(loc, source_projector)
. = ..()
- alpha = 0
- SSvis_overlays.add_vis_overlay(src, icon, icon_state, ABOVE_MOB_LAYER, plane, dir, add_appearance_flags = RESET_ALPHA) //you see mobs under it, but you hit them like they are above it
+ if(use_vis_overlay)
+ alpha = 0
+ SSvis_overlays.add_vis_overlay(src, icon, icon_state, ABOVE_MOB_LAYER, plane, dir, add_appearance_flags = RESET_ALPHA) //you see mobs under it, but you hit them like they are above it
if(source_projector)
projector = source_projector
LAZYADD(projector.signs, src)
@@ -27,6 +29,9 @@
. = ..()
if(.)
return
+ attack_holosign(user, modifiers)
+
+/obj/structure/holosign/proc/attack_holosign(mob/living/user, list/modifiers)
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
user.changeNext_move(CLICK_CD_MELEE)
take_damage(5 , BRUTE, MELEE, 1)
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 dfffb5a68a3..84e6cb64a99 100644
--- a/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
+++ b/code/modules/food_and_drinks/recipes/tablecraft/recipes_burger.dm
@@ -17,7 +17,7 @@
subcategory = CAT_BURGER
/datum/crafting_recipe/food/burger
- name = "Burger"
+ name = "Plain Burger"
reqs = list(
/obj/item/food/patty/plain = 1,
/obj/item/food/bun = 1
diff --git a/code/modules/food_and_drinks/restaurant/_venue.dm b/code/modules/food_and_drinks/restaurant/_venue.dm
new file mode 100644
index 00000000000..52686e4f074
--- /dev/null
+++ b/code/modules/food_and_drinks/restaurant/_venue.dm
@@ -0,0 +1,188 @@
+///Represents the abstract concept of a food venue in the code.
+/datum/venue
+ ///Name of the venue, also used for the icon state of any radials it can be selected in
+ var/name = "unnamed venue"
+ ///Max amount of guests at any time
+ var/max_guests = 6
+ ///Weighted list of customer types
+ var/list/customer_types = list(/datum/customer_data/american = 5, /datum/customer_data/italian = 3, /datum/customer_data/french = 3)
+ ///Is the venue open at the moment?
+ var/open
+ ///Portal linked to this venue at the moment
+ var/obj/machinery/restaurant_portal/restaurant_portal
+ ///Lists the current visitors of a venue
+ var/list/current_visitors = list()
+ ///Cooldown for next guest to arrive
+ COOLDOWN_DECLARE(visit_cooldown)
+ ///Min time between new visits
+ var/min_time_between_visitor = 60 SECONDS
+ ///Max time between new visits
+ var/max_time_between_visitor = 90 SECONDS
+ ///Required access to mess with the venue
+ var/req_access = ACCESS_KITCHEN
+
+
+/datum/venue/process(delta_time)
+ if(!COOLDOWN_FINISHED(src, visit_cooldown))
+ return
+ COOLDOWN_START(src, visit_cooldown, rand(min_time_between_visitor, max_time_between_visitor))
+ if(current_visitors.len < max_guests)
+ create_new_customer()
+
+///Spawns a new customer at the portal
+/datum/venue/proc/create_new_customer()
+ var/mob/living/simple_animal/robot_customer/new_customer = new /mob/living/simple_animal/robot_customer(get_turf(restaurant_portal), pickweight(customer_types), src)
+ current_visitors += new_customer
+
+/datum/venue/proc/order_food(mob/living/simple_animal/robot_customer/customer_pawn, datum/customer_data/customer_data)
+ return
+
+///Checks if the object used is correct for the venue
+/datum/venue/proc/is_correct_order(atom/movable/object_used, wanted_item)
+ return FALSE
+
+///The line the robot says when ordering
+/datum/venue/proc/order_food_line(order)
+ return "broken venue pls call a coder"
+
+///Effects for when a customer receives their order at this venue
+/datum/venue/proc/on_get_order(mob/living/simple_animal/robot_customer/customer_pawn, obj/item/order_item)
+ SEND_SIGNAL(order_item, COMSIG_ITEM_SOLD_TO_CUSTOMER, order_item)
+
+///Toggles whether the venue is open or not
+/datum/venue/proc/toggle_open()
+ if(open)
+ close()
+ else
+ open()
+
+/datum/venue/proc/open()
+ open = TRUE
+ restaurant_portal.update_icon()
+ COOLDOWN_START(src, visit_cooldown, 10 SECONDS) //First one comes faster
+ START_PROCESSING(SSobj, src)
+
+/datum/venue/proc/close()
+ open = FALSE
+ restaurant_portal.update_icon()
+ STOP_PROCESSING(SSobj, src)
+ for(var/mob/living/simple_animal/robot_customer as anything in current_visitors)
+ robot_customer.ai_controller.blackboard[BB_CUSTOMER_LEAVING] = TRUE //LEAVEEEEEE
+
+/obj/machinery/restaurant_portal
+ name = "restaurant portal"
+ desc = "A robot-only gate into the wonders of Space Station cuisine!"
+ icon = 'icons/obj/machines/restaurant_portal.dmi'
+ icon_state = "portal"
+ density = TRUE
+ use_power = IDLE_POWER_USE
+ idle_power_usage = 10
+ active_power_usage = 100
+ circuit = /obj/item/circuitboard/machine/restaurant_portal
+
+ layer = BELOW_OBJ_LAYER
+ density = FALSE
+ anchored = TRUE
+ resistance_flags = INDESTRUCTIBLE | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+ ///What venue is this portal for? Uses a typepath which is turned into an instance on Initialize
+ var/datum/venue/linked_venue = /datum/venue
+
+
+/obj/machinery/restaurant_portal/Initialize()
+ . = ..()
+ if(linked_venue)
+ linked_venue = SSrestaurant.all_venues[linked_venue]
+ linked_venue.restaurant_portal = src
+
+/obj/machinery/restaurant_portal/Destroy()
+ . = ..()
+
+/obj/machinery/restaurant_portal/update_overlays()
+ . = ..()
+ if(!linked_venue.open) //Any open venues
+ . += mutable_appearance(icon, "portal_door")
+
+/obj/machinery/restaurant_portal/attack_hand(mob/living/user)
+ var/obj/item/card/id/used_id = user.get_idcard(TRUE)
+
+ if(!used_id)
+ return ..()
+
+ if(!(linked_venue.req_access in used_id.GetAccess()))
+ to_chat(user, "This card lacks the access to change this venues status.")
+ return
+
+ linked_venue.toggle_open()
+ update_icon()
+
+/obj/machinery/restaurant_portal/attacked_by(obj/item/I, mob/living/user)
+ if(!istype(I, /obj/item/card/id))
+ return ..()
+
+ var/obj/item/card/id/used_id = I
+
+ if(!(linked_venue.req_access in used_id.GetAccess()))
+ to_chat(user, "This card lacks the access to change this venues status.")
+ return
+
+ var/list/radial_items = list()
+ var/list/radial_results = list()
+
+ for(var/type_key in SSrestaurant.all_venues)
+ var/datum/venue/venue = SSrestaurant.all_venues[type_key]
+ radial_items[venue.name] = image('icons/obj/machines/restaurant_portal.dmi', venue.name)
+ radial_results[venue.name] = venue
+
+ var/choice = show_radial_menu(user, src, radial_items, null, require_near = TRUE)
+
+ if(!choice)
+ return
+
+ var/datum/venue/chosen_venue = radial_results[choice]
+
+
+
+ if(!(chosen_venue.req_access in used_id.GetAccess()))
+ to_chat(user, "This card lacks the access to change this venues status.")
+ return
+
+ to_chat(user, "You change the portal's linked venue.")
+
+ if(linked_venue && linked_venue.restaurant_portal) //We're already linked, unlink us.
+ if(linked_venue.open)
+ linked_venue.close()
+ linked_venue.restaurant_portal.linked_venue = null
+
+ linked_venue = chosen_venue
+ linked_venue.restaurant_portal = src
+
+
+/obj/item/holosign_creator/robot_seat
+ name = "seating indicator placer"
+ creation_time = 1 SECONDS
+ holosign_type = /obj/structure/holosign/robot_seat
+ desc = "Use this to place seats for your restaurant guests!"
+ resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
+
+/obj/item/holosign_creator/robot_seat/attack_self(mob/user)
+ return
+/obj/structure/holosign/robot_seat
+ density = FALSE
+ desc = "Used to indicate a place to sit for a robot tourist. I better be careful."
+ icon = 'icons/effects/effects.dmi'
+ icon_state = "eating_zone"
+ layer = BELOW_MOB_LAYER
+ use_vis_overlay = FALSE
+ var/datum/venue/linked_venue = /datum/venue
+
+/obj/structure/holosign/robot_seat/Initialize(loc, source_projector)
+ . = ..()
+ linked_venue = SSrestaurant.all_venues[linked_venue]
+
+/obj/structure/holosign/robot_seat/attack_holosign(mob/living/user, list/modifiers)
+ return
+
+/obj/structure/holosign/robot_seat/attacked_by(obj/item/I, mob/living/user)
+ . = ..()
+ if(I.type == projector?.type && !SSrestaurant.claimed_seats[src])
+ qdel(src)
diff --git a/code/modules/food_and_drinks/restaurant/customers/_customer.dm b/code/modules/food_and_drinks/restaurant/customers/_customer.dm
new file mode 100644
index 00000000000..a714d7657eb
--- /dev/null
+++ b/code/modules/food_and_drinks/restaurant/customers/_customer.dm
@@ -0,0 +1,86 @@
+/datum/customer_data
+ ///Name of the robot's origin
+ var/nationality = "Generic"
+ ///The types of food this robot likes in a assoc list of venue type | weighted list. does NOT include subtypes.
+ var/list/orderable_objects = list()
+ ///The amount a robot pays for each food he likes in an assoc list type | payment
+ var/list/order_prices = list()
+ ///Datum AI used for the robot. Should almost never be overwritten unless theyre subtypes of ai_controller/robot_customer
+ var/datum/ai_controller/ai_controller_used = /datum/ai_controller/robot_customer
+ ///Patience of the AI, how long they will wait for their meal.
+ var/total_patience = 600 SECONDS
+ ///Lines the robot says when it finds a seat
+ var/list/found_seat_lines = list("I found a seat")
+ ///Lines the robot says when it can't find a seat
+ var/list/cant_find_seat_lines = list("I did not find a seat")
+ ///Lines the robot says when leaving without food
+ var/list/leave_mad_lines = list("Leaving without food")
+ ///Lines the robot says when leaving with food
+ var/list/leave_happy_lines = list("Leaving with food")
+ ///Lines the robot says when leaving waiting for food
+ var/list/wait_for_food_lines = list("I'm still waiting for food")
+ ///Clothing sets to pick from when dressing the robot.
+ var/list/clothing_sets = list("amerifat_clothes")
+ ///List of prefixes for our robots name
+ var/list/name_prefixes
+ ///Prefix file to uise
+ var/prefix_file = "strings/names/american_prefix.txt"
+ ///Base icon for the customer
+ var/base_icon = "amerifat"
+
+/datum/customer_data/New()
+ . = ..()
+ name_prefixes = world.file2list(prefix_file)
+
+/datum/customer_data/proc/get_overlays(mob/living/simple_animal/robot_customer/customer)
+ return
+
+/datum/customer_data/american
+ nationality = "Space-American"
+ orderable_objects = list(
+ /datum/venue/restaurant = list(/obj/item/food/burger/plain = 25, /obj/item/food/burger/cheese = 15, /obj/item/food/burger/superbite = 1, /obj/item/food/fries = 10, /obj/item/food/cheesyfries = 6, /obj/item/food/pie/applepie = 4, /obj/item/food/pie/pumpkinpie = 2, /obj/item/food/hotdog = 8, /obj/item/food/pizza/pineapple = 1, /obj/item/food/burger/baconburger = 10, /obj/item/food/pancakes = 4),
+ /datum/venue/bar = list(/datum/reagent/consumable/ethanol/b52 = 6, /datum/reagent/consumable/ethanol/manhattan = 3, /datum/reagent/consumable/ethanol/atomicbomb = 1, /datum/reagent/consumable/ethanol/beer = 25))
+
+
+ found_seat_lines = list("I hope there's a seat that supports my weight.", "I hope I can bring my gun in here.", "I hope they have the triple deluxe fatty burger.", "I just love the culture here.")
+ cant_find_seat_lines = list("I'm so tired from standing...", "I have chronic back pain, please hurry up and get me a seat!", "I'm not going to tip if I don't get a seat.")
+ leave_mad_lines = list("NO TIP FOR YOU. GOODBYE!", "At least at SpaceDonalds they serve their food FAST!", "This venue is horrendous!", "I will speak to your manager!", "I'll be sure to leave a bad Yelp review.")
+ leave_happy_lines = list("An extra tip for you my friend.", "Thanks for the great food!", "Diabetes is a myth anyway!")
+ wait_for_food_lines = list("Listen buddy, I'm getting real impatient over here!", "I've been waiting for ages...")
+
+
+/datum/customer_data/italian
+ nationality = "Space-Italian"
+ prefix_file = "strings/names/italian_prefix.txt"
+ base_icon = "italian"
+ clothing_sets = list("italian_pison", "italian_godfather")
+
+ found_seat_lines = list("What a wonderful place to sit.", "I hope they serve it like-a my momma used to make it.")
+ cant_find_seat_lines = list("Mamma mia! I just want a seat!", "Why-a you making me stand here?")
+ leave_mad_lines = list("I have-a not seen-a this much disrespect in years!", "What-a horrendous establishment!")
+ leave_happy_lines = list("That's amoreee!", "Just like momma used to make it!")
+ wait_for_food_lines = list("I'ma so hungry...")
+ orderable_objects = list(
+ /datum/venue/restaurant = list(/obj/item/food/spaghetti/pastatomato = 20, /obj/item/food/spaghetti/copypasta = 6, /obj/item/food/spaghetti/meatballspaghetti = 4, /obj/item/food/pizza/vegetable = 2, /obj/item/food/pizza/mushroom = 2, /obj/item/food/pizza/meat = 2, /obj/item/food/pizza/margherita = 2),
+ /datum/venue/bar = list(/datum/reagent/consumable/ethanol/fanciulli = 5, /datum/reagent/consumable/ethanol/branca_menta = 3, /datum/reagent/consumable/ethanol/beer = 10, /datum/reagent/consumable/lemonade = 8, /datum/reagent/consumable/ethanol/godfather = 5))
+
+
+/datum/customer_data/french
+ nationality = "Space-French"
+ prefix_file = "strings/names/french_prefix.txt"
+ base_icon = "french"
+ clothing_sets = list("french_fit")
+ found_seat_lines = list("Hon hon hon", "It's not the Eiffel tower but it will do.", "Yuck, I guess this will make do.")
+ cant_find_seat_lines = list("Making someone like me stand? How dare you.", "What a filthy lobby!")
+ leave_mad_lines = list("Sacre bleu!", "Merde! This place is shittier than the Rhine!")
+ leave_happy_lines = list("Hon hon hon.", "A good effort.")
+ wait_for_food_lines = list("Hon hon hon")
+ orderable_objects = list(
+ /datum/venue/restaurant = list(/obj/item/food/baguette = 20, /obj/item/food/garlicbread = 5, /obj/item/food/soup/onion = 4, /obj/item/food/pie/berryclafoutis = 2, /obj/item/food/omelette = 15),
+ /datum/venue/bar = list(/datum/reagent/consumable/ethanol/champagne = 15, /datum/reagent/consumable/ethanol/mojito = 5, /datum/reagent/consumable/ethanol/sidecar = 5, /datum/reagent/consumable/ethanol/between_the_sheets = 4, /datum/reagent/consumable/ethanol/beer = 10))
+
+/datum/customer_data/french/get_overlays(mob/living/simple_animal/robot_customer/customer)
+ if(customer.ai_controller.blackboard[BB_CUSTOMER_LEAVING])
+ var/mutable_appearance/flag = mutable_appearance(customer.icon, "french_flag")
+ flag.appearance_flags = RESET_COLOR
+ return flag
diff --git a/code/modules/food_and_drinks/restaurant/generic_venues.dm b/code/modules/food_and_drinks/restaurant/generic_venues.dm
new file mode 100644
index 00000000000..d319d269a84
--- /dev/null
+++ b/code/modules/food_and_drinks/restaurant/generic_venues.dm
@@ -0,0 +1,119 @@
+/////RESTAURANT/////
+/datum/venue/restaurant
+ name = "restaurant"
+ req_access = ACCESS_KITCHEN
+
+/datum/venue/restaurant/order_food(mob/living/simple_animal/robot_customer/customer_pawn, datum/customer_data/customer_data)
+ var/obj/item/object_to_order = pickweight(customer_data.orderable_objects[type]) //Get what object we are ordering
+
+ . = object_to_order
+
+ customer_pawn.say(order_food_line(object_to_order))
+
+ var/appearance = SSrestaurant.food_appearance_cache[object_to_order]
+
+ if(!appearance) //We havn't made this one before, do so now.
+ var/obj/item/temp_object = new object_to_order() //Make a temp object so we can see it including any overlays
+ appearance = temp_object.appearance //And then steal its appearance
+ SSrestaurant.food_appearance_cache[object_to_order] = appearance //and cache it for future orders
+ qdel(temp_object)
+
+ var/image/I = image(icon = 'icons/obj/machines/restaurant_portal.dmi' , icon_state = "thought_bubble", loc = customer_pawn, layer = HUD_LAYER)
+
+ I.appearance = appearance
+ I.underlays += mutable_appearance(icon = 'icons/obj/machines/restaurant_portal.dmi' , icon_state = "thought_bubble")
+ I.pixel_y = 32
+ I.pixel_x = 16
+ I.plane = HUD_PLANE
+ I.appearance_flags = RESET_COLOR
+ customer_pawn.hud_to_show_on_hover = customer_pawn.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/food_demands, "food_thoughts", I)
+
+/datum/venue/restaurant/is_correct_order(atom/movable/object_used, wanted_item)
+ return object_used.type == wanted_item
+
+/datum/venue/restaurant/order_food_line(obj/item/order)
+ return "I'll take \a [initial(order.name)]"
+
+/datum/venue/restaurant/on_get_order(mob/living/simple_animal/robot_customer/customer_pawn, obj/item/order_item)
+ . = ..()
+ customer_pawn.visible_message("[customer_pawn] pushes [order_item] into their mouth-shaped hole!", "You push [order_item] into your mouth-shaped hole.")
+ playsound(get_turf(customer_pawn),'sound/items/eatfood.ogg', rand(10,50), TRUE)
+ qdel(order_item)
+
+/obj/machinery/restaurant_portal/restaurant
+ linked_venue = /datum/venue/restaurant
+/obj/item/holosign_creator/robot_seat/restaurant
+ name = "restaurant seating indicator placer"
+ holosign_type = /obj/structure/holosign/robot_seat/restaurant
+
+/obj/structure/holosign/robot_seat/restaurant
+ name = "restaurant seating"
+ linked_venue = /datum/venue/restaurant
+
+
+
+
+/////BAR/////
+/datum/venue/bar
+ name = "bar"
+ req_access = ACCESS_BAR
+ min_time_between_visitor = 40 SECONDS
+ max_time_between_visitor = 60 SECONDS
+
+/datum/venue/bar/order_food(mob/living/simple_animal/robot_customer/customer_pawn, datum/customer_data/customer_data)
+ var/datum/reagent/reagent_to_order = pickweight(customer_data.orderable_objects[type])
+
+ var/glass_visual
+
+ if(initial(reagent_to_order.glass_icon_state))
+ glass_visual = initial(reagent_to_order.glass_icon_state)
+ else if(initial(reagent_to_order.shot_glass_icon_state))
+ glass_visual = initial(reagent_to_order.shot_glass_icon_state)
+ else if(initial(reagent_to_order.fallback_icon_state))
+ glass_visual = initial(reagent_to_order.fallback_icon_state)
+ else
+ CRASH("[reagent_to_order] has no icon sprite for restaurant code, please set a fallback_icon_state for this reagent.")
+
+ customer_pawn.say(order_food_line(reagent_to_order))
+
+ var/image/I = image(icon = 'icons/obj/machines/restaurant_portal.dmi' , icon_state = "thought_bubble", loc = customer_pawn, layer = HUD_LAYER)
+ I.add_overlay(mutable_appearance('icons/obj/drinks.dmi', glass_visual))
+ I.pixel_y = 32
+ I.pixel_x = 16
+ I.plane = HUD_PLANE
+ I.appearance_flags = RESET_COLOR
+ customer_pawn.hud_to_show_on_hover = customer_pawn.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/food_demands, "food_thoughts", I)
+
+ return reagent_to_order
+
+/datum/venue/bar/order_food_line(datum/reagent/order)
+ return "I'll take a glass of [initial(order.name)]"
+
+/datum/venue/bar/on_get_order(mob/living/simple_animal/robot_customer/customer_pawn, obj/item/order_item)
+ var/datum/reagent/ordered_reagent_type = customer_pawn.ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER]
+
+ for(var/datum/reagent/reagent as anything in order_item.reagents.reagent_list)
+ if(reagent.type != ordered_reagent_type)
+ continue
+ SEND_SIGNAL(reagent, COMSIG_ITEM_SOLD_TO_CUSTOMER, order_item)
+
+ customer_pawn.visible_message("[customer_pawn] slurps up [order_item] in one go!", "You slurp up [order_item] in one go.")
+ playsound(get_turf(customer_pawn), 'sound/items/drink.ogg', 50, TRUE)
+ order_item.reagents.clear_reagents()
+
+
+///The bar needs to have a minimum amount of the reagent
+/datum/venue/bar/is_correct_order(object_used, wanted_item)
+ if(istype(object_used, /obj/item/reagent_containers/food/drinks))
+ var/obj/item/reagent_containers/food/drinks/potential_drink = object_used
+ return potential_drink.reagents.has_reagent(wanted_item, VENUE_BAR_MINIMUM_REAGENTS)
+/obj/machinery/restaurant_portal/bar
+ linked_venue = /datum/venue/bar
+
+/obj/item/holosign_creator/robot_seat/bar
+ name = "bar seating indicator placer"
+ holosign_type = /obj/structure/holosign/robot_seat/bar
+
+/obj/structure/holosign/robot_seat/bar
+ name = "bar seating"
+ linked_venue = /datum/venue/bar
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index e0116c6c960..ac2d36b73f1 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -191,10 +191,6 @@
// called when something steps onto a human
// this could be made more general, but for now just handle mulebot
/mob/living/carbon/human/Crossed(atom/movable/AM)
- var/mob/living/simple_animal/bot/mulebot/MB = AM
- if(istype(MB))
- MB.RunOver(src)
-
. = ..()
spreadFire(AM)
diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm
index 6e3045641db..eaa6c9a4517 100644
--- a/code/modules/mob/living/simple_animal/bot/mulebot.dm
+++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm
@@ -115,6 +115,13 @@
return
return ..()
+/mob/living/simple_animal/bot/mulebot/Cross(atom/movable/AM)
+ . = ..()
+ if(ishuman(AM))
+ RunOver(AM)
+
+
+
/// returns true if the bot is fully powered.
/mob/living/simple_animal/bot/mulebot/proc/has_power(bypass_open_check)
return (!open || bypass_open_check) && cell && cell.charge > 0 && (!wires.is_cut(WIRE_POWER1) && !wires.is_cut(WIRE_POWER2))
@@ -724,7 +731,6 @@
visible_message("[src] knocks over [L]!")
return ..()
-// called from mob/living/carbon/human/Crossed()
// when mulebot is in the same loc
/mob/living/simple_animal/bot/mulebot/proc/RunOver(mob/living/carbon/human/H)
log_combat(src, H, "run over", null, "(DAMTYPE: [uppertext(BRUTE)])")
diff --git a/code/modules/mob/living/simple_animal/friendly/robot_customer.dm b/code/modules/mob/living/simple_animal/friendly/robot_customer.dm
new file mode 100644
index 00000000000..a1cfa1f00a9
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/friendly/robot_customer.dm
@@ -0,0 +1,81 @@
+///Robot customers
+/mob/living/simple_animal/robot_customer
+ name = "space-tourist bot"
+ maxHealth = 50000000 //go fuck yourself
+ health = 50000000
+ desc = "I wonder what they'll order..."
+ icon = 'icons/mob/tourists.dmi'
+ icon_state = "amerifat"
+ icon_living = "amerifat"
+ ///Override so it uses datum ai
+ can_have_ai = FALSE
+ AIStatus = AI_OFF
+ del_on_death = TRUE
+ mob_biotypes = MOB_ROBOTIC|MOB_HUMANOID
+ ai_controller = /datum/ai_controller/robot_customer
+ unsuitable_atmos_damage = 0
+ minbodytemp = 0
+ maxbodytemp = 1000
+ var/clothes_set = "amerifat_clothes"
+ var/datum/atom_hud/hud_to_show_on_hover
+
+
+/mob/living/simple_animal/robot_customer/Initialize(mapload, datum/customer_data/customer_data = /datum/customer_data/american, datum/venue/attending_venue = SSrestaurant.all_venues[/datum/venue/restaurant])
+ ADD_TRAIT(src, TRAIT_NOMOBSWAP, INNATE_TRAIT) //dont push me bitch
+ ADD_TRAIT(src, TRAIT_NO_TELEPORT, INNATE_TRAIT) //dont teleport me bitch
+ AddComponent(/datum/component/footstep, FOOTSTEP_OBJ_ROBOT, 1, -6, vary = TRUE)
+ var/datum/customer_data/customer_info = SSrestaurant.all_customers[customer_data]
+ clothes_set = pick(customer_info.clothing_sets)
+ ai_controller = customer_info.ai_controller_used
+ . = ..()
+ ai_controller.blackboard[BB_CUSTOMER_CUSTOMERINFO] = customer_info
+ ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE] = attending_venue
+ ai_controller.blackboard[BB_CUSTOMER_PATIENCE] = customer_info.total_patience
+ icon_state = customer_info.base_icon
+ name = "[pick(customer_info.name_prefixes)]-bot ([customer_info.nationality])"
+ color = rgb(rand(150,255), rand(150,255), rand(150,255))
+ update_icon()
+
+///Clean up on the mobs seat etc when its deleted (Either by murder or because it left)
+/mob/living/simple_animal/robot_customer/Destroy()
+ var/datum/venue/attending_venue = ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE]
+ attending_venue.current_visitors -= src
+ SSrestaurant.claimed_seats[ai_controller.blackboard[BB_CUSTOMER_MY_SEAT]] = null
+ QDEL_NULL(hud_to_show_on_hover)
+ return ..()
+
+/mob/living/simple_animal/robot_customer/MouseEntered(location, control, params)
+ . = ..()
+ hud_to_show_on_hover?.add_hud_to(usr)
+
+/mob/living/simple_animal/robot_customer/MouseExited(location, control, params)
+ . = ..()
+ hud_to_show_on_hover?.remove_hud_from(usr)
+
+/mob/living/simple_animal/robot_customer/update_overlays()
+ . = ..()
+ var/mutable_appearance/features = mutable_appearance(icon, "[icon_state]_features")
+ features.appearance_flags = RESET_COLOR
+ . += features
+
+ var/mutable_appearance/clothes = mutable_appearance(icon, clothes_set)
+ clothes.appearance_flags = RESET_COLOR
+ . += clothes
+
+ var/datum/customer_data/customer_info = ai_controller.blackboard[BB_CUSTOMER_CUSTOMERINFO]
+
+ var/bonus_overlays = customer_info.get_overlays(src)
+ if(bonus_overlays)
+ . += bonus_overlays
+
+/mob/living/simple_animal/robot_customer/send_speech(message, message_range, obj/source, bubble_type, list/spans, datum/language/message_language, list/message_mods)
+ . = ..()
+ playsound(get_turf(src), 'sound/effects/tourist_talk.ogg', 100, TRUE)
+
+/mob/living/simple_animal/robot_customer/examine(mob/user)
+ . = ..()
+ if(ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER])
+ var/datum/venue/attending_venue = ai_controller.blackboard[BB_CUSTOMER_ATTENDING_VENUE]
+ . += "Their order was: \"[attending_venue.order_food_line(ai_controller.blackboard[BB_CUSTOMER_CURRENT_ORDER])].\""
+
+
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index cc857f2022d..2e44f79e58d 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -173,7 +173,7 @@
var/pet_bonus_emote = ""
-/mob/living/simple_animal/Initialize()
+/mob/living/simple_animal/Initialize(mapload)
. = ..()
GLOB.simple_animals[AIStatus] += src
if(gender == PLURAL)
diff --git a/code/modules/reagents/chemistry/reagents.dm b/code/modules/reagents/chemistry/reagents.dm
index e2e259432c7..63061bf24cf 100644
--- a/code/modules/reagents/chemistry/reagents.dm
+++ b/code/modules/reagents/chemistry/reagents.dm
@@ -34,6 +34,8 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
var/glass_icon_state = null
/// used for shot glasses, mostly for alcohol
var/shot_glass_icon_state = null
+ /// fallback icon if the reagent has no glass or shot glass icon state. Used for restaurants.
+ var/fallback_icon_state = null
/// reagent holder this belongs to
var/datum/reagents/holder = null
/// LIQUID, SOLID, GAS
diff --git a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
index 946f11919cd..1088f2f3e94 100644
--- a/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/alcohol_reagents.dm
@@ -98,6 +98,8 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "A freezing pint of beer."
ph = 4
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ fallback_icon_state = "beer"
+ glass_price = DRINK_PRICE_STOCK
// Beer is a chemical composition of alcohol and various other things. It's a garbage nutrient but hey, it's still one. Also alcohol is bad, mmmkay?
@@ -116,6 +118,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "A freezing pint of watery light beer."
ph = 5
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ fallback_icon_state = "beer"
/datum/reagent/consumable/ethanol/beer/maltliquor
name = "Malt Liquor"
@@ -894,6 +897,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_desc = "Kahlua, Irish Cream, and cognac. You will get bombed."
shot_glass_icon_state = "b52glass"
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_EASY
/datum/reagent/consumable/ethanol/b52/on_mob_metabolize(mob/living/M)
playsound(M, 'sound/effects/explosion_distant.ogg', 100, FALSE)
@@ -946,6 +950,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Manhattan"
glass_desc = "The Detective's undercover drink of choice. He never could stomach gin..."
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_EASY
/datum/reagent/consumable/ethanol/manhattan_proj
@@ -1457,6 +1462,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Atomic Bomb"
glass_desc = "Nanotrasen cannot take legal responsibility for your actions after imbibing."
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_HIGH
/datum/reagent/consumable/ethanol/atomicbomb/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.set_drugginess(50 * REM * delta_time)
@@ -1928,6 +1934,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Sidecar"
glass_desc = "The one ride you'll gladly give up the wheel for."
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_MEDIUM
/datum/reagent/consumable/ethanol/between_the_sheets
name = "Between the Sheets"
@@ -1977,6 +1984,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Mojito"
glass_desc = "A drink that looks as refreshing as it tastes."
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_MEDIUM
/datum/reagent/consumable/ethanol/moscow_mule
name = "Moscow Mule"
@@ -2038,6 +2046,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "glass of fanciulli"
glass_desc = "A glass of Fanciulli. It's just Manhattan with Fernet."
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_HIGH
/datum/reagent/consumable/ethanol/fanciulli/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
M.adjust_nutrition(-5 * REM * delta_time)
@@ -2062,6 +2071,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "glass of branca menta"
glass_desc = "A glass of Branca Menta, perfect for those lazy and hot Sunday summer afternoons." //Get lazy literally by drinking this
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_MEDIUM
/datum/reagent/consumable/ethanol/branca_menta/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
@@ -2207,6 +2217,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Champagne"
glass_desc = "The flute clearly displays the slowly rising bubbles."
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_EASY
/datum/reagent/consumable/ethanol/wizz_fizz
@@ -2493,6 +2504,7 @@ All effects don't start immediately, but rather get worse over time; the rate is
glass_name = "Godfather"
glass_desc = "A classic from old Italy and enjoyed by gangsters, pray the orange peel doesnt end up in your mouth."
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_MEDIUM
/datum/reagent/consumable/ethanol/godmother
name = "Godmother"
diff --git a/code/modules/reagents/chemistry/reagents/drink_reagents.dm b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
index 93a20cea5ef..b921a7efeb1 100644
--- a/code/modules/reagents/chemistry/reagents/drink_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/drink_reagents.dm
@@ -329,6 +329,7 @@
glass_name = "pitcher of lemonade"
glass_desc = "This drink leaves you feeling nostalgic for some reason."
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
+ glass_price = DRINK_PRICE_EASY
/datum/reagent/consumable/tea/arnold_palmer
name = "Arnold Palmer"
diff --git a/code/modules/reagents/chemistry/reagents/food_reagents.dm b/code/modules/reagents/chemistry/reagents/food_reagents.dm
index b3e08a0ee6d..aced7fd7d5b 100755
--- a/code/modules/reagents/chemistry/reagents/food_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/food_reagents.dm
@@ -11,13 +11,20 @@
name = "Consumable"
taste_description = "generic food"
taste_mult = 4
- /// How much nutrition this reagent supplies
- var/nutriment_factor = 1 * REAGENTS_METABOLISM
- var/quality = 0 //affects mood, typically higher for mixed drinks with more complex recipes
impure_chem = /datum/reagent/water
inverse_chem_val = 0.1
inverse_chem = /datum/reagent/water
failed_chem = /datum/reagent/consumable/nutriment
+ /// How much nutrition this reagent supplies
+ var/nutriment_factor = 1 * REAGENTS_METABOLISM
+ var/quality = 0 //affects mood, typically higher for mixed drinks with more complex recipes'
+ ///The amount a robot will pay for a glass of this (20 units but can be higher if you pour more, be frugal!)
+ var/glass_price
+
+/datum/reagent/consumable/New()
+ . = ..()
+ if(glass_price)
+ AddElement(/datum/element/venue_price, glass_price)
/datum/reagent/consumable/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
current_cycle++
diff --git a/code/modules/research/designs/autolathe_designs.dm b/code/modules/research/designs/autolathe_designs.dm
index 3e5208a9c47..12e489a9365 100644
--- a/code/modules/research/designs/autolathe_designs.dm
+++ b/code/modules/research/designs/autolathe_designs.dm
@@ -1217,3 +1217,24 @@
materials = list(/datum/material/iron = 100, /datum/material/glass = 50)
build_path = /obj/item/assembly/control
category = list("initial","Misc")
+
+
+/datum/design/holosign/restaurant
+ name = "Restaurant Seating Projector"
+ desc = "A holographic projector that creates seating designation for restaurants."
+ id = "holosignrestaurant"
+ build_type = AUTOLATHE
+ materials = list(/datum/material/iron = 2000, /datum/material/glass = 1000)
+ build_path = /obj/item/holosign_creator/robot_seat/restaurant
+ category = list("Equipment")
+ departmental_flags = DEPARTMENTAL_FLAG_SERVICE
+
+/datum/design/holosign/bar
+ name = "Bar Seating Projector"
+ desc = "A holographic projector that creates seating designation for bars."
+ id = "holosignbar"
+ build_type = AUTOLATHE
+ materials = list(/datum/material/iron = 2000, /datum/material/glass = 1000)
+ build_path = /obj/item/holosign_creator/robot_seat/bar
+ category = list("Equipment")
+ departmental_flags = DEPARTMENTAL_FLAG_SERVICE
diff --git a/code/modules/research/designs/machine_designs.dm b/code/modules/research/designs/machine_designs.dm
index 3bb3f2d6335..293f9c2ccad 100644
--- a/code/modules/research/designs/machine_designs.dm
+++ b/code/modules/research/designs/machine_designs.dm
@@ -633,6 +633,14 @@
build_path = /obj/item/circuitboard/machine/sheetifier
category = list ("Misc. Machinery")
+
+/datum/design/board/restaurant_portal
+ name = "Machine Design (Restaurant Portal)"
+ desc = "The circuit board for a restaurant portal"
+ id = "restaurant_portal"
+ build_path = /obj/item/circuitboard/machine/restaurant_portal
+ category = list ("Misc. Machinery")
+
/datum/design/board/vendatray
name = "Machine Design (Vend-a-Tray)"
desc = "The circuit board for a Vend-a-Tray."
diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm
index f02b791f2c9..120c120c678 100644
--- a/code/modules/research/techweb/all_nodes.dm
+++ b/code/modules/research/techweb/all_nodes.dm
@@ -9,7 +9,7 @@
description = "NT default research technologies."
// Default research tech, prevents bricking
design_ids = list("basic_matter_bin", "basic_cell", "basic_scanning", "basic_capacitor", "basic_micro_laser", "micro_mani", "basic_electrolite", "c-reader", "desttagger", "salestagger", "handlabel", "packagewrap",
- "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "bepis", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab",
+ "destructive_analyzer", "circuit_imprinter", "experimentor", "rdconsole", "bepis", "design_disk", "tech_disk", "rdserver", "rdservercontrol", "mechfab", "restaurant_portal",
"paystand", "space_heater", "bucket", "sec_rshot", "sec_beanbag_slug", "sec_Islug", "sec_dart", "sec_38", "rglass", "plasteel", "experi_scanner", "destructive_scanner", "doppler_array",
"plastitanium", "plasmaglass", "plasmareinforcedglass", "titaniumglass", "plastitaniumglass", "plastic_knife", "plastic_fork", "plastic_spoon", "conveyor_belt", "conveyor_switch",
"b6mm","b6mm_rubber","b9mm","b9mm_rubber","b10mm","b10mm_rubber","b12mm","b12mm_rubber") //SKYRAT EDIT ADDITION - SEC_HAUL
diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi
index 7bdbe698795..0a947c671bf 100644
Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ
diff --git a/icons/mob/tourists.dmi b/icons/mob/tourists.dmi
new file mode 100644
index 00000000000..546cff2aed7
Binary files /dev/null and b/icons/mob/tourists.dmi differ
diff --git a/icons/obj/machines/restaurant_portal.dmi b/icons/obj/machines/restaurant_portal.dmi
new file mode 100644
index 00000000000..62591d4b56f
Binary files /dev/null and b/icons/obj/machines/restaurant_portal.dmi differ
diff --git a/sound/effects/tank_treads.ogg b/sound/effects/tank_treads.ogg
new file mode 100644
index 00000000000..be4e0ff273b
Binary files /dev/null and b/sound/effects/tank_treads.ogg differ
diff --git a/sound/effects/tourist_talk.ogg b/sound/effects/tourist_talk.ogg
new file mode 100644
index 00000000000..239e1a79753
Binary files /dev/null and b/sound/effects/tourist_talk.ogg differ
diff --git a/strings/names/american_prefix.txt b/strings/names/american_prefix.txt
new file mode 100644
index 00000000000..58293ab5713
--- /dev/null
+++ b/strings/names/american_prefix.txt
@@ -0,0 +1,23 @@
+Yeehaw
+Gun
+Republican
+Vietnam
+Burger
+Grill
+Chub
+Obesi
+Diabeti
+Anti-healthcare
+Cowboy
+New York
+Texas
+Florida
+Anti-vax
+Nixon
+Independi
+Oorah
+Freedom
+Liberty
+Barbeque
+Democra
+Second amendment
diff --git a/strings/names/french_prefix.txt b/strings/names/french_prefix.txt
new file mode 100644
index 00000000000..201a35dd230
--- /dev/null
+++ b/strings/names/french_prefix.txt
@@ -0,0 +1,9 @@
+Baguette
+Snail
+Surrender
+White flag
+Eiffel
+Paris
+Beret
+Hon hon
+Wine
\ No newline at end of file
diff --git a/strings/names/italian_prefix.txt b/strings/names/italian_prefix.txt
new file mode 100644
index 00000000000..e0a3d83e6e6
--- /dev/null
+++ b/strings/names/italian_prefix.txt
@@ -0,0 +1,8 @@
+Mob
+Don
+Pizza
+Vespa
+Pasta
+Venice
+Rome
+Centuri
\ No newline at end of file
diff --git a/tgstation.dme b/tgstation.dme
index c75e5bfc09e..5d575bc138e 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -348,6 +348,7 @@
#include "code\controllers\subsystem\radiation.dm"
#include "code\controllers\subsystem\radio.dm"
#include "code\controllers\subsystem\research.dm"
+#include "code\controllers\subsystem\restaurant.dm"
#include "code\controllers\subsystem\runechat.dm"
#include "code\controllers\subsystem\server_maint.dm"
#include "code\controllers\subsystem\shuttle.dm"
@@ -444,9 +445,12 @@
#include "code\datums\ai\monkey\monkey_behaviors.dm"
#include "code\datums\ai\monkey\monkey_controller.dm"
#include "code\datums\ai\movement\_ai_movement.dm"
+#include "code\datums\ai\movement\ai_movement_basic_avoidance.dm"
#include "code\datums\ai\movement\ai_movement_dumb.dm"
#include "code\datums\ai\objects\vending_machines\vending_machine_behaviors.dm"
#include "code\datums\ai\objects\vending_machines\vending_machine_controller.dm"
+#include "code\datums\ai\robot_customer\robot_customer_behaviors.dm"
+#include "code\datums\ai\robot_customer\robot_customer_controller.dm"
#include "code\datums\announcers\_announcer.dm"
#include "code\datums\announcers\default_announcer.dm"
#include "code\datums\announcers\intern_announcer.dm"
@@ -680,6 +684,7 @@
#include "code\datums\elements\food\dunkable.dm"
#include "code\datums\elements\food\food_trash.dm"
#include "code\datums\elements\food\processable.dm"
+#include "code\datums\elements\food\venue_price.dm"
#include "code\datums\helper_datums\events.dm"
#include "code\datums\helper_datums\getrev.dm"
#include "code\datums\helper_datums\icon_snapshot.dm"
@@ -2134,6 +2139,9 @@
#include "code\modules\food_and_drinks\recipes\tablecraft\recipes_sandwich.dm"
#include "code\modules\food_and_drinks\recipes\tablecraft\recipes_soup.dm"
#include "code\modules\food_and_drinks\recipes\tablecraft\recipes_spaghetti.dm"
+#include "code\modules\food_and_drinks\restaurant\_venue.dm"
+#include "code\modules\food_and_drinks\restaurant\generic_venues.dm"
+#include "code\modules\food_and_drinks\restaurant\customers\_customer.dm"
#include "code\modules\games\cas.dm"
#include "code\modules\games\kotahi.dm"
#include "code\modules\games\tarot.dm"
@@ -2583,6 +2591,7 @@
#include "code\modules\mob\living\simple_animal\friendly\mouse.dm"
#include "code\modules\mob\living\simple_animal\friendly\penguin.dm"
#include "code\modules\mob\living\simple_animal\friendly\pet.dm"
+#include "code\modules\mob\living\simple_animal\friendly\robot_customer.dm"
#include "code\modules\mob\living\simple_animal\friendly\sloth.dm"
#include "code\modules\mob\living\simple_animal\friendly\snake.dm"
#include "code\modules\mob\living\simple_animal\friendly\drone\_drone.dm"