mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-22 04:22:39 +01:00
For a robust crafting system, I need a new materials framework. For a new materials framework, I need to clean up reagents. To clean up reagents, I need to pare down foods from reagent holders. To pare down foods from reagent holders, I need to port edibility components. To port edibility components, I need to port processing components. To port processing components, I need to port tool behaviors. This is all back-end code, no new features or functionality from this.
645 lines
21 KiB
Plaintext
645 lines
21 KiB
Plaintext
// Update asset_cache.dm if you change these.
|
|
#define BOTTLE_SPRITES list("bottle-1", "bottle-2", "bottle-3", "bottle-4") //list of available bottle sprites
|
|
|
|
#define CHEMMASTER_BOTTLE_SOUND playsound(src, 'sound/items/pickup/bottle.ogg', 75, 1)
|
|
#define CHEMMASTER_DISPENSE_SOUND playsound(src, 'sound/machines/reagent_dispense.ogg', 75, 1)
|
|
#define CHEMMASTER_CHANGESETTINGS_SOUND playsound(src, 'sound/machines/slide_change.ogg', 75, 1)
|
|
#define CHEMMASTER_SWITCH_SOUND playsound(src, 'sound/machines/switch1.ogg', 75, 1)
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
/obj/machinery/chem_master
|
|
name = "ChemMaster 3000"
|
|
density = 1
|
|
anchored = 1
|
|
icon = 'icons/obj/chemical.dmi'
|
|
icon_state = "mixer0"
|
|
use_power = POWER_USE_IDLE
|
|
idle_power_usage = 20
|
|
layer = BELOW_OBJ_LAYER
|
|
clicksound = SFX_BUTTON
|
|
|
|
var/obj/item/reagent_containers/glass/beaker = null
|
|
var/obj/item/storage/pill_bottle/loaded_pill_bottle = null
|
|
var/mode = TRUE
|
|
var/condi = 0
|
|
var/useramount = 30 // Last used amount
|
|
var/pillamount = 10
|
|
var/bottlesprite = "bottle-1" //yes, strings
|
|
var/pillsprite = "pill1"
|
|
var/max_pill_count = 20
|
|
atom_flags = ATOM_FLAG_OPEN_CONTAINER
|
|
var/datum/asset/spritesheet/chem_master/chem_asset
|
|
var/list/forbidden_containers = list(/obj/item/reagent_containers/glass/bucket) //For containers we don't want people to shove into the chem machine. Like big-ass buckets.
|
|
var/datum/tgui/ui = null
|
|
var/list/analysis = list()
|
|
|
|
/obj/machinery/chem_master/Initialize()
|
|
. = ..()
|
|
create_reagents(300)
|
|
|
|
/obj/machinery/chem_master/ex_act(severity)
|
|
switch(severity)
|
|
if(1.0)
|
|
qdel(src)
|
|
return
|
|
if(2.0)
|
|
if (prob(50))
|
|
qdel(src)
|
|
return
|
|
|
|
/obj/machinery/chem_master/proc/eject()
|
|
if(beaker && usr)
|
|
if(!use_check_and_message(usr))
|
|
usr.put_in_hands(beaker, TRUE)
|
|
else
|
|
beaker.loc = get_turf(src)
|
|
beaker = null
|
|
reagents.clear_reagents()
|
|
icon_state = "mixer0"
|
|
return TRUE
|
|
|
|
/obj/machinery/chem_master/AltClick()
|
|
if(!use_check_and_message(usr))
|
|
eject()
|
|
|
|
/obj/machinery/chem_master/attackby(obj/item/attacking_item, mob/user)
|
|
|
|
if(istype(attacking_item, /obj/item/reagent_containers/glass))
|
|
|
|
if(src.beaker)
|
|
to_chat(user, SPAN_WARNING("A beaker is already loaded into the machine."))
|
|
return
|
|
if(is_type_in_list(attacking_item, forbidden_containers))
|
|
to_chat(user, SPAN_WARNING("There's no way to fit [attacking_item] into \the [src]!"))
|
|
return
|
|
src.beaker = attacking_item
|
|
user.drop_from_inventory(attacking_item, src)
|
|
to_chat(user, "You add the beaker to the machine!")
|
|
src.updateUsrDialog()
|
|
icon_state = "mixer1"
|
|
CHEMMASTER_BOTTLE_SOUND
|
|
|
|
else if(istype(attacking_item, /obj/item/storage/pill_bottle))
|
|
if(condi)
|
|
return
|
|
if(src.loaded_pill_bottle)
|
|
to_chat(user, "A pill bottle is already loaded into the machine.")
|
|
return
|
|
|
|
src.loaded_pill_bottle = attacking_item
|
|
user.drop_from_inventory(attacking_item, src)
|
|
to_chat(user, "You add the pill bottle into the dispenser slot!")
|
|
src.updateUsrDialog()
|
|
else if(attacking_item.tool_behaviour == TOOL_WRENCH)
|
|
anchored = !anchored
|
|
to_chat(user, "You [anchored ? "attach" : "detach"] the [src] [anchored ? "to" : "from"] the ground")
|
|
attacking_item.play_tool_sound(get_turf(src), 75)
|
|
|
|
if(ui?.user)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
|
|
|
|
/obj/machinery/chem_master/ui_interact(mob/user, datum/tgui/ui)
|
|
ui = SStgui.try_update_ui(user, src, ui)
|
|
if(!ui)
|
|
ui = new(user, src, "ChemMaster")
|
|
ui.open()
|
|
|
|
/obj/machinery/chem_master/ui_data(mob/user)
|
|
var/list/data = list()
|
|
|
|
var/list/reagents_in_internal_storage = list()
|
|
var/list/reagents_in_beaker = list()
|
|
|
|
data["mode"] = src.mode
|
|
data["loaded_beaker"] = !isnull(src.beaker)
|
|
data["loaded_pill_bottle"] = !isnull(src.loaded_pill_bottle)
|
|
data["current_bottle_icon"] = bottlesprite
|
|
data["current_pill_icon"] = pillsprite
|
|
data["analysis"] = analysis
|
|
|
|
|
|
// Process the beaker
|
|
if(beaker)
|
|
var/datum/reagents/beaker_reagents = beaker.reagents
|
|
for(var/reagent in beaker_reagents.reagent_volumes)
|
|
|
|
var/singleton/reagent/reagent_singleton = GET_SINGLETON(reagent)
|
|
reagents_in_beaker += list(list("name" = reagent_singleton.name, "volume" = REAGENT_VOLUME(beaker_reagents, reagent), "typepath" = reagent_singleton.type))
|
|
|
|
data["reagents_in_beaker"] = reagents_in_beaker
|
|
|
|
//Process the machine content
|
|
for(var/reagent in src.reagents.reagent_volumes)
|
|
var/singleton/reagent/reagent_singleton = GET_SINGLETON(reagent)
|
|
reagents_in_internal_storage += list(list("name" = reagent_singleton.name, "volume" = REAGENT_VOLUME(reagents, reagent), "typepath" = reagent_singleton.type))
|
|
data["reagents_in_internal_storage"] = reagents_in_internal_storage
|
|
|
|
|
|
return data
|
|
|
|
/obj/machinery/chem_master/LateInitialize()
|
|
. = ..()
|
|
if(!chem_asset)
|
|
chem_asset = get_asset_datum(/datum/asset/spritesheet/chem_master)
|
|
|
|
/obj/machinery/chem_master/ui_assets(mob/user)
|
|
return list(
|
|
get_asset_datum(/datum/asset/spritesheet/chem_master)
|
|
)
|
|
|
|
/obj/machinery/chem_master/ui_static_data(mob/user)
|
|
. = ..()
|
|
var/list/data = list()
|
|
|
|
var/list/bottle_icons = list()
|
|
var/list/pill_icons = list()
|
|
|
|
if(!chem_asset)
|
|
chem_asset = get_asset_datum(/datum/asset/spritesheet/chem_master)
|
|
|
|
for(var/sprite in BOTTLE_SPRITES)
|
|
bottle_icons += chem_asset.icon_tag(sprite, FALSE)
|
|
|
|
for(var/i = 1 to MAX_PILL_SPRITE)
|
|
var/pillicon = "pill[i]"
|
|
pill_icons += chem_asset.icon_tag(pillicon, FALSE)
|
|
|
|
data["bottle_icons"] = bottle_icons
|
|
data["pill_icons"] = pill_icons
|
|
data["machine_name"] = name
|
|
data["is_condimaster"] = condi
|
|
|
|
|
|
return data
|
|
|
|
|
|
/obj/machinery/chem_master/ui_act(action, params)
|
|
. = ..()
|
|
|
|
if(.)
|
|
return
|
|
|
|
playsound(src, 'sound/machines/button3.ogg', 75, 1) //Buttons clicky
|
|
|
|
if(action == "ejectp")
|
|
if(loaded_pill_bottle)
|
|
if(Adjacent(usr))
|
|
usr.put_in_hands(loaded_pill_bottle)
|
|
else
|
|
loaded_pill_bottle.forceMove(get_turf(src))
|
|
loaded_pill_bottle = null
|
|
return TRUE
|
|
|
|
else if(action == "close")
|
|
ui.ui_close()
|
|
return TRUE
|
|
|
|
// These actions makes sense only if there's a beaker in
|
|
if(beaker)
|
|
if(action == "analyze")
|
|
var/datum/reagents/R = beaker.reagents
|
|
if(!condi)
|
|
if(params["name"] == "Blood")
|
|
var/singleton/reagent/blood/G = GET_SINGLETON(/singleton/reagent/blood)
|
|
var/Gdata = REAGENT_DATA(R, /singleton/reagent/blood)
|
|
analysis["name"] = G.name
|
|
analysis["type"] = Gdata["blood_type"]
|
|
analysis["DNA"] = Gdata["blood_DNA"]
|
|
else if(params["name"] == "Close")
|
|
analysis = list()
|
|
CHEMMASTER_SWITCH_SOUND
|
|
return TRUE
|
|
|
|
else if(action == "add")
|
|
if(params["amount"])
|
|
var/rtype = text2path(params["add"])
|
|
var/amount = clamp((text2num(params["amount"])), 0, 200)
|
|
beaker.reagents.trans_type_to(src, rtype, amount)
|
|
return TRUE
|
|
|
|
else if (action == "remove")
|
|
if(params["amount"])
|
|
var/rtype = text2path(params["remove"])
|
|
var/amount = clamp((text2num(params["amount"])), 0, 200)
|
|
if(mode)
|
|
reagents.trans_type_to(beaker, rtype, amount)
|
|
else
|
|
reagents.remove_reagent(rtype, amount)
|
|
return TRUE
|
|
|
|
else if (action == "eject")
|
|
if(eject())
|
|
return TRUE
|
|
|
|
if (action == "toggle")
|
|
mode = !mode
|
|
CHEMMASTER_CHANGESETTINGS_SOUND
|
|
return TRUE
|
|
|
|
else if(action == "createbottle")
|
|
if(!condi)
|
|
var/name = sanitizeSafe(input(usr,"Name:","Name your bottle!",reagents.get_primary_reagent_name()), MAX_NAME_LEN)
|
|
var/obj/item/reagent_containers/glass/bottle/P = new/obj/item/reagent_containers/glass/bottle(get_turf(src))
|
|
if(!name) name = reagents.get_primary_reagent_name()
|
|
P.name = "[name] bottle"
|
|
P.pixel_x = rand(-7, 7) //random position
|
|
P.pixel_y = rand(-7, 7)
|
|
P.icon_state = bottlesprite
|
|
reagents.trans_to_obj(P,60)
|
|
P.update_icon()
|
|
else
|
|
var/obj/item/reagent_containers/food/condiment/P = new/obj/item/reagent_containers/food/condiment(get_turf(src))
|
|
reagents.trans_to_obj(P,50)
|
|
CHEMMASTER_BOTTLE_SOUND
|
|
return TRUE
|
|
|
|
else if (action == "createpill" || action == "createpill_multiple")
|
|
var/count = 1
|
|
|
|
if(reagents.total_volume/count < 1) //Sanity checking.
|
|
return TRUE
|
|
|
|
if (action == "createpill_multiple")
|
|
count = tgui_input_number(usr, "Select the number of pills to make.", src.name, pillamount, max_pill_count, 1)
|
|
count = clamp(count, 1, max_pill_count)
|
|
|
|
if(reagents.total_volume/count < 1) //Sanity checking.
|
|
return TRUE
|
|
|
|
var/amount_per_pill = reagents.total_volume/count
|
|
if (amount_per_pill > 60) amount_per_pill = 60
|
|
|
|
var/name = tgui_input_text(usr, "Name your pill.", src.name, "[reagents.get_primary_reagent_name()] ([amount_per_pill] units)", MAX_NAME_LEN)
|
|
|
|
if(reagents.total_volume/count < 1) //Sanity checking.
|
|
return TRUE
|
|
while (count-- && count >= 0)
|
|
var/obj/item/reagent_containers/pill/P = new/obj/item/reagent_containers/pill(get_turf(src))
|
|
if(!name) name = reagents.get_primary_reagent_name()
|
|
P.name = "[name] pill"
|
|
P.pixel_x = rand(-7, 7) //random position
|
|
P.pixel_y = rand(-7, 7)
|
|
P.icon_state = pillsprite
|
|
reagents.trans_to_obj(P,amount_per_pill)
|
|
if(src.loaded_pill_bottle)
|
|
loaded_pill_bottle.insert_into_storage(P)
|
|
CHEMMASTER_DISPENSE_SOUND
|
|
return TRUE
|
|
|
|
else if(action == "pill_sprite")
|
|
pillsprite = sanitizeSafe(params["pill_sprite"])
|
|
CHEMMASTER_CHANGESETTINGS_SOUND
|
|
return TRUE
|
|
|
|
else if(action == "bottle_sprite")
|
|
bottlesprite = sanitizeSafe(params["bottle_sprite"])
|
|
CHEMMASTER_CHANGESETTINGS_SOUND
|
|
return TRUE
|
|
return TRUE
|
|
|
|
/obj/machinery/chem_master/ui_status(mob/user, datum/ui_state/state)
|
|
if(!operable())
|
|
return UI_DISABLED
|
|
|
|
. = ..()
|
|
|
|
|
|
/obj/machinery/chem_master/Topic(href, href_list)
|
|
if(..())
|
|
return 1
|
|
return
|
|
|
|
/obj/machinery/chem_master/attack_ai(mob/user as mob)
|
|
if(!ai_can_interact(user))
|
|
return
|
|
return src.attack_hand(user)
|
|
|
|
/obj/machinery/chem_master/attack_hand(mob/user as mob)
|
|
if(!operable())
|
|
return
|
|
user.set_machine(src)
|
|
ui_interact(user)
|
|
|
|
/obj/machinery/chem_master/condimaster
|
|
name = "CondiMaster 3000"
|
|
condi = 1
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////
|
|
/obj/machinery/reagentgrinder
|
|
|
|
name = "All-In-One Grinder"
|
|
icon = 'icons/obj/machinery/cooking_machines.dmi'
|
|
icon_state = "juicer1"
|
|
layer = BELOW_OBJ_LAYER
|
|
density = 0
|
|
anchored = 0
|
|
use_power = POWER_USE_IDLE
|
|
idle_power_usage = 5
|
|
active_power_usage = 100
|
|
var/inuse = 0
|
|
var/obj/item/reagent_containers/beaker = null
|
|
var/limit = 10
|
|
var/list/holdingitems = list()
|
|
var/list/sheet_reagents = list( //have a number of reagents which is a factor of REAGENTS_PER_SHEET (default 20) unless you like decimals
|
|
/obj/item/stack/material/iron = list(/singleton/reagent/iron),
|
|
/obj/item/stack/material/uranium = list(/singleton/reagent/uranium),
|
|
/obj/item/stack/material/phoron = list(/singleton/reagent/toxin/phoron),
|
|
/obj/item/stack/material/gold = list(/singleton/reagent/gold),
|
|
/obj/item/stack/material/silver = list(/singleton/reagent/silver),
|
|
/obj/item/stack/material/platinum = list(/singleton/reagent/platinum),
|
|
/obj/item/stack/material/mhydrogen = list(/singleton/reagent/hydrazine), // i guess
|
|
/obj/item/stack/material/steel = list(/singleton/reagent/iron, /singleton/reagent/carbon),
|
|
/obj/item/stack/material/plasteel = list(/singleton/reagent/iron, /singleton/reagent/iron, /singleton/reagent/carbon, /singleton/reagent/carbon, /singleton/reagent/platinum), //8 iron, 8 carbon, 4 platinum,
|
|
/obj/item/stack/material/sandstone = list(/singleton/reagent/silicon, /singleton/reagent/acetone),
|
|
/obj/item/stack/material/glass = list(/singleton/reagent/silicate),
|
|
/obj/item/stack/material/glass/phoronglass = list(/singleton/reagent/platinum, /singleton/reagent/silicate, /singleton/reagent/silicate, /singleton/reagent/silicate), //5 platinum, 15 silicate,
|
|
)
|
|
var/list/beaker_types = list( // also can't be ground
|
|
/obj/item/reagent_containers/glass,
|
|
/obj/item/reagent_containers/food/drinks/drinkingglass,
|
|
/obj/item/reagent_containers/food/drinks/shaker,
|
|
/obj/item/reagent_containers/cooking_container
|
|
)
|
|
|
|
/obj/machinery/reagentgrinder/Initialize()
|
|
. = ..()
|
|
beaker = new /obj/item/reagent_containers/glass/beaker/large(src)
|
|
|
|
/obj/machinery/reagentgrinder/update_icon()
|
|
icon_state = "juicer"+num2text(!isnull(beaker))
|
|
return
|
|
|
|
/obj/machinery/reagentgrinder/attackby(obj/item/attacking_item, mob/user)
|
|
if (is_type_in_list(attacking_item, beaker_types))
|
|
if (beaker)
|
|
return 1
|
|
else
|
|
src.beaker = attacking_item
|
|
user.drop_from_inventory(attacking_item,src)
|
|
update_icon()
|
|
src.updateUsrDialog()
|
|
return 0
|
|
|
|
if(holdingitems && holdingitems.len >= limit)
|
|
to_chat(usr, "The machine cannot hold anymore items.")
|
|
return 1
|
|
|
|
if(!istype(attacking_item))
|
|
return
|
|
|
|
if(istype(attacking_item,/obj/item/storage/bag/plants) || istype(attacking_item,/obj/item/storage/pill_bottle))
|
|
var/failed = 1
|
|
var/obj/item/storage/P = attacking_item
|
|
for(var/obj/item/G in P.contents)
|
|
if(!G.reagents || !G.reagents.total_volume)
|
|
continue
|
|
failed = 0
|
|
P.remove_from_storage(G,src)
|
|
holdingitems += G
|
|
if(holdingitems && holdingitems.len >= limit)
|
|
break
|
|
|
|
if(failed)
|
|
to_chat(user, "Nothing in the plant bag is usable.")
|
|
return 1
|
|
|
|
if(!attacking_item.contents.len)
|
|
to_chat(user, "You empty \the [attacking_item] into \the [src].")
|
|
else
|
|
to_chat(user, "You fill \the [src] from \the [attacking_item].")
|
|
|
|
src.updateUsrDialog()
|
|
return 0
|
|
|
|
if(!sheet_reagents[attacking_item.type] && (!attacking_item.reagents || !attacking_item.reagents.total_volume))
|
|
to_chat(user, "\The [attacking_item] is not suitable for blending.")
|
|
return 0
|
|
|
|
user.remove_from_mob(attacking_item)
|
|
attacking_item.forceMove(src)
|
|
holdingitems += attacking_item
|
|
src.updateUsrDialog()
|
|
return 0
|
|
|
|
/obj/machinery/reagentgrinder/attack_ai(mob/user as mob)
|
|
if(!ai_can_interact(user))
|
|
return
|
|
interact(user)
|
|
|
|
/obj/machinery/reagentgrinder/attack_hand(mob/user as mob)
|
|
interact(user)
|
|
|
|
/obj/machinery/reagentgrinder/interact(mob/user as mob) // The microwave Menu
|
|
if(!operable())
|
|
return
|
|
user.set_machine(src)
|
|
var/is_chamber_empty = 0
|
|
var/is_beaker_ready = 0
|
|
var/processing_chamber = ""
|
|
var/beaker_contents = ""
|
|
var/dat = ""
|
|
|
|
if(!inuse)
|
|
for (var/obj/item/O in holdingitems)
|
|
processing_chamber += "\A [O.name]<BR>"
|
|
|
|
if (!processing_chamber)
|
|
is_chamber_empty = 1
|
|
processing_chamber = "Nothing."
|
|
if (!beaker)
|
|
beaker_contents = "<B>No beaker attached.</B><br>"
|
|
else
|
|
is_beaker_ready = 1
|
|
beaker_contents = "<B>The beaker contains:</B><br>"
|
|
if(!LAZYLEN(beaker.reagents.reagent_volumes))
|
|
beaker_contents += "Nothing<br>"
|
|
else
|
|
for(var/_R in beaker.reagents.reagent_volumes)
|
|
var/singleton/reagent/R = GET_SINGLETON(_R)
|
|
beaker_contents += "[beaker.reagents.reagent_volumes[_R]] - [R.name]<br>"
|
|
|
|
dat = {"
|
|
<b>Processing Chamber contains:</b><br>
|
|
[processing_chamber]<br>
|
|
[beaker_contents]<hr>
|
|
"}
|
|
if (is_beaker_ready && !is_chamber_empty && !(stat & (NOPOWER|BROKEN)))
|
|
dat += "<A href='byond://?src=[REF(src)];action=grind'>Process the reagents</a><BR>"
|
|
if(holdingitems && holdingitems.len > 0)
|
|
dat += "<A href='byond://?src=[REF(src)];action=eject'>Eject the reagents</a><BR>"
|
|
if (beaker)
|
|
dat += "<A href='byond://?src=[REF(src)];action=detach'>Detach the beaker</a><BR>"
|
|
else
|
|
dat += "Please wait..."
|
|
|
|
var/datum/browser/grindr_win = new(user, "reagentgrinder", capitalize_first_letters(name))
|
|
grindr_win.set_content(dat)
|
|
grindr_win.open()
|
|
|
|
/obj/machinery/reagentgrinder/Topic(href, href_list)
|
|
if(..())
|
|
return 1
|
|
|
|
switch(href_list["action"])
|
|
if ("grind")
|
|
grind(usr)
|
|
if("eject")
|
|
eject()
|
|
if ("detach")
|
|
detach(usr)
|
|
src.updateUsrDialog()
|
|
return 1
|
|
|
|
/obj/machinery/reagentgrinder/proc/detach(var/mob/user)
|
|
if(!beaker)
|
|
return
|
|
|
|
if(use_check_and_message(user))
|
|
return
|
|
|
|
if(ishuman(user))
|
|
var/mob/living/carbon/human/H = user
|
|
if(!H.put_in_active_hand(beaker))
|
|
beaker.forceMove(get_turf(src))
|
|
else
|
|
beaker.forceMove(get_turf(src))
|
|
beaker = null
|
|
update_icon()
|
|
|
|
/obj/machinery/reagentgrinder/proc/eject()
|
|
|
|
if (usr.stat != 0)
|
|
return
|
|
if (!holdingitems || holdingitems.len == 0)
|
|
return
|
|
|
|
for(var/obj/item/O in holdingitems)
|
|
O.forceMove(get_turf(src))
|
|
holdingitems -= O
|
|
holdingitems.Cut()
|
|
|
|
/obj/machinery/reagentgrinder/proc/grind(mob/user)
|
|
|
|
power_change()
|
|
if(stat & (NOPOWER|BROKEN))
|
|
return
|
|
|
|
// Sanity check.
|
|
if(!beaker || (beaker && beaker.reagents.total_volume >= beaker.reagents.maximum_volume))
|
|
return
|
|
|
|
if(ishuman(user))
|
|
do_hair_pull(user)
|
|
|
|
playsound(get_turf(src), 'sound/machines/blender.ogg', 50, 1)
|
|
intent_message(MACHINE_SOUND)
|
|
inuse = TRUE
|
|
|
|
// Reset the machine.
|
|
addtimer(CALLBACK(src, PROC_REF(grind_reset)), 60)
|
|
|
|
// Process.
|
|
for (var/obj/item/O in holdingitems)
|
|
|
|
var/remaining_volume = beaker.reagents.maximum_volume - beaker.reagents.total_volume
|
|
if(remaining_volume <= 0)
|
|
break
|
|
|
|
if(sheet_reagents[O.type])
|
|
var/obj/item/stack/stack = O
|
|
if(istype(stack))
|
|
var/list/sheet_components = sheet_reagents[stack.type]
|
|
var/amount_to_take = max(0,min(stack.amount,round(remaining_volume/REAGENTS_PER_SHEET)))
|
|
if(amount_to_take)
|
|
stack.use(amount_to_take)
|
|
if(QDELETED(stack))
|
|
holdingitems -= stack
|
|
if(islist(sheet_components))
|
|
amount_to_take = (amount_to_take/(sheet_components.len))
|
|
for(var/i in sheet_components)
|
|
beaker.reagents.add_reagent(i, (amount_to_take*REAGENTS_PER_SHEET))
|
|
else
|
|
beaker.reagents.add_reagent(sheet_components, (amount_to_take*REAGENTS_PER_SHEET))
|
|
continue
|
|
|
|
if(O.reagents)
|
|
O.reagents.trans_to(beaker, min(O.reagents.total_volume, remaining_volume))
|
|
if(O.reagents.total_volume == 0)
|
|
holdingitems -= O
|
|
qdel(O)
|
|
if (beaker.reagents.total_volume >= beaker.reagents.maximum_volume)
|
|
break
|
|
|
|
/obj/machinery/reagentgrinder/proc/grind_reset()
|
|
inuse = FALSE
|
|
updateUsrDialog()
|
|
|
|
|
|
/obj/machinery/reagentgrinder/mouse_drop_receive(atom/dropped, mob/user, params)
|
|
var/mob/living/carbon/human/target = dropped
|
|
if (!istype(target) || target.buckled_to || get_dist(user, src) > 1 || get_dist(user, target) > 1 || user.stat || istype(user, /mob/living/silicon/ai))
|
|
return
|
|
if(target == user)
|
|
if(target.h_style == "Floorlength Braid" || target.h_style == "Very Long Hair")
|
|
user.visible_message(SPAN_NOTICE("[user] looks like they're about to feed their own hair into the [src], but think better of it."),
|
|
SPAN_NOTICE("You grasp your hair and are about to feed it into the [src], but stop and come to your sense."))
|
|
return
|
|
src.add_fingerprint(user)
|
|
var/target_loc = target.loc
|
|
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
|
|
if(target.h_style != "Cut Hair" || target.h_style != "Short Hair" || target.h_style != "Skinhead" || target.h_style != "Buzzcut" || target.h_style != "Crewcut" || target.h_style != "Bald" || target.h_style != "Balding Hair")
|
|
user.visible_message(SPAN_WARNING("[user] starts feeding [target]'s hair into the [src]!"),
|
|
SPAN_WARNING("You start feeding [target]'s hair into the [src]!"))
|
|
if(!do_after(usr, 50))
|
|
return
|
|
if(target_loc != target.loc)
|
|
return
|
|
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
|
|
user.visible_message(SPAN_WARNING("[user] feeds the [target]'s hair into the [src] and flicks it on!"),
|
|
SPAN_WARNING("You turn the [src] on!"))
|
|
target.apply_damage(30, DAMAGE_BRUTE, BP_HEAD)
|
|
target.apply_damage(25, DAMAGE_PAIN)
|
|
target.say("*scream")
|
|
|
|
user.attack_log += "\[[time_stamp()]\] <span class='warning'>Has fed [target.name]'s ([target.ckey]) hair into a [src].</span>"
|
|
target.attack_log += "\[[time_stamp()]\] <font color='orange'>Has had their hair fed into [src] by [user.name] ([user.ckey])</font>"
|
|
msg_admin_attack("[key_name_admin(user)] fed [key_name_admin(target)] in a [src]. (<A href='byond://?_src_=holder;adminplayerobservecoodjump=1;X=[user.x];Y=[user.y];Z=[user.z]'>JMP</a>)",ckey=key_name(user),ckey_target=key_name(target))
|
|
else
|
|
return
|
|
if(!do_after(usr, 35))
|
|
return
|
|
if(target_loc != target.loc)
|
|
return
|
|
if(target != user && !user.restrained() && !user.stat && !user.weakened && !user.stunned && !user.paralysis)
|
|
user.visible_message(SPAN_WARNING("[user] starts tugging on [target]'s head as the [src] keeps running!"),
|
|
SPAN_WARNING("You start tugging on [target]'s head!"))
|
|
target.apply_damage(25, DAMAGE_BRUTE, BP_HEAD)
|
|
target.apply_damage(10, DAMAGE_PAIN)
|
|
target.say("*scream")
|
|
spawn(10)
|
|
user.visible_message(SPAN_WARNING("[user] stops the [src] and leaves [target] resting as they are."),
|
|
SPAN_WARNING("You turn the [src] off and let go of [target]."))
|
|
|
|
/obj/machinery/reagentgrinder/verb/Eject()
|
|
set src in oview(1)
|
|
set category = "Object"
|
|
set name = "Eject contents"
|
|
|
|
if(use_check_and_message(usr))
|
|
return
|
|
usr.visible_message(
|
|
SPAN_NOTICE("[usr] opens [src] and has removed [english_list(holdingitems)].")
|
|
)
|
|
|
|
eject()
|
|
detach()
|
|
|
|
#undef CHEMMASTER_DISPENSE_SOUND
|
|
#undef CHEMMASTER_CHANGESETTINGS_SOUND
|
|
#undef CHEMMASTER_SWITCH_SOUND
|
|
#undef CHEMMASTER_BOTTLE_SOUND
|