TGUI Research

This commit is contained in:
ShadowLarkens
2020-08-25 13:25:57 -07:00
parent 3de27a9e8f
commit 097d4fa283
144 changed files with 9345 additions and 4773 deletions
+28
View File
@@ -0,0 +1,28 @@
/// Module is compatible with Security Cyborg models
#define BORG_MODULE_SECURITY (1<<0)
/// Module is compatible with Miner Cyborg models
#define BORG_MODULE_MINER (1<<1)
/// Module is compatible with Janitor Cyborg models
#define BORG_MODULE_JANITOR (1<<2)
/// Module is compatible with Medical Cyborg models
#define BORG_MODULE_MEDICAL (1<<3)
/// Module is compatible with Engineering Cyborg models
#define BORG_MODULE_ENGINEERING (1<<4)
/// Module is compatible with Ripley Exosuit models
#define EXOSUIT_MODULE_RIPLEY (1<<0)
/// Module is compatible with Odyseeus Exosuit models
#define EXOSUIT_MODULE_ODYSSEUS (1<<1)
/// Module is compatible with Gygax Exosuit models
#define EXOSUIT_MODULE_GYGAX (1<<2)
/// Module is compatible with Durand Exosuit models
#define EXOSUIT_MODULE_DURAND (1<<3)
/// Module is compatible with Phazon Exosuit models
#define EXOSUIT_MODULE_PHAZON (1<<4)
/// Module is compatible with "Working" Exosuit models - Ripley
#define EXOSUIT_MODULE_WORKING EXOSUIT_MODULE_RIPLEY
/// Module is compatible with "Combat" Exosuit models - Gygax, Durand and Phazon
#define EXOSUIT_MODULE_COMBAT EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON
/// Module is compatible with "Medical" Exosuit modelsm - Odysseus
#define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS
+2
View File
@@ -57,6 +57,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define INIT_ORDER_SKYBOX 30
#define INIT_ORDER_MAPPING 25
#define INIT_ORDER_DECALS 20
#define INIT_ORDER_PLANTS 18 // Must initialize before atoms.
#define INIT_ORDER_JOB 17
#define INIT_ORDER_ALARM 16 // Must initialize before atoms.
#define INIT_ORDER_ATOMS 15
@@ -87,6 +88,7 @@ var/global/list/runlevel_flags = list(RUNLEVEL_LOBBY, RUNLEVEL_SETUP, RUNLEVEL_G
#define FIRE_PRIORITY_SHUTTLES 5
#define FIRE_PRIORITY_SUPPLY 5
#define FIRE_PRIORITY_NIGHTSHIFT 5
#define FIRE_PRIORITY_PLANTS 5
#define FIRE_PRIORITY_ORBIT 8
#define FIRE_PRIORITY_VOTE 9
#define FIRE_PRIORITY_AI 10
@@ -1,32 +1,12 @@
// Attempts to offload processing for the spreading plants from the MC.
// Processes vines/spreading plants.
#define PLANTS_PER_TICK 500 // Cap on number of plant segments processed.
#define PLANT_TICK_TIME 75 // Number of ticks between the plant processor cycling.
// Debug for testing seed genes.
/client/proc/show_plant_genes()
set category = "Debug"
set name = "Show Plant Genes"
set desc = "Prints the round's plant gene masks."
SUBSYSTEM_DEF(plants)
name = "Plants"
init_order = INIT_ORDER_PLANTS
priority = FIRE_PRIORITY_PLANTS
wait = PLANT_TICK_TIME
if(!holder) return
if(!plant_controller || !plant_controller.gene_tag_masks)
to_chat(usr, "Gene masks not set.")
return
for(var/mask in plant_controller.gene_tag_masks)
to_chat(usr, "[mask]: [plant_controller.gene_tag_masks[mask]]")
var/global/datum/controller/plants/plant_controller // Set in New().
/datum/controller/plants
var/plants_per_tick = PLANTS_PER_TICK
var/plant_tick_time = PLANT_TICK_TIME
var/list/product_descs = list() // Stores generated fruit descs.
var/list/plant_queue = list() // All queued plants.
var/list/seeds = list() // All seed data stored here.
var/list/gene_tag_masks = list() // Gene obfuscation for delicious trial and error goodness.
var/list/plant_icon_cache = list() // Stores images of growth, fruits and seeds.
@@ -34,24 +14,26 @@ var/global/datum/controller/plants/plant_controller // Set in New().
var/list/accessible_plant_sprites = list() // List of all plant sprites allowed to appear in random generation.
var/list/plant_product_sprites = list() // List of all harvested product sprites.
var/list/accessible_product_sprites = list() // List of all product sprites allowed to appear in random generation.
var/processing = 0 // Off/on.
var/list/gene_masked_list = list() // Stored gene masked list, rather than recreating it when needed.
var/list/plant_gene_datums = list() // Stored datum versions of the gene masked list.
/datum/controller/plants/New()
if(plant_controller && plant_controller != src)
log_debug("Rebuilding plant controller.")
qdel(plant_controller)
plant_controller = src
// To be clear, the only thing this processes are spreading plants
// Hydro trays and growing food normally just chill in SSobj
var/list/processing = list()
var/list/currentrun = list()
/datum/controller/subsystem/plants/stat_entry()
..("P:[processing.len]|S:[seeds.len]")
/datum/controller/subsystem/plants/Initialize(timeofday)
setup()
process()
return ..()
// Predefined/roundstart varieties use a string key to make it
// easier to grab the new variety when mutating. Post-roundstart
// and mutant varieties use their uid converted to a string instead.
// Looks like shit but it's sort of necessary.
/datum/controller/plants/proc/setup()
/datum/controller/subsystem/plants/proc/setup()
// Build the icon lists.
for(var/icostate in cached_icon_states('icons/obj/hydroponics_growing.dmi'))
var/split = findtext(icostate,"-")
@@ -116,10 +98,10 @@ var/global/datum/controller/plants/plant_controller // Set in New().
gene_masked_list.Add(list(list("tag" = gene_tag, "mask" = gene_mask)))
// Proc for creating a random seed type.
/datum/controller/plants/proc/create_random_seed(var/survive_on_station)
/datum/controller/subsystem/plants/proc/create_random_seed(var/survive_on_station)
var/datum/seed/seed = new()
seed.randomize()
seed.uid = plant_controller.seeds.len + 1
seed.uid = SSplants.seeds.len + 1
seed.name = "[seed.uid]"
seeds[seed.name] = seed
@@ -138,32 +120,41 @@ var/global/datum/controller/plants/plant_controller // Set in New().
seed.set_trait(TRAIT_HIGHKPA_TOLERANCE,200)
return seed
/datum/controller/plants/process()
processing = 1
spawn(0)
set background = 1
var/processed = 0
while(1)
if(!processing)
sleep(plant_tick_time)
else
processed = 0
if(plant_queue.len)
var/target_to_process = min(plant_queue.len,plants_per_tick)
for(var/x=0;x<target_to_process;x++)
if(!plant_queue.len)
break
var/obj/effect/plant/plant = pick(plant_queue)
plant_queue -= plant
if(!istype(plant))
continue
plant.process()
processed++
sleep(1) // Stagger processing out so previous tick can resolve (overlapping plant segments etc)
sleep(max(1,(plant_tick_time-processed)))
/datum/controller/subsystem/plants/fire(resumed = 0)
if(!resumed)
src.currentrun = processing.Copy()
/datum/controller/plants/proc/add_plant(var/obj/effect/plant/plant)
plant_queue |= plant
// Caching
var/list/currentrun = src.currentrun
while(currentrun.len)
var/obj/effect/plant/P = currentrun[currentrun.len]
--currentrun.len
if(!P || QDELETED(P))
continue
P.process()
/datum/controller/plants/proc/remove_plant(var/obj/effect/plant/plant)
plant_queue -= plant
if(MC_TICK_CHECK)
return
/datum/controller/subsystem/plants/proc/add_plant(var/obj/effect/plant/plant)
processing |= plant
/datum/controller/subsystem/plants/proc/remove_plant(var/obj/effect/plant/plant)
processing -= plant
// Debug for testing seed genes.
/client/proc/show_plant_genes()
set category = "Debug"
set name = "Show Plant Genes"
set desc = "Prints the round's plant gene masks."
if(!holder) return
if(!SSplants || !SSplants.gene_tag_masks)
to_chat(usr, "Gene masks not set.")
return
for(var/mask in SSplants.gene_tag_masks)
to_chat(usr, "[mask]: [SSplants.gene_tag_masks[mask]]")
-1
View File
@@ -97,7 +97,6 @@
options["LEGACY: cameranet"] = cameranet
options["LEGACY: transfer_controller"] = transfer_controller
options["LEGACY: gas_data"] = gas_data
options["LEGACY: plant_controller"] = plant_controller
var/pick = input(mob, "Choose a controller to debug/view variables of.", "VV controller:") as null|anything in options
if(!pick)
+30 -30
View File
@@ -48,7 +48,7 @@
/datum/category_item/autolathe/arms/pistol_5mm
name = "pistol magazine (5mm)"
path =/obj/item/ammo_magazine/c5mm
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
*/
@@ -237,93 +237,93 @@
/datum/category_item/autolathe/arms/pistol_5mm
name = "pistol magazine (5mm)"
path =/obj/item/ammo_magazine/c5mm/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/smg_5mm
name = "top-mounted SMG magazine (5mm)"
path =/obj/item/ammo_magazine/c5mmt/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_45
name = "pistol magazine (.45)"
path =/obj/item/ammo_magazine/m45/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_45uzi
name = "uzi magazine (.45)"
path =/obj/item/ammo_magazine/m45uzi/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/tommymag
name = "Tommy Gun magazine (.45)"
path =/obj/item/ammo_magazine/m45tommy/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/tommydrum
name = "Tommy Gun drum magazine (.45)"
path =/obj/item/ammo_magazine/m45tommydrum/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_9mm
name = "pistol magazine (9mm)"
path =/obj/item/ammo_magazine/m9mm/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/smg_9mm
name = "top-mounted SMG magazine (9mm)"
path =/obj/item/ammo_magazine/m9mmt/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/smg_10mm
name = "SMG magazine (10mm)"
path =/obj/item/ammo_magazine/m10mm/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_44
name = "pistol magazine (.44)"
path =/obj/item/ammo_magazine/m44/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/rifle_545
name = "10rnd rifle magazine (5.45mm)"
path =/obj/item/ammo_magazine/m545saw/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/rifle_545m
name = "20rnd rifle magazine (5.45mm)"
path =/obj/item/ammo_magazine/m545sawm/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/rifle_SVD
name = "10rnd rifle magazine (7.62mm)"
path =/obj/item/ammo_magazine/m762svd/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/rifle_762
name = "20rnd rifle magazine (7.62mm)"
path =/obj/item/ammo_magazine/m762/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/machinegun_762
name = "machinegun box magazine (7.62)"
path =/obj/item/ammo_magazine/a762/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/shotgun_magazine
name = "24rnd shotgun magazine (12g)"
path =/obj/item/ammo_magazine/m12gdrum/empty
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1*/
///////////////////////////////
@@ -357,73 +357,73 @@
/*/datum/category_item/autolathe/arms/pistol_clip_45
name = "ammo clip (.45)"
path =/obj/item/ammo_magazine/clip/c45
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_clip_45r
name = "ammo clip (.45 rubber)"
path =/obj/item/ammo_magazine/clip/c45/rubber
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_45f
name = "ammo clip (.45 flash)"
path =/obj/item/ammo_magazine/clip/c45/flash
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_45p
name = "ammo clip (.45 practice)"
path =/obj/item/ammo_magazine/clip/c45/practice
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_9mm
name = "ammo clip (9mm)"
path =/obj/item/ammo_magazine/clip/c9mm
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_clip_9mmr
name = "ammo clip (9mm rubber)"
path =/obj/item/ammo_magazine/clip/c9mm/rubber
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_9mmp
name = "ammo clip (9mm practice)"
path =/obj/item/ammo_magazine/clip/c9mm/practice
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_9mmf
name = "ammo clip (9mm flash)"
path =/obj/item/ammo_magazine/clip/c9mm/flash
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/pistol_clip_5mm
name = "ammo clip (5mm)"
path =/obj/item/ammo_magazine/clip/c5mm
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_clip_10mm
name = "ammo clip (10mm)"
path =/obj/item/ammo_magazine/clip/c10mm
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/pistol_clip_50
name = "ammo clip (.44)"
path =/obj/item/ammo_magazine/clip/c50
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
*/
/datum/category_item/autolathe/arms/rifle_clip_545
name = "ammo clip (5.45mm)"
path =/obj/item/ammo_magazine/clip/c545
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
hidden = 1
/datum/category_item/autolathe/arms/rifle_clip_545_practice
name = "ammo clip (5.45mm practice)"
path =/obj/item/ammo_magazine/clip/c545/practice
category = "Arms and Ammunition"
category = list("Arms and Ammunition")
/datum/category_item/autolathe/arms/rifle_clip_762
name = "ammo clip (7.62mm)"
-2
View File
@@ -1,5 +1,3 @@
var/datum/category_collection/autolathe/autolathe_recipes
/datum/category_item/autolathe/New()
..()
var/obj/item/I = new path()
+3
View File
@@ -25,6 +25,7 @@
switch(wire)
if(WIRE_AUTOLATHE_HACK)
A.hacked = !mend
A.update_tgui_static_data(usr)
if(WIRE_ELECTRIFY)
A.shocked = !mend
if(WIRE_AUTOLATHE_DISABLE)
@@ -38,9 +39,11 @@
switch(wire)
if(WIRE_AUTOLATHE_HACK)
A.hacked = !A.hacked
A.update_tgui_static_data(usr)
spawn(50)
if(A && !is_cut(wire))
A.hacked = 0
A.update_tgui_static_data(usr)
if(WIRE_ELECTRIFY)
A.shocked = !A.shocked
spawn(50)
+142 -147
View File
@@ -11,10 +11,10 @@
clickvol = 30
circuit = /obj/item/weapon/circuitboard/autolathe
var/datum/category_collection/autolathe/machine_recipes
var/static/datum/category_collection/autolathe/autolathe_recipes
var/list/stored_material = list(DEFAULT_WALL_MATERIAL = 0, MAT_GLASS = 0, MAT_PLASTEEL = 0, MAT_PLASTIC = 0)
var/list/storage_capacity = list(DEFAULT_WALL_MATERIAL = 0, MAT_GLASS = 0, MAT_PLASTEEL = 0, MAT_PLASTIC = 0)
var/datum/category_group/autolathe/current_category
var/hacked = 0
var/disabled = 0
@@ -33,6 +33,8 @@
/obj/machinery/autolathe/Initialize()
. = ..()
if(!autolathe_recipes)
autolathe_recipes = new()
wires = new(src)
default_apply_parts()
RefreshParts()
@@ -42,87 +44,77 @@
wires = null
return ..()
/obj/machinery/autolathe/proc/update_recipe_list()
if(!machine_recipes)
if(!autolathe_recipes)
autolathe_recipes = new()
machine_recipes = autolathe_recipes
current_category = machine_recipes.categories[1]
/obj/machinery/autolathe/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Autolathe", name)
ui.open()
/obj/machinery/autolathe/interact(mob/user as mob)
update_recipe_list()
/obj/machinery/autolathe/tgui_status(mob/user)
if(disabled)
return STATUS_CLOSE
return ..()
if(..() || (disabled && !panel_open))
/obj/machinery/autolathe/tgui_static_data(mob/user)
var/list/data = ..()
var/list/categories = list()
var/list/recipes = list()
for(var/datum/category_group/autolathe/A in autolathe_recipes.categories)
categories += A.name
for(var/datum/category_item/autolathe/M in A.items)
if(M.hidden && !hacked)
continue
if(M.man_rating > man_rating)
continue
recipes.Add(list(list(
"category" = A.name,
"name" = M.name,
"ref" = REF(M),
"requirements" = M.resources,
"hidden" = M.hidden,
"coeff_applies" = !M.no_scale,
)))
data["recipes"] = recipes
data["categories"] = categories
return data
/obj/machinery/autolathe/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
)
/obj/machinery/autolathe/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/list/material_data = list()
for(var/mat_id in stored_material)
var/amount = stored_material[mat_id]
var/list/material_info = list(
"name" = mat_id,
"amount" = amount,
"sheets" = round(amount / SHEET_MATERIAL_AMOUNT),
"removable" = amount >= SHEET_MATERIAL_AMOUNT
)
material_data += list(material_info)
data["busy"] = busy
data["materials"] = material_data
data["mat_efficiency"] = mat_efficiency
return data
/obj/machinery/autolathe/interact(mob/user)
if(panel_open)
return wires.Interact(user)
if(disabled)
to_chat(user, "<span class='danger'>\The [src] is disabled!</span>")
return
if(shocked)
shock(user, 50)
var/list/dat = list()
dat += "<center><h1>Autolathe Control Panel</h1><hr/>"
if(!disabled)
dat += "<table width = '100%'>"
var/list/material_top = list("<tr>")
var/list/material_bottom = list("<tr>")
for(var/material in stored_material)
if(material != DEFAULT_WALL_MATERIAL && material != MAT_GLASS) // Don't show the Extras unless people care enough to put them in.
if(stored_material[material] <= 0)
continue
material_top += "<td width = '25%' align = center><b>[material]</b></td>"
material_bottom += "<td width = '25%' align = center>[stored_material[material]]<b>/[storage_capacity[material]]</b></td>"
dat += "[material_top.Join()]</tr>[material_bottom.Join()]</tr></table><hr>"
dat += "<b>Filter:</b> <a href='?src=\ref[src];setfilter=1'>[filtertext ? filtertext : "None Set"]</a><br>"
dat += "<h2>Printable Designs</h2><h3>Showing: <a href='?src=\ref[src];change_category=1'>[current_category]</a>.</h3></center><table width = '100%'>"
for(var/datum/category_item/autolathe/R in current_category.items)
if(R.hidden && !hacked) // Illegal or nonstandard.
continue
if(R.man_rating > man_rating) // Advanced parts.
continue
if(filtertext && findtext(R.name, filtertext) == 0)
continue
var/can_make = 1
var/list/material_string = list()
var/list/multiplier_string = list()
var/max_sheets
var/comma
if(!R.resources || !R.resources.len)
material_string += "No resources required.</td>"
else
//Make sure it's buildable and list requires resources.
for(var/material in R.resources)
var/coeff = (R.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
var/sheets = round(stored_material[material]/round(R.resources[material]*coeff))
if(isnull(max_sheets) || max_sheets > sheets)
max_sheets = sheets
if(!isnull(stored_material[material]) && stored_material[material] < round(R.resources[material]*coeff))
can_make = 0
if(!comma)
comma = 1
else
material_string += ", "
material_string += "[round(R.resources[material] * coeff)] [material]"
material_string += ".<br></td>"
//Build list of multipliers for sheets.
if(R.is_stack)
if(max_sheets && max_sheets > 0)
max_sheets = min(max_sheets, R.max_stack) // Limit to the max allowed by stack type.
multiplier_string += "<br>"
for(var/i = 5;i<max_sheets;i*=2) //5,10,20,40...
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[i]'>\[x[i]\]</a>"
multiplier_string += "<a href='?src=\ref[src];make=\ref[R];multiplier=[max_sheets]'>\[x[max_sheets]\]</a>"
dat += "<tr><td width = 180>[R.hidden ? "<font color = 'red'>*</font>" : ""]<b>[can_make ? "<a href='?src=\ref[src];make=\ref[R];multiplier=1'>" : "<span class='linkOff'>"][R.name][can_make ? "</a>" : "</span>"]</b>[R.hidden ? "<font color = 'red'>*</font>" : ""][multiplier_string.Join()]</td><td align = right>[material_string.Join()]</tr>"
dat += "</table><hr>"
dat = jointext(dat, null)
var/datum/browser/popup = new(user, "autolathe", "Autolathe Production Menu", 550, 700)
popup.set_content(dat)
popup.open()
tgui_interact(user)
/obj/machinery/autolathe/attackby(var/obj/item/O as obj, var/mob/user as mob)
if(busy)
@@ -130,7 +122,7 @@
return
if(default_deconstruction_screwdriver(user, O))
updateUsrDialog()
interact(user)
return
if(default_deconstruction_crowbar(user, O))
return
@@ -155,18 +147,6 @@
if(istype(O,/obj/item/ammo_magazine/clip) || istype(O,/obj/item/ammo_magazine/s357) || istype(O,/obj/item/ammo_magazine/s38) || istype (O,/obj/item/ammo_magazine/s44)/* VOREstation Edit*/) // Prevents ammo recycling exploit with speedloaders.
to_chat(user, "\The [O] is too hazardous to recycle with the autolathe!")
return
/* ToDo: Make this actually check for ammo and change the value of the magazine if it's empty. -Spades
var/obj/item/ammo_magazine/speedloader = O
if(speedloader.stored_ammo)
to_chat(user, "\The [speedloader] is too hazardous to put back into the autolathe while there's ammunition inside of it!")
return
else
speedloader.matter = list(DEFAULT_WALL_MATERIAL = 75) // It's just a hunk of scrap metal now.
if(istype(O,/obj/item/ammo_magazine)) // This was just for immersion consistency with above.
var/obj/item/ammo_magazine/mag = O
if(mag.stored_ammo)
to_chat(user, "\The [mag] is too hazardous to put back into the autolathe while there's ammunition inside of it!")
return*/
//Resources are being loaded.
var/obj/item/eating = O
@@ -227,9 +207,9 @@
user.set_machine(src)
interact(user)
/obj/machinery/autolathe/Topic(href, href_list)
/obj/machinery/autolathe/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
return TRUE
usr.set_machine(src)
add_fingerprint(usr)
@@ -237,72 +217,69 @@
if(busy)
to_chat(usr, "<span class='notice'>The autolathe is busy. Please wait for completion of previous operation.</span>")
return
switch(action)
if("make")
var/datum/category_item/autolathe/making = locate(params["make"])
if(!istype(making))
return
if(making.hidden && !hacked)
return
else if(href_list["setfilter"])
var/filterstring = input(usr, "Input a filter string, or blank to not filter:", "Design Filter", filtertext) as null|text
if(!Adjacent(usr))
return
if(isnull(filterstring)) //Clicked Cancel
return
if(filterstring == "") //Cleared value
filtertext = null
filtertext = sanitize(filterstring, 25)
var/multiplier = 1
if(href_list["change_category"])
if(making.is_stack)
var/max_sheets
for(var/material in making.resources)
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
var/sheets = round(stored_material[material]/round(making.resources[material]*coeff))
if(isnull(max_sheets) || max_sheets > sheets)
max_sheets = sheets
if(!isnull(stored_material[material]) && stored_material[material] < round(making.resources[material]*coeff))
max_sheets = 0
//Build list of multipliers for sheets.
multiplier = input(usr, "How many do you want to print? (0-[max_sheets])") as num|null
if(!multiplier || multiplier <= 0 || multiplier > max_sheets || tgui_status(usr, state) != STATUS_INTERACTIVE)
return FALSE
var/choice = input("Which category do you wish to display?") as null|anything in machine_recipes.categories
if(!choice) return
current_category = choice
busy = making.name
update_use_power(USE_POWER_ACTIVE)
if(href_list["make"] && machine_recipes)
var/multiplier = text2num(href_list["multiplier"])
var/datum/category_item/autolathe/making = locate(href_list["make"]) in current_category.items
//Check if we still have the materials.
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
for(var/material in making.resources)
if(!isnull(stored_material[material]))
if(stored_material[material] < round(making.resources[material] * coeff) * multiplier)
return
//Exploit detection, not sure if necessary after rewrite.
if(!making || multiplier < 0 || multiplier > 100)
var/turf/exploit_loc = get_turf(usr)
message_admins("[key_name_admin(usr)] tried to exploit an autolathe to duplicate an item! ([exploit_loc ? "<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[exploit_loc.x];Y=[exploit_loc.y];Z=[exploit_loc.z]'>JMP</a>" : "null"])", 0)
log_admin("EXPLOIT : [key_name(usr)] tried to exploit an autolathe to duplicate an item!")
return
//Consume materials.
for(var/material in making.resources)
if(!isnull(stored_material[material]))
stored_material[material] = max(0, stored_material[material] - round(making.resources[material] * coeff) * multiplier)
busy = 1
update_use_power(USE_POWER_ACTIVE)
update_icon() // So lid closes
//Check if we still have the materials.
var/coeff = (making.no_scale ? 1 : mat_efficiency) //stacks are unaffected by production coefficient
for(var/material in making.resources)
if(!isnull(stored_material[material]))
if(stored_material[material] < round(making.resources[material] * coeff) * multiplier)
return
sleep(build_time)
//Consume materials.
for(var/material in making.resources)
if(!isnull(stored_material[material]))
stored_material[material] = max(0, stored_material[material] - round(making.resources[material] * coeff) * multiplier)
busy = 0
update_use_power(USE_POWER_IDLE)
update_icon() // So lid opens
update_icon() // So lid closes
//Sanity check.
if(!making || !src)
return
sleep(build_time)
busy = 0
update_use_power(USE_POWER_IDLE)
update_icon() // So lid opens
//Sanity check.
if(!making || !src) return
//Create the desired item.
var/obj/item/I = new making.path(src.loc)
flick("[initial(icon_state)]_finish", src)
if(multiplier > 1)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
S.amount = multiplier
else
for(multiplier; multiplier > 1; --multiplier) // Create multiple items if it's not a stack.
new making.path(src.loc)
updateUsrDialog()
//Create the desired item.
var/obj/item/I = new making.path(src.loc)
flick("[initial(icon_state)]_finish", src)
if(multiplier > 1)
if(istype(I, /obj/item/stack))
var/obj/item/stack/S = I
S.amount = multiplier
else
for(multiplier; multiplier > 1; --multiplier) // Create multiple items if it's not a stack.
new making.path(src.loc)
return TRUE
return FALSE
/obj/machinery/autolathe/update_icon()
overlays.Cut()
@@ -332,6 +309,7 @@
storage_capacity["glass"] = mb_rating * 12500
build_time = 50 / man_rating
mat_efficiency = 1.1 - man_rating * 0.1// Normally, price is 1.25 the amount of material, so this shouldn't go higher than 0.6. Maximum rating of parts is 5
update_tgui_static_data(usr)
/obj/machinery/autolathe/dismantle()
for(var/mat in stored_material)
@@ -345,3 +323,20 @@
qdel(S)
..()
return 1
/obj/machinery/autolathe/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything
var/recursive = amount == -1 ? 1 : 0
var/matstring = lowertext(material)
var/material/M = get_material_by_name(matstring)
var/obj/item/stack/material/S = M.place_sheet(get_turf(src))
if(amount <= 0)
amount = S.max_amount
var/ejected = min(round(stored_material[matstring] / S.perunit), amount)
S.amount = min(ejected, amount)
if(S.amount <= 0)
qdel(S)
return
stored_material[matstring] -= ejected * S.perunit
if(recursive && stored_material[matstring] >= S.perunit)
eject_materials(matstring, -1)
+179 -185
View File
@@ -1,3 +1,17 @@
// Use this define to register something as a creatable!
// * n - The proper name of the purchasable
// * o - The object type path of the purchasable to spawn
// * r - The amount to dispense
// * p - The price of the purchasable in biomass
#define BIOGEN_ITEM(n, o, r, p) n = new /datum/data/biogenerator_item(n, o, r, p)
// Use this define to register something as dispensable
// * n - The proper name of the purchasable
// * o - The reagent ID
// * r - The amount of reagent to dispense
// * p - The price of the purchasable in biomass
#define BIOGEN_REAGENT(n, o, r, p) n = new /datum/data/biogenerator_reagent(n, o, r, p)
/obj/machinery/biogenerator
name = "biogenerator"
desc = "Converts plants into biomass, which can be used for fertilizer and sort-of-synthetic products."
@@ -11,10 +25,34 @@
var/processing = 0
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/points = 0
var/menustat = "menu"
var/build_eff = 1
var/eat_eff = 1
var/list/item_list
/datum/data/biogenerator_item
var/equipment_path = null
var/equipment_amt = 1
var/cost = 0
/datum/data/biogenerator_item/New(name, path, amt, cost)
src.name = name
src.equipment_path = path
src.equipment_amt = amt
src.cost = cost
/datum/data/biogenerator_reagent
var/reagent_id = null
var/reagent_amt = 0
var/cost = 0
/datum/data/biogenerator_reagent/New(name, id, amt, cost)
src.name = name
src.reagent_id = id
src.reagent_amt = amt
src.cost = cost
/obj/machinery/biogenerator/Initialize()
. = ..()
var/datum/reagents/R = new/datum/reagents(1000)
@@ -24,6 +62,140 @@
beaker = new /obj/item/weapon/reagent_containers/glass/bottle(src)
default_apply_parts()
item_list = list()
item_list["Food Items"] = list(
BIOGEN_REAGENT("10 milk", "milk", 10, 20),
BIOGEN_REAGENT("50 milk", "milk", 50, 95),
BIOGEN_REAGENT("10 Cream", "cream", 10, 30),
BIOGEN_REAGENT("50 Cream", "cream", 50, 120),
BIOGEN_ITEM("Slab of meat", /obj/item/weapon/reagent_containers/food/snacks/meat, 1, 50),
BIOGEN_ITEM("5 slabs of meat", /obj/item/weapon/reagent_containers/food/snacks/meat, 5, 250),
)
item_list["Cooking Ingredients"] = list(
BIOGEN_REAGENT("10 Universal Enzyme", "enzyme", 10, 30),
BIOGEN_REAGENT("50 Universal Enzyme", "enzyme", 50, 120),
BIOGEN_ITEM("Nutri-spread", /obj/item/weapon/reagent_containers/food/snacks/spreads, 1, 30),
BIOGEN_ITEM("5 nutri-spread", /obj/item/weapon/reagent_containers/food/snacks/spreads, 5, 120),
)
item_list["Gardening Nutrients"] = list(
BIOGEN_ITEM("E-Z-Nutrient", /obj/item/weapon/reagent_containers/glass/bottle/eznutrient, 1, 60),
BIOGEN_ITEM("5 E-Z-Nutrient", /obj/item/weapon/reagent_containers/glass/bottle/eznutrient, 5, 300),
BIOGEN_ITEM("Left 4 Zed", /obj/item/weapon/reagent_containers/glass/bottle/left4zed, 1, 120),
BIOGEN_ITEM("5 Left 4 Zed", /obj/item/weapon/reagent_containers/glass/bottle/left4zed, 5, 600),
BIOGEN_ITEM("Robust Harvest", /obj/item/weapon/reagent_containers/glass/bottle/robustharvest, 1, 150),
BIOGEN_ITEM("5 Robust Harvest", /obj/item/weapon/reagent_containers/glass/bottle/robustharvest, 5, 750),
)
item_list["Leather Products"] = list(
BIOGEN_ITEM("Wallet", /obj/item/weapon/storage/wallet, 1, 100),
BIOGEN_ITEM("Botanical gloves", /obj/item/clothing/gloves/botanic_leather, 1, 250),
BIOGEN_ITEM("Plant bag", /obj/item/weapon/storage/bag/plants, 1, 320),
BIOGEN_ITEM("Large plant bag", /obj/item/weapon/storage/bag/plants/large, 1, 640),
BIOGEN_ITEM("Utility belt", /obj/item/weapon/storage/belt/utility, 1, 300),
BIOGEN_ITEM("Leather Satchel", /obj/item/weapon/storage/backpack/satchel, 1, 400),
BIOGEN_ITEM("Cash Bag", /obj/item/weapon/storage/bag/cash, 1, 400),
BIOGEN_ITEM("Chemistry Bag", /obj/item/weapon/storage/bag/chemistry, 1, 400),
BIOGEN_ITEM("Workboots", /obj/item/clothing/shoes/boots/workboots, 1, 400),
BIOGEN_ITEM("Leather Shoes", /obj/item/clothing/shoes/leather, 1, 400),
BIOGEN_ITEM("Leather Chaps", /obj/item/clothing/under/pants/chaps, 1, 400),
BIOGEN_ITEM("Leather Coat", /obj/item/clothing/suit/leathercoat, 1, 500),
BIOGEN_ITEM("Leather Jacket", /obj/item/clothing/suit/storage/toggle/brown_jacket, 1, 500),
BIOGEN_ITEM("Winter Coat", /obj/item/clothing/suit/storage/hooded/wintercoat, 1, 500),
//VOREStation Edit - Algae for oxygen generator
BIOGEN_ITEM("4 Algae Sheets", /obj/item/stack/material/algae, 4, 400),
)
/obj/machinery/biogenerator/tgui_static_data(mob/user)
var/list/static_data[0]
// Available items - in static data because we don't wanna compute this list every time! It hardly changes.
static_data["items"] = list()
for(var/cat in item_list)
var/list/cat_items = list()
for(var/prize_name in item_list[cat])
var/datum/data/biogenerator_reagent/prize = item_list[cat][prize_name]
cat_items[prize_name] = list("name" = prize_name, "price" = prize.cost, "reagent" = istype(prize))
static_data["items"][cat] = cat_items
return static_data
/obj/machinery/biogenerator/tgui_data(mob/user)
var/list/data = ..()
data["build_eff"] = build_eff
data["points"] = points
data["processing"] = processing
data["beaker"] = !!beaker
return data
/obj/machinery/biogenerator/tgui_interact(mob/user, datum/tgui/ui = null)
// Open the window
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Biogenerator", name)
ui.open()
/obj/machinery/biogenerator/tgui_act(action, params)
if(..())
return
. = TRUE
switch(action)
if("activate")
INVOKE_ASYNC(src, .proc/activate)
return TRUE
if("detach")
if(beaker)
beaker.forceMove(loc)
beaker = null
update_icon()
return TRUE
if("purchase")
var/category = params["cat"] // meow
var/name = params["name"]
if(!(category in item_list) || !(name in item_list[category])) // Not trying something that's not in the list, are you?
return
var/datum/data/biogenerator_item/bi = item_list[category][name]
if(!istype(bi))
var/datum/data/biogenerator_reagent/br = item_list[category][name]
if(!istype(br))
return
if(!beaker)
return
var/cost = round(br.cost / build_eff)
if(cost > points)
to_chat(usr, "<span class='danger'>Insufficient biomass.</span>")
return
var/amt_to_actually_dispense = round(min(beaker.reagents.get_free_space(), br.reagent_amt))
if(amt_to_actually_dispense <= 0)
to_chat(usr, "<span class='danger'>The loaded beaker is full!</span>")
return
points -= (cost * (amt_to_actually_dispense / br.reagent_amt))
beaker.reagents.add_reagent(br.reagent_id, amt_to_actually_dispense)
playsound(src, 'sound/machines/reagent_dispense.ogg', 25, 1)
return
var/cost = round(bi.cost / build_eff)
if(cost > points)
to_chat(usr, "<span class='danger'>Insufficient biomass.</span>")
return
points -= cost
if(ispath(bi.equipment_path, /obj/item/stack))
var/obj/item/stack/S = new bi.equipment_path(loc)
S.amount = bi.equipment_amt
playsound(src, 'sound/machines/vending/vending_drop.ogg', 100, 1)
return TRUE
for(var/i in 1 to bi.equipment_amt)
new bi.equipment_path(loc)
playsound(src, 'sound/machines/vending/vending_drop.ogg', 100, 1)
return TRUE
else
return FALSE
/obj/machinery/biogenerator/on_reagent_change() //When the reagents change, change the icon as well.
update_icon()
@@ -87,68 +259,10 @@
update_icon()
return
/obj/machinery/biogenerator/interact(mob/user as mob)
/obj/machinery/biogenerator/attack_hand(mob/user as mob)
if(stat & BROKEN)
return
user.set_machine(src)
var/dat = "<TITLE>Biogenerator</TITLE>Biogenerator:<BR>"
if(processing)
dat += "<FONT COLOR=red>Biogenerator is processing! Please wait...</FONT>"
else
dat += "Biomass: [points] points.<HR>"
switch(menustat)
if("menu")
if(beaker)
dat += "<A href='?src=\ref[src];action=activate'>Activate Biogenerator!</A><BR>"
dat += "<A href='?src=\ref[src];action=detach'>Detach Container</A><BR><BR>"
dat += "Food Items:<BR>"
dat += "<A href='?src=\ref[src];action=create;item=milk;cost=20'>10 milk</A> <FONT COLOR=blue>([round(20/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=milk5;cost=95'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=cream;cost=30'>10 cream</A> <FONT COLOR=blue>([round(20/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=cream5;cost=120'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=meat;cost=50'>Slab of meat</A> <FONT COLOR=blue>([round(50/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=meat5;cost=250'>x5</A><BR>"
dat += "Cooking Ingredient:<BR>"
dat += "<A href='?src=\ref[src];action=create;item=unizyme;cost=30'>Universal Enzyme</A> <FONT COLOR=yellow>([round(30/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=unizyme50;cost=120'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=nutrispread;cost=30'>Nutri-Spread</A> <FONT COLOR=yellow>([round(30/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=nutrispread5;cost=120'>x5</A><BR>"
// dat += "<A href='?src=\ref[src];action=create;item=unizyme;cost=50'>Universal Enzyme</A> <FONT COLOR=yellow>([round(30/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=unizyme;cost=180'>x5</A><BR>"
// dat += "<A href='?src=\ref[src];action=create;item=unizyme;cost=50'>Universal Enzyme</A> <FONT COLOR=yellow>([round(30/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=unizyme;cost=180'>x5</A><BR>"
dat += "Gardening Nutrients:<BR>"
dat += "<A href='?src=\ref[src];action=create;item=ez;cost=60'>E-Z-Nutrient</A> <FONT COLOR=green>([round(60/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=ez5;cost=300'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=l4z;cost=120'>Left 4 Zed</A> <FONT COLOR=green>([round(120/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=l4z5;cost=600'>x5</A><BR>"
dat += "<A href='?src=\ref[src];action=create;item=rh;cost=150'>Robust Harvest</A> <FONT COLOR=green>([round(150/build_eff)])</FONT> | <A href='?src=\ref[src];action=create;item=rh5;cost=750'>x5</A><BR>"
dat += "Leather Products:<BR>"
dat += "<A href='?src=\ref[src];action=create;item=wallet;cost=100'>Wallet</A> <FONT COLOR=brown>([round(100/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=gloves;cost=250'>Botanical gloves</A> <FONT COLOR=green>([round(250/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=plantbag;cost=320'>Plant bag</A> <FONT COLOR=green>([round(250/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=plantbaglarge;cost=640'>Large plant bag</A> <FONT COLOR=green>([round(250/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=tbelt;cost=300'>Utility belt</A> <FONT COLOR=brown>([round(300/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=satchel;cost=400'>Leather Satchel</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=cashbag;cost=400'>Cash Bag</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=chembag;cost=400'>Chemistry Bag</A> <FONT COLOR=green>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=workboots;cost=400'>Workboots</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=leathershoes;cost=400'>Leather Shoes</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=leatherchaps;cost=400'>Leather Chaps</A> <FONT COLOR=brown>([round(400/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=leathercoat;cost=500'>Leather Coat</A> <FONT COLOR=brown>([round(500/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=leatherjacket;cost=500'>Leather Jacket</A> <FONT COLOR=brown>([round(500/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=wintercoat;cost=500'>Winter Coat</A> <FONT COLOR=brown>([round(500/build_eff)])</FONT><BR>"
dat += "<A href='?src=\ref[src];action=create;item=algae;cost=400'>4 Algae Sheets</A> <FONT COLOR=green>([round(400/build_eff)])</FONT><BR>" //VOREStation Edit - Algae for oxygen generator
//dat += "Other<BR>"
//dat += "<A href='?src=\ref[src];action=create;item=monkey;cost=500'>Monkey</A> <FONT COLOR=blue>(500)</FONT><BR>"
else
dat += "<BR><FONT COLOR=red>No beaker inside. Please insert a beaker.</FONT><BR>"
if("nopoints")
dat += "You do not have biomass to create products.<BR>Please, put growns into reactor and activate it.<BR>"
dat += "<A href='?src=\ref[src];action=menu'>Return to menu</A>"
if("complete")
dat += "Operation complete.<BR>"
dat += "<A href='?src=\ref[src];action=menu'>Return to menu</A>"
if("void")
dat += "<FONT COLOR=red>Error: No growns inside.</FONT><BR>Please, put growns into reactor.<BR>"
dat += "<A href='?src=\ref[src];action=menu'>Return to menu</A>"
user << browse(dat, "window=biogenerator")
onclose(user, "biogenerator")
return
/obj/machinery/biogenerator/attack_hand(mob/user as mob)
interact(user)
tgui_interact(user)
/obj/machinery/biogenerator/proc/activate()
if(usr.stat)
@@ -168,139 +282,17 @@
if(S)
processing = 1
update_icon()
updateUsrDialog()
playsound(src, 'sound/machines/blender.ogg', 40, 1)
use_power(S * 30)
sleep((S + 15) / eat_eff)
processing = 0
SStgui.update_uis(src)
playsound(src, 'sound/machines/biogenerator_end.ogg', 40, 1)
update_icon()
else
menustat = "void"
to_chat(usr, "<span class='warning'>Error: No growns inside. Please insert growns.</span>")
return
/obj/machinery/biogenerator/proc/create_product(var/item, var/cost)
cost = round(cost/build_eff)
if(cost > points)
menustat = "nopoints"
return 0
processing = 1
update_icon()
updateUsrDialog()
points -= cost
sleep(30)
switch(item)
if("milk")
beaker.reagents.add_reagent("milk", 10)
if("milk5")
beaker.reagents.add_reagent("milk", 50)
if("cream")
beaker.reagents.add_reagent("cream", 10)
if("cream5")
beaker.reagents.add_reagent("cream", 50)
if("meat")
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
if("meat5")
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc) //This is ugly.
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
new/obj/item/weapon/reagent_containers/food/snacks/meat(loc)
if("unizyme")
beaker.reagents.add_reagent("enzyme", 10)
if("unizyme50")
beaker.reagents.add_reagent("enzyme", 50)
if("nutrispread")
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
if("nutrispread5")
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
new/obj/item/weapon/reagent_containers/food/snacks/spreads(loc)
if("ez")
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
if("l4z")
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
if("rh")
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
if("ez5") //It's not an elegant method, but it's safe and easy. -Cheridan
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/eznutrient(loc)
if("l4z5")
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/left4zed(loc)
if("rh5")
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
new/obj/item/weapon/reagent_containers/glass/bottle/robustharvest(loc)
if("wallet")
new/obj/item/weapon/storage/wallet(loc)
if("gloves")
new/obj/item/clothing/gloves/botanic_leather(loc)
if("plantbag")
new/obj/item/weapon/storage/bag/plants(loc)
if("plantbaglarge")
new/obj/item/weapon/storage/bag/plants/large(loc)
if("tbelt")
new/obj/item/weapon/storage/belt/utility(loc)
if("satchel")
new/obj/item/weapon/storage/backpack/satchel(loc)
if("cashbag")
new/obj/item/weapon/storage/bag/cash(loc)
if("chembag")
new/obj/item/weapon/storage/bag/chemistry(loc)
if("monkey")
new/mob/living/carbon/human/monkey(loc)
if("workboots")
new/obj/item/clothing/shoes/boots/workboots(loc)
if("leathershoes")
new/obj/item/clothing/shoes/leather(loc)
if("leatherchaps")
new/obj/item/clothing/under/pants/chaps
if("leathercoat")
new/obj/item/clothing/suit/leathercoat(loc)
if("leatherjacket")
new/obj/item/clothing/suit/storage/toggle/brown_jacket(loc)
if("wintercoat")
new/obj/item/clothing/suit/storage/hooded/wintercoat(loc)
if("algae") //VOREStation Edit - Algae for oxygen generator
var/obj/item/stack/material/algae/A = new(loc)
A.amount = 4 //VOREStation Edit End
processing = 0
menustat = "complete"
update_icon()
return 1
/obj/machinery/biogenerator/Topic(href, href_list)
if(stat & BROKEN) return
if(usr.stat || usr.restrained()) return
if(!in_range(src, usr)) return
usr.set_machine(src)
switch(href_list["action"])
if("activate")
activate()
if("detach")
if(beaker)
beaker.loc = src.loc
beaker = null
update_icon()
if("create")
create_product(href_list["item"], text2num(href_list["cost"]))
if("menu")
menustat = "menu"
updateUsrDialog()
/obj/machinery/biogenerator/RefreshParts()
..()
var/man_rating = 0
@@ -314,3 +306,5 @@
build_eff = man_rating
eat_eff = bin_rating
#undef BIOGENITEM
+80 -88
View File
@@ -101,112 +101,104 @@
else
tank2 = I
update_icon()
updateUsrDialog()
SStgui.update_uis(src)
to_chat(user, "<span class='notice'>You connect \the [I] to \the [src]'s [I==tank1 ? "primary" : "secondary"] slot.</span>")
return
..()
/obj/machinery/bomb_tester/attack_hand(var/mob/user)
add_fingerprint(user)
interact(user)
tgui_interact(user)
/obj/machinery/bomb_tester/interact(var/mob/user)
if(stat & NOPOWER)
return
/obj/machinery/bomb_tester/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "BombTester", name)
ui.open()
var/dat = "<HEAD><TITLE>Bomb Tester</TITLE></HEAD>"
/obj/machinery/bomb_tester/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["simulating"] = simulating
if(!simulating)
data["mode"] = sim_mode
data["tank1"] = tank1
data["tank1ref"] = REF(tank1)
data["tank2"] = tank2
data["tank2ref"] = REF(tank2)
data["canister"] = test_canister
data["sim_canister_output"] = sim_canister_output
return data
dat += "<font face='terminal' size ='3'>Virtual Explosive Simulator v1.03</font>"
dat += "<br>"
if(simulating)
dat += "<br><center>Simulation in progress! Please wait for results.</center>"
else
dat += "<br><center>Mode: [sim_mode==MODE_SINGLE?"Single Tank":"<A href='?src=\ref[src];set_mode=1'>Single Tank</a>"] -- [sim_mode==MODE_DOUBLE?"Transfer Valve":"<A href='?src=\ref[src];set_mode=2'>Transfer Valve</a>"] -- [sim_mode==MODE_CANISTER?"Canister":"<A href='?src=\ref[src];set_mode=3'>Canister</a>"]</center>"
dat += "<br>"
dat += "<br><center><u>Gas Sources</u></center>"
dat += "<br><center><A href='?src=\ref[src];tank=1'>[tank1?"\[[tank1.name]\]":"\[Primary Slot\]"]</a> -- <A href='?src=\ref[src];tank=2'>[tank2?"\[[tank2.name]\]":"\[Secondary Slot\]"]</a></center>"
dat += "<br><center>Connected Canister: [test_canister?"[test_canister.name] -- ":"None -- "]<A href='?src=\ref[src];canister_scan=1'>[test_canister?"\[Rescan\]":"\[Scan for canister\]"]</a></center>"
if(test_canister)
dat += "<br><center>Canister Release Pressure: [sim_canister_output] Kilopascals</center>"
dat += "<br><center>"
dat += "<A href='?src=\ref[src];set_can_pressure=-1000'>-1000</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=-100'>-100</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=-10'>-10</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=-1'>-1</a> ||| "
dat += "<A href='?src=\ref[src];set_can_pressure=1'>+1</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=10'>+10</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=100'>+100</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=1000'>+1000</a>"
dat += "</center>"
dat += "<br><br>"
dat += "<br><center><font size='6'><b><A href='?src=\ref[src];start_sim=1'>BEGIN SIMULATION</a></b></font></center>"
user.set_machine(src)
user << browse(dat, "window=bomb_tester")
onclose(user, "bomb_tester")
/obj/machinery/bomb_tester/Topic(href, href_list)
/obj/machinery/bomb_tester/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
if(stat & NOPOWER)
return
if(!usr.Adjacent(src))
usr << browse(null, "window=bomb_tester")
usr.unset_machine()
return
return TRUE
if(simulating)
return
if(href_list["set_mode"])
sim_mode = text2num(href_list["set_mode"])
var/text_mode
switch(sim_mode)
if(MODE_SINGLE)
text_mode = "single gas tank detonation"
if(MODE_DOUBLE)
text_mode = "tank transfer valve detonation"
if(MODE_CANISTER)
text_mode = "canister-assisted single gas tank detonation"
to_chat(usr, "<span class='notice'>[src] set to simulate a [text_mode].</span>")
if(href_list["tank"])
var/tankvar = "tank[href_list["tank"]]"
var/obj/item/weapon/tank/T
if(vars[tankvar])
T = vars[tankvar]
T.forceMove(get_turf(src))
vars[tankvar] = null
else if(istype(usr.get_active_hand(),/obj/item/weapon/tank))
T = usr.get_active_hand()
usr.drop_item(T)
T.forceMove(src)
vars[tankvar] = T
update_icon()
if(href_list["canister_scan"])
for(var/obj/machinery/portable_atmospherics/canister/C in orange(1,src))
if(C && C == test_canister)
continue
else if(C)
test_canister = C
break
switch(action)
if("set_mode")
sim_mode = clamp(text2num(params["mode"]), MODE_SINGLE, MODE_CANISTER)
var/text_mode
switch(sim_mode)
if(MODE_SINGLE)
text_mode = "single gas tank detonation"
if(MODE_DOUBLE)
text_mode = "tank transfer valve detonation"
if(MODE_CANISTER)
text_mode = "canister-assisted single gas tank detonation"
to_chat(usr, "<span class='notice'>[src] set to simulate a [text_mode].</span>")
return TRUE
if("add_tank")
if(istype(usr.get_active_hand(), /obj/item/weapon/tank))
var/obj/item/weapon/tank/T = usr.get_active_hand()
var/slot = params["slot"]
if(slot == 1 && !tank1)
tank1 = T
else if(slot == 2 && !tank2)
tank2 = T
else
to_chat(usr, "<span class='warning'>Slot [slot] is full.</span>")
return
usr.drop_item(T)
T.forceMove(src)
return TRUE
else
test_canister = null
to_chat(usr, "<span class='warning'>You must be wielding a tank to insert it!</span>")
if(href_list["set_can_pressure"])
var/change = text2num(href_list["set_can_pressure"])
sim_canister_output = CLAMP(sim_canister_output+change, ONE_ATMOSPHERE/10, ONE_ATMOSPHERE*10)
if("remove_tank")
var/obj/item/weapon/tank/T = locate(params["ref"]) in list(tank1, tank2)
if(istype(T))
if(T == tank1)
tank1 = null
if(T == tank2)
tank2 = null
T.forceMove(get_turf(src))
update_icon()
return TRUE
if(href_list["start_sim"])
start_simulating()
if("canister_scan")
for(var/obj/machinery/portable_atmospherics/canister/C in orange(1,src))
if(C && C == test_canister)
continue
else if(C)
test_canister = C
break
else
test_canister = null
return TRUE
updateUsrDialog()
if("set_can_pressure")
sim_canister_output = CLAMP(text2num(params["pressure"]), ONE_ATMOSPHERE/10, ONE_ATMOSPHERE*10)
return TRUE
if("start_sim")
start_simulating()
return TRUE
/obj/machinery/bomb_tester/proc/start_simulating()
if(!tank1 || (sim_mode == MODE_DOUBLE && !tank2) || (sim_mode == MODE_CANISTER && !test_canister))
+203 -140
View File
@@ -6,162 +6,225 @@
light_color = "#a97faa"
req_access = list(access_robotics)
circuit = /obj/item/weapon/circuitboard/robotics
var/safety = 1
/obj/machinery/computer/robotics/attack_ai(var/mob/user as mob)
ui_interact(user)
tgui_interact(user)
/obj/machinery/computer/robotics/attack_hand(var/mob/user as mob)
ui_interact(user)
/obj/machinery/computer/robotics/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
data["robots"] = get_cyborgs(user)
data["is_ai"] = issilicon(user)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "robot_control.tmpl", "Robotic Control Console", 400, 500)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/computer/robotics/Topic(href, href_list)
if(..())
return
var/mob/user = usr
if(!src.allowed(user))
to_chat(user, "Access Denied")
if(stat & (NOPOWER|BROKEN))
return
tgui_interact(user)
// Locks or unlocks the cyborg
if (href_list["lockdown"])
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["lockdown"])
var/failmsg = ""
if(!target || !istype(target))
return
/obj/machinery/computer/robotics/proc/is_authenticated(mob/user)
if(!istype(user))
return FALSE
if(isobserver(user))
var/mob/observer/dead/D = user
if(D.can_admin_interact())
return TRUE
if(allowed(user))
return TRUE
return FALSE
if(isAI(user) && (target.connected_ai != user))
to_chat(user, "Access Denied. This robot is not linked to you.")
return
/**
* Does this borg show up in the console
*
* Returns TRUE if a robot will show up in the console
* Returns FALSE if a robot will not show up in the console
* Arguments:
* * R - The [mob/living/silicon/robot] to be checked
*/
/obj/machinery/computer/robotics/proc/console_shows(mob/living/silicon/robot/R)
if(!istype(R))
return FALSE
if(istype(R, /mob/living/silicon/robot/drone))
return FALSE
if(R.scrambledcodes)
return FALSE
if(!AreConnectedZLevels(get_z(src), get_z(R)))
return FALSE
return TRUE
if(isrobot(user))
to_chat(user, "Access Denied.")
return
/**
* Check if a user can send a lockdown/detonate command to a specific borg
*
* Returns TRUE if a user can send the command (does not guarantee it will work)
* Returns FALSE if a user cannot
* Arguments:
* * user - The [mob/user] to be checked
* * R - The [mob/living/silicon/robot] to be checked
* * telluserwhy - Bool of whether the user should be sent a to_chat message if they don't have access
*/
/obj/machinery/computer/robotics/proc/can_control(mob/user, mob/living/silicon/robot/R, telluserwhy = FALSE)
if(!istype(user))
return FALSE
if(!console_shows(R))
return FALSE
if(isAI(user))
if(R.connected_ai != user)
if(telluserwhy)
to_chat(user, "<span class='warning'>AIs can only control cyborgs which are linked to them.</span>")
return FALSE
if(isrobot(user))
if(R != user)
if(telluserwhy)
to_chat(user, "<span class='warning'>Cyborgs cannot control other cyborgs.</span>")
return FALSE
return TRUE
var/choice = input("Really [target.lockcharge ? "unlock" : "lockdown"] [target.name] ?") in list ("Yes", "No")
if(choice != "Yes")
return
/**
* Check if the user is the right kind of entity to be able to hack borgs
*
* Returns TRUE if a user is a traitor AI, or aghost
* Returns FALSE otherwise
* Arguments:
* * user - The [mob/user] to be checked
*/
/obj/machinery/computer/robotics/proc/can_hack_any(mob/user)
if(!istype(user))
return FALSE
if(isobserver(user))
var/mob/observer/dead/D = user
if(D.can_admin_interact())
return TRUE
if(!isAI(user))
return FALSE
return (user.mind.special_role && user.mind.original == user)
if(!target || !istype(target))
return
var/istraitor = target.mind.special_role
if (istraitor)
failmsg = "failed (target is traitor) "
target.lockcharge = !target.lockcharge
if (target.lockcharge)
to_chat(target, "Someone tried to lock you down!")
else
to_chat(target, "Someone tried to lift your lockdown!")
else if (target.emagged)
failmsg = "failed (target is hacked) "
target.lockcharge = !target.lockcharge
if (target.lockcharge)
to_chat(target, "Someone tried to lock you down!")
else
to_chat(target, "Someone tried to lift your lockdown!")
else
target.canmove = !target.canmove
target.lockcharge = !target.canmove //when canmove is 1, lockcharge should be 0
target.lockdown = !target.canmove
if (target.lockcharge)
to_chat(target, "You have been locked down!")
else
to_chat(target, "Your lockdown has been lifted!")
message_admins("<span class='notice'>[key_name_admin(usr)] [failmsg][target.lockcharge ? "lockdown" : "release"] on [target.name]!</span>")
log_game("[key_name(usr)] attempted to [target.lockcharge ? "lockdown" : "release"] [target.name] on the robotics console!")
/**
* Check if the user is allowed to hack a specific borg
*
* Returns TRUE if a user can hack the specific cyborg
* Returns FALSE if a user cannot
* Arguments:
* * user - The [mob/user] to be checked
* * R - The [mob/living/silicon/robot] to be checked
*/
/obj/machinery/computer/robotics/proc/can_hack(mob/user, mob/living/silicon/robot/R)
if(!can_hack_any(user))
return FALSE
if(!istype(R))
return FALSE
if(R.emagged)
return FALSE
if(R.connected_ai != user)
return FALSE
return TRUE
// Remotely hacks the cyborg. Only antag AIs can do this and only to linked cyborgs.
else if (href_list["hack"])
var/mob/living/silicon/robot/target = get_cyborg_by_name(href_list["hack"])
if(!target || !istype(target))
return
// Antag synthetic checks
if(!istype(user, /mob/living/silicon) || !(user.mind.special_role && user.mind.original == user))
to_chat(user, "Access Denied")
return
if(target.emagged)
to_chat(user, "Robot is already hacked.")
return
var/choice = input("Really hack [target.name]? This cannot be undone.") in list("Yes", "No")
if(choice != "Yes")
return
if(!target || !istype(target))
return
message_admins("<span class='notice'>[key_name_admin(usr)] emagged [target.name] using the robotic console!</span>")
log_game("[key_name(usr)] emagged [target.name] using robotic console!")
target.emagged = 1
to_chat(target, "<span class='notice'>Failsafe protocols overriden. New tools available.</span>")
// Proc: get_cyborgs()
// Parameters: 1 (operator - mob which is operating the console.)
// Description: Returns NanoUI-friendly list of accessible cyborgs.
/obj/machinery/computer/robotics/proc/get_cyborgs(var/mob/operator)
var/list/robots = list()
/obj/machinery/computer/robotics/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "RoboticsControlConsole", name)
ui.open()
/obj/machinery/computer/robotics/tgui_data(mob/user)
var/list/data = list()
data["auth"] = is_authenticated(user)
data["can_hack"] = can_hack_any(user)
data["cyborgs"] = list()
data["safety"] = safety
for(var/mob/living/silicon/robot/R in mob_list)
// Ignore drones
if(istype(R, /mob/living/silicon/robot/drone))
continue
// Ignore antagonistic cyborgs
if(R.scrambledcodes)
if(!console_shows(R))
continue
var/area/A = get_area(R)
var/turf/T = get_turf(R)
var/list/cyborg_data = list(
name = R.name,
ref = REF(R),
locked_down = R.lockcharge,
locstring = "[A.name] ([T.x], [T.y])",
status = R.stat,
health = round(R.health * 100 / R.maxHealth, 0.1),
charge = R.cell ? round(R.cell.percent()) : null,
cell_capacity = R.cell ? R.cell.maxcharge : null,
module = R.module ? R.module.name : "No Module Detected",
synchronization = R.connected_ai,
is_hacked = R.connected_ai && R.emagged,
hackable = can_hack(user, R),
)
data["cyborgs"] += list(cyborg_data)
data["show_detonate_all"] = (data["auth"] && length(data["cyborgs"]) > 0 && ishuman(user))
return data
var/list/robot = list()
robot["name"] = R.name
if(R.stat)
robot["status"] = "Not Responding"
else if (R.lockcharge)
robot["status"] = "Lockdown"
else
robot["status"] = "Operational"
if(R.cell)
robot["cell"] = 1
robot["cell_capacity"] = R.cell.maxcharge
robot["cell_current"] = R.cell.charge
robot["cell_percentage"] = round(R.cell.percent())
else
robot["cell"] = 0
robot["module"] = R.module ? R.module.name : "None"
robot["master_ai"] = R.connected_ai ? R.connected_ai.name : "None"
robot["hackable"] = 0
//Antag synths should be able to hack themselves and see their hacked status.
if(operator && isrobot(operator) && (operator.mind.special_role && operator.mind.original == operator) && (operator == R))
robot["hacked"] = R.emagged ? 1 : 0
robot["hackable"] = R.emagged? 0 : 1
// Antag AIs know whether linked cyborgs are hacked or not.
if(operator && isAI(operator) && (R.connected_ai == operator) && (operator.mind.special_role && operator.mind.original == operator))
robot["hacked"] = R.emagged ? 1 : 0
robot["hackable"] = R.emagged? 0 : 1
robots.Add(list(robot))
return robots
// Proc: get_cyborg_by_name()
// Parameters: 1 (name - Cyborg we are trying to find)
// Description: Helper proc for finding cyborg by name
/obj/machinery/computer/robotics/proc/get_cyborg_by_name(var/name)
if (!name)
/obj/machinery/computer/robotics/tgui_act(action, params)
if(..())
return
for(var/mob/living/silicon/robot/R in mob_list)
if(R.name == name)
return R
. = FALSE
if(!is_authenticated(usr))
to_chat(usr, "<span class='warning'>Access denied.</span>")
return
switch(action)
if("arm") // Arms the emergency self-destruct system
if(issilicon(usr))
to_chat(usr, "<span class='danger'>Access Denied (silicon detected)</span>")
return
safety = !safety
to_chat(usr, "<span class='notice'>You [safety ? "disarm" : "arm"] the emergency self destruct.</span>")
. = TRUE
if("nuke") // Destroys all accessible cyborgs if safety is disabled
if(issilicon(usr))
to_chat(usr, "<span class='danger'>Access Denied (silicon detected)</span>")
return
if(safety)
to_chat(usr, "<span class='danger'>Self-destruct aborted - safety active</span>")
return
message_admins("<span class='notice'>[key_name_admin(usr)] detonated all cyborgs!</span>")
log_game("\<span class='notice'>[key_name(usr)] detonated all cyborgs!</span>")
for(var/mob/living/silicon/robot/R in mob_list)
if(istype(R, /mob/living/silicon/robot/drone))
continue
// Ignore antagonistic cyborgs
if(R.scrambledcodes)
continue
to_chat(R, "<span class='danger'>Self-destruct command received.</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
R.self_destruct()
. = TRUE
if("killbot") // destroys one specific cyborg
var/mob/living/silicon/robot/R = locate(params["ref"])
if(!can_control(usr, R, TRUE))
return
if(R.mind && R.mind.special_role && R.emagged)
to_chat(R, "<span class='userdanger'>Extreme danger! Termination codes detected. Scrambling security codes and automatic AI unlink triggered.</span>")
R.ResetSecurityCodes()
. = TRUE
return
var/turf/T = get_turf(R)
message_admins("<span class='notice'>[key_name_admin(usr)] detonated [key_name_admin(R)] ([ADMIN_COORDJMP(T)])!</span>")
log_game("\<span class='notice'>[key_name(usr)] detonated [key_name(R)]!</span>")
to_chat(R, "<span class='danger'>Self-destruct command received.</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "<br><br><span class='alert'>ALERT - Cyborg detonation detected: [R.name]</span><br>")
R.self_destruct()
. = TRUE
if("stopbot") // lock or unlock the borg
if(isrobot(usr))
to_chat(usr, "<span class='danger'>Access Denied.</span>")
return
var/mob/living/silicon/robot/R = locate(params["ref"])
if(!can_control(usr, R, TRUE))
return
message_admins("<span class='notice'>[ADMIN_LOOKUPFLW(usr)] [!R.lockcharge ? "locked down" : "released"] [ADMIN_LOOKUPFLW(R)]!</span>")
log_game("[key_name(usr)] [!R.lockcharge ? "locked down" : "released"] [key_name(R)]!")
R.SetLockdown(!R.lockcharge)
to_chat(R, "[!R.lockcharge ? "<span class='notice'>Your lockdown has been lifted!" : "<span class='alert'>You have been locked down!"]</span>")
if(R.connected_ai)
to_chat(R.connected_ai, "[!R.lockcharge ? "<span class='notice'>NOTICE - Cyborg lockdown lifted</span>" : "<span class='alert'>ALERT - Cyborg lockdown detected</span>"]: <a href='?src=[REF(R.connected_ai)];track=[html_encode(R.name)]'>[R.name]</a></span><br>")
. = TRUE
if("hackbot") // AIs hacking/emagging a borg
var/mob/living/silicon/robot/R = locate(params["ref"])
if(!can_hack(usr, R))
return
var/choice = input("Really hack [R.name]? This cannot be undone.") in list("Yes", "No")
if(choice != "Yes")
return
log_game("[key_name(usr)] emagged [key_name(R)] using robotic console!")
message_admins("<span class='notice'>[key_name_admin(usr)] emagged [key_name_admin(R)] using robotic console!</span>")
R.emagged = TRUE
to_chat(R, "<span class='notice'>Failsafe protocols overriden. New tools available.</span>")
. = TRUE
+76 -69
View File
@@ -234,116 +234,123 @@
if(..())
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/partslathe/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
user.set_machine(src)
/obj/machinery/partslathe/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
)
var/data[0]
/obj/machinery/partslathe/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PartsLathe", name)
ui.open()
/obj/machinery/partslathe/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["panelOpen"] = panel_open
var/materials_ui[0]
var/list/materials_ui = list()
for(var/M in materials)
materials_ui[++materials_ui.len] = list(
"name" = M,
"display" = material_display_name(M),
"qty" = materials[M],
"max" = storage_capacity[M],
"percent" = (materials[M] / storage_capacity[M] * 100))
materials_ui.Add(list(list(
"name" = M,
"amount" = materials[M],
"sheets" = round(materials[M] / SHEET_MATERIAL_AMOUNT),
"removable" = materials[M] >= SHEET_MATERIAL_AMOUNT,
)))
data["materials"] = materials_ui
data["copyBoard"] = null
data["copyBoardReqComponents"] = null
if(istype(copy_board))
data["copyBoard"] = copy_board.name
var/req_components_ui[0]
var/list/req_components_ui = list()
for(var/CP in (copy_board.req_components || list()))
var/obj/comp_path = CP
var/comp_amt = copy_board.req_components[comp_path]
if(comp_amt && (comp_path in partslathe_recipies))
req_components_ui[++req_components_ui.len] = list("name" = initial(comp_path.name), "qty" = comp_amt)
req_components_ui.Add(list(list("name" = initial(comp_path.name), "qty" = comp_amt)))
data["copyBoardReqComponents"] = req_components_ui
data["queue"] = list()
for(var/datum/category_item/partslathe/Q in queue)
data["queue"] += Q.name
data["building"] = null
data["buildPercent"] = null
if(busy && queue.len > 0)
var/datum/category_item/partslathe/current = queue[1]
data["building"] = current.name
data["buildProgress"] = progress
data["buildTime"] = current.time
data["buildPercent"] = (progress / current.time * 100)
data["error"] = null
if(queue.len > 0 && !canBuild(queue[1]))
data["error"] = getLackingMaterials(queue[1])
var/recipies_ui[0]
var/list/recipies_ui = list()
for(var/T in partslathe_recipies)
var/datum/category_item/partslathe/R = partslathe_recipies[T]
recipies_ui[++recipies_ui.len] = list("name" = R.name, "type" = "[T]")
recipies_ui.Add(list(list("name" = R.name, "type" = "[T]")))
data["recipies"] = recipies_ui
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "partslathe.tmpl", "Parts Lathe UI", 500, 450)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(5)
return data
/obj/machinery/partslathe/Topic(href, href_list)
/obj/machinery/partslathe/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
usr.set_machine(src)
return TRUE
add_fingerprint(usr)
// Queue management can be done even while busy
if(href_list["queue"])
var/type_to_build = text2path(href_list["queue"])
var/datum/category_item/partslathe/to_build = partslathe_recipies[type_to_build]
if(to_build)
addToQueue(to_build)
updateUsrDialog()
return
if(href_list["queueBoard"])
if(!istype(copy_board) || !copy_board.req_components)
return
for(var/comp_path in copy_board.req_components)
var/comp_amt = copy_board.req_components[comp_path]
if(!comp_amt)
continue
var/datum/category_item/partslathe/to_build = partslathe_recipies[comp_path]
if(!to_build)
continue // We don't support building whatever this is
for(var/i in 1 to comp_amt)
switch(action)
// Queue management can be done even while busy
if("queue")
var/type_to_build = text2path(params["queue"])
var/datum/category_item/partslathe/to_build = partslathe_recipies[type_to_build]
if(to_build)
addToQueue(to_build)
return
return TRUE
if(href_list["cancel"])
var/index = text2num(href_list["cancel"])
if(index < 1 || index > queue.len)
return
if(busy && index == 1)
return
removeFromQueue(index)
return
if("queueBoard")
if(!istype(copy_board) || !copy_board.req_components)
return
for(var/comp_path in copy_board.req_components)
var/comp_amt = copy_board.req_components[comp_path]
if(!comp_amt)
continue
var/datum/category_item/partslathe/to_build = partslathe_recipies[comp_path]
if(!to_build)
continue // We don't support building whatever this is
for(var/i in 1 to comp_amt)
addToQueue(to_build)
return TRUE
if("cancel")
var/index = text2num(params["cancel"])
if(index < 1 || index > queue.len)
return
if(busy && index == 1)
return
removeFromQueue(index)
return TRUE
if(busy)
to_chat(usr, "<span class='notice'>\The [src]is busy. Please wait for completion of previous operation.</span>")
to_chat(usr, "<span class='notice'>[src] is busy. Please wait for completion of previous operation.</span>")
return
if(href_list["ejectBoard"])
if(copy_board)
visible_message("<span class='notice'>\The [copy_board] is ejected from \the [src]'s circuit reader</span>.")
copy_board.forceMove(src.loc)
copy_board = null
updateUsrDialog()
return
switch(action)
if("ejectBoard")
if(copy_board)
visible_message("<span class='notice'>[copy_board] is ejected from [src]'s circuit reader</span>.")
copy_board.forceMove(src.loc)
copy_board = null
return TRUE
if(href_list["ejectMaterial"])
var/matName = href_list["ejectMaterial"]
if(!(matName in materials))
if("remove_mat")
// Remove a material from the fab
var/mat_id = params["id"]
var/amount = text2num(params["amount"])
eject_materials(mat_id, amount)
return
eject_materials(matName, 0)
updateUsrDialog()
return
/** Build list of recipies to include all tech level 1 stock parts. */
/obj/machinery/partslathe/proc/update_recipe_list()
+2 -2
View File
@@ -16,10 +16,10 @@ obj/machinery/seed_extractor/attackby(var/obj/item/O as obj, var/mob/user as mob
var/datum/seed/new_seed_type
if(istype(O, /obj/item/weapon/grown))
var/obj/item/weapon/grown/F = O
new_seed_type = plant_controller.seeds[F.plantname]
new_seed_type = SSplants.seeds[F.plantname]
else
var/obj/item/weapon/reagent_containers/food/snacks/grown/F = O
new_seed_type = plant_controller.seeds[F.plantname]
new_seed_type = SSplants.seeds[F.plantname]
if(new_seed_type)
to_chat(user, "<span class='notice'>You extract some seeds from [O].</span>")
@@ -21,6 +21,8 @@
var/energy_drain = 0
var/obj/mecha/chassis = null
var/range = MELEE //bitflags
/// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this.
var/mech_flags = NONE
var/salvageable = 1
var/required_type = /obj/mecha //may be either a type or a list of allowed types
var/equip_type = null //mechaequip2
@@ -1,6 +1,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/extinguisher
name = "extinguisher"
desc = "Exosuit-mounted extinguisher (Can be attached to: Engineering exosuits)"
mech_flags = EXOSUIT_MODULE_WORKING | EXOSUIT_MODULE_COMBAT
icon_state = "mecha_exting"
equip_cooldown = 5
energy_drain = 0
+1
View File
@@ -1,6 +1,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/rcd
name = "mounted RCD"
desc = "An exosuit-mounted Rapid Construction Device. (Can be attached to: Any exosuit)"
mech_flags = EXOSUIT_MODULE_WORKING|EXOSUIT_MODULE_COMBAT|EXOSUIT_MODULE_MEDICAL
icon_state = "mecha_rcd"
origin_tech = list(TECH_MATERIAL = 4, TECH_BLUESPACE = 3, TECH_MAGNET = 4, TECH_POWER = 4)
equip_cooldown = 10
@@ -7,6 +7,7 @@
energy_drain = 20
range = MELEE
equip_cooldown = 30
mech_flags = EXOSUIT_MODULE_MEDICAL
var/mob/living/carbon/human/occupant = null
var/datum/global_iterator/pr_mech_sleeper
var/inject_amount = 5
@@ -1,6 +1,7 @@
/obj/item/mecha_parts/mecha_equipment/tool/syringe_gun
name = "syringe gun"
desc = "Exosuit-mounted chem synthesizer with syringe gun. Reagents inside are held in stasis, so no reactions will occur. (Can be attached to: Medical Exosuits)"
mech_flags = EXOSUIT_MODULE_MEDICAL
icon = 'icons/obj/gun.dmi'
icon_state = "syringegun"
var/list/syringes
+553 -182
View File
@@ -11,47 +11,80 @@
req_access = list(access_robotics)
circuit = /obj/item/weapon/circuitboard/mechfab
var/speed = 1
var/mat_efficiency = 1
var/list/materials = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0, "plastic" = 0, MAT_GRAPHITE = 0, MAT_PLASTEEL = 0, "gold" = 0, "silver" = 0, MAT_LEAD = 0, "osmium" = 0, "diamond" = 0, MAT_DURASTEEL = 0, "phoron" = 0, "uranium" = 0, MAT_VERDANTIUM = 0, MAT_MORPHIUM = 0, MAT_METALHYDROGEN = 0, MAT_SUPERMATTER = 0)
var/list/hidden_materials = list(MAT_PLASTEEL, MAT_DURASTEEL, MAT_GRAPHITE, MAT_VERDANTIUM, MAT_MORPHIUM, MAT_METALHYDROGEN, MAT_SUPERMATTER)
/// Current items in the build queue.
var/list/queue = list()
/// Whether or not the machine is building the entire queue automagically.
var/process_queue = FALSE
/// The current design datum that the machine is building.
var/datum/design/being_built
/// World time when the build will finish.
var/build_finish = 0
/// World time when the build started.
var/build_start = 0
/// Reference to all materials used in the creation of the item being_built.
var/list/build_materials
/// Part currently stored in the Exofab.
var/obj/item/stored_part
/// Coefficient for the speed of item building. Based on the installed parts.
var/time_coeff = 1
/// Coefficient for the efficiency of material usage in item building. Based on the installed parts.
var/component_coeff = 1
var/loading_icon_state = "mechfab-idle"
var/list/materials = list(
DEFAULT_WALL_MATERIAL = 0,
"glass" = 0,
"plastic" = 0,
MAT_GRAPHITE = 0,
MAT_PLASTEEL = 0,
"gold" = 0,
"silver" = 0,
MAT_LEAD = 0,
"osmium" = 0,
"diamond" = 0,
MAT_DURASTEEL = 0,
"phoron" = 0,
"uranium" = 0,
MAT_VERDANTIUM = 0,
MAT_MORPHIUM = 0,
MAT_METALHYDROGEN = 0,
MAT_SUPERMATTER = 0)
var/res_max_amount = 200000
var/datum/research/files
var/list/datum/design/queue = list()
var/progress = 0
var/busy = 0
var/list/categories = list()
var/category = null
var/sync_message = ""
var/valid_buildtype = MECHFAB
/// A list of categories that valid MECHFAB design datums will broadly categorise themselves under.
var/list/part_sets = list(
"Cyborg",
"Ripley",
"Odysseus",
"Gygax",
"Durand",
"Janus",
"Vehicle",
"Rigsuit",
"Phazon",
"Gopher", // VOREStation Add
"Polecat", // VOREStation Add
"Weasel", // VOREStation Add
"Exosuit Equipment",
"Exosuit Internals",
"Exosuit Ammunition",
"Cyborg Upgrade Modules",
"Cybernetics",
"Implants",
"Control Interfaces",
"Other",
"Misc",
)
/obj/machinery/mecha_part_fabricator/Initialize()
. = ..()
default_apply_parts()
files = new /datum/research(src) //Setup the research data holder.
update_categories()
/obj/machinery/mecha_part_fabricator/process()
..()
if(stat)
return
if(busy)
update_use_power(USE_POWER_ACTIVE)
progress += speed
check_build()
else
update_use_power(USE_POWER_IDLE)
update_icon()
/obj/machinery/mecha_part_fabricator/update_icon()
overlays.Cut()
if(panel_open)
icon_state = "mechfab-o"
else
icon_state = "mechfab-idle"
if(busy)
overlays += "mechfab-active"
/obj/machinery/mecha_part_fabricator/dismantle()
for(var/f in materials)
@@ -65,67 +98,507 @@
var/T = 0
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
T += M.rating
mat_efficiency = max(1 - (T - 1) / 4, 0.2) // 1 -> 0.2
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; speed is affected by both
component_coeff = max(1 - (T - 1) / 4, 0.2) // 1 -> 0.2
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; time_coeff is affected by both
T += M.rating
speed = T / 2 // 1 -> 3
time_coeff = T / 2 // 1 -> 3
update_tgui_static_data(usr)
/**
* Generates an info list for a given part.
*
* Returns a list of part information.
* * D - Design datum to get information on.
* * categories - Boolean, whether or not to parse snowflake categories into the part information list.
*/
/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D, var/categories = FALSE)
var/cost = list()
for(var/c in D.materials)
cost[c] = get_resource_cost_w_coeff(D, D.materials[c])
var/obj/built_item = D.build_path
var/list/category_override = null
var/list/sub_category = null
if(categories)
// Handle some special cases to build up sub-categories for the fab interface.
// Start with checking if this design builds a cyborg module.
if(built_item in typesof(/obj/item/borg/upgrade))
var/obj/item/borg/upgrade/U = built_item
var/module_types = initial(U.module_flags)
sub_category = list()
if(module_types)
if(module_types & BORG_MODULE_SECURITY)
sub_category += "Security"
if(module_types & BORG_MODULE_MINER)
sub_category += "Mining"
if(module_types & BORG_MODULE_JANITOR)
sub_category += "Janitor"
if(module_types & BORG_MODULE_MEDICAL)
sub_category += "Medical"
if(module_types & BORG_MODULE_ENGINEERING)
sub_category += "Engineering"
else
sub_category += "All Cyborgs"
// Else check if this design builds a piece of exosuit equipment.
else if(built_item in typesof(/obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/E = built_item
var/mech_types = initial(E.mech_flags)
sub_category = "Equipment"
if(mech_types)
category_override = list()
if(mech_types & EXOSUIT_MODULE_RIPLEY)
category_override += "Ripley"
if(mech_types & EXOSUIT_MODULE_ODYSSEUS)
category_override += "Odysseus"
if(mech_types & EXOSUIT_MODULE_GYGAX)
category_override += "Gygax"
if(mech_types & EXOSUIT_MODULE_DURAND)
category_override += "Durand"
if(mech_types & EXOSUIT_MODULE_PHAZON)
category_override += "Phazon"
var/list/part = list(
"name" = D.name,
"desc" = initial(built_item.desc),
"printTime" = get_construction_time_w_coeff(initial(D.time))/10,
"cost" = cost,
"id" = D.id,
"subCategory" = sub_category,
"categoryOverride" = category_override,
"searchMeta" = D.search_metadata
)
return part
/**
* Generates a list of resources / materials available to this Exosuit Fab
*
* Returns null if there is no material container available.
* List format is list(material_name = list(amount = ..., ref = ..., etc.))
*/
/obj/machinery/mecha_part_fabricator/proc/output_available_resources()
var/list/material_data = list()
for(var/mat_id in materials)
var/amount = materials[mat_id]
var/list/material_info = list(
"name" = mat_id,
"amount" = amount,
"sheets" = round(amount / SHEET_MATERIAL_AMOUNT),
"removable" = amount >= SHEET_MATERIAL_AMOUNT
)
material_data += list(material_info)
return material_data
/**
* Intended to be called when an item starts printing.
*
* Adds the overlay to show the fab working and sets active power usage settings.
*/
/obj/machinery/mecha_part_fabricator/proc/on_start_printing()
add_overlay("fab-active")
use_power = USE_POWER_ACTIVE
/**
* Intended to be called when the exofab has stopped working and is no longer printing items.
*
* Removes the overlay to show the fab working and sets idle power usage settings. Additionally resets the description and turns off queue processing.
*/
/obj/machinery/mecha_part_fabricator/proc/on_finish_printing()
cut_overlay("fab-active")
use_power = USE_POWER_IDLE
desc = initial(desc)
process_queue = FALSE
/**
* Calculates resource/material costs for printing an item based on the machine's resource coefficient.
*
* Returns a list of k,v resources with their amounts.
* * D - Design datum to calculate the modified resource cost of.
*/
/obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D)
var/list/resources = list()
for(var/mat_id in D.materials)
resources[mat_id] = get_resource_cost_w_coeff(D, D.materials[mat_id])
return resources
/**
* Checks if the Exofab has enough resources to print a given item.
*
* Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources.
* Returns TRUE if there are sufficient resources to print the item.
* * D - Design datum to calculate the modified resource cost of.
*/
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
if(length(D.chemicals)) // No reagents storage - no reagent designs.
return FALSE
. = TRUE
var/list/coeff_required = get_resources_w_coeff(D)
for(var/mat_id in coeff_required)
if(materials[mat_id] < coeff_required[mat_id])
return FALSE
/**
* Attempts to build the next item in the build queue.
*
* Returns FALSE if either there are no more parts to build or the next part is not buildable.
* Returns TRUE if the next part has started building.
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
*/
/obj/machinery/mecha_part_fabricator/proc/build_next_in_queue(verbose = TRUE)
if(!length(queue))
return FALSE
var/datum/design/D = queue[1]
if(build_part(D, verbose))
remove_from_queue(1)
return TRUE
return FALSE
/**
* Starts the build process for a given design datum.
*
* Returns FALSE if the procedure fails. Returns TRUE when being_built is set.
* Uses materials.
* * D - Design datum to attempt to print.
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
*/
/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D, verbose = TRUE)
if(!D)
return FALSE
if(!check_resources(D))
if(verbose)
atom_say("Not enough resources. Processing stopped.")
return FALSE
build_materials = get_resources_w_coeff(D)
for(var/mat_id in build_materials)
materials[mat_id] -= build_materials[mat_id]
being_built = D
build_finish = world.time + get_construction_time_w_coeff(initial(D.time))
build_start = world.time
desc = "It's building \a [D.name]."
return TRUE
/obj/machinery/mecha_part_fabricator/process()
..()
// If there's a stored part to dispense due to an obstruction, try to dispense it.
if(stored_part)
var/turf/exit = get_step(src,(dir))
if(exit.density)
return TRUE
atom_say("Obstruction cleared. \The [stored_part] is complete.")
stored_part.forceMove(exit)
stored_part = null
// If there's nothing being built, try to build something
if(!being_built)
// If we're not processing the queue anymore or there's nothing to build, end processing.
if(!process_queue || !build_next_in_queue())
on_finish_printing()
return PROCESS_KILL
on_start_printing()
// If there's an item being built, check if it is complete.
if(being_built && (build_finish < world.time))
// Then attempt to dispense it and if appropriate build the next item.
dispense_built_part(being_built)
if(process_queue)
build_next_in_queue(FALSE)
return TRUE
/**
* Dispenses a part to the tile infront of the Exosuit Fab.
*
* Returns FALSE is the machine cannot dispense the part on the appropriate turf.
* Return TRUE if the part was successfully dispensed.
* * D - Design datum to attempt to dispense.
*/
/obj/machinery/mecha_part_fabricator/proc/dispense_built_part(datum/design/D)
var/obj/item/I = D.Fabricate(src, src)
// I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this.
// I.set_custom_materials(build_materials)
being_built = null
var/turf/exit = get_step(src,(dir))
if(exit.density)
atom_say("Error! Part outlet is obstructed.")
desc = "It's trying to dispense \a [D.name], but the part outlet is obstructed."
stored_part = I
return FALSE
atom_say("\The [I] is complete.")
I.forceMove(exit)
return I
/**
* Adds a list of datum designs to the build queue.
*
* Will only add designs that are in this machine's stored techweb.
* Does final checks for datum IDs and makes sure this machine can build the designs.
* * part_list - List of datum design ids for designs to add to the queue.
*/
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(list/part_list)
for(var/datum/design/D in files.known_designs)
if((D.build_type & valid_buildtype) && (D.id in part_list))
add_to_queue(D)
/**
* Adds a datum design to the build queue.
*
* Returns TRUE if successful and FALSE if the design was not added to the queue.
* * D - Datum design to add to the queue.
*/
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(datum/design/D)
if(!istype(queue))
queue = list()
if(D)
queue[++queue.len] = D
return TRUE
return FALSE
/**
* Removes datum design from the build queue based on index.
*
* Returns TRUE if successful and FALSE if a design was not removed from the queue.
* * index - Index in the build queue of the element to remove.
*/
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index)
if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>length(queue)))
return FALSE
queue.Cut(index,++index)
return TRUE
/**
* Generates a list of parts formatted for tgui based on the current build queue.
*
* Returns a formatted list of lists containing formatted part information for every part in the build queue.
*/
/obj/machinery/mecha_part_fabricator/proc/list_queue()
if(!istype(queue) || !length(queue))
return null
var/list/queued_parts = list()
for(var/datum/design/D in queue)
var/list/part = output_part_info(D)
queued_parts += list(part)
return queued_parts
/obj/machinery/mecha_part_fabricator/proc/sync()
for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src)))
if(!RDC.sync)
continue
for(var/datum/tech/T in RDC.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in RDC.files.known_designs)
files.AddDesign2Known(D)
files.RefreshResearch()
update_tgui_static_data(usr)
atom_say("Successfully synchronized with R&D server.")
return
atom_say("Unable to connect to local R&D server.")
return
/**
* Calculates the coefficient-modified resource cost of a single material component of a design's recipe.
*
* Returns coefficient-modified resource cost for the given material component.
* * D - Design datum to pull the resource cost from.
* * resource - Material datum reference to the resource to calculate the cost of.
* * roundto - Rounding value for round() proc
*/
/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/amt, roundto = 1)
return round(amt * component_coeff, roundto)
/**
* Calculates the coefficient-modified build time of a design.
*
* Returns coefficient-modified build time of a given design.
* * D - Design datum to calculate the modified build time of.
* * roundto - Rounding value for round() proc
*/
/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(construction_time, roundto = 1) //aran
return round(construction_time * time_coeff, roundto)
/obj/machinery/mecha_part_fabricator/ui_assets(mob/user)
return list(
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
)
/obj/machinery/mecha_part_fabricator/attack_hand(var/mob/user)
if(..())
return
if(!allowed(user))
return
ui_interact(user)
tgui_interact(user)
/obj/machinery/mecha_part_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/design/current = queue.len ? queue[1] : null
if(current)
data["current"] = current.name
data["queue"] = get_queue_names()
data["buildable"] = get_build_options()
data["category"] = category
data["categories"] = categories
data["materials"] = get_materials()
data["maxres"] = res_max_amount
data["sync"] = sync_message
if(current)
data["builtperc"] = round((progress / current.time) * 100)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
/obj/machinery/mecha_part_fabricator/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, ui_key, "mechfab.tmpl", "Exosuit Fabricator UI", 800, 600)
ui.set_initial_data(data)
ui = new(user, src, "ExosuitFabricator", name)
ui.open()
ui.set_auto_update(1)
/obj/machinery/mecha_part_fabricator/Topic(href, href_list)
if(..())
return
/obj/machinery/mecha_part_fabricator/tgui_static_data(mob/user)
var/list/data = list()
if(href_list["build"])
add_to_queue(text2num(href_list["build"]))
var/list/final_sets = list()
var/list/buildable_parts = list()
if(href_list["remove"])
remove_from_queue(text2num(href_list["remove"]))
for(var/part_set in part_sets)
final_sets += part_set
if(href_list["category"])
if(href_list["category"] in categories)
category = href_list["category"]
for(var/datum/design/D in files.known_designs)
if((D.build_type & valid_buildtype) && D.id != "id") // bugfix for weird null entries
// This is for us.
var/list/part = output_part_info(D, TRUE)
if(href_list["eject"])
eject_materials(href_list["eject"], text2num(href_list["amount"]))
if(part["categoryOverride"])
for(var/cat in part["categoryOverride"])
buildable_parts[cat] += list(part)
if(!(cat in part_sets))
final_sets += cat
continue
if(href_list["sync"])
sync()
for(var/cat in part_sets)
// Find all matching categories.
if(!(cat in D.category))
continue
buildable_parts[cat] += list(part)
data["partSets"] = final_sets
data["buildableParts"] = buildable_parts
return data
/obj/machinery/mecha_part_fabricator/tgui_data(mob/user)
var/list/data = list()
data["materials"] = output_available_resources()
if(being_built)
var/list/part = list(
"name" = being_built.name,
"duration" = build_finish - world.time,
"printTime" = get_construction_time_w_coeff(initial(being_built.time))
)
data["buildingPart"] = part
else
sync_message = ""
data["buildingPart"] = null
return 1
data["queue"] = list_queue()
if(stored_part)
data["storedPart"] = stored_part.name
else
data["storedPart"] = null
data["isProcessingQueue"] = process_queue
return data
/obj/machinery/mecha_part_fabricator/tgui_act(action, var/list/params)
if(..())
return TRUE
. = TRUE
add_fingerprint(usr)
usr.set_machine(src)
switch(action)
if("sync_rnd")
// Sync with R&D Servers
sync()
return
if("add_queue_set")
// Add all parts of a set to queue
var/part_list = params["part_list"]
add_part_set_to_queue(part_list)
return
if("add_queue_part")
// Add a specific part to queue
var/T = params["id"]
for(var/datum/design/D in files.known_designs)
if((D.build_type & valid_buildtype) && (D.id == T))
add_to_queue(D)
break
return
if("del_queue_part")
// Delete a specific from from the queue
var/index = text2num(params["index"])
remove_from_queue(index)
return
if("clear_queue")
// Delete everything from queue
queue.Cut()
return
if("build_queue")
// Build everything in queue
if(process_queue)
return
process_queue = TRUE
if(!being_built)
START_PROCESSING(SSobj, src)
return
if("stop_queue")
// Pause queue building. Also known as stop.
process_queue = FALSE
return
if("build_part")
// Build a single part
if(being_built || process_queue)
return
var/id = params["id"]
var/datum/design/D = null
for(var/datum/design/D_new in files.known_designs)
if((D_new.build_type == valid_buildtype) && (D_new.id == id))
D = D_new
break
if(!D)
return
if(build_part(D))
on_start_printing()
START_PROCESSING(SSobj, src)
return
if("move_queue_part")
// Moves a part up or down in the queue.
var/index = text2num(params["index"])
var/new_index = index + text2num(params["newindex"])
if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index))
if(ISINRANGE(new_index,1,length(queue)))
queue.Swap(index,new_index)
return
if("remove_mat")
// Remove a material from the fab
var/mat_id = params["id"]
var/amount = text2num(params["amount"])
eject_materials(mat_id, amount)
return
return FALSE
/obj/machinery/mecha_part_fabricator/attackby(var/obj/item/I, var/mob/user)
if(busy)
if(being_built)
to_chat(user, "<span class='notice'>\The [src] is busy. Please wait for completion of previous operation.</span>")
return 1
if(default_deconstruction_screwdriver(user, I))
@@ -146,15 +619,17 @@
if(materials[S.material.name] + amnt <= res_max_amount)
if(S && S.get_amount() >= 1)
var/count = 0
overlays += "mechfab-load-metal"
spawn(10)
overlays -= "mechfab-load-metal"
flick("[loading_icon_state]", src)
// yess hacky but whatever
if(loading_icon_state == "mechfab-idle")
overlays += "mechfab-load-metal"
spawn(10)
overlays -= "mechfab-load-metal"
while(materials[S.material.name] + amnt <= res_max_amount && S.get_amount() >= 1)
materials[S.material.name] += amnt
S.use(1)
count++
to_chat(user, "You insert [count] [sname] into the fabricator.")
update_busy()
else
to_chat(user, "The fabricator cannot hold more [sname].")
@@ -181,96 +656,6 @@
if(1)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"No records in User DB\"")
/obj/machinery/mecha_part_fabricator/proc/update_busy()
if(queue.len)
if(can_build(queue[1]))
busy = 1
else
busy = 0
else
busy = 0
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(var/index)
var/datum/design/D = files.known_designs[index]
queue += D
update_busy()
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(var/index)
if(index == 1)
progress = 0
queue.Cut(index, index + 1)
update_busy()
/obj/machinery/mecha_part_fabricator/proc/can_build(var/datum/design/D)
for(var/M in D.materials)
if(materials[M] < (D.materials[M] * mat_efficiency))
return 0
return 1
/obj/machinery/mecha_part_fabricator/proc/check_build()
if(!queue.len)
progress = 0
return
var/datum/design/D = queue[1]
if(!can_build(D))
progress = 0
return
if(D.time > progress)
return
for(var/M in D.materials)
materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency)
if(D.build_path)
var/obj/new_item = D.Fabricate(get_step(get_turf(src), src.dir), src)
visible_message("\The [src] pings, indicating that \the [D] is complete.", "You hear a ping.")
if(mat_efficiency != 1)
if(new_item.matter && new_item.matter.len > 0)
for(var/i in new_item.matter)
new_item.matter[i] = new_item.matter[i] * mat_efficiency
remove_from_queue(1)
/obj/machinery/mecha_part_fabricator/proc/get_queue_names()
. = list()
for(var/i = 2 to queue.len)
var/datum/design/D = queue[i]
. += D.name
/obj/machinery/mecha_part_fabricator/proc/get_build_options()
. = list()
for(var/i = 1 to files.known_designs.len)
var/datum/design/D = files.known_designs[i]
if(!D.build_path || !(D.build_type & MECHFAB))
continue
. += list(list("name" = D.name, "id" = i, "category" = D.category, "resourses" = get_design_resourses(D), "time" = get_design_time(D)))
/obj/machinery/mecha_part_fabricator/proc/get_design_resourses(var/datum/design/D)
var/list/F = list()
for(var/T in D.materials)
F += "[capitalize(T)]: [D.materials[T] * mat_efficiency]"
return english_list(F, and_text = ", ")
/obj/machinery/mecha_part_fabricator/proc/get_design_time(var/datum/design/D)
return time2text(round(10 * D.time / speed), "mm:ss")
/obj/machinery/mecha_part_fabricator/proc/update_categories()
categories = list()
for(var/datum/design/D in files.known_designs)
if(!D.build_path || !(D.build_type & MECHFAB))
continue
categories |= D.category
if(!category || !(category in categories))
category = categories[1]
/obj/machinery/mecha_part_fabricator/proc/get_materials()
. = list()
for(var/T in materials)
var/hidden_mat = FALSE
for(var/HM in hidden_materials) // Direct list contents comparison was failing.
if(T == HM && materials[T] == 0)
hidden_mat = TRUE
continue
if(!hidden_mat)
. += list(list("mat" = capitalize(T), "amt" = materials[T]))
/obj/machinery/mecha_part_fabricator/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything
var/recursive = amount == -1 ? 1 : 0
var/matstring = lowertext(material)
@@ -287,17 +672,3 @@
materials[matstring] -= ejected * S.perunit
if(recursive && materials[matstring] >= S.perunit)
eject_materials(matstring, -1)
update_busy()
/obj/machinery/mecha_part_fabricator/proc/sync()
sync_message = "Error: no console found."
for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src)))
if(!RDC.sync)
continue
for(var/datum/tech/T in RDC.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in RDC.files.known_designs)
files.AddDesign2Known(D)
files.RefreshResearch()
sync_message = "Sync complete."
update_categories()
+93 -290
View File
@@ -1,4 +1,4 @@
/obj/machinery/pros_fabricator
/obj/machinery/mecha_part_fabricator/pros
icon = 'icons/obj/robotics.dmi'
icon_state = "prosfab"
name = "Prosthetics Fabricator"
@@ -11,158 +11,126 @@
req_access = list(access_robotics)
circuit = /obj/item/weapon/circuitboard/prosthetics
var/speed = 1
var/mat_efficiency = 1
var/list/materials = list(DEFAULT_WALL_MATERIAL = 0, "glass" = 0, "plastic" = 0, MAT_GRAPHITE = 0, MAT_PLASTEEL = 0, "gold" = 0, "silver" = 0, MAT_LEAD = 0, "osmium" = 0, "diamond" = 0, MAT_DURASTEEL = 0, "phoron" = 0, "uranium" = 0, MAT_VERDANTIUM = 0, MAT_MORPHIUM = 0)
var/list/hidden_materials = list(MAT_DURASTEEL, MAT_GRAPHITE, MAT_VERDANTIUM, MAT_MORPHIUM)
var/res_max_amount = 200000
var/datum/research/files
var/list/datum/design/queue = list()
var/progress = 0
var/busy = 0
var/list/categories = list()
var/category = null
// Prosfab specific stuff
var/manufacturer = null
var/species_types = list("Human")
var/species = "Human"
var/sync_message = ""
/obj/machinery/pros_fabricator/Initialize()
. = ..()
default_apply_parts()
loading_icon_state = "prosfab_loading"
files = new /datum/research(src) //Setup the research data holder.
materials = list(
DEFAULT_WALL_MATERIAL = 0,
"glass" = 0,
"plastic" = 0,
MAT_GRAPHITE = 0,
MAT_PLASTEEL = 0,
"gold" = 0,
"silver" = 0,
MAT_LEAD = 0,
"osmium" = 0,
"diamond" = 0,
MAT_DURASTEEL = 0,
"phoron" = 0,
"uranium" = 0,
MAT_VERDANTIUM = 0,
MAT_MORPHIUM = 0)
res_max_amount = 200000
/obj/machinery/pros_fabricator/Initialize()
valid_buildtype = PROSFAB
/// A list of categories that valid PROSFAB design datums will broadly categorise themselves under.
part_sets = list(
"Cyborg",
"Ripley",
"Odysseus",
"Gygax",
"Durand",
"Janus",
"Vehicle",
"Rigsuit",
"Phazon",
"Gopher", // VOREStation Add
"Polecat", // VOREStation Add
"Weasel", // VOREStation Add
"Exosuit Equipment",
"Exosuit Internals",
"Exosuit Ammunition",
"Cyborg Modules",
"Prosthetics",
"Prosthetics, Internal",
"Cyborg Parts",
"Cyborg Internals",
"Cybernetics",
"Implants",
"Control Interfaces",
"Other",
"Misc",
)
/obj/machinery/mecha_part_fabricator/pros/Initialize()
. = ..()
manufacturer = basic_robolimb.company
update_categories()
/obj/machinery/pros_fabricator/process()
..()
if(stat)
return
if(busy)
update_use_power(USE_POWER_ACTIVE)
progress += speed
check_build()
else
update_use_power(USE_POWER_IDLE)
update_icon()
/obj/machinery/mecha_part_fabricator/pros/dispense_built_part(datum/design/D)
var/obj/item/I = ..()
if(isobj(I) && I.matter && I.matter.len > 0)
for(var/i in I.matter)
I.matter[i] = I.matter[i] * component_coeff
/obj/machinery/pros_fabricator/update_icon()
overlays.Cut()
icon_state = initial(icon_state)
/obj/machinery/mecha_part_fabricator/pros/tgui_data(mob/user)
var/list/data = ..()
if(panel_open)
overlays.Add(image(icon, "[icon_state]_panel"))
if(stat & NOPOWER)
return
if(busy)
icon_state = "[icon_state]_work"
/obj/machinery/pros_fabricator/dismantle()
for(var/f in materials)
eject_materials(f, -1)
..()
/obj/machinery/pros_fabricator/RefreshParts()
res_max_amount = 0
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
res_max_amount += M.rating * 100000 // 200k -> 600k
var/T = 0
for(var/obj/item/weapon/stock_parts/manipulator/M in component_parts)
T += M.rating
mat_efficiency = max(0.2, 1 - (T - 1) / 4) // 1 -> 0.2
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts) // Not resetting T is intended; speed is affected by both
T += M.rating
speed = T / 2 // 1 -> 3
/obj/machinery/pros_fabricator/attack_hand(var/mob/user)
if(..())
return
if(!allowed(user))
return
ui_interact(user)
/obj/machinery/pros_fabricator/ui_interact(var/mob/user, var/ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
var/data[0]
var/datum/design/current = queue.len ? queue[1] : null
if(current)
data["current"] = current.name
data["queue"] = get_queue_names()
data["buildable"] = get_build_options()
data["category"] = category
data["categories"] = categories
data["species_types"] = species_types
data["species"] = species
if(all_robolimbs)
var/list/T = list()
for(var/A in all_robolimbs)
var/datum/robolimb/R = all_robolimbs[A]
if(R.unavailable_to_build) continue
if(species in R.species_cannot_use) continue
if(R.unavailable_to_build)
continue
if(species in R.species_cannot_use)
continue
T += list(list("id" = A, "company" = R.company))
data["manufacturers"] = T
data["manufacturer"] = manufacturer
data["materials"] = get_materials()
data["maxres"] = res_max_amount
data["sync"] = sync_message
if(current)
data["builtperc"] = round((progress / current.time) * 100)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
ui = new(user, src, ui_key, "mechfab.tmpl", "Prosthetics Fab UI", 800, 600)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
data["manufacturer"] = manufacturer
/obj/machinery/pros_fabricator/Topic(href, href_list)
return data
/obj/machinery/mecha_part_fabricator/pros/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
return TRUE
if(href_list["build"])
add_to_queue(text2num(href_list["build"]))
. = TRUE
if(href_list["remove"])
remove_from_queue(text2num(href_list["remove"]))
add_fingerprint(usr)
usr.set_machine(src)
if(href_list["category"])
if(href_list["category"] in categories)
category = href_list["category"]
switch(action)
if("species")
var/new_species = input(usr, "Select a new species", "Prosfab Species Selection", "Human") as null|anything in species_types
if(new_species && tgui_status(usr, state) == STATUS_INTERACTIVE)
species = new_species
return
if("manufacturer")
var/list/new_manufacturers = list()
for(var/A in all_robolimbs)
var/datum/robolimb/R = all_robolimbs[A]
if(R.unavailable_to_build)
continue
if(species in R.species_cannot_use)
continue
new_manufacturers += A
if(href_list["species"])
if(href_list["species"] in species_types)
species = href_list["species"]
var/new_manufacturer = input(usr, "Select a new manufacturer", "Prosfab Species Selection", "Unbranded") as null|anything in new_manufacturers
if(new_manufacturer && tgui_status(usr, state) == STATUS_INTERACTIVE)
manufacturer = new_manufacturer
return
return FALSE
if(href_list["manufacturer"])
if(href_list["manufacturer"] in all_robolimbs)
manufacturer = href_list["manufacturer"]
if(href_list["eject"])
eject_materials(href_list["eject"], text2num(href_list["amount"]))
if(href_list["sync"])
sync()
else
sync_message = ""
return 1
/obj/machinery/pros_fabricator/attackby(var/obj/item/I, var/mob/user)
if(busy)
to_chat(user, "<span class='notice'>\The [src] is busy. Please wait for completion of previous operation.</span>")
/obj/machinery/mecha_part_fabricator/pros/attackby(var/obj/item/I, var/mob/user)
if(..())
return 1
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(default_part_replacement(user, I))
return
if(istype(I,/obj/item/weapon/disk/limb))
var/obj/item/weapon/disk/limb/D = I
@@ -188,168 +156,3 @@
to_chat(user, "<span class='notice'>Uploaded [D.species] files!</span>")
qdel(I)
return
if(istype(I,/obj/item/stack/material))
var/obj/item/stack/material/S = I
if(!(S.material.name in materials))
to_chat(user, "<span class='warning'>The [src] doesn't accept [S.material]!</span>")
return
var/sname = "[S.name]"
var/amnt = S.perunit
if(materials[S.material.name] + amnt <= res_max_amount)
if(S && S.get_amount() >= 1)
var/count = 0
flick("[initial(icon_state)]_loading", src)
while(materials[S.material.name] + amnt <= res_max_amount && S.get_amount() >= 1)
materials[S.material.name] += amnt
S.use(1)
count++
to_chat(user, "You insert [count] [sname] into the fabricator.")
update_busy()
else
to_chat(user, "The fabricator cannot hold more [sname].")
return
..()
/obj/machinery/pros_fabricator/emag_act(var/remaining_charges, var/mob/user)
switch(emagged)
if(0)
emagged = 0.5
visible_message("[bicon(src)] <b>[src]</b> beeps: \"DB error \[Code 0x00F1\]\"")
sleep(10)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"Attempting auto-repair\"")
sleep(15)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"User DB corrupted \[Code 0x00FA\]. Truncating data structure...\"")
sleep(30)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"User DB truncated. Please contact your [using_map.company_name] system operator for future assistance.\"")
req_access = null
emagged = 1
return 1
if(0.5)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"DB not responding \[Code 0x0003\]...\"")
if(1)
visible_message("[bicon(src)] <b>[src]</b> beeps: \"No records in User DB\"")
/obj/machinery/pros_fabricator/proc/update_busy()
if(queue.len)
if(can_build(queue[1]))
busy = 1
else
busy = 0
else
busy = 0
/obj/machinery/pros_fabricator/proc/add_to_queue(var/index)
var/datum/design/D = files.known_designs[index]
queue += D
update_busy()
/obj/machinery/pros_fabricator/proc/remove_from_queue(var/index)
if(index == 1)
progress = 0
queue.Cut(index, index + 1)
update_busy()
/obj/machinery/pros_fabricator/proc/can_build(var/datum/design/D)
for(var/M in D.materials)
if(materials[M] < (D.materials[M] * mat_efficiency))
return 0
return 1
/obj/machinery/pros_fabricator/proc/check_build()
if(!queue.len)
progress = 0
return
var/datum/design/D = queue[1]
if(!can_build(D))
progress = 0
return
if(D.time > progress)
return
for(var/M in D.materials)
materials[M] = max(0, materials[M] - D.materials[M] * mat_efficiency)
if(D.build_path)
var/obj/new_item = D.Fabricate(get_step(get_turf(src), src.dir), src) // Sometimes returns a mob. Beware!
flick("[initial(icon_state)]_finish", src)
visible_message("\The [src] pings, indicating that \the [D] is complete.", "You hear a ping.")
if(mat_efficiency != 1)
if(istype(new_item, /obj/) && new_item.matter && new_item.matter.len > 0)
for(var/i in new_item.matter)
new_item.matter[i] = new_item.matter[i] * mat_efficiency
remove_from_queue(1)
/obj/machinery/pros_fabricator/proc/get_queue_names()
. = list()
for(var/i = 2 to queue.len)
var/datum/design/D = queue[i]
. += D.name
/obj/machinery/pros_fabricator/proc/get_build_options()
. = list()
for(var/i = 1 to files.known_designs.len)
var/datum/design/D = files.known_designs[i]
if(D.build_path && (D.build_type & PROSFAB))
. += list(list("name" = D.name, "id" = i, "category" = D.category, "resourses" = get_design_resourses(D), "time" = get_design_time(D)))
/obj/machinery/pros_fabricator/proc/get_design_resourses(var/datum/design/D)
var/list/F = list()
for(var/T in D.materials)
F += "[capitalize(T)]: [D.materials[T] * mat_efficiency]"
return english_list(F, and_text = ", ")
/obj/machinery/pros_fabricator/proc/get_design_time(var/datum/design/D)
return time2text(round(10 * D.time / speed), "mm:ss")
/obj/machinery/pros_fabricator/proc/update_categories()
categories = list()
for(var/datum/design/D in files.known_designs)
if(!D.build_path || !(D.build_type & PROSFAB))
continue
categories |= D.category
if(!category || !(category in categories))
category = categories[1]
/obj/machinery/pros_fabricator/proc/get_materials()
. = list()
for(var/T in materials)
var/hidden_mat = FALSE
for(var/HM in hidden_materials) // Direct list contents comparison was failing.
if(T == HM && materials[T] == 0)
hidden_mat = TRUE
continue
if(!hidden_mat)
. += list(list("mat" = capitalize(T), "amt" = materials[T]))
/obj/machinery/pros_fabricator/proc/eject_materials(var/material, var/amount) // 0 amount = 0 means ejecting a full stack; -1 means eject everything
var/recursive = amount == -1 ? 1 : 0
var/matstring = lowertext(material)
var/material/M = get_material_by_name(matstring)
var/obj/item/stack/material/S = M.place_sheet(get_turf(src))
if(amount <= 0)
amount = S.max_amount
var/ejected = min(round(materials[matstring] / S.perunit), amount)
S.amount = min(ejected, amount)
if(S.amount <= 0)
qdel(S)
return
materials[matstring] -= ejected * S.perunit
if(recursive && materials[matstring] >= S.perunit)
eject_materials(matstring, -1)
update_busy()
/obj/machinery/pros_fabricator/proc/sync()
sync_message = "Error: no console found."
for(var/obj/machinery/computer/rdconsole/RDC in get_area_all_atoms(get_area(src)))
if(!RDC.sync)
continue
for(var/datum/tech/T in RDC.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in RDC.files.known_designs)
files.AddDesign2Known(D)
files.RefreshResearch()
sync_message = "Sync complete."
update_categories()
+10
View File
@@ -2243,6 +2243,16 @@
output += "</body></html>"
return output
/obj/mecha/proc/get_log_tgui()
var/list/data = list()
for(var/list/entry in log)
data.Add(list(list(
"time" = time2text(entry["time"], "DDD MMM DD hh:mm:ss"),
"year" = game_year,
"message" = entry["message"],
)))
return data
/obj/mecha/proc/output_access_dialog(obj/item/weapon/card/id/id_card, mob/user)
if(!id_card || !user) return
+107 -94
View File
@@ -8,61 +8,65 @@
circuit = /obj/item/weapon/circuitboard/mecha_control
var/list/located = list()
var/screen = 0
var/stored_data
var/list/stored_data
attack_ai(var/mob/user as mob)
return src.attack_hand(user)
/obj/machinery/computer/mecha/attack_ai(mob/user)
return attack_hand(user)
attack_hand(var/mob/user as mob)
if(..())
return
user.set_machine(src)
var/dat = "<html><head><title>[src.name]</title><style>h3 {margin: 0px; padding: 0px;}</style></head><body>"
if(screen == 0)
dat += "<h3>Tracking beacons data</h3>"
for(var/obj/item/mecha_parts/mecha_tracking/TR in world)
var/answer = TR.get_mecha_info()
if(answer)
dat += {"<hr>[answer]<br/>
<a href='?src=\ref[src];send_message=\ref[TR]'>Send message</a><br/>
<a href='?src=\ref[src];get_log=\ref[TR]'>Show exosuit log</a> | <a style='color: #f00;' href='?src=\ref[src];shock=\ref[TR]'>(EMP pulse)</a><br>"}
if(screen==1)
dat += "<h3>Log contents</h3>"
dat += "<a href='?src=\ref[src];return=1'>Return</a><hr>"
dat += "[stored_data]"
dat += "<A href='?src=\ref[src];refresh=1'>(Refresh)</A><BR>"
dat += "</body></html>"
user << browse(dat, "window=computer;size=400x500")
onclose(user, "computer")
/obj/machinery/computer/mecha/attack_hand(mob/user)
if(..())
return
tgui_interact(user)
Topic(href, href_list)
if(..())
return
var/datum/topic_input/top_filter = new /datum/topic_input(href,href_list)
if(href_list["send_message"])
var/obj/item/mecha_parts/mecha_tracking/MT = top_filter.getObj("send_message")
var/message = sanitize(input(usr,"Input message","Transmit message") as text)
var/obj/mecha/M = MT.in_mecha()
if(message && M)
M.occupant_message(message)
return
if(href_list["shock"])
var/obj/item/mecha_parts/mecha_tracking/MT = top_filter.getObj("shock")
MT.shock()
if(href_list["get_log"])
var/obj/item/mecha_parts/mecha_tracking/MT = top_filter.getObj("get_log")
stored_data = MT.get_mecha_log()
screen = 1
if(href_list["return"])
screen = 0
src.updateUsrDialog()
return
/obj/machinery/computer/mecha/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "MechaControlConsole", name)
ui.open()
/obj/machinery/computer/mecha/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["beacons"] = list()
for(var/obj/item/mecha_parts/mecha_tracking/TR in world)
var/list/tr_data = TR.tgui_data(user)
if(tr_data)
data["beacons"].Add(list(tr_data))
LAZYINITLIST(stored_data)
data["stored_data"] = stored_data
return data
/obj/machinery/computer/mecha/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("send_message")
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["mt"])
if(istype(MT))
var/message = sanitize(input(usr, "Input message", "Transmit message") as text)
var/obj/mecha/M = MT.in_mecha()
if(message && M)
M.occupant_message(message)
return TRUE
if("shock")
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["mt"])
if(istype(MT))
MT.shock()
return TRUE
if("get_log")
var/obj/item/mecha_parts/mecha_tracking/MT = locate(params["mt"])
if(istype(MT))
stored_data = MT.get_mecha_log()
return TRUE
if("clear_log")
stored_data = null
return TRUE
/obj/item/mecha_parts/mecha_tracking
name = "Exosuit tracking beacon"
@@ -71,58 +75,67 @@
icon_state = "motion2"
origin_tech = list(TECH_DATA = 2, TECH_MAGNET = 2)
proc/get_mecha_info()
if(!in_mecha())
return 0
var/obj/mecha/M = src.loc
var/cell_charge = M.get_charge()
var/answer = {"<b>Name:</b> [M.name]<br>
<b>Integrity:</b> [M.health/initial(M.health)*100]%<br>
<b>Cell charge:</b> [isnull(cell_charge)?"Not found":"[M.cell.percent()]%"]<br>
<b>Airtank:</b> [M.return_pressure()]kPa<br>
<b>Pilot:</b> [M.occupant||"None"]<br>
<b>Location:</b> [get_area(M)||"Unknown"]<br>
<b>Active equipment:</b> [M.selected||"None"]"}
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
answer += "<b>Used cargo space:</b> [RM.cargo.len/RM.cargo_capacity*100]%<br>"
/obj/item/mecha_parts/mecha_tracking/tgui_data(mob/user)
var/list/data = ..()
if(!in_mecha())
return FALSE
return answer
var/obj/mecha/M = loc
data["ref"] = REF(src)
data["charge"] = M.get_charge()
data["name"] = M.name
data["health"] = M.health
data["maxHealth"] = initial(M.health)
data["cell"] = M.cell
if(M.cell)
data["cellCharge"] = M.cell.charge
data["cellMaxCharge"] = M.cell.charge
data["airtank"] = M.return_pressure()
data["pilot"] = M.occupant
data["location"] = get_area(M)
data["active"] = M.selected
if(istype(M, /obj/mecha/working/ripley))
var/obj/mecha/working/ripley/RM = M
data["cargoUsed"] = RM.cargo.len
data["cargoMax"] = RM.cargo_capacity
emp_act()
qdel(src)
return
return data
ex_act()
qdel(src)
return
/obj/item/mecha_parts/mecha_tracking/emp_act()
qdel(src)
return
proc/in_mecha()
if(istype(src.loc, /obj/mecha))
return src.loc
return 0
/obj/item/mecha_parts/mecha_tracking/ex_act()
qdel(src)
return
proc/shock()
var/obj/mecha/M = in_mecha()
if(M)
M.emp_act(4)
qdel(src)
/obj/item/mecha_parts/mecha_tracking/proc/in_mecha()
if(istype(loc, /obj/mecha))
return loc
return 0
proc/get_mecha_log()
if(!src.in_mecha())
return 0
var/obj/mecha/M = src.loc
return M.get_log_html()
/obj/item/mecha_parts/mecha_tracking/proc/shock()
var/obj/mecha/M = in_mecha()
if(M)
M.emp_act(4)
qdel(src)
/obj/item/mecha_parts/mecha_tracking/proc/get_mecha_log()
if(!in_mecha())
return list()
var/obj/mecha/M = loc
return M.get_log_tgui()
/obj/item/weapon/storage/box/mechabeacons
name = "Exosuit Tracking Beacons"
New()
..()
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
/obj/item/weapon/storage/box/mechabeacons/New()
..()
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
new /obj/item/mecha_parts/mecha_tracking(src)
+3 -3
View File
@@ -1,5 +1,5 @@
/datum/design/item/mechfab/gopher
category = "Gopher"
category = list("Gopher")
time = 5
/datum/design/item/mechfab/gopher/chassis
@@ -55,7 +55,7 @@
materials = list(DEFAULT_WALL_MATERIAL = 2500)
/datum/design/item/mechfab/polecat
category = "Polecat"
category = list("Polecat")
time = 10
/datum/design/item/mechfab/polecat/chassis
@@ -134,7 +134,7 @@
build_path = /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/microshotgun
/datum/design/item/mechfab/weasel
category = "Weasel"
category = list("Weasel")
time = 5
/datum/design/item/mechfab/weasel/chassis
@@ -77,6 +77,9 @@
return "[..()][append]"
/obj/item/device/radio/headset/tgui_state(mob/user)
return GLOB.tgui_inventory_state
/obj/item/device/radio/headset/syndicate
origin_tech = list(TECH_ILLEGAL = 3)
syndie = 1
@@ -168,7 +168,7 @@ var/global/list/default_medbay_channels = list(
/obj/item/device/radio/tgui_data(mob/user)
var/data[0]
data["rawfreq"] = num2text(frequency)
data["rawfreq"] = frequency
data["listening"] = listening
data["broadcasting"] = broadcasting
data["subspace"] = subspace_transmission
@@ -5,7 +5,7 @@
icon_state = "valve_1"
var/obj/item/weapon/tank/tank_one
var/obj/item/weapon/tank/tank_two
var/obj/item/device/attached_device
var/obj/item/device/assembly/attached_device
var/mob/attacher = null
var/valve_open = 0
var/toggle = 1
@@ -20,18 +20,18 @@
if(!tank_one)
tank_one = item
user.drop_item()
item.loc = src
item.forceMove(src)
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
else if(!tank_two)
tank_two = item
user.drop_item()
item.loc = src
item.forceMove(src)
to_chat(user, "<span class='notice'>You attach the tank to the transfer valve.</span>")
message_admins("[key_name_admin(user)] attached both tanks to a transfer valve. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[location.x];Y=[location.y];Z=[location.z]'>JMP</a>)")
log_game("[key_name_admin(user)] attached both tanks to a transfer valve.")
update_icon()
SSnanoui.update_uis(src) // update all UIs attached to src
SStgui.update_uis(src) // update all UIs attached to src
//TODO: Have this take an assemblyholder
else if(isassembly(item))
var/obj/item/device/assembly/A = item
@@ -43,7 +43,7 @@
return
user.remove_from_mob(item)
attached_device = A
A.loc = src
A.forceMove(src)
to_chat(user, "<span class='notice'>You attach the [item] to the valve controls and secure it.</span>")
A.holder = src
A.toggle_secure() //this calls update_icon(), which calls update_icon() on the holder (i.e. the bomb).
@@ -52,7 +52,7 @@
message_admins("[key_name_admin(user)] attached a [item] to a transfer valve. (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[location.x];Y=[location.y];Z=[location.z]'>JMP</a>)")
log_game("[key_name_admin(user)] attached a [item] to a transfer valve.")
attacher = user
SSnanoui.update_uis(src) // update all UIs attached to src
SStgui.update_uis(src) // update all UIs attached to src
return
@@ -66,53 +66,51 @@
if(isturf(loc))
sense_proximity(callback = .HasProximity)
/obj/item/device/transfer_valve/attack_self(mob/user as mob)
ui_interact(user)
/obj/item/device/transfer_valve/attack_self(mob/user)
tgui_interact(user)
/obj/item/device/transfer_valve/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/item/device/transfer_valve/tgui_state(mob/user)
return GLOB.tgui_inventory_state
// this is the data which will be sent to the ui
var/data[0]
data["attachmentOne"] = tank_one ? tank_one.name : null
data["attachmentTwo"] = tank_two ? tank_two.name : null
data["valveAttachment"] = attached_device ? attached_device.name : null
data["valveOpen"] = valve_open ? 1 : 0
// update the ui if it exists, returns null if no ui is passed/found
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "transfer_valve.tmpl", "Tank Transfer Valve", 460, 280)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
/obj/item/device/transfer_valve/tgui_interact(mob/user, datum/tgui/ui = null)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TransferValve", name) // 460, 320
ui.open()
// auto update every Master Controller tick
//ui.set_auto_update(1)
/obj/item/device/transfer_valve/Topic(href, href_list)
..()
if ( usr.stat || usr.restrained() )
return 0
if (src.loc != usr)
return 0
if(tank_one && href_list["tankone"])
remove_tank(tank_one)
else if(tank_two && href_list["tanktwo"])
remove_tank(tank_two)
else if(href_list["open"])
toggle_valve()
else if(attached_device)
if(href_list["rem_device"])
attached_device.loc = get_turf(src)
attached_device:holder = null
attached_device = null
update_icon()
if(href_list["device"])
attached_device.attack_self(usr)
src.add_fingerprint(usr)
return 1 // Returning 1 sends an update to attached UIs
/obj/item/device/transfer_valve/tgui_data(mob/user)
var/list/data = list()
data["tank_one"] = tank_one ? tank_one.name : null
data["tank_two"] = tank_two ? tank_two.name : null
data["attached_device"] = attached_device ? attached_device.name : null
data["valve"] = valve_open
return data
/obj/item/device/transfer_valve/tgui_act(action, params)
if(..())
return
. = TRUE
switch(action)
if("tankone")
remove_tank(tank_one)
if("tanktwo")
remove_tank(tank_two)
if("toggle")
toggle_valve()
if("device")
if(attached_device)
attached_device.attack_self(usr)
if("remove_device")
if(attached_device)
attached_device.forceMove(get_turf(src))
attached_device.holder = null
attached_device = null
update_icon()
else
. = FALSE
if(.)
update_icon()
add_fingerprint(usr)
/obj/item/device/transfer_valve/proc/process_activation(var/obj/item/device/D)
if(toggle)
@@ -148,7 +146,7 @@
else
return
T.loc = get_turf(src)
T.forceMove(get_turf(src))
update_icon()
/obj/item/device/transfer_valve/proc/merge_gases()
@@ -6,6 +6,8 @@
desc = "Protected by FRM."
icon = 'icons/obj/module.dmi'
icon_state = "cyborg_upgrade"
/// Bitflags listing module compatibility. Used in the exosuit fabricator for creating sub-categories.
var/list/module_flags = NONE
var/locked = 0
var/require_module = 0
var/installed = 0
@@ -95,6 +97,7 @@
desc = "Used to cool a mounted taser, increasing the potential current in it and thus its recharge rate."
icon_state = "cyborg_upgrade3"
item_state = "cyborg_upgrade"
module_flags = BORG_MODULE_SECURITY
require_module = 1
@@ -77,6 +77,9 @@
get_asset_datum(/datum/asset/spritesheet/pipes),
)
/obj/item/weapon/pipe_dispenser/tgui_state(mob/user)
return GLOB.tgui_inventory_state
/obj/item/weapon/pipe_dispenser/tgui_interact(mob/user, datum/tgui/ui)
SetupPipes()
ui = SStgui.try_update_ui(user, src, ui)
@@ -78,7 +78,7 @@ obj/item/weapon/circuitboard/rdserver/attackby(obj/item/I as obj, mob/user as mo
/obj/item/weapon/circuitboard/prosthetics
name = "Circuit board (Prosthetics Fabricator)"
build_path = /obj/machinery/pros_fabricator
build_path = /obj/machinery/mecha_part_fabricator/pros
board_type = new /datum/frame/frame_types/machine
origin_tech = list(TECH_DATA = 3, TECH_ENGINEERING = 3)
req_components = list(
@@ -40,6 +40,9 @@
/obj/item/weapon/card/id/proc/prevent_tracking()
return 0
/obj/item/weapon/card/id/tgui_state(mob/user)
return GLOB.tgui_deep_inventory_state
/obj/item/weapon/card/id/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
@@ -223,6 +223,8 @@ var/list/global/tank_gauge_cache = list()
if (src.proxyassembly.assembly)
src.proxyassembly.assembly.attack_self(user)
/obj/item/weapon/tank/tgui_state(mob/user)
return GLOB.tgui_deep_inventory_state
/obj/item/weapon/tank/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
-3
View File
@@ -45,9 +45,6 @@
log_unit_test("If you did not intend to enable this please check code/__defines/unit_testing.dm")
#endif
// Set up roundstart seed list.
plant_controller = new()
// This is kinda important. Set up details of what the hell things are made of.
populate_material_list()
+6 -6
View File
@@ -1082,18 +1082,18 @@ var/datum/announcement/minor/admin_min_announcer = new
return 0
/datum/admins/proc/spawn_fruit(seedtype in plant_controller.seeds)
/datum/admins/proc/spawn_fruit(seedtype in SSplants.seeds)
set category = "Debug"
set desc = "Spawn the product of a seed."
set name = "Spawn Fruit"
if(!check_rights(R_SPAWN)) return
if(!seedtype || !plant_controller.seeds[seedtype])
if(!seedtype || !SSplants.seeds[seedtype])
return
var/amount = input("Amount of fruit to spawn", "Fruit Amount", 1) as null|num
if(!isnull(amount))
var/datum/seed/S = plant_controller.seeds[seedtype]
var/datum/seed/S = SSplants.seeds[seedtype]
S.harvest(usr,0,0,amount)
log_admin("[key_name(usr)] spawned [seedtype] fruit at ([usr.x],[usr.y],[usr.z])")
@@ -1137,16 +1137,16 @@ var/datum/announcement/minor/admin_min_announcer = new
for(var/datum/custom_item/item in current_items)
to_chat(usr, "- name: [item.name] icon: [item.item_icon] path: [item.item_path] desc: [item.item_desc]")
/datum/admins/proc/spawn_plant(seedtype in plant_controller.seeds)
/datum/admins/proc/spawn_plant(seedtype in SSplants.seeds)
set category = "Debug"
set desc = "Spawn a spreading plant effect."
set name = "Spawn Plant"
if(!check_rights(R_SPAWN)) return
if(!seedtype || !plant_controller.seeds[seedtype])
if(!seedtype || !SSplants.seeds[seedtype])
return
new /obj/effect/plant(get_turf(usr), plant_controller.seeds[seedtype])
new /obj/effect/plant(get_turf(usr), SSplants.seeds[seedtype])
log_admin("[key_name(usr)] spawned [seedtype] vines at ([usr.x],[usr.y],[usr.z])")
/datum/admins/proc/spawn_atom(var/object as text)
+12 -8
View File
@@ -88,15 +88,19 @@
. += "\The [src] can be attached!"
/obj/item/device/assembly/attack_self(mob/user as mob)
if(!user) return 0
if(!user)
return 0
user.set_machine(src)
interact(user)
tgui_interact(user)
return 1
/obj/item/device/assembly/interact(mob/user as mob)
return //HTML MENU FOR WIRES GOES HERE
/obj/item/device/assembly/tgui_state(mob/user)
return GLOB.tgui_deep_inventory_state
/obj/item/device/assembly/nano_host()
if(istype(loc, /obj/item/device/assembly_holder))
return loc.nano_host()
return ..()
/obj/item/device/assembly/tgui_interact(mob/user, datum/tgui/ui)
return // tgui goes here
/obj/item/device/assembly/tgui_host()
if(istype(loc, /obj/item/device/assembly_holder))
return loc.tgui_host()
return ..()
+28 -31
View File
@@ -100,41 +100,38 @@
if(!holder)
visible_message("[bicon(src)] *beep* *beep*")
/obj/item/device/assembly/infra/interact(mob/user as mob)//TODO: change this this to the wire control panel
/obj/item/device/assembly/infra/tgui_interact(mob/user, datum/tgui/ui)
if(!secured)
return
user.set_machine(src)
var/dat = text("<TT><B>Infrared Laser</B>\n<B>Status</B>: []<BR>\n<B>Visibility</B>: []<BR>\n</TT>", (on ? text("<A href='?src=\ref[];state=0'>On</A>", src) : text("<A href='?src=\ref[];state=1'>Off</A>", src)), (src.visible ? text("<A href='?src=\ref[];visible=0'>Visible</A>", src) : text("<A href='?src=\ref[];visible=1'>Invisible</A>", src)))
dat += "<BR><BR><A href='?src=\ref[src];refresh=1'>Refresh</A>"
dat += "<BR><BR><A href='?src=\ref[src];close=1'>Close</A>"
user << browse(dat, "window=infra")
onclose(user, "infra")
to_chat(user, "<span class='warning'>[src] is unsecured!</span>")
return FALSE
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AssemblyInfrared", name)
ui.open()
/obj/item/device/assembly/infra/Topic(href, href_list, state = deep_inventory_state)
/obj/item/device/assembly/infra/tgui_data(mob/user)
var/list/data = ..()
data["on"] = on
data["visible"] = visible
return data
/obj/item/device/assembly/infra/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr << browse(null, "window=infra")
onclose(usr, "infra")
return
return TRUE
if(href_list["state"])
toggle_state()
if(href_list["visible"])
visible = !(visible)
for(var/ibeam in i_beams)
var/obj/effect/beam/i_beam/I = ibeam
I.visible = visible
CHECK_TICK
if(href_list["close"])
usr << browse(null, "window=infra")
return
if(usr)
attack_self(usr)
switch(action)
if("state")
toggle_state()
return TRUE
if("visible")
visible = !visible
for(var/ibeam in i_beams)
var/obj/effect/beam/i_beam/I = ibeam
I.visible = visible
CHECK_TICK
return TRUE
/obj/item/device/assembly/infra/verb/rotate_clockwise()
set name = "Rotate Infrared Laser Clockwise"
+41 -41
View File
@@ -95,49 +95,49 @@
sense_proximity(range = range, callback = .HasProximity)
sense()
/obj/item/device/assembly/prox_sensor/interact(mob/user as mob)//TODO: Change this to the wires thingy
/obj/item/device/assembly/prox_sensor/tgui_interact(mob/user, datum/tgui/ui)
if(!secured)
user.show_message("<font color='red'>The [name] is unsecured!</font>")
return 0
var/second = time % 60
var/minute = (time - second) / 60
var/dat = text("<TT><B>Proximity Sensor</B>\n[] []:[]\n<A href='?src=\ref[];tp=-30'>-</A> <A href='?src=\ref[];tp=-1'>-</A> <A href='?src=\ref[];tp=1'>+</A> <A href='?src=\ref[];tp=30'>+</A>\n</TT>", (timing ? text("<A href='?src=\ref[];time=0'>Arming</A>", src) : text("<A href='?src=\ref[];time=1'>Not Arming</A>", src)), minute, second, src, src, src, src)
dat += text("<BR>Range: <A href='?src=\ref[];range=-1'>-</A> [] <A href='?src=\ref[];range=1'>+</A>", src, range, src)
dat += "<BR><A href='?src=\ref[src];scanning=1'>[scanning?"Armed":"Unarmed"]</A> (Movement sensor active when armed!)"
dat += "<BR><BR><A href='?src=\ref[src];refresh=1'>Refresh</A>"
dat += "<BR><BR><A href='?src=\ref[src];close=1'>Close</A>"
user << browse(dat, "window=prox")
onclose(user, "prox")
to_chat(user, "<span class='warning'>[src] is unsecured!</span>")
return FALSE
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AssemblyProx", name)
ui.open()
/obj/item/device/assembly/prox_sensor/Topic(href, href_list, state = deep_inventory_state)
/obj/item/device/assembly/prox_sensor/tgui_data(mob/user)
var/list/data = ..()
data["time"] = time * 10
data["timing"] = timing
data["range"] = range
data["maxRange"] = 5
data["scanning"] = scanning
return data
/obj/item/device/assembly/prox_sensor/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr << browse(null, "window=prox")
onclose(usr, "prox")
return
if(href_list["scanning"])
toggle_scan()
if(href_list["time"])
timing = text2num(href_list["time"])
update_icon()
if(href_list["tp"])
var/tp = text2num(href_list["tp"])
time += tp
time = min(max(round(time), 0), 600)
if(href_list["range"])
var/r = text2num(href_list["range"])
range += r
range = min(max(range, 1), 5)
if(href_list["close"])
usr << browse(null, "window=prox")
return
if(usr)
attack_self(usr)
switch(action)
if("scanning")
toggle_scan()
return TRUE
if("timing")
timing = !timing
update_icon()
return TRUE
if("set_time")
var/real_new_time = 0
var/new_time = params["time"]
var/list/L = splittext(new_time, ":")
if(LAZYLEN(L))
for(var/i in 1 to LAZYLEN(L))
real_new_time += text2num(L[i]) * (60 ** (LAZYLEN(L) - i))
else
real_new_time = text2num(new_time)
time = clamp(real_new_time, 0, 600)
return TRUE
if("range")
range = clamp(params["range"], 1, 5)
return TRUE
-8
View File
@@ -31,14 +31,6 @@
if(holder)
holder.update_icon()
/obj/item/device/assembly/signaler/interact(mob/user)
if(..())
return TRUE
tgui_interact(user)
/obj/item/device/assembly/signaler/tgui_state(mob/user)
return GLOB.tgui_deep_inventory_state
/obj/item/device/assembly/signaler/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
+31 -36
View File
@@ -62,43 +62,38 @@
holder.update_icon()
return
/obj/item/device/assembly/timer/interact(mob/user as mob)//TODO: Have this use the wires
/obj/item/device/assembly/timer/tgui_interact(mob/user, datum/tgui/ui)
if(!secured)
user.show_message("<font color='red'>The [name] is unsecured!</font>")
return 0
var/second = time % 60
var/minute = (time - second) / 60
var/dat = text("<TT><B>Timing Unit</B>\n[] []:[]\n<A href='?src=\ref[];tp=-30'>-</A> <A href='?src=\ref[];tp=-1'>-</A> <A href='?src=\ref[];tp=1'>+</A> <A href='?src=\ref[];tp=30'>+</A>\n</TT>", (timing ? text("<A href='?src=\ref[];time=0'>Timing</A>", src) : text("<A href='?src=\ref[];time=1'>Not Timing</A>", src)), minute, second, src, src, src, src)
dat += "<BR><BR><A href='?src=\ref[src];refresh=1'>Refresh</A>"
dat += "<BR><BR><A href='?src=\ref[src];close=1'>Close</A>"
user << browse(dat, "window=timer")
onclose(user, "timer")
return
to_chat(user, "<span class='warning'>[src] is unsecured!</span>")
return FALSE
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "AssemblyTimer", name)
ui.open()
/obj/item/device/assembly/timer/tgui_data(mob/user)
var/list/data = ..()
data["time"] = time * 10
data["timing"] = timing
return data
/obj/item/device/assembly/timer/Topic(href, href_list, state = deep_inventory_state)
if(..()) return 1
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
usr << browse(null, "window=timer")
onclose(usr, "timer")
return
/obj/item/device/assembly/timer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
if(href_list["time"])
var/new_timing = text2num(href_list["time"])
set_state(new_timing)
update_icon()
if(href_list["tp"])
var/tp = text2num(href_list["tp"])
time += tp
time = min(max(round(time), 0), 600)
if(href_list["close"])
usr << browse(null, "window=timer")
return
if(usr)
attack_self(usr)
return
switch(action)
if("timing")
timing = !timing
update_icon()
return TRUE
if("set_time")
var/real_new_time = 0
var/new_time = params["time"]
var/list/L = splittext(new_time, ":")
if(LAZYLEN(L))
for(var/i in 1 to LAZYLEN(L))
real_new_time += text2num(L[i]) * (60 ** (LAZYLEN(L) - i))
else
real_new_time = text2num(new_time)
time = clamp(real_new_time, 0, 600)
return TRUE
+8 -1
View File
@@ -498,4 +498,11 @@
assets["synthprinter_working.gif"] = icon('icons/obj/machines/synthpod.dmi', "pod_1")
for(var/asset_name in assets)
register_asset(asset_name, assets[asset_name])
// VOREStation Add End
// VOREStation Add End
/datum/asset/spritesheet/sheetmaterials
name = "sheetmaterials"
/datum/asset/spritesheet/sheetmaterials/register()
InsertAll("", 'icons/obj/stacks.dmi')
..()
+8 -15
View File
@@ -30,7 +30,7 @@
log_debug("Plantname not provided and and [src] requires it at [x],[y],[z]")
return INITIALIZE_HINT_QDEL
seed = plant_controller.seeds[plantname]
seed = SSplants.seeds[plantname]
if(!seed)
log_debug("Plant name '[plantname]' does not exist and [src] requires it at [x],[y],[z]")
@@ -62,18 +62,11 @@
force = 1
/obj/item/weapon/reagent_containers/food/snacks/grown/proc/update_desc()
if(!seed)
return
if(!plant_controller)
sleep(250) // ugly hack, should mean roundstart plants are fine.
if(!plant_controller)
to_world("<span class='danger'>Plant controller does not exist and [src] requires it. Aborting.</span>")
qdel(src)
return
if(plant_controller.product_descs["[seed.uid]"])
desc = plant_controller.product_descs["[seed.uid]"]
if(SSplants.product_descs["[seed.uid]"])
desc = SSplants.product_descs["[seed.uid]"]
else
var/list/descriptors = list()
if(reagents.has_reagent("sugar") || reagents.has_reagent("cherryjelly") || reagents.has_reagent("honey") || reagents.has_reagent("berryjuice"))
@@ -125,17 +118,17 @@
desc += " mushroom"
else
desc += " fruit"
plant_controller.product_descs["[seed.uid]"] = desc
SSplants.product_descs["[seed.uid]"] = desc
desc += ". Delicious! Probably."
/obj/item/weapon/reagent_containers/food/snacks/grown/update_icon()
if(!seed || !plant_controller || !plant_controller.plant_icon_cache)
if(!seed || !SSplants || !SSplants.plant_icon_cache)
return
overlays.Cut()
var/image/plant_icon
var/icon_key = "fruit-[seed.get_trait(TRAIT_PRODUCT_ICON)]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"
if(plant_controller.plant_icon_cache[icon_key])
plant_icon = plant_controller.plant_icon_cache[icon_key]
if(SSplants.plant_icon_cache[icon_key])
plant_icon = SSplants.plant_icon_cache[icon_key]
else
plant_icon = image('icons/obj/hydroponics_products.dmi',"blank")
var/image/fruit_base = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-product")
@@ -145,7 +138,7 @@
var/image/fruit_leaves = image('icons/obj/hydroponics_products.dmi',"[seed.get_trait(TRAIT_PRODUCT_ICON)]-leaf")
fruit_leaves.color = "[seed.get_trait(TRAIT_PLANT_COLOUR)]"
plant_icon.overlays |= fruit_leaves
plant_controller.plant_icon_cache[icon_key] = plant_icon
SSplants.plant_icon_cache[icon_key] = plant_icon
overlays |= plant_icon
/obj/item/weapon/reagent_containers/food/snacks/grown/Crossed(var/mob/living/M)
+1 -1
View File
@@ -19,7 +19,7 @@
//Handle some post-spawn var stuff.
if(planttype)
plantname = planttype
var/datum/seed/S = plant_controller.seeds[plantname]
var/datum/seed/S = SSplants.seeds[plantname]
if(!S || !S.chems)
return
+6 -6
View File
@@ -410,8 +410,8 @@
seed_noun = pick("spores","nodes","cuttings","seeds")
set_trait(TRAIT_POTENCY,rand(5,30),200,0)
set_trait(TRAIT_PRODUCT_ICON,pick(plant_controller.accessible_product_sprites))
set_trait(TRAIT_PLANT_ICON,pick(plant_controller.accessible_plant_sprites))
set_trait(TRAIT_PRODUCT_ICON,pick(SSplants.accessible_product_sprites))
set_trait(TRAIT_PLANT_ICON,pick(SSplants.accessible_plant_sprites))
set_trait(TRAIT_PLANT_COLOUR,"#[get_random_colour(0,75,190)]")
set_trait(TRAIT_PRODUCT_COLOUR,"#[get_random_colour(0,75,190)]")
update_growth_stages()
@@ -788,10 +788,10 @@
to_chat(user, "You [harvest_sample ? "take a sample" : "harvest"] from the [display_name].")
//This may be a new line. Update the global if it is.
if(name == "new line" || !(name in plant_controller.seeds))
uid = plant_controller.seeds.len + 1
if(name == "new line" || !(name in SSplants.seeds))
uid = SSplants.seeds.len + 1
name = "[uid]"
plant_controller.seeds[name] = src
SSplants.seeds[name] = src
if(harvest_sample)
var/obj/item/seeds/seeds = new(get_turf(user))
@@ -877,6 +877,6 @@
/datum/seed/proc/update_growth_stages()
if(get_trait(TRAIT_PLANT_ICON))
growth_stages = plant_controller.plant_sprites[get_trait(TRAIT_PLANT_ICON)]
growth_stages = SSplants.plant_sprites[get_trait(TRAIT_PLANT_ICON)]
else
growth_stages = 0
+105 -109
View File
@@ -62,7 +62,7 @@
return attack_hand(user)
/obj/machinery/botany/attack_hand(mob/user as mob)
ui_interact(user)
tgui_interact(user)
/obj/machinery/botany/proc/finished_task()
active = 0
@@ -136,14 +136,16 @@
var/datum/seed/genetics // Currently scanned seed genetic structure.
var/degradation = 0 // Increments with each scan, stops allowing gene mods after a certain point.
/obj/machinery/botany/extractor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/botany/extractor/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "BotanyIsolator", name)
ui.open()
if(!user)
return
/obj/machinery/botany/extractor/tgui_data(mob/user)
var/list/data = ..()
var/list/data = list()
var/list/geneMasks = plant_controller.gene_masked_list
var/list/geneMasks = SSplants.gene_masked_list
data["geneMasks"] = geneMasks
data["activity"] = active
@@ -168,95 +170,93 @@
data["hasGenetics"] = 0
data["sourceName"] = 0
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "botany_isolator.tmpl", "Lysis-isolation Centrifuge UI", 470, 450)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/botany/Topic(href, href_list)
return data
/obj/machinery/botany/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
if(href_list["eject_packet"])
if(!seed) return
seed.loc = get_turf(src)
if(seed.seed.name == "new line" || isnull(plant_controller.seeds[seed.seed.name]))
seed.seed.uid = plant_controller.seeds.len + 1
seed.seed.name = "[seed.seed.uid]"
plant_controller.seeds[seed.seed.name] = seed.seed
seed.update_seed()
visible_message("[bicon(src)] [src] beeps and spits out [seed].")
seed = null
if(href_list["eject_disk"])
if(!loaded_disk) return
loaded_disk.loc = get_turf(src)
visible_message("[bicon(src)] [src] beeps and spits out [loaded_disk].")
loaded_disk = null
return TRUE
usr.set_machine(src)
src.add_fingerprint(usr)
add_fingerprint(usr)
/obj/machinery/botany/extractor/Topic(href, href_list)
switch(action)
if("eject_packet")
if(!seed)
return
seed.forceMove(get_turf(src))
if(seed.seed.name == "new line" || isnull(SSplants.seeds[seed.seed.name]))
seed.seed.uid = SSplants.seeds.len + 1
seed.seed.name = "[seed.seed.uid]"
SSplants.seeds[seed.seed.name] = seed.seed
seed.update_seed()
visible_message("[bicon(src)] [src] beeps and spits out [seed].")
seed = null
return TRUE
if("eject_disk")
if(!loaded_disk)
return
loaded_disk.forceMove(get_turf(src))
visible_message("[bicon(src)] [src] beeps and spits out [loaded_disk].")
loaded_disk = null
return TRUE
/obj/machinery/botany/extractor/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
return TRUE
usr.set_machine(src)
src.add_fingerprint(usr)
switch(action)
if("scan_genome")
if(!seed)
return
if(href_list["scan_genome"])
last_action = world.time
active = 1
if(!seed) return
if(seed && seed.seed)
genetics = seed.seed
degradation = 0
last_action = world.time
active = 1
qdel(seed)
seed = null
return TRUE
if(seed && seed.seed)
genetics = seed.seed
degradation = 0
if("get_gene")
if(!genetics || !loaded_disk)
return
qdel(seed)
seed = null
last_action = world.time
active = 1
if(href_list["get_gene"])
var/datum/plantgene/P = genetics.get_gene(params["get_gene"])
if(!P)
return
loaded_disk.genes += P
if(!genetics || !loaded_disk) return
loaded_disk.genesource = "[genetics.display_name]"
if(!genetics.roundstart)
loaded_disk.genesource += " (variety #[genetics.uid])"
last_action = world.time
active = 1
loaded_disk.name += " ([SSplants.gene_tag_masks[params["get_gene"]]], #[genetics.uid])"
loaded_disk.desc += " The label reads \'gene [SSplants.gene_tag_masks[params["get_gene"]]], sampled from [genetics.display_name]\'."
eject_disk = 1
var/datum/plantgene/P = genetics.get_gene(href_list["get_gene"])
if(!P) return
loaded_disk.genes += P
degradation += rand(20,60)
if(degradation >= 100)
failed_task = 1
genetics = null
degradation = 0
return TRUE
loaded_disk.genesource = "[genetics.display_name]"
if(!genetics.roundstart)
loaded_disk.genesource += " (variety #[genetics.uid])"
loaded_disk.name += " ([plant_controller.gene_tag_masks[href_list["get_gene"]]], #[genetics.uid])"
loaded_disk.desc += " The label reads \'gene [plant_controller.gene_tag_masks[href_list["get_gene"]]], sampled from [genetics.display_name]\'."
eject_disk = 1
degradation += rand(20,60)
if(degradation >= 100)
failed_task = 1
if("clear_buffer")
if(!genetics)
return
genetics = null
degradation = 0
if(href_list["clear_buffer"])
if(!genetics) return
genetics = null
degradation = 0
src.updateUsrDialog()
return
return TRUE
// Fires an extracted trait into another packet of seeds with a chance
// of destroying it based on the size/complexity of the plasmid.
@@ -265,13 +265,15 @@
icon_state = "traitgun"
disk_needs_genes = 1
/obj/machinery/botany/editor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(!user)
return
var/list/data = list()
/obj/machinery/botany/editor/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "BotanyEditor", name)
ui.open()
/obj/machinery/botany/editor/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["activity"] = active
if(seed)
@@ -286,7 +288,7 @@
for(var/datum/plantgene/P in loaded_disk.genes)
if(data["locus"] != "") data["locus"] += ", "
data["locus"] += "[plant_controller.gene_tag_masks[P.genetype]]"
data["locus"] += "[SSplants.gene_tag_masks[P.genetype]]"
else
data["disk"] = 0
@@ -298,36 +300,30 @@
else
data["loaded"] = 0
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
ui = new(user, src, ui_key, "botany_editor.tmpl", "Bioballistic Delivery UI", 470, 450)
ui.set_initial_data(data)
ui.open()
ui.set_auto_update(1)
/obj/machinery/botany/editor/Topic(href, href_list)
return data
/obj/machinery/botany/editor/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
return TRUE
if(href_list["apply_gene"])
if(!loaded_disk || !seed) return
switch(action)
if("apply_gene")
if(!loaded_disk || !seed)
return
last_action = world.time
active = 1
last_action = world.time
active = 1
if(!isnull(plant_controller.seeds[seed.seed.name]))
seed.seed = seed.seed.diverge(1)
seed.seed_type = seed.seed.name
seed.update_seed()
if(!isnull(SSplants.seeds[seed.seed.name]))
seed.seed = seed.seed.diverge(1)
seed.seed_type = seed.seed.name
seed.update_seed()
if(prob(seed.modified))
failed_task = 1
seed.modified = 101
if(prob(seed.modified))
failed_task = 1
seed.modified = 101
for(var/datum/plantgene/gene in loaded_disk.genes)
seed.seed.apply_gene(gene)
seed.modified += rand(5,10)
usr.set_machine(src)
src.add_fingerprint(usr)
for(var/datum/plantgene/gene in loaded_disk.genes)
seed.seed.apply_gene(gene)
seed.modified += rand(5,10)
return TRUE
+3 -3
View File
@@ -19,8 +19,8 @@ GLOBAL_LIST_BOILERPLATE(all_seed_packs, /obj/item/seeds)
//Grabs the appropriate seed datum from the global list.
/obj/item/seeds/proc/update_seed()
if(!seed && seed_type && !isnull(plant_controller.seeds) && plant_controller.seeds[seed_type])
seed = plant_controller.seeds[seed_type]
if(!seed && seed_type && !isnull(SSplants.seeds) && SSplants.seeds[seed_type])
seed = SSplants.seeds[seed_type]
update_appearance()
//Updates strings and icon appropriately based on seed datum.
@@ -76,7 +76,7 @@ GLOBAL_LIST_BOILERPLATE(all_seed_packs, /obj/item/seeds)
seed_type = null
/obj/item/seeds/random/Initialize()
seed = plant_controller.create_random_seed()
seed = SSplants.create_random_seed()
seed_type = seed.name
. = ..()
+130 -236
View File
@@ -211,23 +211,15 @@
if(lockdown)
return
user.set_machine(src)
interact(user)
tgui_interact(user)
/obj/machinery/seed_storage/interact(mob/user as mob)
if (..())
return
if(smart)
scanner = list("stats", "produce", "soil", "temperature", "light", "pressure")
else
scanner = initial(scanner)
if (!seeds_initialized)
/obj/machinery/seed_storage/tgui_interact(mob/user, datum/tgui/ui)
if(!seeds_initialized)
for(var/typepath in starting_seeds)
var/amount = starting_seeds[typepath]
if(isnull(amount)) amount = 1
for (var/i = 1 to amount)
for(var/i = 1 to amount)
var/O = new typepath
add(O)
for(var/typepath in contraband_seeds)
@@ -239,251 +231,153 @@
add(O, 1)
seeds_initialized = 1
var/dat = "<center><h1>Seed storage contents</h1></center>"
if (piles.len == 0)
dat += "<font color='red'>No seeds</font>"
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "SeedStorage", name)
ui.open()
/obj/machinery/seed_storage/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
if(smart)
scanner = list("stats", "produce", "soil", "temperature", "light", "pressure")
else
dat += "<table style='text-align:center;border-style:solid;border-width:1px;padding:4px'><tr><td>Name</td>"
dat += "<td>Variety</td>"
if ("stats" in scanner)
dat += "<td>E</td><td>Y</td><td>M</td><td>Pr</td><td>Pt</td><td>Harvest</td>"
scanner = initial(scanner)
data["scanner"] = scanner
var/list/piles_to_check = piles
if(hacked || emagged)
piles_to_check = piles + piles_contra
var/list/seeds = list()
for(var/datum/seed_pile/S in piles_to_check)
var/datum/seed/seed = S.seed_type
if(!seed)
continue
var/list/seedinfo = list(
"name" = seed.seed_name,
"uid" = seed.uid,
"amount" = S.amount,
"id" = S.ID,
)
seedinfo["traits"] = list()
if("stats" in scanner)
seedinfo["traits"]["Endurance"] = seed.get_trait(TRAIT_ENDURANCE)
seedinfo["traits"]["Yield"] = seed.get_trait(TRAIT_YIELD)
seedinfo["traits"]["Production"] = seed.get_trait(TRAIT_PRODUCTION)
seedinfo["traits"]["Potency"] = seed.get_trait(TRAIT_POTENCY)
seedinfo["traits"]["Repeat Harvest"] = seed.get_trait(TRAIT_HARVEST_REPEAT)
if("temperature" in scanner)
seedinfo["traits"]["Ideal Heat"] = seed.get_trait(TRAIT_IDEAL_HEAT)
if("light" in scanner)
seedinfo["traits"]["Ideal Light"] = seed.get_trait(TRAIT_IDEAL_LIGHT)
if("soil" in scanner)
if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS))
if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05)
seedinfo["traits"]["Nutrient Consumption"] = "Low"
else if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0.2)
seedinfo["traits"]["Nutrient Consumption"] = "High"
else
seedinfo["traits"]["Nutrient Consumption"] = "Norm"
else
seedinfo["traits"]["Nutrient Consumption"] = "No"
if(seed.get_trait(TRAIT_REQUIRES_WATER))
if(seed.get_trait(TRAIT_WATER_CONSUMPTION) < 1)
seedinfo["traits"]["Water Consumption"] = "Low"
else if(seed.get_trait(TRAIT_WATER_CONSUMPTION) > 5)
seedinfo["traits"]["Water Consumption"] = "High"
else
seedinfo["traits"]["Water Consumption"] = "Norm"
else
seedinfo["traits"]["Water Consumption"] = "No"
seedinfo["traits"]["notes"] = ""
switch(seed.get_trait(TRAIT_CARNIVOROUS))
if(1)
seedinfo["traits"]["notes"] += "CARN "
if(2)
seedinfo["traits"]["notes"] += "FASTCARN"
switch(seed.get_trait(TRAIT_SPREAD))
if(1)
seedinfo["traits"]["notes"] += "VINE "
if(2)
seedinfo["traits"]["notes"] += "FASTVINE"
if ("pressure" in scanner)
if(seed.get_trait(TRAIT_LOWKPA_TOLERANCE) < 20)
seedinfo["traits"]["notes"] += "LP "
if(seed.get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220)
seedinfo["traits"]["notes"] += "HP "
if ("temperature" in scanner)
dat += "<td>Temp</td>"
if(seed.get_trait(TRAIT_HEAT_TOLERANCE) > 30)
seedinfo["traits"]["notes"] += "TEMRES "
else if(seed.get_trait(TRAIT_HEAT_TOLERANCE) < 10)
seedinfo["traits"]["notes"] += "TEMSEN "
if ("light" in scanner)
dat += "<td>Light</td>"
if ("soil" in scanner)
dat += "<td>Nutri</td><td>Water</td>"
dat += "<td>Notes</td><td>Amount</td><td></td></tr>"
for (var/datum/seed_pile/S in piles)
var/datum/seed/seed = S.seed_type
if(!seed)
continue
dat += "<tr>"
dat += "<td>[seed.seed_name]</td>"
dat += "<td>#[seed.uid]</td>"
if ("stats" in scanner)
dat += "<td>[seed.get_trait(TRAIT_ENDURANCE)]</td><td>[seed.get_trait(TRAIT_YIELD)]</td><td>[seed.get_trait(TRAIT_MATURATION)]</td><td>[seed.get_trait(TRAIT_PRODUCTION)]</td><td>[seed.get_trait(TRAIT_POTENCY)]</td>"
if(seed.get_trait(TRAIT_HARVEST_REPEAT))
dat += "<td>Multiple</td>"
else
dat += "<td>Single</td>"
if ("temperature" in scanner)
dat += "<td>[seed.get_trait(TRAIT_IDEAL_HEAT)] K</td>"
if ("light" in scanner)
dat += "<td>[seed.get_trait(TRAIT_IDEAL_LIGHT)] L</td>"
if ("soil" in scanner)
if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS))
if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05)
dat += "<td>Low</td>"
else if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0.2)
dat += "<td>High</td>"
else
dat += "<td>Norm</td>"
else
dat += "<td>No</td>"
if(seed.get_trait(TRAIT_REQUIRES_WATER))
if(seed.get_trait(TRAIT_WATER_CONSUMPTION) < 1)
dat += "<td>Low</td>"
else if(seed.get_trait(TRAIT_WATER_CONSUMPTION) > 5)
dat += "<td>High</td>"
else
dat += "<td>Norm</td>"
else
dat += "<td>No</td>"
if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) > 10)
seedinfo["traits"]["notes"] += "LIGRES "
else if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) < 3)
seedinfo["traits"]["notes"] += "LIGSEN "
if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) < 3)
seedinfo["traits"]["notes"] += "TOXSEN "
else if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) > 6)
seedinfo["traits"]["notes"] += "TOXRES "
if(seed.get_trait(TRAIT_PEST_TOLERANCE) < 3)
seedinfo["traits"]["notes"] += "PESTSEN "
else if(seed.get_trait(TRAIT_PEST_TOLERANCE) > 6)
seedinfo["traits"]["notes"] += "PESTRES "
if(seed.get_trait(TRAIT_WEED_TOLERANCE) < 3)
seedinfo["traits"]["notes"] += "WEEDSEN "
else if(seed.get_trait(TRAIT_WEED_TOLERANCE) > 6)
seedinfo["traits"]["notes"] += "WEEDRES "
if(seed.get_trait(TRAIT_PARASITE))
seedinfo["traits"]["notes"] += "PAR "
if ("temperature" in scanner)
if(seed.get_trait(TRAIT_ALTER_TEMP) > 0)
seedinfo["traits"]["notes"] += "TEMP+ "
if(seed.get_trait(TRAIT_ALTER_TEMP) < 0)
seedinfo["traits"]["notes"] += "TEMP- "
if(seed.get_trait(TRAIT_BIOLUM))
seedinfo["traits"]["notes"] += "LUM "
dat += "<td>"
switch(seed.get_trait(TRAIT_CARNIVOROUS))
if(1)
dat += "CARN "
if(2)
dat += "<font color='red'>CARN </font>"
switch(seed.get_trait(TRAIT_SPREAD))
if(1)
dat += "VINE "
if(2)
dat += "<font color='red'>VINE </font>"
if ("pressure" in scanner)
if(seed.get_trait(TRAIT_LOWKPA_TOLERANCE) < 20)
dat += "LP "
if(seed.get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220)
dat += "HP "
if ("temperature" in scanner)
if(seed.get_trait(TRAIT_HEAT_TOLERANCE) > 30)
dat += "TEMRES "
else if(seed.get_trait(TRAIT_HEAT_TOLERANCE) < 10)
dat += "TEMSEN "
if ("light" in scanner)
if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) > 10)
dat += "LIGRES "
else if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) < 3)
dat += "LIGSEN "
if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) < 3)
dat += "TOXSEN "
else if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) > 6)
dat += "TOXRES "
if(seed.get_trait(TRAIT_PEST_TOLERANCE) < 3)
dat += "PESTSEN "
else if(seed.get_trait(TRAIT_PEST_TOLERANCE) > 6)
dat += "PESTRES "
if(seed.get_trait(TRAIT_WEED_TOLERANCE) < 3)
dat += "WEEDSEN "
else if(seed.get_trait(TRAIT_WEED_TOLERANCE) > 6)
dat += "WEEDRES "
if(seed.get_trait(TRAIT_PARASITE))
dat += "PAR "
if ("temperature" in scanner)
if(seed.get_trait(TRAIT_ALTER_TEMP) > 0)
dat += "TEMP+ "
if(seed.get_trait(TRAIT_ALTER_TEMP) < 0)
dat += "TEMP- "
if(seed.get_trait(TRAIT_BIOLUM))
dat += "LUM "
dat += "</td>"
dat += "<td>[S.amount]</td>"
dat += "<td><a href='byond://?src=\ref[src];task=vend;id=[S.ID]'>Vend</a> <a href='byond://?src=\ref[src];task=purge;id=[S.ID]'>Purge</a></td>"
dat += "</tr>"
if(hacked || emagged)
for (var/datum/seed_pile/S in piles_contra)
var/datum/seed/seed = S.seed_type
if(!seed)
continue
dat += "<tr>"
dat += "<td>[seed.seed_name]</td>"
dat += "<td>#[seed.uid]</td>"
if ("stats" in scanner)
dat += "<td>[seed.get_trait(TRAIT_ENDURANCE)]</td><td>[seed.get_trait(TRAIT_YIELD)]</td><td>[seed.get_trait(TRAIT_MATURATION)]</td><td>[seed.get_trait(TRAIT_PRODUCTION)]</td><td>[seed.get_trait(TRAIT_POTENCY)]</td>"
if(seed.get_trait(TRAIT_HARVEST_REPEAT))
dat += "<td>Multiple</td>"
else
dat += "<td>Single</td>"
if ("temperature" in scanner)
dat += "<td>[seed.get_trait(TRAIT_IDEAL_HEAT)] K</td>"
if ("light" in scanner)
dat += "<td>[seed.get_trait(TRAIT_IDEAL_LIGHT)] L</td>"
if ("soil" in scanner)
if(seed.get_trait(TRAIT_REQUIRES_NUTRIENTS))
if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05)
dat += "<td>Low</td>"
else if(seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0.2)
dat += "<td>High</td>"
else
dat += "<td>Norm</td>"
else
dat += "<td>No</td>"
if(seed.get_trait(TRAIT_REQUIRES_WATER))
if(seed.get_trait(TRAIT_WATER_CONSUMPTION) < 1)
dat += "<td>Low</td>"
else if(seed.get_trait(TRAIT_WATER_CONSUMPTION) > 5)
dat += "<td>High</td>"
else
dat += "<td>Norm</td>"
else
dat += "<td>No</td>"
seeds.Add(list(seedinfo))
dat += "<td>"
switch(seed.get_trait(TRAIT_CARNIVOROUS))
if(1)
dat += "CARN "
if(2)
dat += "<font color='red'>CARN </font>"
switch(seed.get_trait(TRAIT_SPREAD))
if(1)
dat += "VINE "
if(2)
dat += "<font color='red'>VINE </font>"
if ("pressure" in scanner)
if(seed.get_trait(TRAIT_LOWKPA_TOLERANCE) < 20)
dat += "LP "
if(seed.get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220)
dat += "HP "
if ("temperature" in scanner)
if(seed.get_trait(TRAIT_HEAT_TOLERANCE) > 30)
dat += "TEMRES "
else if(seed.get_trait(TRAIT_HEAT_TOLERANCE) < 10)
dat += "TEMSEN "
if ("light" in scanner)
if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) > 10)
dat += "LIGRES "
else if(seed.get_trait(TRAIT_LIGHT_TOLERANCE) < 3)
dat += "LIGSEN "
if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) < 3)
dat += "TOXSEN "
else if(seed.get_trait(TRAIT_TOXINS_TOLERANCE) > 6)
dat += "TOXRES "
if(seed.get_trait(TRAIT_PEST_TOLERANCE) < 3)
dat += "PESTSEN "
else if(seed.get_trait(TRAIT_PEST_TOLERANCE) > 6)
dat += "PESTRES "
if(seed.get_trait(TRAIT_WEED_TOLERANCE) < 3)
dat += "WEEDSEN "
else if(seed.get_trait(TRAIT_WEED_TOLERANCE) > 6)
dat += "WEEDRES "
if(seed.get_trait(TRAIT_PARASITE))
dat += "PAR "
if ("temperature" in scanner)
if(seed.get_trait(TRAIT_ALTER_TEMP) > 0)
dat += "TEMP+ "
if(seed.get_trait(TRAIT_ALTER_TEMP) < 0)
dat += "TEMP- "
if(seed.get_trait(TRAIT_BIOLUM))
dat += "LUM "
dat += "</td>"
dat += "<td>[S.amount]</td>"
dat += "<td><a href='byond://?src=\ref[src];task=vend;id=[S.ID]'>Vend</a> <a href='byond://?src=\ref[src];task=purge;id=[S.ID]'>Purge</a></td>"
dat += "</tr>"
dat += "</table>"
data["seeds"] = seeds
user << browse(dat, "window=seedstorage")
onclose(user, "seedstorage")
return data
/obj/machinery/seed_storage/Topic(var/href, var/list/href_list)
if (..())
return
var/task = href_list["task"]
var/ID = text2num(href_list["id"])
/obj/machinery/seed_storage/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
var/ID = text2num(params["id"])
for (var/datum/seed_pile/N in piles)
if (N.ID == ID)
if (task == "vend")
var/list/piles_to_check = piles
if(hacked || emagged)
piles_to_check = piles + piles_contra
for(var/datum/seed_pile/N in piles_to_check)
if(N.ID == ID)
if(action == "vend")
var/obj/O = pick(N.seeds)
if (O)
if(O)
--N.amount
N.seeds -= O
if (N.amount <= 0 || N.seeds.len <= 0)
if(N.amount <= 0 || N.seeds.len <= 0)
piles -= N
qdel(N)
O.loc = src.loc
else
piles -= N
qdel(N)
else if (task == "purge")
for (var/obj/O in N.seeds)
return TRUE
else if(action == "purge")
for(var/obj/O in N.seeds)
qdel(O)
piles -= N
qdel(N)
return TRUE
break
if(hacked || emagged)
for (var/datum/seed_pile/N in piles_contra)
if (N.ID == ID)
if (task == "vend")
var/obj/O = pick(N.seeds)
if (O)
--N.amount
N.seeds -= O
if (N.amount <= 0 || N.seeds.len <= 0)
piles_contra -= N
qdel(N)
O.loc = src.loc
else
piles_contra -= N
qdel(N)
else if (task == "purge")
for (var/obj/O in N.seeds)
qdel(O)
piles_contra -= N
qdel(N)
break
updateUsrDialog()
/obj/machinery/seed_storage/attackby(var/obj/item/O as obj, var/mob/user as mob)
if (istype(O, /obj/item/seeds) && !lockdown)
@@ -12,7 +12,7 @@
if(turfs.len) //Pick a turf to spawn at if we can
var/turf/simulated/floor/T = pick(turfs)
var/datum/seed/seed = plant_controller.create_random_seed(1)
var/datum/seed/seed = SSplants.create_random_seed(1)
seed.set_trait(TRAIT_SPREAD,2) // So it will function properly as vines.
seed.set_trait(TRAIT_POTENCY,rand(potency_min, potency_max)) // 70-100 potency will help guarantee a wide spread and powerful effects.
seed.set_trait(TRAIT_MATURATION,rand(maturation_min, maturation_max))
@@ -74,9 +74,9 @@
/obj/effect/plant/Destroy()
if(seed.get_trait(TRAIT_SPREAD)==2)
unsense_proximity(callback = .HasProximity, center = get_turf(src))
plant_controller.remove_plant(src)
SSplants.remove_plant(src)
for(var/obj/effect/plant/neighbor in range(1,src))
plant_controller.add_plant(neighbor)
SSplants.add_plant(neighbor)
return ..()
/obj/effect/plant/single
@@ -90,15 +90,15 @@
else
parent = newparent
if(!plant_controller)
if(!SSplants)
sleep(250) // ugly hack, should mean roundstart plants are fine. TODO initialize perhaps?
if(!plant_controller)
if(!SSplants)
to_world("<span class='danger'>Plant controller does not exist and [src] requires it. Aborting.</span>")
qdel(src)
return
if(!istype(newseed))
newseed = plant_controller.seeds[DEFAULT_SEED]
newseed = SSplants.seeds[DEFAULT_SEED]
seed = newseed
if(!seed)
qdel(src)
@@ -135,7 +135,7 @@
/obj/effect/plant/proc/finish_spreading()
set_dir(calc_dir())
update_icon()
plant_controller.add_plant(src)
SSplants.add_plant(src)
//Some plants eat through plating.
if(islist(seed.chems) && !isnull(seed.chems["pacid"]))
var/turf/T = get_turf(src)
@@ -240,7 +240,7 @@
/obj/effect/plant/attackby(var/obj/item/weapon/W, var/mob/user)
user.setClickCooldown(user.get_attack_speed(W))
plant_controller.add_plant(src)
SSplants.add_plant(src)
if(W.is_wirecutter() || istype(W, /obj/item/weapon/surgical/scalpel))
if(sampled)
@@ -33,7 +33,7 @@
neighbors |= floor
if(neighbors.len)
plant_controller.add_plant(src) //if we have neighbours again, start processing
SSplants.add_plant(src) //if we have neighbours again, start processing
// Update all of our friends.
var/turf/T = get_turf(src)
@@ -110,7 +110,7 @@
// We shouldn't have spawned if the controller doesn't exist.
check_health()
if(has_buckled_mobs() || neighbors.len)
plant_controller.add_plant(src)
SSplants.add_plant(src)
//spreading vines aren't created on their final turf.
//Instead, they are created at their parent and then move to their destination.
@@ -160,7 +160,7 @@
continue
for(var/obj/effect/plant/neighbor in check_turf.contents)
neighbor.neighbors |= check_turf
plant_controller.add_plant(neighbor)
SSplants.add_plant(neighbor)
spawn(1) if(src) qdel(src)
#undef NEIGHBOR_REFRESH_TIME
+4 -4
View File
@@ -366,7 +366,7 @@
//Remove the seed if something is already planted.
if(seed) seed = null
seed = plant_controller.seeds[pick(list("reishi","nettle","amanita","mushrooms","plumphelmet","towercap","harebells","weeds"))]
seed = SSplants.seeds[pick(list("reishi","nettle","amanita","mushrooms","plumphelmet","towercap","harebells","weeds"))]
if(!seed) return //Weed does not exist, someone fucked up.
dead = 0
@@ -396,7 +396,7 @@
// We need to make sure we're not modifying one of the global seed datums.
// If it's not in the global list, then no products of the line have been
// harvested yet and it's safe to assume it's restricted to this tray.
if(!isnull(plant_controller.seeds[seed.name]))
if(!isnull(SSplants.seeds[seed.name]))
seed = seed.diverge()
seed.mutate(severity,get_turf(src))
@@ -452,8 +452,8 @@
var/previous_plant = seed.display_name
var/newseed = seed.get_mutant_variant()
if(newseed in plant_controller.seeds)
seed = plant_controller.seeds[newseed]
if(newseed in SSplants.seeds)
seed = SSplants.seeds[newseed]
else
return
+177 -125
View File
@@ -16,42 +16,50 @@
icon = 'icons/obj/device.dmi'
icon_state = "hydro"
item_state = "analyzer"
var/form_title
var/last_data
var/datum/seed/last_seed
var/list/last_reagents
/obj/item/device/analyzer/plant_analyzer/proc/print_report_verb()
set name = "Print Plant Report"
set category = "Object"
set src = usr
/obj/item/device/analyzer/plant_analyzer/attack_self(mob/user)
tgui_interact(user)
if(usr.stat || usr.restrained() || usr.lying)
return
print_report(usr)
/obj/item/device/analyzer/plant_analyzer/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "PlantAnalyzer", name)
ui.open()
/obj/item/device/analyzer/plant_analyzer/tgui_state(mob/user)
return GLOB.tgui_inventory_state
/obj/item/device/analyzer/plant_analyzer/Topic(href, href_list)
/obj/item/device/analyzer/plant_analyzer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/datum/seed/grown_seed = locate(last_seed)
if(!istype(grown_seed))
return list("no_seed" = TRUE)
data["no_seed"] = FALSE
data["seed"] = grown_seed.get_tgui_analyzer_data(user)
data["reagents"] = last_reagents
return data
/obj/item/device/analyzer/plant_analyzer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
if(href_list["print"])
print_report(usr)
/obj/item/device/analyzer/plant_analyzer/proc/print_report(var/mob/living/user)
if(!last_data)
to_chat(user, "There is no scan data to print.")
return
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src))
P.name = "paper - [form_title]"
P.info = "[last_data]"
if(istype(user,/mob/living/carbon/human))
user.put_in_hands(P)
user.visible_message("\The [src] spits out a piece of paper.")
return
/obj/item/device/analyzer/plant_analyzer/attack_self(mob/user as mob)
print_report(user)
return 0
return TRUE
switch(action)
if("print")
print_report(usr)
return TRUE
if("close")
last_seed = null
last_reagents = null
return TRUE
/obj/item/device/analyzer/plant_analyzer/afterattack(obj/target, mob/user, flag)
if(!flag) return
if(!flag)
return
var/datum/seed/grown_seed
var/datum/reagents/grown_reagents
@@ -60,13 +68,13 @@
else if(istype(target,/obj/item/weapon/reagent_containers/food/snacks/grown))
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = target
grown_seed = plant_controller.seeds[G.plantname]
grown_seed = SSplants.seeds[G.plantname]
grown_reagents = G.reagents
else if(istype(target,/obj/item/weapon/grown))
var/obj/item/weapon/grown/G = target
grown_seed = plant_controller.seeds[G.plantname]
grown_seed = SSplants.seeds[G.plantname]
grown_reagents = G.reagents
else if(istype(target,/obj/item/seeds))
@@ -87,12 +95,38 @@
to_chat(user, "<span class='danger'>[src] can tell you nothing about \the [target].</span>")
return
form_title = "[grown_seed.seed_name] (#[grown_seed.uid])"
var/dat = "<h3>Plant data for [form_title]</h3>"
last_seed = REF(grown_seed)
user.visible_message("<span class='notice'>[user] runs the scanner over \the [target].</span>")
dat += "<h2>General Data</h2>"
last_reagents = list()
if(grown_reagents && grown_reagents.reagent_list && grown_reagents.reagent_list.len)
for(var/datum/reagent/R in grown_reagents.reagent_list)
last_reagents.Add(list(list(
"name" = R.name,
"volume" = grown_reagents.get_reagent_amount(R.id),
)))
tgui_interact(user)
/obj/item/device/analyzer/plant_analyzer/proc/print_report_verb()
set name = "Print Plant Report"
set category = "Object"
set src = usr
if(usr.stat || usr.restrained() || usr.lying)
return
print_report(usr)
/obj/item/device/analyzer/plant_analyzer/proc/print_report(var/mob/living/user)
var/datum/seed/grown_seed = locate(last_seed)
if(!istype(grown_seed))
to_chat(user, "<span class='warning'>There is no scan data to print.</span>")
return
var/form_title = "[grown_seed.seed_name] (#[grown_seed.uid])"
var/dat = "<h3>Plant data for [form_title]</h3>"
dat += "<h2>General Data</h2>"
dat += "<table>"
dat += "<tr><td><b>Endurance</b></td><td>[grown_seed.get_trait(TRAIT_ENDURANCE)]</td></tr>"
dat += "<tr><td><b>Yield</b></td><td>[grown_seed.get_trait(TRAIT_YIELD)]</td></tr>"
@@ -101,138 +135,156 @@
dat += "<tr><td><b>Potency</b></td><td>[grown_seed.get_trait(TRAIT_POTENCY)]</td></tr>"
dat += "</table>"
if(grown_reagents && grown_reagents.reagent_list && grown_reagents.reagent_list.len)
if(LAZYLEN(last_reagents))
dat += "<h2>Reagent Data</h2>"
dat += "<br>This sample contains: "
for(var/datum/reagent/R in grown_reagents.reagent_list)
dat += "<br>- [R.name], [grown_reagents.get_reagent_amount(R.id)] unit(s)"
for(var/i in 1 to LAZYLEN(last_reagents))
dat += "<br>- [last_reagents[i]["name"]], [last_reagents[i]["volume"]] unit(s)"
dat += "<h2>Other Data</h2>"
if(grown_seed.get_trait(TRAIT_HARVEST_REPEAT))
dat += "This plant can be harvested repeatedly.<br>"
var/list/tgui_data = grown_seed.get_tgui_analyzer_data()
if(grown_seed.get_trait(TRAIT_IMMUTABLE) == -1)
dat += "This plant is highly mutable.<br>"
else if(grown_seed.get_trait(TRAIT_IMMUTABLE) > 0)
dat += "This plant does not possess genetics that are alterable.<br>"
dat += jointext(tgui_data["trait_info"], "<br>\n")
if(grown_seed.get_trait(TRAIT_REQUIRES_NUTRIENTS))
if(grown_seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05)
dat += "It consumes a small amount of nutrient fluid.<br>"
else if(grown_seed.get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0.2)
dat += "It requires a heavy supply of nutrient fluid.<br>"
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper(get_turf(src))
P.name = "paper - [form_title]"
P.info = "[dat]"
if(istype(user,/mob/living/carbon/human))
user.put_in_hands(P)
user.visible_message("\The [src] spits out a piece of paper.")
return
/datum/seed/proc/get_tgui_analyzer_data(mob/user)
var/list/data = list()
data["name"] = seed_name
data["uid"] = uid
data["endurance"] = get_trait(TRAIT_ENDURANCE)
data["yield"] = get_trait(TRAIT_YIELD)
data["maturation_time"] = get_trait(TRAIT_MATURATION)
data["production_time"] = get_trait(TRAIT_PRODUCTION)
data["potency"] = get_trait(TRAIT_POTENCY)
data["trait_info"] = list()
if(get_trait(TRAIT_HARVEST_REPEAT))
data["trait_info"] += "This plant can be harvested repeatedly."
if(get_trait(TRAIT_IMMUTABLE) == -1)
data["trait_info"] += "This plant is highly mutable."
else if(get_trait(TRAIT_IMMUTABLE) > 0)
data["trait_info"] += "This plant does not possess genetics that are alterable."
if(get_trait(TRAIT_REQUIRES_NUTRIENTS))
if(get_trait(TRAIT_NUTRIENT_CONSUMPTION) < 0.05)
data["trait_info"] += "It consumes a small amount of nutrient fluid."
else if(get_trait(TRAIT_NUTRIENT_CONSUMPTION) > 0.2)
data["trait_info"] += "It requires a heavy supply of nutrient fluid."
else
dat += "It requires a supply of nutrient fluid.<br>"
data["trait_info"] += "It requires a supply of nutrient fluid."
if(grown_seed.get_trait(TRAIT_REQUIRES_WATER))
if(grown_seed.get_trait(TRAIT_WATER_CONSUMPTION) < 1)
dat += "It requires very little water.<br>"
else if(grown_seed.get_trait(TRAIT_WATER_CONSUMPTION) > 5)
dat += "It requires a large amount of water.<br>"
if(get_trait(TRAIT_REQUIRES_WATER))
if(get_trait(TRAIT_WATER_CONSUMPTION) < 1)
data["trait_info"] += "It requires very little water."
else if(get_trait(TRAIT_WATER_CONSUMPTION) > 5)
data["trait_info"] += "It requires a large amount of water."
else
dat += "It requires a stable supply of water.<br>"
data["trait_info"] += "It requires a stable supply of water."
if(grown_seed.mutants && grown_seed.mutants.len)
dat += "It exhibits a high degree of potential subspecies shift.<br>"
if(mutants && mutants.len)
data["trait_info"] += "It exhibits a high degree of potential subspecies shift."
dat += "It thrives in a temperature of [grown_seed.get_trait(TRAIT_IDEAL_HEAT)] Kelvin."
data["trait_info"] += "It thrives in a temperature of [get_trait(TRAIT_IDEAL_HEAT)] Kelvin."
if(grown_seed.get_trait(TRAIT_LOWKPA_TOLERANCE) < 20)
dat += "<br>It is well adapted to low pressure levels."
if(grown_seed.get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220)
dat += "<br>It is well adapted to high pressure levels."
if(get_trait(TRAIT_LOWKPA_TOLERANCE) < 20)
data["trait_info"] += "It is well adapted to low pressure levels."
if(get_trait(TRAIT_HIGHKPA_TOLERANCE) > 220)
data["trait_info"] += "It is well adapted to high pressure levels."
if(grown_seed.get_trait(TRAIT_HEAT_TOLERANCE) > 30)
dat += "<br>It is well adapted to a range of temperatures."
else if(grown_seed.get_trait(TRAIT_HEAT_TOLERANCE) < 10)
dat += "<br>It is very sensitive to temperature shifts."
if(get_trait(TRAIT_HEAT_TOLERANCE) > 30)
data["trait_info"] += "It is well adapted to a range of temperatures."
else if(get_trait(TRAIT_HEAT_TOLERANCE) < 10)
data["trait_info"] += "It is very sensitive to temperature shifts."
dat += "<br>It thrives in a light level of [grown_seed.get_trait(TRAIT_IDEAL_LIGHT)] lumen[grown_seed.get_trait(TRAIT_IDEAL_LIGHT) == 1 ? "" : "s"]."
data["trait_info"] += "It thrives in a light level of [get_trait(TRAIT_IDEAL_LIGHT)] lumen[get_trait(TRAIT_IDEAL_LIGHT) == 1 ? "" : "s"]."
if(grown_seed.get_trait(TRAIT_LIGHT_TOLERANCE) > 10)
dat += "<br>It is well adapted to a range of light levels."
else if(grown_seed.get_trait(TRAIT_LIGHT_TOLERANCE) < 3)
dat += "<br>It is very sensitive to light level shifts."
if(get_trait(TRAIT_LIGHT_TOLERANCE) > 10)
data["trait_info"] += "It is well adapted to a range of light levels."
else if(get_trait(TRAIT_LIGHT_TOLERANCE) < 3)
data["trait_info"] += "It is very sensitive to light level shifts."
if(grown_seed.get_trait(TRAIT_TOXINS_TOLERANCE) < 3)
dat += "<br>It is highly sensitive to toxins."
else if(grown_seed.get_trait(TRAIT_TOXINS_TOLERANCE) > 6)
dat += "<br>It is remarkably resistant to toxins."
if(get_trait(TRAIT_TOXINS_TOLERANCE) < 3)
data["trait_info"] += "It is highly sensitive to toxins."
else if(get_trait(TRAIT_TOXINS_TOLERANCE) > 6)
data["trait_info"] += "It is remarkably resistant to toxins."
if(grown_seed.get_trait(TRAIT_PEST_TOLERANCE) < 3)
dat += "<br>It is highly sensitive to pests."
else if(grown_seed.get_trait(TRAIT_PEST_TOLERANCE) > 6)
dat += "<br>It is remarkably resistant to pests."
if(get_trait(TRAIT_PEST_TOLERANCE) < 3)
data["trait_info"] += "It is highly sensitive to pests."
else if(get_trait(TRAIT_PEST_TOLERANCE) > 6)
data["trait_info"] += "It is remarkably resistant to pests."
if(grown_seed.get_trait(TRAIT_WEED_TOLERANCE) < 3)
dat += "<br>It is highly sensitive to weeds."
else if(grown_seed.get_trait(TRAIT_WEED_TOLERANCE) > 6)
dat += "<br>It is remarkably resistant to weeds."
if(get_trait(TRAIT_WEED_TOLERANCE) < 3)
data["trait_info"] += "It is highly sensitive to weeds."
else if(get_trait(TRAIT_WEED_TOLERANCE) > 6)
data["trait_info"] += "It is remarkably resistant to weeds."
switch(grown_seed.get_trait(TRAIT_SPREAD))
switch(get_trait(TRAIT_SPREAD))
if(1)
dat += "<br>It is able to be planted outside of a tray."
data["trait_info"] += "It is able to be planted outside of a tray."
if(2)
dat += "<br>It is a robust and vigorous vine that will spread rapidly."
data["trait_info"] += "It is a robust and vigorous vine that will spread rapidly."
switch(grown_seed.get_trait(TRAIT_CARNIVOROUS))
switch(get_trait(TRAIT_CARNIVOROUS))
if(1)
dat += "<br>It is carnivorous and will eat tray pests for sustenance."
data["trait_info"] += "It is carnivorous and will eat tray pests for sustenance."
if(2)
dat += "<br>It is carnivorous and poses a significant threat to living things around it."
data["trait_info"] += "It is carnivorous and poses a significant threat to living things around it."
if(grown_seed.get_trait(TRAIT_PARASITE))
dat += "<br>It is capable of parisitizing and gaining sustenance from tray weeds."
if(get_trait(TRAIT_PARASITE))
data["trait_info"] += "It is capable of parisitizing and gaining sustenance from tray weeds."
/*
There's currently no code that actually changes the temperature of the local environment, so let's not show it until there is.
if(grown_seed.get_trait(TRAIT_ALTER_TEMP))
dat += "<br>It will periodically alter the local temperature by [grown_seed.get_trait(TRAIT_ALTER_TEMP)] degrees Kelvin."
if(get_trait(TRAIT_ALTER_TEMP))
data["trait_info"] += "It will periodically alter the local temperature by [get_trait(TRAIT_ALTER_TEMP)] degrees Kelvin."
*/
if(grown_seed.get_trait(TRAIT_BIOLUM))
dat += "<br>It is [grown_seed.get_trait(TRAIT_BIOLUM_COLOUR) ? "<font color='[grown_seed.get_trait(TRAIT_BIOLUM_COLOUR)]'>bio-luminescent</font>" : "bio-luminescent"]."
if(get_trait(TRAIT_BIOLUM))
data["trait_info"] += "It is [get_trait(TRAIT_BIOLUM_COLOUR) ? "<font color='[get_trait(TRAIT_BIOLUM_COLOUR)]'>bio-luminescent</font>" : "bio-luminescent"]."
if(grown_seed.get_trait(TRAIT_PRODUCES_POWER))
dat += "<br>The fruit will function as a battery if prepared appropriately."
if(get_trait(TRAIT_PRODUCES_POWER))
data["trait_info"] += "The fruit will function as a battery if prepared appropriately."
if(grown_seed.get_trait(TRAIT_STINGS))
dat += "<br>The fruit is covered in stinging spines."
if(get_trait(TRAIT_STINGS))
data["trait_info"] += "The fruit is covered in stinging spines."
if(grown_seed.get_trait(TRAIT_JUICY) == 1)
dat += "<br>The fruit is soft-skinned and juicy."
else if(grown_seed.get_trait(TRAIT_JUICY) == 2)
dat += "<br>The fruit is excessively juicy."
if(get_trait(TRAIT_JUICY) == 1)
data["trait_info"] += "The fruit is soft-skinned and juicy."
else if(get_trait(TRAIT_JUICY) == 2)
data["trait_info"] += "The fruit is excessively juicy."
if(grown_seed.get_trait(TRAIT_EXPLOSIVE))
dat += "<br>The fruit is internally unstable."
if(get_trait(TRAIT_EXPLOSIVE))
data["trait_info"] += "The fruit is internally unstable."
if(grown_seed.get_trait(TRAIT_TELEPORTING))
dat += "<br>The fruit is temporal/spatially unstable."
if(get_trait(TRAIT_TELEPORTING))
data["trait_info"] += "The fruit is temporal/spatially unstable."
if(grown_seed.exude_gasses && grown_seed.exude_gasses.len)
for(var/gas in grown_seed.exude_gasses)
if(exude_gasses && exude_gasses.len)
for(var/gas in exude_gasses)
var/amount = ""
if (grown_seed.exude_gasses[gas] > 7)
if (exude_gasses[gas] > 7)
amount = "large amounts of "
else if (grown_seed.exude_gasses[gas] < 5)
else if (exude_gasses[gas] < 5)
amount = "small amounts of "
dat += "<br>It will release [amount][gas_data.name[gas]] into the environment."
data["trait_info"] += "It will release [amount][gas_data.name[gas]] into the environment."
if(grown_seed.consume_gasses && grown_seed.consume_gasses.len)
for(var/gas in grown_seed.consume_gasses)
if(consume_gasses && consume_gasses.len)
for(var/gas in consume_gasses)
var/amount = ""
if (grown_seed.consume_gasses[gas] > 7)
if (consume_gasses[gas] > 7)
amount = "large amounts of "
else if (grown_seed.consume_gasses[gas] < 5)
else if (consume_gasses[gas] < 5)
amount = "small amounts of "
dat += "<br>It will consume [amount][gas_data.name[gas]] from the environment."
data["trait_info"] += "It will consume [amount][gas_data.name[gas]] from the environment."
if(dat)
last_data = dat
dat += "<br><br>\[<a href='?src=\ref[src];print=1'>print report</a>\]"
user << browse(dat,"window=plant_analyzer")
return
return data
@@ -35,7 +35,7 @@
if(dead)
var/ikey = "[seed.get_trait(TRAIT_PLANT_ICON)]-dead"
var/image/dead_overlay = plant_controller.plant_icon_cache["[ikey]"]
var/image/dead_overlay = SSplants.plant_icon_cache["[ikey]"]
if(!dead_overlay)
dead_overlay = image('icons/obj/hydroponics_growing.dmi', "[ikey]")
dead_overlay.color = DEAD_PLANT_COLOUR
@@ -55,23 +55,23 @@
maturation = 1
overlay_stage = maturation ? max(1,round(age/maturation)) : 1
var/ikey = "[seed.get_trait(TRAIT_PLANT_ICON)]-[overlay_stage]"
var/image/plant_overlay = plant_controller.plant_icon_cache["[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"]
var/image/plant_overlay = SSplants.plant_icon_cache["[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"]
if(frozen == 1)
plant_overlay = image('icons/obj/hydroponics_growing.dmi', "[ikey]")
plant_overlay.color = FROZEN_PLANT_COLOUR
if(!plant_overlay)
plant_overlay = image('icons/obj/hydroponics_growing.dmi', "[ikey]")
plant_overlay.color = seed.get_trait(TRAIT_PLANT_COLOUR)
plant_controller.plant_icon_cache["[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"] = plant_overlay
SSplants.plant_icon_cache["[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"] = plant_overlay
add_overlay(plant_overlay)
if(harvest && overlay_stage == seed.growth_stages)
ikey = "[seed.get_trait(TRAIT_PRODUCT_ICON)]"
var/image/harvest_overlay = plant_controller.plant_icon_cache["product-[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"]
var/image/harvest_overlay = SSplants.plant_icon_cache["product-[ikey]-[seed.get_trait(TRAIT_PLANT_COLOUR)]"]
if(!harvest_overlay)
harvest_overlay = image('icons/obj/hydroponics_products.dmi', "[ikey]")
harvest_overlay.color = seed.get_trait(TRAIT_PRODUCT_COLOUR)
plant_controller.plant_icon_cache["product-[ikey]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]"] = harvest_overlay
SSplants.plant_icon_cache["product-[ikey]-[seed.get_trait(TRAIT_PRODUCT_COLOUR)]"] = harvest_overlay
add_overlay(harvest_overlay)
@@ -47,87 +47,125 @@
IC.power_fail()
/obj/item/device/electronic_assembly/proc/resolve_nano_host()
return src
/obj/item/device/electronic_assembly/proc/check_interactivity(mob/user)
if(!CanInteract(user, physical_state))
return 0
return 1
return tgui_status(user, GLOB.tgui_physical_state) == STATUS_INTERACTIVE
/obj/item/device/electronic_assembly/get_cell()
return battery
/obj/item/device/electronic_assembly/interact(mob/user)
if(!check_interactivity(user))
return
// TGUI
/obj/item/device/electronic_assembly/tgui_state(mob/user)
return GLOB.tgui_physical_state
/obj/item/device/electronic_assembly/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ICAssembly", name, parent_ui)
ui.open()
/obj/item/device/electronic_assembly/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
var/total_parts = 0
var/total_complexity = 0
for(var/obj/item/integrated_circuit/part in contents)
total_parts += part.size
total_complexity = total_complexity + part.complexity
var/HTML = list()
HTML += "<html><head><title>[src.name]</title></head><body>"
HTML += "<br><a href='?src=\ref[src]'>\[Refresh\]</a> | "
HTML += "<a href='?src=\ref[src];rename=1'>\[Rename\]</a><br>"
HTML += "[total_parts]/[max_components] ([round((total_parts / max_components) * 100, 0.1)]%) space taken up in the assembly.<br>"
HTML += "[total_complexity]/[max_complexity] ([round((total_complexity / max_complexity) * 100, 0.1)]%) maximum complexity.<br>"
if(battery)
HTML += "[round(battery.charge, 0.1)]/[battery.maxcharge] ([round(battery.percent(), 0.1)]%) cell charge. <a href='?src=\ref[src];remove_cell=1'>\[Remove\]</a><br>"
HTML += "Net energy: [format_SI(net_power / CELLRATE, "W")]."
else
HTML += "<span class='danger'>No powercell detected!</span>"
HTML += "<br><br>"
HTML += "Components:<hr>"
HTML += "Built in:<br>"
data["total_parts"] = total_parts
data["max_components"] = max_components
data["total_complexity"] = total_complexity
data["max_complexity"] = max_complexity
data["battery_charge"] = round(battery?.charge, 0.1)
data["battery_max"] = round(battery?.maxcharge, 0.1)
data["net_power"] = net_power / CELLRATE
//Put removable circuits in separate categories from non-removable
// This works because lists are always passed by reference in BYOND, so modifying unremovable_circuits
// after setting data["unremovable_circuits"] = unremovable_circuits also modifies data["unremovable_circuits"]
// Same for the removable one
var/list/unremovable_circuits = list()
data["unremovable_circuits"] = unremovable_circuits
var/list/removable_circuits = list()
data["removable_circuits"] = removable_circuits
for(var/obj/item/integrated_circuit/circuit in contents)
if(!circuit.removable)
HTML += "<a href=?src=\ref[circuit];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
HTML += "<a href=?src=\ref[circuit];rename=1;from_assembly=1>\[Rename\]</a> | "
HTML += "<a href=?src=\ref[circuit];scan=1;from_assembly=1>\[Scan with Debugger\]</a> | "
HTML += "<a href=?src=\ref[circuit];bottom=\ref[circuit];from_assembly=1>\[Move to Bottom\]</a>"
HTML += "<br>"
var/list/target = circuit.removable ? removable_circuits : unremovable_circuits
target.Add(list(list(
"name" = circuit.displayed_name,
"ref" = REF(circuit),
)))
HTML += "<hr>"
HTML += "Removable:<br>"
return data
for(var/obj/item/integrated_circuit/circuit in contents)
if(circuit.removable)
HTML += "<a href=?src=\ref[circuit];examine=1;from_assembly=1>[circuit.displayed_name]</a> | "
HTML += "<a href=?src=\ref[circuit];rename=1;from_assembly=1>\[Rename\]</a> | "
HTML += "<a href=?src=\ref[circuit];scan=1;from_assembly=1>\[Scan with Debugger\]</a> | "
HTML += "<a href=?src=\ref[circuit];remove=1;from_assembly=1>\[Remove\]</a> | "
HTML += "<a href=?src=\ref[circuit];bottom=\ref[circuit];from_assembly=1>\[Move to Bottom\]</a>"
HTML += "<br>"
HTML += "</body></html>"
user << browse(jointext(HTML,null), "window=assembly-\ref[src];size=600x350;border=1;can_resize=1;can_close=1;can_minimize=1")
/obj/item/device/electronic_assembly/Topic(href, href_list[])
/obj/item/device/electronic_assembly/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
return TRUE
if(href_list["rename"])
rename(usr)
var/obj/held_item = usr.get_active_hand()
if(href_list["remove_cell"])
if(!battery)
to_chat(usr, "<span class='warning'>There's no power cell to remove from \the [src].</span>")
else
switch(action)
// Actual assembly actions
if("rename")
rename(usr)
return TRUE
if("remove_cell")
if(!battery)
to_chat(usr, "<span class='warning'>There's no power cell to remove from \the [src].</span>")
return FALSE
var/turf/T = get_turf(src)
battery.forceMove(T)
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pull \the [battery] out of \the [src]'s power supplier.</span>")
battery = null
return TRUE
interact(usr) // To refresh the UI.
// Circuit actions
if("open_circuit")
var/obj/item/integrated_circuit/C = locate(params["ref"]) in contents
if(!istype(C))
return
C.tgui_interact(usr, null, ui)
return TRUE
if("rename_circuit")
var/obj/item/integrated_circuit/C = locate(params["ref"]) in contents
if(!istype(C))
return
C.rename_component(usr)
return TRUE
if("scan_circuit")
var/obj/item/integrated_circuit/C = locate(params["ref"]) in contents
if(!istype(C))
return
if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/D = held_item
if(D.accepting_refs)
D.afterattack(C, usr, TRUE)
else
to_chat(usr, "<span class='warning'>The Debugger's 'ref scanner' needs to be on.</span>")
else
to_chat(usr, "<span class='warning'>You need a multitool/debugger set to 'ref' mode to do that.</span>")
return TRUE
if("remove_circuit")
var/obj/item/integrated_circuit/C = locate(params["ref"]) in contents
if(!istype(C))
return
C.remove(usr)
return TRUE
if("bottom_circuit")
var/obj/item/integrated_circuit/C = locate(params["ref"]) in contents
if(!istype(C))
return
// Puts it at the bottom of our contents
// Note, this intentionally does *not* use forceMove, because forceMove will stop if it detects the same loc
C.loc = null
C.loc = src
return FALSE
// End TGUI
/obj/item/device/electronic_assembly/verb/rename()
set name = "Rename Circuit"
@@ -177,7 +215,7 @@
for(var/obj/item/integrated_circuit/IC in contents)
. += IC.external_examine(user)
if(opened)
interact(user)
tgui_interact(user)
/obj/item/device/electronic_assembly/proc/get_part_complexity()
. = 0
@@ -249,7 +287,7 @@
if(add_circuit(I, user))
to_chat(user, "<span class='notice'>You slide \the [I] inside \the [src].</span>")
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
interact(user)
tgui_interact(user)
return TRUE
else if(I.is_crowbar())
@@ -261,7 +299,7 @@
else if(istype(I, /obj/item/device/integrated_electronics/wirer) || istype(I, /obj/item/device/integrated_electronics/debugger) || I.is_screwdriver())
if(opened)
interact(user)
tgui_interact(user)
return TRUE
else
to_chat(user, "<span class='warning'>\The [src] isn't opened, so you can't fiddle with the internal components. \
@@ -286,7 +324,7 @@
battery = cell
playsound(src, 'sound/items/Deconstruct.ogg', 50, 1)
to_chat(user, "<span class='notice'>You slot \the [cell] inside \the [src]'s power supplier.</span>")
interact(user)
tgui_interact(user)
return TRUE
else
@@ -296,7 +334,7 @@
if(!check_interactivity(user))
return
if(opened)
interact(user)
tgui_interact(user)
var/list/input_selection = list()
var/list/available_inputs = list()
@@ -12,11 +12,8 @@
max_complexity = IC_COMPLEXITY_BASE
var/obj/item/clothing/clothing = null
/obj/item/device/electronic_assembly/clothing/nano_host()
return clothing
/obj/item/device/electronic_assembly/clothing/resolve_nano_host()
return clothing
/obj/item/device/electronic_assembly/clothing/tgui_host()
return clothing.tgui_host()
/obj/item/device/electronic_assembly/clothing/update_icon()
..()
@@ -10,11 +10,8 @@
max_complexity = IC_COMPLEXITY_BASE / 2
var/obj/item/weapon/implant/integrated_circuit/implant = null
/obj/item/device/electronic_assembly/implant/nano_host()
return implant
/obj/item/device/electronic_assembly/implant/resolve_nano_host()
return implant
/obj/item/device/electronic_assembly/implant/tgui_host()
return implant.tgui_host()
/obj/item/device/electronic_assembly/implant/update_icon()
..()
@@ -7,7 +7,7 @@
w_class = ITEMSIZE_SMALL
var/detail_color = COLOR_ASSEMBLY_WHITE
var/list/color_list = list(
"black" = COLOR_ASSEMBLY_BLACK,
"dark gray" = COLOR_ASSEMBLY_BLACK,
"machine gray" = COLOR_ASSEMBLY_BGRAY,
"white" = COLOR_ASSEMBLY_WHITE,
"red" = COLOR_ASSEMBLY_RED,
@@ -35,11 +35,42 @@
detail_overlay.color = detail_color
add_overlay(detail_overlay)
/obj/item/device/integrated_electronics/detailer/tgui_state(mob/user)
return GLOB.tgui_inventory_state
/obj/item/device/integrated_electronics/detailer/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ICDetailer", name)
ui.open()
/obj/item/device/integrated_electronics/detailer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["detail_color"] = detail_color
data["color_list"] = color_list
return data
/obj/item/device/integrated_electronics/detailer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("change_color")
if(!(params["color"] in color_list))
return // to prevent href exploits causing runtimes
detail_color = color_list[params["color"]]
update_icon()
return TRUE
/obj/item/device/integrated_electronics/detailer/attack_self(mob/user)
var/color_choice = input(user, "Select color.", "Assembly Detailer", detail_color) as null|anything in color_list
if(!color_list[color_choice])
return
if(!in_range(src, user))
return
detail_color = color_list[color_choice]
update_icon()
tgui_interact(user)
// Leaving this commented out in case someone decides that this would be better as an "any color" selection system
// Just uncomment this and get rid of all of the TGUI bullshit lol
// if(!in_range(user, src))
// return
// var/new_color = input(user, "Pick a color", "Color Selection", detail_color) as color|null
// if(!new_color)
// return
// detail_color = new_color
// update_icon()
@@ -6,7 +6,7 @@ a creative player the means to solve many problems. Circuits are held inside an
/obj/item/integrated_circuit/examine(mob/user)
. = ..()
. += external_examine(user)
interact(user)
tgui_interact(user)
// This should be used when someone is examining while the case is opened.
/obj/item/integrated_circuit/proc/internal_examine(mob/user)
@@ -22,7 +22,7 @@ a creative player the means to solve many problems. Circuits are held inside an
if(A.linked.len)
. += "The '[A]' is connected to [A.get_linked_to_desc()]."
. += any_examine(user)
interact(user)
tgui_interact(user)
// This should be used when someone is examining from an 'outside' perspective, e.g. reading a screen or LED.
/obj/item/integrated_circuit/proc/external_examine(mob/user)
@@ -52,22 +52,12 @@ a creative player the means to solve many problems. Circuits are held inside an
qdel(A)
. = ..()
/obj/item/integrated_circuit/nano_host()
if(istype(src.loc, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/assembly = loc
return assembly.resolve_nano_host()
return ..()
/obj/item/integrated_circuit/emp_act(severity)
for(var/datum/integrated_io/io in inputs + outputs + activators)
io.scramble()
/obj/item/integrated_circuit/proc/check_interactivity(mob/user)
if(assembly)
return assembly.check_interactivity(user)
else if(!CanInteract(user, physical_state))
return 0
return 1
return tgui_status(user, GLOB.tgui_physical_state) == STATUS_INTERACTIVE
/obj/item/integrated_circuit/verb/rename_component()
set name = "Rename Circuit"
@@ -83,274 +73,169 @@ a creative player the means to solve many problems. Circuits are held inside an
to_chat(M, "<span class='notice'>The circuit '[src.name]' is now labeled '[input]'.</span>")
displayed_name = input
/obj/item/integrated_circuit/interact(mob/user)
if(!check_interactivity(user))
return
// if(!assembly)
// return
/obj/item/integrated_circuit/tgui_state(mob/user)
return GLOB.tgui_physical_state
var/window_height = 350
var/window_width = 600
/obj/item/integrated_circuit/tgui_host(mob/user)
if(istype(loc, /obj/item/device/electronic_assembly))
return loc.tgui_host()
return ..()
//var/table_edge_width = "[(window_width - window_width * 0.1) / 4]px"
//var/table_middle_width = "[(window_width - window_width * 0.1) - (table_edge_width * 2)]px"
var/table_edge_width = "30%"
var/table_middle_width = "40%"
/obj/item/integrated_circuit/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ICCircuit", name, parent_ui)
ui.open()
var/HTML = list()
HTML += "<html><head><title>[src.displayed_name]</title></head><body>"
HTML += "<div align='center'>"
HTML += "<table border='1' style='undefined;table-layout: fixed; width: 80%'>"
/obj/item/integrated_circuit/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
HTML += "<br><a href='?src=\ref[src];return=1'>\[Return to Assembly\]</a>"
data["name"] = name
data["desc"] = desc
data["displayed_name"] = displayed_name
data["removable"] = removable
HTML += "<br><a href='?src=\ref[src];'>\[Refresh\]</a> | "
HTML += "<a href='?src=\ref[src];rename=1'>\[Rename\]</a> | "
HTML += "<a href='?src=\ref[src];scan=1'>\[Scan with Device\]</a> | "
if(src.removable)
HTML += "<a href='?src=\ref[src];remove=1'>\[Remove\]</a><br>"
data["complexity"] = complexity
data["power_draw_idle"] = power_draw_idle
data["power_draw_per_use"] = power_draw_per_use
data["extended_desc"] = extended_desc
HTML += "<colgroup>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "<col style='width: [table_middle_width]'>"
HTML += "<col style='width: [table_edge_width]'>"
HTML += "</colgroup>"
data["inputs"] = list()
for(var/datum/integrated_io/io in inputs)
data["inputs"].Add(list(tgui_pin_data(io)))
var/column_width = 3
var/row_height = max(inputs.len, outputs.len, 1)
data["outputs"] = list()
for(var/datum/integrated_io/io in outputs)
data["outputs"].Add(list(tgui_pin_data(io)))
for(var/i = 1 to row_height)
HTML += "<tr>"
for(var/j = 1 to column_width)
var/datum/integrated_io/io = null
var/words = list()
var/height = 1
switch(j)
if(1)
io = get_pin_ref(IC_INPUT, i)
if(io)
words += "<b><a href=?src=\ref[src];pin_name=1;pin=\ref[io]>[io.display_pin_type()] [io.name]</a> <a href=?src=\ref[src];pin_data=1;pin=\ref[io]>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/datum/integrated_io/linked in io.linked)
// words += "<a href=?src=\ref[linked.holder];pin_name=1;pin=\ref[linked];link=\ref[io]>\[[linked.name]\]</a>
words += "<a href=?src=\ref[src];pin_unwire=1;pin=\ref[io];link=\ref[linked]>[linked.name]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder.displayed_name]</a><br>"
data["activators"] = list()
for(var/datum/integrated_io/io in activators)
var/list/activator = list(
"ref" = REF(io),
"name" = io.name,
"pulse_out" = io.data,
"linked" = list()
)
for(var/datum/integrated_io/linked in io.linked)
activator["linked"].Add(list(list(
"ref" = REF(linked),
"name" = linked.name,
"holder_ref" = REF(linked.holder),
"holder_name" = linked.holder.displayed_name,
)))
if(outputs.len > inputs.len)
height = 1
if(2)
if(i == 1)
words += "[src.displayed_name]<br>[src.name != src.displayed_name ? "([src.name])":""]<hr>[src.desc]"
height = row_height
else
continue
if(3)
io = get_pin_ref(IC_OUTPUT, i)
if(io)
words += "<b><a href=?src=\ref[src];pin_name=1;pin=\ref[io]>[io.display_pin_type()] [io.name]</a> <a href=?src=\ref[src];pin_data=1;pin=\ref[io]>[io.display_data(io.data)]</a></b><br>"
if(io.linked.len)
for(var/datum/integrated_io/linked in io.linked)
// words += "<a href=?src=\ref[linked.holder];pin_name=1;pin=\ref[linked];link=\ref[io]>\[[linked.name]\]</a>
words += "<a href=?src=\ref[src];pin_unwire=1;pin=\ref[io];link=\ref[linked]>[linked.name]</a> \
@ <a href=?src=\ref[linked.holder];examine=1;>[linked.holder.displayed_name]</a><br>"
data["activators"].Add(list(activator))
if(inputs.len > outputs.len)
height = 1
HTML += "<td align='center' rowspan='[height]'>[jointext(words, null)]</td>"
HTML += "</tr>"
return data
for(var/activator in activators)
var/datum/integrated_io/io = activator
var/words = list()
/obj/item/integrated_circuit/proc/tgui_pin_data(datum/integrated_io/io)
if(!istype(io))
return list()
var/list/pindata = list()
pindata["type"] = io.display_pin_type()
pindata["name"] = io.name
pindata["data"] = io.display_data(io.data)
pindata["ref"] = REF(io)
pindata["linked"] = list()
for(var/datum/integrated_io/linked in io.linked)
pindata["linked"].Add(list(list(
"ref" = REF(linked),
"name" = linked.name,
"holder_ref" = REF(linked.holder),
"holder_name" = linked.holder.displayed_name,
)))
return pindata
words += "<b><a href=?src=\ref[src];pin_name=1;pin=\ref[io]><font color='FF0000'>[io.name]</font></a> <a href=?src=\ref[src];pin_data=1;pin=\ref[io]><font color='FF0000'>[io.data?"\<PULSE OUT\>":"\<PULSE IN\>"]</font></a></b><br>"
if(io.linked.len)
for(var/datum/integrated_io/linked in io.linked)
// words += "<a href=?src=\ref[linked.holder];pin_name=1;pin=\ref[linked];link=\ref[io]>\[[linked.name]\]</a>
words += "<a href=?src=\ref[src];pin_unwire=1;pin=\ref[io];link=\ref[linked]><font color='FF0000'>[linked.name]</font></a> \
@ <a href=?src=\ref[linked.holder];examine=1;><font color='FF0000'>[linked.holder.displayed_name]</font></a><br>"
HTML += "<tr>"
HTML += "<td colspan='3' align='center'>[jointext(words, null)]</td>"
HTML += "</tr>"
HTML += "</table>"
HTML += "</div>"
// HTML += "<br><font color='33CC33'>Meta Variables;</font>" // If more meta vars get introduced, uncomment this.
// HTML += "<br>"
HTML += "<br><font color='0000AA'>Complexity: [complexity]</font>"
if(power_draw_idle)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_idle] W (Idle)</font>"
if(power_draw_per_use)
HTML += "<br><font color='0000AA'>Power Draw: [power_draw_per_use] W (Active)</font>" // Borgcode says that powercells' checked_use() takes joules as input.
HTML += "<br><font color='0000AA'>[extended_desc]</font>"
HTML += "</body></html>"
if(src.assembly)
user << browse(jointext(HTML, null), "window=assembly-\ref[src.assembly];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
else
user << browse(jointext(HTML, null), "window=circuit-\ref[src];size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
onclose(user, "assembly-\ref[src.assembly]")
/obj/item/integrated_circuit/Topic(href, href_list, state = interactive_state)
if(!check_interactivity(usr))
return
/obj/item/integrated_circuit/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
return TRUE
var/update = 1
var/obj/item/device/electronic_assembly/A = src.assembly
var/update_to_assembly = 0
var/datum/integrated_io/pin = locate(href_list["pin"]) in inputs + outputs + activators
var/datum/integrated_io/pin = locate(params["pin"]) in inputs + outputs + activators
var/datum/integrated_io/linked = null
if(href_list["link"])
linked = locate(href_list["link"]) in pin.linked
if(params["link"])
linked = locate(params["link"]) in pin.linked
var/obj/held_item = usr.get_active_hand()
if(href_list["rename"])
rename_component(usr)
if(href_list["from_assembly"])
update = 0
var/obj/item/device/electronic_assembly/ea = loc
if(istype(ea))
ea.interact(usr)
if(href_list["pin_name"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = 1
else
var/obj/item/device/multitool/M = held_item
M.wire(pin,usr)
if(href_list["pin_data"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = 1
else
var/datum/integrated_io/io = pin
io.ask_for_pin_data(usr, held_item) // The pins themselves will determine how to ask for data, and will validate the data.
/*
if(io.io_type == DATA_CHANNEL)
var/type_to_use = input("Please choose a type to use.","[src] type setting") as null|anything in list("string","number", "null")
if(!check_interactivity(usr))
return
var/new_data = null
switch(type_to_use)
if("string")
new_data = input("Now type in a string.","[src] string writing") as null|text
to_chat(usr, "<span class='notice'>You input [new_data] into the pin.</span>")
//to_chat(user, "<span class='notice'>You write '[new_data]' to the '[io]' pin of \the [io.holder].</span>")
if("number")
new_data = input("Now type in a number.","[src] number writing") as null|num
if(isnum(new_data) && check_interactivity(usr) )
to_chat(usr, "<span class='notice'>You input [new_data] into the pin.</span>")
if("null")
if(check_interactivity(usr))
to_chat(usr, "<span class='notice'>You clear the pin's memory.</span>")
io.write_data_to_pin(new_data)
else if(io.io_type == PULSE_CHANNEL)
io.holder.check_then_do_work(ignore_power = TRUE)
to_chat(usr, "<span class='notice'>You pulse \the [io.holder]'s [io] pin.</span>")
*/
if(href_list["pin_unwire"])
if (!istype(held_item, /obj/item/device/multitool) || !allow_multitool)
href_list["wire"] = 1
else
var/obj/item/device/multitool/M = held_item
M.unwire(pin, linked, usr)
if(href_list["wire"])
if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
if(linked)
wirer.wire(linked, usr)
else if(pin)
wirer.wire(pin, usr)
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
if(pin)
debugger.write_data(pin, usr)
else
to_chat(usr, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
if(href_list["examine"])
var/obj/item/integrated_circuit/examined
if(href_list["examined"])
examined = href_list["examined"]
else
examined = src
examined.interact(usr)
update = 0
if(href_list["bottom"])
var/obj/item/integrated_circuit/circuit = locate(href_list["bottom"]) in src.assembly.contents
var/assy = circuit.assembly
if(!circuit)
. = TRUE
switch(action)
if("rename")
rename_component(usr)
return
circuit.loc = null
circuit.loc = assy
. = 1
update_to_assembly = 1
if(href_list["scan"])
if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/D = held_item
if(D.accepting_refs)
D.afterattack(src, usr, TRUE)
if("wire", "pin_name", "pin_data", "pin_unwire")
if(istype(held_item, /obj/item/device/multitool) && allow_multitool)
var/obj/item/device/multitool/M = held_item
switch(action)
if("pin_name")
M.wire(pin, usr)
if("pin_data")
var/datum/integrated_io/io = pin
io.ask_for_pin_data(usr, held_item) // The pins themselves will determine how to ask for data, and will validate the data.
if("pin_unwire")
M.unwire(pin, linked, usr)
else if(istype(held_item, /obj/item/device/integrated_electronics/wirer))
var/obj/item/device/integrated_electronics/wirer/wirer = held_item
if(linked)
wirer.wire(linked, usr)
else if(pin)
wirer.wire(pin, usr)
else if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/debugger = held_item
if(pin)
debugger.write_data(pin, usr)
else
to_chat(usr, "<span class='warning'>The Debugger's 'ref scanner' needs to be on.</span>")
else
to_chat(usr, "<span class='warning'>You need a multitool/debugger set to 'ref' mode to do that.</span>")
if(href_list["return"])
if(A)
update_to_assembly = 1
usr << browse(null, "window=circuit-\ref[src];border=1;can_resize=1;can_close=1;can_minimize=1")
else
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
if(href_list["remove"])
if(!A)
to_chat(usr, "<span class='warning'>This circuit is not in an assembly!</span>")
to_chat(usr, "<span class='warning'>You can't do a whole lot without the proper tools.</span>")
return
if(!removable)
to_chat(usr, "<span class='warning'>\The [src] seems to be permanently attached to the case.</span>")
return
var/obj/item/device/electronic_assembly/ea = loc
power_fail()
disconnect_all()
var/turf/T = get_turf(src)
forceMove(T)
assembly = null
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(usr, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
if(istype(ea))
ea.interact(usr)
update = 0
if("scan")
if(istype(held_item, /obj/item/device/integrated_electronics/debugger))
var/obj/item/device/integrated_electronics/debugger/D = held_item
if(D.accepting_refs)
D.afterattack(src, usr, TRUE)
else
to_chat(usr, "<span class='warning'>The Debugger's 'ref scanner' needs to be on.</span>")
else
to_chat(usr, "<span class='warning'>You need a multitool/debugger set to 'ref' mode to do that.</span>")
return
if("examine")
var/obj/item/integrated_circuit/examined = locate(params["ref"])
if(istype(examined) && (examined.loc == loc))
if(ui.parent_ui)
examined.tgui_interact(usr, null, ui.parent_ui)
else
examined.tgui_interact(usr)
if("remove")
remove(usr)
return
return FALSE
/obj/item/integrated_circuit/proc/remove(mob/user)
var/obj/item/device/electronic_assembly/A = assembly
if(!A)
to_chat(user, "<span class='warning'>This circuit is not in an assembly!</span>")
return
if(!removable)
to_chat(user, "<span class='warning'>\The [src] seems to be permanently attached to the case.</span>")
return
var/obj/item/device/electronic_assembly/ea = loc
if(update)
if(A && istype(A) && update_to_assembly)
A.interact(usr)
else
interact(usr) // To refresh the UI.
power_fail()
disconnect_all()
var/turf/T = get_turf(src)
forceMove(T)
assembly = null
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
to_chat(user, "<span class='notice'>You pop \the [src] out of the case, and slide it out.</span>")
if(istype(ea))
ea.tgui_interact(user)
/obj/item/integrated_circuit/proc/push_data()
for(var/datum/integrated_io/O in outputs)
@@ -13,8 +13,8 @@
var/upgraded = FALSE // When hit with an upgrade disk, will turn true, allowing it to print the higher tier circuits.
var/can_clone = FALSE // Same for above, but will allow the printer to duplicate a specific assembly. (Not implemented)
// var/static/list/recipe_list = list()
var/current_category = null
var/obj/item/device/electronic_assembly/assembly_to_clone = null
var/obj/item/device/electronic_assembly/assembly_to_clone = null // Not implemented x3
var/dirty_items = FALSE
/obj/item/device/integrated_circuit_printer/upgraded
upgraded = TRUE
@@ -47,7 +47,7 @@
if(stack.use(max(1, round(num)))) // We don't want to create stacks that aren't whole numbers
to_chat(user, span("notice", "You add [num] sheet\s to \the [src]."))
metal += num * metal_per_sheet
interact(user)
attack_self(user)
return TRUE
if(istype(O,/obj/item/integrated_circuit))
@@ -55,7 +55,7 @@
user.unEquip(O)
metal = min(metal + O.w_class, max_metal)
qdel(O)
interact(user)
attack_self(user)
return TRUE
if(istype(O,/obj/item/weapon/disk/integrated_circuit/upgrade/advanced))
@@ -64,7 +64,8 @@
return TRUE
to_chat(user, span("notice", "You install \the [O] into \the [src]."))
upgraded = TRUE
interact(user)
dirty_items = TRUE
attack_self(user)
return TRUE
if(istype(O,/obj/item/weapon/disk/integrated_circuit/upgrade/clone))
@@ -73,98 +74,126 @@
return TRUE
to_chat(user, span("notice", "You install \the [O] into \the [src]."))
can_clone = TRUE
interact(user)
attack_self(user)
return TRUE
return ..()
/obj/item/device/integrated_circuit_printer/vv_edit_var(var_name, var_value)
// Gotta update the static data in case an admin VV's the upgraded var for some reason..!
if(var_name == "upgraded")
dirty_items = TRUE
return ..()
/obj/item/device/integrated_circuit_printer/attack_self(var/mob/user)
interact(user)
tgui_interact(user)
/obj/item/device/integrated_circuit_printer/interact(mob/user)
var/window_height = 600
var/window_width = 500
/obj/item/device/integrated_circuit_printer/tgui_state(mob/user)
return GLOB.tgui_inventory_state
if(isnull(current_category))
current_category = SScircuit.circuit_fabricator_recipe_list[1]
/obj/item/device/integrated_circuit_printer/tgui_interact(mob/user, datum/tgui/ui)
if(dirty_items)
update_tgui_static_data(user, ui)
dirty_items = FALSE
var/HTML = "<center><h2>Integrated Circuit Printer</h2></center><br>"
if(!debug)
HTML += "Metal: [metal/metal_per_sheet]/[max_metal/metal_per_sheet] sheets.<br>"
else
HTML += "Metal: INFINITY.<br>"
HTML += "Circuits available: [upgraded ? "Advanced":"Regular"].<br>"
HTML += "Assembly Cloning: [can_clone ? "Available": "Unavailable"].<br>"
if(assembly_to_clone)
HTML += "Assembly '[assembly_to_clone.name]' loaded.<br>"
HTML += "Crossed out circuits mean that the printer is not sufficentally upgraded to create that circuit.<br>"
HTML += "<hr>"
HTML += "Categories:"
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ICPrinter", name) // 500, 600
ui.open()
/obj/item/device/integrated_circuit_printer/tgui_static_data(mob/user)
var/list/data = ..()
var/list/categories = list()
for(var/category in SScircuit.circuit_fabricator_recipe_list)
if(category != current_category)
HTML += " <a href='?src=\ref[src];category=[category]'>\[[category]\]</a> "
else // Bold the button if it's already selected.
HTML += " <b>\[[category]\]</b> "
HTML += "<hr>"
HTML += "<center><h4>[current_category]</h4></center>"
var/list/cat_obj = list(
"name" = category,
"items" = list()
)
var/list/circuit_list = SScircuit.circuit_fabricator_recipe_list[category]
for(var/path in circuit_list)
var/obj/O = path
var/can_build = TRUE
if(ispath(path, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = path
if((initial(IC.spawn_flags) & IC_SPAWN_RESEARCH) && (!(initial(IC.spawn_flags) & IC_SPAWN_DEFAULT)) && !upgraded)
can_build = FALSE
var/list/current_list = SScircuit.circuit_fabricator_recipe_list[current_category]
for(var/path in current_list)
var/obj/O = path
var/can_build = TRUE
if(ispath(path, /obj/item/integrated_circuit))
var/obj/item/integrated_circuit/IC = path
if((initial(IC.spawn_flags) & IC_SPAWN_RESEARCH) && (!(initial(IC.spawn_flags) & IC_SPAWN_DEFAULT)) && !upgraded)
can_build = FALSE
if(can_build)
HTML += "<A href='?src=\ref[src];build=[path]'>\[[initial(O.name)]\]</A>: [initial(O.desc)]<br>"
else
HTML += "<s>\[[initial(O.name)]\]</s>: [initial(O.desc)]<br>"
var/cost = 1
if(ispath(path, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/E = path
cost = round((initial(E.max_complexity) + initial(E.max_components)) / 4)
else
var/obj/item/I = path
cost = initial(I.w_class)
user << browse(jointext(HTML, null), "window=integrated_printer;size=[window_width]x[window_height];border=1;can_resize=1;can_close=1;can_minimize=1")
cat_obj["items"].Add(list(list(
"name" = initial(O.name),
"desc" = initial(O.desc),
"can_build" = can_build,
"cost" = cost,
"path" = path,
)))
categories.Add(list(cat_obj))
data["categories"] = categories
return data
/obj/item/device/integrated_circuit_printer/Topic(href, href_list)
/obj/item/device/integrated_circuit_printer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["metal"] = metal
data["max_metal"] = max_metal
data["metal_per_sheet"] = metal_per_sheet
data["debug"] = debug
data["upgraded"] = upgraded
data["can_clone"] = can_clone
data["assembly_to_clone"] = assembly_to_clone
return data
/obj/item/device/integrated_circuit_printer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
return TRUE
add_fingerprint(usr)
if(href_list["category"])
current_category = href_list["category"]
if(href_list["build"])
var/build_type = text2path(href_list["build"])
if(!build_type || !ispath(build_type))
return 1
var/cost = 1
if(isnull(current_category))
current_category = SScircuit.circuit_fabricator_recipe_list[1]
if(ispath(build_type, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/E = build_type
cost = round( (initial(E.max_complexity) + initial(E.max_components) ) / 4)
else
var/obj/item/I = build_type
cost = initial(I.w_class)
if(!(build_type in SScircuit.circuit_fabricator_recipe_list[current_category]))
return
if(!debug)
if(!Adjacent(usr))
to_chat(usr, "<span class='notice'>You are too far away from \the [src].</span>")
if(metal - cost < 0)
to_chat(usr, "<span class='warning'>You need [cost] metal to build that!.</span>")
switch(action)
if("build")
var/build_type = text2path(params["build"])
if(!build_type || !ispath(build_type))
return 1
metal -= cost
var/obj/item/built = new build_type(get_turf(loc))
usr.put_in_hands(built)
to_chat(usr, "<span class='notice'>[capitalize(built.name)] printed.</span>")
playsound(src, 'sound/items/jaws_pry.ogg', 50, TRUE)
interact(usr)
var/cost = 1
if(ispath(build_type, /obj/item/device/electronic_assembly))
var/obj/item/device/electronic_assembly/E = build_type
cost = round( (initial(E.max_complexity) + initial(E.max_components) ) / 4)
else
var/obj/item/I = build_type
cost = initial(I.w_class)
var/in_some_category = FALSE
for(var/category in SScircuit.circuit_fabricator_recipe_list)
if(build_type in SScircuit.circuit_fabricator_recipe_list[category])
in_some_category = TRUE
break
if(!in_some_category)
return
if(!debug)
if(!Adjacent(usr))
to_chat(usr, "<span class='notice'>You are too far away from \the [src].</span>")
if(metal - cost < 0)
to_chat(usr, "<span class='warning'>You need [cost] metal to build that!.</span>")
return 1
metal -= cost
var/obj/item/built = new build_type(get_turf(loc))
usr.put_in_hands(built)
to_chat(usr, "<span class='notice'>[capitalize(built.name)] printed.</span>")
playsound(src, 'sound/items/jaws_pry.ogg', 50, TRUE)
return TRUE
// FUKKEN UPGRADE DISKS
/obj/item/weapon/disk/integrated_circuit/upgrade
+40 -31
View File
@@ -10,8 +10,8 @@
min_target_dist = 0
var/cleaning = 0
var/screwloose = 0
var/oddbutton = 0
var/wet_floors = 0
var/spray_blood = 0
var/blood = 1
var/list/target_types = list()
@@ -25,16 +25,16 @@
return ..()
/mob/living/bot/cleanbot/handleIdle()
if(!screwloose && !oddbutton && prob(2))
if(!wet_floors && !spray_blood && prob(2))
custom_emote(2, "makes an excited booping sound!")
playsound(src, 'sound/machines/synth_yes.ogg', 50, 0)
if(screwloose && prob(5)) // Make a mess
if(wet_floors && prob(5)) // Make a mess
if(istype(loc, /turf/simulated))
var/turf/simulated/T = loc
T.wet_floor()
if(oddbutton && prob(5)) // Make a big mess
if(spray_blood && prob(5)) // Make a big mess
visible_message("Something flies out of [src]. It seems to be acting oddly.")
var/obj/effect/decal/cleanable/blood/gibs/gib = new /obj/effect/decal/cleanable/blood/gibs(loc)
// TODO - I have a feeling weakrefs will not work in ignore_list, verify this ~Leshana
@@ -149,56 +149,65 @@
icon_state = "cleanbot[on]"
/mob/living/bot/cleanbot/attack_hand(var/mob/user)
var/dat
dat += "<TT><B>Automatic Station Cleaner v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];operation=start'>[on ? "On" : "Off"]</A><BR>"
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
dat += "Maintenance panel is [open ? "opened" : "closed"]"
if(!locked || issilicon(user))
dat += "<BR>Cleans Blood: <A href='?src=\ref[src];operation=blood'>[blood ? "Yes" : "No"]</A><BR>"
if(using_map.bot_patrolling)
dat += "<BR>Patrol station: <A href='?src=\ref[src];operation=patrol'>[will_patrol ? "Yes" : "No"]</A><BR>"
if(open && !locked)
dat += "Odd looking screw twiddled: <A href='?src=\ref[src];operation=screw'>[screwloose ? "Yes" : "No"]</A><BR>"
dat += "Weird button pressed: <A href='?src=\ref[src];operation=oddbutton'>[oddbutton ? "Yes" : "No"]</A>"
tgui_interact(user)
user << browse("<HEAD><TITLE>Cleaner v1.0 controls</TITLE></HEAD>[dat]", "window=autocleaner")
onclose(user, "autocleaner")
return
/mob/living/bot/cleanbot/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Cleanbot", name)
ui.open()
/mob/living/bot/cleanbot/Topic(href, href_list)
/mob/living/bot/cleanbot/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["on"] = on
data["open"] = open
data["locked"] = locked
data["blood"] = blood
data["patrol"] = will_patrol
data["wet_floors"] = wet_floors
data["spray_blood"] = spray_blood
data["version"] = "v2.0"
return data
/mob/living/bot/cleanbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
return TRUE
usr.set_machine(src)
add_fingerprint(usr)
switch(href_list["operation"])
switch(action)
if("start")
if(on)
turn_off()
else
turn_on()
. = TRUE
if("blood")
blood = !blood
get_targets()
. = TRUE
if("patrol")
will_patrol = !will_patrol
patrol_path = null
if("screw")
screwloose = !screwloose
. = TRUE
if("wet_floors")
wet_floors = !wet_floors
to_chat(usr, "<span class='notice'>You twiddle the screw.</span>")
if("oddbutton")
oddbutton = !oddbutton
. = TRUE
if("spray_blood")
spray_blood = !spray_blood
to_chat(usr, "<span class='notice'>You press the weird button.</span>")
attack_hand(usr)
. = TRUE
/mob/living/bot/cleanbot/emag_act(var/remaining_uses, var/mob/user)
. = ..()
if(!screwloose || !oddbutton)
if(!wet_floors || !spray_blood)
if(user)
to_chat(user, "<span class='notice'>The [src] buzzes and beeps.</span>")
playsound(src, 'sound/machines/buzzbeep.ogg', 50, 0)
oddbutton = 1
screwloose = 1
spray_blood = 1
wet_floors = 1
return 1
/mob/living/bot/cleanbot/proc/get_targets()
+16 -38
View File
@@ -71,53 +71,31 @@
qdel(src)
return
/mob/living/bot/cleanbot/edCLN/attack_hand(var/mob/user)
var/dat
usr.set_machine(src)
add_fingerprint(usr)
/mob/living/bot/cleanbot/edCLN/tgui_data(mob/user)
var/list/data = ..()
data["version"] = "v3.0"
data["rgbpanel"] = TRUE
data["red_switch"] = red_switch
data["green_switch"] = green_switch
data["blue_switch"] = blue_switch
return data
dat += "<TT><B>Automatic Station Cleaner v2.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];operation=start'>[on ? "On" : "Off"]</A><BR>"
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
dat += "Maintenance panel is [open ? "opened" : "closed"]"
if(!locked || issilicon(user))
dat += "<BR>Cleans Blood: <A href='?src=\ref[src];operation=blood'>[blood ? "Yes" : "No"]</A><BR>"
if(using_map.bot_patrolling)
dat += "<BR>Patrol station: <A href='?src=\ref[src];operation=patrol'>[will_patrol ? "Yes" : "No"]</A><BR>"
if(open && !locked)
dat += "<BR>Red Switch: <A href='?src=\ref[src];operation=red_switch'>[red_switch ? "On" : "Off"]</A><BR>"
dat += "<BR>Green Switch: <A href='?src=\ref[src];operation=green_switch'>[green_switch ? "On" : "Off"]</A><BR>"
dat += "<BR>Blue Switch: <A href='?src=\ref[src];operation=blue_switch'>[blue_switch ? "On" : "Off"]</A>"
user << browse("<HEAD><TITLE>Cleaner v2.0 controls</TITLE></HEAD>[dat]", "window=autocleaner")
onclose(user, "autocleaner")
return
/mob/living/bot/cleanbot/edCLN/Topic(href, href_list)
usr.set_machine(src)
add_fingerprint(usr)
switch(href_list["operation"])
if("start")
if(on)
turn_off()
else
turn_on()
if("blood")
blood = !blood
get_targets()
if("patrol")
will_patrol = !will_patrol
patrol_path = null
/mob/living/bot/cleanbot/edCLN/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("red_switch")
red_switch = !red_switch
to_chat(usr, "<span class='notice'>You flip the red switch [red_switch ? "on" : "off"].</span>")
. = TRUE
if("green_switch")
green_switch = !blue_switch
green_switch = !green_switch
to_chat(usr, "<span class='notice'>You flip the green switch [green_switch ? "on" : "off"].</span>")
. = TRUE
if("blue_switch")
blue_switch = !blue_switch
to_chat(usr, "<span class='notice'>You flip the blue switch [blue_switch ? "on" : "off"].</span>")
attack_hand(usr)
. = TRUE
/mob/living/bot/cleanbot/edCLN/emag_act(var/remaining_uses, var/mob/user)
. = ..()
+71 -54
View File
@@ -30,38 +30,45 @@
tank = newTank
tank.forceMove(src)
/mob/living/bot/farmbot/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Farmbot", name)
ui.open()
/mob/living/bot/farmbot/attack_hand(var/mob/user as mob)
/mob/living/bot/farmbot/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["on"] = on
data["tank"] = !!tank
if(tank)
data["tankVolume"] = tank.reagents.total_volume
data["tankMaxVolume"] = tank.reagents.maximum_volume
data["locked"] = locked
data["waters_trays"] = null
data["refills_water"] = null
data["uproots_weeds"] = null
data["replaces_nutriment"] = null
data["collects_produce"] = null
data["removes_dead"] = null
if(!locked)
data["waters_trays"] = waters_trays
data["refills_water"] = refills_water
data["uproots_weeds"] = uproots_weeds
data["replaces_nutriment"] = replaces_nutriment
data["collects_produce"] = collects_produce
data["removes_dead"] = removes_dead
return data
/mob/living/bot/farmbot/attack_hand(mob/user)
. = ..()
if(.)
return
var/dat = ""
dat += "<TT><B>Automatic Hyrdoponic Assisting Unit v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Water Tank: "
if (tank)
dat += "[tank.reagents.total_volume]/[tank.reagents.maximum_volume]"
else
dat += "Error: Watertank not found"
dat += "<br>Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
if(!locked)
dat += "<TT>Watering controls:<br>"
dat += "Water plants : <A href='?src=\ref[src];water=1'>[waters_trays ? "Yes" : "No"]</A><BR>"
dat += "Refill watertank : <A href='?src=\ref[src];refill=1'>[refills_water ? "Yes" : "No"]</A><BR>"
dat += "<br>Weeding controls:<br>"
dat += "Weed plants: <A href='?src=\ref[src];weed=1'>[uproots_weeds ? "Yes" : "No"]</A><BR>"
dat += "<br>Nutriment controls:<br>"
dat += "Replace fertilizer: <A href='?src=\ref[src];replacenutri=1'>[replaces_nutriment ? "Yes" : "No"]</A><BR>"
/* VOREStation Removal - No whole-job lag-bot automation.
dat += "<br>Plant controls:<br>"
dat += "Collect produce: <A href='?src=\ref[src];collect=1'>[collects_produce ? "Yes" : "No"]</A><BR>"
dat += "Remove dead plants: <A href='?src=\ref[src];removedead=1'>[removes_dead ? "Yes" : "No"]</A><BR>"
*/
dat += "</TT>"
user << browse("<HEAD><TITLE>Farmbot v1.0 controls</TITLE></HEAD>[dat]", "window=autofarm")
onclose(user, "autofarm")
return
tgui_interact(user)
/mob/living/bot/farmbot/emag_act(var/remaining_charges, var/mob/user)
. = ..()
@@ -73,35 +80,47 @@
emagged = 1
return 1
/mob/living/bot/farmbot/Topic(href, href_list)
/mob/living/bot/farmbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
usr.machine = src
return TRUE
add_fingerprint(usr)
if((href_list["power"]) && (access_scanner.allowed(usr)))
if(on)
turn_off()
else
turn_on()
switch(action)
if("power")
if(!access_scanner.allowed(usr))
return FALSE
if(on)
turn_off()
else
turn_on()
. = TRUE
if(locked)
return
return TRUE
if(href_list["water"])
waters_trays = !waters_trays
else if(href_list["refill"])
refills_water = !refills_water
else if(href_list["weed"])
uproots_weeds = !uproots_weeds
else if(href_list["replacenutri"])
replaces_nutriment = !replaces_nutriment
else if(href_list["collect"])
collects_produce = !collects_produce
else if(href_list["removedead"])
removes_dead = !removes_dead
switch(action)
if("water")
waters_trays = !waters_trays
. = TRUE
if("refill")
refills_water = !refills_water
. = TRUE
if("weed")
uproots_weeds = !uproots_weeds
. = TRUE
if("replacenutri")
replaces_nutriment = !replaces_nutriment
. = TRUE
// VOREStation Edit: No automatic hydroponics
// if("collect")
// collects_produce = !collects_produce
// . = TRUE
// if("removedead")
// removes_dead = !removes_dead
// . = TRUE
// VOREStation Edit End
attack_hand(usr)
return
/mob/living/bot/farmbot/update_icons()
if(on && action)
@@ -109,13 +128,10 @@
else
icon_state = "farmbot[on]"
/mob/living/bot/farmbot/handleRegular()
if(emagged && prob(1))
flick("farmbot_broke", src)
/mob/living/bot/farmbot/handleAdjacentTarget()
UnarmedAttack(target)
@@ -137,6 +153,7 @@
times_idle = 0 //VOREStation Add - Idle shutoff time
return
if(++times_idle == 150) turn_off() //VOREStation Add - Idle shutoff time
/mob/living/bot/farmbot/calcTargetPath() // We need to land NEXT to the tray, because the tray itself is impassable
for(var/trayDir in list(NORTH, SOUTH, EAST, WEST))
target_path = AStar(get_turf(loc), get_step(get_turf(target), trayDir), /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance, 0, max_target_dist, id = botcard)
+48 -40
View File
@@ -29,28 +29,38 @@
else
icon_state = "floorbot[on]e"
/mob/living/bot/floorbot/attack_hand(var/mob/user)
user.set_machine(src)
var/list/dat = list()
dat += "<TT><B>Automatic Station Floor Repairer v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];operation=start'>[src.on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel is [open ? "opened" : "closed"]<BR>"
dat += "Tiles left: [amount]<BR>"
dat += "Behvaiour controls are [locked ? "locked" : "unlocked"]<BR>"
/mob/living/bot/floorbot/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Floorbot", name)
ui.open()
/mob/living/bot/floorbot/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["on"] = on
data["open"] = open
data["locked"] = locked
data["amount"] = amount
data["possible_bmode"] = list("NORTH", "EAST", "SOUTH", "WEST")
data["improvefloors"] = null
data["eattiles"] = null
data["maketiles"] = null
data["bmode"] = null
if(!locked || issilicon(user))
dat += "Improves floors: <A href='?src=\ref[src];operation=improve'>[improvefloors ? "Yes" : "No"]</A><BR>"
dat += "Finds tiles: <A href='?src=\ref[src];operation=tiles'>[eattiles ? "Yes" : "No"]</A><BR>"
dat += "Make singles pieces of metal into tiles when empty: <A href='?src=\ref[src];operation=make'>[maketiles ? "Yes" : "No"]</A><BR>"
var/bmode
if(targetdirection)
bmode = dir2text(targetdirection)
else
bmode = "Disabled"
dat += "<BR><BR>Bridge Mode : <A href='?src=\ref[src];operation=bridgemode'>[bmode]</A><BR>"
var/datum/browser/popup = new(user, "autorepair", "Repairbot v1.1 controls")
popup.set_content(jointext(dat,null))
popup.open()
return
data["improvefloors"] = improvefloors
data["eattiles"] = eattiles
data["maketiles"] = maketiles
data["bmode"] = dir2text(targetdirection)
return data
/mob/living/bot/floorbot/attack_hand(var/mob/user)
tgui_interact(user)
/mob/living/bot/floorbot/emag_act(var/remaining_charges, var/mob/user)
. = ..()
@@ -61,38 +71,36 @@
playsound(src, 'sound/machines/buzzbeep.ogg', 50, 0)
return 1
/mob/living/bot/floorbot/Topic(href, href_list)
/mob/living/bot/floorbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
usr.set_machine(src)
return TRUE
add_fingerprint(usr)
switch(href_list["operation"])
switch(action)
if("start")
if (on)
if(on)
turn_off()
else
turn_on()
. = TRUE
if(locked && !issilicon(usr))
return
switch(action)
if("improve")
improvefloors = !improvefloors
. = TRUE
if("tiles")
eattiles = !eattiles
. = TRUE
if("make")
maketiles = !maketiles
. = TRUE
if("bridgemode")
switch(targetdirection)
if(null)
targetdirection = 1
if(1)
targetdirection = 2
if(2)
targetdirection = 4
if(4)
targetdirection = 8
if(8)
targetdirection = null
else
targetdirection = null
attack_hand(usr)
targetdirection = text2dir(params["dir"])
. = TRUE
/mob/living/bot/floorbot/handleRegular()
++tilemake
+72 -71
View File
@@ -8,6 +8,11 @@
#define MEDBOT_PANIC_ENDING 90
#define MEDBOT_PANIC_END 100
#define MEDBOT_MIN_INJECTION 5
#define MEDBOT_MAX_INJECTION 15
#define MEDBOT_MIN_HEAL 0.1
#define MEDBOT_MAX_HEAL 75
/mob/living/bot/medbot
name = "Medibot"
desc = "A little medical robot. He looks somewhat underwhelmed."
@@ -209,45 +214,39 @@
if(do_after(H, 3 SECONDS, target=src))
set_right(H)
else
interact(H)
tgui_interact(H)
/mob/living/bot/medbot/proc/interact(mob/user)
var/dat
dat += "<TT><B>Automatic Medical Unit v1.0</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Maintenance panel is [open ? "opened" : "closed"]<BR>"
dat += "Beaker: "
if (reagent_glass)
dat += "<A href='?src=\ref[src];eject=1'>Loaded \[[reagent_glass.reagents.total_volume]/[reagent_glass.reagents.maximum_volume]\]</a>"
else
dat += "None Loaded"
dat += "<br>Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
/mob/living/bot/medbot/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["on"] = on
data["open"] = open
data["beaker"] = FALSE
if(reagent_glass)
data["beaker"] = TRUE
data["beaker_total"] = reagent_glass.reagents.total_volume
data["beaker_max"] = reagent_glass.reagents.maximum_volume
data["locked"] = locked
data["heal_threshold"] = null
data["heal_threshold_max"] = MEDBOT_MAX_HEAL
data["injection_amount_min"] = MEDBOT_MIN_INJECTION
data["injection_amount"] = null
data["injection_amount_max"] = MEDBOT_MAX_INJECTION
data["use_beaker"] = null
data["declare_treatment"] = null
data["vocal"] = null
if(!locked || issilicon(user))
dat += "<TT>Healing Threshold: "
dat += "<a href='?src=\ref[src];adj_threshold=-10'>--</a> "
dat += "<a href='?src=\ref[src];adj_threshold=-5'>-</a> "
dat += "[heal_threshold] "
dat += "<a href='?src=\ref[src];adj_threshold=5'>+</a> "
dat += "<a href='?src=\ref[src];adj_threshold=10'>++</a>"
dat += "</TT><br>"
data["heal_threshold"] = heal_threshold
data["injection_amount"] = injection_amount
data["use_beaker"] = use_beaker
data["declare_treatment"] = declare_treatment
data["vocal"] = vocal
return data
dat += "<TT>Injection Level: "
dat += "<a href='?src=\ref[src];adj_inject=-5'>-</a> "
dat += "[injection_amount] "
dat += "<a href='?src=\ref[src];adj_inject=5'>+</a> "
dat += "</TT><br>"
dat += "Reagent Source: "
dat += "<a href='?src=\ref[src];use_beaker=1'>[use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]</a><br>"
dat += "Treatment report is [declare_treatment ? "on" : "off"]. <a href='?src=\ref[src];declaretreatment=[1]'>Toggle</a><br>"
dat += "The speaker switch is [vocal ? "on" : "off"]. <a href='?src=\ref[src];togglevoice=[1]'>Toggle</a><br>"
user << browse("<HEAD><TITLE>Medibot v1.0 controls</TITLE></HEAD>[dat]", "window=automed")
onclose(user, "automed")
return
/mob/living/bot/medbot/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Medbot", name)
ui.open()
/mob/living/bot/medbot/attackby(var/obj/item/O, var/mob/user)
if(istype(O, /obj/item/weapon/reagent_containers/glass))
@@ -266,51 +265,53 @@
else
..()
/mob/living/bot/medbot/Topic(href, href_list)
/mob/living/bot/medbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
return TRUE
usr.set_machine(src)
add_fingerprint(usr)
if ((href_list["power"]) && access_scanner.allowed(usr))
if (on)
turn_off()
else
turn_on()
. = TRUE
switch(action)
if("power")
if(!access_scanner.allowed(usr))
return FALSE
if(on)
turn_off()
else
turn_on()
else if((href_list["adj_threshold"]) && (!locked || issilicon(usr)))
var/adjust_num = text2num(href_list["adj_threshold"])
heal_threshold += adjust_num
if(heal_threshold <= 0)
heal_threshold = 0.1
if(heal_threshold > 75)
heal_threshold = 75
if(locked && !issilicon(usr))
return TRUE
else if((href_list["adj_inject"]) && (!locked || issilicon(usr)))
var/adjust_num = text2num(href_list["adj_inject"])
injection_amount += adjust_num
if(injection_amount < 5)
injection_amount = 5
if(injection_amount > 15)
injection_amount = 15
switch(action)
if("adj_threshold")
heal_threshold = clamp(text2num(params["val"]), MEDBOT_MIN_HEAL, MEDBOT_MAX_HEAL)
. = TRUE
else if((href_list["use_beaker"]) && (!locked || issilicon(usr)))
use_beaker = !use_beaker
if("adj_inject")
injection_amount = clamp(text2num(params["val"]), MEDBOT_MIN_INJECTION, MEDBOT_MAX_INJECTION)
. = TRUE
else if (href_list["eject"] && (!isnull(reagent_glass)))
if(!locked)
reagent_glass.loc = get_turf(src)
reagent_glass = null
else
to_chat(usr, "<span class='notice'>You cannot eject the beaker because the panel is locked.</span>")
if("use_beaker")
use_beaker = !use_beaker
. = TRUE
else if ((href_list["togglevoice"]) && (!locked || issilicon(usr)))
vocal = !vocal
if("eject")
if(reagent_glass)
reagent_glass.forceMove(get_turf(src))
reagent_glass = null
. = TRUE
else if ((href_list["declaretreatment"]) && (!locked || issilicon(usr)))
declare_treatment = !declare_treatment
if("togglevoice")
vocal = !vocal
. = TRUE
if("declaretreatment")
declare_treatment = !declare_treatment
. = TRUE
attack_hand(usr)
return
/mob/living/bot/medbot/emag_act(var/remaining_uses, var/mob/user)
. = ..()
+53 -28
View File
@@ -88,53 +88,78 @@
else
set_light(0)
/mob/living/bot/secbot/attack_hand(var/mob/user)
user.set_machine(src)
var/list/dat = list()
dat += "<TT><B>Automatic Security Unit</B></TT><BR><BR>"
dat += "Status: <A href='?src=\ref[src];power=1'>[on ? "On" : "Off"]</A><BR>"
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
dat += "Maintenance panel is [open ? "opened" : "closed"]"
if(!locked || issilicon(user))
dat += "<BR>Check for Weapon Authorization: <A href='?src=\ref[src];operation=idcheck'>[idcheck ? "Yes" : "No"]</A><BR>"
dat += "Check Security Records: <A href='?src=\ref[src];operation=ignorerec'>[check_records ? "Yes" : "No"]</A><BR>"
dat += "Check Arrest Status: <A href='?src=\ref[src];operation=ignorearr'>[check_arrest ? "Yes" : "No"]</A><BR>"
dat += "Operating Mode: <A href='?src=\ref[src];operation=switchmode'>[arrest_type ? "Detain" : "Arrest"]</A><BR>"
dat += "Report Arrests: <A href='?src=\ref[src];operation=declarearrests'>[declare_arrests ? "Yes" : "No"]</A><BR>"
if(using_map.bot_patrolling)
dat += "Auto Patrol: <A href='?src=\ref[src];operation=patrol'>[will_patrol ? "On" : "Off"]</A>"
var/datum/browser/popup = new(user, "autosec", "Securitron controls")
popup.set_content(jointext(dat,null))
popup.open()
/mob/living/bot/secbot/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Secbot", name)
ui.open()
/mob/living/bot/secbot/Topic(href, href_list)
/mob/living/bot/secbot/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["on"] = on
data["open"] = open
data["locked"] = locked
data["idcheck"] = null
data["check_records"] = null
data["check_arrest"] = null
data["arrest_type"] = null
data["declare_arrests"] = null
data["will_patrol"] = null
if(!locked || issilicon(user))
data["idcheck"] = idcheck
data["check_records"] = check_records
data["check_arrest"] = check_arrest
data["arrest_type"] = arrest_type
data["declare_arrests"] = declare_arrests
if(using_map.bot_patrolling)
data["will_patrol"] = will_patrol
return data
/mob/living/bot/secbot/attack_hand(var/mob/user)
tgui_interact(user)
/mob/living/bot/secbot/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return
usr.set_machine(src)
add_fingerprint(usr)
if((href_list["power"]) && (access_scanner.allowed(usr)))
if(on)
turn_off()
else
turn_on()
return
switch(action)
if("power")
if(!access_scanner.allowed(usr))
return FALSE
if(on)
turn_off()
else
turn_on()
. = TRUE
switch(href_list["operation"])
if(locked && !issilicon(usr))
return TRUE
switch(action)
if("idcheck")
idcheck = !idcheck
. = TRUE
if("ignorerec")
check_records = !check_records
. = TRUE
if("ignorearr")
check_arrest = !check_arrest
. = TRUE
if("switchmode")
arrest_type = !arrest_type
. = TRUE
if("patrol")
will_patrol = !will_patrol
. = TRUE
if("declarearrests")
declare_arrests = !declare_arrests
attack_hand(usr)
. = TRUE
/mob/living/bot/secbot/emag_act(var/remaining_uses, var/mob/user)
. = ..()
@@ -430,7 +430,7 @@
to_chat(src, "<span class='notice'>[pick(fruit_gland.empty_message)]</span>")
return
var/datum/seed/S = plant_controller.seeds["[fruit_gland.fruit_type]"]
var/datum/seed/S = SSplants.seeds["[fruit_gland.fruit_type]"]
S.harvest(usr,0,0,1)
var/index = rand(0,2)
+1 -1
View File
@@ -3,7 +3,7 @@
return 0
//This is a terrible hack and I should be ashamed.
var/datum/seed/diona = plant_controller.seeds["diona"]
var/datum/seed/diona = SSplants.seeds["diona"]
if(!diona)
return 0
@@ -68,12 +68,12 @@
set category = "Object"
set src in view(1)
var/genemask = input("Choose a gene to modify.") as null|anything in plant_controller.plant_gene_datums
var/genemask = input("Choose a gene to modify.") as null|anything in SSplants.plant_gene_datums
if(!genemask)
return
gene = plant_controller.plant_gene_datums[genemask]
gene = SSplants.plant_gene_datums[genemask]
to_chat(usr, "<span class='info'>You set the [src]'s targeted genetic area to [genemask].</span>")
@@ -338,6 +338,9 @@
item_state = "electronic"
slot_flags = SLOT_BELT
/obj/item/device/destTagger/tgui_state(mob/user)
return GLOB.tgui_inventory_state
/obj/item/device/destTagger/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
+6 -1
View File
@@ -29,11 +29,16 @@ other types of metals and chemistry for reagents).
var/list/chemicals = list() //List of chemicals.
var/build_path = null //The path of the object that gets created.
var/time = 10 //How many ticks it requires to build
var/category = null //Primarily used for Mech Fabricators, but can be used for anything.
var/list/category = list() //Primarily used for Mech Fabricators, but can be used for anything.
var/sort_string = "ZZZZZ" //Sorting order
/// Optional string that interfaces can use as part of search filters. See- item/borg/upgrade/ai and the Exosuit Fabs.
var/search_metadata
/datum/design/New()
..()
if(!islist(category))
log_runtime(EXCEPTION("Warning: Design [type] defined a non-list category. Please fix this."))
category = list(category)
item_name = name
AssembleDesignInfo()
+3 -3
View File
@@ -10,7 +10,7 @@
build_type = PROTOLATHE | PROSFAB
materials = list(DEFAULT_WALL_MATERIAL = 1000, "glass" = 500)
build_path = /obj/item/device/mmi
category = "Misc"
category = list("Misc")
sort_string = "SAAAA"
/datum/design/item/ai_holder/posibrain
@@ -20,7 +20,7 @@
build_type = PROTOLATHE | PROSFAB
materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500, "phoron" = 500, "diamond" = 100)
build_path = /obj/item/device/mmi/digital/posibrain
category = "Misc"
category = list("Misc")
sort_string = "SAAAB"
/datum/design/item/ai_holder/dronebrain
@@ -30,7 +30,7 @@
build_type = PROTOLATHE | PROSFAB
materials = list(DEFAULT_WALL_MATERIAL = 2000, "glass" = 1000, "silver" = 1000, "gold" = 500)
build_path = /obj/item/device/mmi/digital/robot
category = "Misc"
category = list("Misc")
sort_string = "SAAAC"
/datum/design/item/ai_holder/paicard
@@ -655,7 +655,7 @@ CIRCUITS BELOW
sort_string = "OAABA"
/datum/design/circuit/pointdefense_control
name = "deluxe microwave"
name = "point defense control"
id = "pointdefense_control"
req_tech = list(TECH_DATA = 4, TECH_ENGINEERING = 3, TECH_COMBAT = 2)
build_path = /obj/item/weapon/circuitboard/pointdefense_control
+6 -6
View File
@@ -22,7 +22,7 @@
req_tech = list(TECH_POWER = 1)
materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50)
build_path = /obj/item/weapon/cell
category = "Misc"
category = list("Misc")
sort_string = "BAAAA"
/datum/design/item/powercell/high
@@ -32,7 +32,7 @@
req_tech = list(TECH_POWER = 2)
materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 60)
build_path = /obj/item/weapon/cell/high
category = "Misc"
category = list("Misc")
sort_string = "BAAAB"
/datum/design/item/powercell/super
@@ -41,7 +41,7 @@
req_tech = list(TECH_POWER = 3, TECH_MATERIAL = 2)
materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 70)
build_path = /obj/item/weapon/cell/super
category = "Misc"
category = list("Misc")
sort_string = "BAAAC"
/datum/design/item/powercell/hyper
@@ -50,7 +50,7 @@
req_tech = list(TECH_POWER = 5, TECH_MATERIAL = 4)
materials = list(DEFAULT_WALL_MATERIAL = 400, "gold" = 150, "silver" = 150, "glass" = 70)
build_path = /obj/item/weapon/cell/hyper
category = "Misc"
category = list("Misc")
sort_string = "BAAAD"
/datum/design/item/powercell/device
@@ -59,7 +59,7 @@
id = "device"
materials = list(DEFAULT_WALL_MATERIAL = 350, "glass" = 25)
build_path = /obj/item/weapon/cell/device
category = "Misc"
category = list("Misc")
sort_string = "BAABA"
/datum/design/item/powercell/weapon
@@ -68,5 +68,5 @@
id = "weapon"
materials = list(DEFAULT_WALL_MATERIAL = 700, "glass" = 50)
build_path = /obj/item/weapon/cell/device/weapon
category = "Misc"
category = list("Misc")
sort_string = "BAABB"
+26 -26
View File
@@ -1,10 +1,10 @@
/datum/design/item/mechfab
build_type = MECHFAB
category = "Other"
category = list("Other")
req_tech = list(TECH_MATERIAL = 1)
/datum/design/item/mechfab/ripley
category = "Ripley"
category = list("Ripley")
/datum/design/item/mechfab/ripley/chassis
name = "Ripley Chassis"
@@ -54,7 +54,7 @@
materials = list(DEFAULT_WALL_MATERIAL = 22500)
/datum/design/item/mechfab/odysseus
category = "Odysseus"
category = list("Odysseus")
/datum/design/item/mechfab/odysseus/chassis
name = "Odysseus Chassis"
@@ -106,7 +106,7 @@
materials = list(DEFAULT_WALL_MATERIAL = 11250)
/datum/design/item/mechfab/gygax
category = "Gygax"
category = list("Gygax")
/datum/design/item/mechfab/gygax/chassis/serenity
name = "Serenity Chassis"
@@ -171,7 +171,7 @@
materials = list(DEFAULT_WALL_MATERIAL = 37500, "diamond" = 7500)
/datum/design/item/mechfab/durand
category = "Durand"
category = list("Durand")
/datum/design/item/mechfab/durand/chassis
name = "Durand Chassis"
@@ -230,7 +230,7 @@
materials = list(DEFAULT_WALL_MATERIAL = 27500, MAT_PLASTEEL = 10000, "uranium" = 7500)
/datum/design/item/mechfab/janus
category = "Janus"
category = list("Janus")
req_tech = list(TECH_MATERIAL = 7, TECH_BLUESPACE = 5, TECH_MAGNET = 6, TECH_PHORON = 3, TECH_ARCANE = 1, TECH_PRECURSOR = 2)
/datum/design/item/mechfab/janus/chassis
@@ -292,7 +292,7 @@
/datum/design/item/mecha
build_type = MECHFAB
category = "Exosuit Equipment"
category = list("Exosuit Equipment")
time = 10
materials = list(DEFAULT_WALL_MATERIAL = 7500)
@@ -758,7 +758,7 @@
build_type = MECHFAB
materials = list(DEFAULT_WALL_MATERIAL = 562, "glass" = 562)
build_path = /obj/item/device/flash/synthetic
category = "Misc"
category = list("Misc")
/*
* Non-Mech Vehicles
@@ -766,7 +766,7 @@
/datum/design/item/mechfab/vehicle
build_type = MECHFAB
category = "Vehicle"
category = list("Vehicle")
req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 6)
/datum/design/item/mechfab/vehicle/spacebike_chassis
@@ -790,7 +790,7 @@
*/
/datum/design/item/mechfab/rigsuit
category = "Rigsuit"
category = list("Rigsuit")
req_tech = list(TECH_MATERIAL = 6, TECH_ENGINEERING = 5, TECH_PHORON = 3, TECH_MAGNET = 4, TECH_POWER = 6)
/datum/design/item/mechfab/rigsuit/basic_belt
@@ -1042,13 +1042,13 @@
// Exosuit Internals
/datum/design/item/mechfab/exointernal
category = "Exosuit Internals"
category = list("Exosuit Internals")
time = 30
req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 3)
/datum/design/item/mechfab/exointernal/stan_armor
name = "Armor Plate (Standard)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_armor_standard"
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
materials = list(DEFAULT_WALL_MATERIAL = 10000)
@@ -1056,7 +1056,7 @@
/datum/design/item/mechfab/exointernal/light_armor
name = "Armor Plate (Lightweight)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_armor_lightweight"
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 3)
materials = list(DEFAULT_WALL_MATERIAL = 5000, MAT_PLASTIC = 3000)
@@ -1064,7 +1064,7 @@
/datum/design/item/mechfab/exointernal/reinf_armor
name = "Armor Plate (Reinforced)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_armor_reinforced"
req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4)
materials = list(DEFAULT_WALL_MATERIAL = 20000, MAT_PLASTEEL = 10000)
@@ -1072,7 +1072,7 @@
/datum/design/item/mechfab/exointernal/mining_armor
name = "Armor Plate (Blast)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_armor_blast"
req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4)
materials = list(DEFAULT_WALL_MATERIAL = 20000, MAT_PLASTEEL = 10000)
@@ -1080,7 +1080,7 @@
/datum/design/item/mechfab/exointernal/gygax_armor
name = "Armor Plate (Marshal)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_armor_gygax"
req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_COMBAT = 2)
materials = list(DEFAULT_WALL_MATERIAL = 40000, MAT_DIAMOND = 8000)
@@ -1088,7 +1088,7 @@
/datum/design/item/mechfab/exointernal/darkgygax_armor
name = "Armor Plate (Blackops)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_armor_dgygax"
req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 5, TECH_COMBAT = 4, TECH_ILLEGAL = 2)
materials = list(MAT_PLASTEEL = 20000, MAT_DIAMOND = 10000, MAT_GRAPHITE = 20000)
@@ -1117,7 +1117,7 @@
/datum/design/item/mechfab/exointernal/stan_hull
name = "Hull (Standard)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_hull_standard"
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
materials = list(DEFAULT_WALL_MATERIAL = 10000)
@@ -1125,7 +1125,7 @@
/datum/design/item/mechfab/exointernal/durable_hull
name = "Hull (Durable)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_hull_durable"
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
materials = list(DEFAULT_WALL_MATERIAL = 8000, MAT_PLASTEEL = 5000)
@@ -1133,7 +1133,7 @@
/datum/design/item/mechfab/exointernal/light_hull
name = "Hull (Lightweight)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_hull_light"
req_tech = list(TECH_MATERIAL = 3, TECH_ENGINEERING = 4)
materials = list(DEFAULT_WALL_MATERIAL = 5000, MAT_PLASTIC = 3000)
@@ -1141,7 +1141,7 @@
/datum/design/item/mechfab/exointernal/stan_gas
name = "Life-Support (Standard)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_lifesup_standard"
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
materials = list(DEFAULT_WALL_MATERIAL = 10000)
@@ -1149,7 +1149,7 @@
/datum/design/item/mechfab/exointernal/reinf_gas
name = "Life-Support (Reinforced)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_lifesup_reinforced"
req_tech = list(TECH_MATERIAL = 4, TECH_ENGINEERING = 4)
materials = list(DEFAULT_WALL_MATERIAL = 8000, MAT_PLASTEEL = 8000, MAT_GRAPHITE = 1000)
@@ -1157,7 +1157,7 @@
/datum/design/item/mechfab/exointernal/stan_electric
name = "Electrical Harness (Standard)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_electric_standard"
req_tech = list(TECH_POWER = 2, TECH_ENGINEERING = 2)
materials = list(DEFAULT_WALL_MATERIAL = 5000, MAT_PLASTIC = 1000)
@@ -1165,7 +1165,7 @@
/datum/design/item/mechfab/exointernal/efficient_electric
name = "Electrical Harness (High)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_electric_efficient"
req_tech = list(TECH_POWER = 4, TECH_ENGINEERING = 4, TECH_DATA = 2)
materials = list(DEFAULT_WALL_MATERIAL = 5000, MAT_PLASTIC = 3000, MAT_SILVER = 3000)
@@ -1173,7 +1173,7 @@
/datum/design/item/mechfab/exointernal/stan_actuator
name = "Actuator Lattice (Standard)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_actuator_standard"
req_tech = list(TECH_MATERIAL = 2, TECH_ENGINEERING = 2)
materials = list(DEFAULT_WALL_MATERIAL = 10000)
@@ -1181,7 +1181,7 @@
/datum/design/item/mechfab/exointernal/hispeed_actuator
name = "Actuator Lattice (Overclocked)"
category = "Exosuit Internals"
category = list("Exosuit Internals")
id = "exo_int_actuator_overclock"
req_tech = list(TECH_MATERIAL = 5, TECH_ENGINEERING = 4, TECH_POWER = 4)
materials = list(MAT_PLASTEEL = 10000, MAT_OSMIUM = 3000, MAT_GOLD = 5000)
+10 -10
View File
@@ -1,15 +1,15 @@
/datum/design/item/prosfab
build_type = PROSFAB
category = "Misc"
category = list("Misc")
req_tech = list(TECH_MATERIAL = 1)
/datum/design/item/prosfab/pros
category = "Prosthetics"
category = list("Prosthetics")
// Make new external organs and make 'em robotish
/datum/design/item/prosfab/pros/Fabricate(var/newloc, var/fabricator)
if(istype(fabricator, /obj/machinery/pros_fabricator))
var/obj/machinery/pros_fabricator/prosfab = fabricator
if(istype(fabricator, /obj/machinery/mecha_part_fabricator/pros))
var/obj/machinery/mecha_part_fabricator/pros/prosfab = fabricator
var/obj/item/organ/O = new build_path(newloc)
if(prosfab.manufacturer)
var/datum/robolimb/manf = all_robolimbs[prosfab.manufacturer]
@@ -37,8 +37,8 @@
// Deep Magic for the torso since it needs to be a new mob
/datum/design/item/prosfab/pros/torso/Fabricate(var/newloc, var/fabricator)
if(istype(fabricator, /obj/machinery/pros_fabricator))
var/obj/machinery/pros_fabricator/prosfab = fabricator
if(istype(fabricator, /obj/machinery/mecha_part_fabricator/pros))
var/obj/machinery/mecha_part_fabricator/pros/prosfab = fabricator
var/newspecies = "Human"
var/datum/robolimb/manf = all_robolimbs[prosfab.manufacturer]
@@ -175,7 +175,7 @@
materials = list(DEFAULT_WALL_MATERIAL = 2813)
/datum/design/item/prosfab/pros/internal
category = "Prosthetics, Internal"
category = list("Prosthetics, Internal")
/datum/design/item/prosfab/pros/internal/cell
name = "Prosthetic Powercell"
@@ -270,7 +270,7 @@
//////////////////// Cyborg Parts ////////////////////
/datum/design/item/prosfab/cyborg
category = "Cyborg Parts"
category = list("Cyborg Parts")
time = 20
materials = list(DEFAULT_WALL_MATERIAL = 3750)
@@ -326,7 +326,7 @@
//////////////////// Cyborg Internals ////////////////////
/datum/design/item/prosfab/cyborg/component
category = "Cyborg Internals"
category = list("Cyborg Internals")
build_type = PROSFAB
time = 12
materials = list(DEFAULT_WALL_MATERIAL = 7500)
@@ -368,7 +368,7 @@
//////////////////// Cyborg Modules ////////////////////
/datum/design/item/prosfab/robot_upgrade
category = "Cyborg Modules"
category = list("Cyborg Modules")
build_type = PROSFAB
time = 12
materials = list(DEFAULT_WALL_MATERIAL = 7500)
+6 -670
View File
@@ -42,7 +42,6 @@ won't update every console in existence) but it's more of a hassle to do. Also,
var/obj/machinery/r_n_d/protolathe/linked_lathe = null //Linked Protolathe
var/obj/machinery/r_n_d/circuit_imprinter/linked_imprinter = null //Linked Circuit Imprinter
var/screen = 1.0 //Which screen is currently showing.
var/id = 0 //ID of the computer (for server restrictions).
var/sync = 1 //If sync = 0, it doesn't show up on Server Control Console
@@ -71,17 +70,10 @@ won't update every console in existence) but it's more of a hassle to do. Also,
return return_name
/obj/machinery/computer/rdconsole/proc/CallReagentName(var/ID)
var/return_name = ID
var/datum/reagent/temp_reagent
for(var/R in (typesof(/datum/reagent) - /datum/reagent))
temp_reagent = null
temp_reagent = new R()
if(temp_reagent.id == ID)
return_name = temp_reagent.name
qdel(temp_reagent)
temp_reagent = null
break
return return_name
var/datum/reagent/R = SSchemistry.chemical_reagents["[ID]"]
if(!R)
return ID
return R.name
/obj/machinery/computer/rdconsole/proc/SyncRDevices() //Makes sure it is properly sync'ed up with the devices attached to it (if any).
for(var/obj/machinery/r_n_d/D in range(3, src))
@@ -142,7 +134,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
//The construction/deconstruction of the console code.
..()
src.updateUsrDialog()
SStgui.update_uis(src)
return
/obj/machinery/computer/rdconsole/emp_act(var/remaining_charges, var/mob/user)
@@ -152,296 +144,6 @@ won't update every console in existence) but it's more of a hassle to do. Also,
to_chat(user, "<span class='notice'>You you disable the security protocols.</span>")
return 1
/obj/machinery/computer/rdconsole/Topic(href, href_list)
if(..())
return 1
add_fingerprint(usr)
usr.set_machine(src)
if((screen < 1 || (screen == 1.6 && href_list["menu"] != "1.0")) && (!allowed(usr) && !emagged)) //Stops people from HREF exploiting out of the lock screen, but allow it if they have the access.
to_chat(usr, "Unauthorized Access")
return
if(href_list["menu"]) //Switches menu screens. Converts a sent text string into a number. Saves a LOT of code.
var/temp_screen = text2num(href_list["menu"])
if(temp_screen <= 1.1 || (3 <= temp_screen && 4.9 >= temp_screen) || allowed(usr) || emagged) //Unless you are making something, you need access.
screen = temp_screen
else
to_chat(usr, "Unauthorized Access.")
else if(href_list["updt_tech"]) //Update the research holder with information from the technology disk.
screen = 0.0
spawn(5 SECONDS)
screen = 1.2
files.AddTech2Known(t_disk.stored)
updateUsrDialog()
griefProtection() //Update CentCom too
else if(href_list["clear_tech"]) //Erase data on the technology disk.
t_disk.stored = null
else if(href_list["eject_tech"]) //Eject the technology disk.
t_disk.loc = loc
t_disk = null
screen = 1.0
else if(href_list["copy_tech"]) //Copys some technology data from the research holder to the disk.
for(var/datum/tech/T in files.known_tech)
if(href_list["copy_tech_ID"] == T.id)
t_disk.stored = T
break
screen = 1.2
else if(href_list["updt_design"]) //Updates the research holder with design data from the design disk.
screen = 0.0
spawn(5 SECONDS)
screen = 1.4
files.AddDesign2Known(d_disk.blueprint)
updateUsrDialog()
griefProtection() //Update CentCom too
else if(href_list["clear_design"]) //Erases data on the design disk.
d_disk.blueprint = null
else if(href_list["eject_design"]) //Eject the design disk.
d_disk.loc = loc
d_disk = null
screen = 1.0
else if(href_list["copy_design"]) //Copy design data from the research holder to the design disk.
for(var/datum/design/D in files.known_designs)
if(href_list["copy_design_ID"] == D.id)
d_disk.blueprint = D
break
screen = 1.4
else if(href_list["eject_item"]) //Eject the item inside the destructive analyzer.
if(linked_destroy)
if(linked_destroy.busy)
to_chat(usr, "<span class='notice'>The destructive analyzer is busy at the moment.</span>")
else if(linked_destroy.loaded_item)
linked_destroy.loaded_item.loc = linked_destroy.loc
linked_destroy.loaded_item = null
linked_destroy.icon_state = "d_analyzer"
screen = 2.1
else if(href_list["deconstruct"]) //Deconstruct the item in the destructive analyzer and update the research holder.
if(linked_destroy)
if(linked_destroy.busy)
to_chat(usr, "<span class='notice'>The destructive analyzer is busy at the moment.</span>")
else
if(alert("Proceeding will destroy loaded item. Continue?", "Destructive analyzer confirmation", "Yes", "No") == "No" || !linked_destroy)
return
linked_destroy.busy = 1
screen = 0.1
updateUsrDialog()
flick("d_analyzer_process", linked_destroy)
spawn(2.4 SECONDS)
if(linked_destroy)
linked_destroy.busy = 0
if(!linked_destroy.loaded_item)
to_chat(usr, "<span class='notice'>The destructive analyzer appears to be empty.</span>")
screen = 1.0
return
for(var/T in linked_destroy.loaded_item.origin_tech)
files.UpdateTech(T, linked_destroy.loaded_item.origin_tech[T])
if(linked_lathe && linked_destroy.loaded_item.matter) // Also sends salvaged materials to a linked protolathe, if any.
for(var/t in linked_destroy.loaded_item.matter)
if(t in linked_lathe.materials)
linked_lathe.materials[t] += min(linked_lathe.max_material_storage - linked_lathe.TotalMaterials(), linked_destroy.loaded_item.matter[t] * linked_destroy.decon_mod)
linked_destroy.loaded_item = null
for(var/obj/I in linked_destroy.contents)
for(var/mob/M in I.contents)
M.death()
if(istype(I,/obj/item/stack/material))//Only deconsturcts one sheet at a time instead of the entire stack
var/obj/item/stack/material/S = I
if(S.get_amount() > 1)
S.use(1)
linked_destroy.loaded_item = S
else
qdel(S)
linked_destroy.icon_state = "d_analyzer"
else
if(I != linked_destroy.circuit && !(I in linked_destroy.component_parts))
qdel(I)
linked_destroy.icon_state = "d_analyzer"
use_power(linked_destroy.active_power_usage)
screen = 1.0
updateUsrDialog()
else if(href_list["lock"]) //Lock the console from use by anyone without tox access.
if(allowed(usr))
screen = text2num(href_list["lock"])
else
to_chat(usr, "Unauthorized Access.")
else if(href_list["sync"]) //Sync the research holder with all the R&D consoles in the game that aren't sync protected.
screen = 0.0
if(!sync)
to_chat(usr, "<span class='notice'>You must connect to the network first.</span>")
else
griefProtection() //Putting this here because I dont trust the sync process
spawn(3 SECONDS)
if(src)
for(var/obj/machinery/r_n_d/server/S in machines)
var/server_processed = 0
if((id in S.id_with_upload) || istype(S, /obj/machinery/r_n_d/server/centcom))
for(var/datum/tech/T in files.known_tech)
S.files.AddTech2Known(T)
for(var/datum/design/D in files.known_designs)
S.files.AddDesign2Known(D)
S.files.RefreshResearch()
server_processed = 1
if((id in S.id_with_download) && !istype(S, /obj/machinery/r_n_d/server/centcom))
for(var/datum/tech/T in S.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in S.files.known_designs)
files.AddDesign2Known(D)
files.RefreshResearch()
server_processed = 1
if(!istype(S, /obj/machinery/r_n_d/server/centcom) && server_processed)
S.produce_heat()
screen = 1.6
updateUsrDialog()
else if(href_list["togglesync"]) //Prevents the console from being synced by other consoles. Can still send data.
sync = !sync
else if(href_list["build"]) //Causes the Protolathe to build something.
if(linked_lathe)
var/datum/design/being_built = null
for(var/datum/design/D in files.known_designs)
if(D.id == href_list["build"])
being_built = D
break
if(being_built)
linked_lathe.addToQueue(being_built)
else if(href_list["buildfive"]) //Causes the Protolathe to build 5 of something.
if(linked_lathe)
var/datum/design/being_built = null
for(var/datum/design/D in files.known_designs)
if(D.id == href_list["buildfive"])
being_built = D
break
if(being_built)
for(var/i = 1 to 5)
linked_lathe.addToQueue(being_built)
screen = 3.1
else if(href_list["protofilter"])
var/filterstring = input(usr, "Input a filter string, or blank to not filter:", "Design Filter", protofilter) as null|text
if(!Adjacent(usr))
return
if(isnull(filterstring)) //Clicked Cancel
return
if(filterstring == "") //Cleared value
protofilter = null
protofilter = sanitize(filterstring, 25)
else if(href_list["circuitfilter"])
var/filterstring = input(usr, "Input a filter string, or blank to not filter:", "Design Filter", circuitfilter) as null|text
if(!Adjacent(usr))
return
if(isnull(filterstring)) //Clicked Cancel
return
if(filterstring == "") //Cleared value
circuitfilter = null
circuitfilter = sanitize(filterstring, 25)
else if(href_list["imprint"]) //Causes the Circuit Imprinter to build something.
if(linked_imprinter)
var/datum/design/being_built = null
for(var/datum/design/D in files.known_designs)
if(D.id == href_list["imprint"])
being_built = D
break
if(being_built)
linked_imprinter.addToQueue(being_built)
screen = 4.1
else if(href_list["disposeI"] && linked_imprinter) //Causes the circuit imprinter to dispose of a single reagent (all of it)
linked_imprinter.reagents.del_reagent(href_list["dispose"])
else if(href_list["disposeallI"] && linked_imprinter) //Causes the circuit imprinter to dispose of all it's reagents.
linked_imprinter.reagents.clear_reagents()
else if(href_list["removeI"] && linked_lathe)
linked_imprinter.removeFromQueue(text2num(href_list["removeI"]))
else if(href_list["disposeP"] && linked_lathe) //Causes the protolathe to dispose of a single reagent (all of it)
linked_lathe.reagents.del_reagent(href_list["dispose"])
else if(href_list["disposeallP"] && linked_lathe) //Causes the protolathe to dispose of all it's reagents.
linked_lathe.reagents.clear_reagents()
else if(href_list["removeP"] && linked_lathe)
linked_lathe.removeFromQueue(text2num(href_list["removeP"]))
else if(href_list["lathe_ejectsheet"] && linked_lathe) //Causes the protolathe to eject a sheet of material
linked_lathe.eject(href_list["lathe_ejectsheet"], text2num(href_list["amount"]))
else if(href_list["imprinter_ejectsheet"] && linked_imprinter) //Causes the protolathe to eject a sheet of material
linked_imprinter.eject(href_list["imprinter_ejectsheet"], text2num(href_list["amount"]))
else if(href_list["find_device"]) //The R&D console looks for devices nearby to link up with.
screen = 0.0
spawn(10)
SyncRDevices()
screen = 1.7
updateUsrDialog()
else if(href_list["disconnect"]) //The R&D console disconnects with a specific device.
switch(href_list["disconnect"])
if("destroy")
linked_destroy.linked_console = null
linked_destroy = null
if("lathe")
linked_lathe.linked_console = null
linked_lathe = null
if("imprinter")
linked_imprinter.linked_console = null
linked_imprinter = null
else if(href_list["reset"]) //Reset the R&D console's database.
griefProtection()
var/choice = alert("R&D Console Database Reset", "Are you sure you want to reset the R&D console's database? Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
screen = 0.0
qdel(files)
files = new /datum/research(src)
spawn(20)
screen = 1.6
updateUsrDialog()
else if (href_list["print"]) //Print research information
screen = 0.5
spawn(20)
var/obj/item/weapon/paper/PR = new/obj/item/weapon/paper
PR.name = "list of researched technologies"
PR.info = "<center><b>[station_name()] Science Laboratories</b>"
PR.info += "<h2>[ (text2num(href_list["print"]) == 2) ? "Detailed" : null] Research Progress Report</h2>"
PR.info += "<i>report prepared at [stationtime2text()] station time</i></center><br>"
if(text2num(href_list["print"]) == 2)
PR.info += GetResearchListInfo()
else
PR.info += GetResearchLevelsInfo()
PR.info_links = PR.info
PR.icon_state = "paper_words"
PR.loc = src.loc
spawn(10)
screen = ((text2num(href_list["print"]) == 2) ? 5.0 : 1.1)
updateUsrDialog()
updateUsrDialog()
return
/obj/machinery/computer/rdconsole/proc/GetResearchLevelsInfo()
var/list/dat = list()
dat += "<UL>"
@@ -469,373 +171,7 @@ won't update every console in existence) but it's more of a hassle to do. Also,
if(stat & (BROKEN|NOPOWER))
return
user.set_machine(src)
var/list/dat = list()
files.RefreshResearch()
switch(screen) //A quick check to make sure you get the right screen when a device is disconnected.
if(2 to 2.9)
if(linked_destroy == null)
screen = 2.0
else if(linked_destroy.loaded_item == null)
screen = 2.1
else
screen = 2.2
if(3 to 3.9)
if(linked_lathe == null)
screen = 3.0
if(4 to 4.9)
if(linked_imprinter == null)
screen = 4.0
switch(screen)
//////////////////////R&D CONSOLE SCREENS//////////////////
if(0.0)
dat += "Updating Database..."
if(0.1)
dat += "Processing and Updating Database..."
if(0.2)
dat += "SYSTEM LOCKED<BR><BR>"
dat += "<A href='?src=\ref[src];lock=1.6'>Unlock</A>"
if(0.3)
dat += "Constructing Prototype. Please Wait..."
if(0.4)
dat += "Imprinting Circuit. Please Wait..."
if(0.5)
dat += "Printing Research Information. Please Wait..."
if(1.0) //Main Menu
dat += "Main Menu:<BR><BR>"
dat += "Loaded disk: "
dat += (t_disk || d_disk) ? (t_disk ? "technology storage disk" : "design storage disk") : "none"
dat += "<HR><UL>"
dat += "<LI><A href='?src=\ref[src];menu=1.1'>Current Research Levels</A>"
dat += "<LI><A href='?src=\ref[src];menu=5.0'>View Researched Technologies</A>"
if(t_disk)
dat += "<LI><A href='?src=\ref[src];menu=1.2'>Disk Operations</A>"
else if(d_disk)
dat += "<LI><A href='?src=\ref[src];menu=1.4'>Disk Operations</A>"
else
dat += "<LI><span class='linkOff'>Disk Operations</span>"
if(linked_destroy)
dat += "<LI><A href='?src=\ref[src];menu=2.2'>Destructive Analyzer Menu</A>"
if(linked_lathe)
dat += "<LI><A href='?src=\ref[src];menu=3.1'>Protolathe Construction Menu</A>"
if(linked_imprinter)
dat += "<LI><A href='?src=\ref[src];menu=4.1'>Circuit Construction Menu</A>"
dat += "<LI><A href='?src=\ref[src];menu=1.6'>Settings</A>"
dat += "</UL>"
if(1.1) //Research viewer
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];print=1'>Print This Page</A><HR>"
dat += "Current Research Levels:<BR><BR>"
dat += GetResearchLevelsInfo()
dat += "</UL>"
if(1.2) //Technology Disk Menu
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "Disk Contents: (Technology Data Disk)<BR><BR>"
if(t_disk.stored == null)
dat += "The disk has no data stored on it.<HR>"
dat += "Operations: "
dat += "<A href='?src=\ref[src];menu=1.3'>Load Tech to Disk</A> || "
else
dat += "Name: [t_disk.stored.name]<BR>"
dat += "Level: [t_disk.stored.level]<BR>"
dat += "Description: [t_disk.stored.desc]<HR>"
dat += "Operations: "
dat += "<A href='?src=\ref[src];updt_tech=1'>Upload to Database</A> || "
dat += "<A href='?src=\ref[src];clear_tech=1'>Clear Disk</A> || "
dat += "<A href='?src=\ref[src];eject_tech=1'>Eject Disk</A>"
if(1.3) //Technology Disk submenu
dat += "<BR><A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=1.2'>Return to Disk Operations</A><HR>"
dat += "Load Technology to Disk:<BR><BR>"
dat += "<UL>"
for(var/datum/tech/T in files.known_tech)
dat += "<LI>[T.name] "
dat += "\[<A href='?src=\ref[src];copy_tech=1;copy_tech_ID=[T.id]'>copy to disk</A>\]"
dat += "</UL>"
if(1.4) //Design Disk menu.
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
if(d_disk.blueprint == null)
dat += "The disk has no data stored on it.<HR>"
dat += "Operations: "
dat += "<A href='?src=\ref[src];menu=1.5'>Load Design to Disk</A> || "
else
dat += "Name: [d_disk.blueprint.name]<BR>"
switch(d_disk.blueprint.build_type)
if(IMPRINTER) dat += "Lathe Type: Circuit Imprinter<BR>"
if(PROTOLATHE) dat += "Lathe Type: Proto-lathe<BR>"
dat += "Required Materials:<BR>"
for(var/M in d_disk.blueprint.materials)
if(copytext(M, 1, 2) == "$") dat += "* [copytext(M, 2)] x [d_disk.blueprint.materials[M]]<BR>"
else dat += "* [M] x [d_disk.blueprint.materials[M]]<BR>"
dat += "<HR>Operations: "
dat += "<A href='?src=\ref[src];updt_design=1'>Upload to Database</A> || "
dat += "<A href='?src=\ref[src];clear_design=1'>Clear Disk</A> || "
dat += "<A href='?src=\ref[src];eject_design=1'>Eject Disk</A>"
if(1.5) //Technology disk submenu
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=1.4'>Return to Disk Operations</A><HR>"
dat += "Load Design to Disk:<BR><BR>"
dat += "<UL>"
for(var/datum/design/D in files.known_designs)
if(D.build_path)
dat += "<LI>[D.name] "
dat += "<A href='?src=\ref[src];copy_design=1;copy_design_ID=[D.id]'>\[copy to disk\]</A>"
dat += "</UL>"
if(1.6) //R&D console settings
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "R&D Console Setting:<HR>"
dat += "<UL>"
if(sync)
dat += "<LI><A href='?src=\ref[src];sync=1'>Sync Database with Network</A><BR>"
dat += "<LI><A href='?src=\ref[src];togglesync=1'>Disconnect from Research Network</A><BR>"
else
dat += "<LI><A href='?src=\ref[src];togglesync=1'>Connect to Research Network</A><BR>"
dat += "<LI><A href='?src=\ref[src];menu=1.7'>Device Linkage Menu</A><BR>"
dat += "<LI><A href='?src=\ref[src];lock=0.2'>Lock Console</A><BR>"
dat += "<LI><A href='?src=\ref[src];reset=1'>Reset R&D Database</A><BR>"
dat += "<UL>"
if(1.7) //R&D device linkage
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=1.6'>Settings Menu</A><HR>"
dat += "R&D Console Device Linkage Menu:<BR><BR>"
dat += "<A href='?src=\ref[src];find_device=1'>Re-sync with Nearby Devices</A><HR>"
dat += "Linked Devices:"
dat += "<UL>"
if(linked_destroy)
dat += "<LI>Destructive Analyzer <A href='?src=\ref[src];disconnect=destroy'>(Disconnect)</A>"
else
dat += "<LI>(No Destructive Analyzer Linked)"
if(linked_lathe)
dat += "<LI>Protolathe <A href='?src=\ref[src];disconnect=lathe'>(Disconnect)</A>"
else
dat += "<LI>(No Protolathe Linked)"
if(linked_imprinter)
dat += "<LI>Circuit Imprinter <A href='?src=\ref[src];disconnect=imprinter'>(Disconnect)</A>"
else
dat += "<LI>(No Circuit Imprinter Linked)"
dat += "</UL>"
////////////////////DESTRUCTIVE ANALYZER SCREENS////////////////////////////
if(2.0)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "NO DESTRUCTIVE ANALYZER LINKED TO CONSOLE<BR><BR>"
if(2.1)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "No Item Loaded. Standing-by...<BR><HR>"
if(2.2)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "Deconstruction Menu<HR>"
dat += "Name: [linked_destroy.loaded_item.name]<BR>"
dat += "Origin Tech:"
dat += "<UL>"
for(var/T in linked_destroy.loaded_item.origin_tech)
dat += "<LI>[CallTechName(T)] [linked_destroy.loaded_item.origin_tech[T]]"
for(var/datum/tech/F in files.known_tech)
if(F.name == CallTechName(T))
dat += " (Current: [F.level])"
break
dat += "</UL>"
dat += "<HR><A href='?src=\ref[src];deconstruct=1'>Deconstruct Item</A> || "
dat += "<A href='?src=\ref[src];eject_item=1'>Eject Item</A> || "
/////////////////////PROTOLATHE SCREENS/////////////////////////
if(3.0)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "NO PROTOLATHE LINKED TO CONSOLE<BR><BR>"
if(3.1)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=3.4'>View Queue</A> || "
dat += "<A href='?src=\ref[src];menu=3.2'>Material Storage</A> || "
dat += "<A href='?src=\ref[src];menu=3.3'>Chemical Storage</A><HR>"
dat += "Protolathe Menu:<BR><BR>"
dat += "<B>Material Amount:</B> [linked_lathe.TotalMaterials()] cm<sup>3</sup> (MAX: [linked_lathe.max_material_storage])<BR>"
dat += "<B>Chemical Volume:</B> [linked_lathe.reagents.total_volume] (MAX: [linked_lathe.reagents.maximum_volume])<HR>"
dat += "<UL>"
dat += "<B>Filter:</B> <A href='?src=\ref[src];protofilter=1'>[protofilter ? protofilter : "None Set"]</A>"
for(var/datum/design/D in files.known_designs)
if(!D.build_path || !(D.build_type & PROTOLATHE))
continue
if(protofilter && findtext(D.name, protofilter) == 0)
continue
var/temp_dat
for(var/M in D.materials)
temp_dat += ", [D.materials[M]*linked_lathe.mat_efficiency] [CallMaterialName(M)]"
for(var/T in D.chemicals)
temp_dat += ", [D.chemicals[T]*linked_lathe.mat_efficiency] [CallReagentName(T)]"
if(temp_dat)
temp_dat = " \[[copytext(temp_dat, 3)]\]"
if(linked_lathe.canBuild(D))
dat += "<LI><B><A href='?src=\ref[src];build=[D.id]'>[D.name]</A></B>(<A href='?src=\ref[src];buildfive=[D.id]'>x5</A>)[temp_dat]"
else
dat += "<LI><B>[D.name]</B>[temp_dat]"
dat += "</UL>"
if(3.2) //Protolathe Material Storage Sub-menu
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=3.1'>Protolathe Menu</A><HR>"
dat += "Material Storage<BR><HR>"
dat += "<UL>"
for(var/M in linked_lathe.materials)
var/amount = linked_lathe.materials[M]
var/hidden_mat = FALSE
for(var/HM in linked_lathe.hidden_materials)
if(M == HM && amount == 0)
hidden_mat = TRUE
break
if(hidden_mat)
continue
dat += "<LI><B>[capitalize(M)]</B>: [amount] cm<sup>3</sup>"
if(amount >= SHEET_MATERIAL_AMOUNT)
dat += " || Eject "
for (var/C in list(1, 3, 5, 10, 15, 20, 25, 30, 40))
if(amount < C * SHEET_MATERIAL_AMOUNT)
break
dat += "[C > 1 ? ", " : ""]<A href='?src=\ref[src];lathe_ejectsheet=[M];amount=[C]'>[C]</A> "
dat += " or <A href='?src=\ref[src];lathe_ejectsheet=[M];amount=50'>max</A> sheets"
dat += ""
dat += "</UL>"
if(3.3) //Protolathe Chemical Storage Submenu
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=3.1'>Protolathe Menu</A><HR>"
dat += "Chemical Storage:<BR><HR>"
for(var/datum/reagent/R in linked_lathe.reagents.reagent_list)
dat += "Name: [R.name] | Units: [R.volume] "
dat += "<A href='?src=\ref[src];disposeP=[R.id]'>(Purge)</A><BR>"
dat += "<A href='?src=\ref[src];disposeallP=1'><U>Disposal All Chemicals in Storage</U></A><BR>"
if(3.4) // Protolathe queue
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=3.1'>Protolathe Menu</A><HR>"
dat += "Protolathe Construction Queue:<BR><HR>"
if(!linked_lathe.queue.len)
dat += "Empty"
else
var/tmp = 1
for(var/datum/design/D in linked_lathe.queue)
if(tmp == 1)
if(linked_lathe.busy)
dat += "<B>1: [D.name]</B><BR>"
else
dat += "<B>1: [D.name]</B> (Awaiting materials) <A href='?src=\ref[src];removeP=[tmp]'>(Remove)</A><BR>"
else
dat += "[tmp]: [D.name] <A href='?src=\ref[src];removeP=[tmp]'>(Remove)</A><BR>"
++tmp
///////////////////CIRCUIT IMPRINTER SCREENS////////////////////
if(4.0)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A><HR>"
dat += "NO CIRCUIT IMPRINTER LINKED TO CONSOLE<BR><BR>"
if(4.1)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=4.4'>View Queue</A> || "
dat += "<A href='?src=\ref[src];menu=4.3'>Material Storage</A> || "
dat += "<A href='?src=\ref[src];menu=4.2'>Chemical Storage</A><HR>"
dat += "Circuit Imprinter Menu:<BR><BR>"
dat += "Material Amount: [linked_imprinter.TotalMaterials()] cm<sup>3</sup><BR>"
dat += "Chemical Volume: [linked_imprinter.reagents.total_volume]<HR>"
dat += "<UL>"
dat += "<B>Filter:</B> <A href='?src=\ref[src];circuitfilter=1'>[circuitfilter ? circuitfilter : "None Set"]</A>"
for(var/datum/design/D in files.known_designs)
if(!D.build_path || !(D.build_type & IMPRINTER))
continue
if(circuitfilter && findtext(D.name, circuitfilter) == 0)
continue
var/temp_dat
for(var/M in D.materials)
temp_dat += ", [D.materials[M]*linked_imprinter.mat_efficiency] [CallMaterialName(M)]"
for(var/T in D.chemicals)
temp_dat += ", [D.chemicals[T]*linked_imprinter.mat_efficiency] [CallReagentName(T)]"
if(temp_dat)
temp_dat = " \[[copytext(temp_dat,3)]\]"
if(linked_imprinter.canBuild(D))
dat += "<LI><B><A href='?src=\ref[src];imprint=[D.id]'>[D.name]</A></B>[temp_dat]"
else
dat += "<LI><B>[D.name]</B>[temp_dat]"
dat += "</UL>"
if(4.2)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=4.1'>Imprinter Menu</A><HR>"
dat += "Chemical Storage<BR><HR>"
for(var/datum/reagent/R in linked_imprinter.reagents.reagent_list)
dat += "Name: [R.name] | Units: [R.volume] "
dat += "<A href='?src=\ref[src];disposeI=[R.id]'>(Purge)</A><BR>"
dat += "<A href='?src=\ref[src];disposeallI=1'><U>Disposal All Chemicals in Storage</U></A><BR>"
if(4.3)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=4.1'>Circuit Imprinter Menu</A><HR>"
dat += "Material Storage<BR><HR>"
dat += "<UL>"
for(var/M in linked_imprinter.materials)
var/amount = linked_imprinter.materials[M]
var/hidden_mat = FALSE
for(var/HM in linked_imprinter.hidden_materials)
if(M == HM && amount == 0)
hidden_mat = TRUE
break
if(hidden_mat)
continue
dat += "<LI><B>[capitalize(M)]</B>: [amount] cm<sup>3</sup>"
if(amount >= SHEET_MATERIAL_AMOUNT)
dat += " || Eject: "
for (var/C in list(1, 3, 5, 10, 15, 20, 25, 30, 40))
if(amount < C * SHEET_MATERIAL_AMOUNT)
break
dat += "[C > 1 ? ", " : ""]<A href='?src=\ref[src];imprinter_ejectsheet=[M];amount=[C]'>[C]</A> "
dat += " or <A href='?src=\ref[src];imprinter_ejectsheet=[M];amount=50'>max</A> sheets"
dat += ""
dat += "</UL>"
if(4.4)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];menu=4.1'>Circuit Imprinter Menu</A><HR>"
dat += "Queue<BR><HR>"
if(linked_imprinter.queue.len == 0)
dat += "Empty"
else
var/tmp = 1
for(var/datum/design/D in linked_imprinter.queue)
if(tmp == 1)
dat += "<B>1: [D.name]</B><BR>"
else
dat += "[tmp]: [D.name] <A href='?src=\ref[src];removeI=[tmp]'>(Remove)</A><BR>"
++tmp
///////////////////Research Information Browser////////////////////
if(5.0)
dat += "<A href='?src=\ref[src];menu=1.0'>Main Menu</A> || "
dat += "<A href='?src=\ref[src];print=2'>Print This Page</A><HR>"
dat += "List of Researched Technologies and Designs:"
dat += GetResearchListInfo()
dat = jointext(dat, null)
var/datum/browser/popup = new(user, "rdconsole", "Research and Development Console", 850, 600)
popup.set_content(dat)
popup.open()
tgui_interact(user) // TODO: remove the other UI
/obj/machinery/computer/rdconsole/robotics
name = "Robotics R&D Console"
+625
View File
@@ -0,0 +1,625 @@
/*
* This file contains all of the UI code for the RD console.
* It's moved off to this file for simplicity and understanding what is UI and what is functionality.
*/
#define ENTRIES_PER_RDPAGE 50
/obj/machinery/computer/rdconsole
var/locked = FALSE
var/busy_msg = null
var/search = ""
var/design_page = 0
var/builder_page = 0
/obj/machinery/computer/rdconsole/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ResearchConsole", name)
ui.open()
/obj/machinery/computer/rdconsole/tgui_status(mob/user)
. = ..()
if(locked && !allowed(user) && !emagged)
. = min(., STATUS_UPDATE)
/obj/machinery/computer/rdconsole/tgui_static_data(mob/user)
var/list/data = ..()
data["tech"] = tgui_GetResearchLevelsInfo()
data["designs"] = tgui_GetDesignInfo(design_page)
data["lathe_designs"] = tgui_GetProtolatheDesigns(linked_lathe, builder_page)
data["imprinter_designs"] = tgui_GetImprinterDesigns(linked_imprinter, builder_page)
return data
/obj/machinery/computer/rdconsole/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["locked"] = locked
data["busy_msg"] = busy_msg
data["search"] = search
data["info"] = null
if(!locked && !busy_msg)
data["info"] = list(
"sync" = sync,
)
data["info"]["linked_destroy"] = list("present" = FALSE)
if(linked_destroy)
data["info"]["linked_destroy"] = list(
"present" = TRUE,
"loaded_item" = linked_destroy.loaded_item,
"origin_tech" = tgui_GetOriginTechForItem(linked_destroy.loaded_item),
)
data["info"]["linked_lathe"] = list("present" = FALSE)
if(linked_lathe)
data["info"]["linked_lathe"] = list(
"present" = TRUE,
"total_materials" = linked_lathe.TotalMaterials(),
"max_materials" = linked_lathe.max_material_storage,
"total_volume" = linked_lathe.reagents.total_volume,
"max_volume" = linked_lathe.reagents.maximum_volume,
"busy" = linked_lathe.busy,
)
var/list/materials = list()
for(var/M in linked_lathe.materials)
var/amount = linked_lathe.materials[M]
var/hidden_mat = FALSE
for(var/HM in linked_lathe.hidden_materials)
if(M == HM && amount == 0)
hidden_mat = TRUE
break
if(hidden_mat)
continue
materials.Add(list(list(
"name" = M,
"amount" = amount,
"sheets" = round(amount / SHEET_MATERIAL_AMOUNT),
"removable" = amount >= SHEET_MATERIAL_AMOUNT,
)))
data["info"]["linked_lathe"]["mats"] = materials
var/list/reagents = list()
for(var/datum/reagent/R in linked_lathe.reagents.reagent_list)
reagents.Add(list(list(
"name" = R.name,
"id" = R.id,
"volume" = R.volume,
)))
data["info"]["linked_lathe"]["reagents"] = reagents
var/list/queue = list()
var/i = 1
for(var/datum/design/D in linked_lathe.queue)
queue.Add(list(list(
"name" = D.name,
"index" = i, // ugghhhh
)))
i++
data["info"]["linked_lathe"]["queue"] = queue
data["info"]["linked_imprinter"] = list("present" = FALSE)
if(linked_imprinter)
data["info"]["linked_imprinter"] = list(
"present" = TRUE,
"total_materials" = linked_imprinter.TotalMaterials(),
"max_materials" = linked_imprinter.max_material_storage,
"total_volume" = linked_imprinter.reagents.total_volume,
"max_volume" = linked_imprinter.reagents.maximum_volume,
"busy" = linked_imprinter.busy,
)
var/list/materials = list()
for(var/M in linked_imprinter.materials)
var/amount = linked_imprinter.materials[M]
var/hidden_mat = FALSE
for(var/HM in linked_imprinter.hidden_materials)
if(M == HM && amount == 0)
hidden_mat = TRUE
break
if(hidden_mat)
continue
materials.Add(list(list(
"name" = M,
"amount" = amount,
"sheets" = round(amount / SHEET_MATERIAL_AMOUNT),
"removable" = amount >= SHEET_MATERIAL_AMOUNT,
)))
data["info"]["linked_imprinter"]["mats"] = materials
var/list/reagents = list()
for(var/datum/reagent/R in linked_imprinter.reagents.reagent_list)
reagents.Add(list(list(
"name" = R.name,
"id" = R.id,
"volume" = R.volume,
)))
data["info"]["linked_imprinter"]["reagents"] = reagents
var/list/queue = list()
var/i = 1
for(var/datum/design/D in linked_imprinter.queue)
queue.Add(list(list(
"name" = D.name,
"index" = i, // ugghhhh
)))
i++
data["info"]["linked_imprinter"]["queue"] = queue
data["info"]["t_disk"] = list("present" = FALSE)
if(t_disk)
data["info"]["t_disk"] = list(
"present" = TRUE,
"stored" = !!t_disk.stored,
)
if(t_disk.stored)
data["info"]["t_disk"]["name"] = t_disk.stored.name
data["info"]["t_disk"]["level"] = t_disk.stored.level
data["info"]["t_disk"]["desc"] = t_disk.stored.desc
data["info"]["d_disk"] = list("present" = FALSE)
if(d_disk)
data["info"]["d_disk"] = list(
"present" = TRUE,
"stored" = !!d_disk.blueprint,
)
if(d_disk.blueprint)
data["info"]["d_disk"]["name"] = d_disk.blueprint.name
data["info"]["d_disk"]["build_type"] = d_disk.blueprint.build_type
data["info"]["d_disk"]["materials"] = d_disk.blueprint.materials
return data
/obj/machinery/computer/rdconsole/proc/tgui_GetResearchLevelsInfo()
var/list/data = list()
for(var/datum/tech/T in files.known_tech)
if(T.level < 1)
continue
data.Add(list(list(
"name" = T.name,
"level" = T.level,
"desc" = T.desc,
"id" = T.id,
)))
return data
/obj/machinery/computer/rdconsole/proc/tgui_GetOriginTechForItem(obj/item/I)
if(!istype(I))
return list()
var/list/data = list()
for(var/T in I.origin_tech)
var/list/subdata = list(
"name" = CallTechName(T),
"level" = I.origin_tech[T],
"current" = null,
)
for(var/datum/tech/F in files.known_tech)
if(F.name == CallTechName(T))
subdata["current"] = F.level
break
data.Add(list(subdata))
return data
/proc/cmp_designs_rdconsole(list/A, list/B)
return sorttext(B["name"], A["name"])
/obj/machinery/computer/rdconsole/proc/tgui_GetProtolatheDesigns(obj/machinery/r_n_d/protolathe/P, page)
if(!istype(P))
return list()
var/list/data = list()
// For some reason, this is faster than direct access.
var/list/known_designs = files.known_designs
for(var/datum/design/D in known_designs)
if(!D.build_path || !(D.build_type & PROTOLATHE))
continue
if(search && !findtext(D.name, search))
continue
var/list/mat_list = list()
for(var/M in D.materials)
mat_list.Add("[D.materials[M] * P.mat_efficiency] [CallMaterialName(M)]")
var/list/chem_list = list()
for(var/T in D.chemicals)
chem_list.Add("[D.chemicals[T] * P.mat_efficiency] [CallReagentName(T)]")
data.Add(list(list(
"name" = D.name,
"id" = D.id,
"mat_list" = mat_list,
"chem_list" = chem_list,
)))
data = sortTim(data, /proc/cmp_designs_rdconsole, FALSE)
if(LAZYLEN(data) > ENTRIES_PER_RDPAGE)
var/first_index = clamp(ENTRIES_PER_RDPAGE * page, 1, LAZYLEN(data))
var/last_index = min((ENTRIES_PER_RDPAGE * page) + ENTRIES_PER_RDPAGE, LAZYLEN(data) + 1)
data = data.Copy(first_index, last_index)
return data
/obj/machinery/computer/rdconsole/proc/tgui_GetImprinterDesigns(obj/machinery/r_n_d/circuit_imprinter/P, page)
if(!istype(P))
return list()
var/list/data = list()
// For some reason, this is faster than direct access.
var/list/known_designs = files.known_designs
for(var/datum/design/D in known_designs)
if(!D.build_path || !(D.build_type & IMPRINTER))
continue
if(search && !findtext(D.name, search))
continue
var/list/mat_list = list()
for(var/M in D.materials)
mat_list.Add("[D.materials[M] * P.mat_efficiency] [CallMaterialName(M)]")
var/list/chem_list = list()
for(var/T in D.chemicals)
chem_list.Add("[D.chemicals[T] * P.mat_efficiency] [CallReagentName(T)]")
data.Add(list(list(
"name" = D.name,
"id" = D.id,
"mat_list" = mat_list,
"chem_list" = chem_list,
)))
data = sortTim(data, /proc/cmp_designs_rdconsole, FALSE)
if(LAZYLEN(data) > ENTRIES_PER_RDPAGE)
var/first_index = clamp(ENTRIES_PER_RDPAGE * page, 1, LAZYLEN(data))
var/last_index = min((ENTRIES_PER_RDPAGE * page) + ENTRIES_PER_RDPAGE, LAZYLEN(data) + 1)
data = data.Copy(first_index, last_index)
return data
/obj/machinery/computer/rdconsole/proc/tgui_GetDesignInfo(page)
var/list/data = list()
// For some reason, this is faster than direct access.
var/list/known_designs = files.known_designs
for(var/datum/design/D in known_designs)
if(search && !findtext(D.name, search))
continue
if(D.build_path)
data.Add(list(list(
"name" = D.name,
"desc" = D.desc,
"id" = D.id,
)))
data = sortTim(data, /proc/cmp_designs_rdconsole, FALSE)
if(LAZYLEN(data) > ENTRIES_PER_RDPAGE)
var/first_index = clamp(ENTRIES_PER_RDPAGE * page, 1, LAZYLEN(data))
var/last_index = clamp((ENTRIES_PER_RDPAGE * page) + ENTRIES_PER_RDPAGE, 1, LAZYLEN(data) + 1)
data = data.Copy(first_index, last_index)
return data
/obj/machinery/computer/rdconsole/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
add_fingerprint(usr)
usr.set_machine(src)
switch(action)
if("search")
search = params["search"]
update_tgui_static_data(usr, ui)
return TRUE
if("design_page")
if(params["reset"])
design_page = 0
else
design_page = max(design_page + (1 * params["reverse"]), 0)
update_tgui_static_data(usr, ui)
return TRUE
if("builder_page")
if(params["reset"])
builder_page = 0
else
builder_page = max(builder_page + (1 * params["reverse"]), 0)
update_tgui_static_data(usr, ui)
return TRUE
if("updt_tech") //Update the research holder with information from the technology disk.
busy_msg = "Updating Database..."
spawn(5 SECONDS)
busy_msg = null
files.AddTech2Known(t_disk.stored)
files.RefreshResearch()
griefProtection() //Update CentCom too
update_tgui_static_data(usr, ui)
return TRUE
if("clear_tech") //Erase data on the technology disk.
t_disk.stored = null
return TRUE
if("eject_tech") //Eject the technology disk.
t_disk.loc = loc
t_disk = null
return TRUE
if("copy_tech") //Copys some technology data from the research holder to the disk.
for(var/datum/tech/T in files.known_tech)
if(params["copy_tech_ID"] == T.id)
t_disk.stored = T
break
return TRUE
if("updt_design") //Updates the research holder with design data from the design disk.
busy_msg = "Updating Database..."
spawn(5 SECONDS)
busy_msg = null
files.AddDesign2Known(d_disk.blueprint)
griefProtection() //Update CentCom too
update_tgui_static_data(usr, ui)
return TRUE
if("clear_design") //Erases data on the design disk.
d_disk.blueprint = null
return TRUE
if("eject_design") //Eject the design disk.
d_disk.loc = loc
d_disk = null
return TRUE
if("copy_design") //Copy design data from the research holder to the design disk.
for(var/datum/design/D in files.known_designs)
if(params["copy_design_ID"] == D.id)
d_disk.blueprint = D
break
return TRUE
if("eject_item") //Eject the item inside the destructive analyzer.
if(linked_destroy)
if(linked_destroy.busy)
to_chat(usr, "<span class='notice'>The destructive analyzer is busy at the moment.</span>")
return FALSE
if(linked_destroy.loaded_item)
linked_destroy.loaded_item.loc = linked_destroy.loc
linked_destroy.loaded_item = null
linked_destroy.icon_state = "d_analyzer"
return TRUE
if("deconstruct") //Deconstruct the item in the destructive analyzer and update the research holder.
if(!linked_destroy)
return FALSE
if(linked_destroy.busy)
to_chat(usr, "<span class='notice'>The destructive analyzer is busy at the moment.</span>")
return
if(alert("Proceeding will destroy loaded item. Continue?", "Destructive analyzer confirmation", "Yes", "No") == "No" || !linked_destroy)
return
linked_destroy.busy = 1
busy_msg = "Processing and Updating Database..."
flick("d_analyzer_process", linked_destroy)
spawn(2.4 SECONDS)
if(linked_destroy)
linked_destroy.busy = 0
busy_msg = null
if(!linked_destroy.loaded_item)
to_chat(usr, "<span class='notice'>The destructive analyzer appears to be empty.</span>")
return
for(var/T in linked_destroy.loaded_item.origin_tech)
files.UpdateTech(T, linked_destroy.loaded_item.origin_tech[T])
if(linked_lathe && linked_destroy.loaded_item.matter) // Also sends salvaged materials to a linked protolathe, if any.
for(var/t in linked_destroy.loaded_item.matter)
if(t in linked_lathe.materials)
linked_lathe.materials[t] += min(linked_lathe.max_material_storage - linked_lathe.TotalMaterials(), linked_destroy.loaded_item.matter[t] * linked_destroy.decon_mod)
linked_destroy.loaded_item = null
for(var/obj/I in linked_destroy.contents)
for(var/mob/M in I.contents)
M.death()
if(istype(I,/obj/item/stack/material))//Only deconsturcts one sheet at a time instead of the entire stack
var/obj/item/stack/material/S = I
if(S.get_amount() > 1)
S.use(1)
linked_destroy.loaded_item = S
else
qdel(S)
linked_destroy.icon_state = "d_analyzer"
else
if(I != linked_destroy.circuit && !(I in linked_destroy.component_parts))
qdel(I)
linked_destroy.icon_state = "d_analyzer"
use_power(linked_destroy.active_power_usage)
files.RefreshResearch()
update_tgui_static_data(usr, ui)
return TRUE
if("lock") //Lock the console from use by anyone without tox access.
if(!allowed(usr))
to_chat(usr, "Unauthorized Access.")
return
locked = !locked
return TRUE
if("sync") //Sync the research holder with all the R&D consoles in the game that aren't sync protected.
if(!sync)
to_chat(usr, "<span class='notice'>You must connect to the network first.</span>")
return
busy_msg = "Updating Database..."
griefProtection() //Putting this here because I dont trust the sync process
spawn(3 SECONDS)
if(src)
for(var/obj/machinery/r_n_d/server/S in machines)
var/server_processed = 0
if((id in S.id_with_upload) || istype(S, /obj/machinery/r_n_d/server/centcom))
for(var/datum/tech/T in files.known_tech)
S.files.AddTech2Known(T)
for(var/datum/design/D in files.known_designs)
S.files.AddDesign2Known(D)
S.files.RefreshResearch()
server_processed = 1
if((id in S.id_with_download) && !istype(S, /obj/machinery/r_n_d/server/centcom))
for(var/datum/tech/T in S.files.known_tech)
files.AddTech2Known(T)
for(var/datum/design/D in S.files.known_designs)
files.AddDesign2Known(D)
server_processed = 1
if(!istype(S, /obj/machinery/r_n_d/server/centcom) && server_processed)
S.produce_heat()
busy_msg = null
files.RefreshResearch()
update_tgui_static_data(usr, ui)
return TRUE
if("togglesync") //Prevents the console from being synced by other consoles. Can still send data.
sync = !sync
return TRUE
if("build") //Causes the Protolathe to build something.
if(linked_lathe)
var/datum/design/being_built = null
for(var/datum/design/D in files.known_designs)
if(D.id == params["build"])
being_built = D
break
if(being_built)
linked_lathe.addToQueue(being_built)
return TRUE
if("buildfive") //Causes the Protolathe to build 5 of something.
if(linked_lathe)
var/datum/design/being_built = null
for(var/datum/design/D in files.known_designs)
if(D.id == params["build"])
being_built = D
break
if(being_built)
for(var/i = 1 to 5)
linked_lathe.addToQueue(being_built)
return TRUE
if("imprint") //Causes the Circuit Imprinter to build something.
if(linked_imprinter)
var/datum/design/being_built = null
for(var/datum/design/D in files.known_designs)
if(D.id == params["imprint"])
being_built = D
break
if(being_built)
linked_imprinter.addToQueue(being_built)
return TRUE
if("disposeI") //Causes the circuit imprinter to dispose of a single reagent (all of it)
if(!linked_imprinter)
return
linked_imprinter.reagents.del_reagent(params["dispose"])
return TRUE
if("disposeallI") //Causes the circuit imprinter to dispose of all it's reagents.
if(!linked_imprinter)
return
linked_imprinter.reagents.clear_reagents()
return TRUE
if("removeI")
if(!linked_imprinter)
return
linked_imprinter.removeFromQueue(text2num(params["removeI"]))
return TRUE
if("imprinter_ejectsheet") //Causes the imprinter to eject a sheet of material
if(!linked_imprinter)
return
linked_imprinter.eject(params["imprinter_ejectsheet"], text2num(params["amount"]))
return TRUE
if("disposeP") //Causes the protolathe to dispose of a single reagent (all of it)
if(!linked_lathe)
return
linked_lathe.reagents.del_reagent(params["dispose"])
return TRUE
if("disposeallP") //Causes the protolathe to dispose of all it's reagents.
if(!linked_lathe)
return
linked_lathe.reagents.clear_reagents()
return TRUE
if("removeP")
if(!linked_lathe)
return
linked_lathe.removeFromQueue(text2num(params["removeP"]))
return TRUE
if("lathe_ejectsheet") //Causes the protolathe to eject a sheet of material
if(!linked_lathe)
return
linked_lathe.eject(params["lathe_ejectsheet"], text2num(params["amount"]))
return TRUE
if("find_device") //The R&D console looks for devices nearby to link up with.
busy_msg = "Updating Database..."
spawn(10)
busy_msg = null
SyncRDevices()
update_tgui_static_data(usr, ui)
return TRUE
if("disconnect") //The R&D console disconnects with a specific device.
switch(params["disconnect"])
if("destroy")
linked_destroy.linked_console = null
linked_destroy = null
if("lathe")
linked_lathe.linked_console = null
linked_lathe = null
if("imprinter")
linked_imprinter.linked_console = null
linked_imprinter = null
update_tgui_static_data(usr, ui)
if("reset") //Reset the R&D console's database.
griefProtection()
var/choice = alert("R&D Console Database Reset", "Are you sure you want to reset the R&D console's database? Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
busy_msg = "Updating Database..."
qdel(files)
files = new /datum/research(src)
spawn(20)
busy_msg = null
update_tgui_static_data(usr, ui)
if("print") //Print research information
busy_msg = "Printing Research Information. Please Wait..."
spawn(20)
var/obj/item/weapon/paper/PR = new/obj/item/weapon/paper
PR.name = "list of researched technologies"
PR.info = "<center><b>[station_name()] Science Laboratories</b>"
PR.info += "<h2>[ (text2num(params["print"]) == 2) ? "Detailed" : null] Research Progress Report</h2>"
PR.info += "<i>report prepared at [stationtime2text()] station time</i></center><br>"
if(text2num(params["print"]) == 2)
PR.info += GetResearchListInfo()
else
PR.info += GetResearchLevelsInfo()
PR.info_links = PR.info
PR.icon_state = "paper_words"
PR.forceMove(loc)
busy_msg = null
+5 -17
View File
@@ -67,11 +67,10 @@ research holder datum.
//Checks to see if design has all the required pre-reqs.
//Input: datum/design; Output: 0/1 (false/true)
/datum/research/proc/DesignHasReqs(var/datum/design/D)
if(D.req_tech.len == 0)
return 1
if(!LAZYLEN(D.req_tech))
return TRUE
var/list/k_tech = list()
for(var/datum/tech/known in known_tech)
k_tech[known.id] = known.level
@@ -79,7 +78,7 @@ research holder datum.
if(isnull(k_tech[req]) || k_tech[req] < D.req_tech[req])
return 0
return 1
return TRUE
//Adds a tech to known_tech list. Checks to make sure there aren't duplicates and updates existing tech's levels if needed.
//Input: datum/tech; Output: Null
@@ -92,18 +91,7 @@ research holder datum.
return
/datum/research/proc/AddDesign2Known(var/datum/design/D)
if(!known_designs.len) // Special case
known_designs.Add(D)
return
for(var/i = 1 to known_designs.len)
var/datum/design/A = known_designs[i]
if(A.id == D.id) // We are guaranteed to reach this if the ids are the same, because sort_string will also be the same
return
if(A.sort_string > D.sort_string)
known_designs.Insert(i, D)
return
known_designs.Add(D)
return
LAZYDISTINCTADD(known_designs, D)
//Refreshes known_tech and known_designs list
//Input/Output: n/a
@@ -112,7 +100,7 @@ research holder datum.
if(DesignHasReqs(PD))
AddDesign2Known(PD)
for(var/datum/tech/T in known_tech)
T = between(0, T.level, 20)
T.level = between(0, T.level, 20)
return
//Refreshes the levels of a given tech.
+121 -120
View File
@@ -157,143 +157,144 @@
var/list/consoles = list()
var/badmin = 0
/obj/machinery/computer/rdservercontrol/Topic(href, href_list)
/obj/machinery/computer/rdservercontrol/tgui_status(mob/user)
. = ..()
if(!allowed(user) && !emagged)
. = min(., STATUS_UPDATE)
/obj/machinery/computer/rdservercontrol/tgui_interact(mob/user, datum/tgui/ui, datum/tgui/parent_ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ResearchServerController", name)
ui.open()
/obj/machinery/computer/rdservercontrol/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["badmin"] = badmin
var/list/server_list = list()
data["servers"] = server_list
for(var/obj/machinery/r_n_d/server/S in machines)
if(istype(S, /obj/machinery/r_n_d/server/centcom) && !badmin)
continue
var/list/server_data = list(
"name" = S.name,
"ref" = REF(S),
"id" = S.server_id,
"id_with_upload" = S.id_with_upload,
"id_with_download" = S.id_with_download,
"tech" = list(),
"designs" = list(),
)
for(var/datum/tech/T in S.files.known_tech)
server_data["tech"].Add(list(list(
"name" = T.name,
"id" = T.id,
)))
for(var/datum/design/D in S.files.known_designs)
server_data["designs"].Add(list(list(
"name" = D.name,
"id" = D.id,
)))
server_list.Add(list(server_data))
var/list/console_list = list()
data["consoles"] = console_list
for(var/obj/machinery/computer/rdconsole/C in machines)
if(!C.sync)
continue
console_list.Add(list(list(
"name" = C.name,
"ref" = REF(C),
"loc" = get_area(C),
"id" = C.id,
)))
return data
/obj/machinery/computer/rdservercontrol/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return 1
return TRUE
add_fingerprint(usr)
usr.set_machine(src)
if(!allowed(usr) && !emagged)
to_chat(usr, "<span class='warning'>You do not have the required access level</span>")
return
switch(action)
if("toggle_upload", "toggle_download")
var/obj/machinery/r_n_d/server/S = locate(params["server"])
if(!istype(S))
return
if(istype(S, /obj/machinery/r_n_d/server/centcom) && !badmin)
return
var/obj/machinery/computer/rdconsole/C = locate(params["console"])
if(!istype(C) || !C.sync)
return
if(href_list["main"])
screen = 0
switch(action)
if("toggle_upload")
if(C.id in S.id_with_upload)
S.id_with_upload -= C.id
else
S.id_with_upload += C.id
if("toggle_download")
if(C.id in S.id_with_download)
S.id_with_download -= C.id
else
S.id_with_download += C.id
return TRUE
else if(href_list["access"] || href_list["data"] || href_list["transfer"])
temp_server = null
consoles = list()
servers = list()
for(var/obj/machinery/r_n_d/server/S in machines)
if(S.server_id == text2num(href_list["access"]) || S.server_id == text2num(href_list["data"]) || S.server_id == text2num(href_list["transfer"]))
temp_server = S
break
if(href_list["access"])
screen = 1
for(var/obj/machinery/computer/rdconsole/C in machines)
if(C.sync)
consoles += C
else if(href_list["data"])
screen = 2
else if(href_list["transfer"])
screen = 3
for(var/obj/machinery/r_n_d/server/S in machines)
if(S == src)
continue
servers += S
if("reset_tech")
var/obj/machinery/r_n_d/server/target = locate(params["server"])
if(!istype(target))
return FALSE
var/choice = alert("Technology Data Rest", "Are you sure you want to reset this technology to its default data? Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
for(var/datum/tech/T in target.files.known_tech)
if(T.id == params["tech"])
T.level = 1
break
target.files.RefreshResearch()
return TRUE
else if(href_list["upload_toggle"])
var/num = text2num(href_list["upload_toggle"])
if(num in temp_server.id_with_upload)
temp_server.id_with_upload -= num
else
temp_server.id_with_upload += num
if("reset_design")
var/obj/machinery/r_n_d/server/target = locate(params["server"])
if(!istype(target))
return FALSE
var/choice = alert("Design Data Deletion", "Are you sure you want to delete this design? If you still have the prerequisites for the design, it'll reset to its base reliability. Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
for(var/datum/design/D in target.files.known_designs)
if(D.id == params["design"])
target.files.known_designs -= D
break
target.files.RefreshResearch()
return TRUE
else if(href_list["download_toggle"])
var/num = text2num(href_list["download_toggle"])
if(num in temp_server.id_with_download)
temp_server.id_with_download -= num
else
temp_server.id_with_download += num
else if(href_list["reset_tech"])
var/choice = alert("Technology Data Rest", "Are you sure you want to reset this technology to its default data? Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
for(var/datum/tech/T in temp_server.files.known_tech)
if(T.id == href_list["reset_tech"])
T.level = 1
break
temp_server.files.RefreshResearch()
else if(href_list["reset_design"])
var/choice = alert("Design Data Deletion", "Are you sure you want to delete this design? If you still have the prerequisites for the design, it'll reset to its base reliability. Data lost cannot be recovered.", "Continue", "Cancel")
if(choice == "Continue")
for(var/datum/design/D in temp_server.files.known_designs)
if(D.id == href_list["reset_design"])
temp_server.files.known_designs -= D
break
temp_server.files.RefreshResearch()
updateUsrDialog()
return
if("transfer_data")
if(!badmin)
// no href exploits, you've been r e p o r t e d
log_admin("Warning: [key_name(usr)] attempted to transfer R&D data from [params["server"]] to [params["target"]] via href exploit with [src] [COORD(src)]")
message_admins("Warning: [ADMIN_FULLMONTY(usr)] attempted to transfer R&D data from [params["server"]] to [params["target"]] via href exploit with [src] [ADMIN_COORDJMP(src)]")
return FALSE
var/obj/machinery/r_n_d/server/from = locate(params["server"])
if(!istype(from))
return
var/obj/machinery/r_n_d/server/target = locate(params["target"])
if(!istype(target))
return
target.files.known_designs |= from.files.known_designs
target.files.known_tech |= from.files.known_tech
return TRUE
/obj/machinery/computer/rdservercontrol/attack_hand(mob/user as mob)
if(stat & (BROKEN|NOPOWER))
return
user.set_machine(src)
var/dat = ""
switch(screen)
if(0) //Main Menu
dat += "Connected Servers:<BR><BR>"
for(var/obj/machinery/r_n_d/server/S in machines)
if(istype(S, /obj/machinery/r_n_d/server/centcom) && !badmin)
continue
dat += "[S.name] || "
dat += "<A href='?src=\ref[src];access=[S.server_id]'> Access Rights</A> | "
dat += "<A href='?src=\ref[src];data=[S.server_id]'>Data Management</A>"
if(badmin) dat += " | <A href='?src=\ref[src];transfer=[S.server_id]'>Server-to-Server Transfer</A>"
dat += "<BR>"
if(1) //Access rights menu
dat += "[temp_server.name] Access Rights<BR><BR>"
dat += "Consoles with Upload Access<BR>"
for(var/obj/machinery/computer/rdconsole/C in consoles)
var/turf/console_turf = get_turf(C)
dat += "* <A href='?src=\ref[src];upload_toggle=[C.id]'>[console_turf.loc]" //FYI, these are all numeric ids, eventually.
if(C.id in temp_server.id_with_upload)
dat += " (Remove)</A><BR>"
else
dat += " (Add)</A><BR>"
dat += "Consoles with Download Access<BR>"
for(var/obj/machinery/computer/rdconsole/C in consoles)
var/turf/console_turf = get_turf(C)
dat += "* <A href='?src=\ref[src];download_toggle=[C.id]'>[console_turf.loc]"
if(C.id in temp_server.id_with_download)
dat += " (Remove)</A><BR>"
else
dat += " (Add)</A><BR>"
dat += "<HR><A href='?src=\ref[src];main=1'>Main Menu</A>"
if(2) //Data Management menu
dat += "[temp_server.name] Data ManagementP<BR><BR>"
dat += "Known Technologies<BR>"
for(var/datum/tech/T in temp_server.files.known_tech)
dat += "* [T.name] "
dat += "<A href='?src=\ref[src];reset_tech=[T.id]'>(Reset)</A><BR>" //FYI, these are all strings.
dat += "Known Designs<BR>"
for(var/datum/design/D in temp_server.files.known_designs)
dat += "* [D.name] "
dat += "<A href='?src=\ref[src];reset_design=[D.id]'>(Delete)</A><BR>"
dat += "<HR><A href='?src=\ref[src];main=1'>Main Menu</A>"
if(3) //Server Data Transfer
dat += "[temp_server.name] Server to Server Transfer<BR><BR>"
dat += "Send Data to what server?<BR>"
for(var/obj/machinery/r_n_d/server/S in servers)
dat += "[S.name] <A href='?src=\ref[src];send_to=[S.server_id]'> (Transfer)</A><BR>"
dat += "<HR><A href='?src=\ref[src];main=1'>Main Menu</A>"
user << browse("<TITLE>R&D Server Control</TITLE><HR>[dat]", "window=server_control;size=575x400")
onclose(user, "server_control")
return
tgui_interact(user)
/obj/machinery/computer/rdservercontrol/emag_act(var/remaining_charges, var/mob/user)
if(!emagged)
playsound(src, 'sound/effects/sparks4.ogg', 75, 1)
emagged = 1
to_chat(user, "<span class='notice'>You you disable the security protocols.</span>")
src.updateUsrDialog()
SStgui.update_uis(src)
return 1
/obj/machinery/r_n_d/server/robotics
+1 -1
View File
@@ -113,7 +113,7 @@
return
closing = TRUE
for(var/datum/tgui/child in children)
child.close()
child.close(can_be_suspended, logout)
children.Cut()
// If we don't have window_id, open proc did not have the opportunity
// to finish, therefore it's safe to skip this whole block.
@@ -14,6 +14,7 @@
var/last_process_time = 0
var/list/construction = list()
var/list/tgui_construction = list()
var/list/spawning_types = list()
var/list/stored_materials = list()
@@ -67,12 +68,35 @@
// /mob/living/simple_mob/mimic/crate, // Vorestation edit //VORESTATION AI TEMPORARY REMOVAL, REPLACE BACK IN LIST WHEN FIXED
var/quantity = rand(5, 15)
for(var/i=0, i<quantity, i++)
var/button_desc = "a [pick("yellow","purple","green","blue","red","orange","white")], "
button_desc += "[pick("round","square","diamond","heart","dog","human")] shaped "
button_desc += "[pick("toggle","switch","lever","button","pad","hole")]"
var/background = pick("yellow","purple","green","blue","red","orange","white")
var/list/icons = list(
"round" = "circle",
"square" = "square",
"diamond" = "gem",
"heart" = "heart",
"dog" = "dog",
"human" = "user",
)
var/icon = pick(icons)
var/list/colors = list(
"toggle" = "pink",
"switch" = "yellow",
"lever" = "red",
"button" = "black",
"pad" = "white",
"hole" = "black",
)
var/color = pick(colors)
var/button_desc = "a [background], [icon] shaped [color]"
var/type = pick(viables)
viables.Remove(type)
construction[button_desc] = type
tgui_construction.Add(list(list(
"key" = button_desc,
"background" = background,
"icon" = icons[icon],
"foreground" = colors[color],
)))
fail_message = "<font color='blue'>[bicon(src)] a [pick("loud","soft","sinister","eery","triumphant","depressing","cheerful","angry")] \
[pick("horn","beep","bing","bleep","blat","honk","hrumph","ding")] sounds and a \
@@ -114,15 +138,38 @@
last_process_time = world.time
/obj/machinery/replicator/attack_hand(mob/user as mob)
interact(user)
tgui_interact(user)
/obj/machinery/replicator/interact(mob/user)
var/dat = "The control panel displays an incomprehensible selection of controls, many with unusual markings or text around them.<br>"
dat += "<br>"
for(var/index=1, index<=construction.len, index++)
dat += "<A href='?src=\ref[src];activate=[index]'>\[[construction[index]]\]</a><br>"
/obj/machinery/replicator/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "XenoarchReplicator", name)
ui.open()
user << browse(dat, "window=alien_replicator")
/obj/machinery/replicator/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["tgui_construction"] = tgui_construction
return data
/obj/machinery/replicator/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("construct")
var/key = params["key"]
if(key in construction)
if(LAZYLEN(stored_materials) > LAZYLEN(spawning_types))
if(LAZYLEN(spawning_types))
visible_message("<span class='notice'>[bicon(src)] a [pick("light","dial","display","meter","pad")] on [src]'s front [pick("blinks","flashes")] [pick("red","yellow","blue","orange","purple","green","white")].</span>")
else
visible_message("<span class='notice'>[bicon(src)] [src]'s front compartment slides shut.</span>")
spawning_types.Add(construction[key])
spawn_progress_time = 0
update_use_power(USE_POWER_ACTIVE)
icon_state = "borgcharger1(old)"
else
visible_message(fail_message)
/obj/machinery/replicator/attackby(obj/item/weapon/W as obj, mob/living/user as mob)
if(!W.canremove || !user.canUnEquip(W)) //No armblades, no grabs. No other-thing-I-didn't-think-of.
@@ -132,21 +179,3 @@
W.loc = src
stored_materials.Add(W)
src.visible_message("<span class='notice'>\The [user] inserts \the [W] into \the [src].</span>")
/obj/machinery/replicator/Topic(href, href_list)
if(href_list["activate"])
var/index = text2num(href_list["activate"])
if(index > 0 && index <= construction.len)
if(stored_materials.len > spawning_types.len)
if(spawning_types.len)
src.visible_message("<span class='notice'>[bicon(src)] a [pick("light","dial","display","meter","pad")] on [src]'s front [pick("blinks","flashes")] [pick("red","yellow","blue","orange","purple","green","white")].</span>")
else
src.visible_message("<span class='notice'>[bicon(src)] [src]'s front compartment slides shut.</span>")
spawning_types.Add(construction[construction[index]])
spawn_progress_time = 0
update_use_power(USE_POWER_ACTIVE)
icon_state = "borgcharger1(old)"
else
src.visible_message(fail_message)
@@ -54,35 +54,73 @@
return ..()
/obj/item/weapon/anodevice/attack_self(var/mob/user as mob)
return src.interact(user)
return tgui_interact(user)
/obj/item/weapon/anodevice/interact(var/mob/user)
var/dat = "<b>Anomalous Materials Energy Utiliser</b><br>"
/obj/item/weapon/anodevice/tgui_state(mob/user)
return GLOB.tgui_inventory_state
/obj/item/weapon/anodevice/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "XenoarchHandheldPowerUtilizer", name)
ui.open()
/obj/item/weapon/anodevice/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["inserted_battery"] = inserted_battery
data["anomaly"] = null
data["charge"] = null
data["capacity"] = null
data["timeleft"] = null
data["activated"] = null
data["duration"] = null
data["interval"] = null
if(inserted_battery)
if(activated)
dat += "Device active.<br>"
data["anomaly"] = inserted_battery?.battery_effect?.artifact_id
data["charge"] = inserted_battery.stored_charge
data["capacity"] = inserted_battery.capacity
data["timeleft"] = round(max((time_end - last_process) / 10, 0))
data["activated"] = activated
data["duration"] = duration / 10
data["interval"] = interval / 10
dat += "[inserted_battery] inserted, anomaly ID: [inserted_battery.battery_effect.artifact_id ? inserted_battery.battery_effect.artifact_id : "NA"]<BR>"
dat += "<b>Charge:</b> [inserted_battery.stored_charge] / [inserted_battery.capacity]<BR>"
dat += "<b>Time left activated:</b> [round(max((time_end - last_process) / 10, 0))]<BR>"
if(activated)
dat += "<a href='?src=\ref[src];shutdown=1'>Shutdown</a><br>"
else
dat += "<A href='?src=\ref[src];startup=1'>Start</a><BR>"
dat += "<BR>"
return data
dat += "<b>Activate duration (sec):</b> <A href='?src=\ref[src];changetime=-100;duration=1'>--</a> <A href='?src=\ref[src];changetime=-10;duration=1'>-</a> [duration/10] <A href='?src=\ref[src];changetime=10;duration=1'>+</a> <A href='?src=\ref[src];changetime=100;duration=1'>++</a><BR>"
dat += "<b>Activate interval (sec):</b> <A href='?src=\ref[src];changetime=-100;interval=1'>--</a> <A href='?src=\ref[src];changetime=-10;interval=1'>-</a> [interval/10] <A href='?src=\ref[src];changetime=10;interval=1'>+</a> <A href='?src=\ref[src];changetime=100;interval=1'>++</a><BR>"
dat += "<br>"
dat += "<A href='?src=\ref[src];ejectbattery=1'>Eject battery</a><BR>"
else
dat += "Please insert battery<br>"
/obj/item/weapon/anodevice/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
dat += "<hr>"
dat += "<a href='?src=\ref[src];refresh=1'>Refresh</a> <a href='?src=\ref[src];close=1'>Close</a>"
user << browse(dat, "window=anodevice;size=400x500")
onclose(user, "anodevice")
switch(action)
if("changeduration")
duration = clamp(text2num(params["duration"]), 0, 300)
if(activated)
time_end = world.time + duration
return TRUE
if("changeinterval")
interval = clamp(text2num(params["interval"]), 0, 100)
return TRUE
if("startup")
if(inserted_battery && inserted_battery.battery_effect && (inserted_battery.stored_charge > 0))
activated = TRUE
visible_message("<font color='blue'>[bicon(src)] [src] whirrs.</font>", "[bicon(src)]<font color='blue'>You hear something whirr.</font>")
if(!inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate(1)
time_end = world.time + duration
last_process = world.time
else
to_chat(usr, "<span class='warning'>[src] is unable to start due to no anomolous power source inserted/remaining.</span>")
return TRUE
if("shutdown")
activated = FALSE
return TRUE
if("ejectbattery")
if(inserted_battery)
inserted_battery.forceMove(get_turf(src))
inserted_battery = null
UpdateSprite()
shutdown_emission()
return TRUE
/obj/item/weapon/anodevice/process()
if(activated)
@@ -150,45 +188,9 @@
/obj/item/weapon/anodevice/proc/shutdown_emission()
if(activated)
activated = 0
if(inserted_battery.battery_effect.activated)
if(inserted_battery?.battery_effect?.activated)
inserted_battery.battery_effect.ToggleActivate(1)
/obj/item/weapon/anodevice/Topic(href, href_list)
if(href_list["changetime"])
var/timedif = text2num(href_list["changetime"])
if(href_list["duration"])
duration += timedif
//max 30 sec duration
duration = min(max(duration, 0), 300)
if(activated)
time_end += timedif
else if(href_list["interval"])
interval += timedif
//max 10 sec interval
interval = min(max(interval, 0), 100)
if(href_list["startup"])
if(inserted_battery && inserted_battery.battery_effect && (inserted_battery.stored_charge > 0) )
activated = 1
src.visible_message("<font color='blue'>[bicon(src)] [src] whirrs.</font>", "[bicon(src)]<font color='blue'>You hear something whirr.</font>")
if(!inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate(1)
time_end = world.time + duration
last_process = world.time
if(href_list["shutdown"])
activated = 0
if(href_list["ejectbattery"])
shutdown_emission()
inserted_battery.loc = get_turf(src)
inserted_battery = null
UpdateSprite()
if(href_list["close"])
usr << browse(null, "window=anodevice")
else if(ismob(src.loc))
var/mob/M = src.loc
src.interact(M)
..()
/obj/item/weapon/anodevice/proc/UpdateSprite()
if(!inserted_battery)
icon_state = "anodev"
@@ -205,8 +207,8 @@
if (!istype(M))
return
if(activated && inserted_battery.battery_effect.effect == EFFECT_TOUCH && !isnull(inserted_battery))
inserted_battery.battery_effect.DoEffectTouch(M)
if(activated && inserted_battery?.battery_effect?.effect == EFFECT_TOUCH && !isnull(inserted_battery))
inserted_battery?.battery_effect?.DoEffectTouch(M)
inserted_battery.use_power(energy_consumed_on_touch)
user.visible_message("<font color='blue'>[user] taps [M] with [src], and it shudders on contact.</font>")
else
@@ -216,5 +218,5 @@
user.lastattacked = M
M.lastattacker = user
if(inserted_battery.battery_effect)
add_attack_logs(user,M,"Anobattery tap ([inserted_battery.battery_effect.name])")
if(inserted_battery?.battery_effect)
add_attack_logs(user,M,"Anobattery tap ([inserted_battery?.battery_effect?.name])")
@@ -24,35 +24,68 @@
if(!owned_scanner)
owned_scanner = locate(/obj/machinery/artifact_scanpad) in orange(1, src)
/obj/machinery/artifact_analyser/attack_hand(var/mob/user as mob)
src.add_fingerprint(user)
interact(user)
/obj/machinery/artifact_analyser/interact(mob/user)
/obj/machinery/artifact_analyser/attack_hand(mob/user)
add_fingerprint(user)
if(stat & (NOPOWER|BROKEN) || get_dist(src, user) > 1)
user.unset_machine(src)
return
tgui_interact(user)
var/dat = "<B>Anomalous material analyser</B><BR>"
dat += "<HR>"
/obj/machinery/artifact_analyser/tgui_interact(mob/user, datum/tgui/ui)
if(!owned_scanner)
reconnect_scanner()
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "XenoarchArtifactAnalyzer", name)
ui.open()
if(!owned_scanner)
dat += "<b><font color=red>Unable to locate analysis pad.</font></b><br>"
else if(scan_in_progress)
dat += "Please wait. Analysis in progress.<br>"
dat += "<a href='?src=\ref[src];halt_scan=1'>Halt scanning.</a><br>"
else
dat += "Scanner is ready.<br>"
dat += "<a href='?src=\ref[src];begin_scan=1'>Begin scanning.</a><br>"
/obj/machinery/artifact_analyser/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
dat += "<br>"
dat += "<hr>"
dat += "<a href='?src=\ref[src]'>Refresh</a> <a href='?src=\ref[src];close=1'>Close</a>"
user << browse(dat, "window=artanalyser;size=450x500")
user.set_machine(src)
onclose(user, "artanalyser")
data["owned_scanner"] = owned_scanner
data["scan_in_progress"] = scan_in_progress
return data
/obj/machinery/artifact_analyser/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
add_fingerprint(usr)
switch(action)
if("scan")
if(scan_in_progress)
scan_in_progress = FALSE
atom_say("Scanning halted.")
return TRUE
if(!owned_scanner)
reconnect_scanner()
if(owned_scanner)
var/artifact_in_use = 0
for(var/obj/O in owned_scanner.loc)
if(O == owned_scanner)
continue
if(O.invisibility)
continue
if(istype(O, /obj/machinery/artifact))
var/obj/machinery/artifact/A = O
if(A.being_used)
artifact_in_use = 1
else
A.anchored = 1
A.being_used = 1
if(artifact_in_use)
atom_say("Cannot scan. Too much interference.")
else
scanned_object = O
scan_in_progress = 1
scan_completion_time = world.time + scan_duration
atom_say("Scanning begun.")
break
if(!scanned_object)
atom_say("Unable to isolate scan target.")
return TRUE
/obj/machinery/artifact_analyser/process()
if(scan_in_progress && world.time > scan_completion_time)
@@ -69,7 +102,7 @@
else
results = get_scan_info(scanned_object)
src.visible_message("<b>[name]</b> states, \"Scanning complete.\"")
atom_say("Scanning complete.")
var/obj/item/weapon/paper/P = new(src.loc)
P.name = "[src] report #[++report_num]"
P.info = "<b>[src] analysis report #[report_num]</b><br>"
@@ -84,46 +117,6 @@
A.being_used = 0
scanned_object = null
/obj/machinery/artifact_analyser/Topic(href, href_list)
if(href_list["begin_scan"])
if(!owned_scanner)
reconnect_scanner()
if(owned_scanner)
var/artifact_in_use = 0
for(var/obj/O in owned_scanner.loc)
if(O == owned_scanner)
continue
if(O.invisibility)
continue
if(istype(O, /obj/machinery/artifact))
var/obj/machinery/artifact/A = O
if(A.being_used)
artifact_in_use = 1
else
A.anchored = 1
A.being_used = 1
if(artifact_in_use)
src.visible_message("<b>[name]</b> states, \"Cannot scan. Too much interference.\"")
else
scanned_object = O
scan_in_progress = 1
scan_completion_time = world.time + scan_duration
src.visible_message("<b>[name]</b> states, \"Scanning begun.\"")
break
if(!scanned_object)
src.visible_message("<b>[name]</b> states, \"Unable to isolate scan target.\"")
if(href_list["halt_scan"])
scan_in_progress = 0
src.visible_message("<b>[name]</b> states, \"Scanning halted.\"")
if(href_list["close"])
usr.unset_machine(src)
usr << browse(null, "window=artanalyser")
..()
updateDialog()
//hardcoded responses, oh well
/obj/machinery/artifact_analyser/proc/get_scan_info(var/obj/scanned_obj)
switch(scanned_obj.type)
@@ -26,47 +26,194 @@
user.drop_item()
I.loc = src
src.inserted_battery = I
updateDialog()
SStgui.update_uis(src)
else
to_chat(user, "<font color='red'>There is already a battery in [src].</font>")
else
return..()
/obj/machinery/artifact_harvester/attack_hand(var/mob/user as mob)
src.add_fingerprint(user)
interact(user)
/obj/machinery/artifact_harvester/interact(var/mob/user as mob)
add_fingerprint(user)
if(stat & (NOPOWER|BROKEN))
return
user.set_machine(src)
var/dat = "<B>Artifact Power Harvester</B><BR>"
dat += "<HR><BR>"
//
if(owned_scanner)
if(harvesting)
if(harvesting > 0)
dat += "Please wait. Harvesting in progress ([round((inserted_battery.stored_charge/inserted_battery.capacity)*100)]%).<br>"
else
dat += "Please wait. Energy dump in progress ([round((inserted_battery.stored_charge/inserted_battery.capacity)*100)]%).<br>"
dat += "<A href='?src=\ref[src];stopharvest=1'>Halt early</A><BR>"
else
if(inserted_battery)
dat += "<b>[inserted_battery.name]</b> inserted, charge level: [inserted_battery.stored_charge]/[inserted_battery.capacity] ([(inserted_battery.stored_charge/inserted_battery.capacity)*100]%)<BR>"
dat += "<b>Energy signature ID:</b>[inserted_battery.battery_effect ? (inserted_battery.battery_effect.artifact_id == "" ? "???" : "[inserted_battery.battery_effect.artifact_id]") : "NA"]<BR>"
dat += "<A href='?src=\ref[src];ejectbattery=1'>Eject battery</a><BR>"
dat += "<A href='?src=\ref[src];drainbattery=1'>Drain battery of all charge</a><BR>"
dat += "<A href='?src=\ref[src];harvest=1'>Begin harvesting</a><BR>"
tgui_interact(user)
/obj/machinery/artifact_harvester/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "XenoarchArtifactHarvester", name)
ui.open()
/obj/machinery/artifact_harvester/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["info"] = list(
"no_scanner" = TRUE,
)
if(owned_scanner)
data["info"] = list(
"no_scanner" = FALSE,
"harvesting" = harvesting,
"inserted_battery" = list(),
)
if(inserted_battery)
data["info"]["inserted_battery"] = list(
"name" = inserted_battery.name,
"stored_charge" = inserted_battery.stored_charge,
"capacity" = inserted_battery.capacity,
"artifact_id" = null
)
if(inserted_battery.battery_effect)
data["info"]["inserted_battery"]["artifact_id"] = inserted_battery.battery_effect.artifact_id || "???"
else
dat += "No battery inserted.<BR>"
else
dat += "<B><font color=red>Unable to locate analysis pad.</font><BR></b>"
//
dat += "<HR>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh</A> <A href='?src=\ref[src];close=1'>Close<BR>"
user << browse(dat, "window=artharvester;size=450x500")
onclose(user, "artharvester")
data["info"]["inserted_battery"]["artifact_id"] = "N/A"
return data
/obj/machinery/artifact_harvester/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
add_fingerprint(usr)
switch(action)
if("harvest")
harvest()
return TRUE
if("stopharvest")
if(harvesting)
if(harvesting < 0 && inserted_battery.battery_effect && inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate()
harvesting = 0
cur_artifact.anchored = 0
cur_artifact.being_used = 0
cur_artifact = null
atom_say("Energy harvesting interrupted.")
icon_state = "incubator"
return TRUE
if("ejectbattery")
if(inserted_battery)
inserted_battery.forceMove(loc)
inserted_battery = null
return TRUE
if("drainbattery")
if(inserted_battery)
if(inserted_battery.battery_effect && inserted_battery.stored_charge > 0)
if(alert("This action will dump all charge, safety gear is recommended before proceeding","Warning","Continue","Cancel"))
if(!inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate(1)
last_process = world.time
harvesting = -1
update_use_power(USE_POWER_ACTIVE)
icon_state = "incubator_on"
atom_say("Warning, battery charge dump commencing.")
else
atom_say("Cannot dump energy. Battery is drained of charge already.")
else
atom_say("Cannot dump energy. No battery inserted.")
return TRUE
/obj/machinery/artifact_harvester/proc/harvest()
if(!inserted_battery)
atom_say("Cannot harvest. No battery inserted.")
return
if(inserted_battery.stored_charge >= inserted_battery.capacity)
atom_say("Cannot harvest. Battery is full.")
return
//locate artifact on analysis pad
cur_artifact = null
var/articount = 0
var/obj/machinery/artifact/analysed
for(var/obj/machinery/artifact/A in get_turf(owned_scanner))
analysed = A
articount++
if(articount <= 0)
atom_say("Cannot harvest. No noteworthy energy signature isolated.")
return
if(analysed && analysed.being_used)
atom_say("Cannot harvest. Source already being harvested.")
return
if(articount > 1)
atom_say("Cannot harvest. Too many artifacts on the pad.")
return
if(analysed)
cur_artifact = analysed
//if both effects are active, we can't harvest either
if(cur_artifact.my_effect && cur_artifact.my_effect.activated && cur_artifact.secondary_effect && cur_artifact.secondary_effect.activated)
atom_say("Cannot harvest. Source is emitting conflicting energy signatures.")
return
if(!cur_artifact.my_effect.activated && !(cur_artifact.secondary_effect && cur_artifact.secondary_effect.activated))
atom_say("Cannot harvest. No energy emitting from source.")
return
//see if we can clear out an old effect
//delete it when the ids match to account for duplicate ids having different effects
if(inserted_battery.battery_effect && inserted_battery.stored_charge <= 0)
qdel(inserted_battery.battery_effect)
inserted_battery.battery_effect = null
//
var/datum/artifact_effect/source_effect
//if we already have charge in the battery, we can only recharge it from the source artifact
if(inserted_battery.stored_charge > 0)
var/battery_matches_primary_id = 0
if(inserted_battery.battery_effect && inserted_battery.battery_effect.artifact_id == cur_artifact.my_effect.artifact_id)
battery_matches_primary_id = 1
if(battery_matches_primary_id && cur_artifact.my_effect.activated)
//we're good to recharge the primary effect!
source_effect = cur_artifact.my_effect
var/battery_matches_secondary_id = 0
if(inserted_battery.battery_effect && inserted_battery.battery_effect.artifact_id == cur_artifact.secondary_effect.artifact_id)
battery_matches_secondary_id = 1
if(battery_matches_secondary_id && cur_artifact.secondary_effect.activated)
//we're good to recharge the secondary effect!
source_effect = cur_artifact.secondary_effect
if(!source_effect)
atom_say("Cannot harvest. Battery is charged with a different energy signature.")
else
//we're good to charge either
if(cur_artifact.my_effect.activated)
//charge the primary effect
source_effect = cur_artifact.my_effect
else if(cur_artifact.secondary_effect.activated)
//charge the secondary effect
source_effect = cur_artifact.secondary_effect
if(source_effect)
harvesting = 1
update_use_power(USE_POWER_ACTIVE)
cur_artifact.anchored = 1
cur_artifact.being_used = 1
icon_state = "incubator_on"
atom_say("Beginning energy harvesting.")
last_process = world.time
//duplicate the artifact's effect datum
if(!inserted_battery.battery_effect)
var/effecttype = source_effect.type
var/datum/artifact_effect/E = new effecttype(inserted_battery)
//duplicate it's unique settings
for(var/varname in list("chargelevelmax","artifact_id","effect","effectrange","trigger"))
E.vars[varname] = source_effect.vars[varname]
//copy the new datum into the battery
inserted_battery.battery_effect = E
inserted_battery.stored_charge = 0
/obj/machinery/artifact_harvester/process()
if(stat & (NOPOWER|BROKEN))
@@ -111,143 +258,3 @@
inserted_battery.battery_effect.ToggleActivate()
src.visible_message("<b>[name]</b> states, \"Battery dump completed.\"")
icon_state = "incubator"
/obj/machinery/artifact_harvester/Topic(href, href_list)
if (href_list["harvest"])
if(!inserted_battery)
src.visible_message("<b>[src]</b> states, \"Cannot harvest. No battery inserted.\"")
else if(inserted_battery.stored_charge >= inserted_battery.capacity)
src.visible_message("<b>[src]</b> states, \"Cannot harvest. battery is full.\"")
else
//locate artifact on analysis pad
cur_artifact = null
var/articount = 0
var/obj/machinery/artifact/analysed
for(var/obj/machinery/artifact/A in get_turf(owned_scanner))
analysed = A
articount++
if(articount <= 0)
var/message = "<b>[src]</b> states, \"Cannot harvest. No noteworthy energy signature isolated.\""
src.visible_message(message)
else if(analysed && analysed.being_used)
src.visible_message("<b>[src]</b> states, \"Cannot harvest. Source already being harvested.\"")
else
if(articount > 1)
state("Cannot harvest. Too many artifacts on the pad.")
else if(analysed)
cur_artifact = analysed
//if both effects are active, we can't harvest either
if(cur_artifact.my_effect && cur_artifact.my_effect.activated && cur_artifact.secondary_effect && cur_artifact.secondary_effect.activated)
src.visible_message("<b>[src]</b> states, \"Cannot harvest. Source is emitting conflicting energy signatures.\"")
else if(!cur_artifact.my_effect.activated && !(cur_artifact.secondary_effect && cur_artifact.secondary_effect.activated))
src.visible_message("<b>[src]</b> states, \"Cannot harvest. No energy emitting from source.\"")
else
//see if we can clear out an old effect
//delete it when the ids match to account for duplicate ids having different effects
if(inserted_battery.battery_effect && inserted_battery.stored_charge <= 0)
qdel(inserted_battery.battery_effect)
inserted_battery.battery_effect = null
//
var/datum/artifact_effect/source_effect
//if we already have charge in the battery, we can only recharge it from the source artifact
if(inserted_battery.stored_charge > 0)
var/battery_matches_primary_id = 0
if(inserted_battery.battery_effect && inserted_battery.battery_effect.artifact_id == cur_artifact.my_effect.artifact_id)
battery_matches_primary_id = 1
if(battery_matches_primary_id && cur_artifact.my_effect.activated)
//we're good to recharge the primary effect!
source_effect = cur_artifact.my_effect
var/battery_matches_secondary_id = 0
if(inserted_battery.battery_effect && inserted_battery.battery_effect.artifact_id == cur_artifact.secondary_effect.artifact_id)
battery_matches_secondary_id = 1
if(battery_matches_secondary_id && cur_artifact.secondary_effect.activated)
//we're good to recharge the secondary effect!
source_effect = cur_artifact.secondary_effect
if(!source_effect)
src.visible_message("<b>[src]</b> states, \"Cannot harvest. Battery is charged with a different energy signature.\"")
else
//we're good to charge either
if(cur_artifact.my_effect.activated)
//charge the primary effect
source_effect = cur_artifact.my_effect
else if(cur_artifact.secondary_effect.activated)
//charge the secondary effect
source_effect = cur_artifact.secondary_effect
if(source_effect)
harvesting = 1
update_use_power(USE_POWER_ACTIVE)
cur_artifact.anchored = 1
cur_artifact.being_used = 1
icon_state = "incubator_on"
var/message = "<b>[src]</b> states, \"Beginning energy harvesting.\""
src.visible_message(message)
last_process = world.time
//duplicate the artifact's effect datum
if(!inserted_battery.battery_effect)
var/effecttype = source_effect.type
var/datum/artifact_effect/E = new effecttype(inserted_battery)
//duplicate it's unique settings
for(var/varname in list("chargelevelmax","artifact_id","effect","effectrange","trigger"))
E.vars[varname] = source_effect.vars[varname]
//copy the new datum into the battery
inserted_battery.battery_effect = E
inserted_battery.stored_charge = 0
if (href_list["stopharvest"])
if(harvesting)
if(harvesting < 0 && inserted_battery.battery_effect && inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate()
harvesting = 0
cur_artifact.anchored = 0
cur_artifact.being_used = 0
cur_artifact = null
src.visible_message("<b>[name]</b> states, \"Energy harvesting interrupted.\"")
icon_state = "incubator"
if (href_list["ejectbattery"])
src.inserted_battery.loc = src.loc
src.inserted_battery = null
if (href_list["drainbattery"])
if(inserted_battery)
if(inserted_battery.battery_effect && inserted_battery.stored_charge > 0)
if(alert("This action will dump all charge, safety gear is recommended before proceeding","Warning","Continue","Cancel"))
if(!inserted_battery.battery_effect.activated)
inserted_battery.battery_effect.ToggleActivate(1)
last_process = world.time
harvesting = -1
update_use_power(USE_POWER_ACTIVE)
icon_state = "incubator_on"
var/message = "<b>[src]</b> states, \"Warning, battery charge dump commencing.\""
src.visible_message(message)
else
var/message = "<b>[src]</b> states, \"Cannot dump energy. Battery is drained of charge already.\""
src.visible_message(message)
else
var/message = "<b>[src]</b> states, \"Cannot dump energy. No battery inserted.\""
src.visible_message(message)
if(href_list["close"])
usr << browse(null, "window=artharvester")
usr.unset_machine(src)
updateDialog()
@@ -59,9 +59,6 @@
coolant_reagents_purity["coolant"] = 1
coolant_reagents_purity["adminordrazine"] = 2
/obj/machinery/radiocarbon_spectrometer/attack_hand(var/mob/user as mob)
ui_interact(user)
/obj/machinery/radiocarbon_spectrometer/attackby(var/obj/I as obj, var/mob/user as mob)
if(scanning)
to_chat(user, "<span class='warning'>You can't do that while [src] is scanning!</span>")
@@ -118,13 +115,19 @@
if(total_purity && fresh_coolant)
coolant_purity = total_purity / fresh_coolant
/obj/machinery/radiocarbon_spectrometer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
/obj/machinery/radiocarbon_spectrometer/attack_hand(mob/user)
tgui_interact(user)
if(user.stat)
return
/obj/machinery/radiocarbon_spectrometer/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "XenoarchSpectrometer", name)
ui.open()
/obj/machinery/radiocarbon_spectrometer/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
// this is the data which will be sent to the ui
var/data[0]
data["scanned_item"] = (scanned_item ? scanned_item.name : "")
data["scanned_item_desc"] = (scanned_item ? (scanned_item.desc ? scanned_item.desc : "No information on record.") : "")
data["last_scan_data"] = last_scan_data
@@ -136,31 +139,62 @@
data["scanner_rpm"] = round(scanner_rpm)
data["scanner_temperature"] = round(scanner_temperature)
//
data["coolant_usage_rate"] = "[coolant_usage_rate]"
data["coolant_usage_rate"] = coolant_usage_rate
data["coolant_usage_max"] = 10
data["unused_coolant_abs"] = round(fresh_coolant)
data["unused_coolant_per"] = round(fresh_coolant / reagents.maximum_volume * 100)
data["coolant_purity"] = "[coolant_purity * 100]"
data["coolant_purity"] = coolant_purity * 100
//
data["optimal_wavelength"] = round(optimal_wavelength)
data["maser_wavelength"] = round(maser_wavelength)
data["maser_wavelength_max"] = 10000
data["maser_efficiency"] = round(maser_efficiency * 100)
//
data["radiation"] = round(radiation)
data["t_left_radspike"] = round(t_left_radspike)
data["rad_shield_on"] = rad_shield
// update the ui if it exists, returns null if no ui is passed/found
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "geoscanner.tmpl", "High Res Radiocarbon Spectrometer", 900, 825)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every Master Controller tick
ui.set_auto_update(1)
return data
/obj/machinery/radiocarbon_spectrometer/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
add_fingerprint(usr)
switch(action)
if("scanItem")
if(scanning)
stop_scanning()
else
if(scanned_item)
if(scanner_seal_integrity > 0)
scanner_progress = 0
scanning = 1
t_left_radspike = pick(5,10,15)
to_chat(usr, "<span class='notice'>Scan initiated.</span>")
else
to_chat(usr, "<span class='warning'>Could not initiate scan, seal requires replacing.</span>")
else
to_chat(usr, "<span class='warning'>Insert an item to scan.</span>")
return TRUE
if("maserWavelength")
maser_wavelength = clamp(text2num(params["wavelength"]), 1, 10000)
return TRUE
if("coolantRate")
coolant_usage_rate = clamp(text2num(params["coolant"]), 0, 10)
return TRUE
if("toggle_rad_shield")
rad_shield = !rad_shield
return TRUE
if("ejectItem")
if(scanned_item)
scanned_item.forceMove(loc)
scanned_item = null
return TRUE
/obj/machinery/radiocarbon_spectrometer/process()
if(scanning)
@@ -323,42 +357,3 @@
scanned_item.loc = src.loc
scanned_item = null
/obj/machinery/radiocarbon_spectrometer/Topic(href, href_list)
if(stat & (NOPOWER|BROKEN))
return 0 // don't update UIs attached to this object
if(href_list["scanItem"])
if(scanning)
stop_scanning()
else
if(scanned_item)
if(scanner_seal_integrity > 0)
scanner_progress = 0
scanning = 1
t_left_radspike = pick(5,10,15)
to_chat(usr, "<span class='notice'>Scan initiated.</span>")
else
to_chat(usr, "<span class='warning'>Could not initiate scan, seal requires replacing.</span>")
else
to_chat(usr, "<span class='warning'>Insert an item to scan.</span>")
if(href_list["maserWavelength"])
maser_wavelength = max(min(maser_wavelength + 1000 * text2num(href_list["maserWavelength"]), 10000), 1)
if(href_list["coolantRate"])
coolant_usage_rate = max(min(coolant_usage_rate + text2num(href_list["coolantRate"]), 10000), 0)
if(href_list["toggle_rad_shield"])
if(rad_shield)
rad_shield = 0
else
rad_shield = 1
if(href_list["ejectItem"])
if(scanned_item)
scanned_item.loc = src.loc
scanned_item = null
add_fingerprint(usr)
return 1 // update UIs attached to this object
@@ -6,125 +6,90 @@
density = 1
req_access = list(access_research)
var/obj/item/weapon/cell/cell
var/obj/item/weapon/card/id/auth_card
var/locked = 1
var/locked = TRUE
var/power_use = 5
var/obj/effect/suspension_field/suspension_field
/obj/machinery/suspension_gen/New()
..()
src.cell = new /obj/item/weapon/cell/high(src)
/obj/machinery/suspension_gen/Initialize()
. = ..()
cell = new /obj/item/weapon/cell/high(src)
/obj/machinery/suspension_gen/process()
if(suspension_field)
cell.charge -= power_use
var/turf/T = get_turf(suspension_field)
for(var/mob/living/M in T)
M.Weaken(3)
cell.charge -= power_use
if(prob(5))
to_chat(M, "<span class='warning'>[pick("You feel tingly","You feel like floating","It is hard to speak","You can barely move")].</span>")
for(var/obj/item/I in T)
if(!suspension_field.contents.len)
suspension_field.icon_state = "energynet"
suspension_field.overlays += "shield2"
I.forceMove(suspension_field)
if(cell.charge <= 0)
deactivate()
/obj/machinery/suspension_gen/interact(var/mob/user)
var/dat = "<b>Multi-phase mobile suspension field generator MK II \"Steadfast\"</b><br>"
if(cell)
var/colour = "red"
if(cell.charge / cell.maxcharge > 0.66)
colour = "green"
else if(cell.charge / cell.maxcharge > 0.33)
colour = "orange"
dat += "<b>Energy cell</b>: <font color='[colour]'>[100 * cell.charge / cell.maxcharge]%</font><br>"
else
dat += "<b>Energy cell</b>: None<br>"
if(auth_card)
dat += "<A href='?src=\ref[src];ejectcard=1'>\[[auth_card]\]<a><br>"
if(!locked)
dat += "<b><A href='?src=\ref[src];toggle_field=1'>[suspension_field ? "Disable" : "Enable"] field</a></b><br>"
else
dat += "<br>"
else
dat += "<A href='?src=\ref[src];insertcard=1'>\[------\]<a><br>"
if(!locked)
dat += "<b><A href='?src=\ref[src];toggle_field=1'>[suspension_field ? "Disable" : "Enable"] field</a></b><br>"
else
dat += "Enter your ID to begin.<br>"
dat += "<hr>"
dat += "<hr>"
dat += "<font color='blue'><b>Always wear safety gear and consult a field manual before operation.</b></font><br>"
if(!locked)
dat += "<A href='?src=\ref[src];lock=1'>Lock console</A><br>"
else
dat += "<br>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh console</A><br>"
dat += "<A href='?src=\ref[src];close=1'>Close console</A>"
user << browse(dat, "window=suspension;size=500x400")
onclose(user, "suspension")
/obj/machinery/suspension_gen/Topic(href, href_list)
..()
usr.set_machine(src)
if(href_list["toggle_field"])
if(!suspension_field)
if(cell.charge > 0)
if(anchored)
activate()
if(cell.use(power_use))
var/turf/T = get_turf(suspension_field)
for(var/mob/living/M in T)
if(cell.use(power_use))
M.Weaken(3)
if(prob(5))
to_chat(M, "<span class='warning'>[pick("You feel tingly","You feel like floating","It is hard to speak","You can barely move")].</span>")
else
to_chat(usr, "<span class='warning'>You are unable to activate [src] until it is properly secured on the ground.</span>")
deactivate()
for(var/obj/item/I in T)
if(!suspension_field.contents.len)
suspension_field.icon_state = "energynet"
suspension_field.overlays += "shield2"
I.forceMove(suspension_field)
else
deactivate()
else if(href_list["insertcard"])
var/obj/item/I = usr.get_active_hand()
if (istype(I, /obj/item/weapon/card))
usr.drop_item()
I.loc = src
auth_card = I
if(attempt_unlock(I, usr))
to_chat(usr, "<span class='info'>You insert [I], the console flashes \'<i>Access granted.</i>\'</span>")
else
to_chat(usr, "<span class='warning'>You insert [I], the console flashes \'<i>Access denied.</i>\'</span>")
else if(href_list["ejectcard"])
if(auth_card)
if(ishuman(usr))
auth_card.loc = usr.loc
if(!usr.get_active_hand())
usr.put_in_hands(auth_card)
auth_card = null
else
auth_card.loc = loc
auth_card = null
else if(href_list["lock"])
locked = 1
else if(href_list["close"])
usr.unset_machine()
usr << browse(null, "window=suspension")
updateUsrDialog()
/obj/machinery/suspension_gen/attack_hand(var/mob/user)
if(!panel_open)
interact(user)
else if(cell)
cell.loc = loc
cell.add_fingerprint(user)
cell.update_icon()
if(panel_open)
if(cell)
to_chat(user, "<span class='notice'>You remove [cell].</span>")
cell.forceMove(loc)
cell.add_fingerprint(user)
cell.update_icon()
icon_state = "suspension0"
cell = null
to_chat(user, "<span class='info'>You remove the power cell</span>")
icon_state = "suspension0"
cell = null
return
/obj/machinery/suspension_gen/attackby(obj/item/weapon/W as obj, mob/user as mob)
tgui_interact(user)
/obj/machinery/suspension_gen/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "XenoarchSuspension", name)
ui.open()
/obj/machinery/suspension_gen/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["cell"] = cell
data["cellCharge"] = cell?.charge
data["cellMaxCharge"] = cell?.maxcharge
data["locked"] = locked
data["suspension_field"] = suspension_field
return data
/obj/machinery/suspension_gen/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("toggle_field")
if(locked)
return
if(!suspension_field)
if(cell.charge > 0)
if(anchored)
activate()
else
to_chat(usr, "<span class='warning'>You are unable to activate [src] until it is properly secured on the ground.</span>")
else
deactivate()
return TRUE
if("lock")
if(allowed(usr))
locked = !locked
return TRUE
/obj/machinery/suspension_gen/attackby(obj/item/W, mob/user)
if(!locked && !suspension_field && default_deconstruction_screwdriver(user, W))
return
else if(W.is_wrench())
@@ -134,45 +99,36 @@
else
anchored = 1
playsound(src, W.usesound, 50, 1)
to_chat(user, "<span class='info'>You wrench the stabilising legs [anchored ? "into place" : "up against the body"].</span>")
to_chat(user, "<span class='notice'>You wrench the stabilising legs [anchored ? "into place" : "up against the body"].</span>")
if(anchored)
desc = "It is resting securely on four stubby legs."
else
desc = "It has stubby legs bolted up against it's body for stabilising."
else
to_chat(user, "<span class='warning'>You are unable to secure [src] while it is active!</span>")
else if (istype(W, /obj/item/weapon/cell))
to_chat(user, "<span class='warning'>You are unable to unsecure [src] while it is active!</span>")
else if(istype(W, /obj/item/weapon/cell))
if(panel_open)
if(cell)
to_chat(user, "<span class='warning'>There is a power cell already installed.</span>")
else
user.drop_item()
W.loc = src
return
if(user.unEquip(W))
W.forceMove(src)
cell = W
to_chat(user, "<span class='info'>You insert the power cell.</span>")
to_chat(user, "<span class='notice'>You insert [cell].</span>")
icon_state = "suspension1"
else if(istype(W, /obj/item/weapon/card))
var/obj/item/weapon/card/I = W
if(!auth_card)
if(attempt_unlock(I, user))
to_chat(user, "<span class='info'>You swipe [I], the console flashes \'<i>Access granted.</i>\'</span>")
else
to_chat(user, "<span class='warning'>You swipe [I], console flashes \'<i>Access denied.</i>\'</span>")
else if(istype(W, /obj/item/weapon/card/emag))
return W.resolve_attackby(src, user)
else
if(check_access(W))
locked = !locked
to_chat(user, "<span class='notice'>You [locked ? "lock" : "unlock"] [src].</span>")
else
to_chat(user, "<span class='warning'>Remove [auth_card] first.</span>")
/obj/machinery/suspension_gen/proc/attempt_unlock(var/obj/item/weapon/card/C, var/mob/user)
if(!panel_open)
if(istype(C, /obj/item/weapon/card/emag))
C.resolve_attackby(src, user)
else if(istype(C, /obj/item/weapon/card/id) && check_access(C))
locked = 0
if(!locked)
return 1
to_chat(user, "<span class='warning'>[src] flashes \'<i>Access denied.</i>\'</span>")
return
/obj/machinery/suspension_gen/emag_act(var/remaining_charges, var/mob/user)
if(cell.charge > 0 && locked)
locked = 0
if(locked)
locked = FALSE
return 1
//checks for whether the machine can be activated or not should already have occurred by this point
@@ -181,11 +137,11 @@
var/collected = 0
for(var/mob/living/M in T)
M.weakened += 5
M.visible_message("<font color='blue'>[bicon(M)] [M] begins to float in the air!</font>","You feel tingly and light, but it is difficult to move.")
M.Weaken(5)
M.visible_message("<span class='notice'>[bicon(M)] [M] begins to float in the air!</span>","You feel tingly and light, but it is difficult to move.")
suspension_field = new(T)
src.visible_message("<font color='blue'>[bicon(src)] [src] activates with a low hum.</font>")
visible_message("<span class='notice'>[bicon(src)] [src] activates with a low hum.</span>")
icon_state = "suspension3"
for(var/obj/item/I in T)
@@ -195,7 +151,7 @@
if(collected)
suspension_field.icon_state = "energynet"
suspension_field.overlays += "shield2"
src.visible_message("<font color='blue'>[bicon(suspension_field)] [suspension_field] gently absconds [collected > 1 ? "something" : "several things"].</font>")
visible_message("<span class='notice'>[bicon(suspension_field)] [suspension_field] gently absconds [collected > 1 ? "something" : "several things"].</span>")
else
if(istype(T,/turf/simulated/mineral) || istype(T,/turf/simulated/wall))
suspension_field.icon_state = "shieldsparkles"
@@ -207,10 +163,10 @@
var/turf/T = get_turf(suspension_field)
for(var/mob/living/M in T)
to_chat(M, "<span class='info'>You no longer feel like floating.</span>")
to_chat(M, "<span class='notice'>You no longer feel like floating.</span>")
M.Weaken(3)
src.visible_message("<font color='blue'>[bicon(src)] [src] deactivates with a gentle shudder.</font>")
visible_message("<span class='notice'>[bicon(src)] [src] deactivates with a gentle shudder.</span>")
qdel(suspension_field)
suspension_field = null
icon_state = "suspension2"
@@ -225,9 +181,9 @@
set category = "Object"
if(anchored)
to_chat(usr, "<font color='red'>You cannot rotate [src], it has been firmly fixed to the floor.</font>")
to_chat(usr, "<span class='warning'>You cannot rotate [src], it has been firmly fixed to the floor.</span>")
return
src.set_dir(turn(src.dir, 90))
set_dir(turn(dir, 90))
/obj/machinery/suspension_gen/verb/rotate_clockwise()
set src in view(1)
@@ -235,9 +191,9 @@
set category = "Object"
if(anchored)
to_chat(usr, "<font color='red'>You cannot rotate [src], it has been firmly fixed to the floor.</font>")
to_chat(usr, "<span class='warning'>You cannot rotate [src], it has been firmly fixed to the floor.</span>")
return
src.set_dir(turn(src.dir, 270))
set_dir(turn(dir, 270))
/obj/effect/suspension_field
name = "energy field"
+89 -83
View File
@@ -154,66 +154,69 @@
to_chat(user, "<span class='notice'>[bicon(src)] [src] pings [pick("madly","wildly","excitedly","crazily")]!</span>")
/obj/item/device/depth_scanner/attack_self(var/mob/living/user)
interact(user)
tgui_interact(user)
/obj/item/device/depth_scanner/interact(var/mob/user as mob)
var/dat = "<b>Coordinates with positive matches</b><br>"
/obj/item/device/depth_scanner/tgui_state(mob/user)
return GLOB.tgui_deep_inventory_state
dat += "<A href='?src=\ref[src];clear=0'>== Clear all ==</a><br>"
/obj/item/device/depth_scanner/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "XenoarchDepthScanner", name)
ui.open()
/obj/item/device/depth_scanner/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
data["current"] = list()
if(current)
dat += "Time: [current.time]<br>"
dat += "Coords: [current.coords]<br>"
dat += "Anomaly depth: [current.depth] cm<br>"
dat += "Anomaly size: [current.clearance] cm<br>"
dat += "Dissonance spread: [current.dissonance_spread]<br>"
data["current"] = list(
"time" = current.time,
"coords" = current.coords,
"depth" = current.depth,
"clearance" = current.clearance,
"dissonance_spread" = current.dissonance_spread,
"index" = current.record_index,
)
data["current"]["material"] = "Unknown"
var/index = responsive_carriers.Find(current.material)
if(index > 0 && index <= finds_as_strings.len)
dat += "Anomaly material: [finds_as_strings[index]]<br>"
else
dat += "Anomaly material: Unknown<br>"
dat += "<A href='?src=\ref[src];clear=[current.record_index]'>clear entry</a><br>"
else
dat += "Select an entry from the list<br>"
dat += "<br><br><br><br>"
dat += "<hr>"
if(positive_locations.len)
for(var/index = 1 to positive_locations.len)
var/datum/depth_scan/D = positive_locations[index]
dat += "<A href='?src=\ref[src];select=[index]'>[D.time], coords: [D.coords]</a><br>"
else
dat += "No entries recorded."
if(index > 0 && index <= LAZYLEN(finds_as_strings))
data["current"]["material"] = finds_as_strings[index]
dat += "<hr>"
dat += "<A href='?src=\ref[src];refresh=1'>Refresh</a><br>"
dat += "<A href='?src=\ref[src];close=1'>Close</a><br>"
user << browse(dat,"window=depth_scanner;size=300x500")
onclose(user, "depth_scanner")
var/list/plocs = list()
data["positive_locations"] = plocs
for(var/i in 1 to LAZYLEN(positive_locations))
var/datum/depth_scan/D = positive_locations[i]
plocs.Add(list(list(
"index" = i,
"time" = D.time,
"coords" = D.coords,
)))
/obj/item/device/depth_scanner/Topic(href, href_list)
..()
usr.set_machine(src)
return data
if(href_list["select"])
var/index = text2num(href_list["select"])
if(index && index <= positive_locations.len)
current = positive_locations[index]
else if(href_list["clear"])
var/index = text2num(href_list["clear"])
if(index)
if(index <= positive_locations.len)
var/datum/depth_scan/D = positive_locations[index]
positive_locations.Remove(D)
qdel(D)
else
//GC will hopefully pick them up before too long
positive_locations = list()
qdel(current)
else if(href_list["close"])
usr.unset_machine()
usr << browse(null, "window=depth_scanner")
/obj/item/device/depth_scanner/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
updateSelfDialog()
switch(action)
if("select")
var/index = text2num(params["select"])
if(index && index <= LAZYLEN(positive_locations))
current = positive_locations[index]
return TRUE
if("clear")
var/index = text2num(params["clear"])
if(index)
if(index <= LAZYLEN(positive_locations))
var/datum/depth_scan/D = positive_locations[index]
positive_locations.Remove(D)
qdel(D)
current = null
else
QDEL_LIST_NULL(positive_locations)
QDEL_NULL(current)
return TRUE
/obj/item/device/beacon_locator
name = "locater device"
@@ -273,43 +276,46 @@
else
icon_state = "pinoff"
/obj/item/device/beacon_locator/attack_self(var/mob/user as mob)
return src.interact(user)
/obj/item/device/beacon_locator/attack_self(mob/user)
return tgui_interact(user)
/obj/item/device/beacon_locator/interact(var/mob/user as mob)
var/dat = "<b>Radio frequency tracker</b><br>"
dat += {"
<A href='byond://?src=\ref[src];reset_tracking=1'>Reset tracker</A><BR>
Frequency:
<A href='byond://?src=\ref[src];freq=-10'>-</A>
<A href='byond://?src=\ref[src];freq=-2'>-</A>
[format_frequency(frequency)]
<A href='byond://?src=\ref[src];freq=2'>+</A>
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
"}
/obj/item/device/beacon_locator/tgui_state(mob/user)
return GLOB.tgui_inventory_state
dat += "<A href='?src=\ref[src];close=1'>Close</a><br>"
user << browse(dat,"window=locater;size=300x150")
onclose(user, "locater")
/obj/item/device/beacon_locator/tgui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "BeaconLocator", name)
ui.open()
/obj/item/device/beacon_locator/Topic(href, href_list)
..()
usr.set_machine(src)
/obj/item/device/beacon_locator/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state)
var/list/data = ..()
if(href_list["reset_tracking"])
scan_ticks = 1
target_radio = null
else if(href_list["freq"])
var/new_frequency = (frequency + text2num(href_list["freq"]))
if (frequency < 1200 || frequency > 1600)
new_frequency = sanitize_frequency(new_frequency, 1499)
frequency = new_frequency
data["scan_ticks"] = scan_ticks
data["degrees"] = null
if(target_radio)
data["degrees"] = round(Get_Angle(get_turf(src), get_turf(target_radio)))
else if(href_list["close"])
usr.unset_machine()
usr << browse(null, "window=locater")
data["rawfreq"] = frequency
data["minFrequency"] = RADIO_LOW_FREQ
data["maxFrequency"] = RADIO_HIGH_FREQ
updateSelfDialog()
return data
/obj/item/device/beacon_locator/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("reset_tracking")
scan_ticks = 1
target_radio = null
return TRUE
if("setFrequency")
var/new_frequency = (text2num(params["freq"]))
new_frequency = sanitize_frequency(new_frequency, RADIO_LOW_FREQ, RADIO_HIGH_FREQ)
frequency = new_frequency
return TRUE
/obj/item/device/xenoarch_multi_tool
name = "xenoarcheology multitool"
@@ -330,7 +336,7 @@
depth_scanner = new/obj/item/device/depth_scanner(src)
/obj/item/device/xenoarch_multi_tool/attack_self(var/mob/living/user)
depth_scanner.interact(user)
depth_scanner.tgui_interact(user)
/obj/item/device/xenoarch_multi_tool/verb/swap_settings(var/mob/living/user)
set name = "Swap Functionality"
+1 -1
View File
@@ -4681,7 +4681,7 @@
"bMa" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/structure/disposalpipe/segment,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMb" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/manifold/hidden/scrubbers,/obj/machinery/atmospherics/pipe/manifold/hidden/supply{dir = 1},/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMc" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/machinery/mecha_part_fabricator,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMd" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/machinery/pros_fabricator,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMd" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/machinery/mecha_part_fabricator/pros,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMe" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/obj/structure/table/standard,/obj/item/device/robotanalyzer,/obj/item/device/robotanalyzer,/obj/item/device/mmi/digital/robot,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMf" = (/obj/structure/cable/green{d1 = 4; d2 = 8; icon_state = "4-8"},/obj/structure/cable/green{d1 = 1; d2 = 8; icon_state = "1-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 4},/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/tiled,/area/assembly/robotics)
"bMg" = (/obj/structure/cable/green{d1 = 2; d2 = 8; icon_state = "2-8"},/obj/machinery/atmospherics/pipe/simple/hidden/supply{dir = 10},/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers{dir = 10},/obj/effect/floor_decal/industrial/warning{dir = 1},/turf/simulated/floor/tiled,/area/assembly/robotics)
+1 -1
View File
@@ -1080,7 +1080,7 @@
/turf/simulated/floor/tiled/white,
/area/ship/aro/centralarea)
"cr" = (
/obj/machinery/pros_fabricator{
/obj/machinery/mecha_part_fabricator/pros{
req_access = list()
},
/turf/simulated/floor/tiled/techmaint,
+1 -1
View File
@@ -6192,7 +6192,7 @@
/turf/simulated/floor/tiled/steel_grid,
/area/mothership/rnd)
"mm" = (
/obj/machinery/pros_fabricator,
/obj/machinery/mecha_part_fabricator/pros,
/turf/simulated/floor/tiled/steel_grid,
/area/mothership/rnd)
"mn" = (
+1 -1
View File
@@ -5242,7 +5242,7 @@
"bWP" = (/obj/effect/floor_decal/industrial/warning{dir = 4},/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/machinery/power/apc{dir = 8; name = "west bump"; pixel_x = -24},/obj/machinery/light_switch{pixel_x = -36},/obj/structure/cable/green,/turf/simulated/floor/tiled/white,/area/assembly/robotics)
"bWQ" = (/obj/machinery/mecha_part_fabricator,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bWR" = (/obj/effect/floor_decal/industrial/outline/yellow,/obj/structure/table/steel_reinforced,/obj/item/device/robotanalyzer,/obj/item/device/robotanalyzer,/obj/item/device/mmi/digital/robot,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bWS" = (/obj/machinery/pros_fabricator,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bWS" = (/obj/machinery/mecha_part_fabricator/pros,/obj/effect/floor_decal/industrial/outline/yellow,/turf/simulated/floor/tiled,/area/assembly/robotics)
"bWT" = (/obj/machinery/camera/network/research{c_tag = "SCI - Robotics"; dir = 1},/turf/simulated/floor/tiled/white,/area/assembly/robotics)
"bWU" = (/obj/effect/floor_decal/industrial/warning{dir = 8},/obj/machinery/firealarm{dir = 1; pixel_x = 0; pixel_y = -24},/turf/simulated/floor/tiled/techfloor,/area/assembly/robotics)
"bWV" = (/obj/machinery/atmospherics/pipe/simple/hidden/scrubbers,/obj/machinery/atmospherics/pipe/simple/hidden/supply,/obj/structure/cable/green{d1 = 1; d2 = 2; icon_state = "1-2"},/turf/simulated/floor/tiled/techfloor,/area/assembly/robotics)
+1 -1
View File
@@ -1983,7 +1983,7 @@
/turf/unsimulated/floor/steel,
/area/centcom/control)
"dT" = (
/obj/machinery/pros_fabricator,
/obj/machinery/mecha_part_fabricator/pros,
/turf/unsimulated/floor/steel,
/area/centcom/control)
"dU" = (
+1 -1
View File
@@ -215,7 +215,7 @@
/turf/simulated/floor/tiled/steel_dirty,
/area/submap/virgo2/Lab1)
"J" = (
/obj/machinery/pros_fabricator,
/obj/machinery/mecha_part_fabricator/pros,
/turf/simulated/floor/tiled/steel_dirty,
/area/submap/virgo2/Lab1)
"K" = (
+1 -1
View File
@@ -586,7 +586,7 @@
/turf/simulated/floor/tiled/techfloor/virgo2,
/area/submap/virgo2/Rockybase)
"cb" = (
/obj/machinery/pros_fabricator,
/obj/machinery/mecha_part_fabricator/pros,
/turf/simulated/floor/tiled/techfloor/virgo2,
/area/submap/virgo2/Rockybase)
"cc" = (
@@ -215,7 +215,7 @@
/turf/simulated/floor/tiled/steel_dirty,
/area/submap/Lab1)
"K" = (
/obj/machinery/pros_fabricator,
/obj/machinery/mecha_part_fabricator/pros,
/turf/simulated/floor/tiled/steel_dirty,
/area/submap/Lab1)
"L" = (
@@ -142,7 +142,7 @@
"cL" = (/mob/living/simple_mob/mechanical/mecha/combat/gygax/dark/advanced{faction = "malf_drone"},/turf/simulated/floor/tiled,/area/submap/Rockybase)
"cM" = (/obj/machinery/drone_fabricator{fabricator_tag = "Unknown"},/turf/simulated/floor/tiled,/area/submap/Rockybase)
"cN" = (/obj/machinery/mecha_part_fabricator,/turf/simulated/floor/tiled,/area/submap/Rockybase)
"cO" = (/obj/machinery/pros_fabricator,/turf/simulated/floor/tiled,/area/submap/Rockybase)
"cO" = (/obj/machinery/mecha_part_fabricator/pros,/turf/simulated/floor/tiled,/area/submap/Rockybase)
"cP" = (/obj/structure/table/standard,/obj/item/mecha_parts/mecha_equipment/repair_droid,/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/explosive,/turf/simulated/floor/tiled,/area/submap/Rockybase)
"cQ" = (/obj/machinery/light{dir = 8},/turf/simulated/floor/tiled,/area/submap/Rockybase)
"cR" = (/obj/effect/decal/cleanable/dirt,/obj/structure/cable{d1 = 1; d2 = 2; icon_state = "1-2"; pixel_y = 0},/obj/structure/cable{d1 = 1; d2 = 4; icon_state = "1-4"},/mob/living/simple_mob/mechanical/combat_drone/lesser,/turf/simulated/floor/tiled,/area/submap/Rockybase)
+3 -3
View File
@@ -17687,15 +17687,15 @@
/turf/simulated/floor/plating,
/area/maintenance/lower/atmos)
"aId" = (
/obj/machinery/pros_fabricator{
/obj/machinery/mecha_part_fabricator/pros{
desc = "A machine used for construction of legit prosthetics. You weren't sure if cardboard was considered an engineering material until now.";
dir = 4;
emagged = 0;
mat_efficiency = 0.9;
component_coeff = 0.9;
name = "Legitimate Prosthetics Fabricator";
req_access = list();
res_max_amount = 150000;
speed = 0.2
time_coeff = 0.2
},
/turf/simulated/floor/plating,
/area/maintenance/lower/atmos)
+1 -1
View File
@@ -16760,7 +16760,7 @@
/turf/simulated/floor/tiled/steel_grid,
/area/assembly/robotics)
"aCv" = (
/obj/machinery/pros_fabricator{
/obj/machinery/mecha_part_fabricator/pros{
dir = 1
},
/obj/structure/reagent_dispensers/acid{
-56
View File
@@ -1,56 +0,0 @@
<!--
Title: Bioballistic Delivery System UI
Used In File(s): \code\modules\hydroponics\seed_machines.dm
-->
{{if data.activity}}
Scanning...
{{else}}
<h3>Buffered Genetic Data</h3>
{{if data.disk}}
<div class="item">
<div class="itemLabel">
Source:
</div>
<div class="itemContent">
{{:data.sourceName}}
</div>
<div class="itemLabel">
Gene decay:
</div>
<div class="itemContent">
{{if data.degradation <= 100}}
{{:data.degradation}}%
{{else}}
<font = '#FF0000'><b>FURTHER AMENDMENTS NONVIABLE</b></font>
{{/if}}
</div>
<div class="itemLabel">
Locus:
</div>
<div class="itemContent">
{{:data.locus}}
</div>
{{:helper.link('Eject Disk', 'circle-arrow-e', {'eject_disk' : 1}, null)}}
</div>
{{else}}
<div class="notice">No disk loaded.</div>
{{/if}}
<h3>Loaded Material</h3>
{{if data.loaded}}
<div class = "item">
<div class = "itemLabel">
Target:
</div>
<div class = "itemContent">
{{:data.loaded}}
</div>
{{if data.degradation <= 100}}
{{:helper.link('Apply Gene Mods', 'gear', {'apply_gene' : 1}, null)}}
{{/if}}
{{:helper.link('Eject Target', 'circle-arrow-e', {'eject_packet' : 1}, null)}}
</div>
{{else}}
<div class="notice">No target seed packet loaded</div>
{{/if}}
{{/if}}
-73
View File
@@ -1,73 +0,0 @@
<!--
Title: Lysis-isolation Centrifuge UI
Used In File(s): \code\modules\hydroponics\seed_machines.dm
-->
{{if data.activity}}
Scanning...
{{else}}
<h3>Buffered Genetic Data</h3>
{{if data.hasGenetics}}
<div class="item">
<div class="itemLabel">
Source:
</div>
<div class="itemContent">
{{:data.sourceName}}
</div>
<div class="itemLabel">
Gene decay:
</div>
<div class="itemContent">
{{:data.degradation}}%
</div>
</div>
{{if data.disk}}
{{for data.geneMasks}}
<div class="item">
<div class="itemLabel">
{{:value.mask}}
</div>
<div class="itemContent">
{{:helper.link('Extract', 'circle-arrow-s', {'get_gene' : value.tag}, null)}}
</div>
</div>
{{empty}}
<div class="notice">Data error. Genetic record corrupt.</div>
{{/for}}
<br>
<div class="item">
{{:helper.link('Eject Loaded Disk', 'circle-arrow-e', {'eject_disk' : 1}, null)}}
{{:helper.link('Clear Genetic Buffer', 'gear', {'clear_buffer' : 1}, null)}}
</div>
{{else}}
<div class="notice">No disk inserted.</div>
{{/if}}
{{else}}
<div class="notice">No data buffered.</div>
{{if data.disk}}
<br>
<div class="item">
{{:helper.link('Eject Loaded Disk', 'circle-arrow-e', {'eject_disk' : 1}, null)}}
</div>
{{else}}
<div class="notice">No disk inserted.</div>
{{/if}}
{{/if}}
<h3>Loaded Material</h3>
{{if data.loaded}}
<div class="item">
<div class="itemLabel">
Packet loaded:
</div>
<div class="itemContent">
{{:data.loaded}}
</div>
<div class="item">
{{:helper.link('Process Genome', 'gear', {'scan_genome' : 1}, null)}}{{:helper.link('Eject Packet', 'circle-arrow-e', {'eject_packet' : 1}, null)}}
</div>
</div>
{{else}}
<div class="notice">No seeds loaded.</div>
{{/if}}
{{/if}}
-185
View File
@@ -1,185 +0,0 @@
<!--
Title: Radiometric Scanner UI
Used In File(s): \code\modules\research\xenoarchaeology\machinery\geosample_scanner.dm
-->
<h3>Machine Status</h3>
<div class="item">
<div class="itemContent" style="width: 20%;">
{{:helper.link(data.scanning ? 'Halt Scan' : 'Begin Scan', 'signal-diag', {'scanItem' : 1}, null)}}
</div>
<div class="itemContent" style="width: 20%;">
{{:helper.link('Eject item', 'eject', {'ejectItem' : 1}, (data.scanned_item && !data.scanning) ? null : 'disabled')}}
</div>
</div>
<div class="statusDisplay">
<div class="line">
<div class="statusLabel">Item:</div>
<div class="statusValue">
{{if data.scanned_item}}
<span class="good">{{:data.scanned_item}}</span>
{{else}}
<span class="bad">No item inserted</span>
{{/if}}
</div>
</div>
<div class="line">
<div class="statusLabel">Heuristic analysis:</div>
<div class="statusValue">
{{if data.scanned_item_desc}}
<span class="average">{{:data.scanned_item_desc}}</span>
{{/if}}
</div>
</div>
</div>
<h3>Scanner</h3>
<div class="item">
<div class="itemLabel" style="width: 21%;">Scan progress:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.scan_progress, 0, 100, 'good')}}
{{:data.scan_progress}} %
</div>
<div class="itemContent" style="width: 44%;">
{{if data.scan_progress >= 100}}
<span class="notice" style="width: 100%;">Scan completed successfully.</span>
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel" style="width: 21%;">Vacuum seal integrity:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.scanner_seal_integrity, 0, 100, ((data.scanner_seal_integrity < 66) ? ((data.scanner_seal_integrity < 33) ? 'bad' : 'average') : 'good'))}}
{{:data.scanner_seal_integrity}} %
</div>
<div class="itemContent" style="width: 44%;">
{{if data.scanner_seal_integrity < 25}}
<span class="notice">Warning! Vacuum seal breach will result in scan failure!</span>
{{/if}}
</div>
</div>
<h3>MASER</h3>
<div class="item">
<div class="itemLabel" style="width: 21%;">MASER Efficiency:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.maser_efficiency, 1, 100, ((data.maser_efficiency < 66) ? ((data.maser_efficiency) < 33 ? 'bad' : 'average') : 'good'))}}
{{:data.maser_efficiency}} %
</div>
<div class="itemContent" style="width: 44%;">
{{if data.maser_efficiency < 50}}
<span class="notice">Match wavelengths to progress the scan.</span>
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel" style="width: 21%;">Optimal Wavelength:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.optimal_wavelength, 1, 10000, 'good')}}
{{:data.optimal_wavelength}} MHz
</div>
</div>
<div class="item">
<div class="itemLabel" style="width: 21%;">Current Wavelength:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.maser_wavelength, 1, 10000, 'good')}}
{{:data.maser_wavelength}} MHz
</div>
<div class="itemContent" style="text-align:left; width: 22%;">
{{:helper.link('-2 GHz', null, {'maserWavelength' : -2}, null)}}
{{:helper.link('-1 GHz', null, {'maserWavelength' : -1}, null)}}
{{:helper.link('-0.5 GHz', null, {'maserWavelength' : -0.5}, null)}}
</div>
<div class="itemContent" style="text-align:right; width: 22%;">
{{:helper.link('+0.5 GHz', null, {'maserWavelength' : 0.5}, null)}}
{{:helper.link('+1 GHz', null, {'maserWavelength' : 1}, null)}}
{{:helper.link('+2 GHz', null, {'maserWavelength' : 2}, null)}}
</div>
</div>
<h3>Environment / Internal</h3>
<div class="item">
<div class="itemLabel" style="width: 21%;">Centrifuge speed:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.scanner_rpm, 0, 1000, 'good')}}
{{:data.scanner_rpm}} RPM
</div>
</div>
<div class="item">
<div class="itemLabel" style="width: 21%;">Internal temperature:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.scanner_temperature, 0, 1273, (data.scanner_temperature > 250 ? (data.scanner_temperature > 1000 ? 'bad' : 'average') : 'good'))}}
{{:data.scanner_temperature}} K
</div>
<div class="itemContent" style="width: 44%;">
{{if data.scanner_temperature > 1000}}
<span class="notice" style="width: 100%;">Warning! Exceeding 1200K will result in scan failure!</span>
{{/if}}
</div>
</div>
<h3>Radiation</h3>
<div class="item">
<div class="itemLabel" style="width: 21%;">Ambient radiation:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.radiation, 0, 100, ((data.radiation > 15) ? ((data.radiation > 65) ? 'bad' : 'average') : 'good'))}}
{{:data.radiation}} mSv
</div>
<div class="itemContent" style="width: 44%;">
{{:helper.link(data.rad_shield_on ? 'Disable Radiation Shielding' : 'Enable Radiation Shielding', 'radiation', {'toggle_rad_shield' : 1}, null)}}
{{if data.rad_shield_on}}
<span class="notice" style="width: 100%;">Shield blocking scanner.</span>
{{/if}}
</div>
</div>
<h3>Cooling</h3>
<div class="item">
<div class="itemLabel" style="width: 21%;">Coolant remaining:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.unused_coolant_per, 0, 100, ((data.unused_coolant_per < 66) ? ((data.unused_coolant_per < 33) ? 'bad' : 'average') : 'good'))}}
{{:data.unused_coolant_abs}} u
</div>
<div class="itemContent" style="width: 44%;">
{{if data.unused_coolant_per < 20}}
<span class="notice" style="width: 100%;">Warning! Coolant stocks low!</span>
{{/if}}
</div>
</div>
<div class="item">
<div class="itemLabel" style="width: 21%;">Coolant flow rate:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.coolant_usage_rate, 0, 10, 'good')}}
{{:data.coolant_usage_rate}} u/s
</div>
<div class="itemContent" style="text-align:left; width: 22%;">
{{:helper.link('Min u/s', null, {'coolantRate' : -10}, null)}}
{{:helper.link('-3 u/s', null, {'coolantRate' : -3}, null)}}
{{:helper.link('-1 u/s', null, {'coolantRate' : -1}, null)}}
</div>
<div class="itemContent" style="text-align:right; width: 22%;">
{{:helper.link('+1 u/s', null, {'coolantRate' : 1}, null)}}
{{:helper.link('+3 u/s', null, {'coolantRate' : 3}, null)}}
{{:helper.link('Max u/s', null, {'coolantRate' : 10}, null)}}
</div>
</div>
<div class="item">
<div class="itemLabel" style="width: 21%;">Coolant purity:</div>
<div class="itemContent" style="width: 35%;">
{{:helper.displayBar(data.coolant_purity, 0, 100, ((data.coolant_purity < 66) ? ((data.coolant_purity < 33) ? 'bad' : 'average') : 'good'))}}
{{:data.coolant_purity}} %
</div>
<div class="itemContent" style="width: 44%;">
{{if data.coolant_purity < 0.5}}
<span class="notice" style="width: 100%;">Warning! Check coolant for contaminants!</span>
{{/if}}
</div>
</div>
<h3>Latest Results</h3>
<div class="statusDisplay">
<div class="line">
<span class="highlight">{{:data.last_scan_data}}</span>
</div>
</div>
-91
View File
@@ -1,91 +0,0 @@
<div style="float: left; width: 60%;">
<div class="item">
{{:helper.link("Sync", null, {'sync' : 1})}}
{{:data.sync}}
</div>
<hr style="width: 90%;">
{{if data.species_types}}
<div class="item">
{{for data.species_types}}
{{:helper.link(value, null, {'species' : value}, value == data.species ? 'selected' : null)}}
{{/for}}
</div>
<hr style="width: 90%;">
{{/if}}
{{if data.manufacturers}}
<div class="item">
{{for data.manufacturers}}
{{:helper.link(value.company, null, {'manufacturer' : value.id}, value.id == data.manufacturer ? 'selected' : null)}}
{{/for}}
</div>
<hr style="width: 90%;">
{{/if}}
<div class="item">
{{for data.categories}}
{{:helper.link(value, null, {'category' : value}, value == data.category ? 'selected' : null)}}
{{empty}}
There are no known designs
{{/for}}
</div>
<hr style="width: 90%;">
{{for data.buildable}}
{{if value.category == data.category}}
<div class="item">
<div class="itemLabelWide">
{{:helper.link(value.name, null, {'build' : value.id})}}
</div>
<div class="itemContentMedium">
{{:value.resourses}}, {{:value.time}}
</div>
</div>
{{/if}}
{{/for}}
</div>
<div style="float: right; width: 40%">
<div class="item">
<b>Queue contains:</b>
</div>
{{if data.current}}
<div class="item">
<div class="itemLabelWide">
<b>Now: {{:data.current}}</b> ({{:data.builtperc}}% ready)
</div>
<div class="itemContentMedium">
{{:helper.link('Cancel', null, {'remove' : 1})}}
</div>
</div>
{{for data.queue}}
<div class="item">
<div class="itemLabelWide">
{{:index + 2}}: {{:value}}
</div>
<div class="itemContentMedium">
{{:helper.link('Remove', null, {'remove' : index + 2})}}
</div>
{{empty}}
<div class="item">
The queue is empty
</div>
{{/for}}
{{else}}
<div class="item">
Nothing
</div>
{{/if}}
<b>Materials:</b>
{{for data.materials}}
<div class="item">
<div class="itemLabelWide">
{{:value.mat}}: {{:value.amt}}/{{:data.maxres}}
</div>
<div class="itemContentMedium">
{{:helper.link('x1', null, {'eject' : value.mat, 'amount' : 1}, value.amt > 2000 ? null : 'disabled')}}
{{:helper.link('x5', null, {'eject' : value.mat, 'amount' : 5}, value.amt > 10000 ? null : 'disabled')}}
{{:helper.link('x10', null, {'eject' : value.mat, 'amount' : 10}, value.amt > 20000 ? null : 'disabled')}}
{{:helper.link('Stack', null, {'eject' : value.mat, 'amount' : 0})}}
{{:helper.link('All', null, {'eject' : value.mat, 'amount' : -1})}}
</div>
</div>
{{/for}}
</div>

Some files were not shown because too many files have changed in this diff Show More