diff --git a/code/modules/chemical/Chemistry-Holder.dm b/code/modules/chemical/Chemistry-Holder.dm index ba4a7b48fb..d27530d2cf 100644 --- a/code/modules/chemical/Chemistry-Holder.dm +++ b/code/modules/chemical/Chemistry-Holder.dm @@ -176,7 +176,7 @@ datum R.on_update (A) update_total() - handle_reactions() + handle_reactions(var/heated = 0) if(my_atom.flags & NOREACT) return //Yup, no reactions here. No siree. var/reaction_occured = 0 @@ -184,6 +184,8 @@ datum reaction_occured = 0 for(var/A in typesof(/datum/chemical_reaction) - /datum/chemical_reaction) var/datum/chemical_reaction/C = new A() + if(C.requires_heating && !heated) + continue var/total_required_reagents = C.required_reagents.len var/total_matching_reagents = 0 var/total_required_catalysts = C.required_catalysts.len diff --git a/code/modules/chemical/Chemistry-Recipes.dm b/code/modules/chemical/Chemistry-Recipes.dm index 578f14acde..a4500c3a52 100644 --- a/code/modules/chemical/Chemistry-Recipes.dm +++ b/code/modules/chemical/Chemistry-Recipes.dm @@ -14,11 +14,14 @@ datum var/result_amount = 0 var/secondary = 0 // set to nonzero if secondary reaction + var/requires_heating = 0 //to avoid lag and other complications, every recipe is restricted to the same heating time (or none) + proc on_reaction(var/datum/reagents/holder, var/created_volume) return //I recommend you set the result amount to the total volume of all components. + //but obviously that's not mandatory. science! explosion_potassium name = "Explosion" diff --git a/code/modules/chemical/Chemistry-Tools.dm b/code/modules/chemical/Chemistry-Tools.dm index fa638a266f..a1e13fed96 100644 --- a/code/modules/chemical/Chemistry-Tools.dm +++ b/code/modules/chemical/Chemistry-Tools.dm @@ -1473,6 +1473,105 @@ else usr << "\blue It is currently empty." +//////////////////////////////////////////////////////////////////////////////// +/// Bunsen Burner +//////////////////////////////////////////////////////////////////////////////// + +//make a subclass of this for cooking at some point, allow it to accept multiple containers etc +//todo: use mini plasma tanks for fuel + +/obj/item/device/cooker + name = "bunsen burner" + desc = "a small, gas-powered cooker." + icon = 'chemical.dmi' + icon_state = "bunsen1" //spawns with an empty beaker already on it + var/obj/item/weapon/reagent_containers/held_container + var/heating_stage = 0 + var/active = 0 + var/icon_empty = "bunsen0" + var/icon_full = "bunsen1" + var/icon_heating = "bunsen2" + +/obj/item/device/cooker/verb/toggle() + if(held_container) + if(!active) + usr << "\blue You switch the [src] on." + active = 1 + icon_state = icon_heating + spawn(50) + heat() + else + usr << "\blue You switch the [src] off." + active = 0 + icon_state = icon_full + else + usr << "\red You can not toggle the [src] when it holds no containers!" + +/obj/item/device/cooker/proc/heat() + if(!held_container) + heating_stage = 0 + active = 0 + icon_state = icon_empty + return + + if(active) + icon_state = icon_heating + spawn(50) + heat() + else + heating_stage = 0 + icon_state = icon_full + return + + if(heating_stage++ > 5) + visible_message("bubbles!") + held_container.reagents.handle_reactions(1) + else + visible_message("hisses and steams!") + +/obj/item/device/cooker/New() + held_container = new /obj/item/weapon/reagent_containers/glass/large/(src) + +/obj/item/device/cooker/attackby(var/obj/item/O as obj, var/mob/user as mob) + if(istype(O, /obj/item/weapon/reagent_containers/)) + if(held_container) + //todo: empty O into held_container + user << "\red There is already a [held_container] on the [src]!" + else + user.drop_item() + user << "\blue You place the [O] on the [src]." + held_container = O + O.loc = src + icon_state = icon_full + return 1 + else if(!held_container) + user << "\red There is nothing to put [O] in to!" + return 1 + else if (istype(O,/obj/item)) + if(w_class > 2) + user << "\red That won't fit in the [held_container]!" + else + //add random things to the container. when the burner is activated, they will melt + O.loc = held_container + return 1 + else + user << "\red That won't fit in the [held_container]!" + return 1 + + return ..() + +/obj/item/device/cooker/attack_hand(var/mob/user as mob) + if(held_container) + held_container.attack_hand(user) + if(held_container.loc != src) + held_container = null + icon_state = icon_empty + user << "\blue You remove the [held_container] from the [src]." + return 1 + else + ..() + + //////////////////////////////////////////////////////////////////////////////// /// Food. diff --git a/code/modules/research/xenoarchaeology/artifact_archaeo.dm b/code/modules/research/xenoarchaeology/artifact_archaeo.dm deleted file mode 100644 index c9108db501..0000000000 --- a/code/modules/research/xenoarchaeology/artifact_archaeo.dm +++ /dev/null @@ -1,306 +0,0 @@ -//Ported from lunacode, seems to be functional. Thanks to Alfie275 for the original code + idea -//talking crystals may quickly turnout to be very annoying - -//strange rocks have been mostly redone -/obj/item/weapon/ore/strangerock/New() - ..() - //var/datum/reagents/r = new/datum/reagents(50) - //src.reagents = r - if(rand(3)) - method = 0 - else - method = 1 - inside = pick(150;"", 50;"/obj/item/weapon/crystal", 25;"/obj/item/weapon/talkingcrystal", "/obj/item/weapon/fossil/base") - -/obj/item/weapon/ore/strangerock/bullet_act(var/obj/item/projectile/P) - -/obj/item/weapon/ore/strangerock/ex_act(var/severity) - src.visible_message("The [src] crumbles away, leaving some dust and gravel behind.") - -/obj/item/weapon/ore/strangerock/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W,/obj/item/weapon/weldingtool/)) - var/obj/item/weapon/weldingtool/w = W - if(w.isOn() && (w.get_fuel() > 3)) - if(!src.method) - if(inside) - var/obj/A = new src.inside(get_turf(src)) - for(var/mob/M in viewers(world.view, user)) - M.show_message("\blue The rock burns away revealing a [A.name].",1) - else - for(var/mob/M in viewers(world.view, user)) - M.show_message("\blue The rock burns away into nothing.",1) - del src - else - for(var/mob/M in viewers(world.view, user)) - M.show_message("\blue A few sparks fly off the rock, but otherwise nothing else happens.",1) - w.remove_fuel(4) - -/obj/item/weapon/ore/strangerock/acid_act(var/datum/reagent/R) - if(src.method) - if(inside) - var/obj/A = new src.inside(get_turf(src)) - for(var/mob/M in viewers(world.view, get_turf(src))) - M.show_message("\blue The rock fizzes away revealing a [A.name].",1) - else - for(var/mob/M in viewers(world.view, get_turf(src))) - M.show_message("\blue The rock fizzes away into nothing.",1) - del src - else - for(var/mob/M in viewers(world.view, get_turf(src))) - M.show_message("\blue The acid splashes harmlessly off the rock, nothing else interesting happens.",1) - return 1 - - -/obj/item/weapon/crystal - name = "Crystal" - icon = 'mining.dmi' - icon_state = "crystal" - -/obj/item/weapon/crystal/bullet_act(var/obj/item/projectile/P) - if(istype(P,/obj/item/projectile/beam/emitter)) - switch(rand(0,3)) - if(0) - var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc ) - A.dir = 1 - A.yo = 20 - A.xo = 0 - if(0) - var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc ) - A.dir = 2 - A.yo = -20 - A.xo = 0 - if(0) - var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc ) - A.dir = 4 - A.yo = 0 - A.xo = 20 - if(0) - var/obj/item/projectile/beam/emitter/A = new /obj/item/projectile/beam/emitter( src.loc ) - A.dir = 8 - A.yo = 0 - A.xo = -20 - else - ..() - -/obj/item/weapon/talkingcrystal - name = "Crystal" - icon = 'mining.dmi' - icon_state = "crystal2" - var/list/list/words = list() - var/lastsaid - -/obj/item/weapon/talkingcrystal/New() - spawn(100) - process() - -/obj/item/weapon/talkingcrystal/bullet_act(var/obj/item/projectile/P) - if(istype(P,/obj/item/projectile/beam)) - switch(rand(0,3)) - if(0) - var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc ) - A.dir = pick(alldirs) - A.yo = 20 - A.xo = 0 - if(0) - var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc ) - A.dir = pick(alldirs) - A.yo = -20 - A.xo = 0 - if(0) - var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc ) - A.dir = pick(alldirs) - A.yo = 0 - A.xo = 20 - if(0) - var/obj/item/projectile/beam/A = new /obj/item/projectile/beam( src.loc ) - A.dir = pick(alldirs) - A.yo = 0 - A.xo = -20 - var/word = pick("pain","hurt","masochism","sadist","rage","repressed","ouch","evil","void","kill","destroy") - SaySomething(word) - else - ..() - -/obj/item/weapon/talkingcrystal/proc/catchMessage(var/msg, var/mob/source) - var/list/seperate = list() - if(findtext(msg,"((")) - return - else if(findtext(msg,"))")) - return - else if(findtext(msg," ")==0) - return - else - /*var/l = lentext(msg) - if(findtext(msg," ",l,l+1)==0) - msg+=" "*/ - seperate = stringsplit(msg, " ") - - var/addressing_crystal = 0 - if("crystal" in seperate || "gem" in seperate) - addressing_crystal = 1 - - for(var/Xa = 1,Xa 20 + rand(10,20)) - words.Remove(words[1]) - if(!words["[lowertext(seperate[Xa])]"]) - words["[lowertext(seperate[Xa])]"] = list() - var/list/w = words["[lowertext(seperate[Xa])]"] - if(w) - w.Add("[lowertext(seperate[next])]") - //world << "Adding [lowertext(seperate[next])] to [lowertext(seperate[Xa])]" - - for(var/mob/O in viewers(src)) - O.show_message("\blue The crystal hums for bit then stops...", 1) - if(!rand(0, 5 - addressing_crystal * 3)) - spawn(2) SaySomething(pick(seperate)) - -/obj/item/weapon/talkingcrystal/proc/debug() - //set src in view() - for(var/v in words) - world << "[uppertext(v)]" - var/list/d = words["[v]"] - for(var/X in d) - world << "[X]" - -/obj/item/weapon/talkingcrystal/proc/SaySomething(var/word = null) - var/msg - var/limit = rand(max(5,words.len/2))+3 - var/text - if(!word) - text = "[pick(words)]" - else - text = pick(stringsplit(word, " ")) - if(lentext(text)==1) - text=uppertext(text) - else - var/cap = copytext(text,1,2) - cap = uppertext(cap) - cap += copytext(text,2,lentext(text)+1) - text=cap - var/q = 0 - msg+=text - if(msg=="What" | msg == "Who" | msg == "How" | msg == "Why" | msg == "Are") - q=1 - - text=lowertext(text) - for(var/ya,ya <= limit,ya++) - - if(words.Find("[text]")) - var/list/w = words["[text]"] - text=pick(w) - else - text = "[pick(words)]" - msg+=" [text]" - if(q) - msg+="?" - else - if(rand(0,10)) - msg+="." - else - msg+="!" - - var/list/listening = viewers(src) - for(var/mob/M in world) - if (!M.client) - continue //skip monkeys and leavers - if (istype(M, /mob/new_player)) - continue - if(M.stat == 2 && M.client.ghost_ears) - listening|=M - - for(var/mob/M in listening) - M << "The crystal reverberates, \blue\"[msg]\"" - lastsaid = world.timeofday + rand(300,800) - -/obj/item/weapon/talkingcrystal/process() - if(prob(25) && world.timeofday >= lastsaid && words.len >= 1) - SaySomething() - spawn(100) - process() - - - - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -/obj/item/weapon/fossil - name = "Fossil" - icon = 'fossil.dmi' - icon_state = "bone" - desc = "It's a fossil." - -/obj/item/weapon/fossil/base/New() - spawn(0) - var/list/l = list("/obj/item/weapon/fossil/bone"=8,"/obj/item/weapon/fossil/skull"=2, - "/obj/item/weapon/fossil/skull/horned"=2,"/obj/item/weapon/fossil/shell"=1) - var/t = pickweight(l) - new t(src.loc) - del src - -/obj/item/weapon/fossil/bone - name = "Fossilised bone" - icon_state = "bone" - desc = "It's a fossilised bone from an unknown creature." - -/obj/item/weapon/fossil/shell - name = "Fossilised shell" - icon_state = "shell" - desc = "It's a fossilised shell from some sort of space mollusc." - -/obj/item/weapon/fossil/skull/horned - icon_state = "hskull" - desc = "It's a fossilised skull, it has horns." - -/obj/item/weapon/fossil/skull - name = "Fossilised skull" - icon_state = "skull" - desc = "It's a fossilised skull." - -/obj/item/weapon/fossil/skull/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W,/obj/item/weapon/fossil/bone)) - var/obj/o = new /obj/skeleton(get_turf(src)) - var/a = new /obj/item/weapon/fossil/bone - var/b = new src.type - o.contents.Add(a) - o.contents.Add(b) - del W - del src - -/obj/skeleton - name = "Incomplete skeleton" - icon = 'fossil.dmi' - icon_state = "uskel" - desc = "Incomplete skeleton." - var/bnum = 1 - var/breq - var/bstate = 0 - -/obj/skeleton/New() - src.breq = rand(6)+3 - src.desc = "Incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones." - -/obj/skeleton/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W,/obj/item/weapon/fossil/bone)) - if(!bstate) - bnum++ - src.contents.Add(new/obj/item/weapon/fossil/bone) - del W - if(bnum==breq) - usr = user - icon_state = "skel" - var/creaturename = input("Input a name for your discovery:","Name your discovery","Spaceosaurus") - src.bstate = 1 - src.density = 1 - src.name = "[creaturename] skeleton" - if(src.contents.Find(/obj/item/weapon/fossil/skull/horned)) - src.desc = "A creature made of [src.contents.len-1] assorted bones and a horned skull, the plaque reads [creaturename]." - else - src.desc = "A creature made of [src.contents.len-1] assorted bones and a skull, the plaque reads [creaturename]." - else - src.desc = "Incomplete skeleton, looks like it could use [src.breq-src.bnum] more bones." - user << "Looks like it could use [src.breq-src.bnum] more bones." - else - ..() - else - ..() diff --git a/icons/obj/chemical.dmi b/icons/obj/chemical.dmi index d52b9b7be1..c3c0752682 100644 Binary files a/icons/obj/chemical.dmi and b/icons/obj/chemical.dmi differ diff --git a/icons/obj/device.dmi b/icons/obj/device.dmi index bdce947d4b..5162031f72 100644 Binary files a/icons/obj/device.dmi and b/icons/obj/device.dmi differ