diff --git a/code/_onclick/ai.dm b/code/_onclick/ai.dm
index 3122f089bd6..800cdd8341a 100644
--- a/code/_onclick/ai.dm
+++ b/code/_onclick/ai.dm
@@ -42,6 +42,9 @@
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
+ if(modifiers["shift"] && modifiers["alt"])
+ AltShiftClickOn(A)
+ return
if(modifiers["middle"])
MiddleClickOn(A)
return
@@ -99,6 +102,8 @@
/mob/living/silicon/ai/CtrlShiftClickOn(var/atom/A)
A.AICtrlShiftClick(src)
+/mob/living/silicon/ai/AltShiftClickOn(var/atom/A)
+ A.AIAltShiftClick(src)
/mob/living/silicon/ai/ShiftClickOn(var/atom/A)
A.AIShiftClick(src)
/mob/living/silicon/ai/CtrlClickOn(var/atom/A)
@@ -118,6 +123,18 @@
examine()
return
+/atom/proc/AIAltShiftClick()
+ return
+
+/obj/machinery/door/airlock/AIAltShiftClick() // Sets/Unsets Emergency Access Override
+ if(emagged)
+ return
+ if(!emergency)
+ Topic("aiEnable=11", list("aiEnable"="11"), 1) // 1 meaning no window (consistency!)
+ else
+ Topic("aiDisable=11", list("aiDisable"="11"), 1)
+ return
+
/atom/proc/AIShiftClick()
return
diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm
index 533a6d26c84..bb288fc7d48 100644
--- a/code/_onclick/click.dm
+++ b/code/_onclick/click.dm
@@ -46,6 +46,9 @@
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
+ if(modifiers["shift"] && modifiers["alt"])
+ AltShiftClickOn(A)
+ return
if(modifiers["middle"])
MiddleClickOn(A)
return
@@ -262,7 +265,7 @@
return T.Adjacent(src)
/*
- Control+Shift click
+ Control+Shift/Alt+Shift click
Unused except for AI
*/
/mob/proc/CtrlShiftClickOn(var/atom/A)
@@ -271,6 +274,14 @@
/atom/proc/CtrlShiftClick(var/mob/user)
return
+
+/mob/proc/AltShiftClickOn(var/atom/A)
+ A.AltShiftClick(src)
+ return
+
+/atom/proc/AltShiftClick(var/mob/user)
+ return
+
/*
Misc helpers
diff --git a/code/_onclick/cyborg.dm b/code/_onclick/cyborg.dm
index fc32220b6d4..4e20ef9ec32 100644
--- a/code/_onclick/cyborg.dm
+++ b/code/_onclick/cyborg.dm
@@ -19,6 +19,9 @@
if(modifiers["shift"] && modifiers["ctrl"])
CtrlShiftClickOn(A)
return
+ if(modifiers["shift"] && modifiers["alt"])
+ AltShiftClickOn(A)
+ return
if(modifiers["middle"])
MiddleClickOn(A)
return
@@ -117,6 +120,8 @@
// for non-doors/apcs
/mob/living/silicon/robot/CtrlShiftClickOn(var/atom/A)
A.BorgCtrlShiftClick(src)
+/mob/living/silicon/robot/AltShiftClickOn(var/atom/A)
+ A.BorgAltShiftClick(src)
/mob/living/silicon/robot/ShiftClickOn(var/atom/A)
A.BorgShiftClick(src)
/mob/living/silicon/robot/CtrlClickOn(var/atom/A)
@@ -129,9 +134,15 @@
examine()
user.face_atom(src)
return
+
+/atom/proc/BorgAltShiftClick()
+ return
+
+/obj/machinery/door/airlock/BorgAltShiftClick() // Enables emergency override on doors! Forwards to AI code.
+ AIAltShiftClick()
/atom/proc/BorgShiftClick()
- return
+ return
/obj/machinery/door/airlock/BorgShiftClick() // Opens and closes doors! Forwards to AI code.
AIShiftClick()
diff --git a/code/datums/wires/airlock.dm b/code/datums/wires/airlock.dm
index f53c822a027..3b6d009a5ff 100644
--- a/code/datums/wires/airlock.dm
+++ b/code/datums/wires/airlock.dm
@@ -34,12 +34,13 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
/datum/wires/airlock/GetInteractWindow()
var/obj/machinery/door/airlock/A = holder
. += ..()
- . += text("
\n[]
\n[]
\n[]
\n[]
\n[]
\n[]", (A.locked ? "The door bolts have fallen!" : "The door bolts look up."),
+ . += text("
\n[]
\n[]
\n[]
\n[]
\n[]
\n[]
\n[]", (A.locked ? "The door bolts have fallen!" : "The door bolts look up."),
(A.lights ? "The door bolt lights are on." : "The door bolt lights are off!"),
((A.arePowerSystemsOn() && !(A.stat & NOPOWER)) ? "The test light is on." : "The test light is off!"),
(A.aiControlDisabled==0 ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."),
(A.safe==0 ? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."),
- (A.normalspeed==0 ? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."))
+ (A.normalspeed==0 ? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."),
+ (A.emergency==0 ? "The emergency lights are off." : "The emergency lights are on."))
/datum/wires/airlock/UpdateCut(var/index, var/mended)
@@ -123,9 +124,12 @@ var/const/AIRLOCK_WIRE_LIGHT = 2048
var/obj/machinery/door/airlock/A = holder
switch(index)
if(AIRLOCK_WIRE_IDSCAN)
- //Sending a pulse through this flashes the red light on the door (if the door has power).
+ //Sending a pulse through this disables emergency access and flashes the red light on the door (if the door has power).
if((A.arePowerSystemsOn()) && (!(A.stat & NOPOWER)))
A.door_animate("deny")
+ if(A.emergency)
+ A.emergency = 0
+ A.update_icon()
if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2)
//Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter).
A.loseMainPower()
diff --git a/code/game/gamemodes/events/power_failure.dm b/code/game/gamemodes/events/power_failure.dm
index f5c63e381bd..017b88f9364 100644
--- a/code/game/gamemodes/events/power_failure.dm
+++ b/code/game/gamemodes/events/power_failure.dm
@@ -5,7 +5,7 @@
for(var/mob/M in player_list)
M << sound('sound/AI/poweroff.ogg')
- var/list/skipped_areas = list(/area/turret_protected/ai)
+ var/list/skipped_areas = list(/area/turret_protected/ai,/area/engine/engineering)
for(var/obj/machinery/power/smes/S in machines)
var/area/current_area = get_area(S)
@@ -23,7 +23,7 @@
C.cell.charge = 0
/proc/power_restore(var/announce = 1)
- var/list/skipped_areas = list(/area/turret_protected/ai)
+ var/list/skipped_areas = list(/area/turret_protected/ai,/area/engine/engineering)
if(announce)
command_alert("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal")
diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm
index 324a9ce53d9..ea15a1bf730 100644
--- a/code/game/machinery/bots/bots.dm
+++ b/code/game/machinery/bots/bots.dm
@@ -414,13 +414,13 @@ obj/machinery/bot/proc/bot_move(var/dest, var/move_speed)
obj/machinery/bot/proc/bot_step(var/dest)
if(path && path.len > 1)
- step_to(src, path[1])
+ step_towards(src, path[1])
if(get_turf(src) == path[1]) //Successful move
path -= path[1]
else
return 0
else if(path.len == 1)
- step_to(src, dest)
+ step_towards(src, dest)
path = list()
return 1
@@ -777,7 +777,7 @@ obj/machinery/bot/proc/bot_summon()
/obj/machinery/bot/Bump(M as mob|obj) //Leave no door unopened!
- if((istype(M, /obj/machinery/door/airlock) || istype(M, /obj/machinery/door/window)) && (!isnull(botcard)))
+ if((istype(M, /obj/machinery/door/airlock) || istype(M, /obj/machinery/door/window)) && (!isnull(botcard)))
var/obj/machinery/door/D = M
if(D.check_access(botcard))
D.open()
@@ -786,4 +786,5 @@ obj/machinery/bot/proc/bot_summon()
var/mob/living/Mb = M
loc = Mb.loc
frustration = 0
- return
\ No newline at end of file
+ return
+
\ No newline at end of file
diff --git a/code/game/machinery/bots/ed209bot.dm b/code/game/machinery/bots/ed209bot.dm
index d5b5566d677..6bcc05dfd92 100644
--- a/code/game/machinery/bots/ed209bot.dm
+++ b/code/game/machinery/bots/ed209bot.dm
@@ -113,6 +113,7 @@
. = ..()
if (.)
return
+ usr.set_machine(src)
var/dat
dat += hack(user)
dat += text({"
@@ -400,25 +401,6 @@ Auto Patrol[]"},
return 1
return 0
-/obj/machinery/bot/ed209/Bump(M as mob|obj) //Leave no door unopened!
- if ((istype(M, /obj/machinery/door)) && (!isnull(botcard)))
- var/obj/machinery/door/D = M
- if (!istype(D, /obj/machinery/door/firedoor) && D.check_access(botcard))
- D.open()
- frustration = 0
- else if ((istype(M, /mob/living/)) && (!anchored))
- loc = M:loc
- frustration = 0
- return
-
-/* terrible
-/obj/machinery/bot/ed209/Bumped(atom/movable/M as mob|obj)
- spawn(0)
- if (M)
- var/turf/T = get_turf(src)
- M:loc = T
-*/
-
/obj/machinery/bot/ed209/explode()
walk_to(src,0)
visible_message("[src] blows apart!")
diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm
index 2c437492097..eb79c59f304 100644
--- a/code/game/machinery/bots/medbot.dm
+++ b/code/game/machinery/bots/medbot.dm
@@ -136,6 +136,7 @@
. = ..()
if (.)
return
+ usr.set_machine(src)
var/dat
dat += hack(user)
dat += "Medical Unit Controls v1.1
"
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index 196cea60241..24076937260 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -435,13 +435,14 @@ About the new airlock wires panel:
/obj/machinery/door/airlock/update_icon()
if(overlays) overlays.Cut()
+ overlays = list()
+ if(emergency) overlays += image('icons/obj/doors/doorint.dmi', "elights")
if(density)
if(locked && lights)
icon_state = "door_locked"
else
icon_state = "door_closed"
if(p_open || welded || frozen)
- overlays = list()
if(p_open)
overlays += image(icon, "panel_open")
if(welded)
@@ -508,6 +509,11 @@ About the new airlock wires panel:
else
t1 += text("IdScan enabled. Disable?
\n", src)
+ if(src.emergency)
+ t1 += text("Emergency Access Override is enabled. Disable?
\n", src)
+ else
+ t1 += text("Emergency Access Override is disabled. Enable?
\n", src)
+
if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER1))
t1 += text("Main Power Input wire is cut.
\n")
if(src.isWireCut(AIRLOCK_WIRE_MAIN_POWER2))
@@ -686,8 +692,9 @@ About the new airlock wires panel:
return 1
/obj/machinery/door/airlock/Topic(href, href_list, var/nowindow = 0)
- // If you add an if(..()) check you must first remove the var/nowindow parameter.
- // Otherwise it will runtime with this kind of error: null.Topic()
+ //AI
+ //aiDisable - 1 idscan, 2 disrupt main power, 3 disrupt backup power, 4 drop door bolts, 5 un-electrify door, 7 close door, 8 door safties, 9 door speed, 11 emergency access
+ //aiEnable - 1 idscan, 4 raise door bolts, 5 electrify door for 30 seconds, 6 electrify door indefinitely, 7 open door, 8 door safties, 9 door speed, 11 emergency access
if(!nowindow)
..()
if(usr.stat || usr.restrained()|| usr.small)
@@ -826,6 +833,13 @@ About the new airlock wires panel:
usr << "The door bolt lights have been disabled."
else
usr << "The door bolt lights are already disabled!"
+ if(11)
+ // Emergency access
+ if (src.emergency)
+ emergency = 0
+ else
+ usr << text("Emergency access is already disabled!")
+
else if(href_list["aiEnable"])
var/code = text2num(href_list["aiEnable"])
@@ -917,6 +931,13 @@ About the new airlock wires panel:
usr << "The door bolt lights have been enabled"
else
usr << "The door bolt lights are already enabled!"
+ if(11)
+ // Emergency access
+ if (!src.emergency)
+ emergency = 1
+ else
+ usr << text("Emergency access is already enabled!")
+
add_fingerprint(usr)
update_icon()
@@ -1209,3 +1230,8 @@ About the new airlock wires panel:
return
else
return
+
+
+/obj/machinery/door/airlock/CanAStarPass(var/obj/item/weapon/card/id/ID)
+//Airlock is passable if it is open (!density), bot has access, and is not bolted shut)
+ return !density || (check_access(ID) && !locked)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index f7410d589f0..e8023a62e8c 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -18,6 +18,7 @@
var/glass = 0
var/normalspeed = 1
var/heat_proof = 0 // For glass airlocks/opacity firedoors
+ var/emergency = 0
var/air_properties_vary_with_direction = 0
//Multi-tile doors
@@ -68,7 +69,7 @@
if(istype(AM, /obj/machinery/bot))
var/obj/machinery/bot/bot = AM
- if(src.check_access(bot.botcard))
+ if(src.check_access(bot.botcard) || emergency == 1)
if(density)
open()
return
@@ -76,7 +77,7 @@
if(istype(AM, /obj/mecha))
var/obj/mecha/mecha = AM
if(density)
- if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access)))
+ if(mecha.occupant && (src.allowed(mecha.occupant) || src.check_access_list(mecha.operation_req_access) || emergency == 1))
open()
else
flick("door_deny", src)
@@ -101,7 +102,7 @@
//used in the AStar algorithm to determinate if the turf the door is on is passable
/obj/machinery/door/proc/CanAStarPass(var/obj/item/weapon/card/id/ID)
- return !density || check_access(ID)
+ return !density
/obj/machinery/door/proc/bumpopen(mob/user as mob)
if(operating) return
@@ -113,8 +114,10 @@
user = null
if(density)
- if(allowed(user)) open()
- else flick("door_deny", src)
+ if(allowed(user) || src.emergency == 1)
+ open()
+ else
+ flick("door_deny", src)
return
/obj/machinery/door/meteorhit(obj/M as obj)
@@ -153,7 +156,7 @@
open()
operating = -1
return 1
- if(src.allowed(user))
+ if(src.allowed(user) || src.emergency == 1)
if(src.density)
open()
else
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 4cc8e45d6a2..a6609c03ec1 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -468,7 +468,3 @@
/obj/machinery/door/firedoor/multi_tile/triple
icon = 'icons/obj/doors/DoorHazard3x1.dmi'
width = 3
-
-//used in the AStar algorithm to determinate if the turf the door is on is passable
-/obj/machinery/door/firedoor/CanAStarPass()
- return !density
diff --git a/code/modules/mob/living/carbon/alien/alien.dm b/code/modules/mob/living/carbon/alien/alien.dm
index 81633dd25f2..0c0d793c34e 100644
--- a/code/modules/mob/living/carbon/alien/alien.dm
+++ b/code/modules/mob/living/carbon/alien/alien.dm
@@ -208,6 +208,41 @@
see_invisible = 45
nightvision = 0
usr.hud_used.nightvisionicon.icon_state = "nightvision0"
+
+
+/mob/living/carbon/alien/assess_threat(var/obj/machinery/bot/secbot/judgebot, var/lasercolor)
+ if(judgebot.emagged == 2)
+ return 10 //Everyone is a criminal!
+ var/threatcount = 0
+
+ //Securitrons can't identify aliens
+ if(!lasercolor && judgebot.idcheck)
+ threatcount += 4
+
+ //Lasertag bullshit
+ if(lasercolor)
+ if(lasercolor == "b")//Lasertag turrets target the opposing team, how great is that? -Sieve
+ if((istype(r_hand,/obj/item/weapon/gun/energy/laser/redtag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/redtag)))
+ threatcount += 4
+
+ if(lasercolor == "r")
+ if((istype(r_hand,/obj/item/weapon/gun/energy/laser/bluetag)) || (istype(l_hand,/obj/item/weapon/gun/energy/laser/bluetag)))
+ threatcount += 4
+
+ return threatcount
+
+ //Check for weapons
+ if(judgebot.weaponscheck)
+ if(judgebot.check_for_weapons(l_hand))
+ threatcount += 4
+ if(judgebot.check_for_weapons(r_hand))
+ threatcount += 4
+
+ //Loyalty implants imply trustworthyness
+ if(isloyal(src))
+ threatcount -= 1
+
+ return threatcount
/*----------------------------------------
Proc: AddInfectionImages()
diff --git a/code/modules/security levels/keycard authentication.dm b/code/modules/security levels/keycard authentication.dm
index 4ff8db96a62..9d94725adf6 100644
--- a/code/modules/security levels/keycard authentication.dm
+++ b/code/modules/security levels/keycard authentication.dm
@@ -160,16 +160,19 @@
var/global/maint_all_access = 0
/proc/make_maint_all_access()
- maint_all_access = 1
+ for(var/area/maintenance/A in world)
+ for(var/obj/machinery/door/airlock/D in A)
+ D.emergency = 1
+ D.update_icon(0)
world << "Attention!"
world << "The maintenance access requirement has been revoked on all airlocks."
-
+ maint_all_access = 1
+
/proc/revoke_maint_all_access()
- maint_all_access = 0
+ for(var/area/maintenance/A in world)
+ for(var/obj/machinery/door/airlock/D in A)
+ D.emergency = 0
+ D.update_icon(0)
world << "Attention!"
world << "The maintenance access requirement has been readded on all maintenance airlocks."
-
-/obj/machinery/door/airlock/allowed(mob/M)
- if(maint_all_access && src.check_access_list(list(access_maint_tunnels)))
- return 1
- return ..(M)
+ maint_all_access = 0
\ No newline at end of file
diff --git a/icons/obj/doors/doorint.dmi b/icons/obj/doors/doorint.dmi
index 68fdd16a566..1938f24e5f8 100644
Binary files a/icons/obj/doors/doorint.dmi and b/icons/obj/doors/doorint.dmi differ