mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-11 18:22:14 +00:00
## About The Pull Request  This implements a new rare maintenance spawn, smokey remains. Piles of bones that used to be Nanotrasen employees, still packed with whatever reagent finally did them in. Rarely replacing a crate spawn (7/1007 chance per crate spawn if I'm doing the math right), these act as landmines for uncareful travelers in maintenance. When you get too close, one will release a cloud of a randomly generated reagents into the air (the same reagent every time, unique to the instance of remains). You can (mostly) avoid this by walking instead of running. These will "re-arm" themselves after 4-6 minutes. They're decals, so you can just sweep them away if they're a problem. This also slightly tweaks the original iteration of this, which I used in my Smoking Room ruin. Don't worry about it. I'm open to adjusting the rarity, cooldown, and selection of reagents if need be. ## Why It's Good For The Game Makes maintenance a bit more spicy. Maybe dangerous, maybe beneficial, maybe it's baldium. Who knows! Better be careful just in case! There's plenty of boring chemicals that could roll, but an interesting one could be a nice injection of uniqueness into an otherwise dull round. It's an infinite supply, but can only be dispensed infrequently (at a fixed location) and would be extremely difficult to harvest. The rarity, combined with the variety of reagents that can be picked, make it unlikely that these will have any serious impact on a round (it's still possible, but rarely, which is good). ## Changelog 🆑 Rhials add: Smokey remains have appeared in maintenance. Make sure to walk when near them! /🆑
233 lines
8.2 KiB
Plaintext
233 lines
8.2 KiB
Plaintext
/proc/chem_recipes_do_conflict(datum/chemical_reaction/r1, datum/chemical_reaction/r2)
|
|
//We have to check to see if either is competitive so can ignore it (competitive reagents are supposed to conflict)
|
|
if((r1.reaction_flags & REACTION_COMPETITIVE) || (r2.reaction_flags & REACTION_COMPETITIVE))
|
|
return FALSE
|
|
|
|
//do the non-list tests first, because they are cheaper
|
|
if(r1.required_container != r2.required_container)
|
|
return FALSE
|
|
if(r1.is_cold_recipe == r2.is_cold_recipe)
|
|
if(r1.required_temp != r2.required_temp)
|
|
//one reaction requires a more extreme temperature than the other, so there is no conflict
|
|
return FALSE
|
|
else
|
|
var/datum/chemical_reaction/cold_one = r1.is_cold_recipe ? r1 : r2
|
|
var/datum/chemical_reaction/warm_one = r1.is_cold_recipe ? r2 : r1
|
|
if(cold_one.required_temp < warm_one.required_temp)
|
|
//the range of temperatures does not overlap, so there is no conflict
|
|
return FALSE
|
|
|
|
//find the reactions with the shorter and longer required_reagents list
|
|
var/datum/chemical_reaction/long_req
|
|
var/datum/chemical_reaction/short_req
|
|
if(r1.required_reagents.len > r2.required_reagents.len)
|
|
long_req = r1
|
|
short_req = r2
|
|
else if(r1.required_reagents.len < r2.required_reagents.len)
|
|
long_req = r2
|
|
short_req = r1
|
|
else
|
|
//if they are the same length, sort instead by the length of the catalyst list
|
|
//this is important if the required_reagents lists are the same
|
|
if(r1.required_catalysts.len > r2.required_catalysts.len)
|
|
long_req = r1
|
|
short_req = r2
|
|
else
|
|
long_req = r2
|
|
short_req = r1
|
|
|
|
|
|
//check if the shorter reaction list is a subset of the longer one
|
|
var/list/overlap = r1.required_reagents & r2.required_reagents
|
|
if(overlap.len != short_req.required_reagents.len)
|
|
//there is at least one reagent in the short list that is not in the long list, so there is no conflict
|
|
return FALSE
|
|
|
|
//check to see if the shorter reaction's catalyst list is also a subset of the longer reaction's catalyst list
|
|
//if the longer reaction's catalyst list is a subset of the shorter ones, that is fine
|
|
//if the reaction lists are the same, the short reaction will have the shorter required_catalysts list, so it will register as a conflict
|
|
var/list/short_minus_long_catalysts = short_req.required_catalysts - long_req.required_catalysts
|
|
if(short_minus_long_catalysts.len)
|
|
//there is at least one unique catalyst for the short reaction, so there is no conflict
|
|
return FALSE
|
|
|
|
//if we got this far, the longer reaction will be impossible to create if the shorter one is earlier in GLOB.chemical_reactions_list_reactant_index, and will require the reagents to be added in a particular order otherwise
|
|
return TRUE
|
|
|
|
/proc/get_chemical_reaction(id)
|
|
if(!GLOB.chemical_reactions_list_reactant_index)
|
|
return
|
|
for(var/reagent in GLOB.chemical_reactions_list_reactant_index)
|
|
for(var/R in GLOB.chemical_reactions_list_reactant_index[reagent])
|
|
var/datum/reac = R
|
|
if(reac.type == id)
|
|
return R
|
|
|
|
/proc/remove_chemical_reaction(datum/chemical_reaction/R)
|
|
if(!GLOB.chemical_reactions_list_reactant_index || !R)
|
|
return
|
|
for(var/rid in R.required_reagents)
|
|
GLOB.chemical_reactions_list_reactant_index[rid] -= R
|
|
|
|
//see build_chemical_reactions_list in holder.dm for explanations
|
|
/proc/add_chemical_reaction(datum/chemical_reaction/add)
|
|
if(!GLOB.chemical_reactions_list_reactant_index || !add.required_reagents || !add.required_reagents.len)
|
|
return
|
|
var/rand_reagent = pick(add.required_reagents)
|
|
if(!GLOB.chemical_reactions_list_reactant_index[rand_reagent])
|
|
GLOB.chemical_reactions_list_reactant_index[rand_reagent] = list()
|
|
GLOB.chemical_reactions_list_reactant_index[rand_reagent] += add
|
|
|
|
//Creates foam from the reagent. Metaltype is for metal foam, notification is what to show people in textbox
|
|
/datum/reagents/proc/create_foam(foamtype, foam_volume, result_type = null, notification = null, log = FALSE)
|
|
var/location = get_turf(my_atom)
|
|
|
|
var/datum/effect_system/fluid_spread/foam/foam = new foamtype()
|
|
foam.set_up(amount = foam_volume, holder = my_atom, location = location, carry = src, result_type = result_type)
|
|
foam.start(log = log)
|
|
|
|
clear_reagents()
|
|
if(!notification)
|
|
return
|
|
for(var/mob/M in viewers(5, location))
|
|
to_chat(M, notification)
|
|
|
|
///Converts the pH into a tgui readable color - i.e. white and black text is readable over it. This is NOT the colourwheel for pHes however.
|
|
/proc/convert_ph_to_readable_color(pH)
|
|
switch(pH)
|
|
if(-INFINITY to 1)
|
|
return "red"
|
|
if(1 to 2)
|
|
return "orange"
|
|
if(2 to 3)
|
|
return "average"
|
|
if(3 to 4)
|
|
return "yellow"
|
|
if(4 to 5)
|
|
return "olive"
|
|
if(5 to 6)
|
|
return "good"
|
|
if(6 to 8)
|
|
return "green"
|
|
if(8 to 9.5)
|
|
return "teal"
|
|
if(9.5 to 11)
|
|
return "blue"
|
|
if(11 to 12.5)
|
|
return "violet"
|
|
if(12.5 to INFINITY)
|
|
return "purple"
|
|
|
|
///Converts pH to universal indicator colours. This is the colorwheel for pHes
|
|
#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" }\
|
|
}
|
|
|
|
///Returns a list of chemical_reaction datums that have the input STRING as a product
|
|
/proc/get_reagent_type_from_product_string(string)
|
|
var/input_reagent = replacetext(LOWER_TEXT(string), " ", "") //95% of the time, the reagent id is a lowercase/no spaces version of the name
|
|
if (isnull(input_reagent))
|
|
return
|
|
|
|
var/list/shortcuts = list("meth" = /datum/reagent/drug/methamphetamine)
|
|
if(shortcuts[input_reagent])
|
|
input_reagent = shortcuts[input_reagent]
|
|
else
|
|
input_reagent = find_reagent(input_reagent)
|
|
return input_reagent
|
|
|
|
///Returns reagent datum from typepath
|
|
/proc/find_reagent(input)
|
|
. = FALSE
|
|
if(GLOB.chemical_reagents_list[input]) //prefer IDs!
|
|
return input
|
|
else
|
|
return get_chem_id(input)
|
|
|
|
/proc/find_reagent_object_from_type(input)
|
|
if(GLOB.chemical_reagents_list[input]) //prefer IDs!
|
|
return GLOB.chemical_reagents_list[input]
|
|
else
|
|
return null
|
|
|
|
///Returns a random reagent object, with the option to blacklist reagents.
|
|
/proc/get_random_reagent_id(list/blacklist)
|
|
var/static/list/reagent_static_list = list() //This is static, and will be used by default if a blacklist is not passed.
|
|
var/list/reagent_list_to_process
|
|
if(blacklist) //If we do have a blacklist, we recompile a new list with the excluded reagents not present and pick from there.
|
|
reagent_list_to_process = list()
|
|
else
|
|
reagent_list_to_process = reagent_static_list
|
|
|
|
if(!reagent_list_to_process.len)
|
|
for(var/datum/reagent/reagent_path as anything in subtypesof(/datum/reagent))
|
|
if(is_path_in_list(reagent_path, blacklist))
|
|
continue
|
|
if(initial(reagent_path.chemical_flags) & REAGENT_CAN_BE_SYNTHESIZED)
|
|
reagent_list_to_process += reagent_path
|
|
|
|
var/picked_reagent = pick(reagent_list_to_process)
|
|
return picked_reagent
|
|
|
|
///Returns a random reagent consumable ethanol object minus blacklisted reagents
|
|
/proc/get_random_drink_id()
|
|
var/static/list/random_drinks = list()
|
|
if(!random_drinks.len)
|
|
for(var/datum/reagent/drink_path as anything in subtypesof(/datum/reagent/consumable/ethanol))
|
|
if(initial(drink_path.chemical_flags) & REAGENT_CAN_BE_SYNTHESIZED)
|
|
random_drinks += drink_path
|
|
var/picked_drink = pick(random_drinks)
|
|
return picked_drink
|
|
|
|
///Returns reagent datum from reagent name string
|
|
/proc/get_chem_id(chem_name)
|
|
for(var/X in GLOB.chemical_reagents_list)
|
|
var/datum/reagent/R = GLOB.chemical_reagents_list[X]
|
|
if(ckey(chem_name) == ckey(LOWER_TEXT(R.name)))
|
|
return X
|
|
|
|
///Takes a type in and returns a list of associated recipes
|
|
/proc/get_recipe_from_reagent_product(input_type)
|
|
if(!input_type)
|
|
return
|
|
var/list/matching_reactions = GLOB.chemical_reactions_list_product_index[input_type]
|
|
return matching_reactions
|
|
|
|
/proc/reagent_paths_list_to_text(list/reagents, addendum)
|
|
var/list/temp = list()
|
|
for(var/datum/reagent/R as anything in reagents)
|
|
temp |= initial(R.name)
|
|
if(addendum)
|
|
temp += addendum
|
|
return jointext(temp, ", ")
|