Revert "PLASE"

This reverts commit 8af225e6e3.
This commit is contained in:
Fermi
2019-11-24 03:06:08 +00:00
parent aeb8606ce0
commit ba4fa1ef67
2145 changed files with 1387321 additions and 5257 deletions
@@ -0,0 +1,656 @@
/obj/machinery/chem_dispenser
name = "chem dispenser"
desc = "Creates and dispenses chemicals."
density = TRUE
icon = 'icons/obj/chemical.dmi'
icon_state = "dispenser"
use_power = IDLE_POWER_USE
idle_power_usage = 40
interaction_flags_machine = INTERACT_MACHINE_OPEN | INTERACT_MACHINE_ALLOW_SILICON | INTERACT_MACHINE_OFFLINE
resistance_flags = FIRE_PROOF | ACID_PROOF
circuit = /obj/item/circuitboard/machine/chem_dispenser
var/obj/item/stock_parts/cell/cell
var/powerefficiency = 0.1
var/amount = 30
var/recharge_amount = 10
var/recharge_counter = 0
var/mutable_appearance/beaker_overlay
var/working_state = "dispenser_working"
var/nopower_state = "dispenser_nopower"
var/has_panel_overlay = TRUE
var/macrotier = 1
var/obj/item/reagent_containers/beaker = null
var/list/dispensable_reagents = list(
"hydrogen",
"lithium",
"carbon",
"nitrogen",
"oxygen",
"fluorine",
"sodium",
"aluminium",
"silicon",
"phosphorus",
"sulfur",
"chlorine",
"potassium",
"iron",
"copper",
"mercury",
"radium",
"water",
"ethanol",
"sugar",
"sacid",
"welding_fuel",
"silver",
"iodine",
"bromine",
"stable_plasma"
)
//these become available once upgraded.
var/list/upgrade_reagents = list(
"oil",
"ammonia",
"ash"
)
var/list/upgrade_reagents2 = list(
"acetone",
"phenol",
"diethylamine"
)
var/list/upgrade_reagents3 = list(
"mine_salve",
"toxin"
)
var/list/emagged_reagents = list(
"space_drugs",
"plasma",
"frostoil",
"carpotoxin",
"histamine",
"morphine"
)
var/list/saved_recipes = list()
/obj/machinery/chem_dispenser/Initialize()
. = ..()
dispensable_reagents = sortList(dispensable_reagents)
update_icon()
/obj/machinery/chem_dispenser/Destroy()
QDEL_NULL(beaker)
QDEL_NULL(cell)
return ..()
/obj/machinery/chem_dispenser/examine(mob/user)
..()
if(panel_open)
to_chat(user, "<span class='notice'>[src]'s maintenance hatch is open!</span>")
if(in_range(user, src) || isobserver(user))
to_chat(user, "<span class='notice'>The status display reads: <br>Recharging <b>[recharge_amount]</b> power units per interval.<br>Power efficiency increased by <b>[(powerefficiency*1000)-100]%</b>.<span>")
switch(macrotier)
if(1)
to_chat(user, "<span class='notice'>Macro granularity at <b>5u</b>.<span>")
if(2)
to_chat(user, "<span class='notice'>Macro granularity at <b>3u</b>.<span>")
if(3)
to_chat(user, "<span class='notice'>Macro granularity at <b>2u</b>.<span>")
if(4)
to_chat(user, "<span class='notice'>Macro granularity at <b>1u</b>.<span>")
/obj/machinery/chem_dispenser/process()
if (recharge_counter >= 4)
if(!is_operational())
return
var/usedpower = cell.give(recharge_amount)
if(usedpower)
use_power(250*recharge_amount)
recharge_counter = 0
return
recharge_counter++
/obj/machinery/chem_dispenser/proc/display_beaker()
var/mutable_appearance/b_o = beaker_overlay || mutable_appearance(icon, "disp_beaker")
b_o.pixel_y = -4
b_o.pixel_x = -7
return b_o
/obj/machinery/chem_dispenser/proc/work_animation()
if(working_state)
flick(working_state,src)
/obj/machinery/chem_dispenser/power_change()
..()
icon_state = "[(nopower_state && !powered()) ? nopower_state : initial(icon_state)]"
/obj/machinery/chem_dispenser/update_icon()
cut_overlays()
if(has_panel_overlay && panel_open)
add_overlay(mutable_appearance(icon, "[initial(icon_state)]_panel-o"))
if(beaker)
beaker_overlay = display_beaker()
add_overlay(beaker_overlay)
/obj/machinery/chem_dispenser/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
to_chat(user, "<span class='warning'>[src] has no functional safeties to emag.</span>")
return
to_chat(user, "<span class='notice'>You short out [src]'s safeties.</span>")
dispensable_reagents |= emagged_reagents//add the emagged reagents to the dispensable ones
obj_flags |= EMAGGED
return TRUE
/obj/machinery/chem_dispenser/ex_act(severity, target)
if(severity < 3)
..()
/obj/machinery/chem_dispenser/contents_explosion(severity, target)
..()
if(beaker)
beaker.ex_act(severity, target)
/obj/machinery/chem_dispenser/Exited(atom/movable/A, atom/newloc)
. = ..()
if(A == beaker)
beaker = null
cut_overlays()
/obj/machinery/chem_dispenser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "chem_dispenser", name, 565, 550, master_ui, state)
if(user.hallucinating())
ui.set_autoupdate(FALSE) //to not ruin the immersion by constantly changing the fake chemicals
ui.open()
/obj/machinery/chem_dispenser/ui_data(mob/user)
var/data = list()
data["amount"] = amount
data["energy"] = cell.charge ? cell.charge * powerefficiency : "0" //To prevent NaN in the UI.
data["maxEnergy"] = cell.maxcharge * powerefficiency
data["isBeakerLoaded"] = beaker ? 1 : 0
var/beakerContents[0]
var/beakerCurrentVolume = 0
if(beaker && beaker.reagents && beaker.reagents.reagent_list.len)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list...
beakerCurrentVolume += R.volume
data["beakerContents"] = beakerContents
if (beaker)
data["beakerCurrentVolume"] = beakerCurrentVolume
data["beakerMaxVolume"] = beaker.volume
data["beakerTransferAmounts"] = beaker.possible_transfer_amounts
data["beakerCurrentpH"] = beaker.reagents.pH
//pH accuracy
for(var/obj/item/stock_parts/capacitor/C in component_parts)
data["partRating"]= 10**(C.rating-1)
else
data["beakerCurrentVolume"] = null
data["beakerMaxVolume"] = null
data["beakerTransferAmounts"] = null
data["beakerCurrentpH"] = null
var/chemicals[0]
var/recipes[0]
var/is_hallucinating = FALSE
if(user.hallucinating())
is_hallucinating = TRUE
for(var/re in dispensable_reagents)
var/datum/reagent/temp = GLOB.chemical_reagents_list[re]
if(temp)
var/chemname = temp.name
if(is_hallucinating && prob(5))
chemname = "[pick_list_replacements("hallucination.json", "chemicals")]"
chemicals.Add(list(list("title" = chemname, "id" = temp.id)))
for(var/recipe in saved_recipes)
recipes.Add(list(recipe))
data["chemicals"] = chemicals
data["recipes"] = recipes
return data
/obj/machinery/chem_dispenser/ui_act(action, params)
if(..())
return
switch(action)
if("amount")
if(!is_operational() || QDELETED(beaker))
return
var/target = text2num(params["target"])
if(target in beaker.possible_transfer_amounts)
amount = target
work_animation()
. = TRUE
if("dispense")
if(!is_operational() || QDELETED(cell))
return
var/reagent = params["reagent"]
if(beaker && dispensable_reagents.Find(reagent))
var/datum/reagents/R = beaker.reagents
var/free = R.maximum_volume - R.total_volume
var/actual = min(amount, (cell.charge * powerefficiency)*10, free)
if(!cell.use(actual / powerefficiency))
say("Not enough energy to complete operation!")
return
R.add_reagent(reagent, actual)
work_animation()
. = TRUE
if("remove")
if(!is_operational())
return
var/amount = text2num(params["amount"])
if(beaker && (amount in beaker.possible_transfer_amounts))
beaker.reagents.remove_all(amount)
work_animation()
. = TRUE
if("eject")
replace_beaker(usr)
. = TRUE //no afterattack
if("dispense_recipe")
if(!is_operational() || QDELETED(cell))
return
var/recipe_to_use = params["recipe"]
var/list/chemicals_to_dispense = process_recipe_list(recipe_to_use)
var/res = get_macro_resolution()
for(var/key in chemicals_to_dispense) // i suppose you could edit the list locally before passing it
var/list/keysplit = splittext(key," ")
var/r_id = keysplit[1]
if(beaker && dispensable_reagents.Find(r_id)) // but since we verify we have the reagent, it'll be fine
var/datum/reagents/R = beaker.reagents
var/free = R.maximum_volume - R.total_volume
var/actual = min(max(chemicals_to_dispense[key], res), (cell.charge * powerefficiency)*10, free)
if(actual)
if(!cell.use(actual / powerefficiency))
say("Not enough energy to complete operation!")
return
R.add_reagent(r_id, actual)
work_animation()
if("clear_recipes")
if(!is_operational())
return
var/yesno = alert("Clear all recipes?",, "Yes","No")
if(yesno == "Yes")
saved_recipes = list()
if("add_recipe")
if(!is_operational())
return
var/name = stripped_input(usr,"Name","What do you want to name this recipe?", "Recipe", MAX_NAME_LEN)
var/recipe = stripped_input(usr,"Recipe","Insert recipe with chem IDs")
if(!usr.canUseTopic(src, !issilicon(usr)))
return
if(name && recipe)
var/list/first_process = splittext(recipe, ";")
if(!LAZYLEN(first_process))
return
var/res = get_macro_resolution()
var/resmismatch = FALSE
for(var/reagents in first_process)
var/list/reagent = splittext(reagents, "=")
if(dispensable_reagents.Find(reagent[1]))
if (!resmismatch && !check_macro_part(reagents, res))
resmismatch = TRUE
continue
else
var/chemid = reagent[1]
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
to_chat(usr, "<span class ='danger'>[src] cannot find Chemical ID: <b>[chemid]</b>!</span>")
playsound(src, 'sound/machines/buzz-two.ogg', 50, 1)
return
if (resmismatch && alert("[src] is not yet capable of replicating this recipe with the precision it needs, do you want to save it anyway?",, "Yes","No") == "No")
return
saved_recipes += list(list("recipe_name" = name, "contents" = recipe))
/obj/machinery/chem_dispenser/attackby(obj/item/I, mob/user, params)
if(default_unfasten_wrench(user, I))
return
if(default_deconstruction_screwdriver(user, icon_state, icon_state, I))
update_icon()
return
if(default_deconstruction_crowbar(I))
return
if(istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container())
var/obj/item/reagent_containers/B = I
. = TRUE //no afterattack
if(!user.transferItemToLoc(B, src))
return
replace_beaker(user, B)
to_chat(user, "<span class='notice'>You add [B] to [src].</span>")
updateUsrDialog()
update_icon()
else if(user.a_intent != INTENT_HARM && !istype(I, /obj/item/card/emag))
to_chat(user, "<span class='warning'>You can't load [I] into [src]!</span>")
return ..()
else
return ..()
/obj/machinery/chem_dispenser/get_cell()
return cell
/obj/machinery/chem_dispenser/emp_act(severity)
. = ..()
if(. & EMP_PROTECT_SELF)
return
var/list/datum/reagents/R = list()
var/total = min(rand(7,15), FLOOR(cell.charge*powerefficiency, 1))
var/datum/reagents/Q = new(total*10)
if(beaker && beaker.reagents)
R += beaker.reagents
for(var/i in 1 to total)
Q.add_reagent(pick(dispensable_reagents), 10)
R += Q
chem_splash(get_turf(src), 3, R)
if(beaker && beaker.reagents)
beaker.reagents.remove_all()
cell.use(total/powerefficiency)
cell.emp_act(severity)
work_animation()
visible_message("<span class='danger'>[src] malfunctions, spraying chemicals everywhere!</span>")
/obj/machinery/chem_dispenser/RefreshParts()
recharge_amount = initial(recharge_amount)
var/newpowereff = 0.0666666
for(var/obj/item/stock_parts/cell/P in component_parts)
cell = P
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
newpowereff += 0.0166666666*M.rating
for(var/obj/item/stock_parts/capacitor/C in component_parts)
recharge_amount *= C.rating
for(var/obj/item/stock_parts/manipulator/M in component_parts)
if (M.rating > macrotier)
macrotier = M.rating
if (M.rating > 1)
dispensable_reagents |= upgrade_reagents
if (M.rating > 2)
dispensable_reagents |= upgrade_reagents2
if (M.rating > 3)
dispensable_reagents |= upgrade_reagents3
powerefficiency = round(newpowereff, 0.01)
/obj/machinery/chem_dispenser/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(beaker)
beaker.forceMove(drop_location())
if(user && Adjacent(user) && !issiliconoradminghost(user))
user.put_in_hands(beaker)
if(new_beaker)
beaker = new_beaker
else
beaker = null
update_icon()
return TRUE
/obj/machinery/chem_dispenser/on_deconstruction()
cell = null
if(beaker)
beaker.forceMove(drop_location())
beaker = null
return ..()
/obj/machinery/chem_dispenser/proc/get_macro_resolution()
. = 5
if (macrotier > 1)
. -= macrotier // 5 for tier1, 3 for 2, 2 for 3, 1 for 4.
/obj/machinery/chem_dispenser/proc/check_macro(macro)
var/res = get_macro_resolution()
for (var/reagent in splittext(trim(macro), ";"))
if (!check_macro_part(reagent, res))
return FALSE
return TRUE
/obj/machinery/chem_dispenser/proc/check_macro_part(var/part, var/res = get_macro_resolution())
var/detail = splittext(part, "=")
if (round(text2num(detail[2]), res) != text2num(detail[2]))
return FALSE
return TRUE
/obj/machinery/chem_dispenser/proc/process_recipe_list(var/fucking_hell)
var/list/key_list = list()
var/list/final_list = list()
var/list/first_process = splittext(fucking_hell, ";")
for(var/reagents in first_process)
var/list/fuck = splittext(reagents, "=")
final_list += list(avoid_assoc_duplicate_keys(fuck[1],key_list) = text2num(fuck[2]))
return final_list
/obj/machinery/chem_dispenser/AltClick(mob/living/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
replace_beaker(user)
return
/obj/machinery/chem_dispenser/drinks/Initialize()
. = ..()
AddComponent(/datum/component/simple_rotation, ROTATION_ALTCLICK | ROTATION_CLOCKWISE)
/obj/machinery/chem_dispenser/drinks/setDir()
var/old = dir
. = ..()
if(dir != old)
update_icon() // the beaker needs to be re-positioned if we rotate
/obj/machinery/chem_dispenser/drinks/display_beaker()
var/mutable_appearance/b_o = beaker_overlay || mutable_appearance(icon, "disp_beaker")
switch(dir)
if(NORTH)
b_o.pixel_y = 7
b_o.pixel_x = rand(-9, 9)
if(EAST)
b_o.pixel_x = 4
b_o.pixel_y = rand(-5, 7)
if(WEST)
b_o.pixel_x = -5
b_o.pixel_y = rand(-5, 7)
else//SOUTH
b_o.pixel_y = -7
b_o.pixel_x = rand(-9, 9)
return b_o
/obj/machinery/chem_dispenser/drinks
name = "soda dispenser"
desc = "Contains a large reservoir of soft drinks."
icon = 'icons/obj/chemical.dmi'
icon_state = "soda_dispenser"
has_panel_overlay = FALSE
amount = 10
pixel_y = 6
layer = WALL_OBJ_LAYER
circuit = /obj/item/circuitboard/machine/chem_dispenser/drinks
working_state = null
nopower_state = null
pass_flags = PASSTABLE
dispensable_reagents = list(
"water",
"ice",
"coffee",
"cream",
"tea",
"icetea",
"cola",
"spacemountainwind",
"dr_gibb",
"space_up",
"tonic",
"sodawater",
"lemon_lime",
"pwr_game",
"shamblers",
"sugar",
"orangejuice",
"grenadine",
"limejuice",
"tomatojuice",
"lemonjuice",
"menthol"
)
upgrade_reagents = list(
"mushroomhallucinogen",
"nothing",
"cryoxadone"
)
upgrade_reagents2 = list(
"banana",
"berryjuice"
)
upgrade_reagents3 = null
emagged_reagents = list(
"thirteenloko",
"changelingsting",
"whiskeycola",
"mindbreaker",
"tirizene"
)
/obj/machinery/chem_dispenser/drinks/fullupgrade //fully ugpraded stock parts, emagged
desc = "Contains a large reservoir of soft drinks. This model has had its safeties shorted out."
obj_flags = CAN_BE_HIT | EMAGGED
flags_1 = NODECONSTRUCT_1
/obj/machinery/chem_dispenser/drinks/fullupgrade/Initialize()
. = ..()
dispensable_reagents |= emagged_reagents //adds emagged reagents
component_parts = list()
component_parts += new /obj/item/circuitboard/machine/chem_dispenser/drinks(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
component_parts += new /obj/item/stack/sheet/glass(null)
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
RefreshParts()
/obj/machinery/chem_dispenser/drinks/beer
name = "booze dispenser"
desc = "Contains a large reservoir of the good stuff."
icon = 'icons/obj/chemical.dmi'
icon_state = "booze_dispenser"
circuit = /obj/item/circuitboard/machine/chem_dispenser/drinks/beer
dispensable_reagents = list(
"beer",
"kahlua",
"whiskey",
"wine",
"vodka",
"gin",
"rum",
"tequila",
"vermouth",
"cognac",
"ale",
"absinthe",
"hcider",
"creme_de_menthe",
"creme_de_cacao",
"triple_sec",
"sake",
"applejack"
)
upgrade_reagents = list(
"ethanol",
"fernet"
)
upgrade_reagents2 = null
upgrade_reagents3 = null
emagged_reagents = list(
"iron",
"alexander",
"clownstears",
"minttoxin",
"atomicbomb",
"aphro",
"aphro+"
)
/obj/machinery/chem_dispenser/drinks/beer/fullupgrade //fully ugpraded stock parts, emagged
desc = "Contains a large reservoir of the good stuff. This model has had its safeties shorted out."
obj_flags = CAN_BE_HIT | EMAGGED
flags_1 = NODECONSTRUCT_1
/obj/machinery/chem_dispenser/drinks/beer/fullupgrade/Initialize()
. = ..()
dispensable_reagents |= emagged_reagents //adds emagged reagents
component_parts = list()
component_parts += new /obj/item/circuitboard/machine/chem_dispenser/drinks/beer(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
component_parts += new /obj/item/stack/sheet/glass(null)
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
RefreshParts()
/obj/machinery/chem_dispenser/mutagen
name = "mutagen dispenser"
desc = "Creates and dispenses mutagen."
dispensable_reagents = list("mutagen")
upgrade_reagents = null
emagged_reagents = list("plasma")
/obj/machinery/chem_dispenser/mutagensaltpeter
name = "botanical chemical dispenser"
desc = "Creates and dispenses chemicals useful for botany."
flags_1 = NODECONSTRUCT_1
dispensable_reagents = list(
"mutagen",
"saltpetre",
"eznutriment",
"left4zednutriment",
"robustharvestnutriment",
"water",
"plantbgone",
"weedkiller",
"pestkiller",
"cryoxadone",
"ammonia",
"ash",
"diethylamine")
//same as above.
upgrade_reagents = null
upgrade_reagents2 = null
upgrade_reagents3 = null
/obj/machinery/chem_dispenser/mutagensaltpeter/Initialize()
. = ..()
component_parts = list()
component_parts += new /obj/item/circuitboard/machine/chem_dispenser(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
component_parts += new /obj/item/stack/sheet/glass(null)
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
RefreshParts()
/obj/machinery/chem_dispenser/fullupgrade //fully ugpraded stock parts, emagged
desc = "Creates and dispenses chemicals. This model has had its safeties shorted out."
obj_flags = CAN_BE_HIT | EMAGGED
flags_1 = NODECONSTRUCT_1
/obj/machinery/chem_dispenser/fullupgrade/Initialize()
. = ..()
dispensable_reagents |= emagged_reagents //adds emagged reagents
component_parts = list()
component_parts += new /obj/item/circuitboard/machine/chem_dispenser(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/matter_bin/bluespace(null)
component_parts += new /obj/item/stock_parts/capacitor/quadratic(null)
component_parts += new /obj/item/stock_parts/manipulator/femto(null)
component_parts += new /obj/item/stack/sheet/glass(null)
component_parts += new /obj/item/stock_parts/cell/bluespace(null)
RefreshParts()
@@ -0,0 +1,523 @@
#define PILL_STYLE_COUNT 22 //Update this if you add more pill icons or you die
#define RANDOM_PILL_STYLE 22 //Dont change this one though
/obj/machinery/chem_master
name = "ChemMaster 3000"
desc = "Used to separate chemicals and distribute them in a variety of forms."
density = TRUE
layer = BELOW_OBJ_LAYER
icon = 'icons/obj/chemical.dmi'
icon_state = "mixer0"
use_power = IDLE_POWER_USE
idle_power_usage = 20
resistance_flags = FIRE_PROOF | ACID_PROOF
circuit = /obj/item/circuitboard/machine/chem_master
var/obj/item/reagent_containers/beaker = null
var/obj/item/storage/pill_bottle/bottle = null
var/mode = 1
var/condi = FALSE
var/chosenPillStyle = 1
var/screen = "home"
var/analyzeVars[0]
var/useramount = 30 // Last used amount
var/list/pillStyles
var/fermianalyze //Give more detail on fermireactions on analysis
/obj/machinery/chem_master/Initialize()
create_reagents(100)
//Calculate the span tags and ids fo all the available pill icons
var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/pills)
pillStyles = list()
for (var/x in 1 to PILL_STYLE_COUNT)
var/list/SL = list()
SL["id"] = x
SL["htmltag"] = assets.icon_tag("pill[x]")
pillStyles += list(SL)
. = ..()
/obj/machinery/chem_master/Destroy()
QDEL_NULL(beaker)
QDEL_NULL(bottle)
return ..()
/obj/machinery/chem_master/RefreshParts()
reagents.maximum_volume = 0
for(var/obj/item/reagent_containers/glass/beaker/B in component_parts)
reagents.maximum_volume += B.reagents.maximum_volume
/obj/machinery/chem_master/ex_act(severity, target)
if(severity < 3)
..()
/obj/machinery/chem_master/contents_explosion(severity, target)
..()
if(beaker)
beaker.ex_act(severity, target)
if(bottle)
bottle.ex_act(severity, target)
/obj/machinery/chem_master/handle_atom_del(atom/A)
..()
if(A == beaker)
beaker = null
reagents.clear_reagents()
update_icon()
else if(A == bottle)
bottle = null
/obj/machinery/chem_master/update_icon()
cut_overlays()
if (stat & BROKEN)
add_overlay("waitlight")
if(beaker)
icon_state = "mixer1"
else
icon_state = "mixer0"
/obj/machinery/chem_master/blob_act(obj/structure/blob/B)
if (prob(50))
qdel(src)
/obj/machinery/chem_master/attackby(obj/item/I, mob/user, params)
if(default_deconstruction_screwdriver(user, "mixer0_nopower", "mixer0", I))
return
else if(default_deconstruction_crowbar(I))
return
if(default_unfasten_wrench(user, I))
return
if(istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container())
. = TRUE // no afterattack
if(panel_open)
to_chat(user, "<span class='warning'>You can't use the [src.name] while its panel is opened!</span>")
return
var/obj/item/reagent_containers/B = I
if(!user.transferItemToLoc(B, src))
return
replace_beaker(user, B)
to_chat(user, "<span class='notice'>You add [B] to [src].</span>")
updateUsrDialog()
update_icon()
else if(!condi && istype(I, /obj/item/storage/pill_bottle))
if(!user.transferItemToLoc(I, src))
return
replace_pillbottle(user, I)
to_chat(user, "<span class='notice'>You add [I] into the dispenser slot.</span>")
updateUsrDialog()
else
return ..()
/obj/machinery/chem_master/AltClick(mob/living/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
replace_beaker(user)
return
/obj/machinery/chem_master/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(beaker)
beaker.forceMove(drop_location())
if(user && Adjacent(user) && !issiliconoradminghost(user))
user.put_in_hands(beaker)
if(new_beaker)
beaker = new_beaker
else
beaker = null
update_icon()
return TRUE
/obj/machinery/chem_master/proc/replace_pillbottle(mob/living/user, obj/item/storage/pill_bottle/new_bottle)
if(bottle)
bottle.forceMove(drop_location())
if(user && Adjacent(user) && !issiliconoradminghost(user))
user.put_in_hands(beaker)
else
adjust_item_drop_location(bottle)
if(new_bottle)
bottle = new_bottle
else
bottle = null
update_icon()
return TRUE
/obj/machinery/chem_master/on_deconstruction()
replace_beaker(usr)
replace_pillbottle(usr)
return ..()
/obj/machinery/chem_master/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/simple/pills)
assets.send(user)
ui = new(user, src, ui_key, "chem_master", name, 500, 550, master_ui, state)
ui.open()
//Insert our custom spritesheet css link into the html
/obj/machinery/chem_master/ui_base_html(html)
var/datum/asset/spritesheet/simple/assets = get_asset_datum(/datum/asset/spritesheet/simple/pills)
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag())
/obj/machinery/chem_master/ui_data(mob/user)
var/list/data = list()
data["isBeakerLoaded"] = beaker ? 1 : 0
data["beakerCurrentVolume"] = beaker ? beaker.reagents.total_volume : null
data["beakerMaxVolume"] = beaker ? beaker.volume : null
data["mode"] = mode
data["condi"] = condi
data["screen"] = screen
data["analyzeVars"] = analyzeVars
data["fermianalyze"] = fermianalyze
data["chosenPillStyle"] = chosenPillStyle
data["isPillBottleLoaded"] = bottle ? 1 : 0
if(bottle)
var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage)
data["pillBotContent"] = bottle.contents.len
data["pillBotMaxContent"] = STRB.max_items
var/beakerContents[0]
if(beaker)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents.Add(list(list("name" = R.name, "id" = R.id, "volume" = R.volume))) // list in a list because Byond merges the first list...
data["beakerContents"] = beakerContents
var/bufferContents[0]
if(reagents.total_volume)
for(var/datum/reagent/N in reagents.reagent_list)
bufferContents.Add(list(list("name" = N.name, "id" = N.id, "volume" = N.volume))) // ^
data["bufferContents"] = bufferContents
//Calculated at init time as it never changes
data["pillStyles"] = pillStyles
return data
/obj/machinery/chem_master/ui_act(action, params)
if(..())
return
switch(action)
if("eject")
replace_beaker(usr)
. = TRUE
if("ejectp")
replace_pillbottle(usr)
. = TRUE
if("transferToBuffer")
if(beaker)
var/id = params["id"]
var/amount = text2num(params["amount"])
if (amount > 0)
end_fermi_reaction()
beaker.reagents.trans_id_to(src, id, amount)
. = TRUE
else if (amount == -1) // -1 means custom amount
useramount = input("Enter the Amount you want to transfer:", name, useramount) as num|null
if (useramount > 0)
end_fermi_reaction()
beaker.reagents.trans_id_to(src, id, useramount)
. = TRUE
if("transferFromBuffer")
var/id = params["id"]
var/amount = text2num(params["amount"])
if (amount > 0)
if(mode)
reagents.trans_id_to(beaker, id, amount)
. = TRUE
else
reagents.remove_reagent(id, amount)
. = TRUE
else if (amount == -1) // -1 means custom amount
useramount = input("Enter the Amount you want to transfer:", name, useramount) as num|null
if (useramount > 0)
end_fermi_reaction()
reagents.trans_id_to(beaker, id, useramount)
. = TRUE
if("toggleMode")
mode = !mode
. = TRUE
if("createPill")
var/many = params["many"]
if(reagents.total_volume == 0)
return
if(!condi)
var/amount = 1
var/vol_each = min(reagents.total_volume, 50)
if(text2num(many))
amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many pills?", amount) as num|null), 0, 10)
if(!amount)
return
vol_each = min(reagents.total_volume / amount, 50)
var/name = stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/pill/P
var/target_loc = bottle ? bottle : drop_location()
var/drop_threshold = INFINITY
if(bottle)
var/datum/component/storage/STRB = bottle.GetComponent(/datum/component/storage)
if(STRB)
drop_threshold = STRB.max_items - bottle.contents.len
for(var/i in 1 to amount)
if(i < drop_threshold)
P = new(target_loc)
else
P = new(drop_location())
P.name = trim("[name] pill")
if(chosenPillStyle == RANDOM_PILL_STYLE)
P.icon_state ="pill[rand(1,21)]"
else
P.icon_state = "pill[chosenPillStyle]"
if(P.icon_state == "pill4")
P.desc = "A tablet or capsule, but not just any, a red one, one taken by the ones not scared of knowledge, freedom, uncertainty and the brutal truths of reality."
adjust_item_drop_location(P)
reagents.trans_to(P,vol_each)
else
var/name = stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN)
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(drop_location())
P.originalname = name
P.name = trim("[name] pack")
P.desc = "A small condiment pack. The label says it contains [name]."
reagents.trans_to(P,10)
. = TRUE
if("pillStyle")
var/id = text2num(params["id"])
chosenPillStyle = id
if("createPatch")
var/many = params["many"]
if(reagents.total_volume == 0)
return
var/amount = 1
var/vol_each = min(reagents.total_volume, 40)
if(text2num(many))
amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many patches?", amount) as num|null), 0, 10)
if(!amount)
return
vol_each = min(reagents.total_volume / amount, 40)
var/name = stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/pill/P
for(var/i = 0; i < amount; i++)
P = new/obj/item/reagent_containers/pill/patch(drop_location())
P.name = trim("[name] patch")
adjust_item_drop_location(P)
reagents.trans_to(P,vol_each)
. = TRUE
if("createBottle")
var/many = params["many"]
if(reagents.total_volume == 0)
return
if(condi)
var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/food/condiment/P = new(drop_location())
P.originalname = name
P.name = trim("[name] bottle")
reagents.trans_to(P, P.volume)
else
var/amount_full = 0
var/vol_part = min(reagents.total_volume, 30)
if(text2num(many))
amount_full = round(reagents.total_volume / 30)
vol_part = ((reagents.total_volume*1000) % 30000) / 1000 //% operator doesn't support decimals.
var/name = stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/glass/bottle/P
for(var/i = 0; i < amount_full; i++)
P = new/obj/item/reagent_containers/glass/bottle(drop_location())
P.name = trim("[name] bottle")
adjust_item_drop_location(P)
reagents.trans_to(P, 30)
if(vol_part)
P = new/obj/item/reagent_containers/glass/bottle(drop_location())
P.name = trim("[name] bottle")
adjust_item_drop_location(P)
reagents.trans_to(P, vol_part)
. = TRUE
//CITADEL ADD Hypospray Vials
if("createVial")
var/many = params["many"]
if(reagents.total_volume == 0)
return
var/amount_full = 0
var/vol_part = min(reagents.total_volume, 60)
if(text2num(many))
amount_full = round(reagents.total_volume / 60)
vol_part = reagents.total_volume % 60
var/name = stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN)
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/glass/bottle/vial/small/P
for(var/i = 0; i < amount_full; i++)
P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location())
P.name = trim("[name] hypovial")
adjust_item_drop_location(P)
reagents.trans_to(P, 60)
if(vol_part)
P = new/obj/item/reagent_containers/glass/bottle/vial/small(drop_location())
P.name = trim("[name] hypovial")
adjust_item_drop_location(P)
reagents.trans_to(P, vol_part)
. = TRUE
if("createDart")
for(var/datum/reagent/R in reagents.reagent_list)
if(!(istype(R, /datum/reagent/medicine)))
visible_message("<b>The [src]</b> beeps, \"<span class='warning'>SmartDarts are insoluble with non-medicinal compounds.\"</span>")
return
var/many = params["many"]
if(reagents.total_volume == 0)
return
var/amount = 1
var/vol_each = min(reagents.total_volume, 20)
if(text2num(many))
amount = CLAMP(round(input(usr, "Max 10. Buffer content will be split evenly.", "How many darts?", amount) as num|null), 0, 10)
if(!amount)
return
vol_each = min(reagents.total_volume / amount, 20)
var/name = stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN)
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
return
var/obj/item/reagent_containers/syringe/dart/D
for(var/i = 0; i < amount; i++)
D = new /obj/item/reagent_containers/syringe/dart(drop_location())
D.name = trim("[name] SmartDart")
adjust_item_drop_location(D)
reagents.trans_to(D, vol_each)
D.mode=!mode
D.update_icon()
. = TRUE
//END CITADEL ADDITIONS
if("analyzeBeak")
var/datum/reagent/R = GLOB.chemical_reagents_list[params["id"]]
if(R)
var/state = "Unknown"
if(initial(R.reagent_state) == 1)
state = "Solid"
else if(initial(R.reagent_state) == 2)
state = "Liquid"
else if(initial(R.reagent_state) == 3)
state = "Gas"
var/const/P = 3 //The number of seconds between life ticks
var/T = initial(R.metabolization_rate) * (60 / P)
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R.id)
if(Rcr && Rcr.FermiChem)
fermianalyze = TRUE
var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
var/datum/reagent/targetReagent = beaker.reagents.has_reagent("[R.id]")
if(!targetReagent)
CRASH("Tried to find a reagent that doesn't exist in the chem_master!")
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = targetReagent.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache)
else
fermianalyze = FALSE
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold))
screen = "analyze"
return
if("analyzeBuff")
var/datum/reagent/R = GLOB.chemical_reagents_list[params["id"]]
if(R)
var/state = "Unknown"
if(initial(R.reagent_state) == 1)
state = "Solid"
else if(initial(R.reagent_state) == 2)
state = "Liquid"
else if(initial(R.reagent_state) == 3)
state = "Gas"
var/const/P = 3 //The number of seconds between life ticks
var/T = initial(R.metabolization_rate) * (60 / P)
if(istype(R, /datum/reagent/fermi))
fermianalyze = TRUE
var/datum/chemical_reaction/Rcr = get_chemical_reaction(R.id)
var/pHpeakCache = (Rcr.OptimalpHMin + Rcr.OptimalpHMax)/2
var/datum/reagent/targetReagent = reagents.has_reagent("[R.id]")
if(!targetReagent)
CRASH("Tried to find a reagent that doesn't exist in the chem_master!")
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold), "purityF" = targetReagent.purity, "inverseRatioF" = initial(R.inverse_chem_val), "purityE" = initial(Rcr.PurityMin), "minTemp" = initial(Rcr.OptimalTempMin), "maxTemp" = initial(Rcr.OptimalTempMax), "eTemp" = initial(Rcr.ExplodeTemp), "pHpeak" = pHpeakCache)
else
fermianalyze = FALSE
analyzeVars = list("name" = initial(R.name), "state" = state, "color" = initial(R.color), "description" = initial(R.description), "metaRate" = T, "overD" = initial(R.overdose_threshold), "addicD" = initial(R.addiction_threshold))
screen = "analyze"
return
if("goScreen")
screen = params["screen"]
. = TRUE
/obj/machinery/chem_master/proc/end_fermi_reaction()//Ends any reactions upon moving.
if(beaker.reagents.fermiIsReacting)
beaker.reagents.fermiEnd()
/obj/machinery/chem_master/proc/isgoodnumber(num)
if(isnum(num))
if(num > 200)
num = 200
else if(num < 0)
num = 0
else
num = round(num)
return num
else
return 0
/obj/machinery/chem_master/adjust_item_drop_location(atom/movable/AM) // Special version for chemmasters and condimasters
if (AM == beaker)
AM.pixel_x = -8
AM.pixel_y = 8
return null
else if (AM == bottle)
if (length(bottle.contents))
AM.pixel_x = -13
else
AM.pixel_x = -7
AM.pixel_y = -8
return null
else
var/md5 = md5(AM.name)
for (var/i in 1 to 32)
. += hex2num(md5[i])
. = . % 9
AM.pixel_x = ((.%3)*6)
AM.pixel_y = -8 + (round( . / 3)*8)
/obj/machinery/chem_master/condimaster
name = "CondiMaster 3000"
desc = "Used to create condiments and other cooking supplies."
condi = TRUE
#undef PILL_STYLE_COUNT
#undef RANDOM_PILL_STYLE
@@ -0,0 +1,259 @@
#define MAIN_SCREEN 1
#define SYMPTOM_DETAILS 2
/obj/machinery/computer/pandemic
name = "PanD.E.M.I.C 2200"
desc = "Used to work with viruses."
density = TRUE
icon = 'icons/obj/chemical.dmi'
icon_state = "mixer0"
circuit = /obj/item/circuitboard/computer/pandemic
use_power = TRUE
idle_power_usage = 20
resistance_flags = ACID_PROOF
var/wait
var/mode = MAIN_SCREEN
var/datum/symptom/selected_symptom
var/obj/item/reagent_containers/beaker
/obj/machinery/computer/pandemic/Initialize()
. = ..()
update_icon()
/obj/machinery/computer/pandemic/Destroy()
QDEL_NULL(beaker)
return ..()
/obj/machinery/computer/pandemic/handle_atom_del(atom/A)
. = ..()
if(A == beaker)
beaker = null
update_icon()
/obj/machinery/computer/pandemic/proc/get_by_index(thing, index)
if(!beaker || !beaker.reagents)
return
var/datum/reagent/blood/B = locate() in beaker.reagents.reagent_list
if(B && B.data[thing])
return B.data[thing][index]
/obj/machinery/computer/pandemic/proc/get_virus_id_by_index(index)
var/datum/disease/D = get_by_index("viruses", index)
if(D)
return D.GetDiseaseID()
/obj/machinery/computer/pandemic/proc/get_viruses_data(datum/reagent/blood/B)
. = list()
var/list/V = B.get_diseases()
var/index = 1
for(var/virus in V)
var/datum/disease/D = virus
if(!istype(D) || D.visibility_flags & HIDDEN_PANDEMIC)
continue
var/list/this = list()
this["name"] = D.name
if(istype(D, /datum/disease/advance))
var/datum/disease/advance/A = D
var/disease_name = SSdisease.get_disease_name(A.GetDiseaseID())
if((disease_name == "Unknown") && A.mutable)
this["can_rename"] = TRUE
this["name"] = disease_name
this["is_adv"] = TRUE
this["symptoms"] = list()
var/symptom_index = 1
for(var/symptom in A.symptoms)
var/datum/symptom/S = symptom
var/list/this_symptom = list()
this_symptom["name"] = S.name
this_symptom["sym_index"] = symptom_index
symptom_index++
this["symptoms"] += list(this_symptom)
this["resistance"] = A.totalResistance()
this["stealth"] = A.totalStealth()
this["stage_speed"] = A.totalStageSpeed()
this["transmission"] = A.totalTransmittable()
this["index"] = index++
this["agent"] = D.agent
this["description"] = D.desc || "none"
this["spread"] = D.spread_text || "none"
this["cure"] = D.cure_text || "none"
. += list(this)
/obj/machinery/computer/pandemic/proc/get_symptom_data(datum/symptom/S)
. = list()
var/list/this = list()
this["name"] = S.name
this["desc"] = S.desc
this["stealth"] = S.stealth
this["resistance"] = S.resistance
this["stage_speed"] = S.stage_speed
this["transmission"] = S.transmittable
this["level"] = S.level
this["neutered"] = S.neutered
this["threshold_desc"] = S.threshold_desc
. += this
/obj/machinery/computer/pandemic/proc/get_resistance_data(datum/reagent/blood/B)
. = list()
if(!islist(B.data["resistances"]))
return
var/list/resistances = B.data["resistances"]
for(var/id in resistances)
var/list/this = list()
var/datum/disease/D = SSdisease.archive_diseases[id]
if(D)
this["id"] = id
this["name"] = D.name
. += list(this)
/obj/machinery/computer/pandemic/proc/reset_replicator_cooldown()
wait = FALSE
update_icon()
playsound(loc, 'sound/machines/ping.ogg', 30, 1)
/obj/machinery/computer/pandemic/update_icon()
if(stat & BROKEN)
icon_state = (beaker ? "mixer1_b" : "mixer0_b")
return
icon_state = "mixer[(beaker) ? "1" : "0"][powered() ? "" : "_nopower"]"
if(wait)
add_overlay("waitlight")
else
cut_overlays()
/obj/machinery/computer/pandemic/ui_interact(mob/user, ui_key = "main", datum/tgui/ui, force_open = FALSE, datum/tgui/master_ui, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "pandemic", name, 700, 500, master_ui, state)
ui.open()
/obj/machinery/computer/pandemic/ui_data(mob/user)
var/list/data = list()
data["is_ready"] = !wait
data["mode"] = mode
switch(mode)
if(MAIN_SCREEN)
if(beaker)
data["has_beaker"] = TRUE
if(!beaker.reagents.total_volume || !beaker.reagents.reagent_list)
data["beaker_empty"] = TRUE
var/datum/reagent/blood/B = locate() in beaker.reagents.reagent_list
if(B)
data["has_blood"] = TRUE
data["blood"] = list()
data["blood"]["dna"] = B.data["blood_DNA"] || "none"
data["blood"]["type"] = B.data["blood_type"] || "none"
data["viruses"] = get_viruses_data(B)
data["resistances"] = get_resistance_data(B)
if(SYMPTOM_DETAILS)
data["symptom"] = get_symptom_data(selected_symptom)
return data
/obj/machinery/computer/pandemic/ui_act(action, params)
if(..())
return
switch(action)
if("eject_beaker")
replace_beaker(usr)
. = TRUE
if("empty_beaker")
if(beaker)
beaker.reagents.clear_reagents()
. = TRUE
if("empty_eject_beaker")
if(beaker)
beaker.reagents.clear_reagents()
replace_beaker(usr)
. = TRUE
if("rename_disease")
var/id = get_virus_id_by_index(text2num(params["index"]))
var/datum/disease/advance/A = SSdisease.archive_diseases[id]
if(!A.mutable)
return
if(A)
var/new_name = stripped_input(usr, "Name the disease", "New name", "", MAX_NAME_LEN)
if(!new_name || ..())
return
A.AssignName(new_name)
. = TRUE
if("create_culture_bottle")
var/id = get_virus_id_by_index(text2num(params["index"]))
var/datum/disease/advance/A = SSdisease.archive_diseases[id]
if(!istype(A) || !A.mutable)
to_chat(usr, "<span class='warning'>ERROR: Cannot replicate virus strain.</span>")
return
A = A.Copy()
var/list/data = list("blood_DNA" = "UNKNOWN DNA", "blood_type" = "SY", "viruses" = list(A))
var/obj/item/reagent_containers/glass/bottle/B = new(drop_location())
B.name = "[A.name] culture bottle"
B.desc = "A small bottle. Contains [A.agent] culture in synthblood medium."
B.reagents.add_reagent("blood", 20, data)
wait = TRUE
update_icon()
var/turf/source_turf = get_turf(src)
log_virus("A culture bottle was printed for the virus [A.admin_details()] at [loc_name(source_turf)] by [key_name(usr)]")
addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 50)
. = TRUE
if("create_vaccine_bottle")
var/id = params["index"]
var/datum/disease/D = SSdisease.archive_diseases[id]
var/obj/item/reagent_containers/glass/bottle/B = new(drop_location())
B.name = "[D.name] vaccine bottle"
B.reagents.add_reagent("vaccine", 15, list(id))
wait = TRUE
update_icon()
addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 200)
. = TRUE
if("symptom_details")
var/picked_symptom_index = text2num(params["picked_symptom"])
var/index = text2num(params["index"])
var/datum/disease/advance/A = get_by_index("viruses", index)
var/datum/symptom/S = A.symptoms[picked_symptom_index]
mode = SYMPTOM_DETAILS
selected_symptom = S
. = TRUE
if("back")
mode = MAIN_SCREEN
selected_symptom = null
. = TRUE
/obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/reagent_containers) && !(I.item_flags & ABSTRACT) && I.is_open_container())
. = TRUE //no afterattack
if(stat & (NOPOWER|BROKEN))
return
var/obj/item/reagent_containers/B = I
if(!user.transferItemToLoc(B, src))
return
replace_beaker(user, B)
to_chat(user, "<span class='notice'>You insert [I] into [src].</span>")
else
return ..()
/obj/machinery/computer/pandemic/AltClick(mob/living/user)
if(!istype(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
return
replace_beaker(user)
return
/obj/machinery/computer/pandemic/proc/replace_beaker(mob/living/user, obj/item/reagent_containers/new_beaker)
if(beaker)
if(user && Adjacent(user) && !issiliconoradminghost(user))
if(!user.put_in_hands(beaker))
beaker.forceMove(drop_location())
if(new_beaker)
beaker = new_beaker
else
beaker = null
update_icon()
return TRUE
/obj/machinery/computer/pandemic/on_deconstruction()
replace_beaker(usr)
. = ..()
@@ -0,0 +1,152 @@
#define REAGENTS_BASE_VOLUME 100 // actual volume is REAGENTS_BASE_VOLUME plus REAGENTS_BASE_VOLUME * rating for each matterbin
/obj/machinery/smoke_machine
name = "smoke machine"
desc = "A machine with a centrifuge installed into it. It produces smoke with any reagents you put into the machine."
icon = 'icons/obj/chemical.dmi'
icon_state = "smoke0"
density = TRUE
circuit = /obj/item/circuitboard/machine/smoke_machine
var/efficiency = 10
var/on = FALSE
var/cooldown = 0
var/screen = "home"
var/useramount = 30 // Last used amount
var/setting = 1 // displayed range is 3 * setting
var/max_range = 3 // displayed max range is 3 * max range
/datum/effect_system/smoke_spread/chem/smoke_machine/set_up(datum/reagents/carry, setting=1, efficiency=10, loc, silent=FALSE)
amount = setting
carry.copy_to(chemholder, 20)
carry.remove_any(amount * 16 / efficiency)
location = loc
/datum/effect_system/smoke_spread/chem/smoke_machine
effect_type = /obj/effect/particle_effect/smoke/chem/smoke_machine
/obj/effect/particle_effect/smoke/chem/smoke_machine
opaque = FALSE
alpha = 100
/obj/machinery/smoke_machine/Initialize()
. = ..()
create_reagents(REAGENTS_BASE_VOLUME)
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
reagents.maximum_volume += REAGENTS_BASE_VOLUME * B.rating
/obj/machinery/smoke_machine/update_icon()
if((!is_operational()) || (!on) || (reagents.total_volume == 0))
if (panel_open)
icon_state = "smoke0-o"
else
icon_state = "smoke0"
else
icon_state = "smoke1"
return ..()
/obj/machinery/smoke_machine/RefreshParts()
var/new_volume = REAGENTS_BASE_VOLUME
for(var/obj/item/stock_parts/matter_bin/B in component_parts)
new_volume += REAGENTS_BASE_VOLUME * B.rating
if(!reagents)
create_reagents(new_volume)
reagents.maximum_volume = new_volume
if(new_volume < reagents.total_volume)
reagents.reaction(loc, TOUCH) // if someone manages to downgrade it without deconstructing
reagents.clear_reagents()
efficiency = 9
for(var/obj/item/stock_parts/capacitor/C in component_parts)
efficiency += C.rating
max_range = 1
for(var/obj/item/stock_parts/manipulator/M in component_parts)
max_range += M.rating
max_range = max(3, max_range)
/obj/machinery/smoke_machine/process()
..()
if(!is_operational())
return
if(reagents.total_volume == 0)
on = FALSE
update_icon()
return
var/turf/T = get_turf(src)
var/smoke_test = locate(/obj/effect/particle_effect/smoke) in T
if(on && !smoke_test)
update_icon()
var/datum/effect_system/smoke_spread/chem/smoke_machine/smoke = new()
smoke.set_up(reagents, setting*3, efficiency, T)
smoke.start()
/obj/machinery/smoke_machine/attackby(obj/item/I, mob/user, params)
add_fingerprint(user)
if(istype(I, /obj/item/reagent_containers) && I.is_open_container())
var/obj/item/reagent_containers/RC = I
var/units = RC.reagents.trans_to(src, RC.amount_per_transfer_from_this)
if(units)
to_chat(user, "<span class='notice'>You transfer [units] units of the solution to [src].</span>")
log_combat(usr, src, "has added [english_list(RC.reagents.reagent_list)] to [src]")
return
if(default_unfasten_wrench(user, I, 40))
on = FALSE
return
if(default_deconstruction_screwdriver(user, "smoke0-o", "smoke0", I))
return
if(default_deconstruction_crowbar(I))
return
return ..()
/obj/machinery/smoke_machine/deconstruct()
reagents.reaction(loc, TOUCH)
reagents.clear_reagents()
return ..()
/obj/machinery/smoke_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "smoke_machine", name, 450, 350, master_ui, state)
ui.open()
/obj/machinery/smoke_machine/ui_data(mob/user)
var/data = list()
var/TankContents[0]
var/TankCurrentVolume = 0
for(var/datum/reagent/R in reagents.reagent_list)
TankContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list...
TankCurrentVolume += R.volume
data["TankContents"] = TankContents
data["isTankLoaded"] = reagents.total_volume ? TRUE : FALSE
data["TankCurrentVolume"] = reagents.total_volume ? reagents.total_volume : null
data["TankMaxVolume"] = reagents.maximum_volume
data["active"] = on
data["setting"] = setting
data["screen"] = screen
data["maxSetting"] = max_range
return data
/obj/machinery/smoke_machine/ui_act(action, params)
if(..() || !anchored)
return
switch(action)
if("purge")
reagents.clear_reagents()
update_icon()
. = TRUE
if("setting")
var/amount = text2num(params["amount"])
if(amount in 1 to max_range)
setting = amount
. = TRUE
if("power")
on = !on
update_icon()
if(on)
message_admins("[ADMIN_LOOKUPFLW(usr)] activated a smoke machine that contains [english_list(reagents.reagent_list)] at [ADMIN_VERBOSEJMP(src)].")
log_game("[key_name(usr)] activated a smoke machine that contains [english_list(reagents.reagent_list)] at [AREACOORD(src)].")
log_combat(usr, src, "has activated [src] which contains [english_list(reagents.reagent_list)] at [AREACOORD(src)].")
if("goScreen")
screen = params["screen"]
. = TRUE
#undef REAGENTS_BASE_VOLUME
+216
View File
@@ -0,0 +1,216 @@
#define REM REAGENTS_EFFECT_MULTIPLIER
//Various reagents
//Toxin & acid reagents
//Hydroponics stuff
/datum/reagent
var/name = "Reagent"
var/id = "reagent"
var/description = ""
var/specific_heat = SPECIFIC_HEAT_DEFAULT //J/(K*mol)
var/taste_description = "metaphorical salt"
var/taste_mult = 1 //how this taste compares to others. Higher values means it is more noticable
var/glass_name = "glass of ...what?" // use for specialty drinks.
var/glass_desc = "You can't really tell what this is."
var/glass_icon_state = null // Otherwise just sets the icon to a normal glass with the mixture of the reagents in the glass.
var/shot_glass_icon_state = null
var/datum/reagents/holder = null
var/reagent_state = LIQUID
var/list/data
var/current_cycle = 0
var/volume = 0 //pretend this is moles
var/color = "#000000" // rgb: 0, 0, 0
var/can_synth = TRUE // can this reagent be synthesized? (for example: odysseus syringe gun)
var/metabolization_rate = REAGENTS_METABOLISM //how fast the reagent is metabolized by the mob
var/overrides_metab = 0
var/overdose_threshold = 0
var/addiction_threshold = 0
var/addiction_stage = 0
var/addiction_stage1_end = 10
var/addiction_stage2_end = 20
var/addiction_stage3_end = 30
var/addiction_stage4_end = 40
var/overdosed = 0 // You fucked up and this is now triggering its overdose effects, purge that shit quick.
var/self_consuming = FALSE //I think this uhhh, makes weird stuff happen when metabolising, but... doesn't seem to do what I think, so I'm gonna leave it.
//Fermichem vars:
var/purity = 1 //How pure a chemical is from 0 - 1.
var/cached_purity = 1
var/turf/loc = null //Should be the creation location!
var/pH = 7 //pH of the specific reagent, used for calculating the sum pH of a holder.
//var/SplitChem = FALSE //If the chem splits on metabolism
var/impure_chem // What chemical is metabolised with an inpure reaction
var/inverse_chem_val = 0 // If the impurity is below 0.5, replace ALL of the chem with inverse_chemupon metabolising
var/inverse_chem // What chem is metabolised when purity is below inverse_chem_val, this shouldn't be made, but if it does, well, I guess I'll know about it.
var/metabolizing = FALSE
var/chemical_flags // See fermi/readme.dm REAGENT_DEAD_PROCESS, REAGENT_DONOTSPLIT, REAGENT_ONLYINVERSE, REAGENT_ONMOBMERGE, REAGENT_INVISIBLE, REAGENT_FORCEONNEW, REAGENT_SNEAKYNAME
var/value = 0 //How much does it sell for in cargo?
/datum/reagent/Destroy() // This should only be called by the holder, so it's already handled clearing its references
. = ..()
holder = null
/datum/reagent/proc/reaction_mob(mob/living/M, method=TOUCH, reac_volume, show_message = 1, touch_protection = 0)
if(!istype(M))
return 0
if(method == VAPOR) //smoke, foam, spray
if(M.reagents)
var/modifier = CLAMP((1 - touch_protection), 0, 1)
var/amount = round(reac_volume*modifier, 0.1)
if(amount >= 0.5)
M.reagents.add_reagent(id, amount)
return 1
/datum/reagent/proc/reaction_obj(obj/O, volume)
return
/datum/reagent/proc/reaction_turf(turf/T, volume)
return
/datum/reagent/proc/on_mob_life(mob/living/carbon/M)
current_cycle++
if(holder)
holder.remove_reagent(src.id, metabolization_rate * M.metabolism_efficiency) //By default it slowly disappears.
return
//called when a mob processes chems when dead.
/datum/reagent/proc/on_mob_dead(mob/living/carbon/M)
if(!(chemical_flags & REAGENT_DEAD_PROCESS)) //justincase
return
current_cycle++
if(holder)
holder.remove_reagent(src.id, metabolization_rate * M.metabolism_efficiency) //By default it slowly disappears.
return
// Called when this reagent is first added to a mob
/datum/reagent/proc/on_mob_add(mob/living/L, amount)
if(!iscarbon(L))
return
var/mob/living/carbon/M = L
if (purity == 1)
log_game("CHEM: [L] ckey: [L.key] has ingested [volume]u of [id]")
return
if(cached_purity == 1)
cached_purity = purity
else if(purity < 0)
CRASH("Purity below 0 for chem: [id], Please let Fermis Know!")
if(chemical_flags & REAGENT_DONOTSPLIT)
return
if ((inverse_chem_val > purity) && (inverse_chem))//Turns all of a added reagent into the inverse chem
M.reagents.remove_reagent(id, amount, FALSE)
M.reagents.add_reagent(inverse_chem, amount, FALSE, other_purity = 1-cached_purity)
var/datum/reagent/R = M.reagents.has_reagent("[inverse_chem]")
if(R.chemical_flags & REAGENT_SNEAKYNAME)
R.name = name//Negative effects are hidden
if(R.chemical_flags & REAGENT_INVISIBLE)
R.chemical_flags |= (REAGENT_INVISIBLE)
log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [inverse_chem]")
return
else if (impure_chem)
var/impureVol = amount * (1 - purity) //turns impure ratio into impure chem
if(!(chemical_flags & REAGENT_SPLITRETAINVOL))
M.reagents.remove_reagent(id, (impureVol), FALSE)
M.reagents.add_reagent(impure_chem, impureVol, FALSE, other_purity = 1-cached_purity)
log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume - impureVol]u of [id]")
log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [impure_chem]")
return
// Called when this reagent is removed while inside a mob
/datum/reagent/proc/on_mob_delete(mob/living/L)
return
// Called when this reagent first starts being metabolized by a liver
/datum/reagent/proc/on_mob_metabolize(mob/living/L)
return
// Called when this reagent stops being metabolized by a liver
/datum/reagent/proc/on_mob_end_metabolize(mob/living/L)
return
/datum/reagent/proc/on_move(mob/M)
return
// Called after add_reagents creates a new reagent.
/datum/reagent/proc/on_new(data)
return
// Called when two reagents of the same are mixing.
/datum/reagent/proc/on_merge(data, amount, mob/living/carbon/M, purity)
if(!iscarbon(M))
return
if (purity == 1)
log_game("FERMICHEM: [M] ckey: [M.key] has ingested [volume]u of [id]")
return
cached_purity = purity //purity SHOULD be precalculated from the add_reagent, update cache.
if (purity < 0)
CRASH("Purity below 0 for chem: [id], Please let Fermis Know!")
if(chemical_flags & REAGENT_DONOTSPLIT)
return
if ((inverse_chem_val > purity) && (inverse_chem)) //INVERT
M.reagents.remove_reagent(id, amount, FALSE)
M.reagents.add_reagent(inverse_chem, amount, FALSE, other_purity = 1-cached_purity)
var/datum/reagent/R = M.reagents.has_reagent("[inverse_chem]")
if(R.chemical_flags & REAGENT_SNEAKYNAME)
R.name = name//Negative effects are hidden
if(R.chemical_flags & REAGENT_INVISIBLE)
R.chemical_flags |= (REAGENT_INVISIBLE)
log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [inverse_chem]")
return
else if (impure_chem) //SPLIT
var/impureVol = amount * (1 - purity)
if(!(chemical_flags & REAGENT_SPLITRETAINVOL))
M.reagents.remove_reagent(id, impureVol, FALSE)
M.reagents.add_reagent(impure_chem, impureVol, FALSE, other_purity = 1-cached_purity)
log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume - impureVol]u of [id]")
log_game("FERMICHEM: [M] ckey: [M.key] has merged [volume]u of [impure_chem]")
return
/datum/reagent/proc/on_update(atom/A)
return
// Called when the reagent container is hit by an explosion
/datum/reagent/proc/on_ex_act(severity)
return
// Called if the reagent has passed the overdose threshold and is set to be triggering overdose effects
/datum/reagent/proc/overdose_process(mob/living/M)
return
/datum/reagent/proc/overdose_start(mob/living/M)
to_chat(M, "<span class='userdanger'>You feel like you took too much of [name]!</span>")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[id]_overdose", /datum/mood_event/overdose, name)
return
/datum/reagent/proc/addiction_act_stage1(mob/living/M)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[id]_overdose", /datum/mood_event/withdrawal_light, name)
if(prob(30))
to_chat(M, "<span class='notice'>You feel like having some [name] right about now.</span>")
return
/datum/reagent/proc/addiction_act_stage2(mob/living/M)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[id]_overdose", /datum/mood_event/withdrawal_medium, name)
if(prob(30))
to_chat(M, "<span class='notice'>You feel like you need [name]. You just can't get enough.</span>")
return
/datum/reagent/proc/addiction_act_stage3(mob/living/M)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[id]_overdose", /datum/mood_event/withdrawal_severe, name)
if(prob(30))
to_chat(M, "<span class='danger'>You have an intense craving for [name].</span>")
return
/datum/reagent/proc/addiction_act_stage4(mob/living/M)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[id]_overdose", /datum/mood_event/withdrawal_critical, name)
if(prob(30))
to_chat(M, "<span class='boldannounce'>You're not feeling good at all! You really need some [name].</span>")
return
/proc/pretty_string_from_reagent_list(list/reagent_list)
//Convert reagent list to a printable string for logging etc
var/list/rs = list()
for (var/datum/reagent/R in reagent_list)
rs += "[R.name], [R.volume]"
return rs.Join(" | ")
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,910 @@
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////// DRINKS BELOW, Beer is up there though, along with cola. Cap'n Pete's Cuban Spiced Rum////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////
/datum/reagent/consumable/orangejuice
name = "Orange Juice"
id = "orangejuice"
description = "Both delicious AND rich in Vitamin C, what more do you need?"
color = "#E78108" // rgb: 231, 129, 8
taste_description = "oranges"
glass_icon_state = "glass_orange"
glass_name = "glass of orange juice"
glass_desc = "Vitamins! Yay!"
pH = 3.3
/datum/reagent/consumable/orangejuice/on_mob_life(mob/living/carbon/M)
if(M.getOxyLoss() && prob(30))
M.adjustOxyLoss(-1, 0)
. = 1
..()
/datum/reagent/consumable/tomatojuice
name = "Tomato Juice"
id = "tomatojuice"
description = "Tomatoes made into juice. What a waste of big, juicy tomatoes, huh?"
color = "#731008" // rgb: 115, 16, 8
taste_description = "tomatoes"
glass_icon_state = "glass_red"
glass_name = "glass of tomato juice"
glass_desc = "Are you sure this is tomato juice?"
/datum/reagent/consumable/tomatojuice/on_mob_life(mob/living/carbon/M)
if(M.getFireLoss() && prob(20))
M.heal_bodypart_damage(0,1, 0)
. = 1
..()
/datum/reagent/consumable/limejuice
name = "Lime Juice"
id = "limejuice"
description = "The sweet-sour juice of limes."
color = "#365E30" // rgb: 54, 94, 48
taste_description = "unbearable sourness"
glass_icon_state = "glass_green"
glass_name = "glass of lime juice"
glass_desc = "A glass of sweet-sour lime juice."
pH = 2.2
/datum/reagent/consumable/limejuice/on_mob_life(mob/living/carbon/M)
if(M.getToxLoss() && prob(20))
M.adjustToxLoss(-1*REM, 0)
. = 1
..()
/datum/reagent/consumable/carrotjuice
name = "Carrot Juice"
id = "carrotjuice"
description = "It is just like a carrot but without crunching."
color = "#973800" // rgb: 151, 56, 0
taste_description = "carrots"
glass_icon_state = "carrotjuice"
glass_name = "glass of carrot juice"
glass_desc = "It's just like a carrot but without crunching."
/datum/reagent/consumable/carrotjuice/on_mob_life(mob/living/carbon/M)
M.adjust_blurriness(-1)
M.adjust_blindness(-1)
switch(current_cycle)
if(1 to 20)
//nothing
if(21 to INFINITY)
if(prob(current_cycle-10))
M.cure_nearsighted(list(EYE_DAMAGE))
..()
return
/datum/reagent/consumable/berryjuice
name = "Berry Juice"
id = "berryjuice"
description = "A delicious blend of several different kinds of berries."
color = "#863333" // rgb: 134, 51, 51
taste_description = "berries"
glass_icon_state = "berryjuice"
glass_name = "glass of berry juice"
glass_desc = "Berry juice. Or maybe it's jam. Who cares?"
/datum/reagent/consumable/applejuice
name = "Apple Juice"
id = "applejuice"
description = "The sweet juice of an apple, fit for all ages."
color = "#ECFF56" // rgb: 236, 255, 86
taste_description = "apples"
pH = 3.2 // ~ 2.7 -> 3.7
/datum/reagent/consumable/poisonberryjuice
name = "Poison Berry Juice"
id = "poisonberryjuice"
description = "A tasty juice blended from various kinds of very deadly and toxic berries."
color = "#863353" // rgb: 134, 51, 83
taste_description = "berries"
glass_icon_state = "poisonberryjuice"
glass_name = "glass of berry juice"
glass_desc = "Berry juice. Or maybe it's poison. Who cares?"
/datum/reagent/consumable/poisonberryjuice/on_mob_life(mob/living/carbon/M)
M.adjustToxLoss(1, 0)
. = 1
..()
/datum/reagent/consumable/watermelonjuice
name = "Watermelon Juice"
id = "watermelonjuice"
description = "Delicious juice made from watermelon."
color = "#863333" // rgb: 134, 51, 51
taste_description = "juicy watermelon"
glass_icon_state = "glass_red"
glass_name = "glass of watermelon juice"
glass_desc = "A glass of watermelon juice."
/datum/reagent/consumable/lemonjuice
name = "Lemon Juice"
id = "lemonjuice"
description = "This juice is VERY sour."
color = "#863333" // rgb: 175, 175, 0
taste_description = "sourness"
glass_icon_state = "lemonglass"
glass_name = "glass of lemon juice"
glass_desc = "Sour..."
pH = 2
/datum/reagent/consumable/banana
name = "Banana Juice"
id = "banana"
description = "The raw essence of a banana. HONK"
color = "#863333" // rgb: 175, 175, 0
taste_description = "banana"
glass_icon_state = "banana"
glass_name = "glass of banana juice"
glass_desc = "The raw essence of a banana. HONK."
/datum/reagent/consumable/banana/on_mob_life(mob/living/carbon/M)
if((ishuman(M) && M.job == "Clown") || ismonkey(M))
M.heal_bodypart_damage(1,1, 0)
. = 1
..()
/datum/reagent/consumable/nothing
name = "Nothing"
id = "nothing"
description = "Absolutely nothing."
taste_description = "nothing"
glass_icon_state = "nothing"
glass_name = "nothing"
glass_desc = "Absolutely nothing."
shot_glass_icon_state = "shotglass"
/datum/reagent/consumable/nothing/on_mob_life(mob/living/carbon/M)
if(ishuman(M) && M.job == "Mime")
M.heal_bodypart_damage(1,1, 0)
. = 1
..()
/datum/reagent/consumable/laughter
name = "Laughter"
id = "laughter"
description = "Some say that this is the best medicine, but recent studies have proven that to be untrue."
metabolization_rate = INFINITY
color = "#FF4DD2"
taste_description = "laughter"
/datum/reagent/consumable/laughter/on_mob_life(mob/living/carbon/M)
M.emote("laugh")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "chemical_laughter", /datum/mood_event/chemical_laughter)
..()
/datum/reagent/consumable/superlaughter
name = "Super Laughter"
id = "superlaughter"
description = "Funny until you're the one laughing."
metabolization_rate = 1.5 * REAGENTS_METABOLISM
color = "#FF4DD2"
taste_description = "laughter"
/datum/reagent/consumable/superlaughter/on_mob_life(mob/living/carbon/M)
if(prob(30))
M.visible_message("<span class='danger'>[M] bursts out into a fit of uncontrollable laughter!</span>", "<span class='userdanger'>You burst out in a fit of uncontrollable laughter!</span>")
M.Stun(5)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "chemical_laughter", /datum/mood_event/chemical_superlaughter)
..()
/datum/reagent/consumable/potato_juice
name = "Potato Juice"
id = "potato"
description = "Juice of the potato. Bleh."
nutriment_factor = 2 * REAGENTS_METABOLISM
color = "#302000" // rgb: 48, 32, 0
taste_description = "irish sadness"
glass_icon_state = "glass_brown"
glass_name = "glass of potato juice"
glass_desc = "Bleh..."
/datum/reagent/consumable/grapejuice
name = "Grape Juice"
id = "grapejuice"
description = "The juice of a bunch of grapes. Guaranteed non-alcoholic."
color = "#290029" // dark purple
taste_description = "grape soda"
/datum/reagent/consumable/milk
name = "Milk"
id = "milk"
description = "An opaque white liquid produced by the mammary glands of mammals."
color = "#DFDFDF" // rgb: 223, 223, 223
taste_description = "milk"
glass_icon_state = "glass_white"
glass_name = "glass of milk"
glass_desc = "White and nutritious goodness!"
pH = 6.5
/datum/reagent/consumable/milk/on_mob_life(mob/living/carbon/M)
if(HAS_TRAIT(M, TRAIT_CALCIUM_HEALER))
M.heal_bodypart_damage(1.5,0, 0)
. = 1
else
if(M.getBruteLoss() && prob(20))
M.heal_bodypart_damage(1,0, 0)
. = 1
if(holder.has_reagent("capsaicin"))
holder.remove_reagent("capsaicin", 2)
..()
/datum/reagent/consumable/soymilk
name = "Soy Milk"
id = "soymilk"
description = "An opaque white liquid made from soybeans."
color = "#DFDFC7" // rgb: 223, 223, 199
taste_description = "soy milk"
glass_icon_state = "glass_white"
glass_name = "glass of soy milk"
glass_desc = "White and nutritious soy goodness!"
/datum/reagent/consumable/soymilk/on_mob_life(mob/living/carbon/M)
if(M.getBruteLoss() && prob(20))
M.heal_bodypart_damage(1,0, 0)
. = 1
..()
/datum/reagent/consumable/cream
name = "Cream"
id = "cream"
description = "The fatty, still liquid part of milk. Why don't you mix this with sum scotch, eh?"
color = "#DFD7AF" // rgb: 223, 215, 175
taste_description = "creamy milk"
glass_icon_state = "glass_white"
glass_name = "glass of cream"
glass_desc = "Ewwww..."
/datum/reagent/consumable/cream/on_mob_life(mob/living/carbon/M)
if(M.getBruteLoss() && prob(20))
M.heal_bodypart_damage(1,0, 0)
. = 1
..()
/datum/reagent/consumable/coffee
name = "Coffee"
id = "coffee"
description = "Coffee is a brewed drink prepared from roasted seeds, commonly called coffee beans, of the coffee plant."
color = "#482000" // rgb: 72, 32, 0
nutriment_factor = 0
overdose_threshold = 80
taste_description = "bitterness"
glass_icon_state = "glass_brown"
glass_name = "glass of coffee"
glass_desc = "Don't drop it, or you'll send scalding liquid and glass shards everywhere."
/datum/reagent/consumable/coffee/overdose_process(mob/living/M)
M.Jitter(5)
..()
/datum/reagent/consumable/coffee/on_mob_life(mob/living/carbon/M)
M.dizziness = max(0,M.dizziness-5)
M.drowsyness = max(0,M.drowsyness-3)
M.AdjustSleeping(-40, FALSE)
//310.15 is the normal bodytemp.
M.adjust_bodytemperature(25 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
if(holder.has_reagent("frostoil"))
holder.remove_reagent("frostoil", 5)
..()
. = 1
/datum/reagent/consumable/tea
name = "Tea"
id = "tea"
description = "Tasty black tea, it has antioxidants, it's good for you!"
color = "#101000" // rgb: 16, 16, 0
nutriment_factor = 0
taste_description = "tart black tea"
glass_icon_state = "teaglass"
glass_name = "glass of tea"
glass_desc = "Drinking it from here would not seem right."
/datum/reagent/consumable/tea/on_mob_life(mob/living/carbon/M)
M.dizziness = max(0,M.dizziness-2)
M.drowsyness = max(0,M.drowsyness-1)
M.jitteriness = max(0,M.jitteriness-3)
M.AdjustSleeping(-20, FALSE)
if(M.getToxLoss() && prob(20))
M.adjustToxLoss(-1, 0)
M.adjust_bodytemperature(20 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
..()
. = 1
/datum/reagent/consumable/lemonade
name = "Lemonade"
id = "lemonade"
description = "Sweet, tangy lemonade. Good for the soul."
quality = DRINK_NICE
taste_description = "sunshine and summertime"
glass_icon_state = "lemonpitcher"
glass_name = "pitcher of lemonade"
glass_desc = "This drink leaves you feeling nostalgic for some reason."
/datum/reagent/consumable/tea/arnold_palmer
name = "Arnold Palmer"
id = "arnold_palmer"
description = "Encourages the patient to go golfing."
color = "#FFB766"
quality = DRINK_NICE
nutriment_factor = 2
taste_description = "bitter tea"
glass_icon_state = "arnold_palmer"
glass_name = "Arnold Palmer"
glass_desc = "You feel like taking a few golf swings after a few swigs of this."
/datum/reagent/consumable/tea/arnold_palmer/on_mob_life(mob/living/carbon/M)
if(prob(5))
to_chat(M, "<span class = 'notice'>[pick("You remember to square your shoulders.","You remember to keep your head down.","You can't decide between squaring your shoulders and keeping your head down.","You remember to relax.","You think about how someday you'll get two strokes off your golf game.")]</span>")
..()
. = 1
/datum/reagent/consumable/icecoffee
name = "Iced Coffee"
id = "icecoffee"
description = "Coffee and ice, refreshing and cool."
color = "#102838" // rgb: 16, 40, 56
nutriment_factor = 0
taste_description = "bitter coldness"
glass_icon_state = "icedcoffeeglass"
glass_name = "iced coffee"
glass_desc = "A drink to perk you up and refresh you!"
/datum/reagent/consumable/icecoffee/on_mob_life(mob/living/carbon/M)
M.dizziness = max(0,M.dizziness-5)
M.drowsyness = max(0,M.drowsyness-3)
M.AdjustSleeping(-40, FALSE)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
M.Jitter(5)
..()
. = 1
/datum/reagent/consumable/icetea
name = "Iced Tea"
id = "icetea"
description = "No relation to a certain rap artist/actor."
color = "#104038" // rgb: 16, 64, 56
nutriment_factor = 0
taste_description = "sweet tea"
glass_icon_state = "icedteaglass"
glass_name = "iced tea"
glass_desc = "All natural, antioxidant-rich flavour sensation."
/datum/reagent/consumable/icetea/on_mob_life(mob/living/carbon/M)
M.dizziness = max(0,M.dizziness-2)
M.drowsyness = max(0,M.drowsyness-1)
M.AdjustSleeping(-40, FALSE)
if(M.getToxLoss() && prob(20))
M.adjustToxLoss(-1, 0)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
. = 1
/datum/reagent/consumable/space_cola
name = "Cola"
id = "cola"
description = "A refreshing beverage."
color = "#100800" // rgb: 16, 8, 0
taste_description = "cola"
glass_icon_state = "glass_brown"
glass_name = "glass of Space Cola"
glass_desc = "A glass of refreshing Space Cola."
/datum/reagent/consumable/space_cola/on_mob_life(mob/living/carbon/M)
M.drowsyness = max(0,M.drowsyness-5)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/nuka_cola
name = "Nuka Cola"
id = "nuka_cola"
description = "Cola, cola never changes."
color = "#100800" // rgb: 16, 8, 0
quality = DRINK_VERYGOOD
taste_description = "the future"
glass_icon_state = "nuka_colaglass"
glass_name = "glass of Nuka Cola"
glass_desc = "Don't cry, Don't raise your eye, It's only nuclear wasteland."
/datum/reagent/consumable/nuka_cola/on_mob_metabolize(mob/living/L)
..()
L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/consumable/nuka_cola/on_mob_end_metabolize(mob/living/L)
L.remove_movespeed_modifier(id)
..()
/datum/reagent/consumable/nuka_cola/on_mob_life(mob/living/carbon/M)
M.Jitter(20)
M.set_drugginess(30)
M.dizziness +=1.5
M.drowsyness = 0
M.AdjustSleeping(-40, FALSE)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
. = 1
/datum/reagent/consumable/spacemountainwind
name = "SM Wind"
id = "spacemountainwind"
description = "Blows right through you like a space wind."
color = "#102000" // rgb: 16, 32, 0
taste_description = "sweet citrus soda"
glass_icon_state = "Space_mountain_wind_glass"
glass_name = "glass of Space Mountain Wind"
glass_desc = "Space Mountain Wind. As you know, there are no mountains in space, only wind."
/datum/reagent/consumable/spacemountainwind/on_mob_life(mob/living/carbon/M)
M.drowsyness = max(0,M.drowsyness-7)
M.AdjustSleeping(-20, FALSE)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
M.Jitter(5)
..()
. = 1
/datum/reagent/consumable/dr_gibb
name = "Dr. Gibb"
id = "dr_gibb"
description = "A delicious blend of 42 different flavours."
color = "#102000" // rgb: 16, 32, 0
taste_description = "cherry soda" // FALSE ADVERTISING
glass_icon_state = "dr_gibb_glass"
glass_name = "glass of Dr. Gibb"
glass_desc = "Dr. Gibb. Not as dangerous as the glass_name might imply."
/datum/reagent/consumable/dr_gibb/on_mob_life(mob/living/carbon/M)
M.drowsyness = max(0,M.drowsyness-6)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/space_up
name = "Space-Up"
id = "space_up"
description = "Tastes like a hull breach in your mouth."
color = "#00FF00" // rgb: 0, 255, 0
taste_description = "cherry soda"
glass_icon_state = "space-up_glass"
glass_name = "glass of Space-Up"
glass_desc = "Space-up. It helps you keep your cool."
/datum/reagent/consumable/space_up/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/lemon_lime
name = "Lemon Lime"
description = "A tangy substance made of 0.5% natural citrus!"
id = "lemon_lime"
color = "#8CFF00" // rgb: 135, 255, 0
taste_description = "tangy lime and lemon soda"
glass_icon_state = "glass_yellow"
glass_name = "glass of lemon-lime"
glass_desc = "You're pretty certain a real fruit has never actually touched this."
/datum/reagent/consumable/lemon_lime/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/pwr_game
name = "Pwr Game"
description = "The only drink with the PWR that true gamers crave."
id = "pwr_game"
color = "#9385bf" // rgb: 58, 52, 75
taste_description = "sweet and salty tang"
glass_icon_state = "glass_red"
glass_name = "glass of Pwr Game"
glass_desc = "Goes well with a Vlad's salad."
/datum/reagent/consumable/pwr_game/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/shamblers
name = "Shambler's Juice"
description = "~Shake me up some of that Shambler's Juice!~"
id = "shamblers"
color = "#f00060" // rgb: 94, 0, 38
taste_description = "carbonated metallic soda"
glass_icon_state = "glass_red"
glass_name = "glass of Shambler's juice"
glass_desc = "Mmm mm, shambly."
/datum/reagent/consumable/shamblers/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(-8 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/grey_bull
name = "Grey Bull"
id = "grey_bull"
description = "Grey Bull, it gives you gloves!"
color = "#EEFF00" // rgb: 238, 255, 0
quality = DRINK_VERYGOOD
taste_description = "carbonated oil"
glass_icon_state = "grey_bull_glass"
glass_name = "glass of Grey Bull"
glass_desc = "Surprisingly it isnt grey."
/datum/reagent/consumable/grey_bull/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_SHOCKIMMUNE, id)
/datum/reagent/consumable/grey_bull/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_SHOCKIMMUNE, id)
..()
/datum/reagent/consumable/grey_bull/on_mob_life(mob/living/carbon/M)
M.Jitter(20)
M.dizziness +=1
M.drowsyness = 0
M.AdjustSleeping(-40, FALSE)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/sodawater
name = "Soda Water"
id = "sodawater"
description = "A can of club soda. Why not make a scotch and soda?"
color = "#619494" // rgb: 97, 148, 148
taste_description = "carbonated water"
glass_icon_state = "glass_clear"
glass_name = "glass of soda water"
glass_desc = "Soda water. Why not make a scotch and soda?"
/datum/reagent/consumable/sodawater/on_mob_life(mob/living/carbon/M)
M.dizziness = max(0,M.dizziness-5)
M.drowsyness = max(0,M.drowsyness-3)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/tonic
name = "Tonic Water"
id = "tonic"
description = "It tastes strange but at least the quinine keeps the Space Malaria at bay."
color = "#0064C8" // rgb: 0, 100, 200
taste_description = "tart and fresh"
glass_icon_state = "glass_clear"
glass_name = "glass of tonic water"
glass_desc = "Quinine tastes funny, but at least it'll keep that Space Malaria away."
/datum/reagent/consumable/tonic/on_mob_life(mob/living/carbon/M)
M.dizziness = max(0,M.dizziness-5)
M.drowsyness = max(0,M.drowsyness-3)
M.AdjustSleeping(-40, FALSE)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
. = 1
/datum/reagent/consumable/ice
name = "Ice"
id = "ice"
description = "Frozen water, your dentist wouldn't like you chewing this."
reagent_state = SOLID
color = "#619494" // rgb: 97, 148, 148
taste_description = "ice"
glass_icon_state = "iceglass"
glass_name = "glass of ice"
glass_desc = "Generally, you're supposed to put something else in there too..."
/datum/reagent/consumable/ice/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/soy_latte
name = "Soy Latte"
id = "soy_latte"
description = "A nice and tasty beverage while you are reading your hippie books."
color = "#664300" // rgb: 102, 67, 0
quality = DRINK_NICE
taste_description = "creamy coffee"
glass_icon_state = "soy_latte"
glass_name = "soy latte"
glass_desc = "A nice and refreshing beverage while you're reading."
/datum/reagent/consumable/soy_latte/on_mob_life(mob/living/carbon/M)
M.dizziness = max(0,M.dizziness-5)
M.drowsyness = max(0,M.drowsyness-3)
M.SetSleeping(0, FALSE)
M.adjust_bodytemperature(5 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
M.Jitter(5)
if(M.getBruteLoss() && prob(20))
M.heal_bodypart_damage(1,0, 0)
..()
. = 1
/datum/reagent/consumable/cafe_latte
name = "Cafe Latte"
id = "cafe_latte"
description = "A nice, strong and tasty beverage while you are reading."
color = "#664300" // rgb: 102, 67, 0
quality = DRINK_NICE
taste_description = "bitter cream"
glass_icon_state = "cafe_latte"
glass_name = "cafe latte"
glass_desc = "A nice, strong and refreshing beverage while you're reading."
/datum/reagent/consumable/cafe_latte/on_mob_life(mob/living/carbon/M)
M.dizziness = max(0,M.dizziness-5)
M.drowsyness = max(0,M.drowsyness-3)
M.SetSleeping(0, FALSE)
M.adjust_bodytemperature(5 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
M.Jitter(5)
if(M.getBruteLoss() && prob(20))
M.heal_bodypart_damage(1,0, 0)
..()
. = 1
/datum/reagent/consumable/doctor_delight
name = "The Doctor's Delight"
id = "doctorsdelight"
description = "A gulp a day keeps the Medibot away! A mixture of juices that heals most damage types fairly quickly at the cost of hunger."
color = "#FF8CFF" // rgb: 255, 140, 255
quality = DRINK_VERYGOOD
taste_description = "homely fruit"
glass_icon_state = "doctorsdelightglass"
glass_name = "Doctor's Delight"
glass_desc = "The space doctor's favorite. Guaranteed to restore bodily injury; side effects include cravings and hunger."
/datum/reagent/consumable/doctor_delight/on_mob_life(mob/living/carbon/M)
M.adjustBruteLoss(-0.5, 0)
M.adjustFireLoss(-0.5, 0)
M.adjustToxLoss(-0.5, 0)
M.adjustOxyLoss(-0.5, 0)
if(M.nutrition && (M.nutrition - 2 > 0))
if(!(M.mind && M.mind.assigned_role == "Medical Doctor")) //Drains the nutrition of the holder. Not medical doctors though, since it's the Doctor's Delight!
M.nutrition -= 2
..()
. = 1
/datum/reagent/consumable/chocolatepudding
name = "Chocolate Pudding"
id = "chocolatepudding"
description = "A great dessert for chocolate lovers."
color = "#800000"
quality = DRINK_VERYGOOD
nutriment_factor = 4 * REAGENTS_METABOLISM
taste_description = "sweet chocolate"
glass_icon_state = "chocolatepudding"
glass_name = "chocolate pudding"
glass_desc = "Tasty."
/datum/reagent/consumable/vanillapudding
name = "Vanilla Pudding"
id = "vanillapudding"
description = "A great dessert for vanilla lovers."
color = "#FAFAD2"
quality = DRINK_VERYGOOD
nutriment_factor = 4 * REAGENTS_METABOLISM
taste_description = "sweet vanilla"
glass_icon_state = "vanillapudding"
glass_name = "vanilla pudding"
glass_desc = "Tasty."
/datum/reagent/consumable/cherryshake
name = "Cherry Shake"
id = "cherryshake"
description = "A cherry flavored milkshake."
color = "#FFB6C1"
quality = DRINK_VERYGOOD
nutriment_factor = 4 * REAGENTS_METABOLISM
taste_description = "creamy cherry"
glass_icon_state = "cherryshake"
glass_name = "cherry shake"
glass_desc = "A cherry flavored milkshake."
/datum/reagent/consumable/bluecherryshake
name = "Blue Cherry Shake"
id = "bluecherryshake"
description = "An exotic milkshake."
color = "#00F1FF"
quality = DRINK_VERYGOOD
nutriment_factor = 4 * REAGENTS_METABOLISM
taste_description = "creamy blue cherry"
glass_icon_state = "bluecherryshake"
glass_name = "blue cherry shake"
glass_desc = "An exotic blue milkshake."
/datum/reagent/consumable/pumpkin_latte
name = "Pumpkin Latte"
id = "pumpkin_latte"
description = "A mix of pumpkin juice and coffee."
color = "#F4A460"
quality = DRINK_VERYGOOD
nutriment_factor = 3 * REAGENTS_METABOLISM
taste_description = "creamy pumpkin"
glass_icon_state = "pumpkin_latte"
glass_name = "pumpkin latte"
glass_desc = "A mix of coffee and pumpkin juice."
/datum/reagent/consumable/gibbfloats
name = "Gibb Floats"
id = "gibbfloats"
description = "Ice cream on top of a Dr. Gibb glass."
color = "#B22222"
quality = DRINK_NICE
nutriment_factor = 3 * REAGENTS_METABOLISM
taste_description = "creamy cherry"
glass_icon_state = "gibbfloats"
glass_name = "Gibbfloat"
glass_desc = "Dr. Gibb with ice cream on top."
/datum/reagent/consumable/pumpkinjuice
name = "Pumpkin Juice"
id = "pumpkinjuice"
description = "Juiced from real pumpkin."
color = "#FFA500"
taste_description = "pumpkin"
/datum/reagent/consumable/blumpkinjuice
name = "Blumpkin Juice"
id = "blumpkinjuice"
description = "Juiced from real blumpkin."
color = "#00BFFF"
taste_description = "a mouthful of pool water"
/datum/reagent/consumable/triple_citrus
name = "Triple Citrus"
id = "triple_citrus"
description = "A solution."
color = "#fff12b"
quality = DRINK_NICE
taste_description = "extreme bitterness"
glass_icon_state = "triplecitrus" //needs own sprite mine are trash
glass_name = "glass of triple citrus"
glass_desc = "A mixture of citrus juices. Tangy, yet smooth."
/datum/reagent/consumable/grape_soda
name = "Grape soda"
id = "grapesoda"
description = "Beloved of children and teetotalers."
color = "#E6CDFF"
taste_description = "grape soda"
glass_name = "glass of grape juice"
glass_desc = "It's grape (soda)!"
/datum/reagent/consumable/grape_soda/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/milk/chocolate_milk
name = "Chocolate Milk"
id = "chocolate_milk"
description = "Milk for cool kids."
color = "#7D4E29"
quality = DRINK_NICE
taste_description = "chocolate milk"
/datum/reagent/consumable/menthol
name = "Menthol"
id = "menthol"
description = "Alleviates coughing symptoms one might have."
color = "#80AF9C"
taste_description = "mint"
glass_icon_state = "glass_green"
glass_name = "glass of menthol"
glass_desc = "Tastes naturally minty, and imparts a very mild numbing sensation."
/datum/reagent/consumable/grenadine
name = "Grenadine"
id = "grenadine"
description = "Not cherry flavored!"
color = "#EA1D26"
taste_description = "sweet pomegranates"
glass_name = "glass of grenadine"
glass_desc = "Delicious flavored syrup."
/datum/reagent/consumable/parsnipjuice
name = "Parsnip Juice"
id = "parsnipjuice"
description = "Why..."
color = "#FFA500"
taste_description = "parsnip"
glass_name = "glass of parsnip juice"
/datum/reagent/consumable/peachjuice //Intended to be extremely rare due to being the limiting ingredients in the blazaam drink
name = "Peach Juice"
id = "peachjuice"
description = "Just peachy."
color = "#E78108"
taste_description = "peaches"
glass_name = "glass of peach juice"
/datum/reagent/consumable/cream_soda
name = "Cream Soda"
id = "cream_soda"
description = "A classic space-American vanilla flavored soft drink."
color = "#dcb137"
quality = DRINK_VERYGOOD
taste_description = "fizzy vanilla"
glass_icon_state = "cream_soda"
glass_name = "Cream Soda"
glass_desc = "A classic space-American vanilla flavored soft drink."
/datum/reagent/consumable/cream_soda/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(-5 * TEMPERATURE_DAMAGE_COEFFICIENT, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/red_queen
name = "Red Queen"
id = "red_queen"
description = "DRINK ME."
color = "#e6ddc3"
quality = DRINK_GOOD
taste_description = "wonder"
glass_icon_state = "red_queen"
glass_name = "Red Queen"
glass_desc = "DRINK ME."
var/current_size = 1
/datum/reagent/consumable/red_queen/on_mob_life(mob/living/carbon/H)
if(prob(75))
return ..()
var/newsize = pick(0.5, 0.75, 1, 1.50, 2)
H.resize = newsize/current_size
current_size = newsize
H.update_transform()
if(prob(40))
H.emote("sneeze")
..()
/datum/reagent/consumable/red_queen/on_mob_end_metabolize(mob/living/M)
M.resize = 1/current_size
M.update_transform()
..()
/datum/reagent/consumable/pinkmilk
name = "Strawberry Milk"
id = "pinkmilk"
description = "A drink of a bygone era of milk and artificial sweetener back on a rock."
color = "#f76aeb"//rgb(247, 106, 235)
glass_icon_state = "pinkmilk"
quality = DRINK_FANTASTIC //Love drink
taste_description = "sweet strawberry and milk cream"
glass_name = "tall glass of strawberry milk"
glass_desc = "Delicious flavored strawberry syrup mixed with milk."
/datum/reagent/consumable/tea/pinkmilk/on_mob_life(mob/living/carbon/M)
if(prob(15))
to_chat(M, "<span class = 'notice'>[pick("You cant help to smile.","You feel nostalgia all of sudden.","You remember to relax.")]</span>")
..()
. = 1
/datum/reagent/consumable/pinktea //Tiny Tim song
name = "Strawberry Tea"
id = "pinktea"
description = "A timeless classic!"
color = "#f76aeb"//rgb(247, 106, 235)
glass_icon_state = "pinktea"
quality = DRINK_FANTASTIC //Love drink
taste_description = "sweet tea with a hint of strawberry"
glass_name = "mug of strawberry tea"
glass_desc = "Delicious traditional tea flavored with strawberries."
/datum/reagent/consumable/tea/pinktea/on_mob_life(mob/living/carbon/M)
if(prob(10))
to_chat(M, "<span class = 'notice'>[pick("Diamond skies where white deer fly.","Sipping strawberry tea.","Silver raindrops drift through timeless, Neverending June.","Crystal ... pearls free, with love!","Beaming love into me.")]</span>")
..()
. = 1
/datum/reagent/consumable/catnip_tea
name = "Catnip Tea"
id = "catnip_tea"
description = "A sleepy and tasty catnip tea!"
color = "#101000" // rgb: 16, 16, 0
nutriment_factor = 0
taste_description = "sugar and catnip"
glass_icon_state = "teaglass"
glass_name = "glass of catnip tea"
glass_desc = "A purrfect drink for a cat."
/datum/reagent/consumable/catnip_tea/on_mob_life(mob/living/carbon/M)
M.adjustStaminaLoss(min(50 - M.getStaminaLoss(), 3))
if(prob(20))
M.emote("nya")
if(prob(20))
to_chat(M, "<span class = 'notice'>[pick("Headpats feel nice.", "Backrubs would be nice.", "Mew")]</span>")
M.adjustArousalLoss(5)
..()
@@ -0,0 +1,529 @@
/datum/reagent/drug
name = "Drug"
id = "drug"
value = 12
metabolization_rate = 0.5 * REAGENTS_METABOLISM
taste_description = "bitterness"
var/trippy = TRUE //Does this drug make you trip?
/datum/reagent/drug/on_mob_end_metabolize(mob/living/M)
if(trippy)
SEND_SIGNAL(M, COMSIG_CLEAR_MOOD_EVENT, "[id]_high")
/datum/reagent/drug/space_drugs
name = "Space drugs"
id = "space_drugs"
description = "An illegal chemical compound used as drug."
color = "#60A584" // rgb: 96, 165, 132
overdose_threshold = 30
pH = 9
/datum/reagent/drug/space_drugs/on_mob_life(mob/living/carbon/M)
M.set_drugginess(15)
if(isturf(M.loc) && !isspaceturf(M.loc))
if(M.canmove)
if(prob(10))
step(M, pick(GLOB.cardinals))
if(prob(7))
M.emote(pick("twitch","drool","moan","giggle"))
..()
/datum/reagent/drug/space_drugs/overdose_start(mob/living/M)
to_chat(M, "<span class='userdanger'>You start tripping hard!</span>")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "[id]_overdose", /datum/mood_event/overdose, name)
/datum/reagent/drug/space_drugs/overdose_process(mob/living/M)
if(M.hallucination < volume && prob(20))
M.hallucination += 5
..()
/datum/reagent/drug/nicotine
name = "Nicotine"
id = "nicotine"
description = "Slightly reduces stun times. If overdosed it will deal toxin and oxygen damage."
reagent_state = LIQUID
color = "#60A584" // rgb: 96, 165, 132
addiction_threshold = 30
taste_description = "smoke"
trippy = FALSE
pH = 8
/datum/reagent/drug/nicotine/on_mob_life(mob/living/carbon/M)
if(prob(1))
var/smoke_message = pick("You feel relaxed.", "You feel calmed.","You feel alert.","You feel rugged.")
to_chat(M, "<span class='notice'>[smoke_message]</span>")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "smoked", /datum/mood_event/smoked, name)
M.AdjustStun(-20, 0)
M.AdjustKnockdown(-20, 0)
M.AdjustUnconscious(-20, 0)
M.adjustStaminaLoss(-0.5*REM, 0)
..()
. = 1
/datum/reagent/drug/crank
name = "Crank"
id = "crank"
description = "Reduces stun times by about 200%. If overdosed or addicted it will deal significant Toxin, Brute and Brain damage."
reagent_state = LIQUID
color = "#FA00C8"
overdose_threshold = 20
addiction_threshold = 10
pH = 10
/datum/reagent/drug/crank/on_mob_life(mob/living/carbon/M)
if(prob(5))
var/high_message = pick("You feel jittery.", "You feel like you gotta go fast.", "You feel like you need to step it up.")
to_chat(M, "<span class='notice'>[high_message]</span>")
M.AdjustStun(-20, 0)
M.AdjustKnockdown(-20, 0)
M.AdjustUnconscious(-20, 0)
..()
. = 1
/datum/reagent/drug/crank/overdose_process(mob/living/M)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM)
M.adjustToxLoss(2*REM, 0)
M.adjustBruteLoss(2*REM, 0)
..()
. = 1
/datum/reagent/drug/crank/addiction_act_stage1(mob/living/M)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5*REM)
..()
/datum/reagent/drug/crank/addiction_act_stage2(mob/living/M)
M.adjustToxLoss(5*REM, 0)
..()
. = 1
/datum/reagent/drug/crank/addiction_act_stage3(mob/living/M)
M.adjustBruteLoss(5*REM, 0)
..()
. = 1
/datum/reagent/drug/crank/addiction_act_stage4(mob/living/M)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 3*REM)
M.adjustToxLoss(5*REM, 0)
M.adjustBruteLoss(5*REM, 0)
..()
. = 1
/datum/reagent/drug/krokodil
name = "Krokodil"
id = "krokodil"
description = "Cools and calms you down. If overdosed it will deal significant Brain and Toxin damage. If addicted it will begin to deal fatal amounts of Brute damage as the subject's skin falls off."
reagent_state = LIQUID
color = "#0064B4"
overdose_threshold = 20
addiction_threshold = 15
pH = 9
/datum/reagent/drug/krokodil/on_mob_life(mob/living/carbon/M)
var/high_message = pick("You feel calm.", "You feel collected.", "You feel like you need to relax.")
if(prob(5))
to_chat(M, "<span class='notice'>[high_message]</span>")
..()
/datum/reagent/drug/krokodil/overdose_process(mob/living/M)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.25*REM)
M.adjustToxLoss(0.25*REM, 0)
..()
. = 1
/datum/reagent/drug/krokodil/addiction_act_stage1(mob/living/M)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM)
M.adjustToxLoss(2*REM, 0)
..()
. = 1
/datum/reagent/drug/krokodil/addiction_act_stage2(mob/living/M)
if(prob(25))
to_chat(M, "<span class='danger'>Your skin feels loose...</span>")
..()
/datum/reagent/drug/krokodil/addiction_act_stage3(mob/living/M)
if(prob(25))
to_chat(M, "<span class='danger'>Your skin starts to peel away...</span>")
M.adjustBruteLoss(3*REM, 0)
..()
. = 1
/datum/reagent/drug/krokodil/addiction_act_stage4(mob/living/carbon/human/M)
CHECK_DNA_AND_SPECIES(M)
if(!istype(M.dna.species, /datum/species/krokodil_addict))
to_chat(M, "<span class='userdanger'>Your skin falls off easily!</span>")
M.adjustBruteLoss(50*REM, 0) // holy shit your skin just FELL THE FUCK OFF
M.set_species(/datum/species/krokodil_addict)
else
M.adjustBruteLoss(5*REM, 0)
..()
. = 1
/datum/reagent/drug/methamphetamine
name = "Methamphetamine"
id = "methamphetamine"
description = "Reduces stun times by about 300%, and allows the user to quickly recover stamina while dealing a small amount of Brain damage. If overdosed the subject will move randomly, laugh randomly, drop items and suffer from Toxin and Brain damage. If addicted the subject will constantly jitter and drool, before becoming dizzy and losing motor control and eventually suffer heavy toxin damage."
reagent_state = LIQUID
color = "#FAFAFA"
overdose_threshold = 20
addiction_threshold = 10
metabolization_rate = 0.75 * REAGENTS_METABOLISM
var/brain_damage = TRUE
var/jitter = TRUE
var/confusion = TRUE
pH = 5
/datum/reagent/drug/methamphetamine/on_mob_metabolize(mob/living/L)
..()
L.ignore_slowdown(id)
/datum/reagent/drug/methamphetamine/on_mob_end_metabolize(mob/living/L)
L.unignore_slowdown(id)
..()
/datum/reagent/drug/methamphetamine/on_mob_life(mob/living/carbon/M)
var/high_message = pick("You feel hyper.", "You feel like you need to go faster.", "You feel like you can run the world.")
if(prob(5))
to_chat(M, "<span class='notice'>[high_message]</span>")
M.AdjustStun(-40, 0)
M.AdjustKnockdown(-40, 0)
M.AdjustUnconscious(-40, 0)
M.adjustStaminaLoss(-7.5 * REM, 0)
if(jitter)
M.Jitter(2)
if(brain_damage)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, rand(1,4))
M.heal_overall_damage(2, 2)
if(prob(5))
M.emote(pick("twitch", "shiver"))
..()
. = 1
/datum/reagent/drug/methamphetamine/overdose_process(mob/living/M)
if(M.canmove && !ismovableatom(M.loc))
for(var/i in 1 to 4)
step(M, pick(GLOB.cardinals))
if(prob(20))
M.emote("laugh")
if(prob(33))
M.visible_message("<span class='danger'>[M]'s hands flip out and flail everywhere!</span>")
M.drop_all_held_items()
..()
M.adjustToxLoss(1, 0)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, pick(0.5, 0.6, 0.7, 0.8, 0.9, 1))
. = 1
/datum/reagent/drug/methamphetamine/addiction_act_stage1(mob/living/M)
M.Jitter(5)
if(prob(20))
M.emote(pick("twitch","drool","moan"))
..()
/datum/reagent/drug/methamphetamine/addiction_act_stage2(mob/living/M)
M.Jitter(10)
M.Dizzy(10)
if(prob(30))
M.emote(pick("twitch","drool","moan"))
..()
/datum/reagent/drug/methamphetamine/addiction_act_stage3(mob/living/M)
if(M.canmove && !ismovableatom(M.loc))
for(var/i = 0, i < 4, i++)
step(M, pick(GLOB.cardinals))
M.Jitter(15)
M.Dizzy(15)
if(prob(40))
M.emote(pick("twitch","drool","moan"))
..()
/datum/reagent/drug/methamphetamine/addiction_act_stage4(mob/living/carbon/human/M)
if(M.canmove && !ismovableatom(M.loc))
for(var/i = 0, i < 8, i++)
step(M, pick(GLOB.cardinals))
M.Jitter(20)
M.Dizzy(20)
M.adjustToxLoss(5, 0)
if(prob(50))
M.emote(pick("twitch","drool","moan"))
..()
. = 1
/datum/reagent/drug/methamphetamine/changeling
id = "changelingmeth"
name = "Changeling Adrenaline"
addiction_threshold = 35
overdose_threshold = 35
jitter = FALSE
brain_damage = FALSE
/datum/reagent/drug/bath_salts
name = "Bath Salts"
id = "bath_salts"
description = "Makes you impervious to stuns and grants a stamina regeneration buff, but you will be a nearly uncontrollable tramp-bearded raving lunatic."
reagent_state = LIQUID
color = "#FAFAFA"
overdose_threshold = 20
addiction_threshold = 10
taste_description = "salt" // because they're bathsalts?
var/datum/brain_trauma/special/psychotic_brawling/bath_salts/rage
pH = 8.2
/datum/reagent/drug/bath_salts/on_mob_metabolize(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_STUNIMMUNE, id)
ADD_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
if(iscarbon(L))
var/mob/living/carbon/C = L
rage = new()
C.gain_trauma(rage, TRAUMA_RESILIENCE_ABSOLUTE)
/datum/reagent/drug/bath_salts/on_mob_end_metabolize(mob/living/L)
REMOVE_TRAIT(L, TRAIT_STUNIMMUNE, id)
REMOVE_TRAIT(L, TRAIT_SLEEPIMMUNE, id)
if(rage)
QDEL_NULL(rage)
..()
/datum/reagent/drug/bath_salts/on_mob_life(mob/living/carbon/M)
var/high_message = pick("You feel amped up.", "You feel ready.", "You feel like you can push it to the limit.")
if(prob(5))
to_chat(M, "<span class='notice'>[high_message]</span>")
M.adjustStaminaLoss(-5, 0)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 4)
M.hallucination += 5
if(M.canmove && !ismovableatom(M.loc))
step(M, pick(GLOB.cardinals))
step(M, pick(GLOB.cardinals))
..()
. = 1
/datum/reagent/drug/bath_salts/overdose_process(mob/living/M)
M.hallucination += 5
if(M.canmove && !ismovableatom(M.loc))
for(var/i in 1 to 8)
step(M, pick(GLOB.cardinals))
if(prob(20))
M.emote(pick("twitch","drool","moan"))
if(prob(33))
M.drop_all_held_items()
..()
/datum/reagent/drug/bath_salts/addiction_act_stage1(mob/living/M)
M.hallucination += 10
if(M.canmove && !ismovableatom(M.loc))
for(var/i = 0, i < 8, i++)
step(M, pick(GLOB.cardinals))
M.Jitter(5)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10)
if(prob(20))
M.emote(pick("twitch","drool","moan"))
..()
/datum/reagent/drug/bath_salts/addiction_act_stage2(mob/living/M)
M.hallucination += 20
if(M.canmove && !ismovableatom(M.loc))
for(var/i = 0, i < 8, i++)
step(M, pick(GLOB.cardinals))
M.Jitter(10)
M.Dizzy(10)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10)
if(prob(30))
M.emote(pick("twitch","drool","moan"))
..()
/datum/reagent/drug/bath_salts/addiction_act_stage3(mob/living/M)
M.hallucination += 30
if(M.canmove && !ismovableatom(M.loc))
for(var/i = 0, i < 12, i++)
step(M, pick(GLOB.cardinals))
M.Jitter(15)
M.Dizzy(15)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10)
if(prob(40))
M.emote(pick("twitch","drool","moan"))
..()
/datum/reagent/drug/bath_salts/addiction_act_stage4(mob/living/carbon/human/M)
M.hallucination += 30
if(M.canmove && !ismovableatom(M.loc))
for(var/i = 0, i < 16, i++)
step(M, pick(GLOB.cardinals))
M.Jitter(50)
M.Dizzy(50)
M.adjustToxLoss(5, 0)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 10)
if(prob(50))
M.emote(pick("twitch","drool","moan"))
..()
. = 1
/datum/reagent/drug/aranesp
name = "Aranesp"
id = "aranesp"
description = "Amps you up and gets you going, fixes all stamina damage you might have but can cause toxin and oxygen damage."
reagent_state = LIQUID
color = "#78FFF0"
pH = 9.2
/datum/reagent/drug/aranesp/on_mob_life(mob/living/carbon/M)
var/high_message = pick("You feel amped up.", "You feel ready.", "You feel like you can push it to the limit.")
if(prob(5))
to_chat(M, "<span class='notice'>[high_message]</span>")
M.adjustStaminaLoss(-18, 0)
M.adjustToxLoss(0.5, 0)
if(prob(50))
M.losebreath++
M.adjustOxyLoss(1, 0)
..()
. = 1
/datum/reagent/drug/happiness
name = "Happiness"
id = "happiness"
description = "Fills you with ecstasic numbness and causes minor brain damage. Highly addictive. If overdosed causes sudden mood swings."
reagent_state = LIQUID
color = "#FFF378"
addiction_threshold = 10
overdose_threshold = 20
pH = 10.5
/datum/reagent/drug/happiness/on_mob_add(mob/living/L)
..()
ADD_TRAIT(L, TRAIT_FEARLESS, id)
SEND_SIGNAL(L, COMSIG_ADD_MOOD_EVENT, "happiness_drug", /datum/mood_event/happiness_drug)
/datum/reagent/drug/happiness/on_mob_delete(mob/living/L)
REMOVE_TRAIT(L, TRAIT_FEARLESS, id)
SEND_SIGNAL(L, COMSIG_CLEAR_MOOD_EVENT, "happiness_drug")
..()
/datum/reagent/drug/happiness/on_mob_life(mob/living/carbon/M)
M.jitteriness = 0
M.confused = 0
M.disgust = 0
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2)
..()
. = 1
/datum/reagent/drug/happiness/overdose_process(mob/living/M)
if(prob(30))
var/reaction = rand(1,3)
switch(reaction)
if(1)
M.emote("laugh")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "happiness_drug", /datum/mood_event/happiness_drug_good_od)
if(2)
M.emote("sway")
M.Dizzy(25)
if(3)
M.emote("frown")
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "happiness_drug", /datum/mood_event/happiness_drug_bad_od)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.5)
..()
. = 1
/datum/reagent/drug/happiness/addiction_act_stage1(mob/living/M)// all work and no play makes jack a dull boy
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(min(mood.sanity, SANITY_DISTURBED))
M.Jitter(5)
if(prob(20))
M.emote(pick("twitch","laugh","frown"))
..()
/datum/reagent/drug/happiness/addiction_act_stage2(mob/living/M)
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(min(mood.sanity, SANITY_UNSTABLE))
M.Jitter(10)
if(prob(30))
M.emote(pick("twitch","laugh","frown"))
..()
/datum/reagent/drug/happiness/addiction_act_stage3(mob/living/M)
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(min(mood.sanity, SANITY_CRAZY))
M.Jitter(15)
if(prob(40))
M.emote(pick("twitch","laugh","frown"))
..()
/datum/reagent/drug/happiness/addiction_act_stage4(mob/living/carbon/human/M)
var/datum/component/mood/mood = M.GetComponent(/datum/component/mood)
mood.setSanity(SANITY_INSANE)
M.Jitter(20)
if(prob(50))
M.emote(pick("twitch","laugh","frown"))
..()
. = 1
/datum/reagent/drug/skooma
name = "Skooma"
id = "skooma"
description = "An ancient, highly-addictive drug of long-forgotten times. It greatly improves the user's speed and strength, but heavily impedes their intelligence and agility."
reagent_state = LIQUID
color = "#F3E0F9"
taste_description = "ancient, unfulfilled prophecies"
addiction_threshold = 1
addiction_stage3_end = 40
addiction_stage4_end = 240
pH = 12.5
/datum/reagent/drug/skooma/on_mob_metabolize(mob/living/L)
. = ..()
L.add_movespeed_modifier(id, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
L.next_move_modifier *= 2
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.physiology)
H.physiology.stamina_mod *= 0.5
if(H.dna && H.dna.species)
H.dna.species.punchdamagehigh *= 5
/datum/reagent/drug/skooma/on_mob_end_metabolize(mob/living/L)
. = ..()
L.remove_movespeed_modifier(id)
L.next_move_modifier *= 0.5
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(H.physiology)
H.physiology.stamina_mod *= 2
if(H.dna && H.dna.species)
H.dna.species.punchdamagehigh *= 0.2
/datum/reagent/drug/skooma/on_mob_life(mob/living/carbon/M)
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 1*REM)
M.adjustToxLoss(1*REM)
if(prob(10))
M.adjust_blurriness(2)
..()
. = 1
/datum/reagent/drug/skooma/addiction_act_stage1(mob/living/M)
M.Jitter(10)
if(prob(50))
M.adjust_blurriness(2)
..()
/datum/reagent/drug/skooma/addiction_act_stage2(mob/living/M)
M.Jitter(20)
M.Dizzy(10)
M.adjust_blurriness(2)
..()
/datum/reagent/drug/skooma/addiction_act_stage3(mob/living/M)
M.Jitter(50)
M.Dizzy(20)
M.adjust_blurriness(4)
if(prob(20))
M.emote(pick("twitch","drool","moan"))
..()
/datum/reagent/drug/skooma/addiction_act_stage4(mob/living/M)
M.Jitter(50)
M.Dizzy(50)
M.adjust_blurriness(10)
if(prob(50)) //This proc will be called about 200 times and the adjustbrainloss() below only has to be called 40 times to kill. This will make surviving skooma addiction pretty rare without mannitol usage.
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
if(prob(40))
M.emote(pick("twitch","drool","moan"))
..()
@@ -0,0 +1,788 @@
///////////////////////////////////////////////////////////////////
//Food Reagents
//////////////////////////////////////////////////////////////////
// Part of the food code. Also is where all the food
// condiments, additives, and such go.
/datum/reagent/consumable
name = "Consumable"
id = "consumable"
taste_description = "generic food"
taste_mult = 4
value = 0.1
var/nutriment_factor = 1 * REAGENTS_METABOLISM
var/quality = 0 //affects mood, typically higher for mixed drinks with more complex recipes
/datum/reagent/consumable/on_mob_life(mob/living/carbon/M)
current_cycle++
M.nutrition += nutriment_factor
holder.remove_reagent(src.id, metabolization_rate)
/datum/reagent/consumable/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(method == INGEST)
if (quality && !HAS_TRAIT(M, TRAIT_AGEUSIA))
switch(quality)
if (DRINK_NICE)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_nice)
if (DRINK_GOOD)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_good)
if (DRINK_VERYGOOD)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_verygood)
if (DRINK_FANTASTIC)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_drink", /datum/mood_event/quality_fantastic)
if (FOOD_AMAZING)
SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "quality_food", /datum/mood_event/amazingtaste)
return ..()
/datum/reagent/consumable/nutriment
name = "Nutriment"
id = "nutriment"
description = "All the vitamins, minerals, and carbohydrates the body needs in pure form."
reagent_state = SOLID
nutriment_factor = 15 * REAGENTS_METABOLISM
color = "#664330" // rgb: 102, 67, 48
var/brute_heal = 1
var/burn_heal = 0
/datum/reagent/consumable/nutriment/on_mob_life(mob/living/carbon/M)
if(prob(50))
M.heal_bodypart_damage(brute_heal,burn_heal, 0)
. = 1
..()
/datum/reagent/consumable/nutriment/on_new(list/supplied_data)
// taste data can sometimes be ("salt" = 3, "chips" = 1)
// and we want it to be in the form ("salt" = 0.75, "chips" = 0.25)
// which is called "normalizing"
if(!supplied_data)
supplied_data = data
// if data isn't an associative list, this has some WEIRD side effects
// TODO probably check for assoc list?
data = counterlist_normalise(supplied_data)
/datum/reagent/consumable/nutriment/on_merge(list/newdata, newvolume)
if(!islist(newdata) || !newdata.len)
return
// data for nutriment is one or more (flavour -> ratio)
// where all the ratio values adds up to 1
var/list/taste_amounts = list()
if(data)
taste_amounts = data.Copy()
counterlist_scale(taste_amounts, volume)
var/list/other_taste_amounts = newdata.Copy()
counterlist_scale(other_taste_amounts, newvolume)
counterlist_combine(taste_amounts, other_taste_amounts)
counterlist_normalise(taste_amounts)
data = taste_amounts
/datum/reagent/consumable/nutriment/vitamin
name = "Vitamin"
id = "vitamin"
description = "All the best vitamins, minerals, and carbohydrates the body needs in pure form."
value = 0.5
brute_heal = 1
burn_heal = 1
/datum/reagent/consumable/nutriment/vitamin/on_mob_life(mob/living/carbon/M)
if(M.satiety < 600)
M.satiety += 30
. = ..()
/datum/reagent/consumable/cooking_oil
name = "Cooking Oil"
id = "cooking_oil"
description = "A variety of cooking oil derived from fat or plants. Used in food preparation and frying."
color = "#EADD6B" //RGB: 234, 221, 107 (based off of canola oil)
taste_mult = 0.8
value = 1
taste_description = "oil"
nutriment_factor = 7 * REAGENTS_METABOLISM //Not very healthy on its own
metabolization_rate = 10 * REAGENTS_METABOLISM
var/fry_temperature = 450 //Around ~350 F (117 C) which deep fryers operate around in the real world
var/boiling //Used in mob life to determine if the oil kills, and only on touch application
/datum/reagent/consumable/cooking_oil/reaction_obj(obj/O, reac_volume)
if(holder && holder.chem_temp >= fry_temperature)
if(isitem(O) && !istype(O, /obj/item/reagent_containers/food/snacks/deepfryholder) && !(O.resistance_flags & (FIRE_PROOF|INDESTRUCTIBLE)))
O.loc.visible_message("<span class='warning'>[O] rapidly fries as it's splashed with hot oil! Somehow.</span>")
var/obj/item/reagent_containers/food/snacks/deepfryholder/F = new(O.drop_location(), O)
F.fry(volume)
F.reagents.add_reagent("cooking_oil", reac_volume)
/datum/reagent/consumable/cooking_oil/reaction_mob(mob/living/M, method = TOUCH, reac_volume, show_message = 1, touch_protection = 0)
if(!istype(M))
return
if(holder && holder.chem_temp >= fry_temperature)
boiling = TRUE
if(method == VAPOR || method == TOUCH) //Directly coats the mob, and doesn't go into their bloodstream
if(boiling)
M.visible_message("<span class='warning'>The boiling oil sizzles as it covers [M]!</span>", \
"<span class='userdanger'>You're covered in boiling oil!</span>")
M.emote("scream")
playsound(M, 'sound/machines/fryer/deep_fryer_emerge.ogg', 25, TRUE)
var/oil_damage = (holder.chem_temp / fry_temperature) * 0.33 //Damage taken per unit
M.adjustFireLoss(min(35, oil_damage * reac_volume)) //Damage caps at 35
else
..()
return TRUE
/datum/reagent/consumable/cooking_oil/reaction_turf(turf/open/T, reac_volume)
if(!istype(T) || isgroundlessturf(T))
return
if(reac_volume >= 5)
T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = reac_volume * 1.5 SECONDS)
T.name = "deep-fried [initial(T.name)]"
T.add_atom_colour(color, TEMPORARY_COLOUR_PRIORITY)
/datum/reagent/consumable/sugar
name = "Sugar"
id = "sugar"
description = "The organic compound commonly known as table sugar and sometimes called saccharose. This white, odorless, crystalline powder has a pleasing, sweet taste."
reagent_state = SOLID
color = "#FFFFFF" // rgb: 255, 255, 255
taste_mult = 1.5 // stop sugar drowning out other flavours
nutriment_factor = 10 * REAGENTS_METABOLISM
metabolization_rate = 2 * REAGENTS_METABOLISM
overdose_threshold = 200 // Hyperglycaemic shock
taste_description = "sweetness"
value = 1
/datum/reagent/consumable/sugar/overdose_start(mob/living/M)
to_chat(M, "<span class='userdanger'>You go into hyperglycaemic shock! Lay off the twinkies!</span>")
M.AdjustSleeping(600, FALSE)
. = 1
/datum/reagent/consumable/sugar/overdose_process(mob/living/M)
M.AdjustSleeping(40, FALSE)
..()
. = 1
/datum/reagent/consumable/virus_food
name = "Virus Food"
id = "virusfood"
description = "A mixture of water and milk. Virus cells can use this mixture to reproduce."
nutriment_factor = 2 * REAGENTS_METABOLISM
color = "#899613" // rgb: 137, 150, 19
taste_description = "watery milk"
/datum/reagent/consumable/soysauce
name = "Soysauce"
id = "soysauce"
description = "A salty sauce made from the soy plant."
nutriment_factor = 2 * REAGENTS_METABOLISM
color = "#792300" // rgb: 121, 35, 0
taste_description = "umami"
/datum/reagent/consumable/ketchup
name = "Ketchup"
id = "ketchup"
description = "Ketchup, catsup, whatever. It's tomato paste."
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#731008" // rgb: 115, 16, 8
taste_description = "ketchup"
/datum/reagent/consumable/mustard
name = "Mustard"
id = "mustard"
description = "Mustard, mostly used on hotdogs, corndogs and burgers."
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#DDED26" // rgb: 221, 237, 38
taste_description = "mustard"
/datum/reagent/consumable/capsaicin
name = "Capsaicin Oil"
id = "capsaicin"
description = "This is what makes chilis hot."
color = "#B31008" // rgb: 179, 16, 8
taste_description = "hot peppers"
taste_mult = 1.5
/datum/reagent/consumable/capsaicin/on_mob_life(mob/living/carbon/M)
var/heating = 0
switch(current_cycle)
if(1 to 15)
heating = 5 * TEMPERATURE_DAMAGE_COEFFICIENT
if(holder.has_reagent("cryostylane"))
holder.remove_reagent("cryostylane", 5)
if(isslime(M))
heating = rand(5,20)
if(15 to 25)
heating = 10 * TEMPERATURE_DAMAGE_COEFFICIENT
if(isslime(M))
heating = rand(10,20)
if(25 to 35)
heating = 15 * TEMPERATURE_DAMAGE_COEFFICIENT
if(isslime(M))
heating = rand(15,20)
if(35 to INFINITY)
heating = 20 * TEMPERATURE_DAMAGE_COEFFICIENT
if(isslime(M))
heating = rand(20,25)
M.adjust_bodytemperature(heating)
..()
/datum/reagent/consumable/frostoil
name = "Frost Oil"
id = "frostoil"
description = "A special oil that noticably chills the body. Extracted from Icepeppers and slimes."
color = "#8BA6E9" // rgb: 139, 166, 233
taste_description = "mint"
value = 2
pH = 13 //HMM! I wonder
/datum/reagent/consumable/frostoil/on_mob_life(mob/living/carbon/M)
var/cooling = 0
switch(current_cycle)
if(1 to 15)
cooling = -10 * TEMPERATURE_DAMAGE_COEFFICIENT
if(holder.has_reagent("capsaicin"))
holder.remove_reagent("capsaicin", 5)
if(isslime(M))
cooling = -rand(5,20)
if(15 to 25)
cooling = -20 * TEMPERATURE_DAMAGE_COEFFICIENT
if(isslime(M))
cooling = -rand(10,20)
if(25 to 35)
cooling = -30 * TEMPERATURE_DAMAGE_COEFFICIENT
if(prob(1))
M.emote("shiver")
if(isslime(M))
cooling = -rand(15,20)
if(35 to INFINITY)
cooling = -40 * TEMPERATURE_DAMAGE_COEFFICIENT
if(prob(5))
M.emote("shiver")
if(isslime(M))
cooling = -rand(20,25)
M.adjust_bodytemperature(cooling, 50)
..()
/datum/reagent/consumable/frostoil/reaction_turf(turf/T, reac_volume)
if(reac_volume >= 5)
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(15,30))
if(reac_volume >= 1) // Make Freezy Foam and anti-fire grenades!
if(isopenturf(T))
var/turf/open/OT = T
OT.MakeSlippery(wet_setting=TURF_WET_ICE, min_wet_time=100, wet_time_to_add=reac_volume SECONDS) // Is less effective in high pressure/high heat capacity environments. More effective in low pressure.
OT.air.temperature -= MOLES_CELLSTANDARD*100*reac_volume/OT.air.heat_capacity() // reduces environment temperature by 5K per unit.
/datum/reagent/consumable/condensedcapsaicin
name = "Condensed Capsaicin"
id = "condensedcapsaicin"
description = "A chemical agent used for self-defense and in police work."
color = "#B31008" // rgb: 179, 16, 8
taste_description = "scorching agony"
pH = 7.4
/datum/reagent/consumable/condensedcapsaicin/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(!ishuman(M) && !ismonkey(M))
return
var/mob/living/carbon/victim = M
if(method == TOUCH || method == VAPOR)
//check for protection
var/mouth_covered = 0
var/eyes_covered = 0
var/obj/item/safe_thing = null
//monkeys and humans can have masks
if( victim.wear_mask )
if ( victim.wear_mask.flags_cover & MASKCOVERSEYES )
eyes_covered = 1
safe_thing = victim.wear_mask
if ( victim.wear_mask.flags_cover & MASKCOVERSMOUTH )
mouth_covered = 1
safe_thing = victim.wear_mask
//only humans can have helmets and glasses
if(ishuman(victim))
var/mob/living/carbon/human/H = victim
if( H.head )
if ( H.head.flags_cover & HEADCOVERSEYES )
eyes_covered = 1
safe_thing = H.head
if ( H.head.flags_cover & HEADCOVERSMOUTH )
mouth_covered = 1
safe_thing = H.head
if(H.glasses)
eyes_covered = 1
if ( !safe_thing )
safe_thing = H.glasses
//actually handle the pepperspray effects
if ( eyes_covered && mouth_covered )
return
else if ( mouth_covered ) // Reduced effects if partially protected
if(prob(5))
victim.emote("scream")
victim.blur_eyes(3)
victim.blind_eyes(2)
victim.confused = max(M.confused, 3)
victim.damageoverlaytemp = 60
victim.Knockdown(80, override_hardstun = 0.1, override_stamdmg = min(reac_volume * 3, 15))
return
else if ( eyes_covered ) // Eye cover is better than mouth cover
victim.blur_eyes(3)
victim.damageoverlaytemp = 30
return
else // Oh dear :D
if(prob(5))
victim.emote("scream")
victim.blur_eyes(5)
victim.blind_eyes(3)
victim.confused = max(M.confused, 6)
victim.damageoverlaytemp = 75
victim.Knockdown(80, override_hardstun = 0.1, override_stamdmg = min(reac_volume * 5, 25))
victim.update_damage_hud()
/datum/reagent/consumable/condensedcapsaicin/on_mob_life(mob/living/carbon/M)
if(prob(5))
M.visible_message("<span class='warning'>[M] [pick("dry heaves!","coughs!","splutters!")]</span>")
..()
/datum/reagent/consumable/sodiumchloride
name = "Table Salt"
id = "sodiumchloride"
description = "A salt made of sodium chloride. Commonly used to season food."
reagent_state = SOLID
color = "#FFFFFF" // rgb: 255,255,255
taste_description = "salt"
/datum/reagent/consumable/sodiumchloride/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(!istype(M))
return
if(M.has_bane(BANE_SALT))
M.mind.disrupt_spells(-200)
/datum/reagent/consumable/sodiumchloride/reaction_turf(turf/T, reac_volume) //Creates an umbra-blocking salt pile
if(!istype(T))
return
if(reac_volume < 1)
return
new/obj/effect/decal/cleanable/salt(T)
/datum/reagent/consumable/blackpepper
name = "Black Pepper"
id = "blackpepper"
description = "A powder ground from peppercorns. *AAAACHOOO*"
reagent_state = SOLID
// no color (ie, black)
taste_description = "pepper"
/datum/reagent/consumable/coco
name = "Coco Powder"
id = "cocoa"
description = "A fatty, bitter paste made from coco beans."
reagent_state = SOLID
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#302000" // rgb: 48, 32, 0
taste_description = "bitterness"
/datum/reagent/consumable/hot_coco
name = "Hot Chocolate"
id = "hot_coco"
description = "Made with love! And coco beans."
nutriment_factor = 3 * REAGENTS_METABOLISM
color = "#403010" // rgb: 64, 48, 16
taste_description = "creamy chocolate"
glass_icon_state = "chocolateglass"
glass_name = "glass of chocolate"
glass_desc = "Tasty."
/datum/reagent/consumable/hot_coco/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(5 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
..()
/datum/reagent/drug/mushroomhallucinogen
name = "Mushroom Hallucinogen"
id = "mushroomhallucinogen"
description = "A strong hallucinogenic drug derived from certain species of mushroom."
color = "#E700E7" // rgb: 231, 0, 231
metabolization_rate = 0.2 * REAGENTS_METABOLISM
taste_description = "mushroom"
pH = 11
/datum/reagent/drug/mushroomhallucinogen/on_mob_life(mob/living/carbon/M)
M.slurring = max(M.slurring,50)
switch(current_cycle)
if(1 to 5)
M.Dizzy(5)
M.set_drugginess(30)
if(prob(10))
M.emote(pick("twitch","giggle"))
if(5 to 10)
M.Jitter(10)
M.Dizzy(10)
M.set_drugginess(35)
if(prob(20))
M.emote(pick("twitch","giggle"))
if (10 to INFINITY)
M.Jitter(20)
M.Dizzy(20)
M.set_drugginess(40)
if(prob(30))
M.emote(pick("twitch","giggle"))
..()
/datum/reagent/consumable/sprinkles
name = "Sprinkles"
id = "sprinkles"
value = 3
description = "Multi-colored little bits of sugar, commonly found on donuts. Loved by cops."
color = "#FF00FF" // rgb: 255, 0, 255
taste_description = "childhood whimsy"
/datum/reagent/consumable/sprinkles/on_mob_life(mob/living/carbon/M)
if(M.mind && HAS_TRAIT(M.mind, TRAIT_LAW_ENFORCEMENT_METABOLISM))
M.heal_bodypart_damage(1,1, 0)
. = 1
..()
/datum/reagent/consumable/peanut_butter
name = "Peanut Butter"
id = "peanut_butter"
description = "A popular food paste made from ground dry-roasted peanuts."
color = "#C29261"
value = 3
nutriment_factor = 15 * REAGENTS_METABOLISM
taste_description = "peanuts"
/datum/reagent/consumable/cornoil
name = "Corn Oil"
id = "cornoil"
description = "An oil derived from various types of corn."
nutriment_factor = 20 * REAGENTS_METABOLISM
value = 4
color = "#302000" // rgb: 48, 32, 0
taste_description = "slime"
/datum/reagent/consumable/cornoil/reaction_turf(turf/open/T, reac_volume)
if (!istype(T))
return
T.MakeSlippery(TURF_WET_LUBE, min_wet_time = 10 SECONDS, wet_time_to_add = reac_volume*2 SECONDS)
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
if(hotspot)
var/datum/gas_mixture/lowertemp = T.remove_air(T.air.total_moles())
lowertemp.temperature = max( min(lowertemp.temperature-2000,lowertemp.temperature / 2) ,0)
lowertemp.react(src)
T.assume_air(lowertemp)
qdel(hotspot)
/datum/reagent/consumable/enzyme
name = "Universal Enzyme"
id = "enzyme"
value = 1
description = "A universal enzyme used in the preperation of certain chemicals and foods."
color = "#365E30" // rgb: 54, 94, 48
taste_description = "sweetness"
/datum/reagent/consumable/dry_ramen
name = "Dry Ramen"
id = "dry_ramen"
description = "Space age food, since August 25, 1958. Contains dried noodles, vegetables, and chemicals that boil in contact with water."
reagent_state = SOLID
color = "#302000" // rgb: 48, 32, 0
taste_description = "dry and cheap noodles"
/datum/reagent/consumable/hot_ramen
name = "Hot Ramen"
id = "hot_ramen"
description = "The noodles are boiled, the flavors are artificial, just like being back in school."
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#302000" // rgb: 48, 32, 0
taste_description = "wet and cheap noodles"
/datum/reagent/consumable/hot_ramen/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT, 0, BODYTEMP_NORMAL)
..()
/datum/reagent/consumable/hell_ramen
name = "Hell Ramen"
id = "hell_ramen"
description = "The noodles are boiled, the flavors are artificial, just like being back in school."
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#302000" // rgb: 48, 32, 0
taste_description = "wet and cheap noodles on fire"
/datum/reagent/consumable/hell_ramen/on_mob_life(mob/living/carbon/M)
M.adjust_bodytemperature(10 * TEMPERATURE_DAMAGE_COEFFICIENT)
..()
/datum/reagent/consumable/flour
name = "Flour"
id = "flour"
value = 0.5
description = "This is what you rub all over yourself to pretend to be a ghost."
reagent_state = SOLID
color = "#FFFFFF" // rgb: 0, 0, 0
taste_description = "chalky wheat"
/datum/reagent/consumable/flour/reaction_turf(turf/T, reac_volume)
if(!isspaceturf(T))
var/obj/effect/decal/cleanable/flour/reagentdecal = new/obj/effect/decal/cleanable/flour(T)
reagentdecal = locate() in T //Might have merged with flour already there.
if(reagentdecal)
reagentdecal.reagents.add_reagent("flour", reac_volume)
/datum/reagent/consumable/cherryjelly
name = "Cherry Jelly"
id = "cherryjelly"
description = "Totally the best. Only to be spread on foods with excellent lateral symmetry."
color = "#801E28" // rgb: 128, 30, 40
value = 1
taste_description = "cherry"
/datum/reagent/consumable/bluecherryjelly
name = "Blue Cherry Jelly"
id = "bluecherryjelly"
description = "Blue and tastier kind of cherry jelly."
color = "#00F0FF"
value = 12
taste_description = "blue cherry"
/datum/reagent/consumable/rice
name = "Rice"
id = "rice"
value = 0.5
description = "tiny nutritious grains"
reagent_state = SOLID
nutriment_factor = 3 * REAGENTS_METABOLISM
color = "#FFFFFF" // rgb: 0, 0, 0
taste_description = "rice"
/datum/reagent/consumable/vanilla
name = "Vanilla Powder"
id = "vanilla"
value = 1
description = "A fatty, bitter paste made from vanilla pods."
reagent_state = SOLID
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#FFFACD"
taste_description = "vanilla"
/datum/reagent/consumable/eggyolk
name = "Egg Yolk"
id = "eggyolk"
value = 1
description = "It's full of protein."
nutriment_factor = 3 * REAGENTS_METABOLISM
color = "#FFB500"
taste_description = "egg"
/datum/reagent/consumable/corn_starch
name = "Corn Starch"
id = "corn_starch"
value = 2
description = "A slippery solution."
color = "#f7f6e4"
taste_description = "slime"
/datum/reagent/consumable/corn_syrup
name = "Corn Syrup"
id = "corn_syrup"
value = 1
description = "Decays into sugar."
color = "#fff882"
metabolization_rate = 3 * REAGENTS_METABOLISM
taste_description = "sweet slime"
/datum/reagent/consumable/corn_syrup/on_mob_life(mob/living/carbon/M)
holder.add_reagent("sugar", 3)
..()
/datum/reagent/consumable/honey
name = "honey"
id = "honey"
description = "Sweet sweet honey that decays into sugar. Has antibacterial and natural healing properties."
color = "#d3a308"
value = 15
nutriment_factor = 15 * REAGENTS_METABOLISM
metabolization_rate = 1 * REAGENTS_METABOLISM
taste_description = "sweetness"
/datum/reagent/consumable/honey/on_mob_life(mob/living/carbon/M)
M.reagents.add_reagent("sugar",3)
if(prob(55))
M.adjustBruteLoss(-1*REM, 0)
M.adjustFireLoss(-1*REM, 0)
M.adjustOxyLoss(-1*REM, 0)
M.adjustToxLoss(-1*REM, 0)
..()
/datum/reagent/consumable/honey/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(iscarbon(M) && (method in list(TOUCH, VAPOR, PATCH)))
var/mob/living/carbon/C = M
for(var/s in C.surgeries)
var/datum/surgery/S = s
S.success_multiplier = max(0.6, S.success_multiplier) // +60% success probability on each step, compared to bacchus' blessing's ~46%
..()
/datum/reagent/consumable/mayonnaise
name = "Mayonnaise"
id = "mayonnaise"
description = "An white and oily mixture of mixed egg yolks."
color = "#DFDFDF"
value = 5
taste_description = "mayonnaise"
/datum/reagent/consumable/tearjuice
name = "Tear Juice"
id = "tearjuice"
description = "A blinding substance extracted from certain onions."
color = "#c0c9a0"
taste_description = "bitterness"
pH = 5
/datum/reagent/consumable/tearjuice/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(!istype(M))
return
var/unprotected = FALSE
switch(method)
if(INGEST)
unprotected = TRUE
if(INJECT)
unprotected = FALSE
else //Touch or vapor
if(!M.is_mouth_covered() && !M.is_eyes_covered())
unprotected = TRUE
if(unprotected)
if(!M.getorganslot(ORGAN_SLOT_EYES)) //can't blind somebody with no eyes
to_chat(M, "<span class = 'notice'>Your eye sockets feel wet.</span>")
else
if(!M.eye_blurry)
to_chat(M, "<span class = 'warning'>Tears well up in your eyes!</span>")
M.blind_eyes(2)
M.blur_eyes(5)
..()
/datum/reagent/consumable/tearjuice/on_mob_life(mob/living/carbon/M)
..()
if(M.eye_blurry) //Don't worsen vision if it was otherwise fine
M.blur_eyes(4)
if(prob(10))
to_chat(M, "<span class = 'warning'>Your eyes sting!</span>")
M.blind_eyes(2)
/datum/reagent/consumable/nutriment/stabilized
name = "Stabilized Nutriment"
id = "stabilizednutriment"
description = "A bioengineered protien-nutrient structure designed to decompose in high saturation. In layman's terms, it won't get you fat."
reagent_state = SOLID
nutriment_factor = 15 * REAGENTS_METABOLISM
color = "#664330" // rgb: 102, 67, 48
/datum/reagent/consumable/nutriment/stabilized/on_mob_life(mob/living/carbon/M)
if(M.nutrition > NUTRITION_LEVEL_FULL - 25)
M.nutrition -= 3*nutriment_factor
..()
////Lavaland Flora Reagents////
/datum/reagent/consumable/entpoly
name = "Entropic Polypnium"
id = "entpoly"
description = "An ichor, derived from a certain mushroom, makes for a bad time."
color = "#1d043d"
taste_description = "bitter mushroom"
pH = 12
/datum/reagent/consumable/entpoly/on_mob_life(mob/living/carbon/M)
if(current_cycle >= 10)
M.Unconscious(40, 0)
. = 1
if(prob(20))
M.losebreath += 4
M.adjustOrganLoss(ORGAN_SLOT_BRAIN, 2*REM, 150)
M.adjustToxLoss(3*REM,0)
M.adjustStaminaLoss(10*REM,0)
M.blur_eyes(5)
. = TRUE
..()
/datum/reagent/consumable/tinlux
name = "Tinea Luxor"
id = "tinlux"
description = "A stimulating ichor which causes luminescent fungi to grow on the skin. "
color = "#b5a213"
taste_description = "tingling mushroom"
pH = 11.2
/datum/reagent/consumable/tinlux/reaction_mob(mob/living/M)
M.set_light(2)
/datum/reagent/consumable/tinlux/on_mob_end_metabolize(mob/living/M)
M.set_light(-2)
/datum/reagent/consumable/vitfro
name = "Vitrium Froth"
id = "vitfro"
description = "A bubbly paste that heals wounds of the skin."
color = "#d3a308"
nutriment_factor = 3 * REAGENTS_METABOLISM
taste_description = "fruity mushroom"
pH = 10.4
/datum/reagent/consumable/vitfro/on_mob_life(mob/living/carbon/M)
if(prob(80))
M.adjustBruteLoss(-1*REM, 0)
M.adjustFireLoss(-1*REM, 0)
. = TRUE
..()
/datum/reagent/consumable/clownstears
name = "Clown's Tears"
id = "clownstears"
description = "The sorrow and melancholy of a thousand bereaved clowns, forever denied their Honkmechs."
nutriment_factor = 5 * REAGENTS_METABOLISM
color = "#eef442" // rgb: 238, 244, 66
taste_description = "mournful honking"
pH = 9.2
/datum/reagent/consumable/astrotame
name = "Astrotame"
id = "astrotame"
description = "A space age artifical sweetener."
nutriment_factor = 0
metabolization_rate = 2 * REAGENTS_METABOLISM
reagent_state = SOLID
color = "#FFFFFF" // rgb: 255, 255, 255
taste_mult = 8
taste_description = "sweetness"
overdose_threshold = 17
value = 0.2
/datum/reagent/consumable/astrotame/overdose_process(mob/living/carbon/M)
if(M.disgust < 80)
M.adjust_disgust(10)
..()
. = TRUE
/datum/reagent/consumable/secretsauce
name = "secret sauce"
id = "secret_sauce"
description = "What could it be."
nutriment_factor = 2 * REAGENTS_METABOLISM
color = "#792300"
taste_description = "indescribable"
quality = FOOD_AMAZING
taste_mult = 100
can_synth = FALSE
pH = 6.1
@@ -0,0 +1,26 @@
//Reagents produced by metabolising/reacting fermichems inoptimally, i.e. inverse_chems or impure_chems
//Inverse = Splitting
//Invert = Whole conversion
/datum/reagent/impure
chemical_flags = REAGENT_INVISIBLE | REAGENT_SNEAKYNAME //by default, it will stay hidden on splitting, but take the name of the source on inverting
/datum/reagent/impure/fermiTox
name = "Chemical Isomers"
id = "fermiTox"
description = "Toxic chemical isomers made from impure reactions. At low volumes will cause light toxin damage, but as the volume increases, it deals larger amounts, damages the liver, then eventually the heart. This is default impure chem for all chems, and changes only if stated."
data = "merge"
color = "FFFFFF"
can_synth = FALSE
var/potency = 1 //potency multiplies the volume when added.
//I'm concerned this is too weak, but I also don't want deathmixes.
//TODO: liver damage, 100+ heart
/datum/reagent/impure/fermiTox/on_mob_life(mob/living/carbon/C, method)
if(C.dna && istype(C.dna.species, /datum/species/jelly))
C.adjustToxLoss(-2)
else
C.adjustToxLoss(2)
..()
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,291 @@
/datum/reagent/thermite
name = "Thermite"
id = "thermite"
description = "Thermite produces an aluminothermic reaction known as a thermite reaction. Can be used to melt walls."
reagent_state = SOLID
color = "#550000"
taste_description = "sweet tasting metal"
/datum/reagent/thermite/reaction_turf(turf/T, reac_volume)
if(reac_volume >= 1)
T.AddComponent(/datum/component/thermite, reac_volume)
/datum/reagent/thermite/on_mob_life(mob/living/carbon/M)
M.adjustFireLoss(1, 0)
..()
return TRUE
/datum/reagent/nitroglycerin
name = "Nitroglycerin"
id = "nitroglycerin"
value = 5
description = "Nitroglycerin is a heavy, colorless, oily, explosive liquid obtained by nitrating glycerol."
color = "#808080" // rgb: 128, 128, 128
taste_description = "oil"
/datum/reagent/stabilizing_agent
name = "Stabilizing Agent"
id = "stabilizing_agent"
description = "Keeps unstable chemicals stable. This does not work on everything."
reagent_state = LIQUID
color = "#FFFF00"
value = 3
taste_description = "metal"
/datum/reagent/clf3
name = "Chlorine Trifluoride"
id = "clf3"
description = "Makes a temporary 3x3 fireball when it comes into existence, so be careful when mixing. ClF3 applied to a surface burns things that wouldn't otherwise burn, sometimes through the very floors of the station and exposing it to the vacuum of space."
reagent_state = LIQUID
color = "#FFC8C8"
metabolization_rate = 4
taste_description = "burning"
/datum/reagent/clf3/on_mob_life(mob/living/carbon/M)
M.adjust_fire_stacks(2)
var/burndmg = max(0.3*M.fire_stacks, 0.3)
M.adjustFireLoss(burndmg, 0)
..()
return TRUE
/datum/reagent/clf3/reaction_turf(turf/T, reac_volume)
if(isplatingturf(T))
var/turf/open/floor/plating/F = T
if(prob(10 + F.burnt + 5*F.broken)) //broken or burnt plating is more susceptible to being destroyed
F.ScrapeAway()
if(isfloorturf(T))
var/turf/open/floor/F = T
if(prob(reac_volume))
F.make_plating()
else if(prob(reac_volume))
F.burn_tile()
if(isfloorturf(F))
for(var/turf/turf in range(1,F))
if(!locate(/obj/effect/hotspot) in turf)
new /obj/effect/hotspot(F)
if(iswallturf(T))
var/turf/closed/wall/W = T
if(prob(reac_volume))
W.ScrapeAway()
/datum/reagent/clf3/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(istype(M))
if(method != INGEST && method != INJECT)
M.adjust_fire_stacks(min(reac_volume/5, 10))
M.IgniteMob()
if(!locate(/obj/effect/hotspot) in M.loc)
new /obj/effect/hotspot(M.loc)
/datum/reagent/sorium
name = "Sorium"
id = "sorium"
description = "Sends everything flying from the detonation point."
reagent_state = LIQUID
color = "#5A64C8"
taste_description = "air and bitterness"
/datum/reagent/liquid_dark_matter
name = "Liquid Dark Matter"
id = "liquid_dark_matter"
description = "Sucks everything into the detonation point."
reagent_state = LIQUID
color = "#210021"
value = 10
taste_description = "compressed bitterness"
/datum/reagent/blackpowder
name = "Black Powder"
id = "blackpowder"
description = "Explodes. Violently."
reagent_state = LIQUID
color = "#000000"
value = 5
metabolization_rate = 0.05
taste_description = "salt"
/datum/reagent/blackpowder/on_mob_life(mob/living/carbon/M)
..()
if(isplasmaman(M))
M.hallucination += 5
/datum/reagent/blackpowder/on_ex_act()
var/location = get_turf(holder.my_atom)
var/datum/effect_system/reagents_explosion/e = new()
e.set_up(1 + round(volume/6, 1), location, 0, 0, message = 0)
e.start()
holder.clear_reagents()
/datum/reagent/flash_powder
name = "Flash Powder"
id = "flash_powder"
description = "Makes a very bright flash."
reagent_state = LIQUID
color = "#C8C8C8"
taste_description = "salt"
/datum/reagent/smoke_powder
name = "Smoke Powder"
id = "smoke_powder"
description = "Makes a large cloud of smoke that can carry reagents."
reagent_state = LIQUID
color = "#C8C8C8"
taste_description = "smoke"
/datum/reagent/sonic_powder
name = "Sonic Powder"
id = "sonic_powder"
description = "Makes a deafening noise."
reagent_state = LIQUID
color = "#C8C8C8"
taste_description = "loud noises"
/datum/reagent/phlogiston
name = "Phlogiston"
id = "phlogiston"
description = "Catches you on fire and makes you ignite."
reagent_state = LIQUID
color = "#FA00AF"
taste_description = "burning"
/datum/reagent/phlogiston/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
M.adjust_fire_stacks(1)
var/burndmg = max(0.3*M.fire_stacks, 0.3)
M.adjustFireLoss(burndmg, 0)
M.IgniteMob()
..()
/datum/reagent/phlogiston/on_mob_life(mob/living/carbon/M)
M.adjust_fire_stacks(1)
var/burndmg = max(0.3*M.fire_stacks, 0.3)
M.adjustFireLoss(burndmg, 0)
..()
return TRUE
/datum/reagent/napalm
name = "Napalm"
id = "napalm"
description = "Very flammable."
reagent_state = LIQUID
color = "#FA00AF"
value = 1
taste_description = "burning"
/datum/reagent/napalm/on_mob_life(mob/living/carbon/M)
M.adjust_fire_stacks(1)
..()
/datum/reagent/napalm/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(istype(M))
if(method != INGEST && method != INJECT)
M.adjust_fire_stacks(min(reac_volume/4, 20))
/datum/reagent/cryostylane
name = "Cryostylane"
id = "cryostylane"
description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Cryostylane slowly cools all other reagents in the container 0K."
color = "#0000DC"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
taste_description = "bitterness"
/datum/reagent/cryostylane/on_mob_life(mob/living/carbon/M) //TODO: code freezing into an ice cube
if(M.reagents.has_reagent("oxygen"))
M.reagents.remove_reagent("oxygen", 0.5)
M.adjust_bodytemperature(-15)
..()
/datum/reagent/cryostylane/reaction_turf(turf/T, reac_volume)
if(reac_volume >= 5)
for(var/mob/living/simple_animal/slime/M in T)
M.adjustToxLoss(rand(15,30))
/datum/reagent/pyrosium
name = "Pyrosium"
id = "pyrosium"
description = "Comes into existence at 20K. As long as there is sufficient oxygen for it to react with, Pyrosium slowly heats all other reagents in the container."
color = "#64FAC8"
metabolization_rate = 0.5 * REAGENTS_METABOLISM
taste_description = "bitterness"
/datum/reagent/pyrosium/on_mob_life(mob/living/carbon/M)
if(M.reagents.has_reagent("oxygen"))
M.reagents.remove_reagent("oxygen", 0.5)
M.adjust_bodytemperature(15)
..()
/datum/reagent/teslium //Teslium. Causes periodic shocks, and makes shocks against the target much more effective.
name = "Teslium"
id = "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."
reagent_state = LIQUID
color = "#20324D" //RGB: 32, 50, 77
metabolization_rate = 0.5 * REAGENTS_METABOLISM
taste_description = "charged metal"
var/shock_timer = 0
/datum/reagent/teslium/on_mob_life(mob/living/carbon/M)
shock_timer++
if(shock_timer >= rand(5,30)) //Random shocks are wildly unpredictable
shock_timer = 0
M.electrocute_act(rand(5,20), "Teslium in their body", 1, 1) //Override because it's caused from INSIDE of you
playsound(M, "sparks", 50, 1)
..()
/datum/reagent/teslium/energized_jelly
name = "Energized Jelly"
id = "energized_jelly"
description = "Electrically-charged jelly. Boosts jellypeople's nervous system, but only shocks other lifeforms."
reagent_state = LIQUID
color = "#CAFF43"
taste_description = "jelly"
/datum/reagent/teslium/energized_jelly/on_mob_life(mob/living/carbon/M)
if(isjellyperson(M))
shock_timer = 0 //immune to shocks
M.AdjustStun(-40, 0)
M.AdjustKnockdown(-40, 0)
M.AdjustUnconscious(-40, 0)
M.adjustStaminaLoss(-2, 0)
if(isluminescent(M))
var/mob/living/carbon/human/H = M
var/datum/species/jelly/luminescent/L = H.dna.species
L.extract_cooldown = max(0, L.extract_cooldown - 20)
..()
/datum/reagent/firefighting_foam
name = "Firefighting Foam"
id = "firefighting_foam"
description = "A historical fire suppressant. Originally believed to simply displace oxygen to starve fires, it actually interferes with the combustion reaction itself. Vastly superior to the cheap water-based extinguishers found on NT vessels."
reagent_state = LIQUID
color = "#A6FAFF55"
taste_description = "the inside of a fire extinguisher"
/datum/reagent/firefighting_foam/reaction_turf(turf/open/T, reac_volume)
if (!istype(T))
return
if(reac_volume >= 1)
var/obj/effect/particle_effect/foam/firefighting/F = (locate(/obj/effect/particle_effect/foam) in T)
if(!F)
F = new(T)
else if(istype(F))
F.lifetime = initial(F.lifetime) //reduce object churn a little bit when using smoke by keeping existing foam alive a bit longer
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
if(hotspot && !isspaceturf(T))
if(T.air)
var/datum/gas_mixture/G = T.air
if(G.temperature > T20C)
G.temperature = max(G.temperature/2,T20C)
G.react(src)
qdel(hotspot)
/datum/reagent/firefighting_foam/reaction_obj(obj/O, reac_volume)
O.extinguish()
/datum/reagent/firefighting_foam/reaction_mob(mob/living/M, method=TOUCH, reac_volume)
if(method in list(VAPOR, TOUCH))
M.adjust_fire_stacks(-reac_volume)
M.ExtinguishMob()
..()
@@ -0,0 +1,316 @@
/datum/chemical_reaction/leporazine
name = "Leporazine"
id = "leporazine"
results = list("leporazine" = 2)
required_reagents = list("silicon" = 1, "copper" = 1)
required_catalysts = list("plasma" = 5)
/datum/chemical_reaction/rezadone
name = "Rezadone"
id = "rezadone"
results = list("rezadone" = 3)
required_reagents = list("carpotoxin" = 1, "cryptobiolin" = 1, "copper" = 1)
/datum/chemical_reaction/spaceacillin
name = "Spaceacillin"
id = "spaceacillin"
results = list("spaceacillin" = 2)
required_reagents = list("cryptobiolin" = 1, "epinephrine" = 1)
/datum/chemical_reaction/inacusiate
name = "inacusiate"
id = "inacusiate"
results = list("inacusiate" = 2)
required_reagents = list("water" = 1, "carbon" = 1, "charcoal" = 1)
/datum/chemical_reaction/synaptizine
name = "Synaptizine"
id = "synaptizine"
results = list("synaptizine" = 3)
required_reagents = list("sugar" = 1, "lithium" = 1, "water" = 1)
/datum/chemical_reaction/charcoal
name = "Charcoal"
id = "charcoal"
results = list("charcoal" = 2)
required_reagents = list("ash" = 1, "sodiumchloride" = 1)
mix_message = "The mixture yields a fine black powder."
required_temp = 380
/datum/chemical_reaction/silver_sulfadiazine
name = "Silver Sulfadiazine"
id = "silver_sulfadiazine"
results = list("silver_sulfadiazine" = 5)
required_reagents = list("ammonia" = 1, "silver" = 1, "sulfur" = 1, "oxygen" = 1, "chlorine" = 1)
/datum/chemical_reaction/salglu_solution
name = "Saline-Glucose Solution"
id = "salglu_solution"
results = list("salglu_solution" = 3)
required_reagents = list("sodiumchloride" = 1, "water" = 1, "sugar" = 1)
/datum/chemical_reaction/mine_salve
name = "Miner's Salve"
id = "mine_salve"
results = list("mine_salve" = 3)
required_reagents = list("oil" = 1, "water" = 1, "iron" = 1)
/datum/chemical_reaction/mine_salve2
name = "Miner's Salve"
id = "mine_salve"
results = list("mine_salve" = 15)
required_reagents = list("plasma" = 5, "iron" = 5, "sugar" = 1) // A sheet of plasma, a twinkie and a sheet of metal makes four of these
/datum/chemical_reaction/synthflesh
name = "Synthflesh"
id = "synthflesh"
results = list("synthflesh" = 3)
required_reagents = list("blood" = 1, "carbon" = 1, "styptic_powder" = 1)
/datum/chemical_reaction/synthtissue
name = "Synthtissue"
id = "synthtissue"
results = list("synthtissue" = 5)
required_reagents = list("synthflesh" = 1)
required_catalysts = list("nutriment" = 0.1)
//FermiChem vars:
OptimalTempMin = 305 // Lower area of bell curve for determining heat based rate reactions
OptimalTempMax = 315 // Upper end for above
ExplodeTemp = 1050 // Temperature at which reaction explodes
OptimalpHMin = 8.5 // Lowest value of pH determining pH a 1 value for pH based rate reactions (Plateu phase)
OptimalpHMax = 9.5 // Higest value for above
ReactpHLim = 2 // How far out pH wil react, giving impurity place (Exponential phase)
CatalystFact = 0 // How much the catalyst affects the reaction (0 = no catalyst)
CurveSharpT = 1 // How sharp the temperature exponential curve is (to the power of value)
CurveSharppH = 2.5 // How sharp the pH exponential curve is (to the power of value)
ThermicConstant = 0.01 // Temperature change per 1u produced
HIonRelease = 0.015 // pH change per 1u reaction (inverse for some reason)
RateUpLim = 0.05 // Optimal/max rate possible if all conditions are perfect
FermiChem = TRUE // If the chemical uses the Fermichem reaction mechanics
PurityMin = 0
/datum/chemical_reaction/synthtissue/FermiCreate(datum/reagents/holder, added_volume, added_purity)
var/datum/reagent/synthtissue/St = holder.has_reagent("synthtissue")
var/datum/reagent/N = holder.has_reagent("nutriment")
if(!St)
return
if(holder.chem_temp > 320)
var/temp_ratio = 1-(330 - holder.chem_temp)/10
holder.remove_reagent(src.id, added_volume*temp_ratio)
if(St.purity < 1)
St.volume *= St.purity
St.purity = 1
var/amount = CLAMP(0.002, 0, N.volume)
N.volume -= amount
St.data["grown_volume"] = St.data["grown_volume"] + added_volume
St.name = "[initial(St.name)] [round(St.data["grown_volume"], 0.1)]u colony"
/datum/chemical_reaction/styptic_powder
name = "Styptic Powder"
id = "styptic_powder"
results = list("styptic_powder" = 4)
required_reagents = list("aluminium" = 1, "hydrogen" = 1, "oxygen" = 1, "sacid" = 1)
mix_message = "The solution yields an astringent powder."
/datum/chemical_reaction/calomel
name = "Calomel"
id = "calomel"
results = list("calomel" = 2)
required_reagents = list("mercury" = 1, "chlorine" = 1)
required_temp = 374
/datum/chemical_reaction/potass_iodide
name = "Potassium Iodide"
id = "potass_iodide"
results = list("potass_iodide" = 2)
required_reagents = list("potassium" = 1, "iodine" = 1)
/datum/chemical_reaction/pen_acid
name = "Pentetic Acid"
id = "pen_acid"
results = list("pen_acid" = 6)
required_reagents = list("welding_fuel" = 1, "chlorine" = 1, "ammonia" = 1, "formaldehyde" = 1, "sodium" = 1, "cyanide" = 1)
/datum/chemical_reaction/pen_jelly
name = "Pentetic Jelly"
id = "pen_jelly"
results = list("pen_jelly" = 2)
required_reagents = list("pen_acid" = 1, "slimejelly" = 1)
/datum/chemical_reaction/sal_acid
name = "Salicyclic Acid"
id = "sal_acid"
results = list("sal_acid" = 5)
required_reagents = list("sodium" = 1, "phenol" = 1, "carbon" = 1, "oxygen" = 1, "sacid" = 1)
/datum/chemical_reaction/oxandrolone
name = "Oxandrolone"
id = "oxandrolone"
results = list("oxandrolone" = 6)
required_reagents = list("carbon" = 3, "phenol" = 1, "hydrogen" = 1, "oxygen" = 1)
/datum/chemical_reaction/salbutamol
name = "Salbutamol"
id = "salbutamol"
results = list("salbutamol" = 5)
required_reagents = list("sal_acid" = 1, "lithium" = 1, "aluminium" = 1, "bromine" = 1, "ammonia" = 1)
/datum/chemical_reaction/perfluorodecalin
name = "Perfluorodecalin"
id = "perfluorodecalin"
results = list("perfluorodecalin" = 3)
required_reagents = list("hydrogen" = 1, "fluorine" = 1, "oil" = 1)
required_temp = 370
mix_message = "The mixture rapidly turns into a dense pink liquid."
/datum/chemical_reaction/ephedrine
name = "Ephedrine"
id = "ephedrine"
results = list("ephedrine" = 4)
required_reagents = list("sugar" = 1, "oil" = 1, "hydrogen" = 1, "diethylamine" = 1)
mix_message = "The solution fizzes and gives off toxic fumes."
/datum/chemical_reaction/diphenhydramine
name = "Diphenhydramine"
id = "diphenhydramine"
results = list("diphenhydramine" = 4)
required_reagents = list("oil" = 1, "carbon" = 1, "bromine" = 1, "diethylamine" = 1, "ethanol" = 1)
mix_message = "The mixture dries into a pale blue powder."
/datum/chemical_reaction/oculine
name = "Oculine"
id = "oculine"
results = list("oculine" = 3)
required_reagents = list("charcoal" = 1, "carbon" = 1, "hydrogen" = 1)
mix_message = "The mixture sputters loudly and becomes a pale pink color."
/datum/chemical_reaction/atropine
name = "Atropine"
id = "atropine"
results = list("atropine" = 5)
required_reagents = list("ethanol" = 1, "acetone" = 1, "diethylamine" = 1, "phenol" = 1, "sacid" = 1)
/datum/chemical_reaction/epinephrine
name = "Epinephrine"
id = "epinephrine"
results = list("epinephrine" = 6)
required_reagents = list("phenol" = 1, "acetone" = 1, "diethylamine" = 1, "oxygen" = 1, "chlorine" = 1, "hydrogen" = 1)
/datum/chemical_reaction/strange_reagent
name = "Strange Reagent"
id = "strange_reagent"
results = list("strange_reagent" = 3)
required_reagents = list("omnizine" = 1, "holywater" = 1, "mutagen" = 1)
/datum/chemical_reaction/mannitol
name = "Mannitol"
id = "mannitol"
results = list("mannitol" = 3)
required_reagents = list("sugar" = 1, "hydrogen" = 1, "water" = 1)
mix_message = "The solution slightly bubbles, becoming thicker."
/datum/chemical_reaction/mutadone
name = "Mutadone"
id = "mutadone"
results = list("mutadone" = 3)
required_reagents = list("mutagen" = 1, "acetone" = 1, "bromine" = 1)
/datum/chemical_reaction/neurine
name = "Neurine"
id = "neurine"
results = list("neurine" = 3)
required_reagents = list("mannitol" = 1, "acetone" = 1, "oxygen" = 1)
/datum/chemical_reaction/antihol
name = "antihol"
id = "antihol"
results = list("antihol" = 3)
required_reagents = list("ethanol" = 1, "charcoal" = 1, "copper" = 1)
/datum/chemical_reaction/cryoxadone
name = "Cryoxadone"
id = "cryoxadone"
results = list("cryoxadone" = 3)
required_reagents = list("stable_plasma" = 1, "acetone" = 1, "mutagen" = 1)
/datum/chemical_reaction/pyroxadone
name = "Pyroxadone"
id = "pyroxadone"
results = list("pyroxadone" = 2)
required_reagents = list("cryoxadone" = 1, "slimejelly" = 1)
/datum/chemical_reaction/clonexadone
name = "Clonexadone"
id = "clonexadone"
results = list("clonexadone" = 2)
required_reagents = list("cryoxadone" = 1, "sodium" = 1)
required_catalysts = list("plasma" = 5)
/datum/chemical_reaction/haloperidol
name = "Haloperidol"
id = "haloperidol"
results = list("haloperidol" = 5)
required_reagents = list("chlorine" = 1, "fluorine" = 1, "aluminium" = 1, "potass_iodide" = 1, "oil" = 1)
/datum/chemical_reaction/bicaridine
name = "Bicaridine"
id = "bicaridine"
results = list("bicaridine" = 3)
required_reagents = list("carbon" = 1, "oxygen" = 1, "sugar" = 1)
/datum/chemical_reaction/kelotane
name = "Kelotane"
id = "kelotane"
results = list("kelotane" = 2)
required_reagents = list("carbon" = 1, "silicon" = 1)
/datum/chemical_reaction/antitoxin
name = "Antitoxin"
id = "antitoxin"
results = list("antitoxin" = 3)
required_reagents = list("nitrogen" = 1, "silicon" = 1, "potassium" = 1)
/datum/chemical_reaction/tricordrazine
name = "Tricordrazine"
id = "tricordrazine"
results = list("tricordrazine" = 3)
required_reagents = list("bicaridine" = 1, "kelotane" = 1, "antitoxin" = 1)
/datum/chemical_reaction/regen_jelly
name = "Regenerative Jelly"
id = "regen_jelly"
results = list("regen_jelly" = 2)
required_reagents = list("tricordrazine" = 1, "slimejelly" = 1)
/datum/chemical_reaction/jelly_convert
name = "Blood Jelly Conversion"
id = "blood_jelly"
results = list("slimejelly" = 1)
required_reagents = list("toxin" = 1, "jellyblood" = 1)
/datum/chemical_reaction/corazone
name = "Corazone"
id = "corazone"
results = list("corazone" = 3)
required_reagents = list("phenol" = 2, "lithium" = 1)
/datum/chemical_reaction/morphine
name = "Morphine"
id = "morphine"
results = list("morphine" = 2)
required_reagents = list("carbon" = 2, "hydrogen" = 2, "ethanol" = 1, "oxygen" = 1)
required_temp = 480
/datum/chemical_reaction/modafinil
name = "Modafinil"
id = "modafinil"
results = list("modafinil" = 5)
required_reagents = list("diethylamine" = 1, "ammonia" = 1, "phenol" = 1, "acetone" = 1, "sacid" = 1)
required_catalysts = list("bromine" = 1) // as close to the real world synthesis as possible
/datum/chemical_reaction/psicodine
name = "Psicodine"
id = "psicodine"
results = list("psicodine" = 5)
required_reagents = list( "mannitol" = 2, "water" = 2, "impedrezene" = 1)
+219
View File
@@ -0,0 +1,219 @@
#define PH_WEAK (1 << 0)
#define TEMP_WEAK (1 << 1)
/obj/item/reagent_containers
name = "Container"
desc = "..."
icon = 'icons/obj/chemical.dmi'
icon_state = null
w_class = WEIGHT_CLASS_TINY
var/amount_per_transfer_from_this = 5
var/list/possible_transfer_amounts = list(5,10,15,20,25,30)
var/volume = 30
var/reagent_flags
var/list/list_reagents = null
var/spawned_disease = null
var/disease_amount = 20
var/spillable = FALSE
var/beaker_weakness_bitflag = NONE//Bitflag!
var/container_HP = 2
var/cached_icon
/obj/item/reagent_containers/Initialize(mapload, vol)
. = ..()
if(isnum(vol) && vol > 0)
volume = vol
create_reagents(volume, reagent_flags)
if(spawned_disease)
var/datum/disease/F = new spawned_disease()
var/list/data = list("blood_DNA" = "UNKNOWN DNA", "blood_type" = "SY","viruses"= list(F))
reagents.add_reagent("blood", disease_amount, data)
add_initial_reagents()
/obj/item/reagent_containers/proc/add_initial_reagents()
if(list_reagents)
reagents.add_reagent_list(list_reagents)
/obj/item/reagent_containers/attack_self(mob/user)
if(possible_transfer_amounts.len)
var/i=0
for(var/A in possible_transfer_amounts)
i++
if(A == amount_per_transfer_from_this)
if(i<possible_transfer_amounts.len)
amount_per_transfer_from_this = possible_transfer_amounts[i+1]
else
amount_per_transfer_from_this = possible_transfer_amounts[1]
to_chat(user, "<span class='notice'>[src]'s transfer amount is now [amount_per_transfer_from_this] units.</span>")
return
/obj/item/reagent_containers/attack(mob/M, mob/user, def_zone)
if(user.a_intent == INTENT_HARM)
return ..()
/obj/item/reagent_containers/proc/canconsume(mob/eater, mob/user)
if(!iscarbon(eater))
return 0
var/mob/living/carbon/C = eater
var/covered = ""
if(C.is_mouth_covered(head_only = 1))
covered = "headgear"
else if(C.is_mouth_covered(mask_only = 1))
covered = "mask"
if(covered)
var/who = (isnull(user) || eater == user) ? "your" : "[eater.p_their()]"
to_chat(user, "<span class='warning'>You have to remove [who] [covered] first!</span>")
return 0
return 1
/obj/item/reagent_containers/ex_act()
if(reagents)
for(var/datum/reagent/R in reagents.reagent_list)
R.on_ex_act()
if(!QDELETED(src))
..()
/obj/item/reagent_containers/fire_act(exposed_temperature, exposed_volume)
reagents.expose_temperature(exposed_temperature)
..()
/obj/item/reagent_containers/throw_impact(atom/target)
. = ..()
SplashReagents(target, TRUE)
/obj/item/reagent_containers/proc/bartender_check(atom/target)
. = FALSE
if(target.CanPass(src, get_turf(src)) && thrownby && thrownby.actions)
for(var/datum/action/innate/drink_fling/D in thrownby.actions)
if(D.active)
return TRUE
/obj/item/reagent_containers/proc/ForceResetRotation()
transform = initial(transform)
/obj/item/reagent_containers/proc/SplashReagents(atom/target, thrown = FALSE)
if(!reagents || !reagents.total_volume || !spillable)
return
if(ismob(target) && target.reagents)
if(thrown)
reagents.total_volume *= rand(5,10) * 0.1 //Not all of it makes contact with the target
var/mob/M = target
var/R
target.visible_message("<span class='danger'>[M] has been splashed with something!</span>", \
"<span class='userdanger'>[M] has been splashed with something!</span>")
for(var/datum/reagent/A in reagents.reagent_list)
R += A.id + " ("
R += num2text(A.volume) + "),"
if(thrownby)
log_combat(thrownby, M, "splashed", R)
reagents.reaction(target, TOUCH)
else if(bartender_check(target) && thrown)
visible_message("<span class='notice'>[src] lands onto the [target.name] without spilling a single drop.</span>")
transform = initial(transform)
addtimer(CALLBACK(src, .proc/ForceResetRotation), 1)
return
else
if(isturf(target) && reagents.reagent_list.len && thrownby)
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]")
log_game("[key_name(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].")
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [ADMIN_VERBOSEJMP(target)].")
visible_message("<span class='notice'>[src] spills its contents all over [target].</span>")
reagents.reaction(target, TOUCH)
if(QDELETED(src))
return
reagents.clear_reagents()
//melts plastic beakers
/obj/item/reagent_containers/microwave_act(obj/machinery/microwave/M)
reagents.expose_temperature(1000)
if(beaker_weakness_bitflag & TEMP_WEAK)
var/list/seen = viewers(5, get_turf(src))
var/iconhtml = icon2html(src, seen)
for(var/mob/H in seen)
to_chat(H, "<span class='notice'>[iconhtml] \The [src]'s melts from the temperature!</span>")
playsound(get_turf(src), 'sound/FermiChem/heatmelt.ogg', 80, 1)
qdel(src)
..()
//melts plastic beakers
/obj/item/reagent_containers/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
reagents.expose_temperature(exposed_temperature)
temp_check()
/obj/item/reagent_containers/proc/temp_check()
if(beaker_weakness_bitflag & TEMP_WEAK)
if(reagents.chem_temp >= 444)//assuming polypropylene
START_PROCESSING(SSobj, src)
//melts glass beakers
/obj/item/reagent_containers/proc/pH_check()
if(beaker_weakness_bitflag & PH_WEAK)
if((reagents.pH < 1.5) || (reagents.pH > 12.5))
START_PROCESSING(SSobj, src)
/obj/item/reagent_containers/process()
if(!cached_icon)
cached_icon = icon_state
var/damage
var/cause
if(beaker_weakness_bitflag & PH_WEAK)
if(reagents.pH < 2)
damage = (2 - reagents.pH)/20
cause = "from the extreme pH"
playsound(get_turf(src), 'sound/FermiChem/bufferadd.ogg', 50, 1)
if(reagents.pH > 12)
damage = (reagents.pH - 12)/20
cause = "from the extreme pH"
playsound(get_turf(src), 'sound/FermiChem/bufferadd.ogg', 50, 1)
if(beaker_weakness_bitflag & TEMP_WEAK)
if(reagents.chem_temp >= 444)
if(damage)
damage += (reagents.chem_temp/444)/5
else
damage = (reagents.chem_temp/444)/5
if(cause)
cause += " and "
cause += "from the high temperature"
playsound(get_turf(src), 'sound/FermiChem/heatdam.ogg', 50, 1)
if(!damage || damage <= 0)
STOP_PROCESSING(SSobj, src)
container_HP -= damage
var/list/seen = viewers(5, get_turf(src))
var/iconhtml = icon2html(src, seen)
var/damage_percent = ((container_HP / initial(container_HP)*100))
switch(damage_percent)
if(-INFINITY to 0)
for(var/mob/M in seen)
to_chat(M, "<span class='notice'>[iconhtml] \The [src]'s melts [cause]!</span>")
playsound(get_turf(src), 'sound/FermiChem/acidmelt.ogg', 80, 1)
SSblackbox.record_feedback("tally", "fermi_chem", 1, "Times beakers have melted")
STOP_PROCESSING(SSobj, src)
qdel(src)
return
if(0 to 35)
icon_state = "[cached_icon]_m3"
desc = "[initial(desc)] It is severely deformed."
if(35 to 70)
icon_state = "[cached_icon]_m2"
desc = "[initial(desc)] It is deformed."
if(70 to 85)
desc = "[initial(desc)] It is mildly deformed."
icon_state = "[cached_icon]_m1"
update_icon()
if(prob(25))
for(var/mob/M in seen)
to_chat(M, "<span class='notice'>[iconhtml] \The [src]'s is damaged by [cause] and begins to deform!</span>")
@@ -0,0 +1,114 @@
/obj/item/reagent_containers/blood
name = "blood pack"
desc = "Contains blood used for transfusion. Must be attached to an IV drip."
icon = 'icons/obj/bloodpack.dmi'
icon_state = "bloodpack"
volume = 200
reagent_flags = DRAINABLE
var/blood_type = null
var/labelled = 0
var/color_to_apply = "#FFFFFF"
var/mutable_appearance/fill_overlay
/obj/item/reagent_containers/blood/Initialize()
. = ..()
if(blood_type != null)
reagents.add_reagent("blood", 200, list("donor"=null,"viruses"=null,"blood_DNA"=null,"blood_colour"=color, "blood_type"=blood_type,"resistances"=null,"trace_chem"=null))
update_icon()
/obj/item/reagent_containers/blood/on_reagent_change(changetype)
if(reagents)
var/datum/reagent/blood/B = reagents.has_reagent("blood")
if(B && B.data && B.data["blood_type"])
blood_type = B.data["blood_type"]
color_to_apply = bloodtype_to_color(blood_type)
else
blood_type = null
update_pack_name()
update_icon()
/obj/item/reagent_containers/blood/proc/update_pack_name()
if(!labelled)
if(blood_type)
name = "blood pack - [blood_type]"
else
name = "blood pack"
/obj/item/reagent_containers/blood/update_icon()
cut_overlays()
var/v = min(round(reagents.total_volume / volume * 10), 10)
if(v > 0)
var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "bloodpack1")
filling.icon_state = "bloodpack[v]"
filling.color = mix_color_from_reagents(reagents.reagent_list)
add_overlay(filling)
/obj/item/reagent_containers/blood/random
icon_state = "random_bloodpack"
/obj/item/reagent_containers/blood/random/Initialize()
icon_state = "bloodpack"
blood_type = pick("A+", "A-", "B+", "B-", "O+", "O-", "L", "SY", "HF", "GEL", "BUG")
return ..()
/obj/item/reagent_containers/blood/APlus
blood_type = "A+"
/obj/item/reagent_containers/blood/AMinus
blood_type = "A-"
/obj/item/reagent_containers/blood/BPlus
blood_type = "B+"
/obj/item/reagent_containers/blood/BMinus
blood_type = "B-"
/obj/item/reagent_containers/blood/OPlus
blood_type = "O+"
/obj/item/reagent_containers/blood/OMinus
blood_type = "O-"
/obj/item/reagent_containers/blood/lizard
blood_type = "L"
/obj/item/reagent_containers/blood/universal
blood_type = "U"
/obj/item/reagent_containers/blood/synthetics
blood_type = "SY"
/obj/item/reagent_containers/blood/oilblood
blood_type = "HF"
/obj/item/reagent_containers/blood/jellyblood
blood_type = "GEL"
/obj/item/reagent_containers/blood/insect
blood_type = "BUG"
/obj/item/reagent_containers/blood/attackby(obj/item/I, mob/user, params)
if (istype(I, /obj/item/pen) || istype(I, /obj/item/toy/crayon))
if(!user.is_literate())
to_chat(user, "<span class='notice'>You scribble illegibly on the label of [src]!</span>")
return
var/t = stripped_input(user, "What would you like to label the blood pack?", name, null, 53)
if(!user.canUseTopic(src, BE_CLOSE))
return
if(user.get_active_held_item() != I)
return
if(t)
labelled = 1
name = "blood pack - [t]"
else
labelled = 0
update_pack_name()
else
return ..()
/obj/item/reagent_containers/blood/bluespace
name = "bluespace blood pack"
desc = "Contains blood used for transfusion, this one has been made with bluespace technology to hold much more blood. Must be attached to an IV drip."
icon_state = "bsbloodpack"
volume = 600 //its a blood bath!
@@ -0,0 +1,364 @@
/obj/item/reagent_containers/glass
name = "glass"
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5, 10, 15, 20, 25, 30, 50)
volume = 50
reagent_flags = OPENCONTAINER
spillable = TRUE
resistance_flags = ACID_PROOF
container_HP = 2
/obj/item/reagent_containers/glass/attack(mob/M, mob/user, obj/target)
if(!canconsume(M, user))
return
if(!spillable)
return
if(!reagents || !reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
if(istype(M))
if(user.a_intent == INTENT_HARM)
var/R
M.visible_message("<span class='danger'>[user] splashes the contents of [src] onto [M]!</span>", \
"<span class='userdanger'>[user] splashes the contents of [src] onto [M]!</span>")
if(reagents)
for(var/datum/reagent/A in reagents.reagent_list)
R += A.id + " ("
R += num2text(A.volume) + "),"
if(isturf(target) && reagents.reagent_list.len && thrownby)
log_combat(thrownby, target, "splashed (thrown) [english_list(reagents.reagent_list)]")
message_admins("[ADMIN_LOOKUPFLW(thrownby)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] at [ADMIN_VERBOSEJMP(target)].")
reagents.reaction(M, TOUCH)
log_combat(user, M, "splashed", R)
reagents.clear_reagents()
else
if(M != user)
M.visible_message("<span class='danger'>[user] attempts to feed something to [M].</span>", \
"<span class='userdanger'>[user] attempts to feed something to you.</span>")
if(!do_mob(user, M))
return
if(!reagents || !reagents.total_volume)
return // The drink might be empty after the delay, such as by spam-feeding
M.visible_message("<span class='danger'>[user] feeds something to [M].</span>", "<span class='userdanger'>[user] feeds something to you.</span>")
log_combat(user, M, "fed", reagents.log_list())
else
to_chat(user, "<span class='notice'>You swallow a gulp of [src].</span>")
var/fraction = min(5/reagents.total_volume, 1)
reagents.reaction(M, INGEST, fraction)
addtimer(CALLBACK(reagents, /datum/reagents.proc/trans_to, M, 5), 5)
playsound(M.loc,'sound/items/drink.ogg', rand(10,50), 1)
/obj/item/reagent_containers/glass/afterattack(obj/target, mob/user, proximity)
. = ..()
if((!proximity) || !check_allowed_items(target,target_self=1))
return
if(target.is_refillable()) //Something like a glass. Player probably wants to transfer TO it.
if(!reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
if(target.reagents.holder_full())
to_chat(user, "<span class='warning'>[target] is full.</span>")
return
var/trans = reagents.trans_to(target, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>You transfer [trans] unit\s of the solution to [target].</span>")
else if(target.is_drainable()) //A dispenser. Transfer FROM it TO us.
if(!target.reagents.total_volume)
to_chat(user, "<span class='warning'>[target] is empty and can't be refilled!</span>")
return
if(reagents.holder_full())
to_chat(user, "<span class='warning'>[src] is full.</span>")
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>You fill [src] with [trans] unit\s of the contents of [target].</span>")
else if(reagents.total_volume)
if(user.a_intent == INTENT_HARM)
user.visible_message("<span class='danger'>[user] splashes the contents of [src] onto [target]!</span>", \
"<span class='notice'>You splash the contents of [src] onto [target].</span>")
reagents.reaction(target, TOUCH)
reagents.clear_reagents()
/obj/item/reagent_containers/glass/attackby(obj/item/I, mob/user, params)
var/hotness = I.get_temperature()
if(hotness && reagents)
reagents.expose_temperature(hotness)
to_chat(user, "<span class='notice'>You heat [name] with [I]!</span>")
if(istype(I, /obj/item/reagent_containers/food/snacks/egg)) //breaking eggs
var/obj/item/reagent_containers/food/snacks/egg/E = I
if(reagents)
if(reagents.total_volume >= reagents.maximum_volume)
to_chat(user, "<span class='notice'>[src] is full.</span>")
else
to_chat(user, "<span class='notice'>You break [E] in [src].</span>")
E.reagents.trans_to(src, E.reagents.total_volume)
qdel(E)
return
..()
/obj/item/reagent_containers/glass/beaker
name = "beaker"
desc = "A beaker. It can hold up to 50 units. Unable to withstand extreme pHes"
icon = 'icons/obj/chemical.dmi'
icon_state = "beaker"
item_state = "beaker"
materials = list(MAT_GLASS=500)
beaker_weakness_bitflag = PH_WEAK
/obj/item/reagent_containers/glass/beaker/Initialize()
. = ..()
update_icon()
/obj/item/reagent_containers/glass/beaker/get_part_rating()
return reagents.maximum_volume
/obj/item/reagent_containers/glass/beaker/on_reagent_change(changetype)
update_icon()
/obj/item/reagent_containers/glass/beaker/update_icon()
if(!cached_icon)
cached_icon = icon_state
cut_overlays()
if(reagents.total_volume)
var/mutable_appearance/filling = mutable_appearance('icons/obj/reagentfillings.dmi', "[cached_icon]10")
var/percent = round((reagents.total_volume / volume) * 100)
switch(percent)
if(0 to 9)
filling.icon_state = "[cached_icon]-10"
if(10 to 24)
filling.icon_state = "[cached_icon]10"
if(25 to 49)
filling.icon_state = "[cached_icon]25"
if(50 to 74)
filling.icon_state = "[cached_icon]50"
if(75 to 79)
filling.icon_state = "[cached_icon]75"
if(80 to 90)
filling.icon_state = "[cached_icon]80"
if(91 to INFINITY)
filling.icon_state = "[cached_icon]100"
filling.color = mix_color_from_reagents(reagents.reagent_list)
add_overlay(filling)
/obj/item/reagent_containers/glass/beaker/jar
name = "honey jar"
desc = "A jar for honey. It can hold up to 50 units of sweet delight. Unable to withstand reagents of an extreme pH."
icon = 'icons/obj/chemical.dmi'
icon_state = "vapour"
/obj/item/reagent_containers/glass/beaker/large
name = "large beaker"
desc = "A large beaker. Can hold up to 100 units. Unable to withstand reagents of an extreme pH."
icon_state = "beakerlarge"
materials = list(MAT_GLASS=2500)
volume = 100
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,20,25,30,50,100)
container_HP = 3
/obj/item/reagent_containers/glass/beaker/plastic
name = "x-large beaker"
desc = "An extra-large beaker. Can hold up to 150 units. Is able to resist acid and alkaline solutions, but melts at 444K"
icon_state = "beakerwhite"
materials = list(MAT_GLASS=2500, MAT_PLASTIC=3000)
volume = 150
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,150)
/obj/item/reagent_containers/glass/beaker/plastic/Initialize()
beaker_weakness_bitflag &= ~PH_WEAK
beaker_weakness_bitflag |= TEMP_WEAK
. = ..()
/obj/item/reagent_containers/glass/beaker/plastic/update_icon()
icon_state = "beakerlarge" // hack to lets us reuse the large beaker reagent fill states
..()
icon_state = "beakerwhite"
/obj/item/reagent_containers/glass/beaker/meta
name = "metamaterial beaker"
desc = "A large beaker. Can hold up to 200 units. Is able to withstand all chemical situations."
icon_state = "beakergold"
materials = list(MAT_GLASS=2500, MAT_PLASTIC=3000, MAT_GOLD=1000, MAT_TITANIUM=1000)
volume = 200
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,200)
/obj/item/reagent_containers/glass/beaker/meta/Initialize()
beaker_weakness_bitflag &= ~PH_WEAK
. = ..()
/obj/item/reagent_containers/glass/beaker/noreact
name = "cryostasis beaker"
desc = "A cryostasis beaker that allows for chemical storage without \
reactions. Can hold up to 50 units."
icon_state = "beakernoreact"
materials = list(MAT_METAL=3000)
reagent_flags = OPENCONTAINER | NO_REACT
volume = 50
amount_per_transfer_from_this = 10
container_HP = 10//shouldn't be needed
/obj/item/reagent_containers/glass/beaker/noreact/Initialize()
beaker_weakness_bitflag &= ~PH_WEAK
. = ..()
//reagents.set_reacting(FALSE) was this removed in a recent pr?
/obj/item/reagent_containers/glass/beaker/bluespace
name = "bluespace beaker"
desc = "A bluespace beaker, powered by experimental bluespace technology \
and Element Cuban combined with the Compound Pete. Can hold up to \
300 units. Unable to withstand reagents of an extreme pH."
icon_state = "beakerbluespace"
materials = list(MAT_GLASS=3000)
volume = 300
amount_per_transfer_from_this = 10
possible_transfer_amounts = list(5,10,15,20,25,30,50,100,300)
container_HP = 4
/obj/item/reagent_containers/glass/beaker/cryoxadone
list_reagents = list("cryoxadone" = 30)
/obj/item/reagent_containers/glass/beaker/sulphuric
list_reagents = list("sacid" = 50)
/obj/item/reagent_containers/glass/beaker/slime
list_reagents = list("slimejelly" = 50)
/obj/item/reagent_containers/glass/beaker/large/styptic
name = "styptic reserve tank"
list_reagents = list("styptic_powder" = 50)
/obj/item/reagent_containers/glass/beaker/large/silver_sulfadiazine
name = "silver sulfadiazine reserve tank"
list_reagents = list("silver_sulfadiazine" = 50)
/obj/item/reagent_containers/glass/beaker/large/charcoal
name = "charcoal reserve tank"
list_reagents = list("charcoal" = 50)
/obj/item/reagent_containers/glass/beaker/large/epinephrine
name = "epinephrine reserve tank"
list_reagents = list("epinephrine" = 50)
/obj/item/reagent_containers/glass/beaker/synthflesh
list_reagents = list("synthflesh" = 50)
/obj/item/reagent_containers/glass/bucket
name = "bucket"
desc = "It's a bucket."
icon = 'icons/obj/janitor.dmi'
icon_state = "bucket"
item_state = "bucket"
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
materials = list(MAT_METAL=200)
w_class = WEIGHT_CLASS_NORMAL
amount_per_transfer_from_this = 20
possible_transfer_amounts = list(5,10,15,20,25,30,50,70)
volume = 70
flags_inv = HIDEHAIR
slot_flags = ITEM_SLOT_HEAD
resistance_flags = NONE
armor = list("melee" = 10, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 75, "acid" = 50) //Weak melee protection, because you can wear it on your head
slot_equipment_priority = list( \
SLOT_BACK, SLOT_WEAR_ID,\
SLOT_W_UNIFORM, SLOT_WEAR_SUIT,\
SLOT_WEAR_MASK, SLOT_HEAD, SLOT_NECK,\
SLOT_SHOES, SLOT_GLOVES,\
SLOT_EARS, SLOT_GLASSES,\
SLOT_BELT, SLOT_S_STORE,\
SLOT_L_STORE, SLOT_R_STORE,\
SLOT_GENERC_DEXTROUS_STORAGE
)
container_HP = 1
/obj/item/reagent_containers/glass/bucket/Initialize()
beaker_weakness_bitflag |= TEMP_WEAK
. = ..()
/obj/item/reagent_containers/glass/bucket/attackby(obj/O, mob/user, params)
if(istype(O, /obj/item/mop))
if(reagents.total_volume < 1)
to_chat(user, "<span class='warning'>[src] is out of water!</span>")
else
reagents.trans_to(O, 5)
to_chat(user, "<span class='notice'>You wet [O] in [src].</span>")
playsound(loc, 'sound/effects/slosh.ogg', 25, 1)
else if(isprox(O))
to_chat(user, "<span class='notice'>You add [O] to [src].</span>")
qdel(O)
qdel(src)
user.put_in_hands(new /obj/item/bot_assembly/cleanbot)
else
..()
/obj/item/reagent_containers/glass/bucket/equipped(mob/user, slot)
..()
if (slot == SLOT_HEAD)
if(reagents.total_volume)
to_chat(user, "<span class='userdanger'>[src]'s contents spill all over you!</span>")
reagents.reaction(user, TOUCH)
reagents.clear_reagents()
reagent_flags = NONE
/obj/item/reagent_containers/glass/bucket/dropped(mob/user)
. = ..()
reagent_flags = initial(reagent_flags)
/obj/item/reagent_containers/glass/bucket/equip_to_best_slot(var/mob/M)
if(reagents.total_volume) //If there is water in a bucket, don't quick equip it to the head
var/index = slot_equipment_priority.Find(SLOT_HEAD)
slot_equipment_priority.Remove(SLOT_HEAD)
. = ..()
slot_equipment_priority.Insert(index, SLOT_HEAD)
return
return ..()
/obj/item/reagent_containers/glass/beaker/waterbottle
name = "bottle of water"
desc = "A bottle of water filled at an old Earth bottling facility."
icon = 'icons/obj/drinks.dmi'
icon_state = "smallbottle"
item_state = "bottle"
list_reagents = list("water" = 49.5, "fluorine" = 0.5)//see desc, don't think about it too hard
materials = list(MAT_GLASS=0)
volume = 50
amount_per_transfer_from_this = 10
container_HP = 1
/obj/item/reagent_containers/glass/beaker/waterbottle/Initialize()
beaker_weakness_bitflag |= TEMP_WEAK
. = ..()
/obj/item/reagent_containers/glass/beaker/waterbottle/empty
list_reagents = list()
/obj/item/reagent_containers/glass/beaker/waterbottle/large
desc = "A fresh commercial-sized bottle of water."
icon_state = "largebottle"
materials = list(MAT_GLASS=0)
list_reagents = list("water" = 100)
volume = 100
amount_per_transfer_from_this = 20
container_HP = 1
/obj/item/reagent_containers/glass/beaker/waterbottle/large/empty
list_reagents = list()
/obj/item/reagent_containers/glass/get_belt_overlay()
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "bottle")
@@ -0,0 +1,513 @@
/obj/item/reagent_containers/hypospray
name = "hypospray"
desc = "The DeForest Medical Corporation hypospray is a sterile, air-needle autoinjector for rapid administration of drugs to patients."
icon = 'icons/obj/syringe.dmi'
item_state = "hypo"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
icon_state = "hypo"
amount_per_transfer_from_this = 5
volume = 30
possible_transfer_amounts = list()
resistance_flags = ACID_PROOF
reagent_flags = OPENCONTAINER
slot_flags = ITEM_SLOT_BELT
var/ignore_flags = 0
var/infinite = FALSE
/obj/item/reagent_containers/hypospray/attack_paw(mob/user)
return attack_hand(user)
/obj/item/reagent_containers/hypospray/attack(mob/living/M, mob/user)
if(!reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
if(!iscarbon(M))
return
//Always log attemped injects for admins
var/list/injected = list()
for(var/datum/reagent/R in reagents.reagent_list)
injected += R.name
var/contained = english_list(injected)
log_combat(user, M, "attempted to inject", src, "([contained])")
if(reagents.total_volume && (ignore_flags || M.can_inject(user, 1))) // Ignore flag should be checked first or there will be an error message.
to_chat(M, "<span class='warning'>You feel a tiny prick!</span>")
to_chat(user, "<span class='notice'>You inject [M] with [src].</span>")
var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1)
reagents.reaction(M, INJECT, fraction)
if(M.reagents)
var/trans = 0
if(!infinite)
trans = reagents.trans_to(M, amount_per_transfer_from_this)
else
trans = reagents.copy_to(M, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>[trans] unit\s injected. [reagents.total_volume] unit\s remaining in [src].</span>")
log_combat(user, M, "injected", src, "([contained])")
/obj/item/reagent_containers/hypospray/CMO
list_reagents = list("omnizine" = 30)
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
/obj/item/reagent_containers/hypospray/combat
name = "combat stimulant injector"
desc = "A modified air-needle autoinjector, used by support operatives to quickly heal injuries in combat."
amount_per_transfer_from_this = 10
icon_state = "combat_hypo"
volume = 90
ignore_flags = 1 // So they can heal their comrades.
list_reagents = list("epinephrine" = 30, "omnizine" = 30, "leporazine" = 15, "atropine" = 15)
/obj/item/reagent_containers/hypospray/combat/nanites
desc = "A modified air-needle autoinjector for use in combat situations. Prefilled with experimental medical compounds for rapid healing."
volume = 100
list_reagents = list("quantum_heal" = 80, "synaptizine" = 20)
/obj/item/reagent_containers/hypospray/magillitis
name = "experimental autoinjector"
desc = "A modified air-needle autoinjector with a small single-use reservoir. It contains an experimental serum."
icon_state = "combat_hypo"
volume = 5
reagent_flags = NONE
list_reagents = list("magillitis" = 5)
//MediPens
/obj/item/reagent_containers/hypospray/medipen
name = "epinephrine medipen"
desc = "A rapid and safe way to stabilize patients in critical condition for personnel without advanced medical knowledge."
icon_state = "medipen"
item_state = "medipen"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
amount_per_transfer_from_this = 10
volume = 10
ignore_flags = 1 //so you can medipen through hardsuits
reagent_flags = DRAWABLE
flags_1 = null
list_reagents = list("epinephrine" = 10)
/obj/item/reagent_containers/hypospray/medipen/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins to choke on \the [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
return OXYLOSS//ironic. he could save others from oxyloss, but not himself.
/obj/item/reagent_containers/hypospray/medipen/attack(mob/M, mob/user)
if(!reagents.total_volume)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
..()
if(!iscyborg(user))
reagents.maximum_volume = 0 //Makes them useless afterwards
reagent_flags = NONE
update_icon()
addtimer(CALLBACK(src, .proc/cyborg_recharge, user), 80)
/obj/item/reagent_containers/hypospray/medipen/proc/cyborg_recharge(mob/living/silicon/robot/user)
if(!reagents.total_volume && iscyborg(user))
var/mob/living/silicon/robot/R = user
if(R.cell.use(100))
reagents.add_reagent_list(list_reagents)
update_icon()
/obj/item/reagent_containers/hypospray/medipen/update_icon()
if(reagents.total_volume > 0)
icon_state = initial(icon_state)
else
icon_state = "[initial(icon_state)]0"
/obj/item/reagent_containers/hypospray/medipen/examine()
..()
if(reagents && reagents.reagent_list.len)
to_chat(usr, "<span class='notice'>It is currently loaded.</span>")
else
to_chat(usr, "<span class='notice'>It is spent.</span>")
/obj/item/reagent_containers/hypospray/medipen/stimulants
name = "illegal stimpack medipen"
desc = "A highly illegal medipen due to its load and small injections, allow for five uses before being drained"
volume = 50
amount_per_transfer_from_this = 10
list_reagents = list("stimulants" = 50)
/obj/item/reagent_containers/hypospray/medipen/stimulants/baseball
name = "the reason the syndicate major league team wins."
desc = "They say drugs never win, but look where you are now, then where they are."
icon_state = "baseballstim"
volume = 50
amount_per_transfer_from_this = 50
list_reagents = list("stimulants" = 50)
/obj/item/reagent_containers/hypospray/medipen/stimpack //goliath kiting
name = "stimpack medipen"
desc = "A rapid way to stimulate your body's adrenaline, allowing for freer movement in restrictive armor."
icon_state = "stimpen"
volume = 20
amount_per_transfer_from_this = 20
list_reagents = list("ephedrine" = 10, "coffee" = 10)
/obj/item/reagent_containers/hypospray/medipen/stimpack/traitor
desc = "A modified stimulants autoinjector for use in combat situations. Has a mild healing effect."
list_reagents = list("stimulants" = 10, "omnizine" = 10)
/obj/item/reagent_containers/hypospray/medipen/morphine
name = "morphine medipen"
desc = "A rapid way to get you out of a tight situation and fast! You'll feel rather drowsy, though."
list_reagents = list("morphine" = 10)
/obj/item/reagent_containers/hypospray/medipen/tuberculosiscure
name = "BVAK autoinjector"
desc = "Bio Virus Antidote Kit autoinjector. Has a two use system for yourself, and someone else. Inject when infected."
icon_state = "stimpen"
volume = 60
amount_per_transfer_from_this = 30
list_reagents = list("atropine" = 10, "epinephrine" = 10, "salbutamol" = 20, "spaceacillin" = 20)
/obj/item/reagent_containers/hypospray/medipen/survival
name = "survival medipen"
desc = "A medipen for surviving in the harshest of environments, heals and protects from environmental hazards. WARNING: Do not inject more than one pen in quick succession."
icon_state = "stimpen"
volume = 52
amount_per_transfer_from_this = 52
list_reagents = list("salbutamol" = 10, "leporazine" = 15, "neo_jelly" = 15, "epinephrine" = 10, "lavaland_extract" = 2)
/obj/item/reagent_containers/hypospray/medipen/species_mutator
name = "species mutator medipen"
desc = "Embark on a whirlwind tour of racial insensitivity by \
literally appropriating other races."
volume = 1
amount_per_transfer_from_this = 1
list_reagents = list("unstablemutationtoxin" = 1)
/obj/item/reagent_containers/hypospray/medipen/firelocker
name = "fire treatment medipen"
desc = "A medipen that has been fulled with burn healing chemicals for personnel without advanced medical knowledge."
volume = 15
amount_per_transfer_from_this = 15
list_reagents = list("oxandrolone" = 5, "kelotane" = 10)
/obj/item/reagent_containers/hypospray/combat/heresypurge
name = "holy water autoinjector"
desc = "A modified air-needle autoinjector for use in combat situations. Prefilled with 5 doses of a holy water mixture."
volume = 250
list_reagents = list("holywater" = 150, "tiresolution" = 50, "dizzysolution" = 50)
amount_per_transfer_from_this = 50
#define HYPO_SPRAY 0
#define HYPO_INJECT 1
#define WAIT_SPRAY 25
#define WAIT_INJECT 25
#define SELF_SPRAY 15
#define SELF_INJECT 15
#define DELUXE_WAIT_SPRAY 20
#define DELUXE_WAIT_INJECT 20
#define DELUXE_SELF_SPRAY 10
#define DELUXE_SELF_INJECT 10
#define COMBAT_WAIT_SPRAY 0
#define COMBAT_WAIT_INJECT 0
#define COMBAT_SELF_SPRAY 0
#define COMBAT_SELF_INJECT 0
//A vial-loaded hypospray. Cartridge-based!
/obj/item/hypospray/mkii
name = "hypospray mk.II"
icon_state = "hypo2"
icon = 'icons/obj/syringe.dmi'
desc = "A new development from DeForest Medical, this hypospray takes 30-unit vials as the drug supply for easy swapping."
w_class = WEIGHT_CLASS_TINY
var/list/allowed_containers = list(/obj/item/reagent_containers/glass/bottle/vial/tiny, /obj/item/reagent_containers/glass/bottle/vial/small)
var/mode = HYPO_INJECT
var/obj/item/reagent_containers/glass/bottle/vial/vial
var/start_vial = /obj/item/reagent_containers/glass/bottle/vial/small
var/spawnwithvial = TRUE
var/inject_wait = WAIT_INJECT
var/spray_wait = WAIT_SPRAY
var/spray_self = SELF_SPRAY
var/inject_self = SELF_INJECT
var/quickload = FALSE
var/penetrates = FALSE
/obj/item/hypospray/mkii/brute
start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/bicaridine
/obj/item/hypospray/mkii/toxin
start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/antitoxin
/obj/item/hypospray/mkii/oxygen
start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/dexalin
/obj/item/hypospray/mkii/burn
start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/kelotane
/obj/item/hypospray/mkii/tricord
start_vial = /obj/item/reagent_containers/glass/bottle/vial/small/preloaded/tricord
/obj/item/hypospray/mkii/enlarge
spawnwithvial = FALSE
/obj/item/hypospray/mkii/CMO
name = "hypospray mk.II deluxe"
allowed_containers = list(/obj/item/reagent_containers/glass/bottle/vial/tiny, /obj/item/reagent_containers/glass/bottle/vial/small, /obj/item/reagent_containers/glass/bottle/vial/large)
icon_state = "cmo2"
desc = "The Deluxe Hypospray can take larger-size vials. It also acts faster and delivers more reagents per spray."
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
start_vial = /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/CMO
inject_wait = DELUXE_WAIT_INJECT
spray_wait = DELUXE_WAIT_SPRAY
spray_self = DELUXE_SELF_SPRAY
inject_self = DELUXE_SELF_INJECT
/obj/item/hypospray/mkii/CMO/combat
name = "combat hypospray mk.II"
desc = "A combat-ready deluxe hypospray that acts almost instantly. It can be tactically reloaded by using a vial on it."
icon_state = "combat2"
start_vial = /obj/item/reagent_containers/glass/bottle/vial/large/preloaded/combat
inject_wait = COMBAT_WAIT_INJECT
spray_wait = COMBAT_WAIT_SPRAY
spray_self = COMBAT_SELF_SPRAY
inject_self = COMBAT_SELF_INJECT
quickload = TRUE
penetrates = TRUE
/obj/item/hypospray/mkii/Initialize()
. = ..()
if(!spawnwithvial)
update_icon()
return
if(start_vial)
vial = new start_vial
update_icon()
/obj/item/hypospray/mkii/update_icon()
..()
icon_state = "[initial(icon_state)][vial ? "" : "-e"]"
if(ismob(loc))
var/mob/M = loc
M.update_inv_hands()
return
/obj/item/hypospray/mkii/examine(mob/user)
. = ..()
if(vial)
to_chat(user, "[vial] has [vial.reagents.total_volume]u remaining.")
else
to_chat(user, "It has no vial loaded in.")
to_chat(user, "[src] is set to [mode ? "Inject" : "Spray"] contents on application.")
/obj/item/hypospray/mkii/proc/unload_hypo(obj/item/I, mob/user)
if((istype(I, /obj/item/reagent_containers/glass/bottle/vial)))
var/obj/item/reagent_containers/glass/bottle/vial/V = I
V.forceMove(user.loc)
user.put_in_hands(V)
to_chat(user, "<span class='notice'>You remove [vial] from [src].</span>")
vial = null
update_icon()
playsound(loc, 'sound/weapons/empty.ogg', 50, 1)
else
to_chat(user, "<span class='notice'>This hypo isn't loaded!</span>")
return
/obj/item/hypospray/mkii/attackby(obj/item/I, mob/living/user)
if((istype(I, /obj/item/reagent_containers/glass/bottle/vial) && vial != null))
if(!quickload)
to_chat(user, "<span class='warning'>[src] can not hold more than one vial!</span>")
return FALSE
unload_hypo(vial, user)
if((istype(I, /obj/item/reagent_containers/glass/bottle/vial)))
var/obj/item/reagent_containers/glass/bottle/vial/V = I
if(!is_type_in_list(V, allowed_containers))
to_chat(user, "<span class='notice'>[src] doesn't accept this type of vial.</span>")
return FALSE
if(!user.transferItemToLoc(V,src))
return FALSE
vial = V
user.visible_message("<span class='notice'>[user] has loaded a vial into [src].</span>","<span class='notice'>You have loaded [vial] into [src].</span>")
update_icon()
playsound(loc, 'sound/weapons/autoguninsert.ogg', 35, 1)
return TRUE
else
to_chat(user, "<span class='notice'>This doesn't fit in [src].</span>")
return FALSE
return FALSE
/obj/item/hypospray/mkii/AltClick(mob/user)
if(vial)
vial.attack_self(user)
// Gunna allow this for now, still really don't approve - Pooj
/obj/item/hypospray/mkii/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED)
to_chat(user, "[src] happens to be already overcharged.")
return
inject_wait = COMBAT_WAIT_INJECT
spray_wait = COMBAT_WAIT_SPRAY
spray_self = COMBAT_SELF_INJECT
inject_self = COMBAT_SELF_SPRAY
penetrates = TRUE
to_chat(user, "You overcharge [src]'s control circuit.")
obj_flags |= EMAGGED
return TRUE
/obj/item/hypospray/mkii/attack_hand(mob/user)
. = ..() //Don't bother changing this or removing it from containers will break.
/obj/item/hypospray/mkii/attack(obj/item/I, mob/user, params)
return
/obj/item/hypospray/mkii/afterattack(atom/target, mob/user, proximity)
if(!vial)
return
if(!proximity)
return
if(!ismob(target))
return
var/mob/living/L
if(isliving(target))
L = target
if(!penetrates && !L.can_inject(user, 1)) //This check appears another four times, since otherwise the penetrating sprays will break in do_mob.
return
if(!L && !target.is_injectable()) //only checks on non-living mobs, due to how can_inject() handles
to_chat(user, "<span class='warning'>You cannot directly fill [target]!</span>")
return
if(target.reagents.total_volume >= target.reagents.maximum_volume)
to_chat(user, "<span class='notice'>[target] is full.</span>")
return
if(ishuman(L))
var/obj/item/bodypart/affecting = L.get_bodypart(check_zone(user.zone_selected))
if(!affecting)
to_chat(user, "<span class='warning'>The limb is missing!</span>")
return
if(affecting.status != BODYPART_ORGANIC)
to_chat(user, "<span class='notice'>Medicine won't work on a robotic limb!</span>")
return
var/contained = vial.reagents.log_list()
log_combat(user, L, "attemped to inject", src, addition="which had [contained]")
//Always log attemped injections for admins
if(vial != null)
switch(mode)
if(HYPO_INJECT)
if(L) //living mob
if(L != user)
L.visible_message("<span class='danger'>[user] is trying to inject [L] with [src]!</span>", \
"<span class='userdanger'>[user] is trying to inject [L] with [src]!</span>")
if(!do_mob(user, L, inject_wait))
return
if(!penetrates && !L.can_inject(user, 1))
return
if(!vial.reagents.total_volume)
return
if(L.reagents.total_volume >= L.reagents.maximum_volume)
return
L.visible_message("<span class='danger'>[user] uses the [src] on [L]!</span>", \
"<span class='userdanger'>[user] uses the [src] on [L]!</span>")
else
if(!do_mob(user, L, inject_self))
return
if(!penetrates && !L.can_inject(user, 1))
return
if(!vial.reagents.total_volume)
return
if(L.reagents.total_volume >= L.reagents.maximum_volume)
return
log_attack("<font color='red'>[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])</font>")
L.log_message("<font color='orange'>applied [src] to themselves ([contained]).</font>", INDIVIDUAL_ATTACK_LOG)
var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
vial.reagents.reaction(L, INJECT, fraction)
vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
if(vial.amount_per_transfer_from_this >= 15)
playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
if(vial.amount_per_transfer_from_this < 15)
playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
to_chat(user, "<span class='notice'>You inject [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.</span>")
if(HYPO_SPRAY)
if(L) //living mob
if(L != user)
L.visible_message("<span class='danger'>[user] is trying to spray [L] with [src]!</span>", \
"<span class='userdanger'>[user] is trying to spray [L] with [src]!</span>")
if(!do_mob(user, L, spray_wait))
return
if(!penetrates && !L.can_inject(user, 1))
return
if(!vial.reagents.total_volume)
return
if(L.reagents.total_volume >= L.reagents.maximum_volume)
return
L.visible_message("<span class='danger'>[user] uses the [src] on [L]!</span>", \
"<span class='userdanger'>[user] uses the [src] on [L]!</span>")
else
if(!do_mob(user, L, spray_self))
return
if(!penetrates && !L.can_inject(user, 1))
return
if(!vial.reagents.total_volume)
return
if(L.reagents.total_volume >= L.reagents.maximum_volume)
return
log_attack("<font color='red'>[user.name] ([user.ckey]) applied [src] to [L.name] ([L.ckey]), which had [contained] (INTENT: [uppertext(user.a_intent)]) (MODE: [src.mode])</font>")
L.log_message("<font color='orange'>applied [src] to themselves ([contained]).</font>", INDIVIDUAL_ATTACK_LOG)
var/fraction = min(vial.amount_per_transfer_from_this/vial.reagents.total_volume, 1)
vial.reagents.reaction(L, PATCH, fraction)
vial.reagents.trans_to(target, vial.amount_per_transfer_from_this)
if(vial.amount_per_transfer_from_this >= 15)
playsound(loc,'sound/items/hypospray_long.ogg',50, 1, -1)
if(vial.amount_per_transfer_from_this < 15)
playsound(loc, pick('sound/items/hypospray.ogg','sound/items/hypospray2.ogg'), 50, 1, -1)
to_chat(user, "<span class='notice'>You spray [vial.amount_per_transfer_from_this] units of the solution. The hypospray's cartridge now contains [vial.reagents.total_volume] units.</span>")
else
to_chat(user, "<span class='notice'>[src] doesn't work here!</span>")
return
/obj/item/hypospray/mkii/attack_self(mob/living/user)
if(user)
if(user.incapacitated())
return
else if(!vial)
to_chat(user, "This Hypo needs to be loaded first!")
return
else
unload_hypo(vial,user)
/obj/item/hypospray/mkii/verb/modes()
set name = "Toggle Application Mode"
set category = "Object"
set src in usr
var/mob/M = usr
switch(mode)
if(HYPO_SPRAY)
mode = HYPO_INJECT
to_chat(M, "[src] is now set to inject contents on application.")
if(HYPO_INJECT)
mode = HYPO_SPRAY
to_chat(M, "[src] is now set to spray contents on application.")
#undef HYPO_SPRAY
#undef HYPO_INJECT
#undef WAIT_SPRAY
#undef WAIT_INJECT
#undef SELF_SPRAY
#undef SELF_INJECT
#undef DELUXE_WAIT_SPRAY
#undef DELUXE_WAIT_INJECT
#undef DELUXE_SELF_SPRAY
#undef DELUXE_SELF_INJECT
#undef COMBAT_WAIT_SPRAY
#undef COMBAT_WAIT_INJECT
#undef COMBAT_SELF_SPRAY
#undef COMBAT_SELF_INJECT
@@ -0,0 +1,257 @@
/obj/item/reagent_containers/pill
name = "pill"
desc = "A tablet or capsule."
icon = 'icons/obj/chemical.dmi'
icon_state = "pill"
item_state = "pill"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
possible_transfer_amounts = list()
volume = 50
grind_results = list()
var/apply_type = INGEST
var/apply_method = "swallow"
var/roundstart = 0
var/self_delay = 0 //pills are instant, this is because patches inheret their aplication from pills
var/dissolvable = TRUE
/obj/item/reagent_containers/pill/Initialize()
. = ..()
if(!icon_state)
icon_state = "pill[rand(1,20)]"
if(reagents.total_volume && roundstart)
name += " ([reagents.total_volume]u)"
/obj/item/reagent_containers/pill/attack_self(mob/user)
return
/obj/item/reagent_containers/pill/attack(mob/M, mob/user, def_zone)
if(!canconsume(M, user))
return 0
if(M == user)
M.visible_message("<span class='notice'>[user] attempts to [apply_method] [src].</span>")
if(self_delay)
if(!do_mob(user, M, self_delay))
return 0
to_chat(M, "<span class='notice'>You [apply_method] [src].</span>")
else
M.visible_message("<span class='danger'>[user] attempts to force [M] to [apply_method] [src].</span>", \
"<span class='userdanger'>[user] attempts to force [M] to [apply_method] [src].</span>")
if(!do_mob(user, M))
return 0
M.visible_message("<span class='danger'>[user] forces [M] to [apply_method] [src].</span>", \
"<span class='userdanger'>[user] forces [M] to [apply_method] [src].</span>")
var/makes_me_think = pick(strings("redpill.json", "redpill_questions"))
if(icon_state == "pill4" && prob(5)) //you take the red pill - you stay in Wonderland, and I show you how deep the rabbit hole goes
addtimer(CALLBACK(GLOBAL_PROC, /proc/to_chat, M, "<span class='notice'>[makes_me_think]</span>"), 50)
log_combat(user, M, "fed", reagents.log_list())
if(reagents.total_volume)
reagents.reaction(M, apply_type)
reagents.trans_to(M, reagents.total_volume)
qdel(src)
return 1
/obj/item/reagent_containers/pill/afterattack(obj/target, mob/user , proximity)
. = ..()
if(!proximity)
return
if(!dissolvable || !target.is_refillable())
return
if(target.is_drainable() && !target.reagents.total_volume)
to_chat(user, "<span class='warning'>[target] is empty! There's nothing to dissolve [src] in.</span>")
return
if(target.reagents.holder_full())
to_chat(user, "<span class='warning'>[target] is full.</span>")
return
to_chat(user, "<span class='notice'>You dissolve [src] in [target].</span>")
for(var/mob/O in viewers(2, user)) //viewers is necessary here because of the small radius
to_chat(O, "<span class='warning'>[user] slips something into [target]!</span>")
reagents.trans_to(target, reagents.total_volume)
qdel(src)
/obj/item/reagent_containers/pill/tox
name = "toxins pill"
desc = "Highly toxic."
icon_state = "pill5"
list_reagents = list("toxin" = 50)
roundstart = 1
/obj/item/reagent_containers/pill/cyanide
name = "cyanide pill"
desc = "Don't swallow this."
icon_state = "pill5"
list_reagents = list("cyanide" = 50)
roundstart = 1
/obj/item/reagent_containers/pill/adminordrazine
name = "adminordrazine pill"
desc = "It's magic. We don't have to explain it."
icon_state = "pill16"
list_reagents = list("adminordrazine" = 50)
roundstart = 1
/obj/item/reagent_containers/pill/morphine
name = "morphine pill"
desc = "Commonly used to treat insomnia."
icon_state = "pill8"
list_reagents = list("morphine" = 30)
roundstart = 1
/obj/item/reagent_containers/pill/stimulant
name = "stimulant pill"
desc = "Often taken by overworked employees, athletes, and the inebriated. You'll snap to attention immediately!"
icon_state = "pill19"
list_reagents = list("ephedrine" = 10, "antihol" = 10, "coffee" = 30)
roundstart = 1
/obj/item/reagent_containers/pill/salbutamol
name = "salbutamol pill"
desc = "Used to treat oxygen deprivation."
icon_state = "pill16"
list_reagents = list("salbutamol" = 30)
roundstart = 1
/obj/item/reagent_containers/pill/charcoal
name = "charcoal pill"
desc = "Neutralizes many common toxins."
icon_state = "pill17"
list_reagents = list("charcoal" = 10)
roundstart = 1
/obj/item/reagent_containers/pill/epinephrine
name = "epinephrine pill"
desc = "Used to stabilize patients."
icon_state = "pill5"
list_reagents = list("epinephrine" = 15)
roundstart = 1
/obj/item/reagent_containers/pill/mannitol
name = "mannitol pill"
desc = "Used to treat brain damage."
icon_state = "pill17"
list_reagents = list("mannitol" = 50)
roundstart = 1
/obj/item/reagent_containers/pill/mutadone
name = "mutadone pill"
desc = "Used to treat genetic damage."
icon_state = "pill20"
list_reagents = list("mutadone" = 50)
roundstart = 1
/obj/item/reagent_containers/pill/salicyclic
name = "salicylic acid pill"
desc = "Used to dull pain."
icon_state = "pill9"
list_reagents = list("sal_acid" = 24)
roundstart = 1
/obj/item/reagent_containers/pill/oxandrolone
name = "oxandrolone pill"
desc = "Used to stimulate burn healing."
icon_state = "pill11"
list_reagents = list("oxandrolone" = 24)
roundstart = 1
/obj/item/reagent_containers/pill/insulin
name = "insulin pill"
desc = "Handles hyperglycaemic coma."
icon_state = "pill18"
list_reagents = list("insulin" = 50)
roundstart = 1
/obj/item/reagent_containers/pill/psicodine
name = "psicodine pill"
desc = "Used to treat mental instability and traumas."
list_reagents = list("psicodine" = 10)
icon_state = "pill22"
roundstart = 1
/obj/item/reagent_containers/pill/antirad
name = "potassium iodide pill"
desc = "Used to treat radition used to counter radiation poisoning."
icon_state = "pill18"
list_reagents = list("potass_iodide" = 50)
roundstart = 1
/obj/item/reagent_containers/pill/antirad_plus
name = "prussian blue pill"
desc = "Used to treat heavy radition poisoning."
icon_state = "prussian_blue"
list_reagents = list("prussian_blue" = 25, "water" = 10)
roundstart = 1
/obj/item/reagent_containers/pill/mutarad
name = "radiation treatment deluxe pill"
desc = "Used to treat heavy radition poisoning and genetic defects."
icon_state = "anit_rad_fixgene"
list_reagents = list("prussian_blue" = 15, "potass_iodide" = 15, "mutadone" = 15, "water" = 5)
roundstart = 1
///////////////////////////////////////// this pill is used only in a legion mob drop
/obj/item/reagent_containers/pill/shadowtoxin
name = "black pill"
desc = "I wouldn't eat this if I were you."
icon_state = "pill9"
color = "#454545"
list_reagents = list("shadowmutationtoxin" = 1)
//////////////////////////////////////// drugs
/obj/item/reagent_containers/pill/zoom
name = "zoom pill"
list_reagents = list("synaptizine" = 10, "nicotine" = 10, "methamphetamine" = 1)
/obj/item/reagent_containers/pill/happy
name = "happy pill"
list_reagents = list("sugar" = 10, "space_drugs" = 10)
/obj/item/reagent_containers/pill/lsd
name = "hallucinogen pill"
list_reagents = list("mushroomhallucinogen" = 15, "mindbreaker" = 15)
/obj/item/reagent_containers/pill/aranesp
name = "speedy pill"
list_reagents = list("aranesp" = 10)
/obj/item/reagent_containers/pill/happiness
name = "happiness pill"
desc = "It has a creepy smiling face on it."
icon_state = "pill_happy"
list_reagents = list("happiness" = 10)
/obj/item/reagent_containers/pill/floorpill
name = "floorpill"
desc = "A strange pill found in the depths of maintenance"
icon_state = "pill21"
var/static/list/names = list("maintenance pill","floorpill","mystery pill","suspicious pill","strange pill")
var/static/list/descs = list("Your feeling is telling you no, but...","Drugs are expensive, you can't afford not to eat any pills that you find."\
, "Surely, there's no way this could go bad.")
/obj/item/reagent_containers/pill/floorpill/Initialize()
list_reagents = list(get_random_reagent_id() = rand(10,50))
. = ..()
name = pick(names)
if(prob(20))
desc = pick(descs)
/obj/item/reagent_containers/pill/get_belt_overlay()
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "pouch")
/obj/item/reagent_containers/pill/penis_enlargement
name = "penis enlargement pill"
list_reagents = list("penis_enlarger" = 10)
/obj/item/reagent_containers/pill/breast_enlargement
name = "breast enlargement pill"
list_reagents = list("breast_enlarger" = 10)
@@ -0,0 +1,324 @@
/obj/item/reagent_containers/spray
name = "spray bottle"
desc = "A spray bottle, with an unscrewable top."
icon = 'icons/obj/janitor.dmi'
icon_state = "cleaner"
item_state = "cleaner"
lefthand_file = 'icons/mob/inhands/equipment/custodial_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/custodial_righthand.dmi'
item_flags = NOBLUDGEON
reagent_flags = OPENCONTAINER
slot_flags = ITEM_SLOT_BELT
throwforce = 0
w_class = WEIGHT_CLASS_SMALL
throw_speed = 3
throw_range = 7
var/stream_mode = 0 //whether we use the more focused mode
var/current_range = 3 //the range of tiles the sprayer will reach.
var/spray_range = 3 //the range of tiles the sprayer will reach when in spray mode.
var/stream_range = 1 //the range of tiles the sprayer will reach when in stream mode.
var/stream_amount = 10 //the amount of reagents transfered when in stream mode.
var/spray_delay = 3 //The amount of sleep() delay between each chempuff step.
var/can_fill_from_container = TRUE
amount_per_transfer_from_this = 5
volume = 250
possible_transfer_amounts = list(5,10,15,20,25,30,50,100)
/obj/item/reagent_containers/spray/afterattack(atom/A, mob/user)
. = ..()
if(istype(A, /obj/structure/sink) || istype(A, /obj/structure/janitorialcart) || istype(A, /obj/machinery/hydroponics))
return
if((A.is_drainable() && !A.is_refillable()) && get_dist(src,A) <= 1 && can_fill_from_container)
if(!A.reagents.total_volume)
to_chat(user, "<span class='warning'>[A] is empty.</span>")
return
if(reagents.holder_full())
to_chat(user, "<span class='warning'>[src] is full.</span>")
return
var/trans = A.reagents.trans_to(src, 50) //transfer 50u , using the spray's transfer amount would take too long to refill
to_chat(user, "<span class='notice'>You fill \the [src] with [trans] units of the contents of \the [A].</span>")
return
if(reagents.total_volume < amount_per_transfer_from_this)
to_chat(user, "<span class='warning'>[src] is empty!</span>")
return
spray(A)
playsound(src.loc, 'sound/effects/spray2.ogg', 50, 1, -6)
user.changeNext_move(CLICK_CD_RANGE*2)
user.newtonian_move(get_dir(A, user))
var/turf/T = get_turf(src)
if(reagents.has_reagent("sacid"))
message_admins("[ADMIN_LOOKUPFLW(user)] fired sulphuric acid from \a [src] at [ADMIN_VERBOSEJMP(T)].")
log_game("[key_name(user)] fired sulphuric acid from \a [src] at [AREACOORD(T)].")
if(reagents.has_reagent("facid"))
message_admins("[ADMIN_LOOKUPFLW(user)] fired Fluacid from \a [src] at [ADMIN_VERBOSEJMP(T)].")
log_game("[key_name(user)] fired Fluacid from \a [src] at [AREACOORD(T)].")
if(reagents.has_reagent("lube"))
message_admins("[ADMIN_LOOKUPFLW(user)] fired Space lube from \a [src] at [ADMIN_VERBOSEJMP(T)].")
log_game("[key_name(user)] fired Space lube from \a [src] at [AREACOORD(T)].")
return
/obj/item/reagent_containers/spray/proc/spray(atom/A)
var/range = CLAMP(get_dist(src, A), 1, current_range)
var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src))
D.create_reagents(amount_per_transfer_from_this)
var/puff_reagent_left = range //how many turf, mob or dense objet we can react with before we consider the chem puff consumed
if(stream_mode)
reagents.trans_to(D, amount_per_transfer_from_this)
puff_reagent_left = 1
else
reagents.trans_to(D, amount_per_transfer_from_this, 1/range)
D.color = mix_color_from_reagents(D.reagents.reagent_list)
var/wait_step = max(round(2+ spray_delay * INVERSE(range)), 2)
do_spray(A, wait_step, D, range, puff_reagent_left)
/obj/item/reagent_containers/spray/proc/do_spray(atom/A, wait_step, obj/effect/decal/chempuff/D, range, puff_reagent_left)
set waitfor = FALSE
var/range_left = range
for(var/i=0, i<range, i++)
range_left--
step_towards(D,A)
sleep(wait_step)
for(var/atom/T in get_turf(D))
if(T == D || T.invisibility) //we ignore the puff itself and stuff below the floor
continue
if(puff_reagent_left <= 0)
break
if(stream_mode)
if(ismob(T))
var/mob/M = T
if(!M.lying || !range_left)
D.reagents.reaction(M, VAPOR)
puff_reagent_left -= 1
else if(!range_left)
D.reagents.reaction(T, VAPOR)
else
D.reagents.reaction(T, VAPOR)
if(ismob(T))
puff_reagent_left -= 1
if(puff_reagent_left > 0 && (!stream_mode || !range_left))
D.reagents.reaction(get_turf(D), VAPOR)
puff_reagent_left -= 1
if(puff_reagent_left <= 0) // we used all the puff so we delete it.
qdel(D)
return
qdel(D)
/obj/item/reagent_containers/spray/attack_self(mob/user)
stream_mode = !stream_mode
if(stream_mode)
amount_per_transfer_from_this = stream_amount
current_range = stream_range
else
amount_per_transfer_from_this = initial(amount_per_transfer_from_this)
current_range = spray_range
to_chat(user, "<span class='notice'>You switch the nozzle setting to [stream_mode ? "\"stream\"":"\"spray\""]. You'll now use [amount_per_transfer_from_this] units per use.</span>")
/obj/item/reagent_containers/spray/attackby(obj/item/I, mob/user, params)
var/hotness = I.get_temperature()
if(hotness && reagents)
reagents.expose_temperature(hotness)
to_chat(user, "<span class='notice'>You heat [name] with [I]!</span>")
return ..()
/obj/item/reagent_containers/spray/verb/empty()
set name = "Empty Spray Bottle"
set category = "Object"
set src in usr
if(usr.incapacitated())
return
if (alert(usr, "Are you sure you want to empty that?", "Empty Bottle:", "Yes", "No") != "Yes")
return
if(isturf(usr.loc) && src.loc == usr)
to_chat(usr, "<span class='notice'>You empty \the [src] onto the floor.</span>")
reagents.reaction(usr.loc)
src.reagents.clear_reagents()
//space cleaner
/obj/item/reagent_containers/spray/cleaner
name = "space cleaner"
desc = "BLAM!-brand non-foaming space cleaner!"
volume = 100
list_reagents = list("cleaner" = 100)
amount_per_transfer_from_this = 2
stream_amount = 5
/obj/item/reagent_containers/spray/cleaner/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is putting the nozzle of \the [src] in [user.p_their()] mouth. It looks like [user.p_theyre()] trying to commit suicide!</span>")
if(do_mob(user,user,30))
if(reagents.total_volume >= amount_per_transfer_from_this)//if not empty
user.visible_message("<span class='suicide'>[user] pulls the trigger!</span>")
src.spray(user)
return BRUTELOSS
else
user.visible_message("<span class='suicide'>[user] pulls the trigger...but \the [src] is empty!</span>")
return SHAME
else
user.visible_message("<span class='suicide'>[user] decided life was worth living.</span>")
return
//Drying Agent
/obj/item/reagent_containers/spray/drying_agent
name = "drying agent spray"
desc = "A spray bottle for drying agent."
volume = 100
list_reagents = list("drying_agent" = 100)
amount_per_transfer_from_this = 2
stream_amount = 5
//spray tan
/obj/item/reagent_containers/spray/spraytan
name = "spray tan"
volume = 50
desc = "Gyaro brand spray tan. Do not spray near eyes or other orifices."
list_reagents = list("spraytan" = 50)
//pepperspray
/obj/item/reagent_containers/spray/pepper
name = "pepperspray"
desc = "Manufactured by UhangInc, used to blind and down an opponent quickly."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "pepperspray"
item_state = "pepperspray"
lefthand_file = 'icons/mob/inhands/equipment/security_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/security_righthand.dmi'
volume = 40
stream_range = 4
spray_delay = 1
amount_per_transfer_from_this = 5
list_reagents = list("condensedcapsaicin" = 40)
/obj/item/reagent_containers/spray/pepper/suicide_act(mob/living/carbon/user)
user.visible_message("<span class='suicide'>[user] begins huffing \the [src]! It looks like [user.p_theyre()] getting a dirty high!</span>")
return OXYLOSS
// Fix pepperspraying yourself
/obj/item/reagent_containers/spray/pepper/afterattack(atom/A as mob|obj, mob/user)
if (A.loc == user)
return
. = ..()
//water flower
/obj/item/reagent_containers/spray/waterflower
name = "water flower"
desc = "A seemingly innocent sunflower...with a twist."
icon = 'icons/obj/hydroponics/harvest.dmi'
icon_state = "sunflower"
item_state = "sunflower"
amount_per_transfer_from_this = 1
volume = 10
list_reagents = list("water" = 10)
/obj/item/reagent_containers/spray/waterflower/attack_self(mob/user) //Don't allow changing how much the flower sprays
return
///Subtype used for the lavaland clown ruin.
/obj/item/reagent_containers/spray/waterflower/superlube
name = "clown flower"
desc = "A delightly devilish flower... you got a feeling where this is going."
icon = 'icons/obj/chemical.dmi'
icon_state = "clownflower"
volume = 30
list_reagents = list(/datum/reagent/lube/superlube = 30)
/obj/item/reagent_containers/spray/waterflower/cyborg
reagent_flags = NONE
volume = 100
list_reagents = list("water" = 100)
var/generate_amount = 5
var/generate_type = "water"
var/last_generate = 0
var/generate_delay = 10 //deciseconds
can_fill_from_container = FALSE
/obj/item/reagent_containers/spray/waterflower/cyborg/hacked
name = "nova flower"
desc = "This doesn't look safe at all..."
list_reagents = list("clf3" = 3)
volume = 3
generate_type = "clf3"
generate_amount = 1
generate_delay = 40 //deciseconds
/obj/item/reagent_containers/spray/waterflower/cyborg/Initialize()
. = ..()
START_PROCESSING(SSfastprocess, src)
/obj/item/reagent_containers/spray/waterflower/cyborg/Destroy()
STOP_PROCESSING(SSfastprocess, src)
return ..()
/obj/item/reagent_containers/spray/waterflower/cyborg/process()
if(world.time < last_generate + generate_delay)
return
last_generate = world.time
generate_reagents()
/obj/item/reagent_containers/spray/waterflower/cyborg/empty()
to_chat(usr, "<span class='warning'>You can not empty this!</span>")
return
/obj/item/reagent_containers/spray/waterflower/cyborg/proc/generate_reagents()
reagents.add_reagent(generate_type, generate_amount)
//chemsprayer
/obj/item/reagent_containers/spray/chemsprayer
name = "chem sprayer"
desc = "A utility used to spray large amounts of reagents in a given area."
icon = 'icons/obj/guns/projectile.dmi'
icon_state = "chemsprayer"
item_state = "chemsprayer"
lefthand_file = 'icons/mob/inhands/weapons/guns_lefthand.dmi'
righthand_file = 'icons/mob/inhands/weapons/guns_righthand.dmi'
throwforce = 0
w_class = WEIGHT_CLASS_NORMAL
stream_mode = 1
current_range = 7
spray_range = 4
stream_range = 7
amount_per_transfer_from_this = 10
volume = 600
/obj/item/reagent_containers/spray/chemsprayer/afterattack(atom/A as mob|obj, mob/user)
// Make it so the bioterror spray doesn't spray yourself when you click your inventory items
if (A.loc == user)
return
. = ..()
/obj/item/reagent_containers/spray/chemsprayer/spray(atom/A)
var/direction = get_dir(src, A)
var/turf/T = get_turf(A)
var/turf/T1 = get_step(T,turn(direction, 90))
var/turf/T2 = get_step(T,turn(direction, -90))
var/list/the_targets = list(T,T1,T2)
for(var/i=1, i<=3, i++) // intialize sprays
if(reagents.total_volume < 1)
return
..(the_targets[i])
/obj/item/reagent_containers/spray/chemsprayer/bioterror
list_reagents = list("sodium_thiopental" = 100, "coniine" = 100, "venom" = 100, "condensedcapsaicin" = 100, "initropidril" = 100, "polonium" = 100)
// Plant-B-Gone
/obj/item/reagent_containers/spray/plantbgone // -- Skie
name = "Plant-B-Gone"
desc = "Kills those pesky weeds!"
icon = 'icons/obj/hydroponics/equipment.dmi'
icon_state = "plantbgone"
item_state = "plantbgone"
lefthand_file = 'icons/mob/inhands/equipment/hydroponics_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/hydroponics_righthand.dmi'
volume = 100
list_reagents = list("plantbgone" = 100)
@@ -0,0 +1,351 @@
/obj/item/reagent_containers/syringe
name = "syringe"
desc = "A syringe that can hold up to 15 units."
icon = 'icons/obj/syringe.dmi'
item_state = "syringe_0"
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
icon_state = "0"
amount_per_transfer_from_this = 5
possible_transfer_amounts = list()
volume = 15
var/mode = SYRINGE_DRAW
var/busy = FALSE // needed for delayed drawing of blood
var/proj_piercing = 0 //does it pierce through thick clothes when shot with syringe gun
materials = list(MAT_METAL=10, MAT_GLASS=20)
reagent_flags = TRANSPARENT
/obj/item/reagent_containers/syringe/Initialize()
. = ..()
if(list_reagents) //syringe starts in inject mode if its already got something inside
mode = SYRINGE_INJECT
update_icon()
/obj/item/reagent_containers/syringe/on_reagent_change(changetype)
update_icon()
/obj/item/reagent_containers/syringe/pickup(mob/user)
..()
update_icon()
/obj/item/reagent_containers/syringe/dropped(mob/user)
..()
update_icon()
/obj/item/reagent_containers/syringe/attack_self(mob/user)
mode = !mode
update_icon()
//ATTACK HAND IGNORING PARENT RETURN VALUE
/obj/item/reagent_containers/syringe/attack_hand()
. = ..()
update_icon()
/obj/item/reagent_containers/syringe/attack_paw(mob/user)
return attack_hand(user)
/obj/item/reagent_containers/syringe/attackby(obj/item/I, mob/user, params)
return
/obj/item/reagent_containers/syringe/afterattack(atom/target, mob/user , proximity)
. = ..()
if(busy)
return
if(!proximity)
return
if(!target.reagents)
return
var/mob/living/L
if(isliving(target))
L = target
if(!L.can_inject(user, 1))
return
// chance of monkey retaliation
if(ismonkey(target) && prob(MONKEY_SYRINGE_RETALIATION_PROB))
var/mob/living/carbon/monkey/M
M = target
M.retaliate(user)
switch(mode)
if(SYRINGE_DRAW)
if(reagents.total_volume >= reagents.maximum_volume)
to_chat(user, "<span class='notice'>The syringe is full.</span>")
return
if(L) //living mob
var/drawn_amount = reagents.maximum_volume - reagents.total_volume
if(target != user)
target.visible_message("<span class='danger'>[user] is trying to take a blood sample from [target]!</span>", \
"<span class='userdanger'>[user] is trying to take a blood sample from [target]!</span>")
busy = TRUE
if(!do_mob(user, target, extra_checks=CALLBACK(L, /mob/living/proc/can_inject,user,1)))
busy = FALSE
return
if(reagents.total_volume >= reagents.maximum_volume)
return
busy = FALSE
if(L.transfer_blood_to(src, drawn_amount))
user.visible_message("[user] takes a blood sample from [L].")
else
to_chat(user, "<span class='warning'>You are unable to draw any blood from [L]!</span>")
else //if not mob
if(!target.reagents.total_volume)
to_chat(user, "<span class='warning'>[target] is empty!</span>")
return
if(!target.is_drawable())
to_chat(user, "<span class='warning'>You cannot directly remove reagents from [target]!</span>")
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this) // transfer from, transfer to - who cares?
to_chat(user, "<span class='notice'>You fill [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.</span>")
if (round(reagents.total_volume, 0.1) >= reagents.maximum_volume)
mode=!mode
update_icon()
if(SYRINGE_INJECT)
// Always log attemped injections for admins
var/contained = reagents.log_list()
log_combat(user, target, "attempted to inject", src, addition="which had [contained]")
if(!reagents.total_volume)
to_chat(user, "<span class='notice'>[src] is empty.</span>")
return
if(!L && !target.is_injectable()) //only checks on non-living mobs, due to how can_inject() handles
to_chat(user, "<span class='warning'>You cannot directly fill [target]!</span>")
return
if(target.reagents.total_volume >= target.reagents.maximum_volume)
to_chat(user, "<span class='notice'>[target] is full.</span>")
return
if(L) //living mob
if(!L.can_inject(user, TRUE))
return
if(L != user)
L.visible_message("<span class='danger'>[user] is trying to inject [L]!</span>", \
"<span class='userdanger'>[user] is trying to inject [L]!</span>")
if(!do_mob(user, L, extra_checks=CALLBACK(L, /mob/living/proc/can_inject,user,1)))
return
if(!reagents.total_volume)
return
if(L.reagents.total_volume >= L.reagents.maximum_volume)
return
L.visible_message("<span class='danger'>[user] injects [L] with the syringe!", \
"<span class='userdanger'>[user] injects [L] with the syringe!</span>")
if(L != user)
log_combat(user, L, "injected", src, addition="which had [contained]")
else
L.log_message("injected themselves ([contained]) with [src.name]", LOG_ATTACK, color="orange")
var/fraction = min(amount_per_transfer_from_this/reagents.total_volume, 1)
reagents.reaction(L, INJECT, fraction)
reagents.trans_to(target, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>You inject [amount_per_transfer_from_this] units of the solution. The syringe now contains [reagents.total_volume] units.</span>")
if (reagents.total_volume <= 0 && mode==SYRINGE_INJECT)
mode = SYRINGE_DRAW
update_icon()
/obj/item/reagent_containers/syringe/update_icon()
cut_overlays()
var/rounded_vol
if(reagents && reagents.total_volume)
rounded_vol = CLAMP(round((reagents.total_volume / volume * 15),5), 1, 15)
var/image/filling_overlay = mutable_appearance('icons/obj/reagentfillings.dmi', "syringe[rounded_vol]")
filling_overlay.color = mix_color_from_reagents(reagents.reagent_list)
add_overlay(filling_overlay)
else
rounded_vol = 0
icon_state = "[rounded_vol]"
item_state = "syringe_[rounded_vol]"
if(ismob(loc))
var/mob/M = loc
var/injoverlay
switch(mode)
if (SYRINGE_DRAW)
injoverlay = "draw"
if (SYRINGE_INJECT)
injoverlay = "inject"
add_overlay(injoverlay)
M.update_inv_hands()
/obj/item/reagent_containers/syringe/epinephrine
name = "syringe (epinephrine)"
desc = "Contains epinephrine - used to stabilize patients."
list_reagents = list("epinephrine" = 15)
/obj/item/reagent_containers/syringe/charcoal
name = "syringe (charcoal)"
desc = "Contains charcoal."
list_reagents = list("charcoal" = 15)
/obj/item/reagent_containers/syringe/antiviral
name = "syringe (spaceacillin)"
desc = "Contains antiviral agents."
list_reagents = list("spaceacillin" = 15)
/obj/item/reagent_containers/syringe/bioterror
name = "bioterror syringe"
desc = "Contains several paralyzing reagents."
list_reagents = list("neurotoxin" = 5, "mutetoxin" = 5, "sodium_thiopental" = 5)
/obj/item/reagent_containers/syringe/stimulants
name = "Stimpack"
desc = "Contains stimulants."
amount_per_transfer_from_this = 50
volume = 50
list_reagents = list("stimulants" = 50)
/obj/item/reagent_containers/syringe/calomel
name = "syringe (calomel)"
desc = "Contains calomel."
list_reagents = list("calomel" = 15)
/obj/item/reagent_containers/syringe/plasma
name = "syringe (plasma)"
desc = "Contains plasma."
list_reagents = list("plasma" = 15)
/obj/item/reagent_containers/syringe/lethal
name = "lethal injection syringe"
desc = "A syringe used for lethal injections. It can hold up to 50 units."
amount_per_transfer_from_this = 50
volume = 50
/obj/item/reagent_containers/syringe/lethal/choral
list_reagents = list("chloralhydrate" = 50)
/obj/item/reagent_containers/syringe/lethal/execution
list_reagents = list("amatoxin" = 15, "formaldehyde" = 15, "cyanide" = 10, "facid" = 10) //Citadel edit, changing out plasma from lethals
/obj/item/reagent_containers/syringe/mulligan
name = "Mulligan"
desc = "A syringe used to completely change the users identity."
amount_per_transfer_from_this = 1
volume = 1
list_reagents = list("mulligan" = 1)
/obj/item/reagent_containers/syringe/gluttony
name = "Gluttony's Blessing"
desc = "A syringe recovered from a dread place. It probably isn't wise to use."
amount_per_transfer_from_this = 1
volume = 1
list_reagents = list("gluttonytoxin" = 1)
/obj/item/reagent_containers/syringe/bluespace
name = "bluespace syringe"
desc = "An advanced syringe that can hold 60 units of chemicals."
amount_per_transfer_from_this = 20
volume = 60
/obj/item/reagent_containers/syringe/noreact
name = "cryo syringe"
desc = "An advanced syringe that stops reagents inside from reacting. It can hold up to 20 units."
volume = 20
reagent_flags = TRANSPARENT | NO_REACT
/obj/item/reagent_containers/syringe/piercing
name = "piercing syringe"
desc = "A diamond-tipped syringe that pierces armor when launched at high velocity. It can hold up to 10 units."
volume = 10
proj_piercing = 1
/obj/item/reagent_containers/syringe/get_belt_overlay()
return mutable_appearance('icons/obj/clothing/belt_overlays.dmi', "pouch")
/obj/item/reagent_containers/syringe/dart
name = "medicinal smartdart"
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented."
volume = 20
amount_per_transfer_from_this = 20
icon_state = "empty"
item_state = "syringe_empty"
var/emptrig = FALSE
/obj/item/reagent_containers/syringe/dart/afterattack(atom/target, mob/user , proximity)
if(busy)
return
if(!proximity)
return
if(!target.reagents)
return
var/mob/living/L
if(isliving(target))
L = target
if(!L.can_inject(user, 1))
return
switch(mode)
if(SYRINGE_DRAW)
if(reagents.total_volume >= reagents.maximum_volume)
to_chat(user, "<span class='notice'>The dart is full!</span>")
return
if(L) //living mob
to_chat(user, "<span class='warning'>You can't draw blood using a dart!</span>")
return
else //if not mob
if(!target.reagents.total_volume)
to_chat(user, "<span class='warning'>[target] is empty!</span>")
return
if(!target.is_drawable())
to_chat(user, "<span class='warning'>You cannot directly remove reagents from [target]!</span>")
return
var/trans = target.reagents.trans_to(src, amount_per_transfer_from_this)
to_chat(user, "<span class='notice'>You soak the [src] with [trans] units of the solution. It now contains [reagents.total_volume] units.</span>")
if (round(reagents.total_volume,1) >= reagents.maximum_volume)
mode=!mode
update_icon()
if(SYRINGE_INJECT)
src.visible_message("<span class='danger'>The smartdart gives a frustrated boop! It's fully saturated; You need to shoot someone with it!</span>")
/obj/item/reagent_containers/syringe/dart/attack_self(mob/user)
return
/obj/item/reagent_containers/syringe/dart/update_icon()
cut_overlays()
var/rounded_vol
rounded_vol = "empty"
if(reagents && reagents.total_volume)
if(volume/round(reagents.total_volume, 1) == 1)
rounded_vol="full"
mode = SYRINGE_INJECT
icon_state = "[rounded_vol]"
item_state = "syringe_[rounded_vol]"
if(ismob(loc))
var/mob/M = loc
var/injoverlay
switch(mode)
if (SYRINGE_DRAW)
injoverlay = "draw"
if (SYRINGE_INJECT)
injoverlay = "ready"
add_overlay(injoverlay)
M.update_inv_hands()
/obj/item/reagent_containers/syringe/dart/emp_act(severity)
emptrig = TRUE
..()
/obj/item/reagent_containers/syringe/dart/bluespace
name = "bluespace smartdart"
desc = "A non-harmful dart that can administer medication from a range. Once it hits a patient using it's smart nanofilter technology only medicines contained within the dart are administered to the patient. Additonally, due to capillary action, injection of chemicals past the overdose limit is prevented. Has an extended volume capacity thanks to bluespace foam."
amount_per_transfer_from_this = 50
volume = 50
+254
View File
@@ -0,0 +1,254 @@
/obj/structure/reagent_dispensers
name = "Dispenser"
desc = "..."
icon = 'icons/obj/objects.dmi'
icon_state = "water"
density = TRUE
anchored = FALSE
pressure_resistance = 2*ONE_ATMOSPHERE
max_integrity = 300
var/tank_volume = 1000 //In units, how much the dispenser can hold
var/reagent_id = "water" //The ID of the reagent that the dispenser uses
/obj/structure/reagent_dispensers/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
. = ..()
if(. && obj_integrity > 0)
if(tank_volume && (damage_flag == "bullet" || damage_flag == "laser"))
boom()
/obj/structure/reagent_dispensers/attackby(obj/item/W, mob/user, params)
if(W.is_refillable())
return 0 //so we can refill them via their afterattack.
else
return ..()
/obj/structure/reagent_dispensers/Initialize()
create_reagents(tank_volume, DRAINABLE | AMOUNT_VISIBLE)
reagents.add_reagent(reagent_id, tank_volume)
. = ..()
/obj/structure/reagent_dispensers/proc/boom()
visible_message("<span class='danger'>\The [src] ruptures!</span>")
chem_splash(loc, 5, list(reagents))
qdel(src)
/obj/structure/reagent_dispensers/deconstruct(disassembled = TRUE)
if(!(flags_1 & NODECONSTRUCT_1))
if(!disassembled)
boom()
else
qdel(src)
///////////////
//Water Tanks//
///////////////
/obj/structure/reagent_dispensers/watertank
name = "water tank"
desc = "A water tank."
icon_state = "water"
/obj/structure/reagent_dispensers/watertank/high
name = "high-capacity water tank"
desc = "A highly pressurized water tank made to hold gargantuan amounts of water."
icon_state = "water_high" //I was gonna clean my room...
tank_volume = 100000
/obj/structure/reagent_dispensers/foamtank
name = "firefighting foam tank"
desc = "A tank full of firefighting foam."
icon_state = "foam"
reagent_id = "firefighting_foam"
tank_volume = 500
/obj/structure/reagent_dispensers/water_cooler
name = "liquid cooler"
desc = "A machine that dispenses liquid to drink."
icon = 'icons/obj/vending.dmi'
icon_state = "water_cooler"
anchored = TRUE
tank_volume = 500
var/paper_cups = 25 //Paper cups left from the cooler
/obj/structure/reagent_dispensers/water_cooler/examine(mob/user)
..()
if (paper_cups > 1)
to_chat(user, "There are [paper_cups] paper cups left.")
else if (paper_cups == 1)
to_chat(user, "There is one paper cup left.")
else
to_chat(user, "There are no paper cups left.")
/obj/structure/reagent_dispensers/water_cooler/attack_hand(mob/living/user)
. = ..()
if(.)
return
if(!paper_cups)
to_chat(user, "<span class='warning'>There aren't any cups left!</span>")
return
user.visible_message("<span class='notice'>[user] takes a cup from [src].</span>", "<span class='notice'>You take a paper cup from [src].</span>")
var/obj/item/reagent_containers/food/drinks/sillycup/S = new(get_turf(src))
user.put_in_hands(S)
paper_cups--
//////////////
//Fuel Tanks//
//////////////
/obj/structure/reagent_dispensers/fueltank
name = "fuel tank"
desc = "A tank full of industrial welding fuel. Do not consume."
icon_state = "fuel"
reagent_id = "welding_fuel"
/obj/structure/reagent_dispensers/fueltank/high //Unused - Good for ghost roles
name = "high-capacity fuel tank"
desc = "A now illegal tank, full of highly pressurized industrial welding fuel. Do not consume or have a open flame close to this tank."
icon_state = "fuel_high"
tank_volume = 3000
/obj/structure/reagent_dispensers/fueltank/boom()
explosion(get_turf(src), 0, 1, 5, flame_range = 5)
qdel(src)
/obj/structure/reagent_dispensers/fueltank/blob_act(obj/structure/blob/B)
boom()
/obj/structure/reagent_dispensers/fueltank/ex_act()
boom()
/obj/structure/reagent_dispensers/fueltank/fire_act(exposed_temperature, exposed_volume)
boom()
/obj/structure/reagent_dispensers/fueltank/tesla_act()
..() //extend the zap
boom()
/obj/structure/reagent_dispensers/fueltank/bullet_act(obj/item/projectile/P)
..()
if(!QDELETED(src)) //wasn't deleted by the projectile's effects.
if(!P.nodamage && ((P.damage_type == BURN) || (P.damage_type == BRUTE)))
var/boom_message = "[ADMIN_LOOKUPFLW(P.firer)] triggered a fueltank explosion via projectile."
GLOB.bombers += boom_message
message_admins(boom_message)
P.firer.log_message("triggered a fueltank explosion via projectile.", LOG_ATTACK)
boom()
/obj/structure/reagent_dispensers/fueltank/attackby(obj/item/I, mob/living/user, params)
if(istype(I, /obj/item/weldingtool))
if(!reagents.has_reagent("welding_fuel"))
to_chat(user, "<span class='warning'>[src] is out of fuel!</span>")
return
var/obj/item/weldingtool/W = I
if(!W.welding)
if(W.reagents.has_reagent("welding_fuel", W.max_fuel))
to_chat(user, "<span class='warning'>Your [W.name] is already full!</span>")
return
reagents.trans_to(W, W.max_fuel)
user.visible_message("<span class='notice'>[user] refills [user.p_their()] [W.name].</span>", "<span class='notice'>You refill [W].</span>")
playsound(src, 'sound/effects/refill.ogg', 50, 1)
W.update_icon()
else
var/turf/T = get_turf(src)
user.visible_message("<span class='warning'>[user] catastrophically fails at refilling [user.p_their()] [W.name]!</span>", "<span class='userdanger'>That was stupid of you.</span>")
var/message_admins = "[ADMIN_LOOKUPFLW(user)] triggered a fueltank explosion via welding tool at [ADMIN_VERBOSEJMP(T)]."
GLOB.bombers += message_admins
message_admins(message_admins)
user.log_message("triggered a fueltank explosion via welding tool.", LOG_ATTACK)
boom()
return
return ..()
///////////////////
//Misc Dispenders//
///////////////////
/obj/structure/reagent_dispensers/peppertank
name = "pepper spray refiller"
desc = "Contains condensed capsaicin for use in law \"enforcement.\""
icon_state = "pepper"
anchored = TRUE
density = FALSE
reagent_id = "condensedcapsaicin"
/obj/structure/reagent_dispensers/peppertank/Initialize()
. = ..()
if(prob(1))
desc = "IT'S PEPPER TIME, BITCH!"
/obj/structure/reagent_dispensers/virusfood
name = "virus food dispenser"
desc = "A dispenser of low-potency virus mutagenic."
icon_state = "virus_food"
anchored = TRUE
density = FALSE
reagent_id = "virusfood"
/obj/structure/reagent_dispensers/cooking_oil
name = "vat of cooking oil"
desc = "A huge metal vat with a tap on the front. Filled with cooking oil for use in frying food."
icon_state = "vat"
anchored = TRUE
reagent_id = "cooking_oil"
////////
//Kegs//
////////
/obj/structure/reagent_dispensers/beerkeg
name = "beer keg"
desc = "Beer is liquid bread, it's good for you..."
icon_state = "beer"
reagent_id = "beer"
/obj/structure/reagent_dispensers/beerkeg/blob_act(obj/structure/blob/B)
explosion(src.loc,0,3,5,7,10)
if(!QDELETED(src))
qdel(src)
/obj/structure/reagent_dispensers/keg
name = "keg"
desc = "A keg."
icon = 'modular_citadel/icons/obj/objects.dmi'
icon_state = "keg"
reagent_id = "water"
/obj/structure/reagent_dispensers/keg/mead
name = "keg of mead"
desc = "A keg of mead."
icon_state = "orangekeg"
reagent_id = "mead"
/obj/structure/reagent_dispensers/keg/aphro
name = "keg of aphrodisiac"
desc = "A keg of aphrodisiac."
icon_state = "pinkkeg"
reagent_id = "aphro"
tank_volume = 150
/obj/structure/reagent_dispensers/keg/aphro/strong
name = "keg of strong aphrodisiac"
desc = "A keg of strong and addictive aphrodisiac."
reagent_id = "aphro+"
tank_volume = 120
/obj/structure/reagent_dispensers/keg/milk
name = "keg of milk"
desc = "It's not quite what you were hoping for."
icon_state = "whitekeg"
reagent_id = "milk"
/obj/structure/reagent_dispensers/keg/semen
name = "keg of semen"
desc = "Dear lord, where did this even come from?"
icon_state = "whitekeg"
reagent_id = "semen"
/obj/structure/reagent_dispensers/keg/gargle
name = "keg of pan galactic gargleblaster"
desc = "A keg of... wow that's a long name."
icon_state = "bluekeg"
reagent_id = "gargleblaster"
tank_volume = 100