Merge remote-tracking branch 'upstream/master'

This commit is contained in:
DeltaFire
2020-08-10 18:33:18 +02:00
635 changed files with 16658 additions and 9315 deletions
@@ -18,9 +18,7 @@
/obj/item/mining_scanner, /obj/item/mining_scanner,
/obj/item/flashlight/lantern, /obj/item/flashlight/lantern,
/obj/item/card/id/mining, /obj/item/card/id/mining,
/obj/item/gps/mining{ /obj/item/gps/mining,
tracking = 0
},
/turf/open/floor/plating, /turf/open/floor/plating,
/area/ruin/powered/golem_ship) /area/ruin/powered/golem_ship)
"d" = ( "d" = (
@@ -34,9 +32,7 @@
/obj/item/mining_scanner, /obj/item/mining_scanner,
/obj/item/flashlight/lantern, /obj/item/flashlight/lantern,
/obj/item/card/id/mining, /obj/item/card/id/mining,
/obj/item/gps/mining{ /obj/item/gps/mining,
tracking = 0
},
/turf/open/floor/plating, /turf/open/floor/plating,
/area/ruin/powered/golem_ship) /area/ruin/powered/golem_ship)
"e" = ( "e" = (
@@ -156,9 +152,7 @@
"x" = ( "x" = (
/obj/structure/table/wood, /obj/structure/table/wood,
/obj/machinery/reagentgrinder, /obj/machinery/reagentgrinder,
/obj/item/gps/mining{ /obj/item/gps/mining,
tracking = 0
},
/turf/open/floor/mineral/titanium/purple, /turf/open/floor/mineral/titanium/purple,
/area/ruin/powered/golem_ship) /area/ruin/powered/golem_ship)
"z" = ( "z" = (
@@ -56560,7 +56560,6 @@
}, },
/area/maintenance/bar) /area/maintenance/bar)
"mqZ" = ( "mqZ" = (
/obj/structure/reagent_dispensers/keg/aphro/strong,
/obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/beaker,
/turf/open/floor/plating, /turf/open/floor/plating,
/area/maintenance/bar) /area/maintenance/bar)
@@ -126013,7 +126013,6 @@
/turf/open/floor/plating, /turf/open/floor/plating,
/area/chapel/office) /area/chapel/office)
"ijB" = ( "ijB" = (
/obj/structure/reagent_dispensers/keg/aphro/strong,
/obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/beaker,
/turf/open/floor/plating, /turf/open/floor/plating,
/area/crew_quarters/abandoned_gambling_den) /area/crew_quarters/abandoned_gambling_den)
-1
View File
@@ -44383,7 +44383,6 @@
/turf/open/floor/plasteel/white, /turf/open/floor/plasteel/white,
/area/hallway/primary/aft) /area/hallway/primary/aft)
"bFB" = ( "bFB" = (
/obj/structure/reagent_dispensers/keg/aphro/strong,
/obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/dirt,
/turf/open/floor/wood{ /turf/open/floor/wood{
icon_state = "wood-broken5" icon_state = "wood-broken5"
@@ -60049,7 +60049,6 @@
/turf/open/floor/plasteel/dark, /turf/open/floor/plasteel/dark,
/area/chapel/office) /area/chapel/office)
"tap" = ( "tap" = (
/obj/structure/reagent_dispensers/keg/aphro,
/turf/open/floor/wood, /turf/open/floor/wood,
/area/maintenance/department/crew_quarters/dorms) /area/maintenance/department/crew_quarters/dorms)
"taA" = ( "taA" = (
+1 -1
View File
@@ -2690,7 +2690,7 @@
/obj/structure/rack, /obj/structure/rack,
/obj/item/storage/box/zipties, /obj/item/storage/box/zipties,
/obj/item/assembly/flash/handheld, /obj/item/assembly/flash/handheld,
/obj/item/melee/classic_baton/telescopic, /obj/item/melee/classic_baton,
/obj/machinery/light/small/built{ /obj/machinery/light/small/built{
dir = 8 dir = 8
}, },
+5
View File
@@ -209,6 +209,8 @@
#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands" //from base of mob/swap_hand(): (obj/item) #define COMSIG_MOB_SWAP_HANDS "mob_swap_hands" //from base of mob/swap_hand(): (obj/item)
#define COMPONENT_BLOCK_SWAP 1 #define COMPONENT_BLOCK_SWAP 1
#define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge"
// /client signals // /client signals
#define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client) #define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client)
#define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client) #define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client)
@@ -452,6 +454,9 @@
#define COMPONENT_TWOHANDED_BLOCK_WIELD 1 #define COMPONENT_TWOHANDED_BLOCK_WIELD 1
#define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield" //from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user) #define COMSIG_TWOHANDED_UNWIELD "twohanded_unwield" //from base of datum/component/two_handed/proc/unwield(mob/living/carbon/user): (/mob/user)
// /datum/component/squeak signals
#define COMSIG_CROSS_SQUEAKED "cross_squeaked" // sent when a squeak component squeaks from crossing something, to delay anything else crossing that might squeak to prevent ear hurt.
// /datum/action signals // /datum/action signals
#define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action) #define COMSIG_ACTION_TRIGGER "action_trigger" //from base of datum/action/proc/Trigger(): (datum/action)
#define COMPONENT_ACTION_BLOCK_TRIGGER 1 #define COMPONENT_ACTION_BLOCK_TRIGGER 1
+35
View File
@@ -0,0 +1,35 @@
/// Module is compatible with Security Cyborg models
#define BORG_MODULE_SECURITY (1<<0)
/// Module is compatible with Miner Cyborg models
#define BORG_MODULE_MINER (1<<1)
/// Module is compatible with Janitor Cyborg models
#define BORG_MODULE_JANITOR (1<<2)
/// Module is compatible with Medical Cyborg models
#define BORG_MODULE_MEDICAL (1<<3)
/// Module is compatible with Engineering Cyborg models
#define BORG_MODULE_ENGINEERING (1<<4)
/// Module is compatible with Ripley Exosuit models
#define EXOSUIT_MODULE_RIPLEY (1<<0)
/// Module is compatible with Odyseeus Exosuit models
#define EXOSUIT_MODULE_ODYSSEUS (1<<1)
/// Module is compatible with Clarke Exosuit models. Rebranded to firefighter because tg nerfed it to this.
#define EXOSUIT_MODULE_FIREFIGHTER (1<<2)
// #define EXOSUIT_MODULE_CLARKE (1<<2)
/// Module is compatible with Gygax Exosuit models
#define EXOSUIT_MODULE_GYGAX (1<<3)
/// Module is compatible with Durand Exosuit models
#define EXOSUIT_MODULE_DURAND (1<<4)
/// Module is compatible with H.O.N.K Exosuit models
#define EXOSUIT_MODULE_HONK (1<<5)
/// Module is compatible with Phazon Exosuit models
#define EXOSUIT_MODULE_PHAZON (1<<6)
/// Module is compatable with N models
#define EXOSUIT_MODULE_GYGAX_MED (1<<7)
/// Module is compatible with "Working" Exosuit models - Ripley and Clarke
#define EXOSUIT_MODULE_WORKING EXOSUIT_MODULE_RIPLEY | EXOSUIT_MODULE_FIREFIGHTER // | EXOSUIT_MODULE_CLARKE
/// Module is compatible with "Combat" Exosuit models - Gygax, H.O.N.K, Durand and Phazon
#define EXOSUIT_MODULE_COMBAT EXOSUIT_MODULE_GYGAX | EXOSUIT_MODULE_HONK | EXOSUIT_MODULE_DURAND | EXOSUIT_MODULE_PHAZON
/// Module is compatible with "Medical" Exosuit modelsm - Odysseus
#define EXOSUIT_MODULE_MEDICAL EXOSUIT_MODULE_ODYSSEUS | EXOSUIT_MODULE_GYGAX_MED
+1
View File
@@ -74,6 +74,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
#define ismush(A) (is_species(A, /datum/species/mush)) #define ismush(A) (is_species(A, /datum/species/mush))
#define isshadow(A) (is_species(A, /datum/species/shadow)) #define isshadow(A) (is_species(A, /datum/species/shadow))
#define isskeleton(A) (is_species(A, /datum/species/skeleton)) #define isskeleton(A) (is_species(A, /datum/species/skeleton))
#define isethereal(A) (is_species(A, /datum/species/ethereal))
// Citadel specific species // Citadel specific species
#define isipcperson(A) (is_species(A, /datum/species/ipc)) #define isipcperson(A) (is_species(A, /datum/species/ipc))
+2
View File
@@ -131,6 +131,8 @@
#define LIGHTING_LAYER 15 #define LIGHTING_LAYER 15
#define LIGHTING_RENDER_TARGET "LIGHT_PLANE" #define LIGHTING_RENDER_TARGET "LIGHT_PLANE"
#define RAD_TEXT_LAYER 15.1
#define ABOVE_LIGHTING_PLANE 16 #define ABOVE_LIGHTING_PLANE 16
#define ABOVE_LIGHTING_LAYER 16 #define ABOVE_LIGHTING_LAYER 16
#define ABOVE_LIGHTING_RENDER_TARGET "ABOVE_LIGHTING_PLANE" #define ABOVE_LIGHTING_RENDER_TARGET "ABOVE_LIGHTING_PLANE"
+5 -4
View File
@@ -341,10 +341,11 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S
#define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are. #define COLOUR_PRIORITY_AMOUNT 4 //how many priority levels there are.
//Endgame Results //Endgame Results
#define NUKE_MISS_STATION 1 #define NUKE_NEAR_MISS 1
#define NUKE_SYNDICATE_BASE 2 #define NUKE_MISS_STATION 2
#define STATION_DESTROYED_NUKE 3 #define NUKE_SYNDICATE_BASE 3
#define STATION_EVACUATED 4 #define STATION_DESTROYED_NUKE 4
#define STATION_EVACUATED 5
#define BLOB_WIN 8 #define BLOB_WIN 8
#define BLOB_NUKE 9 #define BLOB_NUKE 9
#define BLOB_DESTROYED 10 #define BLOB_DESTROYED 10
+10
View File
@@ -176,6 +176,15 @@
#define DISGUST_LEVEL_VERYGROSS 50 #define DISGUST_LEVEL_VERYGROSS 50
#define DISGUST_LEVEL_GROSS 25 #define DISGUST_LEVEL_GROSS 25
//Charge levels for Ethereals
#define ETHEREAL_CHARGE_NONE 0
#define ETHEREAL_CHARGE_LOWPOWER 20
#define ETHEREAL_CHARGE_NORMAL 50
#define ETHEREAL_CHARGE_ALMOSTFULL 75
#define ETHEREAL_CHARGE_FULL 100
#define ETHEREAL_CHARGE_OVERLOAD 125
#define ETHEREAL_CHARGE_DANGEROUS 150
//Slime evolution threshold. Controls how fast slimes can split/grow //Slime evolution threshold. Controls how fast slimes can split/grow
#define SLIME_EVOLUTION_THRESHOLD 10 #define SLIME_EVOLUTION_THRESHOLD 10
@@ -284,6 +293,7 @@
#define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you #define DOOR_CRUSH_DAMAGE 15 //the amount of damage that airlocks deal when they crush you
#define HUNGER_FACTOR 0.1 //factor at which mob nutrition decreases #define HUNGER_FACTOR 0.1 //factor at which mob nutrition decreases
#define ETHEREAL_CHARGE_FACTOR 0.08 //factor at which ethereal's charge decreases
#define REAGENTS_METABOLISM 0.4 //How many units of reagent are consumed per tick, by default. #define REAGENTS_METABOLISM 0.4 //How many units of reagent are consumed per tick, by default.
#define REAGENTS_EFFECT_MULTIPLIER (REAGENTS_METABOLISM / 0.4) // By defining the effect multiplier this way, it'll exactly adjust all effects according to how they originally were with the 0.4 metabolism #define REAGENTS_EFFECT_MULTIPLIER (REAGENTS_METABOLISM / 0.4) // By defining the effect multiplier this way, it'll exactly adjust all effects according to how they originally were with the 0.4 metabolism
-1
View File
@@ -8,6 +8,5 @@
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list( GLOBAL_LIST_INIT(blacklisted_pool_reagents, list(
/datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases /datum/reagent/toxin/plasma, /datum/reagent/oxygen, /datum/reagent/nitrous_oxide, /datum/reagent/nitrogen, //gases
/datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc. /datum/reagent/fermi, //blanket fermichem ban sorry. this also covers mkultra, genital enlargers, etc etc.
/datum/reagent/drug/aphrodisiac, /datum/reagent/drug/anaphrodisiac, /datum/reagent/drug/aphrodisiacplus, /datum/reagent/drug/anaphrodisiacplus, //literally asking for prefbreaks
/datum/reagent/consumable/femcum, /datum/reagent/consumable/semen //NO. /datum/reagent/consumable/femcum, /datum/reagent/consumable/semen //NO.
)) ))
+28 -4
View File
@@ -1,4 +1,28 @@
#define UI_INTERACTIVE 2 // Green/Interactive /// Green eye; fully interactive
#define UI_UPDATE 1 // Orange/Updates Only #define UI_INTERACTIVE 2
#define UI_DISABLED 0 // Red/Disabled /// Orange eye; updates but is not interactive
#define UI_CLOSE -1 // Closed #define UI_UPDATE 1
/// Red eye; disabled, does not update
#define UI_DISABLED 0
/// UI Should close
#define UI_CLOSE -1
/// Maximum number of windows that can be suspended/reused
#define TGUI_WINDOW_SOFT_LIMIT 5
/// Maximum number of open windows
#define TGUI_WINDOW_HARD_LIMIT 9
/// Maximum ping timeout allowed to detect zombie windows
#define TGUI_PING_TIMEOUT 4 SECONDS
/// Window does not exist
#define TGUI_WINDOW_CLOSED 0
/// Window was just opened, but is still not ready to be sent data
#define TGUI_WINDOW_LOADING 1
/// Window is free and ready to receive data
#define TGUI_WINDOW_READY 2
/// Get a window id based on the provided pool index
#define TGUI_WINDOW_ID(index) "tgui-window-[index]"
/// Get a pool index of the provided window id
#define TGUI_WINDOW_INDEX(window_id) text2num(copytext(window_id, 13))
+12 -3
View File
@@ -201,9 +201,18 @@
WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------") WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------")
/* ui logging */ /* ui logging */
/proc/log_tgui(user_or_client, text)
/proc/log_tgui(text) var/entry = ""
WRITE_LOG(GLOB.tgui_log, text) if(!user_or_client)
entry += "no user"
else if(istype(user_or_client, /mob))
var/mob/user = user_or_client
entry += "[user.ckey] (as [user])"
else if(istype(user_or_client, /client))
var/client/client = user_or_client
entry += "[client.ckey]"
entry += ":\n[text]"
WRITE_LOG(GLOB.tgui_log, entry)
/* Close open log handles. This should be called as late as possible, and no logging should hapen after. */ /* Close open log handles. This should be called as late as possible, and no logging should hapen after. */
/proc/shutdown_logging() /proc/shutdown_logging()
+9 -6
View File
@@ -85,9 +85,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_advdisease_resistance_asc(datum/disease/advance/A, datum/disease/advance/B) /proc/cmp_advdisease_resistance_asc(datum/disease/advance/A, datum/disease/advance/B)
return A.totalResistance() - B.totalResistance() return A.totalResistance() - B.totalResistance()
/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
return A.display_order - B.display_order
/proc/cmp_uplink_items_dsc(datum/uplink_item/A, datum/uplink_item/B) /proc/cmp_uplink_items_dsc(datum/uplink_item/A, datum/uplink_item/B)
return sorttext(initial(B.name), initial(A.name)) return sorttext(initial(B.name), initial(A.name))
@@ -97,9 +94,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
/proc/cmp_numbered_displays_name_dsc(datum/numbered_display/A, datum/numbered_display/B) /proc/cmp_numbered_displays_name_dsc(datum/numbered_display/A, datum/numbered_display/B)
return sorttext(B.sample_object.name, A.sample_object.name) return sorttext(B.sample_object.name, A.sample_object.name)
/proc/cmp_reagents_asc(datum/reagent/a, datum/reagent/b)
return sorttext(initial(b.name),initial(a.name))
/proc/cmp_quirk_asc(datum/quirk/A, datum/quirk/B) /proc/cmp_quirk_asc(datum/quirk/A, datum/quirk/B)
var/a_sign = num2sign(initial(A.value) * -1) var/a_sign = num2sign(initial(A.value) * -1)
var/b_sign = num2sign(initial(B.value) * -1) var/b_sign = num2sign(initial(B.value) * -1)
@@ -133,3 +127,12 @@ GLOBAL_VAR_INIT(cmp_field, "name")
return A.required_temp - B.required_temp //return coldest return A.required_temp - B.required_temp //return coldest
else else
return B.required_temp - A.required_temp //return hottest return B.required_temp - A.required_temp //return hottest
/proc/cmp_job_display_asc(datum/job/A, datum/job/B)
return A.display_order - B.display_order
/proc/cmp_reagents_asc(datum/reagent/a, datum/reagent/b)
return sorttext(initial(b.name),initial(a.name))
/proc/cmp_typepaths_asc(A, B)
return sorttext("[B]","[A]")
+7
View File
@@ -264,6 +264,13 @@
if(!findname(.)) if(!findname(.))
break break
/proc/random_unique_ethereal_name(attempts_to_find_unique_name=10)
for(var/i in 1 to attempts_to_find_unique_name)
. = capitalize(ethereal_name())
if(!findname(.))
break
/proc/random_unique_moth_name(attempts_to_find_unique_name=10) /proc/random_unique_moth_name(attempts_to_find_unique_name=10)
for(var/i in 1 to attempts_to_find_unique_name) for(var/i in 1 to attempts_to_find_unique_name)
. = capitalize(pick(GLOB.moth_first)) + " " + capitalize(pick(GLOB.moth_last)) . = capitalize(pick(GLOB.moth_first)) + " " + capitalize(pick(GLOB.moth_last))
+6
View File
@@ -4,6 +4,12 @@
else else
return "[pick(GLOB.lizard_names_female)]-[pick(GLOB.lizard_names_female)]" return "[pick(GLOB.lizard_names_female)]-[pick(GLOB.lizard_names_female)]"
/proc/ethereal_name()
var/tempname = "[pick(GLOB.ethereal_names)] [random_capital_letter()]"
if(prob(65))
tempname += random_capital_letter()
return tempname
/proc/plasmaman_name() /proc/plasmaman_name()
return "[pick(GLOB.plasmaman_names)] \Roman[rand(1,99)]" return "[pick(GLOB.plasmaman_names)] \Roman[rand(1,99)]"
+4
View File
@@ -776,6 +776,10 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
else else
return "[number]\th" return "[number]\th"
/proc/random_capital_letter()
return uppertext(pick(GLOB.alphabet))
/proc/unintelligize(message) /proc/unintelligize(message)
var/regex/word_boundaries = regex(@"\b[\S]+\b", "g") var/regex/word_boundaries = regex(@"\b[\S]+\b", "g")
var/prefix = message[1] var/prefix = message[1]
+1
View File
@@ -17,6 +17,7 @@ GLOBAL_LIST_INIT(golem_names, world.file2list("strings/names/golem.txt"))
GLOBAL_LIST_INIT(moth_first, world.file2list("strings/names/moth_first.txt")) GLOBAL_LIST_INIT(moth_first, world.file2list("strings/names/moth_first.txt"))
GLOBAL_LIST_INIT(moth_last, world.file2list("strings/names/moth_last.txt")) GLOBAL_LIST_INIT(moth_last, world.file2list("strings/names/moth_last.txt"))
GLOBAL_LIST_INIT(plasmaman_names, world.file2list("strings/names/plasmaman.txt")) GLOBAL_LIST_INIT(plasmaman_names, world.file2list("strings/names/plasmaman.txt"))
GLOBAL_LIST_INIT(ethereal_names, world.file2list("strings/names/ethereal.txt"))
GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt")) GLOBAL_LIST_INIT(posibrain_names, world.file2list("strings/names/posibrain.txt"))
GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt")) GLOBAL_LIST_INIT(nightmare_names, world.file2list("strings/names/nightmare.txt"))
GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt")) GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt"))
+10
View File
@@ -493,6 +493,16 @@ Recharging stations are available in robotics, the dormitory bathrooms, and the
desc = "Unit's power cell is running low. Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite." desc = "Unit's power cell is running low. Recharging stations are available in robotics, the dormitory bathrooms, and the AI satellite."
icon_state = "lowcell" icon_state = "lowcell"
/obj/screen/alert/etherealcharge
name = "Low Blood Charge"
desc = "Your blood's electric charge is running low, find a source of charge for your blood. Use a recharging station found in robotics or the dormitory bathrooms, or eat some Ethereal-friendly food."
icon_state = "etherealcharge"
/obj/screen/alert/ethereal_overcharge
name = "Blood Overcharge"
desc = "Your blood's electric charge is becoming dangerously high, find an outlet for your energy. Use Grab Intent on an APC to channel your energy into it."
icon_state = "ethereal_overcharge"
//Need to cover all use cases - emag, illegal upgrade module, malf AI hack, traitor cyborg //Need to cover all use cases - emag, illegal upgrade module, malf AI hack, traitor cyborg
/obj/screen/alert/hacked /obj/screen/alert/hacked
name = "Hacked" name = "Hacked"
+7 -5
View File
@@ -775,12 +775,14 @@ SUBSYSTEM_DEF(shuttle)
preview_shuttle = null preview_shuttle = null
/datum/controller/subsystem/shuttle/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.admin_state) /datum/controller/subsystem/shuttle/ui_state(mob/user)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) return GLOB.admin_state
if(!ui)
ui = new(user, src, ui_key, "ShuttleManipulator", name, 800, 600, master_ui, state)
ui.open()
/datum/controller/subsystem/shuttle/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "ShuttleManipulator")
ui.open()
/datum/controller/subsystem/shuttle/ui_data(mob/user) /datum/controller/subsystem/shuttle/ui_data(mob/user)
var/list/data = list() var/list/data = list()
+330 -16
View File
@@ -1,3 +1,12 @@
/**
* tgui subsystem
*
* Contains all tgui state and subsystem code.
*
* Copyright (c) 2020 Aleksej Komarov
* SPDX-License-Identifier: MIT
*/
SUBSYSTEM_DEF(tgui) SUBSYSTEM_DEF(tgui)
name = "tgui" name = "tgui"
wait = 9 wait = 9
@@ -5,33 +14,338 @@ SUBSYSTEM_DEF(tgui)
priority = FIRE_PRIORITY_TGUI priority = FIRE_PRIORITY_TGUI
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
var/list/currentrun = list() /// A list of UIs scheduled to process
var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key. var/list/current_run = list()
var/list/processing_uis = list() // A list of processing UIs, ungrouped. /// A list of open UIs
var/basehtml // The HTML base used for all UIs. var/list/open_uis = list()
/// A list of open UIs, grouped by src_object.
var/list/open_uis_by_src = list()
/// The HTML base used for all UIs.
var/basehtml
/datum/controller/subsystem/tgui/PreInit() /datum/controller/subsystem/tgui/PreInit()
basehtml = file2text('tgui/packages/tgui/public/tgui.html') basehtml = file2text('tgui/packages/tgui/public/tgui.html')
/datum/controller/subsystem/tgui/Shutdown() /datum/controller/subsystem/tgui/Shutdown()
close_all_uis() close_all_uis()
/datum/controller/subsystem/tgui/stat_entry() /datum/controller/subsystem/tgui/stat_entry()
..("P:[processing_uis.len]") ..("P:[open_uis.len]")
/datum/controller/subsystem/tgui/fire(resumed = 0) /datum/controller/subsystem/tgui/fire(resumed = 0)
if (!resumed) if(!resumed)
src.currentrun = processing_uis.Copy() src.current_run = open_uis.Copy()
//cache for sanic speed (lists are references anyways) // Cache for sanic speed (lists are references anyways)
var/list/currentrun = src.currentrun var/list/current_run = src.current_run
while(current_run.len)
while(currentrun.len) var/datum/tgui/ui = current_run[current_run.len]
var/datum/tgui/ui = currentrun[currentrun.len] current_run.len--
currentrun.len-- // TODO: Move user/src_object check to process()
if(ui && ui.user && ui.src_object) if(ui && ui.user && ui.src_object)
ui.process() ui.process()
else else
processing_uis.Remove(ui) open_uis.Remove(ui)
if (MC_TICK_CHECK) if(MC_TICK_CHECK)
return return
/**
* public
*
* Requests a usable tgui window from the pool.
* Returns null if pool was exhausted.
*
* required user mob
* return datum/tgui
*/
/datum/controller/subsystem/tgui/proc/request_pooled_window(mob/user)
if(!user.client)
return null
var/list/windows = user.client.tgui_windows
var/window_id
var/datum/tgui_window/window
var/window_found = FALSE
// Find a usable window
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
window_id = TGUI_WINDOW_ID(i)
window = windows[window_id]
// As we are looping, create missing window datums
if(!window)
window = new(user.client, window_id, pooled = TRUE)
// Skip windows with acquired locks
if(window.locked)
continue
if(window.status == TGUI_WINDOW_READY)
return window
if(window.status == TGUI_WINDOW_CLOSED)
window.status = TGUI_WINDOW_LOADING
window_found = TRUE
break
if(!window_found)
log_tgui(user, "Error: Pool exhausted")
return null
return window
/**
* public
*
* Force closes all tgui windows.
*
* required user mob
*/
/datum/controller/subsystem/tgui/proc/force_close_all_windows(mob/user)
log_tgui(user, "force_close_all_windows")
if(user.client)
user.client.tgui_windows = list()
for(var/i in 1 to TGUI_WINDOW_HARD_LIMIT)
var/window_id = TGUI_WINDOW_ID(i)
user << browse(null, "window=[window_id]")
/**
* public
*
* Force closes the tgui window by window_id.
*
* required user mob
* required window_id string
*/
/datum/controller/subsystem/tgui/proc/force_close_window(mob/user, window_id)
log_tgui(user, "force_close_window")
// Close all tgui datums based on window_id.
for(var/datum/tgui/ui in user.tgui_open_uis)
if(ui.window && ui.window.id == window_id)
ui.close(can_be_suspended = FALSE)
// Unset machine just to be sure.
user.unset_machine()
// Close window directly just to be sure.
user << browse(null, "window=[window_id]")
/**
* public
*
* Try to find an instance of a UI, and push an update to it.
*
* required user mob The mob who opened/is using the UI.
* required src_object datum The object/datum which owns the UI.
* optional ui datum/tgui The UI to be updated, if it exists.
* optional force_open bool If the UI should be re-opened instead of updated.
*
* return datum/tgui The found UI.
*/
/datum/controller/subsystem/tgui/proc/try_update_ui(
mob/user,
datum/src_object,
datum/tgui/ui)
// Look up a UI if it wasn't passed
if(isnull(ui))
ui = get_open_ui(user, src_object)
// Couldn't find a UI.
if(isnull(ui))
return null
ui.process_status()
// UI ended up with the closed status
// or is actively trying to close itself.
// FIXME: Doesn't actually fix the paper bug.
if(ui.status <= UI_CLOSE)
ui.close()
return null
ui.send_update()
return ui
/**
* public
*
* Get a open UI given a user and src_object.
*
* required user mob The mob who opened/is using the UI.
* required src_object datum The object/datum which owns the UI.
*
* return datum/tgui The found UI.
*/
/datum/controller/subsystem/tgui/proc/get_open_ui(mob/user, datum/src_object)
var/key = "[REF(src_object)]"
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return null
for(var/datum/tgui/ui in open_uis_by_src[key])
// Make sure we have the right user
if(ui.user == user)
return ui
return null
/**
* public
*
* Update all UIs attached to src_object.
*
* required src_object datum The object/datum which owns the UIs.
*
* return int The number of UIs updated.
*/
/datum/controller/subsystem/tgui/proc/update_uis(datum/src_object)
var/count = 0
var/key = "[REF(src_object)]"
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return count
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.process(force = 1)
count++
return count
/**
* public
*
* Close all UIs attached to src_object.
*
* required src_object datum The object/datum which owns the UIs.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/tgui/proc/close_uis(datum/src_object)
var/count = 0
var/key = "[REF(src_object)]"
// No UIs opened for this src_object
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return count
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.close()
count++
return count
/**
* public
*
* Close all UIs regardless of their attachment to src_object.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/tgui/proc/close_all_uis()
var/count = 0
for(var/key in open_uis_by_src)
for(var/datum/tgui/ui in open_uis_by_src[key])
// Check if UI is valid.
if(ui && ui.src_object && ui.user && ui.src_object.ui_host(ui.user))
ui.close()
count++
return count
/**
* public
*
* Update all UIs belonging to a user.
*
* required user mob The mob who opened/is using the UI.
* optional src_object datum If provided, only update UIs belonging this src_object.
*
* return int The number of UIs updated.
*/
/datum/controller/subsystem/tgui/proc/update_user_uis(mob/user, datum/src_object)
var/count = 0
if(length(user?.tgui_open_uis) == 0)
return count
for(var/datum/tgui/ui in user.tgui_open_uis)
if(isnull(src_object) || ui.src_object == src_object)
ui.process(force = 1)
count++
return count
/**
* public
*
* Close all UIs belonging to a user.
*
* required user mob The mob who opened/is using the UI.
* optional src_object datum If provided, only close UIs belonging this src_object.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/tgui/proc/close_user_uis(mob/user, datum/src_object)
var/count = 0
if(length(user?.tgui_open_uis) == 0)
return count
for(var/datum/tgui/ui in user.tgui_open_uis)
if(isnull(src_object) || ui.src_object == src_object)
ui.close()
count++
return count
/**
* private
*
* Add a UI to the list of open UIs.
*
* required ui datum/tgui The UI to be added.
*/
/datum/controller/subsystem/tgui/proc/on_open(datum/tgui/ui)
var/key = "[REF(ui.src_object)]"
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
open_uis_by_src[key] = list()
ui.user.tgui_open_uis |= ui
var/list/uis = open_uis_by_src[key]
uis |= ui
open_uis |= ui
/**
* private
*
* Remove a UI from the list of open UIs.
*
* required ui datum/tgui The UI to be removed.
*
* return bool If the UI was removed or not.
*/
/datum/controller/subsystem/tgui/proc/on_close(datum/tgui/ui)
var/key = "[REF(ui.src_object)]"
if(isnull(open_uis_by_src[key]) || !istype(open_uis_by_src[key], /list))
return FALSE
// Remove it from the list of processing UIs.
open_uis.Remove(ui)
// If the user exists, remove it from them too.
if(ui.user)
ui.user.tgui_open_uis.Remove(ui)
var/list/uis = open_uis_by_src[key]
uis.Remove(ui)
if(length(uis) == 0)
open_uis_by_src.Remove(key)
return TRUE
/**
* private
*
* Handle client logout, by closing all their UIs.
*
* required user mob The mob which logged out.
*
* return int The number of UIs closed.
*/
/datum/controller/subsystem/tgui/proc/on_logout(mob/user)
close_user_uis(user)
/**
* private
*
* Handle clients switching mobs, by transferring their UIs.
*
* required user source The client's original mob.
* required user target The client's new mob.
*
* return bool If the UIs were transferred.
*/
/datum/controller/subsystem/tgui/proc/on_transfer(mob/source, mob/target)
// The old mob had no open UIs.
if(length(source?.tgui_open_uis) == 0)
return FALSE
if(isnull(target.tgui_open_uis) || !istype(target.tgui_open_uis, /list))
target.tgui_open_uis = list()
// Transfer all the UIs.
for(var/datum/tgui/ui in source.tgui_open_uis)
// Inform the UIs of their new owner.
ui.user = target
target.tgui_open_uis.Add(ui)
// Clear the old list.
source.tgui_open_uis.Cut()
return TRUE
+17 -10
View File
@@ -431,25 +431,31 @@
if(!owner) if(!owner)
owner = M owner = M
/datum/ai_laws/proc/get_law_list(include_zeroth = 0, show_numbers = 1) /**
* Generates a list of all laws on this datum, including rendered HTML tags if required
*
* Arguments:
* * include_zeroth - Operator that controls if law 0 or law 666 is returned in the set
* * show_numbers - Operator that controls if law numbers are prepended to the returned laws
* * render_html - Operator controlling if HTML tags are rendered on the returned laws
*/
/datum/ai_laws/proc/get_law_list(include_zeroth = FALSE, show_numbers = TRUE, render_html = TRUE)
var/list/data = list() var/list/data = list()
if (include_zeroth && devillaws && devillaws.len) if (include_zeroth && devillaws)
for(var/i in devillaws) for(var/law in devillaws)
data += "[show_numbers ? "666:" : ""] <font color='#cc5500'>[i]</font>" data += "[show_numbers ? "666:" : ""] [render_html ? "<font color='#cc5500'>[law]</font>" : law]"
if (include_zeroth && zeroth) if (include_zeroth && zeroth)
data += "[show_numbers ? "0:" : ""] <font color='#ff0000'><b>[zeroth]</b></font>" data += "[show_numbers ? "0:" : ""] [render_html ? "<font color='#ff0000'><b>[zeroth]</b></font>" : zeroth]"
for(var/law in hacked) for(var/law in hacked)
if (length(law) > 0) if (length(law) > 0)
var/num = ionnum() data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "<font color='#660000'>[law]</font>" : law]"
data += "[show_numbers ? "[num]:" : ""] <font color='#660000'>[law]</font>"
for(var/law in ion) for(var/law in ion)
if (length(law) > 0) if (length(law) > 0)
var/num = ionnum() data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "<font color='#547DFE'>[law]</font>" : law]"
data += "[show_numbers ? "[num]:" : ""] <font color='#547DFE'>[law]</font>"
var/number = 1 var/number = 1
for(var/law in inherent) for(var/law in inherent)
@@ -459,6 +465,7 @@
for(var/law in supplied) for(var/law in supplied)
if (length(law) > 0) if (length(law) > 0)
data += "[show_numbers ? "[number]:" : ""] <font color='#990099'>[law]</font>" data += "[show_numbers ? "[number]:" : ""] [render_html ? "<font color='#990099'>[law]</font>" : law]"
number++ number++
return data return data
+11 -13
View File
@@ -203,9 +203,9 @@
Set var amt to the value current cycle req is pointing to, its amount of type we need to delete Set var amt to the value current cycle req is pointing to, its amount of type we need to delete
Get var/surroundings list of things accessable to crafting by get_environment() Get var/surroundings list of things accessable to crafting by get_environment()
Check the type of the current cycle req Check the type of the current cycle req
If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isnt remove thing from surroundings If its reagent then do a while loop, inside it try to locate() reagent containers, inside such containers try to locate needed reagent, if there isn't remove thing from surroundings
If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list If there is enough reagent in the search result then delete the needed amount, create the same type of reagent with the same data var and put it into deletion list
If there isnt enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching If there isn't enough take all of that reagent from the container, put into deletion list, substract the amt var by the volume of reagent, remove the container from surroundings list and keep searching
While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one While doing above stuff check deletion list if it already has such reagnet, if yes merge instead of adding second one
If its stack check if it has enough amount If its stack check if it has enough amount
If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack If yes create new stack with the needed amount and put in into deletion list, substract taken amount from the stack
@@ -216,7 +216,7 @@
Then do a loop over parts var of the recipe Then do a loop over parts var of the recipe
Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return Do similar stuff to what we have done above, but now in deletion list, until the parts conditions are satisfied keep taking from the deletion list and putting it into parts list for return
After its done loop over deletion list and delete all the shit that wasnt taken by parts loop After its done loop over deletion list and delete all the shit that wasn't taken by parts loop
del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already del_reqs return the list of parts resulting object will receive as argument of CheckParts proc, on the atom level it will add them all to the contents, on all other levels it calls ..() and does whatever is needed afterwards but from contents list already
*/ */
@@ -323,9 +323,12 @@
if(user == parent) if(user == parent)
ui_interact(user) ui_interact(user)
/datum/component/personal_crafting/ui_state(mob/user)
return GLOB.not_incapacitated_turf_state
//For the UI related things we're going to assume the user is a mob rather than typesetting it to an atom as the UI isn't generated if the parent is an atom //For the UI related things we're going to assume the user is a mob rather than typesetting it to an atom as the UI isn't generated if the parent is an atom
/datum/component/personal_crafting/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_turf_state) /datum/component/personal_crafting/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
cur_category = categories[1] cur_category = categories[1]
if(islist(categories[cur_category])) if(islist(categories[cur_category]))
@@ -333,7 +336,7 @@
cur_subcategory = subcats[1] cur_subcategory = subcats[1]
else else
cur_subcategory = CAT_NONE cur_subcategory = CAT_NONE
ui = new(user, src, ui_key, "PersonalCrafting", "Crafting Menu", 700, 800, master_ui, state) ui = new(user, src, "PersonalCrafting")
ui.open() ui.open()
/datum/component/personal_crafting/ui_data(mob/user) /datum/component/personal_crafting/ui_data(mob/user)
@@ -413,13 +416,8 @@
display_compact = !display_compact display_compact = !display_compact
. = TRUE . = TRUE
if("set_category") if("set_category")
if(!isnull(params["category"])) cur_category = params["category"]
cur_category = params["category"] cur_subcategory = params["subcategory"] || ""
if(!isnull(params["subcategory"]))
if(params["subcategory"] == "0")
cur_subcategory = ""
else
cur_subcategory = params["subcategory"]
. = TRUE . = TRUE
/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R) /datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
+4 -8
View File
@@ -80,19 +80,15 @@ GLOBAL_LIST_EMPTY(GPS_list)
to_chat(user, "<span class='notice'>[parent] is now tracking, and visible to other GPS devices.</span>") to_chat(user, "<span class='notice'>[parent] is now tracking, and visible to other GPS devices.</span>")
tracking = TRUE tracking = TRUE
/datum/component/gps/item/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state. /datum/component/gps/item/ui_interact(mob/user, datum/tgui/ui)
if(emped) if(emped)
to_chat(user, "<span class='hear'>[parent] fizzles weakly.</span>") to_chat(user, "<span class='hear'>[parent] fizzles weakly.</span>")
return return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
// Variable window height, depending on how many GPS units there are ui = new(user, src, "Gps")
// to show, clamped to relatively safe range.
var/gps_window_height = clamp(325 + GLOB.GPS_list.len * 14, 325, 700)
ui = new(user, src, ui_key, "Gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui.open() ui.open()
ui.set_autoupdate(updating)
ui.set_autoupdate(state = updating)
/datum/component/gps/item/ui_data(mob/user) /datum/component/gps/item/ui_data(mob/user)
var/list/data = list() var/list/data = list()
+20
View File
@@ -307,6 +307,10 @@
/datum/component/mood/proc/HandleNutrition(mob/living/L) /datum/component/mood/proc/HandleNutrition(mob/living/L)
if(isethereal(L))
HandleCharge(L)
if(HAS_TRAIT(L, TRAIT_NOHUNGER))
return FALSE //no mood events for nutrition
switch(L.nutrition) switch(L.nutrition)
if(NUTRITION_LEVEL_FULL to INFINITY) if(NUTRITION_LEVEL_FULL to INFINITY)
add_event(null, "nutrition", /datum/mood_event/fat) add_event(null, "nutrition", /datum/mood_event/fat)
@@ -321,6 +325,22 @@
if(0 to NUTRITION_LEVEL_STARVING) if(0 to NUTRITION_LEVEL_STARVING)
add_event(null, "nutrition", /datum/mood_event/starving) add_event(null, "nutrition", /datum/mood_event/starving)
/datum/component/mood/proc/HandleCharge(mob/living/carbon/human/H)
var/datum/species/ethereal/E = H.dna.species
switch(E.get_charge(H))
if(ETHEREAL_CHARGE_NONE to ETHEREAL_CHARGE_LOWPOWER)
add_event(null, "charge", /datum/mood_event/decharged)
if(ETHEREAL_CHARGE_LOWPOWER to ETHEREAL_CHARGE_NORMAL)
add_event(null, "charge", /datum/mood_event/lowpower)
if(ETHEREAL_CHARGE_NORMAL to ETHEREAL_CHARGE_ALMOSTFULL)
clear_event(null, "charge")
if(ETHEREAL_CHARGE_ALMOSTFULL to ETHEREAL_CHARGE_FULL)
add_event(null, "charge", /datum/mood_event/charged)
if(ETHEREAL_CHARGE_FULL to ETHEREAL_CHARGE_OVERLOAD)
add_event(null, "charge", /datum/mood_event/overcharged)
if(ETHEREAL_CHARGE_OVERLOAD to ETHEREAL_CHARGE_DANGEROUS)
add_event(null, "charge", /datum/mood_event/supercharged)
/datum/component/mood/proc/update_beauty(area/A) /datum/component/mood/proc/update_beauty(area/A)
if(A.outdoors) //if we're outside, we don't care. if(A.outdoors) //if we're outside, we don't care.
clear_event(null, "area_beauty") clear_event(null, "area_beauty")
+15
View File
@@ -29,10 +29,18 @@
if(strength > RAD_MINIMUM_CONTAMINATION) if(strength > RAD_MINIMUM_CONTAMINATION)
SSradiation.warn(src) SSradiation.warn(src)
//Let's make er glow
//This relies on parent not being a turf or something. IF YOU CHANGE THAT, CHANGE THIS
var/atom/movable/master = parent
master.add_filter("rad_glow", 2, list("type" = "outline", "color" = "#39ff1430", "size" = 2))
addtimer(CALLBACK(src, .proc/glow_loop, master), rand(1,19))//Things should look uneven
START_PROCESSING(SSradiation, src) START_PROCESSING(SSradiation, src)
/datum/component/radioactive/Destroy() /datum/component/radioactive/Destroy()
STOP_PROCESSING(SSradiation, src) STOP_PROCESSING(SSradiation, src)
var/atom/movable/master = parent
master.remove_filter("rad_glow")
return ..() return ..()
/datum/component/radioactive/process() /datum/component/radioactive/process()
@@ -46,6 +54,13 @@
if(strength <= RAD_BACKGROUND_RADIATION) if(strength <= RAD_BACKGROUND_RADIATION)
return PROCESS_KILL return PROCESS_KILL
/datum/component/radioactive/proc/glow_loop(atom/movable/master)
var/filter = master.get_filter("rad_glow")
if(filter)
animate(filter, alpha = 110, time = 15, loop = -1)
animate(alpha = 40, time = 25)
/datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, _strength, _source, _half_life, _can_contaminate) /datum/component/radioactive/InheritComponent(datum/component/C, i_am_original, _strength, _source, _half_life, _can_contaminate)
if(!i_am_original) if(!i_am_original)
return return
+24 -3
View File
@@ -11,6 +11,13 @@
// This is to stop squeak spam from inhand usage // This is to stop squeak spam from inhand usage
var/last_use = 0 var/last_use = 0
var/use_delay = 20 var/use_delay = 20
// squeak cooldowns
var/last_squeak = 0
var/squeak_delay = 5
/// chance we'll be stopped from squeaking by cooldown when something crossing us squeaks
var/cross_squeak_delay_chance = 33 // about 3 things can squeak at a time
/datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override) /datum/component/squeak/Initialize(custom_sounds, volume_override, chance_override, step_delay_override, use_delay_override)
if(!isatom(parent)) if(!isatom(parent))
@@ -19,6 +26,7 @@
if(ismovable(parent)) if(ismovable(parent))
RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT), .proc/play_squeak) RegisterSignal(parent, list(COMSIG_MOVABLE_BUMP, COMSIG_MOVABLE_IMPACT), .proc/play_squeak)
RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ITEM_WEARERCROSSED), .proc/play_squeak_crossed) RegisterSignal(parent, list(COMSIG_MOVABLE_CROSSED, COMSIG_ITEM_WEARERCROSSED), .proc/play_squeak_crossed)
RegisterSignal(parent, COMSIG_CROSS_SQUEAKED, .proc/delay_squeak)
RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react) RegisterSignal(parent, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react)
if(isitem(parent)) if(isitem(parent))
RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak) RegisterSignal(parent, list(COMSIG_ITEM_ATTACK, COMSIG_ITEM_ATTACK_OBJ, COMSIG_ITEM_HIT_REACT), .proc/play_squeak)
@@ -39,20 +47,28 @@
use_delay = use_delay_override use_delay = use_delay_override
/datum/component/squeak/proc/play_squeak() /datum/component/squeak/proc/play_squeak()
do_play_squeak()
/datum/component/squeak/proc/do_play_squeak(bypass_cooldown = FALSE)
if(!bypass_cooldown && ((last_squeak + squeak_delay) >= world.time))
return FALSE
if(prob(squeak_chance)) if(prob(squeak_chance))
if(!override_squeak_sounds) if(!override_squeak_sounds)
playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1) playsound(parent, pickweight(default_squeak_sounds), volume, 1, -1)
else else
playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1) playsound(parent, pickweight(override_squeak_sounds), volume, 1, -1)
last_squeak = world.time
return TRUE
return FALSE
/datum/component/squeak/proc/step_squeak() /datum/component/squeak/proc/step_squeak()
if(steps > step_delay) if(steps > step_delay)
play_squeak() do_play_squeak(TRUE)
steps = 0 steps = 0
else else
steps++ steps++
/datum/component/squeak/proc/play_squeak_crossed(atom/movable/AM) /datum/component/squeak/proc/play_squeak_crossed(datum/source, atom/movable/AM)
if(isitem(AM)) if(isitem(AM))
var/obj/item/I = AM var/obj/item/I = AM
if(I.item_flags & ABSTRACT) if(I.item_flags & ABSTRACT)
@@ -63,13 +79,18 @@
return return
var/atom/current_parent = parent var/atom/current_parent = parent
if(isturf(current_parent.loc)) if(isturf(current_parent.loc))
play_squeak() if(do_play_squeak())
SEND_SIGNAL(AM, COMSIG_CROSS_SQUEAKED)
/datum/component/squeak/proc/use_squeak() /datum/component/squeak/proc/use_squeak()
if(last_use + use_delay < world.time) if(last_use + use_delay < world.time)
last_use = world.time last_use = world.time
play_squeak() play_squeak()
/datum/component/squeak/proc/delay_squeak()
if(prob(cross_squeak_delay_chance))
last_squeak = world.time
/datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot) /datum/component/squeak/proc/on_equip(datum/source, mob/equipper, slot)
RegisterSignal(equipper, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react, TRUE) RegisterSignal(equipper, COMSIG_MOVABLE_DISPOSING, .proc/disposing_react, TRUE)
+2
View File
@@ -105,6 +105,8 @@
/// Triggered on attack self of the item containing the component /// Triggered on attack self of the item containing the component
/datum/component/two_handed/proc/on_attack_self(datum/source, mob/user) /datum/component/two_handed/proc/on_attack_self(datum/source, mob/user)
if(!user.is_holding(parent))
return //give no quarter to telekinesis powergaemrs (telekinetic wielding will desync the offhand and result in all sorts of bugs so no until someone codes it properly)
if(wielded) if(wielded)
unwield(user) unwield(user)
else else
+16 -10
View File
@@ -143,23 +143,19 @@ GLOBAL_LIST_EMPTY(uplinks)
// an unlocked uplink blocks also opening the PDA or headset menu // an unlocked uplink blocks also opening the PDA or headset menu
return COMPONENT_NO_INTERACT return COMPONENT_NO_INTERACT
/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /datum/component/uplink/ui_state(mob/user)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state) return GLOB.inventory_state
/datum/component/uplink/ui_interact(mob/user, datum/tgui/ui)
active = TRUE active = TRUE
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "Uplink", name, 620, 580, master_ui, state) ui = new(user, src, "Uplink", name)
// This UI is only ever opened by one person, // This UI is only ever opened by one person,
// and never is updated outside of user input. // and never is updated outside of user input.
ui.set_autoupdate(FALSE) ui.set_autoupdate(FALSE)
ui.open() ui.open()
/datum/component/uplink/ui_host(mob/user)
if(istype(parent, /obj/item/implant)) //implants are like organs, not really located inside mobs codewise.
var/obj/item/implant/I = parent
return I.imp_in
return ..()
/datum/component/uplink/ui_data(mob/user) /datum/component/uplink/ui_data(mob/user)
if(!user.mind) if(!user.mind)
return return
@@ -187,8 +183,18 @@ GLOBAL_LIST_EMPTY(uplinks)
is_inaccessible = FALSE is_inaccessible = FALSE
if(is_inaccessible) if(is_inaccessible)
continue continue
/*
if(I.restricted_species) //catpeople specfic gloves.
if(ishuman(user))
var/is_inaccessible = TRUE
var/mob/living/carbon/human/H = user
for(var/F in I.restricted_species)
if(F == H.dna.species.id || debug)
is_inaccessible = FALSE
break
if(is_inaccessible) if(is_inaccessible)
continue continue
*/
cat["items"] += list(list( cat["items"] += list(list(
"name" = I.name, "name" = I.name,
"cost" = I.cost, "cost" = I.cost,
+42 -6
View File
@@ -1,13 +1,13 @@
//TODO: someone please get rid of this shit
/datum/datacore /datum/datacore
var/medical[] = list() var/list/medical = list()
var/medicalPrintCount = 0 var/medicalPrintCount = 0
var/general[] = list() var/list/general = list()
var/security[] = list() var/list/security = list()
var/securityPrintCount = 0 var/securityPrintCount = 0
var/securityCrimeCounter = 0 var/securityCrimeCounter = 0
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character(). ///This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
var/locked[] = list() var/list/locked = list()
/datum/data /datum/data
var/name = "data" var/name = "data"
@@ -91,6 +91,42 @@
if(foundrecord) if(foundrecord)
foundrecord.fields["rank"] = assignment foundrecord.fields["rank"] = assignment
/datum/datacore/proc/get_manifest_tg() //copypasted from tg, renamed to avoid namespace conflicts
var/list/manifest_out = list()
var/list/departments = list(
"Command" = GLOB.command_positions,
"Security" = GLOB.security_positions,
"Engineering" = GLOB.engineering_positions,
"Medical" = GLOB.medical_positions,
"Science" = GLOB.science_positions,
"Supply" = GLOB.supply_positions,
"Service" = GLOB.civilian_positions,
"Silicon" = GLOB.nonhuman_positions
)
for(var/datum/data/record/t in GLOB.data_core.general)
var/name = t.fields["name"]
var/rank = t.fields["rank"]
var/has_department = FALSE
for(var/department in departments)
var/list/jobs = departments[department]
if(rank in jobs)
if(!manifest_out[department])
manifest_out[department] = list()
manifest_out[department] += list(list(
"name" = name,
"rank" = rank
))
has_department = TRUE
break
if(!has_department)
if(!manifest_out["Misc"])
manifest_out["Misc"] = list()
manifest_out["Misc"] += list(list(
"name" = name,
"rank" = rank
))
return manifest_out
/datum/datacore/proc/get_manifest(monochrome, OOC) /datum/datacore/proc/get_manifest(monochrome, OOC)
var/list/heads = list() var/list/heads = list()
var/list/sec = list() var/list/sec = list()
+2
View File
@@ -50,6 +50,7 @@
destination.dna.skin_tone_override = skin_tone_override destination.dna.skin_tone_override = skin_tone_override
destination.dna.features = features.Copy() destination.dna.features = features.Copy()
destination.set_species(species.type, icon_update=0) destination.set_species(species.type, icon_update=0)
destination.dna.species.say_mod = species.say_mod
destination.dna.real_name = real_name destination.dna.real_name = real_name
destination.dna.nameless = nameless destination.dna.nameless = nameless
destination.dna.custom_species = custom_species destination.dna.custom_species = custom_species
@@ -74,6 +75,7 @@
new_dna.skin_tone_override = skin_tone_override new_dna.skin_tone_override = skin_tone_override
new_dna.features = features.Copy() new_dna.features = features.Copy()
new_dna.species = new species.type new_dna.species = new species.type
new_dna.species.say_mod = species.say_mod
new_dna.real_name = real_name new_dna.real_name = real_name
new_dna.nameless = nameless new_dna.nameless = nameless
new_dna.custom_species = custom_species new_dna.custom_species = custom_species
+119 -5
View File
@@ -32,20 +32,29 @@
var/datum/action/innate/end_holocall/hangup //hangup action var/datum/action/innate/end_holocall/hangup //hangup action
var/call_start_time var/call_start_time
var/head_call = FALSE //calls from a head of staff autoconnect, if the receiving pad is not secure.
//creates a holocall made by `caller` from `calling_pad` to `callees` //creates a holocall made by `caller` from `calling_pad` to `callees`
/datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees) /datum/holocall/New(mob/living/caller, obj/machinery/holopad/calling_pad, list/callees, elevated_access = FALSE)
call_start_time = world.time call_start_time = world.time
user = caller user = caller
calling_pad.outgoing_call = src calling_pad.outgoing_call = src
calling_holopad = calling_pad calling_holopad = calling_pad
head_call = elevated_access
dialed_holopads = list() dialed_holopads = list()
for(var/I in callees) for(var/I in callees)
var/obj/machinery/holopad/H = I var/obj/machinery/holopad/H = I
if(!QDELETED(H) && H.is_operational()) if(!QDELETED(H) && H.is_operational())
dialed_holopads += H dialed_holopads += H
H.say("Incoming call.") if(head_call)
if(H.secure)
calling_pad.say("Auto-connection refused, falling back to call mode.")
H.say("Incoming call.")
else
H.say("Incoming connection.")
else
H.say("Incoming call.")
LAZYADD(H.holo_calls, src) LAZYADD(H.holo_calls, src)
if(!dialed_holopads.len) if(!dialed_holopads.len)
@@ -79,6 +88,7 @@
dialed_holopads.Cut() dialed_holopads.Cut()
if(calling_holopad) if(calling_holopad)
calling_holopad.calling = FALSE
calling_holopad.outgoing_call = null calling_holopad.outgoing_call = null
calling_holopad.SetLightsAndPower() calling_holopad.SetLightsAndPower()
calling_holopad = null calling_holopad = null
@@ -145,6 +155,7 @@
if(!Check()) if(!Check())
return return
calling_holopad.calling = FALSE
hologram = H.activate_holo(user) hologram = H.activate_holo(user)
hologram.HC = src hologram.HC = src
@@ -160,6 +171,8 @@
hangup = new(eye, src) hangup = new(eye, src)
hangup.Grant(user) hangup.Grant(user)
playsound(H, 'sound/machines/ping.ogg', 100)
H.say("Connection established.")
//Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise //Checks the validity of a holocall and qdels itself if it's not. Returns TRUE if valid, FALSE otherwise
/datum/holocall/proc/Check() /datum/holocall/proc/Check()
@@ -178,7 +191,6 @@
. = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME) . = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME)
if(!.) if(!.)
calling_holopad.say("No answer received.") calling_holopad.say("No answer received.")
calling_holopad.temp = ""
if(!.) if(!.)
testing("Holocall Check fail") testing("Holocall Check fail")
@@ -241,10 +253,10 @@
record.caller_image = holodiskOriginal.record.caller_image record.caller_image = holodiskOriginal.record.caller_image
record.entries = holodiskOriginal.record.entries.Copy() record.entries = holodiskOriginal.record.entries.Copy()
record.language = holodiskOriginal.record.language record.language = holodiskOriginal.record.language
to_chat(user, "You copy the record from [holodiskOriginal] to [src] by connecting the ports!") to_chat(user, "<span class='notice'>You copy the record from [holodiskOriginal] to [src] by connecting the ports!</span>")
name = holodiskOriginal.name name = holodiskOriginal.name
else else
to_chat(user, "[holodiskOriginal] has no record on it!") to_chat(user, "<span class='warning'>[holodiskOriginal] has no record on it!</span>")
..() ..()
/obj/item/disk/holodisk/proc/build_record() /obj/item/disk/holodisk/proc/build_record()
@@ -331,6 +343,21 @@
DELAY 20"} DELAY 20"}
/datum/preset_holoimage/engineer /datum/preset_holoimage/engineer
outfit_type = /datum/outfit/job/engineer
/datum/preset_holoimage/engineer/rig
outfit_type = /datum/outfit/job/engineer/gloved/rig
/datum/preset_holoimage/engineer/ce
outfit_type = /datum/outfit/job/ce
/datum/preset_holoimage/engineer/ce/rig
outfit_type = /datum/outfit/job/engineer/gloved/rig
/datum/preset_holoimage/engineer/atmos
outfit_type = /datum/outfit/job/atmos
/datum/preset_holoimage/engineer/atmos/rig
outfit_type = /datum/outfit/job/engineer/gloved/rig outfit_type = /datum/outfit/job/engineer/gloved/rig
/datum/preset_holoimage/researcher /datum/preset_holoimage/researcher
@@ -350,3 +377,90 @@
/datum/preset_holoimage/clown /datum/preset_holoimage/clown
outfit_type = /datum/outfit/job/clown outfit_type = /datum/outfit/job/clown
/obj/item/disk/holodisk/donutstation/whiteship
name = "Blackbox Print-out #DS024"
desc = "A holodisk containing the last viable recording of DS024's blackbox."
preset_image_type = /datum/preset_holoimage/engineer/ce
preset_record_text = {"
NAME Geysr Shorthalt
SAY Engine renovations complete and the ships been loaded. We all ready?
DELAY 25
PRESET /datum/preset_holoimage/engineer
NAME Jacob Ullman
SAY Lets blow this popsicle stand of a station.
DELAY 20
PRESET /datum/preset_holoimage/engineer/atmos
NAME Lindsey Cuffler
SAY Uh, sir? Shouldn't we call for a secondary shuttle? The bluespace drive on this thing made an awfully weird noise when we jumped here..
DELAY 30
PRESET /datum/preset_holoimage/engineer/ce
NAME Geysr Shorthalt
SAY Pah! Ship techie at the dock said to give it a good few kicks if it started acting up, let me just..
DELAY 25
SOUND punch
SOUND sparks
DELAY 10
SOUND punch
SOUND sparks
DELAY 10
SOUND punch
SOUND sparks
SOUND warpspeed
DELAY 15
PRESET /datum/preset_holoimage/engineer/atmos
NAME Lindsey Cuffler
SAY Uhh.. is it supposed to be doing that??
DELAY 15
PRESET /datum/preset_holoimage/engineer/ce
NAME Geysr Shorthalt
SAY See? Working as intended. Now, are we all ready?
DELAY 10
PRESET /datum/preset_holoimage/engineer
NAME Jacob Ullman
SAY Is it supposed to be glowing like that?
DELAY 20
SOUND explosion
"}
/obj/item/disk/holodisk/ruin/snowengieruin
name = "Blackbox Print-out #EB412"
desc = "A holodisk containing the last moments of EB412. There's a bloody fingerprint on it."
preset_image_type = /datum/preset_holoimage/engineer
preset_record_text = {"
NAME Dave Tundrale
SAY Maria, how's Build?
DELAY 10
NAME Maria Dell
PRESET /datum/preset_holoimage/engineer/atmos
SAY It's fine, don't worry. I've got Plastic on it. And frankly, i'm kinda busy with, the, uhhm, incinerator.
DELAY 30
NAME Dave Tundrale
PRESET /datum/preset_holoimage/engineer
SAY Aight, wonderful. The science mans been kinda shit though. No RCDs-
DELAY 20
NAME Maria Dell
PRESET /datum/preset_holoimage/engineer/atmos
SAY Enough about your RCDs. They're not even that important, just bui-
DELAY 15
SOUND explosion
DELAY 10
SAY Oh, shit!
DELAY 10
PRESET /datum/preset_holoimage/engineer/atmos/rig
LANGUAGE /datum/language/narsie
NAME Unknown
SAY RISE, MY LORD!!
DELAY 10
LANGUAGE /datum/language/common
NAME Plastic
PRESET /datum/preset_holoimage/engineer/rig
SAY Fuck, fuck, fuck!
DELAY 20
SAY It's loose! CALL THE FUCKING SHUTT-
DELAY 10
PRESET /datum/preset_holoimage/corgi
NAME Blackbox Automated Message
SAY Connection lost. Dumping audio logs to disk.
DELAY 50"}
+21
View File
@@ -19,6 +19,27 @@
description = "<span class='boldwarning'>I'm starving!</span>\n" description = "<span class='boldwarning'>I'm starving!</span>\n"
mood_change = -15 mood_change = -15
//charge
/datum/mood_event/supercharged
description = "<span class='boldwarning'>I can't possibly keep all this power inside, I need to release some quick!</span>\n"
mood_change = -10
/datum/mood_event/overcharged
description = "<span class='warning'>I feel dangerously overcharged, perhaps I should release some power.</span>\n"
mood_change = -4
/datum/mood_event/charged
description = "<span class='nicegreen'>I feel the power in my veins!</span>\n"
mood_change = 6
/datum/mood_event/lowpower
description = "<span class='warning'>My power is running low, I should go charge up somewhere.</span>\n"
mood_change = -6
/datum/mood_event/decharged
description = "<span class='boldwarning'>I'm in desperate need of some electricity!</span>\n"
mood_change = -10
//Disgust //Disgust
/datum/mood_event/gross /datum/mood_event/gross
description = "<span class='warning'>I saw something gross.</span>\n" description = "<span class='warning'>I saw something gross.</span>\n"
-1
View File
@@ -105,7 +105,6 @@
// modify the ignored_things list in __HELPERS/radiation.dm instead // modify the ignored_things list in __HELPERS/radiation.dm instead
var/static/list/blacklisted = typecacheof(list( var/static/list/blacklisted = typecacheof(list(
/turf, /turf,
/mob,
/obj/structure/cable, /obj/structure/cable,
/obj/machinery/atmospherics, /obj/machinery/atmospherics,
/obj/item/ammo_casing, /obj/item/ammo_casing,
+7 -4
View File
@@ -14,11 +14,14 @@
mind.skill_holder.ui_interact(src) mind.skill_holder.ui_interact(src)
/datum/skill_holder/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.always_state) /datum/skill_holder/ui_state(mob/user)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) return GLOB.always_state
/datum/skill_holder/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "SkillPanel", "[owner.name]'s Skills", 620, 580, master_ui, state) ui = new(user, src, "SkillPanel", "[owner.name]'s Skills")
ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input. ui.set_autoupdate(FALSE)
ui.open() ui.open()
else if(need_static_data_update) else if(need_static_data_update)
update_static_data(user) update_static_data(user)
+15 -8
View File
@@ -6,10 +6,13 @@
qdel(src) qdel(src)
owner = new_owner owner = new_owner
/datum/spawners_menu/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.observer_state) /datum/spawners_menu/ui_state(mob/user)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) return GLOB.observer_state
/datum/spawners_menu/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "SpawnersMenu", "Spawners Menu", 700, 600, master_ui, state) ui = new(user, src, "SpawnersMenu")
ui.open() ui.open()
/datum/spawners_menu/ui_data(mob/user) /datum/spawners_menu/ui_data(mob/user)
@@ -42,11 +45,15 @@
if(..()) if(..())
return return
var/spawner_ref = pick(GLOB.mob_spawners[params["name"]]) var/group_name = params["name"]
var/obj/effect/mob_spawn/MS = locate(spawner_ref) in GLOB.poi_list if(!group_name || !(group_name in GLOB.mob_spawners))
if(!MS) return
var/list/spawnerlist = GLOB.mob_spawners[group_name]
if(!spawnerlist.len)
return
var/obj/effect/mob_spawn/MS = pick(spawnerlist)
if(!istype(MS) || !(MS in GLOB.poi_list))
return return
switch(action) switch(action)
if("jump") if("jump")
if(MS) if(MS)
@@ -55,4 +62,4 @@
if("spawn") if("spawn")
if(MS) if(MS)
MS.attack_ghost(owner) MS.attack_ghost(owner)
. = TRUE . = TRUE
+14 -5
View File
@@ -97,6 +97,12 @@
/datum/wires/proc/get_wire(color) /datum/wires/proc/get_wire(color)
return colors[color] return colors[color]
/datum/wires/proc/get_color_of_wire(wire_type)
for(var/color in colors)
var/other_type = colors[color]
if(wire_type == other_type)
return color
/datum/wires/proc/get_attached(color) /datum/wires/proc/get_attached(color)
if(assemblies[color]) if(assemblies[color])
return assemblies[color] return assemblies[color]
@@ -117,7 +123,7 @@
return TRUE return TRUE
/datum/wires/proc/is_dud(wire) /datum/wires/proc/is_dud(wire)
return findtext(wire, WIRE_DUD_PREFIX) return findtext(wire, WIRE_DUD_PREFIX, 1, length(WIRE_DUD_PREFIX) + 1)
/datum/wires/proc/is_dud_color(color) /datum/wires/proc/is_dud_color(color)
return is_dud(get_wire(color)) return is_dud(get_wire(color))
@@ -197,6 +203,7 @@
S.forceMove(holder.drop_location()) S.forceMove(holder.drop_location())
return S return S
/// Called from [/atom/proc/emp_act]
/datum/wires/proc/emp_pulse() /datum/wires/proc/emp_pulse()
var/list/possible_wires = shuffle(wires) var/list/possible_wires = shuffle(wires)
var/remaining_pulses = MAXIMUM_EMP_WIRES var/remaining_pulses = MAXIMUM_EMP_WIRES
@@ -239,11 +246,13 @@
return ..() return ..()
return UI_CLOSE return UI_CLOSE
/datum/wires/ui_interact(mob/user, ui_key = "wires", datum/tgui/ui = null, force_open = FALSE, \ /datum/wires/ui_state(mob/user)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state) return GLOB.physical_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/datum/wires/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if (!ui) if (!ui)
ui = new(user, src, ui_key, "Wires", "[holder.name] Wires", 350, 150 + wires.len * 30, master_ui, state) ui = new(user, src, "Wires", "[holder.name] Wires")
ui.open() ui.open()
/datum/wires/ui_data(mob/user) /datum/wires/ui_data(mob/user)
+10 -21
View File
@@ -53,11 +53,10 @@
/datum/wires/airlock/interactable(mob/user) /datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder var/obj/machinery/door/airlock/A = holder
if(!A.panel_open)
return FALSE
if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100)) if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100))
return FALSE return FALSE
return TRUE if(A.panel_open)
return TRUE
/datum/wires/airlock/get_status() /datum/wires/airlock/get_status()
var/obj/machinery/door/airlock/A = holder var/obj/machinery/door/airlock/A = holder
@@ -115,10 +114,7 @@
A.aiControlDisabled = -1 A.aiControlDisabled = -1
if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks. if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks.
if(!A.secondsElectrified) if(!A.secondsElectrified)
A.set_electrified(30) A.set_electrified(30, usr)
if(usr)
LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]"))
log_combat(usr, A, "electrified")
if(WIRE_SAFETY) if(WIRE_SAFETY)
A.safe = !A.safe A.safe = !A.safe
if(!A.density) if(!A.density)
@@ -135,21 +131,17 @@
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power. if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2)) if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
A.regainMainPower() A.regainMainPower()
if(usr)
A.shock(usr, 50)
else else
A.loseMainPower() A.loseMainPower()
if(usr) if(isliving(usr))
A.shock(usr, 50) A.shock(usr, 50)
if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power. if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power.
if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2)) if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2))
A.regainBackupPower() A.regainBackupPower()
if(usr)
A.shock(usr, 50)
else else
A.loseBackupPower() A.loseBackupPower()
if(usr) if(isliving(usr))
A.shock(usr, 50) A.shock(usr, 50)
if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing. if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing.
if(!mend) if(!mend)
A.bolt() A.bolt()
@@ -170,10 +162,7 @@
A.set_electrified(0) A.set_electrified(0)
else else
if(A.secondsElectrified != -1) if(A.secondsElectrified != -1)
A.set_electrified(-1) A.set_electrified(-1, usr)
if(usr)
LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]"))
log_combat(usr, A, "electrified")
if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable. if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable.
A.safe = mend A.safe = mend
if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable. if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable.
@@ -184,5 +173,5 @@
A.lights = mend A.lights = mend
A.update_icon() A.update_icon()
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch. if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
if(usr) if(isliving(usr))
A.shock(usr, 50) A.shock(usr, 50)
+3
View File
@@ -16,6 +16,8 @@
/// If it's valid territory for gangs/cults to summon /// If it's valid territory for gangs/cults to summon
var/valid_territory = TRUE var/valid_territory = TRUE
/// malf ais can hack this
var/valid_malf_hack = TRUE
/// if blobs can spawn there and if it counts towards their score. /// if blobs can spawn there and if it counts towards their score.
var/blob_allowed = TRUE var/blob_allowed = TRUE
/// whether servants can warp into this area from Reebe /// whether servants can warp into this area from Reebe
@@ -572,6 +574,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
power_environ = FALSE power_environ = FALSE
always_unpowered = FALSE always_unpowered = FALSE
valid_territory = FALSE valid_territory = FALSE
valid_malf_hack = FALSE
blob_allowed = FALSE blob_allowed = FALSE
addSorted() addSorted()
+10 -9
View File
@@ -962,15 +962,16 @@
if(source != target) if(source != target)
target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE) target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE)
/* /**
Proc for attack log creation, because really why not * Log a combat message in the attack log
1 argument is the actor performing the action *
2 argument is the target of the action * Arguments:
3 is a verb describing the action (e.g. punched, throwed, kicked, etc.) * * atom/user - argument is the actor performing the action
4 is a tool with which the action was made (usually an item) * * atom/target - argument is the target of the action
5 is any additional text, which will be appended to the rest of the log line * * what_done - is a verb describing the action (e.g. punched, throwed, kicked, etc.)
*/ * * atom/object - is a tool with which the action was made (usually an item)
* * addition - is any additional text, which will be appended to the rest of the log line
*/
/proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null) /proc/log_combat(atom/user, atom/target, what_done, atom/object=null, addition=null)
var/ssource = key_name(user) var/ssource = key_name(user)
var/starget = key_name(target) var/starget = key_name(target)
+7 -7
View File
@@ -201,15 +201,15 @@
. = ..() . = ..()
. += "<span class='notice'>Alt-click [src] to [state_open ? "close" : "open"] it.</span>" . += "<span class='notice'>Alt-click [src] to [state_open ? "close" : "open"] it.</span>"
/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/sleeper/ui_state(mob/user)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) if(controls_inside)
return GLOB.notcontained_state
return GLOB.default_state
if(controls_inside && state == GLOB.notcontained_state) /obj/machinery/sleeper/ui_interact(mob/user, datum/tgui/ui)
state = GLOB.default_state // If it has a set of controls on the inside, make it actually controllable by the mob in it. ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "Sleeper", name, 550, 700, master_ui, state) ui = new(user, src, "Sleeper", name)
ui.open() ui.open()
/obj/machinery/sleeper/process() /obj/machinery/sleeper/process()
+3 -6
View File
@@ -93,13 +93,10 @@ GLOBAL_LIST_EMPTY(announcement_systems)
for(var/channel in channels) for(var/channel in channels)
radio.talk_into(src, message, channel) radio.talk_into(src, message, channel)
//config stuff /obj/machinery/announcement_system/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
/obj/machinery/announcement_system/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
. = ..()
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "AutomatedAnnouncement", "Automated Announcement System", 500, 225, master_ui, state) ui = new(user, src, "AutomatedAnnouncement")
ui.open() ui.open()
/obj/machinery/announcement_system/ui_data() /obj/machinery/announcement_system/ui_data()
+10 -7
View File
@@ -3,6 +3,7 @@
desc = "A machine used to deposit and withdraw station funds." desc = "A machine used to deposit and withdraw station funds."
icon = 'goon/icons/obj/goon_terminals.dmi' icon = 'goon/icons/obj/goon_terminals.dmi'
idle_power_usage = 100 idle_power_usage = 100
var/siphoning = FALSE var/siphoning = FALSE
var/next_warning = 0 var/next_warning = 0
var/obj/item/radio/radio var/obj/item/radio/radio
@@ -38,7 +39,6 @@
return return
return ..() return ..()
/obj/machinery/computer/bank_machine/process() /obj/machinery/computer/bank_machine/process()
..() ..()
if(siphoning) if(siphoning)
@@ -51,7 +51,7 @@
end_syphon() end_syphon()
return return
playsound(src.loc, 'sound/items/poster_being_created.ogg', 100, 1) playsound(src, 'sound/items/poster_being_created.ogg', 100, TRUE)
syphoning_credits += 200 syphoning_credits += 200
D.adjust_money(-200) D.adjust_money(-200)
if(next_warning < world.time && prob(15)) if(next_warning < world.time && prob(15))
@@ -60,17 +60,20 @@
radio.talk_into(src, message, radio_channel) radio.talk_into(src, message, radio_channel)
next_warning = world.time + minimum_time_between_warnings next_warning = world.time + minimum_time_between_warnings
/obj/machinery/computer/bank_machine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/computer/bank_machine/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "BankMachine", name, 320, 165, master_ui, state) ui = new(user, src, "BankMachine", name)
ui.open() ui.open()
/obj/machinery/computer/bank_machine/ui_data(mob/user) /obj/machinery/computer/bank_machine/ui_data(mob/user)
var/list/data = list() var/list/data = list()
var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR) var/datum/bank_account/D = SSeconomy.get_dep_account(ACCOUNT_CAR)
data["current_balance"] = D.account_balance
if(D)
data["current_balance"] = D.account_balance
else
data["current_balance"] = 0
data["siphoning"] = siphoning data["siphoning"] = siphoning
data["station_name"] = station_name() data["station_name"] = station_name()
+8 -3
View File
@@ -43,10 +43,13 @@
table.computer = src table.computer = src
break break
/obj/machinery/computer/operating/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.not_incapacitated_state) /obj/machinery/computer/operating/ui_state(mob/user)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) return GLOB.not_incapacitated_state
/obj/machinery/computer/operating/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "OperatingComputer", name, 350, 470, master_ui, state) ui = new(user, src, "OperatingComputer", name)
ui.open() ui.open()
/obj/machinery/computer/operating/ui_data(mob/user) /obj/machinery/computer/operating/ui_data(mob/user)
@@ -153,6 +156,8 @@
)) ))
return data return data
/obj/machinery/computer/operating/ui_act(action, params) /obj/machinery/computer/operating/ui_act(action, params)
if(..()) if(..())
return return
+36 -67
View File
@@ -2,14 +2,13 @@
name = "\improper AI system integrity restorer" name = "\improper AI system integrity restorer"
desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order." desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order."
req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS) req_access = list(ACCESS_CAPTAIN, ACCESS_ROBOTICS, ACCESS_HEADS)
var/mob/living/silicon/ai/occupier = null
var/active = 0
circuit = /obj/item/circuitboard/computer/aifixer
icon_keyboard = "tech_key" icon_keyboard = "tech_key"
icon_screen = "ai-fixer" icon_screen = "ai-fixer"
light_color = LIGHT_COLOR_PINK light_color = LIGHT_COLOR_PINK
ui_x = 370 circuit = /obj/item/circuitboard/computer/aifixer
ui_y = 360
var/mob/living/silicon/ai/occupier = null
var/active = FALSE
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params) /obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
if(occupier && istype(I, /obj/item/screwdriver)) if(occupier && istype(I, /obj/item/screwdriver))
@@ -20,64 +19,45 @@
else else
return ..() return ..()
/obj/machinery/computer/aifixer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) /obj/machinery/computer/aifixer/ui_interact(mob/user, datum/tgui/ui) //artur didn't port this correctly
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "AiRestorer", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "AiRestorer", name)
ui.open() ui.open()
var/dat = "" /obj/machinery/computer/aifixer/ui_data(mob/user)
var/list/data = list()
if (src.occupier) data["ejectable"] = FALSE
var/laws data["AI_present"] = FALSE
dat += "<h3>Stored AI: [src.occupier.name]</h3>" data["error"] = null
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>" if(!occupier)
data["error"] = "Please transfer an AI unit."
else
data["AI_present"] = TRUE
data["name"] = occupier.name
data["restoring"] = active
data["health"] = (occupier.health + 100) / 2
data["isDead"] = occupier.stat == DEAD
data["laws"] = occupier.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
if (src.occupier.laws.zeroth) return data
laws += "<b>0:</b> [src.occupier.laws.zeroth]<BR>"
for (var/index = 1, index <= src.occupier.laws.hacked.len, index++) /obj/machinery/computer/aifixer/ui_act(action, params)
var/law = src.occupier.laws.hacked[index] if(..())
if (length(law) > 0) return
var/num = ionnum() if(!occupier)
laws += "<b>[num]:</b> [law]<BR>" active = FALSE
for (var/index = 1, index <= src.occupier.laws.ion.len, index++) switch(action)
var/law = src.occupier.laws.ion[index] if("PRG_beginReconstruction")
if (length(law) > 0) if(occupier?.health < 100)
var/num = ionnum() to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
laws += "<b>[num]:</b> [law]<BR>" playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
active = TRUE
var/number = 1 occupier.notify_ghost_cloning("Your core files are being restored!", source = src)
for (var/index = 1, index <= src.occupier.laws.inherent.len, index++) . = TRUE
var/law = src.occupier.laws.inherent[index]
if (length(law) > 0)
laws += "<b>[number]:</b> [law]<BR>"
number++
for (var/index = 1, index <= src.occupier.laws.supplied.len, index++)
var/law = src.occupier.laws.supplied[index]
if (length(law) > 0)
laws += "<b>[number]:</b> [law]<BR>"
number++
dat += "<b>Laws:</b><br>[laws]<br>"
if (src.occupier.stat == DEAD)
dat += "<span class='bad'>AI non-functional</span>"
else
dat += "<span class='good'>AI functional</span>"
if (!src.active)
dat += {"<br><br><A href='byond://?src=[REF(src)];fix=1'>Begin Reconstruction</A>"}
else
dat += "<br><br>Reconstruction in process, please wait.<br>"
dat += {"<br><A href='?src=[REF(user)];mach_close=computer'>Close</A>"}
var/datum/browser/popup = new(user, "computer", "AI System Integrity Restorer", 400, 500)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
return
/obj/machinery/computer/aifixer/proc/Fix() /obj/machinery/computer/aifixer/proc/Fix()
use_power(1000) use_power(1000)
@@ -97,17 +77,6 @@
active = Fix() active = Fix()
if(oldstat != occupier.stat) if(oldstat != occupier.stat)
update_icon() update_icon()
updateDialog()
/obj/machinery/computer/aifixer/Topic(href, href_list)
if(..())
return
if(href_list["fix"])
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, 0)
active = TRUE
add_fingerprint(usr)
updateUsrDialog()
/obj/machinery/computer/aifixer/update_overlays() /obj/machinery/computer/aifixer/update_overlays()
. = ..() . = ..()
+153 -161
View File
@@ -3,19 +3,19 @@
desc = "Used to remotely control the flow of power to different parts of the station." desc = "Used to remotely control the flow of power to different parts of the station."
icon_screen = "solar" icon_screen = "solar"
icon_keyboard = "power_key" icon_keyboard = "power_key"
req_access = list(ACCESS_ENGINE) req_access = list(ACCESS_CE)
circuit = /obj/item/circuitboard/computer/apc_control circuit = /obj/item/circuitboard/computer/apc_control
light_color = LIGHT_COLOR_YELLOW light_color = LIGHT_COLOR_YELLOW
var/mob/living/operator //Who's operating the computer right now var/mob/living/operator //Who's operating the computer right now
var/obj/machinery/power/apc/active_apc //The APC we're using right now var/obj/machinery/power/apc/active_apc //The APC we're using right now
var/list/result_filters //For sorting the results var/should_log = TRUE
var/checking_logs = 0 var/restoring = FALSE
var/list/logs var/list/logs
var/auth_id = "\[NULL\]" var/auth_id = "\[NULL\]:"
/obj/machinery/computer/apc_control/Initialize() /obj/machinery/computer/apc_control/Initialize(mapload, obj/item/circuitboard/C)
. = ..() . = ..()
result_filters = list("Name" = null, "Charge Above" = null, "Charge Below" = null, "Responsive" = null) logs = list()
/obj/machinery/computer/apc_control/process() /obj/machinery/computer/apc_control/process()
if(operator && (!operator.Adjacent(src) || stat)) if(operator && (!operator.Adjacent(src) || stat))
@@ -23,8 +23,8 @@
if(active_apc) if(active_apc)
if(!active_apc.locked) if(!active_apc.locked)
active_apc.say("Remote access canceled. Interface locked.") active_apc.say("Remote access canceled. Interface locked.")
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0) playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE)
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0) playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE)
active_apc.locked = TRUE active_apc.locked = TRUE
active_apc.update_icon() active_apc.update_icon()
active_apc.remote_control = null active_apc.remote_control = null
@@ -34,171 +34,163 @@
if(!IsAdminGhost(user)) if(!IsAdminGhost(user))
to_chat(user,"<span class='warning'>[src] does not support AI control.</span>") //You already have APC access, cheater! to_chat(user,"<span class='warning'>[src] does not support AI control.</span>") //You already have APC access, cheater!
return return
..(user) ..()
/obj/machinery/computer/apc_control/proc/check_apc(obj/machinery/power/apc/APC) /obj/machinery/computer/apc_control/proc/check_apc(obj/machinery/power/apc/APC)
return APC.z == z && !APC.malfhack && !APC.aidisabled && !(APC.obj_flags & EMAGGED) && !APC.stat && !istype(APC.area, /area/ai_monitored) && !APC.area.outdoors return APC.z == z && !APC.malfhack && !APC.aidisabled && !(APC.obj_flags & EMAGGED) && !APC.stat && !istype(APC.area, /area/ai_monitored) && !APC.area.outdoors
/obj/machinery/computer/apc_control/ui_interact(mob/living/user) /obj/machinery/computer/apc_control/ui_interact(mob/user, datum/tgui/ui)
. = ..() operator = user
var/dat ui = SStgui.try_update_ui(user, src, ui)
if(authenticated) if(!ui)
if(!checking_logs) ui = new(user, src, "ApcControl")
dat += "Logged in as [auth_id].<br><br>" ui.open()
dat += "<i>Filters</i><br>"
dat += "<b>Name:</b> <a href='?src=[REF(src)];name_filter=1'>[result_filters["Name"] ? result_filters["Name"] : "None set"]</a><br>"
dat += "<b>Charge:</b> <a href='?src=[REF(src)];above_filter=1'>\>[result_filters["Charge Above"] ? result_filters["Charge Above"] : "NaN"]%</a> and <a href='?src=[REF(src)];below_filter=1'>\<[result_filters["Charge Below"] ? result_filters["Charge Below"] : "NaN"]%</a><br>"
dat += "<b>Accessible:</b> <a href='?src=[REF(src)];access_filter=1'>[result_filters["Responsive"] ? "Non-Responsive Only" : "All"]</a><br><br>"
for(var/A in GLOB.apcs_list)
if(check_apc(A))
var/obj/machinery/power/apc/APC = A
if(result_filters["Name"] && !findtext(APC.name, result_filters["Name"]) && !findtext(APC.area.name, result_filters["Name"]))
continue
if(result_filters["Charge Above"] && (!APC.cell || (APC.cell && (APC.cell.charge / APC.cell.maxcharge) < result_filters["Charge Above"] / 100)))
continue
if(result_filters["Charge Below"] && APC.cell && (APC.cell.charge / APC.cell.maxcharge) > result_filters["Charge Below"] / 100)
continue
if(result_filters["Responsive"] && !APC.aidisabled)
continue
dat += "<a href='?src=[REF(src)];access_apc=[REF(APC)]'>[A]</a><br>\
<b>Charge:</b> [APC.cell ? "[DisplayEnergy(APC.cell.charge)] / [DisplayEnergy(APC.cell.maxcharge)] ([round((APC.cell.charge / APC.cell.maxcharge) * 100)]%)" : "No Powercell Installed"]<br>\
<b>Area:</b> [APC.area]<br>\
[APC.aidisabled || APC.panel_open ? "<font color='#FF0000'>APC does not respond to interface query.</font>" : "<font color='#00FF00'>APC responds to interface query.</font>"]<br><br>"
dat += "<a href='?src=[REF(src)];check_logs=1'>Check Logs</a><br>"
dat += "<a href='?src=[REF(src)];log_out=1'>Log Out</a><br>"
if(obj_flags & EMAGGED)
dat += "<font color='#FF0000'>WARNING: Logging functionality partially disabled from outside source.</font><br>"
dat += "<a href='?src=[REF(src)];restore_logging=1'>Restore logging functionality?</a><br>"
else
if(logs.len)
for(var/entry in logs)
dat += "[entry]<br>"
else
dat += "<i>No activity has been recorded at this time.</i><br>"
if(obj_flags & EMAGGED)
dat += "<a href='?src=[REF(src)];clear_logs=1'><font color='#FF0000'>@#%! CLEAR LOGS</a>"
dat += "<a href='?src=[REF(src)];check_apcs=1'>Return</a>"
operator = user
else
dat = "<a href='?src=[REF(src)];authenticate=1'>Please swipe a valid ID to log in...</a>"
var/datum/browser/popup = new(user, "apc_control", name, 600, 400)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
popup.open()
/obj/machinery/computer/apc_control/Topic(href, href_list) /obj/machinery/computer/apc_control/ui_data(mob/user)
var/list/data = list()
data["auth_id"] = auth_id
data["authenticated"] = authenticated
data["emagged"] = obj_flags & EMAGGED
data["logging"] = should_log
data["restoring"] = restoring
data["logs"] = list()
data["apcs"] = list()
for(var/entry in logs)
data["logs"] += list(list("entry" = entry))
for(var/apc in GLOB.apcs_list)
if(check_apc(apc))
var/obj/machinery/power/apc/A = apc
var/has_cell = (A.cell) ? TRUE : FALSE
data["apcs"] += list(list(
"name" = A.area.name,
"operating" = A.operating,
"charge" = (has_cell) ? A.cell.percent() : "NOCELL",
"load" = DisplayPower(A.lastused_total),
"charging" = A.charging,
"chargeMode" = A.chargemode,
"eqp" = A.equipment,
"lgt" = A.lighting,
"env" = A.environ,
"responds" = A.aidisabled || A.panel_open,
"ref" = REF(A)
)
)
return data
/obj/machinery/computer/apc_control/ui_act(action, params)
if(..()) if(..())
return return
if(!usr || !usr.canUseTopic(src) || stat || QDELETED(src)) switch(action)
return if("log-in")
if(href_list["authenticate"]) if(obj_flags & EMAGGED)
var/obj/item/card/id/ID = usr.get_idcard(TRUE)
if(ID && istype(ID))
if(check_access(ID))
authenticated = TRUE authenticated = TRUE
auth_id = "[ID.registered_name] ([ID.assignment])" auth_id = "Unknown (Unknown):"
log_activity("logged in") log_activity("[auth_id] logged in to the terminal")
if(href_list["log_out"]) return
log_activity("logged out") var/obj/item/card/id/ID = operator.get_idcard(TRUE)
authenticated = FALSE if(ID && istype(ID))
auth_id = "\[NULL\]" if(check_access(ID))
if(href_list["restore_logging"]) authenticated = TRUE
to_chat(usr, "<span class='robot notice'>[icon2html(src, usr)] Logging functionality restored from backup data.</span>") auth_id = "[ID.registered_name] ([ID.assignment]):"
obj_flags &= ~EMAGGED log_activity("[auth_id] logged in to the terminal")
LAZYADD(logs, "<b>-=- Logging restored to full functionality at this point -=-</b>") playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
if(href_list["access_apc"]) else
playsound(src, "terminal_type", 50, 0) auth_id = "[ID.registered_name] ([ID.assignment]):"
var/obj/machinery/power/apc/APC = locate(href_list["access_apc"]) in GLOB.apcs_list log_activity("[auth_id] attempted to log into the terminal")
if(!APC || APC.aidisabled || APC.panel_open || QDELETED(APC)) return
to_chat(usr, "<span class='robot danger'>[icon2html(src, usr)] APC does not return interface request. Remote access may be disabled.</span>") auth_id = "Unknown (Unknown):"
return log_activity("[auth_id] attempted to log into the terminal")
if(active_apc) if("log-out")
to_chat(usr, "<span class='robot danger'>[icon2html(src, usr)] Disconnected from [active_apc].</span>") log_activity("[auth_id] logged out of the terminal")
active_apc.say("Remote access canceled. Interface locked.") playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0) authenticated = FALSE
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0) auth_id = "\[NULL\]"
active_apc.locked = TRUE if("toggle-logs")
active_apc.update_icon() should_log = !should_log
active_apc.remote_control = null log_game("[key_name(operator)] set the logs of [src] in [AREACOORD(src)] [should_log ? "On" : "Off"]")
active_apc = null if("restore-console")
to_chat(usr, "<span class='robot notice'>[icon2html(src, usr)] Connected to APC in [get_area_name(APC.area, TRUE)]. Interface request sent.</span>") restoring = TRUE
log_activity("remotely accessed APC in [get_area_name(APC.area, TRUE)]") addtimer(CALLBACK(src, .proc/restore_comp), rand(3,5) * 9)
APC.remote_control = src if("access-apc")
APC.ui_interact(usr) var/ref = params["ref"]
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) playsound(src, "terminal_type", 50, FALSE)
message_admins("[ADMIN_LOOKUPFLW(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].") var/obj/machinery/power/apc/APC = locate(ref) in GLOB.apcs_list
log_game("[key_name(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].") if(!APC)
if(APC.locked) return
APC.say("Remote access detected. Interface unlocked.") if(active_apc)
playsound(APC, 'sound/machines/boltsup.ogg', 25, 0) to_chat(operator, "<span class='robot danger'>[icon2html(src, auth_id)] Disconnected from [active_apc].</span>")
playsound(APC, 'sound/machines/terminal_alert.ogg', 50, 0) active_apc.say("Remote access canceled. Interface locked.")
APC.locked = FALSE playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE)
APC.update_icon() playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE)
active_apc = APC active_apc.locked = TRUE
if(href_list["name_filter"]) active_apc.update_icon()
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) active_apc.remote_control = null
var/new_filter = stripped_input(usr, "What name are you looking for?", name) active_apc = null
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src)) APC.remote_control = src
return APC.ui_interact(operator)
log_activity("changed name filter to \"[new_filter]\"") playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) log_game("[key_name(operator)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
result_filters["Name"] = new_filter log_activity("[auth_id] remotely accessed APC in [get_area_name(APC.area, TRUE)]")
if(href_list["above_filter"]) if(APC.locked)
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) APC.say("Remote access detected. Interface unlocked.")
var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (greater than).", name) as null|num playsound(APC, 'sound/machines/boltsup.ogg', 25, FALSE)
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src)) playsound(APC, 'sound/machines/terminal_alert.ogg', 50, FALSE)
return APC.locked = FALSE
log_activity("changed greater than charge filter to \"[new_filter]\"") APC.update_icon()
if(new_filter) active_apc = APC
new_filter = clamp(new_filter, 0, 100) if("check-logs")
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) log_activity("Checked Logs")
result_filters["Charge Above"] = new_filter if("check-apcs")
if(href_list["below_filter"]) log_activity("Checked APCs")
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0) if("toggle-minor")
var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (lesser than).", name) as null|num var/ref = params["ref"]
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src)) var/type = params["type"]
return var/value = params["value"]
log_activity("changed lesser than charge filter to \"[new_filter]\"") var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
if(new_filter) if(!target)
new_filter = clamp(new_filter, 0, 100) return
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) target.vars[type] = target.setsubsystem(text2num(value))
result_filters["Charge Below"] = new_filter target.update_icon()
if(href_list["access_filter"]) target.update()
if(isnull(result_filters["Responsive"])) var/setTo = ""
result_filters["Responsive"] = 1 switch(target.vars[type])
log_activity("sorted by non-responsive APCs only") if(0)
else setTo = "Off"
result_filters["Responsive"] = !result_filters["Responsive"] if(1)
log_activity("sorted by all APCs") setTo = "Auto Off"
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0) if(2)
if(href_list["check_logs"]) setTo = "On"
checking_logs = TRUE if(3)
log_activity("checked logs") setTo = "Auto On"
if(href_list["check_apcs"]) log_activity("Set APC [target.area.name] [type] to [setTo]")
checking_logs = FALSE log_game("[key_name(operator)] Set APC [target.area.name] [type] to [setTo]]")
log_activity("checked APCs") if("breaker")
if(href_list["clear_logs"]) var/ref = params["ref"]
logs = list() var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
ui_interact(usr) //Refresh the UI after a filter changes target.toggle_breaker()
var/setTo = target.operating ? "On" : "Off"
log_activity("Turned APC [target.area.name]'s breaker [setTo]")
/obj/machinery/computer/apc_control/emag_act(mob/user) /obj/machinery/computer/apc_control/emag_act(mob/user)
. = ..() if(obj_flags & EMAGGED)
if(!authenticated) return
to_chat(user, "<span class='warning'>You bypass [src]'s access requirements using your emag.</span>") obj_flags |= EMAGGED
authenticated = TRUE log_game("[key_name(user)] emagged [src] at [AREACOORD(src)]")
log_activity("logged in") playsound(src, "sparks", 50, TRUE)
else
if(obj_flags & EMAGGED)
return
user.visible_message("<span class='warning'>You emag [src], disabling precise logging and allowing you to clear logs.</span>")
log_game("[key_name(user)] emagged [src] at [AREACOORD(src)], disabling operator tracking.")
obj_flags |= EMAGGED
playsound(src, "sparks", 50, 1)
return TRUE
/obj/machinery/computer/apc_control/proc/log_activity(log_text) /obj/machinery/computer/apc_control/proc/log_activity(log_text)
var/op_string = operator && !(obj_flags & EMAGGED) ? operator : "\[NULL OPERATOR\]" if(!should_log)
LAZYADD(logs, "<b>([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)])</b> [op_string] [log_text]") return
LAZYADD(logs, "([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)]): [auth_id] [log_text]")
/obj/machinery/computer/apc_control/proc/restore_comp()
obj_flags &= ~EMAGGED
should_log = TRUE
log_game("[key_name(operator)] restored the logs of [src] in [AREACOORD(src)]")
log_activity("-=- Logging restored to full functionality at this point -=-")
restoring = FALSE
/mob/proc/using_power_flow_console() /mob/proc/using_power_flow_console()
for(var/obj/machinery/computer/apc_control/A in range(1, src)) for(var/obj/machinery/computer/apc_control/A in range(1, src))
+5 -6
View File
@@ -19,11 +19,10 @@
SSradio.remove_object(src, receive_frequency) SSradio.remove_object(src, receive_frequency)
return ..() return ..()
/obj/machinery/computer/atmos_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/computer/atmos_alert/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "AtmosAlertConsole", name, 350, 300, master_ui, state) ui = new(user, src, "AtmosAlertConsole", name)
ui.open() ui.open()
/obj/machinery/computer/atmos_alert/ui_data(mob/user) /obj/machinery/computer/atmos_alert/ui_data(mob/user)
@@ -45,11 +44,11 @@
if("clear") if("clear")
var/zone = params["zone"] var/zone = params["zone"]
if(zone in priority_alarms) if(zone in priority_alarms)
to_chat(usr, "Priority alarm for [zone] cleared.") to_chat(usr, "<span class='notice'>Priority alarm for [zone] cleared.</span>")
priority_alarms -= zone priority_alarms -= zone
. = TRUE . = TRUE
if(zone in minor_alarms) if(zone in minor_alarms)
to_chat(usr, "Minor alarm for [zone] cleared.") to_chat(usr, "<span class='notice'>Minor alarm for [zone] cleared.</span>")
minor_alarms -= zone minor_alarms -= zone
. = TRUE . = TRUE
update_icon() update_icon()
+3 -13
View File
@@ -91,8 +91,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
icon_screen = "tank" icon_screen = "tank"
icon_keyboard = "atmos_key" icon_keyboard = "atmos_key"
circuit = /obj/item/circuitboard/computer/atmos_control circuit = /obj/item/circuitboard/computer/atmos_control
ui_x = 400
ui_y = 925
var/frequency = FREQ_ATMOS_STORAGE var/frequency = FREQ_ATMOS_STORAGE
var/list/sensors = list( var/list/sensors = list(
@@ -123,11 +121,10 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
SSradio.remove_object(src, frequency) SSradio.remove_object(src, frequency)
return ..() return ..()
/obj/machinery/computer/atmos_control/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/computer/atmos_control/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "AtmosControlConsole", name)
ui.open() ui.open()
/obj/machinery/computer/atmos_control/ui_data(mob/user) /obj/machinery/computer/atmos_control/ui_data(mob/user)
@@ -265,13 +262,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices) for(var/obj/machinery/atmospherics/components/unary/vent_pump/U in devices)
U.broadcast_status() U.broadcast_status()
/obj/machinery/computer/atmos_control/tank/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "AtmosControlConsole", name, ui_x, ui_y, master_ui, state)
ui.open()
/obj/machinery/computer/atmos_control/tank/ui_data(mob/user) /obj/machinery/computer/atmos_control/tank/ui_data(mob/user)
var/list/data = ..() var/list/data = ..()
data["tank"] = TRUE data["tank"] = TRUE
+5 -8
View File
@@ -5,8 +5,6 @@
icon_keyboard = "security_key" icon_keyboard = "security_key"
circuit = /obj/item/circuitboard/computer/security circuit = /obj/item/circuitboard/computer/security
light_color = LIGHT_COLOR_RED light_color = LIGHT_COLOR_RED
ui_x = 870
ui_y = 708
var/list/network = list("ss13") var/list/network = list("ss13")
var/obj/machinery/camera/active_camera var/obj/machinery/camera/active_camera
@@ -55,11 +53,9 @@
network -= i network -= i
network += "[idnum][i]" network += "[idnum][i]"
/obj/machinery/computer/security/ui_interact(\ /obj/machinery/computer/security/ui_interact(mob/user, datum/tgui/ui)
mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
// Update UI // Update UI
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
// Show static if can't use the camera // Show static if can't use the camera
if(!active_camera?.can_use()) if(!active_camera?.can_use())
show_camera_static() show_camera_static()
@@ -76,10 +72,11 @@
use_power(active_power_usage) use_power(active_power_usage)
// Register map objects // Register map objects
user.client.register_map_obj(cam_screen) user.client.register_map_obj(cam_screen)
user.client.register_map_obj(cam_plane_master) for(var/plane in cam_plane_master)
user.client.register_map_obj(plane)
user.client.register_map_obj(cam_background) user.client.register_map_obj(cam_background)
// Open UI // Open UI
ui = new(user, src, ui_key, "CameraConsole", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "CameraConsole", name)
ui.open() ui.open()
/obj/machinery/computer/security/ui_data() /obj/machinery/computer/security/ui_data()
+3 -4
View File
@@ -76,11 +76,10 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
/datum/crewmonitor/Destroy() /datum/crewmonitor/Destroy()
return ..() return ..()
/datum/crewmonitor/ui_interact(mob/user, ui_key = "crew", datum/tgui/ui = null, force_open = FALSE, \ /datum/crewmonitor/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if (!ui) if (!ui)
ui = new(user, src, ui_key, "CrewConsole", "crew monitor", 800, 600 , master_ui, state) ui = new(user, src, "CrewConsole")
ui.open() ui.open()
/datum/crewmonitor/proc/show(mob/M, source) /datum/crewmonitor/proc/show(mob/M, source)
+3 -6
View File
@@ -220,9 +220,7 @@
/obj/machinery/computer/scan_consolenew/examine(mob/user) /obj/machinery/computer/scan_consolenew/examine(mob/user)
. = ..() . = ..()
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) /obj/machinery/computer/scan_consolenew/ui_interact(mob/user, datum/tgui/ui)
. = ..()
// Most of ui_interact is spent setting variables for passing to the tgui // Most of ui_interact is spent setting variables for passing to the tgui
// interface. // interface.
// We can also do some general state processing here too as it's a good // We can also do some general state processing here too as it's a good
@@ -264,10 +262,9 @@
time_to_pulse = round((rad_pulse_timer - world.time)/10) time_to_pulse = round((rad_pulse_timer - world.time)/10)
// Attempt to update tgui ui, open and update if needed. // Attempt to update tgui ui, open and update if needed.
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "DnaConsole", name, 539, 710, master_ui, state) ui = new(user, src, "DnaConsole")
ui.open() ui.open()
/obj/machinery/computer/scan_consolenew/ui_data(mob/user) /obj/machinery/computer/scan_consolenew/ui_data(mob/user)
@@ -53,10 +53,10 @@
var/obj/machinery/launchpad/pad = launchpads[number] var/obj/machinery/launchpad/pad = launchpads[number]
return pad return pad
/obj/machinery/computer/launchpad/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) /obj/machinery/computer/launchpad/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "LaunchpadConsole", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "LaunchpadConsole", name)
ui.open() ui.open()
/obj/machinery/computer/launchpad/ui_data(mob/user) /obj/machinery/computer/launchpad/ui_data(mob/user)
@@ -128,4 +128,4 @@
if("pull") if("pull")
teleport(usr, current_pad, FALSE) teleport(usr, current_pad, FALSE)
. = TRUE . = TRUE
. = TRUE . = TRUE
@@ -6,8 +6,6 @@
icon_keyboard = "security_key" icon_keyboard = "security_key"
req_access = list(ACCESS_ARMORY) req_access = list(ACCESS_ARMORY)
circuit = /obj/item/circuitboard/computer/gulag_teleporter_console circuit = /obj/item/circuitboard/computer/gulag_teleporter_console
ui_x = 350
ui_y = 295
var/default_goal = 200 var/default_goal = 200
var/obj/machinery/gulag_teleporter/teleporter = null var/obj/machinery/gulag_teleporter/teleporter = null
@@ -21,11 +19,10 @@
. = ..() . = ..()
scan_machinery() scan_machinery()
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "GulagTeleporterConsole", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "GulagTeleporterConsole", name)
ui.open() ui.open()
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user) /obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user)
+4 -5
View File
@@ -23,11 +23,10 @@
return return
return TRUE return TRUE
/obj/machinery/computer/robotics/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/computer/robotics/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "RoboticsControlConsole", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "RoboticsControlConsole", name)
ui.open() ui.open()
/obj/machinery/computer/robotics/ui_data(mob/user) /obj/machinery/computer/robotics/ui_data(mob/user)
@@ -123,5 +122,5 @@
var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread var/datum/effect_system/spark_spread/s = new /datum/effect_system/spark_spread
s.set_up(3, TRUE, D) s.set_up(3, TRUE, D)
s.start() s.start()
D.visible_message("<span class='danger'>\the [D] self destructs!</span>") D.visible_message("<span class='danger'>\the [D] self-destructs!</span>")
D.gib() D.gib()
@@ -16,11 +16,10 @@
GLOB.alert_consoles -= src GLOB.alert_consoles -= src
return ..() return ..()
/obj/machinery/computer/station_alert/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/computer/station_alert/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "StationAlertConsole", name, 325, 500, master_ui, state) ui = new(user, src, "StationAlertConsole", name)
ui.open() ui.open()
/obj/machinery/computer/station_alert/ui_data(mob/user) /obj/machinery/computer/station_alert/ui_data(mob/user)
@@ -31,6 +30,7 @@
data["alarms"][class] = list() data["alarms"][class] = list()
for(var/area in alarms[class]) for(var/area in alarms[class])
data["alarms"][class] += area data["alarms"][class] += area
return data return data
/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source) /obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
+13 -13
View File
@@ -34,11 +34,10 @@
break break
return power_station return power_station
obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/computer/teleporter/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "Teleporter", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "Teleporter", name)
ui.open() ui.open()
/obj/machinery/computer/teleporter/ui_data(mob/user) /obj/machinery/computer/teleporter/ui_data(mob/user)
@@ -56,7 +55,6 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
return data return data
/obj/machinery/computer/teleporter/ui_act(action, params) /obj/machinery/computer/teleporter/ui_act(action, params)
if(..()) if(..())
return return
@@ -92,16 +90,18 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
say("Processing hub calibration to target...") say("Processing hub calibration to target...")
calibrating = TRUE calibrating = TRUE
power_station.update_icon() power_station.update_icon()
spawn(50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration addtimer(CALLBACK(src, .proc/finish_calibration), 50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration
calibrating = FALSE
if(check_hub_connection())
power_station.teleporter_hub.calibrated = TRUE
say("Calibration complete.")
else
say("Error: Unable to detect hub.")
power_station.update_icon()
. = TRUE . = TRUE
/obj/machinery/computer/teleporter/proc/finish_calibration()
calibrating = FALSE
if(check_hub_connection())
power_station.teleporter_hub.calibrated = TRUE
say("Calibration complete.")
else
say("Error: Unable to detect hub.")
power_station.update_icon()
/obj/machinery/computer/teleporter/proc/check_hub_connection() /obj/machinery/computer/teleporter/proc/check_hub_connection()
if(!power_station) if(!power_station)
return FALSE return FALSE
+64 -46
View File
@@ -9,6 +9,7 @@
var/active = FALSE var/active = FALSE
var/list/rangers = list() var/list/rangers = list()
var/stop = 0 var/stop = 0
var/volume = 70
var/datum/track/selection = null var/datum/track/selection = null
/obj/machinery/jukebox/disco /obj/machinery/jukebox/disco
@@ -51,74 +52,91 @@
else else
icon_state = "[initial(icon_state)]" icon_state = "[initial(icon_state)]"
/obj/machinery/jukebox/ui_interact(mob/user) /obj/machinery/jukebox/ui_status(mob/user)
. = ..() if(!anchored)
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
return
if (!anchored)
to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>") to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>")
return return UI_CLOSE
if(!allowed(user)) if(!allowed(user) && !isobserver(user))
to_chat(user,"<span class='warning'>Error: Access Denied.</span>") to_chat(user,"<span class='warning'>Error: Access Denied.</span>")
user.playsound_local(src,'sound/misc/compiler-failure.ogg', 25, 1) user.playsound_local(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
return return UI_CLOSE
if(!SSjukeboxes.songs.len) if(!SSjukeboxes.songs.len && !isobserver(user))
to_chat(user,"<span class='warning'>Error: No music tracks have been authorized for your station. Petition Central Command to resolve this issue.</span>") to_chat(user,"<span class='warning'>Error: No music tracks have been authorized for your station. Petition Central Command to resolve this issue.</span>")
playsound(src,'sound/misc/compiler-failure.ogg', 25, 1) playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
return return UI_CLOSE
var/list/dat = list() return ..()
dat +="<div class='statusDisplay' style='text-align:center'>"
dat += "<b><A href='?src=[REF(src)];action=toggle'>[!active ? "BREAK IT DOWN" : "SHUT IT DOWN"]<b></A><br>"
dat += "</div><br>"
dat += "<A href='?src=[REF(src)];action=select'> Select Track</A><br>"
if(istype(selection))
dat += "Track Selected: [selection.song_name]<br>"
dat += "Track Length: [DisplayTimeText(selection.song_length)]<br><br>"
else
dat += "Track Selected: None!<br><br>"
var/datum/browser/popup = new(user, "vending", "[name]", 400, 350)
popup.set_content(dat.Join())
popup.open()
/obj/machinery/jukebox/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Jukebox", name)
ui.open()
/obj/machinery/jukebox/Topic(href, href_list) /obj/machinery/jukebox/ui_data(mob/user)
if(..()) var/list/data = list()
data["active"] = active
data["songs"] = list()
for(var/datum/track/S in SSjukeboxes.songs)
var/list/track_data = list(
name = S.song_name
)
data["songs"] += list(track_data)
data["track_selected"] = null
data["track_length"] = null
data["track_beat"] = null
if(selection)
data["track_selected"] = selection.song_name
data["track_length"] = DisplayTimeText(selection.song_length)
data["track_beat"] = selection.song_beat
data["volume"] = volume
return data
/obj/machinery/jukebox/ui_act(action, list/params)
. = ..()
if(.)
return return
add_fingerprint(usr)
switch(href_list["action"]) switch(action)
if("toggle") if("toggle")
if (QDELETED(src)) if(QDELETED(src))
return return
if(!active) if(!active)
if(stop > world.time) if(stop > world.time)
to_chat(usr, "<span class='warning'>Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].</span>") to_chat(usr, "<span class='warning'>Error: The device is still resetting from the last activation, it will be ready again in [DisplayTimeText(stop-world.time)].</span>")
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1) playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE)
return return
if(!istype(selection)) activate_music()
to_chat(usr, "<span class='warning'>Error: Severe user incompetence detected.</span>") START_PROCESSING(SSobj, src)
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1) return TRUE
return else
if(!activate_music())
to_chat(usr, "<span class='warning'>Error: Generic hardware failure.</span>")
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
return
updateUsrDialog()
else if(active)
stop = 0 stop = 0
updateUsrDialog() return TRUE
if("select") if("select_track")
if(active) if(active)
to_chat(usr, "<span class='warning'>Error: You cannot change the song until the current one is over.</span>") to_chat(usr, "<span class='warning'>Error: You cannot change the song until the current one is over.</span>")
return return
var/list/available = list() var/list/available = list()
for(var/datum/track/S in SSjukeboxes.songs) for(var/datum/track/S in SSjukeboxes.songs)
available[S.song_name] = S available[S.song_name] = S
var/selected = input(usr, "Choose your song", "Track:") as null|anything in available var/selected = params["track"]
if(QDELETED(src) || !selected || !istype(available[selected], /datum/track)) if(QDELETED(src) || !selected || !istype(available[selected], /datum/track))
return return
selection = available[selected] selection = available[selected]
updateUsrDialog() return TRUE
if("set_volume")
var/new_volume = params["volume"]
if(new_volume == "reset")
volume = initial(volume)
return TRUE
else if(new_volume == "min")
volume = 0
return TRUE
else if(new_volume == "max")
volume = 100
return TRUE
else if(text2num(new_volume) != null)
volume = text2num(new_volume)
return TRUE
/obj/machinery/jukebox/proc/activate_music() /obj/machinery/jukebox/proc/activate_music()
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2) var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2)
+39 -29
View File
@@ -50,7 +50,7 @@
integrity_failure = 0.25 integrity_failure = 0.25
damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N
autoclose = TRUE autoclose = TRUE
secondsElectrified = 0 //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it. secondsElectrified = NOT_ELECTRIFIED //How many seconds remain until the door is no longer electrified. -1 if it is permanently electrified until someone fixes it.
assemblytype = /obj/structure/door_assembly assemblytype = /obj/structure/door_assembly
normalspeed = 1 normalspeed = 1
explosion_block = 1 explosion_block = 1
@@ -298,10 +298,10 @@
/obj/machinery/door/airlock/Destroy() /obj/machinery/door/airlock/Destroy()
QDEL_NULL(wires) QDEL_NULL(wires)
QDEL_NULL(electronics)
if(charge) if(charge)
qdel(charge) qdel(charge)
charge = null charge = null
QDEL_NULL(electronics)
if (cyclelinkedairlock) if (cyclelinkedairlock)
if (cyclelinkedairlock.cyclelinkedairlock == src) if (cyclelinkedairlock.cyclelinkedairlock == src)
cyclelinkedairlock.cyclelinkedairlock = null cyclelinkedairlock.cyclelinkedairlock = null
@@ -309,7 +309,7 @@
if(id_tag) if(id_tag)
for(var/obj/machinery/doorButtons/D in GLOB.machines) for(var/obj/machinery/doorButtons/D in GLOB.machines)
D.removeMe(src) D.removeMe(src)
qdel(note) QDEL_NULL(note)
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds) for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.remove_from_hud(src) diag_hud.remove_from_hud(src)
return ..() return ..()
@@ -765,8 +765,8 @@
/obj/machinery/door/airlock/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) /obj/machinery/door/airlock/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(!(issilicon(user) || IsAdminGhost(user))) if(!(issilicon(user) || IsAdminGhost(user)))
if(src.isElectrified()) if(isElectrified())
if(src.shock(user, 100)) if(shock(user, 100))
return return
if(ishuman(user) && prob(40) && src.density) if(ishuman(user) && prob(40) && src.density)
@@ -790,15 +790,15 @@
return ..() return ..()
/obj/machinery/door/airlock/proc/electrified_loop() /obj/machinery/door/airlock/proc/electrified_loop()
while (secondsElectrified > 0) while (secondsElectrified > NOT_ELECTRIFIED)
sleep(10) sleep(10)
if(QDELETED(src)) if(QDELETED(src))
return return
secondsElectrified -= 1 secondsElectrified--
updateDialog() updateDialog()
// This is to protect against changing to permanent, mid loop. // This is to protect against changing to permanent, mid loop.
if(secondsElectrified==0) if(secondsElectrified == NOT_ELECTRIFIED)
set_electrified(NOT_ELECTRIFIED) set_electrified(NOT_ELECTRIFIED)
else else
set_electrified(ELECTRIFIED_PERMANENT) set_electrified(ELECTRIFIED_PERMANENT)
@@ -825,8 +825,8 @@
/obj/machinery/door/airlock/attackby(obj/item/C, mob/user, params) /obj/machinery/door/airlock/attackby(obj/item/C, mob/user, params)
if(!issilicon(user) && !IsAdminGhost(user)) if(!issilicon(user) && !IsAdminGhost(user))
if(src.isElectrified()) if(isElectrified())
if(src.shock(user, 75)) if(shock(user, 75))
return return
add_fingerprint(user) add_fingerprint(user)
@@ -839,7 +839,7 @@
to_chat(user, "<span class='warning'>You need at least 2 metal sheets to reinforce [src].</span>") to_chat(user, "<span class='warning'>You need at least 2 metal sheets to reinforce [src].</span>")
return return
to_chat(user, "<span class='notice'>You start reinforcing [src].</span>") to_chat(user, "<span class='notice'>You start reinforcing [src].</span>")
if(do_after(user, 20, 1, target = src)) if(do_after(user, 20, TRUE, target = src))
if(!panel_open || !S.use(2)) if(!panel_open || !S.use(2))
return return
user.visible_message("<span class='notice'>[user] reinforces \the [src] with metal.</span>", user.visible_message("<span class='notice'>[user] reinforces \the [src] with metal.</span>",
@@ -1070,7 +1070,7 @@
INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2) INVOKE_ASYNC(src, (density ? .proc/open : .proc/close), 2)
if(istype(I, /obj/item/crowbar/power)) if(istype(I, /obj/item/crowbar/power))
if(isElectrified()) if(hasPower() && isElectrified())
shock(user,100)//it's like sticking a forck in a power socket shock(user,100)//it's like sticking a forck in a power socket
return return
@@ -1090,12 +1090,11 @@
time_to_open = 50 time_to_open = 50
playsound(src, 'sound/machines/airlock_alien_prying.ogg',100,1) //is it aliens or just the CE being a dick? playsound(src, 'sound/machines/airlock_alien_prying.ogg',100,1) //is it aliens or just the CE being a dick?
prying_so_hard = TRUE prying_so_hard = TRUE
var/result = do_after(user, time_to_open,target = src) if(do_after(user, time_to_open,target = src))
prying_so_hard = FALSE
if(result)
open(2) open(2)
if(density && !open(2)) if(density && !open(2))
to_chat(user, "<span class='warning'>Despite your attempts, [src] refuses to open.</span>") to_chat(user, "<span class='warning'>Despite your attempts, [src] refuses to open.</span>")
prying_so_hard = FALSE
/obj/machinery/door/airlock/open(forced=0) /obj/machinery/door/airlock/open(forced=0)
if( operating || welded || locked ) if( operating || welded || locked )
@@ -1359,12 +1358,25 @@
wires.cut_all() wires.cut_all()
update_icon() update_icon()
/obj/machinery/door/airlock/proc/set_electrified(seconds) /obj/machinery/door/airlock/proc/set_electrified(seconds, mob/user)
secondsElectrified = seconds secondsElectrified = seconds
diag_hud_set_electrified() diag_hud_set_electrified()
if(secondsElectrified > 0) if(secondsElectrified > NOT_ELECTRIFIED)
INVOKE_ASYNC(src, .proc/electrified_loop) INVOKE_ASYNC(src, .proc/electrified_loop)
if(user)
var/message
switch(secondsElectrified)
if(ELECTRIFIED_PERMANENT)
message = "permanently shocked"
if(NOT_ELECTRIFIED)
message = "unshocked"
else
message = "temp shocked for [secondsElectrified] seconds"
LAZYADD(shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(user)] - ([uppertext(message)])"))
log_combat(user, src, message)
//add_hiddenprint(user)
/obj/machinery/door/airlock/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) /obj/machinery/door/airlock/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
. = ..() . = ..()
if(obj_integrity < (0.75 * max_integrity)) if(obj_integrity < (0.75 * max_integrity))
@@ -1438,11 +1450,10 @@
else if(istype(note, /obj/item/photo)) else if(istype(note, /obj/item/photo))
return "photo" return "photo"
/obj/machinery/door/airlock/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/door/airlock/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "AiAirlock", name, 500, 390, master_ui, state) ui = new(user, src, "AiAirlock", name)
ui.open() ui.open()
return TRUE return TRUE
@@ -1450,13 +1461,13 @@
var/list/data = list() var/list/data = list()
var/list/power = list() var/list/power = list()
power["main"] = src.secondsMainPowerLost ? 0 : 2 // boolean power["main"] = secondsMainPowerLost ? 0 : 2 // boolean
power["main_timeleft"] = src.secondsMainPowerLost power["main_timeleft"] = secondsMainPowerLost
power["backup"] = src.secondsBackupPowerLost ? 0 : 2 // boolean power["backup"] = secondsBackupPowerLost ? 0 : 2 // boolean
power["backup_timeleft"] = src.secondsBackupPowerLost power["backup_timeleft"] = secondsBackupPowerLost
data["power"] = power data["power"] = power
data["shock"] = secondsElectrified == 0 ? 2 : 0 data["shock"] = secondsElectrified == NOT_ELECTRIFIED ? 2 : 0
data["shock_timeleft"] = secondsElectrified data["shock_timeleft"] = secondsElectrified
data["id_scanner"] = !aiDisabledIdScanner data["id_scanner"] = !aiDisabledIdScanner
data["emergency"] = emergency // access data["emergency"] = emergency // access
@@ -1493,14 +1504,14 @@
loseMainPower() loseMainPower()
update_icon() update_icon()
else else
to_chat(usr, "Main power is already offline.") to_chat(usr, "<span class='warning'>Main power is already offline.</span>")
. = TRUE . = TRUE
if("disrupt-backup") if("disrupt-backup")
if(!secondsBackupPowerLost) if(!secondsBackupPowerLost)
loseBackupPower() loseBackupPower()
update_icon() update_icon()
else else
to_chat(usr, "Backup power is already offline.") to_chat(usr, "<span class='warning'>Backup power is already offline.</span>")
. = TRUE . = TRUE
if("shock-restore") if("shock-restore")
shock_restore(usr) shock_restore(usr)
@@ -1529,7 +1540,6 @@
. = TRUE . = TRUE
if("speed-toggle") if("speed-toggle")
normalspeed = !normalspeed normalspeed = !normalspeed
. = TRUE . = TRUE
if("open-close") if("open-close")
user_toggle_open(usr) user_toggle_open(usr)
@@ -15,11 +15,13 @@
. = ..() . = ..()
. += "<span class='notice'>Has a neat <i>selection menu</i> for modifying airlock access levels.</span>" . += "<span class='notice'>Has a neat <i>selection menu</i> for modifying airlock access levels.</span>"
/obj/item/electronics/airlock/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/item/electronics/airlock/ui_state(mob/user)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) return GLOB.hands_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/electronics/airlock/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "AirlockElectronics", name, 420, 485, master_ui, state) ui = new(user, src, "AirlockElectronics", name)
ui.open() ui.open()
/obj/item/electronics/airlock/ui_static_data(mob/user) /obj/item/electronics/airlock/ui_static_data(mob/user)
+4 -5
View File
@@ -140,11 +140,10 @@
. = new_time == timer_duration //return 1 on no change . = new_time == timer_duration //return 1 on no change
timer_duration = new_time timer_duration = new_time
/obj/machinery/door_timer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/door_timer/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "BrigTimer", name, 300, 138, master_ui, state) ui = new(user, src, "BrigTimer", name)
ui.open() ui.open()
//icon update function //icon update function
@@ -235,7 +234,7 @@
preset_time = PRESET_LONG preset_time = PRESET_LONG
. = set_timer(preset_time) . = set_timer(preset_time)
if(timing) if(timing)
activation_time = REALTIMEOFDAY activation_time = world.time
else else
. = FALSE . = FALSE
+13 -14
View File
@@ -20,18 +20,15 @@
return ..() return ..()
/obj/machinery/gulag_item_reclaimer/emag_act(mob/user) /obj/machinery/gulag_item_reclaimer/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED) // emagging lets anyone reclaim all the items if(obj_flags & EMAGGED) // emagging lets anyone reclaim all the items
return return
req_access = list() req_access = list()
obj_flags |= EMAGGED obj_flags |= EMAGGED
return TRUE
/obj/machinery/gulag_item_reclaimer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/gulag_item_reclaimer/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "GulagItemReclaimer", name, 300, 400, master_ui, state) ui = new(user, src, "GulagItemReclaimer", name)
ui.open() ui.open()
/obj/machinery/gulag_item_reclaimer/ui_data(mob/user) /obj/machinery/gulag_item_reclaimer/ui_data(mob/user)
@@ -60,20 +57,22 @@
mobs += list(mob_info) mobs += list(mob_info)
data["mobs"] = mobs data["mobs"] = mobs
data["can_reclaim"] = can_reclaim data["can_reclaim"] = can_reclaim
return data return data
/obj/machinery/gulag_item_reclaimer/ui_act(action, list/params) /obj/machinery/gulag_item_reclaimer/ui_act(action, params)
if(..())
return
switch(action) switch(action)
if("release_items") if("release_items")
var/mob/M = locate(params["mobref"]) var/mob/living/carbon/human/H = locate(params["mobref"]) in stored_items
if(M == usr || allowed(usr)) if(H != usr && !allowed(usr))
drop_items(M) to_chat(usr, "<span class='warning'>Access denied.</span>")
else return
to_chat(usr, "Access denied.") drop_items(H)
. = TRUE
/obj/machinery/gulag_item_reclaimer/proc/drop_items(mob/user) /obj/machinery/gulag_item_reclaimer/proc/drop_items(mob/user)
if(!stored_items[user]) if(!stored_items[user])
+182 -187
View File
@@ -25,7 +25,6 @@ Possible to do for anyone motivated enough:
*/ */
GLOBAL_LIST_EMPTY(network_holopads) GLOBAL_LIST_EMPTY(network_holopads)
#define HOLOPAD_PASSIVE_POWER_USAGE 1 #define HOLOPAD_PASSIVE_POWER_USAGE 1
#define HOLOGRAM_POWER_USAGE 2 #define HOLOGRAM_POWER_USAGE 2
@@ -34,34 +33,64 @@ GLOBAL_LIST_EMPTY(network_holopads)
desc = "It's a floor-mounted device for projecting holographic images." desc = "It's a floor-mounted device for projecting holographic images."
icon_state = "holopad0" icon_state = "holopad0"
layer = LOW_OBJ_LAYER layer = LOW_OBJ_LAYER
plane = ABOVE_WALL_PLANE plane = FLOOR_PLANE
flags_1 = HEAR_1 flags_1 = HEAR_1
req_access = list(ACCESS_KEYCARD_AUTH) //Used to allow for forced connecting to other (not secure) holopads. Anyone can make a call, though.
use_power = IDLE_POWER_USE use_power = IDLE_POWER_USE
idle_power_usage = 5 idle_power_usage = 5
active_power_usage = 100 active_power_usage = 100
max_integrity = 300 max_integrity = 300
armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0) armor = list("melee" = 50, "bullet" = 20, "laser" = 20, "energy" = 20, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0)
circuit = /obj/item/circuitboard/machine/holopad circuit = /obj/item/circuitboard/machine/holopad
var/list/masters //List of living mobs that use the holopad /// List of living mobs that use the holopad
var/list/holorays //Holoray-mob link. var/list/masters
var/last_request = 0 //to prevent request spam. ~Carn /// Holoray-mob link
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating. var/list/holorays
var/temp = "" /// To prevent request spam. ~Carn
var/list/holo_calls //array of /datum/holocalls var/last_request = 0
var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs /// Change to change how far the AI can move away from the holopad before deactivating
var/obj/item/disk/holodisk/disk //Record disk var/holo_range = 5
var/replay_mode = FALSE //currently replaying a recording /// Array of /datum/holocalls
var/loop_mode = FALSE //currently looping a recording var/list/holo_calls
var/record_mode = FALSE //currently recording /// Currently outgoing holocall, do not modify the datums only check and call the public procs
var/record_start = 0 //recording start time var/datum/holocall/outgoing_call
var/record_user //user that inititiated the recording /// Record disk
var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram var/obj/item/disk/holodisk/disk
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging /// Currently replaying a recording
var/replay_mode = FALSE
/// Currently looping a recording
var/loop_mode = FALSE
/// Currently recording
var/record_mode = FALSE
/// Recording start time
var/record_start = 0
/// User that inititiated the recording
var/record_user
/// Replay hologram
var/obj/effect/overlay/holo_pad_hologram/replay_holo
/// Calls will be automatically answered after a couple rings, here for debugging
var/static/force_answer_call = FALSE
// var/static/list/holopads = list()
var/obj/effect/overlay/holoray/ray var/obj/effect/overlay/holoray/ray
var/ringing = FALSE var/ringing = FALSE
var/offset = FALSE var/offset = FALSE
var/on_network = TRUE var/on_network = TRUE
/// For pads in secure areas; do not allow forced connecting
var/secure = FALSE
/// If we are currently calling another holopad
var/calling = FALSE
/*
/obj/machinery/holopad/secure
name = "secure holopad"
desc = "It's a floor-mounted device for projecting holographic images. This one will refuse to auto-connect incoming calls."
secure = TRUE
/obj/machinery/holopad/secure/Initialize()
. = ..()
var/obj/item/circuitboard/machine/holopad/board = circuit
board.secure = TRUE
board.build_path = /obj/machinery/holopad/secure
*/
/obj/machinery/holopad/tutorial /obj/machinery/holopad/tutorial
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
flags_1 = NODECONSTRUCT_1 flags_1 = NODECONSTRUCT_1
@@ -121,10 +150,8 @@ GLOBAL_LIST_EMPTY(network_holopads)
return ..() return ..()
/obj/machinery/holopad/power_change() /obj/machinery/holopad/power_change()
if (powered()) . = ..()
stat &= ~NOPOWER if (!powered())
else
stat |= NOPOWER
if(replay_mode) if(replay_mode)
replay_stop() replay_stop()
if(record_mode) if(record_mode)
@@ -163,171 +190,150 @@ GLOBAL_LIST_EMPTY(network_holopads)
if(istype(P,/obj/item/disk/holodisk)) if(istype(P,/obj/item/disk/holodisk))
if(disk) if(disk)
to_chat(user,"<span class='notice'>There's already a disk inside [src]</span>") to_chat(user,"<span class='warning'>There's already a disk inside [src]!</span>")
return return
if (!user.transferItemToLoc(P,src)) if (!user.transferItemToLoc(P,src))
return return
to_chat(user,"<span class='notice'>You insert [P] into [src]</span>") to_chat(user,"<span class='notice'>You insert [P] into [src].</span>")
disk = P disk = P
updateDialog()
return return
return ..() return ..()
/obj/machinery/holopad/ui_status(mob/user)
if(!is_operational())
return UI_CLOSE
if(outgoing_call && !calling)
return UI_CLOSE
return ..()
/obj/machinery/holopad/ui_interact(mob/living/carbon/human/user) //Carn: Hologram requests. /obj/machinery/holopad/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Holopad", name)
ui.open()
/obj/machinery/holopad/ui_data(mob/user)
var/list/data = list()
data["calling"] = calling
data["on_network"] = on_network
data["on_cooldown"] = last_request + 200 < world.time ? FALSE : TRUE
data["allowed"] = allowed(user)
data["disk"] = disk ? TRUE : FALSE
data["disk_record"] = disk?.record ? TRUE : FALSE
data["replay_mode"] = replay_mode
data["loop_mode"] = loop_mode
data["record_mode"] = record_mode
data["holo_calls"] = list()
for(var/I in holo_calls)
var/datum/holocall/HC = I
var/list/call_data = list(
caller = HC.user,
connected = HC.connected_holopad == src ? TRUE : FALSE,
ref = REF(HC)
)
data["holo_calls"] += list(call_data)
return data
/obj/machinery/holopad/ui_act(action, list/params)
. = ..() . = ..()
if(!istype(user)) if(.)
return return
if(outgoing_call || user.incapacitated() || !is_operational()) switch(action)
return if("AIrequest")
if(last_request + 200 < world.time)
user.set_machine(src) last_request = world.time
var/dat to_chat(usr, "<span class='info'>You requested an AI's presence.</span>")
if(temp) var/area/area = get_area(src)
dat = temp for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs)
else if(!AI.client)
if(on_network) continue
dat += "<a href='?src=[REF(src)];AIrequest=1'>Request an AI's presence</a><br>" to_chat(AI, "<span class='info'>Your presence is requested at <a href='?src=[REF(AI)];jumptoholopad=[REF(src)]'>\the [area]</a>.</span>")
dat += "<a href='?src=[REF(src)];Holocall=1'>Call another holopad</a><br>" return TRUE
if(disk)
if(disk.record)
//Replay
dat += "<a href='?src=[REF(src)];replay_start=1'>Replay disk recording</a><br>"
dat += "<a href='?src=[REF(src)];loop_start=1'>Loop disk recording</a><br>"
//Clear
dat += "<a href='?src=[REF(src)];record_clear=1'>Clear disk recording</a><br>"
else else
//Record to_chat(usr, "<span class='info'>A request for AI presence was already sent recently.</span>")
dat += "<a href='?src=[REF(src)];record_start=1'>Start new recording</a><br>" return
//Eject if("holocall")
dat += "<a href='?src=[REF(src)];disk_eject=1'>Eject disk</a><br>" if(outgoing_call)
return
if(usr.loc == loc)
var/list/callnames = list()
for(var/I in GLOB.network_holopads)
var/area/A = get_area(I)
if(A)
LAZYADD(callnames[A], I)
callnames -= get_area(src)
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in sortNames(callnames)
if(QDELETED(usr) || !result || outgoing_call)
return
if(usr.loc == loc)
var/input = text2num(params["headcall"])
var/headcall = input == 1 ? TRUE : FALSE
new /datum/holocall(usr, src, callnames[result], headcall)
calling = TRUE
return TRUE
else
to_chat(usr, "<span class='warning'>You must stand on the holopad to make a call!</span>")
if("connectcall")
var/datum/holocall/call_to_connect = locate(params["holopad"]) in holo_calls
if(!QDELETED(call_to_connect))
call_to_connect.Answer(src)
return TRUE
if("disconnectcall")
var/datum/holocall/call_to_disconnect = locate(params["holopad"]) in holo_calls
if(!QDELETED(call_to_disconnect))
call_to_disconnect.Disconnect(src)
return TRUE
if("disk_eject")
if(disk && !replay_mode)
disk.forceMove(drop_location())
disk = null
return TRUE
if("replay_mode")
if(replay_mode)
replay_stop()
return TRUE
else
replay_start()
return TRUE
if("loop_mode")
loop_mode = !loop_mode
return TRUE
if("record_mode")
if(record_mode)
record_stop()
return TRUE
else
record_start(usr)
return TRUE
if("record_clear")
record_clear()
return TRUE
if("offset")
offset++
if(offset > 4)
offset = FALSE
var/turf/new_turf
if(!offset)
new_turf = get_turf(src)
else
new_turf = get_step(src, GLOB.cardinals[offset])
replay_holo.forceMove(new_turf)
return TRUE
if("hang_up")
if(outgoing_call)
outgoing_call.Disconnect(src)
return TRUE
if(LAZYLEN(holo_calls)) /**
dat += "=====================================================<br>" * hangup_all_calls: Disconnects all current holocalls from the holopad
*/
if(on_network)
var/one_answered_call = FALSE
var/one_unanswered_call = FALSE
for(var/I in holo_calls)
var/datum/holocall/HC = I
if(HC.connected_holopad != src)
dat += "<a href='?src=[REF(src)];connectcall=[REF(HC)]'>Answer call from [get_area(HC.calling_holopad)]</a><br>"
one_unanswered_call = TRUE
else
one_answered_call = TRUE
if(one_answered_call && one_unanswered_call)
dat += "=====================================================<br>"
//we loop twice for formatting
for(var/I in holo_calls)
var/datum/holocall/HC = I
if(HC.connected_holopad == src)
dat += "<a href='?src=[REF(src)];disconnectcall=[REF(HC)]'>Disconnect call from [HC.user]</a><br>"
var/datum/browser/popup = new(user, "holopad", name, 300, 175)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
//Stop ringing the AI!!
/obj/machinery/holopad/proc/hangup_all_calls() /obj/machinery/holopad/proc/hangup_all_calls()
for(var/I in holo_calls) for(var/I in holo_calls)
var/datum/holocall/HC = I var/datum/holocall/HC = I
HC.Disconnect(src) HC.Disconnect(src)
/obj/machinery/holopad/Topic(href, href_list)
if(..() || isAI(usr))
return
add_fingerprint(usr)
if(!is_operational())
return
if (href_list["AIrequest"])
if(last_request + 200 < world.time)
last_request = world.time
temp = "You requested an AI's presence.<BR>"
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
var/area/area = get_area(src)
for(var/mob/living/silicon/ai/AI in GLOB.silicon_mobs)
if(!AI.client)
continue
to_chat(AI, "<span class='info'>Your presence is requested at <a href='?src=[REF(AI)];jumptoholopad=[REF(src)]'>\the [area]</a>.</span>")
else
temp = "A request for AI presence was already sent recently.<BR>"
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
else if(href_list["Holocall"])
if(outgoing_call)
return
temp = "You must stand on the holopad to make a call!<br>"
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
if(usr.loc == loc)
var/list/callnames = list()
for(var/I in GLOB.network_holopads)
var/area/A = get_area(I)
if(A)
LAZYADD(callnames[A], I)
callnames -= get_area(src)
var/result = input(usr, "Choose an area to call", "Holocall") as null|anything in callnames
if(QDELETED(usr) || !result || outgoing_call)
return
if(usr.loc == loc)
temp = "Dialing...<br>"
temp += "<A href='?src=[REF(src)];mainmenu=1'>Main Menu</A>"
new /datum/holocall(usr, src, callnames[result])
else if(href_list["connectcall"])
var/datum/holocall/call_to_connect = locate(href_list["connectcall"])
if(!QDELETED(call_to_connect))
call_to_connect.Answer(src)
temp = ""
else if(href_list["disconnectcall"])
var/datum/holocall/call_to_disconnect = locate(href_list["disconnectcall"])
if(!QDELETED(call_to_disconnect))
call_to_disconnect.Disconnect(src)
temp = ""
else if(href_list["mainmenu"])
temp = ""
if(outgoing_call)
outgoing_call.Disconnect()
else if(href_list["disk_eject"])
if(disk && !replay_mode)
disk.forceMove(drop_location())
disk = null
else if(href_list["replay_stop"])
replay_stop()
else if(href_list["replay_start"])
replay_start()
else if(href_list["loop_start"])
loop_mode = TRUE
replay_start()
else if(href_list["record_start"])
record_start(usr)
else if(href_list["record_stop"])
record_stop()
else if(href_list["record_clear"])
record_clear()
else if(href_list["offset"])
offset++
if (offset > 4)
offset = FALSE
var/turf/new_turf
if (!offset)
new_turf = get_turf(src)
else
new_turf = get_step(src, GLOB.cardinals[offset])
replay_holo.forceMove(new_turf)
updateDialog()
//do not allow AIs to answer calls or people will use it to meta the AI sattelite //do not allow AIs to answer calls or people will use it to meta the AI sattelite
/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user) /obj/machinery/holopad/attack_ai(mob/living/silicon/ai/user)
if (!istype(user)) if (!istype(user))
@@ -366,6 +372,9 @@ GLOBAL_LIST_EMPTY(network_holopads)
if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2))) if(force_answer_call && world.time > (HC.call_start_time + (HOLOPAD_MAX_DIAL_TIME / 2)))
HC.Answer(src) HC.Answer(src)
break break
if(!secure) //HC.head_call &&
HC.Answer(src)
break
if(outgoing_call) if(outgoing_call)
HC.Disconnect(src)//can't answer calls while calling HC.Disconnect(src)//can't answer calls while calling
else else
@@ -412,17 +421,17 @@ GLOBAL_LIST_EMPTY(network_holopads)
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad. /*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
For the other part of the code, check silicon say.dm. Particularly robot talk.*/ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source) /obj/machinery/holopad/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, list/message_mods = list())
. = ..() . = ..()
if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios. if(speaker && LAZYLEN(masters) && !radio_freq)//Master is mostly a safety in case lag hits or something. Radio_freq so AIs dont hear holopad stuff through radios.
for(var/mob/living/silicon/ai/master in masters) for(var/mob/living/silicon/ai/master in masters)
if(masters[master] && speaker != master) if(masters[master] && speaker != master)
master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mode) master.relay_speech(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
for(var/I in holo_calls) for(var/I in holo_calls)
var/datum/holocall/HC = I var/datum/holocall/HC = I
if(HC.connected_holopad == src && speaker != HC.hologram) if(HC.connected_holopad == src && speaker != HC.hologram)
HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode, source) HC.user.Hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mods)
if(outgoing_call && speaker == outgoing_call.user) if(outgoing_call && speaker == outgoing_call.user)
outgoing_call.hologram.say(raw_message) outgoing_call.hologram.say(raw_message)
@@ -449,7 +458,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
else else
icon_state = "holopad0" icon_state = "holopad0"
/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h) /obj/machinery/holopad/proc/set_holo(mob/living/user, obj/effect/overlay/holo_pad_hologram/h)
LAZYSET(masters, user, h) LAZYSET(masters, user, h)
LAZYSET(holorays, user, new /obj/effect/overlay/holoray(loc)) LAZYSET(holorays, user, new /obj/effect/overlay/holoray(loc))
var/mob/living/silicon/ai/AI = user var/mob/living/silicon/ai/AI = user
@@ -504,7 +513,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
else else
return FALSE return FALSE
/obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf, direction) /obj/machinery/holopad/proc/move_hologram(mob/living/user, turf/new_turf)
if(LAZYLEN(masters) && masters[user]) if(LAZYLEN(masters) && masters[user])
var/obj/effect/overlay/holo_pad_hologram/holo = masters[user] var/obj/effect/overlay/holo_pad_hologram/holo = masters[user]
var/transfered = FALSE var/transfered = FALSE
@@ -516,8 +525,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
transfered = TRUE transfered = TRUE
//All is good. //All is good.
holo.forceMove(new_turf) holo.forceMove(new_turf)
if(direction)
holo.setDir(direction)
if(!transfered) if(!transfered)
update_holoray(user,new_turf) update_holoray(user,new_turf)
return TRUE return TRUE
@@ -568,22 +575,15 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
if(!replay_mode) if(!replay_mode)
replay_mode = TRUE replay_mode = TRUE
replay_holo = setup_replay_holo(disk.record) replay_holo = setup_replay_holo(disk.record)
temp = "Replaying...<br>"
temp += "<A href='?src=[REF(src)];offset=1'>Change offset</A><br>"
temp += "<A href='?src=[REF(src)];replay_stop=1'>End replay</A>"
SetLightsAndPower() SetLightsAndPower()
replay_entry(1) replay_entry(1)
return
/obj/machinery/holopad/proc/replay_stop() /obj/machinery/holopad/proc/replay_stop()
if(replay_mode) if(replay_mode)
replay_mode = FALSE replay_mode = FALSE
loop_mode = FALSE
offset = FALSE offset = FALSE
temp = null
QDEL_NULL(replay_holo) QDEL_NULL(replay_holo)
SetLightsAndPower() SetLightsAndPower()
updateDialog()
/obj/machinery/holopad/proc/record_start(mob/living/user) /obj/machinery/holopad/proc/record_start(mob/living/user)
if(!user || !disk || disk.record) if(!user || !disk || disk.record)
@@ -593,8 +593,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
record_start = world.time record_start = world.time
record_user = user record_user = user
disk.record.set_caller_image(user) disk.record.set_caller_image(user)
temp = "Recording...<br>"
temp += "<A href='?src=[REF(src)];record_stop=1'>End recording.</A>"
/obj/machinery/holopad/proc/record_message(mob/living/speaker,message,language) /obj/machinery/holopad/proc/record_message(mob/living/speaker,message,language)
if(!record_mode) if(!record_mode)
@@ -641,7 +639,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
if(replay_holo) if(replay_holo)
replay_holo.say(message) replay_holo.say(message)
if(HOLORECORD_SOUND) if(HOLORECORD_SOUND)
playsound(src,entry[2],50,1) playsound(src,entry[2],50,TRUE)
if(HOLORECORD_DELAY) if(HOLORECORD_DELAY)
addtimer(CALLBACK(src,.proc/replay_entry,entry_number+1),entry[2]) addtimer(CALLBACK(src,.proc/replay_entry,entry_number+1),entry[2])
return return
@@ -660,14 +658,11 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
/obj/machinery/holopad/proc/record_stop() /obj/machinery/holopad/proc/record_stop()
if(record_mode) if(record_mode)
record_mode = FALSE record_mode = FALSE
temp = null
record_user = null record_user = null
updateDialog()
/obj/machinery/holopad/proc/record_clear() /obj/machinery/holopad/proc/record_clear()
if(disk && disk.record) if(disk && disk.record)
QDEL_NULL(disk.record) QDEL_NULL(disk.record)
updateDialog()
/obj/effect/overlay/holo_pad_hologram /obj/effect/overlay/holo_pad_hologram
initial_language_holder = /datum/language_holder/universal initial_language_holder = /datum/language_holder/universal
+9 -10
View File
@@ -6,14 +6,12 @@
circuit = /obj/item/circuitboard/machine/hypnochair circuit = /obj/item/circuitboard/machine/hypnochair
density = TRUE density = TRUE
opacity = 0 opacity = 0
ui_x = 375
ui_y = 480
var/mob/living/carbon/victim = null ///Keeps track of the victim to apply effects if it teleports away var/mob/living/carbon/victim = null ///Keeps track of the victim to apply effects if it teleports away
var/interrogating = FALSE ///Is the device currently interrogating someone? var/interrogating = FALSE ///Is the device currently interrogating someone?
var/start_time = 0 ///Time when the interrogation was started, to calculate effect in case of interruption var/start_time = 0 ///Time when the interrogation was started, to calculate effect in case of interruption
var/trigger_phrase = "" ///Trigger phrase to implant var/trigger_phrase = "" ///Trigger phrase to implant
var/timerid = 0 ///Timer ID for interrogations var/timerid = 0 ///Timer ID for interrogations
var/message_cooldown = 0 ///Cooldown for breakout message var/message_cooldown = 0 ///Cooldown for breakout message
/obj/machinery/hypnochair/Initialize() /obj/machinery/hypnochair/Initialize()
@@ -25,24 +23,24 @@
if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I)) if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))
update_icon() update_icon()
return return
if(default_pry_open(I)) if(default_pry_open(I))
return return
if(default_deconstruction_crowbar(I)) if(default_deconstruction_crowbar(I))
return return
return ..() return ..()
/obj/machinery/hypnochair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) /obj/machinery/hypnochair/ui_state(mob/user)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) return GLOB.notcontained_state
/obj/machinery/hypnochair/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "HypnoChair", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "HypnoChair", name)
ui.open() ui.open()
/obj/machinery/hypnochair/ui_data() /obj/machinery/hypnochair/ui_data()
var/list/data = list() var/list/data = list()
data["occupied"] = occupant ? TRUE : FALSE data["occupied"] = occupant ? 1 : 0
data["open"] = state_open data["open"] = state_open
data["interrogating"] = interrogating data["interrogating"] = interrogating
@@ -201,3 +199,4 @@
if(!(L.mobility_flags & MOBILITY_STAND)) if(!(L.mobility_flags & MOBILITY_STAND))
return return
close_machine(target) close_machine(target)
+7 -5
View File
@@ -282,12 +282,14 @@
ui_interact(user) ui_interact(user)
to_chat(user, "<span class='notice'>[src] projects a display onto your retina.</span>") to_chat(user, "<span class='notice'>[src] projects a display onto your retina.</span>")
/obj/item/launchpad_remote/ui_interact(mob/user, ui_key = "launchpad_remote", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) /obj/item/launchpad_remote/ui_state(mob/user)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) return GLOB.inventory_state
if(!ui)
ui = new(user, src, ui_key, "LaunchpadRemote", "Briefcase Launchpad Remote", 300, 240, master_ui, state) //width, height
ui.open()
/obj/item/launchpad_remote/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "LaunchpadRemote")
ui.open()
ui.set_autoupdate(TRUE) ui.set_autoupdate(TRUE)
/obj/item/launchpad_remote/ui_data(mob/user) /obj/item/launchpad_remote/ui_data(mob/user)
@@ -4,6 +4,15 @@
#define POPUP_ANIM_TIME 5 #define POPUP_ANIM_TIME 5
#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad #define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad
#define TURRET_FLAG_SHOOT_ALL_REACT (1<<0) // The turret gets pissed off and shoots at people nearby (unless they have sec access!)
#define TURRET_FLAG_AUTH_WEAPONS (1<<1) // Checks if it can shoot people that have a weapon they aren't authorized to have
#define TURRET_FLAG_SHOOT_CRIMINALS (1<<2) // Checks if it can shoot people that are wanted
#define TURRET_FLAG_SHOOT_ALL (1<<3) // The turret gets pissed off and shoots at people nearby (unless they have sec access!)
#define TURRET_FLAG_SHOOT_ANOMALOUS (1<<4) // Checks if it can shoot at unidentified lifeforms (ie xenos)
#define TURRET_FLAG_SHOOT_UNSHIELDED (1<<5) // Checks if it can shoot people that aren't mindshielded and who arent heads
#define TURRET_FLAG_SHOOT_BORGS (1<<6) // checks if it can shoot cyborgs
#define TURRET_FLAG_SHOOT_HEADS (1<<7) // checks if it can shoot at heads of staff
/obj/machinery/porta_turret /obj/machinery/porta_turret
name = "turret" name = "turret"
icon = 'icons/obj/turrets.dmi' icon = 'icons/obj/turrets.dmi'
@@ -15,70 +24,79 @@
use_power = IDLE_POWER_USE //this turret uses and requires power use_power = IDLE_POWER_USE //this turret uses and requires power
idle_power_usage = 50 //when inactive, this turret takes up constant 50 Equipment power idle_power_usage = 50 //when inactive, this turret takes up constant 50 Equipment power
active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power active_power_usage = 300 //when active, this turret takes up constant 300 Equipment power
req_access = list(ACCESS_SEC_DOORS) req_access = list(ACCESS_SECURITY) /// Only people with Security access
power_channel = EQUIP //drains power from the EQUIPMENT channel power_channel = EQUIP //drains power from the EQUIPMENT channel
speed_process = TRUE
var/base_icon_state = "standard"
var/scan_range = 7
var/atom/base = null //for turrets inside other objects
var/raised = 0 //if the turret cover is "open" and the turret is raised
var/raising= 0 //if the turret is currently opening or closing its cover
max_integrity = 160 //the turret's health max_integrity = 160 //the turret's health
integrity_failure = 0.5 integrity_failure = 0.5
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
/// Base turret icon state
var/locked = TRUE //if the turret's behaviour control access is locked var/base_icon_state = "standard"
var/controllock = FALSE //if the turret responds to control panels /// Scan range of the turret for locating targets
var/scan_range = 7
var/installation = /obj/item/gun/energy/e_gun/turret //the type of weapon installed by default /// For turrets inside other objects
var/atom/base = null
/// If the turret cover is "open" and the turret is raised
var/raised = FALSE
/// If the turret is currently opening or closing its cover
var/raising = FALSE
/// If the turret's behaviour control access is locked
var/locked = TRUE
/// If the turret responds to control panels
var/controllock = FALSE
/// The type of weapon installed by default
var/installation = /obj/item/gun/energy/e_gun/turret
/// What stored gun is in the turret
var/obj/item/gun/stored_gun = null var/obj/item/gun/stored_gun = null
var/gun_charge = 0 //the charge of the gun when retrieved from wreckage /// The charge of the gun when retrieved from wreckage
var/gun_charge = 0
/// In which mode is turret in, stun or lethal
var/mode = TURRET_STUN var/mode = TURRET_STUN
/// Stun mode projectile type
var/stun_projectile = null //stun mode projectile type var/stun_projectile = null
/// Sound of stun projectile
var/stun_projectile_sound var/stun_projectile_sound
var/nonlethal_projectile //projectile to use in stun mode when the target is resting, if any /// Projectile to use in stun mode when the target is resting, if any
var/nonlethal_projectile
/// Sound of stun projectile wen the target is resting, optional
var/nonlethal_projectile_sound var/nonlethal_projectile_sound
var/lethal_projectile = null //lethal mode projectile type /// Lethal mode projectile type
var/lethal_projectile = null
/// Sound of lethal projectile
var/lethal_projectile_sound var/lethal_projectile_sound
/// Power needed per shot
var/reqpower = 500 //power needed per shot var/reqpower = 500
var/always_up = 0 //Will stay active /// Will stay active
var/has_cover = 1 //Hides the cover var/always_up = FALSE
/// Hides the cover
var/obj/machinery/porta_turret_cover/cover = null //the cover that is covering this turret var/has_cover = TRUE
/// The cover that is covering this turret
var/last_fired = 0 //world.time the turret last fired var/obj/machinery/porta_turret_cover/cover = null
var/shot_delay = 15 //ticks until next shot (1.5 ?) /// World.time the turret last fired
var/shot_stagger = 0 // sleep() shots to stagger attacks var/last_fired = 0
/// Ticks until next shot (1.5 ?)
var/check_records = 1 //checks if it can use the security records var/shot_delay = 15
var/criminals = 1 //checks if it can shoot people on arrest /// Turret flags about who is turret allowed to shoot
var/auth_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have var/turret_flags = TURRET_FLAG_SHOOT_CRIMINALS | TURRET_FLAG_SHOOT_ANOMALOUS
var/stun_all = 0 //if this is active, the turret shoots everything that isn't security or head of staff /// Determines if the turret is on
var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos) var/on = TRUE
var/shoot_unloyal = 0 //checks if it can shoot people that aren't loyalty implantd /// Same faction mobs will never be shot at, no matter the other settings
var/list/faction = list("turret")
var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!) /// The spark system, used for generating... sparks?
var/datum/effect_system/spark_spread/spark_system
var/on = TRUE //determines if the turret is on /// Linked turret control panel of the turret
var/list/faction = list("turret") // Same faction mobs will never be shot at, no matter the other settings
var/datum/effect_system/spark_spread/spark_system //the spark system, used for generating... sparks?
var/obj/machinery/turretid/cp = null var/obj/machinery/turretid/cp = null
/// The turret will try to shoot from a turf in that direction when in a wall
var/wall_turret_direction //The turret will try to shoot from a turf in that direction when in a wall var/wall_turret_direction
/// If the turret is manually controlled
var/manual_control = FALSE // var/manual_control = FALSE
/// Action button holder for quitting manual control
var/datum/action/turret_quit/quit_action var/datum/action/turret_quit/quit_action
/// Action button holder for switching between turret modes when manually controlling
var/datum/action/turret_toggle/toggle_action var/datum/action/turret_toggle/toggle_action
/// Mob that is remotely controlling the turret
var/mob/remote_controller var/mob/remote_controller
/// MISSING:
var/shot_stagger = 0
/obj/machinery/porta_turret/Initialize() /obj/machinery/porta_turret/Initialize()
. = ..() . = ..()
@@ -100,6 +118,27 @@
if(!has_cover) if(!has_cover)
INVOKE_ASYNC(src, .proc/popUp) INVOKE_ASYNC(src, .proc/popUp)
/obj/machinery/porta_turret/proc/toggle_on(var/set_to)
var/current = on
if (!isnull(set_to))
on = set_to
else
on = !on
if (current != on)
check_should_process()
if (!on)
popDown()
/obj/machinery/porta_turret/proc/check_should_process()
if (datum_flags & DF_ISPROCESSING)
if (!on || !anchored || (stat & BROKEN) || !powered())
//end_processing()
STOP_PROCESSING(SSmachines, src)
else
if (on && anchored && !(stat & BROKEN) && powered())
START_PROCESSING(SSmachines, src)
//begin_processing()
/obj/machinery/porta_turret/update_icon_state() /obj/machinery/porta_turret/update_icon_state()
if(!anchored) if(!anchored)
icon_state = "turretCover" icon_state = "turretCover"
@@ -119,7 +158,6 @@
else else
icon_state = "[base_icon_state]_unpowered" icon_state = "[base_icon_state]_unpowered"
/obj/machinery/porta_turret/proc/setup(obj/item/gun/turret_gun) /obj/machinery/porta_turret/proc/setup(obj/item/gun/turret_gun)
if(stored_gun) if(stored_gun)
qdel(stored_gun) qdel(stored_gun)
@@ -160,83 +198,88 @@
remove_control() remove_control()
return ..() return ..()
/obj/machinery/porta_turret/ui_interact(mob/user) /obj/machinery/porta_turret/ui_interact(mob/user, datum/tgui/ui)
. = ..() ui = SStgui.try_update_ui(user, src, ui)
var/dat if(!ui)
dat += "Status: <a href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</a><br>" ui = new(user, src, "PortableTurret", name)
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<br>" ui.open()
if(!locked) /obj/machinery/porta_turret/ui_data(mob/user)
dat += "Check for Weapon Authorization: <A href='?src=[REF(src)];operation=authweapon'>[auth_weapons ? "Yes" : "No"]</A><BR>" var/list/data = list(
dat += "Check Security Records: <A href='?src=[REF(src)];operation=checkrecords'>[check_records ? "Yes" : "No"]</A><BR>" "locked" = locked,
dat += "Neutralize Identified Criminals: <A href='?src=[REF(src)];operation=shootcrooks'>[criminals ? "Yes" : "No"]</A><BR>" "on" = on,
dat += "Neutralize All Non-Security and Non-Command Personnel: <A href='?src=[REF(src)];operation=shootall'>[stun_all ? "Yes" : "No"]</A><BR>" "check_weapons" = turret_flags & TURRET_FLAG_AUTH_WEAPONS,
dat += "Neutralize All Unidentified Life Signs: <A href='?src=[REF(src)];operation=checkxenos'>[check_anomalies ? "Yes" : "No"]</A><BR>" "neutralize_criminals" = turret_flags & TURRET_FLAG_SHOOT_CRIMINALS,
dat += "Neutralize All Non-Loyalty Implanted Personnel: <A href='?src=[REF(src)];operation=checkloyal'>[shoot_unloyal ? "Yes" : "No"]</A><BR>" "neutralize_all" = turret_flags & TURRET_FLAG_SHOOT_ALL,
"neutralize_unidentified" = turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS,
"neutralize_nonmindshielded" = turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED,
"neutralize_cyborgs" = turret_flags & TURRET_FLAG_SHOOT_BORGS,
"ignore_heads" = turret_flags & TURRET_FLAG_SHOOT_HEADS,
"manual_control" = manual_control,
"silicon_user" = FALSE,
"allow_manual_control" = FALSE,
"lasertag_turret" = istype(src, /obj/machinery/porta_turret/lasertag),
)
if(issilicon(user)) if(issilicon(user))
data["silicon_user"] = TRUE
if(!manual_control) if(!manual_control)
var/mob/living/silicon/S = user var/mob/living/silicon/S = user
if(S.hack_software) if(S.hack_software)
dat += "Assume direct control : <a href='?src=[REF(src)];operation=manual'>Manual Control</a><br>" data["allow_manual_control"] = TRUE
else return data
dat += "Warning! Remote control protocol enabled.<br>"
/obj/machinery/porta_turret/ui_act(action, list/params)
var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300) . = ..()
popup.set_content(dat) if(.)
popup.open()
/obj/machinery/porta_turret/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
add_fingerprint(usr)
if(href_list["power"] && !locked)
if(anchored) //you can't turn a turret on/off if it's not anchored/secured
on = !on //toggle on/off
else
to_chat(usr, "<span class='notice'>It has to be secured first!</span>")
interact(usr)
return return
if(href_list["operation"]) switch(action)
switch(href_list["operation"]) //toggles customizable behavioural protocols if("power")
if("authweapon") if(anchored)
auth_weapons = !auth_weapons toggle_on()
if("checkrecords") return TRUE
check_records = !check_records else
if("shootcrooks") to_chat(usr, "<span class='warning'>It has to be secured first!</span>")
criminals = !criminals if("authweapon")
if("shootall") turret_flags ^= TURRET_FLAG_AUTH_WEAPONS
stun_all = !stun_all return TRUE
if("checkxenos") if("shootcriminals")
check_anomalies = !check_anomalies turret_flags ^= TURRET_FLAG_SHOOT_CRIMINALS
if("checkloyal") return TRUE
shoot_unloyal = !shoot_unloyal if("shootall")
if("manual") turret_flags ^= TURRET_FLAG_SHOOT_ALL
if(issilicon(usr) && !manual_control) return TRUE
give_control(usr) if("checkxenos")
interact(usr) turret_flags ^= TURRET_FLAG_SHOOT_ANOMALOUS
return TRUE
if("checkloyal")
turret_flags ^= TURRET_FLAG_SHOOT_UNSHIELDED
return TRUE
if("shootborgs")
turret_flags ^= TURRET_FLAG_SHOOT_BORGS
return TRUE
if("shootheads")
turret_flags ^= TURRET_FLAG_SHOOT_HEADS
return TRUE
if("manual")
if(!issilicon(usr))
return
give_control(usr)
return TRUE
/obj/machinery/porta_turret/ui_host(mob/user)
if(has_cover && cover)
return cover
if(base)
return base
return src
/obj/machinery/porta_turret/power_change() /obj/machinery/porta_turret/power_change()
if(!anchored) . = ..()
if(!anchored || (stat & BROKEN) || !powered())
update_icon() update_icon()
remove_control() remove_control()
return check_should_process()
if(stat & BROKEN)
update_icon()
remove_control()
else
if( powered() )
stat &= ~NOPOWER
update_icon()
else
spawn(rand(0, 15))
stat |= NOPOWER
remove_control()
update_icon()
/obj/machinery/porta_turret/attackby(obj/item/I, mob/user, params) /obj/machinery/porta_turret/attackby(obj/item/I, mob/user, params)
if(stat & BROKEN) if(stat & BROKEN)
@@ -284,8 +327,10 @@
locked = !locked locked = !locked
to_chat(user, "<span class='notice'>Controls are now [locked ? "locked" : "unlocked"].</span>") to_chat(user, "<span class='notice'>Controls are now [locked ? "locked" : "unlocked"].</span>")
else else
to_chat(user, "<span class='notice'>Access denied.</span>") to_chat(user, "<span class='alert'>Access denied.</span>")
else if(istype(I, /obj/item/multitool) && !locked) else if(istype(I, /obj/item/multitool) && !locked)
if(!multitool_check_buffer(user, I))
return
var/obj/item/multitool/M = I var/obj/item/multitool/M = I
M.buffer = src M.buffer = src
to_chat(user, "<span class='notice'>You add [src] to multitool buffer.</span>") to_chat(user, "<span class='notice'>You add [src] to multitool buffer.</span>")
@@ -293,19 +338,17 @@
return ..() return ..()
/obj/machinery/porta_turret/emag_act(mob/user) /obj/machinery/porta_turret/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED) if(obj_flags & EMAGGED)
return return
to_chat(user, "<span class='warning'>You short out [src]'s threat assessment circuits.</span>") to_chat(user, "<span class='warning'>You short out [src]'s threat assessment circuits.</span>")
visible_message("[src] hums oddly...") audible_message("<span class='hear'>[src] hums oddly...</span>")
obj_flags |= EMAGGED obj_flags |= EMAGGED
controllock = TRUE controllock = TRUE
on = FALSE //turns off the turret temporarily toggle_on(FALSE) //turns off the turret temporarily
update_icon() update_icon()
sleep(60) //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit //6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
on = TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 6 SECONDS)
return TRUE //turns it back on. The cover popUp() popDown() are automatically called in process(), no need to define it here
/obj/machinery/porta_turret/emp_act(severity) /obj/machinery/porta_turret/emp_act(severity)
. = ..() . = ..()
@@ -314,63 +357,41 @@
if(on) if(on)
//if the turret is on, the EMP no matter how severe disables the turret for a while //if the turret is on, the EMP no matter how severe disables the turret for a while
//and scrambles its settings, with a slight chance of having an emag effect //and scrambles its settings, with a slight chance of having an emag effect
check_records = pick(0, 1) if(prob(50))
criminals = pick(0, 1) turret_flags |= TURRET_FLAG_SHOOT_CRIMINALS
auth_weapons = pick(0, 1) if(prob(50))
stun_all = pick(0, 0, 0, 0, 1) //stun_all is a pretty big deal, so it's least likely to get turned on turret_flags |= TURRET_FLAG_AUTH_WEAPONS
if(prob(20))
turret_flags |= TURRET_FLAG_SHOOT_ALL // Shooting everyone is a pretty big deal, so it's least likely to get turned on
on = FALSE toggle_on(FALSE)
remove_control() remove_control()
spawn(rand(60,600)) addtimer(CALLBACK(src, .proc/toggle_on, TRUE), rand(60,600))
if(!on)
on = TRUE
/obj/machinery/porta_turret/take_damage(damage, damage_type = BRUTE, damage_flag = 0, sound_effect = 1) /obj/machinery/porta_turret/take_damage(damage, damage_type = BRUTE, damage_flag = 0, sound_effect = 1)
. = ..() . = ..()
if(.) //damage received if(. && obj_integrity > 0) //damage received
if(prob(30)) if(prob(30))
spark_system.start() spark_system.start()
if(on && !attacked && !(obj_flags & EMAGGED)) if(on && !(turret_flags & TURRET_FLAG_SHOOT_ALL_REACT) && !(obj_flags & EMAGGED))
attacked = TRUE turret_flags |= TURRET_FLAG_SHOOT_ALL_REACT
addtimer(CALLBACK(src, .proc/reset_attacked), 60) addtimer(CALLBACK(src, .proc/reset_attacked), 60)
/obj/machinery/porta_turret/proc/reset_attacked() /obj/machinery/porta_turret/proc/reset_attacked()
attacked = FALSE turret_flags &= ~TURRET_FLAG_SHOOT_ALL_REACT
/obj/machinery/porta_turret/deconstruct(disassembled = TRUE) /obj/machinery/porta_turret/deconstruct(disassembled = TRUE)
qdel(src) qdel(src)
/obj/machinery/porta_turret/obj_break(damage_flag) /obj/machinery/porta_turret/obj_break(damage_flag)
if(!(flags_1 & NODECONSTRUCT_1) && !(stat & BROKEN)) . = ..()
stat |= BROKEN //enables the BROKEN bit if(.)
power_change() power_change()
invisibility = 0 invisibility = 0
spark_system.start() //creates some sparks because they look cool spark_system.start() //creates some sparks because they look cool
qdel(cover) //deletes the cover - no need on keeping it there! qdel(cover) //deletes the cover - no need on keeping it there!
//turret healing
/obj/machinery/porta_turret/examine(mob/user)
. = ..()
if(obj_integrity < max_integrity)
. += "<span class='notice'>Use a welder to fix it.</span>"
/obj/machinery/porta_turret/welder_act(mob/living/user, obj/item/I)
. = TRUE
if(obj_integrity < max_integrity)
if(!I.tool_start_check(user, amount=0))
return
user.visible_message("[user] is welding the turret.", \
"<span class='notice'>You begin repairing the turret...</span>", \
"<span class='italics'>You hear welding.</span>")
if(I.use_tool(src, user, 40, volume=50))
obj_integrity = max_integrity
user.visible_message("[user.name] has repaired [src].", \
"<span class='notice'>You finish repairing the turret.</span>")
else
to_chat(user, "<span class='notice'>The turret doesn't need repairing.</span>")
/obj/machinery/porta_turret/process() /obj/machinery/porta_turret/process()
//the main machinery process //the main machinery process
if(cover == null && anchored) //if it has no cover and is anchored if(cover == null && anchored) //if it has no cover and is anchored
@@ -382,35 +403,43 @@
cover.parent_turret = src //assign the cover its parent_turret, which would be this (src) cover.parent_turret = src //assign the cover its parent_turret, which would be this (src)
if(!on || (stat & (NOPOWER|BROKEN)) || manual_control) if(!on || (stat & (NOPOWER|BROKEN)) || manual_control)
return return PROCESS_KILL
var/list/targets = list() var/list/targets = list()
for(var/mob/A in view(scan_range, base)) for(var/mob/A in view(scan_range, base))
if(A.invisibility > SEE_INVISIBLE_LIVING) if(A.invisibility > SEE_INVISIBLE_LIVING)
continue continue
if(check_anomalies)//if it's set to check for simple animals if(turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS)//if it's set to check for simple animals
if(isanimal(A)) if(isanimal(A))
var/mob/living/simple_animal/SA = A var/mob/living/simple_animal/SA = A
if(SA.stat || in_faction(SA)) //don't target if dead or in faction if(SA.stat || in_faction(SA)) //don't target if dead or in faction
continue continue
targets += SA targets += SA
if(issilicon(A)) continue
var/mob/living/silicon/sillycone = A
if(sillycone.stat || in_faction(sillycone)) if(issilicon(A))
var/mob/living/silicon/sillycone = A
if(ispAI(A))
continue
if((turret_flags & TURRET_FLAG_SHOOT_BORGS) && sillycone.stat != DEAD && iscyborg(sillycone))
targets += sillycone
continue
if(sillycone.stat || in_faction(sillycone))
continue
if(iscyborg(sillycone))
var/mob/living/silicon/robot/sillyconerobot = A
if(LAZYLEN(faction) && (ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE)
continue continue
if(iscyborg(sillycone)) else if(iscarbon(A))
var/mob/living/silicon/robot/sillyconerobot = A
if(LAZYLEN(faction) && (ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE)
continue
targets += sillycone
if(iscarbon(A))
var/mob/living/carbon/C = A var/mob/living/carbon/C = A
//If not emagged, only target non downed carbons //If not emagged, only target carbons that can use items
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || (C.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)))//CIT CHANGE - replaces check for lying with check for recoveringstam if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || !(C.mobility_flags & MOBILITY_USE)))
continue continue
//If emagged, target all but dead carbons //If emagged, target all but dead carbons
@@ -419,12 +448,13 @@
//if the target is a human and not in our faction, analyze threat level //if the target is a human and not in our faction, analyze threat level
if(ishuman(C) && !in_faction(C)) if(ishuman(C) && !in_faction(C))
if(assess_perp(C) >= 4) if(assess_perp(C) >= 4)
targets += C targets += C
else if(turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) //non humans who are not simple animals (xenos etc)
else if(check_anomalies) //non humans who are not simple animals (xenos etc)
if(!in_faction(C)) if(!in_faction(C))
targets += C targets += C
for(var/A in GLOB.mechas_list) for(var/A in GLOB.mechas_list)
if((get_dist(A, base) < scan_range) && can_see(base, A, scan_range)) if((get_dist(A, base) < scan_range) && can_see(base, A, scan_range))
var/obj/mecha/Mech = A var/obj/mecha/Mech = A
@@ -432,6 +462,10 @@
if(assess_perp(Mech.occupant) >= 4) if(assess_perp(Mech.occupant) >= 4)
targets += Mech targets += Mech
if((turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) && GLOB.blobs.len && (mode == TURRET_LETHAL))
for(var/obj/structure/blob/B in view(scan_range, base))
targets += B
if(targets.len) if(targets.len)
tryToShootAt(targets) tryToShootAt(targets)
else if(!always_up) else if(!always_up)
@@ -488,36 +522,37 @@
if(obj_flags & EMAGGED) if(obj_flags & EMAGGED)
return 10 //if emagged, always return 10. return 10 //if emagged, always return 10.
if((stun_all || attacked) && !allowed(perp)) if((turret_flags & (TURRET_FLAG_SHOOT_ALL | TURRET_FLAG_SHOOT_ALL_REACT)) && !allowed(perp))
//if the turret has been attacked or is angry, target all non-sec people //if the turret has been attacked or is angry, target all non-sec people
if(!allowed(perp)) if(!allowed(perp))
return 10 return 10
if(auth_weapons) //check for weapon authorization if(turret_flags & TURRET_FLAG_AUTH_WEAPONS) //check for weapon authorization
if(isnull(perp.wear_id) || istype(perp.wear_id.GetID(), /obj/item/card/id/syndicate)) if(isnull(perp.wear_id) || istype(perp.wear_id.GetID(), /obj/item/card/id/syndicate))
if(allowed(perp)) //if the perp has security access, return 0 if(allowed(perp)) //if the perp has security access, return 0
return 0 return 0
if(perp.is_holding_item_of_type(/obj/item/gun) || perp.is_holding_item_of_type(/obj/item/melee/baton)) if(perp.is_holding_item_of_type(/obj/item/gun) || perp.is_holding_item_of_type(/obj/item/melee/baton))
threatcount += 4 threatcount += 4
if(istype(perp.belt, /obj/item/gun) || istype(perp.belt, /obj/item/melee/baton)) if(istype(perp.belt, /obj/item/gun) || istype(perp.belt, /obj/item/melee/baton))
threatcount += 2 threatcount += 2
if(check_records) //if the turret can check the records, check if they are set to *Arrest* on records if(turret_flags & TURRET_FLAG_SHOOT_CRIMINALS) //if the turret can check the records, check if they are set to *Arrest* on records
var/perpname = perp.get_face_name(perp.get_id_name()) var/perpname = perp.get_face_name(perp.get_id_name())
var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security) var/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
if(!R || (R.fields["criminal"] == "*Arrest*")) if(!R || (R.fields["criminal"] == "*Arrest*"))
threatcount += 4 threatcount += 4
if(shoot_unloyal) if((turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED) && (!HAS_TRAIT(perp, TRAIT_MINDSHIELD)))
if (!HAS_TRAIT(perp, TRAIT_MINDSHIELD)) threatcount += 4
threatcount += 4
// If we aren't shooting heads then return a threatcount of 0
if (!(turret_flags & TURRET_FLAG_SHOOT_HEADS) && (perp.get_assignment() in GLOB.command_positions))
return 0
return threatcount return threatcount
/obj/machinery/porta_turret/proc/in_faction(mob/target) /obj/machinery/porta_turret/proc/in_faction(mob/target)
for(var/faction1 in faction) for(var/faction1 in faction)
if(faction1 in target.faction) if(faction1 in target.faction)
@@ -563,15 +598,14 @@
T = closer T = closer
break break
var/mob/living/carbon/C
if(iscarbon(target))
C = target
update_icon() update_icon()
var/obj/item/projectile/A var/obj/item/projectile/A
//any emagged turrets drains 2x power and uses a different projectile? //any emagged turrets drains 2x power and uses a different projectile?
if(mode == TURRET_STUN) if(mode == TURRET_STUN)
if(nonlethal_projectile && C && C.resting) var/mob/living/carbon/C = null
if(iscarbon(target))
C = target
if(nonlethal_projectile && C?.resting)
use_power(reqpower*0.5) use_power(reqpower*0.5)
A = new nonlethal_projectile(T) A = new nonlethal_projectile(T)
playsound(loc, nonlethal_projectile_sound, 75, 1) playsound(loc, nonlethal_projectile_sound, 75, 1)
@@ -582,7 +616,7 @@
else else
use_power(reqpower * 2) use_power(reqpower * 2)
A = new lethal_projectile(T) A = new lethal_projectile(T)
playsound(loc, lethal_projectile_sound, 75, 1) playsound(loc, lethal_projectile_sound, 75, TRUE)
//Shooting Code: //Shooting Code:
@@ -592,16 +626,15 @@
A.fire() A.fire()
return A return A
/obj/machinery/porta_turret/proc/setState(on, mode) /obj/machinery/porta_turret/proc/setState(on, mode, shoot_cyborgs)
if(controllock) if(controllock)
return return
src.on = on
if(!on) shoot_cyborgs ? (turret_flags |= TURRET_FLAG_SHOOT_BORGS) : (turret_flags &= ~TURRET_FLAG_SHOOT_BORGS)
popDown() toggle_on(on)
src.mode = mode src.mode = mode
power_change() power_change()
/datum/action/turret_toggle /datum/action/turret_toggle
name = "Toggle Mode" name = "Toggle Mode"
icon_icon = 'icons/mob/actions/actions_mecha.dmi' icon_icon = 'icons/mob/actions/actions_mecha.dmi'
@@ -685,7 +718,15 @@
/obj/machinery/porta_turret/syndicate/ComponentInitialize() /obj/machinery/porta_turret/syndicate/ComponentInitialize()
. = ..() . = ..()
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) // AddComponent(/datum/component/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES)
AddElement(/datum/element/empprotection, EMP_PROTECT_SELF | EMP_PROTECT_WIRES) //this one or ^ one?
/obj/machinery/porta_turret/syndicate/setup()
return
/obj/machinery/porta_turret/syndicate/assess_perp(mob/living/carbon/human/perp)
return 10 //Syndicate turrets shoot everything not in their faction
/obj/machinery/porta_turret/syndicate/energy /obj/machinery/porta_turret/syndicate/energy
icon_state = "standard_stun" icon_state = "standard_stun"
@@ -698,7 +739,6 @@
lethal_projectile_sound = 'sound/weapons/laser.ogg' lethal_projectile_sound = 'sound/weapons/laser.ogg'
desc = "An energy blaster auto-turret." desc = "An energy blaster auto-turret."
/obj/machinery/porta_turret/syndicate/energy/heavy /obj/machinery/porta_turret/syndicate/energy/heavy
icon_state = "standard_stun" icon_state = "standard_stun"
base_icon_state = "standard" base_icon_state = "standard"
@@ -715,14 +755,13 @@
integrity_failure = 0.08 integrity_failure = 0.08
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90) armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 50, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
/obj/machinery/porta_turret/syndicate/energy/raven
/obj/machinery/porta_turret/syndicate/setup() stun_projectile = /obj/item/projectile/beam/laser
return stun_projectile_sound = 'sound/weapons/laser.ogg'
faction = list("neutral","silicon","turret")
/obj/machinery/porta_turret/syndicate/assess_perp(mob/living/carbon/human/perp)
return 10 //Syndicate turrets shoot everything not in their faction
/obj/machinery/porta_turret/syndicate/pod /obj/machinery/porta_turret/syndicate/pod
integrity_failure = 0.5
max_integrity = 40 max_integrity = 40
stun_projectile = /obj/item/projectile/bullet/syndicate_turret stun_projectile = /obj/item/projectile/bullet/syndicate_turret
lethal_projectile = /obj/item/projectile/bullet/syndicate_turret lethal_projectile = /obj/item/projectile/bullet/syndicate_turret
@@ -749,6 +788,7 @@
faction = list("silicon") faction = list("silicon")
nonlethal_projectile = /obj/item/projectile/beam/disabler nonlethal_projectile = /obj/item/projectile/beam/disabler
nonlethal_projectile_sound = 'sound/weapons/taser2.ogg' nonlethal_projectile_sound = 'sound/weapons/taser2.ogg'
turret_flags = TURRET_FLAG_SHOOT_CRIMINALS | TURRET_FLAG_SHOOT_ANOMALOUS | TURRET_FLAG_SHOOT_HEADS
/obj/machinery/porta_turret/ai/assess_perp(mob/living/carbon/human/perp) /obj/machinery/porta_turret/ai/assess_perp(mob/living/carbon/human/perp)
return 10 //AI turrets shoot at everything not in their faction return 10 //AI turrets shoot at everything not in their faction
@@ -804,6 +844,7 @@
/obj/machinery/porta_turret/centcom_shuttle/weak /obj/machinery/porta_turret/centcom_shuttle/weak
max_integrity = 120 max_integrity = 120
integrity_failure = 0.5
name = "Old Laser Turret" name = "Old Laser Turret"
desc = "A turret built with substandard parts and run down further with age. Still capable of delivering lethal lasers to the odd space carp, but not much else." desc = "A turret built with substandard parts and run down further with age. Still capable of delivering lethal lasers to the odd space carp, but not much else."
stun_projectile = /obj/item/projectile/beam/weak/penetrator stun_projectile = /obj/item/projectile/beam/weak/penetrator
@@ -817,7 +858,6 @@
stun_projectile_sound = 'sound/weapons/gunshot.ogg' stun_projectile_sound = 'sound/weapons/gunshot.ogg'
desc = "A ballistic machine gun auto-turret." desc = "A ballistic machine gun auto-turret."
//////////////////////// ////////////////////////
//Turret Control Panel// //Turret Control Panel//
//////////////////////// ////////////////////////
@@ -828,14 +868,22 @@
icon = 'icons/obj/machines/turret_control.dmi' icon = 'icons/obj/machines/turret_control.dmi'
icon_state = "control_standby" icon_state = "control_standby"
density = FALSE density = FALSE
var/enabled = 1
var/lethal = 0
var/locked = TRUE
var/control_area = null //can be area name, path or nothing.
var/ailock = 0 // AI cannot use this
req_access = list(ACCESS_AI_UPLOAD) req_access = list(ACCESS_AI_UPLOAD)
var/list/obj/machinery/porta_turret/turrets = list()
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
/// Variable dictating if linked turrets are active and will shoot targets
var/enabled = TRUE
/// Variable dictating if linked turrets will shoot lethal projectiles
var/lethal = FALSE
/// Variable dictating if the panel is locked, preventing changes to turret settings
var/locked = TRUE
/// An area in which linked turrets are located, it can be an area name, path or nothing
var/control_area = null
/// AI is unable to use this machine if set to TRUE
var/ailock = FALSE
/// Variable dictating if linked turrets will shoot cyborgs
var/shoot_cyborgs = FALSE
/// List of all linked turrets
var/list/turrets = list()
/obj/machinery/turretid/Initialize(mapload, ndir = 0, built = 0) /obj/machinery/turretid/Initialize(mapload, ndir = 0, built = 0)
. = ..() . = ..()
@@ -868,112 +916,111 @@
T.cp = src T.cp = src
/obj/machinery/turretid/examine(mob/user) /obj/machinery/turretid/examine(mob/user)
. = ..() . += ..()
if(hasSiliconAccessInArea(user) && (!stat & BROKEN)) if(issilicon(user) && !(stat & BROKEN))
. += "<span class='notice'>Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets.</span>" . += {"<span class='notice'>Ctrl-click [src] to [ enabled ? "disable" : "enable"] turrets.</span>
. += "<span class='notice'>Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"].</span>" <span class='notice'>Alt-click [src] to set turrets to [ lethal ? "stun" : "kill"].</span>"}
/obj/machinery/turretid/attackby(obj/item/I, mob/user, params) /obj/machinery/turretid/attackby(obj/item/I, mob/user, params)
if(stat & BROKEN) if(stat & BROKEN)
return return
if (istype(I, /obj/item/multitool)) if (istype(I, /obj/item/multitool))
if(!multitool_check_buffer(user, I))
return
var/obj/item/multitool/M = I var/obj/item/multitool/M = I
if(M.buffer && istype(M.buffer, /obj/machinery/porta_turret)) if(M.buffer && istype(M.buffer, /obj/machinery/porta_turret))
turrets |= M.buffer turrets |= M.buffer
to_chat(user, "You link \the [M.buffer] with \the [src]") to_chat(user, "<span class='notice'>You link \the [M.buffer] with \the [src].</span>")
return return
if (hasSiliconAccessInArea(user)) if (issilicon(user))
return attack_hand(user) return attack_hand(user)
if ( get_dist(src, user) == 0 ) // trying to unlock the interface if ( get_dist(src, user) == 0 ) // trying to unlock the interface
if (allowed(usr)) if (allowed(usr))
if(obj_flags & EMAGGED) if(obj_flags & EMAGGED)
to_chat(user, "<span class='notice'>The turret control is unresponsive.</span>") to_chat(user, "<span class='warning'>The turret control is unresponsive!</span>")
return return
locked = !locked locked = !locked
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] the panel.</span>") to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] the panel.</span>")
if (locked)
if (user.machine==src)
user.unset_machine()
user << browse(null, "window=turretid")
else
if (user.machine==src)
attack_hand(user)
else else
to_chat(user, "<span class='warning'>Access denied.</span>") to_chat(user, "<span class='alert'>Access denied.</span>")
/obj/machinery/turretid/emag_act(mob/user) /obj/machinery/turretid/emag_act(mob/user)
. = ..()
if(obj_flags & EMAGGED) if(obj_flags & EMAGGED)
return return
to_chat(user, "<span class='danger'>You short out the turret controls' access analysis module.</span>") to_chat(user, "<span class='notice'>You short out the turret controls' access analysis module.</span>")
obj_flags |= EMAGGED obj_flags |= EMAGGED
locked = FALSE locked = FALSE
if(user && user.machine == src)
attack_hand(user)
return TRUE
/obj/machinery/turretid/attack_ai(mob/user) /obj/machinery/turretid/attack_ai(mob/user)
if(!ailock || IsAdminGhost(user)) if(!ailock || IsAdminGhost(user))
return attack_hand(user) return attack_hand(user)
else else
to_chat(user, "<span class='notice'>There seems to be a firewall preventing you from accessing this device.</span>") to_chat(user, "<span class='warning'>There seems to be a firewall preventing you from accessing this device!</span>")
/obj/machinery/turretid/ui_interact(mob/user) /obj/machinery/turretid/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "TurretControl", name)
ui.open()
/obj/machinery/turretid/ui_data(mob/user)
var/list/data = list()
data["locked"] = locked
data["siliconUser"] = hasSiliconAccessInArea(user) || IsAdminGhost(user)
data["enabled"] = enabled
data["lethal"] = lethal
data["shootCyborgs"] = shoot_cyborgs
return data
/obj/machinery/turretid/ui_act(action, list/params)
. = ..() . = ..()
if ( get_dist(src, user) > 0 ) if(.)
if ( !(hasSiliconAccessInArea(user) || IsAdminGhost(user)) )
to_chat(user, "<span class='notice'>You are too far away.</span>")
user.unset_machine()
user << browse(null, "window=turretid")
return
var/t = ""
if(locked && !(hasSiliconAccessInArea(user) || IsAdminGhost(user)))
t += "<div class='notice icon'>Swipe ID card to unlock interface</div>"
else
if(!hasSiliconAccessInArea(user) && !IsAdminGhost(user))
t += "<div class='notice icon'>Swipe ID card to lock interface</div>"
t += "Turrets [enabled?"activated":"deactivated"] - <A href='?src=[REF(src)];toggleOn=1'>[enabled?"Disable":"Enable"]?</a><br>"
t += "Currently set for [lethal?"lethal":"stun repeatedly"] - <A href='?src=[REF(src)];toggleLethal=1'>Change to [lethal?"Stun repeatedly":"Lethal"]?</a><br>"
var/datum/browser/popup = new(user, "turretid", "Turret Control Panel ([get_area_name(src, TRUE)])")
popup.set_content(t)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
/obj/machinery/turretid/Topic(href, href_list)
if(..())
return return
if (locked)
if(!(hasSiliconAccessInArea(usr) || IsAdminGhost(usr)))
to_chat(usr, "Control panel is locked!")
return
if (href_list["toggleOn"])
toggle_on()
else if (href_list["toggleLethal"])
toggle_lethal()
attack_hand(usr)
/obj/machinery/turretid/proc/toggle_lethal() switch(action)
if("lock")
if(!hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
return
if((obj_flags & EMAGGED) || (stat & BROKEN))
to_chat(usr, "<span class='warning'>The turret control is unresponsive!</span>")
return
locked = !locked
return TRUE
if("power")
toggle_on(usr)
return TRUE
if("mode")
toggle_lethal(usr)
return TRUE
if("shoot_silicons")
shoot_silicons(usr)
return TRUE
/obj/machinery/turretid/proc/toggle_lethal(mob/user)
lethal = !lethal lethal = !lethal
add_hiddenprint(user)
log_combat(user, src, "[lethal ? "enabled" : "disabled"] lethals on")
updateTurrets() updateTurrets()
/obj/machinery/turretid/proc/toggle_on() /obj/machinery/turretid/proc/toggle_on(mob/user)
enabled = !enabled enabled = !enabled
add_hiddenprint(user)
log_combat(user, src, "[enabled ? "enabled" : "disabled"]")
updateTurrets()
/obj/machinery/turretid/proc/shoot_silicons(mob/user)
shoot_cyborgs = !shoot_cyborgs
add_hiddenprint(user)
log_combat(user, src, "[shoot_cyborgs ? "Shooting Borgs" : "Not Shooting Borgs"]")
updateTurrets() updateTurrets()
/obj/machinery/turretid/proc/updateTurrets() /obj/machinery/turretid/proc/updateTurrets()
for (var/obj/machinery/porta_turret/aTurret in turrets) for (var/obj/machinery/porta_turret/aTurret in turrets)
aTurret.setState(enabled, lethal) aTurret.setState(enabled, lethal, shoot_cyborgs)
update_icon()
/obj/machinery/turretid/power_change()
..()
update_icon() update_icon()
/obj/machinery/turretid/update_icon_state() /obj/machinery/turretid/update_icon_state()
@@ -1051,11 +1098,7 @@
/obj/machinery/porta_turret/lasertag /obj/machinery/porta_turret/lasertag
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE) req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
check_records = 0 turret_flags = TURRET_FLAG_AUTH_WEAPONS
criminals = 0
auth_weapons = 1
stun_all = 0
check_anomalies = 0
var/team_color var/team_color
/obj/machinery/porta_turret/lasertag/assess_perp(mob/living/carbon/human/perp) /obj/machinery/porta_turret/lasertag/assess_perp(mob/living/carbon/human/perp)
@@ -1083,20 +1126,14 @@
if(properties["team_color"]) if(properties["team_color"])
team_color = properties["team_color"] team_color = properties["team_color"]
/obj/machinery/porta_turret/lasertag/ui_interact(mob/user) /obj/machinery/porta_turret/lasertag/ui_status(mob/user)
. = ..()
if(ishuman(user)) if(ishuman(user))
var/mob/living/carbon/human/H = user var/mob/living/carbon/human/H = user
if(team_color == "blue" && istype(H.wear_suit, /obj/item/clothing/suit/redtag)) if(team_color == "blue" && istype(H.wear_suit, /obj/item/clothing/suit/redtag))
return return UI_CLOSE
if(team_color == "red" && istype(H.wear_suit, /obj/item/clothing/suit/bluetag)) if(team_color == "red" && istype(H.wear_suit, /obj/item/clothing/suit/bluetag))
return return UI_CLOSE
return ..()
var/dat = "Status: <a href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</a>"
var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300)
popup.set_content(dat)
popup.open()
//lasertag presets //lasertag presets
/obj/machinery/porta_turret/lasertag/red /obj/machinery/porta_turret/lasertag/red
@@ -1112,11 +1149,9 @@
if(on) if(on)
if(team_color == "blue") if(team_color == "blue")
if(istype(P, /obj/item/projectile/beam/lasertag/redtag)) if(istype(P, /obj/item/projectile/beam/lasertag/redtag))
on = FALSE toggle_on(FALSE)
spawn(100) addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS)
on = TRUE
else if(team_color == "red") else if(team_color == "red")
if(istype(P, /obj/item/projectile/beam/lasertag/bluetag)) if(istype(P, /obj/item/projectile/beam/lasertag/bluetag))
on = FALSE toggle_on(FALSE)
spawn(100) addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS)
on = TRUE
+3 -14
View File
@@ -126,17 +126,6 @@
update_icon() update_icon()
/obj/machinery/recharge_station/proc/process_occupant() /obj/machinery/recharge_station/proc/process_occupant()
if(occupant && iscyborg(occupant)) if(!occupant)
var/mob/living/silicon/robot/R = occupant return
restock_modules() SEND_SIGNAL(occupant, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, recharge_speed, repairs)
if(repairs)
R.heal_bodypart_damage(repairs, repairs - 1)
if(R.cell)
R.cell.charge = min(R.cell.charge + recharge_speed, R.cell.maxcharge)
/obj/machinery/recharge_station/proc/restock_modules()
if(occupant)
var/mob/living/silicon/robot/R = occupant
if(R && R.module)
var/coeff = recharge_speed * 0.005
R.module.respawn_consumable(R, coeff)
+5 -16
View File
@@ -170,12 +170,10 @@
..() ..()
default_unfasten_wrench(user, I, 5) default_unfasten_wrench(user, I, 5)
return TRUE return TRUE
/obj/machinery/space_heater/ui_interact(mob/user, datum/tgui/ui)
/obj/machinery/space_heater/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ ui = SStgui.try_update_ui(user, src, ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "SpaceHeater", name, 400, 305, master_ui, state) ui = new(user, src, "SpaceHeater", name)
ui.open() ui.open()
/obj/machinery/space_heater/ui_data() /obj/machinery/space_heater/ui_data()
@@ -210,7 +208,7 @@
if("power") if("power")
on = !on on = !on
mode = HEATER_MODE_STANDBY mode = HEATER_MODE_STANDBY
usr.visible_message("[usr] switches [on ? "on" : "off"] \the [src].", "<span class='notice'>You switch [on ? "on" : "off"] \the [src].</span>") usr.visible_message("<span class='notice'>[usr] switches [on ? "on" : "off"] \the [src].</span>", "<span class='notice'>You switch [on ? "on" : "off"] \the [src].</span>")
update_icon() update_icon()
if (on) if (on)
START_PROCESSING(SSmachines, src) START_PROCESSING(SSmachines, src)
@@ -222,16 +220,7 @@
if(!panel_open) if(!panel_open)
return return
var/target = params["target"] var/target = params["target"]
var/adjust = text2num(params["adjust"]) if(text2num(target) != null)
if(target == "input")
target = input("New target temperature:", name, round(targetTemperature - T0C, 1)) as num|null
if(!isnull(target) && !..())
target += T0C
. = TRUE
else if(adjust)
target = targetTemperature + adjust
. = TRUE
else if(text2num(target) != null)
target= text2num(target) + T0C target= text2num(target) + T0C
. = TRUE . = TRUE
if(.) if(.)
+6 -4
View File
@@ -377,11 +377,13 @@
return ..() return ..()
/obj/machinery/suit_storage_unit/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/suit_storage_unit/ui_state(mob/user)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) return GLOB.notcontained_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/machinery/suit_storage_unit/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "SuitStorageUnit", name, 400, 305, master_ui, state) ui = new(user, src, "SuitStorageUnit", name)
ui.open() ui.open()
/obj/machinery/suit_storage_unit/ui_data() /obj/machinery/suit_storage_unit/ui_data()
@@ -17,11 +17,10 @@
var/notice = "" var/notice = ""
var/universal_translate = FALSE // set to TRUE(1) if it can translate nonhuman speech var/universal_translate = FALSE // set to TRUE(1) if it can translate nonhuman speech
/obj/machinery/computer/telecomms/server/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/computer/telecomms/server/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "TelecommsLogBrowser", "Telecomms Server Monitor", 575, 400, master_ui, state) ui = new(user, src, "TelecommsLogBrowser", "Telecomms Server Monitor")
ui.open() ui.open()
/obj/machinery/computer/telecomms/server/ui_data(mob/user) /obj/machinery/computer/telecomms/server/ui_data(mob/user)
@@ -36,12 +36,11 @@
light_color = LIGHT_COLOR_GREEN light_color = LIGHT_COLOR_GREEN
/obj/machinery/computer/message_monitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE,\ /obj/machinery/computer/message_monitor/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "TelecommsPDALog", name, 727, 510, master_ui, state) ui = new(user, src, "TelecommsPDALog", name)
ui.open() ui.open()
/obj/machinery/computer/message_monitor/ui_static_data(mob/user) /obj/machinery/computer/message_monitor/ui_static_data(mob/user)
@@ -17,12 +17,11 @@
circuit = /obj/item/circuitboard/computer/comm_monitor circuit = /obj/item/circuitboard/computer/comm_monitor
/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE,\ /obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "TelecommsMonitor", name, 575, 400, master_ui, state) ui = new(user, src, "TelecommsMonitor", name)
ui.open() ui.open()
/obj/machinery/computer/telecomms/monitor/ui_data(mob/user) /obj/machinery/computer/telecomms/monitor/ui_data(mob/user)
@@ -27,16 +27,15 @@
else else
return ..() return ..()
/obj/machinery/telecomms/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE,\ /obj/machinery/telecomms/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
if(!canInteract(user)) if(!canInteract(user))
if(ui) if(ui)
ui.close() //haha no. ui.close() //haha no.
return return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "TelecommsInteraction", "[name] Access", 520, 500, master_ui, state) ui = new(user, src, "TelecommsInteraction", "[name] Access")
ui.open() ui.open()
/obj/machinery/telecomms/ui_data(mob/user) /obj/machinery/telecomms/ui_data(mob/user)
+17 -9
View File
@@ -11,10 +11,15 @@
var/equip_ready = 1 //whether the equipment is ready for use. (or deactivated/activated for static stuff) var/equip_ready = 1 //whether the equipment is ready for use. (or deactivated/activated for static stuff)
var/energy_drain = 0 var/energy_drain = 0
var/obj/mecha/chassis = null var/obj/mecha/chassis = null
var/range = MELEE //bitFflags /// Bitflag. Determines the range of the equipment.
var/range = MELEE
/// Bitflag. Used by exosuit fabricator to assign sub-categories based on which exosuits can equip this.
var/mech_flags = NONE
var/salvageable = 1 var/salvageable = 1
//var/detachable = TRUE // Set to FALSE for built-in equipment that cannot be removed
var/selectable = 1 // Set to 0 for passive equipment such as mining scanner or armor plates var/selectable = 1 // Set to 0 for passive equipment such as mining scanner or armor plates
var/harmful = FALSE //Controls if equipment can be used to attack by a pacifist. var/harmful = FALSE //Controls if equipment can be used to attack by a pacifist.
//var/destroy_sound = 'sound/mecha/critdestr.ogg'
/obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page() /obj/item/mecha_parts/mecha_equipment/proc/update_chassis_page()
if(chassis) if(chassis)
@@ -35,9 +40,14 @@
if(chassis.selected == src) if(chassis.selected == src)
chassis.selected = null chassis.selected = null
src.update_chassis_page() src.update_chassis_page()
chassis.occupant_message("<span class='danger'>[src] is destroyed!</span>") //log_message("[src] is destroyed.", LOG_MECHA)
chassis.log_append_to_last("[src] is destroyed.",1) chassis.log_append_to_last("[src] is destroyed.",1)
SEND_SOUND(chassis.occupant, sound(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon) ? 'sound/mecha/weapdestr.ogg' : 'sound/mecha/critdestr.ogg', volume=50)) if(chassis.occupant)
chassis.occupant_message("<span class='danger'>[src] is destroyed!</span>")
SEND_SOUND(chassis.occupant, sound(istype(src, /obj/item/mecha_parts/mecha_equipment/weapon) ? 'sound/mecha/weapdestr.ogg' : 'sound/mecha/critdestr.ogg', volume=50))
//chassis.occupant.playsound_local(chassis, destroy_sound, 50)
//if(!detachable) //If we're a built-in nondetachable equipment, let's lock up the slot that we were in.
// chassis.max_equip--
chassis = null chassis = null
return ..() return ..()
@@ -59,7 +69,7 @@
return txt return txt
/obj/item/mecha_parts/mecha_equipment/proc/is_ranged()//add a distance restricted equipment. Why not? /obj/item/mecha_parts/mecha_equipment/proc/is_ranged()//add a distance restricted equipment. Why not?
return range&RANGED return range&RANGED //rename to MECHA_RANGE and MECHA_MELEE
/obj/item/mecha_parts/mecha_equipment/proc/is_melee() /obj/item/mecha_parts/mecha_equipment/proc/is_melee()
return range&MELEE return range&MELEE
@@ -72,10 +82,10 @@
return 0 return 0
if(!equip_ready) if(!equip_ready)
return 0 return 0
if(crit_fail)
return 0
if(energy_drain && !chassis.has_charge(energy_drain)) if(energy_drain && !chassis.has_charge(energy_drain))
return 0 return 0
if(crit_fail)
return 0
if(chassis.equipment_disabled) if(chassis.equipment_disabled)
to_chat(chassis.occupant, "<span=warn>Error -- Equipment control unit is unresponsive.</span>") to_chat(chassis.occupant, "<span=warn>Error -- Equipment control unit is unresponsive.</span>")
return 0 return 0
@@ -117,8 +127,6 @@
chassis = M chassis = M
forceMove(M) forceMove(M)
M.mecha_log_message("[src] initialized.") M.mecha_log_message("[src] initialized.")
if(!M.selected && selectable)
M.selected = src
src.update_chassis_page() src.update_chassis_page()
return return
@@ -150,7 +158,7 @@
chassis.occupant_message("[icon2html(src, chassis.occupant)] [message]") chassis.occupant_message("[icon2html(src, chassis.occupant)] [message]")
return return
/obj/item/mecha_parts/mecha_equipment/proc/mecha_log_message(message, color) /obj/item/mecha_parts/mecha_equipment/proc/mecha_log_message(message, color) //on tg this just overrides log_message
log_message(message, LOG_GAME, color) //pass to default admin logging too log_message(message, LOG_GAME, color) //pass to default admin logging too
if(chassis) if(chassis)
chassis.mecha_log_message(message, color) //and pass to our chassis chassis.mecha_log_message(message, color) //and pass to our chassis
@@ -1,6 +1,7 @@
// Sleeper, Medical Beam, and Syringe gun // Sleeper, Medical Beam, and Syringe gun
/obj/item/mecha_parts/mecha_equipment/medical /obj/item/mecha_parts/mecha_equipment/medical
mech_flags = EXOSUIT_MODULE_MEDICAL
/obj/item/mecha_parts/mecha_equipment/medical/Initialize() /obj/item/mecha_parts/mecha_equipment/medical/Initialize()
. = ..() . = ..()
@@ -17,6 +17,7 @@
toolspeed = 0.9 toolspeed = 0.9
var/drill_delay = 7 var/drill_delay = 7
var/drill_level = DRILL_BASIC var/drill_level = DRILL_BASIC
mech_flags = EXOSUIT_MODULE_WORKING | EXOSUIT_MODULE_COMBAT
/obj/item/mecha_parts/mecha_equipment/drill/Initialize() /obj/item/mecha_parts/mecha_equipment/drill/Initialize()
. = ..() . = ..()
@@ -153,6 +154,7 @@
selectable = 0 selectable = 0
equip_cooldown = 15 equip_cooldown = 15
var/scanning_time = 0 var/scanning_time = 0
mech_flags = EXOSUIT_MODULE_WORKING
/obj/item/mecha_parts/mecha_equipment/mining_scanner/Initialize() /obj/item/mecha_parts/mecha_equipment/mining_scanner/Initialize()
. = ..() . = ..()
@@ -8,11 +8,12 @@
icon_state = "mecha_clamp" icon_state = "mecha_clamp"
equip_cooldown = 15 equip_cooldown = 15
energy_drain = 10 energy_drain = 10
tool_behaviour = TOOL_RETRACTOR
toolspeed = 0.8
var/dam_force = 20 var/dam_force = 20
var/obj/mecha/working/ripley/cargo_holder var/obj/mecha/working/ripley/cargo_holder
harmful = TRUE harmful = TRUE
tool_behaviour = TOOL_RETRACTOR mech_flags = EXOSUIT_MODULE_RIPLEY
toolspeed = 0.8
/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj) /obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj)
if(..()) if(..())
@@ -180,6 +181,7 @@
equip_cooldown = 5 equip_cooldown = 5
energy_drain = 0 energy_drain = 0
range = MELEE|RANGED range = MELEE|RANGED
mech_flags = EXOSUIT_MODULE_WORKING
/obj/item/mecha_parts/mecha_equipment/extinguisher/Initialize() /obj/item/mecha_parts/mecha_equipment/extinguisher/Initialize()
. = ..() . = ..()
@@ -9,6 +9,7 @@
var/projectile_delay = 0 var/projectile_delay = 0
var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the weapon is fired. var/firing_effect_type = /obj/effect/temp_visual/dir_setting/firing_effect //the visual effect appearing when the weapon is fired.
var/kickback = TRUE //Will using this weapon in no grav push mecha back. var/kickback = TRUE //Will using this weapon in no grav push mecha back.
mech_flags = EXOSUIT_MODULE_COMBAT
/obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/combat/M) /obj/item/mecha_parts/mecha_equipment/weapon/can_attach(obj/mecha/combat/M)
if(..()) if(..())
+3 -4
View File
@@ -81,10 +81,10 @@
var/obj/machinery/mech_bay_recharge_port/recharge_port var/obj/machinery/mech_bay_recharge_port/recharge_port
light_color = LIGHT_COLOR_PINK light_color = LIGHT_COLOR_PINK
/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) /obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "MechBayPowerConsole", "Mech Bay Power Control Console", 400, 200, master_ui, state) ui = new(user, src, "MechBayPowerConsole", name)
ui.open() ui.open()
/obj/machinery/computer/mech_bay_power_console/ui_act(action, params) /obj/machinery/computer/mech_bay_power_console/ui_act(action, params)
@@ -104,7 +104,6 @@
data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mech.obj_integrity, "maxhealth" = recharge_port.recharging_mech.max_integrity, "cell" = null, "name" = recharge_port.recharging_mech.name,) data["recharge_port"]["mech"] = list("health" = recharge_port.recharging_mech.obj_integrity, "maxhealth" = recharge_port.recharging_mech.max_integrity, "cell" = null, "name" = recharge_port.recharging_mech.name,)
if(recharge_port.recharging_mech.cell && !QDELETED(recharge_port.recharging_mech.cell)) if(recharge_port.recharging_mech.cell && !QDELETED(recharge_port.recharging_mech.cell))
data["recharge_port"]["mech"]["cell"] = list( data["recharge_port"]["mech"]["cell"] = list(
"critfail" = recharge_port.recharging_mech.cell.crit_fail,
"charge" = recharge_port.recharging_mech.cell.charge, "charge" = recharge_port.recharging_mech.cell.charge,
"maxcharge" = recharge_port.recharging_mech.cell.maxcharge "maxcharge" = recharge_port.recharging_mech.cell.maxcharge
) )
+546 -335
View File
@@ -9,17 +9,41 @@
active_power_usage = 5000 active_power_usage = 5000
req_access = list(ACCESS_ROBOTICS) req_access = list(ACCESS_ROBOTICS)
circuit = /obj/item/circuitboard/machine/mechfab circuit = /obj/item/circuitboard/machine/mechfab
var/time_coeff = 1 // processing_flags = START_PROCESSING_MANUALLY
var/component_coeff = 1
var/datum/techweb/specialized/autounlocking/exofab/stored_research // subsystem_type = /datum/controller/subsystem/processing/fastprocess
var/sync = 0
var/part_set /// Current items in the build queue.
var/datum/design/being_built
var/list/queue = list() var/list/queue = list()
var/processing_queue = 0 /// Whether or not the machine is building the entire queue automagically.
var/screen = "main" var/process_queue = FALSE
var/temp
var/offstation_security_levels = TRUE /// The current design datum that the machine is building.
var/datum/design/being_built
/// World time when the build will finish.
var/build_finish = 0
/// World time when the build started.
var/build_start = 0
/// Reference to all materials used in the creation of the item being_built.
var/list/build_materials
/// Part currently stored in the Exofab.
var/obj/item/stored_part
/// Coefficient for the speed of item building. Based on the installed parts.
var/time_coeff = 1
/// Coefficient for the efficiency of material usage in item building. Based on the installed parts.
var/component_coeff = 1
/// Copy of the currently synced techweb.
var/datum/techweb/specialized/autounlocking/exofab/stored_research
/// Whether the Exofab links to the ore silo on init. Special derelict or maintanance variants should set this to FALSE.
var/link_on_init = TRUE
/// Reference to a remote material inventory, such as an ore silo.
var/datum/component/remote_materials/rmat
/// A list of categories that valid MECHFAB design datums will broadly categorise themselves under.
var/list/part_sets = list( var/list/part_sets = list(
"Cyborg", "Cyborg",
"Ripley", "Ripley",
@@ -33,25 +57,17 @@
"Exosuit Equipment", "Exosuit Equipment",
"Exosuit Ammunition", "Exosuit Ammunition",
"Cyborg Upgrade Modules", "Cyborg Upgrade Modules",
"Cybernetics",
"Implants",
"Control Interfaces",
"Misc" "Misc"
) )
/obj/machinery/mecha_part_fabricator/Initialize() /obj/machinery/mecha_part_fabricator/Initialize(mapload)
var/static/list/allowed_types = list(
/datum/material/iron,
/datum/material/glass,
/datum/material/silver,
/datum/material/gold,
/datum/material/diamond,
/datum/material/plasma,
/datum/material/uranium,
/datum/material/bananium,
/datum/material/titanium,
/datum/material/bluespace
)
var/datum/component/material_container/materials = AddComponent(/datum/component/material_container, allowed_types, 0, TRUE, /obj/item/stack, CALLBACK(src, .proc/is_insertion_ready), CALLBACK(src, .proc/AfterMaterialInsert))
materials.precise_insertion = TRUE
stored_research = new stored_research = new
rmat = AddComponent(/datum/component/remote_materials, "mechfab", mapload && link_on_init)
RefreshParts() //Recalculating local material sizes if the fab isn't linked
return ..() return ..()
/obj/machinery/mecha_part_fabricator/RefreshParts() /obj/machinery/mecha_part_fabricator/RefreshParts()
@@ -60,8 +76,7 @@
//maximum stocking amount (default 300000, 600000 at T4) //maximum stocking amount (default 300000, 600000 at T4)
for(var/obj/item/stock_parts/matter_bin/M in component_parts) for(var/obj/item/stock_parts/matter_bin/M in component_parts)
T += M.rating T += M.rating
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) rmat.set_local_size((200000 + (T*50000)))
materials.max_amount = (200000 + (T*50000))
//resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55) //resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55)
T = 1.15 T = 1.15
@@ -74,89 +89,157 @@
for(var/obj/item/stock_parts/manipulator/Ml in component_parts) for(var/obj/item/stock_parts/manipulator/Ml in component_parts)
T += Ml.rating T += Ml.rating
time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01) time_coeff = round(initial(time_coeff) - (initial(time_coeff)*(T))/5,0.01)
var/obj/item/circuitboard/machine/mechfab/C = circuit
offstation_security_levels = C.offstation_security_levels // Adjust the build time of any item currently being built.
if(being_built)
var/last_const_time = build_finish - build_start
var/new_const_time = get_construction_time_w_coeff(initial(being_built.construction_time))
var/const_time_left = build_finish - world.time
var/new_build_time = (new_const_time / last_const_time) * const_time_left
build_finish = world.time + new_build_time
update_static_data(usr)
/obj/machinery/mecha_part_fabricator/examine(mob/user) /obj/machinery/mecha_part_fabricator/examine(mob/user)
. = ..() . = ..()
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
if(in_range(user, src) || isobserver(user)) if(in_range(user, src) || isobserver(user))
. += "<span class='notice'>The status display reads: Storing up to <b>[materials.max_amount]</b> material units.<br>Material consumption at <b>[component_coeff*100]%</b>.<br>Build time reduced by <b>[100-time_coeff*100]%</b>.</span>" . += "<span class='notice'>The status display reads: Storing up to <b>[rmat.local_size]</b> material units.<br>Material consumption at <b>[component_coeff*100]%</b>.<br>Build time reduced by <b>[100-time_coeff*100]%</b>.</span>"
/obj/machinery/mecha_part_fabricator/emag_act() /**
. = ..() * Generates an info list for a given part.
if(obj_flags & EMAGGED) *
return * Returns a list of part information.
obj_flags |= EMAGGED * * D - Design datum to get information on.
req_access = list() * * categories - Boolean, whether or not to parse snowflake categories into the part information list.
INVOKE_ASYNC(src, .proc/error_action_sucessful) */
return TRUE /obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D, categories = FALSE)
var/cost = list()
/obj/machinery/mecha_part_fabricator/proc/error_action_sucessful()
say("DB error \[Code 0x00F1\]")
sleep(10)
say("Attempting auto-repair...")
sleep(15)
say("User DB corrupted \[Code 0x00FA\]. Truncating data structure...")
sleep(30)
say("User DB truncated. Please contact your Nanotrasen system operator for future assistance.")
/obj/machinery/mecha_part_fabricator/proc/output_parts_list(set_name)
var/output = ""
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(!(set_name in D.category))
continue
output += "<div class='part'>[output_part_info(D)]<br>\["
if(check_clearance(D) && check_resources(D))
output += "<a href='?src=[REF(src)];part=[D.id]'>Build</a> | "
output += "<a href='?src=[REF(src)];add_to_queue=[D.id]'>Add to queue</a>\]\[<a href='?src=[REF(src)];part_desc=[D.id]'>?</a>\]</div>"
return output
/obj/machinery/mecha_part_fabricator/proc/check_clearance(datum/design/D)
if(!(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z)) && !ISINRANGE(GLOB.security_level, D.min_security_level, D.max_security_level))
return FALSE
return TRUE
/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D)
var/clearance = !(obj_flags & EMAGGED) && (offstation_security_levels || is_station_level(z))
var/sec_text = ""
if(clearance && (D.min_security_level > SEC_LEVEL_GREEN || D.max_security_level < SEC_LEVEL_DELTA))
sec_text = " (Allowed security levels: "
for(var/n in D.min_security_level to D.max_security_level)
sec_text += NUM2SECLEVEL(n)
if(n + 1 <= D.max_security_level)
sec_text += ", "
sec_text += ") "
var/output = "[initial(D.name)] (Cost: [output_part_cost(D)]) [sec_text][get_construction_time_w_coeff(D)/10]sec"
return output
/obj/machinery/mecha_part_fabricator/proc/output_part_cost(datum/design/D)
var/i = 0
var/output
for(var/c in D.materials) for(var/c in D.materials)
var/datum/material/M = c var/datum/material/M = c
output += "[i?" | ":null][get_resource_cost_w_coeff(D, M)] [M.name]" cost[M.name] = get_resource_cost_w_coeff(D, M)
i++
return output
var/obj/built_item = D.build_path
var/list/category_override = null
var/list/sub_category = null
if(categories)
// Handle some special cases to build up sub-categories for the fab interface.
// Start with checking if this design builds a cyborg module.
if(built_item in typesof(/obj/item/borg/upgrade))
var/obj/item/borg/upgrade/U = built_item
var/module_types = initial(U.module_flags)
sub_category = list()
if(module_types)
if(module_types & BORG_MODULE_SECURITY)
sub_category += "Security"
if(module_types & BORG_MODULE_MINER)
sub_category += "Mining"
if(module_types & BORG_MODULE_JANITOR)
sub_category += "Janitor"
if(module_types & BORG_MODULE_MEDICAL)
sub_category += "Medical"
if(module_types & BORG_MODULE_ENGINEERING)
sub_category += "Engineering"
else
sub_category += "All Cyborgs"
// Else check if this design builds a piece of exosuit equipment.
else if(built_item in typesof(/obj/item/mecha_parts/mecha_equipment))
var/obj/item/mecha_parts/mecha_equipment/E = built_item
var/mech_types = initial(E.mech_flags)
sub_category = "Equipment"
if(mech_types)
category_override = list()
if(mech_types & EXOSUIT_MODULE_RIPLEY)
category_override += "Ripley"
if(mech_types & EXOSUIT_MODULE_FIREFIGHTER)
category_override += "Firefighter"
if(mech_types & EXOSUIT_MODULE_ODYSSEUS)
category_override += "Odysseus"
// if(mech_types & EXOSUIT_MODULE_CLARKE)
// category_override += "Clarke"
if(mech_types & EXOSUIT_MODULE_GYGAX_MED)
category_override += "Medical-Spec Gygax"
if(mech_types & EXOSUIT_MODULE_GYGAX)
category_override += "Gygax"
if(mech_types & EXOSUIT_MODULE_DURAND)
category_override += "Durand"
if(mech_types & EXOSUIT_MODULE_HONK)
category_override += "H.O.N.K"
if(mech_types & EXOSUIT_MODULE_PHAZON)
category_override += "Phazon"
var/list/part = list(
"name" = D.name,
"desc" = initial(built_item.desc),
"printTime" = get_construction_time_w_coeff(initial(D.construction_time))/10,
"cost" = cost,
"id" = D.id,
"subCategory" = sub_category,
"categoryOverride" = category_override,
"searchMeta" = "UNKNOWN"//D.search_metadata
)
return part
/**
* Generates a list of resources / materials available to this Exosuit Fab
*
* Returns null if there is no material container available.
* List format is list(material_name = list(amount = ..., ref = ..., etc.))
*/
/obj/machinery/mecha_part_fabricator/proc/output_available_resources() /obj/machinery/mecha_part_fabricator/proc/output_available_resources()
var/output var/datum/component/material_container/materials = rmat.mat_container
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
for(var/mat_id in materials.materials)
var/datum/material/M = mat_id
var/amount = materials.materials[mat_id]
output += "<span class=\"res_name\">[M.name]: </span>[amount] cm&sup3;"
if(amount >= MINERAL_MATERIAL_AMOUNT)
output += "<span style='font-size:80%;'>- Remove \[<a href='?src=[REF(src)];remove_mat=1;material=[REF(mat_id)]'>1</a>\]"
if(amount >= (MINERAL_MATERIAL_AMOUNT * 10))
output += " | \[<a href='?src=[REF(src)];remove_mat=10;material=[REF(M)]'>10</a>\]"
output += " | \[<a href='?src=[REF(src)];remove_mat=50;material=[REF(M)]'>All</a>\]</span>"
output += "<br/>"
return output
var/list/material_data = list()
if(materials)
for(var/mat_id in materials.materials)
var/datum/material/M = mat_id
var/list/material_info = list()
var/amount = materials.materials[mat_id]
material_info = list(
"name" = M.name,
"ref" = REF(M),
"amount" = amount,
"sheets" = round(amount / MINERAL_MATERIAL_AMOUNT),
"removable" = amount >= MINERAL_MATERIAL_AMOUNT
)
material_data += list(material_info)
return material_data
return null
/**
* Intended to be called when an item starts printing.
*
* Adds the overlay to show the fab working and sets active power usage settings.
*/
/obj/machinery/mecha_part_fabricator/proc/on_start_printing()
add_overlay("fab-active")
use_power = ACTIVE_POWER_USE
/**
* Intended to be called when the exofab has stopped working and is no longer printing items.
*
* Removes the overlay to show the fab working and sets idle power usage settings. Additionally resets the description and turns off queue processing.
*/
/obj/machinery/mecha_part_fabricator/proc/on_finish_printing()
cut_overlay("fab-active")
use_power = IDLE_POWER_USE
desc = initial(desc)
process_queue = FALSE
/**
* Calculates resource/material costs for printing an item based on the machine's resource coefficient.
*
* Returns a list of k,v resources with their amounts.
* * D - Design datum to calculate the modified resource cost of.
*/
/obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D) /obj/machinery/mecha_part_fabricator/proc/get_resources_w_coeff(datum/design/D)
var/list/resources = list() var/list/resources = list()
for(var/R in D.materials) for(var/R in D.materials)
@@ -164,294 +247,419 @@
resources[M] = get_resource_cost_w_coeff(D, M) resources[M] = get_resource_cost_w_coeff(D, M)
return resources return resources
/**
* Checks if the Exofab has enough resources to print a given item.
*
* Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources.
* Returns TRUE if there are sufficient resources to print the item.
* * D - Design datum to calculate the modified resource cost of.
*/
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D) /obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
if(D.reagents_list.len) // No reagents storage - no reagent designs. if(length(D.reagents_list)) // No reagents storage - no reagent designs.
return FALSE return FALSE
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) var/datum/component/material_container/materials = rmat.mat_container
if(materials.has_materials(get_resources_w_coeff(D))) if(materials.has_materials(get_resources_w_coeff(D)))
return TRUE return TRUE
return FALSE return FALSE
/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D) /**
* Attempts to build the next item in the build queue.
*
* Returns FALSE if either there are no more parts to build or the next part is not buildable.
* Returns TRUE if the next part has started building.
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
*/
/obj/machinery/mecha_part_fabricator/proc/build_next_in_queue(verbose = TRUE)
if(!length(queue))
return FALSE
var/datum/design/D = queue[1]
if(build_part(D, verbose))
remove_from_queue(1)
return TRUE
return FALSE
/**
* Starts the build process for a given design datum.
*
* Returns FALSE if the procedure fails. Returns TRUE when being_built is set.
* Uses materials.
* * D - Design datum to attempt to print.
* * verbose - Whether the machine should use say() procs. Set to FALSE to disable the machine saying reasons for failure to build.
*/
/obj/machinery/mecha_part_fabricator/proc/build_part(datum/design/D, verbose = TRUE)
if(!D)
return FALSE
var/datum/component/material_container/materials = rmat.mat_container
if (!materials)
if(verbose)
say("No access to material storage, please contact the quartermaster.")
return FALSE
if (rmat.on_hold())
if(verbose)
say("Mineral access is on hold, please contact the quartermaster.")
return FALSE
if(!check_resources(D))
if(verbose)
say("Not enough resources. Processing stopped.")
return FALSE
build_materials = get_resources_w_coeff(D)
materials.use_materials(build_materials)
being_built = D being_built = D
desc = "It's building \a [initial(D.name)]." build_finish = world.time + get_construction_time_w_coeff(initial(D.construction_time))
var/list/res_coef = get_resources_w_coeff(D) build_start = world.time
desc = "It's building \a [D.name]."
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) rmat.silo_log(src, "built", -1, "[D.name]", build_materials)
materials.use_materials(res_coef)
add_overlay("fab-active")
use_power = ACTIVE_POWER_USE
updateUsrDialog()
sleep(get_construction_time_w_coeff(D))
use_power = IDLE_POWER_USE
cut_overlay("fab-active")
desc = initial(desc)
var/location = get_step(src,(dir))
var/obj/item/I = new D.build_path(location)
I.set_custom_materials(res_coef)
say("\The [I] is complete.")
being_built = null
updateUsrDialog()
return TRUE return TRUE
/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page() /obj/machinery/mecha_part_fabricator/process()
send_byjax(usr,"mecha_fabricator.browser","queue",list_queue()) // If there's a stored part to dispense due to an obstruction, try to dispense it.
return if(stored_part)
var/turf/exit = get_step(src,(dir))
if(exit.density)
return TRUE
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name) say("Obstruction cleared. \The [stored_part] is complete.")
if(set_name in part_sets) stored_part.forceMove(exit)
for(var/v in stored_research.researched_designs) stored_part = null
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(set_name in D.category)
add_to_queue(D)
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(D) // If there's nothing being built, try to build something
if(!being_built)
// If we're not processing the queue anymore or there's nothing to build, end processing.
if(!process_queue || !build_next_in_queue())
on_finish_printing()
STOP_PROCESSING(SSfastprocess, src)
//end_processing()
return TRUE
on_start_printing()
// If there's an item being built, check if it is complete.
if(being_built && (build_finish < world.time))
// Then attempt to dispense it and if appropriate build the next item.
dispense_built_part(being_built)
if(process_queue)
build_next_in_queue(FALSE)
return TRUE
/**
* Dispenses a part to the tile infront of the Exosuit Fab.
*
* Returns FALSE is the machine cannot dispense the part on the appropriate turf.
* Return TRUE if the part was successfully dispensed.
* * D - Design datum to attempt to dispense.
*/
/obj/machinery/mecha_part_fabricator/proc/dispense_built_part(datum/design/D)
var/obj/item/I = new D.build_path(src)
// I.material_flags |= MATERIAL_NO_EFFECTS //Find a better way to do this.
I.set_custom_materials(build_materials)
being_built = null
var/turf/exit = get_step(src,(dir))
if(exit.density)
say("Error! Part outlet is obstructed.")
desc = "It's trying to dispense \a [D.name], but the part outlet is obstructed."
stored_part = I
return FALSE
say("\The [I] is complete.")
I.forceMove(exit)
return TRUE
/**
* Adds a list of datum designs to the build queue.
*
* Will only add designs that are in this machine's stored techweb.
* Does final checks for datum IDs and makes sure this machine can build the designs.
* * part_list - List of datum design ids for designs to add to the queue.
*/
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(list/part_list)
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if((D.build_type & MECHFAB) && (D.id in part_list))
add_to_queue(D)
/**
* Adds a datum design to the build queue.
*
* Returns TRUE if successful and FALSE if the design was not added to the queue.
* * D - Datum design to add to the queue.
*/
/obj/machinery/mecha_part_fabricator/proc/add_to_queue(datum/design/D)
if(!istype(queue)) if(!istype(queue))
queue = list() queue = list()
if(D) if(D)
queue[++queue.len] = D queue[++queue.len] = D
return queue.len return TRUE
return FALSE
/**
* Removes datum design from the build queue based on index.
*
* Returns TRUE if successful and FALSE if a design was not removed from the queue.
* * index - Index in the build queue of the element to remove.
*/
/obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index) /obj/machinery/mecha_part_fabricator/proc/remove_from_queue(index)
if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>queue.len)) if(!isnum(index) || !ISINTEGER(index) || !istype(queue) || (index<1 || index>length(queue)))
return FALSE return FALSE
queue.Cut(index,++index) queue.Cut(index,++index)
return TRUE return TRUE
/obj/machinery/mecha_part_fabricator/proc/process_queue() /**
var/datum/design/D = queue[1] * Generates a list of parts formatted for tgui based on the current build queue.
if(!D) *
remove_from_queue(1) * Returns a formatted list of lists containing formatted part information for every part in the build queue.
if(queue.len) */
return process_queue()
else
return
temp = null
while(D)
if(stat&(NOPOWER|BROKEN))
return FALSE
if(!check_clearance(D))
say("Security level not met. Queue processing stopped.")
temp = {"<span class='alert'>Security level not met to build next part.</span><br>
<a href='?src=[REF(src)];process_queue=1'>Try again</a> | <a href='?src=[REF(src)];clear_temp=1'>Return</a><a>"}
return FALSE
if(!check_resources(D))
say("Not enough resources. Queue processing stopped.")
temp = {"<span class='alert'>Not enough resources to build next part.</span><br>
<a href='?src=[REF(src)];process_queue=1'>Try again</a> | <a href='?src=[REF(src)];clear_temp=1'>Return</a><a>"}
return FALSE
remove_from_queue(1)
build_part(D)
D = listgetindex(queue, 1)
say("Queue processing finished successfully.")
/obj/machinery/mecha_part_fabricator/proc/list_queue() /obj/machinery/mecha_part_fabricator/proc/list_queue()
var/output = "<b>Queue contains:</b>" if(!istype(queue) || !length(queue))
if(!istype(queue) || !queue.len) return null
output += "<br>Nothing"
else
output += "<ol>"
var/i = 0
for(var/datum/design/D in queue)
i++
var/obj/part = D.build_path
output += "<li[(!check_clearance(D) ||!check_resources(D))?" style='color: #f00;'":null]>"
output += initial(part.name) + " - "
output += "[i>1?"<a href='?src=[REF(src)];queue_move=-1;index=[i]' class='arrow'>&uarr;</a>":null] "
output += "[i<queue.len?"<a href='?src=[REF(src)];queue_move=+1;index=[i]' class='arrow'>&darr;</a>":null] "
output += "<a href='?src=[REF(src)];remove_from_queue=[i]'>Remove</a></li>"
output += "</ol>" var/list/queued_parts = list()
output += "\[<a href='?src=[REF(src)];process_queue=1'>Process queue</a> | <a href='?src=[REF(src)];clear_queue=1'>Clear queue</a>\]" for(var/datum/design/D in queue)
return output var/list/part = output_part_info(D)
queued_parts += list(part)
return queued_parts
/**
* Syncs machine with R&D servers.
*
* Requires an R&D Console visible within 7 tiles. Copies techweb research. Updates tgui's state data.
*/
/obj/machinery/mecha_part_fabricator/proc/sync() /obj/machinery/mecha_part_fabricator/proc/sync()
temp = "Updating local R&D database..." for(var/obj/machinery/computer/rdconsole/RDC in orange(7,src))
updateUsrDialog()
sleep(30) //only sleep if called by user
for(var/obj/machinery/computer/rdconsole/RDC in oview(7,src))
RDC.stored_research.copy_research_to(stored_research) RDC.stored_research.copy_research_to(stored_research)
temp = "Processed equipment designs.<br>" update_static_data(usr)
//check if the tech coefficients have changed
temp += "<a href='?src=[REF(src)];clear_temp=1'>Return</a>"
updateUsrDialog()
say("Successfully synchronized with R&D server.") say("Successfully synchronized with R&D server.")
return return
temp = "Unable to connect to local R&D Database.<br>Please check your connections and try again.<br><a href='?src=[REF(src)];clear_temp=1'>Return</a>" say("Unable to connect to local R&D server.")
updateUsrDialog()
return return
/**
* Calculates the coefficient-modified resource cost of a single material component of a design's recipe.
*
* Returns coefficient-modified resource cost for the given material component.
* * D - Design datum to pull the resource cost from.
* * resource - Material datum reference to the resource to calculate the cost of.
* * roundto - Rounding value for round() proc
*/
/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/datum/material/resource, roundto = 1) /obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/datum/material/resource, roundto = 1)
return round(D.materials[resource]*component_coeff, roundto) return round(D.materials[resource]*component_coeff, roundto)
/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(datum/design/D, roundto = 1) //aran /**
return round(initial(D.construction_time)*time_coeff, roundto) * Calculates the coefficient-modified build time of a design.
*
* Returns coefficient-modified build time of a given design.
* * D - Design datum to calculate the modified build time of.
* * roundto - Rounding value for round() proc
*/
/obj/machinery/mecha_part_fabricator/proc/get_construction_time_w_coeff(construction_time, roundto = 1) //aran
return round(construction_time*time_coeff, roundto)
/obj/machinery/mecha_part_fabricator/ui_interact(mob/user as mob) /obj/machinery/mecha_part_fabricator/ui_assets(mob/user)
. = ..() return list(
var/dat, left_part get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
user.set_machine(src) )
var/turf/exit = get_step(src,(dir))
if(exit.density) /obj/machinery/mecha_part_fabricator/ui_interact(mob/user, datum/tgui/ui)
say("Error! Part outlet is obstructed.") ui = SStgui.try_update_ui(user, src, ui)
return if(!ui)
if(temp) ui = new(user, src, "ExosuitFabricator")
left_part = temp ui.open()
else if(being_built)
var/obj/I = being_built.build_path /obj/machinery/mecha_part_fabricator/ui_static_data(mob/user)
left_part = {"<TT>Building [initial(I.name)].<BR> var/list/data = list()
Please wait until completion...</TT>"}
var/list/final_sets = list()
var/list/buildable_parts = list()
for(var/part_set in part_sets)
final_sets += part_set
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
// This is for us.
var/list/part = output_part_info(D, TRUE)
if(part["category_override"])
for(var/cat in part["category_override"])
buildable_parts[cat] += list(part)
if(!(cat in part_sets))
final_sets += cat
continue
for(var/cat in part_sets)
// Find all matching categories.
if(!(cat in D.category))
continue
buildable_parts[cat] += list(part)
data["partSets"] = final_sets
data["buildableParts"] = buildable_parts
return data
/obj/machinery/mecha_part_fabricator/ui_data(mob/user)
var/list/data = list()
data["materials"] = output_available_resources()
if(being_built)
var/list/part = list(
"name" = being_built.name,
"duration" = build_finish - world.time,
"printTime" = get_construction_time_w_coeff(initial(being_built.construction_time))
)
data["buildingPart"] = part
else else
switch(screen) data["buildingPart"] = null
if("main")
left_part = output_available_resources()+"<hr>"
left_part += "<a href='?src=[REF(src)];sync=1'>Sync with R&D servers</a><hr>"
for(var/part_set in part_sets)
left_part += "<a href='?src=[REF(src)];part_set=[part_set]'>[part_set]</a> - \[<a href='?src=[REF(src)];partset_to_queue=[part_set]'>Add all parts to queue</a>\]<br>"
if("parts")
left_part += output_parts_list(part_set)
left_part += "<hr><a href='?src=[REF(src)];screen=main'>Return</a>"
dat = {"<html>
<head>
<meta http-equiv='Content-Type' content='text/html; charset=UTF-8'>
<title>[name] data</title>
<style>
.res_name {font-weight: bold; text-transform: capitalize;}
.red {color: #f00;}
.part {margin-bottom: 10px;}
.arrow {text-decoration: none; font-size: 10px;}
body, table {height: 100%;}
td {vertical-align: top; padding: 5px;}
html, body {padding: 0px; margin: 0px;}
h1 {font-size: 18px; margin: 5px 0px;}
</style>
<script language='javascript' type='text/javascript'>
[js_byjax]
</script>
</head><body>
<body>
<table style='width: 100%;'>
<tr>
<td style='width: 65%; padding-right: 10px;'>
[left_part]
</td>
<td style='width: 35%; background: #ccc;' id='queue'>
[list_queue()]
</td>
<tr>
</table>
</body>
</html>"}
user << browse(dat, "window=mecha_fabricator;size=1000x430")
onclose(user, "mecha_fabricator")
return
/obj/machinery/mecha_part_fabricator/Topic(href, href_list) data["queue"] = list_queue()
if(stored_part)
data["storedPart"] = stored_part.name
else
data["storedPart"] = null
data["isProcessingQueue"] = process_queue
return data
/obj/machinery/mecha_part_fabricator/ui_act(action, var/list/params)
if(..()) if(..())
return return TRUE
if(href_list["part_set"])
var/tpart_set = href_list["part_set"] . = TRUE
if(tpart_set)
if(tpart_set=="clear") add_fingerprint(usr)
part_set = null usr.set_machine(src)
else
part_set = tpart_set switch(action)
screen = "parts" if("sync_rnd")
if(href_list["part"]) // Sync with R&D Servers
var/T = href_list["part"] sync()
for(var/v in stored_research.researched_designs) return
var/datum/design/D = SSresearch.techweb_design_by_id(v) if("add_queue_set")
if(D.build_type & MECHFAB) // Add all parts of a set to queue
if(D.id == T) var/part_list = params["part_list"]
if(!processing_queue) add_part_set_to_queue(part_list)
build_part(D) return
else if("add_queue_part")
add_to_queue(D) // Add a specific part to queue
break var/T = params["id"]
if(href_list["add_to_queue"]) for(var/v in stored_research.researched_designs)
var/T = href_list["add_to_queue"] var/datum/design/D = SSresearch.techweb_design_by_id(v)
for(var/v in stored_research.researched_designs) if((D.build_type & MECHFAB) && (D.id == T))
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(D.id == T)
add_to_queue(D) add_to_queue(D)
break break
return update_queue_on_page() return
if(href_list["remove_from_queue"]) if("del_queue_part")
remove_from_queue(text2num(href_list["remove_from_queue"])) // Delete a specific from from the queue
return update_queue_on_page() var/index = text2num(params["index"])
if(href_list["partset_to_queue"]) remove_from_queue(index)
add_part_set_to_queue(href_list["partset_to_queue"]) return
return update_queue_on_page() if("clear_queue")
if(href_list["process_queue"]) // Delete everything from queue
spawn(0) queue.Cut()
if(processing_queue || being_built) return
return FALSE if("build_queue")
processing_queue = 1 // Build everything in queue
process_queue() if(process_queue)
processing_queue = 0 return
if(href_list["clear_temp"]) process_queue = TRUE
temp = null
if(href_list["screen"])
screen = href_list["screen"]
if(href_list["queue_move"] && href_list["index"])
var/index = text2num(href_list["index"])
var/new_index = index + text2num(href_list["queue_move"])
if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index))
if(ISINRANGE(new_index,1,queue.len))
queue.Swap(index,new_index)
return update_queue_on_page()
if(href_list["clear_queue"])
queue = list()
return update_queue_on_page()
if(href_list["sync"])
sync()
if(href_list["part_desc"])
var/T = href_list["part_desc"]
for(var/v in stored_research.researched_designs)
var/datum/design/D = SSresearch.techweb_design_by_id(v)
if(D.build_type & MECHFAB)
if(D.id == T)
var/obj/part = D.build_path
temp = {"<h1>[initial(part.name)] description:</h1>
[initial(part.desc)]<br>
<a href='?src=[REF(src)];clear_temp=1'>Return</a>
"}
break
if(href_list["remove_mat"] && href_list["material"]) if(!being_built)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) START_PROCESSING(SSfastprocess, src)
var/datum/material/Mat = locate(href_list["material"]) //begin_processing()
materials.retrieve_sheets(text2num(href_list["remove_mat"]), Mat) return
if("stop_queue")
// Pause queue building. Also known as stop.
process_queue = FALSE
return
if("build_part")
// Build a single part
if(being_built || process_queue)
return
updateUsrDialog() var/id = params["id"]
return var/datum/design/D = SSresearch.techweb_design_by_id(id)
/obj/machinery/mecha_part_fabricator/on_deconstruction() if(!(D.build_type & MECHFAB) || !(D.id == id))
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container) return
materials.retrieve_all()
..() if(build_part(D))
on_start_printing()
START_PROCESSING(SSfastprocess, src)
//begin_processing() teege has this as a helper proc. please port it!
return
if("move_queue_part")
// Moves a part up or down in the queue.
var/index = text2num(params["index"])
var/new_index = index + text2num(params["newindex"])
if(isnum(index) && isnum(new_index) && ISINTEGER(index) && ISINTEGER(new_index))
if(ISINRANGE(new_index,1,length(queue)))
queue.Swap(index,new_index)
return
if("remove_mat")
// Remove a material from the fab
var/mat_ref = params["ref"]
var/amount = text2num(params["amount"])
var/datum/material/mat = locate(mat_ref)
eject_sheets(mat, amount)
return
return FALSE
/**
* Eject material sheets.
*
* Returns the number of sheets successfully ejected.
* eject_sheet - Byond REF of the material to eject.
* eject_amt - Number of sheets to attempt to eject.
*/
/obj/machinery/mecha_part_fabricator/proc/eject_sheets(eject_sheet, eject_amt)
var/datum/component/material_container/mat_container = rmat.mat_container
if (!mat_container)
say("No access to material storage, please contact the quartermaster.")
return 0
if (rmat.on_hold())
say("Mineral access is on hold, please contact the quartermaster.")
return 0
var/count = mat_container.retrieve_sheets(text2num(eject_amt), eject_sheet, drop_location())
var/list/matlist = list()
matlist[eject_sheet] = text2num(eject_amt)
rmat.silo_log(src, "ejected", -count, "sheets", matlist)
return count
/obj/machinery/mecha_part_fabricator/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted) /obj/machinery/mecha_part_fabricator/proc/AfterMaterialInsert(item_inserted, id_inserted, amount_inserted)
var/datum/material/M = id_inserted var/datum/material/M = id_inserted
add_overlay("fab-load-[M.name]") add_overlay("fab-load-[M.name]")
addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[M.name]"), 10) addtimer(CALLBACK(src, /atom/proc/cut_overlay, "fab-load-[M.name]"), 10)
updateUsrDialog()
/obj/machinery/mecha_part_fabricator/attackby(obj/item/W, mob/user, params) /obj/machinery/mecha_part_fabricator/screwdriver_act(mob/living/user, obj/item/I)
if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W)) if(..())
return TRUE return TRUE
if(being_built)
to_chat(user, "<span class='warning'>\The [src] is currently processing! Please wait until completion.</span>")
return FALSE
return default_deconstruction_screwdriver(user, "fab-o", "fab-idle", I)
if(default_deconstruction_crowbar(W)) /obj/machinery/mecha_part_fabricator/crowbar_act(mob/living/user, obj/item/I)
if(..())
return TRUE return TRUE
if(being_built)
return ..() to_chat(user, "<span class='warning'>\The [src] is currently processing! Please wait until completion.</span>")
return FALSE
return default_deconstruction_crowbar(I)
/obj/machinery/mecha_part_fabricator/proc/is_insertion_ready(mob/user) /obj/machinery/mecha_part_fabricator/proc/is_insertion_ready(mob/user)
if(panel_open) if(panel_open)
@@ -463,6 +671,9 @@
return TRUE return TRUE
/obj/machinery/mecha_part_fabricator/maint
link_on_init = FALSE
/obj/machinery/mecha_part_fabricator/offstation /obj/machinery/mecha_part_fabricator/offstation
offstation_security_levels = FALSE link_on_init = FALSE
circuit = /obj/item/circuitboard/machine/mechfab/offstation circuit = /obj/item/circuitboard/machine/mechfab/offstation
+3 -6
View File
@@ -5,14 +5,11 @@
icon_keyboard = "tech_key" icon_keyboard = "tech_key"
req_access = list(ACCESS_ROBOTICS) req_access = list(ACCESS_ROBOTICS)
circuit = /obj/item/circuitboard/computer/mecha_control circuit = /obj/item/circuitboard/computer/mecha_control
ui_x = 500
ui_y = 500
/obj/machinery/computer/mecha/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/machinery/computer/mecha/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "ExosuitControlConsole", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "ExosuitControlConsole", name)
ui.open() ui.open()
/obj/machinery/computer/mecha/ui_data(mob/user) /obj/machinery/computer/mecha/ui_data(mob/user)
+45 -29
View File
@@ -8,7 +8,7 @@
anchored = TRUE anchored = TRUE
light_range = 3 light_range = 3
var/movechance = 70 var/movechance = 70
var/obj/item/assembly/signaler/anomaly/aSignal var/obj/item/assembly/signaler/anomaly/aSignal = /obj/item/assembly/signaler/anomaly
var/area/impact_area var/area/impact_area
var/lifespan = 990 var/lifespan = 990
@@ -23,8 +23,10 @@
START_PROCESSING(SSobj, src) START_PROCESSING(SSobj, src)
impact_area = get_area(src) impact_area = get_area(src)
aSignal = new(src) if (!impact_area)
aSignal.name = "[name] core" return INITIALIZE_HINT_QDEL
aSignal = new aSignal(src)
aSignal.code = rand(1,100) aSignal.code = rand(1,100)
aSignal.anomaly_type = type aSignal.anomaly_type = type
@@ -75,7 +77,7 @@
/obj/effect/anomaly/attackby(obj/item/I, mob/user, params) /obj/effect/anomaly/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/analyzer)) if(I.tool_behaviour == TOOL_ANALYZER) //revert if runtimed
to_chat(user, "<span class='notice'>Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(aSignal.frequency)], code [aSignal.code].</span>") to_chat(user, "<span class='notice'>Analyzing... [src]'s unstable field is fluctuating along frequency [format_frequency(aSignal.frequency)], code [aSignal.code].</span>")
/////////////////////// ///////////////////////
@@ -85,6 +87,7 @@
icon_state = "shield2" icon_state = "shield2"
density = FALSE density = FALSE
var/boing = 0 var/boing = 0
aSignal = /obj/item/assembly/signaler/anomaly/grav
/obj/effect/anomaly/grav/anomalyEffect() /obj/effect/anomaly/grav/anomalyEffect()
..() ..()
@@ -95,17 +98,23 @@
for(var/mob/living/M in range(0, src)) for(var/mob/living/M in range(0, src))
gravShock(M) gravShock(M)
for(var/mob/living/M in orange(4, src)) for(var/mob/living/M in orange(4, src))
step_towards(M,src) if(!M.mob_negates_gravity()) //delete when runtimed
step_towards(M,src)
for(var/obj/O in range(0,src)) for(var/obj/O in range(0,src))
if(!O.anchored) if(!O.anchored)
//if(isturf(O.loc))
// var/turf/T = O.loc
// if(T.intact && HAS_TRAIT(O, TRAIT_T_RAY_VISIBLE))
// continue
var/mob/living/target = locate() in view(4,src) var/mob/living/target = locate() in view(4,src)
if(target && !target.stat) if(target && !target.stat)
O.throw_at(target, 5, 10) O.throw_at(target, 5, 10)
/obj/effect/anomaly/grav/Crossed(mob/A) /obj/effect/anomaly/grav/Crossed(atom/movable/AM)
gravShock(A) . = ..()
gravShock(AM)
/obj/effect/anomaly/grav/Bump(mob/A) /obj/effect/anomaly/grav/Bump(atom/A)
gravShock(A) gravShock(A)
/obj/effect/anomaly/grav/Bumped(atom/movable/AM) /obj/effect/anomaly/grav/Bumped(atom/movable/AM)
@@ -138,6 +147,7 @@
name = "flux wave anomaly" name = "flux wave anomaly"
icon_state = "electricity2" icon_state = "electricity2"
density = TRUE density = TRUE
aSignal = /obj/item/assembly/signaler/anomaly/flux
var/canshock = FALSE var/canshock = FALSE
var/shockdamage = 20 var/shockdamage = 20
var/explosive = TRUE var/explosive = TRUE
@@ -148,11 +158,12 @@
for(var/mob/living/M in range(0, src)) for(var/mob/living/M in range(0, src))
mobShock(M) mobShock(M)
/obj/effect/anomaly/flux/Crossed(mob/living/M) /obj/effect/anomaly/flux/Crossed(atom/movable/AM)
mobShock(M) . = ..()
mobShock(AM)
/obj/effect/anomaly/flux/Bump(mob/living/M) /obj/effect/anomaly/flux/Bump(atom/A)
mobShock(M) mobShock(A)
/obj/effect/anomaly/flux/Bumped(atom/movable/AM) /obj/effect/anomaly/flux/Bumped(atom/movable/AM)
mobShock(AM) mobShock(AM)
@@ -160,7 +171,7 @@
/obj/effect/anomaly/flux/proc/mobShock(mob/living/M) /obj/effect/anomaly/flux/proc/mobShock(mob/living/M)
if(canshock && istype(M)) if(canshock && istype(M))
canshock = FALSE //Just so you don't instakill yourself if you slam into the anomaly five times in a second. canshock = FALSE //Just so you don't instakill yourself if you slam into the anomaly five times in a second.
M.electrocute_act(shockdamage, "[name]", flags = SHOCK_NOGLOVES) M.electrocute_act(shockdamage, name, flags = SHOCK_NOGLOVES)
/obj/effect/anomaly/flux/detonate() /obj/effect/anomaly/flux/detonate()
if(explosive) if(explosive)
@@ -176,6 +187,7 @@
icon = 'icons/obj/projectiles.dmi' icon = 'icons/obj/projectiles.dmi'
icon_state = "bluespace" icon_state = "bluespace"
density = TRUE density = TRUE
aSignal = /obj/item/assembly/signaler/anomaly/bluespace
/obj/effect/anomaly/bluespace/anomalyEffect() /obj/effect/anomaly/bluespace/anomalyEffect()
..() ..()
@@ -187,7 +199,7 @@
do_teleport(AM, locate(AM.x, AM.y, AM.z), 8, channel = TELEPORT_CHANNEL_BLUESPACE) do_teleport(AM, locate(AM.x, AM.y, AM.z), 8, channel = TELEPORT_CHANNEL_BLUESPACE)
/obj/effect/anomaly/bluespace/detonate() /obj/effect/anomaly/bluespace/detonate()
var/turf/T = safepick(get_area_turfs(impact_area)) var/turf/T = pick(get_area_turfs(impact_area))
if(T) if(T)
// Calculate new position (searches through beacons in world) // Calculate new position (searches through beacons in world)
var/obj/item/beacon/chosen var/obj/item/beacon/chosen
@@ -224,21 +236,23 @@
if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving if(!A.Move(newloc) && newloc) // if the atom, for some reason, can't move, FORCE them to move! :) We try Move() first to invoke any movement-related checks the atom needs to perform after moving
A.forceMove(newloc) A.forceMove(newloc)
spawn() if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect var/mob/M = A
var/mob/M = A if(M.client)
if(M.client) INVOKE_ASYNC(src, .proc/blue_effect, M)
var/obj/blueeffect = new /obj(src)
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH" /obj/effect/anomaly/bluespace/proc/blue_effect(mob/M)
blueeffect.icon = 'icons/effects/effects.dmi' var/obj/blueeffect = new /obj(src)
blueeffect.icon_state = "shieldsparkles" blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
blueeffect.layer = FLASH_LAYER blueeffect.icon = 'icons/effects/effects.dmi'
blueeffect.plane = FULLSCREEN_PLANE blueeffect.icon_state = "shieldsparkles"
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT blueeffect.layer = FLASH_LAYER
M.client.screen += blueeffect blueeffect.plane = FULLSCREEN_PLANE
sleep(20) blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
M.client.screen -= blueeffect M.client.screen += blueeffect
qdel(blueeffect) sleep(20)
M.client.screen -= blueeffect
qdel(blueeffect)
///////////////////// /////////////////////
@@ -246,6 +260,7 @@
name = "pyroclastic anomaly" name = "pyroclastic anomaly"
icon_state = "mustard" icon_state = "mustard"
var/ticks = 0 var/ticks = 0
aSignal = /obj/item/assembly/signaler/anomaly/pyro
/obj/effect/anomaly/pyro/anomalyEffect() /obj/effect/anomaly/pyro/anomalyEffect()
..() ..()
@@ -278,6 +293,7 @@
name = "vortex anomaly" name = "vortex anomaly"
icon_state = "bhole3" icon_state = "bhole3"
desc = "That's a nice station you have there. It'd be a shame if something happened to it." desc = "That's a nice station you have there. It'd be a shame if something happened to it."
aSignal = /obj/item/assembly/signaler/anomaly/vortex
/obj/effect/anomaly/bhole/anomalyEffect() /obj/effect/anomaly/bhole/anomalyEffect()
..() ..()
+9 -13
View File
@@ -1,10 +1,10 @@
/proc/create_portal_pair(turf/source, turf/destination, _creator = null, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override) /proc/create_portal_pair(turf/source, turf/destination, _lifespan = 300, accuracy = 0, newtype = /obj/effect/portal, atmos_link_override)
if(!istype(source) || !istype(destination)) if(!istype(source) || !istype(destination))
return return
var/turf/actual_destination = get_teleport_turf(destination, accuracy) var/turf/actual_destination = get_teleport_turf(destination, accuracy)
var/obj/effect/portal/P1 = new newtype(source, _creator, _lifespan, null, FALSE, null, atmos_link_override) var/obj/effect/portal/P1 = new newtype(source, _lifespan, null, FALSE, null, atmos_link_override)
var/obj/effect/portal/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE, null, atmos_link_override) var/obj/effect/portal/P2 = new newtype(actual_destination, _lifespan, P1, TRUE, null, atmos_link_override)
if(!istype(P1)||!istype(P2)) if(!istype(P1)||!istype(P2))
return return
P1.link_portal(P2) P1.link_portal(P2)
@@ -21,7 +21,6 @@
var/obj/effect/portal/linked var/obj/effect/portal/linked
var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted. var/hardlinked = TRUE //Requires a linked portal at all times. Destroy if there's no linked portal, if there is destroy it when this one is deleted.
var/teleport_channel = TELEPORT_CHANNEL_BLUESPACE var/teleport_channel = TELEPORT_CHANNEL_BLUESPACE
var/creator
var/turf/hard_target //For when a portal needs a hard target and isn't to be linked. var/turf/hard_target //For when a portal needs a hard target and isn't to be linked.
var/atmos_link = FALSE //Link source/destination atmos. var/atmos_link = FALSE //Link source/destination atmos.
var/turf/open/atmos_source //Atmos link source var/turf/open/atmos_source //Atmos link source
@@ -35,6 +34,7 @@
name = "wormhole" name = "wormhole"
icon = 'icons/obj/objects.dmi' icon = 'icons/obj/objects.dmi'
icon_state = "anom" icon_state = "anom"
layer = RIPPLE_LAYER
mech_sized = TRUE mech_sized = TRUE
teleport_channel = TELEPORT_CHANNEL_WORMHOLE teleport_channel = TELEPORT_CHANNEL_WORMHOLE
@@ -49,7 +49,9 @@
user.forceMove(get_turf(src)) user.forceMove(get_turf(src))
return TRUE return TRUE
/obj/effect/portal/Crossed(atom/movable/AM, oldloc) /obj/effect/portal/Crossed(atom/movable/AM, oldloc, force_stop = 0)
if(force_stop)
return ..()
if(isobserver(AM)) if(isobserver(AM))
return ..() return ..()
if(linked && (get_turf(oldloc) == get_turf(linked))) if(linked && (get_turf(oldloc) == get_turf(linked)))
@@ -66,7 +68,7 @@
if(Adjacent(user)) if(Adjacent(user))
user.forceMove(get_turf(src)) user.forceMove(get_turf(src))
/obj/effect/portal/Initialize(mapload, _creator, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override) /obj/effect/portal/Initialize(mapload, _lifespan = 0, obj/effect/portal/_linked, automatic_link = FALSE, turf/hard_target_override, atmos_link_override)
. = ..() . = ..()
GLOB.portals += src GLOB.portals += src
if(!istype(_linked) && automatic_link) if(!istype(_linked) && automatic_link)
@@ -78,7 +80,6 @@
atmos_link = atmos_link_override atmos_link = atmos_link_override
link_portal(_linked) link_portal(_linked)
hardlinked = automatic_link hardlinked = automatic_link
creator = _creator
if(isturf(hard_target_override)) if(isturf(hard_target_override))
hard_target = hard_target_override hard_target = hard_target_override
@@ -129,10 +130,7 @@
LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source) LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source)
atmos_destination = null atmos_destination = null
/obj/effect/portal/Destroy() //Calls on_portal_destroy(destroyed portal, location of destroyed portal) on creator if creator has such call. /obj/effect/portal/Destroy()
if(creator && hascall(creator, "on_portal_destroy"))
call(creator, "on_portal_destroy")(src, src.loc)
creator = null
GLOB.portals -= src GLOB.portals -= src
unlink_atmos() unlink_atmos()
if(hardlinked && !QDELETED(linked)) if(hardlinked && !QDELETED(linked))
@@ -153,8 +151,6 @@
return FALSE return FALSE
if(!force && (!ismecha(M) && !istype(M, /obj/item/projectile) && M.anchored && !allow_anchored)) if(!force && (!ismecha(M) && !istype(M, /obj/item/projectile) && M.anchored && !allow_anchored))
return return
if(ismegafauna(M))
message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].")
var/no_effect = FALSE var/no_effect = FALSE
if(last_effect == world.time) if(last_effect == world.time)
no_effect = TRUE no_effect = TRUE
@@ -380,8 +380,6 @@
name = "random keg spawner" name = "random keg spawner"
lootcount = 1 lootcount = 1
loot = list(/obj/structure/reagent_dispensers/keg/mead = 5, loot = list(/obj/structure/reagent_dispensers/keg/mead = 5,
/obj/structure/reagent_dispensers/keg/aphro = 2,
/obj/structure/reagent_dispensers/keg/aphro/strong = 2,
/obj/structure/reagent_dispensers/keg/gargle = 1) /obj/structure/reagent_dispensers/keg/gargle = 1)
/obj/effect/spawner/lootdrop/coin /obj/effect/spawner/lootdrop/coin
+14 -15
View File
@@ -238,24 +238,22 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
playsound(get_turf(user), 'sound/items/deconstruct.ogg', 50, 1) playsound(get_turf(user), 'sound/items/deconstruct.ogg', 50, 1)
return(BRUTELOSS) return(BRUTELOSS)
/obj/item/pipe_dispenser/ui_base_html(html) /obj/item/pipe_dispenser/ui_assets(mob/user)
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/pipes) return list(
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag()) get_asset_datum(/datum/asset/spritesheet/pipes),
)
/obj/item/pipe_dispenser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/item/pipe_dispenser/ui_interact(mob/user, datum/tgui/ui)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) ui = SStgui.try_update_ui(user, src, ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui) if(!ui)
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes) ui = new(user, src, "RapidPipeDispenser", name)
assets.send(user)
ui = new(user, src, ui_key, "RapidPipeDispenser", name, 425, 515, master_ui, state)
ui.open() ui.open()
/obj/item/pipe_dispenser/ui_data(mob/user) /obj/item/pipe_dispenser/ui_data(mob/user)
var/list/data = list( var/list/data = list(
"category" = category, "category" = category,
"piping_layer" = piping_layer, "piping_layer" = piping_layer,
// "ducting_layer" = ducting_layer, //uhh is this for chem thing?
"preview_rows" = recipe.get_preview(p_dir), "preview_rows" = recipe.get_preview(p_dir),
"categories" = list(), "categories" = list(),
"selected_color" = paint_color, "selected_color" = paint_color,
@@ -284,7 +282,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
/obj/item/pipe_dispenser/ui_act(action, params) /obj/item/pipe_dispenser/ui_act(action, params)
if(..()) if(..())
return return
if(!usr.canUseTopic(src)) if(!usr.canUseTopic(src, BE_CLOSE))
return return
var/playeffect = TRUE var/playeffect = TRUE
switch(action) switch(action)
@@ -304,6 +302,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
if("piping_layer") if("piping_layer")
piping_layer = text2num(params["piping_layer"]) piping_layer = text2num(params["piping_layer"])
playeffect = FALSE playeffect = FALSE
// if("ducting_layer")
// ducting_layer = text2num(params["ducting_layer"])
// playeffect = FALSE
if("pipe_type") if("pipe_type")
var/static/list/recipes var/static/list/recipes
if(!recipes) if(!recipes)
@@ -320,11 +321,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
mode &= ~n mode &= ~n
else else
mode |= n mode |= n
if(playeffect)
if(playeffect && world.time >= effectcooldown)
spark_system.start() spark_system.start()
effectcooldown = world.time + 100 playsound(get_turf(src), 'sound/effects/pop.ogg', 50, FALSE)
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
return TRUE return TRUE
/obj/item/pipe_dispenser/pre_attack(atom/A, mob/user) /obj/item/pipe_dispenser/pre_attack(atom/A, mob/user)
+3 -3
View File
@@ -180,10 +180,10 @@
stored_decal_total = "[stored_decal][yellow_fix][stored_color]" stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
return return
/obj/item/airlock_painter/decal/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) /obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "DecalPainter", name, 500, 400, master_ui, state) ui = new(user, src, "DecalPainter", name)
ui.open() ui.open()
/obj/item/airlock_painter/decal/ui_data(mob/user) /obj/item/airlock_painter/decal/ui_data(mob/user)
+7 -7
View File
@@ -147,23 +147,23 @@
to_chat(user, "<span class='warning'>There is not enough of [src] left!</span>") to_chat(user, "<span class='warning'>There is not enough of [src] left!</span>")
. = TRUE . = TRUE
/obj/item/toy/crayon/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) /obj/item/toy/crayon/ui_state(mob/user)
// tgui is a plague upon this codebase return GLOB.hands_state
SStgui.try_update_ui(user, src, ui_key, ui, force_open) /obj/item/toy/crayon/ui_interact(mob/user, datum/tgui/ui)
// tgui is a plague upon this codebase
// no u
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "Crayon", name, 600, 600, ui = new(user, src, "Crayon", name)
master_ui, state)
ui.open() ui.open()
/obj/item/toy/crayon/spraycan/AltClick(mob/user) /obj/item/toy/crayon/spraycan/AltClick(mob/user)
. = ..()
if(user.canUseTopic(src, BE_CLOSE, ismonkey(user))) if(user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
if(has_cap) if(has_cap)
is_capped = !is_capped is_capped = !is_capped
to_chat(user, "<span class='notice'>The cap on [src] is now [is_capped ? "on" : "off"].</span>") to_chat(user, "<span class='notice'>The cap on [src] is now [is_capped ? "on" : "off"].</span>")
update_icon() update_icon()
return TRUE
/obj/item/toy/crayon/CtrlClick(mob/user) /obj/item/toy/crayon/CtrlClick(mob/user)
if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, ismonkey(user))) if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
@@ -1027,6 +1027,7 @@ GLOBAL_LIST_EMPTY(PDAs)
else if(is_type_in_list(C, contained_item)) //Checks if there is a pen else if(is_type_in_list(C, contained_item)) //Checks if there is a pen
if(inserted_item) if(inserted_item)
to_chat(user, "<span class='warning'>There is already \a [inserted_item] in \the [src]!</span>") to_chat(user, "<span class='warning'>There is already \a [inserted_item] in \the [src]!</span>")
return ..()
else else
if(!user.transferItemToLoc(C, src)) if(!user.transferItemToLoc(C, src))
return return
+11 -9
View File
@@ -54,18 +54,20 @@
name = initial(name) name = initial(name)
icon_state = initial(icon_state) icon_state = initial(icon_state)
/obj/item/aicard/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/item/aicard/ui_state(mob/user)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) return GLOB.hands_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/aicard/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "Intellicard", name, 500, 500, master_ui, state) ui = new(user, src, "Intellicard", name)
ui.open() ui.open()
/obj/item/aicard/ui_data() /obj/item/aicard/ui_data()
var/list/data = list() var/list/data = list()
if(AI) if(AI)
data["name"] = AI.name data["name"] = AI.name
data["laws"] = AI.laws.get_law_list(include_zeroth = 1) data["laws"] = AI.laws.get_law_list(include_zeroth = TRUE, render_html = FALSE)
data["health"] = (AI.health + 100) / 2 data["health"] = (AI.health + 100) / 2
data["wireless"] = !AI.control_disabled //todo disabled->enabled data["wireless"] = !AI.control_disabled //todo disabled->enabled
data["radio"] = AI.radio_enabled data["radio"] = AI.radio_enabled
@@ -86,19 +88,19 @@
if(confirm == "Yes" && !..()) if(confirm == "Yes" && !..())
flush = TRUE flush = TRUE
if(AI && AI.loc == src) if(AI && AI.loc == src)
to_chat(AI, "Your core files are being wiped!") to_chat(AI, "<span class='userdanger'>Your core files are being wiped!</span>")
while(AI.stat != DEAD && flush) while(AI.stat != DEAD && flush)
AI.adjustOxyLoss(1) AI.adjustOxyLoss(5)
AI.updatehealth() AI.updatehealth()
sleep(5) sleep(5)
flush = FALSE flush = FALSE
. = TRUE . = TRUE
if("wireless") if("wireless")
AI.control_disabled = !AI.control_disabled AI.control_disabled = !AI.control_disabled
to_chat(AI, "[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!") to_chat(AI, "<span class='warning'>[src]'s wireless port has been [AI.control_disabled ? "disabled" : "enabled"]!</span>")
. = TRUE . = TRUE
if("radio") if("radio")
AI.radio_enabled = !AI.radio_enabled AI.radio_enabled = !AI.radio_enabled
to_chat(AI, "Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!") to_chat(AI, "<span class='warning'>Your Subspace Transceiver has been [AI.radio_enabled ? "enabled" : "disabled"]!</span>")
. = TRUE . = TRUE
update_icon() update_icon()
@@ -163,12 +163,13 @@
return return
ui_interact(user) ui_interact(user)
/obj/item/dogborg/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/item/dogborg/sleeper/ui_state(mob/user)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) return GLOB.notcontained_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) /obj/item/dogborg/sleeper/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "dogborg_sleeper", name, 375, 550, master_ui, state) ui = new(user, src, "dogborg_sleeper", name, 375, 550) //UI DOES NOT EXIST
ui.open() ui.open()
/obj/item/dogborg/sleeper/ui_data() /obj/item/dogborg/sleeper/ui_data()
+2 -130
View File
@@ -1,4 +1,4 @@
GLOBAL_LIST_EMPTY(GPS_list)
/obj/item/gps /obj/item/gps
name = "global positioning system" name = "global positioning system"
desc = "Helping lost spacemen find their way through the planets since 2016." desc = "Helping lost spacemen find their way through the planets since 2016."
@@ -8,138 +8,10 @@ GLOBAL_LIST_EMPTY(GPS_list)
slot_flags = ITEM_SLOT_BELT slot_flags = ITEM_SLOT_BELT
obj_flags = UNIQUE_RENAME obj_flags = UNIQUE_RENAME
var/gpstag = "COM0" var/gpstag = "COM0"
var/emped = FALSE
var/tracking = TRUE
var/updating = TRUE //Automatic updating of GPS list. Can be set to manual by user.
var/global_mode = TRUE //If disabled, only GPS signals of the same Z level are shown
/obj/item/gps/examine(mob/user)
. = ..()
var/turf/curr = get_turf(src)
. += "The screen says: [get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
. += "<span class='notice'>Alt-click to switch it [tracking ? "off":"on"].</span>"
/obj/item/gps/Initialize() /obj/item/gps/Initialize()
. = ..() . = ..()
GLOB.GPS_list += src AddComponent(/datum/component/gps/item, gpstag)
name = "global positioning system ([gpstag])"
add_overlay("working")
/obj/item/gps/Destroy()
GLOB.GPS_list -= src
return ..()
/obj/item/gps/emp_act(severity)
. = ..()
if (. & EMP_PROTECT_SELF)
return
emped = TRUE
cut_overlay("working")
add_overlay("emp")
addtimer(CALLBACK(src, .proc/reboot), 300, TIMER_UNIQUE|TIMER_OVERRIDE) //if a new EMP happens, remove the old timer so it doesn't reactivate early
SStgui.close_uis(src) //Close the UI control if it is open.
/obj/item/gps/proc/reboot()
emped = FALSE
cut_overlay("emp")
add_overlay("working")
/obj/item/gps/AltClick(mob/user)
. = ..()
if(!user.canUseTopic(src, BE_CLOSE))
return
toggletracking(user)
return TRUE
/obj/item/gps/proc/toggletracking(mob/user)
if(!user.canUseTopic(src, BE_CLOSE))
return //user not valid to use gps
if(emped)
to_chat(user, "It's busted!")
return
if(tracking)
cut_overlay("working")
to_chat(user, "[src] is no longer tracking, or visible to other GPS devices.")
tracking = FALSE
else
add_overlay("working")
to_chat(user, "[src] is now tracking, and visible to other GPS devices.")
tracking = TRUE
/obj/item/gps/ui_interact(mob/user, ui_key = "gps", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state) // Remember to use the appropriate state.
if(emped)
to_chat(user, "[src] fizzles weakly.")
return
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
// Variable window height, depending on how many GPS units there are
// to show, clamped to relatively safe range.
var/gps_window_height = clamp(325 + GLOB.GPS_list.len * 14, 325, 700)
ui = new(user, src, ui_key, "Gps", "Global Positioning System", 470, gps_window_height, master_ui, state) //width, height
ui.open()
ui.set_autoupdate(state = updating)
/obj/item/gps/ui_data(mob/user)
var/list/data = list()
data["power"] = tracking
data["tag"] = gpstag
data["updating"] = updating
data["globalmode"] = global_mode
if(!tracking || emped) //Do not bother scanning if the GPS is off or EMPed
return data
var/turf/curr = get_turf(src)
data["current"] = "[get_area_name(curr, TRUE)] ([curr.x], [curr.y], [curr.z])"
data["currentArea"] = "[get_area_name(curr, TRUE)]"
data["currentCoords"] = "[curr.x], [curr.y], [curr.z]"
var/list/signals = list()
data["signals"] = list()
for(var/gps in GLOB.GPS_list)
var/obj/item/gps/G = gps
if(G.emped || !G.tracking || G == src)
continue
var/turf/pos = get_turf(G)
if(!global_mode && pos.z != curr.z)
continue
var/list/signal = list()
signal["entrytag"] = G.gpstag //Name or 'tag' of the GPS
signal["coords"] = "[pos.x], [pos.y], [pos.z]"
if(pos.z == curr.z) //Distance/Direction calculations for same z-level only
signal["dist"] = max(get_dist(curr, pos), 0) //Distance between the src and remote GPS turfs
signal["degrees"] = round(Get_Angle(curr, pos)) //0-360 degree directional bearing, for more precision.
signals += list(signal) //Add this signal to the list of signals
data["signals"] = signals
return data
/obj/item/gps/ui_act(action, params)
if(..())
return
switch(action)
if("rename")
var/a = input("Please enter desired tag.", name, gpstag) as text
a = copytext(sanitize(a), 1, 20)
gpstag = a
. = TRUE
name = "global positioning system ([gpstag])"
if("power")
toggletracking(usr)
. = TRUE
if("updating")
updating = !updating
. = TRUE
if("globalmode")
global_mode = !global_mode
. = TRUE
/obj/item/gps/science /obj/item/gps/science
icon_state = "gps-s" icon_state = "gps-s"
@@ -29,7 +29,7 @@
/obj/item/electropack/Destroy() /obj/item/electropack/Destroy()
SSradio.remove_object(src, frequency) SSradio.remove_object(src, frequency)
. = ..() return ..()
/obj/item/electropack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags) /obj/item/electropack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
if(iscarbon(user)) if(iscarbon(user))
@@ -39,7 +39,7 @@
return return
return ..() return ..()
/obj/item/electropack/attackby(obj/item/W, mob/living/user, params) /obj/item/electropack/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/clothing/head/helmet)) if(istype(W, /obj/item/clothing/head/helmet))
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit(user) var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit(user)
A.icon = 'icons/obj/assemblies.dmi' A.icon = 'icons/obj/assemblies.dmi'
@@ -59,56 +59,12 @@
else else
return ..() return ..()
/obj/item/electropack/Topic(href, href_list)
var/mob/living/carbon/C = usr
if(usr.stat || usr.restrained() || C.back == src)
return
if(!usr.canUseTopic(src, BE_CLOSE))
usr << browse(null, "window=radio")
onclose(usr, "radio")
return
if(href_list["set"])
if(href_list["set"] == "freq")
var/new_freq = input(usr, "Input a new receiving frequency", "Electropack Frequency", format_frequency(frequency)) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_freq = unformat_frequency(new_freq)
new_freq = sanitize_frequency(new_freq, TRUE)
set_frequency(new_freq)
if(href_list["set"] == "code")
var/new_code = input(usr, "Input a new receiving code", "Electropack Code", code) as num|null
if(!usr.canUseTopic(src, BE_CLOSE))
return
new_code = round(new_code)
new_code = clamp(new_code, 1, 100)
code = new_code
if(href_list["set"] == "power")
if(!usr.canUseTopic(src, BE_CLOSE))
return
on = !(on)
icon_state = "electropack[on]"
if(usr)
attack_self(usr)
return
/obj/item/electropack/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
frequency = new_frequency
SSradio.add_object(src, frequency, RADIO_SIGNALER)
return
/obj/item/electropack/receive_signal(datum/signal/signal) /obj/item/electropack/receive_signal(datum/signal/signal)
if(!signal || signal.data["code"] != code) if(!signal || signal.data["code"] != code)
return return
if(isliving(loc) && on) if(isliving(loc) && on)
if(shock_cooldown == TRUE) if(shock_cooldown)
return return
shock_cooldown = TRUE shock_cooldown = TRUE
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100) addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
@@ -124,18 +80,59 @@
if(master) if(master)
master.receive_signal() master.receive_signal()
return
/obj/item/electropack/ui_interact(mob/user) /obj/item/electropack/proc/set_frequency(new_frequency)
if(!ishuman(user)) SSradio.remove_object(src, frequency)
frequency = new_frequency
SSradio.add_object(src, frequency, RADIO_SIGNALER)
/obj/item/electropack/ui_state(mob/user)
return GLOB.hands_state
/obj/item/electropack/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui)
ui = new(user, src, "Electropack", name)
ui.open()
/obj/item/electropack/ui_data(mob/user)
var/list/data = list()
data["power"] = on
data["frequency"] = frequency
data["code"] = code
data["minFrequency"] = MIN_FREE_FREQ
data["maxFrequency"] = MAX_FREE_FREQ
return data
/obj/item/electropack/ui_act(action, params)
if(..())
return return
/obj/item/electropack/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ switch(action)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) if("power")
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) on = !on
if(!ui) icon_state = "electropack[on]"
ui = new(user, src, ui_key, "Electropack", name, ui_x, ui_y, master_ui, state) . = TRUE
ui.open() if("freq")
var/value = unformat_frequency(params["freq"])
if(value)
frequency = sanitize_frequency(value, TRUE)
set_frequency(frequency)
. = TRUE
if("code")
var/value = text2num(params["code"])
if(value)
value = round(value)
code = clamp(value, 1, 100)
. = TRUE
if("reset")
if(params["reset"] == "freq")
frequency = initial(frequency)
. = TRUE
else if(params["reset"] == "code")
code = initial(code)
. = TRUE
/obj/item/electropack/shockcollar /obj/item/electropack/shockcollar
name = "shock collar" name = "shock collar"
@@ -145,7 +142,7 @@
icon_state = "shockcollar" icon_state = "shockcollar"
item_state = "shockcollar" item_state = "shockcollar"
body_parts_covered = NECK body_parts_covered = NECK
slot_flags = ITEM_SLOT_NECK | ITEM_SLOT_DENYPOCKET //no more pocket shockers slot_flags = ITEM_SLOT_NECK //no more pocket shockers. Now done without lazyness
w_class = WEIGHT_CLASS_SMALL w_class = WEIGHT_CLASS_SMALL
strip_delay = 60 strip_delay = 60
equip_delay_other = 60 equip_delay_other = 60
@@ -167,16 +164,18 @@
return return
return ..() return ..()
/obj/item/electropack/shockcollar/receive_signal(datum/signal/signal) /obj/item/electropack/shockcollar/receive_signal(datum/signal/signal) //we have to override this because of text
if(!signal || signal.data["code"] != code) if(!signal || signal.data["code"] != code)
return return
if(isliving(loc) && on) if(isliving(loc) && on) //the "on" arg is currently useless
var/mob/living/L = loc
if(!L.get_item_by_slot(SLOT_NECK)) //**properly** stops pocket shockers
return
if(shock_cooldown == TRUE) if(shock_cooldown == TRUE)
return return
shock_cooldown = TRUE shock_cooldown = TRUE
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100) addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
var/mob/living/L = loc
step(L, pick(GLOB.cardinals)) step(L, pick(GLOB.cardinals))
to_chat(L, "<span class='danger'>You feel a sharp shock from the collar!</span>") to_chat(L, "<span class='danger'>You feel a sharp shock from the collar!</span>")
@@ -196,10 +195,13 @@
if(t) if(t)
tagname = t tagname = t
name = "[initial(name)] - [t]" name = "[initial(name)] - [t]"
return
if(istype(W, /obj/item/clothing/head/helmet)) //lazy method of denying this
return
else else
return ..() return ..()
/obj/item/electropack/shockcollar/ui_interact(mob/user) //on_click calls this /obj/item/electropack/shockcollar/ui_interact(mob/user) //note to src: use tgooey
var/dat = {" var/dat = {"
<TT> <TT>
<B>Frequency/Code</B> for shock collar:<BR> <B>Frequency/Code</B> for shock collar:<BR>
+8 -12
View File
@@ -107,19 +107,15 @@
else else
..() ..()
/obj/item/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/item/radio/ui_state(mob/user)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state) return GLOB.inventory_state
. = ..()
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) /obj/item/radio/ui_interact(mob/user, datum/tgui/ui, datum/ui_state/state)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
var/ui_width = 360 ui = new(user, src, "Radio", name)
var/ui_height = 106 if(state)
if(subspace_transmission) ui.set_state(state)
if(channels.len > 0)
ui_height += 6 + channels.len * 21
else
ui_height += 24
ui = new(user, src, ui_key, "Radio", name, ui_width, ui_height, master_ui, state)
ui.open() ui.open()
/obj/item/radio/ui_data(mob/user) /obj/item/radio/ui_data(mob/user)
@@ -86,98 +86,102 @@ effective or pretty fucking useless.
return return
if(!used) if(!used)
log_combat(user, M, "irradiated", src) log_combat(user, M, "irradiated", src)
var/cooldown = GetCooldown() var/cooldown = get_cooldown()
used = 1 used = TRUE
icon_state = "health1" icon_state = "health1"
handle_cooldown(cooldown) // splits off to handle the cooldown while handling wavelength addtimer(VARSET_CALLBACK(src, used, FALSE), cooldown)
addtimer(VARSET_CALLBACK(src, icon_state, "health"), cooldown)
to_chat(user, "<span class='warning'>Successfully irradiated [M].</span>") to_chat(user, "<span class='warning'>Successfully irradiated [M].</span>")
spawn((wavelength+(intensity*4))*5) addtimer(CALLBACK(src, .proc/radiation_aftereffect, M), (wavelength+(intensity*4))*5)
if(M)
if(intensity >= 5)
M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS)
M.rad_act(intensity*10)
else else
to_chat(user, "<span class='warning'>The radioactive microlaser is still recharging.</span>") to_chat(user, "<span class='warning'>The radioactive microlaser is still recharging.</span>")
/obj/item/healthanalyzer/rad_laser/proc/handle_cooldown(cooldown) /obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M)
spawn(cooldown) if(QDELETED(M))
used = 0 return
icon_state = "health" if(intensity >= 5)
M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS)
M.rad_act(intensity*10)
/obj/item/healthanalyzer/rad_laser/proc/get_cooldown()
return round(max(10, (stealth*30 + intensity*5 - wavelength/4)))
/obj/item/healthanalyzer/rad_laser/attack_self(mob/user) /obj/item/healthanalyzer/rad_laser/attack_self(mob/user)
interact(user) interact(user)
/obj/item/healthanalyzer/rad_laser/proc/GetCooldown()
return round(max(10, (stealth*30 + intensity*5 - wavelength/4)))
/obj/item/healthanalyzer/rad_laser/interact(mob/user) /obj/item/healthanalyzer/rad_laser/interact(mob/user)
ui_interact(user) ui_interact(user)
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user) /obj/item/healthanalyzer/rad_laser/ui_state(mob/user)
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ return GLOB.hands_state
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) /obj/item/healthanalyzer/rad_laser/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "RadioactiveMicrolaser", "Radioactive Microlaser", ui_x, ui_y, master_ui, state) ui = new(user, src, "RadioactiveMicrolaser")
ui.open() ui.open()
var/dat = "Irradiation: <A href='?src=[REF(src)];rad=1'>[irradiate ? "On" : "Off"]</A><br>" /obj/item/healthanalyzer/rad_laser/ui_data(mob/user)
dat += "Stealth Mode (NOTE: Deactivates automatically while Irradiation is off): <A href='?src=[REF(src)];stealthy=[TRUE]'>[stealth ? "On" : "Off"]</A><br>" var/list/data = list()
dat += "Scan Mode: <a href='?src=[REF(src)];mode=1'>" data["irradiate"] = irradiate
if(!scanmode) data["stealth"] = stealth
dat += "Scan Health" data["scanmode"] = scanmode
else if(scanmode == 1) data["intensity"] = intensity
dat += "Scan Reagents" data["wavelength"] = wavelength
else data["on_cooldown"] = used
dat += "Disabled" data["cooldown"] = DisplayTimeText(get_cooldown())
dat += "</a><br><br>" return data
dat += {" /obj/item/healthanalyzer/rad_laser/ui_act(action, params)
Radiation Intensity: if(..())
<A href='?src=[REF(src)];radint=-5'>-</A><A href='?src=[REF(src)];radint=-1'>-</A> return
[intensity]
<A href='?src=[REF(src)];radint=1'>+</A><A href='?src=[REF(src)];radint=5'>+</A><BR>
Radiation Wavelength: switch(action)
<A href='?src=[REF(src)];radwav=-5'>-</A><A href='?src=[REF(src)];radwav=-1'>-</A> if("irradiate")
[(wavelength+(intensity*4))] irradiate = !irradiate
<A href='?src=[REF(src)];radwav=1'>+</A><A href='?src=[REF(src)];radwav=5'>+</A><BR> . = TRUE
Laser Cooldown: [DisplayTimeText(GetCooldown())]<BR> if("stealth")
"} stealth = !stealth
. = TRUE
var/datum/browser/popup = new(user, "radlaser", "Radioactive Microlaser Interface", 400, 240) if("scanmode")
popup.set_content(dat) scanmode = !scanmode
popup.open() . = TRUE
if("radintensity")
/obj/item/healthanalyzer/rad_laser/Topic(href, href_list) var/target = params["target"]
if(!usr.canUseTopic(src)) var/adjust = text2num(params["adjust"])
return 1 if(target == "min")
target = 1
usr.set_machine(src) . = TRUE
if(href_list["rad"]) else if(target == "max")
irradiate = !irradiate target = 20
. = TRUE
else if(href_list["stealthy"]) else if(adjust)
stealth = !stealth target = intensity + adjust
. = TRUE
else if(href_list["mode"]) else if(text2num(target) != null)
scanmode += 1 target = text2num(target)
if(scanmode > 2) . = TRUE
scanmode = 0 if(.)
target = round(target)
else if(href_list["radint"]) intensity = clamp(target, 1, 20)
var/amount = text2num(href_list["radint"]) if("radwavelength")
amount += intensity var/target = params["target"]
intensity = max(1,(min(20,amount))) var/adjust = text2num(params["adjust"])
if(target == "min")
else if(href_list["radwav"]) target = 0
var/amount = text2num(href_list["radwav"]) . = TRUE
amount += wavelength else if(target == "max")
wavelength = max(0,(min(120,amount))) target = 120
. = TRUE
attack_self(usr) else if(adjust)
add_fingerprint(usr) target = wavelength + adjust
return . = TRUE
else if(text2num(target) != null)
target = text2num(target)
. = TRUE
if(.)
target = round(target)
wavelength = clamp(target, 0, 120)
/obj/item/shadowcloak /obj/item/shadowcloak
name = "cloaker belt" name = "cloaker belt"
@@ -188,11 +188,10 @@
tank_one.air_contents.merge(temp) tank_one.air_contents.merge(temp)
tank_two.air_contents.set_volume(tank_two.air_contents.return_volume() - tank_one.air_contents.return_volume()) tank_two.air_contents.set_volume(tank_two.air_contents.return_volume() - tank_one.air_contents.return_volume())
/* /*
Exadv1: I know this isn't how it's going to work, but this was just to check Exadv1: I know this isn't how it's going to work, but this was just to check
it explodes properly when it gets a signal (and it does). it explodes properly when it gets a signal (and it does).
*/ */
/obj/item/transfer_valve/proc/toggle_valve() /obj/item/transfer_valve/proc/toggle_valve()
if(!valve_open && tank_one && tank_two) if(!valve_open && tank_one && tank_two)
valve_open = TRUE valve_open = TRUE
@@ -233,16 +232,20 @@
valve_open = FALSE valve_open = FALSE
update_icon() update_icon()
// this doesn't do anything but the timer etc. expects it to be here /*
// eventually maybe have it update icon to show state (timer, prox etc.) like old bombs This doesn't do anything but the timer etc. expects it to be here
eventually maybe have it update icon to show state (timer, prox etc.) like old bombs
*/
/obj/item/transfer_valve/proc/c_state() /obj/item/transfer_valve/proc/c_state()
return return
/obj/item/transfer_valve/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \ /obj/item/transfer_valve/ui_state(mob/user)
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.hands_state) return GLOB.hands_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
/obj/item/transfer_valve/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "TransferValve", name, ui_x, ui_y, master_ui, state) ui = new(user, src, "TransferValve", name)
ui.open() ui.open()
/obj/item/transfer_valve/ui_data(mob/user) /obj/item/transfer_valve/ui_data(mob/user)
+5 -3
View File
@@ -192,11 +192,13 @@
return top_vote return top_vote
/obj/item/toy/eightball/haunted/ui_interact(mob/user, ui_key="main", datum/tgui/ui=null, force_open=0, datum/tgui/master_ui=null, datum/ui_state/state = GLOB.always_state) /obj/item/toy/eightball/haunted/ui_state(mob/user)
return GLOB.observer_state
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) /obj/item/toy/eightball/haunted/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "EightBallVote", name, 400, 600, master_ui, state) ui = new(user, src, "EightBallVote", name)
ui.open() ui.open()
/obj/item/toy/eightball/haunted/ui_data(mob/user) /obj/item/toy/eightball/haunted/ui_data(mob/user)
@@ -47,7 +47,7 @@
/obj/item/implant/warp/activate() /obj/item/implant/warp/activate()
. = ..() . = ..()
uses-- uses--
imp_in.do_adrenaline(150, TRUE, 0, 0, TRUE, list(/datum/reagent/fermi/eigenstate = 1.2), "<span class='boldnotice'>You feel an internal prick as as the bluespace starts ramping up!</span>") imp_in.do_adrenaline(20, TRUE, 0, 0, TRUE, list(/datum/reagent/fermi/eigenstate = 1.2), "<span class='boldnotice'>You feel an internal prick as as the bluespace starts ramping up!</span>")
to_chat(imp_in, "<span class='notice'>You feel an internal prick as as the bluespace starts ramping up!</span>") to_chat(imp_in, "<span class='notice'>You feel an internal prick as as the bluespace starts ramping up!</span>")
if(!uses) if(!uses)
qdel(src) qdel(src)
@@ -86,4 +86,4 @@
healthstring = "<small>Oxygen Deprivation Damage => [round(L.getOxyLoss())]<br />Fire Damage => [round(L.getFireLoss())]<br />Toxin Damage => [round(L.getToxLoss())]<br />Brute Force Damage => [round(L.getBruteLoss())]</small>" healthstring = "<small>Oxygen Deprivation Damage => [round(L.getOxyLoss())]<br />Fire Damage => [round(L.getFireLoss())]<br />Toxin Damage => [round(L.getToxLoss())]<br />Brute Force Damage => [round(L.getBruteLoss())]</small>"
if (!healthstring) if (!healthstring)
healthstring = "ERROR" healthstring = "ERROR"
return healthstring return healthstring
@@ -10,7 +10,7 @@
/obj/item/implant/radio/activate() /obj/item/implant/radio/activate()
. = ..() . = ..()
// needs to be GLOB.deep_inventory_state otherwise it won't open // needs to be GLOB.deep_inventory_state otherwise it won't open
radio.ui_interact(usr, "main", null, FALSE, null, GLOB.deep_inventory_state) radio.ui_interact(usr, state = GLOB.deep_inventory_state)
/obj/item/implant/radio/implant(mob/living/target, mob/user, silent = FALSE) /obj/item/implant/radio/implant(mob/living/target, mob/user, silent = FALSE)
. = ..() . = ..()
@@ -26,14 +26,15 @@
open_machine() open_machine()
update_icon() update_icon()
/obj/machinery/implantchair/ui_state(mob/user)
return GLOB.notcontained_state
/obj/machinery/implantchair/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state) /obj/machinery/implantchair/ui_interact(mob/user, datum/tgui/ui)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) ui = SStgui.try_update_ui(user, src, ui)
if(!ui) if(!ui)
ui = new(user, src, ui_key, "implantchair", name, 375, 280, master_ui, state) ui = new(user, src, "ImplantChair", name)
ui.open() ui.open()
/obj/machinery/implantchair/ui_data() /obj/machinery/implantchair/ui_data()
var/list/data = list() var/list/data = list()
data["occupied"] = occupant ? 1 : 0 data["occupied"] = occupant ? 1 : 0

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