Merge pull request #6990 from VOREStation/pol-tcomupdate

Refactor telecomms and consoles to operate on logical zlevels
This commit is contained in:
Atermonera
2020-04-28 14:55:04 -07:00
committed by GitHub
63 changed files with 1336 additions and 1013 deletions
@@ -176,7 +176,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -151,7 +151,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -128,7 +128,7 @@ Thus, the two variables affect pump operation are set in New():
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -107,7 +107,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -247,7 +247,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -93,7 +93,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
"area" = area_uid,
+15
View File
@@ -74,6 +74,21 @@ var/global/defer_powernet_rebuild = 0 // True if net rebuild will be called
// Those networks can only be accessed by pre-existing terminals. AIs and new terminals can't use them.
var/list/restricted_camera_networks = list(NETWORK_ERT,NETWORK_MERCENARY,"Secret", NETWORK_COMMUNICATORS)
#define TRANSMISSION_WIRE 0 //Is this ever used? I don't think it is.
#define TRANSMISSION_RADIO 1 //Radio transmissions (like airlock controller to pump)
#define TRANSMISSION_SUBSPACE 2 //Like headsets
#define TRANSMISSION_BLUESPACE 3 //Point-to-point links
#define SIGNAL_NORMAL 0 //Normal subspace signals
#define SIGNAL_SIMPLE 1 //Normal inter-machinery(?) signals
#define SIGNAL_FAKE 2 //Untrackable signals
#define SIGNAL_TEST 4 //Unlogged signals
#define DATA_NORMAL 0 //Normal data
#define DATA_INTERCOM 1 //Intercoms only
#define DATA_LOCAL 2 //Intercoms and SBRs
#define DATA_ANTAG 3 //Antag interception
#define DATA_FAKE 4 //Not from a real mob
//singularity defines
#define STAGE_ONE 1
+1 -1
View File
@@ -246,7 +246,7 @@
var/turf/speaker = get_turf(R)
if(speaker)
for(var/turf/T in hear(R.canhear_range,speaker))
speaker_coverage[T] = T
speaker_coverage[T] = R
// Try to find all the players who can hear the message
+1 -1
View File
@@ -104,7 +104,7 @@ SUBSYSTEM_DEF(shuttles)
try_add_landmark_tag(shuttle_landmark_tag, O)
landmarks_still_needed -= shuttle_landmark_tag
else if(istype(shuttle_landmark, /obj/effect/shuttle_landmark/automatic)) //These find their sector automatically
O = map_sectors["[shuttle_landmark.z]"]
O = get_overmap_sector(get_z(shuttle_landmark))
O ? O.add_landmark(shuttle_landmark, shuttle_landmark.shuttle_restricted) : (landmarks_awaiting_sector += shuttle_landmark)
/datum/controller/subsystem/shuttles/proc/get_landmark(var/shuttle_landmark_tag)
+1 -1
View File
@@ -87,7 +87,7 @@ SUBSYSTEM_DEF(skybox)
res.overlays += base
if(global.using_map.use_overmap && settings.use_overmap_details)
var/obj/effect/overmap/visitable/O = map_sectors["[z]"]
var/obj/effect/overmap/visitable/O = get_overmap_sector(z)
if(istype(O))
var/image/overmap = image(settings.icon)
overmap.overlays += O.generate_skybox()
File diff suppressed because it is too large Load Diff
+17 -2
View File
@@ -14,10 +14,25 @@ var/global/datum/repository/cameras/camera_repository = new()
networks = list()
..()
/datum/repository/cameras/proc/cameras_in_network(var/network)
/datum/repository/cameras/proc/cameras_in_network(var/network, var/list/zlevels)
setup_cache()
var/list/network_list = networks[network]
return network_list
if(LAZYLEN(zlevels))
var/list/filtered_cameras = list()
for(var/list/C in network_list)
//Camera is marked as always-visible
if(C["omni"])
filtered_cameras[++filtered_cameras.len] = C
continue
//Camera might be in an adjacent zlevel
var/camz = C["z"]
if(!camz) //It's inside something (helmet, communicator, etc) or nullspace or who knows
camz = get_z(locate(C["camera"]) in cameranet.cameras)
if(camz in zlevels)
filtered_cameras[++filtered_cameras.len] = C //Can't add lists to lists with +=
return filtered_cameras
else
return network_list
/datum/repository/cameras/proc/setup_cache()
if(!invalidated)
+23 -13
View File
@@ -30,7 +30,7 @@
title = "Security Announcement"
announcement_type = "Security Announcement"
/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast, var/msg_sanitized = 0)
/datum/announcement/proc/Announce(var/message as text, var/new_title = "", var/new_sound = null, var/do_newscast = newscast, var/msg_sanitized = 0, var/zlevel)
if(!message)
return
var/message_title = new_title ? new_title : title
@@ -40,13 +40,17 @@
message = sanitize(message, extra = 0)
message_title = sanitizeSafe(message_title)
Message(message, message_title)
var/list/zlevels
if(zlevel)
zlevels = using_map.get_map_levels(zlevel, TRUE)
Message(message, message_title, zlevels)
if(do_newscast)
NewsCast(message, message_title)
Sound(message_sound)
Sound(message_sound, zlevels)
Log(message, message_title)
datum/announcement/proc/Message(message as text, message_title as text)
datum/announcement/proc/Message(message as text, message_title as text, var/list/zlevels)
for(var/mob/M in player_list)
if(!istype(M,/mob/new_player) && !isdeaf(M))
to_chat(M, "<h2 class='alert'>[title]</h2>")
@@ -54,6 +58,7 @@ datum/announcement/proc/Message(message as text, message_title as text)
if (announcer)
to_chat(M, "<span class='alert'> -[html_encode(announcer)]</span>")
// You'll need to update these to_world usages if you want to make these z-level specific ~Aro
datum/announcement/minor/Message(message as text, message_title as text)
to_world("<b>[message]</b>")
@@ -64,7 +69,7 @@ datum/announcement/priority/Message(message as text, message_title as text)
to_world("<span class='alert'> -[html_encode(announcer)]</span>")
to_world("<br>")
datum/announcement/priority/command/Message(message as text, message_title as text)
datum/announcement/priority/command/Message(message as text, message_title as text, var/list/zlevels)
var/command
command += "<h1 class='alert'>[command_name()] Update</h1>"
if (message_title)
@@ -73,6 +78,8 @@ datum/announcement/priority/command/Message(message as text, message_title as te
command += "<br><span class='alert'>[message]</span><br>"
command += "<br>"
for(var/mob/M in player_list)
if(zlevels && !(get_z(M) in zlevels))
continue
if(!istype(M,/mob/new_player) && !isdeaf(M))
to_chat(M, command)
@@ -92,15 +99,18 @@ datum/announcement/proc/NewsCast(message as text, message_title as text)
news.can_be_redacted = 0
announce_newscaster_news(news)
datum/announcement/proc/PlaySound(var/message_sound)
datum/announcement/proc/PlaySound(var/message_sound, var/list/zlevels)
if(!message_sound)
return
for(var/mob/M in player_list)
if(zlevels && !(M.z in zlevels))
continue
if(!istype(M,/mob/new_player) && !isdeaf(M))
M << message_sound
datum/announcement/proc/Sound(var/message_sound)
PlaySound(message_sound)
datum/announcement/proc/Sound(var/message_sound, var/list/zlevels)
PlaySound(message_sound, zlevels)
datum/announcement/priority/Sound(var/message_sound)
if(message_sound)
@@ -124,12 +134,12 @@ datum/announcement/proc/Log(message as text, message_title as text)
/proc/ion_storm_announcement()
command_announcement.Announce("It has come to our attention that \the [station_name()] passed through an ion storm. Please monitor all electronic equipment for malfunctions.", "Anomaly Alert")
/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message)
/proc/AnnounceArrival(var/mob/living/carbon/human/character, var/rank, var/join_message, var/channel = "Common", var/zlevel)
if (ticker.current_state == GAME_STATE_PLAYING)
var/list/zlevels = zlevel ? using_map.get_map_levels(zlevel, TRUE) : null
if(character.mind.role_alt_title)
rank = character.mind.role_alt_title
AnnounceArrivalSimple(character.real_name, rank, join_message)
AnnounceArrivalSimple(character.real_name, rank, join_message, channel, zlevels)
/proc/AnnounceArrivalSimple(var/name, var/rank = "visitor", var/join_message = "will arrive to the station shortly by shuttle", new_sound = 'sound/misc/notice3.ogg')
global_announcer.autosay("[name], [rank], [join_message].", "Arrivals Announcement Computer")
/proc/AnnounceArrivalSimple(var/name, var/rank = "visitor", var/join_message = "will arrive at the station shortly", var/channel = "Common", var/list/zlevels)
global_announcer.autosay("[name], [rank], [join_message].", "Arrivals Announcement Computer", channel, zlevels)
+2 -2
View File
@@ -383,7 +383,7 @@
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = command
@@ -445,7 +445,7 @@
var/datum/signal/alert_signal = new
alert_signal.source = src
alert_signal.transmission_method = 1
alert_signal.transmission_method = TRANSMISSION_RADIO
alert_signal.data["zone"] = alarm_area.name
alert_signal.data["type"] = "Atmospheric"
+7 -7
View File
@@ -29,7 +29,7 @@
/obj/machinery/air_sensor/process()
if(on)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = id_tag
signal.data["timestamp"] = world.time
@@ -212,7 +212,7 @@ obj/machinery/computer/general_air_control/Destroy()
if(!radio_connection)
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
if(href_list["in_refresh_status"])
input_info = null
@@ -322,7 +322,7 @@ obj/machinery/computer/general_air_control/Destroy()
if(!radio_connection)
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
if(href_list["in_refresh_status"])
input_info = null
@@ -383,7 +383,7 @@ obj/machinery/computer/general_air_control/Destroy()
injecting = 1
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
@@ -445,7 +445,7 @@ obj/machinery/computer/general_air_control/Destroy()
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
"tag" = device_tag,
@@ -463,7 +463,7 @@ obj/machinery/computer/general_air_control/Destroy()
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
"tag" = device_tag,
@@ -478,7 +478,7 @@ obj/machinery/computer/general_air_control/Destroy()
return 0
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.source = src
signal.data = list(
"tag" = device_tag,
+1 -1
View File
@@ -67,7 +67,7 @@
var/datum/signal/signal = new
signal.source = src
signal.transmission_method = 1
signal.transmission_method = TRANSMISSION_RADIO
signal.data = list(
"tag" = id,
"device" = "AM",
+2
View File
@@ -33,6 +33,7 @@
var/busy = 0
var/on_open_network = 0
var/always_visible = FALSE //Visable from any map, good for entertainment network cameras
var/affected_by_emp_until = 0
@@ -467,6 +468,7 @@
cam["name"] = sanitize(c_tag)
cam["deact"] = !can_use()
cam["camera"] = "\ref[src]"
cam["omni"] = always_visible
cam["x"] = x
cam["y"] = y
cam["z"] = z
+1
View File
@@ -102,6 +102,7 @@ var/global/list/engineering_networks = list(
/obj/machinery/camera/network/thunder
network = list(NETWORK_THUNDER)
invuln = 1
always_visible = TRUE
// EMP
+5 -5
View File
@@ -43,11 +43,14 @@
data["current_camera"] = current_camera ? current_camera.nano_structure() : null
data["current_network"] = current_network
data["networks"] = network ? network : list()
var/map_levels = using_map.get_map_levels(src.z, TRUE)
data["map_levels"] = map_levels
if(current_network)
data["cameras"] = camera_repository.cameras_in_network(current_network)
data["cameras"] = camera_repository.cameras_in_network(current_network, map_levels)
if(current_camera)
switch_to_camera(user, current_camera)
data["map_levels"] = using_map.get_map_levels(src.z)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
@@ -91,9 +94,6 @@
. = ..()
/obj/machinery/computer/security/attack_hand(var/mob/user as mob)
if (using_map && !(src.z in using_map.contact_levels))
to_chat(user, "<span class='danger'>Unable to establish a connection:</span> You're too far away from the station!")
return
if(stat & (NOPOWER|BROKEN)) return
if(!isAI(user))
@@ -544,7 +544,7 @@
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
switch(command)
@@ -121,7 +121,7 @@ var/prison_shuttle_timeleft = 0
if(!frequency) return
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
frequency.post_signal(src, status_signal)
return
+1 -1
View File
@@ -421,7 +421,7 @@
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
frequency.post_signal(src, status_signal)
+2 -1
View File
@@ -215,6 +215,7 @@
var/on_enter_occupant_message = "You feel cool air surround you. You go numb as your senses turn inward."
var/on_store_visible_message_1 = "hums and hisses as it moves" //We need two variables because byond doesn't let us have variables inside strings at compile-time.
var/on_store_visible_message_2 = "into storage."
var/announce_channel = "Common"
var/allow_occupant_types = list(/mob/living/carbon/human)
var/disallow_occupant_types = list()
@@ -467,7 +468,7 @@
control_computer._admin_logs += "[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) at [stationtime2text()]"
log_and_message_admins("[key_name(to_despawn)] ([to_despawn.mind.role_alt_title]) entered cryostorage.")
announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]")
announce.autosay("[to_despawn.real_name], [to_despawn.mind.role_alt_title], [on_store_message]", "[on_store_name]", announce_channel, using_map.get_map_levels(z, TRUE))
//visible_message("<span class='notice'>\The [initial(name)] hums and hisses as it moves [to_despawn.real_name] into storage.</span>", 3)
visible_message("<span class='notice'>\The [initial(name)] [on_store_visible_message_1] [to_despawn.real_name] [on_store_visible_message_2].</span>", 3)
+4 -4
View File
@@ -91,7 +91,7 @@ obj/machinery/door/airlock/proc/command_completed(var/command)
obj/machinery/door/airlock/proc/send_status(var/bumped = 0)
if(radio_connection)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = id_tag
signal.data["timestamp"] = world.time
@@ -172,7 +172,7 @@ obj/machinery/airlock_sensor/update_icon()
obj/machinery/airlock_sensor/attack_hand(mob/user)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = master_tag
signal.data["command"] = command
@@ -186,7 +186,7 @@ obj/machinery/airlock_sensor/process()
if(abs(pressure - previousPressure) > 0.001 || previousPressure == null)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = id_tag
signal.data["timestamp"] = world.time
signal.data["pressure"] = num2text(pressure)
@@ -263,7 +263,7 @@ obj/machinery/access_button/attack_hand(mob/user)
else if(radio_connection)
var/datum/signal/signal = new
signal.transmission_method = 1 //radio signal
signal.transmission_method = TRANSMISSION_RADIO //radio signal
signal.data["tag"] = master_tag
signal.data["command"] = command
+2 -2
View File
@@ -275,7 +275,7 @@
// Prepare signal beforehand, because this is a radio operation
var/datum/signal/signal = new
signal.transmission_method = 1 // radio transmission
signal.transmission_method = TRANSMISSION_RADIO // radio transmission
signal.source = src
signal.frequency = frequency
signal.data["code"] = code
@@ -341,7 +341,7 @@
// Prepare the radio signal
var/datum/signal/signal = new
signal.transmission_method = 1 // radio transmission
signal.transmission_method = TRANSMISSION_RADIO // radio transmission
signal.source = src
signal.frequency = frequency
signal.data["code"] = code
+156 -44
View File
@@ -23,6 +23,12 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
produces_heat = 0
delay = 7
circuit = /obj/item/weapon/circuitboard/telecomms/broadcaster
//Vars only used if you're using the overmap
var/overmap_range = 0
var/overmap_range_min = 0
var/overmap_range_max = 5
//Linked bluespace radios
var/list/linked_radios_weakrefs = list()
/obj/machinery/telecomms/processor/Initialize()
. = ..()
@@ -34,6 +40,11 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
component_parts += new /obj/item/weapon/stock_parts/micro_laser/high(src)
component_parts += new /obj/item/stack/cable_coil(src, 1)
/obj/machinery/telecomms/broadcaster/proc/link_radio(var/obj/item/device/radio/R)
if(!istype(R))
return
linked_radios_weakrefs |= weakref(R)
/obj/machinery/telecomms/broadcaster/receive_information(datum/signal/signal, obj/machinery/telecomms/machine_from)
// Don't broadcast rejected signals
if(signal.data["reject"])
@@ -58,46 +69,50 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
signal.data["level"] |= listening_level
signal.data["level"] |= using_map.get_map_levels(listening_level, TRUE, overmap_range)
var/list/forced_radios
for(var/weakref/wr in linked_radios_weakrefs)
var/obj/item/device/radio/R = wr.resolve()
if(istype(R))
LAZYDISTINCTADD(forced_radios, R)
/** #### - Normal Broadcast - #### **/
if(signal.data["type"] == 0)
if(signal.data["type"] == SIGNAL_NORMAL)
/* ###### Broadcast a message using signal.data ###### */
Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"],,
signal.data["realname"], signal.data["vname"], DATA_NORMAL,
signal.data["compression"], signal.data["level"], signal.frequency,
signal.data["verb"])
signal.data["verb"], forced_radios)
/** #### - Simple Broadcast - #### **/
if(signal.data["type"] == 1)
if(signal.data["type"] == SIGNAL_SIMPLE)
/* ###### Broadcast a message using signal.data ###### */
Broadcast_SimpleMessage(signal.data["name"], signal.frequency,
signal.data["message"],null, null,
signal.data["compression"], listening_level)
signal.data["message"], DATA_NORMAL, null,
signal.data["compression"], listening_level, forced_radios)
/** #### - Artificial Broadcast - #### **/
// (Imitates a mob)
if(signal.data["type"] == 2)
if(signal.data["type"] == SIGNAL_FAKE)
/* ###### Broadcast a message using signal.data ###### */
// Parameter "data" as 4: AI can't track this person/mob
// Parameter "data" as DATA_FAKE: AI can't track this person/mob
Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency,
signal.data["verb"])
signal.data["realname"], signal.data["vname"], DATA_FAKE,
signal.data["compression"], signal.data["level"], signal.frequency,
signal.data["verb"], forced_radios)
if(!message_delay)
message_delay = 1
@@ -118,6 +133,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/*
Basically just an empty shell for receiving and broadcasting radio messages. Not
very flexible, but it gets the job done.
NOTE: This AIO device listens on *every* zlevel (it does not even check)
*/
/obj/machinery/telecomms/allinone
@@ -126,15 +142,98 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
icon_state = "comm_server"
desc = "A compact machine used for portable subspace telecommuniations processing."
density = 1
use_power = USE_POWER_IDLE
idle_power_usage = 20
anchored = 1
use_power = USE_POWER_OFF
idle_power_usage = 0
machinetype = 6
produces_heat = 0
var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel
var/overmap_range = 0 //Same turf
var/list/linked_radios_weakrefs = list()
/obj/machinery/telecomms/allinone/proc/link_radio(var/obj/item/device/radio/R)
if(!istype(R))
return
linked_radios_weakrefs |= weakref(R)
/obj/machinery/telecomms/allinone/receive_signal(datum/signal/signal)
// Has to be on to receive messages
if(!on)
return
// Why did you use this subtype?
if(!using_map.use_overmap)
return
// Someone else handling it?
if(signal.data["done"])
return
// Where are we able to hear from (and talk to, since we're AIO) anyway?
var/map_levels = using_map.get_map_levels(z, TRUE, overmap_range)
//Bluespace can skip this check
if(signal.transmission_method != TRANSMISSION_BLUESPACE)
var/list/signal_levels = list()
signal_levels += signal.data["level"] //If it's text/number, it'll be the only entry, if it's a list, it'll get combined
var/list/overlap = map_levels & signal_levels //Returns a list of similar levels
if(!overlap.len)
return
if(is_freq_listening(signal)) // detect subspace signals
signal.data["done"] = 1 // mark the signal as being broadcasted since we're a broadcaster
signal.data["compression"] = 0 // decompress since we're a processor
// Search for the original signal and mark it as done as well
var/datum/signal/original = signal.data["original"]
if(original)
original.data["done"] = 1
// For some reason level is both used as a list and not a list, and now it needs to be a list.
signal.data["level"] = map_levels
if(signal.data["slow"] > 0)
sleep(signal.data["slow"]) // simulate the network lag if necessary
/* ###### Broadcast a message using signal.data ###### */
var/datum/radio_frequency/connection = signal.data["connection"]
var/list/forced_radios
for(var/weakref/wr in linked_radios_weakrefs)
var/obj/item/device/radio/R = wr.resolve()
if(istype(R))
LAZYDISTINCTADD(forced_radios, R)
Broadcast_Message(
signal.data["connection"],
signal.data["mob"],
signal.data["vmask"],
signal.data["vmessage"],
signal.data["radio"],
signal.data["message"],
signal.data["name"],
signal.data["job"],
signal.data["realname"],
signal.data["vname"],
DATA_NORMAL,
signal.data["compression"],
signal.data["level"],
connection.frequency,
signal.data["verb"],
signal.data["language"],
forced_radios
)
//Antag version with unlimited range (doesn't even check) and uses no power, to enable antag comms to work anywhere.
/obj/machinery/telecomms/allinone/antag
use_power = USE_POWER_OFF
idle_power_usage = 0
/obj/machinery/telecomms/allinone/antag/receive_signal(datum/signal/signal)
if(!on) // has to be on to receive messages
return
@@ -159,23 +258,29 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/datum/radio_frequency/connection = signal.data["connection"]
var/list/forced_radios
for(var/weakref/wr in linked_radios_weakrefs)
var/obj/item/device/radio/R = wr.resolve()
if(istype(R))
LAZYDISTINCTADD(forced_radios, R)
if(connection.frequency in ANTAG_FREQS) // if antag broadcast, just
Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency,
signal.data["verb"])
signal.data["realname"], signal.data["vname"], DATA_NORMAL,
signal.data["compression"], list(0), connection.frequency,
signal.data["verb"], forced_radios)
else
if(intercept)
Broadcast_Message(signal.data["connection"], signal.data["mob"],
signal.data["vmask"], signal.data["vmessage"],
signal.data["radio"], signal.data["message"],
signal.data["name"], signal.data["job"],
signal.data["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency,
signal.data["verb"])
signal.data["realname"], signal.data["vname"], DATA_ANTAG,
signal.data["compression"], list(0), connection.frequency,
signal.data["verb"], forced_radios)
/**
@@ -237,8 +342,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/proc/Broadcast_Message(var/datum/radio_frequency/connection, var/mob/M,
var/vmask, var/list/vmessage_pieces, var/obj/item/device/radio/radio,
var/list/message_pieces, var/name, var/job, var/realname, var/vname,
var/data, var/compression, var/list/level, var/freq, var/verbage = "says")
var/data, var/compression, var/list/level, var/freq, var/verbage = "says",
var/list/forced_radios)
/* ###### Prepare the radio connection ###### */
@@ -246,17 +351,22 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/list/obj/item/device/radio/radios = list()
for(var/obj/item/device/radio/R in forced_radios)
//Cursory check to ensure they are 'on' and stuff
if(R.receive_range(display_freq, list(0)))
radios |= R
// --- Broadcast only to intercom devices ---
if(data == 1)
if(data == DATA_INTERCOM)
for (var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"])
if(R.receive_range(display_freq, level) > -1)
radios += R
radios |= R
// --- Broadcast only to intercoms and station-bounced radios ---
else if(data == 2)
else if(data == DATA_LOCAL)
for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
@@ -264,16 +374,16 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
continue
if(R.receive_range(display_freq, level) > -1)
radios += R
radios |= R
// --- Broadcast to antag radios! ---
else if(data == 3)
else if(data == DATA_ANTAG)
for(var/antag_freq in ANTAG_FREQS)
var/datum/radio_frequency/antag_connection = radio_controller.return_frequency(antag_freq)
for (var/obj/item/device/radio/R in antag_connection.devices["[RADIO_CHAT]"])
if(R.receive_range(antag_freq, level) > -1)
radios += R
radios |= R
// --- Broadcast to ALL radio devices ---
@@ -281,7 +391,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
if(R.receive_range(display_freq, level) > -1)
radios += R
radios |= R
// Get a list of mobs who can hear from the radios we collected.
var/list/receive = get_mobs_in_radio_ranges(radios)
@@ -307,7 +417,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
continue
// Ghosts hearing all radio chat don't want to hear syndicate intercepts, they're duplicates
if(data == 3 && istype(R, /mob/observer/dead) && R.is_preference_enabled(/datum/client_preference/ghost_radio))
if(data == DATA_ANTAG && istype(R, /mob/observer/dead) && R.is_preference_enabled(/datum/client_preference/ghost_radio))
continue
// --- Check for compression ---
@@ -346,7 +456,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/freq_text = get_frequency_name(display_freq)
var/part_b_extra = ""
if(data == 3) // intercepted radio message
if(data == DATA_ANTAG) // intercepted radio message
part_b_extra = " <i>(Intercepted)</i>"
var/part_a = "<span class='[frequency_span_class(display_freq)]'>[bicon(radio)]<b>\[[freq_text]\][part_b_extra]</b> <span class='name'>" // goes in the actual output
@@ -429,7 +539,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
return 1
/proc/Broadcast_SimpleMessage(var/source, var/frequency, list/message_pieces, var/data, var/mob/M, var/compression, var/level)
/proc/Broadcast_SimpleMessage(var/source, var/frequency, list/message_pieces, var/data, var/mob/M, var/compression, var/level, var/list/forced_radios)
var/text = multilingual_to_message(message_pieces)
/* ###### Prepare the radio connection ###### */
@@ -443,10 +553,12 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
var/list/receive = list()
for(var/obj/item/device/radio/R in forced_radios)
receive |= R.send_hear(display_freq)
// --- Broadcast only to intercom devices ---
if(data == 1)
if(data == DATA_INTERCOM)
for (var/obj/item/device/radio/intercom/R in connection.devices["[RADIO_CHAT]"])
var/turf/position = get_turf(R)
if(position && position.z == level)
@@ -455,7 +567,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Broadcast only to intercoms and station-bounced radios ---
else if(data == 2)
else if(data == DATA_LOCAL)
for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"])
if(istype(R, /obj/item/device/radio/headset))
@@ -467,7 +579,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Broadcast to antag radios! ---
else if(data == 3)
else if(data == DATA_ANTAG)
for(var/freq in ANTAG_FREQS)
var/datum/radio_frequency/antag_connection = radio_controller.return_frequency(freq)
for (var/obj/item/device/radio/R in antag_connection.devices["[RADIO_CHAT]"])
@@ -532,7 +644,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
// --- Some more pre-message formatting ---
var/part_b_extra = ""
if(data == 3) // intercepted radio message
if(data == DATA_ANTAG) // intercepted radio message
part_b_extra = " <i>(Intercepted)</i>"
// Create a radio headset for the sole purpose of using its icon
@@ -608,15 +720,15 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
/atom/proc/test_telecomms()
var/datum/signal/signal = src.telecomms_process()
var/turf/position = get_turf(src)
return (position.z in signal.data["level"] && signal.data["done"])
var/pos_z = get_z(src)
return (pos_z in signal.data["level"] && signal.data["done"])
/atom/proc/telecomms_process(var/do_sleep = 1)
// First, we want to generate a new radio signal
var/datum/signal/signal = new
signal.transmission_method = 2 // 2 would be a subspace transmission.
var/turf/pos = get_turf(src)
signal.transmission_method = TRANSMISSION_SUBSPACE
var/pos_z = get_z(src)
// --- Finally, tag the actual signal with the appropriate values ---
signal.data = list(
@@ -624,10 +736,10 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
"message" = "TEST",
"compression" = rand(45, 50), // If the signal is compressed, compress our message too.
"traffic" = 0, // dictates the total traffic sum that the signal went through
"type" = 4, // determines what type of radio input it is: test broadcast
"type" = SIGNAL_TEST, // determines what type of radio input it is: test broadcast
"reject" = 0,
"done" = 0,
"level" = pos.z // The level it is being broadcasted at.
"level" = pos_z // The level it is being broadcasted at.
)
signal.frequency = PUB_FREQ// Common channel
@@ -219,6 +219,38 @@
temp = "<font color = #666633>-% Frequency changing deactivated %-</font>"
// BROADCASTER
/obj/machinery/telecomms/broadcaster/Options_Menu()
// Note the machine 'displays' 1 higher than overmap_range to save users from the abstraction that range '0' is valid and everything on the same turf.
var/dat = "<br>Broadcast Range (affects power usage)<br><a href='?src=\ref[src];range_down=1'>-</a> [overmap_range+1] gigameter\s <a href='?src=\ref[src];range_up=1'>+</a>"
return dat
/obj/machinery/telecomms/broadcaster/Options_Topic(href, href_list)
if(href_list["range_down"])
if(overmap_range > overmap_range_min)
overmap_range--
idle_power_usage = initial(idle_power_usage)**(overmap_range+1)
if(href_list["range_up"])
if(overmap_range < overmap_range_max)
overmap_range++
idle_power_usage = initial(idle_power_usage)**(overmap_range+1)
// RECEIVER
/obj/machinery/telecomms/receiver/Options_Menu()
// Note the machine 'displays' 1 higher than overmap_range to save users from the abstraction that range '0' is valid and everything on the same turf.
var/dat = "<br>Receive Range (affects power usage)<br><a href='?src=\ref[src];range_down=1'>-</a> [overmap_range+1] gigameter\s <a href='?src=\ref[src];range_up=1'>+</a>"
return dat
/obj/machinery/telecomms/receiver/Options_Topic(href, href_list)
if(href_list["range_down"])
if(overmap_range > overmap_range_min)
overmap_range--
idle_power_usage = initial(idle_power_usage)**(overmap_range+1)
if(href_list["range_up"])
if(overmap_range < overmap_range_max)
overmap_range++
idle_power_usage = initial(idle_power_usage)**(overmap_range+1)
/obj/machinery/telecomms/Topic(href, href_list)
if(!issilicon(usr))
@@ -68,7 +68,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
var/datum/signal/copy
if(copysig)
copy = new
copy.transmission_method = 2
copy.transmission_method = TRANSMISSION_SUBSPACE
copy.frequency = signal.frequency
copy.data = signal.data.Copy()
@@ -141,9 +141,9 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
// Used in auto linking
/obj/machinery/telecomms/proc/add_link(var/obj/machinery/telecomms/T)
var/turf/position = get_turf(src)
var/turf/T_position = get_turf(T)
if((position.z == T_position.z) || (src.long_range_link && T.long_range_link))
var/pos_z = get_z(src)
var/tpos_z = get_z(T)
if((pos_z == tpos_z) || (src.long_range_link && T.long_range_link))
for(var/x in autolinkers)
if(T.autolinkers.Find(x))
if(src != T)
@@ -256,6 +256,12 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
machinetype = 1
produces_heat = 0
circuit = /obj/item/weapon/circuitboard/telecomms/receiver
//Vars only used if you're using the overmap
var/overmap_range = 0
var/overmap_range_min = 0
var/overmap_range_max = 5
var/list/linked_radios_weakrefs = list()
/obj/machinery/telecomms/receiver/Initialize()
. = ..()
@@ -267,8 +273,12 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
component_parts += new /obj/item/weapon/stock_parts/micro_laser(src)
RefreshParts()
/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal)
/obj/machinery/telecomms/receiver/proc/link_radio(var/obj/item/device/radio/R)
if(!istype(R))
return
linked_radios_weakrefs |= weakref(R)
/obj/machinery/telecomms/receiver/receive_signal(datum/signal/signal)
if(!on) // has to be on to receive messages
return
if(!signal)
@@ -276,7 +286,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
if(!check_receive_level(signal))
return
if(signal.transmission_method == 2)
if(signal.transmission_method == TRANSMISSION_SUBSPACE)
if(is_freq_listening(signal)) // detect subspace signals
@@ -288,14 +298,31 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
relay_information(signal, "/obj/machinery/telecomms/bus") // Send it to a bus instead, if it's linked to one
/obj/machinery/telecomms/receiver/proc/check_receive_level(datum/signal/signal)
// If it's a direct message from a bluespace radio, we eat it and convert it into a subspace signal locally
if(signal.transmission_method == TRANSMISSION_BLUESPACE)
var/obj/item/device/radio/R = signal.data["radio"]
if(signal.data["level"] != listening_level)
//Who're you?
if(!(weakref(R) in linked_radios_weakrefs))
signal.data["reject"] = 1
return 0
//We'll resend this for you
signal.data["level"] = z
signal.transmission_method = TRANSMISSION_SUBSPACE
return 1
//Where can we hear?
var/list/listening_levels = using_map.get_map_levels(listening_level, TRUE, overmap_range)
// We couldn't 'hear' it, maybe a relay linked to our hub can 'hear' it
if(!(signal.data["level"] in listening_levels))
for(var/obj/machinery/telecomms/hub/H in links)
var/list/connected_levels = list()
var/list/relayed_levels = list()
for(var/obj/machinery/telecomms/relay/R in H.links)
if(R.can_receive(signal))
connected_levels |= R.listening_level
if(signal.data["level"] in connected_levels)
relayed_levels |= R.listening_level
if(signal.data["level"] in relayed_levels)
return 1
return 0
return 1
@@ -405,7 +432,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
// Add our level and send it back
if(can_send(signal))
signal.data["level"] |= listening_level
signal.data["level"] |= using_map.get_map_levels(listening_level)
// Checks to see if it can send/receive.
@@ -601,7 +628,7 @@ var/global/list/obj/machinery/telecomms/telecomms_list = list()
totaltraffic += traffic // add current traffic to total traffic
//Is this a test signal? Bypass logging
if(signal.data["type"] != 4)
if(signal.data["type"] != SIGNAL_TEST)
// If signal has a message and appropriate frequency
+1 -1
View File
@@ -256,7 +256,7 @@ var/list/civilian_cartridges = list(
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
switch(command)
+1 -1
View File
@@ -22,7 +22,7 @@
var/datum/signal/signal = new()
signal.source = src
signal.transmission_method = 1
signal.transmission_method = TRANSMISSION_RADIO
signal.data[key] = value
if(key2)
signal.data[key2] = value2
@@ -329,7 +329,7 @@
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
switch(command)
+1 -1
View File
@@ -83,7 +83,7 @@ var/list/GPS_list = list()
dat["curr_z_name"] = using_map.get_zlevel_name(curr.z)
dat["gps_list"] = list()
dat["z_level_detection"] = using_map.get_map_levels(curr.z, long_range)
for(var/obj/item/device/gps/G in GPS_list - src)
if(!G.tracking || G.emped || G.hide_signal)
continue
+143 -123
View File
@@ -49,6 +49,13 @@ var/global/list/default_medbay_channels = list(
w_class = ITEMSIZE_SMALL
show_messages = 1
// Bluespace radios talk directly to telecomms equipment
var/bluespace_radio = FALSE
var/weakref/bs_tx_weakref //Maybe misleading, this is the device to TRANSMIT TO
// For mappers or subtypes, to start them prelinked to these devices
var/bs_tx_preload_id
var/bs_rx_preload_id
matter = list("glass" = 25,DEFAULT_WALL_MATERIAL = 75)
var/const/FREQ_LISTENING = 1
var/list/internal_channels
@@ -87,6 +94,43 @@ var/global/list/default_medbay_channels = list(
for (var/ch_name in channels)
secure_radio_connections[ch_name] = radio_controller.add_object(src, radiochannels[ch_name], RADIO_CHAT)
if(bluespace_radio)
if(bs_tx_preload_id)
//Try to find a receiver
for(var/obj/machinery/telecomms/receiver/RX in telecomms_list)
if(RX.id == bs_tx_preload_id) //Again, bs_tx is the thing to TRANSMIT TO, so a receiver.
bs_tx_weakref = weakref(RX)
RX.link_radio(src)
break
//Hmm, howabout an AIO machine
if(!bs_tx_weakref)
for(var/obj/machinery/telecomms/allinone/AIO in telecomms_list)
if(AIO.id == bs_tx_preload_id)
bs_tx_weakref = weakref(AIO)
AIO.link_radio(src)
break
if(!bs_tx_weakref)
testing("A radio [src] at [x],[y],[z] specified bluespace prelink IDs, but the machines with corresponding IDs ([bs_tx_preload_id], [bs_rx_preload_id]) couldn't be found.")
if(bs_rx_preload_id)
var/found = 0
//Try to find a transmitter
for(var/obj/machinery/telecomms/broadcaster/TX in telecomms_list)
if(TX.id == bs_rx_preload_id) //Again, bs_rx is the thing to RECEIVE FROM, so a transmitter.
TX.link_radio(src)
found = 1
break
//Hmm, howabout an AIO machine
if(!found)
for(var/obj/machinery/telecomms/allinone/AIO in telecomms_list)
if(AIO.id == bs_rx_preload_id)
AIO.link_radio(src)
found = 1
break
if(!found)
testing("A radio [src] at [x],[y],[z] specified bluespace prelink IDs, but the machines with corresponding IDs ([bs_tx_preload_id], [bs_rx_preload_id]) couldn't be found.")
/obj/item/device/radio/attack_self(mob/user as mob)
user.set_machine(src)
interact(user)
@@ -237,11 +281,10 @@ var/global/list/default_medbay_channels = list(
if(.)
SSnanoui.update_uis(src)
/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel) //BS12 EDIT
/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel, var/list/zlevels) //BS12 EDIT
var/datum/radio_frequency/connection = null
if(channel && channels && channels.len > 0)
if(channel == "department")
//to_world("DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\"")
channel = channels[1]
connection = secure_radio_connections[channel]
else
@@ -250,12 +293,15 @@ var/global/list/default_medbay_channels = list(
if(!istype(connection))
return
if(!LAZYLEN(zlevels))
zlevels = list(0)
var/static/mob/living/silicon/ai/announcer/A = new /mob/living/silicon/ai/announcer(src, null, null, 1)
A.SetName(from)
Broadcast_Message(connection, A,
0, "*garbled automated announcement*", src,
message_to_multilingual(message), from, "Automated Announcement", from, "synthesized voice",
4, 0, list(0), connection.frequency, "states")
DATA_FAKE, 0, zlevels, connection.frequency, "states")
// Interprets the message mode when talking into a radio, possibly returning a connection datum
/obj/item/device/radio/proc/handle_message_mode(mob/living/M as mob, list/message_pieces, message_mode)
@@ -313,8 +359,8 @@ var/global/list/default_medbay_channels = list(
if(!istype(message_mode, /datum/radio_frequency)) //if not a special case, it should be returning a radio connection
return FALSE
var/pos_z = get_z(src)
var/datum/radio_frequency/connection = message_mode
var/turf/position = get_turf(src)
//#### Tagging the signal with all appropriate identity values ####//
@@ -363,90 +409,12 @@ var/global/list/default_medbay_channels = list(
jobname = "Unknown"
voicemask = 1
/* ###### Radio headsets can only broadcast through subspace ###### */
if(subspace_transmission)
var/list/jamming = is_jammed(src)
if(jamming)
var/distance = jamming["distance"]
to_chat(M, "<span class='danger'>[bicon(src)] You hear the [distance <= 2 ? "loud hiss" : "soft hiss"] of static.</span>")
return FALSE
// First, we want to generate a new radio signal
var/datum/signal/signal = new
signal.transmission_method = 2 // 2 would be a subspace transmission.
// transmission_method could probably be enumerated through #define. Would be neater.
// --- Finally, tag the actual signal with the appropriate values ---
signal.data = list(
// Identity-associated tags:
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
"name" = displayname, // the mob's display name
"job" = jobname, // the mob's job
"key" = mobkey, // the mob's key
"vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood
"vname" = M.voice_name, // the name to display if the voice wasn't understood
"vmask" = voicemask, // 1 if the mob is using a voice gas mask
// We store things that would otherwise be kept in the actual mob
// so that they can be logged even AFTER the mob is deleted or something
// Other tags:
"compression" = rand(45,50), // compressed radio signal
"message" = message_pieces, // the actual sent message
"connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission
"slow" = 0, // how much to sleep() before broadcasting - simulates net lag
"traffic" = 0, // dictates the total traffic sum that the signal went through
"type" = 0, // determines what type of radio input it is: normal broadcast
"server" = null, // the last server to log this signal
"reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
"level" = position.z, // The source's z level
"verb" = verb
)
signal.frequency = connection.frequency // Quick frequency set
//#### Sending the signal to all subspace receivers ####//
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
// Allinone can act as receivers.
for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
R.receive_signal(signal)
// Receiving code can be located in Telecommunications.dm
if(signal.data["done"] && position.z in signal.data["level"])
return TRUE //Huzzah, sent via subspace
else if(adhoc_fallback) //Less huzzah, we have to fallback
to_chat(loc, "<span class='warning'>\The [src] pings as it falls back to local radio transmission.</span>")
subspace_transmission = FALSE
return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
src, message_pieces, displayname, jobname, real_name, M.voice_name,
signal.transmission_method, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency,verb)
/* ###### Intercoms and station-bounced radios ###### */
var/filter_type = 2
/* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
if(istype(src, /obj/item/device/radio/intercom))
filter_type = 1
// First, we want to generate a new radio signal
var/datum/signal/signal = new
signal.transmission_method = 2
/* --- Try to send a normal subspace broadcast first */
// --- Finally, tag the actual signal with the appropriate values ---
signal.data = list(
// Identity-associated tags:
"mob" = M, // store a reference to the mob
"mobtype" = M.type, // the mob's type
"realname" = real_name, // the mob's real name
@@ -455,40 +423,107 @@ var/global/list/default_medbay_channels = list(
"key" = mobkey, // the mob's key
"vmessage" = pick(M.speak_emote), // the message to display if the voice wasn't understood
"vname" = M.voice_name, // the name to display if the voice wasn't understood
"vmask" = voicemask, // 1 if the mob is using a voice gas mas
"vmask" = voicemask, // 1 if the mob is using a voice gas mask
"compression" = 0, // uncompressed radio signal
// We store things that would otherwise be kept in the actual mob
// so that they can be logged even AFTER the mob is deleted or something
// Other tags:
"compression" = rand(45,50), // compressed radio signal
"message" = message_pieces, // the actual sent message
"connection" = connection, // the radio connection to use
"radio" = src, // stores the radio used for transmission
"slow" = 0,
"traffic" = 0,
"type" = 0,
"server" = null,
"reject" = 0,
"level" = position.z,
"slow" = 0, // how much to sleep() before broadcasting - simulates net lag
"traffic" = 0, // dictates the total traffic sum that the signal went through
"type" = SIGNAL_NORMAL, // determines what type of radio input it is: normal broadcast
"server" = null, // the last server to log this signal
"reject" = 0, // if nonzero, the signal will not be accepted by any broadcasting machinery
"level" = pos_z, // The source's z level
"verb" = verb
)
signal.frequency = connection.frequency // Quick frequency set
var/filter_type = DATA_LOCAL //If we end up having to send it the old fashioned way, it's with this data var.
/* ###### Bluespace radios talk directly to receivers (and only directly to receivers) ###### */
if(bluespace_radio)
//Nothing to transmit to
if(!bs_tx_weakref)
to_chat(loc, "<span class='warning'>\The [src] buzzes to inform you of the lack of a functioning connection.</span>")
return FALSE
var/obj/machinery/telecomms/tx_to = bs_tx_weakref.resolve()
//Was linked, now destroyed or something
if(!tx_to)
bs_tx_weakref = null
to_chat(loc, "<span class='warning'>\The [src] buzzes to inform you of the lack of a functioning connection.</span>")
return FALSE
//Transmitted in the blind. If we get a message back, cool. If not, oh well.
signal.transmission_method = TRANSMISSION_BLUESPACE
return tx_to.receive_signal(signal)
/* ###### Radios with subspace_transmission can only broadcast through subspace (unless they have adhoc_fallback) ###### */
else if(subspace_transmission)
var/list/jamming = is_jammed(src)
if(jamming)
var/distance = jamming["distance"]
to_chat(M, "<span class='danger'>[bicon(src)] You hear the [distance <= 2 ? "loud hiss" : "soft hiss"] of static.</span>")
return FALSE
// First, we want to generate a new radio signal
signal.transmission_method = TRANSMISSION_SUBSPACE
//#### Sending the signal to all subspace receivers ####//
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
// Allinone can act as receivers.
for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
R.receive_signal(signal)
// Receiving code can be located in Telecommunications.dm
if(signal.data["done"] && (pos_z in signal.data["level"]))
return TRUE //Huzzah, sent via subspace
else if(adhoc_fallback) //Less huzzah, we have to fallback
to_chat(loc, "<span class='warning'>\The [src] pings as it falls back to local radio transmission.</span>")
subspace_transmission = FALSE
else //Oh well
return FALSE
/* ###### Intercoms and station-bounced radios ###### */
else
/* --- Intercoms can only broadcast to other intercoms, but bounced radios can broadcast to bounced radios and intercoms --- */
if(istype(src, /obj/item/device/radio/intercom))
filter_type = DATA_INTERCOM
/* --- Try to send a normal subspace broadcast first */
signal.transmission_method = TRANSMISSION_SUBSPACE
signal.data["compression"] = 0
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
// Allinone can act as receivers.
for(var/obj/machinery/telecomms/allinone/R in telecomms_list)
R.receive_signal(signal)
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
R.receive_signal(signal)
if(signal.data["done"] && position.z in signal.data["level"])
if(adhoc_fallback)
to_chat(loc, "<span class='notice'>\The [src] pings as it reestablishes subspace communications.</span>")
subspace_transmission = TRUE
// we're done here.
return TRUE
if(signal.data["done"] && pos_z in signal.data["level"])
if(adhoc_fallback)
to_chat(loc, "<span class='notice'>\The [src] pings as it reestablishes subspace communications.</span>")
subspace_transmission = TRUE
// we're done here.
return TRUE
// Oh my god; the comms are down or something because the signal hasn't been broadcasted yet in our level.
// Send a mundane broadcast with limited targets:
//THIS IS TEMPORARY. YEAH RIGHT
if(!connection) return FALSE //~Carn
//Nothing handled any sort of remote radio-ing and returned before now, just squawk on this zlevel.
return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
src, message_pieces, displayname, jobname, real_name, M.voice_name,
filter_type, signal.data["compression"], GetConnectedZlevels(position.z), connection.frequency, verb)
src, message_pieces, displayname, jobname, real_name, M.voice_name,
filter_type, signal.data["compression"], using_map.get_map_levels(pos_z), connection.frequency, verb)
/obj/item/device/radio/hear_talk(mob/M, list/message_pieces, verb)
@@ -496,25 +531,10 @@ var/global/list/default_medbay_channels = list(
if(get_dist(src, M) <= canhear_range)
talk_into(M, message_pieces, null, verb)
/*
/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)
if((R.frequency == frequency && message))
return TRUE
else if
else
return null
return
*/
/obj/item/device/radio/proc/receive_range(freq, level)
// check if this radio can receive on the given frequency, and if so,
// what the range is in which mobs will hear the radio
// returns: -1 if can't receive, range otherwise
if(wires.IsIndexCut(WIRE_RECEIVE))
return -1
if(!listening)
@@ -522,8 +542,8 @@ var/global/list/default_medbay_channels = list(
if(is_jammed(src))
return -1
if(!(0 in level))
var/turf/position = get_turf(src)
if(!position || !(position.z in level))
var/pos_z = get_z(src)
if(!(pos_z in level))
return -1
if(freq in ANTAG_FREQS)
if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys
@@ -0,0 +1,153 @@
/obj/item/device/bluespaceradio
name = "bluespace radio"
desc = "A powerful radio that uses a tiny bluespace wormhole to send signals directly to subspace receivers and transmitters, bypassing the limitations of subspace."
icon = 'icons/obj/radio.dmi'
icon_state = "radiopack"
item_state = "radiopack"
slot_flags = SLOT_BACK
force = 5
throwforce = 6
preserve_item = 1
w_class = ITEMSIZE_LARGE
action_button_name = "Remove/Replace Handset"
var/obj/item/device/radio/bluespacehandset/linked/handset = /obj/item/device/radio/bluespacehandset/linked
/obj/item/device/bluespaceradio/Initialize()
. = ..()
if(ispath(handset))
handset = new handset(src, src)
/obj/item/device/bluespaceradio/Destroy()
. = ..()
QDEL_NULL(handset)
/obj/item/device/bluespaceradio/ui_action_click()
toggle_handset()
/obj/item/device/bluespaceradio/attack_hand(var/mob/user)
if(loc == user)
toggle_handset()
else
..()
/obj/item/device/bluespaceradio/MouseDrop()
if(ismob(loc))
if(!CanMouseDrop(src))
return
var/mob/M = loc
if(!M.unEquip(src))
return
add_fingerprint(usr)
M.put_in_any_hand_if_possible(src)
/obj/item/device/bluespaceradio/attackby(var/obj/item/weapon/W, var/mob/user, var/params)
if(W == handset)
reattach_handset(user)
else
return ..()
/obj/item/device/bluespaceradio/verb/toggle_handset()
set name = "Toggle Handset"
set category = "Object"
var/mob/living/carbon/human/user = usr
if(!handset)
to_chat(user, "<span class='warning'>The handset is missing!</span>")
return
if(handset.loc != src)
reattach_handset(user) //Remove from their hands and back onto the defib unit
return
if(!slot_check())
to_chat(user, "<span class='warning'>You need to equip [src] before taking out [handset].</span>")
else
if(!usr.put_in_hands(handset)) //Detach the handset into the user's hands
to_chat(user, "<span class='warning'>You need a free hand to hold the handset!</span>")
update_icon() //success
//checks that the base unit is in the correct slot to be used
/obj/item/device/bluespaceradio/proc/slot_check()
var/mob/M = loc
if(!istype(M))
return 0 //not equipped
if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_back) == src)
return 1
if((slot_flags & SLOT_BACK) && M.get_equipped_item(slot_s_store) == src)
return 1
return 0
/obj/item/device/bluespaceradio/dropped(var/mob/user)
..()
reattach_handset(user) //handset attached to a base unit should never exist outside of their base unit or the mob equipping the base unit
/obj/item/device/bluespaceradio/proc/reattach_handset(var/mob/user)
if(!handset) return
if(ismob(handset.loc))
var/mob/M = handset.loc
if(M.drop_from_inventory(handset, src))
to_chat(user, "<span class='notice'>\The [handset] snaps back into the main unit.</span>")
else
handset.forceMove(src)
//Subspace Radio Handset
/obj/item/device/radio/bluespacehandset
name = "bluespace radio handset"
desc = "A large walkie talkie attached to the bluespace radio by a retractable cord. It sits comfortably on a slot in the radio when not in use."
bluespace_radio = TRUE
icon_state = "signaller"
slot_flags = null
w_class = ITEMSIZE_LARGE
canhear_range = 1
/obj/item/device/radio/bluespacehandset/linked
var/obj/item/device/bluespaceradio/base_unit
/obj/item/device/radio/bluespacehandset/linked/Initialize(mapload, var/obj/item/device/bluespaceradio/radio)
base_unit = radio
. = ..()
/obj/item/device/radio/bluespacehandset/linked/Destroy()
if(base_unit)
//ensure the base unit's icon updates
if(base_unit.handset == src)
base_unit.handset = null
base_unit = null
return ..()
/obj/item/device/radio/bluespacehandset/linked/dropped(var/mob/user)
..() //update twohanding
if(base_unit)
base_unit.reattach_handset(user) //handset attached to a base unit should never exist outside of their base unit or the mob equipping the base unit
/obj/item/device/radio/bluespacehandset/linked/receive_range(var/freq, var/list/level)
//Only care about megabroadcasts or things that are targeted at us
if(!(0 in level))
return -1
if(wires.IsIndexCut(WIRE_RECEIVE))
return -1
if(!listening)
return -1
if(is_jammed(src))
return -1
if (!on)
return -1
if (!freq) //recieved on main frequency
if (!listening)
return -1
else
var/accept = (freq==frequency && listening)
if (!accept)
for (var/ch_name in channels)
var/datum/radio_frequency/RF = secure_radio_connections[ch_name]
if (RF && RF.frequency==freq && (channels[ch_name]&FREQ_LISTENING))
accept = 1
break
if (!accept)
return -1
return canhear_range
+1 -1
View File
@@ -248,7 +248,7 @@ var/const/enterloopsanity = 100
/turf/proc/inertial_drift(atom/movable/A as mob|obj)
if(!(A.last_move)) return
if((istype(A, /mob/) && src.x > 2 && src.x < (world.maxx - 1) && src.y > 2 && src.y < (world.maxy-1)))
if((istype(A, /mob/) && src.x > 1 && src.x < (world.maxx) && src.y > 1 && src.y < (world.maxy)))
var/mob/M = A
if(M.Process_Spacemove(1))
M.inertia_dir = 0
+1 -1
View File
@@ -505,7 +505,7 @@ Traitors and the like can also be revived with the previous role mostly intact.
//If we're announcing their arrival
if(announce)
AnnounceArrival(new_character, new_character.mind.assigned_role)
AnnounceArrival(new_character, new_character.mind.assigned_role, "Common", new_character.z)
log_admin("[admin] has spawned [player_key]'s character [new_character.real_name].")
message_admins("[admin] has spawned [player_key]'s character [new_character.real_name].", 1)
+18 -11
View File
@@ -47,16 +47,17 @@
existing.clear(source)
return check_alarm_cleared(existing)
/datum/alarm_handler/proc/major_alarms()
return visible_alarms()
/datum/alarm_handler/proc/major_alarms(var/z)
return visible_alarms(z)
/datum/alarm_handler/proc/has_major_alarms()
if(alarms && alarms.len)
return 1
return 0
/datum/alarm_handler/proc/has_major_alarms(var/z)
if(!LAZYLEN(alarms))
return 0
/datum/alarm_handler/proc/minor_alarms()
return visible_alarms()
return LAZYLEN(major_alarms(z))
/datum/alarm_handler/proc/minor_alarms(var/z)
return visible_alarms(z)
/datum/alarm_handler/proc/check_alarm_cleared(var/datum/alarm/alarm)
if ((alarm.end_time && world.time > alarm.end_time) || !alarm.sources.len)
@@ -101,9 +102,15 @@
for(var/listener in listeners)
call(listener, listeners[listener])(src, alarm, was_raised)
/datum/alarm_handler/proc/visible_alarms()
/datum/alarm_handler/proc/visible_alarms(var/z)
if(!LAZYLEN(alarms))
return list()
var/list/map_levels = using_map.get_map_levels(z)
var/list/visible_alarms = new()
for(var/datum/alarm/A in alarms)
if(!A.hidden)
visible_alarms.Add(A)
if(A.hidden || (z && !(A.origin?.z in map_levels)))
continue
visible_alarms.Add(A)
return visible_alarms
+8 -2
View File
@@ -1,16 +1,22 @@
/datum/alarm_handler/atmosphere
category = "Atmosphere Alarms"
/datum/alarm_handler/atmosphere/major_alarms()
/datum/alarm_handler/atmosphere/major_alarms(var/z)
var/list/major_alarms = new()
var/list/map_levels = using_map.get_map_levels(z)
for(var/datum/alarm/A in visible_alarms())
if(z && !(A.origin?.z in map_levels))
continue
if(A.max_severity() > 1)
major_alarms.Add(A)
return major_alarms
/datum/alarm_handler/atmosphere/minor_alarms()
/datum/alarm_handler/atmosphere/minor_alarms(var/z)
var/list/minor_alarms = new()
var/list/map_levels = using_map.get_map_levels(z)
for(var/datum/alarm/A in visible_alarms())
if(z && !(A.origin?.z in map_levels))
continue
if(A.max_severity() == 1)
minor_alarms.Add(A)
return minor_alarms
+6 -4
View File
@@ -364,6 +364,7 @@
var/turf/T = join_props["turf"]
var/join_message = join_props["msg"]
var/announce_channel = join_props["channel"] || "Common"
if(!T || !join_message)
return 0
@@ -413,18 +414,19 @@
//Grab some data from the character prefs for use in random news procs.
AnnounceArrival(character, rank, join_message)
AnnounceArrival(character, rank, join_message, announce_channel, character.z)
else
AnnounceCyborg(character, rank, join_message)
AnnounceCyborg(character, rank, join_message, announce_channel, character.z)
qdel(src)
/mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message)
/mob/new_player/proc/AnnounceCyborg(var/mob/living/character, var/rank, var/join_message, var/channel, var/zlevel)
if (ticker.current_state == GAME_STATE_PLAYING)
var/list/zlevels = zlevel ? using_map.get_map_levels(zlevel, TRUE) : null
if(character.mind.role_alt_title)
rank = character.mind.role_alt_title
// can't use their name here, since cyborg namepicking is done post-spawn, so we'll just say "A new Cyborg has arrived"/"A new Android has arrived"/etc.
global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer")
global_announcer.autosay("A new[rank ? " [rank]" : " visitor" ] [join_message ? join_message : "has arrived on the station"].", "Arrivals Announcement Computer", channel, zlevels)
/mob/new_player/proc/LateChoices()
var/name = client.prefs.be_random_name ? "friend" : client.prefs.real_name
@@ -268,7 +268,7 @@
var/datum/signal/status_signal = new
status_signal.source = src
status_signal.transmission_method = 1
status_signal.transmission_method = TRANSMISSION_RADIO
status_signal.data["command"] = command
switch(command)
@@ -61,31 +61,35 @@
AH.unregister_alarm(object)
/datum/nano_module/alarm_monitor/proc/all_alarms()
var/z = get_z(nano_host())
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
all_alarms += AH.visible_alarms()
all_alarms += AH.visible_alarms(z)
return all_alarms
/datum/nano_module/alarm_monitor/proc/major_alarms()
var/z = get_z(nano_host())
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
all_alarms += AH.major_alarms()
all_alarms += AH.major_alarms(z)
return all_alarms
// Modified version of above proc that uses slightly less resources, returns 1 if there is a major alarm, 0 otherwise.
/datum/nano_module/alarm_monitor/proc/has_major_alarms()
var/z = get_z(nano_host())
for(var/datum/alarm_handler/AH in alarm_handlers)
if(AH.has_major_alarms())
if(AH.has_major_alarms(z))
return 1
return 0
/datum/nano_module/alarm_monitor/proc/minor_alarms()
var/z = get_z(nano_host())
var/list/all_alarms = new()
for(var/datum/alarm_handler/AH in alarm_handlers)
all_alarms += AH.minor_alarms()
all_alarms += AH.minor_alarms(z)
return all_alarms
@@ -104,9 +108,10 @@
var/list/data = host.initial_data()
var/categories[0]
var/z = get_z(nano_host())
for(var/datum/alarm_handler/AH in alarm_handlers)
categories[++categories.len] = list("category" = AH.category, "alarms" = list())
for(var/datum/alarm/A in AH.major_alarms())
for(var/datum/alarm/A in AH.major_alarms(z))
var/cameras[0]
var/lost_sources[0]
@@ -47,12 +47,17 @@
/datum/nano_module/atmos_control/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/master_ui = null, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
var/alarms[0]
var/turf/T = get_turf(nano_host())
var/z = get_z(nano_host())
var/list/map_levels = using_map.get_map_levels(z)
data["map_levels"] = map_levels
// TODO: Move these to a cache, similar to cameras
for(var/obj/machinery/alarm/alarm in (monitored_alarms.len ? monitored_alarms : machines))
if(!monitored_alarms.len && alarm.alarms_hidden)
continue
if(!(alarm.z in map_levels))
continue
alarms[++alarms.len] = list(
"name" = sanitize(alarm.name),
"ref"= "\ref[alarm]",
@@ -61,7 +66,6 @@
"y" = alarm.y,
"z" = alarm.z)
data["alarms"] = alarms
data["map_levels"] = using_map.get_map_levels(T.z)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if(!ui)
@@ -53,10 +53,15 @@
var/list/sensors = list()
// Focus: If it remains null if no sensor is selected and UI will display sensor list, otherwise it will display sensor reading.
var/obj/machinery/power/sensor/focus = null
var/turf/T = get_turf(nano_host())
var/z = get_z(nano_host())
var/list/map_levels = using_map.get_map_levels(z)
data["map_levels"] = map_levels
// Build list of data from sensor readings.
for(var/obj/machinery/power/sensor/S in grid_sensors)
if(!(S.z in map_levels))
continue
sensors.Add(list(list(
"name" = S.name_tag,
"alarm" = S.check_grid_warning()
@@ -67,7 +72,6 @@
data["all_sensors"] = sensors
if(focus)
data["focus"] = focus.return_reading_data()
data["map_levels"] = using_map.get_map_levels(T.z)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
@@ -122,11 +122,19 @@
// Description: Refreshes local list of known devices.
/datum/nano_module/rcon/proc/FindDevices()
known_SMESs = new /list()
var/z = get_z(nano_host())
var/list/map_levels = using_map.get_map_levels(z)
for(var/obj/machinery/power/smes/buildable/SMES in machines)
if(!(SMES.z in map_levels))
continue
if(SMES.RCon_tag && (SMES.RCon_tag != "NO_TAG") && SMES.RCon)
known_SMESs.Add(SMES)
known_breakers = new /list()
for(var/obj/machinery/power/breakerbox/breaker in machines)
if(!(breaker.z in map_levels))
continue
if(breaker.RCon_tag != "NO_TAG")
known_breakers.Add(breaker)
@@ -41,10 +41,10 @@
// Refreshes list of active supermatter crystals
/datum/nano_module/supermatter_monitor/proc/refresh()
supermatters = list()
var/turf/T = get_turf(nano_host())
if(!T)
var/z = get_z(nano_host())
if(!z)
return
var/valid_z_levels = (GetConnectedZlevels(T.z) & using_map.station_levels)
var/valid_z_levels = using_map.get_map_levels(z)
for(var/obj/machinery/power/supermatter/S in machines)
// Delaminating, not within coverage, not on a tile.
if(S.grav_pulling || S.exploded || !(S.z in valid_z_levels) || !istype(S.loc, /turf/))
@@ -62,8 +62,10 @@
data["networks"] = all_networks
var/list/map_levels = using_map.get_map_levels(get_z(nano_host()), TRUE)
if(current_network)
data["cameras"] = camera_repository.cameras_in_network(current_network)
data["cameras"] = camera_repository.cameras_in_network(current_network, map_levels)
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
if (!ui)
@@ -34,16 +34,21 @@
/datum/nano_module/crew_monitor/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1, var/datum/topic_state/state = default_state)
var/list/data = host.initial_data()
var/turf/T = get_turf(nano_host())
data["isAI"] = isAI(user)
data["map_levels"] = using_map.get_map_levels(T.z, FALSE)
var/z = get_z(nano_host())
var/list/map_levels = using_map.get_map_levels(z, TRUE)
data["map_levels"] = map_levels
data["crewmembers"] = list()
for(var/z in (data["map_levels"] | T.z)) // Always show crew from the current Z even if we can't show a map
data["crewmembers"] += crew_repository.health_data(z)
for(var/zlevel in map_levels)
data["crewmembers"] += crew_repository.health_data(zlevel)
if(!data["map_levels"].len)
to_chat(user, "<span class='warning'>The crew monitor doesn't seem like it'll work here.</span>")
if(ui)
ui.close()
return
ui = SSnanoui.try_update_ui(user, src, ui_key, ui, data, force_open)
@@ -79,20 +79,25 @@ var/global/ntnet_card_uid = 1
return 0
if(holder2)
var/turf/T = get_turf(holder2)
if(!istype(T)) //no reception in nullspace
var/holderz = get_z(holder2)
if(!holderz) //no reception in nullspace
return 0
if(T.z in using_map.station_levels)
// Computer is on station. Low/High signal depending on what type of network card you have
if(long_range)
return 2
else
return 1
if(T.z in using_map.contact_levels) //not on station, but close enough for radio signal to travel
if(long_range) // Computer is not on station, but it has upgraded network card. Low signal.
return 1
return 0 // Computer is not on station and does not have upgraded network card. No signal.
var/list/zlevels_in_range = using_map.get_map_levels(holderz, long_range)
var/best = 0
for(var/relay in ntnet_global.relays)
var/obj/machinery/ntnet_relay/R = relay
//Relay is down
if(!R.operable())
continue
//We're on the same z
if(R.z == holderz)
best = 2
break // No point in going further
//Not on the same z but within range anyway
if(R.z in zlevels_in_range)
best = 1
return best
return 0 // No computer!
/obj/item/weapon/computer_hardware/network_card/Destroy()
if(holder2 && (holder2.network_card == src))
-145
View File
@@ -1,145 +0,0 @@
//How far from the edge of overmap zlevel could randomly placed objects spawn
#define OVERMAP_EDGE 2
#define SHIP_SIZE_TINY 1
#define SHIP_SIZE_SMALL 2
#define SHIP_SIZE_LARGE 3
//multipliers for max_speed to find 'slow' and 'fast' speeds for the ship
#define SHIP_SPEED_SLOW 1/(40 SECONDS)
#define SHIP_SPEED_FAST 3/(20 SECONDS)// 15 speed
#define OVERMAP_WEAKNESS_NONE 0
#define OVERMAP_WEAKNESS_FIRE 1
#define OVERMAP_WEAKNESS_EMP 2
#define OVERMAP_WEAKNESS_MINING 4
#define OVERMAP_WEAKNESS_EXPLOSIVE 8
//Dimension of overmap (squares 4 lyfe)
var/global/list/map_sectors = list()
/area/overmap/
name = "System Map"
icon_state = "start"
requires_power = 0
base_turf = /turf/unsimulated/map
/turf/unsimulated/map
icon = 'icons/turf/space.dmi'
icon_state = "map"
initialized = FALSE // TODO - Fix unsimulated turf initialization so this override is not necessary!
/turf/unsimulated/map/edge
opacity = 1
density = 1
/turf/unsimulated/map/Initialize()
. = ..()
name = "[x]-[y]"
var/list/numbers = list()
if(x == 1 || x == global.using_map.overmap_size)
numbers += list("[round(y/10)]","[round(y%10)]")
if(y == 1 || y == global.using_map.overmap_size)
numbers += "-"
if(y == 1 || y == global.using_map.overmap_size)
numbers += list("[round(x/10)]","[round(x%10)]")
for(var/i = 1 to numbers.len)
var/image/I = image('icons/effects/numbers.dmi',numbers[i])
I.pixel_x = 5*i - 2
I.pixel_y = world.icon_size/2 - 3
if(y == 1)
I.pixel_y = 3
I.pixel_x = 5*i + 4
if(y == global.using_map.overmap_size)
I.pixel_y = world.icon_size - 9
I.pixel_x = 5*i + 4
if(x == 1)
I.pixel_x = 5*i - 2
if(x == global.using_map.overmap_size)
I.pixel_x = 5*i + 2
add_overlay(I)
//list used to track which zlevels are being 'moved' by the proc below
var/list/moving_levels = list()
//Proc to 'move' stars in spess
//yes it looks ugly, but it should only fire when state actually change.
//null direction stops movement
proc/toggle_move_stars(zlevel, direction)
if(!zlevel)
return
if (moving_levels["[zlevel]"] != direction)
moving_levels["[zlevel]"] = direction
var/list/spaceturfs = block(locate(1, 1, zlevel), locate(world.maxx, world.maxy, zlevel))
for(var/turf/space/T in spaceturfs)
T.toggle_transit(direction)
CHECK_TICK
/*
//list used to cache empty zlevels to avoid nedless map bloat
var/list/cached_space = list()
proc/overmap_spacetravel(var/turf/space/T, var/atom/movable/A)
var/obj/effect/map/M = map_sectors["[T.z]"]
if (!M)
return
var/mapx = M.x
var/mapy = M.y
var/nx = 1
var/ny = 1
var/nz = M.map_z
if(T.x <= TRANSITIONEDGE)
nx = world.maxx - TRANSITIONEDGE - 2
ny = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
mapx = max(1, mapx-1)
else if (A.x >= (world.maxx - TRANSITIONEDGE - 1))
nx = TRANSITIONEDGE + 2
ny = rand(TRANSITIONEDGE + 2, world.maxy - TRANSITIONEDGE - 2)
mapx = min(world.maxx, mapx+1)
else if (T.y <= TRANSITIONEDGE)
ny = world.maxy - TRANSITIONEDGE -2
nx = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
mapy = max(1, mapy-1)
else if (A.y >= (world.maxy - TRANSITIONEDGE - 1))
ny = TRANSITIONEDGE + 2
nx = rand(TRANSITIONEDGE + 2, world.maxx - TRANSITIONEDGE - 2)
mapy = min(world.maxy, mapy+1)
testing("[A] moving from [M] ([M.x], [M.y]) to ([mapx],[mapy]).")
var/turf/map = locate(mapx,mapy,OVERMAP_ZLEVEL)
var/obj/effect/map/TM = locate() in map
if(TM)
nz = TM.map_z
testing("Destination: [TM]")
else
if(cached_space.len)
var/obj/effect/map/sector/temporary/cache = cached_space[cached_space.len]
cached_space -= cache
nz = cache.map_z
cache.x = mapx
cache.y = mapy
testing("Destination: *cached* [TM]")
else
world.maxz++
nz = world.maxz
TM = new /obj/effect/map/sector/temporary(mapx, mapy, nz)
testing("Destination: *new* [TM]")
var/turf/dest = locate(nx,ny,nz)
if(dest)
A.loc = dest
if(istype(M, /obj/effect/map/sector/temporary))
var/obj/effect/map/sector/temporary/source = M
if (source.can_die())
testing("Catching [M] for future use")
source.loc = null
cached_space += source
*/
+5
View File
@@ -0,0 +1,5 @@
/proc/get_overmap_sector(var/z)
if(using_map.use_overmap)
return map_sectors["[z]"]
else
return null
+1 -1
View File
@@ -1,4 +1,4 @@
#define waypoint_sector(waypoint) map_sectors["[waypoint.z]"]
#define waypoint_sector(waypoint) get_overmap_sector(get_z(waypoint))
/datum/shuttle/autodock/overmap
warmup_time = 10
+1 -1
View File
@@ -17,7 +17,7 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
return 1
/obj/machinery/computer/ship/proc/sync_linked(var/user = null)
var/obj/effect/overmap/visitable/ship/sector = map_sectors["[z]"]
var/obj/effect/overmap/visitable/ship/sector = get_overmap_sector(z)
if(!sector)
return
. = attempt_hook_up_recursive(sector)
+2 -2
View File
@@ -80,7 +80,7 @@
. = ..()
/obj/effect/shuttle_landmark/ship/Destroy()
var/obj/effect/overmap/visitable/ship/landable/ship = map_sectors["[z]"]
var/obj/effect/overmap/visitable/ship/landable/ship = get_overmap_sector(z)
if(istype(ship) && ship.landmark == src)
ship.landmark = null
. = ..()
@@ -141,7 +141,7 @@
on_landing(from, into)
/obj/effect/overmap/visitable/ship/landable/proc/on_landing(obj/effect/shuttle_landmark/from, obj/effect/shuttle_landmark/into)
var/obj/effect/overmap/visitable/target = map_sectors["[into.z]"]
var/obj/effect/overmap/visitable/target = get_overmap_sector(get_z(into))
var/datum/shuttle/shuttle_datum = SSshuttles.shuttles[shuttle]
if(into.landmark_tag == shuttle_datum.motherdock) // If our motherdock is a landable ship, it won't be found properly here so we need to find it manually.
for(var/obj/effect/overmap/visitable/ship/landable/landable in SSshuttles.ships)
+1 -1
View File
@@ -57,7 +57,7 @@ proc/overmap_spacetravel(var/turf/space/T, var/atom/movable/A)
if (!T || !A)
return
var/obj/effect/overmap/visitable/M = map_sectors["[T.z]"]
var/obj/effect/overmap/visitable/M = get_overmap_sector(T.z)
if (!M)
return
+1 -1
View File
@@ -1,7 +1,7 @@
//Dimension of overmap (squares 4 lyfe)
var/global/list/map_sectors = list()
/area/overmap/
/area/overmap
name = "System Map"
icon_state = "start"
requires_power = 0
+3 -3
View File
@@ -55,14 +55,14 @@
if(!istype(docking_controller))
log_error("Could not find docking controller for shuttle waypoint '[name]', docking tag was '[docking_tag]'.")
if(using_map.use_overmap)
var/obj/effect/overmap/visitable/location = map_sectors["[z]"]
var/obj/effect/overmap/visitable/location = get_overmap_sector(z)
if(location && location.docking_codes)
docking_controller.docking_codes = location.docking_codes
/obj/effect/shuttle_landmark/forceMove()
var/obj/effect/overmap/visitable/map_origin = map_sectors["[z]"]
var/obj/effect/overmap/visitable/map_origin = get_overmap_sector(z)
. = ..()
var/obj/effect/overmap/visitable/map_destination = map_sectors["[z]"]
var/obj/effect/overmap/visitable/map_destination = get_overmap_sector(z)
if(map_origin != map_destination)
if(map_origin)
map_origin.remove_landmark(src, shuttle_restricted)
+1 -1
View File
@@ -30,7 +30,7 @@
if(active_docking_controller)
set_docking_codes(active_docking_controller.docking_codes)
else if(global.using_map.use_overmap)
var/obj/effect/overmap/visitable/location = map_sectors["[current_location.z]"]
var/obj/effect/overmap/visitable/location = get_overmap_sector(get_z(current_location))
if(location && location.docking_codes)
set_docking_codes(location.docking_codes)
dock()
+1 -1
View File
@@ -166,7 +166,7 @@ GLOBAL_LIST_BOILERPLATE(papers_dockingcode, /obj/item/weapon/paper/dockingcodes)
var/dockingcodes = null
var/z_to_check = codes_from_z ? codes_from_z : z
if(using_map.use_overmap)
var/obj/effect/overmap/visitable/location = map_sectors["[z_to_check]"]
var/obj/effect/overmap/visitable/location = get_overmap_sector(z_to_check)
if(location && location.docking_codes)
dockingcodes = location.docking_codes
Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 103 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 20 KiB

+34 -10
View File
@@ -144,20 +144,44 @@ var/list/all_maps = list()
empty_levels = list(world.maxz)
return pick(empty_levels)
// Get the list of zlevels that a computer on srcz can see maps of (for power/crew monitor, cameras, etc)
// The long_range parameter expands the coverage. Default is to return map_levels for long range otherwise just srcz.
// zLevels outside station_levels will return an empty list.
/datum/map/proc/get_map_levels(var/srcz, var/long_range = TRUE)
if (long_range && (srcz in map_levels))
return map_levels
else if (srcz in station_levels)
return list(srcz)
// Get a list of 'nearby' or 'connected' zlevels.
// You should at least return a list with the given z if nothing else.
/datum/map/proc/get_map_levels(var/srcz, var/long_range = FALSE, var/om_range = -1)
//Overmap behavior
if(use_overmap)
//Get what sector we're in
var/obj/effect/overmap/visitable/O = get_overmap_sector(srcz)
if(!istype(O))
//Not in a sector, just the passed zlevel
return list(srcz)
//Just the sector we're in
if(om_range == -1)
return O.map_z.Copy()
//Otherwise every sector we're on top of
var/list/connections = list()
var/turf/T = get_turf(O)
var/turfrange = long_range ? max(0, om_range) : om_range
for(var/obj/effect/overmap/visitable/V in range(turfrange, T))
connections += V.map_z // Adding list to list adds contents
return connections
//Traditional behavior
else
return list()
//If long range, and they're at least in contact levels, return contact levels.
if (long_range && (srcz in contact_levels))
return contact_levels.Copy()
//If in station levels, return station levels
else if (srcz in station_levels)
return station_levels.Copy()
//Just give them back their zlevel
else
return list(srcz)
/datum/map/proc/get_zlevel_name(var/index)
var/datum/map_z_level/Z = zlevels["[index]"]
return Z.name
return Z?.name
// Access check is of the type requires one. These have been carefully selected to avoid allowing the janitor to see channels he shouldn't
// This list needs to be purged but people insist on adding more cruft to the radio.
+2 -1
View File
@@ -8,7 +8,8 @@ Used In File(s): \code\game\machinery\computer\camera.dm
{{:helper.link('Reset', 'refresh', {'reset' : 1})}}
<div style="float:left;">
<div class='item'>
<div class='itemLabel'>Current Camera:&nbsp;</div>
<div class='itemLabel'>Current&nbsp;Camera:&nbsp;</div>
<br>
{{if data.current_camera}}
<div class='itemContent'><b>{{:data.current_camera.name}}</b></div>
{{else}}
+2
View File
@@ -996,6 +996,7 @@
#include "code\game\objects\items\devices\radio\intercom.dm"
#include "code\game\objects\items\devices\radio\jammer.dm"
#include "code\game\objects\items\devices\radio\radio.dm"
#include "code\game\objects\items\devices\radio\radiopack.dm"
#include "code\game\objects\items\robot\robot_items.dm"
#include "code\game\objects\items\robot\robot_parts.dm"
#include "code\game\objects\items\robot\robot_upgrades.dm"
@@ -2435,6 +2436,7 @@
#include "code\modules\organs\subtypes\unseverable.dm"
#include "code\modules\organs\subtypes\vox.dm"
#include "code\modules\organs\subtypes\xenos.dm"
#include "code\modules\overmap\helpers.dm"
#include "code\modules\overmap\overmap_object.dm"
#include "code\modules\overmap\overmap_shuttle.dm"
#include "code\modules\overmap\sectors.dm"