mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-05-28 01:27:41 +01:00
d5849910e5
* Begin clickcode attack_self fix Begins the work to make everything call back to parent for attack_self so that signals are sacred. * Makes MORE things call the attack_self() parent Yes, I could make special_handling a var on obj/item HOWEVER i want it to be specific so it can be tracked down later and ONLY the objects that use it can be refactored instead of sitting there literally forever and it just becoming 'a thing'. * Finishes making the rest of attack_self call parent. As mentioned, things such as 'specialty_goggles' 'special_handling' and the such are only there to help with attack_self until the attack_self is recoded for those items. * begone foul demon * some more cleanup * These * GOD this was annoying * yeh * Fix this * fLARES * Thesee too * toys! * Even more! * More fixes * Even more * rest of em * these too * Update syndie.dm * hardref clear * Update code/game/gamemodes/nuclear/pinpointer.dm * Update code/game/objects/effects/mines.dm * Update code/game/objects/items/blueprints_vr.dm * Update code/game/objects/items/blueprints_vr.dm * Update code/game/objects/items/contraband_vr.dm * Update code/game/objects/items/crayons.dm * Update code/game/objects/items/crayons.dm * Update code/game/objects/items/gunbox.dm * Update code/game/objects/items/gunbox.dm * Update code/game/objects/items/gunbox_vr.dm * Update code/game/objects/items/gunbox_vr.dm * Update code/game/objects/items/weapons/gift_wrappaper.dm * Update code/game/objects/items/crayons.dm * Update code/game/objects/items/crayons.dm * Update code/game/objects/items/gunbox.dm * these too * Update maintpanel_stack.dm * angry warning * Fixes packaged snacks. Fixes improper var default. * Special handling for these * proper poly types * Fixes magclaws Makes the 'features' it had just part of base magboots that can be adjusted via varswap. * Fixes jackets Fixes https://github.com/VOREStation/VOREStation/issues/18941 * Small bugfix Makes p_Theyre properly capitialize Makes examine show proper wording * Update gift_wrappaper.dm
263 lines
11 KiB
Plaintext
263 lines
11 KiB
Plaintext
/obj/item/extrapolator
|
|
name = "virus extrapolator"
|
|
icon = 'icons/obj/device.dmi'
|
|
icon_state = "extrapolator_scan"
|
|
desc = "A bulky scanning device, used to extract genetic material of potential pathogens."
|
|
description_info = "Use on hand to change between SCAN and EXTRACT mode."
|
|
item_flags = NOBLUDGEON
|
|
slot_flags = SLOT_BELT
|
|
w_class = ITEMSIZE_NORMAL
|
|
/// Whether the extrapolator is curently in use
|
|
var/using = FALSE
|
|
/// Whether the extrapolator is curently in SCAN or EXTRACT mode
|
|
var/scan = TRUE
|
|
/// The scanning module installed in the extrapolator. Used to determine extraction speed, and the stealthiest virus that's possible to extract.
|
|
var/obj/item/stock_parts/scanning_module/scanner
|
|
/// A list of advance IDs that this extrapolator has already extracted.
|
|
var/list/extracted_ids = list()
|
|
/// How long it takes for the extrapolator to extract a virus.
|
|
var/extract_time = 10 SECONDS
|
|
/// How long it tkaes for the extrapolator to isolate a symptom.
|
|
var/isolate_time = 15 SECONDS
|
|
/// The extrapolator can extract any virus with a stealth below this value.
|
|
var/maximum_stealth = 3
|
|
/// The extrapolator can extract any symptom with a stealth below this value.
|
|
var/maximum_level = 5
|
|
/// The typepath of the default scanning module that will generate in the extrapolator, if it starts with none.
|
|
var/default_scanning_module = /obj/item/stock_parts/scanning_module
|
|
/// Cooldown for when the extrapolator can be used next.
|
|
COOLDOWN_DECLARE(usage_cooldown)
|
|
|
|
/obj/item/extrapolator/Initialize(mapload, obj/item/stock_parts/scanning_module/starting_scanner)
|
|
. = ..()
|
|
starting_scanner = starting_scanner || default_scanning_module
|
|
if(ispath(starting_scanner, /obj/item/stock_parts/scanning_module))
|
|
scanner = new starting_scanner(src)
|
|
else if(istype(starting_scanner))
|
|
starting_scanner.forceMove(src)
|
|
scanner = starting_scanner
|
|
|
|
refresh_parts()
|
|
|
|
/obj/item/extrapolator/attackby(obj/item/item, mob/user, params)
|
|
if(istype(item, /obj/item/stock_parts/scanning_module))
|
|
if(!scanner)
|
|
user.drop_item()
|
|
item.loc = src
|
|
scanner = item
|
|
to_chat(user, span_notice("You install \the [scanner] in [src]."))
|
|
refresh_parts()
|
|
else
|
|
to_chat(user, span_notice("[src] already has \the [scanner] installed."))
|
|
return
|
|
|
|
if(item.has_tool_quality(TOOL_SCREWDRIVER) && scanner)
|
|
if(!scanner) // You never know
|
|
to_chat(user, span_warning("\The [src] has no scanner to remove!"))
|
|
return FALSE
|
|
to_chat(user, span_notice("You remove \the [scanner] from \the [src]."))
|
|
scanner.forceMove(drop_location())
|
|
scanner = null
|
|
playsound(src, item.usesound, 50, 1)
|
|
return TRUE
|
|
|
|
/obj/item/extrapolator/attack_self(mob/user)
|
|
. = ..(user)
|
|
playsound(src, 'sound/machines/click.ogg', 50, TRUE)
|
|
if(scan)
|
|
icon_state = "extrapolator_sample"
|
|
scan = FALSE
|
|
to_chat(user, span_notice("You remove the probe from the device and set it to EXTRACT."))
|
|
else
|
|
icon_state = "extrapolator_scan"
|
|
scan = TRUE
|
|
to_chat(user, span_notice("You put the probe back into the device and set it to SCAN."))
|
|
|
|
/obj/item/extrapolator/examine(mob/user)
|
|
. = ..()
|
|
if(in_range(user, src) || isobserver(user))
|
|
if(!scanner)
|
|
. += span_notice("The scanner is missing.")
|
|
else
|
|
. += span_notice("A class " + span_bold("[scanner.rating]") + " scanning module is installed. It is <i>screwed</i> in place.")
|
|
// . += span_notice("Can detect diseases below stealth " + span_bold("[maximum_stealth]") + ".")
|
|
. += span_notice("Can extract diseases in " + span_bold("[DisplayTimeText(extract_time)]") + ".")
|
|
. += span_notice("Can isolate symptoms <b>[maximum_level >= 9 ? "of any level" : "below level [maximum_level]"]</b>, in <b>[DisplayTimeText(isolate_time)]</b>.")
|
|
|
|
/obj/item/extrapolator/proc/refresh_parts()
|
|
if(!scanner)
|
|
return
|
|
var/effective_scanner_rating = scanner.rating +1
|
|
extract_time = (10 SECONDS) / effective_scanner_rating
|
|
isolate_time = (15 SECONDS) / effective_scanner_rating
|
|
// maximum_stealth = scanner.rating + 2
|
|
maximum_level = scanner.rating + 5
|
|
|
|
/obj/item/extrapolator/attack(atom/AM, mob/living/user)
|
|
return
|
|
|
|
/obj/item/extrapolator/afterattack(atom/target, mob/user, proximity_flag, click_parameters)
|
|
. = ..()
|
|
if(!proximity_flag && !scan)
|
|
return
|
|
if(using)
|
|
to_chat(user, span_warning("[icon2html(src, user)] The extrapolator is already in use."))
|
|
return
|
|
if(!COOLDOWN_FINISHED(src, usage_cooldown))
|
|
to_chat(user, span_warning("[icon2html(src, user)] The extrapolator is still recharging!"))
|
|
return
|
|
if(scanner)
|
|
var/list/result = target?.extrapolator_act(user, src, dry_run = TRUE)
|
|
var/list/diseases = result && result[EXTRAPOLATOR_RESULT_DISEASES]
|
|
if(!length(diseases))
|
|
var/list/atom/targets = find_valid_targets(user, target)
|
|
var/target_amt = length(targets)
|
|
if(target_amt)
|
|
target = target_amt > 1 ? tgui_input_list(user, "Select object to analyze", "Viral Extrapolation", targets, default = targets[1]) : targets[1]
|
|
if(target)
|
|
result = target.extrapolator_act(user, src, dry_run = TRUE)
|
|
diseases = result && result[EXTRAPOLATOR_RESULT_DISEASES]
|
|
if(!target)
|
|
return
|
|
if(!length(diseases))
|
|
if(scan)
|
|
to_chat(user, span_notice("[icon2html(src, user)] \The [src] fails to return any data."))
|
|
else
|
|
to_chat(user, span_notice("[icon2html(src, user)] \The [src]'s probe detects no diseases."))
|
|
return
|
|
if(EXTRAPOLATOR_ACT_CHECK(result, EXTRAPOLATOR_ACT_PRIORITY_SPECIAL))
|
|
// extrapolator_act did some sort of special behavior, we don't need to do anything further
|
|
return
|
|
if(scan)
|
|
scan(user, target)
|
|
else
|
|
extrapolate(user, target)
|
|
else
|
|
to_chat(user, span_warning("The extrapolator has no scanner installed!"))
|
|
|
|
/obj/item/extrapolator/proc/find_valid_targets(mob/living/user, atom/target)
|
|
. = list()
|
|
var/turf/target_turf = get_turf(target)
|
|
if(!target_turf)
|
|
return
|
|
for(var/atom/target_to_try in target_turf.contents - target)
|
|
var/list/result = target_to_try.extrapolator_act(user, src, dry_run = TRUE)
|
|
if(length(result[EXTRAPOLATOR_RESULT_DISEASES]))
|
|
. += target_to_try
|
|
|
|
/obj/item/extrapolator/proc/scan(mob/living/user, atom/target)
|
|
. = TRUE
|
|
var/list/result = target?.extrapolator_act(user, target)
|
|
var/list/diseases = result[EXTRAPOLATOR_RESULT_DISEASES]
|
|
if(!length(diseases))
|
|
return FALSE
|
|
if(EXTRAPOLATOR_ACT_CHECK(result, EXTRAPOLATOR_ACT_PRIORITY_SPECIAL))
|
|
return
|
|
var/list/message = list()
|
|
if(length(diseases))
|
|
message += span_boldnotice("[costly_icon2html(target, user)] [target] scan results")
|
|
message += span_boldnotice("[icon2html(src, user)] \The [src] detects the following diseases:")
|
|
for(var/datum/disease/disease in diseases)
|
|
if(istype(disease, /datum/disease/advance))
|
|
var/datum/disease/advance/advance_disease = disease
|
|
var/list/properties
|
|
if(global_flag_check(advance_disease.virus_modifiers, CARRIER))
|
|
LAZYADD(properties, "carrier")
|
|
if(global_flag_check(advance_disease.virus_modifiers, FALTERED))
|
|
LAZYADD(properties, "faltered")
|
|
message += span_info("<b>[advance_disease.name]</b>[LAZYLEN(properties) ? " ([properties.Join(", ")])" : ""], [global_flag_check(advance_disease.virus_modifiers, DORMANT) ? "<i>dormant virus</i>" : "stage [advance_disease.stage]/5"]")
|
|
if(extracted_ids[advance_disease.GetDiseaseID()])
|
|
message += "This virus has been extracted by \the [src] previously."
|
|
message += "[advance_disease.name] has the following symptoms:"
|
|
for(var/datum/symptom/symptom in advance_disease.symptoms)
|
|
message += "[symptom.name]"
|
|
else
|
|
message += span_info("<b>[disease.name]</b>, [global_flag_check(disease.virus_modifiers, DORMANT) ? "<i>dormant virus</i>" : "stage [disease.stage]/[disease.max_stages]"].")
|
|
|
|
disease.addToDB()
|
|
|
|
to_chat(user, examine_block(jointext(message, "\n")), avoid_highlighting = TRUE, trailing_newline = FALSE, type = MESSAGE_TYPE_INFO)
|
|
|
|
/obj/item/extrapolator/proc/extrapolate(mob/living/user, atom/target, isolate = FALSE)
|
|
. = FALSE
|
|
var/list/result = target?.extrapolator_act(user, target)
|
|
var/list/diseases = result[EXTRAPOLATOR_RESULT_DISEASES]
|
|
if(!length(diseases))
|
|
return
|
|
if(EXTRAPOLATOR_ACT_CHECK(result, EXTRAPOLATOR_ACT_PRIORITY_SPECIAL)) // hardcoded "we handled this ourselves" response
|
|
return TRUE
|
|
if(EXTRAPOLATOR_ACT_CHECK(result, EXTRAPOLATOR_ACT_PRIORITY_ISOLATE))
|
|
isolate = TRUE
|
|
//var/list/advance_diseases = list()
|
|
/*
|
|
for(var/datum/disease/advance/candidate in diseases)
|
|
if(candidate.stealth >= maximum_stealth)
|
|
continue
|
|
advance_diseases += candidate
|
|
*/
|
|
if(!length(diseases))
|
|
to_chat(user, span_warning("[icon2html(src, user)] There are no valid diseases to make a culture from."))
|
|
return
|
|
var/datum/disease/advance/target_disease = length(diseases) > 1 ? tgui_input_list(user, "Select disease to extract", "Viral Extraction", diseases, default = diseases[1]) : diseases[1]
|
|
if(!target_disease)
|
|
return
|
|
using = TRUE
|
|
var/choice = tgui_alert(user, "What would you like to isolate?", "Isolate", list("Symptom", "Disease"))
|
|
if(choice == "Symptom")
|
|
. = isolate_symptom(user, target, target_disease)
|
|
else
|
|
. = isolate_disease(user, target, target_disease)
|
|
using = FALSE
|
|
|
|
/obj/item/extrapolator/proc/isolate_symptom(mob/living/user, atom/target, datum/disease/advance/target_disease)
|
|
. = FALSE
|
|
var/list/symptoms = list()
|
|
for(var/datum/symptom/symptom in target_disease.symptoms)
|
|
if(symptom.level <= maximum_level)
|
|
symptoms += symptom
|
|
continue
|
|
if(!length(symptoms))
|
|
to_chat(user, span_warning("[icon2html(src, user)] There are no symptoms that could be isolated.."))
|
|
return
|
|
var/datum/symptom/chosen = length(symptoms) > 1 ? tgui_input_list(user, "Select symptom to isolate", "Symptom Extraction", symptoms, default = symptoms[1]) : symptoms[1]
|
|
if(!chosen)
|
|
return
|
|
user.visible_message(span_notice("[user] slots [target] into [src], which begins to whir and beep!"), span_notice("[icon2html(src, user)] You begin isolating " + span_bold("[chosen.name]") + " from [target]..."),)
|
|
var/datum/disease/advance/symptom_holder = new
|
|
symptom_holder.name = chosen.name
|
|
symptom_holder.symptoms += chosen
|
|
symptom_holder.Finalize()
|
|
symptom_holder.Refresh()
|
|
if(do_after(user, extract_time, target = target))
|
|
create_culture(user, symptom_holder, target)
|
|
return TRUE
|
|
|
|
/obj/item/extrapolator/proc/isolate_disease(mob/living/user, atom/target, datum/disease/advance/target_disease, timer = 10 SECONDS)
|
|
. = FALSE
|
|
user.visible_message(span_notice("[user] begins to thoroughly scan [target] with [src]..."), \
|
|
span_notice("[icon2html(src, user)] You begin isolating " + span_bold("[target_disease.name]") + " from [target]..."))
|
|
if(do_after(user, isolate_time, target = target))
|
|
create_culture(user, target_disease, target)
|
|
return TRUE
|
|
|
|
/obj/item/extrapolator/proc/create_culture(mob/living/user, datum/disease/advance/disease)
|
|
. = FALSE
|
|
disease = disease.Copy()
|
|
disease.virus_modifiers &= ~DORMANT
|
|
var/list/data = list("viruses" = list(disease))
|
|
if(user.get_active_hand() != src)
|
|
to_chat(user, span_warning("The extrapolator must be held in your active hand to work!"))
|
|
return
|
|
var/obj/item/reagent_containers/glass/beaker/vial/culture_bottle = new(user.drop_location())
|
|
culture_bottle.name = "[disease.name] culture bottle"
|
|
culture_bottle.desc = "A small bottle. Contains [disease.agent] culture in synthblood medium."
|
|
culture_bottle.reagents.add_reagent(REAGENT_ID_BLOOD, 5, data)
|
|
user.put_in_hands(culture_bottle)
|
|
playsound(src, 'sound/machines/ping.ogg', vol = 30, vary = TRUE)
|
|
COOLDOWN_START(src, usage_cooldown, 1 SECONDS)
|
|
extracted_ids[disease.GetDiseaseID()] = TRUE
|
|
return TRUE
|
|
|
|
/obj/item/extrapolator/tier5
|
|
default_scanning_module = /obj/item/stock_parts/scanning_module/omni
|