Files
vgstation13/code/game/communications.dm
eplgr 9910f100d0 Colorblind preset for goonchat, gives non specific radio a different color. (#14662)
* chat_colors

* colorblind

* Goonchat color preset system.

* Revert CSS file changes.

* colorblind_v2

* fix
2017-04-16 13:08:10 -07:00

387 lines
11 KiB
Plaintext

/*
HOW IT WORKS
The radio_controller 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, var/new_frequency as num, var/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, var/filter as text|null = null, var/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, var/receive_method as num, var/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(-1). 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.
*/
var/list/all_radios = list()
/proc/add_radio(var/obj/item/radio, freq)
if(!freq || !radio)
return
if(!all_radios["[freq]"])
all_radios["[freq]"] = list(radio)
return freq
all_radios["[freq]"] |= radio
return freq
/proc/remove_radio(var/obj/item/radio, freq)
if(!freq || !radio)
return
if(!all_radios["[freq]"])
return
all_radios["[freq]"] -= radio
/proc/remove_radio_all(var/obj/item/radio)
for(var/freq in all_radios)
all_radios["[freq]"] -= radio
/*
Frequency range: 1200 to 1600
Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking)
Radio:
1459 - standard radio chat
1351 - Science
1353 - Command
1355 - Medical
1357 - Engineering
1359 - Security
1441 - death squad
1443 - Confession Intercom
1349 - Botany, chef, bartender
1347 - Cargo techs
Devices:
1451 - tracking implant
1457 - RSD default
On the map:
1311 for prison shuttle console (in fact, it is not used)
1367 for recycling/mining processing machinery and conveyors
1435 for status displays
1437 for atmospherics/fire alerts
1439 for engine components
1439 for air pumps, air scrubbers, atmo control
1441 for atmospherics - supply tanks
1443 for atmospherics - distribution loop/mixed air tank
1445 for bot nav beacons
1447 for mulebot, secbot and ed209 control
1449 for airlock controls, electropack, magnets
1451 for toxin lab access
1453 for engineering access
1455 for AI access
*/
var/list/radiochannels = list(
"Common" = 1459,
"AI Private" = 1447,
"Deathsquad" = 1441,
"Security" = 1359,
"Engineering" = 1357,
"Command" = 1353,
"Medical" = 1355,
"Science" = 1351,
"Service" = 1349,
"Supply" = 1347,
"Response Team" = 1345,
"Syndicate" = 1213,
"DJ" = 1201
)
var/list/radiochannelsreverse = list(
"1201" = "DJ",
"1213" = "Syndicate",
"1345" = "Response Team",
"1347" = "Supply",
"1349" = "Service",
"1351" = "Science",
"1355" = "Medical",
"1353" = "Command",
"1357" = "Engineering",
"1359" = "Security",
"1441" = "Deathsquad",
"1447" = "AI Private",
"1459" = "Common"
)
//depenging helpers
var/const/SUPP_FREQ = 1347 //supply, coloured light brown in chat window
var/const/SERV_FREQ = 1349 //service, coloured green in chat window
var/const/DSQUAD_FREQ = 1441 //death squad frequency, coloured grey in chat window
var/const/RESTEAM_FREQ = 1345 //response team frequency, uses the deathsquad color at the moment.
var/const/AIPRIV_FREQ = 1447 //AI private, colored magenta in chat window
var/const/DJ_FREQ = 1201 //Media
var/const/COMMON_FREQ = 1459
// central command channels, i.e deathsquid & response teams
var/list/CENT_FREQS = list(1345, 1441)
var/const/COMM_FREQ = 1353 //command, colored gold in chat window
var/const/SYND_FREQ = 1213
// department channels
var/const/SEC_FREQ = 1359
var/const/ENG_FREQ = 1357
var/const/SCI_FREQ = 1351
var/const/MED_FREQ = 1355
var/const/SUP_FREQ = 1347
var/const/SER_FREQ = 1349
#define TRANSMISSION_WIRE 0
#define TRANSMISSION_RADIO 1
/* filters */
var/const/RADIO_TO_AIRALARM = "1"
var/const/RADIO_FROM_AIRALARM = "2"
var/const/RADIO_CHAT = "3" //deprecated
var/const/RADIO_ATMOSIA = "4"
var/const/RADIO_NAVBEACONS = "5"
var/const/RADIO_AIRLOCK = "6"
var/const/RADIO_SECBOT = "7"
var/const/RADIO_MULEBOT = "8"
var/const/RADIO_MAGNETS = "9"
var/const/RADIO_CONVEYORS = "10"
var/global/datum/controller/radio/radio_controller
/datum/controller/radio
var/list/datum/radio_frequency/frequencies = new
/datum/controller/radio/proc/add_object(const/obj/device, const/_frequency, var/filter = null as text|null)
var/datum/radio_frequency/frequency = return_frequency(_frequency)
if(isnull(frequency))
frequency = new
frequency.frequency = _frequency
frequencies[num2text(_frequency)] = frequency
frequency.add_listener(device, filter)
return frequency
/datum/controller/radio/proc/remove_object(const/obj/device, const/_frequency)
var/datum/radio_frequency/frequency = return_frequency(_frequency)
if(frequency)
frequency.remove_listener(device)
if(frequency.devices.len <= 0)
frequencies.Remove(num2text(_frequency))
return 1
/datum/controller/radio/proc/return_frequency(const/_frequency)
return frequencies[num2text(_frequency)]
/datum/radio_frequency
var/frequency as num
var/list/list/obj/devices = list()
/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, var/filter = null as text|null, var/range = null as num|null)
//log_admin("DEBUG \[[world.timeofday]\]: post_signal {source=\"[source]\", [signal.debug_print()], filter=[filter]}")
//var/N_f=0
//var/N_nf=0
//var/Nt=0
var/turf/start_point
if(range)
start_point = get_turf(source)
if(!start_point)
returnToPool(signal)
return 0
if (filter) //here goes some copypasta. It is for optimisation. -rastaf0
for(var/obj/device in devices[filter])
if(device == source)
continue
if(range)
var/turf/end_point = get_turf(device)
if(!end_point)
continue
//if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range)
if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
continue
device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
for(var/obj/device in devices["_default"])
if(device == source)
continue
if(range)
var/turf/end_point = get_turf(device)
if(!end_point)
continue
//if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range)
if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
continue
device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
//N_f++
else
for (var/next_filter in devices)
//var/list/obj/DDD = devices[next_filter]
//Nt+=DDD.len
for(var/obj/device in devices[next_filter])
if(device == source)
continue
if(range)
var/turf/end_point = get_turf(device)
if(!end_point)
continue
//if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range)
if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
continue
device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
//N_nf++
//log_admin("DEBUG: post_signal(source=[source] ([source.x], [source.y], [source.z]),filter=[filter]) frequency=[frequency], N_f=[N_f], N_nf=[N_nf]")
returnToPool(signal)
/datum/radio_frequency/proc/add_listener(const/obj/device, var/filter)
if(!filter) // FIXME
filter = "_default"
var/list/devices_at_filter = devices[filter]
if(isnull(devices_at_filter))
devices_at_filter = new
devices[filter] = devices_at_filter
devices_at_filter.Add(device)
/datum/radio_frequency/proc/remove_listener(const/obj/device, const/filter)
var/list/devices_at_filter = devices[filter]
// 1. check if it's an object
// 2. check if it has contents
// 3. check if the device is in contents
if(devices_at_filter && devices_at_filter.len && devices_at_filter.Find(device))
devices_at_filter.Remove(device)
if(devices_at_filter.len <= 0)
devices.Remove(filter)
/datum/radio_frequency/remove_listener(const/obj/device)
for(var/filter in devices)
..(device, filter)
var/list/pointers = list()
/client/proc/print_pointers()
set name = "Debug Signals"
set category = "Debug"
if(!holder)
return
to_chat(src, "There are [pointers.len] pointers:")
for(var/p in pointers)
to_chat(src, p)
var/datum/signal/S = locate(p)
if(istype(S))
to_chat(src, S.debug_print())
/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
return
#define SIGNAL_WIRE 0
#define SIGNAL_RADIO 1
#define SIGNAL_SUBSPACE 2
/datum/signal
var/obj/source
var/transmission_method = SIGNAL_WIRE
//0 = wire
//1 = radio transmission
//2 = subspace transmission
var/data = list()
var/encryption
var/frequency = 0
/datum/signal/New()
..()
pointers += "\ref[src]"
/datum/signal/Destroy()
pointers -= "\ref[src]"
/datum/signal/resetVariables()
. = ..("data")
source = null
data = list()
/datum/signal/proc/copy_from(datum/signal/model)
source = model.source
transmission_method = model.transmission_method
data = model.data
encryption = model.encryption
frequency = model.frequency
/datum/signal/proc/debug_print()
if (source)
. = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n"
else
. = "signal = {source = '[source]' ()\n"
for (var/i in data)
. += "data\[\"[i]\"\] = \"[data[i]]\"\n"
if(islist(data[i]))
var/list/L = data[i]
for(var/t in L)
. += "data\[\"[i]\"\] list has: [t]"
/datum/signal/proc/sanitize_data()
for(var/d in data)
var/val = data[d]
if(istext(val))
data[d] = strip_html_simple(val)