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