Files
Bubberstation/code/modules/research/destructive_analyzer.dm
SyncIt21 e4b23f2b4b General maintenance for Lathes (#81244)
## About The Pull Request
1. **Qol Stuff**
- Screentips & examines for screwdriver, crowbar acts, multiool &
wirecutter Also for Alt click
- Techfabs can now also use the Mouse drag functionality to set drop
target for items
- Lathe printing animation now plays on loop instead of just flicking
once till printing is finished for more visual feedback

2. **Code Improvements**
- Merged `start_making()` with `do_make_item()`. That proc was like only
3 lines long and used only in 1 place so let's just move that code to
`ui_act()`
- Merged `user_print_item_id()` with `ui_act()`. Again was used only in
1 place so let's just move that code in to save some proc overhead
- Sets `processing_flags` for autolathe to `NONE` cause we don't use
`process()`
    - Autodocs vars such as `hacked` , `shocked` etc & procs
- `maxmult` is now computed client side saving backend bandwidth,
`construction_time` is removed from lathes which did not use it
- Removed all usages of lathe taxes and their related vars, removed
engineering lathe no tax from ice moon, replaced with normal engineering
lathe

3. **Fixes**
- Lathe sheet insertion animations are now linked & work again for all
material types inserted via remote silo/local storage,
silver/titanium/plastic all play the same animation(that is
`protolathe_shiny` overlay). Other materials have their own respective
overlays
- Fixes #81243. Calling `update_static_data_for_all_viewers()` is too
expensive for the UI. We should instead use `SStgui.update_uis(src)`
which will report the `busy` status to the UI more immediatly
- Fixes #81236. Some problems with the params passed to the timer
callback. It should now print the correct number of requested items
- Fixes #81192. `design.materials` would runtime for custom material
items as they were list of texts not materials. We have to pass our
manually parsed list of materials for an specific item to ensure they
are set & used correctly. Same fixes apply for techfabs as well


## Changelog
🆑
qol: adds screentips & examines for screwdriver & crowbar acts & alt
click.
qol: techfabs can now use the mouse drop functionality to set drop
target.
qol: lathe printing animation plays on loop while printing rather than
flicking once for more visual feedback
fix: lathe sheet insertion animations are now linked & work again for
all material types inserted via remote silo/local storage
fix: printing custom materials items from autolathe works again.
fix: printing multiple items from lathes will actually print that
correct quantity of items requested.
fix: printing items the 2nd time around from lathes won't cause the UI
to reload each time.
code: autodoc for some vars & procs, merges procs.
refactor: Optimized code for autolathe & techfabs in general. Report
bugs on github
/🆑

---------

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
2024-02-08 13:34:03 +01:00

204 lines
7.1 KiB
Plaintext

///How much power it costs to deconstruct an item.
#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"
/**
* ## Destructive Analyzer
* It is used to destroy hand-held objects and advance technological research.
*/
/obj/machinery/rnd/destructive_analyzer
name = "destructive analyzer"
desc = "Learn science by destroying things!"
icon_state = "d_analyzer"
base_icon_state = "d_analyzer"
circuit = /obj/item/circuitboard/machine/destructive_analyzer
/obj/machinery/rnd/destructive_analyzer/add_context(atom/source, list/context, obj/item/held_item, mob/living/user)
. = ..()
var/screentip_set = FALSE
if(loaded_item)
context[SCREENTIP_CONTEXT_ALT_LMB] = "Remove Item"
screentip_set = TRUE
else if(!isnull(held_item))
context[SCREENTIP_CONTEXT_LMB] = "Insert Item"
screentip_set = TRUE
if(screentip_set)
. = CONTEXTUAL_SCREENTIP_SET
/obj/machinery/rnd/destructive_analyzer/examine(mob/user)
. = ..()
if(!in_range(user, src) && !isobserver(user))
return
if(loaded_item)
. += span_notice("[EXAMINE_HINT("Left-Click")] to remove loaded item inside.")
else
. += span_notice("An item can be loaded inside via [EXAMINE_HINT("Left-Click")].")
/obj/machinery/rnd/destructive_analyzer/attackby(obj/item/weapon, mob/living/user, params)
if(user.combat_mode)
return ..()
if(!is_insertion_ready(user))
return ..()
if(!user.transferItemToLoc(weapon, src))
to_chat(user, span_warning("\The [weapon] is stuck to your hand, you cannot put it in the [name]!"))
return TRUE
busy = TRUE
loaded_item = weapon
to_chat(user, span_notice("You add the [weapon.name] to the [name]!"))
flick("[base_icon_state]_la", src)
addtimer(CALLBACK(src, PROC_REF(finish_loading)), 1 SECONDS)
return TRUE
/obj/machinery/rnd/destructive_analyzer/AltClick(mob/user)
. = ..()
unload_item()
/obj/machinery/rnd/destructive_analyzer/update_icon_state()
icon_state = "[base_icon_state][loaded_item ? "_l" : null]"
return ..()
/obj/machinery/rnd/destructive_analyzer/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "DestructiveAnalyzer")
ui.open()
/obj/machinery/rnd/destructive_analyzer/ui_data(mob/user)
var/list/data = list()
data["server_connected"] = !!stored_research
data["node_data"] = list()
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)
var/list/boostable_nodes = techweb_item_unlock_check(loaded_item)
for(var/id in boostable_nodes)
var/datum/techweb_node/unlockable_node = SSresearch.techweb_node_by_id(id)
var/list/node_data = list()
node_data["node_name"] = unlockable_node.display_name
node_data["node_id"] = unlockable_node.id
node_data["node_hidden"] = !!stored_research.hidden_nodes[unlockable_node.id]
data["node_data"] += list(node_data)
else
data["loaded_item"] = null
return data
/obj/machinery/rnd/destructive_analyzer/ui_static_data(mob/user)
var/list/data = list()
data["research_point_id"] = DESTRUCTIVE_ANALYZER_DESTROY_POINTS
return data
/obj/machinery/rnd/destructive_analyzer/ui_act(action, params, datum/tgui/ui)
. = ..()
if(.)
return
var/mob/user = usr
switch(action)
if("eject_item")
if(busy)
balloon_alert(user, "already busy!")
return TRUE
if(loaded_item)
unload_item()
return TRUE
if("deconstruct")
if(!user_try_decon_id(params["deconstruct_id"]))
say("Destructive analysis failed!")
return TRUE
//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)
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
var/item_type = loaded_item.type
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
if(!destroy_item())
return FALSE
SSblackbox.record_feedback("nested tally", "item_deconstructed", 1, list("[node_to_discover.id]", "[item_type]"))
stored_research.unhide_node(node_to_discover)
return TRUE
#undef DESTRUCTIVE_ANALYZER_DESTROY_POINTS
#undef DESTRUCTIVE_ANALYZER_POWER_USAGE