Merge branch 'master' into tinytweaks-2-9-20

This commit is contained in:
Winter Flare
2020-02-11 07:20:16 -05:00
153 changed files with 1648 additions and 948 deletions
@@ -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()
+1 -1
View File
@@ -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()
+44 -1
View File
@@ -488,4 +488,47 @@
if(client && client.prefs.uses_glasses_colour && glasses_equipped)
add_client_colour(G.glass_colour_type)
else
remove_client_colour(G.glass_colour_type)
remove_client_colour(G.glass_colour_type)
/obj/item/clothing/glasses/debug
name = "debug glasses"
desc = "Medical, security and diagnostic hud. Alt click to toggle xray."
icon_state = "nvgmeson"
item_state = "nvgmeson"
flags_cover = GLASSESCOVERSEYES
darkness_view = 8
flash_protect = 2
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
glass_colour_type = FALSE
clothing_flags = SCAN_REAGENTS
vision_flags = SEE_TURFS
var/list/hudlist = list(DATA_HUD_MEDICAL_ADVANCED, DATA_HUD_DIAGNOSTIC_ADVANCED, DATA_HUD_SECURITY_ADVANCED)
var/xray = FALSE
/obj/item/clothing/glasses/debug/equipped(mob/user, slot)
. = ..()
if(slot != ITEM_SLOT_EYES)
return
if(ishuman(user))
for(var/hud in hudlist)
var/datum/atom_hud/H = GLOB.huds[hud]
H.add_hud_to(user)
/obj/item/clothing/glasses/debug/dropped(mob/user)
. = ..()
if(ishuman(user))
for(var/hud in hudlist)
var/datum/atom_hud/H = GLOB.huds[hud]
H.remove_hud_from(user)
/obj/item/clothing/glasses/debug/AltClick(mob/user)
. = ..()
if(ishuman(user))
if(xray)
vision_flags -= SEE_MOBS|SEE_OBJS
else
vision_flags += SEE_MOBS|SEE_OBJS
xray = !xray
var/mob/living/carbon/human/H = user
H.update_sight()
+6
View File
@@ -39,6 +39,12 @@
/obj/item/clothing/mask/gas/welding/attack_self(mob/user)
weldingvisortoggle(user)
/obj/item/clothing/mask/gas/welding/up
/obj/item/clothing/mask/gas/welding/up/Initialize()
..()
visor_toggling()
// ********************************************************************
+22 -9
View File
@@ -427,14 +427,27 @@
/datum/outfit/debug //Debug objs plus hardsuit
name = "Debug outfit"
uniform = /obj/item/clothing/under/patriotsuit
suit = /obj/item/clothing/suit/space/hardsuit/syndi/elite
shoes = /obj/item/clothing/shoes/magboots/advance
suit_store = /obj/item/tank/internals/oxygen
mask = /obj/item/clothing/mask/gas/welding
belt = /obj/item/storage/belt/utility/chief/full
gloves = /obj/item/clothing/gloves/combat
id = /obj/item/card/id/ert
glasses = /obj/item/clothing/glasses/meson/night
suit = /obj/item/clothing/suit/space/hardsuit/syndi/elite/debug
glasses = /obj/item/clothing/glasses/debug
ears = /obj/item/radio/headset/headset_cent/commander
mask = /obj/item/clothing/mask/gas/welding/up
gloves = /obj/item/clothing/gloves/combat
belt = /obj/item/storage/belt/utility/chief/full
l_pocket = /obj/item/gun/magic/wand/resurrection/debug
r_pocket = /obj/item/gun/magic/wand/death/debug
shoes = /obj/item/clothing/shoes/magboots/advance/debug
id = /obj/item/card/id/debug
suit_store = /obj/item/tank/internals/oxygen
back = /obj/item/storage/backpack/holding
backpack_contents = list(/obj/item/card/emag=1, /obj/item/flashlight/emp/debug=1, /obj/item/construction/rcd/combat=1, /obj/item/gun/magic/wand/resurrection/debug=1, /obj/item/melee/transforming/energy/axe=1)
box = /obj/item/storage/box/debugtools
internals_slot = ITEM_SLOT_SUITSTORE
backpack_contents = list(
/obj/item/melee/transforming/energy/axe=1,\
/obj/item/storage/part_replacer/bluespace/tier4=1,\
/obj/item/debug/human_spawner=1,\
)
/datum/outfit/debug/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE)
var/obj/item/card/id/W = H.wear_id
W.registered_name = H.real_name
W.update_label()
+8 -2
View File
@@ -30,8 +30,9 @@
magpulse = !magpulse
icon_state = "[magboot_state][magpulse]"
to_chat(user, "<span class='notice'>You [magpulse ? "enable" : "disable"] the mag-pulse traction system.</span>")
user.update_inv_shoes() //so our mob-overlays update
user.update_gravity(user.has_gravity())
if(user)
user.update_inv_shoes() //so our mob-overlays update
user.update_gravity(user.has_gravity())
for(var/X in actions)
var/datum/action/A = X
A.UpdateButtonIcon()
@@ -52,6 +53,11 @@
slowdown_active = SHOES_SLOWDOWN
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | ACID_PROOF
/obj/item/clothing/shoes/magboots/advance/debug
/obj/item/clothing/shoes/magboots/advance/debug/Initialize()
attack_self(src)
/obj/item/clothing/shoes/magboots/syndie
desc = "Reverse-engineered magnetic boots that have a heavy magnetic pull. Property of Gorlex Marauders."
name = "blood-red magboots"
+10 -1
View File
@@ -269,7 +269,7 @@
item_state = "syndie_helm"
item_color = "syndi"
armor = list("melee" = 40, "bullet" = 50, "laser" = 30, "energy" = 15, "bomb" = 35, "bio" = 100, "rad" = 50, "fire" = 50, "acid" = 90)
on = TRUE
on = FALSE
var/obj/item/clothing/suit/space/hardsuit/syndi/linkedsuit = null
actions_types = list(/datum/action/item_action/toggle_helmet_mode)
visor_flags_inv = HIDEMASK|HIDEEYES|HIDEFACE|HIDEFACIALHAIR
@@ -367,6 +367,12 @@
on = FALSE
resistance_flags = FIRE_PROOF | ACID_PROOF
/obj/item/clothing/head/helmet/space/hardsuit/syndi/elite/debug
/obj/item/clothing/head/helmet/space/hardsuit/syndi/elite/debug/Initialize()
. = ..()
soundloop.volume = 0
/obj/item/clothing/suit/space/hardsuit/syndi/elite
name = "elite syndicate hardsuit"
desc = "An elite version of the syndicate hardsuit, with improved armour and fireproofing. It is in travel mode."
@@ -380,6 +386,9 @@
resistance_flags = FIRE_PROOF | ACID_PROOF
mutantrace_variation = STYLE_DIGITIGRADE|STYLE_SNEK_TAURIC|STYLE_PAW_TAURIC
/obj/item/clothing/suit/space/hardsuit/syndi/elite/debug
helmettype = /obj/item/clothing/head/helmet/space/hardsuit/syndi/elite/debug
slowdown = 0
//The Owl Hardsuit
/obj/item/clothing/head/helmet/space/hardsuit/syndi/owl
+2 -4
View File
@@ -325,17 +325,16 @@
body_parts_covered = CHEST|ARMS
/obj/item/clothing/suit/ran
name = "Shikigami costume"
name = "shikigami costume"
desc = "A costume that looks like a certain shikigami, is super fluffy."
icon_state = "ran_suit"
item_state = "ran_suit"
body_parts_covered = CHEST|GROIN|LEGS
flags_inv = HIDEJUMPSUIT|HIDETAUR
heat_protection = CHEST|GROIN|LEGS //fluffy tails!
//2061
/obj/item/clothing/head/ran
name = "Shikigami hat"
name = "shikigami hat"
desc = "A hat that looks like it keeps any fluffy ears contained super warm, has little charms over it."
icon_state = "ran_hat"
item_state = "ran_hat"
@@ -880,7 +879,6 @@
blood_overlay_type = "armor"
body_parts_covered = CHEST
resistance_flags = NONE
mutantrace_variation = NONE
armor = list("melee" = 0, "bullet" = 0, "laser" = 0,"energy" = 0, "bomb" = 5, "bio" = 0, "rad" = 0, "fire" = -5, "acid" = -15) //nylon sucks against acid
/obj/item/clothing/suit/assu_suit
+1 -1
View File
@@ -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
+5
View File
@@ -177,6 +177,7 @@
shuttleId = "pirateship"
icon_screen = "syndishuttle"
icon_keyboard = "syndie_key"
resistance_flags = INDESTRUCTIBLE
light_color = LIGHT_COLOR_RED
possible_destinations = "pirateship_away;pirateship_home;pirateship_custom"
@@ -184,6 +185,7 @@
name = "pirate shuttle navigation computer"
desc = "Used to designate a precise transit location for the pirate shuttle."
shuttleId = "pirateship"
resistance_flags = INDESTRUCTIBLE
lock_override = CAMERA_LOCK_STATION
shuttlePortId = "pirateship_custom"
x_offset = 9
@@ -226,6 +228,7 @@
desc = "This sophisticated machine scans the nearby space for items of value."
icon = 'icons/obj/machines/research.dmi'
icon_state = "tdoppler"
resistance_flags = INDESTRUCTIBLE
density = TRUE
var/cooldown = 300
var/next_use = 0
@@ -259,6 +262,7 @@
name = "cargo hold pad"
icon = 'icons/obj/telescience.dmi'
icon_state = "lpad-idle-o"
resistance_flags = INDESTRUCTIBLE
var/idle_state = "lpad-idle-o"
var/warmup_state = "lpad-idle"
var/sending_state = "lpad-beam"
@@ -272,6 +276,7 @@
/obj/machinery/computer/piratepad_control
name = "cargo hold control terminal"
resistance_flags = INDESTRUCTIBLE
var/status_report = "Idle"
var/obj/machinery/piratepad/pad
var/warmup_time = 100
@@ -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
+2 -2
View File
@@ -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)
+1 -1
View File
@@ -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))
+1 -1
View File
@@ -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
+26 -26
View File
@@ -479,32 +479,6 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
pixel_y = 0
animate(src, pixel_y = 2, time = 10, loop = -1)
/mob/dead/observer/verb/observe()
set name = "Observe"
set category = "Ghost"
var/list/creatures = getpois()
reset_perspective(null)
var/eye_name = null
eye_name = input("Please, select a player!", "Observe", null, null) as null|anything in creatures
if (!eye_name)
return
var/mob/mob_eye = creatures[eye_name]
//Istype so we filter out points of interest that are not mobs
if(client && mob_eye && istype(mob_eye))
client.eye = mob_eye
if(mob_eye.hud_used)
client.screen = list()
LAZYINITLIST(mob_eye.observers)
mob_eye.observers |= src
mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src)
observetarget = mob_eye
/mob/dead/observer/verb/jumptomob() //Moves the ghost instead of just changing the ghosts's eye -Nodrak
set category = "Ghost"
set name = "Jump to Mob"
@@ -831,6 +805,32 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
client.screen = list()
hud_used.show_hud(hud_used.hud_version)
/mob/dead/observer/verb/observe()
set name = "Observe"
set category = "OOC"
var/list/creatures = getpois()
reset_perspective(null)
var/eye_name = null
eye_name = input("Please, select a player!", "Observe", null, null) as null|anything in creatures
if (!eye_name)
return
var/mob/mob_eye = creatures[eye_name]
//Istype so we filter out points of interest that are not mobs
if(client && mob_eye && istype(mob_eye))
client.eye = mob_eye
if(mob_eye.hud_used)
client.screen = list()
LAZYINITLIST(mob_eye.observers)
mob_eye.observers |= src
mob_eye.hud_used.show_hud(mob_eye.hud_used.hud_version, src)
observetarget = mob_eye
/mob/dead/observer/verb/register_pai_candidate()
set category = "Ghost"
set name = "pAI Setup"
+1 -2
View File
@@ -22,7 +22,7 @@
. = say_dead(message)
/mob/dead/observer/Hear(message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
. = ..()
SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args) //parent calls can't overwrite the current proc args.
var/atom/movable/to_follow = speaker
if(radio_freq)
var/atom/movable/virtualspeaker/V = speaker
@@ -36,4 +36,3 @@
// Recompose the message, because it's scrambled by default
message = compose_message(speaker, message_language, raw_message, radio_freq, spans, message_mode, FALSE, source)
to_chat(src, "[link] [message]")
@@ -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))
@@ -54,21 +54,20 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) //
//Dwarf Speech handling - Basically a filter/forces them to say things. The IC helper
/datum/species/dwarf/proc/handle_speech(datum/source, list/speech_args)
var/message = speech_args[SPEECH_MESSAGE]
if(message[1] != "*")
message = " [message]" //Credits to goonstation for the strings list.
var/list/dwarf_words = strings("dwarf_replacement.json", "dwarf") //thanks to regex too.
if(speech_args[SPEECH_LANGUAGE] != /datum/language/dwarf) // No accent if they speak their language
if(message[1] != "*")
message = " [message]" //Credits to goonstation for the strings list.
var/list/dwarf_words = strings("dwarf_replacement.json", "dwarf") //thanks to regex too.
for(var/key in dwarf_words) //Theres like 1459 words or something man.
var/value = dwarf_words[key] //Thus they will always be in character.
if(islist(value)) //Whether they like it or not.
value = pick(value) //This could be drastically reduced if needed though.
message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]")
message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]")
message = replacetextEx(message, " [key]", " [value]") //Also its scottish.
for(var/key in dwarf_words) //Theres like 1459 words or something man.
var/value = dwarf_words[key] //Thus they will always be in character.
if(islist(value)) //Whether they like it or not.
value = pick(value) //This could be drastically reduced if needed though.
message = replacetextEx(message, " [uppertext(key)]", " [uppertext(value)]")
message = replacetextEx(message, " [capitalize(key)]", " [capitalize(value)]")
message = replacetextEx(message, " [key]", " [value]") //Also its scottish.
if(prob(3))
message += pick(" By Armok!")
if(prob(3))
message += " By Armok!"
speech_args[SPEECH_MESSAGE] = trim(message)
//This mostly exists because my testdwarf's liver died while trying to also not die due to no alcohol.
+1 -1
View File
@@ -224,7 +224,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
. = "<span class='small'>[.]</span>"
/mob/living/Hear(message, atom/movable/speaker, datum/language/message_language, raw_message, radio_freq, list/spans, message_mode, atom/movable/source)
. = ..()
SEND_SIGNAL(src, COMSIG_MOVABLE_HEAR, args) //parent calls can't overwrite the current proc args.
if(!client)
return
var/deaf_message
+1 -1
View File
@@ -315,10 +315,10 @@
var/is_anchored = FALSE
if(move_resist == MOVE_FORCE_OVERPOWERING)
move_resist = MOVE_FORCE_NORMAL
REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, src)
else
is_anchored = TRUE
move_resist = MOVE_FORCE_OVERPOWERING
REMOVE_TRAIT(src, TRAIT_NO_TELEPORT, src)
ADD_TRAIT(src, TRAIT_NO_TELEPORT, src)
to_chat(src, "<b>You are now [is_anchored ? "" : "un"]anchored.</b>")
+3
View File
@@ -7,4 +7,7 @@
var/datum/antagonist/bloodsucker/V = mind.has_antag_datum(/datum/antagonist/bloodsucker)
if(V)
mind.remove_antag_datum(V)
var/datum/antagonist/gang/G = mind.has_antag_datum(/datum/antagonist/gang)
if(G)
mind.remove_antag_datum(G)
..()
@@ -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")
@@ -19,7 +19,7 @@
/mob/living/simple_animal/pet/dog/ComponentInitialize()
. = ..()
AddElement(/datum/element/wuv, "yaps_happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE)
AddElement(/datum/element/wuv, "yaps happily!", EMOTE_AUDIBLE, /datum/mood_event/pet_animal, "growls!", EMOTE_AUDIBLE)
AddElement(/datum/element/mob_holder, held_icon)
//Corgis and pugs are now under one dog subtype
+1 -1
View File
@@ -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)
+4 -1
View File
@@ -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.
+26
View File
@@ -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))
+2 -2
View File
@@ -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
View File
@@ -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()
+10 -2
View File
@@ -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)
@@ -73,6 +73,12 @@
user.adjustOxyLoss(500)
charges--
/obj/item/gun/magic/wand/death/debug
desc = "In some obscure circles, this is known as the 'cloning tester's friend'."
max_charges = 500
variable_charges = FALSE
can_charge = TRUE
recharge_rate = 1
/////////////////////////////////////
//WAND OF HEALING
@@ -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
@@ -170,7 +170,7 @@
if(!A.mutable)
return
if(A)
var/new_name = stripped_input(usr, "Name the disease", "New name", "", MAX_NAME_LEN)
var/new_name = sanitize_name(html_encode(params["name"]))
if(!new_name || ..())
return
A.AssignName(new_name)
@@ -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
@@ -725,11 +725,15 @@ All effects don't start immediately, but rather get worse over time; the rate is
var/dorf_mode
/datum/reagent/consumable/ethanol/manly_dorf/on_mob_metabolize(mob/living/M)
var/real_dorf = isdwarf(M) //_species(H, /datum/species/dwarf)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.dna.check_mutation(DWARFISM) || HAS_TRAIT(H, TRAIT_ALCOHOL_TOLERANCE))
if(H.dna.check_mutation(DWARFISM) || HAS_TRAIT(H, TRAIT_ALCOHOL_TOLERANCE) || real_dorf)
to_chat(H, "<span class='notice'>Now THAT is MANLY!</span>")
boozepwr = 5 //We've had worse in the mines
if(real_dorf)
boozepwr = 100 // Don't want dwarves to die because of a low booze power
else
boozepwr = 5 //We've had worse in the mines
dorf_mode = TRUE
/datum/reagent/consumable/ethanol/manly_dorf/on_mob_life(mob/living/carbon/M)
@@ -994,7 +994,7 @@ datum/reagent/medicine/styptic_powder/overdose_start(mob/living/M)
/datum/reagent/medicine/stimulants/on_mob_metabolize(mob/living/L)
..()
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-1, blacklisted_movetypes=(FLYING|FLOATING))
L.add_movespeed_modifier(type, update=TRUE, priority=100, multiplicative_slowdown=-0.5, blacklisted_movetypes=(FLYING|FLOATING))
/datum/reagent/medicine/stimulants/on_mob_end_metabolize(mob/living/L)
L.remove_movespeed_modifier(type)
@@ -27,7 +27,7 @@
desc = "A tool that can construct and deconstruct walls, airlocks and floors on the fly."
id = "rcd_loaded"
build_type = PROTOLATHE
materials = list(MAT_METAL = MINERAL_MATERIAL_AMOUNT, MAT_GLASS = MINERAL_MATERIAL_AMOUNT) // costs more than what it did in the autolathe, this one comes loaded.
materials = list(MAT_METAL = 36000) // costs more than what it did in the autolathe, this one comes loaded.
build_path = /obj/item/construction/rcd/loaded
category = list("Tool Designs")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING
+3 -4
View File
@@ -52,13 +52,12 @@ Nothing else in the console has ID requirements.
research_control = FALSE
/proc/CallMaterialName(ID)
if(GLOB.chemical_reagents_list[ID])
var/datum/reagent/reagent = GLOB.chemical_reagents_list[ID]
return reagent.name
if (ID[1] == "$" && GLOB.materials_list[ID])
var/datum/material/material = GLOB.materials_list[ID]
return material.name
else if(GLOB.chemical_reagents_list[ID])
var/datum/reagent/reagent = GLOB.chemical_reagents_list[ID]
return reagent.name
return "ERROR: Report This"
/obj/machinery/computer/rdconsole/proc/SyncRDevices() //Makes sure it is properly sync'ed up with the devices attached to it (if any).
+4
View File
@@ -60,6 +60,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
new /obj/item/stock_parts/manipulator(src)
new /obj/item/stock_parts/micro_laser(src)
new /obj/item/stock_parts/matter_bin(src)
new /obj/item/stock_parts/cell/high(src)
/obj/item/storage/part_replacer/bluespace/tier2
@@ -70,6 +71,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
new /obj/item/stock_parts/manipulator/nano(src)
new /obj/item/stock_parts/micro_laser/high(src)
new /obj/item/stock_parts/matter_bin/adv(src)
new /obj/item/stock_parts/cell/super(src)
/obj/item/storage/part_replacer/bluespace/tier3
@@ -80,6 +82,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
new /obj/item/stock_parts/manipulator/pico(src)
new /obj/item/stock_parts/micro_laser/ultra(src)
new /obj/item/stock_parts/matter_bin/super(src)
new /obj/item/stock_parts/cell/hyper(src)
/obj/item/storage/part_replacer/bluespace/tier4
@@ -90,6 +93,7 @@ If you create T5+ please take a pass at gene_modder.dm [L40]. Max_values MUST fi
new /obj/item/stock_parts/manipulator/femto(src)
new /obj/item/stock_parts/micro_laser/quadultra(src)
new /obj/item/stock_parts/matter_bin/bluespace(src)
new /obj/item/stock_parts/cell/bluespace(src)
/obj/item/storage/part_replacer/cargo //used in a cargo crate
+12 -3
View File
@@ -248,6 +248,7 @@
mutations = list(BLINDMUT)
duration = 300
sound = 'sound/magic/blind.ogg'
/obj/effect/proc_holder/spell/aoe_turf/repulse
name = "Repulse"
desc = "This spell throws everything around the user away."
@@ -266,15 +267,22 @@
action_icon_state = "repulse"
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr, stun_amt = 50)
var/list/mobs = list()
var/list/objs = list()
var/list/thrownatoms = list()
var/atom/throwtarget
var/distfromcaster
playMagSound()
for(var/turf/T in targets) //Done this way so things don't get thrown all around hilariously.
for(var/atom/movable/AM in T)
thrownatoms += AM
for(var/mob/M in T)
mobs += M
for(var/obj/O in T)
objs += O
thrownatoms = mobs + objs //mobs first
var/safety = 50
for(var/am in thrownatoms)
if(!safety)
break
var/atom/movable/AM = am
if(AM == user || AM.anchored)
continue
@@ -299,6 +307,7 @@
M.Knockdown(stun_amt, override_hardstun = stun_amt * 0.2)
to_chat(M, "<span class='userdanger'>You're thrown back by [user]!</span>")
AM.throw_at(throwtarget, ((CLAMP((maxthrow - (CLAMP(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time.
safety--
/obj/effect/proc_holder/spell/aoe_turf/repulse/xeno //i fixed conflicts only to find out that this is in the WIZARD file instead of the xeno file?!
name = "Tail Sweep"
+1 -1
View File
@@ -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
+19
View File
@@ -57,3 +57,22 @@
/obj/item/pen/uplink/Initialize(mapload, owner, tc_amount = 20)
. = ..()
AddComponent(/datum/component/uplink, owner, TRUE, FALSE, null, tc_amount)
/obj/item/uplink/debug
name = "debug uplink"
/obj/item/uplink/debug/Initialize(mapload, owner, tc_amount = 9000)
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.name = "debug uplink"
hidden_uplink.debug = TRUE
/obj/item/uplink/nuclear/debug
name = "debug nuclear uplink"
/obj/item/uplink/nuclear/debug/Initialize(mapload, owner, tc_amount = 9000)
. = ..()
var/datum/component/uplink/hidden_uplink = GetComponent(/datum/component/uplink)
hidden_uplink.set_gamemode(/datum/game_mode/nuclear)
hidden_uplink.name = "debug nuclear uplink"
hidden_uplink.debug = TRUE
+2 -1
View File
@@ -157,6 +157,7 @@
category = "Role-Restricted"
exclude_modes = list(/datum/game_mode/nuclear, /datum/game_mode/nuclear/clown_ops)
surplus = 0
cant_discount = TRUE
/datum/uplink_item/badass
category = "(Pointless) Badassery"
@@ -164,4 +165,4 @@
//Discounts (dynamically filled above)
/datum/uplink_item/discounts
category = "Discounted Gear"
category = "Discounted Gear"
@@ -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."