mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-21 20:11:04 +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.
294 lines
10 KiB
Plaintext
294 lines
10 KiB
Plaintext
/obj/item/storage/box/bloodpacks
|
|
name = "\improper IV bags"
|
|
desc = "This box contains IV bags."
|
|
illustration = "blood"
|
|
|
|
/obj/item/storage/box/bloodpacks/fill()
|
|
..()
|
|
new /obj/item/reagent_containers/blood/empty(src)
|
|
new /obj/item/reagent_containers/blood/empty(src)
|
|
new /obj/item/reagent_containers/blood/empty(src)
|
|
new /obj/item/reagent_containers/blood/empty(src)
|
|
new /obj/item/reagent_containers/blood/empty(src)
|
|
new /obj/item/reagent_containers/blood/empty(src)
|
|
new /obj/item/reagent_containers/blood/empty(src)
|
|
|
|
/obj/item/reagent_containers/blood
|
|
name = "\improper IV bag"
|
|
desc = "Contains fluids used for transfusions."
|
|
icon = 'icons/obj/bloodpack.dmi'
|
|
icon_state = "bloodpack"
|
|
filling_states = "-10;10;25;50;75;80;100"
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
volume = 200
|
|
|
|
amount_per_transfer_from_this = 0.2
|
|
possible_transfer_amounts = list(0.2, 1, 2, 3, 4)
|
|
atom_flags = ATOM_FLAG_OPEN_CONTAINER
|
|
|
|
var/datum/weakref/attached_mob
|
|
|
|
var/blood_type = null
|
|
var/vampire_marks = null
|
|
var/being_feed = FALSE
|
|
drop_sound = 'sound/items/drop/food.ogg'
|
|
pickup_sound = 'sound/items/pickup/food.ogg'
|
|
|
|
/obj/item/reagent_containers/blood/feedback_hints(mob/user, distance, is_adjacent)
|
|
. += ..()
|
|
if (distance <= 2 && vampire_marks)
|
|
. += SPAN_WARNING("There are sharp, canine-like teeth marks on it.")
|
|
|
|
/obj/item/reagent_containers/blood/Initialize()
|
|
. = ..()
|
|
if(blood_type != null)
|
|
name = "\improper IV bag - [blood_type] blood"
|
|
reagents.add_reagent(/singleton/reagent/blood, volume, list("donor"=null,"blood_DNA"=null,"blood_type"=blood_type,"trace_chem"=null,"dose_chem"=null))
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
update_icon()
|
|
|
|
/obj/item/reagent_containers/blood/Destroy()
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
attached_mob = null
|
|
return ..()
|
|
|
|
/obj/item/reagent_containers/blood/on_reagent_change()
|
|
update_icon()
|
|
if(reagents.total_volume > volume / 2)
|
|
w_class = WEIGHT_CLASS_NORMAL
|
|
else
|
|
w_class = WEIGHT_CLASS_SMALL
|
|
|
|
/obj/item/reagent_containers/blood/update_icon()
|
|
ClearOverlays()
|
|
|
|
if(blood_type)
|
|
AddOverlays(image('icons/obj/bloodpack.dmi', "[blood_type]"))
|
|
|
|
if(attached_mob)
|
|
AddOverlays(image('icons/obj/bloodpack.dmi', "dongle"))
|
|
|
|
if(reagents && reagents.total_volume)
|
|
AddOverlays(overlay_image('icons/obj/bloodpack.dmi', "[icon_state][get_filling_state()]", color = reagents.get_color()))
|
|
|
|
/obj/item/reagent_containers/blood/attack(mob/living/target_mob, mob/living/user, target_zone)
|
|
if(user == target_mob && (MODE_VAMPIRE in user.mind?.antag_datums))
|
|
var/datum/vampire/vampire = user.mind.antag_datums[MODE_VAMPIRE]
|
|
if (being_feed)
|
|
to_chat(user, SPAN_NOTICE("You are already feeding on \the [src]."))
|
|
return
|
|
if (REAGENT_VOLUME(reagents, /singleton/reagent/blood))
|
|
user.visible_message(SPAN_WARNING("[user] raises \the [src] up to their mouth and bites into it."), SPAN_NOTICE("You raise \the [src] up to your mouth and bite into it, starting to drain its contents.<br>You need to stand still."))
|
|
being_feed = TRUE
|
|
vampire_marks = TRUE
|
|
if (!LAZYLEN(src.other_DNA))
|
|
LAZYADD(src.other_DNA, target_mob.dna.unique_enzymes)
|
|
src.other_DNA_type = "saliva"
|
|
|
|
while (do_after(user, 25, 5))
|
|
var/blood_taken = 0
|
|
blood_taken = min(5, REAGENT_VOLUME(reagents, /singleton/reagent/blood)/4)
|
|
|
|
reagents.remove_reagent(/singleton/reagent/blood, blood_taken*4)
|
|
vampire.blood_usable += blood_taken
|
|
|
|
if (blood_taken)
|
|
to_chat(user, SPAN_NOTICE("You have accumulated [vampire.blood_usable] unit\s of usable blood. It tastes quite stale."))
|
|
|
|
if (REAGENT_VOLUME(reagents, /singleton/reagent/blood) < 1)
|
|
break
|
|
user.visible_message(SPAN_WARNING("[user] licks [user.get_pronoun("his")] fangs dry, lowering \the [src]."), SPAN_NOTICE("You lick your fangs clean of the tasteless blood."))
|
|
being_feed = FALSE
|
|
else
|
|
..()
|
|
|
|
/obj/item/reagent_containers/blood/mouse_drop_dragged(atom/over, mob/user, src_location, over_location, params)
|
|
if(!ismob(loc))
|
|
return
|
|
var/turf/our_turf = get_turf(src)
|
|
var/turf/target_turf = get_turf(over)
|
|
if(!our_turf.Adjacent(target_turf))
|
|
return
|
|
if(attached_mob)
|
|
remove_iv_mob()
|
|
else if(ishuman(over))
|
|
visible_message(SPAN_WARNING("\The [user] starts hooking \the [over] up to \the [src]."))
|
|
if(do_after(user, 30))
|
|
to_chat(user, SPAN_NOTICE("You hook \the [over] up to \the [src]."))
|
|
attached_mob = WEAKREF(over)
|
|
START_PROCESSING(SSprocessing, src)
|
|
update_icon()
|
|
|
|
/obj/item/reagent_containers/blood/process()
|
|
var/mob/living/carbon/human/attached
|
|
if(attached_mob)
|
|
attached = attached_mob.resolve()
|
|
if(!attached)
|
|
attached_mob = null
|
|
return PROCESS_KILL
|
|
var/is_adjacent = loc.Adjacent(attached)
|
|
if(!is_adjacent || !ismob(loc))
|
|
remove_iv_mob(is_adjacent)
|
|
update_icon()
|
|
return PROCESS_KILL
|
|
else
|
|
remove_iv_mob()
|
|
return
|
|
|
|
var/mob/M = loc
|
|
if(M.l_hand != src && M.r_hand != src)
|
|
remove_iv_mob()
|
|
return
|
|
|
|
if(!reagents.total_volume)
|
|
remove_iv_mob()
|
|
return
|
|
|
|
reagents.trans_to_mob(attached, amount_per_transfer_from_this, CHEM_BLOOD)
|
|
update_icon()
|
|
|
|
/obj/item/reagent_containers/blood/proc/remove_iv_mob(var/safe = TRUE)
|
|
if(attached_mob)
|
|
var/mob/living/carbon/human/attached = attached_mob.resolve()
|
|
if(attached)
|
|
if(safe)
|
|
visible_message(SPAN_NOTICE("\The [attached] is taken off \the [src]."))
|
|
else
|
|
var/obj/item/organ/external/affecting = attached.get_organ(pick(BP_R_ARM, BP_L_ARM))
|
|
attached.visible_message(SPAN_WARNING("The needle is ripped out of [attached]'s [affecting.limb_name == BP_R_ARM ? "right arm" : "left arm"]."), SPAN_DANGER("The needle <b>painfully</b> rips out of your [affecting.limb_name == BP_R_ARM ? "right arm" : "left arm"]."))
|
|
affecting.take_damage(brute = 5, damage_flags = DAMAGE_FLAG_SHARP)
|
|
attached_mob = null
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
|
|
/obj/item/reagent_containers/blood/attackby(obj/item/attacking_item, mob/user)
|
|
..()
|
|
if (attacking_item.tool_behaviour == TOOL_PEN)
|
|
if (REAGENT_VOLUME(reagents, /singleton/reagent/blood) && name != "empty IV bag") //Stops people mucking with bloodpacks that are filled
|
|
to_chat(user, SPAN_NOTICE("You can't relabel [name] until it is empty!"))
|
|
return
|
|
|
|
var/choices = list("A+ blood", "A- blood", "B+ blood", "B- blood", "O+ blood", "O- blood", "AB+ blood", "AB- blood", "SBS blood", "Saline Plus", "Cryonics mixture", "Other mixture", "Clear", "Cancel")
|
|
var/blood_name = tgui_input_list(user, "What would you like to label the IV bag?", "Label Selection", choices)
|
|
if(blood_name == "Cancel")
|
|
return
|
|
|
|
var/obj/item/i = user.get_active_hand()
|
|
if(!i.tool_behaviour == TOOL_PEN || !in_range(user, src)) //Checks to see if pen is still held or bloodpack is in range
|
|
return
|
|
|
|
if(blood_name == "Clear")
|
|
blood_type = null
|
|
name = initial(name)
|
|
desc = initial(desc)
|
|
to_chat(user, SPAN_NOTICE("You clear the IV bag label."))
|
|
update_icon()
|
|
return
|
|
|
|
blood_type = blood_name
|
|
name = "\improper IV bag - [blood_type]"
|
|
desc = "Contains fluids used for transfusions."
|
|
to_chat(user, SPAN_NOTICE("You label the IV bag as [blood_type]."))
|
|
update_icon()
|
|
return
|
|
|
|
if (istype(attacking_item, /obj/item/) && attacking_item.sharp == 1)
|
|
var/mob/living/carbon/human/H = usr
|
|
if(LAZYLEN(attacking_item.attack_verb))
|
|
user.visible_message(SPAN_DANGER("[src] has been [pick(attacking_item.attack_verb)] with \the [attacking_item] by [user]!"))
|
|
var/atkmsg_filled = null
|
|
if (REAGENT_VOLUME(reagents, /singleton/reagent/blood))
|
|
atkmsg_filled = " and the contents spray everywhere"
|
|
if (src.loc != usr)
|
|
var/strength
|
|
var/percent = round((REAGENT_VOLUME(reagents, /singleton/reagent/blood) / volume) * 100) //the amount of blood changes the strength of spray
|
|
switch(percent)
|
|
if(1 to 9) strength = 2
|
|
if(10 to 50) strength = 3
|
|
if(51 to INFINITY) strength = 4
|
|
for (var/j = 0, j < strength - 1, j++) //The number of separate splatters
|
|
spray_loop:
|
|
var/direction = pick(GLOB.alldirs)
|
|
var/target
|
|
for (var/i = 1, i < strength, i++) //The distance the splatters will travel from random direction
|
|
switch (direction)
|
|
if (NORTH)
|
|
target = locate(src.x, src.y+i, src.z)
|
|
if (SOUTH)
|
|
target = locate(src.x, src.y-i, src.z)
|
|
if (EAST)
|
|
target = locate(src.x+i, src.y, src.z)
|
|
if (WEST)
|
|
target = locate(src.x-i, src.y, src.z)
|
|
if (NORTHEAST)
|
|
target = locate(src.x+i, src.y+i, src.z)
|
|
if (NORTHWEST)
|
|
target = locate(src.x-i, src.y+i, src.z)
|
|
if (SOUTHEAST)
|
|
target = locate(src.x+i, src.y-i, src.z)
|
|
if (SOUTHWEST)
|
|
target = locate(src.x-i, src.y-i, src.z)
|
|
if (istype(get_turf(target), /turf/simulated/wall))
|
|
blood_splatter(target, null, 1)
|
|
break spray_loop
|
|
var/turf/base = get_turf(target)
|
|
for (var/atom/A in base) // Stops your blood spray if it meets a person, wall, door or window
|
|
if (istype(A, /mob/living/carbon/human/))
|
|
var/mob/living/carbon/human/K = A
|
|
K.bloody_body()
|
|
break spray_loop
|
|
if ((!istype(A, /obj/) && A.density) || istype(A, /obj/structure/window/) || istype(A, /obj/machinery/door/airlock/))
|
|
break spray_loop
|
|
blood_splatter(target, null, 1)
|
|
blood_splatter(src.loc, null, 1)
|
|
playsound(src.loc, 'sound/effects/splat.ogg', 50, 1, -6)
|
|
if(istype(H))
|
|
H.bloody_hands()
|
|
if (loc == usr)
|
|
H.bloody_body()
|
|
// Line below will do a check where the target bloodbag is located and create a new one accordingly
|
|
var/obj/item/reagent_containers/I = src.loc != usr ? new/obj/item/reagent_containers/blood/ripped(src.loc) : new/obj/item/reagent_containers/blood/ripped(usr.loc)
|
|
if (REAGENT_VOLUME(reagents, /singleton/reagent/blood))
|
|
I.add_blood()
|
|
var/atkmsg = SPAN_WARNING("\The [src] rips apart[atkmsg_filled]!")
|
|
user.visible_message(atkmsg)
|
|
qdel(src)
|
|
return
|
|
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/sbs
|
|
blood_type = "SBS"
|
|
|
|
/obj/item/reagent_containers/blood/empty
|
|
name = "empty IV bag"
|
|
desc = "Seems pretty useless... Maybe if there were a way to fill it?"
|
|
icon_state = "bloodpack"
|
|
|
|
/obj/item/reagent_containers/blood/ripped
|
|
name = "ripped IV bag"
|
|
desc = "It's torn up and useless."
|
|
icon = 'icons/obj/bloodpack.dmi'
|
|
icon_state = "ripped"
|
|
volume = 0
|
|
|
|
/obj/item/reagent_containers/blood/ripped/attackby(obj/item/attacking_item, mob/user)
|
|
to_chat(user, SPAN_WARNING("You can't do anything further with this."))
|
|
return
|