diff --git a/code/datums/wires/robot.dm b/code/datums/wires/robot.dm
index 13e53164320..f65ee6be508 100644
--- a/code/datums/wires/robot.dm
+++ b/code/datums/wires/robot.dm
@@ -40,7 +40,7 @@ var/const/BORG_WIRE_CAMERA = 16
if (BORG_WIRE_CAMERA)
if(!isnull(R.camera) && !R.scrambledcodes)
R.camera.status = mended
- R.camera.deactivate(usr, 0) // Will kick anyone who is watching the Cyborg's camera.
+ R.camera.kick_viewers() // Will kick anyone who is watching the Cyborg's camera.
if(BORG_WIRE_LAWCHECK) //Forces a law update if the borg is set to receive them. Since an update would happen when the borg checks its laws anyway, not much use, but eh
if (R.lawupdate)
@@ -83,7 +83,7 @@ var/const/BORG_WIRE_CAMERA = 16
if (BORG_WIRE_CAMERA)
if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes)
- R.camera.deactivate(usr, 0) // Kick anyone watching the Cyborg's camera, doesn't display you disconnecting the camera.
+ R.camera.kick_viewers() // Kick anyone watching the Cyborg's camera
R.visible_message("[R]'s camera lense focuses loudly.")
R << "Your camera lense focuses loudly."
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index 140659a0e51..96f87e89c1d 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -11,13 +11,15 @@
var/list/network = list("SS13")
var/c_tag = null
var/c_tag_order = 999
- var/status = 1.0
+ var/status = 1
anchored = 1.0
var/panel_open = 0 // 0 = Closed / 1 = Open
var/invuln = null
var/bugged = 0
var/obj/item/weapon/camera_assembly/assembly = null
+ var/toughness = 5 //sorta fragile
+
// WIRES
var/datum/wires/camera/wires = null // Wires datum
@@ -49,37 +51,57 @@
ASSERT(src.network.len > 0)
..()
+/obj/machinery/camera/Del()
+ if(!alarm_on)
+ triggerCameraAlarm()
+
+ spawn(50)
+ src = null
+ cancelCameraAlarm() //so camera alarms don't just go on forever
+ ..()
+
/obj/machinery/camera/emp_act(severity)
if(!isEmpProof())
if(prob(100/severity))
- icon_state = "[initial(icon_state)]emp"
- var/list/previous_network = network
- network = list()
- cameranet.removeCamera(src)
stat |= EMPED
SetLuminosity(0)
+ kick_viewers()
triggerCameraAlarm()
+ update_icon()
+
spawn(900)
- network = previous_network
- icon_state = initial(icon_state)
stat &= ~EMPED
cancelCameraAlarm()
- if(can_use())
- cameranet.addCamera(src)
- kick_viewers()
+ update_icon()
+
..()
+/obj/machinery/camera/bullet_act(var/obj/item/projectile/P)
+ if(P.damage_type == BRUTE || P.damage_type == BURN)
+ take_damage(P.damage)
/obj/machinery/camera/ex_act(severity)
if(src.invuln)
return
- else
- ..(severity)
- return
+
+ //camera dies if an explosion touches it!
+ if(severity <= 2 || prob(50))
+ destroy()
+
+ ..() //and give it the regular chance of being deleted outright
+
/obj/machinery/camera/blob_act()
return
+/obj/machinery/camera/hitby(AM as mob|obj)
+ ..()
+ if (istype(AM, /obj))
+ var/obj/O = AM
+ if (O.throwforce >= src.toughness)
+ visible_message("[src] was hit by [O].")
+ take_damage(O.throwforce)
+
/obj/machinery/camera/proc/setViewRange(var/num = 7)
src.view_range = num
cameranet.updateVisibility(src, 0)
@@ -90,14 +112,14 @@
return
if(user.species.can_shred(user))
- status = 0
+ set_status(0)
visible_message("\The [user] slashes at [src]!")
playsound(src.loc, 'sound/weapons/slash.ogg', 100, 1)
icon_state = "[initial(icon_state)]1"
add_hiddenprint(user)
- deactivate(user,0)
+ destroy()
-/obj/machinery/camera/attackby(W as obj, mob/living/user as mob)
+/obj/machinery/camera/attackby(obj/W as obj, mob/living/user as mob)
// DECONSTRUCTION
if(isscrewdriver(W))
@@ -111,16 +133,19 @@
else if((iswirecutter(W) || ismultitool(W)) && panel_open)
interact(user)
- else if(iswelder(W) && wires.CanDeconstruct())
+ else if(iswelder(W) && (wires.CanDeconstruct() || (stat & BROKEN)))
if(weld(W, user))
- if(assembly)
+ if (stat & BROKEN)
+ new /obj/item/broken_device(src.loc) //TODO make a broken electronics item instead of reusing cyborg stuff
+ new /obj/item/stack/cable_coil(src.loc, length=2)
+ else if(assembly)
assembly.loc = src.loc
assembly.state = 1
+ new /obj/item/stack/cable_coil(src.loc, length=2)
del(src)
-
// OTHER
- else if ((istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/device/pda)) && isliving(user))
+ else if (can_use() && (istype(W, /obj/item/weapon/paper) || istype(W, /obj/item/device/pda)) && isliving(user))
var/mob/living/U = user
var/obj/item/weapon/paper/X = null
var/obj/item/device/pda/P = null
@@ -147,6 +172,7 @@
if (S.current == src)
O << "[U] holds \a [itemname] up to one of the cameras ..."
O << browse(text("
[][]", itemname, info), text("window=[]", itemname))
+
else if (istype(W, /obj/item/weapon/camera_bug))
if (!src.can_use())
user << "\blue Camera non-functional"
@@ -157,22 +183,25 @@
else
user << "\blue Camera bugged."
src.bugged = 1
- else if(istype(W, /obj/item/weapon/melee/energy/blade))//Putting it here last since it's a special case. I wonder if there is a better way to do these than type casting.
- deactivate(user,2)//Here so that you can disconnect anyone viewing the camera, regardless if it's on or off.
- var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
- spark_system.set_up(5, 0, loc)
- spark_system.start()
- playsound(loc, 'sound/weapons/blade1.ogg', 50, 1)
- playsound(loc, "sparks", 50, 1)
- visible_message("\blue The camera has been sliced apart by [] with an energy blade!")
- del(src)
+
+ else if(W.damtype == BRUTE || W.damtype == BURN) //bashing cameras
+ if (W.force >= src.toughness)
+ visible_message("[src] has been [pick(W.attack_verb)] with [W] by [user]!")
+ if (istype(W, /obj/item)) //is it even possible to get into attackby() with non-items?
+ var/obj/item/I = W
+ if (I.hitsound)
+ playsound(loc, I.hitsound, 50, 1, -1)
+ take_damage(W.force)
+
else
..()
- return
/obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1)
- if(choice==1)
- status = !( src.status )
+ if(choice != 1)
+ //legacy support, if choice is != 1 then just kick viewers without changing status
+ kick_viewers()
+ else
+ set_status( !src.status )
if (!(src.status))
visible_message("\red [user] has deactivated [src]!")
playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
@@ -183,10 +212,32 @@
playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
icon_state = initial(icon_state)
add_hiddenprint(user)
- // now disconnect anyone using the camera
- //Apparently, this will disconnect anyone even if the camera was re-activated.
- //I guess that doesn't matter since they can't use it anyway?
+
+/obj/machinery/camera/proc/take_damage(var/force, var/message)
+ //prob(25) gives an average of 3-4 hits
+ if (force >= toughness && (force > toughness*4 || prob(25)))
+ destroy()
+
+//Used when someone breaks a camera
+/obj/machinery/camera/proc/destroy()
+ stat |= BROKEN
kick_viewers()
+ triggerCameraAlarm()
+ update_icon()
+
+ //sparks
+ var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread()
+ spark_system.set_up(5, 0, loc)
+ spark_system.start()
+ playsound(loc, "sparks", 50, 1)
+
+/obj/machinery/camera/proc/set_status(var/newstatus)
+ if (status != newstatus)
+ status = newstatus
+ // now disconnect anyone using the camera
+ //Apparently, this will disconnect anyone even if the camera was re-activated.
+ //I guess that doesn't matter since they couldn't use it anyway?
+ kick_viewers()
//This might be redundant, because of check_eye()
/obj/machinery/camera/proc/kick_viewers()
@@ -198,6 +249,14 @@
O.reset_view(null)
O << "The screen bursts into static."
+/obj/machinery/camera/update_icon()
+ if (!status || (stat & BROKEN))
+ icon_state = "[initial(icon_state)]1"
+ else if (stat & EMPED)
+ icon_state = "[initial(icon_state)]emp"
+ else
+ icon_state = initial(icon_state)
+
/obj/machinery/camera/proc/triggerCameraAlarm()
alarm_on = 1
for(var/mob/living/silicon/S in mob_list)
@@ -209,10 +268,11 @@
for(var/mob/living/silicon/S in mob_list)
S.cancelAlarm("Camera", get_area(src), src)
+//if false, then the camera is listed as DEACTIVATED and cannot be used
/obj/machinery/camera/proc/can_use()
if(!status)
return 0
- if(stat & EMPED)
+ if(stat & (EMPED|BROKEN))
return 0
return 1
@@ -284,6 +344,10 @@
/obj/machinery/camera/interact(mob/living/user as mob)
if(!panel_open || istype(user, /mob/living/silicon/ai))
return
+
+ if(stat & BROKEN)
+ user << "\The [src] is broken."
+ return
user.set_machine(src)
wires.Interact(user)
diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm
index 0017b260c29..48f0a94faf2 100644
--- a/code/game/machinery/camera/camera_assembly.dm
+++ b/code/game/machinery/camera/camera_assembly.dm
@@ -1,6 +1,6 @@
/obj/item/weapon/camera_assembly
name = "camera assembly"
- desc = "The basic construction for Nanotrasen-Always-Watching-You cameras."
+ desc = "A pre-fabricated security camera kit, ready to be assembled and mounted to a surface."
icon = 'icons/obj/monitors.dmi'
icon_state = "cameracase"
w_class = 2
@@ -171,4 +171,4 @@
return 0
return 1
busy = 0
- return 0
\ No newline at end of file
+ return 0
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 37966deea69..bc8719060f4 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -129,8 +129,8 @@
/obj/machinery/door/bullet_act(var/obj/item/projectile/Proj)
..()
- //Tasers and the like should not damage doors.
- if(Proj.damage_type == HALLOSS)
+ //Tasers and the like should not damage doors. Nor should TOX, OXY, CLONE, etc damage types
+ if(!(Proj.damage_type == BRUTE || Proj.damage_type == BURN))
return
if(Proj.damage)
@@ -139,7 +139,7 @@
/obj/machinery/door/hitby(AM as mob|obj)
..()
- visible_message("\red [src.name] was hit by [AM].", 1)
+ visible_message("\red [src.name] was hit by [AM].")
var/tforce = 0
if(ismob(AM))
tforce = 15