[MIRROR] General maintenance for Lathes (#26410)

* 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>

* There we go

* aaaa

* Missed this little thingy

* There we go, should be clean af

---------

Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com>
Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com>
Co-authored-by: Useroth <37159550+Useroth@users.noreply.github.com>
This commit is contained in:
SkyratBot
2024-02-09 02:37:42 +01:00
committed by GitHub
parent 6d4b743b7f
commit 561df29ff7
23 changed files with 641 additions and 437 deletions
@@ -88,7 +88,7 @@
/turf/open/floor/iron,
/area/ruin/planetengi)
"aA" = (
/obj/machinery/rnd/production/protolathe/department/engineering/no_tax,
/obj/machinery/rnd/production/protolathe/department/engineering,
/obj/effect/turf_decal/trimline/yellow/filled/warning{
dir = 9
},
@@ -1162,7 +1162,7 @@
/obj/item/stack/sheet/glass/fifty,
/obj/item/circuitboard/machine/protolathe/offstation,
/obj/effect/spawner/random/engineering/toolbox,
/obj/item/circuitboard/machine/circuit_imprinter/department/no_tax,
/obj/item/circuitboard/machine/circuit_imprinter/department,
/obj/item/circuitboard/machine/rtg/advanced,
/obj/item/circuitboard/machine/rtg/advanced,
/obj/item/circuitboard/machine/rtg/advanced,
@@ -118,6 +118,12 @@ handles linking back and forth.
else
silo.holds -= src
/**
* Sets the storage size for local materials when not linked with silo
* Arguments
*
* * size - the new size for local storage. measured in SHEET_MATERIAL_SIZE units
*/
/datum/component/remote_materials/proc/set_local_size(size)
local_size = size
if (!silo && mat_container)
@@ -209,7 +215,7 @@ handles linking back and forth.
return check_z_level() ? silo.holds[src] : FALSE
/**
* Internal proc to check if this connection can use any materials from the silo
* Check if this connection can use any materials from the silo
* Returns true only if
* - The parent is of type movable atom
* - A mat container is actually present
@@ -217,9 +223,7 @@ handles linking back and forth.
* Arguments
* * check_hold - should we check if the silo is on hold
*/
/datum/component/remote_materials/proc/_can_use_resource(check_hold = TRUE)
PRIVATE_PROC(TRUE)
/datum/component/remote_materials/proc/can_use_resource(check_hold = TRUE)
var/atom/movable/movable_parent = parent
if (!istype(movable_parent))
return FALSE
@@ -243,7 +247,7 @@ handles linking back and forth.
* name- For logging only. the design you are trying to build e.g. matter bin, etc.
*/
/datum/component/remote_materials/proc/use_materials(list/mats, coefficient = 1, multiplier = 1, action = "build", name = "design")
if(!_can_use_resource())
if(!can_use_resource())
return 0
var/amount_consumed = mat_container.use_materials(mats, coefficient, multiplier)
@@ -265,7 +269,7 @@ handles linking back and forth.
* [drop_target][atom]- optional where to drop the sheets. null means it is dropped at this components parent location
*/
/datum/component/remote_materials/proc/eject_sheets(datum/material/material_ref, eject_amount, atom/drop_target = null)
if(!_can_use_resource())
if(!can_use_resource())
return 0
var/atom/movable/movable_parent = parent
@@ -282,7 +286,7 @@ handles linking back and forth.
* * multiplier - the multiplier applied on the materials consumed
*/
/datum/component/remote_materials/proc/insert_item(obj/item/weapon, multiplier = 1)
if(!_can_use_resource(FALSE))
if(!can_use_resource(FALSE))
return MATERIAL_INSERT_ITEM_FAILURE
return mat_container.insert_item(weapon, multiplier, parent)
+217 -163
View File
@@ -7,24 +7,24 @@
active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.5
circuit = /obj/item/circuitboard/machine/autolathe
layer = BELOW_OBJ_LAYER
processing_flags = NONE
///Is the autolathe hacked via wiring
var/hacked = FALSE
///Is the autolathe disabled via wiring
var/disabled = FALSE
///Did we recently shock a mob who medled with the wiring
var/shocked = FALSE
///Are we currently printing something
var/busy = FALSE
/// Coefficient applied to consumed materials. Lower values result in lower material consumption.
///Coefficient applied to consumed materials. Lower values result in lower material consumption.
var/creation_efficiency = 1.6
var/datum/design/being_built
///Designs related to the autolathe
var/datum/techweb/autounlocking/stored_research
///Designs imported from technology disks that we can print.
var/list/imported_designs = list()
///The container to hold materials
var/datum/component/material_container/materials
///direction we output onto (if 0, on top of us)
var/drop_direction = 0
@@ -43,17 +43,69 @@
GLOB.autounlock_techwebs[/datum/techweb/autounlocking/autolathe] = new /datum/techweb/autounlocking/autolathe
stored_research = GLOB.autounlock_techwebs[/datum/techweb/autounlocking/autolathe]
register_context()
/obj/machinery/autolathe/Destroy()
materials = null
QDEL_NULL(wires)
return ..()
/obj/machinery/autolathe/examine(mob/user)
. = ..()
if(!in_range(user, src) && !isobserver(user))
return
. += span_notice("Material usage cost at <b>[creation_efficiency * 100]%</b>")
if(drop_direction)
. += span_notice("Currently configured to drop printed objects <b>[dir2text(drop_direction)]</b>.")
. += span_notice("[EXAMINE_HINT("Alt-click")] to reset.")
else
. += span_notice("[EXAMINE_HINT("Drag")] towards a direction (while next to it) to change drop direction.")
. += span_notice("Its maintainence panel can be [EXAMINE_HINT("screwed")] [panel_open ? "closed" : "open"].")
if(panel_open)
. += span_notice("The machine can be [EXAMINE_HINT("pried")] apart.")
/obj/machinery/autolathe/add_context(atom/source, list/context, obj/item/held_item, mob/user)
if(drop_direction)
context[SCREENTIP_CONTEXT_ALT_LMB] = "Reset Drop"
return CONTEXTUAL_SCREENTIP_SET
if(isnull(held_item))
return NONE
if(held_item.tool_behaviour == TOOL_SCREWDRIVER)
context[SCREENTIP_CONTEXT_RMB] = "[panel_open ? "Close" : "Open"] Panel"
return CONTEXTUAL_SCREENTIP_SET
if(panel_open && held_item.tool_behaviour == TOOL_CROWBAR)
context[SCREENTIP_CONTEXT_LMB] = "Deconstruct"
return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/autolathe/crowbar_act(mob/living/user, obj/item/tool)
. = ITEM_INTERACT_BLOCKING
if(default_deconstruction_crowbar(tool))
return ITEM_INTERACT_SUCCESS
/obj/machinery/autolathe/screwdriver_act_secondary(mob/living/user, obj/item/tool)
. = ITEM_INTERACT_BLOCKING
if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", tool))
return ITEM_INTERACT_SUCCESS
/obj/machinery/autolathe/proc/AfterMaterialInsert(container, obj/item/item_inserted, last_inserted_id, mats_consumed, amount_inserted, atom/context)
SIGNAL_HANDLER
flick("autolathe_[item_inserted.has_material_type(/datum/material/glass) ? "r" : "o"]", src)
directly_use_power(round((amount_inserted / SHEET_MATERIAL_AMOUNT) * active_power_usage * 0.0025))
/obj/machinery/autolathe/ui_interact(mob/user, datum/tgui/ui)
if(!is_operational)
return
if(shocked && !(machine_stat & NOPOWER))
shock(user, 50)
return
ui = SStgui.try_update_ui(user, src, ui)
@@ -61,23 +113,75 @@
ui = new(user, src, "Autolathe")
ui.open()
/**
* Converts all the designs supported by this autolathe into UI data
* Arguments
*
* * list/designs - the list of techweb designs we are trying to send to the UI
*/
/obj/machinery/autolathe/proc/handle_designs(list/designs)
PRIVATE_PROC(TRUE)
var/list/output = list()
var/datum/asset/spritesheet/research_designs/spritesheet = get_asset_datum(/datum/asset/spritesheet/research_designs)
var/size32x32 = "[spritesheet.name]32x32"
for(var/design_id in designs)
var/datum/design/design = SSresearch.techweb_design_by_id(design_id)
if(design.make_reagent)
continue
//compute cost & maximum number of printable items
var/coeff = (ispath(design.build_path, /obj/item/stack) ? 1 : creation_efficiency)
var/list/cost = list()
var/customMaterials = FALSE
for(var/i in design.materials)
var/datum/material/mat = i
var/design_cost = OPTIMAL_COST(design.materials[i] * coeff)
if(istype(mat))
cost[mat.name] = design_cost
customMaterials = FALSE
else
cost[i] = design_cost
customMaterials = TRUE
//create & send ui data
var/icon_size = spritesheet.icon_size_id(design.id)
var/list/design_data = list(
"name" = design.name,
"desc" = design.get_description(),
"cost" = cost,
"id" = design.id,
"categories" = design.category,
"icon" = "[icon_size == size32x32 ? "" : "[icon_size] "][design.id]",
"customMaterials" = customMaterials
)
output += list(design_data)
return output
/obj/machinery/autolathe/ui_static_data(mob/user)
var/list/data = materials.ui_static_data()
var/max_available = materials.total_amount()
for(var/datum/material/container_mat as anything in materials.materials)
var/available = materials.materials[container_mat]
if(available)
max_available = max(max_available, available)
data["designs"] = handle_designs(stored_research.researched_designs, max_available)
data["designs"] = handle_designs(stored_research.researched_designs)
if(imported_designs.len)
data["designs"] += handle_designs(imported_designs, max_available)
data["designs"] += handle_designs(imported_designs)
if(hacked)
data["designs"] += handle_designs(stored_research.hacked_designs, max_available)
data["designs"] += handle_designs(stored_research.hacked_designs)
return data
/obj/machinery/autolathe/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials),
get_asset_datum(/datum/asset/spritesheet/research_designs),
)
/obj/machinery/autolathe/ui_data(mob/user)
var/list/data = list()
@@ -89,107 +193,51 @@
return data
/obj/machinery/autolathe/proc/handle_designs(list/designs, max_available)
var/list/output = list()
var/datum/asset/spritesheet/research_designs/spritesheet = get_asset_datum(/datum/asset/spritesheet/research_designs)
var/size32x32 = "[spritesheet.name]32x32"
var/max_multiplier = INFINITY
for(var/design_id in designs)
var/datum/design/design = SSresearch.techweb_design_by_id(design_id)
if(design.make_reagent)
continue
//compute cost & maximum number of printable items
max_multiplier = INFINITY
var/coeff = (ispath(design.build_path, /obj/item/stack) ? 1 : creation_efficiency)
var/list/cost = list()
for(var/i in design.materials)
var/datum/material/mat = i
var/design_cost = OPTIMAL_COST(design.materials[i] * coeff)
if(istype(mat))
cost[mat.name] = design_cost
else
cost[i] = design_cost
var/mat_available
if(istype(mat)) //regular mat
mat_available = materials.get_material_amount(mat)
else //category mat means we can make it from any mat, use largest available mat
mat_available = max_available
max_multiplier = min(max_multiplier, 50, round(mat_available / design_cost))
//create & send ui data
var/icon_size = spritesheet.icon_size_id(design.id)
var/list/design_data = list(
"name" = design.name,
"desc" = design.get_description(),
"cost" = cost,
"id" = design.id,
"categories" = design.category,
"icon" = "[icon_size == size32x32 ? "" : "[icon_size] "][design.id]",
"constructionTime" = -1,
"maxmult" = max_multiplier
)
output += list(design_data)
return output
/obj/machinery/autolathe/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials),
get_asset_datum(/datum/asset/spritesheet/research_designs),
)
/obj/machinery/autolathe/ui_act(action, list/params, datum/tgui/ui)
. = ..()
if(.)
return
//sanity checks to start printing
if(action != "make")
stack_trace("unknown autolathe ui_act: [action]")
return
if(disabled)
say("Unable to print, voltage mismatch in internal wiring.")
return
if(busy)
balloon_alert(ui.user, "busy!")
return
var/turf/target_location = get_step(src, drop_direction)
if(isclosedturf(target_location))
say("Output path is obstructed by a large object.")
say("currently printing.")
return
//validate design
var/design_id = params["id"]
if(!design_id)
return
var/valid_design = stored_research.researched_designs[design_id]
valid_design ||= stored_research.hacked_designs[design_id]
valid_design ||= imported_designs[design_id]
if(!valid_design)
return
var/datum/design/design = SSresearch.techweb_design_by_id(design_id)
if(isnull(design))
stack_trace("got passed an invalid design id: [design_id] and somehow made it past all checks")
return
if(!(design.build_type & AUTOLATHE))
say("This fabricator does not have the necessary keys to decrypt this design.")
return
var/build_count = text2num(params["multiplier"])
if(!build_count)
//validate print quantity
var/build_count = params["multiplier"]
if(isnull(build_count))
return
build_count = text2num(build_count)
if(isnull(build_count))
return
build_count = clamp(build_count, 1, 50)
//check for materials required. For custom material items decode their required materials
var/list/materials_needed = list()
for(var/datum/material/material as anything in design.materials)
for(var/material in design.materials)
var/amount_needed = design.materials[material]
if(istext(material)) // category
var/list/choices = list()
@@ -215,64 +263,70 @@
return
materials_needed[material] = amount_needed
//checks for available materials
var/material_cost_coefficient = ispath(design.build_path, /obj/item/stack) ? 1 : creation_efficiency
if(!materials.has_materials(materials_needed, material_cost_coefficient, build_count))
say("Not enough materials to begin production.")
return
//use power
var/total_charge = 0
//compute power & time to print 1 item
var/charge_per_item = 0
for(var/material in design.materials)
total_charge += round(design.materials[material] * material_cost_coefficient * build_count)
var/charge_per_item = total_charge / build_count
var/total_time = (design.construction_time * design.lathe_time_factor * build_count) ** 0.8
var/time_per_item = total_time / build_count
start_making(design, build_count, time_per_item, material_cost_coefficient, charge_per_item)
return TRUE
/// Begins the act of making the given design the given number of items
/// Does not check or use materials/power/etc
/obj/machinery/autolathe/proc/start_making(datum/design/design, build_count, build_time_per_item, material_cost_coefficient, charge_per_item)
PROTECTED_PROC(TRUE)
charge_per_item += design.materials[material]
charge_per_item = min(active_power_usage, round(charge_per_item * material_cost_coefficient))
var/build_time_per_item = (design.construction_time * design.lathe_time_factor) ** 0.8
//do the printing sequentially
busy = TRUE
icon_state = "autolathe_n"
update_static_data_for_all_viewers()
SStgui.update_uis(src)
var/turf/target_location
if(drop_direction)
target_location = get_step(src, drop_direction)
if(isclosedturf(target_location))
target_location = get_turf(src)
else
target_location = get_turf(src)
addtimer(CALLBACK(src, PROC_REF(do_make_item), design, build_count, build_time_per_item, material_cost_coefficient, charge_per_item, materials_needed, target_location), build_time_per_item)
addtimer(CALLBACK(src, PROC_REF(do_make_item), design, material_cost_coefficient, build_time_per_item, charge_per_item, build_count), build_time_per_item)
return TRUE
/// Callback for start_making, actually makes the item
/// Called using timers started by start_making
/obj/machinery/autolathe/proc/do_make_item(datum/design/design, material_cost_coefficient, time_per_item, charge_per_item, items_remaining)
/**
* Callback for start_making, actually makes the item
* Arguments
*
* * datum/design/design - the design we are trying to print
* * items_remaining - the number of designs left out to print
* * build_time_per_item - the time taken to print 1 item
* * material_cost_coefficient - the cost efficiency to print 1 design
* * charge_per_item - the amount of power to print 1 item
* * list/materials_needed - the list of materials to print 1 item
* * turf/target - the location to drop the printed item on
*/
/obj/machinery/autolathe/proc/do_make_item(datum/design/design, items_remaining, build_time_per_item, material_cost_coefficient, charge_per_item, list/materials_needed, turf/target)
PROTECTED_PROC(TRUE)
if(!items_remaining) // how
if(items_remaining <= 0) // how
finalize_build()
return
if(!directly_use_power(charge_per_item))
if(!is_operational || !directly_use_power(charge_per_item))
say("Unable to continue production, power failure.")
finalize_build()
return
var/list/design_materials = design.materials
var/is_stack = ispath(design.build_path, /obj/item/stack)
if(!materials.has_materials(design_materials, material_cost_coefficient, is_stack ? items_remaining : 1))
if(!materials.has_materials(materials_needed, material_cost_coefficient, is_stack ? items_remaining : 1))
say("Unable to continue production, missing materials.")
return
materials.use_materials(design_materials, material_cost_coefficient, is_stack ? items_remaining : 1)
var/turf/target = get_step(src, drop_direction)
if(isclosedturf(target))
target = get_turf(src)
materials.use_materials(materials_needed, material_cost_coefficient, is_stack ? items_remaining : 1)
var/atom/movable/created
if(is_stack)
created = new design.build_path(target, items_remaining)
else
created = new design.build_path(target)
split_materials_uniformly(design_materials, material_cost_coefficient, created)
split_materials_uniformly(materials_needed, material_cost_coefficient, created)
created.pixel_x = created.base_pixel_x + rand(-6, 6)
created.pixel_y = created.base_pixel_y + rand(-6, 6)
@@ -283,26 +337,44 @@
else
items_remaining -= 1
if(!items_remaining)
if(items_remaining <= 0)
finalize_build()
return
addtimer(CALLBACK(src, PROC_REF(do_make_item), design, material_cost_coefficient, time_per_item, items_remaining), time_per_item)
addtimer(CALLBACK(src, PROC_REF(do_make_item), design, items_remaining, build_time_per_item, material_cost_coefficient, charge_per_item, materials_needed, target), build_time_per_item)
/// Resets the icon state and busy flag
/// Called at the end of do_make_item's timer loop
/**
* Resets the icon state and busy flag
* Called at the end of do_make_item's timer loop
*/
/obj/machinery/autolathe/proc/finalize_build()
PROTECTED_PROC(TRUE)
icon_state = initial(icon_state)
busy = FALSE
update_static_data_for_all_viewers()
SStgui.update_uis(src)
/obj/machinery/autolathe/crowbar_act(mob/living/user, obj/item/tool)
if(default_deconstruction_crowbar(tool))
return ITEM_INTERACT_SUCCESS
/obj/machinery/autolathe/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
. = ..()
if((!issilicon(usr) && !isAdminGhostAI(usr)) && !Adjacent(usr))
return
if(busy)
balloon_alert(usr, "printing started!")
return
var/direction = get_dir(src, over_location)
if(!direction)
return
drop_direction = direction
balloon_alert(usr, "dropping [dir2text(drop_direction)]")
/obj/machinery/autolathe/screwdriver_act_secondary(mob/living/user, obj/item/tool)
if(default_deconstruction_screwdriver(user, "autolathe_t", "autolathe", tool))
return ITEM_INTERACT_SUCCESS
/obj/machinery/autolathe/AltClick(mob/user)
. = ..()
if(!drop_direction || !can_interact(user))
return
if(busy)
balloon_alert(user, "busy printing!")
return
balloon_alert(user, "drop direction reset")
drop_direction = 0
/obj/machinery/autolathe/attackby(obj/item/attacking_item, mob/living/user, params)
if(user.combat_mode) //so we can hit the machine
@@ -346,25 +418,6 @@
return ..()
/obj/machinery/autolathe/proc/AfterMaterialInsert(container, obj/item/item_inserted, last_inserted_id, mats_consumed, amount_inserted, atom/context)
SIGNAL_HANDLER
flick("autolathe_[item_inserted.has_material_type(/datum/material/glass) ? "r" : "o"]", src)
use_power(min(active_power_usage * 0.25, amount_inserted / SHEET_MATERIAL_AMOUNT))
update_static_data_for_all_viewers()
/obj/machinery/autolathe/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
. = ..()
if((!issilicon(usr) && !isAdminGhostAI(usr)) && !Adjacent(usr))
return
var/direction = get_dir(src, over_location)
if(!direction)
return
drop_direction = direction
balloon_alert(usr, "dropping [dir2text(drop_direction)]")
/obj/machinery/autolathe/RefreshParts()
. = ..()
var/mat_capacity = 0
@@ -377,24 +430,12 @@
efficiency -= new_servo.tier * 0.2
creation_efficiency = max(1,efficiency) // creation_efficiency goes 1.6 -> 1.4 -> 1.2 -> 1 per level of servo efficiency
/obj/machinery/autolathe/examine(mob/user)
. += ..()
if(in_range(user, src) || isobserver(user))
. += span_notice("The status display reads: Storing up to <b>[materials.max_amount]</b> material units.<br>Material consumption at <b>[creation_efficiency*100]%</b>.")
if(drop_direction)
. += span_notice("Currently configured to drop printed objects <b>[dir2text(drop_direction)]</b>.")
. += span_notice("<b>Alt-click</b> to reset.")
else
. += span_notice("<b>Drag towards a direction</b> (while next to it) to change drop direction.")
/obj/machinery/autolathe/AltClick(mob/user)
. = ..()
if(!can_interact(user))
return
if(drop_direction)
balloon_alert(user, "drop direction reset")
drop_direction = 0
/**
* Cut a wire in the autolathe
* Arguments
*
* * wire - the wire we are trying to cut
*/
/obj/machinery/autolathe/proc/reset(wire)
switch(wire)
if(WIRE_HACK)
@@ -407,6 +448,13 @@
if(!wires.is_cut(wire))
disabled = FALSE
/**
* Shock a mob who is trying to interact with the autolathe
* Arguments
*
* * mob/user - the mob we are trying to shock
* * prb - the probability of getting shocked
*/
/obj/machinery/autolathe/proc/shock(mob/user, prb)
if(machine_stat & (BROKEN|NOPOWER)) // unpowered, no shock
return FALSE
@@ -417,6 +465,12 @@
s.start()
return electrocute_mob(user, get_area(src), src, 0.7, TRUE)
/**
* Is the autolathe hacked. Allowing us to acess hidden designs
* Arguments
*
* state - TRUE/FALSE for is the autolathe hacked
*/
/obj/machinery/autolathe/proc/adjust_hacked(state)
hacked = state
update_static_data_for_all_viewers()
@@ -309,9 +309,6 @@
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
build_path = /obj/machinery/rnd/production/protolathe/department/engineering
/obj/item/circuitboard/machine/protolathe/department/engineering/no_tax
build_path = /obj/machinery/rnd/production/protolathe/department/engineering/no_tax
/obj/item/circuitboard/machine/rtg
name = "RTG"
greyscale_colors = CIRCUIT_COLOR_ENGINEERING
@@ -4,15 +4,24 @@
req_access = list(ACCESS_AWAY_SCIENCE)
/obj/machinery/rnd/server/oldstation/Initialize(mapload)
register_context()
var/datum/techweb/oldstation_web = locate(/datum/techweb/oldstation) in SSresearch.techwebs
stored_research = oldstation_web
return ..()
/obj/machinery/rnd/server/oldstation/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
if(held_item && istype(held_item, /obj/item/research_notes))
context[SCREENTIP_CONTEXT_LMB] = "Generate research points"
return CONTEXTUAL_SCREENTIP_SET
return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/rnd/server/oldstation/examine(mob/user)
. = ..()
if(!in_range(user, src) && !isobserver(user))
return
. += span_notice("Insert [EXAMINE_HINT("Research Notes")] to generate points.")
/obj/machinery/rnd/server/oldstation/attackby(obj/item/attacking_item, mob/user, params)
if(istype(attacking_item, /obj/item/research_notes) && stored_research)
+18 -5
View File
@@ -14,16 +14,29 @@
base_icon_state = "d_analyzer"
circuit = /obj/item/circuitboard/machine/destructive_analyzer
/obj/machinery/rnd/destructive_analyzer/Initialize(mapload)
. = ..()
register_context()
/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"
return CONTEXTUAL_SCREENTIP_SET
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)
+251 -160
View File
@@ -1,38 +1,37 @@
/obj/machinery/rnd/production
name = "technology fabricator"
desc = "Makes researched and prototype items with materials and energy."
layer = BELOW_OBJ_LAYER
/// The efficiency coefficient. Material costs and print times are multiplied by this number;
/// better parts result in a higher efficiency (and lower value).
var/efficiency_coeff = 1
/// The material storage used by this fabricator.
var/datum/component/remote_materials/materials
/// Which departments are allowed to process this design
var/allowed_department_flags = ALL
/// What's flick()'d on print.
/// Icon state when production has started
var/production_animation
/// The types of designs this fabricator can print.
var/allowed_buildtypes = NONE
/// All designs in the techweb that can be fabricated by this machine, since the last update.
var/list/datum/design/cached_designs
/// What color is this machine's stripe? Leave null to not have a stripe.
var/stripe_color = null
/// Does this charge the user's ID on fabrication?
var/charges_tax = TRUE
///direction we output onto (if 0, on top of us)
var/drop_direction = 0
/obj/machinery/rnd/production/Initialize(mapload)
. = ..()
cached_designs = list()
materials = AddComponent(/datum/component/remote_materials, mapload)
materials = AddComponent(
/datum/component/remote_materials, \
mapload, \
mat_container_signals = list( \
COMSIG_MATCONTAINER_ITEM_CONSUMED = TYPE_PROC_REF(/obj/machinery/rnd, local_material_insert)
) \
)
RegisterSignal(src, COMSIG_SILO_ITEM_CONSUMED, TYPE_PROC_REF(/obj/machinery/rnd/production, silo_material_insert))
AddComponent(
/datum/component/payment, \
@@ -42,9 +41,49 @@
TRUE, \
)
RefreshParts()
update_icon(UPDATE_OVERLAYS)
/obj/machinery/rnd/production/Destroy()
materials = null
cached_designs = null
return ..()
// Stuff for the stripe on the department machines
/obj/machinery/rnd/production/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
. = ..()
update_icon(UPDATE_OVERLAYS)
/obj/machinery/rnd/production/update_overlays()
. = ..()
if(!stripe_color)
return
var/mutable_appearance/stripe = mutable_appearance('icons/obj/machines/research.dmi', "protolathe_stripe[panel_open ? "_t" : ""]")
stripe.color = stripe_color
. += stripe
/obj/machinery/rnd/production/examine(mob/user)
. = ..()
if(!in_range(user, src) && !isobserver(user))
return
. += span_notice("Material usage cost at <b>[efficiency_coeff * 100]%</b>")
if(drop_direction)
. += span_notice("Currently configured to drop printed objects <b>[dir2text(drop_direction)]</b>.")
. += span_notice("[EXAMINE_HINT("Alt-click")] to reset.")
else
. += span_notice("[EXAMINE_HINT("Drag")] towards a direction (while next to it) to change drop direction.")
/obj/machinery/rnd/production/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
if(drop_direction)
context[SCREENTIP_CONTEXT_ALT_LMB] = "Reset Drop"
return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/rnd/production/connect_techweb(datum/techweb/new_techweb)
if(stored_research)
UnregisterSignal(stored_research, list(COMSIG_TECHWEB_ADD_DESIGN, COMSIG_TECHWEB_REMOVE_DESIGN))
@@ -55,24 +94,14 @@
RegisterSignals(
stored_research,
list(COMSIG_TECHWEB_ADD_DESIGN, COMSIG_TECHWEB_REMOVE_DESIGN),
PROC_REF(on_techweb_update)
TYPE_PROC_REF(/obj/machinery/rnd/production, on_techweb_update)
)
update_designs()
/obj/machinery/rnd/production/Destroy()
materials = null
cached_designs = null
return ..()
/obj/machinery/rnd/production/proc/on_techweb_update()
SIGNAL_HANDLER
// We're probably going to get more than one update (design) at a time, so batch
// them together.
addtimer(CALLBACK(src, PROC_REF(update_designs)), 2 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
/// Updates the list of designs this fabricator can print.
/obj/machinery/rnd/production/proc/update_designs()
PROTECTED_PROC(TRUE)
var/previous_design_count = cached_designs.len
cached_designs.Cut()
@@ -91,12 +120,98 @@
update_static_data_for_all_viewers()
/obj/machinery/rnd/production/proc/on_techweb_update()
SIGNAL_HANDLER
// We're probably going to get more than one update (design) at a time, so batch
// them together.
addtimer(CALLBACK(src, PROC_REF(update_designs)), 2 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE)
///When materials are instered via silo link
/obj/machinery/rnd/proc/silo_material_insert(obj/machinery/rnd/machine, container, obj/item/item_inserted, last_inserted_id, list/mats_consumed, amount_inserted)
SIGNAL_HANDLER
process_item(item_inserted, mats_consumed, amount_inserted)
/**
* Consumes power for the item inserted either into silo or local storage.
* Arguments
*
* * obj/item/item_inserted - the item to process
* * list/mats_consumed - list of mats consumed
* * amount_inserted - amount of material actually processed
*/
/obj/machinery/rnd/proc/process_item(obj/item/item_inserted, list/mats_consumed, amount_inserted)
PRIVATE_PROC(TRUE)
if(directly_use_power(round((amount_inserted / SHEET_MATERIAL_AMOUNT) * active_power_usage * 0.00025)))
var/mat_name = "iron"
var/highest_mat = 0
for(var/datum/material/mat as anything in mats_consumed)
var/present_mat = mats_consumed[mat]
if(present_mat > highest_mat)
mat_name = initial(mat.name)
if(mat_name == "silver" || mat_name == "titanium" || mat_name == "plastic") //these materials have similar appearances so use an common overlay for them
mat_name = "shiny"
highest_mat = present_mat
flick_animation(mat_name)
/**
* Plays an visual animation when materials are inserted
* Arguments
*
* * mat_name - the name of the material we are trying to animate on the machine
*/
/obj/machinery/rnd/proc/flick_animation(mat_name)
PROTECTED_PROC(TRUE)
SHOULD_CALL_PARENT(FALSE)
flick_overlay_view(mutable_appearance('icons/obj/machines/research.dmi', "protolathe_[mat_name]"), 1 SECONDS)
///When materials are instered into local storage
/obj/machinery/rnd/proc/local_material_insert(container, obj/item/item_inserted, last_inserted_id, list/mats_consumed, amount_inserted, atom/context)
SIGNAL_HANDLER
process_item(item_inserted, mats_consumed, amount_inserted)
/obj/machinery/rnd/production/RefreshParts()
. = ..()
calculate_efficiency()
if(materials)
var/total_storage = 0
for(var/datum/stock_part/matter_bin/bin in component_parts)
total_storage += bin.tier * 37.5 * SHEET_MATERIAL_AMOUNT
materials.set_local_size(total_storage)
efficiency_coeff = compute_efficiency()
update_static_data_for_all_viewers()
///Computes this machines cost efficiency based on the available parts
/obj/machinery/rnd/production/proc/compute_efficiency()
PROTECTED_PROC(TRUE)
var/efficiency = 1.2
for(var/datum/stock_part/servo/servo in component_parts)
efficiency -= servo.tier * 0.1
return efficiency
/**
* The cost efficiency for an particular design
* Arguments
*
* * path - the design path to check for
*/
/obj/machinery/rnd/production/proc/build_efficiency(path)
PRIVATE_PROC(TRUE)
if(ispath(path, /obj/item/stack/sheet) || ispath(path, /obj/item/stack/ore/bluespace_crystal))
return 1
else
return efficiency_coeff
/obj/machinery/rnd/production/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials),
@@ -117,16 +232,13 @@
var/datum/asset/spritesheet/research_designs/spritesheet = get_asset_datum(/datum/asset/spritesheet/research_designs)
var/size32x32 = "[spritesheet.name]32x32"
var/max_multiplier = INFINITY
var/coefficient
for(var/datum/design/design in cached_designs)
var/cost = list()
max_multiplier = INFINITY
coefficient = build_efficiency(design.build_path)
for(var/datum/material/mat in design.materials)
cost[mat.name] = OPTIMAL_COST(design.materials[mat] * coefficient)
max_multiplier = min(max_multiplier, 50, round(materials.mat_container.get_material_amount(mat) / cost[mat.name]))
var/icon_size = spritesheet.icon_size_id(design.id)
designs[design.id] = list(
@@ -135,9 +247,7 @@
"cost" = cost,
"id" = design.id,
"categories" = design.category,
"icon" = "[icon_size == size32x32 ? "" : "[icon_size] "][design.id]",
"constructionTime" = 0,
"maxmult" = max_multiplier
"icon" = "[icon_size == size32x32 ? "" : "[icon_size] "][design.id]"
)
data["designs"] = designs
@@ -158,141 +268,126 @@
/obj/machinery/rnd/production/ui_act(action, list/params, datum/tgui/ui)
. = ..()
if(.)
return
. = TRUE
switch (action)
if("remove_mat")
var/datum/material/material = locate(params["ref"])
var/amount = text2num(params["amount"])
// SAFETY: eject_sheets checks for valid mats
if(!istype(material))
return
var/amount = params["amount"]
if(isnull(amount))
return
amount = text2num(amount)
if(isnull(amount))
return
materials.eject_sheets(material, amount)
return TRUE
if("build")
user_try_print_id(ui.user, params["ref"], params["amount"])
if(busy)
say("Warning: fabricator is busy!")
return
/// Updates the fabricator's efficiency coefficient based on the installed parts.
/obj/machinery/rnd/production/proc/calculate_efficiency()
efficiency_coeff = 1
//validate design
var/design_id = params["ref"]
if(!design_id)
return
var/datum/design/design = stored_research.researched_designs[design_id] ? SSresearch.techweb_design_by_id(design_id) : null
if(!istype(design))
return FALSE
if(!(isnull(allowed_department_flags) || (design.departmental_flags & allowed_department_flags)))
say("This fabricator does not have the necessary keys to decrypt this design.")
return FALSE
if(design.build_type && !(design.build_type & allowed_buildtypes))
say("This fabricator does not have the necessary manipulation systems for this design.")
return FALSE
if(materials)
var/total_storage = 0
//validate print quantity
var/print_quantity = params["amount"]
if(isnull(print_quantity))
return
print_quantity = text2num(print_quantity)
if(isnull(print_quantity))
return
print_quantity = clamp(print_quantity, 1, 50)
for(var/datum/stock_part/matter_bin/bin in component_parts)
total_storage += bin.tier * (37.5*SHEET_MATERIAL_AMOUNT)
//efficiency for this design, stacks use exact materials
var/coefficient = build_efficiency(design.build_path)
materials.set_local_size(total_storage)
//check for materials
if(!materials.can_use_resource())
return
if(!materials.mat_container.has_materials(design.materials, coefficient, print_quantity))
say("Not enough materials to complete prototype[print_quantity > 1 ? "s" : ""].")
return FALSE
var/total_rating = 1.2
//compute power & time to print 1 item
var/charge_per_item = 0
for(var/material in design.materials)
charge_per_item += design.materials[material]
charge_per_item = min(active_power_usage, round(charge_per_item * coefficient))
var/build_time_per_item = (design.construction_time * design.lathe_time_factor) ** 0.8
for(var/datum/stock_part/servo/servo in component_parts)
total_rating -= servo.tier * 0.1
//start production
busy = TRUE
SStgui.update_uis(src)
if(production_animation)
icon_state = production_animation
var/turf/target_location
if(drop_direction)
target_location = get_step(src, drop_direction)
if(isclosedturf(target_location))
target_location = get_turf(src)
else
target_location = get_turf(src)
addtimer(CALLBACK(src, PROC_REF(do_make_item), design, print_quantity, build_time_per_item, coefficient, charge_per_item, target_location), build_time_per_item)
efficiency_coeff = max(total_rating, 0)
return TRUE
/obj/machinery/rnd/production/proc/build_efficiency(path)
if(ispath(path, /obj/item/stack/sheet) || ispath(path, /obj/item/stack/ore/bluespace_crystal))
return 1
else
return efficiency_coeff
/obj/machinery/rnd/production/proc/user_try_print_id(mob/user, design_id, print_quantity)
if(!design_id)
return FALSE
if(istext(print_quantity))
print_quantity = text2num(print_quantity)
if(isnull(print_quantity))
print_quantity = 1
var/datum/design/design = stored_research.researched_designs[design_id] ? SSresearch.techweb_design_by_id(design_id) : null
if(!istype(design))
return FALSE
if(busy)
say("Warning: fabricator is busy!")
return FALSE
if(!(isnull(allowed_department_flags) || (design.departmental_flags & allowed_department_flags)))
say("This fabricator does not have the necessary keys to decrypt this design.")
return FALSE
if(design.build_type && !(design.build_type & allowed_buildtypes))
say("This fabricator does not have the necessary manipulation systems for this design.")
return FALSE
if(!materials.mat_container)
say("No connection to material storage, please contact the quartermaster.")
return FALSE
if(materials.on_hold())
say("Mineral access is on hold, please contact the quartermaster.")
return FALSE
print_quantity = clamp(print_quantity, 1, 50)
var/coefficient = build_efficiency(design.build_path)
// check if sufficient materials are available.
if(!materials.mat_container.has_materials(design.materials, coefficient, print_quantity))
say("Not enough materials to complete prototype[print_quantity > 1 ? "s" : ""].")
return FALSE
//use power
var/total_charge = 0
for(var/material in design.materials)
total_charge += round(design.materials[material] * coefficient * print_quantity / 35)
var/charge_per_item = total_charge / print_quantity
if(production_animation)
flick(production_animation, src)
var/total_time = (design.construction_time * design.lathe_time_factor * print_quantity) ** 0.8
var/time_per_item = total_time / print_quantity
start_making(design, print_quantity, time_per_item, coefficient, charge_per_item)
return TRUE
/// Begins the act of making the given design the given number of items
/// Does not check or use materials/power/etc
/obj/machinery/rnd/production/proc/start_making(datum/design/design, build_count, build_time_per_item, build_efficiency, charge_per_item)
PROTECTED_PROC(TRUE)
busy = TRUE
update_static_data_for_all_viewers()
addtimer(CALLBACK(src, PROC_REF(do_make_item), design, build_efficiency, build_time_per_item, charge_per_item, build_count), build_time_per_item)
/// Callback for start_making, actually makes the item
/// Called using timers started by start_making
/obj/machinery/rnd/production/proc/do_make_item(datum/design/design, build_efficiency, time_per_item, charge_per_item, items_remaining)
/**
* Callback for start_making, actually makes the item
* Arguments
*
* * datum/design/design - the design we are trying to print
* * items_remaining - the number of designs left out to print
* * build_time_per_item - the time taken to print 1 item
* * material_cost_coefficient - the cost efficiency to print 1 design
* * charge_per_item - the amount of power to print 1 item
* * turf/target - the location to drop the printed item on
*/
/obj/machinery/rnd/production/proc/do_make_item(datum/design/design, items_remaining, build_time_per_item, material_cost_coefficient, charge_per_item, turf/target)
PROTECTED_PROC(TRUE)
if(!items_remaining) // how
finalize_build()
return
if(!directly_use_power(charge_per_item))
if(!is_operational || !directly_use_power(charge_per_item))
say("Unable to continue production, power failure.")
finalize_build()
return
if(!materials.can_use_resource())
finalize_build()
return
var/is_stack = ispath(design.build_path, /obj/item/stack)
var/list/design_materials = design.materials
if(!materials.mat_container.has_materials(design_materials, build_efficiency, is_stack ? items_remaining : 1))
if(!materials.mat_container.has_materials(design_materials, material_cost_coefficient, is_stack ? items_remaining : 1))
say("Unable to continue production, missing materials.")
return
materials.use_materials(design_materials, build_efficiency, is_stack ? items_remaining : 1, "built", "[design.name]")
materials.use_materials(design_materials, material_cost_coefficient, is_stack ? items_remaining : 1, "built", "[design.name]")
var/atom/movable/created
if(is_stack)
created = new design.build_path(get_turf(src), items_remaining)
created = new design.build_path(target, items_remaining)
else
created = new design.build_path(get_turf(src))
split_materials_uniformly(design_materials, build_efficiency, created)
created = new design.build_path(target)
split_materials_uniformly(design_materials, material_cost_coefficient, created)
created.pixel_x = created.base_pixel_x + rand(-6, 6)
created.pixel_y = created.base_pixel_y + rand(-6, 6)
@@ -305,40 +400,36 @@
if(!items_remaining)
finalize_build()
return
addtimer(CALLBACK(src, PROC_REF(do_make_item), design, build_efficiency, time_per_item, items_remaining), time_per_item)
addtimer(CALLBACK(src, PROC_REF(do_make_item), design, items_remaining, build_time_per_item, material_cost_coefficient, charge_per_item, target), build_time_per_item)
/// Resets the busy flag
/// Called at the end of do_make_item's timer loop
/obj/machinery/rnd/production/proc/finalize_build()
PROTECTED_PROC(TRUE)
busy = FALSE
update_static_data_for_all_viewers()
SStgui.update_uis(src)
icon_state = initial(icon_state)
// Stuff for the stripe on the department machines
/obj/machinery/rnd/production/default_deconstruction_screwdriver(mob/user, icon_state_open, icon_state_closed, obj/item/screwdriver)
/obj/machinery/rnd/production/MouseDrop(atom/over, src_location, over_location, src_control, over_control, params)
. = ..()
update_icon(UPDATE_OVERLAYS)
/obj/machinery/rnd/production/update_overlays()
. = ..()
if(!stripe_color)
if((!issilicon(usr) && !isAdminGhostAI(usr)) && !Adjacent(usr))
return
if(busy)
balloon_alert(usr, "busy printing!")
return
var/direction = get_dir(src, over_location)
if(!direction)
return
drop_direction = direction
balloon_alert(usr, "dropping [dir2text(drop_direction)]")
var/mutable_appearance/stripe = mutable_appearance('icons/obj/machines/research.dmi', "protolate_stripe")
if(!panel_open)
stripe.icon_state = "protolathe_stripe"
else
stripe.icon_state = "protolathe_stripe_t"
stripe.color = stripe_color
. += stripe
/obj/machinery/rnd/production/examine(mob/user)
/obj/machinery/rnd/production/AltClick(mob/user)
. = ..()
if(in_range(user, src) || isobserver(user))
. += span_notice("The status display reads: Storing up to <b>[materials.local_size]</b> material units.<br>Material consumption at <b>[efficiency_coeff * 100]%</b>.<br>Build time reduced by <b>[100 - efficiency_coeff * 100]%</b>.")
if(!drop_direction || !can_interact(user))
return
if(busy)
balloon_alert(user, "busy printing!")
return
balloon_alert(user, "drop direction reset")
drop_direction = 0
@@ -2,23 +2,22 @@
name = "circuit imprinter"
desc = "Manufactures circuit boards for the construction of machines."
icon_state = "circuit_imprinter"
circuit = /obj/item/circuitboard/machine/circuit_imprinter
production_animation = "circuit_imprinter_ani"
circuit = /obj/item/circuitboard/machine/circuit_imprinter
allowed_buildtypes = IMPRINTER
/obj/machinery/rnd/production/circuit_imprinter/calculate_efficiency()
. = ..()
/obj/machinery/rnd/production/circuit_imprinter/compute_efficiency()
var/rating = 0
for(var/datum/stock_part/servo/servo in component_parts)
rating += servo.tier // There is only one.
rating += servo.tier
efficiency_coeff = 0.5 ** max(rating - 1, 0) // One sheet, half sheet, quarter sheet, eighth sheet.
return 0.5 ** max(rating - 1, 0) // One sheet, half sheet, quarter sheet, eighth sheet.
/obj/machinery/rnd/production/circuit_imprinter/flick_animation(mat_name)
return //we presently have no animation
/obj/machinery/rnd/production/circuit_imprinter/offstation
name = "ancient circuit imprinter"
desc = "Manufactures circuit boards for the construction of machines. Its ancient construction may limit its ability to print all known technology."
allowed_buildtypes = AWAY_IMPRINTER
circuit = /obj/item/circuitboard/machine/circuit_imprinter/offstation
charges_tax = FALSE
@@ -11,10 +11,6 @@
stripe_color = "#EFB341"
payment_department = ACCOUNT_ENG
/obj/machinery/rnd/production/protolathe/department/engineering/no_tax
circuit = /obj/item/circuitboard/machine/protolathe/department/engineering/no_tax
charges_tax = FALSE
/obj/machinery/rnd/production/protolathe/department/service
name = "department protolathe (Service)"
allowed_department_flags = DEPARTMENT_BITFLAG_SERVICE
@@ -23,4 +23,3 @@
desc = "Converts raw materials into useful objects. Its ancient construction may limit its ability to print all known technology."
circuit = /obj/item/circuitboard/machine/protolathe/offstation
allowed_buildtypes = AWAY_LATHE
charges_tax = FALSE
@@ -3,6 +3,5 @@
desc = "Produces researched prototypes with raw materials and energy."
icon_state = "protolathe"
circuit = /obj/item/circuitboard/machine/techfab
console_link = FALSE
production_animation = "protolathe_n"
allowed_buildtypes = PROTOLATHE | IMPRINTER
+58 -39
View File
@@ -7,21 +7,22 @@
icon = 'icons/obj/machines/research.dmi'
density = TRUE
use_power = IDLE_POWER_USE
///Are we currently printing a machine
var/busy = FALSE
///Is this machne hacked via wires
var/hacked = FALSE
var/console_link = TRUE //allow console link.
///Is this machine disabled via wires
var/disabled = FALSE
/// Ref to global science techweb.
///Ref to global science techweb.
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()
busy = FALSE
/obj/machinery/rnd/Initialize(mapload)
. = ..()
set_wires(new /datum/wires/rnd(src))
register_context()
/obj/machinery/rnd/LateInitialize()
. = ..()
@@ -37,6 +38,46 @@
QDEL_NULL(wires)
return ..()
/obj/machinery/rnd/examine(mob/user)
. = ..()
if(!in_range(user, src) && !isobserver(user))
return
. += span_notice("A [EXAMINE_HINT("multitool")] with techweb designs can be uploaded here.")
. += span_notice("Its maintainence panel can be [EXAMINE_HINT("screwed")] [panel_open ? "closed" : "open"].")
if(panel_open)
. += span_notice("Use a [EXAMINE_HINT("multitool")] or [EXAMINE_HINT("wirecutters")] to interact with wires.")
. += span_notice("The machine can be [EXAMINE_HINT("pried")] apart.")
/obj/machinery/rnd/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = NONE
if(isnull(held_item))
return
if(held_item.tool_behaviour == TOOL_SCREWDRIVER)
context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "Close" : "Open"] Panel"
context[SCREENTIP_CONTEXT_RMB] = "[panel_open ? "Close" : "Open"] Panel"
return CONTEXTUAL_SCREENTIP_SET
if(panel_open)
var/msg
if(held_item.tool_behaviour == TOOL_CROWBAR)
msg = "Deconstruct"
else if(is_wire_tool(held_item))
msg = "Open Wires"
if(msg)
context[SCREENTIP_CONTEXT_LMB] = msg
context[SCREENTIP_CONTEXT_RMB] = msg
return CONTEXTUAL_SCREENTIP_SET
else
if(held_item.tool_behaviour == TOOL_MULTITOOL)
var/obj/item/multitool/tool = held_item
if(!QDELETED(tool.buffer) && istype(tool.buffer, /datum/techweb))
context[SCREENTIP_CONTEXT_LMB] = "Upload Techweb"
context[SCREENTIP_CONTEXT_RMB] = "Upload Techweb"
return CONTEXTUAL_SCREENTIP_SET
///Called when attempting to connect the machine to a techweb, forgetting the old.
/obj/machinery/rnd/proc/connect_techweb(datum/techweb/new_techweb)
if(stored_research)
@@ -49,52 +90,42 @@
/obj/machinery/rnd/proc/on_connected_techweb()
SHOULD_CALL_PARENT(FALSE)
/obj/machinery/rnd/proc/shock(mob/user, prb)
if(machine_stat & (BROKEN|NOPOWER)) // unpowered, no shock
return FALSE
if(!prob(prb))
return FALSE
do_sparks(5, TRUE, src)
if (electrocute_mob(user, get_area(src), src, 0.7, TRUE))
return TRUE
else
return FALSE
///Reset the state of this machine
/obj/machinery/rnd/proc/reset_busy()
busy = FALSE
/obj/machinery/rnd/crowbar_act(mob/living/user, obj/item/tool)
return default_deconstruction_crowbar(tool)
/obj/machinery/rnd/crowbar_act_secondary(mob/living/user, obj/item/tool)
return default_deconstruction_crowbar(tool)
return crowbar_act(user, tool)
/obj/machinery/rnd/screwdriver_act(mob/living/user, obj/item/tool)
return default_deconstruction_screwdriver(user, "[initial(icon_state)]_t", initial(icon_state), tool)
/obj/machinery/rnd/screwdriver_act_secondary(mob/living/user, obj/item/tool)
return default_deconstruction_screwdriver(user, "[initial(icon_state)]_t", initial(icon_state), tool)
return screwdriver_act(user, tool)
/obj/machinery/rnd/multitool_act(mob/living/user, obj/item/multitool/tool)
. = ITEM_INTERACT_BLOCKING
if(panel_open)
wires.interact(user)
return TRUE
return ITEM_INTERACT_SUCCESS
if(!QDELETED(tool.buffer) && istype(tool.buffer, /datum/techweb))
connect_techweb(tool.buffer)
return TRUE
return FALSE
return ITEM_INTERACT_SUCCESS
/obj/machinery/rnd/multitool_act_secondary(mob/living/user, obj/item/tool)
if(panel_open)
wires.interact(user)
return TRUE
return multitool_act(user, tool)
/obj/machinery/rnd/wirecutter_act(mob/living/user, obj/item/tool)
. = ITEM_INTERACT_BLOCKING
if(panel_open)
wires.interact(user)
return TRUE
return ITEM_INTERACT_SUCCESS
/obj/machinery/rnd/wirecutter_act_secondary(mob/living/user, obj/item/tool)
if(panel_open)
wires.interact(user)
return TRUE
return wirecutter_act(user, tool)
//whether the machine can have an item inserted in its current state.
/obj/machinery/rnd/proc/is_insertion_ready(mob/user)
@@ -123,15 +154,3 @@
if(loaded_item)
loaded_item.forceMove(drop_location())
..()
/obj/machinery/rnd/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
var/stack_name
if(istype(item_inserted, /obj/item/stack/ore/bluespace_crystal))
stack_name = "bluespace"
use_power(SHEET_MATERIAL_AMOUNT / 10)
else
var/obj/item/stack/S = item_inserted
stack_name = S.name
use_power(min(active_power_usage, (amount_inserted / 100)))
add_overlay("protolathe_[stack_name]")
addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, cut_overlay), "protolathe_[stack_name]"), 10)
@@ -184,8 +184,7 @@
"cost" = cost,
"id" = researched_design_id,
"categories" = design.category,
"icon" = "[icon_size == size32x32 ? "" : "[icon_size] "][design.id]",
"constructionTime" = -1
"icon" = "[icon_size == size32x32 ? "" : "[icon_size] "][design.id]"
)
data["designs"] = designs
Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 28 KiB

