Files
Skyrat-tg/code/game/communications.dm
WaterpigandMajkl-J bb70889f6e TG Upstream Part 1
3591 individual conflicts

Update build.js

Update install_node.sh

Update byond.js

oh my fucking god

hat

slow

huh

holy shit

we all fall down

2 more I missed

2900 individual conflicts

2700 Individual conflicts

replaces yarn file with tg version, bumping us down to 2200-ish

Down to 2000 individual conflicts

140 down

mmm

aaaaaaaaaaaaaaaaaaa

not yt

575

soon

900 individual conflicts

600 individual conflicts, 121 file conflicts

im not okay

160 across 19 files

29 in 4 files

0 conflicts, compiletime fix time

some minor incap stuff

missed ticks

weird dupe definition stuff

missed ticks 2

incap fixes

undefs and pie fix

Radio update and some extra minor stuff

returns a single override

no more dupe definitions, 175 compiletime errors

Unticked file fix

sound and emote stuff

honk and more radio stuff
2024-10-19 08:04:33 -07:00

264 lines
9.9 KiB
Plaintext

/*
* HOW IT WORKS
*
*The SSradio is a global object maintaining all radio transmissions, think about it as about "ether".
*Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way.
*procs:
*
* add_object(obj/device as obj, new_frequency as num, filter as text|null = null)
* Adds listening object.
* parameters:
* device - device receiving signals, must have proc receive_signal (see description below).
* one device may listen several frequencies, but not same frequency twice.
* new_frequency - see possibly frequencies below;
* filter - thing for optimization. Optional, but recommended.
* All filters should be consolidated in this file, see defines later.
* Device without listening filter will receive all signals (on specified frequency).
* Device with filter will receive any signals sent without filter.
* Device with filter will not receive any signals sent with different filter.
* returns:
* Reference to frequency object.
*
* remove_object (obj/device, old_frequency)
* Obliviously, after calling this proc, device will not receive any signals on old_frequency.
* Other frequencies will left unaffected.
*
*return_frequency(var/frequency as num)
* returns:
* Reference to frequency object. Use it if you need to send and do not need to listen.
*
*radio_frequency is a global object maintaining list of devices that listening specific frequency.
*procs:
*
* post_signal(obj/source as obj|null, datum/signal/signal, filter as text|null = null, range as num|null = null)
* Sends signal to all devices that wants such signal.
* parameters:
* source - object, emitted signal. Usually, devices will not receive their own signals.
* signal - see description below.
* filter - described above.
* range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels.
*
* obj/proc/receive_signal(datum/signal/signal, receive_method as num, receive_param)
* Handler from received signals. By default does nothing. Define your own for your object.
* Avoid of sending signals directly from this proc, use spawn(0). Do not use sleep() here please.
* parameters:
* signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return!
* receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO.
* TRANSMISSION_WIRE is currently unused.
* receive_param - for TRANSMISSION_RADIO here comes frequency.
*
* datum/signal
* vars:
* source
* an object that emitted signal. Used for debug and bearing.
* data
* list with transmitting data. Usual use pattern:
* data["msg"] = "hello world"
* encryption
* Some number symbolizing "encryption key".
* Note that game actually do not use any cryptography here.
* If receiving object don't know right key, it must ignore encrypted signal in its receive_signal.
*
*/
/* the radio controller is a confusing piece of shit and didnt work
so i made radios not use the radio controller.
*/
GLOBAL_LIST_EMPTY(all_radios)
/proc/add_radio(obj/item/radio, freq)
if(!freq || !radio)
return
if(!GLOB.all_radios["[freq]"])
GLOB.all_radios["[freq]"] = list(radio)
return freq
GLOB.all_radios["[freq]"] |= radio
return freq
/proc/remove_radio(obj/item/radio, freq)
if(!freq || !radio)
return
if(!GLOB.all_radios["[freq]"])
return
GLOB.all_radios["[freq]"] -= radio
/proc/remove_radio_all(obj/item/radio)
for(var/freq in GLOB.all_radios)
GLOB.all_radios["[freq]"] -= radio
// For information on what objects or departments use what frequencies,
// see __DEFINES/radio.dm. Mappers may also select additional frequencies for
// use in maps, such as in intercoms.
GLOBAL_LIST_INIT(radiochannels, list(
RADIO_CHANNEL_COMMON = FREQ_COMMON,
RADIO_CHANNEL_SCIENCE = FREQ_SCIENCE,
RADIO_CHANNEL_COMMAND = FREQ_COMMAND,
RADIO_CHANNEL_MEDICAL = FREQ_MEDICAL,
RADIO_CHANNEL_ENGINEERING = FREQ_ENGINEERING,
RADIO_CHANNEL_SECURITY = FREQ_SECURITY,
RADIO_CHANNEL_CENTCOM = FREQ_CENTCOM,
RADIO_CHANNEL_FACTION = FREQ_FACTION, //SKYRAT EDIT ADDITION - FACTION
RADIO_CHANNEL_CYBERSUN = FREQ_CYBERSUN, //SKYRAT EDIT ADDITION - MAPPING
RADIO_CHANNEL_INTERDYNE = FREQ_INTERDYNE, //SKYRAT EDIT ADDITION - MAPPING
RADIO_CHANNEL_GUILD = FREQ_GUILD, //SKYRAT EDIT ADDITION - ASSAULT OPS
RADIO_CHANNEL_TARKON = FREQ_TARKON, //SKYRAT EDIT ADDITION - MAPPING
RADIO_CHANNEL_SOLFED = FREQ_SOLFED, //SKYRAT EDIT ADDITION - SOLFED
RADIO_CHANNEL_SYNDICATE = FREQ_SYNDICATE,
RADIO_CHANNEL_UPLINK = FREQ_UPLINK,
RADIO_CHANNEL_SUPPLY = FREQ_SUPPLY,
RADIO_CHANNEL_SERVICE = FREQ_SERVICE,
RADIO_CHANNEL_AI_PRIVATE = FREQ_AI_PRIVATE,
RADIO_CHANNEL_ENTERTAINMENT = FREQ_ENTERTAINMENT,
RADIO_CHANNEL_CTF_RED = FREQ_CTF_RED,
RADIO_CHANNEL_CTF_BLUE = FREQ_CTF_BLUE,
RADIO_CHANNEL_CTF_GREEN = FREQ_CTF_GREEN,
RADIO_CHANNEL_CTF_YELLOW = FREQ_CTF_YELLOW
))
GLOBAL_LIST_INIT(reverseradiochannels, list(
"[FREQ_COMMON]" = RADIO_CHANNEL_COMMON,
"[FREQ_SCIENCE]" = RADIO_CHANNEL_SCIENCE,
"[FREQ_COMMAND]" = RADIO_CHANNEL_COMMAND,
"[FREQ_MEDICAL]" = RADIO_CHANNEL_MEDICAL,
"[FREQ_ENGINEERING]" = RADIO_CHANNEL_ENGINEERING,
"[FREQ_SECURITY]" = RADIO_CHANNEL_SECURITY,
"[FREQ_CENTCOM]" = RADIO_CHANNEL_CENTCOM,
"[FREQ_FACTION]" = RADIO_CHANNEL_FACTION, //SKYRAT EDIT ADDITION - FACTION
"[FREQ_CYBERSUN]" = RADIO_CHANNEL_CYBERSUN, //SKYRAT EDIT ADDITION - MAPPING
"[FREQ_INTERDYNE]" = RADIO_CHANNEL_INTERDYNE, //SKYRAT EDIT ADDITION - MAPPING
"[FREQ_TARKON]" = RADIO_CHANNEL_TARKON, //SKYRAT EDIT ADDITION - MAPPING
"[FREQ_SOLFED]" = RADIO_CHANNEL_SOLFED, //SKYRAT EDIT ADDITION - SOLFED
"[FREQ_SYNDICATE]" = RADIO_CHANNEL_SYNDICATE,
"[FREQ_UPLINK]" = RADIO_CHANNEL_UPLINK,
"[FREQ_SUPPLY]" = RADIO_CHANNEL_SUPPLY,
"[FREQ_SERVICE]" = RADIO_CHANNEL_SERVICE,
"[FREQ_AI_PRIVATE]" = RADIO_CHANNEL_AI_PRIVATE,
"[FREQ_ENTERTAINMENT]" = RADIO_CHANNEL_ENTERTAINMENT,
"[FREQ_CTF_RED]" = RADIO_CHANNEL_CTF_RED,
"[FREQ_CTF_BLUE]" = RADIO_CHANNEL_CTF_BLUE,
"[FREQ_CTF_GREEN]" = RADIO_CHANNEL_CTF_GREEN,
"[FREQ_CTF_YELLOW]" = RADIO_CHANNEL_CTF_YELLOW
))
GLOBAL_LIST_INIT(radiocolors, list(
RADIO_CHANNEL_COMMON = "#008000",
RADIO_CHANNEL_SCIENCE = "#993399",
RADIO_CHANNEL_COMMAND = "#948f02",
RADIO_CHANNEL_MEDICAL = "#337296",
RADIO_CHANNEL_ENGINEERING = "#fb5613",
RADIO_CHANNEL_SECURITY = "#a30000",
RADIO_CHANNEL_CENTCOM = "#686868",
RADIO_CHANNEL_SYNDICATE = "#6d3f40",
RADIO_CHANNEL_SUPPLY = "#a8732b",
RADIO_CHANNEL_SERVICE = "#6eaa2c",
RADIO_CHANNEL_AI_PRIVATE = "#ff00ff",
RADIO_CHANNEL_ENTERTAINMENT = "#00ff99",
RADIO_CHANNEL_CTF_RED = "#ff0000",
RADIO_CHANNEL_CTF_BLUE = "#0000ff",
RADIO_CHANNEL_CTF_GREEN = "#00ff00",
RADIO_CHANNEL_CTF_YELLOW = "#d1ba22",
))
/datum/radio_frequency
/// The frequency of this radio frequency. Of course.
var/frequency
/// List of filters -> list of devices
var/list/list/datum/weakref/devices = list()
/datum/radio_frequency/New(freq)
frequency = freq
//If range > 0, only post to devices on the same z_level and within range
//Use range = -1, to restrain to the same z_level without limiting range
/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, filter = null as text|null, range = null as num|null)
// Ensure the signal's data is fully filled
signal.source = source
signal.frequency = frequency
//Apply filter to the signal. If none supply, broadcast to every devices
//_default channel is always checked
var/list/filter_list
if(filter)
filter_list = list(filter,"_default")
else
filter_list = devices
//If checking range, find the source turf
var/turf/start_point
if(range)
start_point = get_turf(source)
if(!start_point)
return
//Send the data
for(var/current_filter in filter_list)
for(var/datum/weakref/device_ref as anything in devices[current_filter])
var/obj/device = device_ref.resolve()
if(!device)
devices[current_filter] -= device_ref
continue
if(device == source)
continue
if(range)
var/turf/end_point = get_turf(device)
if(!end_point)
continue
if(start_point.z != end_point.z || (range > 0 && get_dist(start_point, end_point) > range))
continue
device.receive_signal(signal)
CHECK_TICK
/// Handles adding a listener to the radio frequency.
/datum/radio_frequency/proc/add_listener(obj/device, filter as text|null)
if (!filter)
filter = "_default"
var/datum/weakref/new_listener = WEAKREF(device)
if(isnull(new_listener))
return stack_trace("null, non-datum, or qdeleted device")
var/list/devices_line = devices[filter]
if(!devices_line)
devices[filter] = devices_line = list()
devices_line += new_listener
/// Handles removing a listener from this radio frequency.
/datum/radio_frequency/proc/remove_listener(obj/device)
for(var/devices_filter in devices)
var/list/devices_line = devices[devices_filter]
if(!devices_line)
devices -= devices_filter
devices_line -= WEAKREF(device)
if(!devices_line.len)
devices -= devices_filter
/**
* Proc for reacting to a received `/datum/signal`. To be implemented as needed,
* does nothing by default.
*/
/obj/proc/receive_signal(datum/signal/signal)
set waitfor = FALSE
return
/datum/signal
/// The source of this signal.
var/obj/source
/// The frequency on which this signal was emitted.
var/frequency = 0
/// The method through which this signal was transmitted.
/// See all of the `TRANSMISSION_X` in `code/__DEFINES/radio.dm` for
/// all of the possible options.
var/transmission_method
/// The data carried through this signal. Defaults to `null`, otherwise it's
/// an associative list of (string, any).
var/list/data
/// Logging data, used for logging purposes. Makes sense, right?
var/logging_data
/datum/signal/New(data, transmission_method = TRANSMISSION_RADIO, logging_data = null)
src.data = data || list()
src.transmission_method = transmission_method
src.logging_data = logging_data