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
+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')
..()
-114
View File
@@ -1,114 +0,0 @@
//Misc
#define DEAD_PLANT_COLOUR "#C2A180"
#define FROZEN_PLANT_COLOUR "#CCFFFF"
// Definitions for genes (trait groupings)
#define GENE_BIOCHEMISTRY "biochemistry"
#define GENE_HARDINESS "hardiness"
#define GENE_ENVIRONMENT "environment"
#define GENE_METABOLISM "metabolism"
#define GENE_STRUCTURE "appearance"
#define GENE_DIET "diet"
#define GENE_PIGMENT "pigment"
#define GENE_OUTPUT "output"
#define GENE_ATMOSPHERE "atmosphere"
#define GENE_VIGOUR "vigour"
#define GENE_FRUIT "fruit"
#define GENE_SPECIAL "special"
#define ALL_GENES list(GENE_BIOCHEMISTRY,GENE_HARDINESS,GENE_ENVIRONMENT,GENE_METABOLISM,GENE_STRUCTURE,GENE_DIET,GENE_PIGMENT,GENE_OUTPUT,GENE_ATMOSPHERE,GENE_VIGOUR,GENE_FRUIT,GENE_SPECIAL)
//Definitions for traits (individual descriptors)
#define TRAIT_CHEMS 1
#define TRAIT_EXUDE_GASSES 2
#define TRAIT_ALTER_TEMP 3
#define TRAIT_POTENCY 4
#define TRAIT_HARVEST_REPEAT 5
#define TRAIT_PRODUCES_POWER 6
#define TRAIT_JUICY 7
#define TRAIT_PRODUCT_ICON 8
#define TRAIT_PLANT_ICON 0
#define TRAIT_CONSUME_GASSES 10
#define TRAIT_REQUIRES_NUTRIENTS 11
#define TRAIT_NUTRIENT_CONSUMPTION 12
#define TRAIT_REQUIRES_WATER 13
#define TRAIT_WATER_CONSUMPTION 14
#define TRAIT_CARNIVOROUS 15
#define TRAIT_PARASITE 16
#define TRAIT_STINGS 17
#define TRAIT_IDEAL_HEAT 18
#define TRAIT_HEAT_TOLERANCE 19
#define TRAIT_IDEAL_LIGHT 20
#define TRAIT_LIGHT_TOLERANCE 21
#define TRAIT_LOWKPA_TOLERANCE 22
#define TRAIT_HIGHKPA_TOLERANCE 23
#define TRAIT_EXPLOSIVE 24
#define TRAIT_TOXINS_TOLERANCE 25
#define TRAIT_PEST_TOLERANCE 26
#define TRAIT_WEED_TOLERANCE 27
#define TRAIT_ENDURANCE 28
#define TRAIT_YIELD 29
#define TRAIT_SPREAD 30
#define TRAIT_MATURATION 31
#define TRAIT_PRODUCTION 32
#define TRAIT_TELEPORTING 33
#define TRAIT_PLANT_COLOUR 34
#define TRAIT_PRODUCT_COLOUR 35
#define TRAIT_BIOLUM 36
#define TRAIT_BIOLUM_COLOUR 37
#define TRAIT_IMMUTABLE 38
#define TRAIT_FLESH_COLOUR 39
#define TRAIT_SPORING 40
#define TRAIT_BENEFICIAL_REAG 41
#define TRAIT_MUTAGENIC_REAG 42
#define TRAIT_TOXIC_REAG 43
// Global list initialization for plants.
GLOBAL_LIST_INIT(plant_mob_products, list(
/mob/living/simple_mob/creature = 10,
/mob/living/simple_mob/blob/spore = 20,
/mob/living/simple_mob/tomato = 30,
/mob/living/simple_mob/animal/passive/dog = 5,
/mob/living/simple_mob/animal/passive/chicken = 5,
/mob/living/simple_mob/animal/passive/crab = 5,
/mob/living/simple_mob/animal/passive/lizard = 4,
/mob/living/simple_mob/animal/passive/lizard/large = 1,
/mob/living/simple_mob/animal/giant_spider/pepper = 1,
/mob/living/simple_mob/animal/giant_spider/frost = 1,
/mob/living/simple_mob/animal/giant_spider/webslinger = 1,
/mob/living/simple_mob/animal/passive/mouse = 1,
/mob/living/simple_mob/animal/space/carp = 1,
/mob/living/carbon/human/monkey = 1,
/mob/living/carbon/alien/diona = 1
))
GLOBAL_LIST_INIT(plant_item_products, list(
/obj/item/stack/material/cloth = 30,
/obj/item/stack/material/wax = 20,
/obj/item/stack/material/log = 30,
/obj/item/stack/material/resin = 10,
/obj/item/weapon/material/shard/shrapnel = 2,
/obj/item/weapon/ore = 5,
/obj/item/weapon/ore/iron = 2,
/obj/item/weapon/ore/coal = 2,
/obj/item/weapon/reagent_containers/food/snacks/meat = 3,
/obj/random/meat = 1,
/obj/item/weapon/reagent_containers/food/drinks/smallchocmilk = 2,
/obj/item/weapon/reagent_containers/food/drinks/smallmilk = 2,
/obj/item/ammo_casing/a145 = 1,
/obj/item/ammo_casing/chemdart/small = 1,
/obj/item/ammo_casing/chemdart = 1,
/obj/item/organ/internal/brain/grey = 1,
/obj/item/organ/internal/heart/grey = 1,
/obj/item/weapon/spacecash/c1 = 3,
/obj/item/weapon/spacecash/c10 = 1
))
GLOBAL_LIST_INIT(forbidden_plant_growth_sprites, list(
"gnomes"
))
GLOBAL_LIST_INIT(forbidden_plant_product_sprites, list(
"gnomes"
))
+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
-169
View File
@@ -1,169 +0,0 @@
// 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."
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.
var/list/plant_sprites = list() // List of all growth sprites plus number of growth stages.
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
setup()
process()
// 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()
// Build the icon lists.
for(var/icostate in cached_icon_states('icons/obj/hydroponics_growing.dmi'))
var/split = findtext(icostate,"-")
if(!split)
// invalid icon_state
continue
var/ikey = copytext(icostate,(split+1))
if(ikey == "dead")
// don't count dead icons
continue
ikey = text2num(ikey)
var/base = copytext(icostate,1,split)
if(!(plant_sprites[base]) || (plant_sprites[base]<ikey))
plant_sprites[base] = ikey
if(!(base in GLOB.forbidden_plant_growth_sprites))
accessible_plant_sprites[base] = ikey
for(var/icostate in cached_icon_states('icons/obj/hydroponics_products.dmi'))
var/split = findtext(icostate,"-")
var/base = copytext(icostate,1,split)
if(split)
plant_product_sprites |= base
if(!(base in GLOB.forbidden_plant_product_sprites))
accessible_product_sprites |= base
// Populate the global seed datum list.
for(var/type in typesof(/datum/seed)-/datum/seed)
var/datum/seed/S = new type
seeds[S.name] = S
S.uid = "[seeds.len]"
S.roundstart = 1
// Make sure any seed packets that were mapped in are updated
// correctly (since the seed datums did not exist a tick ago).
for(var/obj/item/seeds/S in all_seed_packs)
S.update_seed()
//Might as well mask the gene types while we're at it.
var/list/gene_datums = decls_repository.decls_of_subtype(/decl/plantgene)
var/list/used_masks = list()
var/list/plant_traits = ALL_GENES
while(plant_traits && plant_traits.len)
var/gene_tag = pick(plant_traits)
var/gene_mask = "[uppertext(num2hex(rand(0,255), 2))]"
while(gene_mask in used_masks)
gene_mask = "[uppertext(num2hex(rand(0,255), 2))]"
var/decl/plantgene/G
for(var/D in gene_datums)
var/decl/plantgene/P = gene_datums[D]
if(gene_tag == P.gene_tag)
G = P
gene_datums -= D
used_masks += gene_mask
plant_traits -= gene_tag
gene_tag_masks[gene_tag] = gene_mask
plant_gene_datums[gene_mask] = G
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)
var/datum/seed/seed = new()
seed.randomize()
seed.uid = plant_controller.seeds.len + 1
seed.name = "[seed.uid]"
seeds[seed.name] = seed
if(survive_on_station)
if(seed.consume_gasses)
seed.consume_gasses["phoron"] = null
seed.consume_gasses["carbon_dioxide"] = null
if(seed.chems && !isnull(seed.chems["pacid"]))
seed.chems["pacid"] = null // Eating through the hull will make these plants completely inviable, albeit very dangerous.
seed.chems -= null // Setting to null does not actually remove the entry, which is weird.
seed.set_trait(TRAIT_IDEAL_HEAT,293)
seed.set_trait(TRAIT_HEAT_TOLERANCE,20)
seed.set_trait(TRAIT_IDEAL_LIGHT,8)
seed.set_trait(TRAIT_LIGHT_TOLERANCE,5)
seed.set_trait(TRAIT_LOWKPA_TOLERANCE,25)
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/plants/proc/add_plant(var/obj/effect/plant/plant)
plant_queue |= plant
/datum/controller/plants/proc/remove_plant(var/obj/effect/plant/plant)
plant_queue -= plant
+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"