From 26d0de51bb610202a0ab102d9522557a2cf27d96 Mon Sep 17 00:00:00 2001 From: Markolie Date: Tue, 10 Feb 2015 02:07:02 +0100 Subject: [PATCH 1/8] Add report_alerts variable to areas --- code/game/area/Space Station 13 areas.dm | 6 ++++ code/game/area/areas.dm | 33 ++++++++++++++++++++- code/game/machinery/alarm.dm | 1 + code/game/machinery/computer/atmos_alert.dm | 2 ++ 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index e703f7ba3b2..0ee9267ca01 100644 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -22,6 +22,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station var/poweralm = 1 var/party = null var/radalert = 0 + var/report_alerts = 1 // Should atmos alerts notify the AI/computers level = null name = "Space" icon = 'icons/turf/areas.dmi' @@ -1983,6 +1984,11 @@ area/security/podbay //Traitor Station +/area/traitor + name = "\improper Syndicate Base" + icon_state = "syndie_hall" + report_alerts = 0 + /area/traitor/rnd name = "\improper Syndicate Research and Development" icon_state = "syndie_rnd" diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 3c04e9cf951..596ed5e9d97 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -52,25 +52,32 @@ InitializeLighting() -/area/proc/poweralert(var/state, var/obj/source as obj) +/area/proc/poweralert(var/state, var/obj/source as obj) if (state != poweralm) poweralm = state if(istype(source)) //Only report power alarms on the z-level where the source is located. var/list/cameras = list() for (var/area/RA in related) for (var/obj/machinery/camera/C in RA) + if(!report_alerts) + break cameras += C if(state == 1) + C.network.Remove("Power Alarms") else C.network.Add("Power Alarms") for (var/mob/living/silicon/aiPlayer in player_list) + if(!report_alerts) + break if(aiPlayer.z == source.z) if (state == 1) aiPlayer.cancelAlarm("Power", src, source) else aiPlayer.triggerAlarm("Power", src, cameras, source) for(var/obj/machinery/computer/station_alert/a in machines) + if(!report_alerts) + break if(a.z == source.z) if(state == 1) a.cancelAlarm("Power", src, source) @@ -107,11 +114,17 @@ for(var/area/RA in related) //updateicon() for(var/obj/machinery/camera/C in RA) + if(!report_alerts) + break cameras += C C.network.Add("Atmosphere Alarms") for(var/mob/living/silicon/aiPlayer in player_list) + if(!report_alerts) + break aiPlayer.triggerAlarm("Atmosphere", src, cameras, src) for(var/obj/machinery/computer/station_alert/a in machines) + if(!report_alerts) + break a.triggerAlarm("Atmosphere", src, cameras, src) air_doors_activated=1 CloseFirelocks() @@ -119,10 +132,16 @@ else if (atmosalm == 2) for(var/area/RA in related) for(var/obj/machinery/camera/C in RA) + if(!report_alerts) + break C.network.Remove("Atmosphere Alarms") for(var/mob/living/silicon/aiPlayer in player_list) + if(!report_alerts) + break aiPlayer.cancelAlarm("Atmosphere", src, src) for(var/obj/machinery/computer/station_alert/a in machines) + if(!report_alerts) + break a.cancelAlarm("Atmosphere", src, src) air_doors_activated=0 OpenFirelocks() @@ -162,11 +181,17 @@ var/list/cameras = list() for(var/area/RA in related) for (var/obj/machinery/camera/C in RA) + if(!report_alerts) + continue cameras.Add(C) C.network.Add("Fire Alarms") for (var/mob/living/silicon/ai/aiPlayer in player_list) + if(!report_alerts) + continue aiPlayer.triggerAlarm("Fire", src, cameras, src) for (var/obj/machinery/computer/station_alert/a in machines) + if(!report_alerts) + continue a.triggerAlarm("Fire", src, cameras, src) /area/proc/firereset() @@ -176,10 +201,16 @@ updateicon() for(var/area/RA in related) for (var/obj/machinery/camera/C in RA) + if(!report_alerts) + continue C.network.Remove("Fire Alarms") for (var/mob/living/silicon/ai/aiPlayer in player_list) + if(!report_alerts) + continue aiPlayer.cancelAlarm("Fire", src, src) for (var/obj/machinery/computer/station_alert/a in machines) + if(!report_alerts) + continue a.cancelAlarm("Fire", src, src) OpenFirelocks() diff --git a/code/game/machinery/alarm.dm b/code/game/machinery/alarm.dm index 1424886eae7..ea1107ad722 100644 --- a/code/game/machinery/alarm.dm +++ b/code/game/machinery/alarm.dm @@ -458,6 +458,7 @@ alert_signal.transmission_method = 1 alert_signal.data["zone"] = alarm_area.name alert_signal.data["type"] = "Atmospheric" + alert_signal.data["hidden"] = hidden if(alert_level==2) alert_signal.data["alert"] = "severe" diff --git a/code/game/machinery/computer/atmos_alert.dm b/code/game/machinery/computer/atmos_alert.dm index a24ca549dce..5e9bb34866b 100644 --- a/code/game/machinery/computer/atmos_alert.dm +++ b/code/game/machinery/computer/atmos_alert.dm @@ -23,8 +23,10 @@ var/zone = signal.data["zone"] var/severity = signal.data["alert"] + var/hidden = signal.data["hidden"] if(!zone || !severity) return + if(hidden) return minor_alarms -= zone priority_alarms -= zone From 3a4679bce724956ba47da74bbe3f505a193c365a Mon Sep 17 00:00:00 2001 From: Markolie Date: Tue, 10 Feb 2015 03:06:43 +0100 Subject: [PATCH 2/8] Remove zeroth law with own board --- code/datums/ai_laws.dm | 5 +++ code/game/objects/items/weapons/AI_modules.dm | 38 +++++++++++++------ code/modules/events/blob.dm | 5 +-- code/modules/mob/living/silicon/ai/laws.dm | 4 ++ code/modules/mob/living/silicon/robot/laws.dm | 4 ++ 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/code/datums/ai_laws.dm b/code/datums/ai_laws.dm index d81bbf67085..e1fc26d1709 100644 --- a/code/datums/ai_laws.dm +++ b/code/datums/ai_laws.dm @@ -179,6 +179,11 @@ datum/ai_laws/tyrant //This probably shouldn't be a default lawset. /datum/ai_laws/proc/clear_ion_laws() src.ion = list() + +/datum/ai_laws/proc/clear_zeroth_law(var/law_borg = null) + src.zeroth = null + if(law_borg) + src.zeroth_borg = null /datum/ai_laws/proc/show_laws(var/who) diff --git a/code/game/objects/items/weapons/AI_modules.dm b/code/game/objects/items/weapons/AI_modules.dm index c30f2e1ab1d..5f6de0b0130 100755 --- a/code/game/objects/items/weapons/AI_modules.dm +++ b/code/game/objects/items/weapons/AI_modules.dm @@ -101,13 +101,20 @@ AI MODULES for(var/templaw in laws) target.add_inherent_law(templaw) +/obj/item/weapon/aiModule/zeroth + var/removeownlaw = 0 + /obj/item/weapon/aiModule/zeroth/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) if(target.laws.zeroth) - target << "[sender.real_name] attempted to modify your zeroth law." - target << "It would be in your best interest to play along with [sender.real_name] that:" - for(var/failedlaw in laws) - target << "[failedlaw]" - return 1 + if(removeownlaw && (laws[1] == target.laws.zeroth)) + target.clear_zeroth_law() + return 2 + else + target << "[sender.real_name] attempted to modify your zeroth law." + target << "It would be in your best interest to play along with [sender.real_name] that:" + for(var/failedlaw in laws) + target << "[failedlaw]" + return 1 for(var/templaw in laws) target.set_zeroth_law(templaw) @@ -149,7 +156,7 @@ AI MODULES /obj/item/weapon/aiModule/zeroth/oneHuman name = "'OneHuman' AI Module" var/targetName = "" - desc = "A 'one human' AI module: 'Only is crew.'" + desc = "A 'one human' AI module: 'Only is crew.' This module adds a zeroth law, which can only be removed by uploading this board again." origin_tech = "programming=3;materials=6" //made with diamonds! laws = list("Only is crew.") @@ -159,6 +166,7 @@ AI MODULES targetName = targName laws[1] = "Only [targetName] is crew" desc = "A 'one crew' AI module: '[laws[1]]'" + removeownlaw = 1 /obj/item/weapon/aiModule/zeroth/oneHuman/install(var/mob/living/silicon/S,var/mob/user) if(!targetName) @@ -167,8 +175,10 @@ AI MODULES ..() /obj/item/weapon/aiModule/zeroth/oneHuman/transmitInstructions(var/mob/living/silicon/target, var/mob/sender) - if(..()) - return "[targetName], but the AI's existing law 0 cannot be overriden." + if(..() == 1) + return "[targetName], but the AI's existing zeroth law cannot be overriden." + if(..() == 2) + return "The AI's zeroth law has been overridden." return targetName @@ -186,13 +196,17 @@ AI MODULES /obj/item/weapon/aiModule/zeroth/quarantine name = "'Quarantine' AI Module" - desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, organics from leaving. It is impossible to harm an organic while preventing them from leaving.'" + desc = "A 'quarantine' AI module: 'The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, organics from leaving. It is impossible to harm an organic while preventing them from leaving.' This module adds a zeroth law, which can only be removed by uploading this board again." origin_tech = "programming=3;biotech=2;materials=4" laws = list("The station is under a quarantine. Do not permit anyone to leave. Prevent, by any means necessary, organics from leaving. It is impossible to harm an organic while preventing them from leaving.") + removeownlaw = 1 /obj/item/weapon/aiModule/zeroth/quarantine/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) - if(..()) - return "The AI's existing law 0 cannot be overriden." + var/result = ..() + if(result == 1) + return "The AI's existing zeroth law cannot be overriden." + if(result == 2) + return "The AI's zeroth law has been overridden." return laws[1] /******************** OxygenIsToxicToHumans ********************/ @@ -259,7 +273,7 @@ AI MODULES /obj/item/weapon/aiModule/reset/purge/transmitInstructions(var/mob/living/silicon/ai/target, var/mob/sender) ..() - target.clear_inherent_laws() + target.clear_inherent_laws() /******************* Full Core Boards *******************/ diff --git a/code/modules/events/blob.dm b/code/modules/events/blob.dm index 9a3dc92a754..96729f0014c 100644 --- a/code/modules/events/blob.dm +++ b/code/modules/events/blob.dm @@ -68,8 +68,7 @@ for (var/mob/living/silicon/ai/aiPlayer in player_list) if (aiPlayer.client) - var/law = "" - aiPlayer.set_zeroth_law(law) + aiPlayer.clear_zeroth_law() aiPlayer << "\red You have detected a change in your laws information:" - aiPlayer << "Laws Updated: [law]" + aiPlayer << "Laws Updated: Zeroth law removed." ..() \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/laws.dm b/code/modules/mob/living/silicon/ai/laws.dm index ab6b19e6190..9d30afc6e4d 100755 --- a/code/modules/mob/living/silicon/ai/laws.dm +++ b/code/modules/mob/living/silicon/ai/laws.dm @@ -23,6 +23,10 @@ /mob/living/silicon/ai/proc/set_zeroth_law(var/law, var/law_borg) src.laws_sanity_check() src.laws.set_zeroth_law(law, law_borg) + +/mob/living/silicon/ai/proc/clear_zeroth_law(var/law_borg) + src.laws_sanity_check() + src.laws.clear_zeroth_law(law_borg) /mob/living/silicon/ai/proc/add_inherent_law(var/law) src.laws_sanity_check() diff --git a/code/modules/mob/living/silicon/robot/laws.dm b/code/modules/mob/living/silicon/robot/laws.dm index 84377b6adb4..38267256f4b 100644 --- a/code/modules/mob/living/silicon/robot/laws.dm +++ b/code/modules/mob/living/silicon/robot/laws.dm @@ -77,6 +77,10 @@ laws_sanity_check() laws.set_zeroth_law(law) +/mob/living/silicon/robot/proc/clear_zeroth_law() + laws_sanity_check() + laws.clear_zeroth_law() + /mob/living/silicon/robot/proc/add_inherent_law(var/law) laws_sanity_check() laws.add_inherent_law(law) From c507158b8f06df3a43c7942e4c01fb475172e9c9 Mon Sep 17 00:00:00 2001 From: Markolie Date: Tue, 10 Feb 2015 15:42:47 +0100 Subject: [PATCH 3/8] Camera code update, fix runtime --- code/__HELPERS/lists.dm | 188 ++++++++++++- .../visibility_networks/visibility_network.dm | 8 +- code/game/machinery/camera/camera.dm | 250 +++++++++++------- code/game/machinery/camera/camera_assembly.dm | 16 +- code/game/machinery/camera/motion.dm | 10 +- code/game/machinery/camera/presets.dm | 25 +- code/game/machinery/camera/tracking.dm | 192 +++++++------- code/game/machinery/computer/camera.dm | 56 ++-- code/modules/computer3/computers/camera.dm | 2 +- code/modules/mob/living/silicon/ai/ai.dm | 56 +++- .../mob/living/silicon/ai/freelook/eye.dm | 8 + .../silicon/ai/freelook/update_triggers.dm | 9 +- code/modules/mob/mob_helpers.dm | 8 + code/modules/nano/JSON Writer.dm | 4 +- code/modules/nano/_JSON.dm | 4 +- code/modules/nano/nanoui.dm | 18 +- code/modules/organs/organ_internal.dm | 3 +- code/setup.dm | 10 +- nano/templates/sec_camera.tmpl | 2 +- nano/templates/sec_camera_map_content.tmpl | 2 +- 20 files changed, 629 insertions(+), 242 deletions(-) diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 10ab63c9259..8e6118f6f46 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -396,4 +396,190 @@ proc/listclearnulls(list/list) /proc/find_record(field, value, list/L) for(var/datum/data/record/R in L) if(R.fields[field] == value) - return R \ No newline at end of file + return R + + +/proc/dd_sortedObjectList(var/list/L, var/cache=list()) + if(L.len < 2) + return L + var/middle = L.len / 2 + 1 // Copy is first,second-1 + return dd_mergeObjectList(dd_sortedObjectList(L.Copy(0,middle), cache), dd_sortedObjectList(L.Copy(middle), cache), cache) //second parameter null = to end of list + +/proc/dd_mergeObjectList(var/list/L, var/list/R, var/list/cache) + var/Li=1 + var/Ri=1 + var/list/result = new() + while(Li <= L.len && Ri <= R.len) + var/LLi = L[Li] + var/RRi = R[Ri] + var/LLiV = cache[LLi] + var/RRiV = cache[RRi] + if(!LLiV) + LLiV = LLi:dd_SortValue() + cache[LLi] = LLiV + if(!RRiV) + RRiV = RRi:dd_SortValue() + cache[RRi] = RRiV + if(LLiV < RRiV) + result += L[Li++] + else + result += R[Ri++] + + if(Li <= L.len) + return (result + L.Copy(Li, 0)) + return (result + R.Copy(Ri, 0)) + +// Insert an object into a sorted list, preserving sortedness +/proc/dd_insertObjectList(var/list/L, var/O) + var/min = 1 + var/max = L.len + var/Oval = O:dd_SortValue() + + while(1) + var/mid = min+round((max-min)/2) + + if(mid == max) + L.Insert(mid, O) + return + + var/Lmid = L[mid] + var/midval = Lmid:dd_SortValue() + if(Oval == midval) + L.Insert(mid, O) + return + else if(Oval < midval) + max = mid + else + min = mid+1 + +/* +proc/dd_sortedObjectList(list/incoming) + /* + Use binary search to order by dd_SortValue(). + This works by going to the half-point of the list, seeing if the node in + question is higher or lower cost, then going halfway up or down the list + and checking again. This is a very fast way to sort an item into a list. + */ + var/list/sorted_list = new() + var/low_index + var/high_index + var/insert_index + var/midway_calc + var/current_index + var/current_item + var/current_item_value + var/current_sort_object_value + var/list/list_bottom + + var/current_sort_object + for (current_sort_object in incoming) + low_index = 1 + high_index = sorted_list.len + while (low_index <= high_index) + // Figure out the midpoint, rounding up for fractions. (BYOND rounds down, so add 1 if necessary.) + midway_calc = (low_index + high_index) / 2 + current_index = round(midway_calc) + if (midway_calc > current_index) + current_index++ + current_item = sorted_list[current_index] + + current_item_value = current_item:dd_SortValue() + current_sort_object_value = current_sort_object:dd_SortValue() + if (current_sort_object_value < current_item_value) + high_index = current_index - 1 + else if (current_sort_object_value > current_item_value) + low_index = current_index + 1 + else + // current_sort_object == current_item + low_index = current_index + break + + // Insert before low_index. + insert_index = low_index + + // Special case adding to end of list. + if (insert_index > sorted_list.len) + sorted_list += current_sort_object + continue + + // Because BYOND lists don't support insert, have to do it by: + // 1) taking out bottom of list, 2) adding item, 3) putting back bottom of list. + list_bottom = sorted_list.Copy(insert_index) + sorted_list.Cut(insert_index) + sorted_list += current_sort_object + sorted_list += list_bottom + return sorted_list +*/ + +proc/dd_sortedtextlist(list/incoming, case_sensitive = 0) + // Returns a new list with the text values sorted. + // Use binary search to order by sortValue. + // This works by going to the half-point of the list, seeing if the node in question is higher or lower cost, + // then going halfway up or down the list and checking again. + // This is a very fast way to sort an item into a list. + var/list/sorted_text = new() + var/low_index + var/high_index + var/insert_index + var/midway_calc + var/current_index + var/current_item + var/list/list_bottom + var/sort_result + + var/current_sort_text + for (current_sort_text in incoming) + low_index = 1 + high_index = sorted_text.len + while (low_index <= high_index) + // Figure out the midpoint, rounding up for fractions. (BYOND rounds down, so add 1 if necessary.) + midway_calc = (low_index + high_index) / 2 + current_index = round(midway_calc) + if (midway_calc > current_index) + current_index++ + current_item = sorted_text[current_index] + + if (case_sensitive) + sort_result = sorttextEx(current_sort_text, current_item) + else + sort_result = sorttext(current_sort_text, current_item) + + switch(sort_result) + if (1) + high_index = current_index - 1 // current_sort_text < current_item + if (-1) + low_index = current_index + 1 // current_sort_text > current_item + if (0) + low_index = current_index // current_sort_text == current_item + break + + // Insert before low_index. + insert_index = low_index + + // Special case adding to end of list. + if (insert_index > sorted_text.len) + sorted_text += current_sort_text + continue + + // Because BYOND lists don't support insert, have to do it by: + // 1) taking out bottom of list, 2) adding item, 3) putting back bottom of list. + list_bottom = sorted_text.Copy(insert_index) + sorted_text.Cut(insert_index) + sorted_text += current_sort_text + sorted_text += list_bottom + return sorted_text + + +proc/dd_sortedTextList(list/incoming) + var/case_sensitive = 1 + return dd_sortedtextlist(incoming, case_sensitive) + + +datum/proc/dd_SortValue() + return "[src]" + +/obj/machinery/dd_SortValue() + return "[sanitize(name)]" + +/obj/machinery/camera/dd_SortValue() + return "[c_tag]" \ No newline at end of file diff --git a/code/datums/visibility_networks/visibility_network.dm b/code/datums/visibility_networks/visibility_network.dm index f1bc24e771a..9c9ce550a51 100644 --- a/code/datums/visibility_networks/visibility_network.dm +++ b/code/datums/visibility_networks/visibility_network.dm @@ -1,6 +1,6 @@ /datum/visibility_network var/list/viewpoints = list() - + var/cameras_unsorted = 1 // the type of chunk used by this network var/datum/visibility_chunk/ChunkType = /datum/visibility_chunk @@ -8,6 +8,12 @@ var/list/chunks = list() var/ready = 0 + + +/datum/visibility_network/proc/process_sort() + if(cameras_unsorted) + viewpoints = dd_sortedObjectList(viewpoints) + cameras_unsorted = 0 // Creates a chunk key string from x,y,z coordinates diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index 977c1bd3d3e..9c7085c581d 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -8,17 +8,20 @@ active_power_usage = 10 layer = 5 - var/datum/wires/camera/wires = null // Wires datum 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/invuln = null + panel_open = 0 // 0 = Closed / 1 = Open + var/indestructible = 0 var/bugged = 0 var/obj/item/weapon/camera_assembly/assembly = null - var/watcherslist = list() - var/obj/item/device/camera_bug/hasbug = null + + var/toughness = 5 //sorta fragile + + // WIRES + var/datum/wires/camera/wires = null // Wires datum //OTHER @@ -28,15 +31,18 @@ var/light_disabled = 0 var/alarm_on = 0 var/busy = 0 - var/indestructible = 0 // If set, prevents aliens from destroying it + + var/obj/item/device/camera_bug/hasbug = null /obj/machinery/camera/New() wires = new(src) - assembly = new(src) assembly.state = 4 + + invalidateCameraCache() + /* // Use this to look for cameras that have the same c_tag. - for(var/obj/machinery/camera/C in cameranet.viewpoints) + for(var/obj/machinery/camera/C in cameranet.cameras) var/list/tempnetwork = C.network&src.network if(C != src && C.c_tag == src.c_tag && tempnetwork.len) world.log << "[src.c_tag] [src.x] [src.y] [src.z] conflicts with [C.c_tag] [C.x] [C.y] [C.z]" @@ -50,51 +56,48 @@ ASSERT(src.network.len > 0) ..() +/obj/machinery/camera/Del() + if(!alarm_on) + triggerCameraAlarm() + + cancelCameraAlarm() + ..() + /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) + invalidateCameraCache() 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) - for(var/mob/O in mob_list) - if(O.client && O.client.eye == src) - O.unset_machine() - O.reset_view(null) - O << "The screen bursts into static." + update_icon() + invalidateCameraCache() ..() +/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) + if(indestructible) 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() - del(src) return - -/obj/machinery/camera/proc/setViewRange(var/num = 7) - src.view_range = num - cameranet.updateVisibility(src, 0) - -/obj/machinery/camera/proc/shock(var/mob/living/user) - if(!istype(user)) - return - user.electrocute_act(10, src) - + /obj/machinery/camera/attack_paw(mob/living/carbon/alien/humanoid/user as mob) if(!istype(user)) return @@ -107,10 +110,22 @@ add_hiddenprint(user) deactivate(user,0) -/obj/machinery/camera/attackby(W as obj, mob/living/user as mob) +/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) + +/obj/machinery/camera/attackby(obj/W as obj, mob/living/user as mob) + invalidateCameraCache() // DECONSTRUCTION - if(istype(W, /obj/item/weapon/screwdriver)) + if(isscrewdriver(W)) //user << "You start to [panel_open ? "close" : "open"] the camera's panel." //if(toggle_panel(user)) // No delay because no one likes screwdrivers trying to be hip and have a duration cooldown panel_open = !panel_open @@ -118,19 +133,21 @@ "You screw the camera's panel [panel_open ? "open" : "closed"].") playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1) - else if((istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/device/multitool)) && panel_open) - wires.Interact(user) + else if((iswirecutter(W) || ismultitool(W)) && panel_open) + interact(user) - else if(istype(W, /obj/item/weapon/weldingtool) && wires.CanDeconstruct()) + else if(iswelder(W) && (wires.CanDeconstruct() || (stat & BROKEN))) if(weld(W, user)) - if(assembly) + if (stat & BROKEN) + 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 @@ -152,11 +169,12 @@ else O << "[U] holds \a [itemname] up to one of your cameras ..." O << browse(text("[][]", itemname, info), text("window=[]", itemname)) for(var/mob/O in player_list) - if(O.client && O.client.eye == src) - O.unset_machine() - O.reset_view(null) - O << "[U] holds \a [itemname] up to the camera..." - O << browse("[itemname][info]","window=[itemname]") + if (istype(O.machine, /obj/machinery/computer/security)) + var/obj/machinery/computer/security/S = O.machine + 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/device/camera_bug) && panel_open) if (!src.can_use()) user << "\blue Camera non-functional" @@ -165,32 +183,24 @@ user << "\blue Camera bugged." user.drop_item(W) hasbug = W - contents += W - if(prob(15)) - spawn(30) - if(src.can_use() && hasbug) - desc += "
The power light on the camera is blinking" - triggerCameraAlarm() + src.bugged = 1 else if (iscrowbar(W) && panel_open && src.hasbug) user << "\blue You retrieve \the [hasbug]" user.put_in_hands(hasbug) hasbug = null - deactivatebug(user) - 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(istype(W, /obj/item/device/laser_pointer)) - var/obj/item/device/laser_pointer/L = W - L.laser_act(src, user) + deactivatebug(user) + 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/deactivatebug(user as mob) for(var/mob/O in player_list) if(istype(O.machine, /obj/item/device/handtv)) @@ -201,50 +211,91 @@ O << "The screen bursts into static." /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 + invalidateCameraCache() + set_status( !src.status ) if (!(src.status)) - if(user) - visible_message("\red [user] has deactivated [src]!") - add_hiddenprint(user) - else - visible_message("\red \The [src] deactivates!") + visible_message("\red [user] has deactivated [src]!") playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1) icon_state = "[initial(icon_state)]1" add_hiddenprint(user) else - if(user) - visible_message("\red [user] has reactivated [src]!") - add_hiddenprint(user) - else - visible_message("\red \the [src] reactivates!") + visible_message("\red [user] has reactivated [src]!") 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() + invalidateCameraCache() + 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 + invalidateCameraCache() + // 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() for(var/mob/O in player_list) - if(O.client && O.client.eye == src) - O.unset_machine() - O.reset_view(null) - O << "The screen bursts into static." + if (istype(O.machine, /obj/machinery/computer/security)) + var/obj/machinery/computer/security/S = O.machine + if (S.current == src) + O.unset_machine() + 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 + if(!get_area(src)) + return + for(var/mob/living/silicon/S in mob_list) S.triggerAlarm("Camera", get_area(src), list(src), src) /obj/machinery/camera/proc/cancelCameraAlarm() alarm_on = 0 + if(!get_area(src)) + return + for(var/mob/living/silicon/S in mob_list) - S.cancelAlarm("Camera", get_area(src), list(src), src) + 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 @@ -266,13 +317,13 @@ //If someone knows a better way to do this, let me know. -Giacom switch(i) if(NORTH) - src.dir = SOUTH + dir = SOUTH if(SOUTH) - src.dir = NORTH + dir = NORTH if(WEST) - src.dir = EAST + dir = EAST if(EAST) - src.dir = WEST + dir = WEST break //Return a working camera that can see a given mob @@ -312,3 +363,14 @@ return 1 busy = 0 return 0 + +/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 9f6eb2210af..8e3238ba675 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -1,16 +1,15 @@ /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 anchored = 0 - m_amt = 700 g_amt = 300 // Motion, EMP-Proof, X-Ray - var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/plasma, /obj/item/weapon/reagent_containers/food/snacks/grown/carrot) + var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/osmium, /obj/item/weapon/stock_parts/scanning_module) var/list/upgrades = list() var/state = 0 var/busy = 0 @@ -59,8 +58,10 @@ if(iscoil(W)) var/obj/item/stack/cable_coil/C = W if(C.use(2)) - user << "You add wires to the assembly." + user << "You add wires to the assembly." state = 3 + else + user << "You need 2 coils of wire to wire the assembly." return else if(iswelder(W)) @@ -87,7 +88,8 @@ usr << "No network found please hang up and try your call again." return - var/temptag = "[get_area(src)] ([rand(1, 999)])" + var/area/camera_area = get_area(src) + var/temptag = "[sanitize(camera_area.name)] ([rand(1, 999)])" input = strip_html(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag)) state = 4 @@ -124,7 +126,7 @@ // Upgrades! if(is_type_in_list(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already. - user << "You attach the [W] into the assembly inner circuits." + user << "You attach \the [W] into the assembly inner circuits." upgrades += W user.drop_item(W) W.loc = src @@ -169,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/camera/motion.dm b/code/game/machinery/camera/motion.dm index 588ab5005ce..0c6f7d95a7f 100644 --- a/code/game/machinery/camera/motion.dm +++ b/code/game/machinery/camera/motion.dm @@ -8,6 +8,8 @@ /obj/machinery/camera/process() // motion camera event loop + if (stat & (EMPED|NOPOWER)) + return if(!isMotion()) . = PROCESS_KILL return @@ -40,16 +42,20 @@ cancelAlarm() /obj/machinery/camera/proc/cancelAlarm() + if (!status || (stat & NOPOWER)) + return 0 if (detectTime == -1) for (var/mob/living/silicon/aiPlayer in player_list) - if (status) aiPlayer.cancelAlarm("Motion", src.loc.loc) + aiPlayer.cancelAlarm("Motion", get_area(src), src) detectTime = 0 return 1 /obj/machinery/camera/proc/triggerAlarm() + if (!status || (stat & NOPOWER)) + return 0 if (!detectTime) return 0 for (var/mob/living/silicon/aiPlayer in player_list) - if (status) aiPlayer.triggerAlarm("Motion", src.loc.loc, src) + aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src) detectTime = -1 return 1 diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm index 0ee0e622b8b..21a9dc10616 100644 --- a/code/game/machinery/camera/presets.dm +++ b/code/game/machinery/camera/presets.dm @@ -53,12 +53,14 @@ // CHECKS /obj/machinery/camera/proc/isEmpProof() - var/O = locate(/obj/item/stack/sheet/mineral/plasma) in assembly.upgrades + var/O = locate(/obj/item/stack/sheet/mineral/osmium) in assembly.upgrades return O /obj/machinery/camera/proc/isXRay() - var/O = locate(/obj/item/weapon/reagent_containers/food/snacks/grown/carrot) in assembly.upgrades - return O + var/obj/item/weapon/stock_parts/scanning_module/O = locate(/obj/item/weapon/stock_parts/scanning_module) in assembly.upgrades + if (O && O.rating >= 2) + return O + return null /obj/machinery/camera/proc/isMotion() var/O = locate(/obj/item/device/assembly/prox_sensor) in assembly.upgrades @@ -67,11 +69,22 @@ // UPGRADE PROCS /obj/machinery/camera/proc/upgradeEmpProof() - assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/plasma(assembly)) + assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/osmium(assembly)) + setPowerUsage() /obj/machinery/camera/proc/upgradeXRay() - assembly.upgrades.Add(new /obj/item/weapon/reagent_containers/food/snacks/grown/carrot(assembly)) + assembly.upgrades.Add(new /obj/item/weapon/stock_parts/scanning_module/adv(assembly)) + setPowerUsage() // If you are upgrading Motion, and it isn't in the camera's New(), add it to the machines list. /obj/machinery/camera/proc/upgradeMotion() - assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly)) \ No newline at end of file + assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly)) + setPowerUsage() + +/obj/machinery/camera/proc/setPowerUsage() + var/mult = 1 + if (isXRay()) + mult++ + if (isMotion()) + mult++ + active_power_usage = mult*initial(active_power_usage) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index 47b2edf9fac..aafb582e902 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -1,16 +1,25 @@ +/mob/living/silicon/ai/var/max_locations = 10 +/mob/living/silicon/ai/var/stored_locations[0] + +/mob/living/silicon/ai/proc/InvalidTurf(turf/T as turf) + if(!T) + return 1 + if(T.z == 2) + return 1 + if(T.z > 6) + return 1 + return 0 + /mob/living/silicon/ai/proc/get_camera_list() + if(src.stat == 2) return - var/list/L = list() - for (var/obj/machinery/camera/C in cameranet.viewpoints) - L.Add(C) - - camera_sort(L) + cameranet.process_sort() var/list/T = list() T["Cancel"] = "Cancel" - for (var/obj/machinery/camera/C in L) + for (var/obj/machinery/camera/C in cameranet.viewpoints) var/list/tempnetwork = C.network&src.network if (tempnetwork.len) T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C @@ -19,20 +28,76 @@ track.cameras = T return T + /mob/living/silicon/ai/proc/ai_camera_list(var/camera in get_camera_list()) + set category = "AI Commands" + set name = "Show Camera List" + if(src.stat == 2) src << "You can't list the cameras because you are dead!" return if (!camera || camera == "Cancel") return 0 - + var/obj/machinery/camera/C = track.cameras[camera] - track = null src.eyeobj.setLoc(C) return +/mob/living/silicon/ai/proc/ai_store_location(loc as text) + set category = "AI Commands" + set name = "Store Camera Location" + set desc = "Stores your current camera location by the given name" + + loc = sanitize(copytext(loc, 1, MAX_MESSAGE_LEN)) + if(!loc) + src << "\red Must supply a location name" + return + + if(stored_locations.len >= max_locations) + src << "\red Cannot store additional locations. Remove one first" + return + + if(loc in stored_locations) + src << "\red There is already a stored location by this name" + return + + var/L = src.eyeobj.getLoc() + if (InvalidTurf(get_turf(L))) + src << "\red Unable to store this location" + return + + stored_locations[loc] = L + src << "Location '[loc]' stored" + +/mob/living/silicon/ai/proc/sorted_stored_locations() + return sortList(stored_locations) + +/mob/living/silicon/ai/proc/ai_goto_location(loc in sorted_stored_locations()) + set category = "AI Commands" + set name = "Goto Camera Location" + set desc = "Returns to the selected camera location" + + if (!(loc in stored_locations)) + src << "\red Location [loc] not found" + return + + var/L = stored_locations[loc] + src.eyeobj.setLoc(L) + +/mob/living/silicon/ai/proc/ai_remove_location(loc in sorted_stored_locations()) + set category = "AI Commands" + set name = "Delete Camera Location" + set desc = "Deletes the selected camera location" + + if (!(loc in stored_locations)) + src << "\red Location [loc] not found" + return + + stored_locations.Remove(loc) + src << "Location [loc] removed" + // Used to allow the AI is write in mob names/camera name from the CMD line. /datum/trackable var/list/names = list() @@ -50,12 +115,7 @@ for(var/mob/living/M in mob_list) // Easy checks first. // Don't detect mobs on Centcom. Since the wizard den is on Centcomm, we only need this. - var/turf/T = get_turf(M) - if(!T) - continue - if(T.z == 2) - continue - if(T.z > 6) + if(InvalidTurf(get_turf(M))) continue if(M == usr) continue @@ -72,10 +132,6 @@ //Cameras can't track people wearing an agent card or a ninja hood. if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) continue - if(istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja)) - var/obj/item/clothing/head/helmet/space/space_ninja/hood = H.head - if(!hood.canremove) - continue // Now, are they viewable by a camera? (This is last because it's the most intensive check) if(!near_camera(M)) @@ -98,6 +154,10 @@ return targets /mob/living/silicon/ai/proc/ai_camera_track(var/target_name in trackable_mobs()) + set category = "AI Commands" + set name = "Track With Camera" + set desc = "Select who you would like to track." + if(src.stat == 2) src << "You can't track with camera because you are dead!" return @@ -108,61 +168,18 @@ src.track = null ai_actual_track(target) -/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target as mob) - if(!istype(target)) return - spawn(0) - if(istype(target, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = target - if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) - src << "Unable to locate an airlock" - return - if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) - src << "Unable to locate an airlock" - return - if(istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja) && !H.head.canremove) - src << "Unable to locate an airlock" - return - if(H.digitalcamo) - src << "Unable to locate an airlock" - return - if (!near_camera(target)) - src << "Target is not near any active cameras." - return - var/obj/machinery/door/airlock/tobeopened - var/dist = -1 - for(var/obj/machinery/door/airlock/D in range(3,target)) - if(!D.density) continue - if(dist < 0) - dist = get_dist(D, target) - //world << dist - tobeopened = D - else - if(dist > get_dist(D, target)) - dist = get_dist(D, target) - //world << dist - tobeopened = D - //world << "found [tobeopened.name] closer" - else - //world << "[D.name] not close enough | [get_dist(D, target)] | [dist]" - if(tobeopened) - switch(alert(src, "Do you want to open \the [tobeopened] for [target]?","Doorknob_v2a.exe","Yes","No")) - if("Yes") - var/nhref = "src=\ref[tobeopened];aiEnable=7" - tobeopened.Topic(nhref, params2list(nhref), tobeopened, 1) - src << "\blue You've opened \the [tobeopened] for [target]." - if("No") - src << "\red You deny the request." - else - src << "\red You've failed to open an airlock for [target]" +/mob/living/silicon/ai/proc/ai_cancel_tracking(var/forced = 0) + if(!cameraFollow) return -/mob/living/silicon/ai/proc/ai_actual_track(atom/target as mob|obj) + + src << "Follow camera mode [forced ? "terminated" : "ended"]." + cameraFollow = null + +/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target as mob) if(!istype(target)) return var/mob/living/silicon/ai/U = usr U.cameraFollow = target - //U << text("Now tracking [] on camera.", target.name) - //if (U.machine == null) - // U.machine = U U << "Now tracking [target.name] on camera." spawn (0) @@ -172,30 +189,23 @@ if (istype(target, /mob/living/carbon/human)) var/mob/living/carbon/human/H = target if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) - U << "Follow camera mode terminated." - U.cameraFollow = null + U.ai_cancel_tracking(1) return -/* if(istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja) && !H.head.canremove) - U << "Follow camera mode terminated." - U.cameraFollow = null - return*/ if(H.digitalcamo) - U << "Follow camera mode terminated." - U.cameraFollow = null + U.ai_cancel_tracking(1) return if(istype(target.loc,/obj/effect/dummy)) - U << "Follow camera mode ended." - U.cameraFollow = null + U.ai_cancel_tracking() return - if (!near_camera(target)) + if (!trackable(target)) U << "Target is not near any active cameras." sleep(100) continue if(U.eyeobj) - U.eyeobj.setLoc(get_turf(target)) + U.eyeobj.setLoc(get_turf(target), 0) else view_core() return @@ -212,6 +222,12 @@ return 0 return 1 +/proc/trackable(var/mob/living/M) + var/turf/T = get_turf(M) + if(T && (T.z == 1) && hassensorlevel(M, SUIT_SENSOR_TRACKING)) + return 1 + + return near_camera(M) /obj/machinery/camera/attack_ai(var/mob/living/silicon/ai/user as mob) if (!istype(user)) @@ -223,19 +239,3 @@ /mob/living/silicon/ai/attack_ai(var/mob/user as mob) ai_camera_list() - -/proc/camera_sort(list/L) - var/obj/machinery/camera/a - var/obj/machinery/camera/b - - for (var/i = L.len, i > 0, i--) - for (var/j = 1 to i - 1) - a = L[j] - b = L[j + 1] - if (a.c_tag_order != b.c_tag_order) - if (a.c_tag_order > b.c_tag_order) - L.Swap(j, j + 1) - else - if (sorttext(a.c_tag, b.c_tag) < 0) - L.Swap(j, j + 1) - return L diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 7bc376580b8..59cd90cb17b 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -1,3 +1,7 @@ +/proc/invalidateCameraCache() + for(var/obj/machinery/computer/security/s in world) + s.camera_cache = null + /obj/machinery/computer/security name = "Camera Monitor" desc = "Used to access the various cameras networks on the station." @@ -12,6 +16,7 @@ var/list/tempnets[0] var/list/data[0] var/list/access[0] + var/camera_cache = null New() // Lists existing networks and their required access. Format: networks[] = list() networks["SS13"] = list(access_hos,access_captain) @@ -78,29 +83,38 @@ data["current"] = null - var/list/L = list() - for (var/obj/machinery/camera/C in cameranet.viewpoints) - if(can_access_camera(C)) - L.Add(C) + if(isnull(camera_cache)) + cameranet.process_sort() - camera_sort(L) + var/cameras[0] + for(var/obj/machinery/camera/C in cameranet.viewpoints) + var/cam[0] + cam["name"] = C.c_tag + cam["deact"] = !C.can_use() + cam["camera"] = "\ref[C]" + cam["x"] = C.x + cam["y"] = C.y + cam["z"] = C.z - var/cameras[0] - for(var/obj/machinery/camera/C in L) - var/cam[0] - cam["name"] = C.c_tag - cam["deact"] = !C.can_use() - cam["camera"] = "\ref[C]" - cam["x"] = C.x - cam["y"] = C.y - cam["z"] = C.z + cameras[++cameras.len] = cam - cameras[++cameras.len] = cam + if(C == current) + data["current"] = cam + + var/list/camera_list = list("cameras" = cameras) + camera_cache=list2json(camera_list) + + else + if(current) + var/cam[0] + cam["name"] = current.c_tag + cam["deact"] = !current.can_use() + cam["camera"] = "\ref[current]" + cam["x"] = current.x + cam["y"] = current.y + cam["z"] = current.z - if(C == current) data["current"] = cam - - data["cameras"] = cameras tempnets.Cut() if(emagged) @@ -119,6 +133,9 @@ tempnets.Add(list(list("name" = l, "active" = 0))) break data["networks"] = tempnets + + if(ui) + ui.load_cached_data(camera_cache) ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) @@ -128,7 +145,8 @@ ui.add_template("mapContent", "sec_camera_map_content.tmpl") // adding a template with the key "mapHeader" replaces the map header content ui.add_template("mapHeader", "sec_camera_map_header.tmpl") - + + ui.load_cached_data(camera_cache) ui.set_initial_data(data) ui.open() ui.set_auto_update(1) diff --git a/code/modules/computer3/computers/camera.dm b/code/modules/computer3/computers/camera.dm index e0d485e1da1..ed387513a5f 100644 --- a/code/modules/computer3/computers/camera.dm +++ b/code/modules/computer3/computers/camera.dm @@ -190,7 +190,7 @@ if(temp.len) L.Add(C) - camera_sort(L) + cameranet.process_sort() return L verify_machine(var/obj/machinery/camera/C,var/datum/file/camnet_key/key = null) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 1fabedb239c..a6583841231 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -112,7 +112,7 @@ var/list/ai_list = list() if (istype(loc, /turf)) verbs.Add(/mob/living/silicon/ai/proc/ai_network_change, \ /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ - /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message) + /mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_store_location, /mob/living/silicon/ai/proc/ai_goto_location, /mob/living/silicon/ai/proc/ai_remove_location) if(!safety)//Only used by AIize() to successfully spawn an AI. if (!B)//If there is no player/brain inside. @@ -127,7 +127,7 @@ var/list/ai_list = list() verbs.Remove(,/mob/living/silicon/ai/proc/ai_call_shuttle,/mob/living/silicon/ai/proc/ai_camera_track, \ /mob/living/silicon/ai/proc/ai_camera_list, /mob/living/silicon/ai/proc/ai_network_change, \ /mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \ - /mob/living/silicon/ai/proc/toggle_camera_light,/mob/living/silicon/ai/verb/pick_icon,/mob/living/silicon/ai/proc/control_hud) + /mob/living/silicon/ai/proc/toggle_camera_light,/mob/living/silicon/ai/verb/pick_icon,/mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message) laws = new /datum/ai_laws/alienmov else B.brainmob.mind.transfer_to(src) @@ -631,8 +631,6 @@ var/list/ai_list = list() /mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C) - src.cameraFollow = null - if (!C || stat == 2) //C.can_use()) return 0 @@ -706,7 +704,6 @@ var/list/ai_list = list() set category = "AI Commands" set name = "Jump To Network" unset_machine() - src.cameraFollow = null var/cameralist[0] if(usr.stat == 2) @@ -912,3 +909,52 @@ var/list/ai_list = list() src << "Accessing Subspace Transceiver control..." if (src.aiRadio) src.aiRadio.interact(src) + + +/mob/living/silicon/ai/proc/open_nearest_door(mob/living/target as mob) + if(!istype(target)) return + spawn(0) + if(istype(target, /mob/living/carbon/human)) + var/mob/living/carbon/human/H = target + if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) + src << "Unable to locate an airlock" + return + if(H.wear_id && istype(H.wear_id.GetID(), /obj/item/weapon/card/id/syndicate)) + src << "Unable to locate an airlock" + return + if(istype(H.head, /obj/item/clothing/head/helmet/space/space_ninja) && !H.head.canremove) + src << "Unable to locate an airlock" + return + if(H.digitalcamo) + src << "Unable to locate an airlock" + return + if (!near_camera(target)) + src << "Target is not near any active cameras." + return + var/obj/machinery/door/airlock/tobeopened + var/dist = -1 + for(var/obj/machinery/door/airlock/D in range(3,target)) + if(!D.density) continue + if(dist < 0) + dist = get_dist(D, target) + //world << dist + tobeopened = D + else + if(dist > get_dist(D, target)) + dist = get_dist(D, target) + //world << dist + tobeopened = D + //world << "found [tobeopened.name] closer" + else + //world << "[D.name] not close enough | [get_dist(D, target)] | [dist]" + if(tobeopened) + switch(alert(src, "Do you want to open \the [tobeopened] for [target]?","Doorknob_v2a.exe","Yes","No")) + if("Yes") + var/nhref = "src=\ref[tobeopened];aiEnable=7" + tobeopened.Topic(nhref, params2list(nhref), tobeopened, 1) + src << "\blue You've opened \the [tobeopened] for [target]." + if("No") + src << "\red You deny the request." + else + src << "\red You've failed to open an airlock for [target]" + return \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index c2c23b02188..afe319fc501 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -54,6 +54,14 @@ //Holopad if(ai.holo) ai.holo.move_hologram() + + +/mob/aiEye/proc/getLoc() + + if(ai) + if(!isturf(ai.loc) || !ai.client) + return + return ai.eyeobj.loc /mob/aiEye/Move() diff --git a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm index 775d8864751..d6799548bff 100644 --- a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm +++ b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm @@ -12,12 +12,19 @@ /obj/machinery/camera/New() ..() - cameranet.viewpoints += src //Camera must be added to global list of all cameras no matter what... + //Camera must be added to global list of all cameras no matter what... + if(cameranet.cameras_unsorted || !ticker) + cameranet.viewpoints += src + cameranet.cameras_unsorted = 1 + else + dd_insertObjectList(cameranet.viewpoints, src) + var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS) //...but if all of camera's networks are restricted, it only works for specific camera consoles. if(open_networks.len) //If there is at least one open network, chunk is available for AI usage. cameranet.addViewpoint(src) /obj/machinery/camera/Del() + cameranet.viewpoints -= src var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS) if(open_networks.len) diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm index 0432e4baef6..b652a106824 100644 --- a/code/modules/mob/mob_helpers.dm +++ b/code/modules/mob/mob_helpers.dm @@ -161,6 +161,14 @@ proc/hasorgans(A) /proc/hsl2rgb(h, s, l) return + +proc/hassensorlevel(A, var/level) + var/mob/living/carbon/human/H = A + if(istype(H) && istype(H.w_uniform, /obj/item/clothing/under)) + var/obj/item/clothing/under/U = H.w_uniform + return U.sensor_mode >= level + return 0 + /proc/check_zone(zone) diff --git a/code/modules/nano/JSON Writer.dm b/code/modules/nano/JSON Writer.dm index 3cd3520f177..f4c74d35ebb 100644 --- a/code/modules/nano/JSON Writer.dm +++ b/code/modules/nano/JSON Writer.dm @@ -1,7 +1,7 @@ json_writer proc - WriteObject(list/L) + WriteObject(list/L, cached_data = null) . = "{" var/i = 1 for(var/k in L) @@ -9,6 +9,8 @@ json_writer . += {"\"[k]\":[write(val)]"} if(i++ < L.len) . += "," + if(cached_data) + . = copytext(., 1, lentext(.)) + ",\"cached\":[cached_data]}" .+= "}" write(val) diff --git a/code/modules/nano/_JSON.dm b/code/modules/nano/_JSON.dm index 5692e643baa..4f70e6e664a 100644 --- a/code/modules/nano/_JSON.dm +++ b/code/modules/nano/_JSON.dm @@ -7,6 +7,6 @@ proc var/static/json_reader/_jsonr = new() return _jsonr.ReadObject(_jsonr.ScanJson(json)) - list2json(list/L) + list2json(list/L, var/cached_data = null) var/static/json_writer/_jsonw = new() - return _jsonw.WriteObject(L) + return _jsonw.WriteObject(L, cached_data) diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm index 54ff6b70b01..01792ad0c3d 100644 --- a/code/modules/nano/nanoui.dm +++ b/code/modules/nano/nanoui.dm @@ -58,6 +58,9 @@ nanoui is used to open and update nano browser uis var/is_auto_updating = 0 // the current status/visibility of the ui var/status = STATUS_INTERACTIVE + + var/cached_data = null + // Only allow users with a certain user.stat to get updates. Defaults to 0 (concious) var/allowed_user_stat = 0 // -1 = ignore, 0 = alive, 1 = unconcious or alive, 2 = dead concious or alive @@ -370,7 +373,7 @@ nanoui is used to open and update nano browser uis template_data_json = list2json(templates) var/list/send_data = get_send_data(initial_data) - var/initial_data_json = list2json(send_data) + var/initial_data_json = list2json(send_data, cached_data) var/url_parameters_json = list2json(list("src" = "\ref[src]")) @@ -450,6 +453,17 @@ nanoui is used to open and update nano browser uis var/params = "\ref[src]" winset(user, window_id, "on-close=\"nanoclose [params]\"") + +/** + * Appends already processed json txt to the list2json proc when setting initial-data and data pushes + * Used for data that is fucking huge like manifests and camera lists that doesn't change often. + * And we only want to process them when they change. + * + * @return nothing + */ +/datum/nanoui/proc/load_cached_data(var/data) + cached_data = data + return /** * Push data to an already open UI window @@ -464,7 +478,7 @@ nanoui is used to open and update nano browser uis var/list/send_data = get_send_data(data) //user << list2json(data) // used for debugging - user << output(list2params(list(list2json(send_data))),"[window_id].browser:receiveUpdateData") + user << output(list2params(list(list2json(send_data,cached_data))),"[window_id].browser:receiveUpdateData") /** * This Topic() proc is called whenever a user clicks on a link within a Nano UI diff --git a/code/modules/organs/organ_internal.dm b/code/modules/organs/organ_internal.dm index 54aac02d952..e0872804ce3 100644 --- a/code/modules/organs/organ_internal.dm +++ b/code/modules/organs/organ_internal.dm @@ -96,6 +96,7 @@ P.internal_organs = list() P.internal_organs += src H.internal_organs_by_name[name] = src + H.internal_organs |= src owner = H return @@ -196,7 +197,7 @@ src.damage += 0.2 * process_accuracy //Damaged one shares the fun else - var/datum/organ/internal/O = pick(owner.internal_organs_by_name) + var/datum/organ/internal/O = pick(owner.internal_organs) if(O) O.damage += 0.2 * process_accuracy diff --git a/code/setup.dm b/code/setup.dm index 157b5a47d04..925f72c9536 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -806,6 +806,8 @@ var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accesse "ERT", "NukeOps", "Thunderdome", + "UO45", + "UO45R", "Xeno" ) @@ -943,4 +945,10 @@ var/list/hit_appends = list("-OOF", "-ACK", "-UGH", "-HRNK", "-HURGH", "-GLORF") #define AUTOLATHE 4 //Uses glass/metal only. #define CRAFTLATHE 8 //Uses fuck if I know. For use eventually. #define MECHFAB 16 //Remember, objects utilising this flag should have construction_time and construction_cost vars. -//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable. \ No newline at end of file +//Note: More then one of these can be added to a design but imprinter and lathe designs are incompatable. + +// Suit sensor levels +#define SUIT_SENSOR_OFF 0 +#define SUIT_SENSOR_BINARY 1 +#define SUIT_SENSOR_VITAL 2 +#define SUIT_SENSOR_TRACKING 3 \ No newline at end of file diff --git a/nano/templates/sec_camera.tmpl b/nano/templates/sec_camera.tmpl index b9764555cd6..5aad1e29298 100644 --- a/nano/templates/sec_camera.tmpl +++ b/nano/templates/sec_camera.tmpl @@ -12,7 +12,7 @@ Used In File(s): \code\game\machinery\computer\camera.dm
None
{{/if}} -{{for data.cameras}} +{{for data.cached.cameras}} {{if data.current && value.name == data.current.name}} {{:helper.link(value.name, '', {'switchTo' : value.camera}, 'selected')}} {{else value.deact}} diff --git a/nano/templates/sec_camera_map_content.tmpl b/nano/templates/sec_camera_map_content.tmpl index 52dc8aeadd6..d0abff84285 100644 --- a/nano/templates/sec_camera_map_content.tmpl +++ b/nano/templates/sec_camera_map_content.tmpl @@ -2,7 +2,7 @@ Title: Security Camera Console (Map content) Used In File(s): \code\game\machinery\computer\camera.dm --> -{{for data.cameras}} +{{for data.cached.cameras}} {{if value.z == 1}}
{{if data.current && value.name == data.current.name}} From 64fe9e86007dd61ffcffd88127d02819a5ee3b20 Mon Sep 17 00:00:00 2001 From: Markolie Date: Tue, 10 Feb 2015 17:02:27 +0100 Subject: [PATCH 4/8] Remove legacy viewpoint code, move back to Bay's and /tg/'s system --- code/ZAS/Atom.dm | 10 + code/datums/visibility_networks/chunk.dm | 179 ------------------ code/datums/visibility_networks/dictionary.dm | 11 -- .../visibility_networks/update_triggers.dm | 94 --------- .../visibility_interface.dm | 46 ----- .../visibility_networks/visibility_network.dm | 150 --------------- code/defines/obj/weapon.dm | 2 +- code/game/gamemodes/cult/ritual.dm | 6 +- .../gamemodes/malfunction/Malf_Modules.dm | 4 +- code/game/machinery/camera/camera_assembly.dm | 2 +- code/game/machinery/camera/tracking.dm | 2 +- code/game/machinery/computer/camera.dm | 4 +- code/game/machinery/shieldgen.dm | 9 - code/game/objects/effects/effect_system.dm | 9 - code/game/objects/items/devices/handtv.dm | 2 +- code/game/objects/structures/inflatable.dm | 8 - code/game/objects/structures/mineral_doors.dm | 7 - .../objects/structures/windoor_assembly.dm | 7 - code/game/objects/structures/window.dm | 8 - code/modules/admin/verbs/mapping.dm | 4 +- code/modules/computer3/computers/camera.dm | 2 +- code/modules/mob/living/silicon/ai/ai.dm | 8 +- .../living/silicon/ai/freelook/cameranet.dm | 169 +++++++++++++++-- .../mob/living/silicon/ai/freelook/chunk.dm | 177 +++++++++++++++-- .../mob/living/silicon/ai/freelook/eye.dm | 67 +++---- .../mob/living/silicon/ai/freelook/read_me.dm | 4 +- .../silicon/ai/freelook/update_triggers.dm | 96 +++++++++- .../ai/freelook/visibility_interface.dm | 10 - code/modules/mob/spirit/cultnet.dm | 48 ----- code/modules/mob/spirit/movement.dm | 1 - code/modules/mob/spirit/spirit.dm | 3 - code/modules/mob/spirit/viewpoint.dm | 8 +- code/setup.dm | 2 +- paradise.dme | 6 - 34 files changed, 454 insertions(+), 711 deletions(-) delete mode 100644 code/datums/visibility_networks/chunk.dm delete mode 100644 code/datums/visibility_networks/dictionary.dm delete mode 100644 code/datums/visibility_networks/update_triggers.dm delete mode 100644 code/datums/visibility_networks/visibility_interface.dm delete mode 100644 code/datums/visibility_networks/visibility_network.dm delete mode 100644 code/modules/mob/living/silicon/ai/freelook/visibility_interface.dm diff --git a/code/ZAS/Atom.dm b/code/ZAS/Atom.dm index b4d1de20af4..8d479ecfb14 100644 --- a/code/ZAS/Atom.dm +++ b/code/ZAS/Atom.dm @@ -29,6 +29,16 @@ atom/proc/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0) return 0 return 1 + +//Convenience function for atoms to update turfs they occupy +/atom/movable/proc/update_nearby_tiles(need_rebuild) + if(!air_master) + return 0 + + for(var/turf/simulated/turf in locs) + air_master.mark_for_update(turf) + + return 1 //Basically another way of calling CanPass(null, other, 0, 0) and CanPass(null, other, 1.5, 1). //Returns: diff --git a/code/datums/visibility_networks/chunk.dm b/code/datums/visibility_networks/chunk.dm deleted file mode 100644 index 4abc1340b0f..00000000000 --- a/code/datums/visibility_networks/chunk.dm +++ /dev/null @@ -1,179 +0,0 @@ -#define UPDATE_BUFFER 25 // 2.5 seconds - -// CAMERA CHUNK -// -// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed. -// Allows the mob using this chunk to stream these chunks and know what it can and cannot see. - -/datum/visibility_chunk - var/obscured_image = 'icons/effects/cameravis.dmi' - var/obscured_sub = "black" - var/list/obscuredTurfs = list() - var/list/visibleTurfs = list() - var/list/obscured = list() - var/list/viewpoints = list() - var/list/turfs = list() - var/list/seenby = list() - var/visible = 0 - var/changed = 0 - var/updating = 0 - var/x = 0 - var/y = 0 - var/z = 0 - -/datum/visibility_chunk/proc/add(mob/new_mob) - - // if this thing doesn't use one of these visibility systems, kick it out - if (!new_mob.visibility_interface) - return - - // if the mob being added isn't a valid form of that mob, kick it out - if (!new_mob.visibility_interface:canBeAddedToChunk(src)) - return - - // add this chunk to the list of visible chunks - new_mob.visibility_interface:addChunk(src) - - visible++ - seenby += new_mob - if(changed && !updating) - update() - -/datum/visibility_chunk/proc/remove(mob/new_mob) - // if this thing doesn't use one of these visibility systems, kick it out - if (!new_mob.visibility_interface) - return - - // if the mob being added isn't a valid form of that mob, kick it out - if (!new_mob.visibility_interface:canBeAddedToChunk(src)) - return - - // remove the chunk - new_mob.visibility_interface:removeChunk(src) - - // remove the mob from out lists - seenby -= new_mob - if(visible > 0) - visible-- - -/datum/visibility_chunk/proc/visibilityChanged(turf/loc) - if(!visibleTurfs[loc]) - return - hasChanged() - -/datum/visibility_chunk/proc/hasChanged(var/update_now = 0) - if(visible || update_now) - if(!updating) - updating = 1 - spawn(UPDATE_BUFFER) // Batch large changes, such as many doors opening or closing at once - update() - updating = 0 - else - changed = 1 - - -/* -This function needs to be overwritten to return True if the viewpoint object is valid, and false if it is not. -*/ -/datum/visibility_chunk/proc/validViewpoint(var/viewpoint) - return FALSE - -/* -This function needs to be overwritten to return a list of visible turfs for that viewpoint -*/ -/datum/visibility_chunk/proc/getVisibleTurfsForViewpoint(var/viewpoint) - return list() - -// returns a list of turfs which can be seen in by the chunks viewpoints -/datum/visibility_chunk/proc/getVisibleTurfs() - var/list/newVisibleTurfs = list() - for(var/viewpoint in viewpoints) - if (validViewpoint(viewpoint)) - for (var/turf/t in getVisibleTurfsForViewpoint(viewpoint)) - newVisibleTurfs[t]=t - return newVisibleTurfs - -/* -This function needs to be overwritten to find nearby viewpoint objects to the chunk center. -*/ -/datum/visibility_chunk/proc/findNearbyViewpoints() - return FALSE - -/* -This function can be overwritten to change or randomize the obscuring images -*/ -/datum/visibility_chunk/proc/setObscuredImage(var/turf/target_turf) - if(!target_turf.obscured) - target_turf.obscured = image(obscured_image, target_turf, obscured_sub, 15) - -/datum/visibility_chunk/proc/update() - - set background = 1 - - // get a list of all the turfs that our viewpoints can see - var/list/newVisibleTurfs = getVisibleTurfs() - - // Removes turf that isn't in turfs. - newVisibleTurfs &= turfs - - var/list/visAdded = newVisibleTurfs - visibleTurfs - var/list/visRemoved = visibleTurfs - newVisibleTurfs - - visibleTurfs = newVisibleTurfs - obscuredTurfs = turfs - newVisibleTurfs - - // update the visibility overlays - for(var/turf in visAdded) - var/turf/t = turf - if(t.obscured) - obscured -= t.obscured - for(var/mob/current_mob in seenby) - if (current_mob.visibility_interface) - current_mob.visibility_interface:removeObscuredTurf(t) - - for(var/turf in visRemoved) - var/turf/t = turf - if(obscuredTurfs[t]) - setObscuredImage(t) - obscured += t.obscured - for(var/mob/current_mob in seenby) - if (current_mob.visibility_interface) - current_mob.visibility_interface:addObscuredTurf(t) - else - seenby -= current_mob - - -// Create a new chunk, since the chunks are made as they are needed. -/datum/visibility_chunk/New(loc, x, y, z) - - // 0xf = 15 - x &= ~0xf - y &= ~0xf - - src.x = x - src.y = y - src.z = z - - for(var/turf/t in range(10, locate(x + 8, y + 8, z))) - if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16) - turfs[t] = t - - // locate all nearby viewpoints - findNearbyViewpoints() - - // get the turfs that are visible to those viewpoints - visibleTurfs = getVisibleTurfs() - - // Removes turf that isn't in turfs. - visibleTurfs &= turfs - - // create the list of turfs we can't see - obscuredTurfs = turfs - visibleTurfs - - // create the list of obscuring images to add to viewing clients - for(var/turf in obscuredTurfs) - var/turf/t = turf - setObscuredImage(t) - obscured += t.obscured - -#undef UPDATE_BUFFER \ No newline at end of file diff --git a/code/datums/visibility_networks/dictionary.dm b/code/datums/visibility_networks/dictionary.dm deleted file mode 100644 index 5f57ddd7a17..00000000000 --- a/code/datums/visibility_networks/dictionary.dm +++ /dev/null @@ -1,11 +0,0 @@ -var/datum/visibility_network/cameras/cameranet = new() -var/datum/visibility_network/cult/cultNetwork = new() -var/datum/visibility_network/list/visibility_networks = list("ALL_CAMERAS"=cameranet, "CULT" = cultNetwork) - - -// used by turfs and objects to update all visibility networks -/proc/updateVisibilityNetworks(atom/A, var/opacity_check = 1) - var/datum/visibility_network/currentNetwork - for (var/networkName in visibility_networks) - currentNetwork = visibility_networks[networkName] - currentNetwork.updateVisibility(A, opacity_check) \ No newline at end of file diff --git a/code/datums/visibility_networks/update_triggers.dm b/code/datums/visibility_networks/update_triggers.dm deleted file mode 100644 index 97ed2db3a6c..00000000000 --- a/code/datums/visibility_networks/update_triggers.dm +++ /dev/null @@ -1,94 +0,0 @@ -//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update. - -// TURFS - -/turf - var/image/obscured - -/turf/proc/visibilityChanged() - if(ticker) - updateVisibilityNetworks(src) - -/turf/simulated/Del() - visibilityChanged() - ..() - -/turf/simulated/New() - ..() - visibilityChanged() - - - -// STRUCTURES - -/obj/structure/Del() - if(ticker) - updateVisibilityNetworks(src) - ..() - -/obj/structure/New() - ..() - if(ticker) - updateVisibilityNetworks(src) - -// EFFECTS - -/obj/effect/Del() - if(ticker) - updateVisibilityNetworks(src) - ..() - -/obj/effect/New() - ..() - if(ticker) - updateVisibilityNetworks(src) - - -// DOORS - -// Simply updates the visibility of the area when it opens/closes/destroyed. -/obj/machinery/door/proc/update_nearby_tiles(need_rebuild) - - if(!glass) - updateVisibilityNetworks(src,0) - - if(!air_master) - return 0 - - for(var/turf/simulated/turf in locs) - update_heat_protection(turf) - air_master.mark_for_update(turf) - - return 1 - - - -#define UPDATE_VISIBILITY_NETWORK_BUFFER 30 - -/mob - var/datum/visibility_network/list/visibilityNetworks=list() - var/updatingVisibilityNetworks=FALSE - -/mob/Move(n,direct) - var/oldLoc = src.loc - //. = ..() - if(..(n,direct)) - if(src.visibilityNetworks.len) - if(!src.updatingVisibilityNetworks) - src.updatingVisibilityNetworks = 1 - spawn(UPDATE_VISIBILITY_NETWORK_BUFFER) - if(oldLoc != src.loc) - for (var/datum/visibility_network/currentNetwork in src.visibilityNetworks) - currentNetwork.updateMob(src) - src.updatingVisibilityNetworks = 0 - return . - -/mob/proc/addToVisibilityNetwork(var/datum/visibility_network/network) - if(network) - src.visibilityNetworks+=network - -/mob/proc/removeFromVisibilityNetwork(var/datum/visibility_network/network) - if(network) - src.visibilityNetworks|=network - -#undef UPDATE_VISIBILITY_NETWORK_BUFFER \ No newline at end of file diff --git a/code/datums/visibility_networks/visibility_interface.dm b/code/datums/visibility_networks/visibility_interface.dm deleted file mode 100644 index 7d8efba41d3..00000000000 --- a/code/datums/visibility_networks/visibility_interface.dm +++ /dev/null @@ -1,46 +0,0 @@ -/datum/visibility_interface - var/chunk_type = null - var/mob/controller = null - var/list/visible_chunks = list() - - -/datum/visibility_interface/New(var/mob/controller) - src.controller = controller - - -/datum/visibility_interface/proc/validMob() - return getClient() - -/datum/visibility_interface/proc/getClient() - return controller.client - -/datum/visibility_interface/proc/canBeAddedToChunk(var/datum/visibility_chunk/test_chunk) - return istype(test_chunk,chunk_type) - - -/datum/visibility_interface/proc/addChunk(var/datum/visibility_chunk/test_chunk) - visible_chunks+=test_chunk - var/client/currentClient = getClient() - if(currentClient) - currentClient.images += test_chunk.obscured - - -/datum/visibility_interface/proc/removeChunk(var/datum/visibility_chunk/test_chunk) - visible_chunks-=test_chunk - var/client/currentClient = getClient() - if(currentClient) - currentClient.images -= test_chunk.obscured - - -/datum/visibility_interface/proc/removeObscuredTurf(var/turf/target_turf) - if(validMob()) - var/client/currentClient = getClient() - if(currentClient) - currentClient.images -= target_turf.obscured - - -/datum/visibility_interface/proc/addObscuredTurf(var/turf/target_turf) - if(validMob()) - var/client/currentClient = getClient() - if(currentClient) - currentClient.images -= target_turf.obscured \ No newline at end of file diff --git a/code/datums/visibility_networks/visibility_network.dm b/code/datums/visibility_networks/visibility_network.dm deleted file mode 100644 index 9c9ce550a51..00000000000 --- a/code/datums/visibility_networks/visibility_network.dm +++ /dev/null @@ -1,150 +0,0 @@ -/datum/visibility_network - var/list/viewpoints = list() - var/cameras_unsorted = 1 - // the type of chunk used by this network - var/datum/visibility_chunk/ChunkType = /datum/visibility_chunk - - // The chunks of the map, mapping the areas that the viewpoints can see. - var/list/chunks = list() - - var/ready = 0 - - -/datum/visibility_network/proc/process_sort() - if(cameras_unsorted) - viewpoints = dd_sortedObjectList(viewpoints) - cameras_unsorted = 0 - - -// Creates a chunk key string from x,y,z coordinates -/datum/visibility_network/proc/createChunkKey(x,y,z) - x &= ~0xf - y &= ~0xf - return "[x],[y],[z]" - - -// Checks if a chunk has been Generated in x, y, z. -/datum/visibility_network/proc/chunkGenerated(x, y, z) - return (chunks[createChunkKey(x, y, z)]) - - -// Returns the chunk in the x, y, z. -// If there is no chunk, it creates a new chunk and returns that. -/datum/visibility_network/proc/getChunk(x, y, z) - var/key = createChunkKey(x, y, z) - if(!chunks[key]) - chunks[key] = new ChunkType(null, x, y, z) - return chunks[key] - - -/datum/visibility_network/proc/visibility(var/mob/targetMob) - - // if we've got not visibility interface on the mob, we canot do this - if (!targetMob.visibility_interface) - return - - // 0xf = 15 - var/x1 = max(0, targetMob.x - 16) & ~0xf - var/y1 = max(0, targetMob.y - 16) & ~0xf - var/x2 = min(world.maxx, targetMob.x + 16) & ~0xf - var/y2 = min(world.maxy, targetMob.y + 16) & ~0xf - - var/list/visibleChunks = list() - - for(var/x = x1; x <= x2; x += 16) - for(var/y = y1; y <= y2; y += 16) - visibleChunks += getChunk(x, y, targetMob.z) - - var/list/remove = targetMob.visibility_interface:visible_chunks - visibleChunks - var/list/add = visibleChunks - targetMob.visibility_interface:visible_chunks - - for(var/datum/visibility_chunk/chunk in remove) - chunk.remove(targetMob) - - for(var/datum/visibility_chunk/chunk in add) - chunk.add(targetMob) - - -// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open. -/datum/visibility_network/proc/updateVisibility(atom/A, var/opacity_check = 1) - if(!ticker || (opacity_check && !A.opacity)) - return - majorChunkChange(A, 2) - - -/datum/visibility_network/proc/updateChunk(x, y, z) - if(!chunkGenerated(x, y, z)) - return - var/datum/visibility_chunk/chunk = getChunk(x, y, z) - chunk.hasChanged() - - -/datum/visibility_network/proc/validViewpoint(var/viewpoint) - return FALSE - - -/datum/visibility_network/proc/addViewpoint(var/viewpoint) - if(validViewpoint(viewpoint)) - majorChunkChange(viewpoint, 1) - - -/datum/visibility_network/proc/removeViewpoint(var/viewpoint) - if(validViewpoint(viewpoint)) - majorChunkChange(viewpoint, 0) - -/datum/visibility_network/proc/getViewpointFromMob(var/mob/currentMob) - return FALSE - -/datum/visibility_network/proc/updateMob(var/mob/currentMob) - var/viewpoint = getViewpointFromMob(currentMob) - if(viewpoint) - updateViewpoint(viewpoint) - - -/datum/visibility_network/proc/updateViewpoint(var/viewpoint) - if(validViewpoint(viewpoint)) - majorChunkChange(viewpoint, 1) - - -// Never access this proc directly!!!! -// This will update the chunk and all the surrounding chunks. -// It will also add the atom to the cameras list if you set the choice to 1. -// Setting the choice to 0 will remove the viewpoint from the chunks. -// If you want to update the chunks around an object, without adding/removing a viewpoint, use choice 2. -/datum/visibility_network/proc/majorChunkChange(atom/c, var/choice) - // 0xf = 15 - if(!c) - return - - var/turf/T = get_turf(c) - if(T) - var/x1 = max(0, T.x - 8) & ~0xf - var/y1 = max(0, T.y - 8) & ~0xf - var/x2 = min(world.maxx, T.x + 8) & ~0xf - var/y2 = min(world.maxy, T.y + 8) & ~0xf - - for(var/x = x1; x <= x2; x += 16) - for(var/y = y1; y <= y2; y += 16) - if(chunkGenerated(x, y, T.z)) - var/datum/visibility_chunk/chunk = getChunk(x, y, T.z) - if(choice == 0) - // Remove the viewpoint. - chunk.viewpoints -= c - else if(choice == 1) - // You can't have the same viewpoint in the list twice. - chunk.viewpoints |= c - chunk.hasChanged() - -// checks if the network can see a particular atom -/datum/visibility_network/proc/checkCanSee(var/atom/target) - var/turf/position = get_turf(target) - return checkTurfVis(position) - -/datum/visibility_network/proc/checkTurfVis(var/turf/position) - var/datum/visibility_chunk/chunk = getChunk(position.x, position.y, position.z) - if(chunk) - if(chunk.changed) - chunk.hasChanged(1) // Update now, no matter if it's visible or not. - if(chunk.visibleTurfs[position]) - return 1 - return 0 \ No newline at end of file diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index c5c01751482..a2bcbfdb59e 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -494,7 +494,7 @@ /obj/item/weapon/camera_bug/attack_self(mob/usr as mob) var/list/cameras = new/list() - for (var/obj/machinery/camera/C in cameranet.viewpoints) + for (var/obj/machinery/camera/C in cameranet.cameras) if (C.bugged && C.status) cameras.Add(C) if (length(cameras) == 0) diff --git a/code/game/gamemodes/cult/ritual.dm b/code/game/gamemodes/cult/ritual.dm index 02e20eb7a2f..0bcc4f1a603 100644 --- a/code/game/gamemodes/cult/ritual.dm +++ b/code/game/gamemodes/cult/ritual.dm @@ -72,13 +72,11 @@ var/engwords = list("travel", "blood", "join", "hell", "destroy", "technology", blood.override = 1 for(var/mob/living/silicon/ai/AI in player_list) AI.client.images += blood - cultNetwork.viewpoints+=src - cultNetwork.addViewpoint(src) + cult_viewpoints += src /obj/effect/rune/Del() ..() - cultNetwork.viewpoints-=src - cultNetwork.removeViewpoint(src) + cult_viewpoints -= src /obj/effect/rune/examine() set src in view(2) diff --git a/code/game/gamemodes/malfunction/Malf_Modules.dm b/code/game/gamemodes/malfunction/Malf_Modules.dm index 844669ff039..39c0c004a5c 100644 --- a/code/game/gamemodes/malfunction/Malf_Modules.dm +++ b/code/game/gamemodes/malfunction/Malf_Modules.dm @@ -313,7 +313,7 @@ rcd light flash thingy on matter drain power_type = /client/proc/reactivate_camera -/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.viewpoints) +/client/proc/reactivate_camera(obj/machinery/camera/C as obj in cameranet.cameras) set name = "Reactivate Camera" set category = "Malfunction" if (istype (C, /obj/machinery/camera)) @@ -337,7 +337,7 @@ rcd light flash thingy on matter drain power_type = /client/proc/upgrade_camera -/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.viewpoints) +/client/proc/upgrade_camera(obj/machinery/camera/C as obj in cameranet.cameras) set name = "Upgrade Camera" set category = "Malfunction" if(istype(C)) diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm index 8e3238ba675..7b72b5bc3f4 100644 --- a/code/game/machinery/camera/camera_assembly.dm +++ b/code/game/machinery/camera/camera_assembly.dm @@ -100,7 +100,7 @@ C.auto_turn() C.network = uniquelist(tempnetwork) - tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS) + tempnetwork = difflist(C.network,restricted_camera_networks) if(!tempnetwork.len)//Camera isn't on any open network - remove its chunk from AI visibility. cameranet.removeCamera(C) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index aafb582e902..a26fd25a6f7 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -19,7 +19,7 @@ var/list/T = list() T["Cancel"] = "Cancel" - for (var/obj/machinery/camera/C in cameranet.viewpoints) + for (var/obj/machinery/camera/C in cameranet.cameras) var/list/tempnetwork = C.network&src.network if (tempnetwork.len) T[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm index 59cd90cb17b..e23ce2e3398 100644 --- a/code/game/machinery/computer/camera.dm +++ b/code/game/machinery/computer/camera.dm @@ -87,7 +87,7 @@ cameranet.process_sort() var/cameras[0] - for(var/obj/machinery/camera/C in cameranet.viewpoints) + for(var/obj/machinery/camera/C in cameranet.cameras) var/cam[0] cam["name"] = C.c_tag cam["deact"] = !C.can_use() @@ -155,7 +155,7 @@ if(href_list["switchTo"]) if(src.z>6 || stat&(NOPOWER|BROKEN)) return if(usr.stat || ((get_dist(usr, src) > 1 || !( usr.canmove ) || usr.blinded) && !istype(usr, /mob/living/silicon))) return - var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.viewpoints + var/obj/machinery/camera/C = locate(href_list["switchTo"]) in cameranet.cameras if(!C) return switch_to_camera(usr, C) diff --git a/code/game/machinery/shieldgen.dm b/code/game/machinery/shieldgen.dm index e6225f648d7..86eed40484d 100644 --- a/code/game/machinery/shieldgen.dm +++ b/code/game/machinery/shieldgen.dm @@ -25,15 +25,6 @@ if(!height || air_group) return 0 else return ..() -//Looks like copy/pasted code... I doubt 'need_rebuild' is even used here - Nodrak -/obj/machinery/shield/proc/update_nearby_tiles(need_rebuild) - if(!air_master) return 0 - - air_master.mark_for_update(get_turf(src)) - - return 1 - - /obj/machinery/shield/attackby(obj/item/weapon/W as obj, mob/user as mob) if(!istype(W)) return diff --git a/code/game/objects/effects/effect_system.dm b/code/game/objects/effects/effect_system.dm index 27db5475d94..beee3a49494 100644 --- a/code/game/objects/effects/effect_system.dm +++ b/code/game/objects/effects/effect_system.dm @@ -1109,15 +1109,6 @@ steam.start() -- spawns the effect if(air_group) return 0 return !density - - proc/update_nearby_tiles(need_rebuild) - if(!air_master) - return 0 - - air_master.mark_for_update(get_turf(src)) - - return 1 - /datum/effect/effect/system/reagents_explosion var/amount // TNT equivalent var/flashing = 0 // does explosion creates flash effect? diff --git a/code/game/objects/items/devices/handtv.dm b/code/game/objects/items/devices/handtv.dm index 0406db85852..48e22348f32 100644 --- a/code/game/objects/items/devices/handtv.dm +++ b/code/game/objects/items/devices/handtv.dm @@ -7,7 +7,7 @@ /obj/item/device/handtv/attack_self(mob/usr as mob) var/list/cameras = new/list() - for (var/obj/machinery/camera/C in cameranet.viewpoints) + for (var/obj/machinery/camera/C in cameranet.cameras) if (C.hasbug && C.status) cameras.Add(C) if (length(cameras) == 0) diff --git a/code/game/objects/structures/inflatable.dm b/code/game/objects/structures/inflatable.dm index 8422c076d76..640a7f6951c 100644 --- a/code/game/objects/structures/inflatable.dm +++ b/code/game/objects/structures/inflatable.dm @@ -34,14 +34,6 @@ update_nearby_tiles() ..() - proc/update_nearby_tiles(need_rebuild) //Copypasta from airlock code - if(!air_master) - return 0 - air_master.mark_for_update(get_turf(src)) - return 1 - - - CanPass(atom/movable/mover, turf/target, height=0, air_group=0) return 0 diff --git a/code/game/objects/structures/mineral_doors.dm b/code/game/objects/structures/mineral_doors.dm index 8b7d70b4dc4..06bd5d139a3 100644 --- a/code/game/objects/structures/mineral_doors.dm +++ b/code/game/objects/structures/mineral_doors.dm @@ -157,13 +157,6 @@ CheckHardness() return - proc/update_nearby_tiles(need_rebuild) //Copypasta from airlock code - if(!air_master) return 0 - - air_master.mark_for_update(get_turf(src)) - - return 1 - /obj/structure/mineral_door/iron mineralType = "metal" hardness = 3 diff --git a/code/game/objects/structures/windoor_assembly.dm b/code/game/objects/structures/windoor_assembly.dm index b9e5b2a34f6..20569ee7af8 100644 --- a/code/game/objects/structures/windoor_assembly.dm +++ b/code/game/objects/structures/windoor_assembly.dm @@ -27,13 +27,6 @@ obj/structure/windoor_assembly var/secure = 0 //Whether or not this creates a secure windoor var/state = "01" //How far the door assembly has progressed -/obj/structure/windoor_assembly/proc/update_nearby_tiles(need_rebuild) - if(!air_master) return 0 - - air_master.mark_for_update(loc) - - return 1 - obj/structure/windoor_assembly/New(dir=NORTH) ..() src.ini_dir = src.dir diff --git a/code/game/objects/structures/window.dm b/code/game/objects/structures/window.dm index d6f9288d05f..1c101cf58f4 100644 --- a/code/game/objects/structures/window.dm +++ b/code/game/objects/structures/window.dm @@ -403,14 +403,6 @@ var/global/wcColored dir = ini_dir update_nearby_tiles(need_rebuild=1) - -//This proc has to do with airgroups and atmos, it has nothing to do with smoothwindows, that's update_nearby_tiles(). -/obj/structure/window/proc/update_nearby_tiles(need_rebuild) - if(!air_master) return 0 - air_master.mark_for_update(get_turf(src)) - - return 1 - //checks if this window is full-tile one /obj/structure/window/proc/is_fulltile() if(dir & (dir - 1)) diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm index 1aeed58f7df..c250ceca9d0 100644 --- a/code/modules/admin/verbs/mapping.dm +++ b/code/modules/admin/verbs/mapping.dm @@ -52,7 +52,7 @@ var/intercom_range_display_status = 0 del(C) if(camera_range_display_status) - for(var/obj/machinery/camera/C in cameranet.viewpoints) + for(var/obj/machinery/camera/C in cameranet.cameras) new/obj/effect/debugging/camera_range(C.loc) feedback_add_details("admin_verb","mCRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc! @@ -68,7 +68,7 @@ var/intercom_range_display_status = 0 var/list/obj/machinery/camera/CL = list() - for(var/obj/machinery/camera/C in cameranet.viewpoints) + for(var/obj/machinery/camera/C in cameranet.cameras) CL += C var/output = {"CAMERA ANOMALIES REPORT
diff --git a/code/modules/computer3/computers/camera.dm b/code/modules/computer3/computers/camera.dm index ed387513a5f..ddf583888fd 100644 --- a/code/modules/computer3/computers/camera.dm +++ b/code/modules/computer3/computers/camera.dm @@ -185,7 +185,7 @@ return null var/list/L = list() - for(var/obj/machinery/camera/C in cameranet.viewpoints) + for(var/obj/machinery/camera/C in cameranet.cameras) var/list/temp = C.network & key.networks if(temp.len) L.Add(C) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index a6583841231..8461ad6c816 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -406,7 +406,7 @@ var/list/ai_list = list() unset_machine() src << browse(null, t1) if (href_list["switchcamera"]) - switchCamera(locate(href_list["switchcamera"])) in cameranet.viewpoints + switchCamera(locate(href_list["switchcamera"])) in cameranet.cameras if (href_list["showalerts"]) ai_alerts() //Carn: holopad requests @@ -712,11 +712,11 @@ var/list/ai_list = list() var/mob/living/silicon/ai/U = usr - for (var/obj/machinery/camera/C in cameranet.viewpoints) + for (var/obj/machinery/camera/C in cameranet.cameras) if(!C.can_use()) continue - var/list/tempnetwork = difflist(C.network,RESTRICTED_CAMERA_NETWORKS,1) + var/list/tempnetwork = difflist(C.network,restricted_camera_networks,1) if(tempnetwork.len) for(var/i in tempnetwork) cameralist[i] = i @@ -730,7 +730,7 @@ var/list/ai_list = list() if(isnull(network)) network = old_network // If nothing is selected else - for(var/obj/machinery/camera/C in cameranet.viewpoints) + for(var/obj/machinery/camera/C in cameranet.cameras) if(!C.can_use()) continue if(network in C.network) diff --git a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm index b0caf3b4a69..584af962874 100644 --- a/code/modules/mob/living/silicon/ai/freelook/cameranet.dm +++ b/code/modules/mob/living/silicon/ai/freelook/cameranet.dm @@ -1,25 +1,156 @@ -/datum/visibility_network/cameras - ChunkType = /datum/visibility_chunk/camera +// CAMERA NET +// +// The datum containing all the chunks. -/datum/visibility_network/cameras/getViewpointFromMob(var/mob/currentMob) - var/mob/living/silicon/robot/currentRobot=currentMob - if(currentRobot) - return currentRobot.camera - return FALSE +var/datum/cameranet/cameranet = new() -/datum/visibility_network/cameras/validViewpoint(var/viewpoint) - var/obj/machinery/camera/c = viewpoint - if (!c) - return FALSE - return c.can_use() +/datum/cameranet + // The cameras on the map, no matter if they work or not. Updated in obj/machinery/camera.dm by New() and Del(). + var/list/cameras = list() + var/cameras_unsorted = 1 + // The chunks of the map, mapping the areas that the cameras can see. + var/list/chunks = list() + var/ready = 0 +/datum/cameranet/proc/process_sort() + if(cameras_unsorted) + cameras = dd_sortedObjectList(cameras) + cameras_unsorted = 0 -// adding some indirection so that I don't have to edit a ton of files -/datum/visibility_network/cameras/proc/addCamera(var/camera) - return addViewpoint(camera) +// Checks if a chunk has been Generated in x, y, z. +/datum/cameranet/proc/chunkGenerated(x, y, z) + x &= ~0xf + y &= ~0xf + var/key = "[x],[y],[z]" + return (chunks[key]) -/datum/visibility_network/cameras/proc/removeCamera(var/camera) - return removeViewpoint(camera) +// Returns the chunk in the x, y, z. +// If there is no chunk, it creates a new chunk and returns that. +/datum/cameranet/proc/getCameraChunk(x, y, z) + x &= ~0xf + y &= ~0xf + var/key = "[x],[y],[z]" + if(!chunks[key]) + chunks[key] = new /datum/camerachunk(null, x, y, z) -/datum/visibility_network/cameras/proc/checkCameraVis(var/atom/target) - return checkCanSee(target) + return chunks[key] + +// Updates what the aiEye can see. It is recommended you use this when the aiEye moves or it's location is set. + +/datum/cameranet/proc/visibility(mob/aiEye/ai) + // 0xf = 15 + var/x1 = max(0, ai.x - 16) & ~0xf + var/y1 = max(0, ai.y - 16) & ~0xf + var/x2 = min(world.maxx, ai.x + 16) & ~0xf + var/y2 = min(world.maxy, ai.y + 16) & ~0xf + + var/list/visibleChunks = list() + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + visibleChunks += getCameraChunk(x, y, ai.z) + + var/list/remove = ai.visibleCameraChunks - visibleChunks + var/list/add = visibleChunks - ai.visibleCameraChunks + + for(var/chunk in remove) + var/datum/camerachunk/c = chunk + c.remove(ai) + + for(var/chunk in add) + var/datum/camerachunk/c = chunk + c.add(ai) + +// Updates the chunks that the turf is located in. Use this when obstacles are destroyed or when doors open. + +/datum/cameranet/proc/updateVisibility(atom/A, var/opacity_check = 1) + + if(!ticker || (opacity_check && !A.opacity)) + return + majorChunkChange(A, 2) + +/datum/cameranet/proc/updateChunk(x, y, z) + // 0xf = 15 + if(!chunkGenerated(x, y, z)) + return + var/datum/camerachunk/chunk = getCameraChunk(x, y, z) + chunk.hasChanged() + +// Removes a camera from a chunk. + +/datum/cameranet/proc/removeCamera(obj/machinery/camera/c) + if(c.can_use()) + majorChunkChange(c, 0) + +// Add a camera to a chunk. + +/datum/cameranet/proc/addCamera(obj/machinery/camera/c) + if(c.can_use()) + majorChunkChange(c, 1) + +// Used for Cyborg cameras. Since portable cameras can be in ANY chunk. + +/datum/cameranet/proc/updatePortableCamera(obj/machinery/camera/c) + if(c.can_use()) + majorChunkChange(c, 1) + //else + // majorChunkChange(c, 0) + +// Never access this proc directly!!!! +// This will update the chunk and all the surrounding chunks. +// It will also add the atom to the cameras list if you set the choice to 1. +// Setting the choice to 0 will remove the camera from the chunks. +// If you want to update the chunks around an object, without adding/removing a camera, use choice 2. + +/datum/cameranet/proc/majorChunkChange(atom/c, var/choice) + // 0xf = 15 + if(!c) + return + + var/turf/T = get_turf(c) + if(T) + var/x1 = max(0, T.x - 8) & ~0xf + var/y1 = max(0, T.y - 8) & ~0xf + var/x2 = min(world.maxx, T.x + 8) & ~0xf + var/y2 = min(world.maxy, T.y + 8) & ~0xf + + //world << "X1: [x1] - Y1: [y1] - X2: [x2] - Y2: [y2]" + + for(var/x = x1; x <= x2; x += 16) + for(var/y = y1; y <= y2; y += 16) + if(chunkGenerated(x, y, T.z)) + var/datum/camerachunk/chunk = getCameraChunk(x, y, T.z) + if(choice == 0) + // Remove the camera. + chunk.cameras -= c + else if(choice == 1) + // You can't have the same camera in the list twice. + chunk.cameras |= c + chunk.hasChanged() + +// Will check if a mob is on a viewable turf. Returns 1 if it is, otherwise returns 0. + +/datum/cameranet/proc/checkCameraVis(mob/living/target as mob) + + // 0xf = 15 + var/turf/position = get_turf(target) + return checkTurfVis(position) + +/datum/cameranet/proc/checkTurfVis(var/turf/position) + var/datum/camerachunk/chunk = getCameraChunk(position.x, position.y, position.z) + if(chunk) + if(chunk.changed) + chunk.hasChanged(1) // Update now, no matter if it's visible or not. + if(chunk.visibleTurfs[position]) + return 1 + return 0 + +// Debug verb for VVing the chunk that the turf is in. +/* +/turf/verb/view_chunk() + set src in world + + if(cameranet.chunkGenerated(x, y, z)) + var/datum/camerachunk/chunk = cameranet.getCameraChunk(x, y, z) + usr.client.debug_variables(chunk) +*/ \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/chunk.dm b/code/modules/mob/living/silicon/ai/freelook/chunk.dm index ba4e7892f57..fda4ef2f78e 100644 --- a/code/modules/mob/living/silicon/ai/freelook/chunk.dm +++ b/code/modules/mob/living/silicon/ai/freelook/chunk.dm @@ -1,23 +1,168 @@ -/datum/visibility_chunk/camera +#define UPDATE_BUFFER 25 // 2.5 seconds -/datum/visibility_chunk/camera/validViewpoint(var/viewpoint) - var/obj/machinery/camera/c = viewpoint - if(!c) - return FALSE - if(!c.can_use()) - return FALSE - var/turf/point = locate(src.x + 8, src.y + 8, src.z) - if(get_dist(point, c) > 24) - return FALSE - return TRUE +// CAMERA CHUNK +// +// A 16x16 grid of the map with a list of turfs that can be seen, are visible and are dimmed. +// Allows the AI Eye to stream these chunks and know what it can and cannot see. +/datum/camerachunk + var/list/obscuredTurfs = list() + var/list/visibleTurfs = list() + var/list/obscured = list() + var/list/cameras = list() + var/list/turfs = list() + var/list/seenby = list() + var/visible = 0 + var/changed = 0 + var/updating = 0 + var/x = 0 + var/y = 0 + var/z = 0 -/datum/visibility_chunk/camera/getVisibleTurfsForViewpoint(var/viewpoint) - var/obj/machinery/camera/c = viewpoint - return c.can_see() +// Add an AI eye to the chunk, then update if changed. +/datum/camerachunk/proc/add(mob/aiEye/ai) + if(!ai.ai) + return + ai.visibleCameraChunks += src + if(ai.ai.client) + ai.ai.client.images += obscured + visible++ + seenby += ai + if(changed && !updating) + update() + +// Remove an AI eye from the chunk, then update if changed. + +/datum/camerachunk/proc/remove(mob/aiEye/ai) + if(!ai.ai) + return + ai.visibleCameraChunks -= src + if(ai.ai.client) + ai.ai.client.images -= obscured + seenby -= ai + if(visible > 0) + visible-- + +// Called when a chunk has changed. I.E: A wall was deleted. + +/datum/camerachunk/proc/visibilityChanged(turf/loc) + if(!visibleTurfs[loc]) + return + hasChanged() + +// Updates the chunk, makes sure that it doesn't update too much. If the chunk isn't being watched it will +// instead be flagged to update the next time an AI Eye moves near it. + +/datum/camerachunk/proc/hasChanged(var/update_now = 0) + if(visible || update_now) + if(!updating) + updating = 1 + spawn(UPDATE_BUFFER) // Batch large changes, such as many doors opening or closing at once + update() + updating = 0 + else + changed = 1 + +// The actual updating. It gathers the visible turfs from cameras and puts them into the appropiate lists. + +/datum/camerachunk/proc/update() + + set background = 1 + + var/list/newVisibleTurfs = list() + + for(var/camera in cameras) + var/obj/machinery/camera/c = camera + + if(!c) + continue + + if(!c.can_use()) + continue + + var/turf/point = locate(src.x + 8, src.y + 8, src.z) + if(get_dist(point, c) > 24) + continue + + for(var/turf/t in c.can_see()) + newVisibleTurfs[t] = t + + // Removes turf that isn't in turfs. + newVisibleTurfs &= turfs + + var/list/visAdded = newVisibleTurfs - visibleTurfs + var/list/visRemoved = visibleTurfs - newVisibleTurfs + + visibleTurfs = newVisibleTurfs + obscuredTurfs = turfs - newVisibleTurfs + + for(var/turf in visAdded) + var/turf/t = turf + if(t.obscured) + obscured -= t.obscured + for(var/eye in seenby) + var/mob/aiEye/m = eye + if(!m || !m.ai) + continue + if(m.ai.client) + m.ai.client.images -= t.obscured + + for(var/turf in visRemoved) + var/turf/t = turf + if(obscuredTurfs[t]) + if(!t.obscured) + t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15) + + obscured += t.obscured + for(var/eye in seenby) + var/mob/aiEye/m = eye + if(!m || !m.ai) + seenby -= m + continue + if(m.ai.client) + m.ai.client.images += t.obscured + +// Create a new camera chunk, since the chunks are made as they are needed. + +/datum/camerachunk/New(loc, x, y, z) + + // 0xf = 15 + x &= ~0xf + y &= ~0xf + + src.x = x + src.y = y + src.z = z -/datum/visibility_chunk/camera/findNearbyViewpoints() for(var/obj/machinery/camera/c in range(16, locate(x + 8, y + 8, z))) if(c.can_use()) - viewpoints += c + cameras += c + + for(var/turf/t in range(10, locate(x + 8, y + 8, z))) + if(t.x >= x && t.y >= y && t.x < x + 16 && t.y < y + 16) + turfs[t] = t + + for(var/camera in cameras) + var/obj/machinery/camera/c = camera + if(!c) + continue + + if(!c.can_use()) + continue + + for(var/turf/t in c.can_see()) + visibleTurfs[t] = t + + // Removes turf that isn't in turfs. + visibleTurfs &= turfs + + obscuredTurfs = turfs - visibleTurfs + + for(var/turf in obscuredTurfs) + var/turf/t = turf + if(!t.obscured) + t.obscured = image('icons/effects/cameravis.dmi', t, "black", 15) + obscured += t.obscured + +#undef UPDATE_BUFFER \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index afe319fc501..cb035d047e5 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -1,51 +1,41 @@ // AI EYE // -// A mob that the AI controls to look around the station with. +// An invisible (no icon) mob that the AI controls to look around the station with. // It streams chunks as it moves around, which will show it what the AI can and cannot see. /mob/aiEye name = "Inactive AI Eye" - icon = 'icons/mob/AI.dmi' - icon_state = "eye" - alpha = 127 + icon = 'icons/obj/status_display.dmi' // For AI friend secret shh :o + var/list/visibleCameraChunks = list() var/mob/living/silicon/ai/ai = null density = 0 status_flags = GODMODE // You can't damage it. mouse_opacity = 0 see_in_dark = 7 - invisibility = INVISIBILITY_AI_EYE - -/mob/aiEye/New() - ..() - visibility_interface = new /datum/visibility_interface/ai_eye(src) + invisibility = INVISIBILITY_MAXIMUM // Movement code. Returns 0 to stop air movement from moving it. /mob/aiEye/Move() return 0 -// Hide popout menu verbs -/mob/aiEye/examine() +/mob/aiEye/examine(atom/A as mob|obj|turf in view()) set popup_menu = 0 set src = usr.contents return 0 -/mob/aiEye/pull() - set popup_menu = 0 - set src = usr.contents - return 0 - -/mob/aiEye/point() - set popup_menu = 0 - set src = usr.contents - return 0 +/mob/aiEye/examine(mob/user) // Use this when setting the aiEye's location. // It will also stream the chunk that the new loc is in. +/mob/aiEye/setLoc(var/T, var/cancel_tracking = 1) -/mob/aiEye/setLoc(var/T) if(ai) if(!isturf(ai.loc)) return + + if(cancel_tracking) + ai.ai_cancel_tracking() + T = get_turf(T) loc = T cameranet.visibility(src) @@ -54,7 +44,6 @@ //Holopad if(ai.holo) ai.holo.move_hologram() - /mob/aiEye/proc/getLoc() @@ -63,10 +52,6 @@ return return ai.eyeobj.loc - -/mob/aiEye/Move() - return 0 - // AI MOVEMENT // The AI's "eye". Described on the top of the page. @@ -78,7 +63,6 @@ var/acceleration = 1 var/obj/machinery/hologram/holopad/holo = null - // Intiliaze the eye by assigning it's "ai" variable to us. Then set it's loc to us. /mob/living/silicon/ai/New() ..() @@ -87,7 +71,7 @@ spawn(5) eyeobj.loc = src.loc -/mob/living/silicon/ai/Destroy() +/mob/living/silicon/ai/Del() eyeobj.ai = null del(eyeobj) // No AI, no Eye ..() @@ -96,9 +80,7 @@ if(istype(usr, /mob/living/silicon/ai)) var/mob/living/silicon/ai/AI = usr if(AI.eyeobj && AI.client.eye == AI.eyeobj) - AI.cameraFollow = null - if (isturf(src.loc) || isturf(src)) - AI.eyeobj.setLoc(src) + AI.eyeobj.setLoc(src) // This will move the AIEye. It will also cause lights near the eye to light up, if toggled. // This is handled in the proc below this one. @@ -122,23 +104,24 @@ else user.sprint = initial - user.cameraFollow = null - //user.unset_machine() //Uncomment this if it causes problems. //user.lightNearbyCamera() // Return to the Core. -/mob/living/silicon/ai/proc/view_core() +/mob/living/silicon/ai/proc/core() + set category = "AI Commands" + set name = "AI Core" + + view_core() + + +/mob/living/silicon/ai/proc/view_core() current = null - cameraFollow = null unset_machine() - if(src.eyeobj && src.loc) - src.eyeobj.z = src.z - src.eyeobj.loc = src.loc - else + if(!src.eyeobj) src << "ERROR: Eyeobj not found. Creating new eye..." src.eyeobj = new(src.loc) src.eyeobj.ai = src @@ -146,11 +129,11 @@ if(client && client.eye) client.eye = src - - for(var/datum/visibility_chunk/camera/c in eyeobj.visibility_interface.visible_chunks) + for(var/datum/camerachunk/c in eyeobj.visibleCameraChunks) c.remove(eyeobj) + src.eyeobj.setLoc(src) -/mob/living/silicon/ai/verb/toggle_acceleration() +/mob/living/silicon/ai/proc/toggle_acceleration() set category = "AI Commands" set name = "Toggle Camera Acceleration" diff --git a/code/modules/mob/living/silicon/ai/freelook/read_me.dm b/code/modules/mob/living/silicon/ai/freelook/read_me.dm index e71b0903b85..53e68ff1377 100644 --- a/code/modules/mob/living/silicon/ai/freelook/read_me.dm +++ b/code/modules/mob/living/silicon/ai/freelook/read_me.dm @@ -20,7 +20,7 @@ HOW IT WORKS It works by first creating a camera network datum. Inside of this camera network are "chunks" (which will be - explained later) and "cameras". The cameras list is kept up to date by obj/machinery/camera/New() and Destroy(). + explained later) and "cameras". The cameras list is kept up to date by obj/machinery/camera/New() and Del(). Next the camera network has chunks. These chunks are a 16x16 tile block of turfs and cameras contained inside the chunk. These turfs are then sorted out based on what the cameras can and cannot see. If none of the cameras can see the turf, inside @@ -43,7 +43,7 @@ WHERE IS EVERYTHING? - cameraNetwork.dm = Everything about the cameraNetwork datum. + cameranet.dm = Everything about the cameranet datum. chunk.dm = Everything about the chunk datum. eye.dm = Everything about the AI and the AIEye. updating.dm = Everything about triggers that will update chunks. diff --git a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm index d6799548bff..9458a768633 100644 --- a/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm +++ b/code/modules/mob/living/silicon/ai/freelook/update_triggers.dm @@ -1,3 +1,80 @@ +#define BORG_CAMERA_BUFFER 30 + +//UPDATE TRIGGERS, when the chunk (and the surrounding chunks) should update. + +// TURFS + +/turf + var/image/obscured + +/turf/proc/visibilityChanged() + if(ticker) + cameranet.updateVisibility(src) + +/turf/simulated/Del() + visibilityChanged() + ..() + +/turf/simulated/New() + ..() + visibilityChanged() + + + +// STRUCTURES + +/obj/structure/Del() + if(ticker) + cameranet.updateVisibility(src) + ..() + +/obj/structure/New() + ..() + if(ticker) + cameranet.updateVisibility(src) + +// EFFECTS + +/obj/effect/Del() + if(ticker) + cameranet.updateVisibility(src) + ..() + +/obj/effect/New() + ..() + if(ticker) + cameranet.updateVisibility(src) + + +// DOORS + +// Simply updates the visibility of the area when it opens/closes/destroyed. +/obj/machinery/door/update_nearby_tiles(need_rebuild) + . = ..(need_rebuild) + // Glass door glass = 1 + // don't check then? + if(!glass && cameranet) + cameranet.updateVisibility(src, 0) + + +// ROBOT MOVEMENT + +// Update the portable camera everytime the Robot moves. +// This might be laggy, comment it out if there are problems. +/mob/living/silicon/robot/var/updating = 0 + +/mob/living/silicon/robot/Move() + var/oldLoc = src.loc + . = ..() + if(.) + if(src.camera && src.camera.network.len) + if(!updating) + updating = 1 + spawn(BORG_CAMERA_BUFFER) + if(oldLoc != src.loc) + cameranet.updatePortableCamera(src.camera) + updating = 0 + // CAMERA // An addition to deactivate which removes/adds the camera from the chunk list based on if it works or not. @@ -5,30 +82,29 @@ /obj/machinery/camera/deactivate(user as mob, var/choice = 1) ..(user, choice) if(src.can_use()) - cameranet.addViewpoint(src) + cameranet.addCamera(src) else src.SetLuminosity(0) - cameranet.removeViewpoint(src) + cameranet.removeCamera(src) /obj/machinery/camera/New() ..() //Camera must be added to global list of all cameras no matter what... if(cameranet.cameras_unsorted || !ticker) - cameranet.viewpoints += src + cameranet.cameras += src cameranet.cameras_unsorted = 1 else - dd_insertObjectList(cameranet.viewpoints, src) + dd_insertObjectList(cameranet.cameras, src) - var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS) //...but if all of camera's networks are restricted, it only works for specific camera consoles. + var/list/open_networks = difflist(network,restricted_camera_networks) //...but if all of camera's networks are restricted, it only works for specific camera consoles. if(open_networks.len) //If there is at least one open network, chunk is available for AI usage. - cameranet.addViewpoint(src) + cameranet.addCamera(src) /obj/machinery/camera/Del() - - cameranet.viewpoints -= src - var/list/open_networks = difflist(network,RESTRICTED_CAMERA_NETWORKS) + cameranet.cameras -= src + var/list/open_networks = difflist(network,restricted_camera_networks) if(open_networks.len) - cameranet.removeViewpoint(src) + cameranet.removeCamera(src) ..() #undef BORG_CAMERA_BUFFER \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/freelook/visibility_interface.dm b/code/modules/mob/living/silicon/ai/freelook/visibility_interface.dm deleted file mode 100644 index b55598c6090..00000000000 --- a/code/modules/mob/living/silicon/ai/freelook/visibility_interface.dm +++ /dev/null @@ -1,10 +0,0 @@ -/datum/visibility_interface/ai_eye - chunk_type = /datum/visibility_chunk/camera - -/datum/visibility_interface/ai_eye/getClient() - var/mob/aiEye/eye = controller - if (!eye) - return FALSE - if (!eye.ai) - return FALSE - return eye.ai.client diff --git a/code/modules/mob/spirit/cultnet.dm b/code/modules/mob/spirit/cultnet.dm index df0cd57ff5d..c3f37f8fdd1 100644 --- a/code/modules/mob/spirit/cultnet.dm +++ b/code/modules/mob/spirit/cultnet.dm @@ -19,54 +19,6 @@ It reuses a lot of code from the AIEye cameraNetwork. In order to work properly, if (vp) return TRUE return FALSE - - -/datum/visibility_chunk/cult/validViewpoint(var/atom/viewpoint) - var/turf/point = locate(src.x + 8, src.y + 8, src.z) - if(get_dist(point, viewpoint) > 24) - return FALSE - - if (isCultRune(viewpoint) || isCultViewpoint(viewpoint)) - return viewpoint:can_use() - return FALSE - - -/datum/visibility_chunk/cult/getVisibleTurfsForViewpoint(var/viewpoint) - var/obj/effect/rune/rune = viewpoint - if (rune) - return rune.can_see() - var/obj/cult_viewpoint/cvp = viewpoint - if (cvp) - return cvp.can_see() - return null - - -/datum/visibility_chunk/cult/findNearbyViewpoints() - for(var/obj/cult_viewpoint/vp in range(16, locate(x + 8, y + 8, z))) - if(vp.can_use()) - viewpoints += vp - for(var/obj/effect/rune/rune in range(16, locate(x + 8, y + 8, z))) - viewpoints += rune - - -/datum/visibility_network/cult - ChunkType = /datum/visibility_chunk/cult - - -/datum/visibility_network/cult/validViewpoint(var/viewpoint) - if (isCultRune(viewpoint) || isCultViewpoint(viewpoint)) - return viewpoint:can_use() - return FALSE - -/datum/visibility_network/cult/getViewpointFromMob(var/mob/currentMob) - for(var/obj/cult_viewpoint/currentView in currentMob) - return currentView - return FALSE - - -/datum/visibility_interface/cult - chunk_type = /datum/visibility_chunk/cult - /* RUNE JUNK diff --git a/code/modules/mob/spirit/movement.dm b/code/modules/mob/spirit/movement.dm index bd794b6fd2b..b5ac53fbeae 100644 --- a/code/modules/mob/spirit/movement.dm +++ b/code/modules/mob/spirit/movement.dm @@ -52,7 +52,6 @@ mob/spirit/proc/Spirit_Move(direct) mob/spirit/setLoc(var/T) T = get_turf(T) loc = T - cultNetwork.visibility(src) mob/spirit/verb/toggle_acceleration() set category = "Spirit" diff --git a/code/modules/mob/spirit/spirit.dm b/code/modules/mob/spirit/spirit.dm index ce7080b744c..c90f0f569b7 100644 --- a/code/modules/mob/spirit/spirit.dm +++ b/code/modules/mob/spirit/spirit.dm @@ -38,9 +38,6 @@ mob/spirit/New() loc = pick(latejoin) - // hook them to the cult visibility network - visibility_interface = new /datum/visibility_interface/cult(src) - // no nameless spirits if (!name) name = "Boogyman" diff --git a/code/modules/mob/spirit/viewpoint.dm b/code/modules/mob/spirit/viewpoint.dm index b4bd911ea1c..0cd54451361 100644 --- a/code/modules/mob/spirit/viewpoint.dm +++ b/code/modules/mob/spirit/viewpoint.dm @@ -18,9 +18,6 @@ var/obj/cult_viewpoint/list/cult_viewpoints = list() /obj/cult_viewpoint/New(var/mob/target) owner = target //src.loc = owner - owner.addToVisibilityNetwork(cultNetwork) - cultNetwork.viewpoints+=src - cultNetwork.addViewpoint(src) cult_viewpoints+=src //handle_missing_mask() ..() @@ -28,10 +25,7 @@ var/obj/cult_viewpoint/list/cult_viewpoints = list() /obj/cult_viewpoint/Del() processing_objects.Remove(src) - cultNetwork.viewpoints-=src - cultNetwork.removeViewpoint(src) cult_viewpoints-=src - owner.removeFromVisibilityNetwork(cultNetwork) ..() return @@ -134,6 +128,8 @@ var/obj/cult_viewpoint/list/cult_viewpoints = list() /obj/cult_viewpoint/proc/get_display_name() + if(istype(src,/obj/effect/rune)) + return name if (!owner) return if (cult_name) diff --git a/code/setup.dm b/code/setup.dm index 925f72c9536..4906f0e6bdf 100644 --- a/code/setup.dm +++ b/code/setup.dm @@ -801,7 +801,7 @@ var/list/cheartstopper = list("potassium_chloride") //this stops the heart when #define GETPULSE_HAND 0 //less accurate (hand) #define GETPULSE_TOOL 1 //more accurate (med scanner, sleeper, etc) -var/list/RESTRICTED_CAMERA_NETWORKS = list( //Those networks can only be accessed by preexisting terminals. AIs and new terminals can't use them. +var/list/restricted_camera_networks = list( //Those networks can only be accessed by preexisting terminals. AIs and new terminals can't use them. "CentCom", "ERT", "NukeOps", diff --git a/paradise.dme b/paradise.dme index 230ec3d1e2a..a8cf74d3ba8 100644 --- a/paradise.dme +++ b/paradise.dme @@ -218,11 +218,6 @@ #include "code\datums\spells\trigger.dm" #include "code\datums\spells\turf_teleport.dm" #include "code\datums\spells\wizard.dm" -#include "code\datums\visibility_networks\chunk.dm" -#include "code\datums\visibility_networks\dictionary.dm" -#include "code\datums\visibility_networks\update_triggers.dm" -#include "code\datums\visibility_networks\visibility_interface.dm" -#include "code\datums\visibility_networks\visibility_network.dm" #include "code\datums\wires\airlock.dm" #include "code\datums\wires\alarm.dm" #include "code\datums\wires\apc.dm" @@ -1273,7 +1268,6 @@ #include "code\modules\mob\living\silicon\ai\freelook\eye.dm" #include "code\modules\mob\living\silicon\ai\freelook\read_me.dm" #include "code\modules\mob\living\silicon\ai\freelook\update_triggers.dm" -#include "code\modules\mob\living\silicon\ai\freelook\visibility_interface.dm" #include "code\modules\mob\living\silicon\decoy\death.dm" #include "code\modules\mob\living\silicon\decoy\decoy.dm" #include "code\modules\mob\living\silicon\decoy\life.dm" From 97b75276fa777f94fd085b999fc7a70ff28937df Mon Sep 17 00:00:00 2001 From: Markolie Date: Tue, 10 Feb 2015 17:26:35 +0100 Subject: [PATCH 5/8] Fix robot tracking --- code/game/machinery/bots/bots.dm | 2 +- code/game/machinery/camera/tracking.dm | 6 +++--- code/modules/mob/living/silicon/ai/ai.dm | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/code/game/machinery/bots/bots.dm b/code/game/machinery/bots/bots.dm index 539dd775b0f..30ed21fbede 100644 --- a/code/game/machinery/bots/bots.dm +++ b/code/game/machinery/bots/bots.dm @@ -583,7 +583,7 @@ obj/machinery/bot/proc/start_patrol() new_destination = "__nearest__" post_signal(beacon_freq, "findbeacon", "patrol") awaiting_beacon = 1 - spawn(150) + spawn(200) awaiting_beacon = 0 if(nearest_beacon) set_destination(nearest_beacon) diff --git a/code/game/machinery/camera/tracking.dm b/code/game/machinery/camera/tracking.dm index a26fd25a6f7..47c27591e99 100644 --- a/code/game/machinery/camera/tracking.dm +++ b/code/game/machinery/camera/tracking.dm @@ -175,7 +175,7 @@ src << "Follow camera mode [forced ? "terminated" : "ended"]." cameraFollow = null -/mob/living/silicon/ai/proc/ai_actual_track(mob/living/target as mob) +/mob/living/silicon/ai/proc/ai_actual_track(atom/movable/target as mob|obj) if(!istype(target)) return var/mob/living/silicon/ai/U = usr @@ -222,9 +222,9 @@ return 0 return 1 -/proc/trackable(var/mob/living/M) +/proc/trackable(atom/movable/M) var/turf/T = get_turf(M) - if(T && (T.z == 1) && hassensorlevel(M, SUIT_SENSOR_TRACKING)) + if(T && (T.z == 1 || T.z == 3 || T.z == 5)) return 1 return near_camera(M) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 8461ad6c816..d7a4b51d522 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -585,14 +585,14 @@ var/list/ai_list = list() src << "Wireless communication is disabled." return var/turf/ai_current_turf = get_turf(src) - var/ai_Zlevel = ai_current_turf.z + var/ai_allowed_Zlevel = list(1,3,5) var/d var/area/bot_area d += "Query network status
" d += "" for (Bot in aibots) - if(Bot.z == ai_Zlevel && !Bot.remote_disabled) //Only non-emagged bots on the same Z-level are detected! + if((Bot.z in ai_allowed_Zlevel) && !Bot.remote_disabled) //Only non-emagged bots on the allowed Z-level are detected! bot_area = get_area(Bot) d += "" //If the bot is on, it will display the bot's current mode status. If the bot is not mode, it will just report "Idle". "Inactive if it is not on at all. From 76911cc7102ae73a597ff0308b45693e8cb57ed5 Mon Sep 17 00:00:00 2001 From: Markolie Date: Tue, 10 Feb 2015 17:30:30 +0100 Subject: [PATCH 6/8] Warning fix --- code/modules/mob/living/silicon/ai/ai.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index d7a4b51d522..47464bc12e4 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -584,7 +584,6 @@ var/list/ai_list = list() if(control_disabled) src << "Wireless communication is disabled." return - var/turf/ai_current_turf = get_turf(src) var/ai_allowed_Zlevel = list(1,3,5) var/d var/area/bot_area From 6f6338cea4354d0631ba9895d7d378881c74e227 Mon Sep 17 00:00:00 2001 From: Markolie Date: Tue, 10 Feb 2015 23:30:16 +0100 Subject: [PATCH 7/8] Fix AI eye invisibility --- code/modules/mob/living/silicon/ai/freelook/eye.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index cb035d047e5..cfeb8d5db32 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -12,7 +12,7 @@ status_flags = GODMODE // You can't damage it. mouse_opacity = 0 see_in_dark = 7 - invisibility = INVISIBILITY_MAXIMUM + invisibility = INVISIBILITY_AI_EYE // Movement code. Returns 0 to stop air movement from moving it. /mob/aiEye/Move() From a7ab903b4eec423266d37db683a65664cdb1f920 Mon Sep 17 00:00:00 2001 From: Markolie Date: Tue, 10 Feb 2015 23:34:17 +0100 Subject: [PATCH 8/8] And another AI fix --- code/modules/mob/living/silicon/ai/freelook/eye.dm | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/code/modules/mob/living/silicon/ai/freelook/eye.dm b/code/modules/mob/living/silicon/ai/freelook/eye.dm index cfeb8d5db32..8218bec993e 100644 --- a/code/modules/mob/living/silicon/ai/freelook/eye.dm +++ b/code/modules/mob/living/silicon/ai/freelook/eye.dm @@ -18,12 +18,21 @@ /mob/aiEye/Move() return 0 +// Hide popout menu verbs /mob/aiEye/examine(atom/A as mob|obj|turf in view()) set popup_menu = 0 set src = usr.contents return 0 + +/mob/aiEye/pull() + set popup_menu = 0 + set src = usr.contents + return 0 -/mob/aiEye/examine(mob/user) +/mob/aiEye/point() + set popup_menu = 0 + set src = usr.contents + return 0 // Use this when setting the aiEye's location. // It will also stream the chunk that the new loc is in.

Name

Status

Location

Control

[Bot.hacked ? "(!) [Bot.name]" : Bot.name] ([Bot.bot_type_name])