mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-21 20:20:33 +01:00
Fermichem part 2.2 Adds new tools, crafts and methods for ghetto chemists to handle the new reaction mechanics. (#56871)
Since reactions now require a bit more involvement from chemists, ghetto chemistry is a bit harder. This seeks to help some of those problems by providing new tools for those without a chem heater/reaction chamber. Also some of these might be useful for chemists in the lab too! Here's what you can make: image the burners are similar to candles - except they burn their internal reagents. The temperature they heat by is dependant on the flame, fuel and oil burn for a lower amount, ethanol for a higher amount and plasma for the highest amount. They can be put on tables and bonked with beakers for a quick way to heat them (similar to lighters). You'll need to light them with a match or lighter too, though, and can be put out by use in hand. The thermometer looks like this and gives you temperature readings! thermom The pH booklets are the same as before - but you can now craft them by making universal indicator. These are the best way for a ghetto chemist to check their pH, and multiple sheets should be used over a reaction. The improvised chem heater looks like this, and is a reconfigured space heater, it requires more materials and tools lending itself to a static drug den, but has the best method of adjusting temperature and fighting against exo/endo thermic reactions: Improv_heater Finally, the cooling spray lets chemists do the oposite of a lighter on their beaker - cooling the reagents within. In addition, fire extinquishers perform the same function. In addition ice and universal indicator have been added as reactions. Co-authored-by: Rohesie <rohesie@gmail.com> Co-authored-by: Mothblocks <35135081+Jared-Fogle@users.noreply.github.com> Co-authored-by: Aleksej Komarov <stylemistake@gmail.com>
This commit is contained in:
co-authored by
Rohesie
Mothblocks
Aleksej Komarov
parent
1d6de2e5aa
commit
fa575db934
@@ -95,6 +95,7 @@
|
||||
#define CAT_SPAGHETTI "Spaghettis"
|
||||
#define CAT_ICE "Frozen"
|
||||
#define CAT_DRINK "Drinks"
|
||||
#define CAT_CHEMISTRY "Chemistry"
|
||||
|
||||
//rcd modes
|
||||
#define RCD_FLOORWALL 0
|
||||
|
||||
@@ -194,6 +194,8 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
|
||||
#define isgun(A) (istype(A, /obj/item/gun))
|
||||
|
||||
#define is_reagent_container(O) (istype(O, /obj/item/reagent_containers))
|
||||
|
||||
//Assemblies
|
||||
#define isassembly(O) (istype(O, /obj/item/assembly))
|
||||
|
||||
|
||||
@@ -89,3 +89,38 @@
|
||||
return
|
||||
for(var/mob/M in viewers(5, location))
|
||||
to_chat(M, notification)
|
||||
|
||||
#define CONVERT_PH_TO_COLOR(pH, color) \
|
||||
switch(pH) {\
|
||||
if(14 to INFINITY)\
|
||||
{ color = "#462c83" }\
|
||||
if(13 to 14)\
|
||||
{ color = "#63459b" }\
|
||||
if(12 to 13)\
|
||||
{ color = "#5a51a2" }\
|
||||
if(11 to 12)\
|
||||
{ color = "#3853a4" }\
|
||||
if(10 to 11)\
|
||||
{ color = "#3f93cf" }\
|
||||
if(9 to 10)\
|
||||
{ color = "#0bb9b7" }\
|
||||
if(8 to 9)\
|
||||
{ color = "#23b36e" }\
|
||||
if(7 to 8)\
|
||||
{ color = "#3aa651" }\
|
||||
if(6 to 7)\
|
||||
{ color = "#4cb849" }\
|
||||
if(5 to 6)\
|
||||
{ color = "#b5d335" }\
|
||||
if(4 to 5)\
|
||||
{ color = "#f7ec1e" }\
|
||||
if(3 to 4)\
|
||||
{ color = "#fbc314" }\
|
||||
if(2 to 3)\
|
||||
{ color = "#f26724" }\
|
||||
if(1 to 2)\
|
||||
{ color = "#ef1d26" }\
|
||||
if(-INFINITY to 1)\
|
||||
{ color = "#c6040c" }\
|
||||
}
|
||||
|
||||
|
||||
@@ -132,6 +132,7 @@ GLOBAL_LIST_INIT(common_loot, list( //common: basic items
|
||||
/obj/item/reagent_containers/glass/beaker = 1,
|
||||
/obj/item/reagent_containers/glass/rag = 1,
|
||||
/obj/item/reagent_containers/hypospray/medipen/pumpup = 2,
|
||||
/obj/item/reagent_containers/glass/bottle/random_buffer = 2,
|
||||
) = 1,
|
||||
|
||||
list(//food
|
||||
|
||||
@@ -68,8 +68,10 @@
|
||||
*/
|
||||
/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
|
||||
@@ -100,6 +102,10 @@
|
||||
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)
|
||||
|
||||
/datum/component/personal_crafting/proc/get_environment(atom/a, list/blacklist = null, radius_range = 1)
|
||||
@@ -119,24 +125,27 @@
|
||||
.["tool_behaviour"] = list()
|
||||
.["other"] = list()
|
||||
.["instances"] = list()
|
||||
for(var/obj/item/I in get_environment(a,blacklist))
|
||||
if(.["instances"][I.type])
|
||||
.["instances"][I.type] += I
|
||||
else
|
||||
.["instances"][I.type] = list(I)
|
||||
if(istype(I, /obj/item/stack))
|
||||
var/obj/item/stack/S = I
|
||||
.["other"][I.type] += S.amount
|
||||
else if(I.tool_behaviour)
|
||||
.["tool_behaviour"] += I.tool_behaviour
|
||||
.["other"][I.type] += 1
|
||||
else
|
||||
if(istype(I, /obj/item/reagent_containers))
|
||||
var/obj/item/reagent_containers/RC = I
|
||||
if(RC.is_drainable())
|
||||
for(var/datum/reagent/A in RC.reagents.reagent_list)
|
||||
.["other"][A.type] += A.volume
|
||||
.["other"][I.type] += 1
|
||||
.["machinery"] = list()
|
||||
for(var/obj/object in get_environment(a, blacklist))
|
||||
if(isitem(object))
|
||||
var/obj/item/item = object
|
||||
LAZYADDASSOCLIST(.["instances"], item.type, item)
|
||||
if(isstack(item))
|
||||
var/obj/item/stack/stack = item
|
||||
.["other"][item.type] += stack.amount
|
||||
else if(item.tool_behaviour)
|
||||
.["tool_behaviour"] += item.tool_behaviour
|
||||
.["other"][item.type] += 1
|
||||
else
|
||||
if(is_reagent_container(item))
|
||||
var/obj/item/reagent_containers/container = item
|
||||
if(container.is_drainable())
|
||||
for(var/datum/reagent/reagent in container.reagents.reagent_list)
|
||||
.["other"][reagent.type] += reagent.volume
|
||||
.["other"][item.type] += 1
|
||||
else if (ismachinery(object))
|
||||
LAZYADDASSOCLIST(.["machinery"], object.type, object)
|
||||
|
||||
|
||||
|
||||
/// Returns a boolean on whether the tool requirements of the input recipe are satisfied by the input source and surroundings.
|
||||
@@ -166,7 +175,7 @@
|
||||
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)
|
||||
@@ -177,7 +186,7 @@
|
||||
if(found_this_tool)
|
||||
continue
|
||||
return FALSE
|
||||
|
||||
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -233,17 +242,24 @@
|
||||
. = list()
|
||||
var/data
|
||||
var/amt
|
||||
var/list/requirements = list()
|
||||
if(R.reqs)
|
||||
requirements += R.reqs
|
||||
if(R.machinery)
|
||||
requirements += R.machinery
|
||||
main_loop:
|
||||
for(var/A in R.reqs)
|
||||
amt = R.reqs[A]
|
||||
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(A, /datum/reagent))
|
||||
var/datum/reagent/RG = new A
|
||||
if(ispath(path_key, /datum/reagent))
|
||||
var/datum/reagent/RG = new path_key
|
||||
var/datum/reagent/RGNT
|
||||
while(amt > 0)
|
||||
var/obj/item/reagent_containers/RC = locate() in surroundings
|
||||
RG = RC.reagents.get_reagent(A)
|
||||
RG = RC.reagents.get_reagent(path_key)
|
||||
if(RG)
|
||||
if(!locate(RG.type) in Deletion)
|
||||
Deletion += new RG.type()
|
||||
@@ -267,11 +283,11 @@
|
||||
SEND_SIGNAL(RC.reagents, COMSIG_REAGENTS_CRAFTING_PING) // - [] TODO: Make this entire thing less spaghetti
|
||||
else
|
||||
surroundings -= RC
|
||||
else if(ispath(A, /obj/item/stack))
|
||||
else if(ispath(path_key, /obj/item/stack))
|
||||
var/obj/item/stack/S
|
||||
var/obj/item/stack/SD
|
||||
while(amt > 0)
|
||||
S = locate(A) in surroundings
|
||||
S = locate(path_key) in surroundings
|
||||
if(S.amount >= amt)
|
||||
if(!locate(S.type) in Deletion)
|
||||
SD = new S.type()
|
||||
@@ -292,34 +308,34 @@
|
||||
else
|
||||
var/atom/movable/I
|
||||
while(amt > 0)
|
||||
I = locate(A) in surroundings
|
||||
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/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]
|
||||
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
|
||||
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]
|
||||
else if(istype(part, /obj/item/stack))
|
||||
var/obj/item/stack/ST = locate(part) in Deletion
|
||||
if(ST.amount > partlist[part])
|
||||
ST.amount = partlist[part]
|
||||
. += ST
|
||||
Deletion -= ST
|
||||
continue
|
||||
else
|
||||
while(partlist[A] > 0)
|
||||
var/atom/movable/AM = locate(A) in Deletion
|
||||
while(partlist[part] > 0)
|
||||
var/atom/movable/AM = locate(part) in Deletion
|
||||
. += AM
|
||||
Deletion -= AM
|
||||
partlist[A] -= 1
|
||||
partlist[part] -= 1
|
||||
while(Deletion.len)
|
||||
var/DL = Deletion[Deletion.len]
|
||||
Deletion.Cut(Deletion.len)
|
||||
@@ -423,6 +439,7 @@
|
||||
else
|
||||
result.forceMove(user.drop_location())
|
||||
to_chat(user, "<span class='notice'>[TR.name] constructed.</span>")
|
||||
TR.on_craft_completion(user, result)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>Construction failed[result]</span>")
|
||||
busy = FALSE
|
||||
@@ -441,26 +458,24 @@
|
||||
var/list/data = list()
|
||||
data["name"] = R.name
|
||||
data["ref"] = "[REF(R)]"
|
||||
var/req_text = ""
|
||||
var/catalyst_text = ""
|
||||
var/list/req_text = list()
|
||||
var/list/tool_list = list()
|
||||
var/list/catalyst_text = list()
|
||||
|
||||
for(var/a in R.reqs)
|
||||
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]"
|
||||
var/atom/A = a
|
||||
req_text += " [R.reqs[A]] [initial(A.name)],"
|
||||
req_text += "[R.reqs[req_atom]] [initial(req_atom.name)]"
|
||||
for(var/obj/machinery/content as anything in R.machinery)
|
||||
req_text += "[R.reqs[content]] [initial(content.name)]"
|
||||
if(R.additional_req_text)
|
||||
req_text += R.additional_req_text
|
||||
req_text = replacetext(req_text,",","",-1)
|
||||
data["req_text"] = req_text
|
||||
data["req_text"] = req_text.Join(", ")
|
||||
|
||||
for(var/a in R.chem_catalysts)
|
||||
var/atom/A = a //cheat-typecast
|
||||
catalyst_text += " [R.chem_catalysts[A]] [initial(A.name)],"
|
||||
catalyst_text = replacetext(catalyst_text,",","",-1)
|
||||
data["catalyst_text"] = catalyst_text
|
||||
for(var/atom/req_catalyst as anything in R.chem_catalysts)
|
||||
catalyst_text += "[R.chem_catalysts[req_catalyst]] [initial(req_catalyst.name)]"
|
||||
data["catalyst_text"] = catalyst_text.Join(", ")
|
||||
|
||||
var/list/tool_list = list()
|
||||
for(var/required_quality in R.tool_behaviors)
|
||||
tool_list += required_quality
|
||||
for(var/obj/item/required_path as anything in R.tool_paths)
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
///If the machine is used/deleted in the crafting process
|
||||
#define CRAFTING_MACHINERY_CONSUME 1
|
||||
///If the machine is only "used" i.e. it checks to see if it's nearby and allows crafting, but doesn't delete it
|
||||
#define CRAFTING_MACHINERY_USE 0
|
||||
|
||||
/datum/crafting_recipe
|
||||
var/name = "" //in-game display name
|
||||
@@ -10,12 +14,14 @@
|
||||
var/list/tool_paths
|
||||
var/time = 30 //time in deciseconds
|
||||
var/list/parts = list() //type paths of items that will be placed in the result
|
||||
var/list/chem_catalysts = list() //like tools but for reagents
|
||||
var/list/chem_catalysts = list() //like tool_behaviors but for reagents
|
||||
var/category = CAT_NONE //where it shows up in the crafting UI
|
||||
var/subcategory = CAT_NONE
|
||||
var/always_available = TRUE //Set to FALSE if it needs to be learned first.
|
||||
/// Additonal requirements text shown in UI
|
||||
var/additional_req_text
|
||||
///Required machines for the craft, set the assigned value of the typepath to CRAFTING_MACHINERY_CONSUME or CRAFTING_MACHINERY_USE. Lazy associative list: type_path key -> flag value.
|
||||
var/list/machinery
|
||||
|
||||
/datum/crafting_recipe/New()
|
||||
if(!(result in reqs))
|
||||
@@ -34,6 +40,9 @@
|
||||
/datum/crafting_recipe/proc/check_requirements(mob/user, list/collected_requirements)
|
||||
return TRUE
|
||||
|
||||
/datum/crafting_recipe/proc/on_craft_completion(mob/user, atom/result)
|
||||
return
|
||||
|
||||
/datum/crafting_recipe/improv_explosive
|
||||
name = "IED"
|
||||
result = /obj/item/grenade/iedcasing
|
||||
@@ -1158,3 +1167,113 @@
|
||||
/obj/item/aquarium_kit = 1
|
||||
)
|
||||
category = CAT_MISC
|
||||
|
||||
/datum/crafting_recipe/alcohol_burner
|
||||
name = "Alcohol burner"
|
||||
result = /obj/item/burner
|
||||
time = 5 SECONDS
|
||||
reqs = list(/obj/item/reagent_containers/glass/beaker = 1,
|
||||
/datum/reagent/consumable/ethanol = 15,
|
||||
/obj/item/paper = 1
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/datum/crafting_recipe/oil_burner
|
||||
name = "Oil burner"
|
||||
result = /obj/item/burner/oil
|
||||
time = 5 SECONDS
|
||||
reqs = list(/obj/item/reagent_containers/glass/beaker = 1,
|
||||
/datum/reagent/fuel/oil = 15,
|
||||
/obj/item/paper = 1
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/datum/crafting_recipe/fuel_burner
|
||||
name = "Fuel burner"
|
||||
result = /obj/item/burner/fuel
|
||||
time = 5 SECONDS
|
||||
reqs = list(/obj/item/reagent_containers/glass/beaker = 1,
|
||||
/datum/reagent/fuel = 15,
|
||||
/obj/item/paper = 1
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/datum/crafting_recipe/thermometer
|
||||
name = "Thermometer"
|
||||
tool_behaviors = list(TOOL_WELDER)
|
||||
result = /obj/item/thermometer
|
||||
time = 5 SECONDS
|
||||
reqs = list(
|
||||
/datum/reagent/mercury = 5,
|
||||
/obj/item/stack/sheet/glass = 1
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/datum/crafting_recipe/thermometer_alt
|
||||
name = "Thermometer"
|
||||
result = /obj/item/thermometer/pen
|
||||
time = 5 SECONDS
|
||||
reqs = list(
|
||||
/datum/reagent/mercury = 5,
|
||||
/obj/item/pen = 1
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/datum/crafting_recipe/ph_booklet
|
||||
name = "pH booklet"
|
||||
result = /obj/item/ph_booklet
|
||||
time = 5 SECONDS
|
||||
reqs = list(
|
||||
/datum/reagent/universal_indicator = 5,
|
||||
/obj/item/paper = 1
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/datum/crafting_recipe/dropper //Maybe make a glass pipette icon?
|
||||
name = "Dropper"
|
||||
result = /obj/item/reagent_containers/dropper
|
||||
tool_behaviors = list(TOOL_WELDER)
|
||||
time = 5 SECONDS
|
||||
reqs = list(
|
||||
/obj/item/stack/sheet/glass = 1,
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/datum/crafting_recipe/improvised_chem_heater
|
||||
name = "Improvised chem heater"
|
||||
result = /obj/machinery/space_heater/improvised_chem_heater
|
||||
tool_behaviors = list(TOOL_SCREWDRIVER, TOOL_MULTITOOL, TOOL_WIRECUTTER)
|
||||
time = 15 SECONDS
|
||||
reqs = list(
|
||||
/obj/item/stack/cable_coil = 2,
|
||||
/obj/item/stack/sheet/glass = 2,
|
||||
/obj/item/stack/sheet/iron = 2,
|
||||
/datum/reagent/water = 50,
|
||||
/obj/item/thermometer = 1
|
||||
)
|
||||
machinery = list(/obj/machinery/space_heater = CRAFTING_MACHINERY_CONSUME)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
/datum/crafting_recipe/improvised_chem_heater/on_craft_completion(mob/user, atom/result)
|
||||
var/obj/item/stock_parts/cell/cell = locate(/obj/item/stock_parts/cell) in range(1)
|
||||
if(!cell)
|
||||
return
|
||||
var/obj/machinery/space_heater/improvised_chem_heater/heater = result
|
||||
var/turf/turf = get_turf(cell)
|
||||
heater.forceMove(turf)
|
||||
heater.attackby(cell, user) //puts it into the heater
|
||||
|
||||
/datum/crafting_recipe/improvised_coolant
|
||||
name = "Improvised cooling spray"
|
||||
tool_behaviors = list(TOOL_SCREWDRIVER, TOOL_WIRECUTTER)
|
||||
result = /obj/item/extinguisher/crafted
|
||||
time = 10 SECONDS
|
||||
reqs = list(
|
||||
/obj/item/toy/crayon/spraycan = 1,
|
||||
/datum/reagent/water = 20,
|
||||
/datum/reagent/consumable/ice = 10
|
||||
)
|
||||
category = CAT_CHEMISTRY
|
||||
|
||||
#undef CRAFTING_MACHINERY_CONSUME
|
||||
#undef CRAFTING_MACHINERY_USE
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#define HEATER_MODE_STANDBY "standby"
|
||||
#define HEATER_MODE_HEAT "heat"
|
||||
#define HEATER_MODE_COOL "cool"
|
||||
#define HEATER_MODE_AUTO "auto"
|
||||
|
||||
/obj/machinery/space_heater
|
||||
anchored = FALSE
|
||||
@@ -16,10 +17,10 @@
|
||||
circuit = /obj/item/circuitboard/machine/space_heater
|
||||
/// We don't use area power, we always use the cell
|
||||
use_power = NO_POWER_USE
|
||||
var/obj/item/stock_parts/cell/cell
|
||||
var/obj/item/stock_parts/cell/cell = /obj/item/stock_parts/cell
|
||||
var/on = FALSE
|
||||
var/mode = HEATER_MODE_STANDBY
|
||||
var/setMode = "auto" // Anything other than "heat" or "cool" is considered auto.
|
||||
var/setMode = HEATER_MODE_AUTO // Anything other than "heat" or "cool" is considered auto.
|
||||
var/targetTemperature = T20C
|
||||
var/heatingPower = 20000
|
||||
var/efficiency = 20000
|
||||
@@ -32,7 +33,8 @@
|
||||
|
||||
/obj/machinery/space_heater/Initialize()
|
||||
. = ..()
|
||||
cell = new(src)
|
||||
if(ispath(cell))
|
||||
cell = new cell(src)
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/space_heater/on_construction()
|
||||
@@ -60,7 +62,8 @@
|
||||
|
||||
/obj/machinery/space_heater/update_icon_state()
|
||||
icon_state = "[base_icon_state]-[on ? mode : "off"]"
|
||||
return ..()
|
||||
. = ..()
|
||||
return
|
||||
|
||||
/obj/machinery/space_heater/update_overlays()
|
||||
. = ..()
|
||||
@@ -179,6 +182,7 @@
|
||||
data["on"] = on
|
||||
data["mode"] = setMode
|
||||
data["hasPowercell"] = !!cell
|
||||
data["chemHacked"] = FALSE
|
||||
if(cell)
|
||||
data["powerLevel"] = round(cell.percent(), 1)
|
||||
data["targetTemp"] = round(targetTemperature - T0C, 1)
|
||||
@@ -232,6 +236,174 @@
|
||||
cell = null
|
||||
. = TRUE
|
||||
|
||||
///For use with heating reagents in a ghetto way
|
||||
/obj/machinery/space_heater/improvised_chem_heater
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "sheater-off"
|
||||
name = "Improvised chem heater"
|
||||
desc = "A space heater hacked to reroute heating to a water bath on the top."
|
||||
panel_open = TRUE //This is always open - since we've injected wires in the panel
|
||||
//We inherit the cell from the heater prior
|
||||
cell = null
|
||||
///The beaker within the heater
|
||||
var/obj/item/reagent_containers/beaker = null
|
||||
///How powerful the heating is, upgrades with parts. (ala chem_heater.dm's method, basically the same level of heating, but this is restricted)
|
||||
var/chem_heating_power = 1
|
||||
|
||||
/obj/machinery/space_heater/improvised_chem_heater/Destroy()
|
||||
. = ..()
|
||||
QDEL_NULL(beaker)
|
||||
|
||||
/obj/machinery/space_heater/improvised_chem_heater/process(delta_time)
|
||||
if(!on)
|
||||
update_appearance()
|
||||
return PROCESS_KILL
|
||||
|
||||
if(!is_operational || !cell || cell.charge <= 0)
|
||||
on = FALSE
|
||||
update_appearance()
|
||||
return PROCESS_KILL
|
||||
|
||||
if(!beaker)//No beaker to heat
|
||||
update_appearance()
|
||||
return
|
||||
|
||||
if(beaker.reagents.total_volume)
|
||||
var/power_mod = 0.1 * chem_heating_power
|
||||
switch(setMode)
|
||||
if(HEATER_MODE_AUTO)
|
||||
power_mod *= 0.5
|
||||
beaker.reagents.adjust_thermal_energy((targetTemperature - beaker.reagents.chem_temp) * power_mod * delta_time * SPECIFIC_HEAT_DEFAULT * beaker.reagents.total_volume)
|
||||
beaker.reagents.handle_reactions()
|
||||
if(HEATER_MODE_HEAT)
|
||||
if(targetTemperature < beaker.reagents.chem_temp)
|
||||
return
|
||||
beaker.reagents.adjust_thermal_energy((targetTemperature - beaker.reagents.chem_temp) * power_mod * delta_time * SPECIFIC_HEAT_DEFAULT * beaker.reagents.total_volume)
|
||||
if(HEATER_MODE_COOL)
|
||||
if(targetTemperature > beaker.reagents.chem_temp)
|
||||
return
|
||||
beaker.reagents.adjust_thermal_energy((targetTemperature - beaker.reagents.chem_temp) * power_mod * delta_time * SPECIFIC_HEAT_DEFAULT * beaker.reagents.total_volume)
|
||||
var/requiredEnergy = heatingPower * delta_time * (power_mod * 4)
|
||||
cell.use(requiredEnergy / efficiency)
|
||||
beaker.reagents.handle_reactions()
|
||||
update_appearance()
|
||||
|
||||
/obj/machinery/space_heater/improvised_chem_heater/ui_data()
|
||||
. = ..()
|
||||
.["chemHacked"] = TRUE
|
||||
.["beaker"] = beaker
|
||||
.["currentTemp"] = beaker ? (round(beaker.reagents.chem_temp - T0C)) : "N/A"
|
||||
|
||||
/obj/machinery/space_heater/improvised_chem_heater/ui_act(action, params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
switch(action)
|
||||
if("ejectBeaker")
|
||||
//Eject doesn't turn it off, so you can preheat for beaker swapping
|
||||
replace_beaker(usr)
|
||||
. = TRUE
|
||||
|
||||
///Slightly modified to ignore the open_hatch - it's always open, we hacked it.
|
||||
/obj/machinery/space_heater/improvised_chem_heater/attackby(obj/item/item, mob/user, params)
|
||||
add_fingerprint(user)
|
||||
if(default_unfasten_wrench(user, item))
|
||||
return
|
||||
if(default_deconstruction_crowbar(item))
|
||||
return
|
||||
if(istype(item, /obj/item/stock_parts/cell))
|
||||
if(cell)
|
||||
to_chat(user, "<span class='warning'>There is already a power cell inside!</span>")
|
||||
return
|
||||
else if(!user.transferItemToLoc(item, src))
|
||||
return
|
||||
cell = item
|
||||
item.add_fingerprint(usr)
|
||||
|
||||
user.visible_message("<span class='notice'>\The [user] inserts a power cell into \the [src].</span>", "<span class='notice'>You insert the power cell into \the [src].</span>")
|
||||
SStgui.update_uis(src)
|
||||
//reagent containers
|
||||
if(is_reagent_container(item) && !(item.item_flags & ABSTRACT) && item.is_open_container())
|
||||
. = TRUE //no afterattack
|
||||
var/obj/item/reagent_containers/container = item
|
||||
if(!user.transferItemToLoc(container, src))
|
||||
return
|
||||
replace_beaker(user, container)
|
||||
to_chat(user, "<span class='notice'>You add [container] to [src]'s water bath.</span>")
|
||||
updateUsrDialog()
|
||||
return
|
||||
//Dropper tools
|
||||
if(beaker)
|
||||
if(is_type_in_list(item, list(/obj/item/reagent_containers/dropper, /obj/item/ph_meter, /obj/item/ph_paper, /obj/item/reagent_containers/syringe)))
|
||||
item.afterattack(beaker, user, 1)
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/space_heater/improvised_chem_heater/on_deconstruction(disassembled = TRUE)
|
||||
. = ..()
|
||||
if(disassembled)
|
||||
beaker?.forceMove(drop_location())
|
||||
beaker = null
|
||||
var/static/bonus_junk = list(
|
||||
/obj/item/stack/cable_coil = 2,
|
||||
/obj/item/stack/sheet/glass = 2,
|
||||
/obj/item/stack/sheet/iron = 2,
|
||||
/obj/item/thermometer = 1
|
||||
)
|
||||
for(var/item in bonus_junk)
|
||||
if(prob(80))
|
||||
new item(get_turf(loc))
|
||||
|
||||
/obj/machinery/space_heater/improvised_chem_heater/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
|
||||
if(!user)
|
||||
return FALSE
|
||||
if(beaker)
|
||||
try_put_in_hand(beaker, user)
|
||||
beaker = null
|
||||
if(new_beaker)
|
||||
beaker = new_beaker
|
||||
update_appearance()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/space_heater/improvised_chem_heater/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(!can_interact(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
replace_beaker(user)
|
||||
|
||||
/obj/machinery/space_heater/improvised_chem_heater/update_icon_state()
|
||||
. = ..()
|
||||
if(!on || !beaker || !cell)
|
||||
icon_state = "sheater-off"
|
||||
return
|
||||
if(targetTemperature < beaker.reagents.chem_temp)
|
||||
icon_state = "sheater-cool"
|
||||
return
|
||||
if(targetTemperature > beaker.reagents.chem_temp)
|
||||
icon_state = "sheater-heat"
|
||||
return
|
||||
icon_state = "sheater-off"
|
||||
|
||||
/obj/machinery/space_heater/improvised_chem_heater/RefreshParts()
|
||||
var/lasers_rating = 0
|
||||
var/capacitors_rating = 0
|
||||
for(var/obj/item/stock_parts/micro_laser/laser in component_parts)
|
||||
lasers_rating += laser.rating
|
||||
for(var/obj/item/stock_parts/capacitor/capacitor in component_parts)
|
||||
capacitors_rating += capacitor.rating
|
||||
|
||||
heatingPower = lasers_rating * 20000
|
||||
|
||||
settableTemperatureRange = capacitors_rating * 50 //-20 - 80 at base
|
||||
efficiency = (capacitors_rating + 1) * 10000
|
||||
|
||||
targetTemperature = clamp(targetTemperature,
|
||||
max(settableTemperatureMedian - settableTemperatureRange, TCMB),
|
||||
settableTemperatureMedian + settableTemperatureRange)
|
||||
|
||||
chem_heating_power = efficiency/20000 //1-2.5
|
||||
|
||||
#undef HEATER_MODE_STANDBY
|
||||
#undef HEATER_MODE_HEAT
|
||||
#undef HEATER_MODE_COOL
|
||||
#undef HEATER_MODE_AUTO
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
/obj/effect/particle_effect/water/Bump(atom/A)
|
||||
if(reagents)
|
||||
reagents.expose(A)
|
||||
if(A.reagents)
|
||||
A.reagents.expose_temperature(-25)
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -51,3 +53,7 @@
|
||||
|
||||
/datum/effect_system/steam_spread
|
||||
effect_type = /obj/effect/particle_effect/steam
|
||||
|
||||
/obj/effect/particle_effect/water/Bump(atom/A)
|
||||
if(A.reagents && reagents)
|
||||
A.reagents.expose_temperature(reagents.chem_temp)
|
||||
|
||||
@@ -44,6 +44,28 @@
|
||||
sprite_name = "miniFE"
|
||||
dog_fashion = null
|
||||
|
||||
/obj/item/extinguisher/crafted
|
||||
name = "Improvised cooling spray"
|
||||
desc = "Spraycan turned coolant dipsenser. Can be sprayed on containers to cool them. Refll using water."
|
||||
icon_state = "coolant0"
|
||||
inhand_icon_state = "miniFE"
|
||||
hitsound = null //it is much lighter, after all.
|
||||
flags_1 = null //doesn't CONDUCT_1
|
||||
throwforce = 1
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
force = 3
|
||||
custom_materials = list(/datum/material/iron = 50, /datum/material/glass = 40)
|
||||
max_water = 30
|
||||
sprite_name = "coolant"
|
||||
dog_fashion = null
|
||||
cooling_power = 1.5
|
||||
power = 3
|
||||
|
||||
/obj/item/extinguisher/crafted/attack_self(mob/user)
|
||||
safety = !safety
|
||||
icon_state = "[sprite_name][!safety]"
|
||||
to_chat(user, "[safety ? "You remove the straw and put it on the side of the cool canister" : "You insert the straw, readying it for use"].")
|
||||
|
||||
/obj/item/extinguisher/proc/refill()
|
||||
if(!chem)
|
||||
return
|
||||
|
||||
@@ -116,6 +116,20 @@
|
||||
if(hotness && reagents)
|
||||
reagents.expose_temperature(hotness)
|
||||
to_chat(user, "<span class='notice'>You heat [name] with [I]!</span>")
|
||||
|
||||
//Cooling method
|
||||
if(istype(I, /obj/item/extinguisher))
|
||||
var/obj/item/extinguisher/extinguisher = I
|
||||
if(extinguisher.safety)
|
||||
return
|
||||
if(extinguisher.reagents.total_volume < 1)
|
||||
to_chat(user, "<span class='warning'>\The [extinguisher] is empty!</span>")
|
||||
return
|
||||
var/cooling = (0 - reagents.chem_temp) * (extinguisher.cooling_power * 2)
|
||||
reagents.expose_temperature(cooling)
|
||||
to_chat(user, "<span class='notice'>You cool the [name] with the [I]!</span>")
|
||||
playsound(loc, 'sound/effects/extinguish.ogg', 75, TRUE, -3)
|
||||
extinguisher.reagents.remove_all(1)
|
||||
..()
|
||||
|
||||
/obj/item/reagent_containers/food/drinks/throw_impact(atom/hit_atom, datum/thrownthing/throwingdatum)
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
new /obj/item/food/chocolatebar(location)
|
||||
return
|
||||
|
||||
/datum/chemical_reaction/soysauce
|
||||
/datum/chemical_reaction/food/soysauce
|
||||
results = list(/datum/reagent/consumable/soysauce = 5)
|
||||
required_reagents = list(/datum/reagent/consumable/soymilk = 4, /datum/reagent/toxin/acid = 1)
|
||||
|
||||
|
||||
@@ -79,45 +79,15 @@
|
||||
var/used = FALSE
|
||||
|
||||
/obj/item/ph_paper/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
var/obj/item/reagent_containers/cont = target
|
||||
if(!istype(cont))
|
||||
if(!is_reagent_container(target))
|
||||
return
|
||||
var/obj/item/reagent_containers/cont = target
|
||||
if(used == TRUE)
|
||||
to_chat(user, "<span class='warning'>[src] has already been used!</span>")
|
||||
return
|
||||
if(!LAZYLEN(cont.reagents.reagent_list))
|
||||
return
|
||||
switch(round(cont.reagents.ph, 1))
|
||||
if(14 to INFINITY)
|
||||
color = "#462c83"
|
||||
if(13 to 14)
|
||||
color = "#63459b"
|
||||
if(12 to 13)
|
||||
color = "#5a51a2"
|
||||
if(11 to 12)
|
||||
color = "#3853a4"
|
||||
if(10 to 11)
|
||||
color = "#3f93cf"
|
||||
if(9 to 10)
|
||||
color = "#0bb9b7"
|
||||
if(8 to 9)
|
||||
color = "#23b36e"
|
||||
if(7 to 8)
|
||||
color = "#3aa651"
|
||||
if(6 to 7)
|
||||
color = "#4cb849"
|
||||
if(5 to 6)
|
||||
color = "#b5d335"
|
||||
if(4 to 5)
|
||||
color = "#f7ec1e"
|
||||
if(3 to 4)
|
||||
color = "#fbc314"
|
||||
if(2 to 3)
|
||||
color = "#f26724"
|
||||
if(1 to 2)
|
||||
color = "#ef1d26"
|
||||
if(-INFINITY to 1)
|
||||
color = "#c6040c"
|
||||
CONVERT_PH_TO_COLOR(round(cont.reagents.ph, 1), color)
|
||||
desc += " The paper looks to be around a pH of [round(cont.reagents.ph, 1)]"
|
||||
name = "used [name]"
|
||||
used = TRUE
|
||||
@@ -130,7 +100,6 @@
|
||||
desc = "An electrode attached to a small circuit box that will display details of a solution. Can be toggled to provide a description of each of the reagents. The screen currently displays nothing."
|
||||
icon_state = "pHmeter"
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
resistance_flags = FLAMMABLE
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
///level of detail for output for the meter
|
||||
var/scanmode = DETAILED_CHEM_OUTPUT
|
||||
@@ -145,7 +114,7 @@
|
||||
|
||||
/obj/item/ph_meter/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(!istype(target, /obj/item/reagent_containers))
|
||||
if(!is_reagent_container(target))
|
||||
return
|
||||
var/obj/item/reagent_containers/cont = target
|
||||
if(LAZYLEN(cont.reagents.reagent_list) == null)
|
||||
@@ -162,3 +131,203 @@
|
||||
out_message += "<b>Analysis:</b> [R.description]\n"
|
||||
to_chat(user, "[out_message.Join()]</span>")
|
||||
desc = "An electrode attached to a small circuit box that will display details of a solution. Can be toggled to provide a description of each of the reagents. The screen currently displays detected vol: [round(cont.volume, 0.01)] detected pH:[round(cont.reagents.ph, 0.1)]."
|
||||
|
||||
/obj/item/burner
|
||||
name = "Alcohol burner"
|
||||
desc = "A small table size burner used for heating up beakers."
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
icon_state = "burner"
|
||||
grind_results = list(/datum/reagent/consumable/ethanol = 5, /datum/reagent/silicon = 10)
|
||||
item_flags = NOBLUDGEON
|
||||
resistance_flags = FLAMMABLE
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
heat = 2000
|
||||
///If the flame is lit - i.e. if we're processing and burning
|
||||
var/lit = FALSE
|
||||
///total reagent volume
|
||||
var/max_volume = 50
|
||||
///What the creation reagent is
|
||||
var/reagent_type = /datum/reagent/consumable/ethanol
|
||||
|
||||
/obj/item/burner/Initialize()
|
||||
. = ..()
|
||||
create_reagents(max_volume, TRANSPARENT)//We have our own refillable - since we want to heat and pour
|
||||
if(reagent_type)
|
||||
reagents.add_reagent(reagent_type, 15)
|
||||
|
||||
/obj/item/burner/attackby(obj/item/I, mob/living/user, params)
|
||||
. = ..()
|
||||
if(is_reagent_container(I))
|
||||
if(lit)
|
||||
var/obj/item/reagent_containers/container = I
|
||||
container.reagents.expose_temperature(get_temperature())
|
||||
to_chat(user, "<span class='notice'>You heat up the [I] with the [src].</span>")
|
||||
playsound(user.loc, 'sound/chemistry/heatdam.ogg', 50, TRUE)
|
||||
return
|
||||
else if(I.is_drainable()) //Transfer FROM it TO us. Special code so it only happens when flame is off.
|
||||
var/obj/item/reagent_containers/container = I
|
||||
if(!container.reagents.total_volume)
|
||||
to_chat(user, "<span class='warning'>[container] is empty and can't be poured!</span>")
|
||||
return
|
||||
|
||||
if(reagents.holder_full())
|
||||
to_chat(user, "<span class='warning'>[src] is full.</span>")
|
||||
return
|
||||
|
||||
var/trans = container.reagents.trans_to(src, container.amount_per_transfer_from_this, transfered_by = user)
|
||||
to_chat(user, "<span class='notice'>You fill [src] with [trans] unit\s of the contents of [container].</span>")
|
||||
if(I.heat < 1000)
|
||||
return
|
||||
set_lit(TRUE)
|
||||
user.visible_message("<span class='notice'>[user] lights up the [src].</span>")
|
||||
|
||||
/obj/item/burner/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(lit)
|
||||
if(is_reagent_container(target))
|
||||
var/obj/item/reagent_containers/container = target
|
||||
container.reagents.expose_temperature(get_temperature())
|
||||
to_chat(user, "<span class='notice'>You heat up the [src].</span>")
|
||||
playsound(user.loc, 'sound/chemistry/heatdam.ogg', 50, TRUE)
|
||||
return
|
||||
else if(isitem(target))
|
||||
var/obj/item/item = target
|
||||
if(item.heat > 1000)
|
||||
set_lit(TRUE)
|
||||
user.visible_message("<span class='notice'>[user] lights up the [src].</span>")
|
||||
|
||||
/obj/item/burner/update_icon_state()
|
||||
. = ..()
|
||||
icon_state = "[initial(icon_state)][lit ? "-on" : ""]"
|
||||
|
||||
/obj/item/burner/proc/set_lit(new_lit)
|
||||
if(lit == new_lit)
|
||||
return
|
||||
lit = new_lit
|
||||
if(lit)
|
||||
force = 5
|
||||
damtype = BURN
|
||||
hitsound = 'sound/items/welder.ogg'
|
||||
attack_verb_continuous = string_list(list("burns", "sings"))
|
||||
attack_verb_simple = string_list(list("burn", "sing"))
|
||||
START_PROCESSING(SSobj, src)
|
||||
else
|
||||
hitsound = "swing_hit"
|
||||
force = 0
|
||||
attack_verb_continuous = null //human_defense.dm takes care of it
|
||||
attack_verb_simple = null
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
set_light_on(lit)
|
||||
update_icon()
|
||||
|
||||
/obj/item/burner/extinguish()
|
||||
set_lit(FALSE)
|
||||
|
||||
/obj/item/burner/attack_self(mob/living/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(lit)
|
||||
set_lit(FALSE)
|
||||
user.visible_message("<span class='notice'>[user] snuffs out [src]'s flame.</span>")
|
||||
|
||||
/obj/item/burner/attack(mob/living/carbon/M, mob/living/carbon/user)
|
||||
if(lit && M.IgniteMob())
|
||||
message_admins("[ADMIN_LOOKUPFLW(user)] set [key_name_admin(M)] on fire with [src] at [AREACOORD(user)]")
|
||||
log_game("[key_name(user)] set [key_name(M)] on fire with [src] at [AREACOORD(user)]")
|
||||
return ..()
|
||||
|
||||
/obj/item/burner/process()
|
||||
var/current_heat = 0
|
||||
var/number_of_burning_reagents = 0
|
||||
for(var/datum/reagent/reagent as anything in reagents.reagent_list)
|
||||
reagent.burn(reagents) //burn can set temperatures of reagents
|
||||
if(!isnull(reagent.burning_temperature))
|
||||
current_heat += reagent.burning_temperature
|
||||
number_of_burning_reagents += 1
|
||||
reagents.remove_reagent(reagent.type, reagent.burning_volume)
|
||||
continue
|
||||
|
||||
if(!number_of_burning_reagents)
|
||||
set_lit(FALSE)
|
||||
heat = 0
|
||||
return
|
||||
open_flame()
|
||||
current_heat /= number_of_burning_reagents
|
||||
heat = current_heat
|
||||
|
||||
/obj/item/burner/get_temperature()
|
||||
return lit * heat
|
||||
|
||||
/obj/item/burner/oil
|
||||
name = "Oil burner"
|
||||
reagent_type = /datum/reagent/fuel/oil
|
||||
grind_results = list(/datum/reagent/fuel/oil = 5, /datum/reagent/silicon = 10)
|
||||
|
||||
/obj/item/burner/fuel
|
||||
name = "Fuel burner"
|
||||
reagent_type = /datum/reagent/fuel
|
||||
grind_results = list(/datum/reagent/fuel = 5, /datum/reagent/silicon = 10)
|
||||
|
||||
/obj/item/thermometer
|
||||
name = "thermometer"
|
||||
desc = "A thermometer for checking a beaker's temperature"
|
||||
icon_state = "thermometer"
|
||||
icon = 'icons/obj/chemical.dmi'
|
||||
item_flags = NOBLUDGEON
|
||||
w_class = WEIGHT_CLASS_TINY
|
||||
grind_results = list(/datum/reagent/mercury = 5)
|
||||
///The reagents datum that this object is attached to, so we know where we are when it's added to something.
|
||||
var/datum/reagents/attached_to_reagents
|
||||
|
||||
/obj/item/thermometer/Destroy()
|
||||
QDEL_NULL(attached_to_reagents) //I have no idea how you can destroy this, but not the beaker, but here we go
|
||||
return ..()
|
||||
|
||||
/obj/item/thermometer/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
||||
. = ..()
|
||||
if(target.reagents)
|
||||
if(!user.transferItemToLoc(src, target))
|
||||
return
|
||||
attached_to_reagents = target.reagents
|
||||
to_chat(user, "<span class='notice'>You add the [src] to the [target].</span>")
|
||||
ui_interact(usr, null)
|
||||
|
||||
/obj/item/thermometer/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "Thermometer", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/thermometer/ui_close(mob/user)
|
||||
. = ..()
|
||||
remove_thermometer(user)
|
||||
|
||||
/obj/item/thermometer/ui_status(mob/user)
|
||||
if(!(in_range(src, user)))
|
||||
return UI_CLOSE
|
||||
return UI_INTERACTIVE
|
||||
|
||||
/obj/item/thermometer/ui_state(mob/user)
|
||||
return GLOB.physical_state
|
||||
|
||||
/obj/item/thermometer/ui_data(mob/user)
|
||||
if(!attached_to_reagents)
|
||||
ui_close(user)
|
||||
var/data = list()
|
||||
data["Temperature"] = round(attached_to_reagents.chem_temp)
|
||||
return data
|
||||
|
||||
/obj/item/thermometer/proc/remove_thermometer(mob/target)
|
||||
try_put_in_hand(src, target)
|
||||
attached_to_reagents = null
|
||||
|
||||
/obj/item/thermometer/proc/try_put_in_hand(obj/object, mob/living/user)
|
||||
to_chat(user, "<span class='notice'>You remove the [src] from the [attached_to_reagents.my_atom].</span>")
|
||||
if(!issilicon(user) && in_range(src.loc, user))
|
||||
user.put_in_hands(object)
|
||||
else
|
||||
object.forceMove(drop_location())
|
||||
|
||||
/obj/item/thermometer/pen
|
||||
color = "#888888"
|
||||
|
||||
@@ -81,10 +81,15 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
|
||||
var/impure_chem = /datum/reagent/impurity
|
||||
/// If the impurity is below 0.5, replace ALL of the chem with inverse_chem upon metabolising
|
||||
var/inverse_chem_val = 0.25
|
||||
/// What chem is metabolised when purity is below inverse_chem_val
|
||||
/// What chem is metabolised when purity is below inverse_chem_val
|
||||
var/inverse_chem = /datum/reagent/impurity/toxic
|
||||
///what chem is made at the end of a reaction IF the purity is below the recipies purity_min at the END of a reaction only
|
||||
var/failed_chem = /datum/reagent/consumable/failed_reaction
|
||||
///Thermodynamic vars
|
||||
///How hot this reagent burns when it's on fire - null means it can't burn
|
||||
var/burning_temperature = null
|
||||
///How much is consumed when it is burnt per second
|
||||
var/burning_volume = 0.5
|
||||
///Assoc list with key type of addiction this reagent feeds, and value amount of addiction points added per unit of reagent metabolzied (which means * REAGENTS_METABOLISM every life())
|
||||
var/list/addiction_types = null
|
||||
|
||||
@@ -129,6 +134,10 @@ GLOBAL_LIST_INIT(name2reagent, build_name2reagent())
|
||||
|
||||
return SEND_SIGNAL(src, COMSIG_REAGENT_EXPOSE_TURF, exposed_turf, reac_volume)
|
||||
|
||||
///Called whenever a reagent is on fire, or is in a holder that is on fire. (WIP)
|
||||
/datum/reagent/proc/burn(datum/reagents/holder)
|
||||
return
|
||||
|
||||
/// Called from [/datum/reagents/proc/metabolize]
|
||||
/datum/reagent/proc/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
|
||||
current_cycle++
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
taste_description = "alcohol"
|
||||
metabolization_rate = 0.5 * REAGENTS_METABOLISM
|
||||
ph = 7.33
|
||||
burning_temperature = 2193//ethanol burns at 1970C (at it's peak)
|
||||
burning_volume = 0.1
|
||||
var/boozepwr = 65 //Higher numbers equal higher hardness, higher hardness equals more intense alcohol poisoning
|
||||
|
||||
/*
|
||||
|
||||
@@ -156,6 +156,8 @@
|
||||
color = "#0000C8"
|
||||
taste_description = "blue"
|
||||
ph = 11
|
||||
burning_temperature = 20 //cold burning
|
||||
burning_volume = 0.1
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
|
||||
/datum/reagent/medicine/cryoxadone/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
|
||||
|
||||
@@ -12,6 +12,12 @@
|
||||
penetrates_skin = NONE
|
||||
ph = 7.4
|
||||
|
||||
// FEED ME
|
||||
/datum/reagent/blood/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray)
|
||||
. = ..()
|
||||
if(chems.has_reagent(type, 1))
|
||||
mytray.adjustPests(rand(2,3))
|
||||
|
||||
/datum/reagent/blood/expose_mob(mob/living/exposed_mob, methods=TOUCH, reac_volume, show_message=TRUE, touch_protection=0)
|
||||
. = ..()
|
||||
if(data && data["viruses"])
|
||||
@@ -224,6 +230,14 @@
|
||||
ph = 7.5 //God is alkaline
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
|
||||
// Holy water. Mostly the same as water, it also heals the plant a little with the power of the spirits. Also ALSO increases instability.
|
||||
/datum/reagent/water/holywater/on_hydroponics_apply(obj/item/seeds/myseed, datum/reagents/chems, obj/machinery/hydroponics/mytray)
|
||||
if(chems.has_reagent(type, 1))
|
||||
mytray.adjustWater(round(chems.get_reagent_amount(type) * 1))
|
||||
mytray.adjustHealth(round(chems.get_reagent_amount(type) * 0.1))
|
||||
if(myseed)
|
||||
myseed.adjust_instability(round(chems.get_reagent_amount(type) * 0.15))
|
||||
|
||||
/datum/reagent/water/holywater/on_mob_metabolize(mob/living/L)
|
||||
..()
|
||||
ADD_TRAIT(L, TRAIT_HOLY, type)
|
||||
@@ -1103,6 +1117,8 @@
|
||||
glass_desc = "Unless you're an industrial tool, this is probably not safe for consumption."
|
||||
penetrates_skin = NONE
|
||||
ph = 4
|
||||
burning_temperature = 1725 //more refined than oil
|
||||
burning_volume = 0.2
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
addiction_types = list(/datum/addiction/alcohol = 4)
|
||||
|
||||
@@ -1711,6 +1727,8 @@
|
||||
reagent_state = LIQUID
|
||||
color = "#2D2D2D"
|
||||
taste_description = "oil"
|
||||
burning_temperature = 1200//Oil is crude
|
||||
burning_volume = 0.05 //but has a lot of hydrocarbons
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
addiction_types = null
|
||||
|
||||
@@ -2573,3 +2591,16 @@
|
||||
M.adjustBruteLoss(2 * REM * delta_time, FALSE)
|
||||
..()
|
||||
|
||||
/datum/reagent/universal_indicator
|
||||
name = "Universal indicator"
|
||||
description = "A solution that can be used to create pH paper booklets, or sprayed on things to colour them by their pH."
|
||||
taste_description = "a strong chemical taste"
|
||||
color = "#1f8016"
|
||||
|
||||
//Colours things by their pH
|
||||
/datum/reagent/universal_indicator/expose_atom(atom/exposed_atom, reac_volume)
|
||||
. = ..()
|
||||
if(exposed_atom.reagents)
|
||||
var/color
|
||||
CONVERT_PH_TO_COLOR(exposed_atom.reagents.ph, color)
|
||||
exposed_atom.add_atom_colour(color, WASHABLE_COLOUR_PRIORITY)
|
||||
|
||||
@@ -216,8 +216,14 @@
|
||||
metabolization_rate = 0.5 * REAGENTS_METABOLISM
|
||||
taste_description = "bitterness"
|
||||
self_consuming = TRUE
|
||||
burning_volume = 0.05
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
|
||||
/datum/reagent/cryostylane/burn(datum/reagents/holder)
|
||||
if(holder.has_reagent(/datum/reagent/oxygen))
|
||||
burning_temperature = 0//king chilly
|
||||
return
|
||||
burning_temperature = null
|
||||
|
||||
/datum/reagent/cryostylane/on_mob_life(mob/living/carbon/M, delta_time, times_fired) //TODO: code freezing into an ice cube
|
||||
if(M.reagents.has_reagent(/datum/reagent/oxygen))
|
||||
@@ -242,6 +248,8 @@
|
||||
metabolization_rate = 0.5 * REAGENTS_METABOLISM
|
||||
taste_description = "bitterness"
|
||||
self_consuming = TRUE
|
||||
burning_temperature = null
|
||||
burning_volume = 0.05
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
|
||||
/datum/reagent/pyrosium/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
|
||||
@@ -253,6 +261,12 @@
|
||||
humi.adjust_coretemperature(15 * REM * delta_time)
|
||||
..()
|
||||
|
||||
/datum/reagent/pyrosium/burn(datum/reagents/holder)
|
||||
if(holder.has_reagent(/datum/reagent/oxygen))
|
||||
burning_temperature = 3500
|
||||
return
|
||||
burning_temperature = null
|
||||
|
||||
/datum/reagent/teslium //Teslium. Causes periodic shocks, and makes shocks against the target much more effective.
|
||||
name = "Teslium"
|
||||
description = "An unstable, electrically-charged metallic slurry. Periodically electrocutes its victim, and makes electrocutions against them more deadly. Excessively heating teslium results in dangerous destabilization. Do not allow to come into contact with water."
|
||||
|
||||
@@ -78,6 +78,8 @@
|
||||
material = /datum/material/plasma
|
||||
penetrates_skin = NONE
|
||||
ph = 4
|
||||
burning_temperature = 4500//plasma is hot!!
|
||||
burning_volume = 0.3//But burns fast
|
||||
chemical_flags = REAGENT_CAN_BE_SYNTHESIZED
|
||||
|
||||
/datum/reagent/toxin/plasma/on_new(data)
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
///Determines if a chemical reaction can occur inside a mob
|
||||
var/mob_react = TRUE
|
||||
|
||||
///The message shown to nearby people upon mixing, if applicable
|
||||
var/mix_message = "The solution begins to bubble."
|
||||
///The sound played upon mixing, if applicable
|
||||
|
||||
@@ -643,3 +643,50 @@
|
||||
for(var/i in 1 to created_volume)
|
||||
new /obj/item/stack/sheet/mineral/silver(location)
|
||||
|
||||
//////////////////////////////////// Water ////////////////////////////////////////////////
|
||||
|
||||
/datum/chemical_reaction/ice
|
||||
results = list(/datum/reagent/consumable/ice = 1.09)//density
|
||||
required_reagents = list(/datum/reagent/water = 1)
|
||||
is_cold_recipe = TRUE
|
||||
required_temp = 274 // So we can be sure that basic ghetto rigged stuff can freeze
|
||||
optimal_temp = 200
|
||||
overheat_temp = 0
|
||||
optimal_ph_min = 0
|
||||
optimal_ph_max = 14
|
||||
thermic_constant = 0
|
||||
H_ion_release = 0
|
||||
rate_up_lim = 50
|
||||
purity_min = 0
|
||||
mix_message = "The solution freezes up into ice!"
|
||||
reaction_flags = REACTION_COMPETITIVE
|
||||
|
||||
/datum/chemical_reaction/water
|
||||
results = list(/datum/reagent/water = 0.92)//rough density excahnge
|
||||
required_reagents = list(/datum/reagent/consumable/ice = 1)
|
||||
required_temp = 275
|
||||
optimal_temp = 350
|
||||
overheat_temp = 99999
|
||||
optimal_ph_min = 0
|
||||
optimal_ph_max = 14
|
||||
thermic_constant = 0
|
||||
H_ion_release = 0
|
||||
rate_up_lim = 50
|
||||
purity_min = 0
|
||||
mix_message = "The ice melts back into water!"
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
/datum/chemical_reaction/universal_indicator
|
||||
results = list(/datum/reagent/universal_indicator = 3)//rough density excahnge
|
||||
required_reagents = list(/datum/reagent/ash = 1, /datum/reagent/consumable/ethanol = 1, /datum/reagent/iodine = 1)
|
||||
required_temp = 274
|
||||
optimal_temp = 350
|
||||
overheat_temp = 99999
|
||||
optimal_ph_min = 0
|
||||
optimal_ph_max = 14
|
||||
thermic_constant = 0
|
||||
H_ion_release = 0
|
||||
rate_up_lim = 50
|
||||
purity_min = 0
|
||||
mix_message = "The mixture's colors swirl together."
|
||||
|
||||
@@ -32,9 +32,6 @@
|
||||
RegisterSignal(reagents, list(COMSIG_REAGENTS_NEW_REAGENT, COMSIG_REAGENTS_ADD_REAGENT, COMSIG_REAGENTS_DEL_REAGENT, COMSIG_REAGENTS_REM_REAGENT), .proc/on_reagent_change)
|
||||
RegisterSignal(reagents, COMSIG_PARENT_QDELETING, .proc/on_reagents_del)
|
||||
|
||||
/obj/item/reagent_containers/Destroy()
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/attack(mob/living/M, mob/living/user, params)
|
||||
if (!user.combat_mode)
|
||||
return
|
||||
|
||||
@@ -86,6 +86,20 @@
|
||||
reagents.expose_temperature(hotness)
|
||||
to_chat(user, "<span class='notice'>You heat [name] with [I]!</span>")
|
||||
|
||||
//Cooling method
|
||||
if(istype(I, /obj/item/extinguisher))
|
||||
var/obj/item/extinguisher/extinguisher = I
|
||||
if(extinguisher.safety)
|
||||
return
|
||||
if (extinguisher.reagents.total_volume < 1)
|
||||
to_chat(user, "<span class='warning'>\The [extinguisher] is empty!</span>")
|
||||
return
|
||||
var/cooling = (0 - reagents.chem_temp) * extinguisher.cooling_power * 2
|
||||
reagents.expose_temperature(cooling)
|
||||
to_chat(user, "<span class='notice'>You cool the [name] with the [I]!</span>")
|
||||
playsound(loc, 'sound/effects/extinguish.ogg', 75, TRUE, -3)
|
||||
extinguisher.reagents.remove_all(1)
|
||||
|
||||
if(istype(I, /obj/item/food/egg)) //breaking eggs
|
||||
var/obj/item/food/egg/E = I
|
||||
if(reagents)
|
||||
|
||||
@@ -129,6 +129,21 @@
|
||||
if(hotness && reagents)
|
||||
reagents.expose_temperature(hotness)
|
||||
to_chat(user, "<span class='notice'>You heat [name] with [I]!</span>")
|
||||
|
||||
//Cooling method
|
||||
if(istype(I, /obj/item/extinguisher))
|
||||
var/obj/item/extinguisher/extinguisher = I
|
||||
if(extinguisher.safety)
|
||||
return
|
||||
if (extinguisher.reagents.total_volume < 1)
|
||||
to_chat(user, "<span class='warning'>\The [extinguisher] is empty!</span>")
|
||||
return
|
||||
var/cooling = (0 - reagents.chem_temp) * extinguisher.cooling_power * 2
|
||||
reagents.expose_temperature(cooling)
|
||||
to_chat(user, "<span class='notice'>You cool the [name] with the [I]!</span>")
|
||||
playsound(loc, 'sound/effects/extinguish.ogg', 75, TRUE, -3)
|
||||
extinguisher.reagents.remove_all(1)
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/item/reagent_containers/spray/verb/empty()
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 57 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
@@ -30,6 +30,11 @@ export const COLORS = {
|
||||
burn: '#e67e22',
|
||||
brute: '#e74c3c',
|
||||
},
|
||||
// reagent / chemistry related colours
|
||||
reagent: {
|
||||
acidicbuffer: "#fbc314",
|
||||
basicbuffer: "#3853a4",
|
||||
},
|
||||
};
|
||||
|
||||
// Colors defined in CSS
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { resolveAsset } from '../assets';
|
||||
import { round, toFixed } from 'common/math';
|
||||
import { resolveAsset } from '../assets';
|
||||
import { useBackend } from '../backend';
|
||||
import { AnimatedNumber, Box, Button, NumberInput, Section, ProgressBar, Table, RoundGauge, Flex, Icon, TextArea } from '../components';
|
||||
import { TableCell, TableRow } from '../components/Table';
|
||||
import { AnimatedNumber, Box, Button, Flex, Icon, NumberInput, ProgressBar, RoundGauge, Section, Table } from '../components';
|
||||
import { COLORS } from '../constants';
|
||||
import { Window } from '../layouts';
|
||||
import { BeakerContents } from './common/BeakerContents';
|
||||
|
||||
|
||||
export const ChemHeater = (props, context) => {
|
||||
const { act, data } = useBackend(context);
|
||||
const {
|
||||
@@ -26,7 +25,7 @@ export const ChemHeater = (props, context) => {
|
||||
beakerContents = [],
|
||||
activeReactions = [],
|
||||
} = data;
|
||||
return (
|
||||
return (
|
||||
<Window
|
||||
width={330}
|
||||
height={tutorialMessage ? 680 : 350}>
|
||||
@@ -51,17 +50,15 @@ export const ChemHeater = (props, context) => {
|
||||
)}>
|
||||
<Table>
|
||||
<Table.Row>
|
||||
<Table.Cell
|
||||
bold
|
||||
collapsing color="label">
|
||||
<Table.Cell bold collapsing color="label">
|
||||
Heat
|
||||
</Table.Cell>
|
||||
<TableCell />
|
||||
<Table.Cell />
|
||||
<Table.Cell bold collapsing color="label">
|
||||
Buffers
|
||||
</Table.Cell>
|
||||
<TableCell />
|
||||
<TableCell>
|
||||
<Table.Cell />
|
||||
<Table.Cell>
|
||||
<NumberInput
|
||||
width="45px"
|
||||
unit="u"
|
||||
@@ -73,13 +70,13 @@ export const ChemHeater = (props, context) => {
|
||||
onDrag={(e, value) => act('disp_vol', {
|
||||
target: value,
|
||||
})} />
|
||||
</TableCell>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<TableRow>
|
||||
<TableCell collapsing color="label">
|
||||
<Table.Row>
|
||||
<Table.Cell collapsing color="label">
|
||||
Target:
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<NumberInput
|
||||
width="65px"
|
||||
unit="K"
|
||||
@@ -91,11 +88,11 @@ export const ChemHeater = (props, context) => {
|
||||
onDrag={(e, value) => act('temperature', {
|
||||
target: value,
|
||||
})} />
|
||||
</TableCell>
|
||||
<TableCell collapsing color="label">
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing color="label">
|
||||
Acidic:
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
icon={'syringe'}
|
||||
disabled={!acidicBufferVol}
|
||||
@@ -104,11 +101,11 @@ export const ChemHeater = (props, context) => {
|
||||
onClick={() => act('acidBuffer', {
|
||||
target: 1,
|
||||
})} />
|
||||
</TableCell>
|
||||
<TableCell color={"#fbc314"} textAlign="center">
|
||||
{acidicBufferVol+"u"}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
</Table.Cell>
|
||||
<Table.Cell color={COLORS.reagent.acidicbuffer} textAlign="center">
|
||||
{acidicBufferVol + "u"}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
icon={'upload'}
|
||||
tooltip={'Draw all'}
|
||||
@@ -117,13 +114,13 @@ export const ChemHeater = (props, context) => {
|
||||
onClick={() => act('acidBuffer', {
|
||||
target: -100,
|
||||
})} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow>
|
||||
<TableCell collapsing color="label">
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
<Table.Row>
|
||||
<Table.Cell collapsing color="label">
|
||||
Reading:
|
||||
</TableCell>
|
||||
<TableCell collapsing color="default">
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing color="default">
|
||||
<Box
|
||||
width="60px"
|
||||
textAlign="right">
|
||||
@@ -133,24 +130,24 @@ export const ChemHeater = (props, context) => {
|
||||
format={value => toFixed(value) + ' K'} />
|
||||
) || '—'}
|
||||
</Box>
|
||||
</TableCell>
|
||||
<TableCell collapsing color="label">
|
||||
</Table.Cell>
|
||||
<Table.Cell collapsing color="label">
|
||||
Basic:
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
icon={'syringe'}
|
||||
tooltip={'Inject'}
|
||||
tooltipPosition={"left"}
|
||||
tooltipPosition={"left"}
|
||||
disabled={!basicBufferVol}
|
||||
onClick={() => act('basicBuffer', {
|
||||
target: 1,
|
||||
})} />
|
||||
</TableCell>
|
||||
<TableCell color={"#3853a4"} textAlign="center">
|
||||
{basicBufferVol+"u"}
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
</Table.Cell>
|
||||
<Table.Cell color={COLORS.reagent.basicbuffer} textAlign="center">
|
||||
{basicBufferVol + "u"}
|
||||
</Table.Cell>
|
||||
<Table.Cell>
|
||||
<Button
|
||||
icon={'upload'}
|
||||
tooltip={'Draw all'}
|
||||
@@ -158,8 +155,8 @@ export const ChemHeater = (props, context) => {
|
||||
onClick={() => act('basicBuffer', {
|
||||
target: -100,
|
||||
})} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
</Table>
|
||||
</Section>
|
||||
{!!isBeakerLoaded && (
|
||||
@@ -175,7 +172,7 @@ export const ChemHeater = (props, context) => {
|
||||
<Flex.Item>
|
||||
<AnimatedNumber value={currentpH}>
|
||||
{(_, value) => (
|
||||
<RoundGauge
|
||||
<RoundGauge
|
||||
size={1.60}
|
||||
value={value}
|
||||
minValue={0}
|
||||
@@ -205,34 +202,34 @@ export const ChemHeater = (props, context) => {
|
||||
No active reactions.
|
||||
</Box>
|
||||
) || (
|
||||
<Table collapsing={false} key={"reactions"}>
|
||||
<TableRow>
|
||||
<TableCell bold color="label">
|
||||
<Table>
|
||||
<Table.Row>
|
||||
<Table.Cell bold color="label">
|
||||
Reaction
|
||||
</TableCell>
|
||||
<TableCell bold color="label">
|
||||
</Table.Cell>
|
||||
<Table.Cell bold color="label">
|
||||
{upgradeLevel < 4 ? "Status" : "Reaction quality"}
|
||||
</TableCell>
|
||||
<TableCell bold color="label">
|
||||
</Table.Cell>
|
||||
<Table.Cell bold color="label">
|
||||
Target
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
{activeReactions.map(reaction => (
|
||||
<TableRow key="reactions">
|
||||
<TableCell width={'60px'} color={reaction.danger ? "red" : "white"}>
|
||||
<Table.Row key="reactions">
|
||||
<Table.Cell width={'60px'} color={reaction.danger && "red"}>
|
||||
{reaction.name}
|
||||
</TableCell>
|
||||
<TableCell width={'100px'} pr={'10px'}>
|
||||
</Table.Cell>
|
||||
<Table.Cell width={'100px'} pr={'10px'}>
|
||||
{upgradeLevel < 4 && (
|
||||
<Icon
|
||||
name={reaction.danger ? "exclamation-triangle" : "spinner"}
|
||||
color={reaction.danger ? "red" : "white"}
|
||||
spin={reaction.danger ? false : true}
|
||||
<Icon
|
||||
name={reaction.danger ? "exclamation-triangle" : "spinner"}
|
||||
color={reaction.danger && "red"}
|
||||
spin={!reaction.danger}
|
||||
ml={2.5} />
|
||||
) || (
|
||||
<AnimatedNumber value={reaction.quality}>
|
||||
{(_, value) => (
|
||||
<RoundGauge
|
||||
<RoundGauge
|
||||
size={1.30}
|
||||
value={value}
|
||||
minValue={0}
|
||||
@@ -250,42 +247,44 @@ export const ChemHeater = (props, context) => {
|
||||
)}
|
||||
</AnimatedNumber>
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell width={'70px'}>
|
||||
</Table.Cell>
|
||||
<Table.Cell width={'70px'}>
|
||||
{upgradeLevel > 2 && (
|
||||
<ProgressBar
|
||||
value={reaction.reactedVol}
|
||||
minValue={0}
|
||||
maxValue={reaction.targetVol}
|
||||
textAlign={'center'}
|
||||
icon={reaction.overheat ? "thermometer-full" : ""}
|
||||
icon={reaction.overheat && "thermometer-full"}
|
||||
width={7}
|
||||
color={reaction.overheat ? "red" : "label"}>
|
||||
{reaction.targetVol}u
|
||||
</ProgressBar>
|
||||
) || (
|
||||
<Box
|
||||
color={reaction.danger ? "red" : "white"}
|
||||
color={reaction.danger && "red"}
|
||||
ml={2}>
|
||||
{reaction.targetVol}u
|
||||
</Box>
|
||||
)}
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
</Table.Cell>
|
||||
</Table.Row>
|
||||
))}
|
||||
<TableRow />
|
||||
<Table.Row />
|
||||
</Table>
|
||||
)}
|
||||
</Section>
|
||||
)}
|
||||
{tutorialMessage && (
|
||||
<Section
|
||||
title="Tutorial"
|
||||
<Section
|
||||
title="Tutorial"
|
||||
style={{
|
||||
'white-space': 'pre-wrap',
|
||||
}}>
|
||||
<img left={-1} mx={-1} src={resolveAsset("chem_help_advisor.gif")} width={"30px"} />
|
||||
{tutorialMessage}
|
||||
<img
|
||||
src={resolveAsset("chem_help_advisor.gif")}
|
||||
width="30px" />
|
||||
{tutorialMessage}
|
||||
</Section>
|
||||
)}
|
||||
<Section
|
||||
|
||||
@@ -13,6 +13,13 @@ export const SpaceHeater = (props, context) => {
|
||||
title="Power"
|
||||
buttons={(
|
||||
<>
|
||||
{!!data.chemHacked && (
|
||||
<Button
|
||||
icon="eject"
|
||||
content="Eject beaker"
|
||||
disabled={!data.beaker}
|
||||
onClick={() => act('ejectBeaker')} />
|
||||
)}
|
||||
<Button
|
||||
icon="eject"
|
||||
content="Eject Cell"
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
import { Component } from 'inferno';
|
||||
import { useBackend } from '../backend';
|
||||
import { Box, Stack } from '../components';
|
||||
import { Window } from '../layouts';
|
||||
|
||||
export class Thermometer extends Component {
|
||||
componentDidMount() {
|
||||
Byond.winset(window.__windowId__, {
|
||||
'transparent-color': '#242322',
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
Byond.winset(window.__windowId__, {
|
||||
'transparent-color': null,
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const { act, data } = useBackend(this.context);
|
||||
return (
|
||||
<Window
|
||||
width={70}
|
||||
height={430}>
|
||||
<Stack
|
||||
fill
|
||||
align="center"
|
||||
justify="space-around"
|
||||
backgroundColor="#242322"
|
||||
style={{
|
||||
'background-image': "url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAQMAAABIeJ9nAAAABlBMVEVya3UjIyN3S/1dAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAMSURBVAjXY2hgcAAAAcQAwUlFKkkAAAAASUVORK5CYII=')",
|
||||
}}>
|
||||
<Stack.Item ml={1}>
|
||||
<ThermometerIcon
|
||||
temperature={data.Temperature}
|
||||
maxTemperature={1000} />
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Window>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const ThermometerIcon = props => {
|
||||
const { temperature, maxTemperature } = props;
|
||||
return (
|
||||
<Box>
|
||||
<Box
|
||||
style={{
|
||||
'position': 'relative',
|
||||
'width': '22px',
|
||||
'height': '340px',
|
||||
'margin': '0 auto',
|
||||
'background-color': '#595959',
|
||||
'border': '4px solid #363636',
|
||||
'border-radius': '12px',
|
||||
'border-bottom': 'none',
|
||||
'border-index': '0',
|
||||
'box-shadow': '4px 4px #000000',
|
||||
}}>
|
||||
<Box
|
||||
style={{
|
||||
'position': 'absolute',
|
||||
'width': '5x',
|
||||
'bottom': 0,
|
||||
'left': '0px',
|
||||
'right': 0,
|
||||
'transition': 'height 2s ease-out',
|
||||
// Temp in %
|
||||
'height': `${((temperature / maxTemperature)*100)}%`,
|
||||
'background-color': '#bd2020',
|
||||
'border-radius': '8px',
|
||||
'border-bottom': 'none',
|
||||
'z-index': '1',
|
||||
}} />
|
||||
</Box>
|
||||
<Box
|
||||
style={{
|
||||
'position': 'relative',
|
||||
'width': '56px',
|
||||
'line-height': '48px',
|
||||
'text-align': 'center',
|
||||
'margin': '-8px auto 0 auto',
|
||||
'background-color': '#bd2020',
|
||||
'border': '4px solid #363636',
|
||||
'border-spacing': '5px',
|
||||
'border-radius': '35px',
|
||||
'border-index': '1',
|
||||
'border-bottom': '0.1',
|
||||
'box-shadow': '4px 4px #000000',
|
||||
'z-index': '0',
|
||||
}}>
|
||||
{temperature}K
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user