@@ -18,9 +18,7 @@
|
||||
/obj/item/mining_scanner,
|
||||
/obj/item/flashlight/lantern,
|
||||
/obj/item/card/id/mining,
|
||||
/obj/item/gps/mining{
|
||||
tracking = 0
|
||||
},
|
||||
/obj/item/gps/mining,
|
||||
/turf/open/floor/plating,
|
||||
/area/ruin/powered/golem_ship)
|
||||
"d" = (
|
||||
@@ -34,9 +32,7 @@
|
||||
/obj/item/mining_scanner,
|
||||
/obj/item/flashlight/lantern,
|
||||
/obj/item/card/id/mining,
|
||||
/obj/item/gps/mining{
|
||||
tracking = 0
|
||||
},
|
||||
/obj/item/gps/mining,
|
||||
/turf/open/floor/plating,
|
||||
/area/ruin/powered/golem_ship)
|
||||
"e" = (
|
||||
@@ -156,9 +152,7 @@
|
||||
"x" = (
|
||||
/obj/structure/table/wood,
|
||||
/obj/machinery/reagentgrinder,
|
||||
/obj/item/gps/mining{
|
||||
tracking = 0
|
||||
},
|
||||
/obj/item/gps/mining,
|
||||
/turf/open/floor/mineral/titanium/purple,
|
||||
/area/ruin/powered/golem_ship)
|
||||
"z" = (
|
||||
|
||||
@@ -56560,7 +56560,6 @@
|
||||
},
|
||||
/area/maintenance/bar)
|
||||
"mqZ" = (
|
||||
/obj/structure/reagent_dispensers/keg/aphro/strong,
|
||||
/obj/item/reagent_containers/glass/beaker,
|
||||
/turf/open/floor/plating,
|
||||
/area/maintenance/bar)
|
||||
|
||||
@@ -126013,7 +126013,6 @@
|
||||
/turf/open/floor/plating,
|
||||
/area/chapel/office)
|
||||
"ijB" = (
|
||||
/obj/structure/reagent_dispensers/keg/aphro/strong,
|
||||
/obj/item/reagent_containers/glass/beaker,
|
||||
/turf/open/floor/plating,
|
||||
/area/crew_quarters/abandoned_gambling_den)
|
||||
|
||||
@@ -44383,7 +44383,6 @@
|
||||
/turf/open/floor/plasteel/white,
|
||||
/area/hallway/primary/aft)
|
||||
"bFB" = (
|
||||
/obj/structure/reagent_dispensers/keg/aphro/strong,
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/turf/open/floor/wood{
|
||||
icon_state = "wood-broken5"
|
||||
|
||||
@@ -60049,7 +60049,6 @@
|
||||
/turf/open/floor/plasteel/dark,
|
||||
/area/chapel/office)
|
||||
"tap" = (
|
||||
/obj/structure/reagent_dispensers/keg/aphro,
|
||||
/turf/open/floor/wood,
|
||||
/area/maintenance/department/crew_quarters/dorms)
|
||||
"taA" = (
|
||||
|
||||
@@ -2690,7 +2690,7 @@
|
||||
/obj/structure/rack,
|
||||
/obj/item/storage/box/zipties,
|
||||
/obj/item/assembly/flash/handheld,
|
||||
/obj/item/melee/classic_baton/telescopic,
|
||||
/obj/item/melee/classic_baton,
|
||||
/obj/machinery/light/small/built{
|
||||
dir = 8
|
||||
},
|
||||
|
||||
@@ -209,6 +209,8 @@
|
||||
#define COMSIG_MOB_SWAP_HANDS "mob_swap_hands" //from base of mob/swap_hand(): (obj/item)
|
||||
#define COMPONENT_BLOCK_SWAP 1
|
||||
|
||||
#define COMSIG_PROCESS_BORGCHARGER_OCCUPANT "living_charge"
|
||||
|
||||
// /client signals
|
||||
#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)
|
||||
|
||||
@@ -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
|
||||
@@ -74,6 +74,7 @@ GLOBAL_LIST_INIT(turfs_without_ground, typecacheof(list(
|
||||
#define ismush(A) (is_species(A, /datum/species/mush))
|
||||
#define isshadow(A) (is_species(A, /datum/species/shadow))
|
||||
#define isskeleton(A) (is_species(A, /datum/species/skeleton))
|
||||
#define isethereal(A) (is_species(A, /datum/species/ethereal))
|
||||
|
||||
// Citadel specific species
|
||||
#define isipcperson(A) (is_species(A, /datum/species/ipc))
|
||||
|
||||
@@ -131,6 +131,8 @@
|
||||
#define LIGHTING_LAYER 15
|
||||
#define LIGHTING_RENDER_TARGET "LIGHT_PLANE"
|
||||
|
||||
#define RAD_TEXT_LAYER 15.1
|
||||
|
||||
#define ABOVE_LIGHTING_PLANE 16
|
||||
#define ABOVE_LIGHTING_LAYER 16
|
||||
#define ABOVE_LIGHTING_RENDER_TARGET "ABOVE_LIGHTING_PLANE"
|
||||
|
||||
@@ -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.
|
||||
|
||||
//Endgame Results
|
||||
#define NUKE_MISS_STATION 1
|
||||
#define NUKE_SYNDICATE_BASE 2
|
||||
#define STATION_DESTROYED_NUKE 3
|
||||
#define STATION_EVACUATED 4
|
||||
#define NUKE_NEAR_MISS 1
|
||||
#define NUKE_MISS_STATION 2
|
||||
#define NUKE_SYNDICATE_BASE 3
|
||||
#define STATION_DESTROYED_NUKE 4
|
||||
#define STATION_EVACUATED 5
|
||||
#define BLOB_WIN 8
|
||||
#define BLOB_NUKE 9
|
||||
#define BLOB_DESTROYED 10
|
||||
|
||||
@@ -176,6 +176,15 @@
|
||||
#define DISGUST_LEVEL_VERYGROSS 50
|
||||
#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
|
||||
#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 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_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
|
||||
|
||||
|
||||
@@ -8,6 +8,5 @@
|
||||
GLOBAL_LIST_INIT(blacklisted_pool_reagents, list(
|
||||
/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/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.
|
||||
))
|
||||
|
||||
+28
-4
@@ -1,4 +1,28 @@
|
||||
#define UI_INTERACTIVE 2 // Green/Interactive
|
||||
#define UI_UPDATE 1 // Orange/Updates Only
|
||||
#define UI_DISABLED 0 // Red/Disabled
|
||||
#define UI_CLOSE -1 // Closed
|
||||
/// Green eye; fully interactive
|
||||
#define UI_INTERACTIVE 2
|
||||
/// Orange eye; updates but is not interactive
|
||||
#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))
|
||||
|
||||
@@ -201,9 +201,18 @@
|
||||
WRITE_LOG(log, "Starting up round ID [GLOB.round_id].\n-------------------------")
|
||||
|
||||
/* ui logging */
|
||||
|
||||
/proc/log_tgui(text)
|
||||
WRITE_LOG(GLOB.tgui_log, text)
|
||||
/proc/log_tgui(user_or_client, text)
|
||||
var/entry = ""
|
||||
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. */
|
||||
/proc/shutdown_logging()
|
||||
|
||||
@@ -85,9 +85,6 @@ GLOBAL_VAR_INIT(cmp_field, "name")
|
||||
/proc/cmp_advdisease_resistance_asc(datum/disease/advance/A, datum/disease/advance/B)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
var/a_sign = num2sign(initial(A.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
|
||||
else
|
||||
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]")
|
||||
@@ -264,6 +264,13 @@
|
||||
if(!findname(.))
|
||||
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)
|
||||
for(var/i in 1 to attempts_to_find_unique_name)
|
||||
. = capitalize(pick(GLOB.moth_first)) + " " + capitalize(pick(GLOB.moth_last))
|
||||
|
||||
@@ -4,6 +4,12 @@
|
||||
else
|
||||
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()
|
||||
return "[pick(GLOB.plasmaman_names)] \Roman[rand(1,99)]"
|
||||
|
||||
|
||||
@@ -776,6 +776,10 @@ GLOBAL_LIST_INIT(binary, list("0","1"))
|
||||
else
|
||||
return "[number]\th"
|
||||
|
||||
|
||||
/proc/random_capital_letter()
|
||||
return uppertext(pick(GLOB.alphabet))
|
||||
|
||||
/proc/unintelligize(message)
|
||||
var/regex/word_boundaries = regex(@"\b[\S]+\b", "g")
|
||||
var/prefix = message[1]
|
||||
|
||||
@@ -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_last, world.file2list("strings/names/moth_last.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(nightmare_names, world.file2list("strings/names/nightmare.txt"))
|
||||
GLOBAL_LIST_INIT(megacarp_first_names, world.file2list("strings/names/megacarp1.txt"))
|
||||
|
||||
@@ -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."
|
||||
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
|
||||
/obj/screen/alert/hacked
|
||||
name = "Hacked"
|
||||
|
||||
@@ -775,12 +775,14 @@ SUBSYSTEM_DEF(shuttle)
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "ShuttleManipulator", name, 800, 600, master_ui, state)
|
||||
ui.open()
|
||||
/datum/controller/subsystem/shuttle/ui_state(mob/user)
|
||||
return GLOB.admin_state
|
||||
|
||||
/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)
|
||||
var/list/data = list()
|
||||
|
||||
@@ -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)
|
||||
name = "tgui"
|
||||
wait = 9
|
||||
@@ -5,33 +14,338 @@ SUBSYSTEM_DEF(tgui)
|
||||
priority = FIRE_PRIORITY_TGUI
|
||||
runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT
|
||||
|
||||
var/list/currentrun = list()
|
||||
var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key.
|
||||
var/list/processing_uis = list() // A list of processing UIs, ungrouped.
|
||||
var/basehtml // The HTML base used for all UIs.
|
||||
/// A list of UIs scheduled to process
|
||||
var/list/current_run = list()
|
||||
/// A list of open 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()
|
||||
basehtml = file2text('tgui/packages/tgui/public/tgui.html')
|
||||
basehtml = file2text('tgui/packages/tgui/public/tgui.html')
|
||||
|
||||
/datum/controller/subsystem/tgui/Shutdown()
|
||||
close_all_uis()
|
||||
|
||||
/datum/controller/subsystem/tgui/stat_entry()
|
||||
..("P:[processing_uis.len]")
|
||||
..("P:[open_uis.len]")
|
||||
|
||||
/datum/controller/subsystem/tgui/fire(resumed = 0)
|
||||
if (!resumed)
|
||||
src.currentrun = processing_uis.Copy()
|
||||
//cache for sanic speed (lists are references anyways)
|
||||
var/list/currentrun = src.currentrun
|
||||
|
||||
while(currentrun.len)
|
||||
var/datum/tgui/ui = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
if(!resumed)
|
||||
src.current_run = open_uis.Copy()
|
||||
// Cache for sanic speed (lists are references anyways)
|
||||
var/list/current_run = src.current_run
|
||||
while(current_run.len)
|
||||
var/datum/tgui/ui = current_run[current_run.len]
|
||||
current_run.len--
|
||||
// TODO: Move user/src_object check to process()
|
||||
if(ui && ui.user && ui.src_object)
|
||||
ui.process()
|
||||
else
|
||||
processing_uis.Remove(ui)
|
||||
if (MC_TICK_CHECK)
|
||||
open_uis.Remove(ui)
|
||||
if(MC_TICK_CHECK)
|
||||
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
@@ -431,25 +431,31 @@
|
||||
if(!owner)
|
||||
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()
|
||||
|
||||
if (include_zeroth && devillaws && devillaws.len)
|
||||
for(var/i in devillaws)
|
||||
data += "[show_numbers ? "666:" : ""] <font color='#cc5500'>[i]</font>"
|
||||
if (include_zeroth && devillaws)
|
||||
for(var/law in devillaws)
|
||||
data += "[show_numbers ? "666:" : ""] [render_html ? "<font color='#cc5500'>[law]</font>" : law]"
|
||||
|
||||
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)
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
data += "[show_numbers ? "[num]:" : ""] <font color='#660000'>[law]</font>"
|
||||
data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "<font color='#660000'>[law]</font>" : law]"
|
||||
|
||||
for(var/law in ion)
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
data += "[show_numbers ? "[num]:" : ""] <font color='#547DFE'>[law]</font>"
|
||||
data += "[show_numbers ? "[ionnum()]:" : ""] [render_html ? "<font color='#547DFE'>[law]</font>" : law]"
|
||||
|
||||
var/number = 1
|
||||
for(var/law in inherent)
|
||||
@@ -459,6 +465,7 @@
|
||||
|
||||
for(var/law in supplied)
|
||||
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++
|
||||
return data
|
||||
|
||||
|
||||
@@ -203,9 +203,9 @@
|
||||
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()
|
||||
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 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
|
||||
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
|
||||
@@ -216,7 +216,7 @@
|
||||
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
|
||||
|
||||
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
|
||||
*/
|
||||
@@ -323,9 +323,12 @@
|
||||
if(user == parent)
|
||||
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
|
||||
/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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/datum/component/personal_crafting/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
cur_category = categories[1]
|
||||
if(islist(categories[cur_category]))
|
||||
@@ -333,7 +336,7 @@
|
||||
cur_subcategory = subcats[1]
|
||||
else
|
||||
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()
|
||||
|
||||
/datum/component/personal_crafting/ui_data(mob/user)
|
||||
@@ -413,13 +416,8 @@
|
||||
display_compact = !display_compact
|
||||
. = TRUE
|
||||
if("set_category")
|
||||
if(!isnull(params["category"]))
|
||||
cur_category = params["category"]
|
||||
if(!isnull(params["subcategory"]))
|
||||
if(params["subcategory"] == "0")
|
||||
cur_subcategory = ""
|
||||
else
|
||||
cur_subcategory = params["subcategory"]
|
||||
cur_category = params["category"]
|
||||
cur_subcategory = params["subcategory"] || ""
|
||||
. = TRUE
|
||||
|
||||
/datum/component/personal_crafting/proc/build_recipe_data(datum/crafting_recipe/R)
|
||||
|
||||
@@ -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>")
|
||||
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)
|
||||
to_chat(user, "<span class='hear'>[parent] fizzles weakly.</span>")
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
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 = new(user, src, "Gps")
|
||||
ui.open()
|
||||
|
||||
ui.set_autoupdate(state = updating)
|
||||
ui.set_autoupdate(updating)
|
||||
|
||||
/datum/component/gps/item/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
@@ -307,6 +307,10 @@
|
||||
|
||||
|
||||
/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)
|
||||
if(NUTRITION_LEVEL_FULL to INFINITY)
|
||||
add_event(null, "nutrition", /datum/mood_event/fat)
|
||||
@@ -321,6 +325,22 @@
|
||||
if(0 to NUTRITION_LEVEL_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)
|
||||
if(A.outdoors) //if we're outside, we don't care.
|
||||
clear_event(null, "area_beauty")
|
||||
|
||||
@@ -29,10 +29,18 @@
|
||||
if(strength > RAD_MINIMUM_CONTAMINATION)
|
||||
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)
|
||||
|
||||
/datum/component/radioactive/Destroy()
|
||||
STOP_PROCESSING(SSradiation, src)
|
||||
var/atom/movable/master = parent
|
||||
master.remove_filter("rad_glow")
|
||||
return ..()
|
||||
|
||||
/datum/component/radioactive/process()
|
||||
@@ -46,6 +54,13 @@
|
||||
if(strength <= RAD_BACKGROUND_RADIATION)
|
||||
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)
|
||||
if(!i_am_original)
|
||||
return
|
||||
|
||||
@@ -143,23 +143,19 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
// an unlocked uplink blocks also opening the PDA or headset menu
|
||||
return COMPONENT_NO_INTERACT
|
||||
|
||||
/datum/component/uplink/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
|
||||
/datum/component/uplink/ui_state(mob/user)
|
||||
return GLOB.inventory_state
|
||||
|
||||
/datum/component/uplink/ui_interact(mob/user, datum/tgui/ui)
|
||||
active = TRUE
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, 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,
|
||||
// and never is updated outside of user input.
|
||||
ui.set_autoupdate(FALSE)
|
||||
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)
|
||||
if(!user.mind)
|
||||
return
|
||||
@@ -187,8 +183,18 @@ GLOBAL_LIST_EMPTY(uplinks)
|
||||
is_inaccessible = FALSE
|
||||
if(is_inaccessible)
|
||||
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)
|
||||
continue
|
||||
*/
|
||||
cat["items"] += list(list(
|
||||
"name" = I.name,
|
||||
"cost" = I.cost,
|
||||
|
||||
+42
-6
@@ -1,13 +1,13 @@
|
||||
|
||||
//TODO: someone please get rid of this shit
|
||||
/datum/datacore
|
||||
var/medical[] = list()
|
||||
var/list/medical = list()
|
||||
var/medicalPrintCount = 0
|
||||
var/general[] = list()
|
||||
var/security[] = list()
|
||||
var/list/general = list()
|
||||
var/list/security = list()
|
||||
var/securityPrintCount = 0
|
||||
var/securityCrimeCounter = 0
|
||||
//This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
|
||||
var/locked[] = list()
|
||||
///This list tracks characters spawned in the world and cannot be modified in-game. Currently referenced by respawn_character().
|
||||
var/list/locked = list()
|
||||
|
||||
/datum/data
|
||||
var/name = "data"
|
||||
@@ -91,6 +91,42 @@
|
||||
if(foundrecord)
|
||||
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)
|
||||
var/list/heads = list()
|
||||
var/list/sec = list()
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
destination.dna.skin_tone_override = skin_tone_override
|
||||
destination.dna.features = features.Copy()
|
||||
destination.set_species(species.type, icon_update=0)
|
||||
destination.dna.species.say_mod = species.say_mod
|
||||
destination.dna.real_name = real_name
|
||||
destination.dna.nameless = nameless
|
||||
destination.dna.custom_species = custom_species
|
||||
@@ -74,6 +75,7 @@
|
||||
new_dna.skin_tone_override = skin_tone_override
|
||||
new_dna.features = features.Copy()
|
||||
new_dna.species = new species.type
|
||||
new_dna.species.say_mod = species.say_mod
|
||||
new_dna.real_name = real_name
|
||||
new_dna.nameless = nameless
|
||||
new_dna.custom_species = custom_species
|
||||
|
||||
+119
-5
@@ -32,20 +32,29 @@
|
||||
var/datum/action/innate/end_holocall/hangup //hangup action
|
||||
|
||||
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`
|
||||
/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
|
||||
user = caller
|
||||
calling_pad.outgoing_call = src
|
||||
calling_holopad = calling_pad
|
||||
head_call = elevated_access
|
||||
dialed_holopads = list()
|
||||
|
||||
for(var/I in callees)
|
||||
var/obj/machinery/holopad/H = I
|
||||
if(!QDELETED(H) && H.is_operational())
|
||||
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)
|
||||
|
||||
if(!dialed_holopads.len)
|
||||
@@ -79,6 +88,7 @@
|
||||
dialed_holopads.Cut()
|
||||
|
||||
if(calling_holopad)
|
||||
calling_holopad.calling = FALSE
|
||||
calling_holopad.outgoing_call = null
|
||||
calling_holopad.SetLightsAndPower()
|
||||
calling_holopad = null
|
||||
@@ -145,6 +155,7 @@
|
||||
if(!Check())
|
||||
return
|
||||
|
||||
calling_holopad.calling = FALSE
|
||||
hologram = H.activate_holo(user)
|
||||
hologram.HC = src
|
||||
|
||||
@@ -160,6 +171,8 @@
|
||||
|
||||
hangup = new(eye, src)
|
||||
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
|
||||
/datum/holocall/proc/Check()
|
||||
@@ -178,7 +191,6 @@
|
||||
. = world.time < (call_start_time + HOLOPAD_MAX_DIAL_TIME)
|
||||
if(!.)
|
||||
calling_holopad.say("No answer received.")
|
||||
calling_holopad.temp = ""
|
||||
|
||||
if(!.)
|
||||
testing("Holocall Check fail")
|
||||
@@ -241,10 +253,10 @@
|
||||
record.caller_image = holodiskOriginal.record.caller_image
|
||||
record.entries = holodiskOriginal.record.entries.Copy()
|
||||
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
|
||||
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()
|
||||
@@ -331,6 +343,21 @@
|
||||
DELAY 20"}
|
||||
|
||||
/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
|
||||
|
||||
/datum/preset_holoimage/researcher
|
||||
@@ -350,3 +377,90 @@
|
||||
|
||||
/datum/preset_holoimage/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"}
|
||||
|
||||
@@ -19,6 +19,27 @@
|
||||
description = "<span class='boldwarning'>I'm starving!</span>\n"
|
||||
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
|
||||
/datum/mood_event/gross
|
||||
description = "<span class='warning'>I saw something gross.</span>\n"
|
||||
|
||||
@@ -105,7 +105,6 @@
|
||||
// modify the ignored_things list in __HELPERS/radiation.dm instead
|
||||
var/static/list/blacklisted = typecacheof(list(
|
||||
/turf,
|
||||
/mob,
|
||||
/obj/structure/cable,
|
||||
/obj/machinery/atmospherics,
|
||||
/obj/item/ammo_casing,
|
||||
|
||||
@@ -14,11 +14,14 @@
|
||||
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/datum/skill_holder/ui_state(mob/user)
|
||||
return GLOB.always_state
|
||||
|
||||
/datum/skill_holder/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "SkillPanel", "[owner.name]'s Skills", 620, 580, master_ui, state)
|
||||
ui.set_autoupdate(FALSE) // This UI is only ever opened by one person, and never is updated outside of user input.
|
||||
ui = new(user, src, "SkillPanel", "[owner.name]'s Skills")
|
||||
ui.set_autoupdate(FALSE)
|
||||
ui.open()
|
||||
else if(need_static_data_update)
|
||||
update_static_data(user)
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
qdel(src)
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/datum/spawners_menu/ui_state(mob/user)
|
||||
return GLOB.observer_state
|
||||
|
||||
/datum/spawners_menu/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "SpawnersMenu", "Spawners Menu", 700, 600, master_ui, state)
|
||||
ui = new(user, src, "SpawnersMenu")
|
||||
ui.open()
|
||||
|
||||
/datum/spawners_menu/ui_data(mob/user)
|
||||
@@ -42,11 +45,15 @@
|
||||
if(..())
|
||||
return
|
||||
|
||||
var/spawner_ref = pick(GLOB.mob_spawners[params["name"]])
|
||||
var/obj/effect/mob_spawn/MS = locate(spawner_ref) in GLOB.poi_list
|
||||
if(!MS)
|
||||
var/group_name = params["name"]
|
||||
if(!group_name || !(group_name in GLOB.mob_spawners))
|
||||
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
|
||||
|
||||
switch(action)
|
||||
if("jump")
|
||||
if(MS)
|
||||
@@ -55,4 +62,4 @@
|
||||
if("spawn")
|
||||
if(MS)
|
||||
MS.attack_ghost(owner)
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
|
||||
@@ -97,6 +97,12 @@
|
||||
/datum/wires/proc/get_wire(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)
|
||||
if(assemblies[color])
|
||||
return assemblies[color]
|
||||
@@ -117,7 +123,7 @@
|
||||
return TRUE
|
||||
|
||||
/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)
|
||||
return is_dud(get_wire(color))
|
||||
@@ -197,6 +203,7 @@
|
||||
S.forceMove(holder.drop_location())
|
||||
return S
|
||||
|
||||
/// Called from [/atom/proc/emp_act]
|
||||
/datum/wires/proc/emp_pulse()
|
||||
var/list/possible_wires = shuffle(wires)
|
||||
var/remaining_pulses = MAXIMUM_EMP_WIRES
|
||||
@@ -239,11 +246,13 @@
|
||||
return ..()
|
||||
return UI_CLOSE
|
||||
|
||||
/datum/wires/ui_interact(mob/user, ui_key = "wires", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/datum/wires/ui_state(mob/user)
|
||||
return GLOB.physical_state
|
||||
|
||||
/datum/wires/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/datum/wires/ui_data(mob/user)
|
||||
|
||||
@@ -53,11 +53,10 @@
|
||||
|
||||
/datum/wires/airlock/interactable(mob/user)
|
||||
var/obj/machinery/door/airlock/A = holder
|
||||
if(!A.panel_open)
|
||||
return FALSE
|
||||
if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100))
|
||||
return FALSE
|
||||
return TRUE
|
||||
if(A.panel_open)
|
||||
return TRUE
|
||||
|
||||
/datum/wires/airlock/get_status()
|
||||
var/obj/machinery/door/airlock/A = holder
|
||||
@@ -115,10 +114,7 @@
|
||||
A.aiControlDisabled = -1
|
||||
if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks.
|
||||
if(!A.secondsElectrified)
|
||||
A.set_electrified(30)
|
||||
if(usr)
|
||||
LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]"))
|
||||
log_combat(usr, A, "electrified")
|
||||
A.set_electrified(30, usr)
|
||||
if(WIRE_SAFETY)
|
||||
A.safe = !A.safe
|
||||
if(!A.density)
|
||||
@@ -135,21 +131,17 @@
|
||||
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
|
||||
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
|
||||
A.regainMainPower()
|
||||
if(usr)
|
||||
A.shock(usr, 50)
|
||||
else
|
||||
A.loseMainPower()
|
||||
if(usr)
|
||||
A.shock(usr, 50)
|
||||
if(isliving(usr))
|
||||
A.shock(usr, 50)
|
||||
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))
|
||||
A.regainBackupPower()
|
||||
if(usr)
|
||||
A.shock(usr, 50)
|
||||
else
|
||||
A.loseBackupPower()
|
||||
if(usr)
|
||||
A.shock(usr, 50)
|
||||
if(isliving(usr))
|
||||
A.shock(usr, 50)
|
||||
if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing.
|
||||
if(!mend)
|
||||
A.bolt()
|
||||
@@ -170,10 +162,7 @@
|
||||
A.set_electrified(0)
|
||||
else
|
||||
if(A.secondsElectrified != -1)
|
||||
A.set_electrified(-1)
|
||||
if(usr)
|
||||
LAZYADD(A.shockedby, text("\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(usr)]"))
|
||||
log_combat(usr, A, "electrified")
|
||||
A.set_electrified(-1, usr)
|
||||
if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable.
|
||||
A.safe = mend
|
||||
if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable.
|
||||
@@ -184,5 +173,5 @@
|
||||
A.lights = mend
|
||||
A.update_icon()
|
||||
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
|
||||
if(usr)
|
||||
A.shock(usr, 50)
|
||||
if(isliving(usr))
|
||||
A.shock(usr, 50)
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
/// If it's valid territory for gangs/cults to summon
|
||||
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.
|
||||
var/blob_allowed = TRUE
|
||||
/// whether servants can warp into this area from Reebe
|
||||
@@ -572,6 +574,7 @@ GLOBAL_LIST_EMPTY(teleportlocs)
|
||||
power_environ = FALSE
|
||||
always_unpowered = FALSE
|
||||
valid_territory = FALSE
|
||||
valid_malf_hack = FALSE
|
||||
blob_allowed = FALSE
|
||||
addSorted()
|
||||
|
||||
|
||||
+10
-9
@@ -962,15 +962,16 @@
|
||||
if(source != target)
|
||||
target.log_talk(message, message_type, tag="[tag] from [key_name(source)]", log_globally=FALSE)
|
||||
|
||||
/*
|
||||
Proc for attack log creation, because really why not
|
||||
1 argument is the actor performing the action
|
||||
2 argument is the target of the action
|
||||
3 is a verb describing the action (e.g. punched, throwed, kicked, etc.)
|
||||
4 is a tool with which the action was made (usually an item)
|
||||
5 is any additional text, which will be appended to the rest of the log line
|
||||
*/
|
||||
|
||||
/**
|
||||
* Log a combat message in the attack log
|
||||
*
|
||||
* Arguments:
|
||||
* * atom/user - argument is the actor performing the action
|
||||
* * atom/target - argument is the target of the action
|
||||
* * 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)
|
||||
var/ssource = key_name(user)
|
||||
var/starget = key_name(target)
|
||||
|
||||
@@ -201,15 +201,15 @@
|
||||
. = ..()
|
||||
. += "<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, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
|
||||
/obj/machinery/sleeper/ui_state(mob/user)
|
||||
if(controls_inside)
|
||||
return GLOB.notcontained_state
|
||||
return GLOB.default_state
|
||||
|
||||
if(controls_inside && state == GLOB.notcontained_state)
|
||||
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_key, ui, force_open)
|
||||
/obj/machinery/sleeper/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Sleeper", name, 550, 700, master_ui, state)
|
||||
ui = new(user, src, "Sleeper", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/sleeper/process()
|
||||
|
||||
@@ -93,13 +93,10 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
for(var/channel in channels)
|
||||
radio.talk_into(src, message, channel)
|
||||
|
||||
//config stuff
|
||||
|
||||
/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)
|
||||
/obj/machinery/announcement_system/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/obj/machinery/announcement_system/ui_data()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
desc = "A machine used to deposit and withdraw station funds."
|
||||
icon = 'goon/icons/obj/goon_terminals.dmi'
|
||||
idle_power_usage = 100
|
||||
|
||||
var/siphoning = FALSE
|
||||
var/next_warning = 0
|
||||
var/obj/item/radio/radio
|
||||
@@ -38,7 +39,6 @@
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/machinery/computer/bank_machine/process()
|
||||
..()
|
||||
if(siphoning)
|
||||
@@ -51,7 +51,7 @@
|
||||
end_syphon()
|
||||
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
|
||||
D.adjust_money(-200)
|
||||
if(next_warning < world.time && prob(15))
|
||||
@@ -60,17 +60,20 @@
|
||||
radio.talk_into(src, message, radio_channel)
|
||||
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, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/bank_machine/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "BankMachine", name, 320, 165, master_ui, state)
|
||||
ui = new(user, src, "BankMachine", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/bank_machine/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
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["station_name"] = station_name()
|
||||
|
||||
|
||||
@@ -43,10 +43,13 @@
|
||||
table.computer = src
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/operating/ui_state(mob/user)
|
||||
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)
|
||||
ui = new(user, src, ui_key, "OperatingComputer", name, 350, 470, master_ui, state)
|
||||
ui = new(user, src, "OperatingComputer", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/operating/ui_data(mob/user)
|
||||
@@ -153,6 +156,8 @@
|
||||
))
|
||||
return data
|
||||
|
||||
|
||||
|
||||
/obj/machinery/computer/operating/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
name = "\improper AI system integrity restorer"
|
||||
desc = "Used with intelliCards containing nonfunctional AIs to restore them to working order."
|
||||
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_screen = "ai-fixer"
|
||||
light_color = LIGHT_COLOR_PINK
|
||||
ui_x = 370
|
||||
ui_y = 360
|
||||
circuit = /obj/item/circuitboard/computer/aifixer
|
||||
|
||||
var/mob/living/silicon/ai/occupier = null
|
||||
var/active = FALSE
|
||||
|
||||
/obj/machinery/computer/aifixer/attackby(obj/I, mob/user, params)
|
||||
if(occupier && istype(I, /obj/item/screwdriver))
|
||||
@@ -20,64 +19,45 @@
|
||||
else
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
|
||||
/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)
|
||||
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()
|
||||
|
||||
var/dat = ""
|
||||
/obj/machinery/computer/aifixer/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
if (src.occupier)
|
||||
var/laws
|
||||
dat += "<h3>Stored AI: [src.occupier.name]</h3>"
|
||||
dat += "<b>System integrity:</b> [(src.occupier.health+100)/2]%<br>"
|
||||
data["ejectable"] = FALSE
|
||||
data["AI_present"] = FALSE
|
||||
data["error"] = null
|
||||
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)
|
||||
laws += "<b>0:</b> [src.occupier.laws.zeroth]<BR>"
|
||||
return data
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.hacked.len, index++)
|
||||
var/law = src.occupier.laws.hacked[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
/obj/machinery/computer/aifixer/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!occupier)
|
||||
active = FALSE
|
||||
|
||||
for (var/index = 1, index <= src.occupier.laws.ion.len, index++)
|
||||
var/law = src.occupier.laws.ion[index]
|
||||
if (length(law) > 0)
|
||||
var/num = ionnum()
|
||||
laws += "<b>[num]:</b> [law]<BR>"
|
||||
|
||||
var/number = 1
|
||||
for (var/index = 1, index <= src.occupier.laws.inherent.len, index++)
|
||||
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
|
||||
switch(action)
|
||||
if("PRG_beginReconstruction")
|
||||
if(occupier?.health < 100)
|
||||
to_chat(usr, "<span class='notice'>Reconstruction in progress. This will take several minutes.</span>")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 25, FALSE)
|
||||
active = TRUE
|
||||
occupier.notify_ghost_cloning("Your core files are being restored!", source = src)
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/computer/aifixer/proc/Fix()
|
||||
use_power(1000)
|
||||
@@ -97,17 +77,6 @@
|
||||
active = Fix()
|
||||
if(oldstat != occupier.stat)
|
||||
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()
|
||||
. = ..()
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
desc = "Used to remotely control the flow of power to different parts of the station."
|
||||
icon_screen = "solar"
|
||||
icon_keyboard = "power_key"
|
||||
req_access = list(ACCESS_ENGINE)
|
||||
req_access = list(ACCESS_CE)
|
||||
circuit = /obj/item/circuitboard/computer/apc_control
|
||||
light_color = LIGHT_COLOR_YELLOW
|
||||
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/list/result_filters //For sorting the results
|
||||
var/checking_logs = 0
|
||||
var/should_log = TRUE
|
||||
var/restoring = FALSE
|
||||
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()
|
||||
if(operator && (!operator.Adjacent(src) || stat))
|
||||
@@ -23,8 +23,8 @@
|
||||
if(active_apc)
|
||||
if(!active_apc.locked)
|
||||
active_apc.say("Remote access canceled. Interface locked.")
|
||||
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0)
|
||||
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE)
|
||||
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE)
|
||||
active_apc.locked = TRUE
|
||||
active_apc.update_icon()
|
||||
active_apc.remote_control = null
|
||||
@@ -34,171 +34,163 @@
|
||||
if(!IsAdminGhost(user))
|
||||
to_chat(user,"<span class='warning'>[src] does not support AI control.</span>") //You already have APC access, cheater!
|
||||
return
|
||||
..(user)
|
||||
..()
|
||||
|
||||
/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
|
||||
|
||||
/obj/machinery/computer/apc_control/ui_interact(mob/living/user)
|
||||
. = ..()
|
||||
var/dat
|
||||
if(authenticated)
|
||||
if(!checking_logs)
|
||||
dat += "Logged in as [auth_id].<br><br>"
|
||||
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/ui_interact(mob/user, datum/tgui/ui)
|
||||
operator = user
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ApcControl")
|
||||
ui.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(..())
|
||||
return
|
||||
if(!usr || !usr.canUseTopic(src) || stat || QDELETED(src))
|
||||
return
|
||||
if(href_list["authenticate"])
|
||||
var/obj/item/card/id/ID = usr.get_idcard(TRUE)
|
||||
if(ID && istype(ID))
|
||||
if(check_access(ID))
|
||||
switch(action)
|
||||
if("log-in")
|
||||
if(obj_flags & EMAGGED)
|
||||
authenticated = TRUE
|
||||
auth_id = "[ID.registered_name] ([ID.assignment])"
|
||||
log_activity("logged in")
|
||||
if(href_list["log_out"])
|
||||
log_activity("logged out")
|
||||
authenticated = FALSE
|
||||
auth_id = "\[NULL\]"
|
||||
if(href_list["restore_logging"])
|
||||
to_chat(usr, "<span class='robot notice'>[icon2html(src, usr)] Logging functionality restored from backup data.</span>")
|
||||
obj_flags &= ~EMAGGED
|
||||
LAZYADD(logs, "<b>-=- Logging restored to full functionality at this point -=-</b>")
|
||||
if(href_list["access_apc"])
|
||||
playsound(src, "terminal_type", 50, 0)
|
||||
var/obj/machinery/power/apc/APC = locate(href_list["access_apc"]) in GLOB.apcs_list
|
||||
if(!APC || APC.aidisabled || APC.panel_open || QDELETED(APC))
|
||||
to_chat(usr, "<span class='robot danger'>[icon2html(src, usr)] APC does not return interface request. Remote access may be disabled.</span>")
|
||||
return
|
||||
if(active_apc)
|
||||
to_chat(usr, "<span class='robot danger'>[icon2html(src, usr)] Disconnected from [active_apc].</span>")
|
||||
active_apc.say("Remote access canceled. Interface locked.")
|
||||
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, 0)
|
||||
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
active_apc.locked = TRUE
|
||||
active_apc.update_icon()
|
||||
active_apc.remote_control = null
|
||||
active_apc = null
|
||||
to_chat(usr, "<span class='robot notice'>[icon2html(src, usr)] Connected to APC in [get_area_name(APC.area, TRUE)]. Interface request sent.</span>")
|
||||
log_activity("remotely accessed APC in [get_area_name(APC.area, TRUE)]")
|
||||
APC.remote_control = src
|
||||
APC.ui_interact(usr)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
|
||||
log_game("[key_name(usr)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
|
||||
if(APC.locked)
|
||||
APC.say("Remote access detected. Interface unlocked.")
|
||||
playsound(APC, 'sound/machines/boltsup.ogg', 25, 0)
|
||||
playsound(APC, 'sound/machines/terminal_alert.ogg', 50, 0)
|
||||
APC.locked = FALSE
|
||||
APC.update_icon()
|
||||
active_apc = APC
|
||||
if(href_list["name_filter"])
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
var/new_filter = stripped_input(usr, "What name are you looking for?", name)
|
||||
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src))
|
||||
return
|
||||
log_activity("changed name filter to \"[new_filter]\"")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
result_filters["Name"] = new_filter
|
||||
if(href_list["above_filter"])
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (greater than).", name) as null|num
|
||||
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src))
|
||||
return
|
||||
log_activity("changed greater than charge filter to \"[new_filter]\"")
|
||||
if(new_filter)
|
||||
new_filter = clamp(new_filter, 0, 100)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
result_filters["Charge Above"] = new_filter
|
||||
if(href_list["below_filter"])
|
||||
playsound(src, 'sound/machines/terminal_prompt.ogg', 50, 0)
|
||||
var/new_filter = input(usr, "Enter a percentage from 1-100 to sort by (lesser than).", name) as null|num
|
||||
if(!src || !usr || !usr.canUseTopic(src) || stat || QDELETED(src))
|
||||
return
|
||||
log_activity("changed lesser than charge filter to \"[new_filter]\"")
|
||||
if(new_filter)
|
||||
new_filter = clamp(new_filter, 0, 100)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
result_filters["Charge Below"] = new_filter
|
||||
if(href_list["access_filter"])
|
||||
if(isnull(result_filters["Responsive"]))
|
||||
result_filters["Responsive"] = 1
|
||||
log_activity("sorted by non-responsive APCs only")
|
||||
else
|
||||
result_filters["Responsive"] = !result_filters["Responsive"]
|
||||
log_activity("sorted by all APCs")
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, 0)
|
||||
if(href_list["check_logs"])
|
||||
checking_logs = TRUE
|
||||
log_activity("checked logs")
|
||||
if(href_list["check_apcs"])
|
||||
checking_logs = FALSE
|
||||
log_activity("checked APCs")
|
||||
if(href_list["clear_logs"])
|
||||
logs = list()
|
||||
ui_interact(usr) //Refresh the UI after a filter changes
|
||||
auth_id = "Unknown (Unknown):"
|
||||
log_activity("[auth_id] logged in to the terminal")
|
||||
return
|
||||
var/obj/item/card/id/ID = operator.get_idcard(TRUE)
|
||||
if(ID && istype(ID))
|
||||
if(check_access(ID))
|
||||
authenticated = TRUE
|
||||
auth_id = "[ID.registered_name] ([ID.assignment]):"
|
||||
log_activity("[auth_id] logged in to the terminal")
|
||||
playsound(src, 'sound/machines/terminal_on.ogg', 50, FALSE)
|
||||
else
|
||||
auth_id = "[ID.registered_name] ([ID.assignment]):"
|
||||
log_activity("[auth_id] attempted to log into the terminal")
|
||||
return
|
||||
auth_id = "Unknown (Unknown):"
|
||||
log_activity("[auth_id] attempted to log into the terminal")
|
||||
if("log-out")
|
||||
log_activity("[auth_id] logged out of the terminal")
|
||||
playsound(src, 'sound/machines/terminal_off.ogg', 50, FALSE)
|
||||
authenticated = FALSE
|
||||
auth_id = "\[NULL\]"
|
||||
if("toggle-logs")
|
||||
should_log = !should_log
|
||||
log_game("[key_name(operator)] set the logs of [src] in [AREACOORD(src)] [should_log ? "On" : "Off"]")
|
||||
if("restore-console")
|
||||
restoring = TRUE
|
||||
addtimer(CALLBACK(src, .proc/restore_comp), rand(3,5) * 9)
|
||||
if("access-apc")
|
||||
var/ref = params["ref"]
|
||||
playsound(src, "terminal_type", 50, FALSE)
|
||||
var/obj/machinery/power/apc/APC = locate(ref) in GLOB.apcs_list
|
||||
if(!APC)
|
||||
return
|
||||
if(active_apc)
|
||||
to_chat(operator, "<span class='robot danger'>[icon2html(src, auth_id)] Disconnected from [active_apc].</span>")
|
||||
active_apc.say("Remote access canceled. Interface locked.")
|
||||
playsound(active_apc, 'sound/machines/boltsdown.ogg', 25, FALSE)
|
||||
playsound(active_apc, 'sound/machines/terminal_alert.ogg', 50, FALSE)
|
||||
active_apc.locked = TRUE
|
||||
active_apc.update_icon()
|
||||
active_apc.remote_control = null
|
||||
active_apc = null
|
||||
APC.remote_control = src
|
||||
APC.ui_interact(operator)
|
||||
playsound(src, 'sound/machines/terminal_prompt_confirm.ogg', 50, FALSE)
|
||||
log_game("[key_name(operator)] remotely accessed [APC] from [src] at [AREACOORD(src)].")
|
||||
log_activity("[auth_id] remotely accessed APC in [get_area_name(APC.area, TRUE)]")
|
||||
if(APC.locked)
|
||||
APC.say("Remote access detected. Interface unlocked.")
|
||||
playsound(APC, 'sound/machines/boltsup.ogg', 25, FALSE)
|
||||
playsound(APC, 'sound/machines/terminal_alert.ogg', 50, FALSE)
|
||||
APC.locked = FALSE
|
||||
APC.update_icon()
|
||||
active_apc = APC
|
||||
if("check-logs")
|
||||
log_activity("Checked Logs")
|
||||
if("check-apcs")
|
||||
log_activity("Checked APCs")
|
||||
if("toggle-minor")
|
||||
var/ref = params["ref"]
|
||||
var/type = params["type"]
|
||||
var/value = params["value"]
|
||||
var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
|
||||
if(!target)
|
||||
return
|
||||
target.vars[type] = target.setsubsystem(text2num(value))
|
||||
target.update_icon()
|
||||
target.update()
|
||||
var/setTo = ""
|
||||
switch(target.vars[type])
|
||||
if(0)
|
||||
setTo = "Off"
|
||||
if(1)
|
||||
setTo = "Auto Off"
|
||||
if(2)
|
||||
setTo = "On"
|
||||
if(3)
|
||||
setTo = "Auto On"
|
||||
log_activity("Set APC [target.area.name] [type] to [setTo]")
|
||||
log_game("[key_name(operator)] Set APC [target.area.name] [type] to [setTo]]")
|
||||
if("breaker")
|
||||
var/ref = params["ref"]
|
||||
var/obj/machinery/power/apc/target = locate(ref) in GLOB.apcs_list
|
||||
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)
|
||||
. = ..()
|
||||
if(!authenticated)
|
||||
to_chat(user, "<span class='warning'>You bypass [src]'s access requirements using your emag.</span>")
|
||||
authenticated = TRUE
|
||||
log_activity("logged in")
|
||||
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
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
log_game("[key_name(user)] emagged [src] at [AREACOORD(src)]")
|
||||
playsound(src, "sparks", 50, TRUE)
|
||||
|
||||
/obj/machinery/computer/apc_control/proc/log_activity(log_text)
|
||||
var/op_string = operator && !(obj_flags & EMAGGED) ? operator : "\[NULL OPERATOR\]"
|
||||
LAZYADD(logs, "<b>([STATION_TIME_TIMESTAMP("hh:mm:ss", world.time)])</b> [op_string] [log_text]")
|
||||
if(!should_log)
|
||||
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()
|
||||
for(var/obj/machinery/computer/apc_control/A in range(1, src))
|
||||
|
||||
@@ -19,11 +19,10 @@
|
||||
SSradio.remove_object(src, receive_frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/atmos_alert/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)
|
||||
/obj/machinery/computer/atmos_alert/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AtmosAlertConsole", name, 350, 300, master_ui, state)
|
||||
ui = new(user, src, "AtmosAlertConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/atmos_alert/ui_data(mob/user)
|
||||
@@ -45,11 +44,11 @@
|
||||
if("clear")
|
||||
var/zone = params["zone"]
|
||||
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
|
||||
. = TRUE
|
||||
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
|
||||
. = TRUE
|
||||
update_icon()
|
||||
|
||||
@@ -91,8 +91,6 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
icon_screen = "tank"
|
||||
icon_keyboard = "atmos_key"
|
||||
circuit = /obj/item/circuitboard/computer/atmos_control
|
||||
ui_x = 400
|
||||
ui_y = 925
|
||||
|
||||
var/frequency = FREQ_ATMOS_STORAGE
|
||||
var/list/sensors = list(
|
||||
@@ -123,11 +121,10 @@ GLOBAL_LIST_EMPTY(atmos_air_controllers)
|
||||
SSradio.remove_object(src, frequency)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/atmos_control/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)
|
||||
/obj/machinery/computer/atmos_control/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/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)
|
||||
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)
|
||||
var/list/data = ..()
|
||||
data["tank"] = TRUE
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
icon_keyboard = "security_key"
|
||||
circuit = /obj/item/circuitboard/computer/security
|
||||
light_color = LIGHT_COLOR_RED
|
||||
ui_x = 870
|
||||
ui_y = 708
|
||||
|
||||
var/list/network = list("ss13")
|
||||
var/obj/machinery/camera/active_camera
|
||||
@@ -55,11 +53,9 @@
|
||||
network -= i
|
||||
network += "[idnum][i]"
|
||||
|
||||
/obj/machinery/computer/security/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/security/ui_interact(mob/user, datum/tgui/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
|
||||
if(!active_camera?.can_use())
|
||||
show_camera_static()
|
||||
@@ -76,10 +72,11 @@
|
||||
use_power(active_power_usage)
|
||||
// Register map objects
|
||||
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)
|
||||
// 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()
|
||||
|
||||
/obj/machinery/computer/security/ui_data()
|
||||
|
||||
@@ -76,11 +76,10 @@ GLOBAL_DATUM_INIT(crewmonitor, /datum/crewmonitor, new)
|
||||
/datum/crewmonitor/Destroy()
|
||||
return ..()
|
||||
|
||||
/datum/crewmonitor/ui_interact(mob/user, ui_key = "crew", 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)
|
||||
/datum/crewmonitor/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "CrewConsole", "crew monitor", 800, 600 , master_ui, state)
|
||||
ui = new(user, src, "CrewConsole")
|
||||
ui.open()
|
||||
|
||||
/datum/crewmonitor/proc/show(mob/M, source)
|
||||
|
||||
@@ -220,9 +220,7 @@
|
||||
/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
|
||||
// interface.
|
||||
// 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)
|
||||
|
||||
// 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)
|
||||
ui = new(user, src, ui_key, "DnaConsole", name, 539, 710, master_ui, state)
|
||||
ui = new(user, src, "DnaConsole")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/ui_data(mob/user)
|
||||
|
||||
@@ -53,10 +53,10 @@
|
||||
var/obj/machinery/launchpad/pad = launchpads[number]
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/launchpad/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/obj/machinery/computer/launchpad/ui_data(mob/user)
|
||||
@@ -128,4 +128,4 @@
|
||||
if("pull")
|
||||
teleport(usr, current_pad, FALSE)
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
. = TRUE
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
icon_keyboard = "security_key"
|
||||
req_access = list(ACCESS_ARMORY)
|
||||
circuit = /obj/item/circuitboard/computer/gulag_teleporter_console
|
||||
ui_x = 350
|
||||
ui_y = 295
|
||||
|
||||
var/default_goal = 200
|
||||
var/obj/machinery/gulag_teleporter/teleporter = null
|
||||
@@ -21,11 +19,10 @@
|
||||
. = ..()
|
||||
scan_machinery()
|
||||
|
||||
/obj/machinery/computer/prisoner/gulag_teleporter_computer/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)
|
||||
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/obj/machinery/computer/prisoner/gulag_teleporter_computer/ui_data(mob/user)
|
||||
|
||||
@@ -23,11 +23,10 @@
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/computer/robotics/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)
|
||||
/obj/machinery/computer/robotics/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/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
|
||||
s.set_up(3, TRUE, D)
|
||||
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()
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
GLOB.alert_consoles -= src
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/station_alert/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)
|
||||
/obj/machinery/computer/station_alert/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "StationAlertConsole", name, 325, 500, master_ui, state)
|
||||
ui = new(user, src, "StationAlertConsole", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/station_alert/ui_data(mob/user)
|
||||
@@ -31,6 +30,7 @@
|
||||
data["alarms"][class] = list()
|
||||
for(var/area in alarms[class])
|
||||
data["alarms"][class] += area
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/computer/station_alert/proc/triggerAlarm(class, area/A, O, obj/source)
|
||||
|
||||
@@ -34,11 +34,10 @@
|
||||
break
|
||||
return power_station
|
||||
|
||||
obj/machinery/computer/teleporter/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)
|
||||
/obj/machinery/computer/teleporter/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/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
|
||||
|
||||
|
||||
/obj/machinery/computer/teleporter/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
@@ -92,16 +90,18 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
|
||||
say("Processing hub calibration to target...")
|
||||
calibrating = TRUE
|
||||
power_station.update_icon()
|
||||
spawn(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()
|
||||
addtimer(CALLBACK(src, .proc/finish_calibration), 50 * (3 - power_station.teleporter_hub.accuracy)) //Better parts mean faster calibration
|
||||
. = 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()
|
||||
if(!power_station)
|
||||
return FALSE
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
var/active = FALSE
|
||||
var/list/rangers = list()
|
||||
var/stop = 0
|
||||
var/volume = 70
|
||||
var/datum/track/selection = null
|
||||
|
||||
/obj/machinery/jukebox/disco
|
||||
@@ -51,74 +52,91 @@
|
||||
else
|
||||
icon_state = "[initial(icon_state)]"
|
||||
|
||||
/obj/machinery/jukebox/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
if (!anchored)
|
||||
/obj/machinery/jukebox/ui_status(mob/user)
|
||||
if(!anchored)
|
||||
to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>")
|
||||
return
|
||||
if(!allowed(user))
|
||||
return UI_CLOSE
|
||||
if(!allowed(user) && !isobserver(user))
|
||||
to_chat(user,"<span class='warning'>Error: Access Denied.</span>")
|
||||
user.playsound_local(src,'sound/misc/compiler-failure.ogg', 25, 1)
|
||||
return
|
||||
if(!SSjukeboxes.songs.len)
|
||||
user.playsound_local(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return UI_CLOSE
|
||||
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>")
|
||||
playsound(src,'sound/misc/compiler-failure.ogg', 25, 1)
|
||||
return
|
||||
var/list/dat = list()
|
||||
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()
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 25, TRUE)
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
/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)
|
||||
if(..())
|
||||
/obj/machinery/jukebox/ui_data(mob/user)
|
||||
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
|
||||
add_fingerprint(usr)
|
||||
switch(href_list["action"])
|
||||
|
||||
switch(action)
|
||||
if("toggle")
|
||||
if (QDELETED(src))
|
||||
if(QDELETED(src))
|
||||
return
|
||||
if(!active)
|
||||
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>")
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, TRUE)
|
||||
return
|
||||
if(!istype(selection))
|
||||
to_chat(usr, "<span class='warning'>Error: Severe user incompetence detected.</span>")
|
||||
playsound(src, 'sound/misc/compiler-failure.ogg', 50, 1)
|
||||
return
|
||||
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)
|
||||
activate_music()
|
||||
START_PROCESSING(SSobj, src)
|
||||
return TRUE
|
||||
else
|
||||
stop = 0
|
||||
updateUsrDialog()
|
||||
if("select")
|
||||
return TRUE
|
||||
if("select_track")
|
||||
if(active)
|
||||
to_chat(usr, "<span class='warning'>Error: You cannot change the song until the current one is over.</span>")
|
||||
return
|
||||
|
||||
var/list/available = list()
|
||||
for(var/datum/track/S in SSjukeboxes.songs)
|
||||
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))
|
||||
return
|
||||
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()
|
||||
var/jukeboxslottotake = SSjukeboxes.addjukebox(src, selection, 2)
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
integrity_failure = 0.25
|
||||
damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N
|
||||
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
|
||||
normalspeed = 1
|
||||
explosion_block = 1
|
||||
@@ -298,10 +298,10 @@
|
||||
|
||||
/obj/machinery/door/airlock/Destroy()
|
||||
QDEL_NULL(wires)
|
||||
QDEL_NULL(electronics)
|
||||
if(charge)
|
||||
qdel(charge)
|
||||
charge = null
|
||||
QDEL_NULL(electronics)
|
||||
if (cyclelinkedairlock)
|
||||
if (cyclelinkedairlock.cyclelinkedairlock == src)
|
||||
cyclelinkedairlock.cyclelinkedairlock = null
|
||||
@@ -309,7 +309,7 @@
|
||||
if(id_tag)
|
||||
for(var/obj/machinery/doorButtons/D in GLOB.machines)
|
||||
D.removeMe(src)
|
||||
qdel(note)
|
||||
QDEL_NULL(note)
|
||||
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
|
||||
diag_hud.remove_from_hud(src)
|
||||
return ..()
|
||||
@@ -765,8 +765,8 @@
|
||||
|
||||
/obj/machinery/door/airlock/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(!(issilicon(user) || IsAdminGhost(user)))
|
||||
if(src.isElectrified())
|
||||
if(src.shock(user, 100))
|
||||
if(isElectrified())
|
||||
if(shock(user, 100))
|
||||
return
|
||||
|
||||
if(ishuman(user) && prob(40) && src.density)
|
||||
@@ -790,15 +790,15 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/door/airlock/proc/electrified_loop()
|
||||
while (secondsElectrified > 0)
|
||||
while (secondsElectrified > NOT_ELECTRIFIED)
|
||||
sleep(10)
|
||||
if(QDELETED(src))
|
||||
return
|
||||
|
||||
secondsElectrified -= 1
|
||||
secondsElectrified--
|
||||
updateDialog()
|
||||
// This is to protect against changing to permanent, mid loop.
|
||||
if(secondsElectrified==0)
|
||||
if(secondsElectrified == NOT_ELECTRIFIED)
|
||||
set_electrified(NOT_ELECTRIFIED)
|
||||
else
|
||||
set_electrified(ELECTRIFIED_PERMANENT)
|
||||
@@ -825,8 +825,8 @@
|
||||
|
||||
/obj/machinery/door/airlock/attackby(obj/item/C, mob/user, params)
|
||||
if(!issilicon(user) && !IsAdminGhost(user))
|
||||
if(src.isElectrified())
|
||||
if(src.shock(user, 75))
|
||||
if(isElectrified())
|
||||
if(shock(user, 75))
|
||||
return
|
||||
add_fingerprint(user)
|
||||
|
||||
@@ -839,7 +839,7 @@
|
||||
to_chat(user, "<span class='warning'>You need at least 2 metal sheets to reinforce [src].</span>")
|
||||
return
|
||||
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))
|
||||
return
|
||||
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)
|
||||
|
||||
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
|
||||
return
|
||||
|
||||
@@ -1090,12 +1090,11 @@
|
||||
time_to_open = 50
|
||||
playsound(src, 'sound/machines/airlock_alien_prying.ogg',100,1) //is it aliens or just the CE being a dick?
|
||||
prying_so_hard = TRUE
|
||||
var/result = do_after(user, time_to_open,target = src)
|
||||
prying_so_hard = FALSE
|
||||
if(result)
|
||||
if(do_after(user, time_to_open,target = src))
|
||||
open(2)
|
||||
if(density && !open(2))
|
||||
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)
|
||||
if( operating || welded || locked )
|
||||
@@ -1359,12 +1358,25 @@
|
||||
wires.cut_all()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/door/airlock/proc/set_electrified(seconds)
|
||||
/obj/machinery/door/airlock/proc/set_electrified(seconds, mob/user)
|
||||
secondsElectrified = seconds
|
||||
diag_hud_set_electrified()
|
||||
if(secondsElectrified > 0)
|
||||
if(secondsElectrified > NOT_ELECTRIFIED)
|
||||
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)
|
||||
. = ..()
|
||||
if(obj_integrity < (0.75 * max_integrity))
|
||||
@@ -1438,11 +1450,10 @@
|
||||
else if(istype(note, /obj/item/photo))
|
||||
return "photo"
|
||||
|
||||
/obj/machinery/door/airlock/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)
|
||||
SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/door/airlock/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AiAirlock", name, 500, 390, master_ui, state)
|
||||
ui = new(user, src, "AiAirlock", name)
|
||||
ui.open()
|
||||
return TRUE
|
||||
|
||||
@@ -1450,13 +1461,13 @@
|
||||
var/list/data = list()
|
||||
|
||||
var/list/power = list()
|
||||
power["main"] = src.secondsMainPowerLost ? 0 : 2 // boolean
|
||||
power["main_timeleft"] = src.secondsMainPowerLost
|
||||
power["backup"] = src.secondsBackupPowerLost ? 0 : 2 // boolean
|
||||
power["backup_timeleft"] = src.secondsBackupPowerLost
|
||||
power["main"] = secondsMainPowerLost ? 0 : 2 // boolean
|
||||
power["main_timeleft"] = secondsMainPowerLost
|
||||
power["backup"] = secondsBackupPowerLost ? 0 : 2 // boolean
|
||||
power["backup_timeleft"] = secondsBackupPowerLost
|
||||
data["power"] = power
|
||||
|
||||
data["shock"] = secondsElectrified == 0 ? 2 : 0
|
||||
data["shock"] = secondsElectrified == NOT_ELECTRIFIED ? 2 : 0
|
||||
data["shock_timeleft"] = secondsElectrified
|
||||
data["id_scanner"] = !aiDisabledIdScanner
|
||||
data["emergency"] = emergency // access
|
||||
@@ -1493,14 +1504,14 @@
|
||||
loseMainPower()
|
||||
update_icon()
|
||||
else
|
||||
to_chat(usr, "Main power is already offline.")
|
||||
to_chat(usr, "<span class='warning'>Main power is already offline.</span>")
|
||||
. = TRUE
|
||||
if("disrupt-backup")
|
||||
if(!secondsBackupPowerLost)
|
||||
loseBackupPower()
|
||||
update_icon()
|
||||
else
|
||||
to_chat(usr, "Backup power is already offline.")
|
||||
to_chat(usr, "<span class='warning'>Backup power is already offline.</span>")
|
||||
. = TRUE
|
||||
if("shock-restore")
|
||||
shock_restore(usr)
|
||||
@@ -1529,7 +1540,6 @@
|
||||
. = TRUE
|
||||
if("speed-toggle")
|
||||
normalspeed = !normalspeed
|
||||
|
||||
. = TRUE
|
||||
if("open-close")
|
||||
user_toggle_open(usr)
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
. = ..()
|
||||
. += "<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, \
|
||||
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/electronics/airlock/ui_state(mob/user)
|
||||
return GLOB.hands_state
|
||||
|
||||
/obj/item/electronics/airlock/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "AirlockElectronics", name, 420, 485, master_ui, state)
|
||||
ui = new(user, src, "AirlockElectronics", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/electronics/airlock/ui_static_data(mob/user)
|
||||
|
||||
@@ -140,11 +140,10 @@
|
||||
. = new_time == timer_duration //return 1 on no change
|
||||
timer_duration = new_time
|
||||
|
||||
/obj/machinery/door_timer/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)
|
||||
/obj/machinery/door_timer/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "BrigTimer", name, 300, 138, master_ui, state)
|
||||
ui = new(user, src, "BrigTimer", name)
|
||||
ui.open()
|
||||
|
||||
//icon update function
|
||||
@@ -235,7 +234,7 @@
|
||||
preset_time = PRESET_LONG
|
||||
. = set_timer(preset_time)
|
||||
if(timing)
|
||||
activation_time = REALTIMEOFDAY
|
||||
activation_time = world.time
|
||||
else
|
||||
. = FALSE
|
||||
|
||||
|
||||
@@ -20,18 +20,15 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED) // emagging lets anyone reclaim all the items
|
||||
return
|
||||
req_access = list()
|
||||
obj_flags |= EMAGGED
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/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)
|
||||
/obj/machinery/gulag_item_reclaimer/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "GulagItemReclaimer", name, 300, 400, master_ui, state)
|
||||
ui = new(user, src, "GulagItemReclaimer", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/ui_data(mob/user)
|
||||
@@ -60,20 +57,22 @@
|
||||
mobs += list(mob_info)
|
||||
|
||||
data["mobs"] = mobs
|
||||
|
||||
|
||||
data["can_reclaim"] = can_reclaim
|
||||
|
||||
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)
|
||||
if("release_items")
|
||||
var/mob/M = locate(params["mobref"])
|
||||
if(M == usr || allowed(usr))
|
||||
drop_items(M)
|
||||
else
|
||||
to_chat(usr, "Access denied.")
|
||||
var/mob/living/carbon/human/H = locate(params["mobref"]) in stored_items
|
||||
if(H != usr && !allowed(usr))
|
||||
to_chat(usr, "<span class='warning'>Access denied.</span>")
|
||||
return
|
||||
drop_items(H)
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/gulag_item_reclaimer/proc/drop_items(mob/user)
|
||||
if(!stored_items[user])
|
||||
|
||||
+182
-187
@@ -25,7 +25,6 @@ Possible to do for anyone motivated enough:
|
||||
*/
|
||||
|
||||
GLOBAL_LIST_EMPTY(network_holopads)
|
||||
|
||||
#define HOLOPAD_PASSIVE_POWER_USAGE 1
|
||||
#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."
|
||||
icon_state = "holopad0"
|
||||
layer = LOW_OBJ_LAYER
|
||||
plane = ABOVE_WALL_PLANE
|
||||
plane = FLOOR_PLANE
|
||||
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
|
||||
idle_power_usage = 5
|
||||
active_power_usage = 100
|
||||
max_integrity = 300
|
||||
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
|
||||
var/list/masters //List of living mobs that use the holopad
|
||||
var/list/holorays //Holoray-mob link.
|
||||
var/last_request = 0 //to prevent request spam. ~Carn
|
||||
var/holo_range = 5 // Change to change how far the AI can move away from the holopad before deactivating.
|
||||
var/temp = ""
|
||||
var/list/holo_calls //array of /datum/holocalls
|
||||
var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs
|
||||
var/obj/item/disk/holodisk/disk //Record disk
|
||||
var/replay_mode = FALSE //currently replaying a recording
|
||||
var/loop_mode = FALSE //currently looping a recording
|
||||
var/record_mode = FALSE //currently recording
|
||||
var/record_start = 0 //recording start time
|
||||
var/record_user //user that inititiated the recording
|
||||
var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram
|
||||
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
|
||||
/// List of living mobs that use the holopad
|
||||
var/list/masters
|
||||
/// Holoray-mob link
|
||||
var/list/holorays
|
||||
/// To prevent request spam. ~Carn
|
||||
var/last_request = 0
|
||||
/// Change to change how far the AI can move away from the holopad before deactivating
|
||||
var/holo_range = 5
|
||||
/// Array of /datum/holocalls
|
||||
var/list/holo_calls
|
||||
/// Currently outgoing holocall, do not modify the datums only check and call the public procs
|
||||
var/datum/holocall/outgoing_call
|
||||
/// Record disk
|
||||
var/obj/item/disk/holodisk/disk
|
||||
/// 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/ringing = FALSE
|
||||
var/offset = FALSE
|
||||
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
|
||||
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
|
||||
flags_1 = NODECONSTRUCT_1
|
||||
@@ -121,10 +150,8 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
return ..()
|
||||
|
||||
/obj/machinery/holopad/power_change()
|
||||
if (powered())
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
. = ..()
|
||||
if (!powered())
|
||||
if(replay_mode)
|
||||
replay_stop()
|
||||
if(record_mode)
|
||||
@@ -163,171 +190,150 @@ GLOBAL_LIST_EMPTY(network_holopads)
|
||||
|
||||
if(istype(P,/obj/item/disk/holodisk))
|
||||
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
|
||||
if (!user.transferItemToLoc(P,src))
|
||||
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
|
||||
updateDialog()
|
||||
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
|
||||
|
||||
if(outgoing_call || user.incapacitated() || !is_operational())
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if(temp)
|
||||
dat = temp
|
||||
else
|
||||
if(on_network)
|
||||
dat += "<a href='?src=[REF(src)];AIrequest=1'>Request an AI's presence</a><br>"
|
||||
dat += "<a href='?src=[REF(src)];Holocall=1'>Call another holopad</a><br>"
|
||||
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>"
|
||||
switch(action)
|
||||
if("AIrequest")
|
||||
if(last_request + 200 < world.time)
|
||||
last_request = world.time
|
||||
to_chat(usr, "<span class='info'>You requested an AI's presence.</span>")
|
||||
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>")
|
||||
return TRUE
|
||||
else
|
||||
//Record
|
||||
dat += "<a href='?src=[REF(src)];record_start=1'>Start new recording</a><br>"
|
||||
//Eject
|
||||
dat += "<a href='?src=[REF(src)];disk_eject=1'>Eject disk</a><br>"
|
||||
to_chat(usr, "<span class='info'>A request for AI presence was already sent recently.</span>")
|
||||
return
|
||||
if("holocall")
|
||||
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>"
|
||||
|
||||
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!!
|
||||
/**
|
||||
* hangup_all_calls: Disconnects all current holocalls from the holopad
|
||||
*/
|
||||
/obj/machinery/holopad/proc/hangup_all_calls()
|
||||
for(var/I in holo_calls)
|
||||
var/datum/holocall/HC = I
|
||||
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
|
||||
/obj/machinery/holopad/attack_ai(mob/living/silicon/ai/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)))
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(!secure) //HC.head_call &&
|
||||
HC.Answer(src)
|
||||
break
|
||||
if(outgoing_call)
|
||||
HC.Disconnect(src)//can't answer calls while calling
|
||||
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.
|
||||
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.
|
||||
for(var/mob/living/silicon/ai/master in masters)
|
||||
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)
|
||||
var/datum/holocall/HC = I
|
||||
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)
|
||||
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
|
||||
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(holorays, user, new /obj/effect/overlay/holoray(loc))
|
||||
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
|
||||
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])
|
||||
var/obj/effect/overlay/holo_pad_hologram/holo = masters[user]
|
||||
var/transfered = FALSE
|
||||
@@ -516,8 +525,6 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
transfered = TRUE
|
||||
//All is good.
|
||||
holo.forceMove(new_turf)
|
||||
if(direction)
|
||||
holo.setDir(direction)
|
||||
if(!transfered)
|
||||
update_holoray(user,new_turf)
|
||||
return TRUE
|
||||
@@ -568,22 +575,15 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
if(!replay_mode)
|
||||
replay_mode = TRUE
|
||||
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()
|
||||
replay_entry(1)
|
||||
return
|
||||
|
||||
/obj/machinery/holopad/proc/replay_stop()
|
||||
if(replay_mode)
|
||||
replay_mode = FALSE
|
||||
loop_mode = FALSE
|
||||
offset = FALSE
|
||||
temp = null
|
||||
QDEL_NULL(replay_holo)
|
||||
SetLightsAndPower()
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/holopad/proc/record_start(mob/living/user)
|
||||
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_user = 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)
|
||||
if(!record_mode)
|
||||
@@ -641,7 +639,7 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
if(replay_holo)
|
||||
replay_holo.say(message)
|
||||
if(HOLORECORD_SOUND)
|
||||
playsound(src,entry[2],50,1)
|
||||
playsound(src,entry[2],50,TRUE)
|
||||
if(HOLORECORD_DELAY)
|
||||
addtimer(CALLBACK(src,.proc/replay_entry,entry_number+1),entry[2])
|
||||
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()
|
||||
if(record_mode)
|
||||
record_mode = FALSE
|
||||
temp = null
|
||||
record_user = null
|
||||
updateDialog()
|
||||
|
||||
/obj/machinery/holopad/proc/record_clear()
|
||||
if(disk && disk.record)
|
||||
QDEL_NULL(disk.record)
|
||||
updateDialog()
|
||||
|
||||
/obj/effect/overlay/holo_pad_hologram
|
||||
initial_language_holder = /datum/language_holder/universal
|
||||
|
||||
@@ -6,14 +6,12 @@
|
||||
circuit = /obj/item/circuitboard/machine/hypnochair
|
||||
density = TRUE
|
||||
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/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/trigger_phrase = "" ///Trigger phrase to implant
|
||||
var/timerid = 0 ///Timer ID for interrogations
|
||||
|
||||
var/message_cooldown = 0 ///Cooldown for breakout message
|
||||
|
||||
/obj/machinery/hypnochair/Initialize()
|
||||
@@ -25,24 +23,24 @@
|
||||
if(!occupant && default_deconstruction_screwdriver(user, icon_state, icon_state, I))
|
||||
update_icon()
|
||||
return
|
||||
|
||||
if(default_pry_open(I))
|
||||
return
|
||||
|
||||
if(default_deconstruction_crowbar(I))
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/hypnochair/ui_state(mob/user)
|
||||
return GLOB.notcontained_state
|
||||
|
||||
/obj/machinery/hypnochair/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/obj/machinery/hypnochair/ui_data()
|
||||
var/list/data = list()
|
||||
data["occupied"] = occupant ? TRUE : FALSE
|
||||
data["occupied"] = occupant ? 1 : 0
|
||||
data["open"] = state_open
|
||||
data["interrogating"] = interrogating
|
||||
|
||||
@@ -201,3 +199,4 @@
|
||||
if(!(L.mobility_flags & MOBILITY_STAND))
|
||||
return
|
||||
close_machine(target)
|
||||
|
||||
|
||||
@@ -282,12 +282,14 @@
|
||||
ui_interact(user)
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
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_state(mob/user)
|
||||
return GLOB.inventory_state
|
||||
|
||||
/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)
|
||||
|
||||
/obj/item/launchpad_remote/ui_data(mob/user)
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
#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 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
|
||||
name = "turret"
|
||||
icon = 'icons/obj/turrets.dmi'
|
||||
@@ -15,70 +24,79 @@
|
||||
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
|
||||
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
|
||||
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
|
||||
integrity_failure = 0.5
|
||||
armor = list("melee" = 50, "bullet" = 30, "laser" = 30, "energy" = 30, "bomb" = 30, "bio" = 0, "rad" = 0, "fire" = 90, "acid" = 90)
|
||||
|
||||
var/locked = TRUE //if the turret's behaviour control access is locked
|
||||
var/controllock = FALSE //if the turret responds to control panels
|
||||
|
||||
var/installation = /obj/item/gun/energy/e_gun/turret //the type of weapon installed by default
|
||||
/// Base turret icon state
|
||||
var/base_icon_state = "standard"
|
||||
/// Scan range of the turret for locating targets
|
||||
var/scan_range = 7
|
||||
/// 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/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/stun_projectile = null //stun mode projectile type
|
||||
/// Stun mode projectile type
|
||||
var/stun_projectile = null
|
||||
/// Sound of stun projectile
|
||||
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/lethal_projectile = null //lethal mode projectile type
|
||||
/// Lethal mode projectile type
|
||||
var/lethal_projectile = null
|
||||
/// Sound of lethal projectile
|
||||
var/lethal_projectile_sound
|
||||
|
||||
var/reqpower = 500 //power needed per shot
|
||||
var/always_up = 0 //Will stay active
|
||||
var/has_cover = 1 //Hides the cover
|
||||
|
||||
var/obj/machinery/porta_turret_cover/cover = null //the cover that is covering this turret
|
||||
|
||||
var/last_fired = 0 //world.time the turret last fired
|
||||
var/shot_delay = 15 //ticks until next shot (1.5 ?)
|
||||
var/shot_stagger = 0 // sleep() shots to stagger attacks
|
||||
|
||||
var/check_records = 1 //checks if it can use the security records
|
||||
var/criminals = 1 //checks if it can shoot people on arrest
|
||||
var/auth_weapons = 0 //checks if it can shoot people that have a weapon they aren't authorized to have
|
||||
var/stun_all = 0 //if this is active, the turret shoots everything that isn't security or head of staff
|
||||
var/check_anomalies = 1 //checks if it can shoot at unidentified lifeforms (ie xenos)
|
||||
var/shoot_unloyal = 0 //checks if it can shoot people that aren't loyalty implantd
|
||||
|
||||
var/attacked = 0 //if set to 1, the turret gets pissed off and shoots at people nearby (unless they have sec access!)
|
||||
|
||||
var/on = TRUE //determines if the turret is on
|
||||
|
||||
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?
|
||||
|
||||
/// Power needed per shot
|
||||
var/reqpower = 500
|
||||
/// Will stay active
|
||||
var/always_up = FALSE
|
||||
/// Hides the cover
|
||||
var/has_cover = TRUE
|
||||
/// The cover that is covering this turret
|
||||
var/obj/machinery/porta_turret_cover/cover = null
|
||||
/// World.time the turret last fired
|
||||
var/last_fired = 0
|
||||
/// Ticks until next shot (1.5 ?)
|
||||
var/shot_delay = 15
|
||||
/// Turret flags about who is turret allowed to shoot
|
||||
var/turret_flags = TURRET_FLAG_SHOOT_CRIMINALS | TURRET_FLAG_SHOOT_ANOMALOUS
|
||||
/// Determines if the turret is on
|
||||
var/on = TRUE
|
||||
/// Same faction mobs will never be shot at, no matter the other settings
|
||||
var/list/faction = list("turret")
|
||||
/// The spark system, used for generating... sparks?
|
||||
var/datum/effect_system/spark_spread/spark_system
|
||||
/// Linked turret control panel of the turret
|
||||
var/obj/machinery/turretid/cp = null
|
||||
|
||||
var/wall_turret_direction //The turret will try to shoot from a turf in that direction when in a wall
|
||||
|
||||
var/manual_control = FALSE //
|
||||
/// 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
|
||||
/// Action button holder for quitting manual control
|
||||
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
|
||||
/// Mob that is remotely controlling the turret
|
||||
var/mob/remote_controller
|
||||
/// MISSING:
|
||||
var/shot_stagger = 0
|
||||
|
||||
/obj/machinery/porta_turret/Initialize()
|
||||
. = ..()
|
||||
@@ -100,6 +118,27 @@
|
||||
if(!has_cover)
|
||||
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()
|
||||
if(!anchored)
|
||||
icon_state = "turretCover"
|
||||
@@ -119,7 +158,6 @@
|
||||
else
|
||||
icon_state = "[base_icon_state]_unpowered"
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/proc/setup(obj/item/gun/turret_gun)
|
||||
if(stored_gun)
|
||||
qdel(stored_gun)
|
||||
@@ -160,83 +198,88 @@
|
||||
remove_control()
|
||||
return ..()
|
||||
|
||||
/obj/machinery/porta_turret/ui_interact(mob/user)
|
||||
. = ..()
|
||||
var/dat
|
||||
dat += "Status: <a href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</a><br>"
|
||||
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<br>"
|
||||
/obj/machinery/porta_turret/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "PortableTurret", name)
|
||||
ui.open()
|
||||
|
||||
if(!locked)
|
||||
dat += "Check for Weapon Authorization: <A href='?src=[REF(src)];operation=authweapon'>[auth_weapons ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Check Security Records: <A href='?src=[REF(src)];operation=checkrecords'>[check_records ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Neutralize Identified Criminals: <A href='?src=[REF(src)];operation=shootcrooks'>[criminals ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Neutralize All Non-Security and Non-Command Personnel: <A href='?src=[REF(src)];operation=shootall'>[stun_all ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Neutralize All Unidentified Life Signs: <A href='?src=[REF(src)];operation=checkxenos'>[check_anomalies ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Neutralize All Non-Loyalty Implanted Personnel: <A href='?src=[REF(src)];operation=checkloyal'>[shoot_unloyal ? "Yes" : "No"]</A><BR>"
|
||||
/obj/machinery/porta_turret/ui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"locked" = locked,
|
||||
"on" = on,
|
||||
"check_weapons" = turret_flags & TURRET_FLAG_AUTH_WEAPONS,
|
||||
"neutralize_criminals" = turret_flags & TURRET_FLAG_SHOOT_CRIMINALS,
|
||||
"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))
|
||||
data["silicon_user"] = TRUE
|
||||
if(!manual_control)
|
||||
var/mob/living/silicon/S = user
|
||||
if(S.hack_software)
|
||||
dat += "Assume direct control : <a href='?src=[REF(src)];operation=manual'>Manual Control</a><br>"
|
||||
else
|
||||
dat += "Warning! Remote control protocol enabled.<br>"
|
||||
data["allow_manual_control"] = TRUE
|
||||
return data
|
||||
|
||||
|
||||
var/datum/browser/popup = new(user, "autosec", "Automatic Portable Turret Installation", 300, 300)
|
||||
popup.set_content(dat)
|
||||
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)
|
||||
/obj/machinery/porta_turret/ui_act(action, list/params)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
|
||||
if(href_list["operation"])
|
||||
switch(href_list["operation"]) //toggles customizable behavioural protocols
|
||||
if("authweapon")
|
||||
auth_weapons = !auth_weapons
|
||||
if("checkrecords")
|
||||
check_records = !check_records
|
||||
if("shootcrooks")
|
||||
criminals = !criminals
|
||||
if("shootall")
|
||||
stun_all = !stun_all
|
||||
if("checkxenos")
|
||||
check_anomalies = !check_anomalies
|
||||
if("checkloyal")
|
||||
shoot_unloyal = !shoot_unloyal
|
||||
if("manual")
|
||||
if(issilicon(usr) && !manual_control)
|
||||
give_control(usr)
|
||||
interact(usr)
|
||||
switch(action)
|
||||
if("power")
|
||||
if(anchored)
|
||||
toggle_on()
|
||||
return TRUE
|
||||
else
|
||||
to_chat(usr, "<span class='warning'>It has to be secured first!</span>")
|
||||
if("authweapon")
|
||||
turret_flags ^= TURRET_FLAG_AUTH_WEAPONS
|
||||
return TRUE
|
||||
if("shootcriminals")
|
||||
turret_flags ^= TURRET_FLAG_SHOOT_CRIMINALS
|
||||
return TRUE
|
||||
if("shootall")
|
||||
turret_flags ^= TURRET_FLAG_SHOOT_ALL
|
||||
return TRUE
|
||||
if("checkxenos")
|
||||
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()
|
||||
if(!anchored)
|
||||
. = ..()
|
||||
if(!anchored || (stat & BROKEN) || !powered())
|
||||
update_icon()
|
||||
remove_control()
|
||||
return
|
||||
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()
|
||||
|
||||
check_should_process()
|
||||
|
||||
/obj/machinery/porta_turret/attackby(obj/item/I, mob/user, params)
|
||||
if(stat & BROKEN)
|
||||
@@ -284,8 +327,10 @@
|
||||
locked = !locked
|
||||
to_chat(user, "<span class='notice'>Controls are now [locked ? "locked" : "unlocked"].</span>")
|
||||
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)
|
||||
if(!multitool_check_buffer(user, I))
|
||||
return
|
||||
var/obj/item/multitool/M = I
|
||||
M.buffer = src
|
||||
to_chat(user, "<span class='notice'>You add [src] to multitool buffer.</span>")
|
||||
@@ -293,19 +338,17 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/porta_turret/emag_act(mob/user)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
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
|
||||
controllock = TRUE
|
||||
on = FALSE //turns off the turret temporarily
|
||||
toggle_on(FALSE) //turns off the turret temporarily
|
||||
update_icon()
|
||||
sleep(60) //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
|
||||
return TRUE
|
||||
|
||||
//6 seconds for the traitor to gtfo of the area before the turret decides to ruin his shit
|
||||
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 6 SECONDS)
|
||||
//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)
|
||||
. = ..()
|
||||
@@ -314,63 +357,41 @@
|
||||
if(on)
|
||||
//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
|
||||
check_records = pick(0, 1)
|
||||
criminals = pick(0, 1)
|
||||
auth_weapons = pick(0, 1)
|
||||
stun_all = pick(0, 0, 0, 0, 1) //stun_all is a pretty big deal, so it's least likely to get turned on
|
||||
if(prob(50))
|
||||
turret_flags |= TURRET_FLAG_SHOOT_CRIMINALS
|
||||
if(prob(50))
|
||||
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()
|
||||
|
||||
spawn(rand(60,600))
|
||||
if(!on)
|
||||
on = TRUE
|
||||
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), rand(60,600))
|
||||
|
||||
/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))
|
||||
spark_system.start()
|
||||
if(on && !attacked && !(obj_flags & EMAGGED))
|
||||
attacked = TRUE
|
||||
if(on && !(turret_flags & TURRET_FLAG_SHOOT_ALL_REACT) && !(obj_flags & EMAGGED))
|
||||
turret_flags |= TURRET_FLAG_SHOOT_ALL_REACT
|
||||
addtimer(CALLBACK(src, .proc/reset_attacked), 60)
|
||||
|
||||
/obj/machinery/porta_turret/proc/reset_attacked()
|
||||
attacked = FALSE
|
||||
turret_flags &= ~TURRET_FLAG_SHOOT_ALL_REACT
|
||||
|
||||
/obj/machinery/porta_turret/deconstruct(disassembled = TRUE)
|
||||
qdel(src)
|
||||
|
||||
/obj/machinery/porta_turret/obj_break(damage_flag)
|
||||
if(!(flags_1 & NODECONSTRUCT_1) && !(stat & BROKEN))
|
||||
stat |= BROKEN //enables the BROKEN bit
|
||||
. = ..()
|
||||
if(.)
|
||||
power_change()
|
||||
invisibility = 0
|
||||
spark_system.start() //creates some sparks because they look cool
|
||||
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()
|
||||
//the main machinery process
|
||||
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)
|
||||
|
||||
if(!on || (stat & (NOPOWER|BROKEN)) || manual_control)
|
||||
return
|
||||
return PROCESS_KILL
|
||||
|
||||
var/list/targets = list()
|
||||
for(var/mob/A in view(scan_range, base))
|
||||
if(A.invisibility > SEE_INVISIBLE_LIVING)
|
||||
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))
|
||||
var/mob/living/simple_animal/SA = A
|
||||
if(SA.stat || in_faction(SA)) //don't target if dead or in faction
|
||||
continue
|
||||
targets += SA
|
||||
if(issilicon(A))
|
||||
var/mob/living/silicon/sillycone = A
|
||||
if(sillycone.stat || in_faction(sillycone))
|
||||
continue
|
||||
|
||||
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
|
||||
|
||||
if(iscyborg(sillycone))
|
||||
var/mob/living/silicon/robot/sillyconerobot = A
|
||||
if(LAZYLEN(faction) && (ROLE_SYNDICATE in faction) && sillyconerobot.emagged == TRUE)
|
||||
continue
|
||||
|
||||
targets += sillycone
|
||||
|
||||
if(iscarbon(A))
|
||||
else if(iscarbon(A))
|
||||
var/mob/living/carbon/C = A
|
||||
//If not emagged, only target non downed carbons
|
||||
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 not emagged, only target carbons that can use items
|
||||
if(mode != TURRET_LETHAL && (C.stat || C.handcuffed || !(C.mobility_flags & MOBILITY_USE)))
|
||||
continue
|
||||
|
||||
//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(ishuman(C) && !in_faction(C))
|
||||
|
||||
if(assess_perp(C) >= 4)
|
||||
targets += C
|
||||
|
||||
else if(check_anomalies) //non humans who are not simple animals (xenos etc)
|
||||
else if(turret_flags & TURRET_FLAG_SHOOT_ANOMALOUS) //non humans who are not simple animals (xenos etc)
|
||||
if(!in_faction(C))
|
||||
targets += C
|
||||
|
||||
for(var/A in GLOB.mechas_list)
|
||||
if((get_dist(A, base) < scan_range) && can_see(base, A, scan_range))
|
||||
var/obj/mecha/Mech = A
|
||||
@@ -432,6 +462,10 @@
|
||||
if(assess_perp(Mech.occupant) >= 4)
|
||||
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)
|
||||
tryToShootAt(targets)
|
||||
else if(!always_up)
|
||||
@@ -488,36 +522,37 @@
|
||||
if(obj_flags & EMAGGED)
|
||||
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(!allowed(perp))
|
||||
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(allowed(perp)) //if the perp has security access, return 0
|
||||
return 0
|
||||
|
||||
if(perp.is_holding_item_of_type(/obj/item/gun) || perp.is_holding_item_of_type(/obj/item/melee/baton))
|
||||
threatcount += 4
|
||||
|
||||
if(istype(perp.belt, /obj/item/gun) || istype(perp.belt, /obj/item/melee/baton))
|
||||
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/datum/data/record/R = find_record("name", perpname, GLOB.data_core.security)
|
||||
if(!R || (R.fields["criminal"] == "*Arrest*"))
|
||||
threatcount += 4
|
||||
|
||||
if(shoot_unloyal)
|
||||
if (!HAS_TRAIT(perp, TRAIT_MINDSHIELD))
|
||||
threatcount += 4
|
||||
if((turret_flags & TURRET_FLAG_SHOOT_UNSHIELDED) && (!HAS_TRAIT(perp, TRAIT_MINDSHIELD)))
|
||||
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
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/proc/in_faction(mob/target)
|
||||
for(var/faction1 in faction)
|
||||
if(faction1 in target.faction)
|
||||
@@ -563,15 +598,14 @@
|
||||
T = closer
|
||||
break
|
||||
|
||||
var/mob/living/carbon/C
|
||||
if(iscarbon(target))
|
||||
C = target
|
||||
|
||||
update_icon()
|
||||
var/obj/item/projectile/A
|
||||
//any emagged turrets drains 2x power and uses a different projectile?
|
||||
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)
|
||||
A = new nonlethal_projectile(T)
|
||||
playsound(loc, nonlethal_projectile_sound, 75, 1)
|
||||
@@ -582,7 +616,7 @@
|
||||
else
|
||||
use_power(reqpower * 2)
|
||||
A = new lethal_projectile(T)
|
||||
playsound(loc, lethal_projectile_sound, 75, 1)
|
||||
playsound(loc, lethal_projectile_sound, 75, TRUE)
|
||||
|
||||
|
||||
//Shooting Code:
|
||||
@@ -592,16 +626,15 @@
|
||||
A.fire()
|
||||
return A
|
||||
|
||||
/obj/machinery/porta_turret/proc/setState(on, mode)
|
||||
/obj/machinery/porta_turret/proc/setState(on, mode, shoot_cyborgs)
|
||||
if(controllock)
|
||||
return
|
||||
src.on = on
|
||||
if(!on)
|
||||
popDown()
|
||||
|
||||
shoot_cyborgs ? (turret_flags |= TURRET_FLAG_SHOOT_BORGS) : (turret_flags &= ~TURRET_FLAG_SHOOT_BORGS)
|
||||
toggle_on(on)
|
||||
src.mode = mode
|
||||
power_change()
|
||||
|
||||
|
||||
/datum/action/turret_toggle
|
||||
name = "Toggle Mode"
|
||||
icon_icon = 'icons/mob/actions/actions_mecha.dmi'
|
||||
@@ -685,7 +718,15 @@
|
||||
|
||||
/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
|
||||
icon_state = "standard_stun"
|
||||
@@ -698,7 +739,6 @@
|
||||
lethal_projectile_sound = 'sound/weapons/laser.ogg'
|
||||
desc = "An energy blaster auto-turret."
|
||||
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/energy/heavy
|
||||
icon_state = "standard_stun"
|
||||
base_icon_state = "standard"
|
||||
@@ -715,14 +755,13 @@
|
||||
integrity_failure = 0.08
|
||||
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/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/raven
|
||||
stun_projectile = /obj/item/projectile/beam/laser
|
||||
stun_projectile_sound = 'sound/weapons/laser.ogg'
|
||||
faction = list("neutral","silicon","turret")
|
||||
|
||||
/obj/machinery/porta_turret/syndicate/pod
|
||||
integrity_failure = 0.5
|
||||
max_integrity = 40
|
||||
stun_projectile = /obj/item/projectile/bullet/syndicate_turret
|
||||
lethal_projectile = /obj/item/projectile/bullet/syndicate_turret
|
||||
@@ -749,6 +788,7 @@
|
||||
faction = list("silicon")
|
||||
nonlethal_projectile = /obj/item/projectile/beam/disabler
|
||||
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)
|
||||
return 10 //AI turrets shoot at everything not in their faction
|
||||
@@ -804,6 +844,7 @@
|
||||
|
||||
/obj/machinery/porta_turret/centcom_shuttle/weak
|
||||
max_integrity = 120
|
||||
integrity_failure = 0.5
|
||||
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."
|
||||
stun_projectile = /obj/item/projectile/beam/weak/penetrator
|
||||
@@ -817,7 +858,6 @@
|
||||
stun_projectile_sound = 'sound/weapons/gunshot.ogg'
|
||||
desc = "A ballistic machine gun auto-turret."
|
||||
|
||||
|
||||
////////////////////////
|
||||
//Turret Control Panel//
|
||||
////////////////////////
|
||||
@@ -828,14 +868,22 @@
|
||||
icon = 'icons/obj/machines/turret_control.dmi'
|
||||
icon_state = "control_standby"
|
||||
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)
|
||||
var/list/obj/machinery/porta_turret/turrets = list()
|
||||
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)
|
||||
. = ..()
|
||||
@@ -868,112 +916,111 @@
|
||||
T.cp = src
|
||||
|
||||
/obj/machinery/turretid/examine(mob/user)
|
||||
. = ..()
|
||||
if(hasSiliconAccessInArea(user) && (!stat & BROKEN))
|
||||
. += "<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>"
|
||||
. += ..()
|
||||
if(issilicon(user) && !(stat & BROKEN))
|
||||
. += {"<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>"}
|
||||
|
||||
/obj/machinery/turretid/attackby(obj/item/I, mob/user, params)
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
if (istype(I, /obj/item/multitool))
|
||||
if(!multitool_check_buffer(user, I))
|
||||
return
|
||||
var/obj/item/multitool/M = I
|
||||
if(M.buffer && istype(M.buffer, /obj/machinery/porta_turret))
|
||||
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
|
||||
|
||||
if (hasSiliconAccessInArea(user))
|
||||
if (issilicon(user))
|
||||
return attack_hand(user)
|
||||
|
||||
if ( get_dist(src, user) == 0 ) // trying to unlock the interface
|
||||
if (allowed(usr))
|
||||
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
|
||||
|
||||
locked = !locked
|
||||
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
|
||||
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)
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
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
|
||||
locked = FALSE
|
||||
if(user && user.machine == src)
|
||||
attack_hand(user)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/turretid/attack_ai(mob/user)
|
||||
if(!ailock || IsAdminGhost(user))
|
||||
return attack_hand(user)
|
||||
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 ( !(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(..())
|
||||
if(.)
|
||||
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
|
||||
add_hiddenprint(user)
|
||||
log_combat(user, src, "[lethal ? "enabled" : "disabled"] lethals on")
|
||||
updateTurrets()
|
||||
|
||||
/obj/machinery/turretid/proc/toggle_on()
|
||||
/obj/machinery/turretid/proc/toggle_on(mob/user)
|
||||
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()
|
||||
|
||||
/obj/machinery/turretid/proc/updateTurrets()
|
||||
for (var/obj/machinery/porta_turret/aTurret in turrets)
|
||||
aTurret.setState(enabled, lethal)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/turretid/power_change()
|
||||
..()
|
||||
aTurret.setState(enabled, lethal, shoot_cyborgs)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/turretid/update_icon_state()
|
||||
@@ -1051,11 +1098,7 @@
|
||||
|
||||
/obj/machinery/porta_turret/lasertag
|
||||
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE)
|
||||
check_records = 0
|
||||
criminals = 0
|
||||
auth_weapons = 1
|
||||
stun_all = 0
|
||||
check_anomalies = 0
|
||||
turret_flags = TURRET_FLAG_AUTH_WEAPONS
|
||||
var/team_color
|
||||
|
||||
/obj/machinery/porta_turret/lasertag/assess_perp(mob/living/carbon/human/perp)
|
||||
@@ -1083,20 +1126,14 @@
|
||||
if(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))
|
||||
var/mob/living/carbon/human/H = user
|
||||
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))
|
||||
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()
|
||||
return UI_CLOSE
|
||||
return ..()
|
||||
|
||||
//lasertag presets
|
||||
/obj/machinery/porta_turret/lasertag/red
|
||||
@@ -1112,11 +1149,9 @@
|
||||
if(on)
|
||||
if(team_color == "blue")
|
||||
if(istype(P, /obj/item/projectile/beam/lasertag/redtag))
|
||||
on = FALSE
|
||||
spawn(100)
|
||||
on = TRUE
|
||||
toggle_on(FALSE)
|
||||
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS)
|
||||
else if(team_color == "red")
|
||||
if(istype(P, /obj/item/projectile/beam/lasertag/bluetag))
|
||||
on = FALSE
|
||||
spawn(100)
|
||||
on = TRUE
|
||||
toggle_on(FALSE)
|
||||
addtimer(CALLBACK(src, .proc/toggle_on, TRUE), 10 SECONDS)
|
||||
|
||||
@@ -126,17 +126,6 @@
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/recharge_station/proc/process_occupant()
|
||||
if(occupant && iscyborg(occupant))
|
||||
var/mob/living/silicon/robot/R = occupant
|
||||
restock_modules()
|
||||
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)
|
||||
if(!occupant)
|
||||
return
|
||||
SEND_SIGNAL(occupant, COMSIG_PROCESS_BORGCHARGER_OCCUPANT, recharge_speed, repairs)
|
||||
|
||||
@@ -170,12 +170,10 @@
|
||||
..()
|
||||
default_unfasten_wrench(user, I, 5)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/space_heater/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.physical_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/space_heater/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "SpaceHeater", name, 400, 305, master_ui, state)
|
||||
ui = new(user, src, "SpaceHeater", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/space_heater/ui_data()
|
||||
@@ -210,7 +208,7 @@
|
||||
if("power")
|
||||
on = !on
|
||||
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()
|
||||
if (on)
|
||||
START_PROCESSING(SSmachines, src)
|
||||
@@ -222,16 +220,7 @@
|
||||
if(!panel_open)
|
||||
return
|
||||
var/target = params["target"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
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)
|
||||
if(text2num(target) != null)
|
||||
target= text2num(target) + T0C
|
||||
. = TRUE
|
||||
if(.)
|
||||
|
||||
@@ -377,11 +377,13 @@
|
||||
|
||||
return ..()
|
||||
|
||||
/obj/machinery/suit_storage_unit/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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/suit_storage_unit/ui_state(mob/user)
|
||||
return GLOB.notcontained_state
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "SuitStorageUnit", name, 400, 305, master_ui, state)
|
||||
ui = new(user, src, "SuitStorageUnit", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/suit_storage_unit/ui_data()
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
var/notice = ""
|
||||
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, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/telecomms/server/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/obj/machinery/computer/telecomms/server/ui_data(mob/user)
|
||||
|
||||
@@ -36,12 +36,11 @@
|
||||
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
|
||||
/obj/machinery/computer/message_monitor/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)
|
||||
/obj/machinery/computer/message_monitor/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "TelecommsPDALog", name, 727, 510, master_ui, state)
|
||||
ui = new(user, src, "TelecommsPDALog", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/message_monitor/ui_static_data(mob/user)
|
||||
|
||||
@@ -17,12 +17,11 @@
|
||||
|
||||
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,\
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/telecomms/monitor/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "TelecommsMonitor", name, 575, 400, master_ui, state)
|
||||
ui = new(user, src, "TelecommsMonitor", name)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/computer/telecomms/monitor/ui_data(mob/user)
|
||||
|
||||
@@ -27,16 +27,15 @@
|
||||
else
|
||||
return ..()
|
||||
|
||||
/obj/machinery/telecomms/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/telecomms/ui_interact(mob/user, datum/tgui/ui)
|
||||
if(!canInteract(user))
|
||||
if(ui)
|
||||
ui.close() //haha no.
|
||||
return
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/obj/machinery/telecomms/ui_data(mob/user)
|
||||
|
||||
@@ -11,10 +11,15 @@
|
||||
var/equip_ready = 1 //whether the equipment is ready for use. (or deactivated/activated for static stuff)
|
||||
var/energy_drain = 0
|
||||
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/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/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()
|
||||
if(chassis)
|
||||
@@ -35,9 +40,14 @@
|
||||
if(chassis.selected == src)
|
||||
chassis.selected = null
|
||||
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)
|
||||
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
|
||||
return ..()
|
||||
|
||||
@@ -59,7 +69,7 @@
|
||||
return txt
|
||||
|
||||
/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()
|
||||
return range&MELEE
|
||||
@@ -72,10 +82,10 @@
|
||||
return 0
|
||||
if(!equip_ready)
|
||||
return 0
|
||||
if(crit_fail)
|
||||
return 0
|
||||
if(energy_drain && !chassis.has_charge(energy_drain))
|
||||
return 0
|
||||
if(crit_fail)
|
||||
return 0
|
||||
if(chassis.equipment_disabled)
|
||||
to_chat(chassis.occupant, "<span=warn>Error -- Equipment control unit is unresponsive.</span>")
|
||||
return 0
|
||||
@@ -117,8 +127,6 @@
|
||||
chassis = M
|
||||
forceMove(M)
|
||||
M.mecha_log_message("[src] initialized.")
|
||||
if(!M.selected && selectable)
|
||||
M.selected = src
|
||||
src.update_chassis_page()
|
||||
return
|
||||
|
||||
@@ -150,7 +158,7 @@
|
||||
chassis.occupant_message("[icon2html(src, chassis.occupant)] [message]")
|
||||
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
|
||||
if(chassis)
|
||||
chassis.mecha_log_message(message, color) //and pass to our chassis
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Sleeper, Medical Beam, and Syringe gun
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/medical
|
||||
mech_flags = EXOSUIT_MODULE_MEDICAL
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/medical/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
toolspeed = 0.9
|
||||
var/drill_delay = 7
|
||||
var/drill_level = DRILL_BASIC
|
||||
mech_flags = EXOSUIT_MODULE_WORKING | EXOSUIT_MODULE_COMBAT
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/drill/Initialize()
|
||||
. = ..()
|
||||
@@ -153,6 +154,7 @@
|
||||
selectable = 0
|
||||
equip_cooldown = 15
|
||||
var/scanning_time = 0
|
||||
mech_flags = EXOSUIT_MODULE_WORKING
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/mining_scanner/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -8,11 +8,12 @@
|
||||
icon_state = "mecha_clamp"
|
||||
equip_cooldown = 15
|
||||
energy_drain = 10
|
||||
tool_behaviour = TOOL_RETRACTOR
|
||||
toolspeed = 0.8
|
||||
var/dam_force = 20
|
||||
var/obj/mecha/working/ripley/cargo_holder
|
||||
harmful = TRUE
|
||||
tool_behaviour = TOOL_RETRACTOR
|
||||
toolspeed = 0.8
|
||||
mech_flags = EXOSUIT_MODULE_RIPLEY
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/hydraulic_clamp/can_attach(obj/mecha/working/ripley/M as obj)
|
||||
if(..())
|
||||
@@ -180,6 +181,7 @@
|
||||
equip_cooldown = 5
|
||||
energy_drain = 0
|
||||
range = MELEE|RANGED
|
||||
mech_flags = EXOSUIT_MODULE_WORKING
|
||||
|
||||
/obj/item/mecha_parts/mecha_equipment/extinguisher/Initialize()
|
||||
. = ..()
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
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/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)
|
||||
if(..())
|
||||
|
||||
@@ -81,10 +81,10 @@
|
||||
var/obj/machinery/mech_bay_recharge_port/recharge_port
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/mech_bay_power_console/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/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,)
|
||||
if(recharge_port.recharging_mech.cell && !QDELETED(recharge_port.recharging_mech.cell))
|
||||
data["recharge_port"]["mech"]["cell"] = list(
|
||||
"critfail" = recharge_port.recharging_mech.cell.crit_fail,
|
||||
"charge" = recharge_port.recharging_mech.cell.charge,
|
||||
"maxcharge" = recharge_port.recharging_mech.cell.maxcharge
|
||||
)
|
||||
|
||||
+546
-335
@@ -9,17 +9,41 @@
|
||||
active_power_usage = 5000
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
circuit = /obj/item/circuitboard/machine/mechfab
|
||||
var/time_coeff = 1
|
||||
var/component_coeff = 1
|
||||
var/datum/techweb/specialized/autounlocking/exofab/stored_research
|
||||
var/sync = 0
|
||||
var/part_set
|
||||
var/datum/design/being_built
|
||||
// processing_flags = START_PROCESSING_MANUALLY
|
||||
|
||||
// subsystem_type = /datum/controller/subsystem/processing/fastprocess
|
||||
|
||||
/// Current items in the build queue.
|
||||
var/list/queue = list()
|
||||
var/processing_queue = 0
|
||||
var/screen = "main"
|
||||
var/temp
|
||||
var/offstation_security_levels = TRUE
|
||||
/// Whether or not the machine is building the entire queue automagically.
|
||||
var/process_queue = FALSE
|
||||
|
||||
/// The current design datum that the machine is building.
|
||||
var/datum/design/being_built
|
||||
/// World time when the build will finish.
|
||||
var/build_finish = 0
|
||||
/// World time when the build started.
|
||||
var/build_start = 0
|
||||
/// Reference to all materials used in the creation of the item being_built.
|
||||
var/list/build_materials
|
||||
/// Part currently stored in the Exofab.
|
||||
var/obj/item/stored_part
|
||||
|
||||
/// Coefficient for the speed of item building. Based on the installed parts.
|
||||
var/time_coeff = 1
|
||||
/// Coefficient for the efficiency of material usage in item building. Based on the installed parts.
|
||||
var/component_coeff = 1
|
||||
|
||||
/// 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(
|
||||
"Cyborg",
|
||||
"Ripley",
|
||||
@@ -33,25 +57,17 @@
|
||||
"Exosuit Equipment",
|
||||
"Exosuit Ammunition",
|
||||
"Cyborg Upgrade Modules",
|
||||
"Cybernetics",
|
||||
"Implants",
|
||||
"Control Interfaces",
|
||||
"Misc"
|
||||
)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/Initialize()
|
||||
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
|
||||
/obj/machinery/mecha_part_fabricator/Initialize(mapload)
|
||||
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 ..()
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/RefreshParts()
|
||||
@@ -60,8 +76,7 @@
|
||||
//maximum stocking amount (default 300000, 600000 at T4)
|
||||
for(var/obj/item/stock_parts/matter_bin/M in component_parts)
|
||||
T += M.rating
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.max_amount = (200000 + (T*50000))
|
||||
rmat.set_local_size((200000 + (T*50000)))
|
||||
|
||||
//resources adjustment coefficient (1 -> 0.85 -> 0.7 -> 0.55)
|
||||
T = 1.15
|
||||
@@ -74,89 +89,157 @@
|
||||
for(var/obj/item/stock_parts/manipulator/Ml in component_parts)
|
||||
T += Ml.rating
|
||||
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)
|
||||
. = ..()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
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()
|
||||
. = ..()
|
||||
if(obj_flags & EMAGGED)
|
||||
return
|
||||
obj_flags |= EMAGGED
|
||||
req_access = list()
|
||||
INVOKE_ASYNC(src, .proc/error_action_sucessful)
|
||||
return TRUE
|
||||
|
||||
/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
|
||||
/**
|
||||
* Generates an info list for a given part.
|
||||
*
|
||||
* Returns a list of part information.
|
||||
* * D - Design datum to get information on.
|
||||
* * categories - Boolean, whether or not to parse snowflake categories into the part information list.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/output_part_info(datum/design/D, categories = FALSE)
|
||||
var/cost = list()
|
||||
for(var/c in D.materials)
|
||||
var/datum/material/M = c
|
||||
output += "[i?" | ":null][get_resource_cost_w_coeff(D, M)] [M.name]"
|
||||
i++
|
||||
return output
|
||||
cost[M.name] = get_resource_cost_w_coeff(D, M)
|
||||
|
||||
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()
|
||||
var/output
|
||||
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³"
|
||||
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/datum/component/material_container/materials = rmat.mat_container
|
||||
|
||||
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)
|
||||
var/list/resources = list()
|
||||
for(var/R in D.materials)
|
||||
@@ -164,294 +247,419 @@
|
||||
resources[M] = get_resource_cost_w_coeff(D, M)
|
||||
return resources
|
||||
|
||||
/**
|
||||
* Checks if the Exofab has enough resources to print a given item.
|
||||
*
|
||||
* Returns FALSE if the design has no reagents used in its construction (?) or if there are insufficient resources.
|
||||
* Returns TRUE if there are sufficient resources to print the item.
|
||||
* * D - Design datum to calculate the modified resource cost of.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/check_resources(datum/design/D)
|
||||
if(D.reagents_list.len) // No reagents storage - no reagent designs.
|
||||
if(length(D.reagents_list)) // No reagents storage - no reagent designs.
|
||||
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)))
|
||||
return TRUE
|
||||
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
|
||||
desc = "It's building \a [initial(D.name)]."
|
||||
var/list/res_coef = get_resources_w_coeff(D)
|
||||
build_finish = world.time + get_construction_time_w_coeff(initial(D.construction_time))
|
||||
build_start = world.time
|
||||
desc = "It's building \a [D.name]."
|
||||
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
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)
|
||||
rmat.silo_log(src, "built", -1, "[D.name]", build_materials)
|
||||
|
||||
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
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/update_queue_on_page()
|
||||
send_byjax(usr,"mecha_fabricator.browser","queue",list_queue())
|
||||
return
|
||||
/obj/machinery/mecha_part_fabricator/process()
|
||||
// If there's a stored part to dispense due to an obstruction, try to dispense it.
|
||||
if(stored_part)
|
||||
var/turf/exit = get_step(src,(dir))
|
||||
if(exit.density)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/add_part_set_to_queue(set_name)
|
||||
if(set_name in part_sets)
|
||||
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)
|
||||
add_to_queue(D)
|
||||
say("Obstruction cleared. \The [stored_part] is complete.")
|
||||
stored_part.forceMove(exit)
|
||||
stored_part = null
|
||||
|
||||
/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))
|
||||
queue = list()
|
||||
if(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)
|
||||
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
|
||||
queue.Cut(index,++index)
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/proc/process_queue()
|
||||
var/datum/design/D = queue[1]
|
||||
if(!D)
|
||||
remove_from_queue(1)
|
||||
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.")
|
||||
|
||||
/**
|
||||
* Generates a list of parts formatted for tgui based on the current build queue.
|
||||
*
|
||||
* Returns a formatted list of lists containing formatted part information for every part in the build queue.
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/list_queue()
|
||||
var/output = "<b>Queue contains:</b>"
|
||||
if(!istype(queue) || !queue.len)
|
||||
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'>↑</a>":null] "
|
||||
output += "[i<queue.len?"<a href='?src=[REF(src)];queue_move=+1;index=[i]' class='arrow'>↓</a>":null] "
|
||||
output += "<a href='?src=[REF(src)];remove_from_queue=[i]'>Remove</a></li>"
|
||||
if(!istype(queue) || !length(queue))
|
||||
return null
|
||||
|
||||
output += "</ol>"
|
||||
output += "\[<a href='?src=[REF(src)];process_queue=1'>Process queue</a> | <a href='?src=[REF(src)];clear_queue=1'>Clear queue</a>\]"
|
||||
return output
|
||||
var/list/queued_parts = list()
|
||||
for(var/datum/design/D in queue)
|
||||
var/list/part = output_part_info(D)
|
||||
queued_parts += list(part)
|
||||
return queued_parts
|
||||
|
||||
/**
|
||||
* 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()
|
||||
temp = "Updating local R&D database..."
|
||||
updateUsrDialog()
|
||||
sleep(30) //only sleep if called by user
|
||||
|
||||
for(var/obj/machinery/computer/rdconsole/RDC in oview(7,src))
|
||||
for(var/obj/machinery/computer/rdconsole/RDC in orange(7,src))
|
||||
RDC.stored_research.copy_research_to(stored_research)
|
||||
temp = "Processed equipment designs.<br>"
|
||||
//check if the tech coefficients have changed
|
||||
temp += "<a href='?src=[REF(src)];clear_temp=1'>Return</a>"
|
||||
|
||||
updateUsrDialog()
|
||||
update_static_data(usr)
|
||||
say("Successfully synchronized with R&D server.")
|
||||
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>"
|
||||
updateUsrDialog()
|
||||
say("Unable to connect to local R&D server.")
|
||||
return
|
||||
|
||||
/**
|
||||
* Calculates the coefficient-modified resource cost of a single material component of a design's recipe.
|
||||
*
|
||||
* Returns coefficient-modified resource cost for the given material component.
|
||||
* * D - Design datum to pull the resource cost from.
|
||||
* * resource - Material datum reference to the resource to calculate the cost of.
|
||||
* * roundto - Rounding value for round() proc
|
||||
*/
|
||||
/obj/machinery/mecha_part_fabricator/proc/get_resource_cost_w_coeff(datum/design/D, var/datum/material/resource, roundto = 1)
|
||||
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)
|
||||
. = ..()
|
||||
var/dat, left_part
|
||||
user.set_machine(src)
|
||||
var/turf/exit = get_step(src,(dir))
|
||||
if(exit.density)
|
||||
say("Error! Part outlet is obstructed.")
|
||||
return
|
||||
if(temp)
|
||||
left_part = temp
|
||||
else if(being_built)
|
||||
var/obj/I = being_built.build_path
|
||||
left_part = {"<TT>Building [initial(I.name)].<BR>
|
||||
Please wait until completion...</TT>"}
|
||||
/obj/machinery/mecha_part_fabricator/ui_assets(mob/user)
|
||||
return list(
|
||||
get_asset_datum(/datum/asset/spritesheet/sheetmaterials)
|
||||
)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, "ExosuitFabricator")
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/ui_static_data(mob/user)
|
||||
var/list/data = list()
|
||||
|
||||
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
|
||||
switch(screen)
|
||||
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
|
||||
data["buildingPart"] = null
|
||||
|
||||
/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(..())
|
||||
return
|
||||
if(href_list["part_set"])
|
||||
var/tpart_set = href_list["part_set"]
|
||||
if(tpart_set)
|
||||
if(tpart_set=="clear")
|
||||
part_set = null
|
||||
else
|
||||
part_set = tpart_set
|
||||
screen = "parts"
|
||||
if(href_list["part"])
|
||||
var/T = href_list["part"]
|
||||
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)
|
||||
if(!processing_queue)
|
||||
build_part(D)
|
||||
else
|
||||
add_to_queue(D)
|
||||
break
|
||||
if(href_list["add_to_queue"])
|
||||
var/T = href_list["add_to_queue"]
|
||||
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)
|
||||
return TRUE
|
||||
|
||||
. = TRUE
|
||||
|
||||
add_fingerprint(usr)
|
||||
usr.set_machine(src)
|
||||
|
||||
switch(action)
|
||||
if("sync_rnd")
|
||||
// Sync with R&D Servers
|
||||
sync()
|
||||
return
|
||||
if("add_queue_set")
|
||||
// Add all parts of a set to queue
|
||||
var/part_list = params["part_list"]
|
||||
add_part_set_to_queue(part_list)
|
||||
return
|
||||
if("add_queue_part")
|
||||
// Add a specific part to queue
|
||||
var/T = params["id"]
|
||||
for(var/v in stored_research.researched_designs)
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(v)
|
||||
if((D.build_type & MECHFAB) && (D.id == T))
|
||||
add_to_queue(D)
|
||||
break
|
||||
return update_queue_on_page()
|
||||
if(href_list["remove_from_queue"])
|
||||
remove_from_queue(text2num(href_list["remove_from_queue"]))
|
||||
return update_queue_on_page()
|
||||
if(href_list["partset_to_queue"])
|
||||
add_part_set_to_queue(href_list["partset_to_queue"])
|
||||
return update_queue_on_page()
|
||||
if(href_list["process_queue"])
|
||||
spawn(0)
|
||||
if(processing_queue || being_built)
|
||||
return FALSE
|
||||
processing_queue = 1
|
||||
process_queue()
|
||||
processing_queue = 0
|
||||
if(href_list["clear_temp"])
|
||||
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
|
||||
return
|
||||
if("del_queue_part")
|
||||
// Delete a specific from from the queue
|
||||
var/index = text2num(params["index"])
|
||||
remove_from_queue(index)
|
||||
return
|
||||
if("clear_queue")
|
||||
// Delete everything from queue
|
||||
queue.Cut()
|
||||
return
|
||||
if("build_queue")
|
||||
// Build everything in queue
|
||||
if(process_queue)
|
||||
return
|
||||
process_queue = TRUE
|
||||
|
||||
if(href_list["remove_mat"] && href_list["material"])
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
var/datum/material/Mat = locate(href_list["material"])
|
||||
materials.retrieve_sheets(text2num(href_list["remove_mat"]), Mat)
|
||||
if(!being_built)
|
||||
START_PROCESSING(SSfastprocess, src)
|
||||
//begin_processing()
|
||||
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()
|
||||
return
|
||||
var/id = params["id"]
|
||||
var/datum/design/D = SSresearch.techweb_design_by_id(id)
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/on_deconstruction()
|
||||
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
|
||||
materials.retrieve_all()
|
||||
..()
|
||||
if(!(D.build_type & MECHFAB) || !(D.id == id))
|
||||
return
|
||||
|
||||
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)
|
||||
var/datum/material/M = id_inserted
|
||||
add_overlay("fab-load-[M.name]")
|
||||
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)
|
||||
if(default_deconstruction_screwdriver(user, "fab-o", "fab-idle", W))
|
||||
/obj/machinery/mecha_part_fabricator/screwdriver_act(mob/living/user, obj/item/I)
|
||||
if(..())
|
||||
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 ..()
|
||||
if(being_built)
|
||||
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)
|
||||
if(panel_open)
|
||||
@@ -463,6 +671,9 @@
|
||||
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/maint
|
||||
link_on_init = FALSE
|
||||
|
||||
/obj/machinery/mecha_part_fabricator/offstation
|
||||
offstation_security_levels = FALSE
|
||||
link_on_init = FALSE
|
||||
circuit = /obj/item/circuitboard/machine/mechfab/offstation
|
||||
|
||||
@@ -5,14 +5,11 @@
|
||||
icon_keyboard = "tech_key"
|
||||
req_access = list(ACCESS_ROBOTICS)
|
||||
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, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/computer/mecha/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/obj/machinery/computer/mecha/ui_data(mob/user)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
anchored = TRUE
|
||||
light_range = 3
|
||||
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/lifespan = 990
|
||||
@@ -23,8 +23,10 @@
|
||||
START_PROCESSING(SSobj, src)
|
||||
impact_area = get_area(src)
|
||||
|
||||
aSignal = new(src)
|
||||
aSignal.name = "[name] core"
|
||||
if (!impact_area)
|
||||
return INITIALIZE_HINT_QDEL
|
||||
|
||||
aSignal = new aSignal(src)
|
||||
aSignal.code = rand(1,100)
|
||||
aSignal.anomaly_type = type
|
||||
|
||||
@@ -75,7 +77,7 @@
|
||||
|
||||
|
||||
/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>")
|
||||
|
||||
///////////////////////
|
||||
@@ -85,6 +87,7 @@
|
||||
icon_state = "shield2"
|
||||
density = FALSE
|
||||
var/boing = 0
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/grav
|
||||
|
||||
/obj/effect/anomaly/grav/anomalyEffect()
|
||||
..()
|
||||
@@ -95,17 +98,23 @@
|
||||
for(var/mob/living/M in range(0, src))
|
||||
gravShock(M)
|
||||
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))
|
||||
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)
|
||||
if(target && !target.stat)
|
||||
O.throw_at(target, 5, 10)
|
||||
|
||||
/obj/effect/anomaly/grav/Crossed(mob/A)
|
||||
gravShock(A)
|
||||
/obj/effect/anomaly/grav/Crossed(atom/movable/AM)
|
||||
. = ..()
|
||||
gravShock(AM)
|
||||
|
||||
/obj/effect/anomaly/grav/Bump(mob/A)
|
||||
/obj/effect/anomaly/grav/Bump(atom/A)
|
||||
gravShock(A)
|
||||
|
||||
/obj/effect/anomaly/grav/Bumped(atom/movable/AM)
|
||||
@@ -138,6 +147,7 @@
|
||||
name = "flux wave anomaly"
|
||||
icon_state = "electricity2"
|
||||
density = TRUE
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/flux
|
||||
var/canshock = FALSE
|
||||
var/shockdamage = 20
|
||||
var/explosive = TRUE
|
||||
@@ -148,11 +158,12 @@
|
||||
for(var/mob/living/M in range(0, src))
|
||||
mobShock(M)
|
||||
|
||||
/obj/effect/anomaly/flux/Crossed(mob/living/M)
|
||||
mobShock(M)
|
||||
/obj/effect/anomaly/flux/Crossed(atom/movable/AM)
|
||||
. = ..()
|
||||
mobShock(AM)
|
||||
|
||||
/obj/effect/anomaly/flux/Bump(mob/living/M)
|
||||
mobShock(M)
|
||||
/obj/effect/anomaly/flux/Bump(atom/A)
|
||||
mobShock(A)
|
||||
|
||||
/obj/effect/anomaly/flux/Bumped(atom/movable/AM)
|
||||
mobShock(AM)
|
||||
@@ -160,7 +171,7 @@
|
||||
/obj/effect/anomaly/flux/proc/mobShock(mob/living/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.
|
||||
M.electrocute_act(shockdamage, "[name]", flags = SHOCK_NOGLOVES)
|
||||
M.electrocute_act(shockdamage, name, flags = SHOCK_NOGLOVES)
|
||||
|
||||
/obj/effect/anomaly/flux/detonate()
|
||||
if(explosive)
|
||||
@@ -176,6 +187,7 @@
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "bluespace"
|
||||
density = TRUE
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/bluespace
|
||||
|
||||
/obj/effect/anomaly/bluespace/anomalyEffect()
|
||||
..()
|
||||
@@ -187,7 +199,7 @@
|
||||
do_teleport(AM, locate(AM.x, AM.y, AM.z), 8, channel = TELEPORT_CHANNEL_BLUESPACE)
|
||||
|
||||
/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)
|
||||
// Calculate new position (searches through beacons in world)
|
||||
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
|
||||
A.forceMove(newloc)
|
||||
|
||||
spawn()
|
||||
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
|
||||
var/mob/M = A
|
||||
if(M.client)
|
||||
var/obj/blueeffect = new /obj(src)
|
||||
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
blueeffect.icon = 'icons/effects/effects.dmi'
|
||||
blueeffect.icon_state = "shieldsparkles"
|
||||
blueeffect.layer = FLASH_LAYER
|
||||
blueeffect.plane = FULLSCREEN_PLANE
|
||||
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
M.client.screen += blueeffect
|
||||
sleep(20)
|
||||
M.client.screen -= blueeffect
|
||||
qdel(blueeffect)
|
||||
if(ismob(A) && !(A in flashers)) // don't flash if we're already doing an effect
|
||||
var/mob/M = A
|
||||
if(M.client)
|
||||
INVOKE_ASYNC(src, .proc/blue_effect, M)
|
||||
|
||||
/obj/effect/anomaly/bluespace/proc/blue_effect(mob/M)
|
||||
var/obj/blueeffect = new /obj(src)
|
||||
blueeffect.screen_loc = "WEST,SOUTH to EAST,NORTH"
|
||||
blueeffect.icon = 'icons/effects/effects.dmi'
|
||||
blueeffect.icon_state = "shieldsparkles"
|
||||
blueeffect.layer = FLASH_LAYER
|
||||
blueeffect.plane = FULLSCREEN_PLANE
|
||||
blueeffect.mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
M.client.screen += blueeffect
|
||||
sleep(20)
|
||||
M.client.screen -= blueeffect
|
||||
qdel(blueeffect)
|
||||
|
||||
/////////////////////
|
||||
|
||||
@@ -246,6 +260,7 @@
|
||||
name = "pyroclastic anomaly"
|
||||
icon_state = "mustard"
|
||||
var/ticks = 0
|
||||
aSignal = /obj/item/assembly/signaler/anomaly/pyro
|
||||
|
||||
/obj/effect/anomaly/pyro/anomalyEffect()
|
||||
..()
|
||||
@@ -278,6 +293,7 @@
|
||||
name = "vortex anomaly"
|
||||
icon_state = "bhole3"
|
||||
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()
|
||||
..()
|
||||
|
||||
@@ -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))
|
||||
return
|
||||
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/P2 = new newtype(actual_destination, _creator, _lifespan, P1, TRUE, 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, _lifespan, P1, TRUE, null, atmos_link_override)
|
||||
if(!istype(P1)||!istype(P2))
|
||||
return
|
||||
P1.link_portal(P2)
|
||||
@@ -21,7 +21,6 @@
|
||||
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/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/atmos_link = FALSE //Link source/destination atmos.
|
||||
var/turf/open/atmos_source //Atmos link source
|
||||
@@ -35,6 +34,7 @@
|
||||
name = "wormhole"
|
||||
icon = 'icons/obj/objects.dmi'
|
||||
icon_state = "anom"
|
||||
layer = RIPPLE_LAYER
|
||||
mech_sized = TRUE
|
||||
teleport_channel = TELEPORT_CHANNEL_WORMHOLE
|
||||
|
||||
@@ -49,7 +49,9 @@
|
||||
user.forceMove(get_turf(src))
|
||||
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))
|
||||
return ..()
|
||||
if(linked && (get_turf(oldloc) == get_turf(linked)))
|
||||
@@ -66,7 +68,7 @@
|
||||
if(Adjacent(user))
|
||||
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
|
||||
if(!istype(_linked) && automatic_link)
|
||||
@@ -78,7 +80,6 @@
|
||||
atmos_link = atmos_link_override
|
||||
link_portal(_linked)
|
||||
hardlinked = automatic_link
|
||||
creator = _creator
|
||||
if(isturf(hard_target_override))
|
||||
hard_target = hard_target_override
|
||||
|
||||
@@ -129,10 +130,7 @@
|
||||
LAZYREMOVE(atmos_destination.atmos_adjacent_turfs, atmos_source)
|
||||
atmos_destination = null
|
||||
|
||||
/obj/effect/portal/Destroy() //Calls on_portal_destroy(destroyed portal, location of destroyed portal) on creator if creator has such call.
|
||||
if(creator && hascall(creator, "on_portal_destroy"))
|
||||
call(creator, "on_portal_destroy")(src, src.loc)
|
||||
creator = null
|
||||
/obj/effect/portal/Destroy()
|
||||
GLOB.portals -= src
|
||||
unlink_atmos()
|
||||
if(hardlinked && !QDELETED(linked))
|
||||
@@ -153,8 +151,6 @@
|
||||
return FALSE
|
||||
if(!force && (!ismecha(M) && !istype(M, /obj/item/projectile) && M.anchored && !allow_anchored))
|
||||
return
|
||||
if(ismegafauna(M))
|
||||
message_admins("[M] has used a portal at [ADMIN_VERBOSEJMP(src)] made by [usr].")
|
||||
var/no_effect = FALSE
|
||||
if(last_effect == world.time)
|
||||
no_effect = TRUE
|
||||
|
||||
@@ -380,8 +380,6 @@
|
||||
name = "random keg spawner"
|
||||
lootcount = 1
|
||||
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/effect/spawner/lootdrop/coin
|
||||
|
||||
@@ -238,24 +238,22 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
playsound(get_turf(user), 'sound/items/deconstruct.ogg', 50, 1)
|
||||
return(BRUTELOSS)
|
||||
|
||||
/obj/item/pipe_dispenser/ui_base_html(html)
|
||||
var/datum/asset/spritesheet/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
|
||||
. = replacetext(html, "<!--customheadhtml-->", assets.css_tag())
|
||||
/obj/item/pipe_dispenser/ui_assets(mob/user)
|
||||
return list(
|
||||
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, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.default_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/pipe_dispenser/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
var/datum/asset/assets = get_asset_datum(/datum/asset/spritesheet/pipes)
|
||||
assets.send(user)
|
||||
|
||||
ui = new(user, src, ui_key, "RapidPipeDispenser", name, 425, 515, master_ui, state)
|
||||
ui = new(user, src, "RapidPipeDispenser", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/pipe_dispenser/ui_data(mob/user)
|
||||
var/list/data = list(
|
||||
"category" = category,
|
||||
"piping_layer" = piping_layer,
|
||||
// "ducting_layer" = ducting_layer, //uhh is this for chem thing?
|
||||
"preview_rows" = recipe.get_preview(p_dir),
|
||||
"categories" = list(),
|
||||
"selected_color" = paint_color,
|
||||
@@ -284,7 +282,7 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
/obj/item/pipe_dispenser/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
if(!usr.canUseTopic(src))
|
||||
if(!usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
var/playeffect = TRUE
|
||||
switch(action)
|
||||
@@ -304,6 +302,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
if("piping_layer")
|
||||
piping_layer = text2num(params["piping_layer"])
|
||||
playeffect = FALSE
|
||||
// if("ducting_layer")
|
||||
// ducting_layer = text2num(params["ducting_layer"])
|
||||
// playeffect = FALSE
|
||||
if("pipe_type")
|
||||
var/static/list/recipes
|
||||
if(!recipes)
|
||||
@@ -320,11 +321,9 @@ GLOBAL_LIST_INIT(transit_tube_recipes, list(
|
||||
mode &= ~n
|
||||
else
|
||||
mode |= n
|
||||
|
||||
if(playeffect && world.time >= effectcooldown)
|
||||
if(playeffect)
|
||||
spark_system.start()
|
||||
effectcooldown = world.time + 100
|
||||
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, 0)
|
||||
playsound(get_turf(src), 'sound/effects/pop.ogg', 50, FALSE)
|
||||
return TRUE
|
||||
|
||||
/obj/item/pipe_dispenser/pre_attack(atom/A, mob/user)
|
||||
|
||||
@@ -180,10 +180,10 @@
|
||||
stored_decal_total = "[stored_decal][yellow_fix][stored_color]"
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/airlock_painter/decal/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "DecalPainter", name, 500, 400, master_ui, state)
|
||||
ui = new(user, src, "DecalPainter", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/airlock_painter/decal/ui_data(mob/user)
|
||||
|
||||
@@ -147,23 +147,23 @@
|
||||
to_chat(user, "<span class='warning'>There is not enough of [src] left!</span>")
|
||||
. = 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)
|
||||
// tgui is a plague upon this codebase
|
||||
/obj/item/toy/crayon/ui_state(mob/user)
|
||||
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)
|
||||
ui = new(user, src, ui_key, "Crayon", name, 600, 600,
|
||||
master_ui, state)
|
||||
ui = new(user, src, "Crayon", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/toy/crayon/spraycan/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
if(has_cap)
|
||||
is_capped = !is_capped
|
||||
to_chat(user, "<span class='notice'>The cap on [src] is now [is_capped ? "on" : "off"].</span>")
|
||||
update_icon()
|
||||
return TRUE
|
||||
|
||||
/obj/item/toy/crayon/CtrlClick(mob/user)
|
||||
if(can_change_colour && !isturf(loc) && user.canUseTopic(src, BE_CLOSE, ismonkey(user)))
|
||||
|
||||
@@ -54,18 +54,20 @@
|
||||
name = initial(name)
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/item/aicard/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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/aicard/ui_state(mob/user)
|
||||
return GLOB.hands_state
|
||||
|
||||
/obj/item/aicard/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Intellicard", name, 500, 500, master_ui, state)
|
||||
ui = new(user, src, "Intellicard", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/aicard/ui_data()
|
||||
var/list/data = list()
|
||||
if(AI)
|
||||
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["wireless"] = !AI.control_disabled //todo disabled->enabled
|
||||
data["radio"] = AI.radio_enabled
|
||||
@@ -86,19 +88,19 @@
|
||||
if(confirm == "Yes" && !..())
|
||||
flush = TRUE
|
||||
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)
|
||||
AI.adjustOxyLoss(1)
|
||||
AI.adjustOxyLoss(5)
|
||||
AI.updatehealth()
|
||||
sleep(5)
|
||||
flush = FALSE
|
||||
. = TRUE
|
||||
if("wireless")
|
||||
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
|
||||
if("radio")
|
||||
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
|
||||
update_icon()
|
||||
|
||||
@@ -163,12 +163,13 @@
|
||||
return
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/dogborg/sleeper/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/item/dogborg/sleeper/ui_state(mob/user)
|
||||
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)
|
||||
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()
|
||||
|
||||
/obj/item/dogborg/sleeper/ui_data()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
GLOBAL_LIST_EMPTY(GPS_list)
|
||||
|
||||
/obj/item/gps
|
||||
name = "global positioning system"
|
||||
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
|
||||
obj_flags = UNIQUE_RENAME
|
||||
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()
|
||||
. = ..()
|
||||
GLOB.GPS_list += src
|
||||
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
|
||||
|
||||
AddComponent(/datum/component/gps/item, gpstag)
|
||||
|
||||
/obj/item/gps/science
|
||||
icon_state = "gps-s"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/obj/item/electropack/Destroy()
|
||||
SSradio.remove_object(src, frequency)
|
||||
. = ..()
|
||||
return ..()
|
||||
|
||||
/obj/item/electropack/on_attack_hand(mob/user, act_intent = user.a_intent, unarmed_attack_flags)
|
||||
if(iscarbon(user))
|
||||
@@ -39,7 +39,7 @@
|
||||
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))
|
||||
var/obj/item/assembly/shock_kit/A = new /obj/item/assembly/shock_kit(user)
|
||||
A.icon = 'icons/obj/assemblies.dmi'
|
||||
@@ -59,56 +59,12 @@
|
||||
else
|
||||
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)
|
||||
if(!signal || signal.data["code"] != code)
|
||||
return
|
||||
|
||||
if(isliving(loc) && on)
|
||||
if(shock_cooldown == TRUE)
|
||||
if(shock_cooldown)
|
||||
return
|
||||
shock_cooldown = TRUE
|
||||
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
|
||||
@@ -124,18 +80,59 @@
|
||||
|
||||
if(master)
|
||||
master.receive_signal()
|
||||
return
|
||||
|
||||
/obj/item/electropack/ui_interact(mob/user)
|
||||
if(!ishuman(user))
|
||||
/obj/item/electropack/proc/set_frequency(new_frequency)
|
||||
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
|
||||
|
||||
/obj/item/electropack/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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Electropack", name, ui_x, ui_y, master_ui, state)
|
||||
ui.open()
|
||||
switch(action)
|
||||
if("power")
|
||||
on = !on
|
||||
icon_state = "electropack[on]"
|
||||
. = TRUE
|
||||
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
|
||||
name = "shock collar"
|
||||
@@ -145,7 +142,7 @@
|
||||
icon_state = "shockcollar"
|
||||
item_state = "shockcollar"
|
||||
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
|
||||
strip_delay = 60
|
||||
equip_delay_other = 60
|
||||
@@ -167,16 +164,18 @@
|
||||
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)
|
||||
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)
|
||||
return
|
||||
shock_cooldown = TRUE
|
||||
addtimer(VARSET_CALLBACK(src, shock_cooldown, FALSE), 100)
|
||||
var/mob/living/L = loc
|
||||
step(L, pick(GLOB.cardinals))
|
||||
|
||||
to_chat(L, "<span class='danger'>You feel a sharp shock from the collar!</span>")
|
||||
@@ -196,10 +195,13 @@
|
||||
if(t)
|
||||
tagname = t
|
||||
name = "[initial(name)] - [t]"
|
||||
return
|
||||
if(istype(W, /obj/item/clothing/head/helmet)) //lazy method of denying this
|
||||
return
|
||||
else
|
||||
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 = {"
|
||||
<TT>
|
||||
<B>Frequency/Code</B> for shock collar:<BR>
|
||||
|
||||
@@ -107,19 +107,15 @@
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/item/radio/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
|
||||
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.inventory_state)
|
||||
. = ..()
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/radio/ui_state(mob/user)
|
||||
return GLOB.inventory_state
|
||||
|
||||
/obj/item/radio/ui_interact(mob/user, datum/tgui/ui, datum/ui_state/state)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
var/ui_width = 360
|
||||
var/ui_height = 106
|
||||
if(subspace_transmission)
|
||||
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 = new(user, src, "Radio", name)
|
||||
if(state)
|
||||
ui.set_state(state)
|
||||
ui.open()
|
||||
|
||||
/obj/item/radio/ui_data(mob/user)
|
||||
|
||||
@@ -86,98 +86,102 @@ effective or pretty fucking useless.
|
||||
return
|
||||
if(!used)
|
||||
log_combat(user, M, "irradiated", src)
|
||||
var/cooldown = GetCooldown()
|
||||
used = 1
|
||||
var/cooldown = get_cooldown()
|
||||
used = TRUE
|
||||
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>")
|
||||
spawn((wavelength+(intensity*4))*5)
|
||||
if(M)
|
||||
if(intensity >= 5)
|
||||
M.apply_effect(round(intensity/0.075), EFFECT_UNCONSCIOUS)
|
||||
M.rad_act(intensity*10)
|
||||
addtimer(CALLBACK(src, .proc/radiation_aftereffect, M), (wavelength+(intensity*4))*5)
|
||||
else
|
||||
to_chat(user, "<span class='warning'>The radioactive microlaser is still recharging.</span>")
|
||||
|
||||
/obj/item/healthanalyzer/rad_laser/proc/handle_cooldown(cooldown)
|
||||
spawn(cooldown)
|
||||
used = 0
|
||||
icon_state = "health"
|
||||
/obj/item/healthanalyzer/rad_laser/proc/radiation_aftereffect(mob/living/M)
|
||||
if(QDELETED(M))
|
||||
return
|
||||
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)
|
||||
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)
|
||||
ui_interact(user)
|
||||
|
||||
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user)
|
||||
/obj/item/healthanalyzer/rad_laser/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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/healthanalyzer/rad_laser/ui_state(mob/user)
|
||||
return GLOB.hands_state
|
||||
|
||||
/obj/item/healthanalyzer/rad_laser/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
var/dat = "Irradiation: <A href='?src=[REF(src)];rad=1'>[irradiate ? "On" : "Off"]</A><br>"
|
||||
dat += "Stealth Mode (NOTE: Deactivates automatically while Irradiation is off): <A href='?src=[REF(src)];stealthy=[TRUE]'>[stealth ? "On" : "Off"]</A><br>"
|
||||
dat += "Scan Mode: <a href='?src=[REF(src)];mode=1'>"
|
||||
if(!scanmode)
|
||||
dat += "Scan Health"
|
||||
else if(scanmode == 1)
|
||||
dat += "Scan Reagents"
|
||||
else
|
||||
dat += "Disabled"
|
||||
dat += "</a><br><br>"
|
||||
/obj/item/healthanalyzer/rad_laser/ui_data(mob/user)
|
||||
var/list/data = list()
|
||||
data["irradiate"] = irradiate
|
||||
data["stealth"] = stealth
|
||||
data["scanmode"] = scanmode
|
||||
data["intensity"] = intensity
|
||||
data["wavelength"] = wavelength
|
||||
data["on_cooldown"] = used
|
||||
data["cooldown"] = DisplayTimeText(get_cooldown())
|
||||
return data
|
||||
|
||||
dat += {"
|
||||
Radiation Intensity:
|
||||
<A href='?src=[REF(src)];radint=-5'>-</A><A href='?src=[REF(src)];radint=-1'>-</A>
|
||||
[intensity]
|
||||
<A href='?src=[REF(src)];radint=1'>+</A><A href='?src=[REF(src)];radint=5'>+</A><BR>
|
||||
/obj/item/healthanalyzer/rad_laser/ui_act(action, params)
|
||||
if(..())
|
||||
return
|
||||
|
||||
Radiation Wavelength:
|
||||
<A href='?src=[REF(src)];radwav=-5'>-</A><A href='?src=[REF(src)];radwav=-1'>-</A>
|
||||
[(wavelength+(intensity*4))]
|
||||
<A href='?src=[REF(src)];radwav=1'>+</A><A href='?src=[REF(src)];radwav=5'>+</A><BR>
|
||||
Laser Cooldown: [DisplayTimeText(GetCooldown())]<BR>
|
||||
"}
|
||||
|
||||
var/datum/browser/popup = new(user, "radlaser", "Radioactive Microlaser Interface", 400, 240)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/obj/item/healthanalyzer/rad_laser/Topic(href, href_list)
|
||||
if(!usr.canUseTopic(src))
|
||||
return 1
|
||||
|
||||
usr.set_machine(src)
|
||||
if(href_list["rad"])
|
||||
irradiate = !irradiate
|
||||
|
||||
else if(href_list["stealthy"])
|
||||
stealth = !stealth
|
||||
|
||||
else if(href_list["mode"])
|
||||
scanmode += 1
|
||||
if(scanmode > 2)
|
||||
scanmode = 0
|
||||
|
||||
else if(href_list["radint"])
|
||||
var/amount = text2num(href_list["radint"])
|
||||
amount += intensity
|
||||
intensity = max(1,(min(20,amount)))
|
||||
|
||||
else if(href_list["radwav"])
|
||||
var/amount = text2num(href_list["radwav"])
|
||||
amount += wavelength
|
||||
wavelength = max(0,(min(120,amount)))
|
||||
|
||||
attack_self(usr)
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
switch(action)
|
||||
if("irradiate")
|
||||
irradiate = !irradiate
|
||||
. = TRUE
|
||||
if("stealth")
|
||||
stealth = !stealth
|
||||
. = TRUE
|
||||
if("scanmode")
|
||||
scanmode = !scanmode
|
||||
. = TRUE
|
||||
if("radintensity")
|
||||
var/target = params["target"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(target == "min")
|
||||
target = 1
|
||||
. = TRUE
|
||||
else if(target == "max")
|
||||
target = 20
|
||||
. = TRUE
|
||||
else if(adjust)
|
||||
target = intensity + adjust
|
||||
. = TRUE
|
||||
else if(text2num(target) != null)
|
||||
target = text2num(target)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target = round(target)
|
||||
intensity = clamp(target, 1, 20)
|
||||
if("radwavelength")
|
||||
var/target = params["target"]
|
||||
var/adjust = text2num(params["adjust"])
|
||||
if(target == "min")
|
||||
target = 0
|
||||
. = TRUE
|
||||
else if(target == "max")
|
||||
target = 120
|
||||
. = TRUE
|
||||
else if(adjust)
|
||||
target = wavelength + adjust
|
||||
. = TRUE
|
||||
else if(text2num(target) != null)
|
||||
target = text2num(target)
|
||||
. = TRUE
|
||||
if(.)
|
||||
target = round(target)
|
||||
wavelength = clamp(target, 0, 120)
|
||||
|
||||
/obj/item/shadowcloak
|
||||
name = "cloaker belt"
|
||||
|
||||
@@ -188,11 +188,10 @@
|
||||
tank_one.air_contents.merge(temp)
|
||||
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
|
||||
it explodes properly when it gets a signal (and it does).
|
||||
*/
|
||||
|
||||
*/
|
||||
/obj/item/transfer_valve/proc/toggle_valve()
|
||||
if(!valve_open && tank_one && tank_two)
|
||||
valve_open = TRUE
|
||||
@@ -233,16 +232,20 @@
|
||||
valve_open = FALSE
|
||||
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()
|
||||
return
|
||||
|
||||
/obj/item/transfer_valve/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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/transfer_valve/ui_state(mob/user)
|
||||
return GLOB.hands_state
|
||||
|
||||
/obj/item/transfer_valve/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, 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()
|
||||
|
||||
/obj/item/transfer_valve/ui_data(mob/user)
|
||||
|
||||
@@ -192,11 +192,13 @@
|
||||
|
||||
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)
|
||||
ui = new(user, src, ui_key, "EightBallVote", name, 400, 600, master_ui, state)
|
||||
ui = new(user, src, "EightBallVote", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/toy/eightball/haunted/ui_data(mob/user)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
/obj/item/implant/radio/activate()
|
||||
. = ..()
|
||||
// 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)
|
||||
. = ..()
|
||||
|
||||
@@ -26,14 +26,15 @@
|
||||
open_machine()
|
||||
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)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/machinery/implantchair/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "implantchair", name, 375, 280, master_ui, state)
|
||||
ui = new(user, src, "ImplantChair", name)
|
||||
ui.open()
|
||||
|
||||
|
||||
/obj/machinery/implantchair/ui_data()
|
||||
var/list/data = list()
|
||||
data["occupied"] = occupant ? 1 : 0
|
||||
|
||||
@@ -6,21 +6,24 @@
|
||||
desc = "Protected by FRM."
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "cyborg_upgrade"
|
||||
w_class = WEIGHT_CLASS_SMALL
|
||||
var/locked = FALSE
|
||||
var/installed = 0
|
||||
var/require_module = 0
|
||||
var/list/module_type
|
||||
/// Bitflags listing module compatibility. Used in the exosuit fabricator for creating sub-categories.
|
||||
var/module_flags = NONE
|
||||
// if true, is not stored in the robot to be ejected
|
||||
// if module is reset
|
||||
var/one_use = FALSE
|
||||
|
||||
/obj/item/borg/upgrade/proc/action(mob/living/silicon/robot/R, user = usr)
|
||||
if(R.stat == DEAD)
|
||||
to_chat(user, "<span class='notice'>[src] will not function on a deceased cyborg.</span>")
|
||||
to_chat(user, "<span class='warning'>[src] will not function on a deceased cyborg.</span>")
|
||||
return FALSE
|
||||
if(module_type && !is_type_in_list(R.module, module_type))
|
||||
to_chat(R, "Upgrade mounting error! No suitable hardpoint detected!")
|
||||
to_chat(user, "There's no mounting point for the module!")
|
||||
to_chat(R, "<span class='alert'>Upgrade mounting error! No suitable hardpoint detected.</span>")
|
||||
to_chat(user, "<span class='warning'>There's no mounting point for the module!</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
@@ -37,7 +40,7 @@
|
||||
one_use = TRUE
|
||||
|
||||
/obj/item/borg/upgrade/rename/attack_self(mob/user)
|
||||
heldname = stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN)
|
||||
heldname = sanitize_name(stripped_input(user, "Enter new robot name", "Cyborg Reclassification", heldname, MAX_NAME_LEN))
|
||||
|
||||
/obj/item/borg/upgrade/rename/action(mob/living/silicon/robot/R)
|
||||
. = ..()
|
||||
@@ -95,6 +98,7 @@
|
||||
desc = "Used to cool a mounted energy-based firearm, increasing the potential current in it and thus its recharge rate."
|
||||
icon_state = "cyborg_upgrade3"
|
||||
require_module = 1
|
||||
module_flags = BORG_MODULE_SECURITY
|
||||
|
||||
/obj/item/borg/upgrade/disablercooler/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
@@ -147,6 +151,7 @@
|
||||
icon_state = "cyborg_upgrade3"
|
||||
require_module = 1
|
||||
module_type = list(/obj/item/robot_module/miner)
|
||||
module_flags = BORG_MODULE_MINER
|
||||
|
||||
/obj/item/borg/upgrade/ddrill/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
@@ -207,6 +212,7 @@
|
||||
icon_state = "cyborg_upgrade3"
|
||||
require_module = 1
|
||||
module_type = list(/obj/item/robot_module/butler)
|
||||
module_flags = BORG_MODULE_JANITOR
|
||||
|
||||
/obj/item/borg/upgrade/tboh/action(mob/living/silicon/robot/R)
|
||||
. = ..()
|
||||
@@ -234,6 +240,7 @@
|
||||
icon_state = "cyborg_upgrade3"
|
||||
require_module = 1
|
||||
module_type = list(/obj/item/robot_module/butler)
|
||||
module_flags = BORG_MODULE_JANITOR
|
||||
|
||||
/obj/item/borg/upgrade/amop/action(mob/living/silicon/robot/R)
|
||||
. = ..()
|
||||
@@ -283,6 +290,7 @@
|
||||
resistance_flags = LAVA_PROOF | FIRE_PROOF
|
||||
require_module = 1
|
||||
module_type = list(/obj/item/robot_module/miner)
|
||||
module_flags = BORG_MODULE_MINER
|
||||
|
||||
/obj/item/borg/upgrade/lavaproof/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
@@ -402,6 +410,7 @@
|
||||
module_type = list(/obj/item/robot_module/medical,
|
||||
/obj/item/robot_module/syndicate_medical)
|
||||
var/list/additional_reagents = list()
|
||||
module_flags = BORG_MODULE_MEDICAL
|
||||
|
||||
/obj/item/borg/upgrade/hypospray/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
@@ -471,6 +480,7 @@
|
||||
require_module = 1
|
||||
module_type = list(/obj/item/robot_module/medical,
|
||||
/obj/item/robot_module/syndicate_medical)
|
||||
module_flags = BORG_MODULE_MEDICAL
|
||||
|
||||
/obj/item/borg/upgrade/processor/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
@@ -578,6 +588,7 @@
|
||||
icon_state = "borg_BS_RPED"
|
||||
require_module = TRUE
|
||||
module_type = list(/obj/item/robot_module/engineering, /obj/item/robot_module/saboteur)
|
||||
module_flags = BORG_MODULE_ENGINEERING
|
||||
|
||||
/obj/item/borg/upgrade/rped/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
@@ -612,8 +623,8 @@
|
||||
icon = 'icons/obj/device.dmi'
|
||||
icon_state = "pinpointer_crew"
|
||||
require_module = TRUE
|
||||
module_type = list(/obj/item/robot_module/medical,
|
||||
/obj/item/robot_module/syndicate_medical)
|
||||
module_type = list(/obj/item/robot_module/medical, /obj/item/robot_module/syndicate_medical)
|
||||
module_flags = BORG_MODULE_MEDICAL
|
||||
|
||||
/obj/item/borg/upgrade/pinpointer/action(mob/living/silicon/robot/R, user = usr)
|
||||
. = ..()
|
||||
|
||||
@@ -115,14 +115,15 @@
|
||||
|
||||
/obj/item/stack/medical/gauze
|
||||
name = "medical gauze"
|
||||
desc = "A roll of elastic cloth, perfect for stabilizing all kinds of wounds, from cuts and burns, to broken bones. "
|
||||
desc = "A roll of elastic cloth, perfect for stabilizing all kinds of wounds, from cuts and burns to broken bones."
|
||||
gender = PLURAL
|
||||
singular_name = "medical gauze"
|
||||
icon_state = "gauze"
|
||||
heal_brute = 5
|
||||
self_delay = 50
|
||||
other_delay = 20
|
||||
amount = 6
|
||||
amount = 10
|
||||
max_amount = 10
|
||||
absorption_rate = 0.25
|
||||
absorption_capacity = 5
|
||||
splint_factor = 0.35
|
||||
@@ -170,6 +171,14 @@
|
||||
"<span class='notice'>You cut [src] into pieces of cloth with [I].</span>", \
|
||||
"<span class='italics'>You hear cutting.</span>")
|
||||
use(2)
|
||||
else if(I.is_drainable() && I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine))
|
||||
if(!I.reagents.has_reagent(/datum/reagent/space_cleaner/sterilizine, 10))
|
||||
to_chat(user, "<span class='warning'>There's not enough sterilizine in [I] to sterilize [src]!</span>")
|
||||
return
|
||||
user.visible_message("<span class='notice'>[user] pours the contents of [I] onto [src], sterilizing it.</span>", "<span class='notice'>You pour the contents of [I] onto [src], sterilizing it.</span>")
|
||||
I.reagents.remove_reagent(/datum/reagent/space_cleaner/sterilizine, 10)
|
||||
new /obj/item/stack/medical/gauze/adv/one(user.drop_location())
|
||||
use(1)
|
||||
else
|
||||
return ..()
|
||||
|
||||
@@ -181,7 +190,7 @@
|
||||
name = "improvised gauze"
|
||||
singular_name = "improvised gauze"
|
||||
heal_brute = 0
|
||||
desc = "A roll of cloth roughly cut from something that does a decent job of stabilizing wounds, but less efficiently so than real medical gauze."
|
||||
desc = "A roll of cloth roughly cut from something that does a decent job of stabilizing wounds, but less efficiently than real medical gauze."
|
||||
self_delay = 60
|
||||
other_delay = 30
|
||||
absorption_rate = 0.15
|
||||
@@ -189,9 +198,13 @@
|
||||
|
||||
/obj/item/stack/medical/gauze/adv
|
||||
name = "sterilized medical gauze"
|
||||
desc = "A roll of elastic sterilized cloth that is extremely effective at stopping bleeding, heals minor wounds and cleans them."
|
||||
singular_name = "sterilized medical gauze"
|
||||
self_delay = 5
|
||||
desc = "A roll of elastic sterilized cloth that is extremely effective at stopping bleeding and covering burns."
|
||||
heal_brute = 6
|
||||
self_delay = 45
|
||||
other_delay = 15
|
||||
absorption_rate = 0.4
|
||||
absorption_capacity = 6
|
||||
|
||||
/obj/item/stack/medical/gauze/adv/one
|
||||
amount = 1
|
||||
@@ -209,8 +222,8 @@
|
||||
icon_state = "suture"
|
||||
self_delay = 30
|
||||
other_delay = 10
|
||||
amount = 10
|
||||
max_amount = 10
|
||||
amount = 15
|
||||
max_amount = 15
|
||||
repeating = TRUE
|
||||
heal_brute = 10
|
||||
stop_bleeding = 0.6
|
||||
@@ -264,8 +277,8 @@
|
||||
icon_state = "ointment"
|
||||
lefthand_file = 'icons/mob/inhands/equipment/medical_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi'
|
||||
amount = 10
|
||||
max_amount = 10
|
||||
amount = 12
|
||||
max_amount = 12
|
||||
self_delay = 40
|
||||
other_delay = 20
|
||||
|
||||
@@ -295,8 +308,8 @@
|
||||
self_delay = 30
|
||||
other_delay = 10
|
||||
amount = 15
|
||||
heal_burn = 10
|
||||
max_amount = 15
|
||||
heal_burn = 10
|
||||
repeating = TRUE
|
||||
sanitization = 0.75
|
||||
flesh_regeneration = 3
|
||||
|
||||
@@ -335,6 +335,7 @@
|
||||
new /obj/item/reagent_containers/glass/bottle/romerol(src)
|
||||
new /obj/item/reagent_containers/syringe(src)
|
||||
new /obj/item/reagent_containers/dropper(src)
|
||||
new /obj/item/paper/guides/antag/romerol_instructions(src)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/ez_clean/PopulateContents()
|
||||
for(var/i in 1 to 3)
|
||||
|
||||
@@ -164,11 +164,13 @@
|
||||
else
|
||||
. = ..()
|
||||
|
||||
/obj/item/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.hands_state)
|
||||
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
|
||||
/obj/item/tank/ui_state(mob/user)
|
||||
return GLOB.hands_state
|
||||
|
||||
/obj/item/tank/ui_interact(mob/user, datum/tgui/ui)
|
||||
ui = SStgui.try_update_ui(user, src, ui)
|
||||
if(!ui)
|
||||
ui = new(user, src, ui_key, "Tank", name, 400, 120, master_ui, state)
|
||||
ui = new(user, src, "Tank", name)
|
||||
ui.open()
|
||||
|
||||
/obj/item/tank/ui_data(mob/user)
|
||||
@@ -205,10 +207,6 @@
|
||||
else if(pressure == "max")
|
||||
pressure = TANK_MAX_RELEASE_PRESSURE
|
||||
. = TRUE
|
||||
else if(pressure == "input")
|
||||
pressure = input("New release pressure ([TANK_MIN_RELEASE_PRESSURE]-[TANK_MAX_RELEASE_PRESSURE] kPa):", name, distribute_pressure) as num|null
|
||||
if(!isnull(pressure) && !..())
|
||||
. = TRUE
|
||||
else if(text2num(pressure) != null)
|
||||
pressure = text2num(pressure)
|
||||
. = TRUE
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user