@@ -110,6 +110,7 @@
|
||||
#define TRAIT_NOHARDCRIT "nohardcrit"
|
||||
#define TRAIT_NOSOFTCRIT "nosoftcrit"
|
||||
#define TRAIT_MINDSHIELD "mindshield"
|
||||
#define TRAIT_HIJACKER "hijacker"
|
||||
#define TRAIT_SIXTHSENSE "sixthsense"
|
||||
#define TRAIT_DISSECTED "dissected"
|
||||
#define TRAIT_FEARLESS "fearless"
|
||||
|
||||
@@ -544,6 +544,70 @@
|
||||
cooldown = world.time
|
||||
owner.playsound_local(box, 'sound/misc/box_deploy.ogg', 50, TRUE)
|
||||
|
||||
/datum/action/item_action/removeAPCs
|
||||
name = "Relinquish APC"
|
||||
desc = "Let go of an APC, relinquish control back to the station."
|
||||
icon_icon = 'icons/obj/implants.dmi'
|
||||
button_icon_state = "hijackx"
|
||||
|
||||
/datum/action/item_action/removeAPCs/Trigger()
|
||||
var/list/areas = list()
|
||||
for (var/area/a in owner.siliconaccessareas)
|
||||
areas[a.name] = a
|
||||
var/removeAPC = input("Select an APC to remove:","Remove APC Control",1) as null|anything in areas
|
||||
if (!removeAPC)
|
||||
return
|
||||
var/area/area = areas[removeAPC]
|
||||
var/obj/machinery/power/apc/apc = area.get_apc()
|
||||
if (!apc || !(area in owner.siliconaccessareas))
|
||||
return
|
||||
apc.hijacker = null
|
||||
apc.update_icon()
|
||||
apc.set_hijacked_lighting()
|
||||
owner.toggleSiliconAccessArea(area)
|
||||
|
||||
/datum/action/item_action/accessAPCs
|
||||
name = "Access APC Interface"
|
||||
desc = "Open the APC's interface."
|
||||
icon_icon = 'icons/obj/implants.dmi'
|
||||
button_icon_state = "hijacky"
|
||||
|
||||
/datum/action/item_action/accessAPCs/Trigger()
|
||||
var/list/areas = list()
|
||||
for (var/area/a in owner.siliconaccessareas)
|
||||
areas[a.name] = a
|
||||
var/accessAPC = input("Select an APC to access:","Access APC Interface",1) as null|anything in areas
|
||||
if (!accessAPC)
|
||||
return
|
||||
var/area/area = areas[accessAPC]
|
||||
var/obj/machinery/power/apc/apc = area.get_apc()
|
||||
if (!apc || !(area in owner.siliconaccessareas))
|
||||
return
|
||||
apc.ui_interact(owner)
|
||||
|
||||
/datum/action/item_action/stealthmodetoggle
|
||||
name = "Toggle Stealth Mode"
|
||||
desc = "Toggles the stealth mode on the hijack implant."
|
||||
icon_icon = 'icons/obj/implants.dmi'
|
||||
button_icon_state = "hijackz"
|
||||
|
||||
/datum/action/item_action/stealthmodetoggle/Trigger()
|
||||
var/obj/item/implant/hijack/H = target
|
||||
if (!istype(H))
|
||||
return
|
||||
if (H.stealthcooldown > world.time)
|
||||
to_chat(owner,"<span class='warning'>The hijack implant's stealth mode toggle is still rebooting!</span>")
|
||||
return
|
||||
H.stealthmode = !H.stealthmode
|
||||
for (var/area/area in H.imp_in.siliconaccessareas)
|
||||
var/obj/machinery/power/apc/apc = area.get_apc()
|
||||
if (apc)
|
||||
apc.set_hijacked_lighting()
|
||||
apc.update_icon()
|
||||
H.stealthcooldown = world.time + 15 SECONDS
|
||||
H.toggle_eyes()
|
||||
to_chat(owner,"<span class='notice'>You toggle the hijack implant's stealthmode [H.stealthmode ? "on" : "off"].</span>")
|
||||
|
||||
/datum/action/item_action/flash
|
||||
name = "Flash"
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
/datum/wires/airlock/interactable(mob/user)
|
||||
var/obj/machinery/door/airlock/A = holder
|
||||
if(!issilicon(user) && A.isElectrified() && A.shock(user, 100))
|
||||
if(!A.hasSiliconAccessInArea(user) && A.isElectrified() && A.shock(user, 100))
|
||||
return FALSE
|
||||
if(A.panel_open)
|
||||
return TRUE
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
/datum/wires/vending/interactable(mob/user)
|
||||
var/obj/machinery/vending/V = holder
|
||||
if(!issilicon(user) && V.seconds_electrified && V.shock(user, 100))
|
||||
if(!V.hasSiliconAccessInArea(user) && V.seconds_electrified && V.shock(user, 100))
|
||||
return FALSE
|
||||
if(V.panel_open)
|
||||
return TRUE
|
||||
|
||||
@@ -182,7 +182,7 @@
|
||||
|
||||
/obj/machinery/sleeper/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
if(state_open)
|
||||
close_machine()
|
||||
|
||||
@@ -229,7 +229,7 @@ Class Procs:
|
||||
return !(stat & (NOPOWER|BROKEN|MAINT))
|
||||
|
||||
/obj/machinery/can_interact(mob/user)
|
||||
var/silicon = issiliconoradminghost(user)
|
||||
var/silicon = hasSiliconAccessInArea(user) || IsAdminGhost(user)
|
||||
if((stat & (NOPOWER|BROKEN)) && !(interaction_flags_machine & INTERACT_MACHINE_OFFLINE))
|
||||
return FALSE
|
||||
if(panel_open && !(interaction_flags_machine & INTERACT_MACHINE_OPEN))
|
||||
|
||||
@@ -105,7 +105,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
|
||||
/obj/machinery/announcement_system/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
if(stat & BROKEN)
|
||||
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
|
||||
@@ -123,7 +123,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
/obj/machinery/announcement_system/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
if(stat & BROKEN)
|
||||
visible_message("<span class='warning'>[src] buzzes.</span>", "<span class='italics'>You hear a faint buzz.</span>")
|
||||
@@ -132,13 +132,13 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
|
||||
if(href_list["ArrivalTopic"])
|
||||
var/NewMessage = stripped_input(usr, "Enter in the arrivals announcement configuration.", "Arrivals Announcement Config", arrival)
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
if(NewMessage)
|
||||
arrival = NewMessage
|
||||
else if(href_list["NewheadTopic"])
|
||||
var/NewMessage = stripped_input(usr, "Enter in the departmental head announcement configuration.", "Head Departmental Announcement Config", newhead)
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
if(NewMessage)
|
||||
newhead = NewMessage
|
||||
@@ -157,7 +157,7 @@ GLOBAL_LIST_EMPTY(announcement_systems)
|
||||
. = attack_ai(user)
|
||||
|
||||
/obj/machinery/announcement_system/attack_ai(mob/user)
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
if(stat & BROKEN)
|
||||
to_chat(user, "<span class='warning'>[src]'s firmware appears to be malfunctioning!</span>")
|
||||
|
||||
@@ -304,12 +304,12 @@
|
||||
/obj/machinery/computer/arcade/minesweeper/proc/custom_generation(mob/user)
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10) //Entered into the menu so ping sound
|
||||
var/new_rows = input(user, "How many rows do you want? (Minimum: 4, Maximum: 30)", "Minesweeper Rows") as null|num
|
||||
if(!new_rows || !user.canUseTopic(src, !issilicon(user)))
|
||||
if(!new_rows || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return FALSE
|
||||
new_rows = CLAMP(new_rows + 1, 4, 30)
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
|
||||
var/new_columns = input(user, "How many columns do you want? (Minimum: 4, Maximum: 50)", "Minesweeper Squares") as null|num
|
||||
if(!new_columns || !user.canUseTopic(src, !issilicon(user)))
|
||||
if(!new_columns || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return FALSE
|
||||
new_columns = CLAMP(new_columns + 1, 4, 50)
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
|
||||
@@ -317,7 +317,7 @@
|
||||
var/lower_limit = round(grid_area*0.156)
|
||||
var/upper_limit = round(grid_area*0.85)
|
||||
var/new_mine_limit = input(user, "How many mines do you want? (Minimum: [lower_limit], Maximum: [upper_limit])", "Minesweeper Mines") as null|num
|
||||
if(!new_mine_limit || !user.canUseTopic(src, !issilicon(user)))
|
||||
if(!new_mine_limit || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return FALSE
|
||||
playsound(loc, 'sound/arcade/minesweeper_menuselect.ogg', 50, 0, extrarange = -3, falloff = 10)
|
||||
rows = new_rows
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/computer/security/can_interact(mob/user)
|
||||
if((!issilicon(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
|
||||
if((!hasSiliconAccessInArea(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
|
||||
return FALSE
|
||||
return ..()
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
|
||||
/obj/machinery/computer/card/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)) || !is_operational())
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)) || !is_operational())
|
||||
return
|
||||
if(inserted_modify_id)
|
||||
if(id_eject(user, inserted_modify_id))
|
||||
@@ -360,7 +360,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)) || !is_operational())
|
||||
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)) || !is_operational())
|
||||
usr.unset_machine()
|
||||
usr << browse(null, "window=id_com")
|
||||
return
|
||||
@@ -392,7 +392,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
inserted_scan_id = id_to_insert
|
||||
updateUsrDialog()
|
||||
if ("auth")
|
||||
if ((!( authenticated ) && (inserted_scan_id || issilicon(usr)) || mode))
|
||||
if ((!( authenticated ) && (inserted_scan_id || hasSiliconAccessInArea(usr)) || mode))
|
||||
if (check_access(inserted_scan_id))
|
||||
region_access = list()
|
||||
head_subordinates = list()
|
||||
@@ -426,7 +426,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
get_subordinates("Quartermaster")
|
||||
if(region_access)
|
||||
authenticated = 1
|
||||
else if ((!( authenticated ) && issilicon(usr)) && (!inserted_modify_id))
|
||||
else if ((!( authenticated ) && hasSiliconAccessInArea(usr)) && (!inserted_modify_id))
|
||||
to_chat(usr, "<span class='warning'>You can't modify an ID without an ID inserted to modify! Once one is in the modify slot on the computer, you can log in.</span>")
|
||||
if ("logout")
|
||||
region_access = null
|
||||
@@ -481,7 +481,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
|
||||
if ("reg")
|
||||
if (authenticated)
|
||||
var/t2 = inserted_modify_id
|
||||
if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || issilicon(usr)) && isturf(loc)))
|
||||
if ((authenticated && inserted_modify_id == t2 && (in_range(src, usr) || hasSiliconAccessInArea(usr)) && isturf(loc)))
|
||||
var/newName = reject_bad_name(href_list["reg"])
|
||||
if(newName)
|
||||
inserted_modify_id.registered_name = newName
|
||||
|
||||
@@ -449,7 +449,7 @@
|
||||
var/datum/browser/popup = new(user, "communications", "Communications Console", 400, 500)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
|
||||
if(issilicon(user))
|
||||
if(issilicon(user) || (hasSiliconAccessInArea(user) && !in_range(user,src)))
|
||||
var/dat2 = interact_ai(user) // give the AI a different interact proc to limit its access
|
||||
if(dat2)
|
||||
dat += dat2
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
if(!user)
|
||||
return
|
||||
var/datum/browser/popup = new(user, "scannernew", "DNA Modifier Console", 800, 630) // Set up the popup browser window
|
||||
if(!(in_range(src, user) || issilicon(user)))
|
||||
if(!(in_range(src, user) || hasSiliconAccessInArea(user)))
|
||||
popup.close()
|
||||
return
|
||||
popup.add_stylesheet("scannernew", 'html/browser/scannernew.css')
|
||||
@@ -318,7 +318,7 @@
|
||||
return
|
||||
if(!isturf(usr.loc))
|
||||
return
|
||||
if(!((isturf(loc) && in_range(src, usr)) || issilicon(usr)))
|
||||
if(!((isturf(loc) && in_range(src, usr)) || hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
if(current_screen == "working")
|
||||
return
|
||||
|
||||
@@ -190,7 +190,7 @@
|
||||
if(!(active2 in GLOB.data_core.medical))
|
||||
active2 = null
|
||||
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr))
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
|
||||
usr.set_machine(src)
|
||||
if(href_list["temp"])
|
||||
temp = null
|
||||
@@ -216,7 +216,7 @@
|
||||
else if(href_list["login"])
|
||||
var/mob/M = usr
|
||||
var/obj/item/card/id/I = M.get_idcard(TRUE)
|
||||
if(issilicon(M))
|
||||
if(hasSiliconAccessInArea(M))
|
||||
active1 = null
|
||||
active2 = null
|
||||
authenticated = 1
|
||||
@@ -569,7 +569,7 @@
|
||||
if(user)
|
||||
if(message)
|
||||
if(authenticated)
|
||||
if(user.canUseTopic(src, !issilicon(user)))
|
||||
if(user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
if(!record1 || record1 == active1)
|
||||
if(!record2 || record2 == active2)
|
||||
return 1
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
/obj/machinery/computer/pod/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
|
||||
usr.set_machine(src)
|
||||
if(href_list["power"])
|
||||
var/t = text2num(href_list["power"])
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
/obj/machinery/computer/prisoner/management/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
|
||||
usr.set_machine(src)
|
||||
|
||||
if(href_list["id"])
|
||||
|
||||
@@ -265,7 +265,7 @@ What a mess.*/
|
||||
active1 = null
|
||||
if(!( GLOB.data_core.security.Find(active2) ))
|
||||
active2 = null
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr) || IsAdminGhost(usr))
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr) || IsAdminGhost(usr))
|
||||
usr.set_machine(src)
|
||||
switch(href_list["choice"])
|
||||
// SORTING!
|
||||
@@ -299,7 +299,7 @@ What a mess.*/
|
||||
if("Log In")
|
||||
var/mob/M = usr
|
||||
var/obj/item/card/id/I = M.get_idcard(TRUE)
|
||||
if(issilicon(M))
|
||||
if(hasSiliconAccessInArea(M))
|
||||
var/mob/living/silicon/borg = M
|
||||
active1 = null
|
||||
active2 = null
|
||||
@@ -802,7 +802,7 @@ What a mess.*/
|
||||
/obj/machinery/computer/secure_data/proc/canUseSecurityRecordsConsole(mob/user, message1 = 0, record1, record2)
|
||||
if(user)
|
||||
if(authenticated)
|
||||
if(user.canUseTopic(src, !issilicon(user)))
|
||||
if(user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
if(!trim(message1))
|
||||
return 0
|
||||
if(!record1 || record1 == active1)
|
||||
|
||||
@@ -140,7 +140,7 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
|
||||
L[avoid_assoc_duplicate_keys(M.real_name, areaindex)] = M
|
||||
|
||||
var/desc = input("Please select a location to lock in.", "Locking Computer") as null|anything in L
|
||||
if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //check if we are still around
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user), NO_DEXTERY)) //check if we are still around
|
||||
return
|
||||
target = L[desc]
|
||||
if(imp_t)
|
||||
@@ -168,7 +168,7 @@ obj/machinery/computer/teleporter/ui_interact(mob/user, ui_key = "main", datum/t
|
||||
to_chat(user, "<span class='alert'>No active connected stations located.</span>")
|
||||
return
|
||||
var/desc = input("Please select a station to lock in.", "Locking Computer") as null|anything in L
|
||||
if(!user.canUseTopic(src, !issilicon(user), NO_DEXTERY)) //again, check if we are still around
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user), NO_DEXTERY)) //again, check if we are still around
|
||||
return
|
||||
var/obj/machinery/teleport/station/target_station = L[desc]
|
||||
if(!target_station || !target_station.teleporter_hub)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
|
||||
/obj/machinery/jukebox/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
if (!anchored)
|
||||
to_chat(user,"<span class='warning'>This device must be anchored by a wrench!</span>")
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
|
||||
/obj/machinery/dish_drive/AltClick(mob/living/user)
|
||||
. = ..()
|
||||
if(user.canUseTopic(src, !issilicon(user)))
|
||||
if(user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
do_the_dishes(TRUE)
|
||||
return TRUE
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
|
||||
/obj/machinery/dna_scannernew/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
interact(user)
|
||||
return TRUE
|
||||
|
||||
@@ -676,7 +676,7 @@
|
||||
else
|
||||
. += "It looks very robust."
|
||||
|
||||
if(issilicon(user) && (!stat & BROKEN))
|
||||
if(hasSiliconAccessInArea(user) && (!stat & BROKEN))
|
||||
. += "<span class='notice'>Shift-click [src] to [ density ? "open" : "close"] it.</span>"
|
||||
. += "<span class='notice'>Ctrl-click [src] to [ locked ? "raise" : "drop"] its bolts.</span>"
|
||||
. += "<span class='notice'>Alt-click [src] to [ secondsElectrified ? "un-electrify" : "permanently electrify"] it.</span>"
|
||||
@@ -1322,9 +1322,9 @@
|
||||
if(density && !open(2)) //The airlock is still closed, but something prevented it opening. (Another player noticed and bolted/welded the airlock in time!)
|
||||
to_chat(user, "<span class='warning'>Despite your efforts, [src] managed to resist your attempts to open it!</span>")
|
||||
|
||||
/obj/machinery/door/airlock/hostile_lockdown(mob/origin)
|
||||
/obj/machinery/door/airlock/hostile_lockdown(mob/origin, aicontrolneeded = TRUE)
|
||||
// Must be powered and have working AI wire.
|
||||
if(canAIControl(src) && !stat)
|
||||
if((aicontrolneeded && canAIControl(src) && !stat) || !aicontrolneeded)
|
||||
locked = FALSE //For airlocks that were bolted open.
|
||||
safe = FALSE //DOOR CRUSH
|
||||
close()
|
||||
@@ -1334,9 +1334,9 @@
|
||||
LAZYADD(shockedby, "\[[TIME_STAMP("hh:mm:ss", FALSE)]\] [key_name(origin)]")
|
||||
|
||||
|
||||
/obj/machinery/door/airlock/disable_lockdown()
|
||||
/obj/machinery/door/airlock/disable_lockdown(aicontrolneeded = TRUE)
|
||||
// Must be powered and have working AI wire.
|
||||
if(canAIControl(src) && !stat)
|
||||
if((aicontrolneeded && canAIControl(src) && !stat) || !aicontrolneeded)
|
||||
unbolt()
|
||||
set_electrified(NOT_ELECTRIFIED)
|
||||
open()
|
||||
@@ -1528,7 +1528,7 @@
|
||||
. = TRUE
|
||||
|
||||
/obj/machinery/door/airlock/proc/user_allowed(mob/user)
|
||||
return (issilicon(user) && canAIControl(user)) || IsAdminGhost(user)
|
||||
return (hasSiliconAccessInArea(user) && canAIControl(user)) || IsAdminGhost(user)
|
||||
|
||||
/obj/machinery/door/airlock/proc/shock_restore(mob/user)
|
||||
if(!user_allowed(user))
|
||||
|
||||
@@ -514,7 +514,7 @@ GLOBAL_LIST_EMPTY(allCasters)
|
||||
if(active_user && !isobserver(active_user) && get_dist(active_user,src)<=1 && usr!=active_user)
|
||||
to_chat(usr, "<span class='warning'>You must wait for [active_user] to finish and move away.</span>")
|
||||
return
|
||||
if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && isturf(loc))) || issilicon(usr) || isobserver(usr))
|
||||
if ((usr.contents.Find(src) || ((get_dist(src, usr) <= 1) && isturf(loc))) || hasSiliconAccessInArea(usr) || isobserver(usr))
|
||||
usr.set_machine(src)
|
||||
scan_user(usr)
|
||||
if(href_list["set_channel_name"])
|
||||
|
||||
@@ -865,7 +865,7 @@
|
||||
|
||||
/obj/machinery/turretid/examine(mob/user)
|
||||
. = ..()
|
||||
if(issilicon(user) && (!stat & BROKEN))
|
||||
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>"
|
||||
|
||||
@@ -880,7 +880,7 @@
|
||||
to_chat(user, "You link \the [M.buffer] with \the [src]")
|
||||
return
|
||||
|
||||
if (issilicon(user))
|
||||
if (hasSiliconAccessInArea(user))
|
||||
return attack_hand(user)
|
||||
|
||||
if ( get_dist(src, user) == 0 ) // trying to unlock the interface
|
||||
@@ -921,7 +921,7 @@
|
||||
/obj/machinery/turretid/ui_interact(mob/user)
|
||||
. = ..()
|
||||
if ( get_dist(src, user) > 0 )
|
||||
if ( !(issilicon(user) || IsAdminGhost(user)) )
|
||||
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")
|
||||
@@ -929,10 +929,10 @@
|
||||
|
||||
var/t = ""
|
||||
|
||||
if(locked && !(issilicon(user) || IsAdminGhost(user)))
|
||||
if(locked && !(hasSiliconAccessInArea(user) || IsAdminGhost(user)))
|
||||
t += "<div class='notice icon'>Swipe ID card to unlock interface</div>"
|
||||
else
|
||||
if(!issilicon(user) && !IsAdminGhost(user))
|
||||
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>"
|
||||
@@ -946,7 +946,7 @@
|
||||
if(..())
|
||||
return
|
||||
if (locked)
|
||||
if(!(issilicon(usr) || IsAdminGhost(usr)))
|
||||
if(!(hasSiliconAccessInArea(usr) || IsAdminGhost(usr)))
|
||||
to_chat(usr, "Control panel is locked!")
|
||||
return
|
||||
if (href_list["toggleOn"])
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
if(locked && !issilicon(user))
|
||||
if(locked && !hasSiliconAccessInArea(user))
|
||||
to_chat(user, "<span class='warning'>The machine is locked, you are unable to use it!</span>")
|
||||
return
|
||||
if(panel_open)
|
||||
@@ -370,7 +370,7 @@
|
||||
if(!anchored)
|
||||
to_chat(user, "<span class='warning'>\The [src] needs to be firmly secured to the floor first!</span>")
|
||||
return
|
||||
if(locked && !issilicon(user))
|
||||
if(locked && !hasSiliconAccessInArea(user))
|
||||
to_chat(user, "<span class='warning'>The controls are locked!</span>")
|
||||
return
|
||||
if(!power)
|
||||
|
||||
@@ -196,7 +196,7 @@
|
||||
|
||||
var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network)
|
||||
|
||||
if(newnet && ((usr in range(1, src)) || issilicon(usr)))
|
||||
if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr)))
|
||||
if(length(newnet) > 15)
|
||||
temp = "<font color = #D70B00>- FAILED: NETWORK TAG STRING TOO LENGHTLY -</font color>"
|
||||
|
||||
|
||||
@@ -260,7 +260,7 @@
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
|
||||
//Authenticate
|
||||
if (href_list["auth"])
|
||||
if(LINKED_SERVER_NONRESPONSIVE)
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
if(href_list["network"])
|
||||
|
||||
var/newnet = stripped_input(usr, "Which network do you want to view?", "Comm Monitor", network)
|
||||
if(newnet && ((usr in range(1, src)) || issilicon(usr)))
|
||||
if(newnet && ((usr in range(1, src)) || hasSiliconAccessInArea(usr)))
|
||||
if(length(newnet) > 15)
|
||||
temp = "<font color = #D70B00>- FAILED: NETWORK TAG STRING TOO LENGHTLY -</font color>"
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
/obj/machinery/telecomms/ui_interact(mob/user)
|
||||
. = ..()
|
||||
// You need a multitool to use this, or be silicon
|
||||
if(!issilicon(user))
|
||||
if(!hasSiliconAccessInArea(user))
|
||||
// istype returns false if the value is null
|
||||
if(!istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
return
|
||||
@@ -97,7 +97,7 @@
|
||||
|
||||
var/obj/item/multitool/P = null
|
||||
// Let's double check
|
||||
if(!issilicon(user) && istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
if(!hasSiliconAccessInArea(user) && istype(user.get_active_held_item(), /obj/item/multitool))
|
||||
P = user.get_active_held_item()
|
||||
else if(isAI(user))
|
||||
var/mob/living/silicon/ai/U = user
|
||||
@@ -162,7 +162,7 @@
|
||||
if(..())
|
||||
return
|
||||
|
||||
if(!issilicon(usr))
|
||||
if(!hasSiliconAccessInArea(usr))
|
||||
if(!istype(usr.get_active_held_item(), /obj/item/multitool))
|
||||
return
|
||||
|
||||
@@ -270,6 +270,6 @@
|
||||
updateUsrDialog()
|
||||
|
||||
/obj/machinery/telecomms/proc/canAccess(mob/user)
|
||||
if(issilicon(user) || in_range(user, src))
|
||||
if(hasSiliconAccessInArea(user) || in_range(user, src))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
/obj/machinery/transformer/examine(mob/user)
|
||||
. = ..()
|
||||
if(cooldown && (issilicon(user) || isobserver(user)))
|
||||
if(cooldown && (hasSiliconAccessInArea(user) || isobserver(user)))
|
||||
. += "It will be ready in [DisplayTimeText(cooldown_timer - world.time)]."
|
||||
|
||||
/obj/machinery/transformer/Destroy()
|
||||
|
||||
@@ -721,7 +721,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
return
|
||||
|
||||
/obj/item/pda/proc/remove_id(mob/user)
|
||||
if(issilicon(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
if(hasSiliconAccessInArea(user) || !user.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
do_remove_id(user)
|
||||
|
||||
@@ -916,7 +916,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
remove_pen()
|
||||
|
||||
/obj/item/pda/proc/toggle_light()
|
||||
if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE))
|
||||
if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE))
|
||||
return
|
||||
if(fon)
|
||||
fon = FALSE
|
||||
@@ -928,7 +928,7 @@ GLOBAL_LIST_EMPTY(PDAs)
|
||||
|
||||
/obj/item/pda/proc/remove_pen()
|
||||
|
||||
if(issilicon(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
if(hasSiliconAccessInArea(usr) || !usr.canUseTopic(src, BE_CLOSE, FALSE, NO_TK))
|
||||
return
|
||||
|
||||
if(inserted_item)
|
||||
|
||||
@@ -609,7 +609,7 @@ Code:
|
||||
/obj/item/cartridge/Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
usr.unset_machine()
|
||||
usr << browse(null, "window=pda")
|
||||
return
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
#define HIJACK_APC_MAX_AMOUNT 5
|
||||
|
||||
/obj/item/implant/hijack
|
||||
name = "hijack implant"
|
||||
desc = "Allows you to control the machinery in a room by hacking into the APC."
|
||||
actions_types = list(/datum/action/item_action/hands_free/activate, /datum/action/item_action/removeAPCs, /datum/action/item_action/accessAPCs, /datum/action/item_action/stealthmodetoggle)
|
||||
activated = 1
|
||||
var/toggled = FALSE
|
||||
icon_state = "hijack"
|
||||
var/eye_color
|
||||
var/stealthmode = FALSE
|
||||
var/stealthcooldown = 0
|
||||
var/hijacking = FALSE
|
||||
|
||||
/obj/item/implant/hijack/activate()
|
||||
. = ..()
|
||||
toggled = !toggled
|
||||
imp_in.click_intercept = toggled ? src : null
|
||||
imp_in.siliconaccesstoggle = toggled ? TRUE : FALSE
|
||||
to_chat(imp_in,"<span class='notice'>You turn [toggled ? "on" : "off"] [src]'s silicon interactions.</span>")
|
||||
toggle_eyes()
|
||||
|
||||
/obj/item/implant/hijack/proc/toggle_eyes()
|
||||
if (!ishuman(imp_in))
|
||||
return
|
||||
var/on = toggled && !stealthmode
|
||||
var/mob/living/carbon/human/H = imp_in
|
||||
H.eye_color = on ? "ff0" : eye_color
|
||||
H.dna.update_ui_block(DNA_EYE_COLOR_BLOCK)
|
||||
H.update_body()
|
||||
|
||||
/obj/item/implant/hijack/implant(mob/living/target, mob/user, silent = FALSE)
|
||||
if(..())
|
||||
ADD_TRAIT(target, TRAIT_HIJACKER, "implant")
|
||||
if (ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
eye_color = H.eye_color
|
||||
return TRUE
|
||||
|
||||
/obj/item/implant/hijack/removed(mob/target, silent = FALSE, special = 0)
|
||||
if(..())
|
||||
REMOVE_TRAIT(target, TRAIT_HIJACKER, "implant")
|
||||
for (var/area/area in imp_in.siliconaccessareas)
|
||||
imp_in.toggleSiliconAccessArea(area)
|
||||
var/obj/machinery/power/apc/apc = area.get_apc()
|
||||
if (apc)
|
||||
apc.hijacker = null
|
||||
apc.set_hijacked_lighting()
|
||||
apc.update_icon()
|
||||
if (ishuman(target))
|
||||
var/mob/living/carbon/human/H = target
|
||||
H.eye_color = eye_color
|
||||
return TRUE
|
||||
|
||||
/obj/item/implant/hijack/proc/InterceptClickOn(mob/living/user,params,atom/object)
|
||||
if (isitem(object) || !toggled || user.incapacitated())
|
||||
return
|
||||
if (stealthmode == FALSE && istype(object,/obj/machinery/power/apc) && !user.CanReach(object))
|
||||
if (hijack_remotely(object))
|
||||
return
|
||||
if (stealthmode && !user.CanReach(object))
|
||||
return
|
||||
if (!object.hasSiliconAccessInArea(imp_in))
|
||||
return
|
||||
var/list/modifiers = params2list(params)
|
||||
imp_in.face_atom(object)
|
||||
if (modifiers["shift"] && modifiers["ctrl"])
|
||||
object.AICtrlShiftClick(imp_in)
|
||||
return TRUE
|
||||
if (modifiers["shift"])
|
||||
object.AIShiftClick(imp_in)
|
||||
return TRUE
|
||||
if (modifiers["ctrl"])
|
||||
object.AICtrlClick(imp_in)
|
||||
return TRUE
|
||||
if (modifiers["alt"])
|
||||
object.AIAltClick(imp_in)
|
||||
return TRUE
|
||||
if (user.get_active_held_item())
|
||||
return
|
||||
if (user.CanReach(object))
|
||||
object.attack_robot(imp_in)
|
||||
else
|
||||
object.attack_ai(imp_in)
|
||||
return TRUE
|
||||
|
||||
/obj/item/implant/hijack/proc/hijack_remotely(obj/machinery/power/apc/apc)
|
||||
if (apc.hijacker || hijacking)
|
||||
return FALSE //can't remotely hijack an already hijacked APC
|
||||
hijacking = TRUE
|
||||
to_chat(imp_in, "<span class='notice'>Establishing remote connection with APC.</span>")
|
||||
if (!do_after(imp_in, 4 SECONDS,target=apc))
|
||||
to_chat(imp_in, "<span class='warning'>Aborting.</span>")
|
||||
hijacking = FALSE
|
||||
return TRUE
|
||||
if (LAZYLEN(imp_in.siliconaccessareas) >= HIJACK_APC_MAX_AMOUNT)
|
||||
to_chat(src,"<span class='warning'>You are connected to too many APCs! Too many more will fry your brain.</span>")
|
||||
hijacking = FALSE
|
||||
return TRUE
|
||||
imp_in.light_power = 2
|
||||
imp_in.light_range = 2
|
||||
imp_in.light_color = COLOR_YELLOW
|
||||
imp_in.update_light()
|
||||
imp_in.visible_message("<span class='warning'>[imp_in] starts glowing a with a hollow yellow light!</span>")
|
||||
to_chat(imp_in, "<span class='notice'>Beginning hijack of APC.</span>")
|
||||
if (do_after(imp_in, 21 SECONDS,target=apc))
|
||||
apc.hijacker = imp_in
|
||||
stealthmode = FALSE
|
||||
apc.set_hijacked_lighting()
|
||||
imp_in.toggleSiliconAccessArea(apc.area)
|
||||
apc.update_icon()
|
||||
stealthcooldown = world.time + 1 MINUTES + 30 SECONDS
|
||||
toggle_eyes()
|
||||
else
|
||||
to_chat(imp_in, "<span class='warning'>Aborting.</span>")
|
||||
hijacking = FALSE
|
||||
imp_in.light_power = 0
|
||||
imp_in.light_range = 0
|
||||
imp_in.light_color = COLOR_YELLOW
|
||||
imp_in.update_light()
|
||||
return TRUE
|
||||
@@ -74,4 +74,8 @@
|
||||
|
||||
/obj/item/implanter/stealth
|
||||
name = "implanter (stealth)"
|
||||
imp_type = /obj/item/implant/stealth
|
||||
imp_type = /obj/item/implant/stealth
|
||||
|
||||
/obj/item/implanter/hijack
|
||||
name = "implanter (hijack)"
|
||||
imp_type = /obj/item/implant/hijack
|
||||
@@ -125,7 +125,7 @@
|
||||
if ((M.client && M.machine == src))
|
||||
is_in_use = TRUE
|
||||
ui_interact(M)
|
||||
if(isAI(usr) || iscyborg(usr) || IsAdminGhost(usr))
|
||||
if(isAI(usr) || iscyborg(usr) || IsAdminGhost(usr) || hasSiliconAccessInArea(usr))
|
||||
if (!(usr in nearby))
|
||||
if (usr.client && usr.machine==src) // && M.machine == src is omitted because if we triggered this by using the dialog, it doesn't matter if our machine changed in between triggering it and this - the dialog is probably still supposed to refresh.
|
||||
is_in_use = TRUE
|
||||
|
||||
@@ -168,7 +168,7 @@ GLOBAL_LIST_EMPTY(bodycontainers) //Let them act as spawnpoints for revenants an
|
||||
|
||||
/obj/structure/bodycontainer/morgue/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)))
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
beeper = !beeper
|
||||
to_chat(user, "<span class='notice'>You turn the speaker function [beeper ? "on" : "off"].</span>")
|
||||
|
||||
@@ -245,7 +245,7 @@
|
||||
/obj/machinery/airalarm/ui_data(mob/user)
|
||||
var/data = list(
|
||||
"locked" = locked,
|
||||
"siliconUser" = user.has_unlimited_silicon_privilege,
|
||||
"siliconUser" = user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user),
|
||||
"emagged" = (obj_flags & EMAGGED ? 1 : 0),
|
||||
"danger_level" = danger_level,
|
||||
)
|
||||
@@ -288,7 +288,7 @@
|
||||
"danger_level" = cur_tlv.get_danger_level(environment.gases[gas_id] * partial_pressure)
|
||||
))
|
||||
|
||||
if(!locked || user.has_unlimited_silicon_privilege)
|
||||
if(!locked || user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user))
|
||||
data["vents"] = list()
|
||||
for(var/id_tag in A.air_vent_names)
|
||||
var/long_name = A.air_vent_names[id_tag]
|
||||
@@ -368,7 +368,7 @@
|
||||
/obj/machinery/airalarm/ui_act(action, params)
|
||||
if(..() || buildstage != 2)
|
||||
return
|
||||
if((locked && !usr.has_unlimited_silicon_privilege) || (usr.has_unlimited_silicon_privilege && aidisabled))
|
||||
if((locked && !usr.has_unlimited_silicon_privilege && !hasSiliconAccessInArea(usr)) || (usr.has_unlimited_silicon_privilege && aidisabled))
|
||||
return
|
||||
var/device_id = params["id_tag"]
|
||||
switch(action)
|
||||
@@ -840,7 +840,7 @@
|
||||
|
||||
/obj/machinery/airalarm/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc))
|
||||
if(!user.canUseTopic(src, !hasSiliconAccessInArea(user)) || !isturf(loc))
|
||||
return
|
||||
togglelock(user)
|
||||
return TRUE
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
return
|
||||
if(reload < reload_cooldown)
|
||||
return
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || issilicon(usr))
|
||||
if(usr.contents.Find(src) || (in_range(src, usr) && isturf(loc)) || hasSiliconAccessInArea(usr))
|
||||
priority_announce("Bluespace artillery fire detected. Brace for impact.")
|
||||
message_admins("[ADMIN_LOOKUPFLW(usr)] has launched an artillery strike.")
|
||||
var/list/L = list()
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
|
||||
/obj/item/supplypod_beacon/AltClick(mob/user)
|
||||
. = ..()
|
||||
if (!user.canUseTopic(src, !issilicon(user)))
|
||||
if (!user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
if (express_console)
|
||||
unlink_console()
|
||||
|
||||
@@ -140,7 +140,7 @@
|
||||
/obj/item/valentine/examine(mob/user)
|
||||
. = ..()
|
||||
if(in_range(user, src) || isobserver(user))
|
||||
if( !(ishuman(user) || isobserver(user) || issilicon(user)) )
|
||||
if( !(ishuman(user) || isobserver(user) || hasSiliconAccessInArea(user)) )
|
||||
user << browse("<HTML><HEAD><TITLE>[name]</TITLE></HEAD><BODY>[stars(message)]</BODY></HTML>", "window=[name]")
|
||||
onclose(user, "[name]")
|
||||
else
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
if(!operating)
|
||||
. += "<span class='notice'>Alt-click [src] to turn it on.</span>"
|
||||
|
||||
if(!in_range(user, src) && !issilicon(user) && !isobserver(user))
|
||||
if(!in_range(user, src) && !hasSiliconAccessInArea(user) && !isobserver(user))
|
||||
. += "<span class='warning'>You're too far away to examine [src]'s contents and display!</span>"
|
||||
return
|
||||
if(operating)
|
||||
@@ -63,7 +63,7 @@
|
||||
return
|
||||
|
||||
if(length(ingredients))
|
||||
if(issilicon(user))
|
||||
if(hasSiliconAccessInArea(user))
|
||||
. += "<span class='notice'>\The [src] camera shows:</span>"
|
||||
else
|
||||
. += "<span class='notice'>\The [src] contains:</span>"
|
||||
@@ -187,14 +187,14 @@
|
||||
|
||||
/obj/machinery/microwave/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(user.canUseTopic(src, !issilicon(usr)))
|
||||
if(user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
cook()
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/microwave/ui_interact(mob/user)
|
||||
. = ..()
|
||||
|
||||
if(operating || panel_open || !anchored || !user.canUseTopic(src, !issilicon(user)))
|
||||
if(operating || panel_open || !anchored || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
if(isAI(user) && (stat & NOPOWER))
|
||||
return
|
||||
@@ -206,10 +206,10 @@
|
||||
to_chat(user, "<span class='warning'>\The [src] is empty.</span>")
|
||||
return
|
||||
|
||||
var/choice = show_radial_menu(user, src, isAI(user) ? ai_radial_options : radial_options, require_near = !issilicon(user))
|
||||
var/choice = show_radial_menu(user, src, isAI(user) ? ai_radial_options : radial_options, require_near = !hasSiliconAccessInArea(user))
|
||||
|
||||
// post choice verification
|
||||
if(operating || panel_open || !anchored || !user.canUseTopic(src, !issilicon(user)))
|
||||
if(operating || panel_open || !anchored || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
if(isAI(user) && (stat & NOPOWER))
|
||||
return
|
||||
|
||||
@@ -92,7 +92,7 @@
|
||||
data["emagged"] = TRUE
|
||||
data["emag_programs"] = emag_programs
|
||||
data["program"] = program
|
||||
data["can_toggle_safety"] = issilicon(user) || IsAdminGhost(user)
|
||||
data["can_toggle_safety"] = hasSiliconAccessInArea(user) || IsAdminGhost(user)
|
||||
|
||||
return data
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
if(A)
|
||||
load_program(A)
|
||||
if("safety")
|
||||
if(!issilicon(usr) && !IsAdminGhost(usr))
|
||||
if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr))
|
||||
var/msg = "[key_name(usr)] attempted to emag the holodeck using a href they shouldn't have!"
|
||||
message_admins(msg)
|
||||
log_admin(msg)
|
||||
|
||||
@@ -105,7 +105,7 @@
|
||||
return
|
||||
|
||||
var/datum/browser/popup = new(user, "plantdna", "Plant DNA Manipulator", 450, 600)
|
||||
if(!(in_range(src, user) || issilicon(user)))
|
||||
if(!(in_range(src, user) || hasSiliconAccessInArea(user)))
|
||||
popup.close()
|
||||
return
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
interact(user)
|
||||
|
||||
/obj/item/integrated_circuit_printer/interact(mob/user)
|
||||
if(!(in_range(src, user) || issilicon(user)))
|
||||
if(!(in_range(src, user) || hasSiliconAccessInArea(user)))
|
||||
return
|
||||
|
||||
if(isnull(current_category))
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
//check if it doesn't require any access at all
|
||||
if(src.check_access(null))
|
||||
return TRUE
|
||||
if(issilicon(M))
|
||||
if(hasSiliconAccessInArea(M))
|
||||
if(ispAI(M))
|
||||
return FALSE
|
||||
return TRUE //AI can do whatever it wants
|
||||
|
||||
@@ -99,6 +99,10 @@
|
||||
. += "[t_He] [t_has] [glasses.get_examine_string(user)] covering [t_his] eyes."
|
||||
else if(eye_color == BLOODCULT_EYE && iscultist(src) && HAS_TRAIT(src, TRAIT_CULT_EYES))
|
||||
. += "<span class='warning'><B>[t_His] eyes are glowing an unnatural red!</B></span>"
|
||||
else if(HAS_TRAIT(src, TRAIT_HIJACKER))
|
||||
var/obj/item/implant/hijack/H = user.getImplant(/obj/item/implant/hijack)
|
||||
if (H && !H.stealthmode && H.toggled)
|
||||
. += "<b><font color=orange>[t_His] eyes are flickering a bright yellow!</font></b>"
|
||||
|
||||
//ears
|
||||
if(ears && !(SLOT_EARS in obscured))
|
||||
|
||||
@@ -810,14 +810,14 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
|
||||
switch(href_list["operation"])
|
||||
if("patrol")
|
||||
if(!issilicon(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
|
||||
if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
|
||||
return TRUE
|
||||
auto_patrol = !auto_patrol
|
||||
bot_reset()
|
||||
if("remote")
|
||||
remote_disabled = !remote_disabled
|
||||
if("hack")
|
||||
if(!issilicon(usr) && !IsAdminGhost(usr))
|
||||
if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr))
|
||||
var/msg = "[key_name(usr)] attempted to hack a bot with a href that shouldn't be available!"
|
||||
message_admins(msg)
|
||||
log_admin(msg)
|
||||
@@ -836,7 +836,7 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
to_chat(usr, "<span class='notice'>[text_dehack]</span>")
|
||||
bot_reset()
|
||||
if("ejectpai")
|
||||
if(paicard && (!locked || issilicon(usr) || IsAdminGhost(usr)))
|
||||
if(paicard && (!locked || hasSiliconAccessInArea(usr) || IsAdminGhost(usr)))
|
||||
to_chat(usr, "<span class='notice'>You eject [paicard] from [bot_name]</span>")
|
||||
ejectpai(usr)
|
||||
update_controls()
|
||||
@@ -863,13 +863,13 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
if(emagged == 2) //An emagged bot cannot be controlled by humans, silicons can if one hacked it.
|
||||
if(!hacked) //Manually emagged by a human - access denied to all.
|
||||
return TRUE
|
||||
else if(!issilicon(user) && !IsAdminGhost(user)) //Bot is hacked, so only silicons and admins are allowed access.
|
||||
else if(!hasSiliconAccessInArea(user) && !IsAdminGhost(user)) //Bot is hacked, so only silicons and admins are allowed access.
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/bot/proc/hack(mob/user)
|
||||
var/hack
|
||||
if(issilicon(user) || IsAdminGhost(user)) //Allows silicons or admins to toggle the emag status of a bot.
|
||||
if(hasSiliconAccessInArea(user) || IsAdminGhost(user)) //Allows silicons or admins to toggle the emag status of a bot.
|
||||
hack += "[emagged == 2 ? "Software compromised! Unit may exhibit dangerous or erratic behavior." : "Unit operating normally. Release safety lock?"]<BR>"
|
||||
hack += "Harm Prevention Safety System: <A href='?src=[REF(src)];operation=hack'>[emagged ? "<span class='bad'>DANGER</span>" : "Engaged"]</A><BR>"
|
||||
else if(!locked) //Humans with access can use this option to hide a bot from the AI's remote control panel and PDA control.
|
||||
@@ -878,7 +878,7 @@ Pass a positive integer as an argument to override a bot's default speed.
|
||||
|
||||
/mob/living/simple_animal/bot/proc/showpai(mob/user)
|
||||
var/eject = ""
|
||||
if((!locked || issilicon(usr) || IsAdminGhost(usr)))
|
||||
if((!locked || hasSiliconAccessInArea(usr) || IsAdminGhost(usr)))
|
||||
if(paicard || allow_pai)
|
||||
eject += "Personality card status: "
|
||||
if(paicard)
|
||||
|
||||
@@ -298,7 +298,7 @@
|
||||
Status: <A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A><BR>
|
||||
Behaviour controls are [locked ? "locked" : "unlocked"]<BR>
|
||||
Maintenance panel panel is [open ? "opened" : "closed"]"})
|
||||
if(!locked || issilicon(user)|| IsAdminGhost(user))
|
||||
if(!locked || hasSiliconAccessInArea(user)|| IsAdminGhost(user))
|
||||
dat += "<BR>Clean Blood: <A href='?src=[REF(src)];operation=blood'>[blood ? "Yes" : "No"]</A>"
|
||||
dat += "<BR>Clean Trash: <A href='?src=[REF(src)];operation=trash'>[trash ? "Yes" : "No"]</A>"
|
||||
dat += "<BR>Exterminate Pests: <A href='?src=[REF(src)];operation=pests'>[pests ? "Yes" : "No"]</A>"
|
||||
|
||||
@@ -110,7 +110,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]<BR>"},
|
||||
|
||||
"<A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A>" )
|
||||
|
||||
if(!locked || issilicon(user)|| IsAdminGhost(user))
|
||||
if(!locked || hasSiliconAccessInArea(user)|| IsAdminGhost(user))
|
||||
if(!lasercolor)
|
||||
dat += text({"<BR>
|
||||
Arrest Unidentifiable Persons: []<BR>
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
dat += "Maintenance panel panel is [open ? "opened" : "closed"]<BR>"
|
||||
|
||||
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
|
||||
if(!locked || issilicon(user) || IsAdminGhost(user))
|
||||
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
|
||||
dat += "Extinguish Fires: <A href='?src=[REF(src)];operation=extinguish_fires'>[extinguish_fires ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Extinguish People: <A href='?src=[REF(src)];operation=extinguish_people'>[extinguish_people ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Patrol Station: <A href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "Yes" : "No"]</A><BR>"
|
||||
|
||||
@@ -83,7 +83,7 @@
|
||||
dat += "None Loaded<BR>"
|
||||
|
||||
dat += "Behaviour controls are [locked ? "locked" : "unlocked"]<BR>"
|
||||
if(!locked || issilicon(user) || IsAdminGhost(user))
|
||||
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
|
||||
dat += "Add tiles to new hull plating: <A href='?src=[REF(src)];operation=autotile'>[autotile ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Place floor tiles: <A href='?src=[REF(src)];operation=place'>[placetiles ? "Yes" : "No"]</A><BR>"
|
||||
dat += "Replace existing floor tiles with custom tiles: <A href='?src=[REF(src)];operation=replace'>[replacetiles ? "Yes" : "No"]</A><BR>"
|
||||
|
||||
@@ -90,7 +90,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
|
||||
"<A href='?src=[REF(src)];power=[TRUE]'>[on ? "On" : "Off"]</A>" )
|
||||
|
||||
if(!locked || issilicon(user) || IsAdminGhost(user))
|
||||
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
|
||||
dat += text({"<BR> Auto Patrol: []"},
|
||||
|
||||
"<A href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "On" : "Off"]</A>" )
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
else
|
||||
dat += "None Loaded"
|
||||
dat += "<br>Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
|
||||
if(!locked || issilicon(user) || IsAdminGhost(user))
|
||||
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
|
||||
dat += "<TT>Healing Threshold: "
|
||||
dat += "<a href='?src=[REF(src)];adj_threshold=-10'>--</a> "
|
||||
dat += "<a href='?src=[REF(src)];adj_threshold=-5'>-</a> "
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
|
||||
// TODO: remove this; PDAs currently depend on it
|
||||
/mob/living/simple_animal/bot/mulebot/get_controls(mob/user)
|
||||
var/ai = issilicon(user)
|
||||
var/ai = hasSiliconAccessInArea(user)
|
||||
var/dat
|
||||
dat += "<h3>Multiple Utility Load Effector Mk. V</h3>"
|
||||
dat += "<b>ID:</b> [id]<BR>"
|
||||
|
||||
@@ -110,7 +110,7 @@ Maintenance panel panel is [open ? "opened" : "closed"]"},
|
||||
|
||||
"<A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A>" )
|
||||
|
||||
if(!locked || issilicon(user) || IsAdminGhost(user))
|
||||
if(!locked || hasSiliconAccessInArea(user) || IsAdminGhost(user))
|
||||
dat += text({"<BR>
|
||||
Arrest Unidentifiable Persons: []<BR>
|
||||
Arrest for Unauthorized Weapons: []<BR>
|
||||
@@ -131,7 +131,7 @@ Auto Patrol: []"},
|
||||
/mob/living/simple_animal/bot/secbot/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
if(!issilicon(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
|
||||
if(!hasSiliconAccessInArea(usr) && !IsAdminGhost(usr) && !(bot_core.allowed(usr) || !locked))
|
||||
return TRUE
|
||||
switch(href_list["operation"])
|
||||
if("idcheck")
|
||||
|
||||
@@ -808,7 +808,7 @@ GLOBAL_VAR_INIT(exploit_warn_spam_prevention, 0)
|
||||
|
||||
//Can the mob interact() with an atom?
|
||||
/mob/proc/can_interact_with(atom/A)
|
||||
return IsAdminGhost(src) || Adjacent(A)
|
||||
return IsAdminGhost(src) || Adjacent(A) || A.hasSiliconAccessInArea(src)
|
||||
|
||||
//Can the mob use Topic to interact with machines
|
||||
/mob/proc/canUseTopic(atom/movable/M, be_close=FALSE, no_dextery=FALSE, no_tk=FALSE)
|
||||
|
||||
@@ -121,4 +121,7 @@
|
||||
|
||||
var/mob/audiovisual_redirect //Mob to redirect messages, speech, and sounds to
|
||||
|
||||
var/voluntary_ghosted = FALSE //whether or not they voluntarily ghosted.
|
||||
var/siliconaccessareas = list()
|
||||
var/siliconaccesstoggle = FALSE
|
||||
|
||||
var/voluntary_ghosted = FALSE //whether or not they voluntarily ghosted.
|
||||
@@ -402,6 +402,32 @@ It's fairly easy to fix if dealing with single letters but not so much with comp
|
||||
return
|
||||
return TRUE
|
||||
|
||||
/atom/proc/hasSiliconAccessInArea(mob/user)
|
||||
return user && (issilicon(user) || (user.siliconaccesstoggle && (get_area(src) in user.siliconaccessareas)))
|
||||
|
||||
/mob/proc/toggleSiliconAccessArea(area/area)
|
||||
if (area in siliconaccessareas)
|
||||
siliconaccessareas -= area
|
||||
to_chat(src,"<span class='warning'>You lost control of [area]!</span>")
|
||||
return FALSE
|
||||
else
|
||||
if (LAZYLEN(siliconaccessareas) < HIJACK_APC_MAX_AMOUNT)
|
||||
siliconaccessareas += area
|
||||
to_chat(src,"<span class='notice'>You successfully took control of [area].</span>")
|
||||
else
|
||||
to_chat(src,"<span class='warning'>You are connected to too many APCs! Too many more will fry your brain.</span>")
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/mob/proc/getImplant(type)
|
||||
if (!istype(src,/mob/living))
|
||||
return
|
||||
var/mob/living/L = src
|
||||
for (var/I in L.implants)
|
||||
if (istype(I,type))
|
||||
return I
|
||||
return null
|
||||
|
||||
/proc/canGhostWrite(var/mob/A, var/obj/target, var/desc="", var/allow_all=FALSE)
|
||||
if(allow_all & TRUE)
|
||||
if(!target.GetComponent(/datum/component/anti_magic))
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
return 0
|
||||
|
||||
// Robots don't really need to see the screen, their wireless connection works as long as computer is on.
|
||||
if(!screen_on && !issilicon(user))
|
||||
if(!screen_on && !hasSiliconAccessInArea(user))
|
||||
if(ui)
|
||||
ui.close()
|
||||
return 0
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
if(IsAdminGhost(user))
|
||||
return TRUE
|
||||
|
||||
if(issilicon(user))
|
||||
if(computer && computer.hasSiliconAccessInArea(user))
|
||||
return TRUE
|
||||
|
||||
if(ishuman(user))
|
||||
|
||||
@@ -35,9 +35,9 @@
|
||||
return ..()
|
||||
|
||||
/obj/machinery/oui_canview(mob/user)
|
||||
if(user.has_unlimited_silicon_privilege)
|
||||
if(user.has_unlimited_silicon_privilege || hasSiliconAccessInArea(user))
|
||||
return TRUE
|
||||
if(!can_interact())
|
||||
if(!can_interact(user))
|
||||
return FALSE
|
||||
if(iscyborg(user))
|
||||
return can_see(user, src, 7)
|
||||
|
||||
+113
-24
@@ -106,6 +106,8 @@
|
||||
var/update_overlay = -1
|
||||
var/icon_update_needed = FALSE
|
||||
var/obj/machinery/computer/apc_control/remote_control = null
|
||||
var/mob/living/carbon/hijacker
|
||||
var/hijackerlast = FALSE
|
||||
|
||||
/obj/machinery/power/apc/unlocked
|
||||
locked = FALSE
|
||||
@@ -260,7 +262,7 @@
|
||||
|
||||
. += "<span class='notice'>Alt-Click the APC to [ locked ? "unlock" : "lock"] the interface.</span>"
|
||||
|
||||
if(issilicon(user))
|
||||
if(area.hasSiliconAccessInArea(user))
|
||||
. += "<span class='notice'>Ctrl-Click the APC to switch the breaker [ operating ? "off" : "on"].</span>"
|
||||
|
||||
// update the APC icon to show the three base states
|
||||
@@ -299,12 +301,15 @@
|
||||
|
||||
if(!(update_state & UPSTATE_ALLGOOD))
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
|
||||
var/hijackerreturn
|
||||
if (hijacker)
|
||||
var/obj/item/implant/hijack/H = hijacker.getImplant(/obj/item/implant/hijack)
|
||||
hijackerreturn = H && !H.stealthmode
|
||||
if(update & 2)
|
||||
SSvis_overlays.remove_vis_overlay(src, managed_vis_overlays)
|
||||
if(!(stat & (BROKEN|MAINT)) && update_state & UPSTATE_ALLGOOD)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "apcox-[locked]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "apco3-[charging]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "apco3-[hijackerreturn ? "3" : charging]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
if(operating)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "apco0-[equipment]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
SSvis_overlays.add_vis_overlay(src, icon, "apco1-[lighting]", ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE, dir)
|
||||
@@ -319,6 +324,8 @@
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
if(APC_FULLY_CHARGED)
|
||||
light_color = LIGHT_COLOR_GREEN
|
||||
if (hijackerreturn)
|
||||
light_color = LIGHT_COLOR_YELLOW
|
||||
set_light(lon_range)
|
||||
else if(update_state & UPSTATE_BLUESCREEN)
|
||||
light_color = LIGHT_COLOR_BLUE
|
||||
@@ -387,14 +394,19 @@
|
||||
else if(environ==2)
|
||||
update_overlay |= APC_UPOVERLAY_ENVIRON2
|
||||
|
||||
|
||||
var/results = 0
|
||||
if(last_update_state == update_state && last_update_overlay == update_overlay)
|
||||
var/hijackerreturn
|
||||
if (hijacker)
|
||||
var/obj/item/implant/hijack/H = hijacker.getImplant(/obj/item/implant/hijack)
|
||||
hijackerreturn = H && !H.stealthmode
|
||||
if(last_update_state == update_state && last_update_overlay == update_overlay && hijackerreturn ? hijackerlast : !hijackerlast)
|
||||
return 0
|
||||
if(last_update_state != update_state)
|
||||
results += 1
|
||||
if(last_update_overlay != update_overlay)
|
||||
if(last_update_overlay != update_overlay || hijackerreturn ? !hijackerlast : hijackerlast)
|
||||
results += 2
|
||||
if (hijackerreturn ? !hijackerlast : hijackerlast)
|
||||
hijackerlast = hijackerreturn ? TRUE : FALSE
|
||||
return results
|
||||
|
||||
// Used in process so it doesn't update the icon too much
|
||||
@@ -534,7 +546,7 @@
|
||||
|
||||
/obj/machinery/power/apc/attackby(obj/item/W, mob/living/user, params)
|
||||
|
||||
if(issilicon(user) && get_dist(src,user)>1)
|
||||
if(area.hasSiliconAccessInArea(user) && get_dist(src,user)>1)
|
||||
return attack_hand(user)
|
||||
|
||||
if (istype(W, /obj/item/stock_parts/cell) && opened)
|
||||
@@ -741,7 +753,7 @@
|
||||
|
||||
/obj/machinery/power/apc/AltClick(mob/user)
|
||||
. = ..()
|
||||
if(!user.canUseTopic(src, !issilicon(user)) || !isturf(loc))
|
||||
if(!user.canUseTopic(src, !area.hasSiliconAccessInArea(user)) || !isturf(loc))
|
||||
return
|
||||
togglelock(user)
|
||||
return TRUE
|
||||
@@ -756,7 +768,7 @@
|
||||
else if(stat & (BROKEN|MAINT))
|
||||
to_chat(user, "<span class='warning'>Nothing happens!</span>")
|
||||
else
|
||||
if(allowed(usr) && !wires.is_cut(WIRE_IDSCAN) && !malfhack)
|
||||
if((allowed(usr) || area.hasSiliconAccessInArea(usr)) && !wires.is_cut(WIRE_IDSCAN) && !malfhack)
|
||||
locked = !locked
|
||||
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] the APC interface.</span>")
|
||||
update_icon()
|
||||
@@ -833,6 +845,11 @@
|
||||
if((stat & MAINT) && !opened) //no board; no interface
|
||||
return
|
||||
|
||||
/obj/machinery/power/apc/oui_canview(mob/user)
|
||||
if(user.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(user))
|
||||
return TRUE
|
||||
return ..()
|
||||
|
||||
/obj/machinery/power/apc/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)
|
||||
@@ -842,8 +859,12 @@
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/power/apc/ui_data(mob/user)
|
||||
var/obj/item/implant/hijack/H = user.getImplant(/obj/item/implant/hijack)
|
||||
var/abilitiesavail = FALSE
|
||||
if (H && !H.stealthmode && H.toggled)
|
||||
abilitiesavail = TRUE
|
||||
var/list/data = list(
|
||||
"locked" = locked && !(integration_cog && is_servant_of_ratvar(user)),
|
||||
"locked" = locked && !(integration_cog && is_servant_of_ratvar(user)) && !area.hasSiliconAccessInArea(user),
|
||||
"lock_nightshift" = nightshift_requires_auth,
|
||||
"failTime" = failure_timer,
|
||||
"isOperating" = operating,
|
||||
@@ -853,11 +874,14 @@
|
||||
"chargingStatus" = charging,
|
||||
"totalLoad" = DisplayPower(lastused_total),
|
||||
"coverLocked" = coverlocked,
|
||||
"siliconUser" = user.has_unlimited_silicon_privilege || user.using_power_flow_console(),
|
||||
"siliconUser" = user.has_unlimited_silicon_privilege || user.using_power_flow_console() || area.hasSiliconAccessInArea(user),
|
||||
"malfStatus" = get_malf_status(user),
|
||||
"emergencyLights" = !emergency_lights,
|
||||
"nightshiftLights" = nightshift_lights,
|
||||
|
||||
"hijackable" = HAS_TRAIT(user,TRAIT_HIJACKER),
|
||||
"hijacker" = hijacker == user ? TRUE : FALSE,
|
||||
"drainavail" = cell && cell.percent() >= 85 && abilitiesavail,
|
||||
"lockdownavail" = cell && cell.percent() >= 35 && abilitiesavail,
|
||||
"powerChannels" = list(
|
||||
list(
|
||||
"title" = "Equipment",
|
||||
@@ -925,17 +949,12 @@
|
||||
/obj/machinery/power/apc/proc/can_use(mob/user, loud = 0) //used by attack_hand() and Topic()
|
||||
if(IsAdminGhost(user))
|
||||
return TRUE
|
||||
if (user == hijacker || (area.hasSiliconAccessInArea(user) && !aidisabled))
|
||||
return TRUE
|
||||
if(user.has_unlimited_silicon_privilege)
|
||||
var/mob/living/silicon/ai/AI = user
|
||||
var/mob/living/silicon/robot/robot = user
|
||||
if ( \
|
||||
src.aidisabled || \
|
||||
malfhack && istype(malfai) && \
|
||||
( \
|
||||
(istype(AI) && (malfai!=AI && malfai != AI.parent)) || \
|
||||
(istype(robot) && (robot in malfai.connected_robots)) \
|
||||
) \
|
||||
)
|
||||
if (src.aidisabled || malfhack && istype(malfai) && ((istype(AI) && (malfai!=AI && malfai != AI.parent)) || (istype(robot) && (robot in malfai.connected_robots))))
|
||||
if(!loud)
|
||||
to_chat(user, "<span class='danger'>\The [src] has eee disabled!</span>")
|
||||
return FALSE
|
||||
@@ -945,11 +964,15 @@
|
||||
. = ..()
|
||||
if (!. && !QDELETED(remote_control))
|
||||
. = remote_control.can_interact(user)
|
||||
if (hijacker == user && area.hasSiliconAccessInArea(user))
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/power/apc/ui_status(mob/user)
|
||||
. = ..()
|
||||
if (!QDELETED(remote_control) && user == remote_control.operator)
|
||||
. = UI_INTERACTIVE
|
||||
if (user == hijacker && area.hasSiliconAccessInArea(user))
|
||||
. = UI_INTERACTIVE
|
||||
|
||||
/obj/machinery/power/apc/ui_act(action, params)
|
||||
if(..() || !can_use(usr, 1))
|
||||
@@ -959,7 +982,10 @@
|
||||
failure_timer = 0
|
||||
update_icon()
|
||||
update()
|
||||
var/authorized = (!locked || usr.has_unlimited_silicon_privilege || (integration_cog && (is_servant_of_ratvar(usr))))
|
||||
if (action == "hijack" && can_use(usr, 1)) //don't need auth for hijack button
|
||||
hijack(usr)
|
||||
return
|
||||
var/authorized = (!locked || usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr) || (integration_cog && (is_servant_of_ratvar(usr))))
|
||||
if((action == "toggle_nightshift") && (!nightshift_requires_auth || authorized))
|
||||
toggle_nightshift_lights()
|
||||
return TRUE
|
||||
@@ -967,7 +993,7 @@
|
||||
return
|
||||
switch(action)
|
||||
if("lock")
|
||||
if(usr.has_unlimited_silicon_privilege)
|
||||
if(usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr))
|
||||
if((obj_flags & EMAGGED) || (stat & (BROKEN|MAINT)))
|
||||
to_chat(usr, "The APC does not respond to the command.")
|
||||
else
|
||||
@@ -1001,7 +1027,7 @@
|
||||
update()
|
||||
return TRUE
|
||||
if("overload")
|
||||
if(usr.has_unlimited_silicon_privilege)
|
||||
if(usr.has_unlimited_silicon_privilege || area.hasSiliconAccessInArea(usr))
|
||||
overload_lighting()
|
||||
return TRUE
|
||||
if("hack")
|
||||
@@ -1023,7 +1049,26 @@
|
||||
L.no_emergency = emergency_lights
|
||||
INVOKE_ASYNC(L, /obj/machinery/light/.proc/update, FALSE)
|
||||
CHECK_TICK
|
||||
return TRUE
|
||||
if("drain")
|
||||
cell.use(cell.charge)
|
||||
hijacker.toggleSiliconAccessArea(area)
|
||||
hijacker = null
|
||||
set_hijacked_lighting()
|
||||
update_icon()
|
||||
var/obj/item/implant/hijack/H = usr.getImplant(/obj/item/implant/hijack)
|
||||
H.stealthcooldown = world.time + 2 MINUTES
|
||||
energy_fail(30 SECONDS * (cell.charge / cell.maxcharge))
|
||||
if("lockdown")
|
||||
var/celluse = rand(20,35)
|
||||
celluse = celluse /100
|
||||
for (var/obj/machinery/door/D in GLOB.airlocks)
|
||||
if (get_area(D) == area)
|
||||
INVOKE_ASYNC(D,/obj/machinery/door.proc/hostile_lockdown,usr, FALSE)
|
||||
addtimer(CALLBACK(D,/obj/machinery/door.proc/disable_lockdown, FALSE), 30 SECONDS)
|
||||
cell.charge -= cell.maxcharge*celluse
|
||||
var/obj/item/implant/hijack/H = usr.getImplant(/obj/item/implant/hijack)
|
||||
H.stealthcooldown = world.time + 3 MINUTES
|
||||
return TRUE
|
||||
|
||||
/obj/machinery/power/apc/proc/toggle_breaker()
|
||||
if(!is_operational() || failure_timer)
|
||||
@@ -1032,6 +1077,39 @@
|
||||
update()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/power/apc/proc/hijack(mob/living/L)
|
||||
if (!istype(L))
|
||||
return
|
||||
if (hijacker && hijacker != L)
|
||||
var/obj/item/implant/hijack/H = L.getImplant(/obj/item/implant/hijack)
|
||||
to_chat(L, "<span class='warning'>Someone already has control of this APC. Beginning counter-hijack.</span>")
|
||||
H.hijacking = TRUE
|
||||
if (do_after(L,20 SECONDS,target=src))
|
||||
hijacker.toggleSiliconAccessArea(area)
|
||||
if (L.toggleSiliconAccessArea(area))
|
||||
hijacker = L
|
||||
update_icon()
|
||||
set_hijacked_lighting()
|
||||
H.hijacking = FALSE
|
||||
return
|
||||
else
|
||||
to_chat(L, "<span class='warning'>Aborting.</span>")
|
||||
H.hijacking = FALSE
|
||||
return
|
||||
to_chat(L, "<span class='notice'>Beginning hijack of APC.</span>")
|
||||
var/obj/item/implant/hijack/H = L.getImplant(/obj/item/implant/hijack)
|
||||
H.hijacking = TRUE
|
||||
if (do_after(L,H.stealthmode ? 12 SECONDS : 5 SECONDS,target=src))
|
||||
if (L.toggleSiliconAccessArea(area))
|
||||
hijacker = L
|
||||
update_icon()
|
||||
set_hijacked_lighting()
|
||||
H.hijacking = FALSE
|
||||
else
|
||||
to_chat(L, "<span class='warning'>Aborting.</span>")
|
||||
H.hijacking = FALSE
|
||||
return
|
||||
|
||||
/obj/machinery/power/apc/proc/malfhack(mob/living/silicon/ai/malf)
|
||||
if(!istype(malf))
|
||||
return
|
||||
@@ -1438,6 +1516,17 @@
|
||||
L.update(FALSE)
|
||||
CHECK_TICK
|
||||
|
||||
/obj/machinery/power/apc/proc/set_hijacked_lighting()
|
||||
set waitfor = FALSE
|
||||
var/hijackerreturn
|
||||
if (hijacker)
|
||||
var/obj/item/implant/hijack/H = hijacker.getImplant(/obj/item/implant/hijack)
|
||||
hijackerreturn = H && !H.stealthmode
|
||||
for(var/obj/machinery/light/L in area)
|
||||
L.hijacked = hijackerreturn
|
||||
L.update(FALSE)
|
||||
CHECK_TICK
|
||||
|
||||
/obj/machinery/power/apc/proc/update_nightshift_auth_requirement()
|
||||
nightshift_requires_auth = nightshift_toggle_requires_auth()
|
||||
|
||||
|
||||
@@ -220,6 +220,7 @@
|
||||
var/bulb_emergency_colour = "#FF3232" // determines the colour of the light while it's in emergency mode
|
||||
var/bulb_emergency_pow_mul = 0.75 // the multiplier for determining the light's power in emergency mode
|
||||
var/bulb_emergency_pow_min = 0.5 // the minimum value for the light's power in emergency mode
|
||||
var/hijacked = FALSE // if true, the light is in a hijacked area
|
||||
|
||||
/obj/machinery/light/broken
|
||||
status = LIGHT_BROKEN
|
||||
@@ -298,7 +299,10 @@
|
||||
if(emergency_mode || (A && A.fire))
|
||||
icon_state = "[base_state]_emergency"
|
||||
else
|
||||
icon_state = "[base_state]"
|
||||
if (hijacked)
|
||||
icon_state = "[base_state]_hijacked"
|
||||
else
|
||||
icon_state = "[base_state]"
|
||||
if(on)
|
||||
var/mutable_appearance/glowybit = mutable_appearance(overlayicon, base_state, ABOVE_LIGHTING_LAYER, ABOVE_LIGHTING_PLANE)
|
||||
glowybit.alpha = CLAMP(light_power*250, 30, 200)
|
||||
@@ -326,6 +330,10 @@
|
||||
var/area/A = get_base_area(src)
|
||||
if (A && A.fire)
|
||||
CO = bulb_emergency_colour
|
||||
else if (hijacked)
|
||||
BR = BR * 1.5
|
||||
PO = PO * 1.5
|
||||
CO = color ? color : LIGHT_COLOR_YELLOW
|
||||
else if (nightshift_enabled)
|
||||
BR = nightshift_brightness
|
||||
PO = nightshift_light_power
|
||||
@@ -355,7 +363,7 @@
|
||||
if(on != on_gs)
|
||||
on_gs = on
|
||||
if(on)
|
||||
static_power_used = brightness * 14.4 //20W per unit luminosity
|
||||
static_power_used = brightness * 14.4 * (hijacked ? 2 : 1) //20W per unit luminosity
|
||||
addStaticPower(static_power_used, STATIC_LIGHT)
|
||||
else
|
||||
removeStaticPower(static_power_used, STATIC_LIGHT)
|
||||
|
||||
@@ -319,7 +319,7 @@
|
||||
if(!is_operational())
|
||||
return
|
||||
var/name = stripped_input(usr,"Name","What do you want to name this recipe?", "Recipe", MAX_NAME_LEN)
|
||||
if(!usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
if(saved_recipes[name] && alert("\"[name]\" already exists, do you want to overwrite it?",, "Yes", "No") == "No")
|
||||
return
|
||||
|
||||
@@ -261,7 +261,7 @@
|
||||
return
|
||||
vol_each = min(reagents.total_volume / amount, 50)
|
||||
var/name = html_decode(stripped_input(usr,"Name:","Name your pill!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/pill/P
|
||||
var/target_loc = drop_location()
|
||||
@@ -288,7 +288,7 @@
|
||||
reagents.trans_to(P,vol_each)
|
||||
else
|
||||
var/name = html_decode(stripped_input(usr, "Name:", "Name your pack!", reagents.get_master_reagent_name(), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/food/condiment/pack/P = new/obj/item/reagent_containers/food/condiment/pack(drop_location())
|
||||
|
||||
@@ -314,7 +314,7 @@
|
||||
return
|
||||
vol_each = min(reagents.total_volume / amount, 40)
|
||||
var/name = html_decode(stripped_input(usr,"Name:","Name your patch!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/pill/P
|
||||
|
||||
@@ -332,7 +332,7 @@
|
||||
|
||||
if(condi)
|
||||
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
var/obj/item/reagent_containers/food/condiment/P = new(drop_location())
|
||||
P.originalname = name
|
||||
@@ -345,7 +345,7 @@
|
||||
amount_full = round(reagents.total_volume / 30)
|
||||
vol_part = ((reagents.total_volume*1000) % 30000) / 1000 //% operator doesn't support decimals.
|
||||
var/name = html_decode(stripped_input(usr, "Name:","Name your bottle!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
|
||||
var/obj/item/reagent_containers/glass/bottle/P
|
||||
@@ -373,7 +373,7 @@
|
||||
amount_full = round(reagents.total_volume / 60)
|
||||
vol_part = reagents.total_volume % 60
|
||||
var/name = html_decode(stripped_input(usr, "Name:","Name your hypovial!", (reagents.total_volume ? reagents.get_master_reagent_name() : " "), MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
|
||||
var/obj/item/reagent_containers/glass/bottle/vial/small/P
|
||||
@@ -408,7 +408,7 @@
|
||||
vol_each = min(reagents.total_volume / amount, 20)
|
||||
|
||||
var/name = html_decode(stripped_input(usr,"Name:","Name your SmartDart!", "[reagents.get_master_reagent_name()] ([vol_each]u)", MAX_NAME_LEN))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !issilicon(usr)))
|
||||
if(!name || !reagents.total_volume || !src || QDELETED(src) || !usr.canUseTopic(src, !hasSiliconAccessInArea(usr)))
|
||||
return
|
||||
|
||||
var/obj/item/reagent_containers/syringe/dart/D
|
||||
|
||||
@@ -142,7 +142,7 @@
|
||||
/obj/machinery/reagentgrinder/ui_interact(mob/user) // The microwave Menu //I am reasonably certain that this is not a microwave
|
||||
. = ..()
|
||||
|
||||
if(operating || !user.canUseTopic(src, !issilicon(user)))
|
||||
if(operating || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
|
||||
var/list/options = list()
|
||||
@@ -170,10 +170,10 @@
|
||||
for(var/key in options)
|
||||
choice = key
|
||||
else
|
||||
choice = show_radial_menu(user, src, options, require_near = !issilicon(user))
|
||||
choice = show_radial_menu(user, src, options, require_near = !hasSiliconAccessInArea(user))
|
||||
|
||||
// post choice verification
|
||||
if(operating || (isAI(user) && stat & NOPOWER) || !user.canUseTopic(src, !issilicon(user)))
|
||||
if(operating || (isAI(user) && stat & NOPOWER) || !user.canUseTopic(src, !hasSiliconAccessInArea(user)))
|
||||
return
|
||||
|
||||
switch(choice)
|
||||
@@ -190,7 +190,7 @@
|
||||
|
||||
/obj/machinery/reagentgrinder/examine(mob/user)
|
||||
. = ..()
|
||||
if(!in_range(user, src) && !issilicon(user) && !isobserver(user))
|
||||
if(!in_range(user, src) && !hasSiliconAccessInArea(user) && !isobserver(user))
|
||||
. += "<span class='warning'>You're too far away to examine [src]'s contents and display!</span>"
|
||||
return
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
return UI_CLOSE
|
||||
|
||||
var/dist = get_dist(src_object, src)
|
||||
if(dist <= 1) // Open and interact if 1-0 tiles away.
|
||||
if(dist <= 1 || src_object.hasSiliconAccessInArea(src)) // Open and interact if 1-0 tiles away.
|
||||
return UI_INTERACTIVE
|
||||
else if(dist <= 2) // View only if 2-3 tiles away.
|
||||
return UI_UPDATE
|
||||
|
||||
@@ -29,6 +29,22 @@
|
||||
item = /obj/item/storage/box/syndie_kit/imp_freedom
|
||||
cost = 5
|
||||
|
||||
/datum/uplink_item/implants/hijack
|
||||
name = "Hijack Implant"
|
||||
desc = "An implant that will let you hack into the APCs on station, allowing you to control them at will and the machinery within those rooms."
|
||||
item = /obj/item/implanter/hijack
|
||||
cost = 14 //really overkill, 14 tc, can still get caught in a room you haven't hijacked and you're fucked.
|
||||
surplus = 0 //nope not having hijack implants with surplus crates nope nope nope nope
|
||||
restricted = TRUE
|
||||
|
||||
/datum/uplink_item/implants/radio
|
||||
name = "Internal Syndicate Radio Implant"
|
||||
desc = "An implant injected into the body, allowing the use of an internal Syndicate radio. \
|
||||
Used just like a regular headset, but can be disabled to use external headsets normally and to avoid detection."
|
||||
item = /obj/item/storage/box/syndie_kit/imp_radio
|
||||
cost = 4
|
||||
restricted = TRUE
|
||||
|
||||
/datum/uplink_item/implants/microbomb
|
||||
name = "Microbomb Implant"
|
||||
desc = "An implant injected into the body, and later activated either manually or automatically upon death. \
|
||||
@@ -47,14 +63,6 @@
|
||||
include_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
|
||||
restricted = TRUE
|
||||
|
||||
/datum/uplink_item/implants/radio
|
||||
name = "Internal Syndicate Radio Implant"
|
||||
desc = "An implant injected into the body, allowing the use of an internal Syndicate radio. \
|
||||
Used just like a regular headset, but can be disabled to use external headsets normally and to avoid detection."
|
||||
item = /obj/item/storage/box/syndie_kit/imp_radio
|
||||
cost = 4
|
||||
restricted = TRUE
|
||||
|
||||
/datum/uplink_item/implants/reviver
|
||||
name = "Reviver Implant"
|
||||
desc = "This implant will attempt to revive and heal you if you lose consciousness. Comes with an autosurgeon."
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.6 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 76 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
@@ -981,6 +981,7 @@
|
||||
#include "code\game\objects\items\implants\implant_exile.dm"
|
||||
#include "code\game\objects\items\implants\implant_explosive.dm"
|
||||
#include "code\game\objects\items\implants\implant_freedom.dm"
|
||||
#include "code\game\objects\items\implants\implant_hijack.dm"
|
||||
#include "code\game\objects\items\implants\implant_krav_maga.dm"
|
||||
#include "code\game\objects\items\implants\implant_mindshield.dm"
|
||||
#include "code\game\objects\items\implants\implant_misc.dm"
|
||||
|
||||
@@ -201,6 +201,29 @@ export const Apc = props => {
|
||||
onClick={() => act('toggle_nightshift')} />
|
||||
)} />
|
||||
</Section>
|
||||
{data.hijackable && (
|
||||
<Section
|
||||
title="Hijacking"
|
||||
buttons={(
|
||||
<Fragment>
|
||||
<Button
|
||||
icon="unlock"
|
||||
content="Hijack"
|
||||
disabled={data.hijacker}
|
||||
onClick={() => act('hijack')} />
|
||||
<Button
|
||||
icon="lock"
|
||||
content="Lockdown"
|
||||
disabled={!data.lockdownavail}
|
||||
onClick={() => act('lockdown')} />
|
||||
<Button
|
||||
icon="lightbulb-o"
|
||||
content="Drain"
|
||||
disabled={!data.drainavail}
|
||||
onClick={() => act('drain')} />
|
||||
</Fragment>
|
||||
)} />
|
||||
)}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+21
-1
File diff suppressed because one or more lines are too long
@@ -148,4 +148,18 @@
|
||||
{{/if}}
|
||||
</ui-section>
|
||||
</ui-notice>
|
||||
{{#if data.hijackable}}
|
||||
<ui-display title='Hijacking'>
|
||||
{{#if !data.hijacker}}
|
||||
<ui-button icon='unlock' action='hijack'>Hijack APC</ui-button>
|
||||
{{else}}
|
||||
{{#if data.drainavail}}
|
||||
<ui-button icon='lightbulb-o' action='drain'>Drain APC</ui-button>
|
||||
{{/if}}
|
||||
{{#if data.lockdownavail}}
|
||||
<ui-button icon='lock' action='lockdown'>Lockdown Room</ui-button>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</ui-display>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
Reference in New Issue
Block a user