//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 += "
[first_part ? "[first_part.name]" : "EMPTY"] [second_part ? "[second_part.name]" : "EMPTY"] [resultName]

" html += "


" for(var/obj/item/I in src) if(!I.amount) continue if(first_part == I) continue if(second_part == I) continue html += "
[I.name]

" 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'