//This serves as a bridge between old materials pieces and new ones. Eventually old ones should just be updated.
/obj/machinery/processor
name = "Material processor"
desc = "Turns raw materials, and objects containing materials, into processed pieces."
icon = 'icons/obj/crafting.dmi'
icon_state = "fab3-on"
anchored = 1
density = 1
layer = FLOOR_EQUIP_LAYER1
var/atom/output_location = null
New()
..()
process()
if(contents.len)
var/atom/X = contents[1]
var/list/matches = list()
for(var/atom/A in contents)
if(A == X) continue
if(isSameMaterial(A.material, X.material))
matches.Add(A)
var/obj/item/material_piece/exists_nearby = null
for(var/obj/item/material_piece/G in get_output_location())
if(isSameMaterial(G.material, X.material))
exists_nearby = G
break
matches.Add(X)
var/totalAmount = 0
for(var/obj/item/M in matches)
totalAmount += M.amount
if(exists_nearby)
exists_nearby.change_stack_amount(totalAmount)
else
var/newType = getProcessedMaterialForm(X.material)
var/obj/item/material_piece/P = unpool(newType)
P.set_loc(get_output_location())
P.setMaterial(copyMaterial(X.material))
P.change_stack_amount(totalAmount - P.amount)
for(var/atom/movable/D in matches)
D.set_loc(null)
qdel(D)
D = null
playsound(src.loc, "sound/effects/pop.ogg", 40, 1)
flick("fab3-work",src)
return
attackby(var/obj/item/W as obj, mob/user as mob)
//Wire: Fix for: undefined proc or verb /turf/simulated/floor/set loc()
// like somehow a dude tried to load a turf? how the fuck? whatever just kill me
if (!istype(W))
return
if(isExploitableObject(W))
boutput(user, "\the [src] grumps at you and refuses to use [W].")
return
if(istype(W, /obj/item/material_piece))
boutput(user, "[W] has already been processed.")
return
if(istype(W, /obj/item/satchel))
var/obj/item/satchel/S = W
boutput(user, "You empty \the [W] into \the [src].")
for(var/obj/item/I in S)
if(I.material)
I.set_loc(src)
S.satchel_updateicon()
return
if(W.material)
boutput(user, "You put \the [W] into \the [src].")
user.u_equip(W)
W.set_loc(src)
W.dropped()
return
return
MouseDrop(over_object, src_location, over_location)
if(!isliving(usr))
boutput(usr, "Get your filthy dead fingers off that!")
return
if(over_object == src)
output_location = null
boutput(usr, "You reset the processor's output target.")
return
if(get_dist(over_object,src) > 1)
boutput(usr, "The processor is too far away from the target!")
return
if(get_dist(over_object,usr) > 1)
boutput(usr, "You are too far away from the target!")
return
if (istype(over_object,/obj/storage/crate/))
var/obj/storage/crate/C = over_object
if (C.locked || C.welded)
boutput(usr, "You can't use a currently unopenable crate as an output target.")
else
src.output_location = over_object
boutput(usr, "You set the processor to output to [over_object]!")
else if (istype(over_object,/obj/machinery/manufacturer/))
var/obj/machinery/manufacturer/M = over_object
if (M.status & BROKEN || M.status & NOPOWER || M.dismantle_stage > 0)
boutput(usr, "You can't use a non-functioning manufacturer as an output target.")
else
src.output_location = M
boutput(usr, "You set the processor to output to [over_object]!")
else if (istype(over_object, /obj/machinery/nanofab))
var/obj/machinery/nanofab/N = over_object
if (N.status & BROKEN || N.status & NOPOWER)
boutput(usr, "You can't use a non-functioning nano-fabricator as an output target.")
else
src.output_location = N
boutput(usr, "You set the processor to output to [over_object]!")
else if (istype(over_object,/obj/table/) && istype(over_object,/obj/rack/))
var/obj/O = over_object
src.output_location = O.loc
boutput(usr, "You set the processor to output on top of [O]!")
else if (istype(over_object,/turf/simulated/floor/))
src.output_location = over_object
boutput(usr, "You set the processor to output to [over_object]!")
else
boutput(usr, "You can't use that as an output target.")
return
MouseDrop_T(atom/movable/O as mob|obj, mob/user as mob)
if (get_dist(user, src) > 1 || get_dist(user, O) > 1 || user.stat || user.getStatusDuration("paralysis") || user.getStatusDuration("stunned") || user.getStatusDuration("weakened") || isAI(user))
return
if (istype(O, /obj/storage/crate/))
user.visible_message("[user] uses [src]'s automatic loader on [O]!", "You use [src]'s automatic loader on [O].")
var/amtload = 0
for (var/obj/item/raw_material/M in O.contents)
if(!M.material)
continue
if(isExploitableObject(M))
continue
if(istype(M, /obj/item/material_piece))
continue
M.set_loc(src)
amtload += max(M.amount, 1)
if (amtload) boutput(user, "[amtload] materials loaded from [O]!")
else boutput(user, "No material loaded!")
return
var/obj/item/W = O
if(W in user)
user.u_equip(W)
W.set_loc(src.loc)
W.dropped()
//if (istype(W, /obj/item/raw_material/) || istype(W, /obj/item/sheet/) || istype(W, /obj/item/rods/) || istype(W, /obj/item/tile/) || istype(W, /obj/item/cable_coil))
if(!isExploitableObject(W) && W.material && !istype(W, /obj/item/material_piece))
quickload(user, W)
else
attackby(W, user)
return
ex_act(severity)
return
proc/quickload(var/mob/living/user,var/obj/item/O)
if (!user || !O || !istype(O))
return
user.visible_message("[user] begins quickly stuffing [O] into [src]!")
O.set_loc(src)
var/staystill = user.loc
for(var/obj/item/M in view(1,user))
if (!M)
continue
if (M.type != O.type)
continue
if(!istype(M, /obj/item/cable_coil))
if (!istype(M.material))
continue
//if (!M.material.material_flags & MATERIAL_CRYSTAL || !M.material.material_flags & MATERIAL_METAL)
// continue
M.set_loc(src)
playsound(get_turf(src), "sound/items/Deconstruct.ogg", 40, 1)
sleep(0.5)
if (user.loc != staystill) break
boutput(user, "You finish stuffing [O] into [src]!")
return
proc/get_output_location()
if (isnull(output_location))
return src.loc
if (get_dist(src.output_location,src) > 1)
output_location = null
return src.loc
if (istype(output_location,/obj/machinery/manufacturer))
var/obj/machinery/manufacturer/M = output_location
if (M.status & NOPOWER || M.status & BROKEN | M.dismantle_stage > 0)
return M.loc
return M
else if (istype(output_location,/obj/storage/crate))
var/obj/storage/crate/C = output_location
if (C.locked || C.welded || C.open)
return C.loc
return C
return output_location
/obj/machinery/processor/portable
name = "Portable material processor"
icon = 'icons/obj/scrap.dmi'
icon_state = "reclaimer"
anchored = 0
density = 1
/obj/machinery/neosmelter
name = "Nano-crucible"
desc = "A huge furnace-like machine used to combine materials."
icon = 'icons/effects/96x96.dmi'
icon_state = "smelter0"
anchored = 1
bound_height = 96
bound_width = 96
density = 1
layer = FLOOR_EQUIP_LAYER1
var/datum/light/light
var/obj/item/first_part = null
var/obj/item/second_part = null
var/resultName = "???"
New()
..()
light = new /datum/light/point
light.attach(src, 1.5, 1.5)
light.set_brightness(0.5)
light.set_color(0.4, 0.8, 1)
attack_hand(mob/user as mob)
var/html = ""
html += "
"
html += "
"
for(var/obj/item/I in src)
if(!I.amount) continue
if(first_part == I) continue
if(second_part == I) continue
html += "
"
user.Browse(html, "window=crucible;size=500x650;title=Nano-crucible;fade_in=0", 1)
return
Topic(href, href_list)
if(get_dist(usr, src) > 1 || usr.z != src.z) return
if(href_list["select_l"])
var/obj/item/L = locate(href_list["select_l"]) in src
if(!L) return
first_part = L
else if(href_list["select_r"])
var/obj/item/R = locate(href_list["select_r"]) in src
if(!R) return
second_part = R
else if(href_list["activate"])
if(first_part && second_part)
var/obj/item/FP = first_part
var/obj/item/SP = second_part
var/maxamt = min(FP.amount, SP.amount)
var/amt = input(usr, "How many? ([maxamt] max)", "Select amount", maxamt) as null|num
if(amt && isnum(amt) && FP && FP.amount >= amt && SP && SP.amount >= amt && (FP in src) && (SP in src))
flick("smelter1",src)
var/datum/material/merged = getFusedMaterial(FP.material, SP.material)
var/datum/material_recipe/RE = matchesMaterialRecipe(merged)
var/newtype = getProcessedMaterialForm(merged)
var/apply_material = 1
var/output_item = 0
if(RE)
if(!RE.result_id && !RE.result_item)
RE.apply_to(merged)
else if(RE.result_item)
newtype = RE.result_item
apply_material = 0
output_item = 1
else if(RE.result_id)
merged = getMaterial(RE.result_id)
var/obj/item/piece = new newtype(src)
if(apply_material)
piece.setMaterial(merged)
piece.change_stack_amount(amt - piece.amount)
FP.change_stack_amount(-amt)
SP.change_stack_amount(-amt)
if(!output_item)
addMaterial(piece, usr)
else
piece.set_loc(get_turf(src))
first_part = null
second_part = null
boutput(usr, "You make [amt] [piece].")
else if(href_list["eject"])
var/obj/item/L = locate(href_list["eject"]) in src
if(!(L in src)) return
if(first_part == L)
first_part = null
else if (second_part == L)
second_part = null
L.set_loc(src.loc)
else if(href_list["remove"])
var/obj/item/L = locate(href_list["remove"]) in src
if(first_part == L)
first_part = null
else if (second_part == L)
second_part = null
updateResultName()
attack_hand(usr)
proc/updateResultName()
if(first_part && second_part)
resultName = getInterpolatedName(first_part.material.name, second_part.material.name, 0.5)
else
resultName = "???"
proc/addMaterial(var/obj/item/W, var/mob/user)
for(var/obj/item/A in src)
if(A == W|| !A.amount) continue
if(A.material)
if(isSameMaterial(A.material, W.material))
var/obj/item/I = A
I.change_stack_amount(W.amount)
if(W == user.equipped())
user.drop_item()
W.set_loc(null)
qdel(W)
W = null
return
if(W == user.equipped())
user.drop_item()
W.set_loc(src)
return
attackby(var/obj/item/W , mob/user as mob)
if(isExploitableObject(W))
boutput(user, "\the [src] grumps at you and refuses to use [W].")
return
if(W.material != null)
if(!W.material.canMix)
boutput(user, "This material can not be used in \the [src].")
return
user.visible_message("[user] puts \the [W] in \the [src].")
if( istype(W, /obj/item/material_piece) || istype(W, /obj/item/raw_material) )
addMaterial(W, user)
else
boutput(user, "The crucible can only use raw materials.")
return
return
custom_suicide = 1
suicide(var/mob/user)
if (!src.user_can_suicide(user))
return 0
user.visible_message("[user] hops right into [src]! Jesus!")
user.unequip_all()
user.set_loc(src)
var/datum/material/M = new /datum/material/organic/flesh {desc="A disgusting wad of flesh."; color="#881111";} ()
M.name = "[user.real_name] flesh"
var/obj/item/material_piece/wad/dummyItem = unpool(/obj/item/material_piece/wad)
dummyItem.set_loc(src)
dummyItem.setMaterial(M)
dummyItem.change_stack_amount(5)
addMaterial(dummyItem, user)
user.remove()
ex_act(severity)
return
/obj/machinery/smelter_portable
name = "Portable Smelter"
desc = "A small furnace-like machine used to melt and combine metals or minerals."
icon = 'icons/obj/crafting.dmi'
icon_state = "portsmelter0"
anchored = 0
density = 1
layer = FLOOR_EQUIP_LAYER1
var/list/components = list()
var/sound/sound_bubble = sound('sound/effects/bubbles.ogg')
var/datum/material/output = null
var/datum/light/light
New()
..()
light = new /datum/light/point
light.attach(src)
light.set_brightness(0.5)
light.set_color(1, 0.6, 0.2)
ex_act(severity)
return
/obj/machinery/smelter
name = "Arc Smelter"
desc = "A huge furnace-like machine used to melt and combine metals or minerals."
icon = 'icons/effects/96x96.dmi'
icon_state = "smelter0"
anchored = 1
bound_height = 96
bound_width = 96
density = 1
layer = FLOOR_EQUIP_LAYER1
var/list/components = list()
var/slag_level = 0
var/sound/sound_thunk = sound('sound/items/Deconstruct.ogg')
var/sound/sound_zap = sound('sound/effects/elec_bzzz.ogg')
var/sound/sound_hiss = sound('sound/machines/hiss.ogg')
var/sound/sound_bubble = sound('sound/effects/bubbles.ogg')
var/datum/material/output = null
var/datum/light/light
New()
..()
light = new /datum/light/point
light.attach(src, 1.5, 1.5)
light.set_brightness(0.5)
light.set_color(0.4, 0.8, 1)
proc/resetMats()
icon_state = "smelter0"
output = null
for(var/atom/movable/A in components)
A.set_loc(null)
qdel(A)
A = null
components.Cut()
return
attack_hand(mob/user as mob)
if(output)
var/datum/material_recipe/R = matchesMaterialRecipe(output)
if(R)
if(R.result_item)
var/atom/A = new R.result_item(locate(src.x + 1, src.y, src.z))
boutput(user, "You remove [A.name] from the [src].")
playsound(src.loc, sound_thunk, 40, 1)
resetMats()
return
else if(length(R.result_id))
output = getMaterial(R.result_id)
else
R.apply_to(output)
boutput(user, "You remove [output.name] from the [src].")
var/bar_type = getProcessedMaterialForm(output)
var/obj/item/material_piece/M = unpool(bar_type)
M.set_loc(locate(src.x + 1, src.y, src.z))
M.add_fingerprint(user) // May not be the same person who smelted the materials (Convair880).
src.add_fingerprint(user) // Add some prints to the smelter too.
M.setMaterial(output)
resetMats()
playsound(src.loc, sound_thunk, 40, 1)
if(M.material && M.material.getProperty("stability") <= 30 && prob((30 - M.material.getProperty("stability")) * 2 ) )
M.visible_message("[M] [getMatFailString(M.material.material_flags)]!")
M.material.triggerOnFail(M)
return
if(components.len > 0)
light.enable()
playsound(src.loc, sound_zap, 40, 1)
SPAWN_DBG(5 DECI SECONDS)
playsound(src.loc, sound_bubble, 40, 1)
if(components.len == 1)
boutput(user, "You activate the [src].")
icon_state = "smelter1"
sleep(10)
var/atom/obj1 = components[1]
output = copyMaterial(obj1.material)
logTheThing("station", user, null, "creates a [output] bar (Material: [output.mat_id]) with the [src] at [log_loc(src)].") // Re-added/fixed because of erebite, plasmastone etc. alloys (Convair880).
handleSlag()
else
icon_state = "smelter1"
sleep(10)
var/atom/obj1 = components[1]
var/atom/obj2 = components[2]
var/datum/material/mat1 = obj1.material
var/datum/material/mat2 = obj2.material
if(!mat1 || !mat2)
icon_state = "smelter0"
return
output = getFusedMaterial(mat1, mat2)
output.generation++
logTheThing("station", user, null, "creates a [output] bar (Material: [output.mat_id]) with the [src] at [log_loc(src)].") // Sorry for code duplication, but I'm regularly seeing runtime errors for some reason if this proc is called after handleSlag (Convair880).
handleSlag()
SPAWN_DBG(8 DECI SECONDS)
playsound(src.loc, sound_hiss, 45, 1)
light.disable()
else
boutput(user, "There is nothing in the [src].")
return
proc/handleSlag()
switch(slag_level)
if(500 to 1000)
particleMaster.SpawnSystem(new /datum/particleSystem/localSmoke("#967360", 10, locate(src.x +1, src.y, src.z)))
//output.adjustProperty(PROP_INSTABILITY , 5)
output.quality += rand(5, -15)
if(1000 to INFINITY)
particleMaster.SpawnSystem(new /datum/particleSystem/localSmoke("#221511", 10, locate(src.x +1, src.y, src.z)))
output.quality += rand(-15, -30)
//output.adjustProperty(PROP_INSTABILITY , 15)
slag_level += (100 - output.quality)
return
custom_suicide = 1
suicide(var/mob/user)
if (!src.user_can_suicide(user))
return 0
user.visible_message("[user] hops right into [src]! Jesus!")
user.unequip_all()
user.set_loc(src)
var/datum/material/M = new /datum/material/organic/flesh {desc="A disgusting wad of flesh."; color="#881111";} ()
M.name = "[user.real_name] flesh"
var/obj/item/dummyItem = new (src)
dummyItem.setMaterial(M, appearance = 0, setname = 0)
components += dummyItem
user.ghostize()
attackby(obj/item/W as obj, mob/user as mob)
if (istype(W, /obj/item/slag_shovel))
if(slag_level)
src.visible_message("[user] removes slag from the [src]")
slag_level = 0
var/obj/item/material_piece/slag/S = unpool(/obj/item/material_piece/slag)
S.set_loc(src.loc)
return
else
boutput(user, "There is no slag in [src].")
return
if(istype(W, /obj/item/wizard_crystal) && components.len < 2 && !W.material)
W.setMaterial(W:assoc_material, appearance = 0, setname = 0)
if(W.material != null)
if(!W.material.canMix)
boutput(user, "This material can not be used in the [src].")
return
if((W.material.material_flags & MATERIAL_METAL || W.material.material_flags & MATERIAL_CRYSTAL) && (istype(W, /obj/item/material_piece) || istype(W, /obj/item/raw_material)) )
if(components.len < 2)
src.visible_message("[user] puts [W] into [src]")
user.drop_item()
components.Add(W)
W.loc = src
playsound(src.loc, sound_thunk, 40, 1)
else
boutput(user, "The smelter is already filled to capacity!")
return
else
boutput(user, "The smelter can only use metals or minerals in raw form.")
return
return
ex_act(severity) // bloo bloo we blew it up and nobody gets to have fun
return
//
/obj/item/device/matanalyzer
icon_state = "matanalyzer"
name = "Material analyzer"
desc = "This piece of equipment can detect and analyze materials."
flags = FPRINT | EXTRADELAY | TABLEPASS | CONDUCT
w_class = 2
afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
if(get_dist(src, target) <= world.view)
var/atom/W = target
if(!W.material)
boutput(user, "No significant material found in \the [target].")
else
boutput(user, "[capitalize(W.material.name)]")
boutput(user, "[W.material.desc]")
if(W.material.properties.len)
boutput(user, "The material is:")
for(var/datum/material_property/X in W.material.properties)
var/value = W.material.getProperty(X.id)
boutput(user, "• [X.getAdjective(W.material)] ([value])")
else
boutput(user, "The material is completely unremarkable.")
else
boutput(user, "[target] is too far away.")
return
/obj/item/slag_shovel
name = "slag shovel"
desc = "Used to remove slag from the arc smelter."
icon = 'icons/obj/items.dmi'
icon_state = "shovel"
inhand_image_icon = 'icons/mob/inhand/hand_tools.dmi'
item_state = "pick"
w_class = 3
flags = ONBELT
force = 7 // 15 puts it significantly above most other weapons
hitsound = 'sound/impact_sounds/Metal_Hit_1.ogg'