@@ -1,5 +0,0 @@
/obj/item/circuitboard/machine/circuit_imprinter/department/no_tax
build_path = /obj/machinery/rnd/production/circuit_imprinter/department/no_tax
/obj/machinery/rnd/production/circuit_imprinter/department/no_tax
charges_tax = FALSE
@@ -12,7 +12,6 @@
obj_flags = CAN_BE_HIT | NO_DECONSTRUCTION
light_color = LIGHT_COLOR_BRIGHT_YELLOW
light_power = 5
charges_tax = FALSE
allowed_buildtypes = COLONY_FABRICATOR
/// The item we turn into when repacked
var/repacked_type = /obj/item/flatpacked_machine
@@ -33,16 +32,13 @@
QDEL_NULL(soundloop)
return ..()
/obj/machinery/rnd/production/colony_lathe/user_try_print_id(design_id, print_quantity)
/obj/machinery/rnd/production/colony_lathe/ui_act(action, list/params, datum/tgui/ui)
. = ..()
if(!.)
return
soundloop.start()
set_light(l_range = 1.5)
icon_state = "colony_lathe_working"
update_appearance()
if (. && action == "build")
soundloop.start()
set_light(l_range = 1.5)
icon_state = "colony_lathe_working"
update_appearance()
/obj/machinery/rnd/production/colony_lathe/finalize_build()
. = ..()
@@ -52,9 +48,6 @@
update_appearance()
flick("colony_lathe_finish_print", src)
/obj/machinery/rnd/production/colony_lathe/calculate_efficiency()
efficiency_coeff = 1
// We take from all nodes even unresearched ones
/obj/machinery/rnd/production/colony_lathe/update_designs()
var/previous_design_count = cached_designs.len
@@ -88,15 +88,21 @@
req_access = list(ACCESS_AWAY_SCIENCE)
/obj/machinery/rnd/server/tarkon/Initialize(mapload)
register_context()
var/datum/techweb/tarkon_techweb = locate(/datum/techweb/tarkon) in SSresearch.techwebs
stored_research = tarkon_techweb
return ..()
/obj/machinery/rnd/server/tarkon/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
if(held_item && istype(held_item, /obj/item/research_notes))
context[SCREENTIP_CONTEXT_LMB] = "Generate research points"
return CONTEXTUAL_SCREENTIP_SET
return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/rnd/server/tarkon/examine(mob/user)
. = ..()
if(!in_range(user, src) && !isobserver(user))
return
. += span_notice("Insert [EXAMINE_HINT("Research Notes")] to generate points.")
/obj/machinery/rnd/server/tarkon/attackby(obj/item/attacking_item, mob/user, params)
if(istype(attacking_item, /obj/item/research_notes) && stored_research)
@@ -112,8 +118,6 @@
desc = "Converts raw materials into useful objects. Refurbished and updated from its previous, limited capabilities."
circuit = /obj/item/circuitboard/machine/protolathe/tarkon
stripe_color = "#350f04"
charges_tax = FALSE
/obj/item/circuitboard/machine/protolathe/tarkon
name = "Tarkon Industries Protolathe"
greyscale_colors = CIRCUIT_COLOR_SUPPLY
-1
View File
@@ -6506,7 +6506,6 @@
#include "modular_skyrat\master_files\code\modules\research\designs\medical_designs.dm"
#include "modular_skyrat\master_files\code\modules\research\designs\misc_designs.dm"
#include "modular_skyrat\master_files\code\modules\research\designs\tool_designs.dm"
#include "modular_skyrat\master_files\code\modules\research\machinery\departmental_circuit_imprinter.dm"
#include "modular_skyrat\master_files\code\modules\research\techweb\all_nodes.dm"
#include "modular_skyrat\master_files\code\modules\shuttle\shuttle.dm"
#include "modular_skyrat\master_files\code\modules\shuttle\shuttle_events\meteors.dm"
+38 -3
View File
@@ -19,12 +19,16 @@ import { MaterialCostSequence } from './Fabrication/MaterialCostSequence';
import { Design, MaterialMap } from './Fabrication/Types';
import { Material } from './Fabrication/Types';
type AutolatheDesign = Design & {
customMaterials: BooleanLike;
};
type AutolatheData = {
materials: Material[];
materialtotal: number;
materialsmax: number;
SHEET_MATERIAL_AMOUNT: number;
designs: Design[];
designs: AutolatheDesign[];
active: BooleanLike;
};
@@ -174,7 +178,7 @@ const PrintButton = (props: PrintButtonProps) => {
};
type AutolatheRecipeProps = {
design: Design;
design: AutolatheDesign;
availableMaterials: MaterialMap;
SHEET_MATERIAL_AMOUNT: number;
};
@@ -183,7 +187,38 @@ const AutolatheRecipe = (props: AutolatheRecipeProps) => {
const { act } = useBackend<AutolatheData>();
const { design, availableMaterials, SHEET_MATERIAL_AMOUNT } = props;
const maxmult = design.maxmult;
let maxmult = 0;
if (design.customMaterials) {
const smallest_mat =
Object.entries(availableMaterials).reduce(
(accumulator: number, [material, amount]) => {
return Math.min(accumulator, amount);
},
Infinity,
) || 0;
if (smallest_mat > 0) {
maxmult = Object.entries(design.cost).reduce(
(accumulator: number, [material, required]) => {
return Math.min(accumulator, smallest_mat / required);
},
Infinity,
);
} else {
maxmult = 0;
}
} else {
maxmult = Object.entries(design.cost).reduce(
(accumulator: number, [material, required]) => {
return Math.min(
accumulator,
(availableMaterials[material] || 0) / required,
);
},
Infinity,
);
}
maxmult = Math.min(Math.floor(maxmult), 50);
const canPrint = maxmult > 0;
return (
@@ -9,8 +9,13 @@ import { MaterialAccessBar } from './Fabrication/MaterialAccessBar';
import { MaterialCostSequence } from './Fabrication/MaterialCostSequence';
import { Design, FabricatorData, MaterialMap } from './Fabrication/Types';
type ExosuitDesign = Design & {
constructionTime: number;
};
type ExosuitFabricatorData = FabricatorData & {
processing: BooleanLike;
designs: Record<string, ExosuitDesign>;
};
export const ExosuitFabricator = (props) => {
@@ -68,16 +68,6 @@ export type Design = {
* 32x32.**
*/
icon: string;
/**
* The amount of time, in seconds, that this design takes to print.
*/
constructionTime: number;
/**
* The maximum number of items than can be printed
*/
maxmult: number;
};
/**
+8 -4
View File
@@ -116,10 +116,14 @@ type CustomPrintProps = {
const CustomPrint = (props: CustomPrintProps) => {
const { act } = useBackend();
const { design, available } = props;
const canPrint = !Object.entries(design.cost).some(
([material, amount]) =>
!available[material] || amount > (available[material] ?? 0),
let maxMult = Object.entries(design.cost).reduce(
(accumulator: number, [material, required]) => {
return Math.min(accumulator, (available[material] || 0) / required);
},
Infinity,
);
maxMult = Math.min(Math.floor(maxMult), 50);
const canPrint = maxMult > 0;
return (
<div
@@ -137,7 +141,7 @@ const CustomPrint = (props: CustomPrintProps) => {
})
}
>
[Max: {design.maxmult}]
[Max: {maxMult}]
</Button.Input>
</div>
);