mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-12 02:32:10 +00:00
[MIRROR] TGUI Destructive Analyzer [MDB IGNORE] (#25005)
* TGUI Destructive Analyzer (#79572) ## About The Pull Request I made this to help me move more towards my goals [laid out here](https://hackmd.io/XLt5MoRvRxuhFbwtk4VAUA) which currently doesn't have much interest. This makes the Destructive Analyzer use a little neat TGUI menu instead of its old HTML one. I also touch a lot of science stuff and a little experimentor stuff, so let me explain a bit: Old iterations of Science had different items that you can use to boost nodes through deconstruction. This has been removed, and its only feature is the auto-unlocking of nodes (that is; making them visible to the R&D console). I thought that instead of keeping this deprecated code around, I would rework it a little to make it clear what we actually use it for (unhiding nodes). All vars and procs that mentioned this have been renamed or reworked to make more sense now. Experimentor stuff shares a lot with the destructive analyzer, so I had to mess with that a bit to keep its decayed corpse of deprecated code, functional. I also added context tips to the destructive analyzer, and added the ability to AltClick to remove the inserted item. Removing items now also plays a little sound because it was kinda lame. Also, balloon alerts. ## Why It's Good For The Game Moves a shitty machine to TGUI so it is slightly less shitty, now it's more direct and compact with more player-feedback. Helps me with a personal project and yea ### Video demonstration I show off connecting the machine to R&D Servers, but I haven't changed the behavior of that and the roundstart analyzers are connected to servers by default. https://github.com/tgstation/tgstation/assets/53777086/65295600-4fae-42d1-9bae-eccefe337a2b ## Changelog 🆑 refactor: Destructive Analyzers now have a TGUI menu. /🆑 * TGUI Destructive Analyzer * Modular --------- Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com>
This commit is contained in:
@@ -1,10 +1,6 @@
|
|||||||
#define RDSCREEN_NOBREAK "<NO_HTML_BREAK>"
|
|
||||||
|
|
||||||
/// For instances where we don't want a design showing up due to it being for debug/sanity purposes
|
/// For instances where we don't want a design showing up due to it being for debug/sanity purposes
|
||||||
#define DESIGN_ID_IGNORE "IGNORE_THIS_DESIGN"
|
#define DESIGN_ID_IGNORE "IGNORE_THIS_DESIGN"
|
||||||
|
|
||||||
#define RESEARCH_MATERIAL_DESTROY_ID "__destroy"
|
|
||||||
|
|
||||||
//! Techweb names for new point types. Can be used to define specific point values for specific types of research (science, security, engineering, etc.)
|
//! Techweb names for new point types. Can be used to define specific point values for specific types of research (science, security, engineering, etc.)
|
||||||
#define TECHWEB_POINT_TYPE_GENERIC "General Research"
|
#define TECHWEB_POINT_TYPE_GENERIC "General Research"
|
||||||
|
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ SUBSYSTEM_DEF(research)
|
|||||||
var/list/techweb_nodes_starting = list()
|
var/list/techweb_nodes_starting = list()
|
||||||
///category name = list(node.id = TRUE)
|
///category name = list(node.id = TRUE)
|
||||||
var/list/techweb_categories = list()
|
var/list/techweb_categories = list()
|
||||||
///associative double-layer path = list(id = list(point_type = point_discount))
|
///List of all items that can unlock a node. (node.id = list(items))
|
||||||
var/list/techweb_boost_items = list()
|
var/list/techweb_unlock_items = list()
|
||||||
///Node ids that should be hidden by default.
|
///Node ids that should be hidden by default.
|
||||||
var/list/techweb_nodes_hidden = list()
|
var/list/techweb_nodes_hidden = list()
|
||||||
///Node ids that are exclusive to the BEPIS.
|
///Node ids that are exclusive to the BEPIS.
|
||||||
@@ -64,7 +64,7 @@ SUBSYSTEM_DEF(research)
|
|||||||
/// Lookup list for ordnance briefers.
|
/// Lookup list for ordnance briefers.
|
||||||
var/list/ordnance_experiments = list()
|
var/list/ordnance_experiments = list()
|
||||||
/// Lookup list for scipaper partners.
|
/// Lookup list for scipaper partners.
|
||||||
var/list/scientific_partners = list()
|
var/list/datum/scientific_partner/scientific_partners = list()
|
||||||
|
|
||||||
/datum/controller/subsystem/research/Initialize()
|
/datum/controller/subsystem/research/Initialize()
|
||||||
point_types = TECHWEB_POINT_TYPE_LIST_ASSOCIATIVE_NAMES
|
point_types = TECHWEB_POINT_TYPE_LIST_ASSOCIATIVE_NAMES
|
||||||
@@ -153,7 +153,7 @@ SUBSYSTEM_DEF(research)
|
|||||||
if (!verify_techweb_nodes()) //Verify all nodes have ids and such.
|
if (!verify_techweb_nodes()) //Verify all nodes have ids and such.
|
||||||
stack_trace("Invalid techweb nodes detected")
|
stack_trace("Invalid techweb nodes detected")
|
||||||
calculate_techweb_nodes()
|
calculate_techweb_nodes()
|
||||||
calculate_techweb_boost_list()
|
calculate_techweb_item_unlocking_requirements()
|
||||||
if (!verify_techweb_nodes()) //Verify nodes and designs have been crosslinked properly.
|
if (!verify_techweb_nodes()) //Verify nodes and designs have been crosslinked properly.
|
||||||
CRASH("Invalid techweb nodes detected")
|
CRASH("Invalid techweb nodes detected")
|
||||||
|
|
||||||
@@ -209,25 +209,15 @@ SUBSYSTEM_DEF(research)
|
|||||||
N.unlock_ids -= u
|
N.unlock_ids -= u
|
||||||
research_node_id_error(u)
|
research_node_id_error(u)
|
||||||
. = FALSE
|
. = FALSE
|
||||||
for(var/p in N.boost_item_paths)
|
for(var/p in N.required_items_to_unlock)
|
||||||
if(!ispath(p))
|
if(!ispath(p))
|
||||||
N.boost_item_paths -= p
|
N.required_items_to_unlock -= p
|
||||||
WARNING("[p] is not a valid path.")
|
WARNING("[p] is not a valid path.")
|
||||||
node_boost_error(N.id, "[p] is not a valid path.")
|
node_boost_error(N.id, "[p] is not a valid path.")
|
||||||
. = FALSE
|
. = FALSE
|
||||||
var/list/points = N.boost_item_paths[p]
|
var/list/points = N.required_items_to_unlock[p]
|
||||||
if(islist(points))
|
if(!isnull(points))
|
||||||
for(var/i in points)
|
N.required_items_to_unlock -= p
|
||||||
if(!isnum(points[i]))
|
|
||||||
WARNING("[points[i]] is not a valid number.")
|
|
||||||
node_boost_error(N.id, "[points[i]] is not a valid number.")
|
|
||||||
. = FALSE
|
|
||||||
else if(!point_types[i])
|
|
||||||
WARNING("[i] is not a valid point type.")
|
|
||||||
node_boost_error(N.id, "[i] is not a valid point type.")
|
|
||||||
. = FALSE
|
|
||||||
else if(!isnull(points))
|
|
||||||
N.boost_item_paths -= p
|
|
||||||
node_boost_error(N.id, "No valid list.")
|
node_boost_error(N.id, "No valid list.")
|
||||||
WARNING("No valid list.")
|
WARNING("No valid list.")
|
||||||
. = FALSE
|
. = FALSE
|
||||||
@@ -281,18 +271,16 @@ SUBSYSTEM_DEF(research)
|
|||||||
var/datum/techweb_node/prereq_node = techweb_node_by_id(prereq_id)
|
var/datum/techweb_node/prereq_node = techweb_node_by_id(prereq_id)
|
||||||
prereq_node.unlock_ids[node.id] = node
|
prereq_node.unlock_ids[node.id] = node
|
||||||
|
|
||||||
/datum/controller/subsystem/research/proc/calculate_techweb_boost_list(clearall = FALSE)
|
/datum/controller/subsystem/research/proc/calculate_techweb_item_unlocking_requirements()
|
||||||
if(clearall)
|
|
||||||
techweb_boost_items = list()
|
|
||||||
for(var/node_id in techweb_nodes)
|
for(var/node_id in techweb_nodes)
|
||||||
var/datum/techweb_node/node = techweb_nodes[node_id]
|
var/datum/techweb_node/node = techweb_nodes[node_id]
|
||||||
for(var/path in node.boost_item_paths)
|
for(var/path in node.required_items_to_unlock)
|
||||||
if(!ispath(path))
|
if(!ispath(path))
|
||||||
continue
|
continue
|
||||||
if(length(techweb_boost_items[path]))
|
if(length(techweb_unlock_items[path]))
|
||||||
techweb_boost_items[path][node.id] = node.boost_item_paths[path]
|
techweb_unlock_items[path][node.id] = node.required_items_to_unlock[path]
|
||||||
else
|
else
|
||||||
techweb_boost_items[path] = list(node.id = node.boost_item_paths[path])
|
techweb_unlock_items[path] = list(node.id = node.required_items_to_unlock[path])
|
||||||
CHECK_TICK
|
CHECK_TICK
|
||||||
|
|
||||||
/datum/controller/subsystem/research/proc/populate_ordnance_experiments()
|
/datum/controller/subsystem/research/proc/populate_ordnance_experiments()
|
||||||
|
|||||||
@@ -443,7 +443,7 @@
|
|||||||
///Separator between the items on the list
|
///Separator between the items on the list
|
||||||
var/sep = ""
|
var/sep = ""
|
||||||
///Nodes that can be boosted
|
///Nodes that can be boosted
|
||||||
var/list/boostable_nodes = techweb_item_boost_check(src)
|
var/list/boostable_nodes = techweb_item_unlock_check(src)
|
||||||
if (boostable_nodes)
|
if (boostable_nodes)
|
||||||
for(var/id in boostable_nodes)
|
for(var/id in boostable_nodes)
|
||||||
var/datum/techweb_node/node = SSresearch.techweb_node_by_id(id)
|
var/datum/techweb_node/node = SSresearch.techweb_node_by_id(id)
|
||||||
@@ -618,9 +618,6 @@
|
|||||||
R.activate_module(src)
|
R.activate_module(src)
|
||||||
R.hud_used.update_robot_modules_display()
|
R.hud_used.update_robot_modules_display()
|
||||||
|
|
||||||
/obj/item/proc/GetDeconstructableContents()
|
|
||||||
return get_all_contents() - src
|
|
||||||
|
|
||||||
// afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency
|
// afterattack() and attack() prototypes moved to _onclick/item_attack.dm for consistency
|
||||||
|
|
||||||
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
|
/obj/item/proc/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE)
|
||||||
|
|||||||
@@ -968,7 +968,8 @@
|
|||||||
req_components = list(
|
req_components = list(
|
||||||
/datum/stock_part/scanning_module = 1,
|
/datum/stock_part/scanning_module = 1,
|
||||||
/datum/stock_part/servo = 1,
|
/datum/stock_part/servo = 1,
|
||||||
/datum/stock_part/micro_laser = 1)
|
/datum/stock_part/micro_laser = 1,
|
||||||
|
)
|
||||||
|
|
||||||
/obj/item/circuitboard/machine/experimentor
|
/obj/item/circuitboard/machine/experimentor
|
||||||
name = "E.X.P.E.R.I-MENTOR"
|
name = "E.X.P.E.R.I-MENTOR"
|
||||||
|
|||||||
@@ -65,9 +65,9 @@
|
|||||||
singular_partner["path"] = partner.type
|
singular_partner["path"] = partner.type
|
||||||
singular_partner["boostedNodes"] = list()
|
singular_partner["boostedNodes"] = list()
|
||||||
singular_partner["acceptedExperiments"] = list()
|
singular_partner["acceptedExperiments"] = list()
|
||||||
for (var/node_id in partner.boosted_nodes)
|
for (var/node_id in partner.boostable_nodes)
|
||||||
var/datum/techweb_node/node = SSresearch.techweb_node_by_id(node_id)
|
var/datum/techweb_node/node = SSresearch.techweb_node_by_id(node_id)
|
||||||
singular_partner["boostedNodes"] += list(list("name" = node.display_name, "discount" = partner.boosted_nodes[node_id], "id"=node_id))
|
singular_partner["boostedNodes"] += list(list("name" = node.display_name, "discount" = partner.boostable_nodes[node_id], "id" = node_id))
|
||||||
for (var/datum/experiment/ordnance/ordnance_experiment as anything in partner.accepted_experiments)
|
for (var/datum/experiment/ordnance/ordnance_experiment as anything in partner.accepted_experiments)
|
||||||
singular_partner["acceptedExperiments"] += initial(ordnance_experiment.name)
|
singular_partner["acceptedExperiments"] += initial(ordnance_experiment.name)
|
||||||
parsed_partners += list(singular_partner)
|
parsed_partners += list(singular_partner)
|
||||||
@@ -154,7 +154,7 @@
|
|||||||
data["purchaseableBoosts"][partner.type] = list()
|
data["purchaseableBoosts"][partner.type] = list()
|
||||||
for(var/node_id in linked_techweb.get_available_nodes())
|
for(var/node_id in linked_techweb.get_available_nodes())
|
||||||
// Not from our partner
|
// Not from our partner
|
||||||
if(!(node_id in partner.boosted_nodes))
|
if(!(node_id in partner.boostable_nodes))
|
||||||
continue
|
continue
|
||||||
if(!partner.allowed_to_boost(linked_techweb, node_id))
|
if(!partner.allowed_to_boost(linked_techweb, node_id))
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
/*
|
///How much power it costs to deconstruct an item.
|
||||||
Destructive Analyzer
|
#define DESTRUCTIVE_ANALYZER_POWER_USAGE (BASE_MACHINE_IDLE_CONSUMPTION * 2.5)
|
||||||
|
///The 'ID' for deconstructing items for Research points instead of nodes.
|
||||||
|
#define DESTRUCTIVE_ANALYZER_DESTROY_POINTS "research_points"
|
||||||
|
|
||||||
It is used to destroy hand-held objects and advance technological research. Controls are in the linked R&D console.
|
/**
|
||||||
|
* ## Destructive Analyzer
|
||||||
Note: Must be placed within 3 tiles of the R&D Console
|
* It is used to destroy hand-held objects and advance technological research.
|
||||||
*/
|
*/
|
||||||
/obj/machinery/rnd/destructive_analyzer
|
/obj/machinery/rnd/destructive_analyzer
|
||||||
name = "destructive analyzer"
|
name = "destructive analyzer"
|
||||||
@@ -11,215 +13,177 @@ Note: Must be placed within 3 tiles of the R&D Console
|
|||||||
icon_state = "d_analyzer"
|
icon_state = "d_analyzer"
|
||||||
base_icon_state = "d_analyzer"
|
base_icon_state = "d_analyzer"
|
||||||
circuit = /obj/item/circuitboard/machine/destructive_analyzer
|
circuit = /obj/item/circuitboard/machine/destructive_analyzer
|
||||||
var/decon_mod = 0
|
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/RefreshParts()
|
/obj/machinery/rnd/destructive_analyzer/Initialize(mapload)
|
||||||
. = ..()
|
. = ..()
|
||||||
var/T = 0
|
register_context()
|
||||||
for(var/datum/stock_part/stock_part in component_parts)
|
|
||||||
T += stock_part.tier
|
|
||||||
decon_mod = T
|
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/proc/ConvertReqString2List(list/source_list)
|
/obj/machinery/rnd/destructive_analyzer/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
|
||||||
var/list/temp_list = params2list(source_list)
|
if(loaded_item)
|
||||||
for(var/O in temp_list)
|
context[SCREENTIP_CONTEXT_ALT_LMB] = "Remove Item"
|
||||||
temp_list[O] = text2num(temp_list[O])
|
else if(!isnull(held_item))
|
||||||
return temp_list
|
context[SCREENTIP_CONTEXT_LMB] = "Insert Item"
|
||||||
|
return CONTEXTUAL_SCREENTIP_SET
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/Insert_Item(obj/item/O, mob/living/user)
|
/obj/machinery/rnd/destructive_analyzer/attackby(obj/item/weapon, mob/living/user, params)
|
||||||
if(!user.combat_mode)
|
if(user.combat_mode)
|
||||||
. = 1
|
return ..()
|
||||||
if(!is_insertion_ready(user))
|
if(!is_insertion_ready(user))
|
||||||
return
|
return ..()
|
||||||
if(!user.transferItemToLoc(O, src))
|
if(!user.transferItemToLoc(weapon, src))
|
||||||
to_chat(user, span_warning("\The [O] is stuck to your hand, you cannot put it in the [src.name]!"))
|
to_chat(user, span_warning("\The [weapon] is stuck to your hand, you cannot put it in the [name]!"))
|
||||||
return
|
return TRUE
|
||||||
busy = TRUE
|
busy = TRUE
|
||||||
loaded_item = O
|
loaded_item = weapon
|
||||||
to_chat(user, span_notice("You add the [O.name] to the [src.name]!"))
|
to_chat(user, span_notice("You add the [weapon.name] to the [name]!"))
|
||||||
flick("d_analyzer_la", src)
|
flick("[base_icon_state]_la", src)
|
||||||
addtimer(CALLBACK(src, PROC_REF(finish_loading)), 10)
|
addtimer(CALLBACK(src, PROC_REF(finish_loading)), 1 SECONDS)
|
||||||
updateUsrDialog()
|
return TRUE
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/proc/finish_loading()
|
/obj/machinery/rnd/destructive_analyzer/AltClick(mob/user)
|
||||||
update_appearance()
|
. = ..()
|
||||||
reset_busy()
|
unload_item()
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/update_icon_state()
|
/obj/machinery/rnd/destructive_analyzer/update_icon_state()
|
||||||
icon_state = "[base_icon_state][loaded_item ? "_l" : null]"
|
icon_state = "[base_icon_state][loaded_item ? "_l" : null]"
|
||||||
return ..()
|
return ..()
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/proc/destroy_item(obj/item/thing, innermode = FALSE)
|
/obj/machinery/rnd/destructive_analyzer/ui_interact(mob/user, datum/tgui/ui)
|
||||||
if(QDELETED(thing) || QDELETED(src))
|
ui = SStgui.try_update_ui(user, src, ui)
|
||||||
return FALSE
|
if(!ui)
|
||||||
if(!innermode)
|
ui = new(user, src, "DestructiveAnalyzer")
|
||||||
flick("d_analyzer_process", src)
|
ui.open()
|
||||||
busy = TRUE
|
|
||||||
addtimer(CALLBACK(src, PROC_REF(reset_busy)), 24)
|
|
||||||
use_power(250)
|
|
||||||
if(thing == loaded_item)
|
|
||||||
loaded_item = null
|
|
||||||
var/list/food = thing.GetDeconstructableContents()
|
|
||||||
for(var/obj/item/innerthing in food)
|
|
||||||
destroy_item(innerthing, TRUE)
|
|
||||||
for(var/mob/living/victim in thing)
|
|
||||||
if(victim.stat != DEAD)
|
|
||||||
victim.investigate_log("has been killed by a destructive analyzer.", INVESTIGATE_DEATHS)
|
|
||||||
victim.death()
|
|
||||||
|
|
||||||
qdel(thing)
|
/obj/machinery/rnd/destructive_analyzer/ui_data(mob/user)
|
||||||
loaded_item = null
|
var/list/data = list()
|
||||||
if (!innermode)
|
data["server_connected"] = !!stored_research
|
||||||
update_appearance()
|
data["node_data"] = list()
|
||||||
return TRUE
|
if(loaded_item)
|
||||||
|
data["item_icon"] = icon2base64(getFlatIcon(image(icon = loaded_item.icon, icon_state = loaded_item.icon_state), no_anim = TRUE))
|
||||||
|
data["indestructible"] = !(loaded_item.resistance_flags & INDESTRUCTIBLE)
|
||||||
|
data["loaded_item"] = loaded_item
|
||||||
|
data["already_deconstructed"] = !!stored_research.deconstructed_items[loaded_item.type]
|
||||||
|
var/list/points = techweb_item_point_check(loaded_item)
|
||||||
|
data["recoverable_points"] = techweb_point_display_generic(points)
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/proc/user_try_decon_id(id, mob/user)
|
var/list/boostable_nodes = techweb_item_unlock_check(loaded_item)
|
||||||
if(!istype(loaded_item))
|
|
||||||
return FALSE
|
|
||||||
|
|
||||||
if (id && id != RESEARCH_MATERIAL_DESTROY_ID)
|
|
||||||
var/datum/techweb_node/TN = SSresearch.techweb_node_by_id(id)
|
|
||||||
if(!istype(TN))
|
|
||||||
return FALSE
|
|
||||||
var/dpath = loaded_item.type
|
|
||||||
var/list/worths = TN.boost_item_paths[dpath]
|
|
||||||
var/list/differences = list()
|
|
||||||
var/list/already_boosted = stored_research.boosted_nodes[TN.id]
|
|
||||||
for(var/i in worths)
|
|
||||||
var/used = already_boosted? already_boosted[i] : 0
|
|
||||||
var/value = min(worths[i], TN.research_costs[i]) - used
|
|
||||||
if(value > 0)
|
|
||||||
differences[i] = value
|
|
||||||
if(length(worths) && !length(differences))
|
|
||||||
return FALSE
|
|
||||||
var/choice = tgui_alert(user, "Are you sure you want to destroy [loaded_item] to [!length(worths) ? "reveal [TN.display_name]" : "boost [TN.display_name] by [json_encode(differences)] point\s"]?", "Destructive Analyzer", list("Proceed", "Cancel"))
|
|
||||||
if(choice != "Proceed")
|
|
||||||
return FALSE
|
|
||||||
if(QDELETED(loaded_item) || QDELETED(src))
|
|
||||||
return FALSE
|
|
||||||
SSblackbox.record_feedback("nested tally", "item_deconstructed", 1, list("[TN.id]", "[loaded_item.type]"))
|
|
||||||
if(destroy_item(loaded_item))
|
|
||||||
stored_research.boost_with_item(SSresearch.techweb_node_by_id(TN.id), dpath)
|
|
||||||
|
|
||||||
else
|
|
||||||
var/list/point_value = techweb_item_point_check(loaded_item)
|
|
||||||
if(stored_research.deconstructed_items[loaded_item.type])
|
|
||||||
point_value = list()
|
|
||||||
var/user_mode_string = ""
|
|
||||||
if(length(point_value))
|
|
||||||
user_mode_string = " for [json_encode(point_value)] points"
|
|
||||||
var/choice = tgui_alert(usr, "Are you sure you want to destroy [loaded_item][user_mode_string]?",, list("Proceed", "Cancel"))
|
|
||||||
if(choice == "Cancel")
|
|
||||||
return FALSE
|
|
||||||
if(QDELETED(loaded_item) || QDELETED(src))
|
|
||||||
return FALSE
|
|
||||||
destroy_item(loaded_item)
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/proc/unload_item()
|
|
||||||
if(!loaded_item)
|
|
||||||
return FALSE
|
|
||||||
loaded_item.forceMove(get_turf(src))
|
|
||||||
loaded_item = null
|
|
||||||
update_appearance()
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/ui_interact(mob/user)
|
|
||||||
. = ..()
|
|
||||||
var/datum/browser/popup = new(user, "destructive_analyzer", name, 900, 600)
|
|
||||||
popup.set_content(ui_deconstruct())
|
|
||||||
popup.open()
|
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/proc/ui_deconstruct() //Legacy code
|
|
||||||
var/list/l = list()
|
|
||||||
if(!loaded_item)
|
|
||||||
l += "<div class='statusDisplay'>No item loaded. Standing-by...</div>"
|
|
||||||
else
|
|
||||||
l += "<div class='statusDisplay'>[RDSCREEN_NOBREAK]"
|
|
||||||
l += "<table><tr><td>[icon2html(loaded_item, usr)]</td><td><b>[loaded_item.name]</b> <A href='?src=[REF(src)];eject_item=1'>Eject</A></td></tr></table>[RDSCREEN_NOBREAK]"
|
|
||||||
l += "Select a node to boost by deconstructing this item. This item can boost:"
|
|
||||||
|
|
||||||
var/anything = FALSE
|
|
||||||
var/list/boostable_nodes = techweb_item_boost_check(loaded_item)
|
|
||||||
for(var/id in boostable_nodes)
|
for(var/id in boostable_nodes)
|
||||||
anything = TRUE
|
var/datum/techweb_node/unlockable_node = SSresearch.techweb_node_by_id(id)
|
||||||
var/list/worth = boostable_nodes[id]
|
var/list/node_data = list()
|
||||||
var/datum/techweb_node/N = SSresearch.techweb_node_by_id(id)
|
node_data["node_name"] = unlockable_node.display_name
|
||||||
|
node_data["node_id"] = unlockable_node.id
|
||||||
l += "<div class='statusDisplay'>[RDSCREEN_NOBREAK]"
|
node_data["node_hidden"] = !!stored_research.hidden_nodes[unlockable_node.id]
|
||||||
if (stored_research.researched_nodes[N.id]) // already researched
|
data["node_data"] += list(node_data)
|
||||||
l += "<span class='linkOff'>[N.display_name]</span>"
|
|
||||||
l += "This node has already been researched."
|
|
||||||
else if(!length(worth)) // reveal only
|
|
||||||
if (stored_research.hidden_nodes[N.id])
|
|
||||||
l += "<A href='?src=[REF(src)];deconstruct=[N.id]'>[N.display_name]</A>"
|
|
||||||
l += "This node will be revealed."
|
|
||||||
else
|
else
|
||||||
l += "<span class='linkOff'>[N.display_name]</span>"
|
data["loaded_item"] = null
|
||||||
l += "This node has already been revealed."
|
return data
|
||||||
else // boost by the difference
|
|
||||||
var/list/differences = list()
|
|
||||||
var/list/already_boosted = stored_research.boosted_nodes[N.id]
|
|
||||||
for(var/i in worth)
|
|
||||||
var/already_boosted_amount = already_boosted? stored_research.boosted_nodes[N.id][i] : 0
|
|
||||||
var/amt = min(worth[i], N.research_costs[i]) - already_boosted_amount
|
|
||||||
if(amt > 0)
|
|
||||||
differences[i] = amt
|
|
||||||
if (length(differences))
|
|
||||||
l += "<A href='?src=[REF(src)];deconstruct=[N.id]'>[N.display_name]</A>"
|
|
||||||
l += "This node will be boosted with the following:<BR>[techweb_point_display_generic(differences)]"
|
|
||||||
else
|
|
||||||
l += "<span class='linkOff'>[N.display_name]</span>"
|
|
||||||
l += "This node has already been boosted.</span>"
|
|
||||||
l += "</div>[RDSCREEN_NOBREAK]"
|
|
||||||
|
|
||||||
var/list/point_values = techweb_item_point_check(loaded_item)
|
/obj/machinery/rnd/destructive_analyzer/ui_static_data(mob/user)
|
||||||
if(point_values)
|
var/list/data = list()
|
||||||
anything = TRUE
|
data["research_point_id"] = DESTRUCTIVE_ANALYZER_DESTROY_POINTS
|
||||||
l += "<div class='statusDisplay'>[RDSCREEN_NOBREAK]"
|
return data
|
||||||
if (stored_research.deconstructed_items[loaded_item.type])
|
|
||||||
l += "<span class='linkOff'>Point Deconstruction</span>"
|
|
||||||
l += "This item's points have already been claimed."
|
|
||||||
else
|
|
||||||
l += "<A href='?src=[REF(src)];deconstruct=[RESEARCH_MATERIAL_DESTROY_ID]'>Point Deconstruction</A>"
|
|
||||||
l += "This item is worth: <BR>[techweb_point_display_generic(point_values)]!"
|
|
||||||
l += "</div>[RDSCREEN_NOBREAK]"
|
|
||||||
|
|
||||||
if(!(loaded_item.resistance_flags & INDESTRUCTIBLE))
|
/obj/machinery/rnd/destructive_analyzer/ui_act(action, params, datum/tgui/ui)
|
||||||
l += "<div class='statusDisplay'><A href='?src=[REF(src)];deconstruct=[RESEARCH_MATERIAL_DESTROY_ID]'>Destroy Item</A>"
|
|
||||||
l += "</div>[RDSCREEN_NOBREAK]"
|
|
||||||
anything = TRUE
|
|
||||||
|
|
||||||
if (!anything)
|
|
||||||
l += "Nothing!"
|
|
||||||
|
|
||||||
l += "</div>"
|
|
||||||
|
|
||||||
for(var/i in 1 to length(l))
|
|
||||||
if(!findtextEx(l[i], RDSCREEN_NOBREAK))
|
|
||||||
l[i] += "<br>"
|
|
||||||
. = l.Join("")
|
|
||||||
return replacetextEx(., RDSCREEN_NOBREAK, "")
|
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/Topic(raw, ls)
|
|
||||||
. = ..()
|
. = ..()
|
||||||
if(.)
|
if(.)
|
||||||
return
|
return
|
||||||
|
|
||||||
add_fingerprint(usr)
|
var/mob/user = usr
|
||||||
usr.set_machine(src)
|
switch(action)
|
||||||
|
if("eject_item")
|
||||||
if(ls["eject_item"]) //Eject the item inside the destructive analyzer.
|
|
||||||
if(busy)
|
if(busy)
|
||||||
to_chat(usr, span_danger("The destructive analyzer is busy at the moment."))
|
balloon_alert(user, "already busy!")
|
||||||
return
|
return TRUE
|
||||||
if(loaded_item)
|
if(loaded_item)
|
||||||
unload_item()
|
unload_item()
|
||||||
if(ls["deconstruct"])
|
return TRUE
|
||||||
if(!user_try_decon_id(ls["deconstruct"], usr))
|
if("deconstruct")
|
||||||
|
if(!user_try_decon_id(params["deconstruct_id"]))
|
||||||
say("Destructive analysis failed!")
|
say("Destructive analysis failed!")
|
||||||
|
return TRUE
|
||||||
|
|
||||||
updateUsrDialog()
|
//This allows people to put syndicate screwdrivers in the machine. Secondary act still passes.
|
||||||
|
|
||||||
/obj/machinery/rnd/destructive_analyzer/screwdriver_act(mob/living/user, obj/item/tool)
|
/obj/machinery/rnd/destructive_analyzer/screwdriver_act(mob/living/user, obj/item/tool)
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
|
///Drops the loaded item where it can and nulls it.
|
||||||
|
/obj/machinery/rnd/destructive_analyzer/proc/unload_item()
|
||||||
|
if(!loaded_item)
|
||||||
|
return FALSE
|
||||||
|
playsound(loc, 'sound/machines/terminal_insert_disc.ogg', 30, FALSE)
|
||||||
|
loaded_item.forceMove(drop_location())
|
||||||
|
loaded_item = null
|
||||||
|
update_appearance(UPDATE_ICON)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
///Called in a timer callback after loading something into it, this handles resetting the 'busy' state back to its initial state
|
||||||
|
///So the machine can be used.
|
||||||
|
/obj/machinery/rnd/destructive_analyzer/proc/finish_loading()
|
||||||
|
update_appearance(UPDATE_ICON)
|
||||||
|
reset_busy()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys an item by going through all its contents (including itself) and calling destroy_item_individual
|
||||||
|
* Args:
|
||||||
|
* gain_research_points - Whether deconstructing each individual item should check for research points to boost.
|
||||||
|
*/
|
||||||
|
/obj/machinery/rnd/destructive_analyzer/proc/destroy_item(gain_research_points = FALSE)
|
||||||
|
if(QDELETED(loaded_item) || QDELETED(src))
|
||||||
|
return FALSE
|
||||||
|
flick("[base_icon_state]_process", src)
|
||||||
|
busy = TRUE
|
||||||
|
addtimer(CALLBACK(src, PROC_REF(reset_busy)), 2.4 SECONDS)
|
||||||
|
use_power(DESTRUCTIVE_ANALYZER_POWER_USAGE)
|
||||||
|
var/list/all_contents = loaded_item.get_all_contents()
|
||||||
|
for(var/innerthing in all_contents)
|
||||||
|
destroy_item_individual(innerthing, gain_research_points)
|
||||||
|
|
||||||
|
loaded_item = null
|
||||||
|
update_appearance(UPDATE_ICON)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the individual provided item
|
||||||
|
* Args:
|
||||||
|
* thing - The thing being destroyed. Generally an object, but it can be a mob too, such as intellicards and pAIs.
|
||||||
|
* gain_research_points - Whether deconstructing this should give research points to the stored techweb, if applicable.
|
||||||
|
*/
|
||||||
|
/obj/machinery/rnd/destructive_analyzer/proc/destroy_item_individual(obj/item/thing, gain_research_points = FALSE)
|
||||||
|
if(isliving(thing))
|
||||||
|
var/mob/living/mob_thing = thing
|
||||||
|
if(mob_thing.stat != DEAD)
|
||||||
|
mob_thing.investigate_log("has been killed by a destructive analyzer.", INVESTIGATE_DEATHS)
|
||||||
|
mob_thing.death()
|
||||||
|
var/list/point_value = techweb_item_point_check(thing)
|
||||||
|
if(point_value && !stored_research.deconstructed_items[thing.type])
|
||||||
|
stored_research.deconstructed_items[thing.type] = TRUE
|
||||||
|
stored_research.add_point_list(list(TECHWEB_POINT_TYPE_GENERIC = point_value))
|
||||||
|
qdel(thing)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to destroy the loaded item using a provided research id.
|
||||||
|
* Args:
|
||||||
|
* id - The techweb ID node that we're meant to unlock if applicable.
|
||||||
|
*/
|
||||||
|
/obj/machinery/rnd/destructive_analyzer/proc/user_try_decon_id(id)
|
||||||
|
if(!istype(loaded_item))
|
||||||
|
return FALSE
|
||||||
|
if(isnull(id))
|
||||||
|
return FALSE
|
||||||
|
|
||||||
|
if(id == DESTRUCTIVE_ANALYZER_DESTROY_POINTS)
|
||||||
|
if(!destroy_item(gain_research_points = TRUE))
|
||||||
|
return FALSE
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
var/datum/techweb_node/node_to_discover = SSresearch.techweb_node_by_id(id)
|
||||||
|
if(!istype(node_to_discover))
|
||||||
|
return FALSE
|
||||||
|
SSblackbox.record_feedback("nested tally", "item_deconstructed", 1, list("[node_to_discover.id]", "[loaded_item.type]"))
|
||||||
|
if(!destroy_item())
|
||||||
|
return FALSE
|
||||||
|
stored_research.unhide_node(SSresearch.techweb_node_by_id(node_to_discover.id))
|
||||||
|
return TRUE
|
||||||
|
|
||||||
|
#undef DESTRUCTIVE_ANALYZER_DESTROY_POINTS
|
||||||
|
#undef DESTRUCTIVE_ANALYZER_POWER_USAGE
|
||||||
|
|||||||
@@ -42,12 +42,6 @@
|
|||||||
var/static/list/valid_items //valid items for special reactions like transforming
|
var/static/list/valid_items //valid items for special reactions like transforming
|
||||||
var/list/critical_items_typecache //items that can cause critical reactions
|
var/list/critical_items_typecache //items that can cause critical reactions
|
||||||
|
|
||||||
/obj/machinery/rnd/experimentor/proc/ConvertReqString2List(list/source_list)
|
|
||||||
var/list/temp_list = params2list(source_list)
|
|
||||||
for(var/O in temp_list)
|
|
||||||
temp_list[O] = text2num(temp_list[O])
|
|
||||||
return temp_list
|
|
||||||
|
|
||||||
/obj/machinery/rnd/experimentor/proc/valid_items()
|
/obj/machinery/rnd/experimentor/proc/valid_items()
|
||||||
RETURN_TYPE(/list)
|
RETURN_TYPE(/list)
|
||||||
|
|
||||||
@@ -131,20 +125,22 @@
|
|||||||
return FALSE
|
return FALSE
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/obj/machinery/rnd/experimentor/Insert_Item(obj/item/O, mob/living/user)
|
/obj/machinery/rnd/experimentor/attackby(obj/item/weapon, mob/living/user, params)
|
||||||
if(!user.combat_mode)
|
if(user.combat_mode)
|
||||||
. = 1
|
return ..()
|
||||||
if(!is_insertion_ready(user))
|
if(!is_insertion_ready(user))
|
||||||
return
|
return ..()
|
||||||
if(!user.transferItemToLoc(O, src))
|
if(!user.transferItemToLoc(weapon, src))
|
||||||
return
|
to_chat(user, span_warning("\The [weapon] is stuck to your hand, you cannot put it in the [name]!"))
|
||||||
loaded_item = O
|
return TRUE
|
||||||
to_chat(user, span_notice("You add [O] to the machine."))
|
loaded_item = weapon
|
||||||
|
to_chat(user, span_notice("You add [weapon] to the machine."))
|
||||||
flick("h_lathe_load", src)
|
flick("h_lathe_load", src)
|
||||||
|
return TRUE
|
||||||
|
|
||||||
/obj/machinery/rnd/experimentor/default_deconstruction_crowbar(obj/item/O)
|
/obj/machinery/rnd/experimentor/default_deconstruction_crowbar(obj/item/O)
|
||||||
ejectItem()
|
ejectItem()
|
||||||
. = ..(O)
|
return ..(O)
|
||||||
|
|
||||||
/obj/machinery/rnd/experimentor/ui_interact(mob/user)
|
/obj/machinery/rnd/experimentor/ui_interact(mob/user)
|
||||||
var/list/dat = list("<center>")
|
var/list/dat = list("<center>")
|
||||||
@@ -161,22 +157,19 @@
|
|||||||
if(istype(loaded_item,/obj/item/relic))
|
if(istype(loaded_item,/obj/item/relic))
|
||||||
dat += "<b><a href='byond://?src=[REF(src)];item=[REF(loaded_item)];function=[SCANTYPE_DISCOVER]'>Discover</A></b>"
|
dat += "<b><a href='byond://?src=[REF(src)];item=[REF(loaded_item)];function=[SCANTYPE_DISCOVER]'>Discover</A></b>"
|
||||||
dat += "<b><a href='byond://?src=[REF(src)];function=eject'>Eject</A>"
|
dat += "<b><a href='byond://?src=[REF(src)];function=eject'>Eject</A>"
|
||||||
var/list/listin = techweb_item_boost_check(src)
|
var/list/listin = techweb_item_unlock_check(src)
|
||||||
if(listin)
|
if(listin)
|
||||||
var/list/output = list("<b><font color='purple'>Research Boost Data:</font></b>")
|
var/list/output = list("<b><font color='purple'>Research Boost Data:</font></b>")
|
||||||
var/list/res = list("<b><font color='blue'>Already researched:</font></b>")
|
var/list/res = list("<b><font color='blue'>Already researched:</font></b>")
|
||||||
var/list/boosted = list("<b><font color='red'>Already boosted:</font></b>")
|
|
||||||
for(var/node_id in listin)
|
for(var/node_id in listin)
|
||||||
var/datum/techweb_node/N = SSresearch.techweb_node_by_id(node_id)
|
var/datum/techweb_node/N = SSresearch.techweb_node_by_id(node_id)
|
||||||
var/str = "<b>[N.display_name]</b>: [listin[N]] points.</b>"
|
var/str = "<b>[N.display_name]</b>: [listin[N]] points.</b>"
|
||||||
var/datum/techweb/science_web = locate(/datum/techweb/science) in SSresearch.techwebs
|
var/datum/techweb/science_web = locate(/datum/techweb/science) in SSresearch.techwebs
|
||||||
if(science_web.researched_nodes[N.id])
|
if(science_web.researched_nodes[N.id])
|
||||||
res += str
|
res += str
|
||||||
else if(science_web.boosted_nodes[N.id])
|
|
||||||
boosted += str
|
|
||||||
if(science_web.visible_nodes[N.id]) //JOY OF DISCOVERY!
|
if(science_web.visible_nodes[N.id]) //JOY OF DISCOVERY!
|
||||||
output += str
|
output += str
|
||||||
output += boosted + res
|
output += res
|
||||||
dat += output
|
dat += output
|
||||||
else
|
else
|
||||||
dat += "<b>Nothing loaded.</b>"
|
dat += "<b>Nothing loaded.</b>"
|
||||||
@@ -218,9 +211,9 @@
|
|||||||
experiment(dotype,process)
|
experiment(dotype,process)
|
||||||
use_power(750)
|
use_power(750)
|
||||||
if(dotype != FAIL)
|
if(dotype != FAIL)
|
||||||
var/list/nodes = techweb_item_boost_check(process)
|
var/list/nodes = techweb_item_unlock_check(process)
|
||||||
var/picked = pick_weight(nodes) //This should work.
|
var/picked = pick_weight(nodes) //This should work.
|
||||||
stored_research.boost_with_item(SSresearch.techweb_node_by_id(picked), process.type)
|
stored_research.unhide_node(SSresearch.techweb_node_by_id(picked))
|
||||||
updateUsrDialog()
|
updateUsrDialog()
|
||||||
|
|
||||||
/obj/machinery/rnd/experimentor/proc/matchReaction(matching,reaction)
|
/obj/machinery/rnd/experimentor/proc/matchReaction(matching,reaction)
|
||||||
|
|||||||
@@ -287,21 +287,20 @@
|
|||||||
/// List of ordnance experiments that our partner is willing to accept. If this list is not filled it means the partner will accept everything.
|
/// List of ordnance experiments that our partner is willing to accept. If this list is not filled it means the partner will accept everything.
|
||||||
var/list/accepted_experiments = list()
|
var/list/accepted_experiments = list()
|
||||||
/// Associative list of which technology the partner might be able to boost and by how much.
|
/// Associative list of which technology the partner might be able to boost and by how much.
|
||||||
var/list/boosted_nodes = list()
|
var/list/boostable_nodes = list()
|
||||||
|
|
||||||
|
|
||||||
/datum/scientific_partner/proc/purchase_boost(datum/techweb/purchasing_techweb, datum/techweb_node/node)
|
/datum/scientific_partner/proc/purchase_boost(datum/techweb/purchasing_techweb, datum/techweb_node/node)
|
||||||
if(!allowed_to_boost(purchasing_techweb, node.id))
|
if(!allowed_to_boost(purchasing_techweb, node.id))
|
||||||
return FALSE
|
return FALSE
|
||||||
purchasing_techweb.boost_techweb_node(node, list(TECHWEB_POINT_TYPE_GENERIC=boosted_nodes[node.id]))
|
purchasing_techweb.boost_techweb_node(node, list(TECHWEB_POINT_TYPE_GENERIC = boostable_nodes[node.id]))
|
||||||
purchasing_techweb.scientific_cooperation[type] -= boosted_nodes[node.id] * SCIENTIFIC_COOPERATION_PURCHASE_MULTIPLIER
|
purchasing_techweb.scientific_cooperation[type] -= boostable_nodes[node.id] * SCIENTIFIC_COOPERATION_PURCHASE_MULTIPLIER
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/datum/scientific_partner/proc/allowed_to_boost(datum/techweb/purchasing_techweb, node_id)
|
/datum/scientific_partner/proc/allowed_to_boost(datum/techweb/purchasing_techweb, node_id)
|
||||||
if(purchasing_techweb.scientific_cooperation[type] < (boosted_nodes[node_id] * SCIENTIFIC_COOPERATION_PURCHASE_MULTIPLIER)) // Too expensive
|
if(purchasing_techweb.scientific_cooperation[type] < (boostable_nodes[node_id] * SCIENTIFIC_COOPERATION_PURCHASE_MULTIPLIER)) // Too expensive
|
||||||
return FALSE
|
return FALSE
|
||||||
if(!(node_id in purchasing_techweb.get_available_nodes())) // Not currently available
|
if(!(node_id in purchasing_techweb.get_available_nodes())) // Not currently available
|
||||||
return FALSE
|
return FALSE
|
||||||
if((TECHWEB_POINT_TYPE_GENERIC in purchasing_techweb.boosted_nodes[node_id]) && (purchasing_techweb.boosted_nodes[node_id][TECHWEB_POINT_TYPE_GENERIC] >= boosted_nodes[node_id])) // Already bought or we have a bigger discount
|
if((TECHWEB_POINT_TYPE_GENERIC in purchasing_techweb.boosted_nodes[node_id]) && (purchasing_techweb.boosted_nodes[node_id][TECHWEB_POINT_TYPE_GENERIC] >= boostable_nodes[node_id])) // Already bought or we have a bigger discount
|
||||||
return FALSE
|
return FALSE
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
flufftext = "A local group of miners are looking for ways to improve their mining output. They are interested in smaller scale explosives."
|
flufftext = "A local group of miners are looking for ways to improve their mining output. They are interested in smaller scale explosives."
|
||||||
accepted_experiments = list(/datum/experiment/ordnance/explosive/lowyieldbomb)
|
accepted_experiments = list(/datum/experiment/ordnance/explosive/lowyieldbomb)
|
||||||
multipliers = list(SCIPAPER_COOPERATION_INDEX = 0.75, SCIPAPER_FUNDING_INDEX = 0.75)
|
multipliers = list(SCIPAPER_COOPERATION_INDEX = 0.75, SCIPAPER_FUNDING_INDEX = 0.75)
|
||||||
boosted_nodes = list(
|
boostable_nodes = list(
|
||||||
"bluespace_basic" = 2000,
|
"bluespace_basic" = 2000,
|
||||||
"NVGtech" = 1500,
|
"NVGtech" = 1500,
|
||||||
"practical_bluespace" = 2500,
|
"practical_bluespace" = 2500,
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
name = "Ghost Writing"
|
name = "Ghost Writing"
|
||||||
flufftext = "A nearby research station ran by a very wealthy captain seems to be struggling with their scientific output. They might reward us handsomely if we ghostwrite for them."
|
flufftext = "A nearby research station ran by a very wealthy captain seems to be struggling with their scientific output. They might reward us handsomely if we ghostwrite for them."
|
||||||
multipliers = list(SCIPAPER_COOPERATION_INDEX = 0.25, SCIPAPER_FUNDING_INDEX = 2)
|
multipliers = list(SCIPAPER_COOPERATION_INDEX = 0.25, SCIPAPER_FUNDING_INDEX = 2)
|
||||||
boosted_nodes = list(
|
boostable_nodes = list(
|
||||||
"comp_recordkeeping" = 500,
|
"comp_recordkeeping" = 500,
|
||||||
"computer_data_disks" = 500,
|
"computer_data_disks" = 500,
|
||||||
)
|
)
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
/datum/experiment/ordnance/explosive/pressurebomb,
|
/datum/experiment/ordnance/explosive/pressurebomb,
|
||||||
/datum/experiment/ordnance/explosive/hydrogenbomb,
|
/datum/experiment/ordnance/explosive/hydrogenbomb,
|
||||||
)
|
)
|
||||||
boosted_nodes = list(
|
boostable_nodes = list(
|
||||||
"adv_weaponry" = 5000,
|
"adv_weaponry" = 5000,
|
||||||
"weaponry" = 2500,
|
"weaponry" = 2500,
|
||||||
"sec_basic" = 1250,
|
"sec_basic" = 1250,
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
/datum/experiment/ordnance/gaseous/nitrous_oxide,
|
/datum/experiment/ordnance/gaseous/nitrous_oxide,
|
||||||
/datum/experiment/ordnance/gaseous/bz,
|
/datum/experiment/ordnance/gaseous/bz,
|
||||||
)
|
)
|
||||||
boosted_nodes = list(
|
boostable_nodes = list(
|
||||||
"cyber_organs" = 750,
|
"cyber_organs" = 750,
|
||||||
"cyber_organs_upgraded" = 1000,
|
"cyber_organs_upgraded" = 1000,
|
||||||
"genetics" = 500,
|
"genetics" = 500,
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
/datum/experiment/ordnance/gaseous/noblium,
|
/datum/experiment/ordnance/gaseous/noblium,
|
||||||
/datum/experiment/ordnance/explosive/nobliumbomb,
|
/datum/experiment/ordnance/explosive/nobliumbomb,
|
||||||
)
|
)
|
||||||
boosted_nodes = list(
|
boostable_nodes = list(
|
||||||
"engineering" = 5000,
|
"engineering" = 5000,
|
||||||
"adv_engi" = 5000,
|
"adv_engi" = 5000,
|
||||||
"emp_super" = 3000,
|
"emp_super" = 3000,
|
||||||
|
|||||||
@@ -11,9 +11,10 @@
|
|||||||
var/hacked = FALSE
|
var/hacked = FALSE
|
||||||
var/console_link = TRUE //allow console link.
|
var/console_link = TRUE //allow console link.
|
||||||
var/disabled = FALSE
|
var/disabled = FALSE
|
||||||
var/obj/item/loaded_item = null //the item loaded inside the machine (currently only used by experimentor and destructive analyzer)
|
|
||||||
/// Ref to global science techweb.
|
/// Ref to global science techweb.
|
||||||
var/datum/techweb/stored_research
|
var/datum/techweb/stored_research
|
||||||
|
///The item loaded inside the machine, used by experimentors and destructive analyzers only.
|
||||||
|
var/obj/item/loaded_item
|
||||||
|
|
||||||
/obj/machinery/rnd/proc/reset_busy()
|
/obj/machinery/rnd/proc/reset_busy()
|
||||||
busy = FALSE
|
busy = FALSE
|
||||||
@@ -59,14 +60,6 @@
|
|||||||
else
|
else
|
||||||
return FALSE
|
return FALSE
|
||||||
|
|
||||||
/obj/machinery/rnd/attackby(obj/item/O, mob/user, params)
|
|
||||||
if(is_refillable() && O.is_drainable())
|
|
||||||
return FALSE //inserting reagents into the machine
|
|
||||||
if(Insert_Item(O, user))
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
return ..()
|
|
||||||
|
|
||||||
/obj/machinery/rnd/crowbar_act(mob/living/user, obj/item/tool)
|
/obj/machinery/rnd/crowbar_act(mob/living/user, obj/item/tool)
|
||||||
return default_deconstruction_crowbar(tool)
|
return default_deconstruction_crowbar(tool)
|
||||||
|
|
||||||
@@ -103,36 +96,32 @@
|
|||||||
wires.interact(user)
|
wires.interact(user)
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
//proc used to handle inserting items or reagents into rnd machines
|
|
||||||
/obj/machinery/rnd/proc/Insert_Item(obj/item/I, mob/user)
|
|
||||||
return
|
|
||||||
|
|
||||||
//whether the machine can have an item inserted in its current state.
|
//whether the machine can have an item inserted in its current state.
|
||||||
/obj/machinery/rnd/proc/is_insertion_ready(mob/user)
|
/obj/machinery/rnd/proc/is_insertion_ready(mob/user)
|
||||||
if(panel_open)
|
if(panel_open)
|
||||||
to_chat(user, span_warning("You can't load [src] while it's opened!"))
|
balloon_alert(user, "panel open!")
|
||||||
return FALSE
|
return FALSE
|
||||||
if(disabled)
|
if(disabled)
|
||||||
to_chat(user, span_warning("The insertion belts of [src] won't engage!"))
|
balloon_alert(user, "belts disabled!")
|
||||||
return FALSE
|
return FALSE
|
||||||
if(busy)
|
if(busy)
|
||||||
to_chat(user, span_warning("[src] is busy right now."))
|
balloon_alert(user, "still busy!")
|
||||||
return FALSE
|
return FALSE
|
||||||
if(machine_stat & BROKEN)
|
if(machine_stat & BROKEN)
|
||||||
to_chat(user, span_warning("[src] is broken."))
|
balloon_alert(user, "machine broken!")
|
||||||
return FALSE
|
return FALSE
|
||||||
if(machine_stat & NOPOWER)
|
if(machine_stat & NOPOWER)
|
||||||
to_chat(user, span_warning("[src] has no power."))
|
balloon_alert(user, "no power!")
|
||||||
return FALSE
|
return FALSE
|
||||||
if(loaded_item)
|
if(loaded_item)
|
||||||
to_chat(user, span_warning("[src] is already loaded."))
|
balloon_alert(user, "item already loaded!")
|
||||||
return FALSE
|
return FALSE
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
//we eject the loaded item when deconstructing the machine
|
//we eject the loaded item when deconstructing the machine
|
||||||
/obj/machinery/rnd/on_deconstruction()
|
/obj/machinery/rnd/on_deconstruction()
|
||||||
if(loaded_item)
|
if(loaded_item)
|
||||||
loaded_item.forceMove(loc)
|
loaded_item.forceMove(drop_location())
|
||||||
..()
|
..()
|
||||||
|
|
||||||
/obj/machinery/rnd/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
|
/obj/machinery/rnd/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
|
||||||
|
|||||||
@@ -10,14 +10,15 @@
|
|||||||
WARNING("Invalid boost information for node \[[id]\]: [message]")
|
WARNING("Invalid boost information for node \[[id]\]: [message]")
|
||||||
SSresearch.invalid_node_boost[id] = message
|
SSresearch.invalid_node_boost[id] = message
|
||||||
|
|
||||||
///Returns an associative list of techweb node datums with values of the boost it gives. var/list/returned = list()
|
///Returns an associative list of techweb node datums with values of the nodes it unlocks.
|
||||||
/proc/techweb_item_boost_check(obj/item/I)
|
/proc/techweb_item_unlock_check(obj/item/I)
|
||||||
if(SSresearch.techweb_boost_items[I.type])
|
if(SSresearch.techweb_unlock_items[I.type])
|
||||||
return SSresearch.techweb_boost_items[I.type] //It should already be formatted in node datum = list(point type = value)
|
return SSresearch.techweb_unlock_items[I.type] //It should already be formatted in node datum = list(point type = value)
|
||||||
|
|
||||||
/proc/techweb_item_point_check(obj/item/I)
|
/proc/techweb_item_point_check(obj/item/I)
|
||||||
if(SSresearch.techweb_point_items[I.type])
|
if(SSresearch.techweb_point_items[I.type])
|
||||||
return SSresearch.techweb_point_items[I.type]
|
return SSresearch.techweb_point_items[I.type]
|
||||||
|
return FALSE
|
||||||
|
|
||||||
/proc/techweb_point_display_generic(pointlist)
|
/proc/techweb_point_display_generic(pointlist)
|
||||||
var/list/ret = list()
|
var/list/ret = list()
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
var/list/boosted_nodes = list()
|
var/list/boosted_nodes = list()
|
||||||
/// Hidden nodes. id = TRUE. Used for unhiding nodes when requirements are met by removing the entry of the node.
|
/// Hidden nodes. id = TRUE. Used for unhiding nodes when requirements are met by removing the entry of the node.
|
||||||
var/list/hidden_nodes = list()
|
var/list/hidden_nodes = list()
|
||||||
/// Items already deconstructed for a generic point boost, path = list(point_type = points)
|
/// List of items already deconstructed for research points, preventing infinite research point generation.
|
||||||
var/list/deconstructed_items = list()
|
var/list/deconstructed_items = list()
|
||||||
/// Available research points, type = number
|
/// Available research points, type = number
|
||||||
var/list/research_points = list()
|
var/list/research_points = list()
|
||||||
@@ -400,17 +400,15 @@
|
|||||||
LAZYINITLIST(boosted_nodes[node.id])
|
LAZYINITLIST(boosted_nodes[node.id])
|
||||||
for(var/point_type in pointlist)
|
for(var/point_type in pointlist)
|
||||||
boosted_nodes[node.id][point_type] = max(boosted_nodes[node.id][point_type], pointlist[point_type])
|
boosted_nodes[node.id][point_type] = max(boosted_nodes[node.id][point_type], pointlist[point_type])
|
||||||
if(node.autounlock_by_boost)
|
unhide_node(node)
|
||||||
hidden_nodes -= node.id
|
|
||||||
update_node_status(node)
|
update_node_status(node)
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/// Boosts a techweb node by using items.
|
///Removes a node from the hidden_nodes list, making it viewable and researchable (if no experiments are required).
|
||||||
/datum/techweb/proc/boost_with_item(datum/techweb_node/node, itempath)
|
/datum/techweb/proc/unhide_node(datum/techweb_node/node)
|
||||||
if(!istype(node) || !ispath(itempath))
|
if(!istype(node))
|
||||||
return FALSE
|
return FALSE
|
||||||
var/list/boost_amount = node.boost_item_paths[itempath]
|
hidden_nodes -= node.id
|
||||||
boost_techweb_node(node, boost_amount)
|
|
||||||
return TRUE
|
return TRUE
|
||||||
|
|
||||||
/datum/techweb/proc/update_tiers(datum/techweb_node/base)
|
/datum/techweb/proc/update_tiers(datum/techweb_node/base)
|
||||||
|
|||||||
@@ -24,8 +24,8 @@
|
|||||||
var/list/design_ids = list()
|
var/list/design_ids = list()
|
||||||
/// CALCULATED FROM OTHER NODE'S PREREQUISITIES. Associated list id = TRUE
|
/// CALCULATED FROM OTHER NODE'S PREREQUISITIES. Associated list id = TRUE
|
||||||
var/list/unlock_ids = list()
|
var/list/unlock_ids = list()
|
||||||
/// Associative list, path = list(point type = point_value)
|
/// List of items you need to deconstruct to unlock this node.
|
||||||
var/list/boost_item_paths = list()
|
var/list/required_items_to_unlock = list()
|
||||||
/// Boosting this will autounlock this node
|
/// Boosting this will autounlock this node
|
||||||
var/autounlock_by_boost = TRUE
|
var/autounlock_by_boost = TRUE
|
||||||
/// The points cost to research the node, type = amount
|
/// The points cost to research the node, type = amount
|
||||||
|
|||||||
@@ -2161,7 +2161,7 @@
|
|||||||
display_name = "Alien Technology"
|
display_name = "Alien Technology"
|
||||||
description = "Things used by the greys."
|
description = "Things used by the greys."
|
||||||
prereq_ids = list("biotech","engineering")
|
prereq_ids = list("biotech","engineering")
|
||||||
boost_item_paths = list(
|
required_items_to_unlock = list(
|
||||||
/obj/item/stack/sheet/mineral/abductor,
|
/obj/item/stack/sheet/mineral/abductor,
|
||||||
/obj/item/abductor,
|
/obj/item/abductor,
|
||||||
/obj/item/cautery/alien,
|
/obj/item/cautery/alien,
|
||||||
@@ -2204,7 +2204,7 @@
|
|||||||
"alien_scalpel",
|
"alien_scalpel",
|
||||||
)
|
)
|
||||||
|
|
||||||
boost_item_paths = list(
|
required_items_to_unlock = list(
|
||||||
/obj/item/abductor,
|
/obj/item/abductor,
|
||||||
/obj/item/cautery/alien,
|
/obj/item/cautery/alien,
|
||||||
/obj/item/circuitboard/machine/abductor,
|
/obj/item/circuitboard/machine/abductor,
|
||||||
@@ -2243,7 +2243,7 @@
|
|||||||
"alien_wrench",
|
"alien_wrench",
|
||||||
)
|
)
|
||||||
|
|
||||||
boost_item_paths = list(
|
required_items_to_unlock = list(
|
||||||
/obj/item/abductor,
|
/obj/item/abductor,
|
||||||
/obj/item/circuitboard/machine/abductor,
|
/obj/item/circuitboard/machine/abductor,
|
||||||
/obj/item/crowbar/abductor,
|
/obj/item/crowbar/abductor,
|
||||||
@@ -2296,12 +2296,12 @@
|
|||||||
/datum/techweb_node/syndicate_basic/proc/register_uplink_items()
|
/datum/techweb_node/syndicate_basic/proc/register_uplink_items()
|
||||||
SIGNAL_HANDLER
|
SIGNAL_HANDLER
|
||||||
UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE)
|
UnregisterSignal(SSearly_assets, COMSIG_SUBSYSTEM_POST_INITIALIZE)
|
||||||
boost_item_paths = list()
|
required_items_to_unlock = list()
|
||||||
for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type)
|
for(var/datum/uplink_item/item_path as anything in SStraitor.uplink_items_by_type)
|
||||||
var/datum/uplink_item/item = SStraitor.uplink_items_by_type[item_path]
|
var/datum/uplink_item/item = SStraitor.uplink_items_by_type[item_path]
|
||||||
if(!item.item || !item.illegal_tech)
|
if(!item.item || !item.illegal_tech)
|
||||||
continue
|
continue
|
||||||
boost_item_paths |= item.item //allows deconning to unlock.
|
required_items_to_unlock |= item.item //allows deconning to unlock.
|
||||||
|
|
||||||
|
|
||||||
////////////////////////B.E.P.I.S. Locked Techs////////////////////////
|
////////////////////////B.E.P.I.S. Locked Techs////////////////////////
|
||||||
|
|||||||
@@ -496,15 +496,5 @@
|
|||||||
return FALSE
|
return FALSE
|
||||||
return default_deconstruction_crowbar(I)
|
return default_deconstruction_crowbar(I)
|
||||||
|
|
||||||
/obj/machinery/mecha_part_fabricator/proc/is_insertion_ready(mob/user)
|
|
||||||
if(panel_open)
|
|
||||||
to_chat(user, span_warning("You can't load [src] while it's opened!"))
|
|
||||||
return FALSE
|
|
||||||
if(being_built)
|
|
||||||
to_chat(user, span_warning("\The [src] is currently processing! Please wait until completion."))
|
|
||||||
return FALSE
|
|
||||||
|
|
||||||
return TRUE
|
|
||||||
|
|
||||||
/obj/machinery/mecha_part_fabricator/maint
|
/obj/machinery/mecha_part_fabricator/maint
|
||||||
link_on_init = FALSE
|
link_on_init = FALSE
|
||||||
|
|||||||
@@ -163,17 +163,17 @@
|
|||||||
timer_id = null
|
timer_id = null
|
||||||
. = ..()
|
. = ..()
|
||||||
|
|
||||||
/obj/machinery/rnd/rna_recombinator/Insert_Item(obj/item/O, mob/living/user)
|
/obj/machinery/rnd/rna_recombinator/attackby(obj/item/weapon, mob/living/user, params)
|
||||||
if(user.combat_mode)
|
if(user.combat_mode)
|
||||||
return FALSE
|
return FALSE
|
||||||
if(!is_insertion_ready(user))
|
if(!is_insertion_ready(user))
|
||||||
return FALSE
|
return FALSE
|
||||||
if(!istype(O, /obj/item/rna_vial))
|
if(!istype(weapon, /obj/item/rna_vial))
|
||||||
return FALSE
|
return FALSE
|
||||||
if(!user.transferItemToLoc(O, src))
|
if(!user.transferItemToLoc(weapon, src))
|
||||||
return FALSE
|
return FALSE
|
||||||
loaded_item = O
|
loaded_item = weapon
|
||||||
to_chat(user, span_notice("You insert [O] to into [src] reciprocal."))
|
to_chat(user, span_notice("You insert [weapon] to into [src] reciprocal."))
|
||||||
flick("h_lathe_load", src)
|
flick("h_lathe_load", src)
|
||||||
update_appearance()
|
update_appearance()
|
||||||
playsound(loc, 'sound/weapons/autoguninsert.ogg', 35, 1)
|
playsound(loc, 'sound/weapons/autoguninsert.ogg', 35, 1)
|
||||||
|
|||||||
135
tgui/packages/tgui/interfaces/DestructiveAnalyzer.tsx
Normal file
135
tgui/packages/tgui/interfaces/DestructiveAnalyzer.tsx
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
import { BooleanLike } from 'common/react';
|
||||||
|
import { useBackend } from '../backend';
|
||||||
|
import { Button, Box, Section, NoticeBox } from '../components';
|
||||||
|
import { Window } from '../layouts';
|
||||||
|
|
||||||
|
type Data = {
|
||||||
|
server_connected: BooleanLike;
|
||||||
|
loaded_item: string;
|
||||||
|
item_icon: string;
|
||||||
|
indestructible: BooleanLike;
|
||||||
|
already_deconstructed: BooleanLike;
|
||||||
|
recoverable_points: string;
|
||||||
|
node_data: NodeData[];
|
||||||
|
research_point_id: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type NodeData = {
|
||||||
|
node_name: string;
|
||||||
|
node_id: string;
|
||||||
|
node_hidden: BooleanLike;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DestructiveAnalyzer = (props, context) => {
|
||||||
|
const { act, data } = useBackend<Data>(context);
|
||||||
|
const {
|
||||||
|
server_connected,
|
||||||
|
indestructible,
|
||||||
|
loaded_item,
|
||||||
|
item_icon,
|
||||||
|
already_deconstructed,
|
||||||
|
recoverable_points,
|
||||||
|
research_point_id,
|
||||||
|
node_data = [],
|
||||||
|
} = data;
|
||||||
|
if (!server_connected) {
|
||||||
|
return (
|
||||||
|
<Window width={400} height={260} title="Destructive Analyzer">
|
||||||
|
<Window.Content>
|
||||||
|
<NoticeBox textAlign="center" danger>
|
||||||
|
Not connected to a server. Please sync one using a multitool.
|
||||||
|
</NoticeBox>
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (!loaded_item) {
|
||||||
|
return (
|
||||||
|
<Window width={400} height={260} title="Destructive Analyzer">
|
||||||
|
<Window.Content>
|
||||||
|
<NoticeBox textAlign="center" danger>
|
||||||
|
No item loaded! <br />
|
||||||
|
Put any item inside to see what it's capable of!
|
||||||
|
</NoticeBox>
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<Window
|
||||||
|
width={400}
|
||||||
|
height={260}
|
||||||
|
scrollable
|
||||||
|
fill
|
||||||
|
title="Destructive Analyzer">
|
||||||
|
<Window.Content scrollable>
|
||||||
|
<Section
|
||||||
|
title={loaded_item}
|
||||||
|
buttons={
|
||||||
|
<Button
|
||||||
|
icon="eject"
|
||||||
|
tooltip="Ejects the item currently inside the machine."
|
||||||
|
onClick={() => act('eject_item')}
|
||||||
|
/>
|
||||||
|
}>
|
||||||
|
<Box
|
||||||
|
as="img"
|
||||||
|
src={`data:image/jpeg;base64,${item_icon}`}
|
||||||
|
height="64px"
|
||||||
|
width="64px"
|
||||||
|
style={{
|
||||||
|
'-ms-interpolation-mode': 'nearest-neighbor',
|
||||||
|
'vertical-align': 'middle',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
|
<Section title="Deconstruction Methods">
|
||||||
|
{!indestructible && (
|
||||||
|
<NoticeBox textAlign="center" danger>
|
||||||
|
This item can't be deconstructed!
|
||||||
|
</NoticeBox>
|
||||||
|
)}
|
||||||
|
{!!indestructible && (
|
||||||
|
<>
|
||||||
|
{!!recoverable_points && (
|
||||||
|
<>
|
||||||
|
<Box fontSize="14px">Research points from deconstruction</Box>
|
||||||
|
<Box>{recoverable_points}</Box>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
<Button.Confirm
|
||||||
|
content="Deconstruct"
|
||||||
|
icon="hammer"
|
||||||
|
tooltip={
|
||||||
|
already_deconstructed
|
||||||
|
? 'This item item has already been deconstructed, and will not give any additional information.'
|
||||||
|
: 'Destroys the object currently residing in the machine.'
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
act('deconstruct', { deconstruct_id: research_point_id })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
{node_data.map((node) => (
|
||||||
|
<Button.Confirm
|
||||||
|
content={node.node_name}
|
||||||
|
icon="cash-register"
|
||||||
|
mt={1}
|
||||||
|
disabled={!node.node_hidden}
|
||||||
|
key={node.node_id}
|
||||||
|
tooltip={
|
||||||
|
node.node_hidden
|
||||||
|
? 'Deconstructing this will allow you to research the node in question by making it visible to R&D consoles.'
|
||||||
|
: 'This node has already been researched, and does not need to be deconstructed.'
|
||||||
|
}
|
||||||
|
onClick={() =>
|
||||||
|
act('deconstruct', { deconstruct_id: node.node_id })
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</Section>
|
||||||
|
</Window.Content>
|
||||||
|
</Window>
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user