diff --git a/code/controllers/Processes/alarm.dm b/code/controllers/Processes/alarm.dm
index bf2d501ae7a..311d8912d7a 100644
--- a/code/controllers/Processes/alarm.dm
+++ b/code/controllers/Processes/alarm.dm
@@ -1,6 +1,7 @@
// We manually initialize the alarm handlers instead of looping over all existing types
// to make it possible to write: camera.triggerAlarm() rather than alarm_manager.managers[datum/alarm_handler/camera].triggerAlarm() or a variant thereof.
/var/global/datum/alarm_handler/atmosphere/atmosphere_alarm = new()
+/var/global/datum/alarm_handler/burglar/burglar_alarm = new()
/var/global/datum/alarm_handler/camera/camera_alarm = new()
/var/global/datum/alarm_handler/fire/fire_alarm = new()
/var/global/datum/alarm_handler/motion/motion_alarm = new()
@@ -15,7 +16,7 @@ var/datum/controller/process/alarm/alarm_manager
/datum/controller/process/alarm/setup()
name = "alarm"
schedule_interval = 20 // every 2 seconds
- all_handlers = list(atmosphere_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
+ all_handlers = list(atmosphere_alarm, burglar_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
alarm_manager = src
/datum/controller/process/alarm/doWork()
diff --git a/code/controllers/hooks-defs.dm b/code/controllers/hooks-defs.dm
index 0d283a3e5ba..ae0e7e85b69 100644
--- a/code/controllers/hooks-defs.dm
+++ b/code/controllers/hooks-defs.dm
@@ -92,3 +92,10 @@
* Parameters: var/obj/structure/closet/crate/sold, var/area/shuttle
*/
/hook/sell_crate
+
+/**
+ * Captain spawned hook.
+ * Called in supervisor.dm when a captain spawns
+ * Parameters: var/mob/living/carbon/human/captain
+ */
+/hook/captain_spawned
diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm
index 7dafb778e7a..1f52c4f56fb 100644
--- a/code/game/area/areas.dm
+++ b/code/game/area/areas.dm
@@ -108,6 +108,31 @@
updateicon()
mouse_opacity = 0
air_doors_open()
+
+ return
+
+/area/proc/burglaralert(var/obj/trigger)
+ if(always_unpowered == 1) //no burglar alarms in space/asteroid
+ return
+
+ //Trigger alarm effect
+ set_fire_alarm_effect()
+
+ //Lockdown airlocks
+ for(var/obj/machinery/door/airlock/A in src)
+ spawn(0)
+ A.close()
+ if(A.density)
+ A.lock()
+
+ burglar_alarm.triggerAlarm(src, trigger)
+ spawn(600)
+ burglar_alarm.clearAlarm(src, trigger)
+
+/area/proc/set_fire_alarm_effect()
+ fire = 1
+ updateicon()
+ mouse_opacity = 0
/area/proc/readyalert()
if(!eject)
diff --git a/code/game/jobs/job/supervisor.dm b/code/game/jobs/job/supervisor.dm
index f9f2fc8316e..9b193628eda 100644
--- a/code/game/jobs/job/supervisor.dm
+++ b/code/game/jobs/job/supervisor.dm
@@ -42,6 +42,7 @@ var/datum/announcement/minor/captain_announcement = new(do_newscast = 1)
var/obj/item/organ/external/affected = H.organs_by_name["head"]
affected.implants += L
L.part = affected
+ callHook("captain_spawned", list("captain" = H))
return 1
get_access()
diff --git a/code/game/objects/structures/displaycase.dm b/code/game/objects/structures/displaycase.dm
index 5b5109a8b9c..404326e6bc6 100644
--- a/code/game/objects/structures/displaycase.dm
+++ b/code/game/objects/structures/displaycase.dm
@@ -1,19 +1,35 @@
+#define DISPLAYCASE_FRAME_CIRCUIT 0
+#define DISPLAYCASE_FRAME_SCREWDRIVER 1
+
+// List and hook used to set up the captain's print on their display case
+var/global/list/captain_display_cases = list()
+
+/hook/captain_spawned/proc/displaycase(mob/living/carbon/human/captain)
+ if(!captain_display_cases.len)
+ return 1
+ var/fingerprint = captain.get_print()
+ for(var/obj/structure/displaycase/D in captain_display_cases)
+ if(istype(D))
+ D.ue = fingerprint
+
+ return 1
+
/obj/structure/displaycase_frame
name = "display case frame"
icon = 'icons/obj/stock_parts.dmi'
- icon_state="box_glass"
+ icon_state = "box_glass"
var/obj/item/weapon/airlock_electronics/circuit = null
- var/state=0
+ var/state = DISPLAYCASE_FRAME_CIRCUIT
/obj/structure/displaycase_frame/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
- var/pstate=state
- var/turf/T=get_turf(src)
+ var/pstate = state
+ var/turf/T = get_turf(src)
switch(state)
- if(0)
+ if(DISPLAYCASE_FRAME_CIRCUIT)
if(istype(W, /obj/item/weapon/airlock_electronics) && W:icon_state != "door_electronics_smoked")
user.drop_item()
circuit = W
- circuit.loc = src
+ circuit.forceMove(src)
state++
playsound(get_turf(src), 'sound/items/Screwdriver.ogg', 50, 1)
if(istype(W, /obj/item/weapon/crowbar))
@@ -23,9 +39,9 @@
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
return
- if(1)
+ if(DISPLAYCASE_FRAME_SCREWDRIVER)
if(isscrewdriver(W))
- var/obj/structure/displaycase/C=new(T)
+ var/obj/structure/displaycase/C = new(T)
if(circuit.one_access)
C.req_access = null
C.req_one_access = circuit.conf_access
@@ -36,20 +52,20 @@
qdel(src)
return
if(istype(W, /obj/item/weapon/crowbar))
- circuit.loc=T
- circuit=null
+ circuit.forceMove(T)
+ circuit = null
state--
playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1)
- if(pstate!=state)
- pstate=state
+ if(pstate != state)
+ pstate = state
update_icon()
/obj/structure/displaycase_frame/update_icon()
switch(state)
if(1)
- icon_state="box_glass_circuit"
+ icon_state = "box_glass_circuit"
else
- icon_state="box_glass"
+ icon_state = "box_glass"
/obj/structure/displaycase
name = "display case"
@@ -58,7 +74,7 @@
desc = "A display case for prized possessions. It taunts you to kick it."
density = 1
anchored = 1
- unacidable = 1//Dissolving the case would also delete the contents.
+ unacidable = 1 //Dissolving the case would also delete the contents.
var/health = 30
var/obj/item/occupant = null
var/destroyed = 0
@@ -69,31 +85,39 @@
/obj/structure/displaycase/captains_laser
name = "captain's display case"
- desc = "A display case for the captain's antique laser gun. It taunts you to kick it."
+ desc = "A display case for the captain's antique laser gun. Hooked up with an anti-theft system."
/obj/structure/displaycase/captains_laser/New()
+ captain_display_cases += src
req_access = list(access_captain)
locked = 1
spawn(5)
occupant = new /obj/item/weapon/gun/energy/laser/captain(src)
update_icon()
-
-/obj/structure/proc/getPrint(mob/user as mob)
- return md5(user:dna:uni_identity)
+
+/obj/structure/displaycase/Destroy()
+ dump()
+ qdel(circuit)
+ circuit = null
+ return ..()
+
+/obj/structure/displaycase/captain_laser/Destroy()
+ captain_display_cases -= src
+ return ..()
/obj/structure/displaycase/examine()
..()
- usr << "\blue Peering through the glass, you see that it contains:"
+ usr << "Peering through the glass, you see that it contains:"
if(occupant)
- usr << "\icon[occupant] \blue \A [occupant]"
+ usr << "\icon[occupant] \A [occupant]."
else:
usr << "Nothing."
/obj/structure/displaycase/proc/dump()
if(occupant)
- occupant.loc=get_turf(src)
- occupant=null
- occupant_overlay=null
+ occupant.forceMove(get_turf(src))
+ occupant = null
+ occupant_overlay = null
/obj/structure/displaycase/ex_act(severity)
switch(severity)
@@ -111,7 +135,6 @@
src.health -= 5
src.healthcheck()
-
/obj/structure/displaycase/bullet_act(var/obj/item/projectile/Proj)
if((Proj.damage_type == BRUTE || Proj.damage_type == BURN))
health -= Proj.damage
@@ -133,10 +156,16 @@
PoolOrNew(/obj/item/weapon/shard, loc)
playsound(get_turf(src), "shatter", 70, 1)
update_icon()
+
+ burglar_alarm()
else
playsound(get_turf(src), 'sound/effects/Glasshit.ogg', 75, 1)
return
-
+
+/obj/structure/displaycase/proc/burglar_alarm()
+ var/area/alarmed = get_area(src)
+ alarmed.burglaralert(src)
+
/obj/structure/displaycase/update_icon()
if(src.destroyed)
src.icon_state = "glassbox2b"
@@ -147,52 +176,50 @@
var/icon/occupant_icon=getFlatIcon(occupant)
occupant_icon.Scale(16,16)
occupant_overlay = image(occupant_icon)
- occupant_overlay.pixel_x=8
- occupant_overlay.pixel_y=8
+ occupant_overlay.pixel_x = 8
+ occupant_overlay.pixel_y = 8
if(locked)
- occupant_overlay.alpha=128//ChangeOpacity(0.5)
- //underlays += occupant_overlay
+ occupant_overlay.alpha = 128
overlays += occupant_overlay
return
-
/obj/structure/displaycase/attackby(obj/item/weapon/W as obj, mob/user as mob, params)
if(istype(W, /obj/item/weapon/card))
- var/obj/item/weapon/card/id/I=W
+ var/obj/item/weapon/card/id/I = W
if(!check_access(I))
- user << "\red Access denied."
+ user << "Access denied."
return
locked = !locked
if(!locked)
- user << "\icon[src] \blue \The [src] clicks as locks release, and it slowly opens for you."
+ user << "\icon[src] \The [src] clicks as locks release, and it slowly opens for you."
else
- user << "\icon[src] \blue You close \the [src] and swipe your card, locking it."
+ user << "\icon[src] You close \the [src] and swipe your card, locking it."
update_icon()
return
if(istype(W,/obj/item/weapon/crowbar) && (!locked || destroyed))
user.visible_message("[user.name] pries \the [src] apart.", \
"You pry \the [src] apart.", \
"You hear something pop.")
- var/turf/T=get_turf(src)
+ var/turf/T = get_turf(src)
playsound(T, 'sound/items/Crowbar.ogg', 50, 1)
dump()
var/obj/item/weapon/airlock_electronics/C = circuit
if(!C)
- C=new (src)
- C.one_access=!(req_access && req_access.len>0)
+ C = new (src)
+ C.one_access = !(req_access && req_access.len>0)
if(!C.one_access)
- C.conf_access=req_access
+ C.conf_access = req_access
else
- C.conf_access=req_one_access
+ C.conf_access = req_one_access
if(!destroyed)
- var/obj/structure/displaycase_frame/F=new(T)
- F.state=1
- F.circuit=C
- F.circuit.loc=F
+ var/obj/structure/displaycase_frame/F = new(T)
+ F.state = DISPLAYCASE_FRAME_SCREWDRIVER
+ F.circuit = C
+ F.circuit.forceMove(F)
F.update_icon()
else
- C.loc=T
- circuit=null
+ C.forceMove(T)
+ circuit = null
new /obj/machinery/constructable_frame/machine_frame(T)
qdel(src)
if(user.a_intent == I_HARM)
@@ -201,48 +228,49 @@
..()
else
if(locked)
- user << "\red It's locked, you can't put anything into it."
+ user << "It's locked, you can't put anything into it."
return
if(!occupant)
- user << "\blue You insert \the [W] into \the [src], and it floats as the hoverfield activates."
+ user << "You insert \the [W] into \the [src], and it floats as the hoverfield activates."
user.drop_item()
- W.loc=src
+ W.forceMove(src)
occupant=W
update_icon()
-
/obj/structure/displaycase/attack_hand(mob/user as mob)
if (destroyed)
if(occupant)
dump()
- user << "\red You smash your fist into the delicate electronics at the bottom of the case, and deactivate the hover field permanently."
+ user << "You smash your fist into the delicate electronics at the bottom of the case, and deactivate the hover field permanently."
src.add_fingerprint(user)
update_icon()
else
if(user.a_intent == I_HARM)
user.changeNext_move(CLICK_CD_MELEE)
user.do_attack_animation(src)
- user.visible_message("\red [user.name] kicks \the [src]!", \
- "\red You kick \the [src]!", \
+ user.visible_message("[user.name] kicks \the [src]!", \
+ "You kick \the [src]!", \
"You hear glass crack.")
src.health -= 2
healthcheck()
else if(!locked)
if(ishuman(user))
+ var/mob/living/carbon/human/H = user
+ var/print = H.get_print()
if(!ue)
- user << "\blue Your press your thumb against the fingerprint scanner, registering your identity with the case."
- ue = getPrint(user)
+ user << "Your press your thumb against the fingerprint scanner, registering your identity with the case."
+ ue = print
return
- if(ue!=getPrint(user))
- user << "\red Access denied."
+ if(ue != print)
+ user << "Access denied."
return
if(occupant)
- user << "\blue Your press your thumb against the fingerprint scanner, and deactivate the hover field built into the case."
+ user << "Your press your thumb against the fingerprint scanner, and deactivate the hover field built into the case."
dump()
update_icon()
else
- src << "\icon[src] \red \The [src] is empty!"
+ src << "\icon[src] \The [src] is empty!"
else
user.visible_message("[user.name] gently runs his hands over \the [src] in appreciation of its contents.", \
"You gently run your hands over \the [src] in appreciation of its contents.", \
diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
index 4af9b504ed3..0a9917fda9d 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
@@ -63,7 +63,7 @@
handle_rotation()
if(pulling) // Driver
if(pulling.loc == src.loc) // We moved onto the wheelchair? Revert!
- pulling.loc = T
+ pulling.forceMove(T)
else
spawn(0)
if(get_dist(src, pulling) > 1) // We are too far away? Losing control.
@@ -95,7 +95,7 @@
pulling = null
else
if (occupant && (src.loc != occupant.loc))
- src.loc = occupant.loc // Failsafe to make sure the wheelchair stays beneath the occupant after driving
+ forceMove(occupant.loc) // Failsafe to make sure the wheelchair stays beneath the occupant after driving
handle_rotation()
/obj/structure/stool/bed/chair/wheelchair/attack_hand(mob/user as mob)
diff --git a/code/modules/alarm/burglar_alarm.dm b/code/modules/alarm/burglar_alarm.dm
new file mode 100644
index 00000000000..c55cb12deef
--- /dev/null
+++ b/code/modules/alarm/burglar_alarm.dm
@@ -0,0 +1,2 @@
+/datum/alarm_handler/burglar
+ category = "Burglar Alarms"
diff --git a/code/modules/mob/inventory.dm b/code/modules/mob/inventory.dm
index 04b8745c4ac..e5b37c78657 100644
--- a/code/modules/mob/inventory.dm
+++ b/code/modules/mob/inventory.dm
@@ -27,7 +27,7 @@
if(!istype(W))
return 0
if(!l_hand)
- W.loc = src //TODO: move to equipped?
+ W.forceMove(src) //TODO: move to equipped?
l_hand = W
W.layer = 20 //TODO: move to equipped?
// l_hand.screen_loc = ui_lhand
@@ -45,7 +45,7 @@
if(!istype(W))
return 0
if(!r_hand)
- W.loc = src
+ W.forceMove(src)
r_hand = W
W.layer = 20
// r_hand.screen_loc = ui_rhand
@@ -71,7 +71,7 @@
//This is probably the main one you need to know :)
//Just puts stuff on the floor for most mobs, since all mobs have hands but putting stuff in the AI/corgi/ghost hand is VERY BAD.
/mob/proc/put_in_hands(obj/item/W)
- W.loc = get_turf(src)
+ W.forceMove(get_turf(src))
W.layer = initial(W.layer)
W.dropped()
@@ -114,7 +114,7 @@
if(I)
if(client)
client.screen -= I
- I.loc = loc
+ I.forceMove(loc)
I.dropped(src)
if(I)
I.layer = initial(I.layer)
@@ -249,13 +249,13 @@
if (src.back && istype(src.back, /obj/item/weapon/storage/backpack))
var/obj/item/weapon/storage/backpack/B = src.back
if(B.contents.len < B.storage_slots && W.w_class <= B.max_w_class)
- W.loc = B
+ W.forceMove(B)
equipped = 1
if(equipped)
W.layer = 20
if(src.back && W.loc != src.back)
- W.loc = src
+ W.forceMove(src)
else
if (del_on_fail)
qdel(W)
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 149273f6351..2421bbea635 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -1779,4 +1779,9 @@
if(I.body_parts_covered & HEAD)
prot["head"] = max(1 - I.permeability_coefficient, prot["head"])
var/protection = (prot["head"] + prot["arms"] + prot["feet"] + prot["legs"] + prot["groin"] + prot["chest"] + prot["hands"])/7
- return protection
\ No newline at end of file
+ return protection
+
+/mob/living/carbon/human/proc/get_print()
+ if(!dna)
+ return 0
+ return md5(dna.uni_identity)
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/subsystems.dm b/code/modules/mob/living/silicon/subsystems.dm
index e2dd77d75a6..9a1c713ab72 100644
--- a/code/modules/mob/living/silicon/subsystems.dm
+++ b/code/modules/mob/living/silicon/subsystems.dm
@@ -41,7 +41,7 @@
if(!register_alarms)
return
- var/list/register_to = list(atmosphere_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
+ var/list/register_to = list(atmosphere_alarm, burglar_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
for(var/datum/alarm_handler/AH in register_to)
AH.register(src, /mob/living/silicon/proc/receive_alarm)
queued_alarms[AH] = list() // Makes sure alarms remain listed in consistent order
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 8f38853de78..44cf995e14b 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1235,7 +1235,7 @@ mob/proc/yank_out_object()
var/mob/living/carbon/human/human_user = U
human_user.bloody_hands(H)
- selection.loc = get_turf(src)
+ selection.forceMove(get_turf(src))
if(!(U.l_hand && U.r_hand))
U.put_in_hands(selection)
diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm
index 1201c95b74c..a9d8f2b595f 100644
--- a/code/modules/mob/mob_movement.dm
+++ b/code/modules/mob/mob_movement.dm
@@ -170,7 +170,7 @@
if(!mob.control_object) return
mob.control_object.dir = direct
else
- mob.control_object.loc = get_step(mob.control_object,direct)
+ mob.control_object.forceMove(get_step(mob.control_object,direct))
return
@@ -391,7 +391,7 @@
var/mob/living/L = mob
switch(L.incorporeal_move)
if(1)
- L.loc = get_step(L, direct)
+ L.forceMove(get_step(L, direct))
L.dir = direct
if(2)
if(prob(50))
@@ -420,7 +420,7 @@
return
else
return
- L.loc = locate(locx,locy,mobloc.z)
+ L.forceMove(locate(locx,locy,mobloc.z))
spawn(0)
var/limit = 2//For only two trailing shadows.
for(var/turf/T in getline(mobloc, L.loc))
@@ -431,7 +431,7 @@
else
spawn(0)
anim(mobloc,mob,'icons/mob/mob.dmi',,"shadow",,L.dir)
- L.loc = get_step(L, direct)
+ L.forceMove(get_step(L, direct))
L.dir = direct
if(3) //Incorporeal move, but blocked by holy-watered tiles
var/turf/simulated/floor/stepTurf = get_step(L, direct)
@@ -441,7 +441,7 @@
spawn(2)
L.notransform = 0
else
- L.loc = get_step(L, direct)
+ L.forceMove(get_step(L, direct))
L.dir = direct
return 1
diff --git a/code/modules/nano/modules/alarm_monitor.dm b/code/modules/nano/modules/alarm_monitor.dm
index 8625e1cce3b..5c38f480a49 100644
--- a/code/modules/nano/modules/alarm_monitor.dm
+++ b/code/modules/nano/modules/alarm_monitor.dm
@@ -5,7 +5,7 @@
/datum/nano_module/alarm_monitor/all/New()
..()
- alarm_handlers = list(atmosphere_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
+ alarm_handlers = list(atmosphere_alarm, burglar_alarm, camera_alarm, fire_alarm, motion_alarm, power_alarm)
/datum/nano_module/alarm_monitor/engineering/New()
..()
@@ -13,7 +13,7 @@
/datum/nano_module/alarm_monitor/security/New()
..()
- alarm_handlers = list(camera_alarm, motion_alarm)
+ alarm_handlers = list(burglar_alarm, camera_alarm, motion_alarm)
/datum/nano_module/alarm_monitor/proc/register(var/object, var/procName)
for(var/datum/alarm_handler/AH in alarm_handlers)
diff --git a/paradise.dme b/paradise.dme
index 12deff3c44e..88cc193ae1c 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -953,6 +953,7 @@
#include "code\modules\alarm\alarm.dm"
#include "code\modules\alarm\alarm_handler.dm"
#include "code\modules\alarm\atmosphere_alarm.dm"
+#include "code\modules\alarm\burglar_alarm.dm"
#include "code\modules\alarm\camera_alarm.dm"
#include "code\modules\alarm\fire_alarm.dm"
#include "code\modules\alarm\motion_alarm.dm"