mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
Merge pull request #3094 from CHOMPStationBot/upstream-merge-11553
[MIRROR] [MIRROR] Refactors crafting to support requirement alternatives
This commit is contained in:
@@ -62,55 +62,7 @@
|
||||
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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check that the contents of the recipe meet the requirements.
|
||||
*
|
||||
* user: The /mob that initated the crafting.
|
||||
* R: The /datum/crafting_recipe being attempted.
|
||||
* contents: List of items to search for R's reqs.
|
||||
*/
|
||||
/datum/component/personal_crafting/proc/check_contents(atom/a, datum/crafting_recipe/R, list/contents)
|
||||
var/list/item_instances = contents["instances"]
|
||||
var/list/machines = contents["machinery"]
|
||||
contents = contents["other"]
|
||||
|
||||
|
||||
var/list/requirements_list = list()
|
||||
|
||||
// Process all requirements
|
||||
for(var/requirement_path in R.reqs)
|
||||
// Check we have the appropriate amount available in the contents list
|
||||
var/needed_amount = R.reqs[requirement_path]
|
||||
for(var/content_item_path in contents)
|
||||
// Right path and not blacklisted
|
||||
if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(content_item_path))
|
||||
continue
|
||||
|
||||
needed_amount -= contents[content_item_path]
|
||||
if(needed_amount <= 0)
|
||||
break
|
||||
|
||||
if(needed_amount > 0)
|
||||
return FALSE
|
||||
|
||||
// Store the instances of what we will use for R.check_requirements() for requirement_path
|
||||
var/list/instances_list = list()
|
||||
for(var/instance_path in item_instances)
|
||||
if(ispath(instance_path, requirement_path))
|
||||
instances_list += item_instances[instance_path]
|
||||
|
||||
requirements_list[requirement_path] = instances_list
|
||||
|
||||
for(var/requirement_path in R.chem_catalysts)
|
||||
if(contents[requirement_path] < R.chem_catalysts[requirement_path])
|
||||
return FALSE
|
||||
|
||||
for(var/machinery_path in R.machinery)
|
||||
if(!machines[machinery_path])//We don't care for volume with machines, just if one is there or not
|
||||
return FALSE
|
||||
|
||||
return R.check_requirements(a, requirements_list)
|
||||
|
||||
// Returns a list of objects available
|
||||
/datum/component/personal_crafting/proc/get_environment(atom/a, list/blacklist = null, radius_range = 1)
|
||||
. = list()
|
||||
|
||||
@@ -122,13 +74,13 @@
|
||||
continue
|
||||
. += AM
|
||||
|
||||
|
||||
// Returns an associative list containing the types of tools available, and the paths of objects available
|
||||
/datum/component/personal_crafting/proc/get_surroundings(atom/a, list/blacklist=null)
|
||||
. = list()
|
||||
.["tool_qualities"] = list()
|
||||
.["other"] = list()
|
||||
.["instances"] = list()
|
||||
.["machinery"] = list()
|
||||
.["tool_qualities"] = list() // List of tool types available
|
||||
.["other"] = list() // List of reagents/material stacks available
|
||||
.["instances"] = list() // List of /obj/items available, maybe?
|
||||
.["machinery"] = list() // List of /obj/machinery available
|
||||
for(var/obj/object in get_environment(a, blacklist))
|
||||
if(isitem(object))
|
||||
var/obj/item/item = object
|
||||
@@ -150,11 +102,55 @@
|
||||
else if (istype(object, /obj/machinery))
|
||||
LAZYADDASSOCLIST(.["machinery"], object.type, object)
|
||||
|
||||
/**
|
||||
* Check that the contents of the recipe meet the requirements.
|
||||
*
|
||||
* user: The /mob that initated the crafting.
|
||||
* R: The /datum/crafting_recipe being attempted.
|
||||
* contents: List of items to search for R's reqs.
|
||||
*/
|
||||
/datum/component/personal_crafting/proc/check_contents(atom/a, datum/crafting_recipe/R, list/contents)
|
||||
var/list/item_instances = contents["instances"]
|
||||
contents = contents["other"]
|
||||
|
||||
|
||||
var/list/requirements_list = list()
|
||||
|
||||
// Process all requirements
|
||||
for(var/list/requirement in R.reqs)
|
||||
var/satisfied = FALSE
|
||||
for(var/requirement_path in requirement)
|
||||
// Check we have the appropriate amount available in the contents list
|
||||
var/needed_amount = requirement[requirement_path]
|
||||
for(var/content_item_path in contents)
|
||||
// Right path and not blacklisted
|
||||
if(!ispath(content_item_path, requirement_path) || R.blacklist.Find(content_item_path))
|
||||
continue
|
||||
|
||||
needed_amount -= contents[content_item_path]
|
||||
if(needed_amount <= 0)
|
||||
break
|
||||
|
||||
if(needed_amount > 0)
|
||||
continue
|
||||
|
||||
// Store the instances of what we will use for R.check_requirements() for requirement_path
|
||||
var/list/instances_list = list()
|
||||
for(var/instance_path in item_instances)
|
||||
if(ispath(instance_path, requirement_path))
|
||||
instances_list += item_instances[instance_path]
|
||||
|
||||
requirements_list[requirement_path] = instances_list
|
||||
satisfied = TRUE
|
||||
break
|
||||
if(!satisfied)
|
||||
return FALSE
|
||||
|
||||
return R.check_requirements(a, requirements_list)
|
||||
|
||||
/// Returns a boolean on whether the tool requirements of the input recipe are satisfied by the input source and surroundings.
|
||||
/datum/component/personal_crafting/proc/check_tools(atom/source, datum/crafting_recipe/recipe, list/surroundings)
|
||||
if(!length(recipe.tool_behaviors) && !length(recipe.tool_paths))
|
||||
/datum/component/personal_crafting/proc/check_tools(atom/source, datum/crafting_recipe/R, list/surroundings)
|
||||
if(!length(R.tool_behaviors) && !length(R.tool_paths))
|
||||
return TRUE
|
||||
var/list/available_tools = list()
|
||||
var/list/present_qualities = list()
|
||||
@@ -176,50 +172,70 @@
|
||||
for(var/path in surroundings["other"])
|
||||
available_tools[path] = TRUE
|
||||
|
||||
for(var/required_quality in recipe.tool_behaviors)
|
||||
for(var/required_quality in R.tool_behaviors)
|
||||
if(present_qualities[required_quality])
|
||||
continue
|
||||
return FALSE
|
||||
|
||||
for(var/required_path in recipe.tool_paths)
|
||||
var/found_this_tool = FALSE
|
||||
for(var/tool_path in available_tools)
|
||||
if(!ispath(required_path, tool_path))
|
||||
continue
|
||||
found_this_tool = TRUE
|
||||
break
|
||||
if(found_this_tool)
|
||||
for(var/required_path in R.tool_paths)
|
||||
if(is_path_in_list(required_path, available_tools))
|
||||
continue
|
||||
return FALSE
|
||||
|
||||
return TRUE
|
||||
|
||||
/datum/component/personal_crafting/proc/check_reagents(atom/source, datum/crafting_recipe/R, list/surroundings)
|
||||
var/list/reagents = surroundings["other"]
|
||||
for(var/requirement_path in R.chem_catalysts)
|
||||
if(reagents[requirement_path] < R.chem_catalysts[requirement_path])
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/component/personal_crafting/proc/check_machinery(atom/source, datum/crafting_recipe/R, list/surroundings)
|
||||
var/list/machines = surroundings["machinery"]
|
||||
for(var/machinery_path in R.machinery)
|
||||
if(!machines[machinery_path])//We don't care for volume with machines, just if one is there or not
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/component/personal_crafting/proc/check_requirements(atom/source, datum/crafting_recipe/R, list/surroundings)
|
||||
if(!check_contents(source, R, surroundings))
|
||||
return ", missing component."
|
||||
if(!check_tools(source, R, surroundings))
|
||||
return ", missing tool."
|
||||
if(!check_reagents(source, R, surroundings))
|
||||
return ", missing reagents."
|
||||
if(!check_machinery(source, R, surroundings))
|
||||
return ", missing machinery."
|
||||
return
|
||||
|
||||
/datum/component/personal_crafting/proc/construct_item(atom/a, datum/crafting_recipe/R)
|
||||
var/list/contents = get_surroundings(a,R.blacklist)
|
||||
var/list/surroundings = get_surroundings(a,R.blacklist)
|
||||
// var/send_feedback = 1
|
||||
if(check_contents(a, R, contents))
|
||||
if(check_tools(a, R, contents))
|
||||
if(R.one_per_turf)
|
||||
for(var/content in get_turf(a))
|
||||
if(istype(content, R.result))
|
||||
return ", object already present."
|
||||
//If we're a mob we'll try a do_after; non mobs will instead instantly construct the item
|
||||
if(ismob(a) && !do_after(a, R.time, target = a))
|
||||
return "."
|
||||
contents = get_surroundings(a,R.blacklist)
|
||||
if(!check_contents(a, R, contents))
|
||||
return ", missing component."
|
||||
if(!check_tools(a, R, contents))
|
||||
return ", missing tool."
|
||||
var/list/parts = del_reqs(R, a)
|
||||
var/atom/movable/I = new R.result (get_turf(a.loc))
|
||||
I.CheckParts(parts, R)
|
||||
// if(send_feedback)
|
||||
// SSblackbox.record_feedback("tally", "object_crafted", 1, I.type)
|
||||
return I //Send the item back to whatever called this proc so it can handle whatever it wants to do with the new item
|
||||
return ", missing tool."
|
||||
return ", missing component."
|
||||
. = check_requirements(a, R, surroundings)
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(R.one_per_turf)
|
||||
for(var/content in get_turf(a))
|
||||
if(istype(content, R.result))
|
||||
return ", object already present."
|
||||
|
||||
//If we're a mob we'll try a do_after; non mobs will instead instantly construct the item
|
||||
if(ismob(a) && !do_after(a, R.time, target = a))
|
||||
return "."
|
||||
|
||||
surroundings = get_surroundings(a, R.blacklist)
|
||||
. = check_requirements(a, R, surroundings)
|
||||
if(.)
|
||||
return
|
||||
|
||||
var/list/parts = del_reqs(R, a)
|
||||
var/atom/movable/I = new R.result (get_turf(a.loc))
|
||||
I.CheckParts(parts, R)
|
||||
// if(send_feedback)
|
||||
// SSblackbox.record_feedback("tally", "object_crafted", 1, I.type)
|
||||
return I //Send the item back to whatever called this proc so it can handle whatever it wants to do with the new item
|
||||
|
||||
/*Del reqs works like this:
|
||||
|
||||
@@ -246,119 +262,108 @@
|
||||
*/
|
||||
|
||||
/datum/component/personal_crafting/proc/del_reqs(datum/crafting_recipe/R, atom/a)
|
||||
var/list/surroundings
|
||||
var/list/Deletion = list()
|
||||
. = list()
|
||||
var/data
|
||||
var/amt
|
||||
var/list/surroundings = get_environment(a)
|
||||
var/list/parts = list("items" = list())
|
||||
if(R.get_parts_reagents_volume())
|
||||
parts["reagents"] = new /datum/reagents(R.get_parts_reagents_volume()) // Datums don't have create_reagents()
|
||||
var/list/requirements = list()
|
||||
if(R.reqs)
|
||||
requirements += R.reqs
|
||||
for(var/list/L in R.reqs)
|
||||
requirements += L
|
||||
if(R.machinery)
|
||||
requirements += R.machinery
|
||||
main_loop:
|
||||
for(var/path_key in requirements)
|
||||
amt = R.reqs[path_key] || R.machinery[path_key]
|
||||
if(!amt)//since machinery can have 0 aka CRAFTING_MACHINERY_USE - i.e. use it, don't consume it!
|
||||
continue main_loop
|
||||
surroundings = get_environment(a, R.blacklist)
|
||||
surroundings -= Deletion
|
||||
if(ispath(path_key, /datum/reagent))
|
||||
var/datum/reagent/RG = new path_key
|
||||
var/datum/reagent/RGNT
|
||||
while(amt > 0)
|
||||
var/obj/item/weapon/reagent_containers/RC = locate() in surroundings
|
||||
RG = RC.reagents.get_reagent(path_key)
|
||||
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)
|
||||
SEND_SIGNAL(RC.reagents, COMSIG_REAGENTS_CRAFTING_PING) // - [] TODO: Make this entire thing less spaghetti
|
||||
else
|
||||
surroundings -= RC
|
||||
else if(ispath(path_key, /obj/item/stack))
|
||||
var/obj/item/stack/S
|
||||
var/obj/item/stack/SD
|
||||
while(amt > 0)
|
||||
S = locate(path_key) in surroundings
|
||||
if(S.get_amount() >= amt)
|
||||
if(!locate(S.type) in Deletion)
|
||||
SD = new S.type()
|
||||
Deletion += SD
|
||||
S.use(amt)
|
||||
SD = locate(S.type) in Deletion
|
||||
SD.add(amt)
|
||||
continue main_loop
|
||||
else
|
||||
amt -= S.get_amount()
|
||||
if(!locate(S.type) in Deletion)
|
||||
Deletion += S
|
||||
else
|
||||
data = S.get_amount()
|
||||
S = locate(S.type) in Deletion
|
||||
S.add(data)
|
||||
surroundings -= S
|
||||
else
|
||||
var/atom/movable/I
|
||||
while(amt > 0)
|
||||
I = locate(path_key) 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/part in R.parts)
|
||||
if(istype(part, /datum/reagent))
|
||||
var/datum/reagent/RG = locate(part) in Deletion
|
||||
if(RG.volume > partlist[part])
|
||||
RG.volume = partlist[part]
|
||||
. += RG
|
||||
Deletion -= RG
|
||||
|
||||
// Try to find everything that was actually used to craft
|
||||
for(var/path_key in requirements)
|
||||
var/amt = requirements[path_key]
|
||||
if(amt <= 0)//since machinery can have 0 aka CRAFTING_MACHINERY_USE - i.e. use it, don't consume it!
|
||||
continue
|
||||
else if(istype(part, /obj/item/stack))
|
||||
var/obj/item/stack/ST = locate(part) in Deletion
|
||||
if(ST.get_amount() > partlist[part])
|
||||
ST.set_amount(partlist[part])
|
||||
. += ST
|
||||
Deletion -= ST
|
||||
continue
|
||||
else
|
||||
while(partlist[part] > 0)
|
||||
var/atom/movable/AM = locate(part) in Deletion
|
||||
. += AM
|
||||
Deletion -= AM
|
||||
partlist[part] -= 1
|
||||
while(Deletion.len)
|
||||
var/DL = Deletion[Deletion.len]
|
||||
Deletion.Cut(Deletion.len)
|
||||
// Snowflake handling of reagent containers and storage atoms.
|
||||
// If we consumed them in our crafting, we should dump their contents out before qdeling them.
|
||||
if(istype(DL, /obj/item/weapon/reagent_containers))
|
||||
var/obj/item/weapon/reagent_containers/container = DL
|
||||
container.reagents.clear_reagents()
|
||||
// container.reagents.expose(container.loc, TOUCH)
|
||||
else if(istype(DL, /obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/container = DL
|
||||
container.spill()
|
||||
container.close_all()
|
||||
qdel(DL)
|
||||
|
||||
// If the path is in R.parts, we want to grab those to stuff into the product
|
||||
var/amt_to_transfer = 0
|
||||
if(is_path_in_list(path_key, R.parts))
|
||||
amt_to_transfer = R.parts[path_key]
|
||||
|
||||
|
||||
// Reagent: gotta go sniffing in all the beakers
|
||||
if(ispath(path_key, /datum/reagent))
|
||||
var/datum/reagent/reagent = path_key
|
||||
var/id = initial(reagent.id)
|
||||
|
||||
for(var/obj/item/weapon/reagent_containers/RC in surroundings)
|
||||
// Found everything we need
|
||||
if(amt <= 0 && amt_to_transfer <= 0)
|
||||
break
|
||||
|
||||
// If we need to keep any to put in the new object, pull it out
|
||||
if(amt_to_transfer > 0)
|
||||
var/A = RC.reagents.trans_id_to(parts["reagents"], id, amt_to_transfer)
|
||||
amt_to_transfer -= A
|
||||
amt -= A
|
||||
|
||||
// If we need to consume some amount of it
|
||||
if(amt > 0)
|
||||
var/datum/reagent/RG = RC.reagents.get_reagent(id)
|
||||
var/A = min(RG.volume, amt)
|
||||
RC.reagents.remove_reagent(id, A)
|
||||
amt -= A
|
||||
SEND_SIGNAL(RC.reagents, COMSIG_REAGENTS_CRAFTING_PING)
|
||||
|
||||
// Material stacks may have to accumulate across multiple stacks
|
||||
else if(ispath(path_key, /obj/item/stack))
|
||||
for(var/obj/item/stack/S in surroundings)
|
||||
if(amt <= 0 && amt_to_transfer <= 0)
|
||||
break
|
||||
|
||||
// This could put 50 stacks in an object but frankly so long as the amount's right we don't care
|
||||
if(amt_to_transfer > 0)
|
||||
var/obj/item/stack/split = S.split(amt_to_transfer)
|
||||
if(istype(split))
|
||||
parts["items"] += split
|
||||
amt_to_transfer -= split.get_amount()
|
||||
amt -= split.get_amount()
|
||||
|
||||
if(amt > 0)
|
||||
var/A = min(amt, S.get_amount())
|
||||
if(S.use(A))
|
||||
amt -= A
|
||||
|
||||
|
||||
else // Just a regular item. Find them all and delete them
|
||||
for(var/atom/movable/I in surroundings)
|
||||
if(amt <= 0 && amt_to_transfer <= 0)
|
||||
break
|
||||
|
||||
if(!istype(I, path_key))
|
||||
continue
|
||||
|
||||
// Special case: the reagents may be needed for other recipes
|
||||
if(istype(I, /obj/item/weapon/reagent_containers))
|
||||
var/obj/item/weapon/reagent_containers/RC = I
|
||||
if(RC.reagents.total_volume > 0)
|
||||
continue
|
||||
|
||||
// We're using it for something
|
||||
amt--
|
||||
|
||||
// Prepare to stuff inside product, don't delete it
|
||||
if(is_path_in_list(path_key, parts))
|
||||
parts["items"] += I
|
||||
amt_to_transfer--
|
||||
continue
|
||||
|
||||
// Snowflake handling of reagent containers and storage atoms.
|
||||
// If we consumed them in our crafting, we should dump their contents out before qdeling them.
|
||||
if(istype(I, /obj/item/weapon/reagent_containers))
|
||||
var/obj/item/weapon/reagent_containers/container = I
|
||||
container.reagents.clear_reagents()
|
||||
// container.reagents.expose(container.loc, TOUCH)
|
||||
else if(istype(I, /obj/item/weapon/storage))
|
||||
var/obj/item/weapon/storage/container = I
|
||||
container.spill()
|
||||
container.close_all()
|
||||
qdel(I)
|
||||
return parts
|
||||
|
||||
/datum/component/personal_crafting/proc/component_ui_interact(source, location, control, params, user)
|
||||
// SIGNAL_HANDLER
|
||||
@@ -487,10 +492,14 @@
|
||||
var/list/tool_list = list()
|
||||
var/list/catalyst_text = list()
|
||||
|
||||
for(var/atom/req_atom as anything in R.reqs)
|
||||
//We just need the name, so cheat-typecast to /atom for speed (even tho Reagents are /datum they DO have a "name" var)
|
||||
//Also these are typepaths so sadly we can't just do "[a]"
|
||||
req_text += "[R.reqs[req_atom]] [initial(req_atom.name)]"
|
||||
for(var/list/req in R.reqs)
|
||||
var/list/L = list()
|
||||
for(var/atom/req_atom as anything in req)
|
||||
//We just need the name, so cheat-typecast to /atom for speed (even tho Reagents are /datum they DO have a "name" var)
|
||||
//Also these are typepaths so sadly we can't just do "[a]"
|
||||
L += "[req[req_atom]] [initial(req_atom.name)]"
|
||||
req_text += L.Join(" OR ")
|
||||
|
||||
for(var/obj/machinery/content as anything in R.machinery)
|
||||
req_text += "[R.reqs[content]] [initial(content.name)]"
|
||||
if(R.additional_req_text)
|
||||
|
||||
@@ -12,21 +12,30 @@
|
||||
*/
|
||||
/atom/proc/CheckParts(list/parts_list, datum/crafting_recipe/R)
|
||||
SEND_SIGNAL(src, COMSIG_ATOM_CHECKPARTS, parts_list, R)
|
||||
if(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(ismovable(A))
|
||||
var/atom/movable/M = A
|
||||
if(isliving(M.loc))
|
||||
var/mob/living/L = M.loc
|
||||
L.unEquip(M, target = src)
|
||||
else
|
||||
M.forceMove(src)
|
||||
SEND_SIGNAL(M, COMSIG_ATOM_USED_IN_CRAFT, src)
|
||||
if(LAZYLEN(parts_list))
|
||||
if(istype(parts_list["reagents"], /datum/reagents))
|
||||
var/datum/reagents/RG = parts_list["reagents"]
|
||||
if(istype(reagents))
|
||||
RG.trans_to_holder(reagents, RG.total_volume)
|
||||
else
|
||||
reagents = RG
|
||||
RG.my_atom = src
|
||||
reagents.conditional_update()
|
||||
|
||||
for(var/atom/movable/M as anything in parts_list["items"])
|
||||
if(isliving(M.loc))
|
||||
var/mob/living/L = M.loc
|
||||
L.unEquip(M, target = src)
|
||||
else
|
||||
M.forceMove(src)
|
||||
SEND_SIGNAL(M, COMSIG_ATOM_USED_IN_CRAFT, src)
|
||||
|
||||
var/list/L = parts_list["reagents"]
|
||||
if(LAZYLEN(L))
|
||||
L.Cut()
|
||||
L = parts_list["items"]
|
||||
if(LAZYLEN(L))
|
||||
L.Cut()
|
||||
parts_list.Cut()
|
||||
|
||||
/obj/machinery/CheckParts(list/parts_list)
|
||||
|
||||
@@ -47,3 +47,28 @@
|
||||
|
||||
/datum/crafting_recipe/proc/on_craft_completion(mob/user, atom/result)
|
||||
return
|
||||
|
||||
// Computes the total reagents volume
|
||||
/datum/crafting_recipe/proc/get_parts_reagents_volume()
|
||||
. = 0
|
||||
for(var/list/L in parts)
|
||||
for(var/path in L)
|
||||
if(ispath(path, /datum/reagent))
|
||||
. += L[path]
|
||||
|
||||
// Locate one of the things that set the material type, and update it from the default (glass)
|
||||
/datum/crafting_recipe/spear/on_craft_completion(mob/user, atom/result)
|
||||
var/obj/item/weapon/material/M
|
||||
for(var/path in parts)
|
||||
var/obj/item/weapon/material/N = locate(path) in result
|
||||
if(istype(N, path))
|
||||
if(!istype(M))
|
||||
M = N
|
||||
else
|
||||
N.forceMove(get_turf(result))
|
||||
if(!istype(M))
|
||||
return
|
||||
|
||||
var/obj/item/weapon/material/twohanded/spear/S = result
|
||||
S.set_material(M.material.name)
|
||||
qdel(M)
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
/datum/crafting_recipe/cloth
|
||||
name = "Cloth bolt"
|
||||
result = /obj/item/stack/material/cloth
|
||||
reqs = list(/obj/item/stack/material/fiber = 3)
|
||||
reqs = list(list(/obj/item/stack/material/fiber = 3))
|
||||
time = 40
|
||||
category = CAT_PRIMAL
|
||||
|
||||
/datum/crafting_recipe/crude_bandage
|
||||
name = "Crude bandages (x10)"
|
||||
result = /obj/item/stack/medical/crude_pack
|
||||
reqs = list(/obj/item/stack/material/cloth = 2)
|
||||
reqs = list(list(/obj/item/stack/material/cloth = 2))
|
||||
time = 40
|
||||
category = CAT_PRIMAL
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
name = "primitive clothes"
|
||||
result = /obj/item/clothing/under/primitive
|
||||
reqs = list(
|
||||
/obj/item/stack/material/fiber = 4,
|
||||
/obj/item/stack/material/cloth = 6
|
||||
list(/obj/item/stack/material/fiber = 4),
|
||||
list(/obj/item/stack/material/cloth = 6)
|
||||
)
|
||||
time = 90
|
||||
category = CAT_CLOTHING
|
||||
@@ -30,8 +30,8 @@
|
||||
name = "primitive shoes"
|
||||
result = /obj/item/clothing/shoes/primitive
|
||||
reqs = list(
|
||||
/obj/item/stack/material/fiber = 2,
|
||||
/obj/item/stack/material/cloth = 3
|
||||
list(/obj/item/stack/material/fiber = 2),
|
||||
list(/obj/item/stack/material/cloth = 3)
|
||||
)
|
||||
time = 60
|
||||
category = CAT_CLOTHING
|
||||
@@ -2,10 +2,10 @@
|
||||
name = "Wooden Shovel"
|
||||
result = /obj/item/weapon/shovel/wood
|
||||
reqs = list(
|
||||
/obj/item/stack/material/stick = 5,
|
||||
/obj/item/stack/material/wood = 1,
|
||||
/obj/item/stack/material/fiber = 3,
|
||||
/obj/item/stack/material/flint = 1
|
||||
list(/obj/item/stack/material/stick = 5),
|
||||
list(/obj/item/stack/material/wood = 1),
|
||||
list(/obj/item/stack/material/fiber = 3),
|
||||
list(/obj/item/stack/material/flint = 1)
|
||||
)
|
||||
time = 120
|
||||
category = CAT_WEAPONRY
|
||||
@@ -15,7 +15,7 @@
|
||||
name = "stone blade"
|
||||
result = /obj/item/weapon/material/knife/stone
|
||||
reqs = list(
|
||||
/obj/item/stack/material/flint = 2
|
||||
list(/obj/item/stack/material/flint = 2)
|
||||
)
|
||||
time = 60
|
||||
category = CAT_WEAPONRY
|
||||
@@ -25,10 +25,10 @@
|
||||
name = "stone knife"
|
||||
result = /obj/item/weapon/material/knife/stone/wood
|
||||
reqs = list(
|
||||
/obj/item/weapon/material/knife/stone = 1,
|
||||
/obj/item/stack/material/flint = 1,
|
||||
/obj/item/stack/material/wood = 1,
|
||||
/obj/item/stack/material/fiber = 3
|
||||
list(/obj/item/weapon/material/knife/stone = 1),
|
||||
list(/obj/item/stack/material/flint = 1),
|
||||
list(/obj/item/stack/material/wood = 1),
|
||||
list(/obj/item/stack/material/fiber = 3)
|
||||
)
|
||||
time = 120
|
||||
category = CAT_WEAPONRY
|
||||
@@ -38,10 +38,10 @@
|
||||
name = "stone knife"
|
||||
result = /obj/item/weapon/material/knife/stone/bone
|
||||
reqs = list(
|
||||
/obj/item/weapon/material/knife/stone = 1,
|
||||
/obj/item/stack/material/flint = 1,
|
||||
/obj/item/weapon/bone = 1,
|
||||
/obj/item/stack/material/fiber = 3
|
||||
list(/obj/item/weapon/material/knife/stone = 1),
|
||||
list(/obj/item/stack/material/flint = 1),
|
||||
list(/obj/item/weapon/bone = 1),
|
||||
list(/obj/item/stack/material/fiber = 3)
|
||||
)
|
||||
time = 120
|
||||
category = CAT_WEAPONRY
|
||||
@@ -51,9 +51,9 @@
|
||||
name = "wooden bucket"
|
||||
result = /obj/item/weapon/reagent_containers/glass/bucket/wood
|
||||
reqs = list(
|
||||
/obj/item/stack/material/wood = 1,
|
||||
/obj/item/stack/material/stick = 1,
|
||||
/obj/item/stack/material/fiber = 2
|
||||
list(/obj/item/stack/material/wood = 1),
|
||||
list(/obj/item/stack/material/stick = 1),
|
||||
list(/obj/item/stack/material/fiber = 2)
|
||||
)
|
||||
time = 60
|
||||
category = CAT_TOOL
|
||||
@@ -61,7 +61,7 @@
|
||||
/datum/crafting_recipe/sticks
|
||||
name = "sticks"
|
||||
result = /obj/item/stack/material/stick/fivestack
|
||||
reqs = list(/obj/item/stack/material/wood = 1)
|
||||
reqs = list(list(/obj/item/stack/material/wood = 1))
|
||||
tool_paths = list(/obj/item/weapon/material/knife)
|
||||
time = 200
|
||||
category = CAT_MISC
|
||||
@@ -70,10 +70,10 @@
|
||||
name = "stone axe"
|
||||
result = /obj/item/weapon/material/knife/machete/hatchet/stone
|
||||
reqs = list(
|
||||
/obj/item/weapon/material/knife/stone = 1,
|
||||
/obj/item/stack/material/flint = 1,
|
||||
/obj/item/stack/material/stick = 10,
|
||||
/obj/item/stack/material/fiber = 3
|
||||
list(/obj/item/weapon/material/knife/stone = 1),
|
||||
list(/obj/item/stack/material/flint = 1),
|
||||
list(/obj/item/stack/material/stick = 1),
|
||||
list(/obj/item/stack/material/fiber = 3)
|
||||
)
|
||||
time = 120
|
||||
category = CAT_WEAPONRY
|
||||
@@ -83,10 +83,10 @@
|
||||
name = "stone axe"
|
||||
result = /obj/item/weapon/material/knife/machete/hatchet/stone/bone
|
||||
reqs = list(
|
||||
/obj/item/weapon/material/knife/stone = 1,
|
||||
/obj/item/stack/material/flint = 1,
|
||||
/obj/item/weapon/bone = 1,
|
||||
/obj/item/stack/material/fiber = 3
|
||||
list(/obj/item/weapon/material/knife/stone = 1),
|
||||
list(/obj/item/stack/material/flint = 1),
|
||||
list(/obj/item/weapon/bone = 1),
|
||||
list(/obj/item/stack/material/fiber = 3)
|
||||
)
|
||||
time = 120
|
||||
category = CAT_WEAPONRY
|
||||
@@ -96,10 +96,10 @@
|
||||
name = "stone spear"
|
||||
result = /obj/item/weapon/material/twohanded/spear/flint
|
||||
reqs = list(
|
||||
/obj/item/weapon/material/knife/stone = 1,
|
||||
/obj/item/stack/material/flint = 1,
|
||||
/obj/item/stack/material/wood = 2,
|
||||
/obj/item/stack/material/fiber = 3
|
||||
list(/obj/item/weapon/material/knife/stone = 1),
|
||||
list(/obj/item/stack/material/flint = 1),
|
||||
list(/obj/item/stack/material/wood = 2),
|
||||
list(/obj/item/stack/material/fiber = 3)
|
||||
)
|
||||
time = 120
|
||||
category = CAT_WEAPONRY
|
||||
@@ -109,10 +109,10 @@
|
||||
name = "stone spear"
|
||||
result = /obj/item/weapon/material/twohanded/spear/flint
|
||||
reqs = list(
|
||||
/obj/item/weapon/material/knife/stone = 1,
|
||||
/obj/item/stack/material/flint = 1,
|
||||
/obj/item/weapon/bone = 2,
|
||||
/obj/item/stack/material/fiber = 3
|
||||
list(/obj/item/weapon/material/knife/stone = 1),
|
||||
list(/obj/item/stack/material/flint = 1),
|
||||
list(/obj/item/weapon/bone = 2),
|
||||
list(/obj/item/stack/material/fiber = 3)
|
||||
)
|
||||
time = 120
|
||||
category = CAT_WEAPONRY
|
||||
@@ -121,6 +121,6 @@
|
||||
/datum/crafting_recipe/ropebindings
|
||||
name = "rope bindings"
|
||||
result = /obj/item/weapon/handcuffs/cable/plantfiber
|
||||
reqs = list(/obj/item/stack/material/fiber = 3)
|
||||
reqs = list(list(/obj/item/stack/material/fiber = 3))
|
||||
time = 60
|
||||
category = CAT_MISC
|
||||
|
||||
@@ -1,9 +1,23 @@
|
||||
/datum/crafting_recipe/stunprod
|
||||
name = "Stunprod"
|
||||
result = /obj/item/weapon/melee/baton/cattleprod
|
||||
reqs = list(/obj/item/weapon/handcuffs/cable = 1,
|
||||
/obj/item/stack/rods = 1,
|
||||
/obj/item/weapon/tool/wirecutters = 1)
|
||||
reqs = list(list(/obj/item/weapon/handcuffs/cable = 1),
|
||||
list(/obj/item/stack/rods = 1),
|
||||
list(/obj/item/weapon/tool/wirecutters = 1))
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
|
||||
/datum/crafting_recipe/spear
|
||||
name = "Spear"
|
||||
result = /obj/item/weapon/material/twohanded/spear
|
||||
reqs = list(list(/obj/item/weapon/handcuffs/cable = 1),
|
||||
list(/obj/item/stack/rods = 1),
|
||||
list(/obj/item/weapon/material/shard = 1,
|
||||
/obj/item/weapon/material/butterflyblade = 1)
|
||||
)
|
||||
parts = list(/obj/item/weapon/material/shard = 1,
|
||||
/obj/item/weapon/material/butterflyblade = 1)
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
@@ -11,10 +25,8 @@
|
||||
/datum/crafting_recipe/shortbow
|
||||
name = "Shortbow"
|
||||
result = /obj/item/weapon/gun/launcher/crossbow/bow
|
||||
reqs = list(
|
||||
/obj/item/stack/material/wood = 10,
|
||||
/obj/item/stack/material/cloth = 5
|
||||
)
|
||||
reqs = list(list(/obj/item/stack/material/wood = 10),
|
||||
list(/obj/item/stack/material/cloth = 5))
|
||||
time = 120
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_WEAPON
|
||||
@@ -22,10 +34,8 @@
|
||||
/datum/crafting_recipe/arrow_sandstone
|
||||
name = "Wood arrow (sandstone tip)"
|
||||
result = /obj/item/weapon/arrow/standard
|
||||
reqs = list(
|
||||
/obj/item/stack/material/wood = 2,
|
||||
/obj/item/stack/material/sandstone = 2
|
||||
)
|
||||
reqs = list(list(/obj/item/stack/material/wood = 2),
|
||||
list(/obj/item/stack/material/sandstone = 2))
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
@@ -33,10 +43,8 @@
|
||||
/datum/crafting_recipe/arrow_marble
|
||||
name = "Wood arrow (marble tip)"
|
||||
result = /obj/item/weapon/arrow/standard
|
||||
reqs = list(
|
||||
/obj/item/stack/material/wood = 2,
|
||||
/obj/item/stack/material/marble = 2
|
||||
)
|
||||
reqs = list(list(/obj/item/stack/material/wood = 2),
|
||||
list(/obj/item/stack/material/marble = 2))
|
||||
time = 40
|
||||
category = CAT_WEAPONRY
|
||||
subcategory = CAT_AMMO
|
||||
|
||||
Reference in New Issue
Block a user