diff --git a/code/__DEFINES/crafting.dm b/code/__DEFINES/crafting.dm
new file mode 100644
index 00000000000..8218d392640
--- /dev/null
+++ b/code/__DEFINES/crafting.dm
@@ -0,0 +1,7 @@
+#define CAT_NONE ""
+#define CAT_WEAPON "Weaponry"
+#define CAT_AMMO "Ammunition"
+#define CAT_ROBOT "Robots"
+#define CAT_FOOD "Food"
+#define CAT_MISC "Misc"
+#define CAT_PRIMAL "Tribal"
diff --git a/code/__HELPERS/global_lists.dm b/code/__HELPERS/global_lists.dm
index 8a44c1b7cab..7398518bb03 100644
--- a/code/__HELPERS/global_lists.dm
+++ b/code/__HELPERS/global_lists.dm
@@ -46,7 +46,7 @@
if(S.flags & IS_WHITELISTED)
whitelisted_species += S.name
- init_subtypes(/datum/table_recipe, table_recipes)
+ init_subtypes(/datum/crafting_recipe, crafting_recipes)
return 1
/* // Uncomment to debug chemical reaction list.
diff --git a/code/_globalvars/lists/objects.dm b/code/_globalvars/lists/objects.dm
index ec3be384bad..9204d5ec524 100644
--- a/code/_globalvars/lists/objects.dm
+++ b/code/_globalvars/lists/objects.dm
@@ -11,7 +11,7 @@ var/global/list/joblist = list() //list of all jobstypes, minus borg and AI
var/global/list/airlocks = list() //list of all airlocks
var/global/list/singularities = list() //list of all singularities
var/global/list/janitorial_equipment = list() //list of janitorial equipment
-var/global/list/table_recipes = list() //list of all table craft recipes
+var/global/list/crafting_recipes = list() //list of all crafting recipes
var/global/list/all_areas = list()
var/global/list/machines = list()
@@ -30,4 +30,4 @@ var/global/list/beacons = list()
var/global/list/shuttle_caller_list = list() //list of all communication consoles and AIs, for automatic shuttle calls when there are none.
var/global/list/tracked_implants = list() //list of all current implants that are tracked to work out what sort of trek everyone is on. Sadly not on lavaworld not implemented...
var/global/list/abductor_equipment = list() //list of all abductor equipment
-var/global/list/global_intercoms = list() //list of all intercomms, across all z-levels
\ No newline at end of file
+var/global/list/global_intercoms = list() //list of all intercomms, across all z-levels
diff --git a/code/_onclick/hud/_defines.dm b/code/_onclick/hud/_defines.dm
index d04022cc3e8..3fb4ff12d38 100644
--- a/code/_onclick/hud/_defines.dm
+++ b/code/_onclick/hud/_defines.dm
@@ -35,8 +35,7 @@
#define ui_swaphand2 "CENTER: 16,SOUTH+1:5"
#define ui_storage1 "CENTER+1:18,SOUTH:5"
#define ui_storage2 "CENTER+2:20,SOUTH:5"
-
-#define ui_pda "CENTER+3:22,SOUTH:5"
+#define ui_crafting "12:-10,1:5"
#define ui_alien_head "4:12,1:5" //aliens
#define ui_alien_oclothing "5:14,1:5" //aliens
@@ -154,4 +153,4 @@
#define HUD_VERSIONS 3 //used in show_hud()
//1 = standard hud
//2 = reduced hud (just hands and intent switcher)
-//3 = no hud (for screenshots)
\ No newline at end of file
+//3 = no hud (for screenshots)
diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm
index 7e0768ad869..a56c6b3bcf8 100644
--- a/code/_onclick/hud/human.dm
+++ b/code/_onclick/hud/human.dm
@@ -60,6 +60,12 @@
var/obj/screen/using
var/obj/screen/inventory/inv_box
+ using = new /obj/screen/inventory/craft
+ using.icon = ui_style
+ using.color = ui_color
+ using.alpha = ui_alpha
+ static_inventory += using
+
using = new /obj/screen/act_intent()
using.icon_state = mymob.a_intent
using.color = ui_color
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index 1b32a9201a3..24440f013c9 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -361,6 +361,16 @@
/obj/screen/zone_sel/robot
icon = 'icons/mob/screen_robot.dmi'
+/obj/screen/inventory/craft
+ name = "crafting menu"
+ icon = 'icons/mob/screen_midnight.dmi'
+ icon_state = "craft"
+ screen_loc = ui_crafting
+
+/obj/screen/inventory/craft/Click()
+ var/mob/living/M = usr
+ M.OpenCraftingMenu()
+
/obj/screen/inventory
var/slot_id //The indentifier for the slot. It has nothing to do with ID cards.
layer = 19
@@ -473,4 +483,3 @@
name = "health doll"
icon_state = "healthdoll_DEAD"
screen_loc = ui_healthdoll
-
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index a4840393f54..c8ba2b49c40 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -79,8 +79,19 @@
invisibility = 101
return ..()
-/atom/proc/CheckParts()
- return
+/atom/proc/CheckParts(list/parts_list)
+ for(var/A in parts_list)
+ if(istype(A, /datum/reagent))
+ if(!reagents)
+ reagents = new()
+ reagents.reagent_list.Add(A)
+ reagents.conditional_update()
+ else if(istype(A, /atom/movable))
+ var/atom/movable/M = A
+ if(istype(M.loc, /mob/living))
+ var/mob/living/L = M.loc
+ L.unEquip(M)
+ M.loc = src
/atom/proc/assume_air(datum/gas_mixture/giver)
qdel(giver)
@@ -442,4 +453,4 @@
O.show_message("[src] [atom_say_verb], \"[message]\"",2)
/atom/proc/speech_bubble(var/bubble_state = "",var/bubble_loc = src, var/list/bubble_recipients = list())
- return
\ No newline at end of file
+ return
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index d96f4124459..2e8096cab15 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -361,6 +361,7 @@ Class Procs:
return ..()
/obj/machinery/CheckParts()
+ ..()
RefreshParts()
return
diff --git a/code/game/objects/items/devices/guitar.dm b/code/game/objects/items/devices/guitar.dm
index 9a3b4dd6901..dc9067c34e4 100644
--- a/code/game/objects/items/devices/guitar.dm
+++ b/code/game/objects/items/devices/guitar.dm
@@ -34,7 +34,7 @@
/obj/item/device/guitar/Topic(href, href_list)
song.Topic(href, href_list)
-/datum/table_recipe/guitar
+/datum/crafting_recipe/guitar
name = "Guitar"
result = /obj/item/device/guitar
reqs = list(/obj/item/stack/sheet/wood = 5,
diff --git a/code/game/objects/items/weapons/defib.dm b/code/game/objects/items/weapons/defib.dm
index f0311a8ae24..394bf244d59 100644
--- a/code/game/objects/items/weapons/defib.dm
+++ b/code/game/objects/items/weapons/defib.dm
@@ -70,6 +70,7 @@
overlays += "[icon_state]-charge[ratio]"
/obj/item/weapon/defibrillator/CheckParts()
+ ..()
bcell = locate(/obj/item/weapon/stock_parts/cell) in contents
update_icon()
@@ -561,4 +562,4 @@
update_icon()
else
to_chat(user, "You need to target your patient's chest with [src].")
- return
\ No newline at end of file
+ return
diff --git a/code/game/objects/items/weapons/flamethrower.dm b/code/game/objects/items/weapons/flamethrower.dm
index 1c819f4c77a..c3a23b2ba7d 100644
--- a/code/game/objects/items/weapons/flamethrower.dm
+++ b/code/game/objects/items/weapons/flamethrower.dm
@@ -165,6 +165,7 @@
return
/obj/item/weapon/flamethrower/CheckParts()
+ ..()
weldtool = locate(/obj/item/weapon/weldingtool) in contents
igniter = locate(/obj/item/device/assembly/igniter) in contents
update_icon()
@@ -226,4 +227,4 @@
var/target_turf = get_turf(owner)
ignite_turf(target_turf, 100)
qdel(ptank)
- return 1 //It hit the flamethrower, not them
\ No newline at end of file
+ return 1 //It hit the flamethrower, not them
diff --git a/code/game/objects/items/weapons/grenades/ghettobomb.dm b/code/game/objects/items/weapons/grenades/ghettobomb.dm
index b7bbb4ed805..cad1b7630e3 100644
--- a/code/game/objects/items/weapons/grenades/ghettobomb.dm
+++ b/code/game/objects/items/weapons/grenades/ghettobomb.dm
@@ -94,6 +94,7 @@
range = pick(2,2,2,3,3,3,4)
/obj/item/weapon/grenade/iedcasing/CheckParts()
+ ..()
var/obj/item/weapon/reagent_containers/food/drinks/cans/can = locate() in contents
if(can)
underlays += can
diff --git a/code/game/objects/items/weapons/pneumaticCannon.dm b/code/game/objects/items/weapons/pneumaticCannon.dm
index 1130ab3808b..88d3f202ac6 100644
--- a/code/game/objects/items/weapons/pneumaticCannon.dm
+++ b/code/game/objects/items/weapons/pneumaticCannon.dm
@@ -132,7 +132,7 @@
maxWeightClass = 7
gasPerThrow = 5
-/datum/table_recipe/improvised_pneumatic_cannon //Pretty easy to obtain but
+/datum/crafting_recipe/improvised_pneumatic_cannon //Pretty easy to obtain but
name = "Pneumatic Cannon"
result = /obj/item/weapon/pneumatic_cannon/ghetto
tools = list(/obj/item/weapon/weldingtool,
diff --git a/code/game/objects/items/weapons/signs.dm b/code/game/objects/items/weapons/signs.dm
index 0eba3b837d2..2155aeb69c6 100644
--- a/code/game/objects/items/weapons/signs.dm
+++ b/code/game/objects/items/weapons/signs.dm
@@ -35,7 +35,7 @@
sleep(8)
delayed = 0
-/datum/table_recipe/picket_sign
+/datum/crafting_recipe/picket_sign
name = "Picket Sign"
result = /obj/item/weapon/picket_sign
reqs = list(/obj/item/stack/rods = 1,
diff --git a/code/game/objects/items/weapons/stunbaton.dm b/code/game/objects/items/weapons/stunbaton.dm
index df131be786c..305befe2ecb 100644
--- a/code/game/objects/items/weapons/stunbaton.dm
+++ b/code/game/objects/items/weapons/stunbaton.dm
@@ -24,6 +24,7 @@
return
/obj/item/weapon/melee/baton/CheckParts()
+ ..()
bcell = locate(/obj/item/weapon/stock_parts/cell) in contents
update_icon()
@@ -205,4 +206,4 @@
else if(!bcell)
icon_state = "stunprod_nocell"
else
- icon_state = "stunprod"
\ No newline at end of file
+ icon_state = "stunprod"
diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm
index 9a2f3fcade3..3eb380d703f 100644
--- a/code/modules/clothing/shoes/miscellaneous.dm
+++ b/code/modules/clothing/shoes/miscellaneous.dm
@@ -184,7 +184,7 @@
desc = "Looks sneaky."
icon_state = "sheet-cloth"
-/datum/table_recipe/shoe_rags
+/datum/crafting_recipe/shoe_rags
name = "Shoe Rags"
result = /obj/item/shoe_silencer
diff --git a/code/modules/crafting/craft.dm b/code/modules/crafting/craft.dm
new file mode 100644
index 00000000000..6c47470c09b
--- /dev/null
+++ b/code/modules/crafting/craft.dm
@@ -0,0 +1,341 @@
+/datum/personal_crafting
+ var/busy
+ var/viewing_category = 1 //typical powergamer starting on the Weapons tab
+ var/list/categories = list(CAT_WEAPON,CAT_AMMO,CAT_ROBOT,CAT_FOOD,CAT_MISC,CAT_PRIMAL)
+ //var/datum/action/innate/crafting/button // Holdover from when crafting was still an action button. TODO: Remove this before I commit.
+
+
+
+
+
+/* This is what procs do:
+ get_environment - gets a list of things accessable for crafting by user
+ get_surroundings - takes a list of things and makes a list of key-types to values-amounts of said type in the list
+ check_contents - takes a recipe and a key-type list and checks if said recipe can be done with available stuff
+ check_tools - takes recipe, a key-type list, and a user and checks if there are enough tools to do the stuff, checks bugs one level deep
+ construct_item - takes a recipe and a user, call all the checking procs, calls do_after, checks all the things again, calls del_reqs, creates result, calls CheckParts of said result with argument being list returned by deel_reqs
+ del_reqs - takes recipe and a user, loops over the recipes reqs var and tries to find everything in the list make by get_environment and delete it/add to parts list, then returns the said list
+*/
+
+
+
+
+/datum/personal_crafting/proc/check_contents(datum/crafting_recipe/R, list/contents)
+ main_loop:
+ for(var/A in R.reqs)
+ var/needed_amount = R.reqs[A]
+ for(var/B in contents)
+ if(ispath(B, A))
+ if(contents[B] >= R.reqs[A])
+ continue main_loop
+ else
+ needed_amount -= contents[B]
+ if(needed_amount <= 0)
+ continue main_loop
+ else
+ continue
+ return 0
+ for(var/A in R.chem_catalists)
+ if(contents[A] < R.chem_catalists[A])
+ return 0
+ return 1
+
+/datum/personal_crafting/proc/get_environment(mob/user)
+ . = list()
+ . += user.r_hand
+ . += user.l_hand
+ if(!istype(user.loc, /turf))
+ return
+ var/list/L = block(get_step(user, SOUTHWEST), get_step(user, NORTHEAST))
+ for(var/A in L)
+ var/turf/T = A
+ if(T.Adjacent(user))
+ . += T.contents
+
+
+/datum/personal_crafting/proc/get_surroundings(mob/user)
+ . = list()
+ for(var/obj/item/I in get_environment(user))
+ if(istype(I, /obj/item/stack))
+ var/obj/item/stack/S = I
+ .[I.type] += S.amount
+ else
+ if(istype(I, /obj/item/weapon/reagent_containers))
+ var/obj/item/weapon/reagent_containers/RC = I
+ if(RC.flags & OPENCONTAINER)
+ for(var/datum/reagent/A in RC.reagents.reagent_list)
+ .[A.type] += A.volume
+ .[I.type] += 1
+
+/datum/personal_crafting/proc/check_tools(mob/user, datum/crafting_recipe/R, list/contents)
+ if(!R.tools.len)
+ return 1
+ var/list/possible_tools = list()
+ for(var/obj/item/I in user.contents)
+ if(istype(I, /obj/item/weapon/storage))
+ for(var/obj/item/SI in I.contents)
+ possible_tools += SI.type
+ possible_tools += I.type
+ possible_tools += contents
+
+ main_loop:
+ for(var/A in R.tools)
+ for(var/I in possible_tools)
+ if(ispath(I,A))
+ continue main_loop
+ return 0
+ return 1
+
+/datum/personal_crafting/proc/construct_item(mob/user, datum/crafting_recipe/R)
+ for(var/A in R.parts)
+ var/list/contents = get_surroundings(user)
+ var/send_feedback = 1
+ if(check_contents(R, contents))
+ if(check_tools(user, R, contents))
+ if(do_after(user, R.time, target = user))
+ contents = get_surroundings(user)
+ if(!check_contents(R, contents))
+ return ", missing component."
+ if(!check_tools(user, R, contents))
+ return ", missing tool."
+ var/list/parts = del_reqs(R, user)
+ var/atom/movable/I = new R.result (get_turf(user.loc))
+ I.CheckParts(parts, R)
+ if(send_feedback)
+ feedback_add_details("object_crafted","[I.type]")
+ return 0
+ return "."
+ return ", missing tool."
+ return ", missing component."
+
+
+/*Del reqs works like this:
+ Loop over reqs var of the recipe
+ Set var amt to the value current cycle req is pointing to, its amount of type we need to delete
+ Get var/surroundings list of things accessable to crafting by get_environment()
+ Check the type of the current cycle req
+ If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isnt remove thing from surroundings
+ If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list
+ If there isnt enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching
+ While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one
+ If its stack check if it has enough amount
+ If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack
+ If no put all of the stack in the deletion list, substract its amount from amt and keep searching
+ While doing above stuff check deletion list if it already has such stack type, if yes try to merge them instead of adding new one
+ If its anything else just locate() in in the list in a while loop, each find --s the amt var and puts the found stuff in deletion loop
+ Then do a loop over parts var of the recipe
+ Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return
+ After its done loop over deletion list and delete all the shit that wasnt taken by parts loop
+ del_reqs return the list of parts resulting object will recieve as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already
+*/
+
+/datum/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, mob/user)
+ var/list/surroundings
+ var/list/Deletion = list()
+ . = list()
+ var/data
+ var/amt
+ main_loop:
+ for(var/A in R.reqs)
+ amt = R.reqs[A]
+ surroundings = get_environment(user)
+ surroundings -= Deletion
+ if(ispath(A, /datum/reagent))
+ var/datum/reagent/RG = new A
+ var/datum/reagent/RGNT
+ while(amt > 0)
+ var/obj/item/weapon/reagent_containers/RC = locate() in surroundings
+ RG = RC.reagents.get_reagent(A)
+ if(RG)
+ if(!locate(RG.type) in Deletion)
+ Deletion += new RG.type()
+ if(RG.volume > amt)
+ RG.volume -= amt
+ data = RG.data
+ RC.reagents.conditional_update(RC)
+ RG = locate(RG.type) in Deletion
+ RG.volume = amt
+ RG.data += data
+ continue main_loop
+ else
+ surroundings -= RC
+ amt -= RG.volume
+ RC.reagents.reagent_list -= RG
+ RC.reagents.conditional_update(RC)
+ RGNT = locate(RG.type) in Deletion
+ RGNT.volume += RG.volume
+ RGNT.data += RG.data
+ qdel(RG)
+ else
+ surroundings -= RC
+ else if(ispath(A, /obj/item/stack))
+ var/obj/item/stack/S
+ var/obj/item/stack/SD
+ while(amt > 0)
+ S = locate(A) in surroundings
+ if(S.amount >= amt)
+ if(!locate(S.type) in Deletion)
+ SD = new S.type()
+ Deletion += SD
+ S.use(amt)
+ SD = locate(S.type) in Deletion
+ SD.amount += amt
+ continue main_loop
+ else
+ amt -= S.amount
+ if(!locate(S.type) in Deletion)
+ Deletion += S
+ else
+ data = S.amount
+ S = locate(S.type) in Deletion
+ S.amount += data
+ surroundings -= S
+ else
+ var/atom/movable/I
+ while(amt > 0)
+ I = locate(A) in surroundings
+ Deletion += I
+ surroundings -= I
+ amt--
+ var/list/partlist = list(R.parts.len)
+ for(var/M in R.parts)
+ partlist[M] = R.parts[M]
+ for(var/A in R.parts)
+ if(istype(A, /datum/reagent))
+ var/datum/reagent/RG = locate(A) in Deletion
+ if(RG.volume > partlist[A])
+ RG.volume = partlist[A]
+ . += RG
+ Deletion -= RG
+ continue
+ else if(istype(A, /obj/item/stack))
+ var/obj/item/stack/ST = locate(A) in Deletion
+ if(ST.amount > partlist[A])
+ ST.amount = partlist[A]
+ . += ST
+ Deletion -= ST
+ continue
+ else
+ while(partlist[A] > 0)
+ var/atom/movable/AM = locate(A) in Deletion
+ . += AM
+ Deletion -= AM
+ partlist[A] -= 1
+ while(Deletion.len)
+ var/DL = Deletion[Deletion.len]
+ Deletion.Cut(Deletion.len)
+ qdel(DL)
+
+/datum/personal_crafting/proc/craft(mob/user)
+ if(user.incapacitated() || user.lying || istype(user.loc, /obj/mecha))
+ return
+ var/list/surroundings = get_surroundings(user)
+ var/dat = "
Crafting menu
"
+ if(busy)
+ dat += ""
+ dat += "Crafting in progress...
"
+ else
+ dat += "<--"
+ dat += " [categories[prev_cat()]] |"
+ dat += " [categories[viewing_category]] "
+ dat += "| [categories[next_cat()]] "
+ dat += "-->
"
+
+ dat += ""
+
+ //Filter the recipes we can craft to the top
+ var/list/can_craft = list()
+ var/list/cant_craft = list()
+ for(var/datum/crafting_recipe/R in crafting_recipes)
+ if(R.category != categories[viewing_category])
+ continue
+ if(check_contents(R, surroundings))
+ can_craft += R
+ else
+ cant_craft += R
+
+ for(var/datum/crafting_recipe/R in can_craft)
+ dat += build_recipe_text(R, surroundings)
+ for(var/datum/crafting_recipe/R in cant_craft)
+ dat += build_recipe_text(R, surroundings)
+
+
+ dat += "
"
+
+ var/datum/browser/popup = new(user, "crafting", "Crafting", 500, 500)
+ popup.set_content(dat)
+ popup.open()
+ return
+
+/datum/personal_crafting/Topic(href, href_list)
+ if(usr.stat || usr.lying)
+ return
+ if(href_list["make"])
+ var/datum/crafting_recipe/TR = locate(href_list["make"])
+ busy = 1
+ craft(usr)
+ var/fail_msg = construct_item(usr, TR)
+ if(!fail_msg)
+ usr << "[TR.name] constructed."
+ else
+ usr << "Construction failed[fail_msg]"
+ busy = 0
+ craft(usr)
+ if(href_list["forwardCat"])
+ viewing_category = next_cat()
+ usr << "Category is now [categories[viewing_category]]."
+ craft(usr)
+ if(href_list["backwardCat"])
+ viewing_category = prev_cat()
+ usr << "Category is now [categories[viewing_category]]."
+ craft(usr)
+
+//Next works nicely with modular arithmetic
+/datum/personal_crafting/proc/next_cat()
+ . = viewing_category % categories.len + 1
+
+//Previous can go fuck itself
+/datum/personal_crafting/proc/prev_cat()
+ if(viewing_category == categories.len)
+ . = viewing_category-1
+ else
+ . = viewing_category % categories.len - 1
+ if(. <= 0)
+ . = categories.len
+
+/datum/personal_crafting/proc/build_recipe_text(datum/crafting_recipe/R, list/contents)
+ . = ""
+ var/name_text = ""
+ var/req_text = ""
+ var/tool_text = ""
+ var/catalist_text = ""
+ if(check_contents(R, contents))
+ name_text ="[R.name]"
+
+ else
+ name_text = "[R.name]"
+
+ if(name_text)
+ for(var/A in R.reqs)
+ if(ispath(A, /obj))
+ var/obj/O = A
+ req_text += " [R.reqs[A]] [initial(O.name)]"
+ else if(ispath(A, /datum/reagent))
+ var/datum/reagent/RE = A
+ req_text += " [R.reqs[A]] [initial(RE.name)]"
+
+ if(R.chem_catalists.len)
+ catalist_text += ", Catalysts:"
+ for(var/C in R.chem_catalists)
+ if(ispath(C, /datum/reagent))
+ var/datum/reagent/RE = C
+ catalist_text += " [R.chem_catalists[C]] [initial(RE.name)]"
+
+ if(R.tools.len)
+ tool_text += ", Tools:"
+ for(var/O in R.tools)
+ if(ispath(O, /obj))
+ var/obj/T = O
+ tool_text += " [R.tools[O]] [initial(T.name)]"
+
+ . = "[name_text][req_text][tool_text][catalist_text]
"
diff --git a/code/modules/crafting/recipes.dm b/code/modules/crafting/recipes.dm
index d8586b6c0d8..60d830a1c89 100644
--- a/code/modules/crafting/recipes.dm
+++ b/code/modules/crafting/recipes.dm
@@ -1,4 +1,4 @@
-/datum/table_recipe
+/datum/crafting_recipe
var/name = "" //in-game display name
var/reqs[] = list() //type paths of items consumed associated with how many are needed
var/result //type path of item resulting from this craft
@@ -7,14 +7,15 @@
var/parts[] = list() //type paths of items that will be placed in the result
var/chem_catalists[] = list() //like tools but for reagents
var/fruit[] = list() //grown products required by the recipe
+ var/category = CAT_MISC // Recipe category
-/datum/table_recipe/proc/AdjustChems(var/obj/resultobj as obj)
+/datum/crafting_recipe/proc/AdjustChems(var/obj/resultobj as obj)
//This proc is to replace the make_food proc of recipes from microwaves and such that are being converted to table crafting recipes.
//Use it to handle the removal of reagents after the food has been created (like removing toxins from a salad made with ambrosia)
//If a recipe does not require it's chems adjusted, don't bother declaring this for the recipe, as it will call this placeholder
return
-/datum/table_recipe/IED
+/datum/crafting_recipe/IED
name = "IED"
result = /obj/item/weapon/grenade/iedcasing/filled
reqs = list(/datum/reagent/fuel = 50,
@@ -23,8 +24,9 @@
/obj/item/weapon/reagent_containers/food/drinks/cans = 1)
parts = list(/obj/item/weapon/reagent_containers/food/drinks/cans = 1)
time = 80
+ category = CAT_WEAPON
-/datum/table_recipe/stunprod
+/datum/crafting_recipe/stunprod
name = "Stunprod"
result = /obj/item/weapon/melee/baton/cattleprod
reqs = list(/obj/item/weapon/restraints/handcuffs/cable = 1,
@@ -33,8 +35,9 @@
/obj/item/weapon/stock_parts/cell = 1)
time = 80
parts = list(/obj/item/weapon/stock_parts/cell = 1)
+ category = CAT_WEAPON
-/datum/table_recipe/ed209
+/datum/crafting_recipe/ed209
name = "ED209"
result = /mob/living/simple_animal/bot/ed209
reqs = list(/obj/item/robot_parts/robot_suit = 1,
@@ -50,8 +53,9 @@
/obj/item/robot_parts/r_arm = 1)
tools = list(/obj/item/weapon/weldingtool, /obj/item/weapon/screwdriver)
time = 120
+ category = CAT_ROBOT
-/datum/table_recipe/secbot
+/datum/crafting_recipe/secbot
name = "Secbot"
result = /mob/living/simple_animal/bot/secbot
reqs = list(/obj/item/device/assembly/signaler = 1,
@@ -61,16 +65,18 @@
/obj/item/robot_parts/r_arm = 1)
tools = list(/obj/item/weapon/weldingtool)
time = 120
+ category = CAT_ROBOT
-/datum/table_recipe/cleanbot
+/datum/crafting_recipe/cleanbot
name = "Cleanbot"
result = /mob/living/simple_animal/bot/cleanbot
reqs = list(/obj/item/weapon/reagent_containers/glass/bucket = 1,
/obj/item/device/assembly/prox_sensor = 1,
/obj/item/robot_parts/r_arm = 1)
time = 80
+ category = CAT_ROBOT
-/datum/table_recipe/floorbot
+/datum/crafting_recipe/floorbot
name = "Floorbot"
result = /mob/living/simple_animal/bot/floorbot
reqs = list(/obj/item/weapon/storage/toolbox/mechanical = 1,
@@ -78,8 +84,9 @@
/obj/item/device/assembly/prox_sensor = 1,
/obj/item/robot_parts/r_arm = 1)
time = 80
+ category = CAT_ROBOT
-/datum/table_recipe/medbot
+/datum/crafting_recipe/medbot
name = "Medbot"
result = /mob/living/simple_animal/bot/medbot
reqs = list(/obj/item/device/healthanalyzer = 1,
@@ -87,8 +94,9 @@
/obj/item/device/assembly/prox_sensor = 1,
/obj/item/robot_parts/r_arm = 1)
time = 80
+ category = CAT_ROBOT
-/datum/table_recipe/flamethrower
+/datum/crafting_recipe/flamethrower
name = "Flamethrower"
result = /obj/item/weapon/flamethrower
reqs = list(/obj/item/weapon/weldingtool = 1,
@@ -96,8 +104,9 @@
/obj/item/stack/rods = 2)
tools = list(/obj/item/weapon/screwdriver)
time = 20
+ category = CAT_WEAPON
-/datum/table_recipe/meteorshot
+/datum/crafting_recipe/meteorshot
name = "Meteorshot Shell"
result = /obj/item/ammo_casing/shotgun/meteorshot
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
@@ -105,8 +114,9 @@
/obj/item/weapon/stock_parts/manipulator = 2)
tools = list(/obj/item/weapon/screwdriver)
time = 5
+ category = CAT_AMMO
-/datum/table_recipe/pulseslug
+/datum/crafting_recipe/pulseslug
name = "Pulse Slug Shell"
result = /obj/item/ammo_casing/shotgun/pulseslug
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
@@ -114,16 +124,18 @@
/obj/item/weapon/stock_parts/micro_laser/ultra = 1)
tools = list(/obj/item/weapon/screwdriver)
time = 5
+ category = CAT_AMMO
-/datum/table_recipe/dragonsbreath
+/datum/crafting_recipe/dragonsbreath
name = "Dragonsbreath Shell"
result = /obj/item/ammo_casing/shotgun/incendiary/dragonsbreath
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
/datum/reagent/phosphorus = 5,)
tools = list(/obj/item/weapon/screwdriver)
time = 5
+ category = CAT_AMMO
-/datum/table_recipe/frag12
+/datum/crafting_recipe/frag12
name = "FRAG-12 Shell"
result = /obj/item/ammo_casing/shotgun/frag12
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
@@ -132,8 +144,9 @@
/datum/reagent/facid = 5,)
tools = list(/obj/item/weapon/screwdriver)
time = 5
+ category = CAT_AMMO
-/datum/table_recipe/ionslug
+/datum/crafting_recipe/ionslug
name = "Ion Scatter Shell"
result = /obj/item/ammo_casing/shotgun/ion
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
@@ -141,8 +154,9 @@
/obj/item/weapon/stock_parts/subspace/crystal = 1)
tools = list(/obj/item/weapon/screwdriver)
time = 5
+ category = CAT_AMMO
-/datum/table_recipe/improvisedslug
+/datum/crafting_recipe/improvisedslug
name = "Improvised Shotgun Shell"
result = /obj/item/ammo_casing/shotgun/improvised
reqs = list(/obj/item/weapon/grenade/chem_grenade = 1,
@@ -151,16 +165,18 @@
/datum/reagent/fuel = 10)
tools = list(/obj/item/weapon/screwdriver)
time = 5
+ category = CAT_AMMO
-/datum/table_recipe/improvisedslugoverload
+/datum/crafting_recipe/improvisedslugoverload
name = "Overload Improvised Shell"
result = /obj/item/ammo_casing/shotgun/improvised/overload
reqs = list(/obj/item/ammo_casing/shotgun/improvised = 1,
/datum/reagent/blackpowder = 5)
tools = list(/obj/item/weapon/screwdriver)
time = 5
+ category = CAT_AMMO
-/datum/table_recipe/laserslug
+/datum/crafting_recipe/laserslug
name = "Laser Slug Shell"
result = /obj/item/ammo_casing/shotgun/laserslug
reqs = list(/obj/item/ammo_casing/shotgun/techshell = 1,
@@ -168,8 +184,9 @@
/obj/item/weapon/stock_parts/micro_laser/high = 1)
tools = list(/obj/item/weapon/screwdriver)
time = 5
+ category = CAT_AMMO
-/datum/table_recipe/ishotgun
+/datum/crafting_recipe/ishotgun
name = "Improvised Shotgun"
result = /obj/item/weapon/gun/projectile/revolver/doublebarrel/improvised
reqs = list(/obj/item/weaponcrafting/receiver = 1,
@@ -178,8 +195,9 @@
/obj/item/stack/packageWrap = 5,)
tools = list(/obj/item/weapon/screwdriver)
time = 200
+ category = CAT_WEAPON
-/datum/table_recipe/spooky_camera
+/datum/crafting_recipe/spooky_camera
name = "Camera Obscura"
result = /obj/item/device/camera/spooky
time = 15
@@ -187,29 +205,31 @@
/datum/reagent/holywater = 10)
parts = list(/obj/item/device/camera = 1)
-/datum/table_recipe/notreallysoap
+/datum/crafting_recipe/notreallysoap
name = "Homemade Soap"
result = /obj/item/weapon/soap/ducttape
time = 100
reqs = list(/obj/item/stack/tape_roll = 1,
/datum/reagent/liquidgibs = 10)
-/datum/table_recipe/garrote
+/datum/crafting_recipe/garrote
name = "Makeshift Garrote"
result = /obj/item/weapon/twohanded/garrote/improvised
time = 15
reqs = list(/obj/item/stack/sheet/wood = 1,
/obj/item/stack/cable_coil = 5)
tools = list(/obj/item/weapon/kitchen/knife) // Gotta carve the wood into handles
+ category = CAT_WEAPON
-/datum/table_recipe/makeshift_bolt
+/datum/crafting_recipe/makeshift_bolt
name = "Makeshift Bolt"
result = /obj/item/weapon/arrow/rod
time = 15
reqs = list(/obj/item/stack/rods = 1)
tools = list(/obj/item/weapon/weldingtool)
+ category = CAT_AMMO
-/datum/table_recipe/crossbow
+/datum/crafting_recipe/crossbow
name = "Powered Crossbow"
result = /obj/item/weapon/gun/throw/crossbow
time = 300
@@ -219,10 +239,11 @@
/obj/item/stack/sheet/wood = 5)
tools = list(/obj/item/weapon/weldingtool,
/obj/item/weapon/screwdriver)
+ category = CAT_WEAPON
-/datum/table_recipe/glove_balloon
+/datum/crafting_recipe/glove_balloon
name = "Latex Glove Balloon"
result = /obj/item/latexballon
time = 15
reqs = list(/obj/item/clothing/gloves/color/latex = 1,
- /obj/item/stack/cable_coil = 5)
\ No newline at end of file
+ /obj/item/stack/cable_coil = 5)
diff --git a/code/modules/crafting/table.dm b/code/modules/crafting/table.dm
deleted file mode 100644
index 19ea37c3866..00000000000
--- a/code/modules/crafting/table.dm
+++ /dev/null
@@ -1,225 +0,0 @@
-#define TABLECRAFT_MAX_ITEMS 30
-
-/obj/structure/table
- var/list/table_contents = list()
-
-/obj/structure/table/MouseDrop(atom/over)
- if(over != usr)
- return
- interact(usr)
-
-/obj/structure/table/proc/check_contents(datum/table_recipe/R)
- check_table()
- main_loop:
- if(R.fruit)
- for(var/A in R.fruit)
- for(var/B in table_contents)
- if(B == A)
- if(table_contents[B] >= R.fruit[A])
- continue main_loop
- return 0
- for(var/A in R.reqs)
- for(var/B in table_contents)
- if(ispath(B, A))
- if(table_contents[B] >= R.reqs[A])
- continue main_loop
- return 0
- for(var/A in R.chem_catalists)
- if(table_contents[A] < R.chem_catalists[A])
- return 0
- return 1
-
-/obj/structure/table/proc/check_table()
- table_contents = list()
- for(var/obj/item/I in loc)
- if(istype(I, /obj/item/stack))
- var/obj/item/stack/S = I
- table_contents[I.type] += S.amount
- else if(istype(I, /obj/item/weapon/reagent_containers/food/snacks/grown))
- var/obj/item/weapon/reagent_containers/food/snacks/grown/G = I
- if(G.seed && G.seed.kitchen_tag)
- table_contents[G.seed.kitchen_tag] += 1
- else
- if(istype(I, /obj/item/weapon/reagent_containers))
- var/obj/item/weapon/reagent_containers/RC = I
- if(RC.flags & OPENCONTAINER)
- for(var/datum/reagent/A in RC.reagents.reagent_list)
- table_contents[A.type] += A.volume
- table_contents[I.type] += 1
-
-/obj/structure/table/proc/check_tools(mob/user, datum/table_recipe/R)
- if(!R.tools.len)
- return 1
- var/list/possible_tools = list()
- for(var/obj/item/I in user.contents)
- if(istype(I, /obj/item/weapon/storage))
- for(var/obj/item/SI in I.contents)
- possible_tools += SI.type
- else
- possible_tools += I.type
- possible_tools += table_contents
- var/i = R.tools.len
- var/I
- for(var/A in R.tools)
- I = possible_tools.Find(A)
- if(I)
- possible_tools.Cut(I, I+1)
- i--
- else
- break
- return !i
-
-/obj/structure/table/proc/construct_item(mob/user, datum/table_recipe/R)
- check_table()
- if(check_contents(R) && check_tools(user, R))
- if(do_after(user, R.time, target = src))
- if(!check_contents(R) || !check_tools(user, R))
- return 0
- var/atom/movable/I = new R.result (loc)
- var/list/parts = del_reqs(R, I)
- for(var/A in parts)
- if(istype(A, /obj/item))
- var/atom/movable/B = A
- B.loc = I
- else
- if(!I.reagents)
- I.reagents = new /datum/reagents()
- I.reagents.reagent_list.Add(A)
- I.CheckParts()
- R.AdjustChems(I)
- return 1
- return 0
-
-/obj/structure/table/proc/del_reqs(datum/table_recipe/R, atom/movable/resultobject)
- var/list/Deletion = list()
- var/amt
- var/reagenttransfer = 0
- if(istype(resultobject,/obj/item/weapon/reagent_containers))
- reagenttransfer = 1
- if(R.fruit)
- for(var/A in R.fruit)
- amt = R.fruit[A]
- fruit_loop: //ha
- for(var/obj/item/weapon/reagent_containers/food/snacks/grown/G in loc)
- if(G.seed && G.seed.kitchen_tag && (G.seed.kitchen_tag == A))
- amt--
- G.loc = null //remove it from the table loc so that we don't locate the same fruit every time
- if(reagenttransfer)
- G.reagents.trans_to(resultobject, G.reagents.total_volume)
- qdel(G)
- if(amt <= 0)
- break fruit_loop
- for(var/A in R.reqs)
- amt = R.reqs[A]
- if(ispath(A, /obj/item/stack))
- var/obj/item/stack/S
- stack_loop:
- for(var/B in table_contents)
- if(ispath(B, A))
- while(amt > 0)
- S = locate(B) in loc
- if(S.amount >= amt)
- S.use(amt)
- break stack_loop
- else
- amt -= S.amount
- qdel(S)
- else if(ispath(A, /obj/item))
- var/obj/item/I
- item_loop:
- for(var/B in table_contents)
- if(ispath(B, A))
- while(amt > 0)
- I = locate(B) in loc
- Deletion.Add(I)
- I.loc = null //remove it from the table loc so that we don't locate the same item every time (will be relocated inside the crafted item in construct_item())
- amt--
- if(reagenttransfer && istype(I,/obj/item/weapon/reagent_containers))
- var/obj/item/weapon/reagent_containers/RC = I
- RC.reagents.trans_to(resultobject, RC.reagents.total_volume)
- break item_loop
- else
- var/datum/reagent/RG = new A
- reagent_loop:
- for(var/B in table_contents)
- if(ispath(B, /obj/item/weapon/reagent_containers))
- var/obj/item/RC = locate(B) in loc
- if(RC.reagents.has_reagent(RG.id, amt))
- if(reagenttransfer)
- RC.reagents.trans_id_to(resultobject,RG.id, amt)
- else
- RC.reagents.remove_reagent(RG.id, amt)
- RG.volume = amt
- Deletion.Add(RG)
- break reagent_loop
- else if(RC.reagents.has_reagent(RG.id))
- Deletion.Add(RG)
- RG.volume += RC.reagents.get_reagent_amount(RG.id)
- amt -= RC.reagents.get_reagent_amount(RG.id)
- if(reagenttransfer)
- RC.reagents.trans_id_to(resultobject,RG.id, RG.volume)
- else
- RC.reagents.del_reagent(RG.id)
-
- var/list/partlist = list(R.parts.len)
- for(var/M in R.parts)
- partlist[M] = R.parts[M]
- deletion_loop:
- for(var/B in Deletion)
- for(var/A in R.parts)
- if(istype(B, A))
- if(partlist[A] > 0) //do we still need a part like that?
- partlist[A] -= 1
- continue deletion_loop
- Deletion.Remove(B)
- qdel(B)
-
- return Deletion
-
-/obj/structure/table/interact(mob/user)
- if(user.stat || user.lying || !Adjacent(user))
- return
- check_table()
- if(!table_contents.len)
- return
- user.face_atom(src)
- var/dat = "Crafting menu
"
- dat += ""
- if(busy)
- dat += "Crafting in progress...
"
- else
- for(var/datum/table_recipe/R in table_recipes)
- if(check_contents(R))
- dat += "[R.name]
"
- dat += ""
-
- var/datum/browser/popup = new(user, "table", "Table", 300, 300)
- popup.set_content(dat)
- popup.open()
- return
-
-/obj/structure/table/Topic(href, href_list)
- if(usr.stat || !Adjacent(usr) || usr.lying)
- return
- if(href_list["make"])
- if(!check_table_space())
- to_chat(usr, "The table is too crowded.")
- return
- var/datum/table_recipe/TR = locate(href_list["make"])
- busy = 1
- interact(usr)
- if(construct_item(usr, TR))
- to_chat(usr, "[TR.name] constructed.")
- else
- to_chat(usr, "Construction failed.")
- busy = 0
- interact(usr)
-
-/obj/structure/table/proc/check_table_space()
- var/Item_amount = 0
- for(var/obj/item/I in loc)
- Item_amount++
- if(Item_amount <= TABLECRAFT_MAX_ITEMS) //is the table crowded?
- return 1
-
- #undef TABLECRAFT_MAX_ITEMS
\ No newline at end of file
diff --git a/code/modules/food/recipes_table.dm b/code/modules/food/recipes_table.dm
index 0c9f72dd6d5..005be6c1f7e 100644
--- a/code/modules/food/recipes_table.dm
+++ b/code/modules/food/recipes_table.dm
@@ -1,5 +1,5 @@
/* Example for reference when defining recipes
-/datum/table_recipe/food
+/datum/crafting_recipe/food
name = "" //in-game display name
reqs[] = list() //type paths of items/reagents consumed associated with how many are needed (equivalent to var/list/items and var/list/reagents combined)
result //type path of item resulting from this craft
@@ -9,7 +9,7 @@
fruit[] = list() //grown products required by the recipe
*/
-/datum/table_recipe/sandwich
+/datum/crafting_recipe/sandwich
name = "Sandwich"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/meatsteak = 1,
@@ -17,55 +17,61 @@
/obj/item/weapon/reagent_containers/food/snacks/cheesewedge = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sandwich
+ category = CAT_FOOD
-/datum/table_recipe/slimesandwich
+/datum/crafting_recipe/slimesandwich
name = "Slime Jelly Sandwich"
reqs = list(
/datum/reagent/slimejelly = 5,
/obj/item/weapon/reagent_containers/food/snacks/breadslice = 2,
)
result = /obj/item/weapon/reagent_containers/food/snacks/jellysandwich/slime
+ category = CAT_FOOD
-/datum/table_recipe/cherrysandwich
+/datum/crafting_recipe/cherrysandwich
name = "Cherry Jelly Sandwich"
reqs = list(
/datum/reagent/cherryjelly = 5,
/obj/item/weapon/reagent_containers/food/snacks/breadslice = 2,
)
result = /obj/item/weapon/reagent_containers/food/snacks/jellysandwich/cherry
+ category = CAT_FOOD
-/datum/table_recipe/slimeburger
+/datum/crafting_recipe/slimeburger
name = "Slime Jelly Burger"
reqs = list(
/datum/reagent/slimejelly = 5,
/obj/item/weapon/reagent_containers/food/snacks/bun = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/jellyburger/slime
+ category = CAT_FOOD
-/datum/table_recipe/jellyburger
+/datum/crafting_recipe/jellyburger
name = "Cherry Jelly Burger"
reqs = list(
/datum/reagent/cherryjelly = 5,
/obj/item/weapon/reagent_containers/food/snacks/bun = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/jellyburger/cherry
+ category = CAT_FOOD
-/datum/table_recipe/herbsalad
+/* Temporarily disabled until we can find a workaround for this fruit shit.
+/datum/crafting_recipe/herbsalad
name = "herb salad"
fruit = list("ambrosia" = 3, "apple" = 1)
result = /obj/item/weapon/reagent_containers/food/snacks/herbsalad
-/datum/table_recipe/herbsalad/AdjustChems(var/obj/resultobj as obj)
+/datum/crafting_recipe/herbsalad/AdjustChems(var/obj/resultobj as obj)
if(istype(resultobj, /obj/item/weapon/reagent_containers))
var/obj/item/weapon/reagent_containers/RC = resultobj
RC.reagents.del_reagent("toxin")
-/datum/table_recipe/aesirsalad
+/datum/crafting_recipe/aesirsalad
name = "Aesir salad"
fruit = list("ambrosiadeus" = 3, "goldapple" = 1)
result = /obj/item/weapon/reagent_containers/food/snacks/aesirsalad
-/datum/table_recipe/validsalad
+/datum/crafting_recipe/validsalad
name = "valid salad"
fruit = list("ambrosia" = 3, "potato" = 1)
reqs = list(
@@ -73,20 +79,12 @@
)
result = /obj/item/weapon/reagent_containers/food/snacks/validsalad
-/datum/table_recipe/validsalad/AdjustChems(var/obj/resultobj as obj)
+/datum/crafting_recipe/validsalad/AdjustChems(var/obj/resultobj as obj)
if(istype(resultobj, /obj/item/weapon/reagent_containers))
var/obj/item/weapon/reagent_containers/RC = resultobj
RC.reagents.del_reagent("toxin")
-/datum/table_recipe/notasandwich
- name = "not-a-sandwich"
- reqs = list(
- /obj/item/weapon/reagent_containers/food/snacks/breadslice = 2,
- /obj/item/clothing/mask/fakemoustache = 1,
- )
- result = /obj/item/weapon/reagent_containers/food/snacks/notasandwich
-
-/datum/table_recipe/wrap
+/datum/crafting_recipe/wrap
name = "egg wrap"
fruit = list("cabbage" = 1)
reqs = list(
@@ -94,75 +92,95 @@
/obj/item/weapon/reagent_containers/food/snacks/friedegg = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/wrap
+*/
-/datum/table_recipe/sushi_Ebi
+/datum/crafting_recipe/notasandwich
+ name = "not-a-sandwich"
+ reqs = list(
+ /obj/item/weapon/reagent_containers/food/snacks/breadslice = 2,
+ /obj/item/clothing/mask/fakemoustache = 1,
+ )
+ result = /obj/item/weapon/reagent_containers/food/snacks/notasandwich
+ category = CAT_FOOD
+
+
+/datum/crafting_recipe/sushi_Ebi
name = "Ebi Sushi"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/weapon/reagent_containers/food/snacks/boiled_shrimp = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Ebi
+ category = CAT_FOOD
-/datum/table_recipe/sushi_Ikura
+/datum/crafting_recipe/sushi_Ikura
name = "Ikura Sushi"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/fish_eggs/salmon = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Ikura
+ category = CAT_FOOD
-/datum/table_recipe/sushi_Inari
+/datum/crafting_recipe/sushi_Inari
name = "Inari Sushi"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/weapon/reagent_containers/food/snacks/fried_tofu = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Inari
+ category = CAT_FOOD
-/datum/table_recipe/sushi_Sake
+/datum/crafting_recipe/sushi_Sake
name = "Sake Sushi"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/weapon/reagent_containers/food/snacks/salmonmeat = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Sake
+ category = CAT_FOOD
-/datum/table_recipe/sushi_SmokedSalmon
+/datum/crafting_recipe/sushi_SmokedSalmon
name = "Smoked Salmon Sushi"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/weapon/reagent_containers/food/snacks/salmonsteak = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sushi_SmokedSalmon
+ category = CAT_FOOD
-/datum/table_recipe/sushi_Masago
+/datum/crafting_recipe/sushi_Masago
name = "Masago Sushi"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/fish_eggs/goldfish = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Masago
+ category = CAT_FOOD
-/datum/table_recipe/sushi_Tobiko
+/datum/crafting_recipe/sushi_Tobiko
name = "Tobiko Sushi"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/fish_eggs/shark = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Tobiko
+ category = CAT_FOOD
-/datum/table_recipe/sushi_TobikoEgg
+/datum/crafting_recipe/sushi_TobikoEgg
name = "Tobiko and Egg Sushi"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/sushi_Tobiko = 1,
/obj/item/weapon/reagent_containers/food/snacks/egg = 1,
)
result = /obj/item/weapon/reagent_containers/food/snacks/sushi_TobikoEgg
+ category = CAT_FOOD
-/datum/table_recipe/sushi_Tai
+/datum/crafting_recipe/sushi_Tai
name = "Tai Sushi"
reqs = list(
/obj/item/weapon/reagent_containers/food/snacks/boiledrice = 1,
/obj/item/weapon/reagent_containers/food/snacks/catfishmeat = 1,
)
- result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Tai
\ No newline at end of file
+ result = /obj/item/weapon/reagent_containers/food/snacks/sushi_Tai
+ category = CAT_FOOD
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 54e378678b9..33ad123c34d 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -39,6 +39,8 @@
martial_art = default_martial_art
+ handcrafting = new()
+
var/mob/M = src
faction |= "\ref[M]" //what
@@ -53,6 +55,9 @@
UpdateAppearance()
+/mob/living/carbon/human/OpenCraftingMenu()
+ handcrafting.craft(src)
+
/mob/living/carbon/human/prepare_data_huds()
//Update med hud images...
..()
diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm
index d4f000ad8fe..a74409a9b44 100644
--- a/code/modules/mob/living/carbon/human/human_defines.dm
+++ b/code/modules/mob/living/carbon/human/human_defines.dm
@@ -53,6 +53,8 @@ var/global/default_martial_art = new/datum/martial_art
var/speech_problem_flag = 0
+ var/datum/personal_crafting/handcrafting
+
var/datum/martial_art/martial_art = null
var/special_voice = "" // For changing our voice. Used by a symptom.
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 4e2007872a2..44d51324576 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -3,6 +3,9 @@
..()
return QDEL_HINT_HARDDEL_NOW
+/mob/living/proc/OpenCraftingMenu()
+ return
+
/mob/living/Stat()
. = ..()
if(. && get_rig_stats)
diff --git a/code/modules/paperwork/photography.dm b/code/modules/paperwork/photography.dm
index 00ce925fae0..689799680ec 100644
--- a/code/modules/paperwork/photography.dm
+++ b/code/modules/paperwork/photography.dm
@@ -154,6 +154,7 @@
/obj/item/device/camera/spooky/CheckParts()
+ ..()
var/obj/item/device/camera/C = locate(/obj/item/device/camera) in contents
if(C)
pictures_max = C.pictures_max
diff --git a/code/modules/pda/PDA.dm b/code/modules/pda/PDA.dm
index 50e9146dcb6..4dfd8575a22 100755
--- a/code/modules/pda/PDA.dm
+++ b/code/modules/pda/PDA.dm
@@ -301,8 +301,6 @@ var/global/list/obj/item/device/pda/PDAs = list()
to_chat(usr, "You cannot do this while restrained.")
/obj/item/device/pda/AltClick()
- ..()
-
if(issilicon(usr))
return
diff --git a/code/modules/reagents/Chemistry-Holder.dm b/code/modules/reagents/Chemistry-Holder.dm
index 88a7e1518a2..ab97744e8bc 100644
--- a/code/modules/reagents/Chemistry-Holder.dm
+++ b/code/modules/reagents/Chemistry-Holder.dm
@@ -520,6 +520,9 @@ var/const/INGEST = 2
return res
+/datum/reagents/proc/get_reagent(type)
+ . = locate(type) in reagent_list
+
/datum/reagents/proc/remove_all_type(var/reagent_type, var/amount, var/strict = 0, var/safety = 1) // Removes all reagent of X type. @strict set to 1 determines whether the childs of the type are included.
if(!isnum(amount)) return 1
@@ -608,4 +611,4 @@ atom/proc/create_reagents(var/max_vol)
reagent_list.Cut()
reagent_list = null
if(my_atom && my_atom.reagents == src)
- my_atom.reagents = null
\ No newline at end of file
+ my_atom.reagents = null
diff --git a/icons/mob/screen_midnight.dmi b/icons/mob/screen_midnight.dmi
index 25b3d7355d9..2dab86ef7f9 100644
Binary files a/icons/mob/screen_midnight.dmi and b/icons/mob/screen_midnight.dmi differ
diff --git a/icons/mob/screen_operative.dmi b/icons/mob/screen_operative.dmi
index d14e354d7f4..8d90aa7c3b3 100644
Binary files a/icons/mob/screen_operative.dmi and b/icons/mob/screen_operative.dmi differ
diff --git a/icons/mob/screen_plasmafire.dmi b/icons/mob/screen_plasmafire.dmi
index 9e22298fc27..cca826d272c 100644
Binary files a/icons/mob/screen_plasmafire.dmi and b/icons/mob/screen_plasmafire.dmi differ
diff --git a/icons/mob/screen_retro.dmi b/icons/mob/screen_retro.dmi
index ec36561ea0c..77aefd6a16b 100644
Binary files a/icons/mob/screen_retro.dmi and b/icons/mob/screen_retro.dmi differ
diff --git a/icons/mob/screen_slimecore.dmi b/icons/mob/screen_slimecore.dmi
index 0e412d41c9c..3af866db6bd 100644
Binary files a/icons/mob/screen_slimecore.dmi and b/icons/mob/screen_slimecore.dmi differ
diff --git a/icons/mob/screen_white.dmi b/icons/mob/screen_white.dmi
index a30d30bd3ef..8288217dcd0 100644
Binary files a/icons/mob/screen_white.dmi and b/icons/mob/screen_white.dmi differ
diff --git a/paradise.dme b/paradise.dme
index fbbf5394196..4a2ce73967c 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -20,6 +20,7 @@
#include "code\__DEFINES\bots.dm"
#include "code\__DEFINES\clothing.dm"
#include "code\__DEFINES\combat.dm"
+#include "code\__DEFINES\crafting.dm"
#include "code\__DEFINES\error_handler.dm"
#include "code\__DEFINES\flags.dm"
#include "code\__DEFINES\game.dm"
@@ -1225,9 +1226,9 @@
#include "code\modules\computer3\computers\robot.dm"
#include "code\modules\computer3\computers\security.dm"
#include "code\modules\computer3\computers\welcome.dm"
+#include "code\modules\crafting\craft.dm"
#include "code\modules\crafting\guncrafting.dm"
#include "code\modules\crafting\recipes.dm"
-#include "code\modules\crafting\table.dm"
#include "code\modules\customitems\item_defines.dm"
#include "code\modules\customitems\item_spawning.dm"
#include "code\modules\detective_work\detective_work.dm"