mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-19 02:54:41 +01:00
Revert "Revert "Saycode/language/species port from Bay""
This reverts commit d54579850c.
Conflicts:
code/game/gamemodes/nuclear/nuclearbomb.dm
code/game/objects/items/devices/radio/intercom.dm
code/modules/mob/living/silicon/pai/pai.dm
This commit is contained in:
+23
-32
@@ -167,8 +167,6 @@
|
||||
// The old system would loop through lists for a total of 5000 per function call, in an empty server.
|
||||
// This new system will loop at around 1000 in an empty server.
|
||||
|
||||
// SCREW THAT SHIT, we're not recursing.
|
||||
|
||||
/proc/get_mobs_in_view(var/R, var/atom/source)
|
||||
// Returns a list of mobs in range of R from source. Used in radio and say code.
|
||||
|
||||
@@ -180,48 +178,40 @@
|
||||
|
||||
var/list/range = hear(R, T)
|
||||
|
||||
for(var/mob/M in range)
|
||||
hear += M
|
||||
for(var/atom/A in range)
|
||||
if(ismob(A))
|
||||
var/mob/M = A
|
||||
if(M.client)
|
||||
hear += M
|
||||
//world.log << "Start = [M] - [get_turf(M)] - ([M.x], [M.y], [M.z])"
|
||||
else if(istype(A, /obj/item/device/radio))
|
||||
hear += A
|
||||
|
||||
var/list/objects = list()
|
||||
if(isobj(A) || ismob(A))
|
||||
hear |= recursive_mob_check(A, hear, 3, 1, 0, 1)
|
||||
|
||||
for(var/obj/O in range) //Get a list of objects in hearing range. We'll check to see if any clients have their "eye" set to the object
|
||||
objects += O
|
||||
|
||||
for(var/client/C in clients)
|
||||
if(!istype(C) || !C.eye || istype(C.eye, /mob/aiEye))
|
||||
continue //I have no idea when this client check would be needed, but if this runtimes people won't hear anything
|
||||
//So kinda paranoid about runtime avoidance.
|
||||
if(istype(C.eye, /obj/machinery/camera))
|
||||
continue //No microphones in cameras.
|
||||
|
||||
if(C.mob in hear)
|
||||
continue
|
||||
|
||||
var/list/hear_and_objects = (hear|objects) //Combined these lists here instead of doing the combine 3 more times.
|
||||
|
||||
if(C.eye in hear_and_objects)
|
||||
hear += C.mob
|
||||
|
||||
else if(C.mob && C.mob.loc in hear_and_objects)
|
||||
hear += C.mob
|
||||
else if(C.mob && C.mob.loc.loc in hear_and_objects)
|
||||
hear += C.mob
|
||||
else if(C.mob && C.mob.loc.loc.loc in hear_and_objects)
|
||||
hear += C.mob
|
||||
return hear
|
||||
|
||||
|
||||
/proc/get_mobs_in_radio_ranges(var/list/obj/item/device/radio/radios)
|
||||
|
||||
//set background = 1
|
||||
set background = 1
|
||||
|
||||
. = list()
|
||||
// Returns a list of mobs who can hear any of the radios given in @radios
|
||||
var/list/speaker_coverage = list()
|
||||
for(var/i = 1; i <= radios.len; i++)
|
||||
var/obj/item/device/radio/R = radios[i]
|
||||
for(var/obj/item/device/radio/R in radios)
|
||||
if(R)
|
||||
//Cyborg checks. Receiving message uses a bit of cyborg's charge.
|
||||
var/obj/item/device/radio/borg/BR = R
|
||||
if(istype(BR) && BR.myborg)
|
||||
var/mob/living/silicon/robot/borg = BR.myborg
|
||||
var/datum/robot_component/CO = borg.get_component("radio")
|
||||
if(!CO)
|
||||
continue //No radio component (Shouldn't happen)
|
||||
if(!borg.is_component_functioning("radio") || !borg.use_power(CO.energy_consumption))
|
||||
continue //No power.
|
||||
|
||||
var/turf/speaker = get_turf(R)
|
||||
if(speaker)
|
||||
for(var/turf/T in hear(R.canhear_range,speaker))
|
||||
@@ -239,6 +229,7 @@
|
||||
. |= M // Since we're already looping through mobs, why bother using |= ? This only slows things down.
|
||||
return .
|
||||
|
||||
|
||||
#define SIGN(X) ((X<0)?-1:1)
|
||||
|
||||
proc
|
||||
|
||||
@@ -28,6 +28,7 @@ var/global/list/airlocks = list() //list of all airlocks
|
||||
//Languages/species/whitelist.
|
||||
var/global/list/all_species[0]
|
||||
var/global/list/all_languages[0]
|
||||
var/global/list/language_keys[0] // Table of say codes for all languages
|
||||
var/global/list/all_nations[0]
|
||||
var/global/list/whitelisted_species = list()
|
||||
|
||||
@@ -114,6 +115,13 @@ var/global/list/backbaglist = list("Nothing", "Backpack", "Satchel", "Satchel Al
|
||||
var/datum/language/L = new T
|
||||
all_languages[L.name] = L
|
||||
|
||||
for (var/language_name in all_languages)
|
||||
var/datum/language/L = all_languages[language_name]
|
||||
if(!(L.flags & NONGLOBAL))
|
||||
language_keys[":[lowertext(L.key)]"] = L
|
||||
language_keys[".[lowertext(L.key)]"] = L
|
||||
language_keys["#[lowertext(L.key)]"] = L
|
||||
|
||||
var/rkey = 0
|
||||
paths = typesof(/datum/species)-/datum/species
|
||||
for(var/T in paths)
|
||||
|
||||
+12
-8
@@ -49,15 +49,19 @@ proc/random_facial_hair_style(gender, species = "Human")
|
||||
|
||||
return f_style
|
||||
|
||||
proc/random_name(gender, speciesName = "Human")
|
||||
var/datum/species/S = all_species[speciesName]
|
||||
if(S)
|
||||
return S.makeName(gender)
|
||||
else
|
||||
if(gender==FEMALE)
|
||||
proc/random_name(gender, species = "Human")
|
||||
|
||||
var/datum/species/current_species
|
||||
if(species)
|
||||
current_species = all_species[species]
|
||||
|
||||
if(!current_species || current_species.name == "Human")
|
||||
if(gender==FEMALE)
|
||||
return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
|
||||
else
|
||||
return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
|
||||
else
|
||||
return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
|
||||
else
|
||||
return current_species.get_random_name(gender)
|
||||
|
||||
proc/random_skin_tone()
|
||||
switch(pick(60;"caucasian", 15;"afroamerican", 10;"african", 10;"latino", 5;"albino"))
|
||||
|
||||
@@ -341,4 +341,5 @@ proc/checkhtml(var/t)
|
||||
return sanitize(input)
|
||||
|
||||
/proc/trim_strip_html_properly(var/input, var/max_length = MAX_MESSAGE_LEN)
|
||||
return trim(strip_html_properly(input, max_length))
|
||||
return trim(strip_html_properly(input, max_length))
|
||||
|
||||
@@ -64,10 +64,11 @@
|
||||
// Now you can click through portals, wormholes, gateways, and teleporters while observing. -Sayu
|
||||
|
||||
/obj/machinery/teleport/hub/attack_ghost(mob/user as mob)
|
||||
var/atom/l = loc
|
||||
var/obj/machinery/computer/teleporter/com = locate(/obj/machinery/computer/teleporter, locate(l.x - 2, l.y, l.z))
|
||||
if(com && com.locked)
|
||||
user.loc = get_turf(com.locked)
|
||||
var/obj/machinery/teleport/station/S = power_station
|
||||
if(S)
|
||||
var/obj/machinery/computer/teleporter/com = S.teleporter_console
|
||||
if(com && com.target)
|
||||
user.loc = get_turf(com.target)
|
||||
|
||||
/obj/effect/portal/attack_ghost(mob/user as mob)
|
||||
if(target)
|
||||
|
||||
@@ -124,30 +124,14 @@ On the map:
|
||||
1455 for AI access
|
||||
*/
|
||||
|
||||
var/list/radiochannels = list(
|
||||
"Common" = 1459,
|
||||
"Science" = 1351,
|
||||
"Command" = 1353,
|
||||
"Medical" = 1355,
|
||||
"Engineering" = 1357,
|
||||
"Security" = 1359,
|
||||
"Response Team" = 1443,
|
||||
"Deathsquad" = 1441,
|
||||
"Syndicate" = 1213,
|
||||
"Supply" = 1347,
|
||||
"Service" = 1349,
|
||||
"AI Private" = 1447
|
||||
)
|
||||
//depenging helpers
|
||||
var/list/DEPT_FREQS = list(1351, 1355, 1357, 1359, 1213, 1443, 1441, 1347, 1349)
|
||||
|
||||
// central command channels, i.e deathsquid & response teams
|
||||
var/list/CENT_FREQS = list(1441, 1443)
|
||||
|
||||
var/const/COMM_FREQ = 1353 //command, colored gold in chat window
|
||||
var/const/COMM_FREQ = 1353
|
||||
var/const/SYND_FREQ = 1213
|
||||
var/const/ERT_FREQ = 1345
|
||||
var/const/DTH_FREQ = 1341
|
||||
var/const/AI_FREQ = 1447
|
||||
|
||||
// department channels
|
||||
var/const/PUB_FREQ = 1459
|
||||
var/const/SEC_FREQ = 1359
|
||||
var/const/ENG_FREQ = 1357
|
||||
var/const/SCI_FREQ = 1351
|
||||
@@ -155,12 +139,65 @@ var/const/MED_FREQ = 1355
|
||||
var/const/SUP_FREQ = 1347
|
||||
var/const/SRV_FREQ = 1349
|
||||
|
||||
// other channels
|
||||
var/const/AIPRIV_FREQ = 1447
|
||||
var/list/radiochannels = list(
|
||||
"Common" = PUB_FREQ,
|
||||
"Science" = SCI_FREQ,
|
||||
"Command" = COMM_FREQ,
|
||||
"Medical" = MED_FREQ,
|
||||
"Engineering" = ENG_FREQ,
|
||||
"Security" = SEC_FREQ,
|
||||
"Response Team" = ERT_FREQ,
|
||||
"Special Ops" = DTH_FREQ,
|
||||
"Syndicate" = SYND_FREQ,
|
||||
"Supply" = SUP_FREQ,
|
||||
"Service" = SRV_FREQ,
|
||||
"AI Private" = AI_FREQ
|
||||
)
|
||||
|
||||
// central command channels, i.e deathsquid & response teams
|
||||
var/list/CENT_FREQS = list(ERT_FREQ, DTH_FREQ)
|
||||
|
||||
// Antag channels, i.e. Syndicate
|
||||
var/list/ANTAG_FREQS = list(SYND_FREQ)
|
||||
|
||||
//depending helpers
|
||||
var/list/DEPT_FREQS = list(SCI_FREQ, MED_FREQ, ENG_FREQ, SEC_FREQ, SUP_FREQ, SRV_FREQ, ERT_FREQ, SYND_FREQ, DTH_FREQ)
|
||||
|
||||
#define TRANSMISSION_WIRE 0
|
||||
#define TRANSMISSION_RADIO 1
|
||||
|
||||
/proc/frequency_span_class(var/frequency)
|
||||
// Antags!
|
||||
if (frequency in ANTAG_FREQS)
|
||||
return "syndradio"
|
||||
// centcomm channels (deathsquid and ert)
|
||||
else if(frequency in CENT_FREQS)
|
||||
return "centradio"
|
||||
// command channel
|
||||
else if(frequency == COMM_FREQ)
|
||||
return "comradio"
|
||||
// AI private channel
|
||||
else if(frequency == AI_FREQ)
|
||||
return "airadio"
|
||||
// department radio formatting (poorly optimized, ugh)
|
||||
else if(frequency == SEC_FREQ)
|
||||
return "secradio"
|
||||
else if (frequency == ENG_FREQ)
|
||||
return "engradio"
|
||||
else if(frequency == SCI_FREQ)
|
||||
return "sciradio"
|
||||
else if(frequency == MED_FREQ)
|
||||
return "medradio"
|
||||
else if(frequency == SUP_FREQ) // cargo
|
||||
return "supradio"
|
||||
else if(frequency == SRV_FREQ) // service
|
||||
return "srvradio"
|
||||
// If all else fails and it's a dept_freq, color me purple!
|
||||
else if(frequency in DEPT_FREQS)
|
||||
return "deptradio"
|
||||
|
||||
return "radio"
|
||||
|
||||
/* filters */
|
||||
var/const/RADIO_TO_AIRALARM = "1"
|
||||
var/const/RADIO_FROM_AIRALARM = "2"
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
var/list/station_levels = list(1) // Defines which Z-levels the station exists on.
|
||||
var/list/admin_levels= list(2) // Defines which Z-levels which are for admin functionality, for example including such areas as Central Command and the Syndicate Shuttle
|
||||
var/list/contact_levels = list(1, 5) // Defines which Z-levels which, for example, a Code Red announcement may affect
|
||||
var/list/player_levels = list(1, 3, 4, 5, 6) // Defines all Z-levels a character can typically reach
|
||||
var/list/player_levels = list(1, 3, 4, 5, 6, 7) // Defines all Z-levels a character can typically reach
|
||||
|
||||
var/const/minutes_to_ticks = 60 * 10
|
||||
// Event settings
|
||||
|
||||
@@ -21,11 +21,24 @@ var/const/WIRE_TRANSMIT = 4
|
||||
var/obj/item/device/radio/R = holder
|
||||
switch(index)
|
||||
if(WIRE_SIGNAL)
|
||||
R.listening = !R.listening
|
||||
R.broadcasting = R.listening
|
||||
R.listening = !R.listening && !IsIndexCut(WIRE_RECEIVE)
|
||||
R.broadcasting = R.listening && !IsIndexCut(WIRE_TRANSMIT)
|
||||
|
||||
if(WIRE_RECEIVE)
|
||||
R.listening = !R.listening
|
||||
R.listening = !R.listening && !IsIndexCut(WIRE_SIGNAL)
|
||||
|
||||
if(WIRE_TRANSMIT)
|
||||
R.broadcasting = !R.broadcasting
|
||||
R.broadcasting = !R.broadcasting && !IsIndexCut(WIRE_SIGNAL)
|
||||
|
||||
/datum/wires/radio/UpdateCut(var/index, var/mended)
|
||||
var/obj/item/device/radio/R = holder
|
||||
switch(index)
|
||||
if(WIRE_SIGNAL)
|
||||
R.listening = mended && !IsIndexCut(WIRE_RECEIVE)
|
||||
R.broadcasting = mended && !IsIndexCut(WIRE_TRANSMIT)
|
||||
|
||||
if(WIRE_RECEIVE)
|
||||
R.listening = mended && !IsIndexCut(WIRE_SIGNAL)
|
||||
|
||||
if(WIRE_TRANSMIT)
|
||||
R.broadcasting = mended && !IsIndexCut(WIRE_SIGNAL)
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
#define TELECOMMS_RECEPTION_NONE 0
|
||||
#define TELECOMMS_RECEPTION_SENDER 1
|
||||
#define TELECOMMS_RECEPTION_RECEIVER 2
|
||||
#define TELECOMMS_RECEPTION_BOTH 3
|
||||
|
||||
/proc/get_frequency_name(var/display_freq)
|
||||
var/freq_text
|
||||
|
||||
// the name of the channel
|
||||
if(display_freq in ANTAG_FREQS)
|
||||
freq_text = "#unkn"
|
||||
else
|
||||
for(var/channel in radiochannels)
|
||||
if(radiochannels[channel] == display_freq)
|
||||
freq_text = channel
|
||||
break
|
||||
|
||||
// --- If the frequency has not been assigned a name, just use the frequency as the name ---
|
||||
if(!freq_text)
|
||||
freq_text = format_frequency(display_freq)
|
||||
|
||||
return freq_text
|
||||
|
||||
/datum/reception
|
||||
var/obj/machinery/message_server/message_server = null
|
||||
var/telecomms_reception = TELECOMMS_RECEPTION_NONE
|
||||
var/message = ""
|
||||
|
||||
/datum/receptions
|
||||
var/obj/machinery/message_server/message_server = null
|
||||
var/sender_reception = TELECOMMS_RECEPTION_NONE
|
||||
var/list/receiver_reception = new
|
||||
|
||||
/proc/get_message_server()
|
||||
if(message_servers)
|
||||
for (var/obj/machinery/message_server/MS in message_servers)
|
||||
if(MS.active)
|
||||
return MS
|
||||
return null
|
||||
|
||||
/proc/check_signal(var/datum/signal/signal)
|
||||
return signal && signal.data["done"]
|
||||
|
||||
/proc/get_sender_reception(var/atom/sender, var/datum/signal/signal)
|
||||
return check_signal(signal) ? TELECOMMS_RECEPTION_SENDER : TELECOMMS_RECEPTION_NONE
|
||||
|
||||
/proc/get_receiver_reception(var/receiver, var/datum/signal/signal)
|
||||
if(receiver && check_signal(signal))
|
||||
var/turf/pos = get_turf(receiver)
|
||||
if(pos && (pos.z in signal.data["level"]))
|
||||
return TELECOMMS_RECEPTION_RECEIVER
|
||||
return TELECOMMS_RECEPTION_NONE
|
||||
|
||||
/proc/get_reception(var/atom/sender, var/receiver, var/message = "", var/do_sleep = 1)
|
||||
var/datum/reception/reception = new
|
||||
|
||||
// check if telecomms I/O route 1459 is stable
|
||||
reception.message_server = get_message_server()
|
||||
|
||||
var/datum/signal/signal = sender.telecomms_process(do_sleep) // Be aware that this proc calls sleep, to simulate transmition delays
|
||||
reception.telecomms_reception |= get_sender_reception(sender, signal)
|
||||
reception.telecomms_reception |= get_receiver_reception(receiver, signal)
|
||||
reception.message = signal && signal.data["compression"] > 0 ? Gibberish(message, signal.data["compression"] + 50) : message
|
||||
|
||||
return reception
|
||||
|
||||
/proc/get_receptions(var/atom/sender, var/list/atom/receivers, var/do_sleep = 1)
|
||||
var/datum/receptions/receptions = new
|
||||
receptions.message_server = get_message_server()
|
||||
|
||||
var/datum/signal/signal
|
||||
if(sender)
|
||||
signal = sender.telecomms_process(do_sleep)
|
||||
receptions.sender_reception = get_sender_reception(sender, signal)
|
||||
|
||||
for(var/atom/receiver in receivers)
|
||||
if(!signal)
|
||||
signal = receiver.telecomms_process()
|
||||
receptions.receiver_reception[receiver] = get_receiver_reception(receiver, signal)
|
||||
|
||||
return receptions
|
||||
@@ -2268,6 +2268,7 @@ area/security/podbay
|
||||
|
||||
/area/awaycontent
|
||||
name = "space"
|
||||
report_alerts = 0
|
||||
|
||||
/area/awaycontent/a1
|
||||
icon_state = "awaycontent1"
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// flags: See below, bitfield.
|
||||
#define MUTCHK_FORCED 1
|
||||
/proc/domutcheck(var/mob/living/M, var/connected=null, var/flags=0)
|
||||
|
||||
for(var/datum/dna/gene/gene in dna_genes)
|
||||
if(!M || !M.dna)
|
||||
return
|
||||
@@ -75,6 +76,14 @@
|
||||
var/gene_active = (gene.flags & GENE_ALWAYS_ACTIVATE)
|
||||
if(!gene_active)
|
||||
gene_active = M.dna.GetSEState(gene.block)
|
||||
|
||||
var/defaultgenes // Do not mutate inherent species abilities
|
||||
if(ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
defaultgenes = H.species.default_genes
|
||||
|
||||
if((gene in defaultgenes) && gene_active)
|
||||
return
|
||||
|
||||
// Prior state
|
||||
var/gene_prior_status = (gene.type in M.active_genes)
|
||||
|
||||
@@ -335,7 +335,7 @@
|
||||
|
||||
if(L)
|
||||
usr.attack_log += text("\[[time_stamp()]\] <font color='red'>[usr.real_name] ([usr.ckey]) cast the spell [name] on [L.real_name] ([L.ckey]).</font>")
|
||||
msg_admin_attack("[usr.real_name] ([usr.ckey]) has cast the spell [name] on [L.real_name] ([L.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
|
||||
msg_admin_attack("[usr.real_name] ([usr.ckey]) has cast the spell [name] on [L.real_name] ([L.ckey]) (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
|
||||
|
||||
L.adjust_fire_stacks(0.5)
|
||||
L.visible_message("\red <b>[L.name]</b> suddenly bursts into flames!")
|
||||
|
||||
@@ -162,12 +162,12 @@
|
||||
H.visible_message("\red [usr] sprays a cloud of fine ice crystals, engulfing [H]!",
|
||||
"<span class='notice'>[usr] sprays a cloud of fine ice crystals over your [H.head]'s visor.</span>")
|
||||
log_admin("[ckey(usr.key)] has used cryokinesis on [ckey(C.key)], internals yes, suit yes")
|
||||
msg_admin_attack("[usr.real_name] ([usr.ckey]) has cast cryokinesis on [C.real_name] ([C.ckey]), (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
|
||||
msg_admin_attack("[usr.real_name] ([usr.ckey]) has cast cryokinesis on [C.real_name] ([C.ckey]), (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
|
||||
else
|
||||
H.visible_message("\red [usr] sprays a cloud of fine ice crystals engulfing, [H]!",
|
||||
"<span class='warning'>[usr] sprays a cloud of fine ice crystals cover your [H.head]'s visor and make it into your air vents!.</span>")
|
||||
log_admin("[usr.real_name] ([ckey(usr.key)]) has used cryokinesis on [C.real_name] ([ckey(C.key)]), (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>)")
|
||||
msg_admin_attack("[usr.real_name] ([usr.ckey]) has cast cryokinesis on [C.real_name] ([C.ckey]), (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
|
||||
msg_admin_attack("[usr.real_name] ([usr.ckey]) has cast cryokinesis on [C.real_name] ([C.ckey]), (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
|
||||
H.bodytemperature = max(0, H.bodytemperature - 50)
|
||||
H.adjustFireLoss(5)
|
||||
if(!handle_suit)
|
||||
@@ -177,7 +177,7 @@
|
||||
|
||||
C.visible_message("\red [usr] sprays a cloud of fine ice crystals, engulfing [C]!")
|
||||
log_admin("[ckey(usr.key)] has used cryokinesis on [ckey(C.key)], internals no, suit no")
|
||||
msg_admin_attack("[usr.real_name] ([usr.ckey]) has cast cryokinesis on [C.real_name] ([C.ckey]), (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
|
||||
msg_admin_attack("[usr.real_name] ([usr.ckey]) has cast cryokinesis on [C.real_name] ([C.ckey]), (<A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[usr.x];Y=[usr.y];Z=[usr.z]'>JMP</a>)")
|
||||
|
||||
//playsound(usr.loc, 'bamf.ogg', 50, 0)
|
||||
|
||||
|
||||
@@ -310,13 +310,4 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
|
||||
user << "<span class='warning'>We already have this DNA in storage!</span>"
|
||||
|
||||
return 1
|
||||
|
||||
//More snowflake stuff, but for languages.
|
||||
/datum/changeling/proc/changeling_update_languages(var/updated_languages, var/mob/living/carbon/user)
|
||||
if(!istype(user) || !user)
|
||||
return
|
||||
user.languages = list()
|
||||
for(var/language in updated_languages)
|
||||
user.languages += language
|
||||
|
||||
return
|
||||
|
||||
@@ -360,10 +360,11 @@ var/list/sting_paths
|
||||
sting_paths = init_subtypes(/obj/effect/proc_holder/changeling)
|
||||
if(mind.changeling.purchasedpowers)
|
||||
remove_changeling_powers(1)
|
||||
|
||||
add_language("Changeling")
|
||||
|
||||
for(var/language in languages)
|
||||
if(!(language in mind.changeling.absorbed_languages))
|
||||
mind.changeling.absorbed_languages += language
|
||||
mind.changeling.absorbed_languages |= language
|
||||
|
||||
// purchase free powers.
|
||||
for(var/obj/effect/proc_holder/changeling/path in sting_paths)
|
||||
@@ -376,6 +377,17 @@ var/list/sting_paths
|
||||
var/mob/living/carbon/C = src //only carbons have dna now, so we have to typecaste
|
||||
mind.changeling.absorbed_dna |= C.dna
|
||||
return 1
|
||||
|
||||
//Used to dump the languages from the changeling datum into the actual mob.
|
||||
/mob/proc/changeling_update_languages(var/updated_languages)
|
||||
|
||||
for(var/datum/language/L in updated_languages)
|
||||
add_language("L.name")
|
||||
|
||||
//This isn't strictly necessary but just to be safe...
|
||||
add_language("Changeling")
|
||||
|
||||
return
|
||||
|
||||
/datum/changeling/proc/reset()
|
||||
chosen_sting = null
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
for(var/language in T.languages)
|
||||
if(!(language in absorbed_languages))
|
||||
absorbed_languages += language
|
||||
changeling_update_languages(absorbed_languages, user)
|
||||
T.changeling_update_languages(absorbed_languages)
|
||||
|
||||
absorbedcount++
|
||||
store_dna(new_dna, user)
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
I.implanted = O
|
||||
|
||||
user.mind.transfer_to(O)
|
||||
O.mind.changeling.changeling_update_languages(changeling.absorbed_languages)
|
||||
O.changeling_update_languages(changeling.absorbed_languages)
|
||||
O.mind.changeling.purchasedpowers -= src
|
||||
//O.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/lesserform(null)
|
||||
feedback_add_details("changeling_powers","LFT")
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
|
||||
C.mind.transfer_to(O)
|
||||
O.mind.changeling.purchasedpowers += new /obj/effect/proc_holder/changeling/humanform(null)
|
||||
O.mind.changeling.changeling_update_languages(changeling.absorbed_languages)
|
||||
O.changeling_update_languages(changeling.absorbed_languages)
|
||||
|
||||
feedback_add_details("changeling_powers","LF")
|
||||
qdel(C)
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
user.set_species()
|
||||
user.UpdateAppearance()
|
||||
domutcheck(user, null)
|
||||
|
||||
user.changeling_update_languages(changeling.absorbed_languages)
|
||||
|
||||
feedback_add_details("changeling_powers","TR")
|
||||
return 1
|
||||
|
||||
@@ -1351,21 +1351,21 @@ ________________________________________________________________________________
|
||||
var/chance = rand(1,100)
|
||||
switch(chance)
|
||||
if(1 to 70)//High chance of a regular name.
|
||||
voice = "[rand(0,1)==1?pick(first_names_female):pick(first_names_male)] [pick(last_names)]"
|
||||
changer.voice = "[rand(0,1)==1?pick(first_names_female):pick(first_names_male)] [pick(last_names)]"
|
||||
if(71 to 80)//Smaller chance of a clown name.
|
||||
voice = "[pick(clown_names)]"
|
||||
changer.voice = "[pick(clown_names)]"
|
||||
if(81 to 90)//Small chance of a wizard name.
|
||||
voice = "[pick(wizard_first)] [pick(wizard_second)]"
|
||||
changer.voice = "[pick(wizard_first)] [pick(wizard_second)]"
|
||||
if(91 to 100)//Small chance of an existing crew name.
|
||||
var/names[] = new()
|
||||
for(var/mob/living/carbon/human/M in player_list)
|
||||
if(M==U||!M.client||!M.real_name) continue
|
||||
names.Add(M.real_name)
|
||||
voice = !names.len ? "Cuban Pete" : pick(names)
|
||||
U << "You are now mimicking <B>[voice]</B>."
|
||||
changer.voice = !names.len ? "Cuban Pete" : pick(names)
|
||||
U << "You are now mimicking <B>[changer.voice]</B>."
|
||||
else
|
||||
U << "The voice synthesizer is [voice!="Unknown"?"now":"already"] deactivated."
|
||||
voice = "Unknown"
|
||||
U << "The voice synthesizer is [changer.voice!="Unknown"?"now":"already"] deactivated."
|
||||
changer.voice = "Unknown"
|
||||
return
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/space_ninja/proc/switchm()
|
||||
@@ -1408,7 +1408,7 @@ ________________________________________________________________________________
|
||||
if(3)
|
||||
mode = "Meson Scanner"
|
||||
usr << "<B>[mode]</B> is active."//Leaving usr here since it may be on the floor or on a person.
|
||||
usr << "Voice mimicking algorithm is set <B>[!vchange?"inactive":"active"]</B>."
|
||||
usr << "Voice mimicking algorithm is set <B>[!changer.active?"inactive":"active"]</B>."
|
||||
|
||||
|
||||
/*
|
||||
|
||||
@@ -132,6 +132,7 @@ proc/issyndicate(mob/living/M as mob)
|
||||
synd_mind.current.loc = synd_spawn[spawnpos]
|
||||
|
||||
forge_syndicate_objectives(synd_mind)
|
||||
create_syndicate(synd_mind)
|
||||
greet_syndicate(synd_mind)
|
||||
equip_syndicate(synd_mind.current)
|
||||
|
||||
@@ -162,7 +163,38 @@ proc/issyndicate(mob/living/M as mob)
|
||||
spawn (rand(waittime_l, waittime_h))
|
||||
send_intercept()
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/proc/create_syndicate(var/datum/mind/synd_mind) // So we don't have inferior species as ops - randomize a human
|
||||
var/mob/living/carbon/human/M = synd_mind.current
|
||||
M.set_species("Human",1)
|
||||
M.dna.ready_dna(M) // Quadriplegic Nuke Ops won't be participating in the paralympics
|
||||
|
||||
var/hair_c = pick("#8B4513","#000000","#FF4500","#FFD700") // Brown, black, red, blonde
|
||||
var/eye_c = pick("#000000","#8B4513","1E90FF") // Black, brown, blue
|
||||
var/skin_tone = pick(35, 60, 75, 90, 105, 120, 135, 150) // Caucasian - black
|
||||
var/hair_style = "Bald"
|
||||
var/facial_hair_style = "Shaved"
|
||||
if(M.gender == MALE)
|
||||
hair_style = pick(hair_styles_male_list)
|
||||
facial_hair_style = pick(facial_hair_styles_list)
|
||||
else
|
||||
hair_style = pick(hair_styles_female_list)
|
||||
if(prob(5))
|
||||
facial_hair_style = pick(facial_hair_styles_list)
|
||||
|
||||
M.r_facial = hex2num(copytext(hair_c, 2, 4))
|
||||
M.g_facial = hex2num(copytext(hair_c, 4, 6))
|
||||
M.b_facial = hex2num(copytext(hair_c, 6, 8))
|
||||
M.r_hair = hex2num(copytext(hair_c, 2, 4))
|
||||
M.g_hair = hex2num(copytext(hair_c, 4, 6))
|
||||
M.b_hair = hex2num(copytext(hair_c, 6, 8))
|
||||
M.r_eyes = hex2num(copytext(eye_c, 2, 4))
|
||||
M.g_eyes = hex2num(copytext(eye_c, 4, 6))
|
||||
M.b_eyes = hex2num(copytext(eye_c, 6, 8))
|
||||
M.s_tone = skin_tone + 35
|
||||
M.s_tone = -M.s_tone + 35
|
||||
M.h_style = hair_style
|
||||
M.f_style = facial_hair_style
|
||||
|
||||
/datum/game_mode/proc/prepare_syndicate_leader(var/datum/mind/synd_mind, var/nuke_code)
|
||||
var/leader_title = pick("Czar", "Boss", "Commander", "Chief", "Kingpin", "Director", "Overlord")
|
||||
|
||||
@@ -23,10 +23,7 @@ var/bomb_set
|
||||
var/timing_wire
|
||||
var/removal_stage = 0 // 0 is no removal, 1 is covers removed, 2 is covers open, 3 is sealant open, 4 is unwrenched, 5 is removed from bolts.
|
||||
var/lastentered
|
||||
var/data[0]
|
||||
var/uiwidth
|
||||
var/uiheight
|
||||
var/uititle
|
||||
flags = FPRINT
|
||||
use_power = 0
|
||||
unacidable = 1
|
||||
|
||||
@@ -84,7 +81,7 @@ var/bomb_set
|
||||
|
||||
if (istype(O, /obj/item/device/multitool) || istype(O, /obj/item/weapon/wirecutters))
|
||||
ui_interact(user)
|
||||
|
||||
|
||||
if (src.extended)
|
||||
if (istype(O, /obj/item/weapon/disk/nuclear))
|
||||
usr.drop_item()
|
||||
@@ -186,8 +183,12 @@ var/bomb_set
|
||||
|
||||
obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob)
|
||||
ui_interact(user)
|
||||
|
||||
|
||||
/obj/machinery/nuclearbomb/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/data[0]
|
||||
var/uiwidth
|
||||
var/uiheight
|
||||
var/uititle
|
||||
if(!src.opened)
|
||||
data["hacking"] = 0
|
||||
data["auth"] = src.auth
|
||||
@@ -197,12 +198,12 @@ obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob)
|
||||
else
|
||||
data["authstatus"] = "Auth. S2"
|
||||
else
|
||||
if (src.timing)
|
||||
if (src.timing)
|
||||
data["authstatus"] = "Set"
|
||||
else
|
||||
data["authstatus"] = "Auth. S1"
|
||||
data["safe"] = src.safety ? "Safe" : "Engaged"
|
||||
data["time"] = src.timeleft
|
||||
data["safe"] = src.safety ? "Safe" : "Engaged"
|
||||
data["time"] = src.timeleft
|
||||
data["timer"] = src.timing
|
||||
data["safety"] = src.safety
|
||||
data["anchored"] = src.anchored
|
||||
@@ -217,7 +218,7 @@ obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob)
|
||||
uititle = "Nuke Control Panel"
|
||||
else
|
||||
data["hacking"] = 1
|
||||
var/list/tempwires[0]
|
||||
var/list/tempwires[0]
|
||||
for(var/wire in src.wires)
|
||||
tempwires.Add(list(list("name" = wire, "cut" = src.wires[wire])))
|
||||
data["wires"] = tempwires
|
||||
@@ -227,10 +228,10 @@ obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob)
|
||||
uiwidth = 420
|
||||
uiheight = 440
|
||||
uititle = "Nuclear Bomb Defusion"
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "nuclear_bomb.tmpl", uititle, uiwidth, uiheight)
|
||||
ui.set_initial_data(data)
|
||||
ui.set_initial_data(data)
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/nuclearbomb/verb/make_deployable()
|
||||
@@ -337,8 +338,8 @@ obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob)
|
||||
if (src.timing == -1.0)
|
||||
return
|
||||
if (src.safety)
|
||||
usr << "\red The safety is still on."
|
||||
nanomanager.update_uis(src)
|
||||
usr << "\red The safety is still on."
|
||||
nanomanager.update_uis(src)
|
||||
return
|
||||
src.timing = !( src.timing )
|
||||
if (src.timing)
|
||||
@@ -426,7 +427,7 @@ obj/machinery/nuclearbomb/proc/nukehack_win(mob/user as mob)
|
||||
if(ticker.mode.name == "nuclear emergency")
|
||||
ticker.mode:nukes_left --
|
||||
else if(off_station == 1)
|
||||
world << "<b>A nuclear device was set off, but the explosion was out of reach of the station!</b>"
|
||||
world << "<b>A nuclear device was set off, but the explosion was out of reach of the station!</b>"
|
||||
else if(off_station == 2)
|
||||
world << "<b>A nuclear device was set off, but the device was not on the station!</b>"
|
||||
else
|
||||
|
||||
@@ -727,10 +727,14 @@ datum/objective/absorb
|
||||
var/n_p = 1 //autowin
|
||||
if (ticker.current_state == GAME_STATE_SETTING_UP)
|
||||
for(var/mob/new_player/P in player_list)
|
||||
if(P.client && P.ready && P.mind!=owner)
|
||||
if(P.client && P.ready && P.mind != owner)
|
||||
if(P.client.prefs && (P.client.prefs.species == "Vox" || P.client.prefs.species == "Slime People" || P.client.prefs.species == "Machine")) // Special check for species that can't be absorbed. No better solution.
|
||||
continue
|
||||
n_p ++
|
||||
else if (ticker.current_state == GAME_STATE_PLAYING)
|
||||
for(var/mob/living/carbon/human/P in player_list)
|
||||
if((P.species.flags & IS_SYNTHETIC) || (P.species.flags & NO_SCAN))
|
||||
continue
|
||||
if(P.client && !(P.mind in ticker.mode.changelings) && P.mind!=owner)
|
||||
n_p ++
|
||||
target_amount = min(target_amount, n_p)
|
||||
|
||||
@@ -134,22 +134,6 @@
|
||||
|
||||
//testing("DNA2: [numsToAssign.len] blocks are unused: [english_list(numsToAssign)]")
|
||||
|
||||
// Run AFTER genetics setup and AFTER species setup.
|
||||
/proc/setup_species()
|
||||
// SPECIES GENETICS FUN
|
||||
for(var/name in all_species)
|
||||
// I hate BYOND. Can't just call while it's in the list.
|
||||
var/datum/species/species = all_species[name]
|
||||
if(species.default_block_names.len>0)
|
||||
testing("Setting up genetics for [species.name] (needs [english_list(species.default_block_names)])")
|
||||
species.default_blocks.Cut()
|
||||
for(var/block=1;block<DNA_SE_LENGTH;block++)
|
||||
if(assigned_blocks[block] in species.default_block_names)
|
||||
testing(" Found [assigned_blocks[block]] ([block])")
|
||||
species.default_blocks.Add(block)
|
||||
if(species.default_blocks.len)
|
||||
all_species[name]=species
|
||||
|
||||
/proc/setupfactions()
|
||||
|
||||
// Populate the factions list:
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
var/remote_disabled = 0 //If enabled, the AI cannot *Remotely* control a bot. It can still control it through cameras.
|
||||
var/mob/living/silicon/ai/calling_ai //Links a bot to the AI calling it.
|
||||
var/obj/item/device/radio/Radio //The bot's radio, for speaking to people.
|
||||
var/radio_frequency //The bot's default radio speaking freqency. Recommended to be on a department frequency.
|
||||
var/radio_name = "Common"
|
||||
//var/emagged = 0 //Urist: Moving that var to the general /bot tree as it's used by most bots
|
||||
var/auto_patrol = 0// set to make bot automatically patrol
|
||||
@@ -339,11 +338,9 @@
|
||||
/obj/machinery/bot/attack_ai(mob/user as mob)
|
||||
attack_hand(user)
|
||||
|
||||
/obj/machinery/bot/proc/speak(var/message, freq, var/freqname = null) //Pass a message to have the bot say() it. Pass a frequency to say it on the radio.
|
||||
/obj/machinery/bot/proc/speak(var/message, var/freqname = null) //Pass a message to have the bot say() it. Pass a frequency to say it on the radio.
|
||||
if((!on) || (!message))
|
||||
return
|
||||
if(freq)
|
||||
Radio.set_frequency(radio_frequency)
|
||||
if(freqname)
|
||||
Radio.autosay(message, src.name, freqname, list(src.z))
|
||||
else
|
||||
@@ -654,7 +651,7 @@ obj/machinery/bot/proc/start_patrol()
|
||||
botcard.access = user_access + prev_access //Adds the user's access, if any.
|
||||
mode = BOT_SUMMON
|
||||
calc_summon_path()
|
||||
speak("Responding.", radio_frequency, radio_name)
|
||||
speak("Responding.", radio_name)
|
||||
return
|
||||
|
||||
// receive response from beacon
|
||||
@@ -741,7 +738,7 @@ obj/machinery/bot/proc/bot_summon()
|
||||
check_bot_access()
|
||||
path = AStar(loc, summon_target, /turf/proc/CardinalTurfsWithAccess, /turf/proc/Distance_cardinal, 0, 150, id=botcard, exclude=avoid)
|
||||
if(!path || tries >= 5) //Cannot reach target. Give up and announce the issue.
|
||||
speak("Summon command failed, destination unreachable.", radio_frequency, radio_name)
|
||||
speak("Summon command failed, destination unreachable.", radio_name)
|
||||
bot_reset()
|
||||
|
||||
/obj/machinery/bot/proc/summon_step()
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
var/failed_steps
|
||||
var/next_dest
|
||||
var/next_dest_loc
|
||||
radio_frequency = SRV_FREQ //Service
|
||||
radio_name = "Service"
|
||||
bot_type = CLEAN_BOT
|
||||
bot_type_name = "Cleanbot"
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
var/arrest_type = 0 //If true, don't handcuff
|
||||
var/projectile = /obj/item/projectile/energy/electrode //Holder for projectile type
|
||||
var/shoot_sound = 'sound/weapons/Taser.ogg'
|
||||
radio_frequency = SEC_FREQ
|
||||
radio_name = "Security"
|
||||
bot_type = SEC_BOT
|
||||
bot_type_name = "ED-209"
|
||||
@@ -269,7 +268,7 @@ Auto Patrol[]"},
|
||||
|
||||
if(declare_arrests)
|
||||
var/area/location = get_area(src)
|
||||
speak("[arrest_type ? "Detaining" : "Arresting"] level [threatlevel] scumbag <b>[target]</b> in [location].",radio_frequency, radio_name)
|
||||
speak("[arrest_type ? "Detaining" : "Arresting"] level [threatlevel] scumbag <b>[target]</b> in [location].", radio_name)
|
||||
target.visible_message("<span class='danger'>[target] has been stunned by [src]!</span>",\
|
||||
"<span class='userdanger'>[target] has been stunned by [src]!</span></span>")
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@
|
||||
var/oldloc = null
|
||||
req_one_access = list(access_construction, access_robotics)
|
||||
var/targetdirection
|
||||
radio_frequency = ENG_FREQ //Engineering channel
|
||||
radio_name = "Engineering"
|
||||
bot_type = FLOOR_BOT
|
||||
bot_type_name = "Floorbot"
|
||||
@@ -318,7 +317,7 @@
|
||||
/obj/machinery/bot/floorbot/proc/nag() //Annoy everyone on the channel to refill us!
|
||||
if(!nagged)
|
||||
var/area/location = get_area(src)
|
||||
speak("Requesting refill at <b>[location]</b>!", radio_frequency, radio_name)
|
||||
speak("Requesting refill at <b>[location]</b>!", radio_name)
|
||||
nagged = 1
|
||||
|
||||
/obj/machinery/bot/floorbot/proc/is_hull_breach(var/turf/t) //Ignore space tiles not considered part of a structure, also ignores shuttle docking areas.
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
var/declare_crit = 1 //If active, the bot will transmit a critical patient alert to MedHUD users.
|
||||
var/declare_cooldown = 0 //Prevents spam of critical patient alerts.
|
||||
var/stationary_mode = 0 //If enabled, the Medibot will not move automatically.
|
||||
radio_frequency = MED_FREQ //Medical frequency
|
||||
radio_name = "Medical"
|
||||
//Setting which reagents to use to treat what by default. By id.
|
||||
var/treatment_brute = "tricordrazine"
|
||||
@@ -533,7 +532,7 @@
|
||||
if((skin == "bezerk"))
|
||||
return
|
||||
var/area/location = get_area(src)
|
||||
speak("Medical emergency! [crit_patient ? "<b>[crit_patient]</b>" : "A patient"] is in critical condition at [location]!",radio_frequency, radio_name)
|
||||
speak("Medical emergency! [crit_patient ? "<b>[crit_patient]</b>" : "A patient"] is in critical condition at [location]!", radio_name)
|
||||
declare_cooldown = 1
|
||||
spawn(200) //Twenty seconds
|
||||
declare_cooldown = 0
|
||||
|
||||
@@ -71,7 +71,7 @@ var/global/mulebot_count = 0
|
||||
cell.charge = 2000
|
||||
cell.maxcharge = 2000
|
||||
|
||||
spawn(5) // must wait for map loading to finish
|
||||
spawn(50) // must wait for map loading to finish
|
||||
add_to_beacons(bot_filter)
|
||||
|
||||
mulebot_count += 1
|
||||
@@ -238,7 +238,7 @@ var/global/mulebot_count = 0
|
||||
|
||||
//user << browse("<HEAD><TITLE>M.U.L.E. Mk. III [suffix ? "([suffix])" : ""]</TITLE></HEAD>[dat]", "window=mulebot;size=350x500")
|
||||
//onclose(user, "mulebot")
|
||||
var/datum/browser/popup = new(user, "mulebot", "M.U.L.E. Mk. V [suffix ? "([suffix])" : ""]", 350, 535)
|
||||
var/datum/browser/popup = new(user, "mulebot", "M.U.L.E. Mk. V [suffix ? "([suffix])" : ""]", 350, 620)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(icon, icon_state))
|
||||
popup.open()
|
||||
@@ -313,6 +313,8 @@ var/global/mulebot_count = 0
|
||||
updateDialog()
|
||||
|
||||
if("destination")
|
||||
if(!delivery_beacons.len)
|
||||
post_signal(beacon_freq, "findbeacon", "delivery")
|
||||
refresh=0
|
||||
var/new_dest = input("Select M.U.L.E. Destination", "Mulebot [suffix ? "([suffix])" : ""]", destination) as null|anything in delivery_beacons
|
||||
refresh=1
|
||||
@@ -683,7 +685,6 @@ var/global/mulebot_count = 0
|
||||
// called when bot reaches current target
|
||||
/obj/machinery/bot/mulebot/proc/at_target()
|
||||
if(!reached_target)
|
||||
radio_frequency = SUP_FREQ //Supply channel
|
||||
radio_name = "Supply"
|
||||
Radio.config(list("[radio_name]" = 0))
|
||||
visible_message("[src] makes a chiming sound!", "You hear a chime.")
|
||||
@@ -696,12 +697,11 @@ var/global/mulebot_count = 0
|
||||
calling_ai << "<span class='notice'>\icon[src] [src] wirelessly plays a chiming sound!</span>"
|
||||
playsound(calling_ai, 'sound/machines/chime.ogg',40, 0)
|
||||
calling_ai = null
|
||||
radio_frequency = AIPRIV_FREQ //Report on AI Private instead if the AI is controlling us.
|
||||
radio_name = "AI Private"
|
||||
Radio.config(list("[radio_name]" = 0))
|
||||
|
||||
if(load) // if loaded, unload at target
|
||||
speak("Destination <b>[destination]</b> reached. Unloading [load].", radio_frequency, radio_name)
|
||||
speak("Destination <b>[destination]</b> reached. Unloading [load].", radio_name)
|
||||
unload(loaddir)
|
||||
else
|
||||
// not loaded
|
||||
@@ -717,7 +717,7 @@ var/global/mulebot_count = 0
|
||||
if(AM)
|
||||
load(AM)
|
||||
if(report_delivery)
|
||||
speak("Now loading [load] at <b>[get_area(src)]</b>.", radio_frequency, radio_name)
|
||||
speak("Now loading [load] at <b>[get_area(src)]</b>.", radio_name)
|
||||
// whatever happened, check to see if we return home
|
||||
|
||||
if(auto_return && destination != home_destination)
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
var/arrest_type = 0 //If true, don't handcuff
|
||||
var/harmbaton = 0
|
||||
var/base_icon = "secbot"
|
||||
radio_frequency = SEC_FREQ //Security channel
|
||||
radio_name = "Security"
|
||||
bot_type = SEC_BOT
|
||||
bot_type_name = "Secbot"
|
||||
@@ -50,7 +49,6 @@
|
||||
/obj/machinery/bot/secbot/pingsky
|
||||
name = "Officer Pingsky"
|
||||
desc = "It's Officer Pingsky! Delegated to satellite guard duty for harbouring anti-human sentiment."
|
||||
radio_frequency = AIPRIV_FREQ
|
||||
radio_name = "AI Private"
|
||||
|
||||
/obj/machinery/bot/secbot/ofitser
|
||||
@@ -256,7 +254,7 @@ Auto Patrol: []"},
|
||||
|
||||
if(declare_arrests)
|
||||
var/area/location = get_area(src)
|
||||
speak("[arrest_type ? "Detaining" : "Arresting"] level [threatlevel] scumbag <b>[target]</b> in [location].",radio_frequency, radio_name)
|
||||
speak("[arrest_type ? "Detaining" : "Arresting"] level [threatlevel] scumbag <b>[target]</b> in [location].", radio_name)
|
||||
target.visible_message("<span class='danger'>[target] has been [harmbaton ? "beaten" : "stunned"] by [src]!</span>",\
|
||||
"<span class='userdanger'>[target] has been [harmbaton ? "beaten" : "stunned"] by [src]!</span>")
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/mob/living/silicon/ai/proc/InvalidTurf(turf/T as turf)
|
||||
if(!T)
|
||||
return 1
|
||||
if((T.z in config.station_levels))
|
||||
if((T.z in config.admin_levels))
|
||||
return 1
|
||||
if(T.z > 6)
|
||||
return 1
|
||||
|
||||
@@ -81,13 +81,20 @@ var/const/HOLOPAD_MODE = 0
|
||||
|
||||
/*This is the proc for special two-way communication between AI and holopad/people talking near holopad.
|
||||
For the other part of the code, check silicon say.dm. Particularly robot talk.*/
|
||||
/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text, verb)
|
||||
/obj/machinery/hologram/holopad/hear_talk(mob/living/M, text, verb, datum/language/speaking)
|
||||
if(M&&hologram&&master)//Master is mostly a safety in case lag hits or something.
|
||||
if(!master.say_understands(M))//The AI will be able to understand most mobs talking through the holopad.
|
||||
text = stars(text)
|
||||
if(!master.say_understands(M, speaking))//The AI will be able to understand most mobs talking through the holopad.
|
||||
if(speaking)
|
||||
text = speaking.scramble(text)
|
||||
else
|
||||
text = stars(text)
|
||||
var/name_used = M.GetVoice()
|
||||
//This communication is imperfect because the holopad "filters" voices and is only designed to connect to the master only.
|
||||
var/rendered = "<i><span class='game say'>Holopad received, <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span></i>"
|
||||
var/rendered
|
||||
if(speaking)
|
||||
rendered = "<i><span class='game say'>Holopad received, <span class='name'>[name_used]</span> [speaking.format_message(text, verb)]</span></i>"
|
||||
else
|
||||
rendered = "<i><span class='game say'>Holopad received, <span class='name'>[name_used]</span> [verb], <span class='message'>\"[text]\"</span></span></i>"
|
||||
master.show_message(rendered, 2)
|
||||
return
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
use_power = 1
|
||||
idle_power_usage = 25
|
||||
machinetype = 5
|
||||
heatgen = 0
|
||||
delay = 7
|
||||
circuitboard = "/obj/item/weapon/circuitboard/telecomms/broadcaster"
|
||||
|
||||
@@ -59,7 +58,9 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
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"], signal.data["level"], signal.frequency)
|
||||
signal.data["realname"], signal.data["vname"],,
|
||||
signal.data["compression"], signal.data["level"], signal.frequency,
|
||||
signal.data["verb"], signal.data["language"] )
|
||||
|
||||
|
||||
/** #### - Simple Broadcast - #### **/
|
||||
@@ -84,7 +85,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
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["realname"], signal.data["vname"], 4, signal.data["compression"], signal.data["level"], signal.frequency,
|
||||
signal.data["verb"], signal.data["language"])
|
||||
|
||||
if(!message_delay)
|
||||
message_delay = 1
|
||||
@@ -95,7 +97,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
/* --- Do a snazzy animation! --- */
|
||||
flick("broadcaster_send", src)
|
||||
|
||||
/obj/machinery/telecomms/broadcaster/Destroy()
|
||||
/obj/machinery/telecomms/broadcaster/Del()
|
||||
// In case message_delay is left on 1, otherwise it won't reset the list and people can't say the same thing twice anymore.
|
||||
if(message_delay)
|
||||
message_delay = 0
|
||||
@@ -117,7 +119,6 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
use_power = 0
|
||||
idle_power_usage = 0
|
||||
machinetype = 6
|
||||
heatgen = 0
|
||||
var/intercept = 0 // if nonzero, broadcasts all messages to syndicate channel
|
||||
|
||||
/obj/machinery/telecomms/allinone/receive_signal(datum/signal/signal)
|
||||
@@ -142,19 +143,21 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
|
||||
var/datum/radio_frequency/connection = signal.data["connection"]
|
||||
|
||||
if(connection.frequency == SYND_FREQ) // if syndicate broadcast, just
|
||||
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["realname"], signal.data["vname"],, signal.data["compression"], list(0), connection.frequency,
|
||||
signal.data["verb"], signal.data["language"])
|
||||
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["realname"], signal.data["vname"], 3, signal.data["compression"], list(0), connection.frequency,
|
||||
signal.data["verb"], signal.data["language"])
|
||||
|
||||
|
||||
|
||||
@@ -218,7 +221,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/vmessage, var/obj/item/device/radio/radio,
|
||||
var/message, var/name, var/job, var/realname, var/vname,
|
||||
var/data, var/compression, var/list/level, var/freq)
|
||||
var/data, var/compression, var/list/level, var/freq, var/verbage = "says", var/datum/language/speaking = null)
|
||||
|
||||
|
||||
/* ###### Prepare the radio connection ###### */
|
||||
|
||||
@@ -246,16 +250,14 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
if(R.receive_range(display_freq, level) > -1)
|
||||
radios += R
|
||||
|
||||
// --- Broadcast to syndicate radio! ---
|
||||
// --- Broadcast to antag radios! ---
|
||||
|
||||
else if(data == 3)
|
||||
|
||||
var/datum/radio_frequency/syndicateconnection = radio_controller.return_frequency(SYND_FREQ)
|
||||
|
||||
for (var/obj/item/device/radio/R in syndicateconnection.devices["[RADIO_CHAT]"])
|
||||
|
||||
if(R.receive_range(SYND_FREQ, level) > -1)
|
||||
radios += R
|
||||
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
|
||||
|
||||
// --- Broadcast to ALL radio devices ---
|
||||
|
||||
@@ -283,6 +285,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
|
||||
/* --- Loop through the receivers and categorize them --- */
|
||||
|
||||
if (R.client && (R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
|
||||
continue
|
||||
|
||||
if(istype(R, /mob/new_player)) // we don't want new players to hear messages. rare but generates runtimes.
|
||||
continue
|
||||
@@ -324,88 +328,17 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled) || length(heard_gibberish))
|
||||
|
||||
/* --- Some miscellaneous variables to format the string output --- */
|
||||
var/part_a = "<span class='radio'><span class='name'>" // goes in the actual output
|
||||
var/freq_text // the name of the channel
|
||||
|
||||
// --- Set the name of the channel ---
|
||||
switch(display_freq)
|
||||
|
||||
if(SYND_FREQ)
|
||||
freq_text = "#unkn"
|
||||
if(COMM_FREQ)
|
||||
freq_text = "Command"
|
||||
if(1351)
|
||||
freq_text = "Science"
|
||||
if(1355)
|
||||
freq_text = "Medical"
|
||||
if(1357)
|
||||
freq_text = "Engineering"
|
||||
if(1359)
|
||||
freq_text = "Security"
|
||||
if(1347)
|
||||
freq_text = "Supply"
|
||||
if(1349)
|
||||
freq_text = "Service"
|
||||
if(1441)
|
||||
freq_text = "Special Ops"
|
||||
if(1443)
|
||||
freq_text = "Response Team"
|
||||
if(1447)
|
||||
freq_text = "AI Private"
|
||||
//There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO
|
||||
|
||||
|
||||
// --- If the frequency has not been assigned a name, just use the frequency as the name ---
|
||||
|
||||
if(!freq_text)
|
||||
freq_text = format_frequency(display_freq)
|
||||
|
||||
// --- Some more pre-message formatting ---
|
||||
var/freq_text = get_frequency_name(display_freq)
|
||||
|
||||
var/part_b_extra = ""
|
||||
if(data == 3) // intercepted radio message
|
||||
part_b_extra = " <i>(Intercepted)</i>"
|
||||
var/part_b = "</span><b> \icon[radio]\[[freq_text]\][part_b_extra]</b> <span class='message'>" // Tweaked for security headsets -- TLE
|
||||
var/part_a = "<span class='[frequency_span_class(display_freq)]'>\icon[radio]<b>\[[freq_text]\][part_b_extra]</b> <span class='name'>" // goes in the actual output
|
||||
|
||||
// --- Some more pre-message formatting ---
|
||||
var/part_b = "</span> <span class='message'>" // Tweaked for security headsets -- TLE
|
||||
var/part_c = "</span></span>"
|
||||
|
||||
// syndies!
|
||||
if (display_freq == SYND_FREQ)
|
||||
part_a = "<span class='syndradio'><span class='name'>"
|
||||
|
||||
// centcomm channels (deathsquid and ert)
|
||||
else if (display_freq in CENT_FREQS)
|
||||
part_a = "<span class='centradio'><span class='name'>"
|
||||
|
||||
// command channel
|
||||
else if (display_freq == COMM_FREQ)
|
||||
part_a = "<span class='comradio'><span class='name'>"
|
||||
|
||||
// AI private channel
|
||||
else if (display_freq == 1447)
|
||||
part_a = "<span class='airadio'><span class='name'>"
|
||||
|
||||
// department radio formatting (poorly optimized, ugh)
|
||||
else if (display_freq == SEC_FREQ)
|
||||
part_a = "<span class='secradio'><span class='name'>"
|
||||
|
||||
else if (display_freq == ENG_FREQ)
|
||||
part_a = "<span class='engradio'><span class='name'>"
|
||||
|
||||
else if (display_freq == SCI_FREQ)
|
||||
part_a = "<span class='sciradio'><span class='name'>"
|
||||
|
||||
else if (display_freq == MED_FREQ)
|
||||
part_a = "<span class='medradio'><span class='name'>"
|
||||
|
||||
else if (display_freq == SUP_FREQ) // cargo
|
||||
part_a = "<span class='supradio'><span class='name'>"
|
||||
|
||||
else if (display_freq == SRV_FREQ) // cargo
|
||||
part_a = "<span class='srvradio'><span class='name'>"
|
||||
// If all else fails and it's a dept_freq, color me purple!
|
||||
else if (display_freq in DEPT_FREQS)
|
||||
part_a = "<span class='deptradio'><span class='name'>"
|
||||
|
||||
|
||||
// --- Filter the message; place it in quotes apply a verb ---
|
||||
|
||||
@@ -424,133 +357,67 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
//BR.messages_admin += blackbox_admin_msg
|
||||
if(istype(blackbox))
|
||||
switch(display_freq)
|
||||
if(1459)
|
||||
if(PUB_FREQ)
|
||||
blackbox.msg_common += blackbox_msg
|
||||
if(1351)
|
||||
if(SCI_FREQ)
|
||||
blackbox.msg_science += blackbox_msg
|
||||
if(1353)
|
||||
if(COMM_FREQ)
|
||||
blackbox.msg_command += blackbox_msg
|
||||
if(1355)
|
||||
if(MED_FREQ)
|
||||
blackbox.msg_medical += blackbox_msg
|
||||
if(1357)
|
||||
if(ENG_FREQ)
|
||||
blackbox.msg_engineering += blackbox_msg
|
||||
if(1359)
|
||||
if(SEC_FREQ)
|
||||
blackbox.msg_security += blackbox_msg
|
||||
if(1441)
|
||||
if(DTH_FREQ)
|
||||
blackbox.msg_deathsquad += blackbox_msg
|
||||
if(1213)
|
||||
if(SYND_FREQ)
|
||||
blackbox.msg_syndicate += blackbox_msg
|
||||
if(1347)
|
||||
if(SUP_FREQ)
|
||||
blackbox.msg_cargo += blackbox_msg
|
||||
if(1349)
|
||||
if(SRV_FREQ)
|
||||
blackbox.msg_service += blackbox_msg
|
||||
else
|
||||
blackbox.messages += blackbox_msg
|
||||
|
||||
//End of research and feedback code.
|
||||
|
||||
var/aitrack = ""
|
||||
var/aiopen = ""
|
||||
/* ###### Send the message ###### */
|
||||
|
||||
|
||||
/* --- Process all the mobs that heard a masked voice (understood) --- */
|
||||
|
||||
if (length(heard_masked))
|
||||
var/N = name
|
||||
var/J = job
|
||||
var/rendered = "[part_a][N][part_b][quotedmsg][part_c]"
|
||||
for (var/mob/R in heard_masked)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];track=\ref[M]'>"
|
||||
aiopen = "<a href='byond://?src=\ref[radio];open2=\ref[R];open=\ref[M]'>\[OPEN\] </a>"
|
||||
if(data == 4)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];faketrack=\ref[M]'>"
|
||||
|
||||
if(istype(R, /mob/living/silicon/ai))
|
||||
R.show_message("[part_a][aitrack][N] ([J]) </a>[aiopen][part_b][quotedmsg][part_c]", 2)
|
||||
else
|
||||
R.show_message(rendered, 2)
|
||||
R.hear_radio(message,verbage, speaking, part_a, part_b, M, 0, name)
|
||||
|
||||
/* --- Process all the mobs that heard the voice normally (understood) --- */
|
||||
|
||||
if (length(heard_normal))
|
||||
var/rendered = "[part_a][realname][part_b][quotedmsg][part_c]"
|
||||
|
||||
for (var/mob/R in heard_normal)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];track=\ref[M]'>"
|
||||
aiopen = "<a href='byond://?src=\ref[radio];open2=\ref[R];open=\ref[M]'>\[OPEN\] </a>"
|
||||
if(data == 4)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];faketrack=\ref[M]'>"
|
||||
|
||||
if(istype(R, /mob/living/silicon/ai))
|
||||
R.show_message("[part_a][aitrack][realname] ([job]) </a>[aiopen][part_b][quotedmsg][part_c]", 2)
|
||||
else
|
||||
R.show_message(rendered, 2)
|
||||
R.hear_radio(message, verbage, speaking, part_a, part_b, M, 0, realname)
|
||||
|
||||
/* --- Process all the mobs that heard the voice normally (did not understand) --- */
|
||||
|
||||
if (length(heard_voice))
|
||||
var/rendered = "[part_a][vname][part_b][vmessage][part_c]"
|
||||
|
||||
for (var/mob/R in heard_voice)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];track=\ref[M]'>"
|
||||
aiopen = "<a href='byond://?src=\ref[radio];open2=\ref[R];open=\ref[M]'>\[OPEN\] </a>"
|
||||
if(data == 4)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];faketrack=\ref[M]'>"
|
||||
|
||||
|
||||
if(istype(R, /mob/living/silicon/ai))
|
||||
R.show_message("[part_a][aitrack][vname] ([job]) </a>[aiopen][part_b][vmessage]][part_c]", 2)
|
||||
else
|
||||
R.show_message(rendered, 2)
|
||||
R.hear_radio(message,verbage, speaking, part_a, part_b, M,0, vname)
|
||||
|
||||
/* --- Process all the mobs that heard a garbled voice (did not understand) --- */
|
||||
// Displays garbled message (ie "f*c* **u, **i*er!")
|
||||
|
||||
if (length(heard_garbled))
|
||||
if(M)
|
||||
quotedmsg = M.say_quote(stars(message))
|
||||
else
|
||||
quotedmsg = stars(quotedmsg)
|
||||
|
||||
var/rendered = "[part_a][vname][part_b][quotedmsg][part_c]"
|
||||
|
||||
for (var/mob/R in heard_garbled)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];track=\ref[M]'>"
|
||||
aiopen = "<a href='byond://?src=\ref[radio];open2=\ref[R];open=\ref[M]'>\[OPEN\] </a>"
|
||||
if(data == 4)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];faketrack=\ref[M]'>"
|
||||
|
||||
|
||||
if(istype(R, /mob/living/silicon/ai))
|
||||
R.show_message("[part_a][aitrack][vname]</a>[aiopen][part_b][quotedmsg][part_c]", 2)
|
||||
else
|
||||
R.show_message(rendered, 2)
|
||||
R.hear_radio(message, verbage, speaking, part_a, part_b, M, 1, vname)
|
||||
|
||||
|
||||
/* --- Complete gibberish. Usually happens when there's a compressed message --- */
|
||||
|
||||
if (length(heard_gibberish))
|
||||
if(M)
|
||||
quotedmsg = M.say_quote(Gibberish(message, compression + 50))
|
||||
else
|
||||
quotedmsg = Gibberish(quotedmsg, compression + 50)
|
||||
|
||||
var/rendered = "[part_a][Gibberish(name, compression + 50)][part_b][quotedmsg][part_c]"
|
||||
|
||||
for (var/mob/R in heard_gibberish)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];track=\ref[M]'>"
|
||||
aiopen = "<a href='byond://?src=\ref[radio];open2=\ref[R];open=\ref[M]'>\[OPEN\] </a>"
|
||||
if(data == 4)
|
||||
aitrack = "<a href='byond://?src=\ref[radio];track2=\ref[R];faketrack=\ref[M]'>"
|
||||
|
||||
|
||||
if(istype(R, /mob/living/silicon/ai))
|
||||
R.show_message("[part_a][aitrack][Gibberish(realname, compression + 50)] ([Gibberish(job, compression + 50)]) </a>[aiopen][part_b][quotedmsg][part_c]", 2)
|
||||
else
|
||||
R.show_message(rendered, 2)
|
||||
|
||||
R.hear_radio(message, verbage, speaking, part_a, part_b, M, 1)
|
||||
|
||||
return 1
|
||||
|
||||
/proc/Broadcast_SimpleMessage(var/source, var/frequency, var/text, var/data, var/mob/M, var/compression, var/level)
|
||||
|
||||
@@ -588,15 +455,15 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
receive |= R.send_hear(display_freq)
|
||||
|
||||
|
||||
// --- Broadcast to syndicate radio! ---
|
||||
// --- Broadcast to antag radios! ---
|
||||
|
||||
else if(data == 3)
|
||||
var/datum/radio_frequency/syndicateconnection = radio_controller.return_frequency(SYND_FREQ)
|
||||
|
||||
for (var/obj/item/device/radio/R in syndicateconnection.devices["[RADIO_CHAT]"])
|
||||
var/turf/position = get_turf(R)
|
||||
if(position && position.z == level)
|
||||
receive |= R.send_hear(SYND_FREQ)
|
||||
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]"])
|
||||
var/turf/position = get_turf(R)
|
||||
if(position && position.z == level)
|
||||
receive |= R.send_hear(freq)
|
||||
|
||||
|
||||
// --- Broadcast to ALL radio devices ---
|
||||
@@ -621,6 +488,8 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
|
||||
/* --- Loop through the receivers and categorize them --- */
|
||||
|
||||
if (R.client && !(R.client.prefs.toggles & CHAT_RADIO)) //Adminning with 80 people on can be fun when you're trying to talk and all you can hear is radios.
|
||||
continue
|
||||
|
||||
|
||||
// --- Check for compression ---
|
||||
@@ -648,34 +517,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
|
||||
/* --- Some miscellaneous variables to format the string output --- */
|
||||
var/part_a = "<span class='radio'><span class='name'>" // goes in the actual output
|
||||
var/freq_text // the name of the channel
|
||||
|
||||
// --- Set the name of the channel ---
|
||||
switch(display_freq)
|
||||
|
||||
if(SYND_FREQ)
|
||||
freq_text = "#unkn"
|
||||
if(COMM_FREQ)
|
||||
freq_text = "Command"
|
||||
if(1351)
|
||||
freq_text = "Science"
|
||||
if(1355)
|
||||
freq_text = "Medical"
|
||||
if(1357)
|
||||
freq_text = "Engineering"
|
||||
if(1359)
|
||||
freq_text = "Security"
|
||||
if(1347)
|
||||
freq_text = "Supply"
|
||||
if(1349)
|
||||
freq_text = "Service"
|
||||
//There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO
|
||||
|
||||
|
||||
// --- If the frequency has not been assigned a name, just use the frequency as the name ---
|
||||
|
||||
if(!freq_text)
|
||||
freq_text = format_frequency(display_freq)
|
||||
var/freq_text = get_frequency_name(display_freq)
|
||||
|
||||
// --- Some more pre-message formatting ---
|
||||
|
||||
@@ -689,7 +531,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
var/part_b = "</span><b> \icon[radio]\[[freq_text]\][part_b_extra]</b> <span class='message'>" // Tweaked for security headsets -- TLE
|
||||
var/part_c = "</span></span>"
|
||||
|
||||
if (display_freq==SYND_FREQ)
|
||||
if (display_freq in ANTAG_FREQS)
|
||||
part_a = "<span class='syndradio'><span class='name'>"
|
||||
else if (display_freq==COMM_FREQ)
|
||||
part_a = "<span class='comradio'><span class='name'>"
|
||||
@@ -705,25 +547,25 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
//BR.messages_admin += blackbox_admin_msg
|
||||
if(istype(blackbox))
|
||||
switch(display_freq)
|
||||
if(1459)
|
||||
if(PUB_FREQ)
|
||||
blackbox.msg_common += blackbox_msg
|
||||
if(1351)
|
||||
if(SCI_FREQ)
|
||||
blackbox.msg_science += blackbox_msg
|
||||
if(1353)
|
||||
if(COMM_FREQ)
|
||||
blackbox.msg_command += blackbox_msg
|
||||
if(1355)
|
||||
if(MED_FREQ)
|
||||
blackbox.msg_medical += blackbox_msg
|
||||
if(1357)
|
||||
if(ENG_FREQ)
|
||||
blackbox.msg_engineering += blackbox_msg
|
||||
if(1359)
|
||||
if(SEC_FREQ)
|
||||
blackbox.msg_security += blackbox_msg
|
||||
if(1441)
|
||||
if(DTH_FREQ)
|
||||
blackbox.msg_deathsquad += blackbox_msg
|
||||
if(1213)
|
||||
if(SYND_FREQ)
|
||||
blackbox.msg_syndicate += blackbox_msg
|
||||
if(1347)
|
||||
if(SUP_FREQ)
|
||||
blackbox.msg_cargo += blackbox_msg
|
||||
if(1349)
|
||||
if(SRV_FREQ)
|
||||
blackbox.msg_service += blackbox_msg
|
||||
else
|
||||
blackbox.messages += blackbox_msg
|
||||
@@ -767,7 +609,7 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
var/turf/position = get_turf(src)
|
||||
return (position.z in signal.data["level"] && signal.data["done"])
|
||||
|
||||
/atom/proc/telecomms_process()
|
||||
/atom/proc/telecomms_process(var/do_sleep = 1)
|
||||
|
||||
// First, we want to generate a new radio signal
|
||||
var/datum/signal/signal = new
|
||||
@@ -785,13 +627,14 @@ var/message_delay = 0 // To make sure restarting the recentmessages list is kept
|
||||
"done" = 0,
|
||||
"level" = pos.z // The level it is being broadcasted at.
|
||||
)
|
||||
signal.frequency = 1459// Common channel
|
||||
signal.frequency = PUB_FREQ// Common channel
|
||||
|
||||
//#### Sending the signal to all subspace receivers ####//
|
||||
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
|
||||
R.receive_signal(signal)
|
||||
|
||||
sleep(rand(10,25))
|
||||
if(do_sleep)
|
||||
sleep(rand(10,25))
|
||||
|
||||
//world.log << "Level: [signal.data["level"]] - Done: [signal.data["done"]]"
|
||||
|
||||
|
||||
@@ -161,19 +161,13 @@
|
||||
<table class="request">
|
||||
<tr>
|
||||
<td class="radio">Transmit:</td>
|
||||
<td><a href='byond://?src=\ref[src];wires=[WIRE_TRANSMIT]'>[(!radio.isWireCut(WIRE_TRANSMIT)) ? "<font color=#55FF55>En" : "<font color=#FF5555>Dis" ]abled</font></a>
|
||||
<td><a href='byond://?src=\ref[src];wires=4'>[radio.broadcasting ? "<font color=#55FF55>En" : "<font color=#FF5555>Dis" ]abled</font></a>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="radio">Receive:</td>
|
||||
<td><a href='byond://?src=\ref[src];wires=[WIRE_RECEIVE]'>[(!radio.isWireCut(WIRE_RECEIVE)) ? "<font color=#55FF55>En" : "<font color=#FF5555>Dis" ]abled</font></a>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="radio">Signal Pulser:</td>
|
||||
<td><a href='byond://?src=\ref[src];wires=[WIRE_SIGNAL]'>[(!radio.isWireCut(WIRE_SIGNAL)) ? "<font color=#55FF55>En" : "<font color=#FF5555>Dis" ]abled</font></a>
|
||||
<td><a href='byond://?src=\ref[src];wires=2'>[radio.listening ? "<font color=#55FF55>En" : "<font color=#FF5555>Dis" ]abled</font></a>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
@@ -265,8 +259,11 @@
|
||||
removePersonality()
|
||||
if(href_list["wires"])
|
||||
var/t1 = text2num(href_list["wires"])
|
||||
if(radio)
|
||||
radio.wires.CutWireIndex(t1)
|
||||
switch(t1)
|
||||
if(4)
|
||||
radio.ToggleBroadcast()
|
||||
if(2)
|
||||
radio.ToggleReception()
|
||||
if(href_list["setlaws"])
|
||||
var/newlaws = copytext(sanitize(input("Enter any additional directives you would like your pAI personality to follow. Note that these directives will not override the personality's allegiance to its imprinted master. Conflicting directives will be ignored.", "pAI Directive Configuration", pai.pai_laws) as message),1,MAX_MESSAGE_LEN)
|
||||
if(newlaws)
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
|
||||
/obj/item/device/radio/headset/heads/captain/alt
|
||||
name = "\proper the captain's bowman headset"
|
||||
desc = "The headset of the boss. Protects ears from flashbangs. \nChannels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :v - service, :m - medical, :n - science."
|
||||
desc = "The headset of the boss. Protects ears from flashbangs. \nChannels are as follows: :c - command, :s - security, :e - engineering, :u - supply, :zz - service, :m - medical, :n - science."
|
||||
flags = EARBANGPROTECT
|
||||
icon_state = "com_headset_alt"
|
||||
item_state = "com_headset_alt"
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
// 0 = old radios
|
||||
// 1 = new radios (subspace technology)
|
||||
|
||||
|
||||
/obj/item/device/radio
|
||||
icon = 'icons/obj/radio.dmi'
|
||||
name = "station bounced radio"
|
||||
@@ -11,19 +6,18 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
item_state = "walkietalkie"
|
||||
var/on = 1 // 0 for off
|
||||
var/last_transmission
|
||||
var/frequency = 1459 //common chat
|
||||
var/frequency = PUB_FREQ //common chat
|
||||
var/traitor_frequency = 0 //tune to frequency to unlock traitor supplies
|
||||
var/canhear_range = 3 // the range which mobs can hear this radio from
|
||||
var/obj/item/device/radio/patch_link = null
|
||||
var/datum/wires/radio/wires = null
|
||||
var/prison_radio = 0
|
||||
var/b_stat = 0
|
||||
var/broadcasting = 0
|
||||
var/listening = 1
|
||||
var/freerange = 0 // 0 - Sanitize frequencies, 1 - Full range
|
||||
var/list/channels = list() //see communications.dm for full list. First channels is a "default" for :h
|
||||
var/list/channels = list() //see communications.dm for full list. First channes is a "default" for :h
|
||||
var/subspace_transmission = 0
|
||||
var/syndie = 0//Holder to see if it's a syndicate encrypted radio
|
||||
var/syndie = 0//Holder to see if it's a syndicate encrpyed radio
|
||||
var/maxf = 1499
|
||||
// "Example" = FREQ_LISTENING|FREQ_BROADCASTING
|
||||
flags = CONDUCT
|
||||
@@ -31,32 +25,31 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
throw_speed = 2
|
||||
throw_range = 9
|
||||
w_class = 2
|
||||
g_amt = 25
|
||||
|
||||
m_amt = 75
|
||||
|
||||
var/const/TRANSMISSION_DELAY = 5 // only 2/second/radio
|
||||
g_amt = 25
|
||||
var/const/FREQ_LISTENING = 1
|
||||
//FREQ_BROADCASTING = 2
|
||||
var/prison_radio = 0
|
||||
|
||||
var/always_talk=0 // ALWAYS catch signals. Useful for covert listening devices.
|
||||
|
||||
/obj/item/device/radio
|
||||
var/datum/radio_frequency/radio_connection
|
||||
var/list/datum/radio_frequency/secure_radio_connections
|
||||
var/list/datum/radio_frequency/secure_radio_connections = new
|
||||
|
||||
proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT)
|
||||
|
||||
|
||||
/obj/item/device/radio/New()
|
||||
wires = new(src)
|
||||
if(prison_radio)
|
||||
wires.CutWireIndex(WIRE_TRANSMIT)
|
||||
secure_radio_connections = new
|
||||
..()
|
||||
wires = new(src)
|
||||
if(radio_controller)
|
||||
initialize()
|
||||
|
||||
if(prison_radio)
|
||||
wires.CutWireIndex(WIRE_TRANSMIT)
|
||||
|
||||
|
||||
/obj/item/device/radio/initialize()
|
||||
@@ -117,9 +110,16 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
/obj/item/device/radio/proc/text_sec_channel(var/chan_name, var/chan_stat)
|
||||
var/list = !!(chan_stat&FREQ_LISTENING)!=0
|
||||
return {"
|
||||
<B>[chan_name]</B>: <A href='byond://?src=\ref[src];ch_name=[chan_name];listen=[!list]'>[list ? "Engaged" : "Disengaged"]</A><BR>
|
||||
<B>[chan_name]</B><br>
|
||||
Speaker: <A href='byond://?src=\ref[src];ch_name=[chan_name];listen=[!list]'>[list ? "Engaged" : "Disengaged"]</A><BR>
|
||||
"}
|
||||
|
||||
/obj/item/device/radio/proc/ToggleBroadcast()
|
||||
broadcasting = !broadcasting && !(wires.IsIndexCut(WIRE_TRANSMIT) || wires.IsIndexCut(WIRE_SIGNAL))
|
||||
|
||||
/obj/item/device/radio/proc/ToggleReception()
|
||||
listening = !listening && !(wires.IsIndexCut(WIRE_RECEIVE) || wires.IsIndexCut(WIRE_SIGNAL))
|
||||
|
||||
/obj/item/device/radio/Topic(href, href_list)
|
||||
//..()
|
||||
if (usr.stat || !on)
|
||||
@@ -129,13 +129,6 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
usr << browse(null, "window=radio")
|
||||
return
|
||||
usr.set_machine(src)
|
||||
if (href_list["open"])
|
||||
var/mob/target = locate(href_list["open"])
|
||||
var/mob/living/silicon/ai/A = locate(href_list["open2"])
|
||||
if(A && target)
|
||||
A.open_nearest_door(target)
|
||||
return
|
||||
|
||||
if (href_list["track"])
|
||||
var/mob/target = locate(href_list["track"])
|
||||
var/mob/living/silicon/ai/A = locate(href_list["track2"])
|
||||
@@ -143,23 +136,6 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
A.ai_actual_track(target)
|
||||
return
|
||||
|
||||
else if (href_list["faketrack"])
|
||||
var/mob/target = locate(href_list["track"])
|
||||
var/mob/living/silicon/ai/A = locate(href_list["track2"])
|
||||
if(A && target)
|
||||
|
||||
A:cameraFollow = target
|
||||
A << text("Now tracking [] on camera.", target.name)
|
||||
if (usr.machine == null)
|
||||
usr.machine = usr
|
||||
|
||||
while (usr:cameraFollow == target)
|
||||
usr << "Target is not on or near any active cameras on the station. We'll check again in 5 seconds (unless you use the cancel-camera verb)."
|
||||
sleep(40)
|
||||
continue
|
||||
|
||||
return
|
||||
|
||||
else if (href_list["freq"])
|
||||
var/new_frequency = (frequency + text2num(href_list["freq"]))
|
||||
if (!freerange || (frequency < 1200 || frequency > 1600))
|
||||
@@ -171,16 +147,17 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
return
|
||||
|
||||
else if (href_list["talk"])
|
||||
broadcasting = text2num(href_list["talk"])
|
||||
ToggleBroadcast()
|
||||
else if (href_list["listen"])
|
||||
var/chan_name = href_list["ch_name"]
|
||||
if (!chan_name)
|
||||
listening = text2num(href_list["listen"])
|
||||
ToggleReception()
|
||||
else
|
||||
if (channels[chan_name] & FREQ_LISTENING)
|
||||
channels[chan_name] &= ~FREQ_LISTENING
|
||||
else
|
||||
channels[chan_name] |= FREQ_LISTENING
|
||||
|
||||
if (!( master ))
|
||||
if (istype(loc, /mob))
|
||||
interact(loc)
|
||||
@@ -193,10 +170,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
updateDialog()
|
||||
add_fingerprint(usr)
|
||||
|
||||
/obj/item/device/radio/proc/isWireCut(var/index)
|
||||
return wires.IsIndexCut(index)
|
||||
|
||||
/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel, var/zlevel = list(1)) //BS12 EDIT
|
||||
/obj/item/device/radio/proc/autosay(var/message, var/from, var/channel, var/zlevel = config.contact_levels) //BS12 EDIT
|
||||
var/datum/radio_frequency/connection = null
|
||||
if(channel && channels && channels.len > 0)
|
||||
if (channel == "department")
|
||||
@@ -219,173 +193,115 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
del(A)
|
||||
return
|
||||
|
||||
/obj/item/device/radio/talk_into(mob/living/M as mob, message, channel)
|
||||
if(!on) return // the device has to be on
|
||||
// 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, message, message_mode)
|
||||
// If a channel isn't specified, send to common.
|
||||
if(!message_mode || message_mode == "headset")
|
||||
return radio_connection
|
||||
|
||||
// Otherwise, if a channel is specified, look for it.
|
||||
if(channels && channels.len > 0)
|
||||
if (message_mode == "department") // Department radio shortcut
|
||||
message_mode = channels[1]
|
||||
|
||||
if (channels[message_mode]) // only broadcast if the channel is set on
|
||||
return secure_radio_connections[message_mode]
|
||||
|
||||
// If we were to send to a channel we don't have, drop it.
|
||||
return null
|
||||
|
||||
/obj/item/device/radio/talk_into(mob/living/M as mob, message, channel, var/verb = "says", var/datum/language/speaking = null)
|
||||
if(!on) return 0 // the device has to be on
|
||||
// Fix for permacell radios, but kinda eh about actually fixing them.
|
||||
if(!M || !message) return
|
||||
if(!M || !message) return 0
|
||||
|
||||
// Uncommenting this. To the above comment:
|
||||
// The permacell radios aren't suppose to be able to transmit, this isn't a bug and this "fix" is just making radio wires useless. -Giacom
|
||||
if(isWireCut(WIRE_TRANSMIT)) // The device has to have all its wires and shit intact
|
||||
return
|
||||
if(wires.IsIndexCut(WIRE_TRANSMIT)) // The device has to have all its wires and shit intact
|
||||
return 0
|
||||
|
||||
M.last_target_click = world.time
|
||||
|
||||
/* Quick introduction:
|
||||
This new radio system uses a very robust FTL signaling technology unoriginally
|
||||
dubbed "subspace" which is somewhat similar to 'blue-space' but can't
|
||||
actually transmit large mass. Headsets are the only radio devices capable
|
||||
of sending subspace transmissions to the Communications Satellite.
|
||||
|
||||
A headset sends a signal to a subspace listener/reciever elsewhere in space,
|
||||
the signal gets processed and logged, and an audible transmission gets sent
|
||||
to each individual headset.
|
||||
*/
|
||||
|
||||
//#### Grab the connection datum ####//
|
||||
var/datum/radio_frequency/connection = handle_message_mode(M, message, channel)
|
||||
if (!istype(connection))
|
||||
return 0
|
||||
if (!connection)
|
||||
return 0
|
||||
|
||||
var/turf/position = get_turf(src)
|
||||
|
||||
//#### Tagging the signal with all appropriate identity values ####//
|
||||
|
||||
// ||-- The mob's name identity --||
|
||||
var/displayname = M.name // grab the display name (name you get when you hover over someone's icon)
|
||||
var/real_name = M.real_name // mob's real name
|
||||
var/mobkey = "none" // player key associated with mob
|
||||
var/voicemask = 0 // the speaker is wearing a voice mask
|
||||
if(M.client)
|
||||
mobkey = M.key // assign the mob's key
|
||||
|
||||
|
||||
if(GLOBAL_RADIO_TYPE == 1) // NEW RADIO SYSTEMS: By Doohl
|
||||
var/jobname // the mob's "job"
|
||||
|
||||
/* Quick introduction:
|
||||
This new radio system uses a very robust FTL signaling technology unoriginally
|
||||
dubbed "subspace" which is somewhat similar to 'blue-space' but can't
|
||||
actually transmit large mass. Headsets are the only radio devices capable
|
||||
of sending subspace transmissions to the Communications Satellite.
|
||||
// --- Human: use their actual job ---
|
||||
if (ishuman(M))
|
||||
var/mob/living/carbon/human/H = M
|
||||
jobname = H.get_assignment()
|
||||
|
||||
A headset sends a signal to a subspace listener/reciever elsewhere in space,
|
||||
the signal gets processed and logged, and an audible transmission gets sent
|
||||
to each individual headset.
|
||||
*/
|
||||
// --- Carbon Nonhuman ---
|
||||
else if (iscarbon(M)) // Nonhuman carbon mob
|
||||
jobname = "No id"
|
||||
|
||||
//#### Grab the connection datum ####//
|
||||
var/datum/radio_frequency/connection = null
|
||||
//testing("[src]: talk_into([M], [message], [channel])")
|
||||
if(channel == "headset")
|
||||
channel = null
|
||||
if(channel) // If a channel is specified, look for it.
|
||||
if(channels && channels.len > 0)
|
||||
if (channel == "department")
|
||||
//world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
|
||||
channel = channels[1]
|
||||
connection = secure_radio_connections[channel]
|
||||
if (!channels[channel]) // if the channel is turned off, don't broadcast
|
||||
return
|
||||
else
|
||||
// If we were to send to a channel we don't have, drop it.
|
||||
return
|
||||
else // If a channel isn't specified, send to common.
|
||||
connection = radio_connection
|
||||
channel = null
|
||||
if (!istype(connection))
|
||||
return
|
||||
if (!connection)
|
||||
return
|
||||
// --- AI ---
|
||||
else if (isAI(M))
|
||||
jobname = "AI"
|
||||
|
||||
var/turf/position = get_turf(src)
|
||||
// --- Cyborg ---
|
||||
else if (isrobot(M))
|
||||
jobname = "Cyborg"
|
||||
|
||||
//#### Tagging the signal with all appropriate identity values ####//
|
||||
// --- Personal AI (pAI) ---
|
||||
else if (istype(M, /mob/living/silicon/pai))
|
||||
jobname = "Personal AI"
|
||||
|
||||
// ||-- The mob's name identity --||
|
||||
var/displayname = M.name // grab the display name (name you get when you hover over someone's icon)
|
||||
var/real_name = M.real_name // mob's real name
|
||||
var/mobkey = "none" // player key associated with mob
|
||||
var/voicemask = 0 // the speaker is wearing a voice mask
|
||||
if(M.client)
|
||||
mobkey = M.key // assign the mob's key
|
||||
// --- Unidentifiable mob ---
|
||||
else
|
||||
jobname = "Unknown"
|
||||
|
||||
|
||||
var/jobname // the mob's "job"
|
||||
// --- Modifications to the mob's identity ---
|
||||
|
||||
// --- Human: use their actual job ---
|
||||
if (ishuman(M))
|
||||
jobname = M:get_assignment()
|
||||
|
||||
// --- Carbon Nonhuman ---
|
||||
else if (iscarbon(M)) // Nonhuman carbon mob
|
||||
jobname = "No id"
|
||||
|
||||
// --- AI ---
|
||||
else if (isAI(M))
|
||||
jobname = "AI"
|
||||
|
||||
// --- Cyborg ---
|
||||
else if (isrobot(M))
|
||||
var/mob/living/silicon/robot/B = M
|
||||
jobname = "[B.designation] Cyborg"
|
||||
|
||||
// --- Personal AI (pAI) ---
|
||||
else if (istype(M, /mob/living/silicon/pai))
|
||||
jobname = "Personal AI"
|
||||
|
||||
// --- Unidentifiable mob ---
|
||||
else
|
||||
jobname = "Unknown"
|
||||
|
||||
|
||||
// --- Modifications to the mob's identity ---
|
||||
|
||||
// The mob is disguising their identity:
|
||||
if (ishuman(M) && M.GetVoice() != real_name)
|
||||
displayname = M.GetVoice()
|
||||
jobname = "Unknown"
|
||||
voicemask = 1
|
||||
// The mob is disguising their identity:
|
||||
if (ishuman(M) && M.GetVoice() != real_name)
|
||||
displayname = M.GetVoice()
|
||||
jobname = "Unknown"
|
||||
voicemask = 1
|
||||
|
||||
|
||||
|
||||
/* ###### Radio headsets can only broadcast through subspace ###### */
|
||||
|
||||
if(subspace_transmission)
|
||||
// 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, // 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
|
||||
)
|
||||
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
|
||||
return
|
||||
|
||||
|
||||
/* ###### 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
|
||||
|
||||
/* ###### Radio headsets can only broadcast through subspace ###### */
|
||||
|
||||
if(subspace_transmission)
|
||||
// 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 */
|
||||
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
|
||||
@@ -394,215 +310,110 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
"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, // 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" = 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
|
||||
"language" = speaking,
|
||||
"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)
|
||||
|
||||
sleep(rand(10,25)) // wait a little...
|
||||
|
||||
if(signal.data["done"] && position.z in signal.data["level"])
|
||||
// we're done here.
|
||||
return
|
||||
|
||||
// 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.
|
||||
if(!connection) return //~Carn
|
||||
|
||||
Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
|
||||
src, message, displayname, jobname, real_name, M.voice_name,
|
||||
filter_type, signal.data["compression"], list(position.z), connection.frequency)
|
||||
// Receiving code can be located in Telecommunications.dm
|
||||
return signal.data["done"] && position.z in signal.data["level"]
|
||||
|
||||
|
||||
/* ###### Intercoms and station-bounced radios ###### */
|
||||
|
||||
else // OLD RADIO SYSTEMS: By Goons?
|
||||
var/filter_type = 2
|
||||
|
||||
var/datum/radio_frequency/connection = null
|
||||
if(channel && channels && channels.len > 0)
|
||||
if (channel == "department")
|
||||
//world << "DEBUG: channel=\"[channel]\" switching to \"[channels[1]]\""
|
||||
channel = channels[1]
|
||||
connection = secure_radio_connections[channel]
|
||||
else
|
||||
connection = radio_connection
|
||||
channel = null
|
||||
if (!istype(connection))
|
||||
return
|
||||
var/display_freq = connection.frequency
|
||||
/* --- 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
|
||||
|
||||
//world << "DEBUG: used channel=\"[channel]\" frequency= \"[display_freq]\" connection.devices.len = [connection.devices.len]"
|
||||
|
||||
var/eqjobname
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 2
|
||||
|
||||
if (ishuman(M))
|
||||
eqjobname = M:get_assignment()
|
||||
else if (iscarbon(M))
|
||||
eqjobname = "No id" //only humans can wear ID
|
||||
else if (isAI(M))
|
||||
eqjobname = "AI"
|
||||
else if (isrobot(M))
|
||||
eqjobname = "Cyborg"//Androids don't really describe these too well, in my opinion.
|
||||
else if (istype(M, /mob/living/silicon/pai))
|
||||
eqjobname = "Personal AI"
|
||||
else
|
||||
eqjobname = "Unknown"
|
||||
|
||||
if (isWireCut(WIRE_TRANSMIT))
|
||||
return
|
||||
/* --- Try to send a normal subspace broadcast first */
|
||||
|
||||
var/list/receive = list()
|
||||
signal.data = list(
|
||||
|
||||
//for (var/obj/item/device/radio/R in radio_connection.devices)
|
||||
for (var/obj/item/device/radio/R in connection.devices["[RADIO_CHAT]"]) // Modified for security headset code -- TLE
|
||||
//if(R.accept_rad(src, message))
|
||||
receive |= R.send_hear(display_freq, 0)
|
||||
"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 mas
|
||||
|
||||
//world << "DEBUG: receive.len=[receive.len]"
|
||||
var/list/heard_masked = list() // masked name or no real name
|
||||
var/list/heard_normal = list() // normal message
|
||||
var/list/heard_voice = list() // voice message
|
||||
var/list/heard_garbled = list() // garbled message
|
||||
"compression" = 0, // uncompressed radio signal
|
||||
"message" = message, // 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,
|
||||
"language" = speaking,
|
||||
"verb" = verb
|
||||
)
|
||||
signal.frequency = connection.frequency // Quick frequency set
|
||||
|
||||
for (var/mob/R in receive)
|
||||
if (R.say_understands(M))
|
||||
if (ishuman(M) && M.GetVoice() != M.real_name)
|
||||
heard_masked += R
|
||||
else
|
||||
heard_normal += R
|
||||
else
|
||||
heard_voice += R
|
||||
for(var/obj/machinery/telecomms/receiver/R in telecomms_list)
|
||||
R.receive_signal(signal)
|
||||
|
||||
if (length(heard_masked) || length(heard_normal) || length(heard_voice) || length(heard_garbled))
|
||||
var/part_a = "<span class='radio'><span class='name'>"
|
||||
//var/part_b = "</span><b> \icon[src]\[[format_frequency(frequency)]\]</b> <span class='message'>"
|
||||
var/freq_text
|
||||
switch(display_freq)
|
||||
if(SYND_FREQ)
|
||||
freq_text = "#unkn"
|
||||
if(COMM_FREQ)
|
||||
freq_text = "Command"
|
||||
if(1351)
|
||||
freq_text = "Science"
|
||||
if(1355)
|
||||
freq_text = "Medical"
|
||||
if(1357)
|
||||
freq_text = "Engineering"
|
||||
if(1359)
|
||||
freq_text = "Security"
|
||||
if(1347)
|
||||
freq_text = "Supply"
|
||||
//There's probably a way to use the list var of channels in code\game\communications.dm to make the dept channels non-hardcoded, but I wasn't in an experimentive mood. --NEO
|
||||
|
||||
if(!freq_text)
|
||||
freq_text = format_frequency(display_freq)
|
||||
sleep(rand(10,25)) // wait a little...
|
||||
|
||||
var/part_b = "</span><b> \icon[src]\[[freq_text]\]</b> <span class='message'>" // Tweaked for security headsets -- TLE
|
||||
var/part_c = "</span></span>"
|
||||
if(signal.data["done"] && position.z in signal.data["level"])
|
||||
// we're done here.
|
||||
return 1
|
||||
|
||||
if (display_freq==SYND_FREQ)
|
||||
part_a = "<span class='syndradio'><span class='name'>"
|
||||
else if (display_freq==COMM_FREQ)
|
||||
part_a = "<span class='comradio'><span class='name'>"
|
||||
else if (display_freq in DEPT_FREQS)
|
||||
part_a = "<span class='deptradio'><span class='name'>"
|
||||
// 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:
|
||||
|
||||
var/quotedmsg = M.say_quote(message)
|
||||
//THIS IS TEMPORARY. YEAH RIGHT
|
||||
if(!connection) return 0 //~Carn
|
||||
|
||||
//This following recording is intended for research and feedback in the use of department radio channels.
|
||||
return Broadcast_Message(connection, M, voicemask, pick(M.speak_emote),
|
||||
src, message, displayname, jobname, real_name, M.voice_name,
|
||||
filter_type, signal.data["compression"], list(position.z), connection.frequency,verb,speaking)
|
||||
|
||||
var/part_blackbox_b = "</span><b> \[[freq_text]\]</b> <span class='message'>" // Tweaked for security headsets -- TLE
|
||||
var/blackbox_msg = "[part_a][M.name][part_blackbox_b][quotedmsg][part_c]"
|
||||
//var/blackbox_admin_msg = "[part_a][M.name] (Real name: [M.real_name])[part_blackbox_b][quotedmsg][part_c]"
|
||||
if(istype(blackbox))
|
||||
//BR.messages_admin += blackbox_admin_msg
|
||||
switch(display_freq)
|
||||
if(1459)
|
||||
blackbox.msg_common += blackbox_msg
|
||||
if(1351)
|
||||
blackbox.msg_science += blackbox_msg
|
||||
if(1353)
|
||||
blackbox.msg_command += blackbox_msg
|
||||
if(1355)
|
||||
blackbox.msg_medical += blackbox_msg
|
||||
if(1357)
|
||||
blackbox.msg_engineering += blackbox_msg
|
||||
if(1359)
|
||||
blackbox.msg_security += blackbox_msg
|
||||
if(1441)
|
||||
blackbox.msg_deathsquad += blackbox_msg
|
||||
if(1213)
|
||||
blackbox.msg_syndicate += blackbox_msg
|
||||
if(1347)
|
||||
blackbox.msg_cargo += blackbox_msg
|
||||
if(1349)
|
||||
blackbox.msg_service += blackbox_msg
|
||||
else
|
||||
blackbox.messages += blackbox_msg
|
||||
|
||||
//End of research and feedback code.
|
||||
|
||||
if (length(heard_masked))
|
||||
var/N = M.name
|
||||
var/J = eqjobname
|
||||
if(ishuman(M) && M.GetVoice() != M.real_name)
|
||||
N = M.GetVoice()
|
||||
J = "Unknown"
|
||||
var/rendered = "[part_a][N][part_b][quotedmsg][part_c]"
|
||||
for (var/mob/R in heard_masked)
|
||||
if(istype(R, /mob/living/silicon/ai))
|
||||
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[N] ([J]) </a><a href='byond://?src=\ref[src];open2=\ref[R];open=\ref[M]'>\[OPEN\] </a> [part_b][quotedmsg][part_c]", 2)
|
||||
else
|
||||
R.show_message(rendered, 2)
|
||||
|
||||
if (length(heard_normal))
|
||||
var/rendered = "[part_a][M.real_name][part_b][quotedmsg][part_c]"
|
||||
|
||||
for (var/mob/R in heard_normal)
|
||||
if(istype(R, /mob/living/silicon/ai))
|
||||
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.real_name] ([eqjobname]) </a><a href='byond://?src=\ref[src];open2=\ref[R];open=\ref[M]'>\[OPEN\] </a>[part_b][quotedmsg][part_c]", 2)
|
||||
else
|
||||
R.show_message(rendered, 2)
|
||||
|
||||
if (length(heard_voice))
|
||||
var/rendered = "[part_a][M.voice_name][part_b][pick(M.speak_emote)][part_c]"
|
||||
|
||||
for (var/mob/R in heard_voice)
|
||||
if(istype(R, /mob/living/silicon/ai))
|
||||
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.voice_name] ([eqjobname]) </a><a href='byond://?src=\ref[src];open2=\ref[R];open=\ref[M]'>\[OPEN\] </a>[part_b][pick(M.speak_emote)][part_c]", 2)
|
||||
else
|
||||
R.show_message(rendered, 2)
|
||||
|
||||
if (length(heard_garbled))
|
||||
quotedmsg = M.say_quote(stars(message))
|
||||
var/rendered = "[part_a][M.voice_name][part_b][quotedmsg][part_c]"
|
||||
|
||||
for (var/mob/R in heard_voice)
|
||||
if(istype(R, /mob/living/silicon/ai))
|
||||
R.show_message("[part_a]<a href='byond://?src=\ref[src];track2=\ref[R];track=\ref[M]'>[M.voice_name]</a><a href='byond://?src=\ref[src];open2=\ref[R];open=\ref[M]'>\[OPEN\] </a>[part_b][quotedmsg][part_c]", 2)
|
||||
else
|
||||
R.show_message(rendered, 2)
|
||||
|
||||
/obj/item/device/radio/hear_talk(mob/M as mob, msg)
|
||||
/obj/item/device/radio/hear_talk(mob/M as mob, msg, var/verb = "says", var/datum/language/speaking = null)
|
||||
|
||||
if (broadcasting)
|
||||
if(get_dist(src, M) <= canhear_range)
|
||||
talk_into(M, msg)
|
||||
talk_into(M, msg,null,verb,speaking)
|
||||
|
||||
|
||||
/*
|
||||
/obj/item/device/radio/proc/accept_rad(obj/item/device/radio/R as obj, message)
|
||||
|
||||
@@ -621,7 +432,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
// what the range is in which mobs will hear the radio
|
||||
// returns: -1 if can't receive, range otherwise
|
||||
|
||||
if (isWireCut(WIRE_RECEIVE))
|
||||
if (wires.IsIndexCut(WIRE_RECEIVE))
|
||||
return -1
|
||||
if(!listening)
|
||||
return -1
|
||||
@@ -629,7 +440,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
var/turf/position = get_turf(src)
|
||||
if(!position || !(position.z in level))
|
||||
return -1
|
||||
if(freq == SYND_FREQ)
|
||||
if(freq in ANTAG_FREQS)
|
||||
if(!(src.syndie))//Checks to see if it's allowed on that frequency, based on the encryption keys
|
||||
return -1
|
||||
if (!on)
|
||||
@@ -656,15 +467,13 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
return get_mobs_in_view(canhear_range, src)
|
||||
|
||||
|
||||
/obj/item/device/radio/examine()
|
||||
set src in view()
|
||||
|
||||
..()
|
||||
if ((in_range(src, usr) || loc == usr))
|
||||
/obj/item/device/radio/examine(mob/user)
|
||||
. = ..()
|
||||
if ((in_range(src, user) || loc == user))
|
||||
if (b_stat)
|
||||
usr.show_message("\blue \the [src] can be attached and modified!")
|
||||
user.show_message("\blue \the [src] can be attached and modified!")
|
||||
else
|
||||
usr.show_message("\blue \the [src] can not be modified or attached!")
|
||||
user.show_message("\blue \the [src] can not be modified or attached!")
|
||||
return
|
||||
|
||||
/obj/item/device/radio/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
@@ -697,8 +506,14 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
//Giving borgs their own radio to have some more room to work with -Sieve
|
||||
|
||||
/obj/item/device/radio/borg
|
||||
var/mob/living/silicon/robot/myborg = null // Cyborg which owns this radio. Used for power checks
|
||||
var/obj/item/device/encryptionkey/keyslot = null//Borg radios can handle a single encryption key
|
||||
|
||||
var/shut_up = 0
|
||||
icon = 'icons/obj/robot_component.dmi' // Cyborgs radio icons should look like the component.
|
||||
icon_state = "radio"
|
||||
canhear_range = 3
|
||||
subspace_transmission = 1
|
||||
|
||||
/obj/item/device/radio/borg/syndicate
|
||||
syndie = 1
|
||||
keyslot = new /obj/item/device/encryptionkey/syndicate
|
||||
@@ -713,6 +528,13 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
..()
|
||||
set_frequency(1441)
|
||||
|
||||
/obj/item/device/radio/borg/talk_into()
|
||||
. = ..()
|
||||
if (isrobot(src.loc))
|
||||
var/mob/living/silicon/robot/R = src.loc
|
||||
var/datum/robot_component/C = R.components["radio"]
|
||||
R.use_power(C.energy_consumption)
|
||||
|
||||
/obj/item/device/radio/borg/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
// ..()
|
||||
user.set_machine(src)
|
||||
@@ -758,18 +580,25 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
src.channels = list()
|
||||
src.syndie = 0
|
||||
|
||||
var/mob/living/silicon/robot/D = src.loc
|
||||
if(D.module)
|
||||
for(var/ch_name in D.module.channels)
|
||||
if(ch_name in src.channels)
|
||||
continue
|
||||
src.channels += ch_name
|
||||
src.channels[ch_name] += D.module.channels[ch_name]
|
||||
if(keyslot)
|
||||
for(var/ch_name in keyslot.channels)
|
||||
if(ch_name in src.channels)
|
||||
continue
|
||||
src.channels += ch_name
|
||||
src.channels[ch_name] = keyslot.channels[ch_name]
|
||||
src.channels[ch_name] += keyslot.channels[ch_name]
|
||||
|
||||
if(keyslot.syndie)
|
||||
src.syndie = 1
|
||||
|
||||
|
||||
for (var/ch_name in channels)
|
||||
for (var/ch_name in src.channels)
|
||||
if(!radio_controller)
|
||||
sleep(30) // Waiting for the radio_controller to be created.
|
||||
if(!radio_controller)
|
||||
@@ -784,12 +613,23 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
if(usr.stat || !on)
|
||||
return
|
||||
if (href_list["mode"])
|
||||
subspace_transmission = !subspace_transmission
|
||||
if(!subspace_transmission)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled
|
||||
if(subspace_transmission != 1)
|
||||
subspace_transmission = 1
|
||||
usr << "Subspace Transmission is enabled"
|
||||
else
|
||||
subspace_transmission = 0
|
||||
usr << "Subspace Transmission is disabled"
|
||||
if(subspace_transmission == 0)//Simple as fuck, clears the channel list to prevent talking/listening over them if subspace transmission is disabled
|
||||
channels = list()
|
||||
else
|
||||
recalculateChannels()
|
||||
usr << "Subspace Transmission is [(subspace_transmission) ? "enabled" : "disabled"]"
|
||||
if (href_list["shutup"]) // Toggle loudspeaker mode, AKA everyone around you hearing your radio.
|
||||
shut_up = !shut_up
|
||||
if(shut_up)
|
||||
canhear_range = 0
|
||||
else
|
||||
canhear_range = 3
|
||||
|
||||
..()
|
||||
|
||||
/obj/item/device/radio/borg/interact(mob/user as mob)
|
||||
@@ -806,6 +646,7 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
<A href='byond://?src=\ref[src];freq=2'>+</A>
|
||||
<A href='byond://?src=\ref[src];freq=10'>+</A><BR>
|
||||
<A href='byond://?src=\ref[src];mode=1'>Toggle Broadcast Mode</A><BR>
|
||||
Loudspeaker: [shut_up ? "<A href='byond://?src=\ref[src];shutup=0'>Disengaged</A>" : "<A href='byond://?src=\ref[src];shutup=1'>Engaged</A>"]<BR>
|
||||
"}
|
||||
|
||||
if(subspace_transmission)//Don't even bother if subspace isn't turned on
|
||||
@@ -830,11 +671,3 @@ var/GLOBAL_RADIO_TYPE = 1 // radio type to use
|
||||
|
||||
/obj/item/device/radio/off
|
||||
listening = 0
|
||||
|
||||
/obj/item/device/radio/Destroy()
|
||||
if(radio_connection)
|
||||
radio_connection.remove_listener(src)
|
||||
if(isrobot(src.loc))
|
||||
var/mob/living/silicon/robot/R = src.loc
|
||||
R.radio = null
|
||||
..()
|
||||
|
||||
@@ -63,6 +63,10 @@
|
||||
attached_device.HasProximity(AM)
|
||||
return
|
||||
|
||||
/obj/item/device/transfer_valve/hear_talk(mob/living/M as mob, msg)
|
||||
..()
|
||||
for(var/obj/O in contents)
|
||||
O.hear_talk(M, msg)
|
||||
|
||||
/obj/item/device/transfer_valve/attack_self(mob/user as mob)
|
||||
ui_interact(user)
|
||||
|
||||
@@ -32,9 +32,11 @@
|
||||
R.icon_state = "robot"
|
||||
del(R.module)
|
||||
R.module = null
|
||||
R.camera.network.Remove(list("Engineering","Medical","MINE"))
|
||||
R.camera.network.Remove(list("Engineering","Medical","Mining Outpost"))
|
||||
R.updatename("Default")
|
||||
R.status_flags |= CANPUSH
|
||||
R.languages = list()
|
||||
R.speech_synthesizer_langs = list()
|
||||
R.notify_ai(2)
|
||||
R.updateicon()
|
||||
|
||||
|
||||
@@ -4,151 +4,83 @@
|
||||
density = 1
|
||||
layer = 2
|
||||
var/state = 0
|
||||
var/health = 200
|
||||
|
||||
attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/wrench) && state == 0)
|
||||
if(anchored && !istype(src,/obj/structure/girder/displaced))
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
|
||||
user << "\blue Now disassembling the girder"
|
||||
if(do_after(user,40))
|
||||
if(!src) return
|
||||
user << "\blue You dissasembled the girder!"
|
||||
new /obj/item/stack/sheet/metal(get_turf(src))
|
||||
del(src)
|
||||
else if(!anchored)
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
|
||||
user << "\blue Now securing the girder"
|
||||
if(get_turf(user, 40))
|
||||
user << "\blue You secured the girder!"
|
||||
new/obj/structure/girder( src.loc )
|
||||
del(src)
|
||||
|
||||
else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter))
|
||||
user << "\blue Now slicing apart the girder"
|
||||
if(do_after(user,30))
|
||||
/obj/structure/girder/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/wrench) && state == 0)
|
||||
if(anchored && !istype(src,/obj/structure/girder/displaced))
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
|
||||
user << "\blue Now disassembling the girder"
|
||||
if(do_after(user,40))
|
||||
if(!src) return
|
||||
user << "\blue You slice apart the girder!"
|
||||
user << "\blue You dissasembled the girder!"
|
||||
new /obj/item/stack/sheet/metal(get_turf(src))
|
||||
del(src)
|
||||
|
||||
else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill))
|
||||
user << "\blue You drill through the girder!"
|
||||
new /obj/item/stack/sheet/metal(get_turf(src))
|
||||
del(src)
|
||||
|
||||
else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 && istype(src,/obj/structure/girder/reinforced))
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1)
|
||||
user << "\blue Now unsecuring support struts"
|
||||
if(do_after(user,40))
|
||||
if(!src) return
|
||||
user << "\blue You unsecured the support struts!"
|
||||
state = 1
|
||||
|
||||
else if(istype(W, /obj/item/weapon/wirecutters) && istype(src,/obj/structure/girder/reinforced) && state == 1)
|
||||
playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
|
||||
user << "\blue Now removing support struts"
|
||||
if(do_after(user,40))
|
||||
if(!src) return
|
||||
user << "\blue You removed the support struts!"
|
||||
else if(!anchored)
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
|
||||
user << "\blue Now securing the girder"
|
||||
if(get_turf(user, 40))
|
||||
user << "\blue You secured the girder!"
|
||||
new/obj/structure/girder( src.loc )
|
||||
del(src)
|
||||
|
||||
else if(istype(W, /obj/item/weapon/crowbar) && state == 0 && anchored )
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
|
||||
user << "\blue Now dislodging the girder"
|
||||
if(do_after(user, 40))
|
||||
if(!src) return
|
||||
user << "\blue You dislodged the girder!"
|
||||
new/obj/structure/girder/displaced( src.loc )
|
||||
del(src)
|
||||
else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter))
|
||||
user << "\blue Now slicing apart the girder"
|
||||
if(do_after(user,30))
|
||||
if(!src) return
|
||||
user << "\blue You slice apart the girder!"
|
||||
new /obj/item/stack/sheet/metal(get_turf(src))
|
||||
del(src)
|
||||
|
||||
else if(istype(W, /obj/item/stack/sheet))
|
||||
else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill))
|
||||
user << "\blue You drill through the girder!"
|
||||
new /obj/item/stack/sheet/metal(get_turf(src))
|
||||
del(src)
|
||||
|
||||
var/obj/item/stack/sheet/S = W
|
||||
switch(S.type)
|
||||
else if(istype(W, /obj/item/weapon/screwdriver) && state == 2 && istype(src,/obj/structure/girder/reinforced))
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 100, 1)
|
||||
user << "\blue Now unsecuring support struts"
|
||||
if(do_after(user,40))
|
||||
if(!src) return
|
||||
user << "\blue You unsecured the support struts!"
|
||||
state = 1
|
||||
|
||||
if(/obj/item/stack/sheet/metal, /obj/item/stack/sheet/metal/cyborg)
|
||||
if(!anchored)
|
||||
if(S.amount < 2) return
|
||||
var/pdiff=performWallPressureCheck(src.loc)
|
||||
if(!pdiff)
|
||||
S.use(2)
|
||||
user << "\blue You create a false wall! Push on it to open or close the passage."
|
||||
new /obj/structure/falsewall (src.loc)
|
||||
del(src)
|
||||
else
|
||||
user << "\red There is too much air moving through the gap! The door wouldn't stay closed if you built it."
|
||||
message_admins("Attempted false wall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!")
|
||||
log_admin("Attempted false wall made by [user.real_name] (user.ckey) at [loc] had a pressure difference of [pdiff]!")
|
||||
return
|
||||
else
|
||||
if(S.amount < 2) return ..()
|
||||
user << "\blue Now adding plating..."
|
||||
if (do_after(user,40))
|
||||
if(!src || !S || S.amount < 2) return
|
||||
S.use(2)
|
||||
user << "\blue You added the plating!"
|
||||
var/turf/Tsrc = get_turf(src)
|
||||
Tsrc.ChangeTurf(/turf/simulated/wall)
|
||||
for(var/turf/simulated/wall/X in Tsrc.loc)
|
||||
if(X) X.add_hiddenprint(usr)
|
||||
del(src)
|
||||
return
|
||||
else if(istype(W, /obj/item/weapon/wirecutters) && istype(src,/obj/structure/girder/reinforced) && state == 1)
|
||||
playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
|
||||
user << "\blue Now removing support struts"
|
||||
if(do_after(user,40))
|
||||
if(!src) return
|
||||
user << "\blue You removed the support struts!"
|
||||
new/obj/structure/girder( src.loc )
|
||||
del(src)
|
||||
|
||||
if(/obj/item/stack/sheet/plasteel)
|
||||
if(!anchored)
|
||||
if(S.amount < 2) return
|
||||
var/pdiff=performWallPressureCheck(src.loc)
|
||||
if(!pdiff)
|
||||
S.use(2)
|
||||
user << "\blue You create a false wall! Push on it to open or close the passage."
|
||||
new /obj/structure/falsewall/reinforced (src.loc)
|
||||
del(src)
|
||||
else
|
||||
user << "\red There is too much air moving through the gap! The door wouldn't stay closed if you built it."
|
||||
message_admins("Attempted false rwall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!")
|
||||
log_admin("Attempted false rwall made by [user.real_name] ([user.ckey]) at [loc] had a pressure difference of [pdiff]!")
|
||||
return
|
||||
else
|
||||
if (src.icon_state == "reinforced") //I cant believe someone would actually write this line of code...
|
||||
if(S.amount < 1) return ..()
|
||||
user << "\blue Now finalising reinforced wall."
|
||||
if(do_after(user, 50))
|
||||
if(!src || !S || S.amount < 1) return
|
||||
S.use(1)
|
||||
user << "\blue Wall fully reinforced!"
|
||||
var/turf/Tsrc = get_turf(src)
|
||||
Tsrc.ChangeTurf(/turf/simulated/wall/r_wall)
|
||||
for(var/turf/simulated/wall/r_wall/X in Tsrc.loc)
|
||||
if(X) X.add_hiddenprint(usr)
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
if(S.amount < 1) return ..()
|
||||
user << "\blue Now reinforcing girders"
|
||||
if (do_after(user,60))
|
||||
if(!src || !S || S.amount < 1) return
|
||||
S.use(1)
|
||||
user << "\blue Girders reinforced!"
|
||||
new/obj/structure/girder/reinforced( src.loc )
|
||||
del(src)
|
||||
return
|
||||
else if(istype(W, /obj/item/weapon/crowbar) && state == 0 && anchored )
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 100, 1)
|
||||
user << "\blue Now dislodging the girder"
|
||||
if(do_after(user, 40))
|
||||
if(!src) return
|
||||
user << "\blue You dislodged the girder!"
|
||||
new/obj/structure/girder/displaced( src.loc )
|
||||
del(src)
|
||||
|
||||
if(S.sheettype)
|
||||
var/M = S.sheettype
|
||||
else if(istype(W, /obj/item/stack/sheet))
|
||||
|
||||
var/obj/item/stack/sheet/S = W
|
||||
switch(S.type)
|
||||
|
||||
if(/obj/item/stack/sheet/metal, /obj/item/stack/sheet/metal/cyborg)
|
||||
if(!anchored)
|
||||
if(S.amount < 2) return
|
||||
var/pdiff=performWallPressureCheck(src.loc)
|
||||
if(!pdiff)
|
||||
S.use(2)
|
||||
user << "\blue You create a false wall! Push on it to open or close the passage."
|
||||
var/F = text2path("/obj/structure/falsewall/[M]")
|
||||
new F (src.loc)
|
||||
new /obj/structure/falsewall (src.loc)
|
||||
del(src)
|
||||
else
|
||||
user << "\red There is too much air moving through the gap! The door wouldn't stay closed if you built it."
|
||||
message_admins("Attempted false [M] wall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!")
|
||||
log_admin("Attempted false [M] wall made by [user.real_name] ([user.ckey]) at [loc] had a pressure difference of [pdiff]!")
|
||||
message_admins("Attempted false wall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!")
|
||||
log_admin("Attempted false wall made by [user.real_name] (user.ckey) at [loc] had a pressure difference of [pdiff]!")
|
||||
return
|
||||
else
|
||||
if(S.amount < 2) return ..()
|
||||
@@ -158,67 +90,138 @@
|
||||
S.use(2)
|
||||
user << "\blue You added the plating!"
|
||||
var/turf/Tsrc = get_turf(src)
|
||||
Tsrc.ChangeTurf(text2path("/turf/simulated/wall/mineral/[M]"))
|
||||
for(var/turf/simulated/wall/mineral/X in Tsrc.loc)
|
||||
Tsrc.ChangeTurf(/turf/simulated/wall)
|
||||
for(var/turf/simulated/wall/X in Tsrc.loc)
|
||||
if(X) X.add_hiddenprint(usr)
|
||||
del(src)
|
||||
return
|
||||
|
||||
add_hiddenprint(usr)
|
||||
if(/obj/item/stack/sheet/plasteel)
|
||||
if(!anchored)
|
||||
if(S.amount < 2) return
|
||||
var/pdiff=performWallPressureCheck(src.loc)
|
||||
if(!pdiff)
|
||||
S.use(2)
|
||||
user << "\blue You create a false wall! Push on it to open or close the passage."
|
||||
new /obj/structure/falsewall/reinforced (src.loc)
|
||||
del(src)
|
||||
else
|
||||
user << "\red There is too much air moving through the gap! The door wouldn't stay closed if you built it."
|
||||
message_admins("Attempted false rwall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!")
|
||||
log_admin("Attempted false rwall made by [user.real_name] ([user.ckey]) at [loc] had a pressure difference of [pdiff]!")
|
||||
return
|
||||
else
|
||||
if (src.icon_state == "reinforced") //I cant believe someone would actually write this line of code...
|
||||
if(S.amount < 1) return ..()
|
||||
user << "\blue Now finalising reinforced wall."
|
||||
if(do_after(user, 50))
|
||||
if(!src || !S || S.amount < 1) return
|
||||
S.use(1)
|
||||
user << "\blue Wall fully reinforced!"
|
||||
var/turf/Tsrc = get_turf(src)
|
||||
Tsrc.ChangeTurf(/turf/simulated/wall/r_wall)
|
||||
for(var/turf/simulated/wall/r_wall/X in Tsrc.loc)
|
||||
if(X) X.add_hiddenprint(usr)
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
if(S.amount < 1) return ..()
|
||||
user << "\blue Now reinforcing girders"
|
||||
if (do_after(user,60))
|
||||
if(!src || !S || S.amount < 1) return
|
||||
S.use(1)
|
||||
user << "\blue Girders reinforced!"
|
||||
new/obj/structure/girder/reinforced( src.loc )
|
||||
del(src)
|
||||
return
|
||||
|
||||
else if(istype(W, /obj/item/pipe))
|
||||
var/obj/item/pipe/P = W
|
||||
if (P.pipe_type in list(0, 1, 5)) //simple pipes, simple bends, and simple manifolds.
|
||||
user.drop_item()
|
||||
P.loc = src.loc
|
||||
user << "\blue You fit the pipe into the [src]!"
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
bullet_act(var/obj/item/projectile/Proj)
|
||||
if(istype(Proj ,/obj/item/projectile/beam/pulse))
|
||||
src.ex_act(2)
|
||||
..()
|
||||
return 0
|
||||
|
||||
blob_act()
|
||||
if(prob(40))
|
||||
del(src)
|
||||
|
||||
bullet_act(var/obj/item/projectile/Proj)
|
||||
if(istype(Proj ,/obj/item/projectile/beam/pulse))
|
||||
src.ex_act(2)
|
||||
..()
|
||||
return 0
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
qdel(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(75))
|
||||
var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal)
|
||||
new remains(loc)
|
||||
qdel(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(30))
|
||||
var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal)
|
||||
new remains(loc)
|
||||
qdel(src)
|
||||
return
|
||||
if(S.sheettype)
|
||||
var/M = S.sheettype
|
||||
if(!anchored)
|
||||
if(S.amount < 2) return
|
||||
var/pdiff=performWallPressureCheck(src.loc)
|
||||
if(!pdiff)
|
||||
S.use(2)
|
||||
user << "\blue You create a false wall! Push on it to open or close the passage."
|
||||
var/F = text2path("/obj/structure/falsewall/[M]")
|
||||
new F (src.loc)
|
||||
del(src)
|
||||
else
|
||||
user << "\red There is too much air moving through the gap! The door wouldn't stay closed if you built it."
|
||||
message_admins("Attempted false [M] wall made by [user.real_name] ([formatPlayerPanel(user,user.ckey)]) at [formatJumpTo(loc)] had a pressure difference of [pdiff]!")
|
||||
log_admin("Attempted false [M] wall made by [user.real_name] ([user.ckey]) at [loc] had a pressure difference of [pdiff]!")
|
||||
return
|
||||
else
|
||||
return
|
||||
if(S.amount < 2) return ..()
|
||||
user << "\blue Now adding plating..."
|
||||
if (do_after(user,40))
|
||||
if(!src || !S || S.amount < 2) return
|
||||
S.use(2)
|
||||
user << "\blue You added the plating!"
|
||||
var/turf/Tsrc = get_turf(src)
|
||||
Tsrc.ChangeTurf(text2path("/turf/simulated/wall/mineral/[M]"))
|
||||
for(var/turf/simulated/wall/mineral/X in Tsrc.loc)
|
||||
if(X) X.add_hiddenprint(usr)
|
||||
del(src)
|
||||
return
|
||||
|
||||
add_hiddenprint(usr)
|
||||
|
||||
else if(istype(W, /obj/item/pipe))
|
||||
var/obj/item/pipe/P = W
|
||||
if (P.pipe_type in list(0, 1, 5)) //simple pipes, simple bends, and simple manifolds.
|
||||
user.drop_item()
|
||||
P.loc = src.loc
|
||||
user << "\blue You fit the pipe into the [src]!"
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/structure/girder/blob_act()
|
||||
if(prob(40))
|
||||
del(src)
|
||||
|
||||
/obj/structure/girder/bullet_act(var/obj/item/projectile/Proj)
|
||||
if(istype(Proj, /obj/item/projectile/beam))
|
||||
health -= Proj.damage
|
||||
..()
|
||||
if(health <= 0)
|
||||
new /obj/item/stack/sheet/metal(get_turf(src))
|
||||
del(src)
|
||||
|
||||
if(istype(Proj ,/obj/item/projectile/beam/pulse))
|
||||
src.ex_act(2)
|
||||
..()
|
||||
return 0
|
||||
|
||||
/obj/structure/girder/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
qdel(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(75))
|
||||
var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal)
|
||||
new remains(loc)
|
||||
qdel(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(30))
|
||||
var/remains = pick(/obj/item/stack/rods,/obj/item/stack/sheet/metal)
|
||||
new remains(loc)
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
/obj/structure/girder/displaced
|
||||
icon_state = "displaced"
|
||||
anchored = 0
|
||||
health = 50
|
||||
|
||||
/obj/structure/girder/reinforced
|
||||
icon_state = "reinforced"
|
||||
state = 2
|
||||
health = 500
|
||||
|
||||
/obj/structure/cultgirder
|
||||
icon= 'icons/obj/cult.dmi'
|
||||
@@ -226,47 +229,55 @@
|
||||
anchored = 1
|
||||
density = 1
|
||||
layer = 2
|
||||
var/health = 250
|
||||
|
||||
attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/wrench))
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
|
||||
user << "\blue Now disassembling the girder"
|
||||
if(do_after(user,40))
|
||||
user << "\blue You dissasembled the girder!"
|
||||
new /obj/effect/decal/remains/human(get_turf(src))
|
||||
del(src)
|
||||
/obj/structure/cultgirder/attackby(obj/item/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/wrench))
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 100, 1)
|
||||
user << "\blue Now disassembling the girder"
|
||||
if(do_after(user,40))
|
||||
user << "\blue You dissasembled the girder!"
|
||||
dismantle()
|
||||
|
||||
else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter))
|
||||
user << "\blue Now slicing apart the girder"
|
||||
if(do_after(user,30))
|
||||
user << "\blue You slice apart the girder!"
|
||||
new /obj/effect/decal/remains/human(get_turf(src))
|
||||
del(src)
|
||||
else if(istype(W, /obj/item/weapon/pickaxe/plasmacutter))
|
||||
user << "\blue Now slicing apart the girder"
|
||||
if(do_after(user,30))
|
||||
user << "\blue You slice apart the girder!"
|
||||
dismantle()
|
||||
|
||||
else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill))
|
||||
user << "\blue You drill through the girder!"
|
||||
new /obj/effect/decal/remains/human(get_turf(src))
|
||||
del(src)
|
||||
else if(istype(W, /obj/item/weapon/pickaxe/diamonddrill))
|
||||
user << "\blue You drill through the girder!"
|
||||
dismantle()
|
||||
|
||||
/obj/structure/cultgirder/proc/dismantle()
|
||||
new /obj/effect/decal/remains/human(get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
blob_act()
|
||||
if(prob(40))
|
||||
del(src)
|
||||
/obj/structure/cultgirder/blob_act()
|
||||
if(prob(40))
|
||||
dismantle()
|
||||
|
||||
/obj/structure/cultgirder/bullet_act(var/obj/item/projectile/Proj) //No beam check- How else will you destroy the cult girder with silver bullets?????
|
||||
health -= Proj.damage
|
||||
..()
|
||||
if(health <= 0)
|
||||
dismantle()
|
||||
return
|
||||
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
/obj/structure/cultgirder/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
qdel(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(30))
|
||||
new /obj/effect/decal/remains/human(loc)
|
||||
qdel(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(30))
|
||||
new /obj/effect/decal/remains/human(loc)
|
||||
qdel(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(5))
|
||||
new /obj/effect/decal/remains/human(loc)
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(5))
|
||||
new /obj/effect/decal/remains/human(loc)
|
||||
qdel(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
@@ -182,9 +182,9 @@
|
||||
mecha.loc.assume_air(leaked_gas)
|
||||
else
|
||||
del(leaked_gas)
|
||||
if(mecha.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT))
|
||||
/*if(mecha.hasInternalDamage(MECHA_INT_SHORT_CIRCUIT)) // LAG INDUCING - it'll keep on creating sparks
|
||||
if(mecha.get_charge())
|
||||
mecha.spark_system.start()
|
||||
mecha.cell.charge -= min(20,mecha.cell.charge)
|
||||
mecha.cell.maxcharge -= min(20,mecha.cell.maxcharge)
|
||||
mecha.cell.maxcharge -= min(20,mecha.cell.maxcharge) */
|
||||
return
|
||||
@@ -42,7 +42,7 @@ var/list/admin_verbs_admin = list(
|
||||
/client/proc/admin_memo, /*admin memo system. show/delete/write. +SERVER needed to delete admin memos of others*/
|
||||
/client/proc/dsay, /*talk in deadchat using our ckey/fakekey*/
|
||||
/client/proc/toggleprayers, /*toggles prayers on/off*/
|
||||
// /client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/
|
||||
/client/proc/toggle_hear_radio, /*toggles whether we hear the radio*/
|
||||
/client/proc/investigate_show, /*various admintools for investigation. Such as a singulo grief-log*/
|
||||
/datum/admins/proc/toggleooc, /*toggles ooc on/off for everyone*/
|
||||
/datum/admins/proc/toggleoocdead, /*toggles ooc on/off for everyone who is dead*/
|
||||
|
||||
@@ -35,7 +35,6 @@
|
||||
|
||||
/obj/effect/landmark/corpse/proc/createCorpse() //Creates a mob and checks for gear in each slot before attempting to equip it.
|
||||
var/mob/living/carbon/human/human/M = new /mob/living/carbon/human/human (src.loc)
|
||||
M.dna.mutantrace = mutantrace
|
||||
M.real_name = src.name
|
||||
M.death(1) //Kills the new mob
|
||||
M.timeofdeath = timeofdeath
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
/area/awaymission/academy
|
||||
name = "\improper Academy Asteroids"
|
||||
icon_state = "away"
|
||||
report_alerts = 0
|
||||
|
||||
/area/awaymission/academy/headmaster
|
||||
name = "\improper Academy Fore Block"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
name = "\improper BMP Asteroids"
|
||||
icon_state = "away"
|
||||
luminosity = 0
|
||||
|
||||
report_alerts = 0
|
||||
|
||||
/area/awaymission/BMPship/Aft
|
||||
name = "\improper Aft Block"
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
name = "XCC-P5831"
|
||||
icon_state = "away"
|
||||
requires_power = 0
|
||||
|
||||
report_alerts = 0
|
||||
|
||||
/area/awaymission/centcomAway/general
|
||||
name = "XCC-P5831"
|
||||
music = "music/ambigen3.ogg"
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
//Challenge Areas
|
||||
|
||||
/area/awaymission/challenge
|
||||
name = "Challenge"
|
||||
icon_state = "away"
|
||||
report_alerts = 0
|
||||
|
||||
/area/awaymission/challenge/start
|
||||
name = "Where Am I?"
|
||||
icon_state = "away"
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
luminosity = 1
|
||||
lighting_use_dynamic = 0
|
||||
requires_power = 0
|
||||
report_alerts = 0
|
||||
|
||||
/area/awaymission/clownplanet/miningtown
|
||||
name = "\improper Clown Planet - Bananium-o-Rama"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
name = "\improper Space Battle"
|
||||
icon_state = "away"
|
||||
requires_power = 0
|
||||
report_alerts = 0
|
||||
|
||||
/area/awaymission/spacebattle/cruiser
|
||||
name = "\improper Nanotrasen Cruiser"
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
* Areas
|
||||
*/
|
||||
//Gateroom gets its own APC specifically for the gate
|
||||
/area/awaymission
|
||||
report_alerts = 0
|
||||
|
||||
/area/awaymission/gateroom
|
||||
|
||||
//Library, medbay, storage room
|
||||
|
||||
@@ -25,6 +25,16 @@
|
||||
src << "As a ghost, you will now [(prefs.toggles & CHAT_GHOSTRADIO) ? "hear all radio chat in the world" : "only hear from nearby speakers"]."
|
||||
prefs.save_preferences(src)
|
||||
feedback_add_details("admin_verb","TGR")
|
||||
|
||||
/client/proc/toggle_hear_radio()
|
||||
set name = "Show/Hide RadioChatter"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggle seeing radiochatter from radios and speakers"
|
||||
if(!holder) return
|
||||
prefs.toggles ^= CHAT_RADIO
|
||||
prefs.save_preferences(src)
|
||||
usr << "You will [(prefs.toggles & CHAT_RADIO) ? "no longer" : "now"] see radio chatter from radios or speakers"
|
||||
feedback_add_details("admin_verb","THR") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/verb/toggleadminhelpsound()
|
||||
set name = "Hear/Silence Adminhelps"
|
||||
|
||||
@@ -51,44 +51,6 @@
|
||||
siemens_coefficient = 0.7
|
||||
species_fit = list("Vox")
|
||||
|
||||
/obj/item/clothing/mask/gas/voice
|
||||
name = "gas mask"
|
||||
//desc = "A face-covering mask that can be connected to an air supply. It seems to house some odd electronics."
|
||||
var/mode = 0// 0==Scouter | 1==Night Vision | 2==Thermal | 3==Meson
|
||||
var/voice = "Unknown"
|
||||
var/vchange = 0//This didn't do anything before. It now checks if the mask has special functions/N
|
||||
origin_tech = "syndicate=4"
|
||||
species_fit = list("Vox")
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/space_ninja
|
||||
name = "ninja mask"
|
||||
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement."
|
||||
icon_state = "s-ninja(norm)"
|
||||
item_state = "s-ninja_mask"
|
||||
vchange = 1
|
||||
unacidable = 1
|
||||
siemens_coefficient = 0.2
|
||||
species_fit = list("Vox")
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/space_ninja/scar
|
||||
name = "ninja mask"
|
||||
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement. This mask appears to have already seen battle."
|
||||
icon_state = "s-ninja(scar)"
|
||||
item_state = "s-ninja_mask"
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/space_ninja/visor
|
||||
name = "ninja mask"
|
||||
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement. This variant appears to have a visor to increase vision."
|
||||
icon_state = "s-ninja(visor)"
|
||||
item_state = "s-ninja_mask"
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/space_ninja/monocular
|
||||
name = "ninja mask"
|
||||
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement. This variant appears to focus the user's vision out of a single port."
|
||||
icon_state = "s-ninja(mon)"
|
||||
item_state = "s-ninja_mask"
|
||||
|
||||
|
||||
/obj/item/clothing/mask/gas/clown_hat
|
||||
name = "clown wig and mask"
|
||||
desc = "A true prankster's facial attire. A clown is incomplete without his wig and mask."
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/obj/item/voice_changer
|
||||
name = "voice changer"
|
||||
desc = "A voice scrambling module. If you can see this, report it as a bug on the tracker."
|
||||
var/voice //If set and item is present in mask/suit, this name will be used for the wearer's speech.
|
||||
var/active
|
||||
|
||||
/obj/item/clothing/mask/gas/voice
|
||||
name = "gas mask"
|
||||
desc = "A face-covering mask that can be connected to an air supply. It seems to house some odd electronics."
|
||||
var/obj/item/voice_changer/changer
|
||||
origin_tech = "syndicate=4"
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/verb/Toggle_Voice_Changer()
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
|
||||
changer.active = !changer.active
|
||||
usr << "<span class='notice'>You [changer.active ? "enable" : "disable"] the voice-changing module in \the [src].</span>"
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/verb/Set_Voice(name as text)
|
||||
set category = "Object"
|
||||
set src in usr
|
||||
|
||||
var/voice = sanitize(copytext(name,1,MAX_MESSAGE_LEN))
|
||||
if(!voice || !length(voice)) return
|
||||
changer.voice = voice
|
||||
usr << "<span class='notice'>You are now mimicking <B>[changer.voice]</B>.</span>"
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/New()
|
||||
..()
|
||||
changer = new(src)
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/space_ninja
|
||||
name = "ninja mask"
|
||||
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement."
|
||||
icon_state = "s-ninja(norm)"
|
||||
item_state = "s-ninja_mask"
|
||||
unacidable = 1
|
||||
siemens_coefficient = 0.2
|
||||
species_fit = list("Vox")
|
||||
var/mode = 0// 0==Scouter | 1==Night Vision | 2==Thermal | 3==Meson
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/space_ninja/scar
|
||||
name = "ninja mask"
|
||||
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement. This mask appears to have already seen battle."
|
||||
icon_state = "s-ninja(scar)"
|
||||
item_state = "s-ninja_mask"
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/space_ninja/visor
|
||||
name = "ninja mask"
|
||||
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement. This variant appears to have a visor to increase vision."
|
||||
icon_state = "s-ninja(visor)"
|
||||
item_state = "s-ninja_mask"
|
||||
|
||||
/obj/item/clothing/mask/gas/voice/space_ninja/monocular
|
||||
name = "ninja mask"
|
||||
desc = "A close-fitting mask that acts both as an air filter and a post-modern fashion statement. This variant appears to focus the user's vision out of a single port."
|
||||
icon_state = "s-ninja(mon)"
|
||||
item_state = "s-ninja_mask"
|
||||
@@ -345,8 +345,8 @@ You've gained <b>[totalkarma]</b> total karma in your time here.<br>"}
|
||||
message_admins("SQL ERROR during karmaspent updating (updating existing entry). Error: \[[err]\]\n")
|
||||
return
|
||||
else
|
||||
usr << "You have been charged [cost] karma."
|
||||
message_admins("[key_name(usr)] has been charged [cost] karma.")
|
||||
usr << "You have been [refund ? "refunded" : "charged"] [cost] karma."
|
||||
message_admins("[key_name(usr)] has been [refund ? "refunded" : "charged"] [cost] karma.")
|
||||
return
|
||||
|
||||
/client/proc/karmarefund(var/type,var/name,var/cost)
|
||||
|
||||
@@ -12,14 +12,15 @@
|
||||
var/obj/item/weapon/card/id/prisoner/inserted_id
|
||||
var/obj/machinery/door/airlock/release_door
|
||||
var/door_tag = "prisonshuttle"
|
||||
var/obj/item/device/radio/Radio //needed to send messages to sec radio
|
||||
var/use_release_door = 0
|
||||
var/obj/item/device/radio/intercom/announcer
|
||||
|
||||
|
||||
/obj/machinery/mineral/labor_claim_console/New()
|
||||
..()
|
||||
Radio = new/obj/item/device/radio(src)
|
||||
Radio.listening = 0
|
||||
announcer = new /obj/item/device/radio/intercom(null)
|
||||
announcer.config(list("Security" = 0))
|
||||
|
||||
spawn(7)
|
||||
src.machine = locate(/obj/machinery/mineral/stacking_machine, get_step(src, machinedir))
|
||||
var/t
|
||||
@@ -103,8 +104,8 @@
|
||||
else
|
||||
if(shuttle.location == 1)
|
||||
if (shuttle.moving_status == SHUTTLE_IDLE)
|
||||
Radio.set_frequency(SEC_FREQ)
|
||||
Radio.talk_into(src, "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval.", SEC_FREQ)
|
||||
var/message = "[inserted_id.registered_name] has returned to the station. Minerals and Prisoner ID card ready for retrieval."
|
||||
announcer.autosay(message, "Labor Camp Controller", "Security")
|
||||
usr << "<span class='notice'>Shuttle received message and will be sent shortly.</span>"
|
||||
shuttle.launch()
|
||||
else
|
||||
@@ -131,7 +132,7 @@
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/laborstacker
|
||||
var/points = 0 //The unclaimed value of ore stacked. Value for each ore loosely relative to its rarity.
|
||||
var/list/ore_values = list(("glass" = 1), ("metal" = 2), ("solid plasma" = 20), ("plasteel" = 23), ("reinforced glass" = 4), ("gold" = 20), ("silver" = 20), ("uranium" = 20), ("diamond" = 25), ("bananium" = 50))
|
||||
var/list/ore_values = list(("glass" = 1), ("metal" = 2), ("iron" = 3), ("solid plasma" = 20), ("plasteel" = 23), ("reinforced glass" = 4), ("gold" = 20), ("silver" = 20), ("uranium" = 20), ("diamond" = 25), ("bananium" = 50))
|
||||
|
||||
/obj/machinery/mineral/stacking_machine/laborstacker/proc/get_ore_values()
|
||||
var/dat = "<table border='0' width='200'>"
|
||||
@@ -155,6 +156,17 @@
|
||||
S.loc = output.loc
|
||||
else
|
||||
O.loc = output.loc
|
||||
|
||||
//Output amounts that are past stack_amt.
|
||||
for(var/sheet in stack_storage)
|
||||
if(stack_storage[sheet] >= stack_amt)
|
||||
var/stacktype = stack_paths[sheet]
|
||||
var/obj/item/stack/sheet/S = new stacktype (get_turf(output))
|
||||
S.amount = stack_amt
|
||||
stack_storage[sheet] -= stack_amt
|
||||
|
||||
console.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
/**********************Point Lookup Console**************************/
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
var/atom/movable/following = null
|
||||
var/medHUD = 0
|
||||
var/secHUD = 0
|
||||
var/anonsay = 0
|
||||
|
||||
/mob/dead/observer/New(var/mob/body=null, var/flags=1)
|
||||
sight |= SEE_TURFS | SEE_MOBS | SEE_OBJS | SEE_SELF
|
||||
@@ -490,6 +491,11 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
if(usr != src)
|
||||
return
|
||||
..()
|
||||
|
||||
if (href_list["track"])
|
||||
var/mob/target = locate(href_list["track"]) in mob_list
|
||||
if(target)
|
||||
ManualFollow(target)
|
||||
|
||||
if (href_list["follow"])
|
||||
var/mob/target = locate(href_list["follow"]) in mob_list
|
||||
@@ -532,3 +538,14 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
|
||||
following = null
|
||||
..()
|
||||
//END TELEPORT HREF CODE
|
||||
|
||||
/mob/dead/observer/verb/toggle_anonsay()
|
||||
set category = "Ghost"
|
||||
set name = "Toggle Anonymous Chat"
|
||||
set desc = "Toggles showing your key in dead chat."
|
||||
|
||||
src.anonsay = !src.anonsay
|
||||
if(anonsay)
|
||||
src << "<span class='info'>Your key won't be shown when you speak in dead chat.</span>"
|
||||
else
|
||||
src << "<span class='info'>Your key will be publicly visible again.</span>"
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
// At minimum every mob has a hear_say proc.
|
||||
|
||||
/mob/proc/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
|
||||
if(!client)
|
||||
return
|
||||
|
||||
if(speaker && !speaker.client && istype(src,/mob/dead/observer) && client.prefs.toggles & CHAT_GHOSTEARS && !speaker in view(src))
|
||||
//Does the speaker have a client? It's either random stuff that observers won't care about (Experiment 97B says, 'EHEHEHEHEHEHEHE')
|
||||
//Or someone snoring. So we make it where they won't hear it.
|
||||
return
|
||||
|
||||
//make sure the air can transmit speech - hearer's side
|
||||
var/turf/T = get_turf(src)
|
||||
if ((T) && (!(istype(src, /mob/dead/observer)))) //Ghosts can hear even in vacuum.
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
var/pressure = (environment)? environment.return_pressure() : 0
|
||||
if(pressure < SOUND_MINIMUM_PRESSURE && get_dist(speaker, src) > 1)
|
||||
return
|
||||
|
||||
if (pressure < ONE_ATMOSPHERE*0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
|
||||
italics = 1
|
||||
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
|
||||
|
||||
if(sleeping || stat == 1)
|
||||
hear_sleep(message)
|
||||
return
|
||||
|
||||
//non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet.
|
||||
if (language && (language.flags & NONVERBAL))
|
||||
if (!speaker || (src.sdisabilities & BLIND || src.blinded) || !(speaker in view(src)))
|
||||
message = stars(message)
|
||||
|
||||
if(!(language && (language.flags & INNATE))) // skip understanding checks for INNATE languages
|
||||
if(!say_understands(speaker,language))
|
||||
if(istype(speaker,/mob/living/simple_animal))
|
||||
var/mob/living/simple_animal/S = speaker
|
||||
message = pick(S.speak)
|
||||
else
|
||||
if(language)
|
||||
message = language.scramble(message)
|
||||
else
|
||||
message = stars(message)
|
||||
|
||||
var/speaker_name = speaker.name
|
||||
if(istype(speaker, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = speaker
|
||||
speaker_name = H.GetVoice()
|
||||
|
||||
if(italics)
|
||||
message = "<i>[message]</i>"
|
||||
|
||||
var/track = null
|
||||
if(istype(src, /mob/dead/observer))
|
||||
if(italics && client.prefs.toggles & CHAT_GHOSTRADIO)
|
||||
return
|
||||
if(speaker_name != speaker.real_name && speaker.real_name)
|
||||
speaker_name = "[speaker.real_name] ([speaker_name])"
|
||||
track = "(<a href='byond://?src=\ref[src];track=\ref[speaker]'>follow</a>) "
|
||||
if(client.prefs.toggles & CHAT_GHOSTEARS && speaker in view(src))
|
||||
message = "<b>[message]</b>"
|
||||
|
||||
if(sdisabilities & DEAF || ear_deaf)
|
||||
if(!language || !(language.flags & INNATE)) // INNATE is the flag for audible-emote-language, so we don't want to show an "x talks but you cannot hear them" message if it's set
|
||||
if(speaker == src)
|
||||
src << "<span class='warning'>You cannot hear yourself speak!</span>"
|
||||
else
|
||||
src << "<span class='name'>[speaker_name]</span>[alt_name] talks but you cannot hear \him."
|
||||
else
|
||||
if(language)
|
||||
src << "<span class='game say'><span class='name'>[speaker_name]</span>[alt_name] [track][language.format_message(message, verb)]</span>"
|
||||
else
|
||||
src << "<span class='game say'><span class='name'>[speaker_name]</span>[alt_name] [track][verb], <span class='message'><span class='body'>\"[message]\"</span></span></span>"
|
||||
if (speech_sound && (get_dist(speaker, src) <= world.view && src.z == speaker.z))
|
||||
var/turf/source = speaker? get_turf(speaker) : get_turf(src)
|
||||
src.playsound_local(source, speech_sound, sound_vol, 1)
|
||||
|
||||
|
||||
/mob/proc/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
|
||||
|
||||
if(!client)
|
||||
return
|
||||
|
||||
if(sleeping || stat==1) //If unconscious or sleeping
|
||||
hear_sleep(message)
|
||||
return
|
||||
|
||||
var/track = null
|
||||
|
||||
//non-verbal languages are garbled if you can't see the speaker. Yes, this includes if they are inside a closet.
|
||||
if (language && (language.flags & NONVERBAL))
|
||||
if (!speaker || (src.sdisabilities & BLIND || src.blinded) || !(speaker in view(src)))
|
||||
message = stars(message)
|
||||
|
||||
if(!(language && (language.flags & INNATE))) // skip understanding checks for INNATE languages
|
||||
if(!say_understands(speaker,language))
|
||||
if(istype(speaker,/mob/living/simple_animal))
|
||||
var/mob/living/simple_animal/S = speaker
|
||||
if(S.speak && S.speak.len)
|
||||
message = pick(S.speak)
|
||||
else
|
||||
return
|
||||
else
|
||||
if(language)
|
||||
message = language.scramble(message)
|
||||
else
|
||||
message = stars(message)
|
||||
|
||||
if(hard_to_hear)
|
||||
message = stars(message)
|
||||
|
||||
var/speaker_name = speaker.name
|
||||
|
||||
if(vname)
|
||||
speaker_name = vname
|
||||
|
||||
if(istype(speaker, /mob/living/carbon/human))
|
||||
var/mob/living/carbon/human/H = speaker
|
||||
if(H.voice)
|
||||
speaker_name = H.voice
|
||||
|
||||
if(hard_to_hear)
|
||||
speaker_name = "unknown"
|
||||
|
||||
var/changed_voice
|
||||
|
||||
if(istype(src, /mob/living/silicon/ai) && !hard_to_hear)
|
||||
var/jobname // the mob's "job"
|
||||
var/mob/living/carbon/human/impersonating //The crewmember being impersonated, if any.
|
||||
|
||||
if (ishuman(speaker))
|
||||
var/mob/living/carbon/human/H = speaker
|
||||
|
||||
if((H.wear_id && istype(H.wear_id,/obj/item/weapon/card/id/syndicate)) && (H.wear_mask && istype(H.wear_mask,/obj/item/clothing/mask/gas/voice)))
|
||||
|
||||
changed_voice = 1
|
||||
var/mob/living/carbon/human/I = locate(speaker_name)
|
||||
|
||||
if(I)
|
||||
impersonating = I
|
||||
jobname = impersonating.get_assignment()
|
||||
else
|
||||
jobname = "Unknown"
|
||||
else
|
||||
jobname = H.get_assignment()
|
||||
|
||||
else if (iscarbon(speaker)) // Nonhuman carbon mob
|
||||
jobname = "No id"
|
||||
else if (isAI(speaker))
|
||||
jobname = "AI"
|
||||
else if (isrobot(speaker))
|
||||
jobname = "Cyborg"
|
||||
else if (istype(speaker, /mob/living/silicon/pai))
|
||||
jobname = "Personal AI"
|
||||
else
|
||||
jobname = "Unknown"
|
||||
|
||||
if(changed_voice)
|
||||
if(impersonating)
|
||||
track = "<a href='byond://?src=\ref[src];trackname=[html_encode(speaker_name)];track=\ref[impersonating]'>[speaker_name] ([jobname])</a>"
|
||||
else
|
||||
track = "[speaker_name] ([jobname])"
|
||||
else
|
||||
track = "<a href='byond://?src=\ref[src];trackname=[html_encode(speaker_name)];track=\ref[speaker]'>[speaker_name] ([jobname])</a>"
|
||||
|
||||
if(istype(src, /mob/dead/observer))
|
||||
if(speaker_name != speaker.real_name && !isAI(speaker)) //Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs.
|
||||
speaker_name = "[speaker.real_name] ([speaker_name])"
|
||||
track = "[speaker_name] (<a href='byond://?src=\ref[src];track=\ref[speaker]'>follow</a>)"
|
||||
|
||||
var/formatted
|
||||
if(language)
|
||||
formatted = language.format_message_radio(message, verb)
|
||||
else
|
||||
formatted = "[verb], <span class=\"body\">\"[message]\"</span>"
|
||||
if(sdisabilities & DEAF || ear_deaf)
|
||||
if(prob(20))
|
||||
src << "<span class='warning'>You feel your headset vibrate but can hear nothing from it!</span>"
|
||||
else if(track)
|
||||
src << "[part_a][track][part_b][formatted]</span></span>"
|
||||
else
|
||||
src << "[part_a][speaker_name][part_b][formatted]</span></span>"
|
||||
|
||||
/mob/proc/hear_signlang(var/message, var/verb = "gestures", var/datum/language/language, var/mob/speaker = null)
|
||||
if(!client)
|
||||
return
|
||||
|
||||
if(say_understands(speaker, language))
|
||||
message = "<B>[src]</B> [verb], \"[message]\""
|
||||
else
|
||||
message = "<B>[src]</B> [verb]."
|
||||
|
||||
if(src.status_flags & PASSEMOTES)
|
||||
for(var/obj/item/weapon/holder/H in src.contents)
|
||||
H.show_message(message)
|
||||
for(var/mob/living/M in src.contents)
|
||||
M.show_message(message)
|
||||
src.show_message(message)
|
||||
|
||||
/mob/proc/hear_sleep(var/message)
|
||||
var/heard = ""
|
||||
if(prob(15))
|
||||
var/list/punctuation = list(",", "!", ".", ";", "?")
|
||||
var/list/messages = text2list(message, " ")
|
||||
var/R = rand(1, messages.len)
|
||||
var/heardword = messages[R]
|
||||
if(copytext(heardword,1, 1) in punctuation)
|
||||
heardword = copytext(heardword,2)
|
||||
if(copytext(heardword,-1) in punctuation)
|
||||
heardword = copytext(heardword,1,lentext(heardword))
|
||||
heard = "<span class = 'game_say'>...You hear something about...[heardword]</span>"
|
||||
|
||||
else
|
||||
heard = "<span class = 'game_say'>...<i>You almost hear someone talking</i>...</span>"
|
||||
|
||||
src << heard
|
||||
+360
-39
@@ -1,3 +1,5 @@
|
||||
#define SCRAMBLE_CACHE_LEN 20
|
||||
|
||||
/*
|
||||
Datum based languages. Easily editable and modular.
|
||||
*/
|
||||
@@ -5,13 +7,106 @@
|
||||
/datum/language
|
||||
var/name = "an unknown language" // Fluff name of language if any.
|
||||
var/desc = "A language." // Short description for 'Check Languages'.
|
||||
var/speech_verb = "says" // 'says', 'hisses'.
|
||||
var/ask_verb = "asks" // Used when sentence ends in a ?
|
||||
var/speech_verb = "says" // 'says', 'hisses', 'farts'.
|
||||
var/ask_verb = "asks" // Used when sentence ends in a ?
|
||||
var/exclaim_verb = "exclaims" // Used when sentence ends in a !
|
||||
var/colour = "say_quote" // CSS style to use for strings in this language.
|
||||
var/whisper_verb // Optional. When not specified speech_verb + quietly/softly is used instead.
|
||||
var/signlang_verb = list() // list of emotes that might be displayed if this language has NONVERBAL or SIGNLANG flags
|
||||
var/colour = "body" // CSS style to use for strings in this language.
|
||||
var/key = "x" // Character used to speak in language eg. :o for Unathi.
|
||||
var/flags = 0 // Various language flags.
|
||||
var/native // If set, non-native speakers will have trouble speaking.
|
||||
var/list/syllables // Used when scrambling text for a non-speaker.
|
||||
var/list/space_chance = 55 // Likelihood of getting a space in the random scramble string.
|
||||
|
||||
/datum/language/proc/get_random_name(var/gender, name_count=2, syllable_count=4)
|
||||
if(!syllables || !syllables.len)
|
||||
if(gender==FEMALE)
|
||||
return capitalize(pick(first_names_female)) + " " + capitalize(pick(last_names))
|
||||
else
|
||||
return capitalize(pick(first_names_male)) + " " + capitalize(pick(last_names))
|
||||
|
||||
var/full_name = ""
|
||||
var/new_name = ""
|
||||
|
||||
for(var/i = 0;i<name_count;i++)
|
||||
new_name = ""
|
||||
for(var/x = rand(Floor(syllable_count/2),syllable_count);x>0;x--)
|
||||
new_name += pick(syllables)
|
||||
full_name += " [capitalize(lowertext(new_name))]"
|
||||
|
||||
return "[trim(full_name)]"
|
||||
|
||||
/datum/language
|
||||
var/list/scramble_cache = list()
|
||||
|
||||
/datum/language/proc/scramble(var/input)
|
||||
|
||||
if(!syllables || !syllables.len)
|
||||
return stars(input)
|
||||
|
||||
// If the input is cached already, move it to the end of the cache and return it
|
||||
if(input in scramble_cache)
|
||||
var/n = scramble_cache[input]
|
||||
scramble_cache -= input
|
||||
scramble_cache[input] = n
|
||||
return n
|
||||
|
||||
var/input_size = length(input)
|
||||
var/scrambled_text = ""
|
||||
var/capitalize = 1
|
||||
|
||||
while(length(scrambled_text) < input_size)
|
||||
var/next = pick(syllables)
|
||||
if(capitalize)
|
||||
next = capitalize(next)
|
||||
capitalize = 0
|
||||
scrambled_text += next
|
||||
var/chance = rand(100)
|
||||
if(chance <= 5)
|
||||
scrambled_text += ". "
|
||||
capitalize = 1
|
||||
else if(chance > 5 && chance <= space_chance)
|
||||
scrambled_text += " "
|
||||
|
||||
scrambled_text = trim(scrambled_text)
|
||||
var/ending = copytext(scrambled_text, length(scrambled_text))
|
||||
if(ending == ".")
|
||||
scrambled_text = copytext(scrambled_text,1,length(scrambled_text)-1)
|
||||
var/input_ending = copytext(input, input_size)
|
||||
if(input_ending in list("!","?","."))
|
||||
scrambled_text += input_ending
|
||||
|
||||
// Add it to cache, cutting old entries if the list is too long
|
||||
scramble_cache[input] = scrambled_text
|
||||
if(scramble_cache.len > SCRAMBLE_CACHE_LEN)
|
||||
scramble_cache.Cut(1, scramble_cache.len-SCRAMBLE_CACHE_LEN-1)
|
||||
|
||||
|
||||
return scrambled_text
|
||||
|
||||
/datum/language/proc/format_message(message, verb)
|
||||
return "[verb], <span class='message'><span class='[colour]'>\"[capitalize(message)]\"</span></span>"
|
||||
|
||||
/datum/language/proc/format_message_radio(message, verb)
|
||||
return "[verb], <span class='[colour]'>\"[capitalize(message)]\"</span>"
|
||||
|
||||
/datum/language/proc/get_talkinto_msg_range(message)
|
||||
// if you yell, you'll be heard from two tiles over instead of one
|
||||
return (copytext(message, length(message)) == "!") ? 2 : 1
|
||||
|
||||
/datum/language/proc/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
|
||||
log_say("[key_name(speaker)] : ([name]) [message]")
|
||||
|
||||
if(!speaker_mask) speaker_mask = speaker.name
|
||||
var/msg = "<i><span class='game say'>[name], <span class='name'>[speaker_mask]</span> [format_message(message, get_spoken_verb(message))]</span></i>"
|
||||
|
||||
for(var/mob/player in player_list)
|
||||
if(istype(player,/mob/dead) || ((src in player.languages) && check_special_condition(player)))
|
||||
player << msg
|
||||
|
||||
/datum/language/proc/check_special_condition(var/mob/other)
|
||||
return 1
|
||||
|
||||
/datum/language/proc/get_spoken_verb(var/msg_end)
|
||||
switch(msg_end)
|
||||
@@ -19,8 +114,25 @@
|
||||
return exclaim_verb
|
||||
if("?")
|
||||
return ask_verb
|
||||
return speech_verb
|
||||
|
||||
return speech_verb
|
||||
|
||||
// Noise "language", for audible emotes.
|
||||
/datum/language/noise
|
||||
name = "Noise"
|
||||
desc = "Noises"
|
||||
key = ""
|
||||
flags = RESTRICTED|NONGLOBAL|INNATE|NO_TALK_MSG
|
||||
|
||||
/datum/language/noise/format_message(message, verb)
|
||||
return "<span class='message'><span class='[colour]'>[message]</span></span>"
|
||||
|
||||
/datum/language/noise/format_message_radio(message, verb)
|
||||
return "<span class='[colour]'>[message]</span>"
|
||||
|
||||
/datum/language/noise/get_talkinto_msg_range(message)
|
||||
// if you make a loud noise (screams etc), you'll be heard from 4 tiles over instead of two
|
||||
return (copytext(message, length(message)) == "!") ? 4 : 2
|
||||
|
||||
/datum/language/unathi
|
||||
name = "Sinta'unathi"
|
||||
desc = "The common language of Moghes, composed of sibilant hisses and rattles. Spoken natively by Unathi."
|
||||
@@ -29,17 +141,38 @@
|
||||
exclaim_verb = "roars"
|
||||
colour = "soghun"
|
||||
key = "o"
|
||||
flags = WHITELISTED
|
||||
flags = RESTRICTED
|
||||
syllables = list("ss","ss","ss","ss","skak","seeki","resh","las","esi","kor","sh")
|
||||
|
||||
/datum/language/unathi/get_random_name()
|
||||
|
||||
var/new_name = ..()
|
||||
while(findtextEx(new_name,"sss",1,null))
|
||||
new_name = replacetext(new_name, "sss", "ss")
|
||||
return capitalize(new_name)
|
||||
|
||||
/datum/language/tajaran
|
||||
name = "Siik'tajr"
|
||||
desc = "An expressive language that combines yowls and chirps with posture, tail and ears. Native to the Tajaran."
|
||||
desc = "The traditionally employed tongue of Ahdomai, composed of expressive yowls and chirps. Native to the Tajaran."
|
||||
speech_verb = "mrowls"
|
||||
ask_verb = "mrowls"
|
||||
exclaim_verb = "yowls"
|
||||
colour = "tajaran"
|
||||
key = "j"
|
||||
flags = WHITELISTED
|
||||
flags = RESTRICTED
|
||||
syllables = list("rr","rr","tajr","kir","raj","kii","mir","kra","ahk","nal","vah","khaz","jri","ran","darr", \
|
||||
"mi","jri","dynh","manq","rhe","zar","rrhaz","kal","chur","eech","thaa","dra","jurl","mah","sanu","dra","ii'r", \
|
||||
"ka","aasi","far","wa","baq","ara","qara","zir","sam","mak","hrar","nja","rir","khan","jun","dar","rik","kah", \
|
||||
"hal","ket","jurl","mah","tul","cresh","azu","ragh")
|
||||
|
||||
/datum/language/tajaran/get_random_name(var/gender)
|
||||
|
||||
var/new_name = ..(gender,1)
|
||||
if(prob(80))
|
||||
new_name += " [pick(list("Hadii","Kaytam","Zhan-Khazan","Hharar","Njarir'Akhan"))]"
|
||||
else
|
||||
new_name += ..(gender,1)
|
||||
return new_name
|
||||
|
||||
/datum/language/skrell
|
||||
name = "Skrellian"
|
||||
@@ -49,7 +182,8 @@
|
||||
exclaim_verb = "warbles"
|
||||
colour = "skrell"
|
||||
key = "k"
|
||||
flags = WHITELISTED
|
||||
flags = RESTRICTED
|
||||
syllables = list("qr","qrr","xuq","qil","quum","xuqm","vol","xrim","zaoo","qu-uu","qix","qoo","zix","*","!")
|
||||
|
||||
/datum/language/vox
|
||||
name = "Vox-pidgin"
|
||||
@@ -59,7 +193,12 @@
|
||||
exclaim_verb = "SHRIEKS"
|
||||
colour = "vox"
|
||||
key = "v"
|
||||
flags = RESTRICTED
|
||||
flags = RESTRICTED | WHITELISTED
|
||||
syllables = list("ti","ti","ti","hi","hi","ki","ki","ki","ki","ya","ta","ha","ka","ya","chi","cha","kah", \
|
||||
"SKRE","AHK","EHK","RAWK","KRA","AAA","EEE","KI","II","KRI","KA")
|
||||
|
||||
/datum/language/vox/get_random_name()
|
||||
return ..(FEMALE,1,6)
|
||||
|
||||
/datum/language/diona
|
||||
name = "Rootspeak"
|
||||
@@ -67,79 +206,258 @@
|
||||
speech_verb = "creaks and rustles"
|
||||
ask_verb = "creaks"
|
||||
exclaim_verb = "rustles"
|
||||
colour = "soghun"
|
||||
colour = "diona"
|
||||
key = "q"
|
||||
flags = RESTRICTED
|
||||
syllables = list("hs","zt","kr","st","sh")
|
||||
|
||||
/datum/language/diona/get_random_name()
|
||||
var/new_name = "[pick(list("To Sleep Beneath","Wind Over","Embrace of","Dreams of","Witnessing","To Walk Beneath","Approaching the"))]"
|
||||
new_name += " [pick(list("the Void","the Sky","Encroaching Night","Planetsong","Starsong","the Wandering Star","the Empty Day","Daybreak","Nightfall","the Rain"))]"
|
||||
return new_name
|
||||
|
||||
/datum/language/trinary
|
||||
name = "Trinary"
|
||||
desc = "A modification of binary to allow fuzzy logic. 0 is no, 1 is maybe, 2 is yes. Credited with giving Machine People the ability to think creatively."
|
||||
speech_verb = "states"
|
||||
ask_verb = "queries"
|
||||
exclaim_verb = "exclaims"
|
||||
colour = "trinary"
|
||||
key = "5"
|
||||
flags = RESTRICTED | WHITELISTED
|
||||
syllables = list("02011","01222","10100","10210","21012","02011","21200","1002","2001","0002","0012","0012","000","120","121","201","220","10","11","0")
|
||||
|
||||
/datum/language/kidan
|
||||
name = "Chittin"
|
||||
desc = "The noise made by rubbing it's antennae together is actually a complex form of communication for Kidan."
|
||||
speech_verb = "rubs its antenna together"
|
||||
ask_verb = "rubs its antenna together"
|
||||
exclaim_verb = "rubs its antenna together"
|
||||
colour = "tajaran"
|
||||
desc = "The noise made by rubbing its antennae together is actually a complex form of communication for Kidan."
|
||||
speech_verb = "rubs its antennae together"
|
||||
ask_verb = "rubs its antennae together"
|
||||
exclaim_verb = "rubs its antennae together"
|
||||
colour = "kidan"
|
||||
key = "4"
|
||||
flags = RESTRICTED
|
||||
|
||||
flags = RESTRICTED | WHITELISTED
|
||||
syllables = list("click","clack")
|
||||
|
||||
/datum/language/slime
|
||||
name = "Bubblish"
|
||||
desc = "Languages of slimes, a mixture of bubbling noises and pops. Almost impossible to speak without mechanical aid for non slime people."
|
||||
desc = "The language of slimes. It's a mixture of bubbling noises and pops. Very difficult to speak without mechanical aid for humans."
|
||||
speech_verb = "bubbles and pops"
|
||||
ask_verb = "bubbles and pops"
|
||||
exclaim_verb = "bubbles and pops"
|
||||
colour = "skrell"
|
||||
colour = "slime"
|
||||
key = "f"
|
||||
flags = RESTRICTED | WHITELISTED
|
||||
syllables = list("blob","plop","pop","bop","boop")
|
||||
|
||||
/datum/language/common
|
||||
name = "Galactic Common"
|
||||
desc = "The common galactic tongue."
|
||||
speech_verb = "says"
|
||||
whisper_verb = "whispers"
|
||||
key = "0"
|
||||
flags = RESTRICTED
|
||||
syllables = list("blah","blah","blah","bleh","meh","neh","nah","wah")
|
||||
|
||||
//TODO flag certain languages to use the mob-type specific say_quote and then get rid of these.
|
||||
/datum/language/common/get_spoken_verb(var/msg_end)
|
||||
switch(msg_end)
|
||||
if("!")
|
||||
return pick("exclaims","shouts","yells") //TODO: make the basic proc handle lists of verbs.
|
||||
if("?")
|
||||
return ask_verb
|
||||
return speech_verb
|
||||
|
||||
/datum/language/human
|
||||
name = "Sol Common"
|
||||
desc = "A bastardized hybrid of informal English and elements of Mandarin Chinese; the common language of the Sol system."
|
||||
speech_verb = "says"
|
||||
whisper_verb = "whispers"
|
||||
colour = "solcom"
|
||||
key = "1"
|
||||
flags = RESTRICTED
|
||||
syllables = list("tao","shi","tzu","yi","com","be","is","i","op","vi","ed","lec","mo","cle","te","dis","e")
|
||||
|
||||
/datum/language/trinary
|
||||
name = "Trinary"
|
||||
desc = "A modification of binary to allow fuzzy logic. 0 is no, 1 maybe, 2 yes. Credited with giving Machine People the ability to think creatively."
|
||||
key = "5"
|
||||
flags = RESTRICTED
|
||||
|
||||
/datum/language/human/get_spoken_verb(var/msg_end)
|
||||
switch(msg_end)
|
||||
if("!")
|
||||
return pick("exclaims","shouts","yells") //TODO: make the basic proc handle lists of verbs.
|
||||
if("?")
|
||||
return ask_verb
|
||||
return speech_verb
|
||||
|
||||
// Galactic common languages (systemwide accepted standards).
|
||||
/datum/language/trader
|
||||
name = "Tradeband"
|
||||
desc = "Maintained by the various trading cartels in major systems, this elegant, structured language is used for bartering and bargaining."
|
||||
speech_verb = "enunciates"
|
||||
colour = "say_quote"
|
||||
key = "2"
|
||||
space_chance = 100
|
||||
syllables = list("lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit",
|
||||
"sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore",
|
||||
"magna", "aliqua", "ut", "enim", "ad", "minim", "veniam", "quis", "nostrud",
|
||||
"exercitation", "ullamco", "laboris", "nisi", "ut", "aliquip", "ex", "ea", "commodo",
|
||||
"consequat", "duis", "aute", "irure", "dolor", "in", "reprehenderit", "in",
|
||||
"voluptate", "velit", "esse", "cillum", "dolore", "eu", "fugiat", "nulla",
|
||||
"pariatur", "excepteur", "sint", "occaecat", "cupidatat", "non", "proident", "sunt",
|
||||
"in", "culpa", "qui", "officia", "deserunt", "mollit", "anim", "id", "est", "laborum")
|
||||
|
||||
/datum/language/gutter
|
||||
name = "Gutter"
|
||||
desc = "Much like Standard, this crude pidgin tongue descended from numerous languages and serves as Tradeband for criminal elements."
|
||||
speech_verb = "growls"
|
||||
colour = "rough"
|
||||
key = "3"
|
||||
syllables = list ("gra","ba","ba","breh","bra","rah","dur","ra","ro","gro","go","ber","bar","geh","heh", "gra")
|
||||
|
||||
/datum/language/xenocommon
|
||||
name = "Xenomorph"
|
||||
colour = "alien"
|
||||
desc = "The common tongue of the xenomorphs."
|
||||
speech_verb = "hisses"
|
||||
ask_verb = "hisses"
|
||||
exclaim_verb = "hisses"
|
||||
key = "6"
|
||||
flags = RESTRICTED
|
||||
syllables = list("sss","sSs","SSS")
|
||||
|
||||
/datum/language/xenos
|
||||
name = "Hivemind"
|
||||
desc = "Xenomorphs have the strange ability to commune over a psychic hivemind."
|
||||
speech_verb = "hisses"
|
||||
ask_verb = "hisses"
|
||||
exclaim_verb = "hisses"
|
||||
colour = "alien"
|
||||
key = "a"
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
|
||||
/datum/language/xenos/check_special_condition(var/mob/other)
|
||||
var/mob/living/carbon/M = other
|
||||
if(!istype(M))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/language/ling
|
||||
name = "Changeling"
|
||||
desc = "Although they are normally wary and suspicious of each other, changelings can commune over a distance."
|
||||
speech_verb = "says"
|
||||
colour = "changeling"
|
||||
key = "g"
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
|
||||
/datum/language/ling/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
|
||||
|
||||
if(speaker.mind && speaker.mind.changeling)
|
||||
..(speaker,message,speaker.mind.changeling.changelingID)
|
||||
else
|
||||
..(speaker,message)
|
||||
|
||||
/datum/language/corticalborer
|
||||
name = "Cortical Link"
|
||||
desc = "Cortical borers possess a strange link between their tiny minds."
|
||||
speech_verb = "sings"
|
||||
ask_verb = "sings"
|
||||
exclaim_verb = "sings"
|
||||
colour = "alien"
|
||||
key = "x"
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
|
||||
/datum/language/corticalborer/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
|
||||
|
||||
var/mob/living/simple_animal/borer/B
|
||||
|
||||
if(istype(speaker,/mob/living/carbon))
|
||||
var/mob/living/carbon/M = speaker
|
||||
B = M.has_brain_worms()
|
||||
else if(istype(speaker,/mob/living/simple_animal/borer))
|
||||
B = speaker
|
||||
|
||||
if(B)
|
||||
speaker_mask = B.truename
|
||||
..(speaker,message,speaker_mask)
|
||||
|
||||
/datum/language/binary
|
||||
name = "Robot Talk"
|
||||
desc = "Most human stations support free-use communications protocols and routing hubs for synthetic use."
|
||||
colour = "say_quote"
|
||||
speech_verb = "states"
|
||||
ask_verb = "queries"
|
||||
exclaim_verb = "declares"
|
||||
key = "b"
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
var/drone_only
|
||||
|
||||
/datum/language/binary/broadcast(var/mob/living/speaker,var/message,var/speaker_mask)
|
||||
|
||||
if(!speaker.binarycheck())
|
||||
return
|
||||
|
||||
if (!message)
|
||||
return
|
||||
|
||||
var/message_start = "<i><span class='game say'>[name], <span class='name'>[speaker.name]</span>"
|
||||
var/message_body = "<span class='message'>[speaker.say_quote(message)], \"[message]\"</span></span></i>"
|
||||
|
||||
for (var/mob/M in dead_mob_list)
|
||||
if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) //No meta-evesdropping
|
||||
M.show_message("[message_start] [message_body]", 2)
|
||||
|
||||
for (var/mob/living/S in living_mob_list)
|
||||
|
||||
if(drone_only && !istype(S,/mob/living/silicon/robot/drone))
|
||||
continue
|
||||
else if(istype(S , /mob/living/silicon/ai))
|
||||
message_start = "<i><span class='game say'>[name], <a href='byond://?src=\ref[S];track2=\ref[S];track=\ref[speaker];trackname=[html_encode(speaker.name)]'><span class='name'>[speaker.name]</span></a>"
|
||||
else if (!S.binarycheck())
|
||||
continue
|
||||
|
||||
S.show_message("[message_start] [message_body]", 2)
|
||||
|
||||
var/list/listening = hearers(1, src)
|
||||
listening -= src
|
||||
|
||||
for (var/mob/living/M in listening)
|
||||
if(istype(M, /mob/living/silicon) || M.binarycheck())
|
||||
continue
|
||||
M.show_message("<i><span class='game say'><span class='name'>synthesised voice</span> <span class='message'>beeps, \"beep beep beep\"</span></span></i>",2)
|
||||
|
||||
//robot binary xmitter component power usage
|
||||
if (isrobot(speaker))
|
||||
var/mob/living/silicon/robot/R = speaker
|
||||
var/datum/robot_component/C = R.components["comms"]
|
||||
R.use_power(C.energy_consumption)
|
||||
|
||||
/datum/language/binary/drone
|
||||
name = "Drone Talk"
|
||||
desc = "A heavily encoded damage control coordination stream."
|
||||
speech_verb = "transmits"
|
||||
ask_verb = "transmits"
|
||||
exclaim_verb = "transmits"
|
||||
colour = "say_quote"
|
||||
key = "d"
|
||||
flags = RESTRICTED | HIVEMIND
|
||||
drone_only = 1
|
||||
|
||||
// Language handling.
|
||||
/mob/proc/add_language(var/language)
|
||||
|
||||
for(var/datum/language/L in languages)
|
||||
if(L && L.name == language)
|
||||
return 0
|
||||
|
||||
var/datum/language/new_language = all_languages[language]
|
||||
|
||||
if(!istype(new_language,/datum/language))
|
||||
if(!istype(new_language) || new_language in languages)
|
||||
return 0
|
||||
|
||||
languages += new_language
|
||||
languages |= new_language
|
||||
return 1
|
||||
|
||||
/mob/proc/remove_language(var/rem_language)
|
||||
var/datum/language/L = all_languages[rem_language]
|
||||
. = (L in languages)
|
||||
languages.Remove(L)
|
||||
|
||||
for(var/datum/language/L in languages)
|
||||
if(L && L.name == rem_language)
|
||||
languages -= L
|
||||
return 1
|
||||
// Can we speak this language, as opposed to just understanding it?
|
||||
/mob/proc/can_speak(datum/language/speaking)
|
||||
|
||||
return 0
|
||||
return (universal_speak || (speaking && speaking.flags & INNATE) || speaking in src.languages)
|
||||
|
||||
//TBD
|
||||
/mob/verb/check_languages()
|
||||
@@ -150,7 +468,10 @@
|
||||
var/dat = "<b><font size = 5>Known Languages</font></b><br/><br/>"
|
||||
|
||||
for(var/datum/language/L in languages)
|
||||
dat += "<b>[L.name] (:[L.key])</b><br/>[L.desc]<br/><br/>"
|
||||
if(!(L.flags & NONGLOBAL))
|
||||
dat += "<b>[L.name] (:[L.key])</b><br/>[L.desc]<br/><br/>"
|
||||
|
||||
src << browse(dat, "window=checklanguage")
|
||||
return
|
||||
return
|
||||
|
||||
#undef SCRAMBLE_CACHE_LEN
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
if(name == "alien")
|
||||
name = text("alien ([rand(1, 1000)])")
|
||||
real_name = name
|
||||
add_language("Xenomorph")
|
||||
add_language("Hivemind")
|
||||
..()
|
||||
|
||||
//This is fine, works the same as a human
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
name = "alien larva ([rand(1, 1000)])"
|
||||
real_name = name
|
||||
regenerate_icons()
|
||||
add_language("Xenomorph")
|
||||
add_language("Hivemind")
|
||||
..()
|
||||
|
||||
//This is fine, works the same as a human
|
||||
|
||||
@@ -1,69 +1,28 @@
|
||||
/mob/living/carbon/alien/say(var/message)
|
||||
var/verb = "says"
|
||||
var/message_range = world.view
|
||||
|
||||
if (silent)
|
||||
return
|
||||
if(client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot speak in IC (Muted)."
|
||||
return
|
||||
|
||||
if (length(message) >= 2)
|
||||
if (department_radio_keys[copytext(message, 1, 3)] == "alientalk")
|
||||
message = copytext(message, 3)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
if (stat == 2)
|
||||
return say_dead(message)
|
||||
else
|
||||
alien_talk(message)
|
||||
else
|
||||
if (copytext(message, 1, 2) != "*" && !stat)
|
||||
playsound(loc, "hiss", 25, 1, 1)//So aliens can hiss while they hiss yo/N
|
||||
return ..(message)
|
||||
else
|
||||
message = trim_strip_html_properly(message)
|
||||
|
||||
/mob/living/proc/alien_talk(var/message)
|
||||
if(stat == 2)
|
||||
return say_dead(message)
|
||||
|
||||
if(copytext(message,1,2) == "*")
|
||||
return emote(copytext(message,2))
|
||||
|
||||
var/datum/language/speaking = parse_language(message)
|
||||
|
||||
if(speaking)
|
||||
message = copytext(message, 2+length(speaking.key))
|
||||
|
||||
log_say("[key_name(src)] : [message]")
|
||||
message = trim(message)
|
||||
|
||||
if (!message)
|
||||
if(!message || stat)
|
||||
return
|
||||
|
||||
var/message_a = say_quote(message)
|
||||
var/rendered = "<i><span class='game say'>Hivemind, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
|
||||
for (var/mob/living/S in player_list)
|
||||
if(!S.stat)
|
||||
if(S.alien_talk_understand)
|
||||
if(S.alien_talk_understand == alien_talk_understand)
|
||||
S.show_message(rendered, 2)
|
||||
else if (S.hivecheck())
|
||||
S.show_message(rendered, 2)
|
||||
|
||||
var/list/listening = hearers(1, src)
|
||||
listening -= src
|
||||
listening += src
|
||||
|
||||
var/list/heard = list()
|
||||
for (var/mob/M in listening)
|
||||
if(!istype(M, /mob/living/carbon/alien) && !M.alien_talk_understand)
|
||||
heard += M
|
||||
|
||||
|
||||
if (length(heard))
|
||||
var/message_b
|
||||
|
||||
message_b = "hsssss"
|
||||
message_b = say_quote(message_b)
|
||||
message_b = "<i>[message_b]</i>"
|
||||
|
||||
rendered = "<i><span class='game say'><span class='name'>[voice_name]</span> <span class='message'>[message_b]</span></span></i>"
|
||||
|
||||
for (var/mob/M in heard)
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
message = say_quote(message)
|
||||
|
||||
rendered = "<i><span class='game say'>Hivemind, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
|
||||
var/rendered2 = null
|
||||
for (var/mob/M in player_list)
|
||||
if (istype(M, /mob/new_player))
|
||||
continue
|
||||
if (M.stat > 1 && istype(M, /mob/dead/observer))
|
||||
rendered2 = "<i><span class='game say'>Hivemind, <span class='name'>[name]</span> <a href='byond://?src=\ref[M];follow2=\ref[M];follow=\ref[src]'>(Follow)</a> <span class='message'>[message_a]</span></span></i>"
|
||||
M.show_message(rendered2, 2)
|
||||
..(message, speaking, verb, null, null, message_range, null)
|
||||
@@ -55,4 +55,7 @@
|
||||
canmove = 1
|
||||
use_me = 1 //If it can move, let it emote
|
||||
else canmove = 0
|
||||
return canmove
|
||||
return canmove
|
||||
|
||||
/mob/living/carbon/brain/binarycheck()
|
||||
return istype(loc, /obj/item/device/mmi/posibrain)
|
||||
@@ -1,3 +1,4 @@
|
||||
//TODO: Convert this over for languages.
|
||||
/mob/living/carbon/brain/say(var/message)
|
||||
if (silent)
|
||||
return
|
||||
@@ -8,18 +9,31 @@
|
||||
if(!(container && (istype(container, /obj/item/device/mmi) || istype(container, /obj/item/device/mmi/posibrain))))
|
||||
return //No MMI, can't speak, bucko./N
|
||||
else
|
||||
if ((department_radio_keys[copytext(message, 1, 3)] == "binary") && (container && istype(container, /obj/item/device/mmi/posibrain)))
|
||||
message = copytext(message, 3)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
robot_talk(message)
|
||||
return
|
||||
var/datum/language/speaking = parse_language(message)
|
||||
if(speaking)
|
||||
message = copytext(message, 2+length(speaking.key))
|
||||
var/verb = "says"
|
||||
var/ending = copytext(message, length(message))
|
||||
if (speaking)
|
||||
verb = speaking.get_spoken_verb(ending)
|
||||
else
|
||||
if(ending=="!")
|
||||
verb=pick("exclaims","shouts","yells")
|
||||
if(ending=="?")
|
||||
verb="asks"
|
||||
|
||||
if(prob(emp_damage*4))
|
||||
if(prob(10))//10% chane to drop the message entirely
|
||||
return
|
||||
else
|
||||
message = Gibberish(message, (emp_damage*6))//scrambles the message, gets worse when emp_damage is higher
|
||||
|
||||
if(speaking && speaking.flags & HIVEMIND)
|
||||
speaking.broadcast(src,trim(message))
|
||||
return
|
||||
|
||||
if(istype(container, /obj/item/device/mmi/radio_enabled))
|
||||
var/obj/item/device/mmi/radio_enabled/R = container
|
||||
if(R.radio)
|
||||
spawn(0) R.radio.hear_talk(src, sanitize(message))
|
||||
..()
|
||||
spawn(0) R.radio.hear_talk(src, trim(sanitize(message)), verb, speaking)
|
||||
..(trim(message), speaking, verb)
|
||||
|
||||
@@ -9,6 +9,40 @@
|
||||
var/datum/species/species //Contains icon generation and language information, set during New().
|
||||
var/embedded_flag //To check if we've need to roll for damage on movement while an item is imbedded in us.
|
||||
|
||||
/mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna=0)
|
||||
if(!species)
|
||||
if(new_species)
|
||||
set_species(new_species,null,1)
|
||||
else
|
||||
set_species()
|
||||
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
reagents = R
|
||||
R.my_atom = src
|
||||
|
||||
hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudhealth100")
|
||||
hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudhealthy")
|
||||
hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudunknown")
|
||||
hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[STATUS_HUD_OOC] = image('icons/mob/hud.dmi', src, "hudhealthy")
|
||||
hud_list[NATIONS_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
|
||||
..()
|
||||
|
||||
if(dna)
|
||||
dna.real_name = real_name
|
||||
|
||||
prev_gender = gender // Debug for plural genders
|
||||
make_blood()
|
||||
|
||||
// Set up DNA.
|
||||
if(!delay_ready_dna)
|
||||
dna.ready_dna(src)
|
||||
|
||||
/mob/living/carbon/human/dummy
|
||||
real_name = "Test Dummy"
|
||||
status_flags = GODMODE|CANPUSH
|
||||
@@ -49,8 +83,6 @@
|
||||
|
||||
/mob/living/carbon/human/grey/New(var/new_loc)
|
||||
..(new_loc, "Grey")
|
||||
spell_list += new /obj/effect/proc_holder/spell/wizard/targeted/remotetalk
|
||||
|
||||
|
||||
/mob/living/carbon/human/human/New(var/new_loc)
|
||||
..(new_loc, "Human")
|
||||
@@ -63,50 +95,6 @@
|
||||
h_style = "blue IPC screen"
|
||||
..(new_loc, "Machine")
|
||||
|
||||
/mob/living/carbon/human/New(var/new_loc, var/new_species = null, var/delay_ready_dna=0)
|
||||
if(!species)
|
||||
if(new_species)
|
||||
set_species(new_species,null,1)
|
||||
else
|
||||
set_species()
|
||||
|
||||
if(species.language)
|
||||
var/datum/language/L = all_languages[species.language]
|
||||
if(L)
|
||||
languages += L
|
||||
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
reagents = R
|
||||
R.my_atom = src
|
||||
|
||||
if(!dna)
|
||||
dna = new /datum/dna(null)
|
||||
dna.species=species.name
|
||||
|
||||
hud_list[HEALTH_HUD] = image('icons/mob/hud.dmi', src, "hudhealth100")
|
||||
hud_list[STATUS_HUD] = image('icons/mob/hud.dmi', src, "hudhealthy")
|
||||
hud_list[ID_HUD] = image('icons/mob/hud.dmi', src, "hudunknown")
|
||||
hud_list[WANTED_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[IMPLOYAL_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[IMPCHEM_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[IMPTRACK_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[SPECIALROLE_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
hud_list[STATUS_HUD_OOC] = image('icons/mob/hud.dmi', src, "hudhealthy")
|
||||
hud_list[NATIONS_HUD] = image('icons/mob/hud.dmi', src, "hudblank")
|
||||
|
||||
..()
|
||||
|
||||
if(dna)
|
||||
dna.real_name = real_name
|
||||
|
||||
prev_gender = gender // Debug for plural genders
|
||||
make_blood()
|
||||
|
||||
// Set up DNA.
|
||||
if(!delay_ready_dna)
|
||||
dna.ready_dna(src)
|
||||
|
||||
|
||||
/mob/living/carbon/human/Bump(atom/movable/AM as mob|obj, yes)
|
||||
if ((!( yes ) || now_pushing))
|
||||
return
|
||||
@@ -1313,7 +1301,8 @@
|
||||
usr << "\blue [self ? "Your" : "[src]'s"] pulse is [src.get_pulse(GETPULSE_HAND)]."
|
||||
|
||||
/mob/living/carbon/human/proc/set_species(var/new_species, var/force_organs, var/default_colour)
|
||||
|
||||
|
||||
var/datum/species/oldspecies = species
|
||||
if(!dna)
|
||||
if(!new_species)
|
||||
new_species = "Human"
|
||||
@@ -1323,19 +1312,34 @@
|
||||
else
|
||||
dna.species = new_species
|
||||
|
||||
if(species && (species.name && species.name == new_species))
|
||||
return
|
||||
|
||||
if(species && species.language)
|
||||
remove_language(species.language)
|
||||
if(species)
|
||||
if(species.name && species.name == new_species)
|
||||
return
|
||||
|
||||
if(species.language)
|
||||
remove_language(species.language)
|
||||
|
||||
if(species.default_language)
|
||||
remove_language(species.default_language)
|
||||
|
||||
species = all_species[new_species]
|
||||
|
||||
if(oldspecies)
|
||||
if(oldspecies.default_genes.len)
|
||||
oldspecies.handle_dna(src,1) // Remove any genes that belong to the old species
|
||||
|
||||
if(force_organs || !organs || !organs.len)
|
||||
species.create_organs(src)
|
||||
|
||||
if(vessel)
|
||||
vessel = null
|
||||
make_blood()
|
||||
|
||||
if(species.language)
|
||||
add_language(species.language)
|
||||
|
||||
if(species.default_language)
|
||||
add_language(species.default_language)
|
||||
|
||||
see_in_dark = species.darksight
|
||||
if(see_in_dark > 2)
|
||||
@@ -1343,9 +1347,6 @@
|
||||
else
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
|
||||
if(species.default_mutations.len>0 || species.default_blocks.len>0)
|
||||
do_deferred_species_setup=1
|
||||
|
||||
spawn(0)
|
||||
update_icons()
|
||||
|
||||
@@ -1358,21 +1359,18 @@
|
||||
r_skin = 0
|
||||
g_skin = 0
|
||||
b_skin = 0
|
||||
|
||||
if(!dna)
|
||||
dna = new /datum/dna(null)
|
||||
dna.species = species.name
|
||||
dna.real_name = real_name
|
||||
dna.mutantrace = null
|
||||
|
||||
species.handle_post_spawn(src)
|
||||
|
||||
spawn(0)
|
||||
update_icons()
|
||||
if(species && species.flags & NO_BLOOD) //We want the var for safety but we can do without the actual blood.
|
||||
if(vessel.has_reagent("water") || vessel.has_reagent("blood"))
|
||||
var/water = vessel.get_reagent_amount("water")
|
||||
var/blood = vessel.get_reagent_amount("blood")
|
||||
vessel.remove_reagent("water",water)
|
||||
vessel.remove_reagent("blood",blood)
|
||||
if(species.bloodflags & BLOOD_SLIME)
|
||||
vessel.add_reagent("water",560-vessel.total_volume)
|
||||
else
|
||||
vessel.add_reagent("blood",560-vessel.total_volume)
|
||||
overlays.Cut()
|
||||
update_mutantrace(1)
|
||||
fixblood()
|
||||
|
||||
if(species)
|
||||
|
||||
@@ -32,9 +32,12 @@
|
||||
timeofdeath = 0
|
||||
|
||||
/mob/living/carbon/human/getBrainLoss()
|
||||
if(species && species.flags & NO_INTORGANS) return
|
||||
if(species && species.flags & NO_INTORGANS)
|
||||
return
|
||||
var/res = brainloss
|
||||
var/datum/organ/internal/brain/sponge = internal_organs_by_name["brain"]
|
||||
if(!sponge)
|
||||
return
|
||||
if (sponge.is_bruised())
|
||||
res += 20
|
||||
if (sponge.is_broken())
|
||||
@@ -197,6 +200,7 @@
|
||||
UpdateDamageIcon()
|
||||
hud_updateflag |= 1 << HEALTH_HUD
|
||||
updatehealth()
|
||||
speech_problem_flag = 1
|
||||
|
||||
|
||||
//Heal MANY external organs, in random order
|
||||
@@ -218,6 +222,7 @@
|
||||
parts -= picked
|
||||
updatehealth()
|
||||
hud_updateflag |= 1 << HEALTH_HUD
|
||||
speech_problem_flag = 1
|
||||
if(update) UpdateDamageIcon()
|
||||
|
||||
// damage MANY external organs, in random order
|
||||
|
||||
@@ -50,6 +50,10 @@
|
||||
|
||||
var/icon/stand_icon = null
|
||||
var/icon/lying_icon = null
|
||||
|
||||
var/voice = "" //Instead of new say code calling GetVoice() over and over and over, we're just going to ask this variable, which gets updated in Life()
|
||||
|
||||
var/speech_problem_flag = 0
|
||||
|
||||
var/miming = null //Toggle for the mime's abilities.
|
||||
var/special_voice = "" // For changing our voice. Used by a symptom.
|
||||
|
||||
@@ -33,27 +33,9 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
|
||||
var/prev_gender = null // Debug for plural genders
|
||||
var/temperature_alert = 0
|
||||
var/in_stasis = 0
|
||||
var/do_deferred_species_setup=0
|
||||
var/exposedtimenow = 0
|
||||
var/firstexposed = 0
|
||||
|
||||
// Doing this during species init breaks shit.
|
||||
/mob/living/carbon/human/proc/DeferredSpeciesSetup()
|
||||
var/mut_update=0
|
||||
if(species.default_mutations.len>0)
|
||||
for(var/mutation in species.default_mutations)
|
||||
if(!(mutation in mutations))
|
||||
mutations.Add(mutation)
|
||||
mut_update=1
|
||||
if(species.default_blocks.len>0)
|
||||
for(var/block in species.default_blocks)
|
||||
if(!dna.GetSEState(block))
|
||||
dna.SetSEState(block,1)
|
||||
mut_update=1
|
||||
if(mut_update)
|
||||
domutcheck(src,null,MUTCHK_FORCED)
|
||||
update_mutations()
|
||||
|
||||
/mob/living/carbon/human/Life()
|
||||
set invisibility = 0
|
||||
//set background = 1
|
||||
@@ -63,10 +45,6 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
|
||||
|
||||
..()
|
||||
|
||||
if(do_deferred_species_setup)
|
||||
DeferredSpeciesSetup()
|
||||
do_deferred_species_setup=0
|
||||
|
||||
//Apparently, the person who wrote this code designed it so that
|
||||
//blinded get reset each cycle and then get activated later in the
|
||||
//code. Very ugly. I dont care. Moving this stuff here so its easy
|
||||
@@ -84,6 +62,8 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
|
||||
|
||||
if(life_tick%30==15)
|
||||
hud_updateflag = 1022
|
||||
|
||||
voice = GetVoice()
|
||||
|
||||
//No need to update all of these procs if the guy is dead.
|
||||
if(stat != DEAD && !in_stasis)
|
||||
@@ -252,22 +232,26 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
|
||||
drop_item()
|
||||
emote("cough")
|
||||
if (disabilities & TOURETTES)
|
||||
speech_problem_flag = 1
|
||||
if ((prob(10) && paralysis <= 1))
|
||||
Stun(10)
|
||||
switch(rand(1, 3))
|
||||
if(1)
|
||||
emote("twitch")
|
||||
if(2 to 3)
|
||||
say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]")
|
||||
var/tourettes = pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")
|
||||
say("[prob(50) ? ";" : ""][tourettes]")
|
||||
var/x_offset = pixel_x + rand(-2,2) //Should probably be moved into the twitch emote at some point.
|
||||
var/y_offset = pixel_y + rand(-1,1)
|
||||
animate(src, pixel_x = pixel_x + x_offset, pixel_y = pixel_y + y_offset, time = 1)
|
||||
animate(pixel_x = pixel_x - x_offset, pixel_y = pixel_y - y_offset, time = 1)
|
||||
if (disabilities & NERVOUS)
|
||||
speech_problem_flag = 1
|
||||
if (prob(10))
|
||||
stuttering = max(10, stuttering)
|
||||
|
||||
if (getBrainLoss() >= 60 && stat != 2)
|
||||
speech_problem_flag = 1
|
||||
if (prob(3))
|
||||
switch(pick(1,2,3))
|
||||
if(1)
|
||||
@@ -329,6 +313,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
|
||||
if(gene.is_active(src))
|
||||
/* if (prob(10) && prob(gene.instability))
|
||||
adjustCloneLoss(1) */
|
||||
speech_problem_flag = 1
|
||||
gene.OnMobLife(src)
|
||||
|
||||
if (radiation)
|
||||
@@ -1091,6 +1076,7 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
|
||||
if(halloss > 0)
|
||||
adjustHalLoss(-3)
|
||||
else if(sleeping)
|
||||
speech_problem_flag = 1
|
||||
handle_dreams()
|
||||
adjustStaminaLoss(-10)
|
||||
adjustHalLoss(-3)
|
||||
@@ -1944,7 +1930,29 @@ var/global/list/brutefireloss_overlays = list("1" = image("icon" = 'icons/mob/sc
|
||||
var/client/C = client
|
||||
for(var/mob/living/carbon/human/H in view(src, 14))
|
||||
C.images += H.hud_list[NATIONS_HUD]
|
||||
|
||||
/mob/living/carbon/human/handle_silent()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return silent
|
||||
|
||||
/mob/living/carbon/human/handle_slurring()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return slurring
|
||||
|
||||
/mob/living/carbon/human/handle_stunned()
|
||||
if(species.flags & NO_PAIN)
|
||||
stunned = 0
|
||||
return 0
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return stunned
|
||||
|
||||
/mob/living/carbon/human/handle_stuttering()
|
||||
if(..())
|
||||
speech_problem_flag = 1
|
||||
return stuttering
|
||||
|
||||
// Need this in species.
|
||||
//#undef HUMAN_MAX_OXYLOSS
|
||||
|
||||
@@ -1,81 +1,152 @@
|
||||
/mob/living/carbon/human/say(var/message)
|
||||
if(miming)
|
||||
if(length(message) >= 2)
|
||||
if(mind && mind.changeling)
|
||||
if(copytext(message, 1, 2) != "*" && department_radio_keys[copytext(message, 1, 3)] != "changeling")
|
||||
return
|
||||
else
|
||||
return ..(message)
|
||||
if(stat == DEAD)
|
||||
return ..(message)
|
||||
|
||||
if(length(message) >= 1) //In case people forget the '*help' command, this will slow them the message and prevent people from saying one letter at a time
|
||||
if (copytext(message, 1, 2) != "*")
|
||||
return
|
||||
var/verb = "says"
|
||||
var/alt_name = ""
|
||||
var/message_range = world.view
|
||||
var/italics = 0
|
||||
|
||||
if(dna)
|
||||
if(length(message) >= 2)
|
||||
if (copytext(message, 1, 2) != "*" && department_radio_keys[copytext(message, 1, 3)] != "changeling")
|
||||
for(var/datum/dna/gene/gene in dna_genes)
|
||||
if(!gene.block)
|
||||
continue
|
||||
if(gene.is_active(src))
|
||||
message = gene.OnSay(src,message)
|
||||
/*
|
||||
if(dna.mutantrace == "lizard")
|
||||
if(copytext(message, 1, 2) != "*")
|
||||
message = replacetext(message, "s", stutter("ss"))
|
||||
if(client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot speak in IC (Muted)."
|
||||
return
|
||||
|
||||
if(dna.mutantrace == "slime" && prob(5))
|
||||
if(copytext(message, 1, 2) != "*")
|
||||
if(copytext(message, 1, 2) == ";")
|
||||
message = ";"
|
||||
else
|
||||
message = ""
|
||||
message += "SKR"
|
||||
var/imax = rand(5,20)
|
||||
for(var/i = 0,i<imax,i++)
|
||||
message += "E"*/
|
||||
message = trim_strip_html_properly(message)
|
||||
|
||||
if(stat)
|
||||
if(stat == 2)
|
||||
return say_dead(message)
|
||||
return
|
||||
|
||||
if (istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
|
||||
src << "<span class='danger'>You're muzzled and cannot speak!</span>"
|
||||
return
|
||||
|
||||
var/message_mode = parse_message_mode(message, "headset")
|
||||
|
||||
if(copytext(message,1,2) == "*")
|
||||
return emote(copytext(message,2))
|
||||
|
||||
if(name != GetVoice())
|
||||
alt_name = "(as [get_id_name("Unknown")])"
|
||||
|
||||
//parse the radio code and consume it
|
||||
if (message_mode)
|
||||
if (message_mode == "headset")
|
||||
message = copytext(message,2) //it would be really nice if the parse procs could do this for us.
|
||||
else
|
||||
message = copytext(message,3)
|
||||
|
||||
//parse the language code and consume it
|
||||
var/datum/language/speaking = parse_language(message)
|
||||
if(speaking)
|
||||
message = copytext(message,2+length(speaking.key))
|
||||
else if(species.default_language)
|
||||
speaking = all_languages[species.default_language]
|
||||
|
||||
var/ending = copytext(message, length(message))
|
||||
if (speaking)
|
||||
// This is broadcast to all mobs with the language,
|
||||
// irrespective of distance or anything else.
|
||||
if(speaking.flags & HIVEMIND)
|
||||
speaking.broadcast(src,trim(message))
|
||||
return
|
||||
//If we've gotten this far, keep going!
|
||||
verb = speaking.get_spoken_verb(ending)
|
||||
else
|
||||
if(ending=="!")
|
||||
verb=pick("exclaims","shouts","yells")
|
||||
if(ending=="?")
|
||||
verb="asks"
|
||||
|
||||
message = trim(message)
|
||||
|
||||
if(speech_problem_flag)
|
||||
var/list/handle_r = handle_speech_problems(message)
|
||||
message = handle_r[1]
|
||||
verb = handle_r[2]
|
||||
speech_problem_flag = handle_r[3]
|
||||
|
||||
if(!message || message == "")
|
||||
return
|
||||
|
||||
var/list/obj/item/used_radios = new
|
||||
|
||||
switch (message_mode)
|
||||
if("headset")
|
||||
if(l_ear && istype(l_ear,/obj/item/device/radio))
|
||||
var/obj/item/device/radio/R = l_ear
|
||||
R.talk_into(src,message,null,verb,speaking)
|
||||
used_radios += l_ear
|
||||
else if(r_ear && istype(r_ear,/obj/item/device/radio))
|
||||
var/obj/item/device/radio/R = r_ear
|
||||
R.talk_into(src,message,null,verb,speaking)
|
||||
used_radios += r_ear
|
||||
|
||||
if("right ear")
|
||||
var/obj/item/device/radio/R
|
||||
var/has_radio = 0
|
||||
if(r_ear && istype(r_ear,/obj/item/device/radio))
|
||||
R = r_ear
|
||||
has_radio = 1
|
||||
if(r_hand && istype(r_hand, /obj/item/device/radio))
|
||||
R = r_hand
|
||||
has_radio = 1
|
||||
if(has_radio)
|
||||
R.talk_into(src,message,null,verb,speaking)
|
||||
used_radios += R
|
||||
|
||||
|
||||
if(wear_mask)
|
||||
if(istype(wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja) && wear_mask:voice == "Unknown")
|
||||
if(copytext(message, 1, 2) != "*")
|
||||
var/list/temp_message = text2list(message, " ")
|
||||
var/list/pick_list = list()
|
||||
for(var/i = 1, i <= temp_message.len, i++)
|
||||
pick_list += i
|
||||
for(var/i=1, i <= abs(temp_message.len/3), i++)
|
||||
var/H = pick(pick_list)
|
||||
if(findtext(temp_message[H], "*") || findtext(temp_message[H], ";") || findtext(temp_message[H], ":")) continue
|
||||
temp_message[H] = ninjaspeak(temp_message[H])
|
||||
pick_list -= H
|
||||
message = list2text(temp_message, " ")
|
||||
message = replacetext(message, "o", "¤")
|
||||
message = replacetext(message, "p", "þ")
|
||||
message = replacetext(message, "l", "£")
|
||||
message = replacetext(message, "s", "§")
|
||||
message = replacetext(message, "u", "µ")
|
||||
message = replacetext(message, "b", "ß")
|
||||
if("left ear")
|
||||
var/obj/item/device/radio/R
|
||||
var/has_radio = 0
|
||||
if(l_ear && istype(l_ear,/obj/item/device/radio))
|
||||
R = l_ear
|
||||
has_radio = 1
|
||||
if(l_hand && istype(l_hand,/obj/item/device/radio))
|
||||
R = l_hand
|
||||
has_radio = 1
|
||||
if(has_radio)
|
||||
R.talk_into(src,message,null,verb,speaking)
|
||||
used_radios += R
|
||||
|
||||
else if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
|
||||
var/obj/item/clothing/mask/horsehead/hoers = wear_mask
|
||||
if(hoers.voicechange)
|
||||
if(!(copytext(message, 1, 2) == "*" || (mind && mind.changeling && department_radio_keys[copytext(message, 1, 3)] != "changeling")))
|
||||
message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
|
||||
if("intercom")
|
||||
for(var/obj/item/device/radio/intercom/I in view(1, null))
|
||||
I.talk_into(src, message, verb, speaking)
|
||||
used_radios += I
|
||||
if("whisper")
|
||||
whisper_say(message, speaking, alt_name)
|
||||
return
|
||||
else
|
||||
if(message_mode)
|
||||
if(l_ear && istype(l_ear,/obj/item/device/radio))
|
||||
l_ear.talk_into(src,message, message_mode, verb, speaking)
|
||||
used_radios += l_ear
|
||||
else if(r_ear && istype(r_ear,/obj/item/device/radio))
|
||||
r_ear.talk_into(src,message, message_mode, verb, speaking)
|
||||
used_radios += r_ear
|
||||
|
||||
if ((M_HULK in mutations) && health >= 25 && length(message))
|
||||
if(copytext(message, 1, 2) != "*")
|
||||
message = "[uppertext(message)]!!" //because I don't know how to code properly in getting vars from other files -Bro
|
||||
var/sound/speech_sound
|
||||
var/sound_vol
|
||||
if(species.speech_sounds && prob(species.speech_chance))
|
||||
speech_sound = sound(pick(species.speech_sounds))
|
||||
sound_vol = 50
|
||||
|
||||
if (src.slurring)
|
||||
if(copytext(message, 1, 2) != "*")
|
||||
message = slur(message)
|
||||
//speaking into radios
|
||||
if(used_radios.len)
|
||||
italics = 1
|
||||
message_range = 1
|
||||
if(speaking)
|
||||
message_range = speaking.get_talkinto_msg_range(message)
|
||||
var/msg
|
||||
if(!speaking || !(speaking.flags & NO_TALK_MSG))
|
||||
msg = "<span class='notice'>\The [src] talks into \the [used_radios[1]]</span>"
|
||||
for(var/mob/living/M in hearers(5, src))
|
||||
if((M != src) && msg)
|
||||
M.show_message(msg)
|
||||
if (speech_sound)
|
||||
sound_vol *= 0.5
|
||||
|
||||
if((species.name == "Vox" || species.name == "Vox Armalis") && prob(20))
|
||||
playsound(src.loc, 'sound/voice/shriek1.ogg', 50, 1)
|
||||
|
||||
..(message)
|
||||
..(message, speaking, verb, alt_name, italics, message_range, speech_sound, sound_vol) //ohgod we should really be passing a datum here.
|
||||
|
||||
/mob/living/carbon/human/proc/forcesay(list/append)
|
||||
if(stat == CONSCIOUS)
|
||||
@@ -100,6 +171,7 @@
|
||||
if(findtext(temp, "*", 1, 2)) //emotes
|
||||
return
|
||||
temp = copytext(trim_left(temp), 1, rand(5,8))
|
||||
|
||||
var/trimmed = trim_left(temp)
|
||||
if(length(trimmed))
|
||||
if(append)
|
||||
@@ -108,25 +180,45 @@
|
||||
say(temp)
|
||||
winset(client, "input", "text=[null]")
|
||||
|
||||
/mob/living/carbon/human/say_understands(var/other,var/datum/language/speaking = null)
|
||||
/mob/living/carbon/human/say_understands(var/mob/other,var/datum/language/speaking = null)
|
||||
|
||||
if(has_brain_worms()) //Brain worms translate everything. Even mice and alien speak.
|
||||
return 1
|
||||
if (istype(other, /mob/living/silicon))
|
||||
return 1
|
||||
if (istype(other, /mob/living/carbon/brain))
|
||||
return 1
|
||||
if (istype(other, /mob/living/carbon/slime))
|
||||
|
||||
if(species.can_understand(other))
|
||||
return 1
|
||||
|
||||
//These only pertain to common. Languages are handled by mob/say_understands()
|
||||
if (!speaking)
|
||||
if (istype(other, /mob/living/carbon/monkey/diona))
|
||||
if(other.languages.len >= 2) //They've sucked down some blood and can speak common now.
|
||||
return 1
|
||||
if (istype(other, /mob/living/silicon))
|
||||
return 1
|
||||
if (istype(other, /mob/living/carbon/brain))
|
||||
return 1
|
||||
if (istype(other, /mob/living/carbon/slime))
|
||||
return 1
|
||||
|
||||
//This is already covered by mob/say_understands()
|
||||
//if (istype(other, /mob/living/simple_animal))
|
||||
// if((other.universal_speak && !speaking) || src.universal_speak || src.universal_understand)
|
||||
// return 1
|
||||
// return 0
|
||||
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/human/GetVoice()
|
||||
if(istype(src.wear_mask, /obj/item/clothing/mask/gas/voice))
|
||||
var/obj/item/clothing/mask/gas/voice/V = src.wear_mask
|
||||
if(V.vchange)
|
||||
return V.voice
|
||||
else
|
||||
return name
|
||||
|
||||
var/voice_sub
|
||||
for(var/obj/item/gear in list(wear_mask,wear_suit,head))
|
||||
if(!gear)
|
||||
continue
|
||||
var/obj/item/voice_changer/changer = locate() in gear
|
||||
if(changer && changer.active && changer.voice)
|
||||
voice_sub = changer.voice
|
||||
if(voice_sub)
|
||||
return voice_sub
|
||||
if(mind && mind.changeling && mind.changeling.mimicing)
|
||||
return mind.changeling.mimicing
|
||||
if(GetSpecialVoice())
|
||||
@@ -143,4 +235,81 @@
|
||||
return
|
||||
|
||||
/mob/living/carbon/human/proc/GetSpecialVoice()
|
||||
return special_voice
|
||||
return special_voice
|
||||
|
||||
|
||||
/*
|
||||
***Deprecated***
|
||||
let this be handled at the hear_say or hear_radio proc
|
||||
This is left in for robot speaking when humans gain binary channel access until I get around to rewriting
|
||||
robot_talk() proc.
|
||||
There is no language handling build into it however there is at the /mob level so we accept the call
|
||||
for it but just ignore it.
|
||||
*/
|
||||
|
||||
/mob/living/carbon/human/say_quote(var/message, var/datum/language/speaking = null)
|
||||
var/verb = "says"
|
||||
var/ending = copytext(message, length(message))
|
||||
|
||||
if(speaking)
|
||||
verb = speaking.get_spoken_verb(ending)
|
||||
else
|
||||
if(ending == "!")
|
||||
verb = "exclaims"
|
||||
else if(ending == "?")
|
||||
verb = "asks"
|
||||
|
||||
return verb
|
||||
|
||||
/mob/living/carbon/human/proc/handle_speech_problems(var/message)
|
||||
|
||||
var/list/returns[3]
|
||||
var/verb = "says"
|
||||
var/handled = 0
|
||||
if(silent || (sdisabilities & MUTE))
|
||||
message = ""
|
||||
handled = 1
|
||||
if(istype(wear_mask, /obj/item/clothing/mask/horsehead))
|
||||
var/obj/item/clothing/mask/horsehead/hoers = wear_mask
|
||||
if(hoers.voicechange)
|
||||
if(mind && mind.changeling && department_radio_keys[copytext(message, 1, 3)] != "changeling")
|
||||
message = pick("NEEIIGGGHHHH!", "NEEEIIIIGHH!", "NEIIIGGHH!", "HAAWWWWW!", "HAAAWWW!")
|
||||
verb = pick("whinnies","neighs", "says")
|
||||
handled = 1
|
||||
|
||||
if(dna)
|
||||
for(var/datum/dna/gene/gene in dna_genes)
|
||||
if(!gene.block)
|
||||
continue
|
||||
if(gene.is_active(src))
|
||||
message = gene.OnSay(src,message)
|
||||
handled = 1
|
||||
|
||||
if(message != "")
|
||||
if((M_HULK in mutations) && health >= 25 && length(message))
|
||||
message = "[uppertext(message)]!!!"
|
||||
verb = pick("yells","roars","hollers")
|
||||
handled = 1
|
||||
if(slurring)
|
||||
message = slur(message)
|
||||
verb = "slurs"
|
||||
handled = 1
|
||||
if(stuttering)
|
||||
message = stutter(message)
|
||||
verb = "stammers"
|
||||
handled = 1
|
||||
|
||||
var/braindam = getBrainLoss()
|
||||
if(braindam >= 60)
|
||||
handled = 1
|
||||
if(prob(braindam/4))
|
||||
message = stutter(message)
|
||||
verb = "gibbers"
|
||||
if(prob(braindam))
|
||||
message = uppertext(message)
|
||||
verb = "yells loudly"
|
||||
|
||||
returns[1] = message
|
||||
returns[2] = verb
|
||||
returns[3] = handled
|
||||
return returns
|
||||
|
||||
@@ -290,11 +290,12 @@ proc/get_damage_icon_part(damage_state, body_part)
|
||||
//Robotic limbs are handled in get_icon() so all we worry about are missing or dead limbs.
|
||||
//No icon stored, so we need to start with a basic one.
|
||||
var/datum/organ/external/chest = get_organ("chest")
|
||||
base_icon = chest.get_icon(g,fat)
|
||||
if(chest)
|
||||
base_icon = chest.get_icon(g,fat)
|
||||
|
||||
if(chest.status & ORGAN_DEAD)
|
||||
base_icon.ColorTone(necrosis_color_mod)
|
||||
base_icon.SetIntensity(0.7)
|
||||
if(chest.status & ORGAN_DEAD)
|
||||
base_icon.ColorTone(necrosis_color_mod)
|
||||
base_icon.SetIntensity(0.7)
|
||||
|
||||
for(var/datum/organ/external/part in organs)
|
||||
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
//Lallander was here
|
||||
/mob/living/carbon/human/whisper(message as text)
|
||||
var/alt_name = ""
|
||||
|
||||
message = trim(copytext(strip_html_simple(message), 1, MAX_MESSAGE_LEN))
|
||||
|
||||
if (!message || silent || miming)
|
||||
return
|
||||
|
||||
message = trim_strip_html_properly(message)
|
||||
log_whisper("[src.name]/[src.key] : [message]")
|
||||
|
||||
if (src.client)
|
||||
@@ -16,28 +13,74 @@
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
|
||||
|
||||
if (src.stat == 2)
|
||||
return src.say_dead(message)
|
||||
|
||||
if (src.stat)
|
||||
return
|
||||
|
||||
var/alt_name = ""
|
||||
if (istype(src, /mob/living/carbon/human) && src.name != GetVoice())
|
||||
var/mob/living/carbon/human/H = src
|
||||
alt_name = " (as [H.get_id_name("Unknown")])"
|
||||
// Mute disability
|
||||
if (src.sdisabilities & MUTE)
|
||||
return
|
||||
if(name != GetVoice())
|
||||
alt_name = "(as [get_id_name("Unknown")])"
|
||||
|
||||
//parse the language code and consume it
|
||||
var/datum/language/speaking = parse_language(message)
|
||||
if (speaking)
|
||||
message = copytext(message,2+length(speaking.key))
|
||||
|
||||
whisper_say(message, speaking, alt_name)
|
||||
|
||||
|
||||
//This is used by both the whisper verb and human/say() to handle whispering
|
||||
/mob/living/carbon/human/proc/whisper_say(var/message, var/datum/language/speaking = null, var/alt_name="", var/verb="whispers")
|
||||
|
||||
if (istype(src.wear_mask, /obj/item/clothing/mask/muzzle))
|
||||
src << "<span class='danger'>You're muzzled and cannot speak!</span>"
|
||||
return
|
||||
|
||||
var/italics = 1
|
||||
var/message_range = 1
|
||||
var/eavesdropping_range = 2
|
||||
var/watching_range = 5
|
||||
var/italics = 1
|
||||
|
||||
if(istype(src.wear_mask, /obj/item/clothing/mask/gas/voice/space_ninja)&&src.wear_mask:voice=="Unknown")
|
||||
var/not_heard //the message displayed to people who could not hear the whispering
|
||||
if (speaking)
|
||||
if (speaking.whisper_verb)
|
||||
verb = speaking.whisper_verb
|
||||
not_heard = "[verb] something"
|
||||
else
|
||||
var/adverb = pick("quietly", "softly")
|
||||
verb = "[speaking.speech_verb] [adverb]"
|
||||
not_heard = "[speaking.speech_verb] something [adverb]"
|
||||
else
|
||||
not_heard = "[verb] something" //TODO get rid of the null language and just prevent speech if language is null
|
||||
|
||||
message = capitalize(trim(message))
|
||||
|
||||
if(speech_problem_flag)
|
||||
var/list/handle_r = handle_speech_problems(message)
|
||||
message = handle_r[1]
|
||||
verb = handle_r[2]
|
||||
if(verb == "yells loudly")
|
||||
verb = "slurs emphatically"
|
||||
else
|
||||
var/adverb = pick("quietly", "softly")
|
||||
verb = "[verb] [adverb]"
|
||||
|
||||
speech_problem_flag = handle_r[3]
|
||||
|
||||
if(!message || message=="")
|
||||
return
|
||||
|
||||
//looks like this only appears in whisper. Should it be elsewhere as well? Maybe handle_speech_problems?
|
||||
var/voice_sub
|
||||
for(var/obj/item/gear in list(wear_mask,wear_suit,head))
|
||||
if(!gear)
|
||||
continue
|
||||
var/obj/item/voice_changer/changer = locate() in gear
|
||||
if(changer && changer.active && changer.voice)
|
||||
voice_sub = changer.voice
|
||||
|
||||
if(voice_sub == "Unknown")
|
||||
if(copytext(message, 1, 2) != "*")
|
||||
var/list/temp_message = text2list(message, " ")
|
||||
var/list/pick_list = list()
|
||||
@@ -49,97 +92,60 @@
|
||||
temp_message[H] = ninjaspeak(temp_message[H])
|
||||
pick_list -= H
|
||||
message = list2text(temp_message, " ")
|
||||
message = replacetext(message, "o", "?")
|
||||
message = replacetext(message, "p", "?")
|
||||
message = replacetext(message, "l", "?")
|
||||
message = replacetext(message, "s", "?")
|
||||
message = replacetext(message, "u", "?")
|
||||
message = replacetext(message, "b", "?")
|
||||
|
||||
if (src.stuttering)
|
||||
message = stutter(message)
|
||||
|
||||
for (var/obj/O in view(message_range, src))
|
||||
spawn (0)
|
||||
if (O)
|
||||
O.hear_talk(src, message)
|
||||
message = replacetext(message, "o", "�")
|
||||
message = replacetext(message, "p", "�")
|
||||
message = replacetext(message, "l", "�")
|
||||
message = replacetext(message, "s", "�")
|
||||
message = replacetext(message, "u", "�")
|
||||
message = replacetext(message, "b", "�")
|
||||
|
||||
var/list/listening = hearers(message_range, src)
|
||||
listening |= src
|
||||
|
||||
//ghosts
|
||||
for (var/mob/M in dead_mob_list) //does this include players who joined as observers as well?
|
||||
if (!(M.client))
|
||||
continue
|
||||
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
|
||||
listening |= M
|
||||
|
||||
//Pass whispers on to anything inside the immediate listeners.
|
||||
for(var/mob/L in listening)
|
||||
for(var/mob/C in L.contents)
|
||||
if(istype(C,/mob/living))
|
||||
listening += C
|
||||
|
||||
var/list/eavesdropping = hearers(2, src)
|
||||
//pass on the message to objects that can hear us.
|
||||
for (var/obj/O in view(message_range, src))
|
||||
spawn (0)
|
||||
if (O)
|
||||
O.hear_talk(src, message, verb, speaking)
|
||||
|
||||
var/list/eavesdropping = hearers(eavesdropping_range, src)
|
||||
eavesdropping -= src
|
||||
eavesdropping -= listening
|
||||
|
||||
var/list/watching = hearers(5, src)
|
||||
var/list/watching = hearers(watching_range, src)
|
||||
watching -= src
|
||||
watching -= listening
|
||||
watching -= eavesdropping
|
||||
|
||||
var/list/heard_a = list() // understood us
|
||||
var/list/heard_b = list() // didn't understand us
|
||||
//now mobs
|
||||
var/speech_bubble_test = say_test(message)
|
||||
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
|
||||
spawn(30) del(speech_bubble)
|
||||
|
||||
for (var/mob/M in listening)
|
||||
if (M.say_understands(src))
|
||||
heard_a += M
|
||||
else
|
||||
heard_b += M
|
||||
for(var/mob/M in listening)
|
||||
M << speech_bubble
|
||||
M.hear_say(message, verb, speaking, alt_name, italics, src)
|
||||
|
||||
var/rendered = null
|
||||
if (eavesdropping.len)
|
||||
var/new_message = stars(message) //hopefully passing the message twice through stars() won't hurt... I guess if you already don't understand the language, when they speak it too quietly to hear normally you would be able to catch even less.
|
||||
for(var/mob/M in eavesdropping)
|
||||
M << speech_bubble
|
||||
M.hear_say(new_message, verb, speaking, alt_name, italics, src)
|
||||
|
||||
for (var/mob/M in watching)
|
||||
if (M.say_understands(src))
|
||||
rendered = "<span class='game say'><span class='name'>[src.name]</span> whispers something.</span>"
|
||||
else
|
||||
rendered = "<span class='game say'><span class='name'>[src.voice_name]</span> whispers something.</span>"
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
if (length(heard_a))
|
||||
var/message_a = message
|
||||
|
||||
if (italics)
|
||||
message_a = "<i>[message_a]</i>"
|
||||
//This appears copied from carbon/living say.dm so the istype check for mob is probably not needed. Appending for src is also not needed as the game will check that automatically.
|
||||
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] whispers, <span class='message'>\"[message_a]\"</span></span>"
|
||||
|
||||
for (var/mob/M in heard_a)
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
if (length(heard_b))
|
||||
var/message_b
|
||||
|
||||
message_b = stars(message)
|
||||
|
||||
if (italics)
|
||||
message_b = "<i>[message_b]</i>"
|
||||
|
||||
rendered = "<span class='game say'><span class='name'>[src.voice_name]</span> whispers, <span class='message'>\"[message_b]\"</span></span>"
|
||||
|
||||
for (var/mob/M in heard_b)
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
for (var/mob/M in eavesdropping)
|
||||
if (M.say_understands(src))
|
||||
var/message_c
|
||||
message_c = stars(message)
|
||||
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] whispers, <span class='message'>\"[message_c]\"</span></span>"
|
||||
M.show_message(rendered, 2)
|
||||
else
|
||||
rendered = "<span class='game say'><span class='name'>[src.voice_name]</span> whispers something.</span>"
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
if (italics)
|
||||
message = "<i>[message]</i>"
|
||||
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] whispers, <span class='message'>\"[message]\"</span></span>"
|
||||
|
||||
for (var/mob/M in dead_mob_list)
|
||||
if (!(M.client))
|
||||
continue
|
||||
if (M.stat > 1 && !(M in heard_a) && (M.client.prefs.toggles & CHAT_GHOSTEARS))
|
||||
if (watching.len)
|
||||
var/rendered = "<span class='game say'><span class='name'>[src.name]</span> [not_heard].</span>"
|
||||
for (var/mob/M in watching)
|
||||
M.show_message(rendered, 2)
|
||||
|
||||
@@ -21,3 +21,16 @@
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/mob/living/carbon/slime/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "", var/italics = 0, var/mob/speaker = null, var/sound/speech_sound, var/sound_vol)
|
||||
if (speaker in Friends)
|
||||
speech_buffer = list()
|
||||
speech_buffer.Add(speaker)
|
||||
speech_buffer.Add(lowertext(html_decode(message)))
|
||||
..()
|
||||
|
||||
/mob/living/carbon/slime/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0, var/vname ="")
|
||||
if (speaker in Friends)
|
||||
speech_buffer = list()
|
||||
speech_buffer.Add(speaker)
|
||||
speech_buffer.Add(lowertext(html_decode(message)))
|
||||
..()
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
var/icobase = 'icons/mob/human_races/r_human.dmi' // Normal icon set.
|
||||
var/deform = 'icons/mob/human_races/r_def_human.dmi' // Mutated icon set.
|
||||
var/eyes = "eyes_s" // Icon for eyes.
|
||||
var/blurb = "A completely nondescript species." // A brief lore summary for use in the chargen screen.
|
||||
|
||||
var/primitive // Lesser form, if any (ie. monkey for humans)
|
||||
var/tail // Name of tail image in species effects icon file.
|
||||
var/language // Default racial language, if any.
|
||||
var/unarmed //For empty hand harm-intent attack
|
||||
var/unarmed_type = /datum/unarmed_attack
|
||||
var/mutantrace // Safeguard due to old code.
|
||||
@@ -41,11 +41,8 @@
|
||||
var/brute_mod = null // Physical damage reduction/malus.
|
||||
var/burn_mod = null // Burn damage reduction/malus.
|
||||
|
||||
// For grays
|
||||
var/max_hurt_damage = 9 // Max melee damage dealt + 5 if hulk
|
||||
var/list/default_mutations = list()
|
||||
var/list/default_blocks = list() // Don't touch.
|
||||
var/list/default_block_names = list() // Use this instead, using the names from setupgame.dm
|
||||
var/list/default_genes = list()
|
||||
|
||||
var/flags = 0 // Various specific features.
|
||||
var/bloodflags=0
|
||||
@@ -60,12 +57,21 @@
|
||||
//Used in icon caching.
|
||||
var/race_key = 0
|
||||
var/icon/icon_template
|
||||
|
||||
|
||||
// Language/culture vars.
|
||||
var/default_language = "Galactic Common" // Default language is used when 'say' is used without modifiers.
|
||||
var/language = "Galactic Common" // Default racial language, if any.
|
||||
var/secondary_langs = list() // The names of secondary languages that are available to this species.
|
||||
var/list/speech_sounds // A list of sounds to potentially play when speaking.
|
||||
var/list/speech_chance // The likelihood of a speech sound playing.
|
||||
|
||||
/datum/species/New()
|
||||
unarmed = new unarmed_type()
|
||||
|
||||
|
||||
/datum/species/proc/get_random_name(var/gender)
|
||||
var/datum/language/species_language = all_languages[language]
|
||||
return species_language.get_random_name(gender)
|
||||
|
||||
/datum/species/proc/create_organs(var/mob/living/carbon/human/H) //Handles creation of mob organs.
|
||||
//This is a basic humanoid limb setup.
|
||||
H.organs = list()
|
||||
@@ -81,7 +87,7 @@
|
||||
H.organs_by_name["l_foot"] = new/datum/organ/external/l_foot(H.organs_by_name["l_leg"])
|
||||
H.organs_by_name["r_foot"] = new/datum/organ/external/r_foot(H.organs_by_name["r_leg"])
|
||||
|
||||
if (name!="Slime People")
|
||||
if (name != "Slime People")
|
||||
new/datum/organ/internal/heart(H)
|
||||
new/datum/organ/internal/lungs(H)
|
||||
new/datum/organ/internal/liver(H)
|
||||
@@ -247,6 +253,10 @@
|
||||
return 1
|
||||
|
||||
/datum/species/proc/handle_post_spawn(var/mob/living/carbon/C) //Handles anything not already covered by basic species assignment.
|
||||
handle_dna(C)
|
||||
return
|
||||
|
||||
/datum/species/proc/handle_dna(var/mob/living/carbon/C, var/remove) //Handles DNA mutations, as that doesn't work at init.
|
||||
return
|
||||
|
||||
// Used for species-specific names (Vox, etc)
|
||||
@@ -262,6 +272,10 @@
|
||||
return message
|
||||
|
||||
/datum/species/proc/equip(var/mob/living/carbon/human/H)
|
||||
return
|
||||
|
||||
/datum/species/proc/can_understand(var/mob/other)
|
||||
return
|
||||
|
||||
/datum/species/human
|
||||
name = "Human"
|
||||
@@ -272,17 +286,29 @@
|
||||
flags = HAS_LIPS | HAS_UNDERWEAR | CAN_BE_FAT
|
||||
bodyflags = HAS_SKIN_TONE
|
||||
unarmed_type = /datum/unarmed_attack/punch
|
||||
blurb = "Humanity originated in the Sol system, and over the last five centuries has spread \
|
||||
colonies across a wide swathe of space. They hold a wide range of forms and creeds.<br/><br/> \
|
||||
While the central Sol government maintains control of its far-flung people, powerful corporate \
|
||||
interests, rampant cyber and bio-augmentation and secretive factions make life on most human \
|
||||
worlds tumultous at best."
|
||||
|
||||
/datum/species/unathi
|
||||
name = "Unathi"
|
||||
icobase = 'icons/mob/human_races/r_lizard.dmi'
|
||||
deform = 'icons/mob/human_races/r_def_lizard.dmi'
|
||||
path = /mob/living/carbon/human/unathi
|
||||
default_language = "Galactic Common"
|
||||
language = "Sinta'unathi"
|
||||
tail = "sogtail"
|
||||
unarmed_type = /datum/unarmed_attack/claws
|
||||
primitive = /mob/living/carbon/monkey/unathi
|
||||
darksight = 3
|
||||
|
||||
blurb = "A heavily reptillian species, Unathi (or 'Sinta as they call themselves) hail from the \
|
||||
Uuosa-Eso system, which roughly translates to 'burning mother'.<br/><br/>Coming from a harsh, radioactive \
|
||||
desert planet, they mostly hold ideals of honesty, virtue, martial combat and bravery above all \
|
||||
else, frequently even their own lives. They prefer warmer temperatures than most species and \
|
||||
their native tongue is a heavy hissing laungage called Sinta'Unathi."
|
||||
|
||||
flags = HAS_LIPS | HAS_UNDERWEAR
|
||||
bodyflags = FEET_CLAWS | HAS_TAIL | HAS_SKIN_COLOR
|
||||
@@ -305,10 +331,17 @@
|
||||
icobase = 'icons/mob/human_races/r_tajaran.dmi'
|
||||
deform = 'icons/mob/human_races/r_def_tajaran.dmi'
|
||||
path = /mob/living/carbon/human/tajaran
|
||||
default_language = "Galactic Common"
|
||||
language = "Siik'tajr"
|
||||
tail = "tajtail"
|
||||
unarmed_type = /datum/unarmed_attack/claws
|
||||
darksight = 8
|
||||
|
||||
blurb = "The Tajaran race is a species of feline-like bipeds hailing from the planet of Ahdomai in the \
|
||||
S'randarr system. They have been brought up into the space age by the Humans and Skrell, and have been \
|
||||
influenced heavily by their long history of Slavemaster rule. They have a structured, clan-influenced way \
|
||||
of family and politics. They prefer colder environments, and speak a variety of languages, mostly Siik'Maas, \
|
||||
using unique inflections their mouths form."
|
||||
|
||||
cold_level_1 = 200
|
||||
cold_level_2 = 140
|
||||
@@ -331,9 +364,16 @@
|
||||
icobase = 'icons/mob/human_races/r_skrell.dmi'
|
||||
deform = 'icons/mob/human_races/r_def_skrell.dmi'
|
||||
path = /mob/living/carbon/human/skrell
|
||||
default_language = "Galactic Common"
|
||||
language = "Skrellian"
|
||||
primitive = /mob/living/carbon/monkey/skrell
|
||||
unarmed_type = /datum/unarmed_attack/punch
|
||||
|
||||
blurb = "An amphibious species, Skrell come from the star system known as Qerr'Vallis, which translates to 'Star of \
|
||||
the royals' or 'Light of the Crown'.<br/><br/>Skrell are a highly advanced and logical race who live under the rule \
|
||||
of the Qerr'Katish, a caste within their society which keeps the empire of the Skrell running smoothly. Skrell are \
|
||||
herbivores on the whole and tend to be co-operative with the other species of the galaxy, although they rarely reveal \
|
||||
the secrets of their empire to their allies."
|
||||
|
||||
flags = HAS_LIPS | HAS_UNDERWEAR
|
||||
bloodflags = BLOOD_GREEN
|
||||
@@ -348,8 +388,20 @@
|
||||
icobase = 'icons/mob/human_races/r_vox.dmi'
|
||||
deform = 'icons/mob/human_races/r_def_vox.dmi'
|
||||
path = /mob/living/carbon/human/vox
|
||||
language = "Vox-pidgin"
|
||||
|
||||
default_language = "Galactic Common"
|
||||
language = "Vox-pidgin"
|
||||
speech_sounds = list('sound/voice/shriek1.ogg')
|
||||
speech_chance = 20
|
||||
|
||||
unarmed_type = /datum/unarmed_attack/claws //I dont think it will hurt to give vox claws too.
|
||||
|
||||
blurb = "The Vox are the broken remnants of a once-proud race, now reduced to little more than \
|
||||
scavenging vermin who prey on isolated stations, ships or planets to keep their own ancient arkships \
|
||||
alive. They are four to five feet tall, reptillian, beaked, tailed and quilled; human crews often \
|
||||
refer to them as 'shitbirds' for their violent and offensive nature, as well as their horrible \
|
||||
smell.<br/><br/>Most humans will never meet a Vox raider, instead learning of this insular species through \
|
||||
dealing with their traders and merchants; those that do rarely enjoy the experience."
|
||||
|
||||
warning_low_pressure = 50
|
||||
hazard_low_pressure = 0
|
||||
@@ -393,7 +445,6 @@
|
||||
name = "Vox Armalis"
|
||||
icobase = 'icons/mob/human_races/r_armalis.dmi'
|
||||
deform = 'icons/mob/human_races/r_armalis.dmi'
|
||||
language = "Vox-pidgin"
|
||||
path = /mob/living/carbon/human/voxarmalis
|
||||
unarmed_type = /datum/unarmed_attack/claws/armalis
|
||||
|
||||
@@ -454,20 +505,19 @@
|
||||
icobase = 'icons/mob/human_races/r_kidan.dmi'
|
||||
deform = 'icons/mob/human_races/r_def_kidan.dmi'
|
||||
path = /mob/living/carbon/human/kidan
|
||||
default_language = "Galactic Common"
|
||||
language = "Chittin"
|
||||
unarmed_type = /datum/unarmed_attack/claws
|
||||
|
||||
|
||||
brute_mod = 0.8
|
||||
|
||||
flags = IS_WHITELISTED
|
||||
bloodflags = BLOOD_GREEN
|
||||
bodyflags = FEET_CLAWS
|
||||
|
||||
|
||||
|
||||
/datum/species/slime
|
||||
name = "Slime People"
|
||||
default_language = "Galactic Common"
|
||||
language = "Bubblish"
|
||||
path = /mob/living/carbon/human/slime
|
||||
primitive = /mob/living/carbon/slime
|
||||
@@ -478,37 +528,48 @@
|
||||
|
||||
/datum/species/slime/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
H.dna = new /datum/dna(null)
|
||||
H.dna.species=H.species.name
|
||||
H.dna.real_name = H.real_name
|
||||
H.dna.species = H.species.name
|
||||
H.dna.mutantrace = "slime"
|
||||
H.update_mutantrace()
|
||||
|
||||
return ..()
|
||||
..()
|
||||
|
||||
/datum/species/grey // /vg/
|
||||
/datum/species/grey
|
||||
name = "Grey"
|
||||
icobase = 'icons/mob/human_races/r_grey.dmi'
|
||||
deform = 'icons/mob/human_races/r_def_grey.dmi'
|
||||
language = "Grey"
|
||||
default_language = "Galactic Common"
|
||||
//language = "Grey" // Perhaps if they ever get a hivemind
|
||||
unarmed_type = /datum/unarmed_attack/punch
|
||||
darksight = 5 // BOOSTED from 2
|
||||
eyes = "grey_eyes_s"
|
||||
|
||||
brute_mod = 1.25 //greys are fragile
|
||||
|
||||
default_genes = list(M_REMOTE_TALK)
|
||||
|
||||
primitive = /mob/living/carbon/monkey // TODO
|
||||
|
||||
flags = IS_WHITELISTED | HAS_LIPS | HAS_UNDERWEAR | CAN_BE_FAT
|
||||
|
||||
// Both must be set or it's only a 45% chance of manifesting.
|
||||
default_mutations=list(M_REMOTE_TALK)
|
||||
default_block_names=list("REMOTETALK")
|
||||
|
||||
|
||||
/datum/species/grey/handle_dna(var/mob/living/carbon/C, var/remove)
|
||||
if(!remove)
|
||||
C.dna.SetSEState(REMOTETALKBLOCK,1,1)
|
||||
C.mutations |= M_REMOTE_TALK
|
||||
genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED)
|
||||
else
|
||||
C.dna.SetSEState(REMOTETALKBLOCK,0,1)
|
||||
C.mutations -= M_REMOTE_TALK
|
||||
genemutcheck(C,REMOTETALKBLOCK,null,MUTCHK_FORCED)
|
||||
C.update_mutations()
|
||||
..()
|
||||
|
||||
/datum/species/diona
|
||||
name = "Diona"
|
||||
icobase = 'icons/mob/human_races/r_diona.dmi'
|
||||
deform = 'icons/mob/human_races/r_def_plant.dmi'
|
||||
path = /mob/living/carbon/human/diona
|
||||
default_language = "Galactic Common"
|
||||
language = "Rootspeak"
|
||||
unarmed_type = /datum/unarmed_attack/diona
|
||||
primitive = /mob/living/carbon/monkey/diona
|
||||
@@ -523,6 +584,14 @@
|
||||
heat_level_1 = 300
|
||||
heat_level_2 = 350
|
||||
heat_level_3 = 700
|
||||
|
||||
blurb = "Commonly referred to (erroneously) as 'plant people', the Dionaea are a strange space-dwelling collective \
|
||||
species hailing from Epsilon Ursae Minoris. Each 'diona' is a cluster of numerous cat-sized organisms called nymphs; \
|
||||
there is no effective upper limit to the number that can fuse in gestalt, and reports exist of the Epsilon Ursae \
|
||||
Minoris primary being ringed with a cloud of singing space-station-sized entities.<br/><br/>The Dionaea coexist peacefully with \
|
||||
all known species, especially the Skrell. Their communal mind makes them slow to react, and they have difficulty understanding \
|
||||
even the simplest concepts of other minds. Their alien physiology allows them survive happily off a diet of nothing but light, \
|
||||
water and other radiation."
|
||||
|
||||
flags = NO_BREATHE | REQUIRE_LIGHT | IS_PLANT | RAD_ABSORB | NO_BLOOD | IS_SLOW | NO_PAIN
|
||||
|
||||
@@ -532,6 +601,12 @@
|
||||
flesh_color = "#907E4A"
|
||||
|
||||
reagent_tag = IS_DIONA
|
||||
|
||||
/datum/species/diona/can_understand(var/mob/other)
|
||||
var/mob/living/carbon/monkey/diona/D = other
|
||||
if(istype(D))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/species/diona/handle_post_spawn(var/mob/living/carbon/human/H)
|
||||
H.gender = NEUTER
|
||||
@@ -561,6 +636,7 @@
|
||||
icobase = 'icons/mob/human_races/r_machine.dmi'
|
||||
deform = 'icons/mob/human_races/r_machine.dmi'
|
||||
path = /mob/living/carbon/human/machine
|
||||
default_language = "Galactic Common"
|
||||
language = "Trinary"
|
||||
unarmed_type = /datum/unarmed_attack/punch
|
||||
|
||||
|
||||
+76
-452
@@ -1,25 +1,22 @@
|
||||
var/list/department_radio_keys = list(
|
||||
":r" = "right ear", "#r" = "right ear", ".r" = "right ear", "!r" = "fake right ear",
|
||||
":l" = "left ear", "#l" = "left ear", ".l" = "left ear", "!l" = "fake left ear",
|
||||
":r" = "right ear", "#r" = "right ear", ".r" = "right ear",
|
||||
":l" = "left ear", "#l" = "left ear", ".l" = "left ear",
|
||||
":i" = "intercom", "#i" = "intercom", ".i" = "intercom",
|
||||
":h" = "department", "#h" = "department", ".h" = "department",
|
||||
":+" = "special", "#+" = "special", ".+" = "special", //activate radio-specific special functions
|
||||
":c" = "Command", "#c" = "Command", ".c" = "Command",
|
||||
":n" = "Science", "#n" = "Science", ".n" = "Science",
|
||||
":m" = "Medical", "#m" = "Medical", ".m" = "Medical",
|
||||
":e" = "Engineering", "#e" = "Engineering", ".e" = "Engineering",
|
||||
":s" = "Security", "#s" = "Security", ".s" = "Security",
|
||||
":w" = "whisper", "#w" = "whisper", ".w" = "whisper",
|
||||
":b" = "binary", "#b" = "binary", ".b" = "binary",
|
||||
":d" = "drone", "#d" = "drone", ".d" = "drone",
|
||||
":a" = "alientalk", "#a" = "alientalk", ".a" = "alientalk",
|
||||
":t" = "Syndicate", "#t" = "Syndicate", ".t" = "Syndicate",
|
||||
":u" = "Supply", "#u" = "Supply", ".u" = "Supply",
|
||||
":z" = "Service", "#z" = "Service", ".z" = "Service",
|
||||
":g" = "changeling", "#g" = "changeling", ".g" = "changeling",
|
||||
":p" = "AI Private", "#p" = "AI Private", ".p" = "AI Private",
|
||||
|
||||
|
||||
":R" = "right ear", "#R" = "right ear", ".R" = "right ear", "!R" = "fake right ear",
|
||||
":L" = "left ear", "#L" = "left ear", ".L" = "left ear", "!L" = "fake left ear",
|
||||
":R" = "right ear", "#R" = "right ear", ".R" = "right ear",
|
||||
":L" = "left ear", "#L" = "left ear", ".L" = "left ear",
|
||||
":I" = "intercom", "#I" = "intercom", ".I" = "intercom",
|
||||
":H" = "department", "#H" = "department", ".H" = "department",
|
||||
":C" = "Command", "#C" = "Command", ".C" = "Command",
|
||||
@@ -28,40 +25,35 @@ var/list/department_radio_keys = list(
|
||||
":E" = "Engineering", "#E" = "Engineering", ".E" = "Engineering",
|
||||
":S" = "Security", "#S" = "Security", ".S" = "Security",
|
||||
":W" = "whisper", "#W" = "whisper", ".W" = "whisper",
|
||||
":D" = "drone", "#D" = "drone", ".D" = "drone",
|
||||
":B" = "binary", "#B" = "binary", ".B" = "binary",
|
||||
":A" = "alientalk", "#A" = "alientalk", ".A" = "alientalk",
|
||||
":T" = "Syndicate", "#T" = "Syndicate", ".T" = "Syndicate",
|
||||
":U" = "Supply", "#U" = "Supply", ".U" = "Supply",
|
||||
":Z" = "Service", "#Z" = "Service", ".Z" = "Service",
|
||||
":G" = "changeling", "#G" = "changeling", ".G" = "changeling"
|
||||
|
||||
/* //kinda localization -- rastaf0
|
||||
//same keys as above, but on russian keyboard layout. This file uses cp1251 as encoding.
|
||||
":ê" = "right hand", "#ê" = "right hand", ".ê" = "right hand",
|
||||
":ä" = "left hand", "#ä" = "left hand", ".ä" = "left hand",
|
||||
":ø" = "intercom", "#ø" = "intercom", ".ø" = "intercom",
|
||||
":ð" = "department", "#ð" = "department", ".ð" = "department",
|
||||
":ñ" = "Command", "#ñ" = "Command", ".ñ" = "Command",
|
||||
":ò" = "Science", "#ò" = "Science", ".ò" = "Science",
|
||||
":ü" = "Medical", "#ü" = "Medical", ".ü" = "Medical",
|
||||
":ó" = "Engineering", "#ó" = "Engineering", ".ó" = "Engineering",
|
||||
":û" = "Security", "#û" = "Security", ".û" = "Security",
|
||||
":ö" = "whisper", "#ö" = "whisper", ".ö" = "whisper",
|
||||
":è" = "binary", "#è" = "binary", ".è" = "binary",
|
||||
":ô" = "alientalk", "#ô" = "alientalk", ".ô" = "alientalk",
|
||||
":å" = "Syndicate", "#å" = "Syndicate", ".å" = "Syndicate",
|
||||
":é" = "Supply", "#é" = "Supply", ".é" = "Supply",
|
||||
":ï" = "changeling", "#ï" = "changeling", ".ï" = "changeling" */
|
||||
":P" = "AI Private", "#P" = "AI Private", ".P" = "AI Private"
|
||||
)
|
||||
|
||||
|
||||
var/list/channel_to_radio_key = new
|
||||
proc/get_radio_key_from_channel(var/channel)
|
||||
var/key = channel_to_radio_key[channel]
|
||||
if(!key)
|
||||
for(var/radio_key in department_radio_keys)
|
||||
if(department_radio_keys[radio_key] == channel)
|
||||
key = radio_key
|
||||
break
|
||||
if(!key)
|
||||
key = ""
|
||||
channel_to_radio_key[channel] = key
|
||||
|
||||
return key
|
||||
|
||||
/mob/living/proc/binarycheck()
|
||||
|
||||
if (istype(src, /mob/living/silicon/pai))
|
||||
return
|
||||
if (issilicon(src))
|
||||
return 1
|
||||
|
||||
if (!ishuman(src))
|
||||
return
|
||||
|
||||
var/mob/living/carbon/human/H = src
|
||||
if (H.l_ear || H.r_ear)
|
||||
var/obj/item/device/radio/headset/dongle
|
||||
@@ -72,446 +64,78 @@ var/list/department_radio_keys = list(
|
||||
if(!istype(dongle)) return
|
||||
if(dongle.translate_binary) return 1
|
||||
|
||||
/mob/living/proc/hivecheck()
|
||||
if (isalien(src)) return 1
|
||||
if (!ishuman(src)) return
|
||||
var/mob/living/carbon/human/H = src
|
||||
if (H.l_ear || H.r_ear)
|
||||
var/obj/item/device/radio/headset/dongle
|
||||
if(istype(H.l_ear,/obj/item/device/radio/headset))
|
||||
dongle = H.l_ear
|
||||
else
|
||||
dongle = H.r_ear
|
||||
if(!istype(dongle)) return
|
||||
if(dongle.translate_hive) return 1
|
||||
|
||||
/mob/living/say(var/message)
|
||||
|
||||
/*
|
||||
Formatting and sanitizing.
|
||||
*/
|
||||
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
|
||||
|
||||
/*
|
||||
Sanity checking and speech failure.
|
||||
*/
|
||||
|
||||
if (!message)
|
||||
return
|
||||
|
||||
if(silent)
|
||||
return
|
||||
|
||||
if (stat == 2) // Dead.
|
||||
return say_dead(message)
|
||||
else if (stat) // Unconcious.
|
||||
return
|
||||
|
||||
if (src.client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot speak in IC (muted)."
|
||||
return
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
// undo last word status.
|
||||
|
||||
if(ishuman(src))
|
||||
var/mob/living/carbon/human/H=src
|
||||
if(H.said_last_words)
|
||||
H.said_last_words=0
|
||||
|
||||
// Mute disability
|
||||
if (sdisabilities & MUTE)
|
||||
return
|
||||
|
||||
// Muzzled.
|
||||
if (istype(wear_mask, /obj/item/clothing/mask/muzzle))
|
||||
return
|
||||
|
||||
// Emotes.
|
||||
if (copytext(message, 1, 2) == "*" && !stat)
|
||||
return emote(copytext(message, 2))
|
||||
|
||||
/*
|
||||
Identity hiding.
|
||||
*/
|
||||
var/alt_name = ""
|
||||
if (istype(src, /mob/living/carbon/human) && name != GetVoice())
|
||||
var/mob/living/carbon/human/H = src
|
||||
alt_name = " (as [H.get_id_name("Unknown")])"
|
||||
|
||||
/*
|
||||
Now we get into the real meat of the say processing. Determining the message mode.
|
||||
*/
|
||||
|
||||
var/italics = 0
|
||||
var/message_range = null
|
||||
var/message_mode = null
|
||||
|
||||
var/datum/language/speaking = null //For use if a specific language is being spoken.
|
||||
|
||||
var/braindam = getBrainLoss()
|
||||
if (braindam >= 60)
|
||||
if(prob(braindam/4))
|
||||
message = stutter(message)
|
||||
if(prob(braindam))
|
||||
message = uppertext(message)
|
||||
|
||||
// General public key. Special message handling
|
||||
var/mmode
|
||||
var/cprefix = ""
|
||||
if(length(message) >= 2)
|
||||
cprefix = copytext(message, 1, 3)
|
||||
if(cprefix in department_radio_keys)
|
||||
mmode = department_radio_keys[cprefix]
|
||||
if (copytext(message, 1, 2) == ";" || (prob(braindam/2) && !mmode))
|
||||
message_mode = "headset"
|
||||
message = copytext(message, 2)
|
||||
// Begin checking for either a message mode or a language to speak.
|
||||
else if (length(message) >= 2)
|
||||
var/channel_prefix = copytext(message, 1, 3)
|
||||
|
||||
//Check if the person is speaking a language that they know.
|
||||
if(languages.len)
|
||||
for(var/datum/language/L in languages)
|
||||
if(lowertext(channel_prefix) == ":[L.key]")
|
||||
speaking = L
|
||||
break
|
||||
message_mode = department_radio_keys[channel_prefix]
|
||||
if (message_mode || speaking || copytext(message,1,2) == ":")
|
||||
message = trim(copytext(message, 3))
|
||||
if (!(istype(src,/mob/living/carbon/human) && !isAI(src) && !isrobot(src) || istype(src,/mob/living/carbon/monkey) || istype(src, /mob/living/simple_animal/parrot) || isrobot(src) && (message_mode=="department") || isAI(src) && (message_mode=="department") || (message_mode in radiochannels)))
|
||||
message_mode = null //only humans can use headsets
|
||||
|
||||
if(traumatic_shock > 61 && prob(50))
|
||||
if(message_mode)
|
||||
src << "<span class='warning'>You try to use your radio, but you are in too much pain.</span>"
|
||||
message_mode = null //people in shock will have a high chance of not being able to speak on radio; needed since people don't instantly pass out at 100 damage.
|
||||
|
||||
message = capitalize(message)
|
||||
|
||||
if (!message)
|
||||
return
|
||||
|
||||
if (stuttering)
|
||||
message = stutter(message)
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
// VIDEO KILLED THE RADIO STAR V2.0
|
||||
//
|
||||
// EXPERIMENTAL CODE BY YOUR PALS AT /vg/
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
var/list/obj/item/used_radios = new
|
||||
|
||||
// Actually speaking on the radio?
|
||||
var/is_speaking_radio = 0
|
||||
|
||||
// Devices selected
|
||||
var/list/devices=list()
|
||||
|
||||
// Select all always_talk devices
|
||||
// Carbon lifeforms
|
||||
//if(istype(src, /mob/living/carbon))
|
||||
for(var/obj/item/device/radio/R in contents)
|
||||
if(R.always_talk)
|
||||
devices += R
|
||||
|
||||
//src << "Speaking on [message_mode]: [message]"
|
||||
if(message_mode)
|
||||
switch (message_mode)
|
||||
if ("right ear")
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C=src
|
||||
if(C:r_ear) devices += C:r_ear
|
||||
message_mode="headset"
|
||||
message_range = 1
|
||||
italics = 1
|
||||
|
||||
if ("left ear")
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C=src
|
||||
if(C:l_ear) devices += C:l_ear
|
||||
message_mode="headset"
|
||||
message_range = 1
|
||||
italics = 1
|
||||
|
||||
// Select a headset and speak into it without actually sending a message
|
||||
if ("fake")
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C=src
|
||||
if(C:l_ear) used_radios += C:l_ear
|
||||
if(C:r_ear) used_radios += C:r_ear
|
||||
if(issilicon(src))
|
||||
var/mob/living/silicon/Ro=src
|
||||
if(Ro:radio) devices += Ro:radio
|
||||
message_range = 1
|
||||
italics = 1
|
||||
if ("fake left ear")
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C=src
|
||||
if(C:l_ear) used_radios += C:l_ear
|
||||
message_range = 1
|
||||
italics = 1
|
||||
if ("fake right ear")
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C=src
|
||||
if(C:r_ear) used_radios += C:r_ear
|
||||
message_range = 1
|
||||
italics = 1
|
||||
|
||||
if ("intercom")
|
||||
for (var/obj/item/device/radio/intercom/I in view(1, null))
|
||||
devices += I
|
||||
message_mode=null
|
||||
message_range = 1
|
||||
italics = 1
|
||||
|
||||
//I see no reason to restrict such way of whispering
|
||||
if ("whisper")
|
||||
whisper(message)
|
||||
return
|
||||
|
||||
if ("binary")
|
||||
if(robot_talk_understand || binarycheck())
|
||||
//message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant
|
||||
robot_talk(message)
|
||||
return
|
||||
|
||||
if ("alientalk")
|
||||
if(alien_talk_understand || hivecheck())
|
||||
//message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN)) //seems redundant
|
||||
alien_talk(message)
|
||||
return
|
||||
|
||||
if ("pAI")
|
||||
message_range = 1
|
||||
italics = 1
|
||||
|
||||
if("changeling")
|
||||
if(mind && mind.changeling)
|
||||
log_say("[key_name(src)] ([mind.changeling.changelingID]): [message]")
|
||||
for(var/mob/Changeling in mob_list)
|
||||
if(istype(Changeling, /mob/living/silicon)) continue //WHY IS THIS NEEDED?
|
||||
if((Changeling.mind && Changeling.mind.changeling) || istype(Changeling, /mob/dead/observer))
|
||||
Changeling << "<i><font color=#800080><b>[mind.changeling.changelingID]:</b> [message]</font></i>"
|
||||
else if(istype(Changeling,/mob/dead/observer) && (Changeling.client && Changeling.client.prefs.toggles & CHAT_GHOSTEARS))
|
||||
Changeling << "<i><font color=#800080><b>[mind.changeling.changelingID] (:</b> <a href='byond://?src=\ref[Changeling];follow2=\ref[Changeling];follow=\ref[src]'>(Follow)</a> [message]</font></i>"
|
||||
return
|
||||
else // headset, department channels.
|
||||
if(iscarbon(src))
|
||||
var/mob/living/carbon/C=src
|
||||
if(C:l_ear) devices += C:l_ear
|
||||
if(C:r_ear) devices += C:r_ear
|
||||
if(issilicon(src))
|
||||
if(isAI(src))//for the AI's radio. This can't be with the borg thing above due to typecasting.
|
||||
var/mob/living/silicon/ai/A = src
|
||||
if(A.aiRadio)
|
||||
A.aiRadio.talk_into(src, message, message_mode)
|
||||
used_radios += A.aiRadio
|
||||
else
|
||||
var/mob/living/silicon/Ro=src
|
||||
if(!isAI(Ro))
|
||||
if(Ro:radio)
|
||||
devices += Ro:radio
|
||||
else
|
||||
warning("[src] has no radio!")
|
||||
message_range = 1
|
||||
italics = 1
|
||||
if(devices.len>0)
|
||||
for(var/obj/item/device/radio/R in devices)
|
||||
if(istype(R))
|
||||
R.talk_into(src, message, message_mode)
|
||||
used_radios += R
|
||||
is_speaking_radio = 1
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// </NEW RADIO CODE>
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
if(environment)
|
||||
var/pressure = environment.return_pressure()
|
||||
if(pressure < SOUND_MINIMUM_PRESSURE)
|
||||
italics = 1
|
||||
message_range = 1
|
||||
|
||||
var/list/listening
|
||||
|
||||
listening = get_mobs_in_view(message_range, src)
|
||||
var/list/onscreen = viewers()
|
||||
for(var/mob/M in player_list)
|
||||
if (!M.client)
|
||||
continue //skip monkeys and leavers
|
||||
if (istype(M, /mob/new_player))
|
||||
continue
|
||||
if(M.stat == DEAD && (M.client.prefs.toggles & CHAT_GHOSTEARS) && src.client) // src.client is so that ghosts don't have to listen to mice
|
||||
listening|=M
|
||||
/mob/living/say(var/message, var/datum/language/speaking = null, var/verb="says", var/alt_name="", var/italics=0, var/message_range = world.view, var/sound/speech_sound, var/sound_vol)
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
var/list/W = hear(message_range, T)
|
||||
|
||||
for (var/obj/O in ((W | contents)-used_radios))
|
||||
W |= O
|
||||
//handle nonverbal and sign languages here
|
||||
if (speaking)
|
||||
if (speaking.flags & NONVERBAL)
|
||||
if (prob(30))
|
||||
src.custom_emote(1, "[pick(speaking.signlang_verb)].")
|
||||
|
||||
for (var/mob/M in W)
|
||||
W |= M.contents
|
||||
if (speaking.flags & SIGNLANG)
|
||||
return say_signlang(message, pick(speaking.signlang_verb), speaking)
|
||||
|
||||
for (var/atom/A in W)
|
||||
if(istype(A, /mob/living/simple_animal/parrot)) //Parrot speech mimickry
|
||||
if(A == src)
|
||||
continue //Dont imitate ourselves
|
||||
var/list/listening = list()
|
||||
var/list/listening_obj = list()
|
||||
|
||||
var/mob/living/simple_animal/parrot/P = A
|
||||
if(P.speech_buffer.len >= 10)
|
||||
P.speech_buffer.Remove(pick(P.speech_buffer))
|
||||
P.speech_buffer.Add(message)
|
||||
if(T)
|
||||
//make sure the air can transmit speech - speaker's side
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
var/pressure = (environment)? environment.return_pressure() : 0
|
||||
if(pressure < SOUND_MINIMUM_PRESSURE)
|
||||
message_range = 1
|
||||
|
||||
if (isslime(A))
|
||||
var/mob/living/carbon/slime/S = A
|
||||
if (src in S.Friends)
|
||||
S.speech_buffer = list()
|
||||
S.speech_buffer.Add(src)
|
||||
S.speech_buffer.Add(lowertext(html_decode(message)))
|
||||
if (pressure < ONE_ATMOSPHERE*0.4) //sound distortion pressure, to help clue people in that the air is thin, even if it isn't a vacuum yet
|
||||
italics = 1
|
||||
sound_vol *= 0.5 //muffle the sound a bit, so it's like we're actually talking through contact
|
||||
|
||||
if(istype(A, /obj/)) //radio in pocket could work, radio in backpack wouldn't --rastaf0
|
||||
var/obj/O = A
|
||||
spawn (0)
|
||||
if(O && !istype(O.loc, /obj/item/weapon/storage))
|
||||
O.hear_talk(src, message)
|
||||
var/list/hear = hear(message_range, T)
|
||||
var/list/hearturfs = list()
|
||||
|
||||
for(var/I in hear)
|
||||
if(istype(I, /mob/))
|
||||
var/mob/M = I
|
||||
listening += M
|
||||
hearturfs += M.locs[1]
|
||||
for(var/obj/O in M.contents)
|
||||
listening_obj |= O
|
||||
else if(istype(I, /obj/))
|
||||
var/obj/O = I
|
||||
hearturfs += O.locs[1]
|
||||
listening_obj |= O
|
||||
|
||||
var/list/heard_a = list() // understood us
|
||||
var/list/heard_b = list() // didn't understand us
|
||||
|
||||
for (var/M in listening)
|
||||
if(hascall(M,"say_understands"))
|
||||
if (M:say_understands(src,speaking))
|
||||
heard_a += M
|
||||
else
|
||||
heard_b += M
|
||||
else
|
||||
heard_a += M
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat == DEAD && M.client && (M.client.prefs.toggles & CHAT_GHOSTEARS))
|
||||
listening |= M
|
||||
continue
|
||||
if(M.loc && M.locs[1] in hearturfs)
|
||||
listening |= M
|
||||
|
||||
var/speech_bubble_test = say_test(message)
|
||||
var/image/speech_bubble = image('icons/mob/talk.dmi',src,"h[speech_bubble_test]")
|
||||
spawn(30) del(speech_bubble)
|
||||
|
||||
for(var/mob/M in hearers(5, src))
|
||||
if(M != src && is_speaking_radio)
|
||||
M:show_message("<span class='notice'>[src] talks into [used_radios.len ? used_radios[1] : "radio"]</span>")
|
||||
for(var/mob/M in listening)
|
||||
M << speech_bubble
|
||||
M.hear_say(message, verb, speaking, alt_name, italics, src, speech_sound, sound_vol)
|
||||
|
||||
/* if(message_mode == null)
|
||||
var/accent = "en-us"
|
||||
var/voice = "m7"
|
||||
var/speed = 175
|
||||
var/pitch = 0
|
||||
var/echo = 10
|
||||
if(istype(src, /mob/living/silicon/ai))
|
||||
echo = 90
|
||||
if(istype(src, /mob/living/silicon/robot))
|
||||
echo = 60
|
||||
if(src.client && src.client.prefs)
|
||||
accent = src.client.prefs.accent
|
||||
voice = src.client.prefs.voice
|
||||
speed = src.client.prefs.talkspeed
|
||||
pitch = src.client.prefs.pitch
|
||||
src:texttospeech(message, speed, pitch, accent, "+[voice]", echo)*/
|
||||
|
||||
var/rendered = null
|
||||
|
||||
if (length(heard_a))
|
||||
var/message_a = say_quote(message,speaking)
|
||||
|
||||
if (italics)
|
||||
message_a = "<i>[message_a]</i>"
|
||||
|
||||
var/message_ghost = "<b>[message_a]</b>" // bold so ghosts know the person is in view.
|
||||
rendered = "<span class='game say'><span class='name'>[GetVoice()]</span>[alt_name] <span class='message'>[message_a]</span></span>"
|
||||
var/rendered2 = null
|
||||
|
||||
for (var/mob/M in heard_a)
|
||||
//BEGIN TELEPORT CHANGES
|
||||
/* if(message_mode == null && fexists("sound/playervoices/[src.ckey].ogg"))
|
||||
if(M.client)
|
||||
if(M.client.prefs)
|
||||
if(M.client.prefs.sound & SOUND_VOICES)
|
||||
M.playsound_local(get_turf(src), "sound/playervoices/[src.ckey].ogg", 70, 0, 5, 1)*/
|
||||
if(!istype(M, /mob/new_player))
|
||||
if(M && M.stat == DEAD)
|
||||
if (M.client && M.client.prefs && (M.client.prefs.toggles & CHAT_GHOSTEARS) && M in onscreen)
|
||||
rendered2 = "<span class='game say'><span class='name'>[GetVoice()]</span></span> [alt_name] <a href='byond://?src=\ref[M];follow2=\ref[M];follow=\ref[src]'>(Follow)</a> <span class='message'>[message_ghost]</span></span>"
|
||||
else
|
||||
rendered2 = "<span class='game say'><span class='name'>[GetVoice()]</span></span> [alt_name] <a href='byond://?src=\ref[M];follow2=\ref[M];follow=\ref[src]'>(Follow)</a> <span class='message'>[message_a]</span></span>"
|
||||
M:show_message(rendered2, 2)
|
||||
continue
|
||||
//END CHANGES
|
||||
|
||||
if(hascall(M,"show_message"))
|
||||
var/deaf_message = ""
|
||||
var/deaf_type = 1
|
||||
if(M != src)
|
||||
deaf_message = "<span class='name'>[name]</span>[alt_name] talks but you cannot hear them."
|
||||
else
|
||||
deaf_message = "<span class='notice'>You cannot hear yourself!</span>"
|
||||
deaf_type = 2 // Since you should be able to hear yourself without looking
|
||||
M:show_message(rendered, 2, deaf_message, deaf_type)
|
||||
M << speech_bubble
|
||||
|
||||
if (length(heard_b))
|
||||
|
||||
var/message_b
|
||||
message_b = stars(message)
|
||||
message_b = say_quote(message_b,speaking)
|
||||
|
||||
if (italics)
|
||||
message_b = "<i>[message_b]</i>"
|
||||
|
||||
rendered = "<span class='game say'><span class='name'>[name]</span>[alt_name] <span class='message'>[message_b]</span></span>" //Voice_name isn't too useful. You'd be able to tell who was talking presumably.
|
||||
var/rendered2 = null
|
||||
|
||||
for (var/M in heard_b)
|
||||
var/mob/MM
|
||||
if(istype(M, /mob))
|
||||
MM = M
|
||||
if(!istype(MM, /mob/new_player) && MM)
|
||||
if(MM && MM.stat == DEAD)
|
||||
rendered2 = "<span class='game say'><span class='name'>[voice_name]</span></span> <a href='byond://?src=\ref[MM];follow2=\ref[MM];follow=\ref[src]'>(Follow)</a> <span class='message'>[message_b]</span></span>"
|
||||
MM:show_message(rendered2, 2)
|
||||
continue
|
||||
if(hascall(M,"show_message"))
|
||||
M:show_message(rendered, 2)
|
||||
M << speech_bubble
|
||||
|
||||
/*
|
||||
if(M.client)
|
||||
|
||||
if(!M.client.bubbles || M == src)
|
||||
var/image/I = image('icons/effects/speechbubble.dmi', B, "override")
|
||||
I.override = 1
|
||||
M << I
|
||||
*/ /*
|
||||
|
||||
flick("[presay]say", B)
|
||||
|
||||
if(istype(loc, /turf))
|
||||
B.loc = loc
|
||||
else
|
||||
B.loc = loc.loc
|
||||
|
||||
spawn()
|
||||
sleep(11)
|
||||
del(B)
|
||||
*/
|
||||
for(var/obj/O in listening_obj)
|
||||
spawn(0)
|
||||
if(O) //It's possible that it could be deleted in the meantime.
|
||||
O.hear_talk(src, message, verb, speaking)
|
||||
|
||||
log_say("[name]/[key] : [message]")
|
||||
return 1
|
||||
|
||||
/mob/living/proc/say_signlang(var/message, var/verb="gestures", var/datum/language/language)
|
||||
for (var/mob/O in viewers(src, null))
|
||||
O.hear_signlang(message, verb, language, src)
|
||||
return 1
|
||||
|
||||
/obj/effect/speech_bubble
|
||||
var/mob/parent
|
||||
|
||||
/mob/living/proc/GetVoice()
|
||||
return name
|
||||
|
||||
|
||||
|
||||
@@ -112,6 +112,20 @@ var/list/ai_list = list()
|
||||
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light, /mob/living/silicon/ai/proc/botcall, /mob/living/silicon/ai/proc/control_integrated_radio, /mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_store_location, /mob/living/silicon/ai/proc/ai_goto_location, /mob/living/silicon/ai/proc/ai_remove_location, /mob/living/silicon/ai/proc/nano_crew_monitor, /mob/living/silicon/ai/proc/ai_cancel_call)
|
||||
|
||||
//Languages
|
||||
add_language("Robot Talk", 1)
|
||||
add_language("Sol Common", 1)
|
||||
add_language("Tradeband", 1)
|
||||
add_language("Sinta'unathi", 0)
|
||||
add_language("Siik'tajr", 0)
|
||||
add_language("Skrellian", 0)
|
||||
add_language("Vox-pidgin", 0)
|
||||
add_language("Rootspeak", 0)
|
||||
add_language("Trinary", 1)
|
||||
add_language("Chittin", 0)
|
||||
add_language("Bubblish", 0)
|
||||
add_language("Gutter", 0)
|
||||
|
||||
if(!safety)//Only used by AIize() to successfully spawn an AI.
|
||||
if (!B)//If there is no player/brain inside.
|
||||
empty_playable_ai_cores += new/obj/structure/AIcore/deactivated(loc)//New empty terminal.
|
||||
@@ -127,6 +141,7 @@ var/list/ai_list = list()
|
||||
/mob/living/silicon/ai/proc/ai_statuschange, /mob/living/silicon/ai/proc/ai_hologram_change, \
|
||||
/mob/living/silicon/ai/proc/toggle_camera_light,/mob/living/silicon/ai/verb/pick_icon,/mob/living/silicon/ai/proc/control_hud, /mob/living/silicon/ai/proc/change_arrival_message, /mob/living/silicon/ai/proc/ai_cancel_call)
|
||||
laws = new /datum/ai_laws/alienmov
|
||||
add_language("xenocommon", 1)
|
||||
else
|
||||
B.brainmob.mind.transfer_to(src)
|
||||
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
|
||||
/mob/aiEye
|
||||
name = "Inactive AI Eye"
|
||||
icon = 'icons/obj/status_display.dmi' // For AI friend secret shh :o
|
||||
icon = 'icons/mob/AI.dmi'
|
||||
icon_state = "eye"
|
||||
alpha = 127
|
||||
var/list/visibleCameraChunks = list()
|
||||
var/mob/living/silicon/ai/ai = null
|
||||
density = 0
|
||||
|
||||
@@ -1,32 +1,8 @@
|
||||
/mob/living/silicon/ai/say(var/message)
|
||||
if(parent && istype(parent) && parent.stat != 2)
|
||||
parent.say(message) //If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
|
||||
return
|
||||
|
||||
..(message)
|
||||
|
||||
/mob/living/silicon/ai/say_understands(var/other)
|
||||
if (istype(other, /mob/living/carbon/human))
|
||||
return 1
|
||||
if (istype(other, /mob/living/silicon/robot))
|
||||
return 1
|
||||
if (istype(other, /mob/living/silicon/decoy))
|
||||
return 1
|
||||
if (istype(other, /mob/living/carbon/brain))
|
||||
return 1
|
||||
if (istype(other, /mob/living/silicon/pai))
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/ai/say_quote(var/text)
|
||||
var/ending = copytext(text, length(text))
|
||||
|
||||
if (ending == "?")
|
||||
return "queries, \"[text]\"";
|
||||
else if (ending == "!")
|
||||
return "declares, \"[text]\"";
|
||||
|
||||
return "states, \"[text]\"";
|
||||
return parent.say(message)
|
||||
//If there is a defined "parent" AI, it is actually an AI, and it is alive, anything the AI tries to say is said by the parent instead.
|
||||
return ..(message)
|
||||
|
||||
/mob/living/silicon/ai/proc/IsVocal()
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
|
||||
var/obj/item/radio/integrated/signal/sradio // AI's signaller
|
||||
|
||||
var/translator_on = 0 // keeps track of the translator module
|
||||
|
||||
/mob/living/silicon/pai/New(var/obj/item/device/paicard)
|
||||
canmove = 0
|
||||
@@ -81,6 +82,13 @@
|
||||
if(!card.radio)
|
||||
card.radio = new /obj/item/device/radio(src.card)
|
||||
radio = card.radio
|
||||
|
||||
//Default languages without universal translator software
|
||||
add_language("Sol Common", 1)
|
||||
add_language("Tradeband", 1)
|
||||
add_language("Gutter", 1)
|
||||
add_language("Trinary", 1)
|
||||
|
||||
//Verbs for pAI mobile form, chassis and Say flavor text
|
||||
verbs += /mob/living/silicon/pai/proc/choose_chassis
|
||||
verbs += /mob/living/silicon/pai/proc/choose_verbs
|
||||
@@ -334,7 +342,7 @@
|
||||
//I'm not sure how much of this is necessary, but I would rather avoid issues.
|
||||
if(istype(card.loc,/mob))
|
||||
var/mob/holder = card.loc
|
||||
holder.unEquip(card)
|
||||
holder.drop_from_inventory(card)
|
||||
else if(istype(card.loc,/obj/item/clothing/suit/space/space_ninja))
|
||||
var/obj/item/clothing/suit/space/space_ninja/holder = card.loc
|
||||
holder.pai = null
|
||||
@@ -503,3 +511,7 @@
|
||||
spawn(1)
|
||||
close_up()
|
||||
return 2
|
||||
|
||||
// No binary for pAIs.
|
||||
/mob/living/silicon/pai/binarycheck()
|
||||
return 0
|
||||
@@ -268,7 +268,7 @@
|
||||
src.medHUD = !src.medHUD
|
||||
if("translator")
|
||||
if(href_list["toggle"])
|
||||
src.universal_speak = !src.universal_speak
|
||||
src.translator_toggle()
|
||||
if("doorjack")
|
||||
if(href_list["jack"])
|
||||
if(src.cable && src.cable.machine)
|
||||
@@ -687,4 +687,36 @@
|
||||
else
|
||||
dat += addtext("<tr><td class='a'><i><b>From</b></i></td><td class='a'><i><b>→</b></i></td><td><i><b><a href='byond://?src=\ref[src];software=pdamessage;target=",index["target"],"'>", index["owner"],"</a>: </b></i>", index["message"], "<br></td></tr>")
|
||||
dat += "</table>"
|
||||
return dat
|
||||
return dat
|
||||
|
||||
/mob/living/silicon/pai/proc/translator_toggle()
|
||||
|
||||
// Sol Common, Tradeband, Gutter and Trinary are added with New() and are therefore the current default, always active languages
|
||||
|
||||
if(translator_on)
|
||||
translator_on = 0
|
||||
|
||||
remove_language("Sinta'unathi")
|
||||
remove_language("Siik'tajr")
|
||||
remove_language("Skrellian")
|
||||
remove_language("Vox-pidgin")
|
||||
remove_language("Rootspeak")
|
||||
remove_language("Trinary")
|
||||
remove_language("Chittin")
|
||||
remove_language("Bubblish")
|
||||
|
||||
src << "\blue Translator Module toggled OFF."
|
||||
|
||||
else
|
||||
translator_on = 1
|
||||
|
||||
add_language("Sinta'unathi")
|
||||
add_language("Siik'tajr")
|
||||
add_language("Skrellian")
|
||||
add_language("Vox-pidgin")
|
||||
add_language("Rootspeak")
|
||||
add_language("Trinary")
|
||||
add_language("Chittin")
|
||||
add_language("Bubblish")
|
||||
|
||||
src << "\blue Translator Module toggled ON."
|
||||
@@ -121,6 +121,11 @@
|
||||
/mob/living/silicon/robot/proc/is_component_functioning(module_name)
|
||||
var/datum/robot_component/C = components[module_name]
|
||||
return C && C.installed == 1 && C.toggled && C.is_powered()
|
||||
|
||||
// Returns component by it's string name
|
||||
/mob/living/silicon/robot/proc/get_component(var/component_name)
|
||||
var/datum/robot_component/C = components[component_name]
|
||||
return C
|
||||
|
||||
/obj/item/broken_device
|
||||
name = "broken component"
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
lawupdate = 0
|
||||
density = 1
|
||||
req_access = list(access_engine, access_robotics)
|
||||
|
||||
local_transmit = 1
|
||||
|
||||
// We need to keep track of a few module items so we don't need to do list operations
|
||||
// every time we need them. These get set in New() after the module is chosen.
|
||||
var/obj/item/stack/sheet/metal/cyborg/stack_metal = null
|
||||
@@ -25,11 +26,13 @@
|
||||
//Used for self-mailing.
|
||||
var/mail_destination = 0
|
||||
|
||||
//Used for pulling.
|
||||
|
||||
/mob/living/silicon/robot/drone/New()
|
||||
|
||||
..()
|
||||
|
||||
remove_language("Robot Talk")
|
||||
add_language("Drone Talk", 1)
|
||||
|
||||
if(camera && "Robots" in camera.network)
|
||||
camera.network.Add("Engineering")
|
||||
@@ -88,79 +91,6 @@
|
||||
/mob/living/silicon/robot/drone/pick_module()
|
||||
return
|
||||
|
||||
//Drones can only use binary and say emotes. NOTHING else.
|
||||
//TBD, fix up boilerplate. ~ Z
|
||||
/mob/living/silicon/robot/drone/say(var/message)
|
||||
if (!message)
|
||||
return
|
||||
|
||||
if (src.client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
src << "You cannot send IC messages (muted)."
|
||||
return
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
|
||||
if (stat == 2)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
return say_dead(message)
|
||||
|
||||
//Must be concious to speak
|
||||
if (stat)
|
||||
return
|
||||
|
||||
if(copytext(message,1,2) == "*")
|
||||
return emote(copytext(message,2))
|
||||
|
||||
if (length(message) >= 2)
|
||||
var/prefix = copytext(message, 1, 3)
|
||||
if (department_radio_keys[prefix] == "drone")
|
||||
message = copytext(message, 3)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
|
||||
if(istype(src, /mob/living/silicon/robot/drone))
|
||||
var/mob/living/silicon/robot/drone/R = src
|
||||
if(!R.is_component_functioning("comms"))
|
||||
src << "\red Your drone communications component isn't functional."
|
||||
return
|
||||
drone_talk(message)
|
||||
else
|
||||
var/list/listeners = hearers(5,src)
|
||||
listeners |= src
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
for(var/mob/living/silicon/D in listeners)
|
||||
if(D.client)
|
||||
D << "<b>[src]</b> transmits, \"[message]\""
|
||||
|
||||
for (var/mob/M in player_list)
|
||||
if (!M.client)
|
||||
continue
|
||||
if (istype(M, /mob/new_player))
|
||||
continue
|
||||
else if(M.stat == 2 && (M.client.prefs.toggles & CHAT_GHOSTEARS) && src.client)
|
||||
M << "<b>[src]</b> <a href='byond://?src=\ref[M];follow2=\ref[M];follow=\ref[src]'>(Follow)</a> transmits, \"[message]\""
|
||||
else if(M.stat == 2 && src.client && M in listeners)
|
||||
M << "<b>[src]</b> <a href='byond://?src=\ref[M];follow2=\ref[M];follow=\ref[src]'>(Follow)</a> transmits, \"[message]\""
|
||||
|
||||
/mob/living/proc/drone_talk(var/message)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
message = trim(message)
|
||||
|
||||
if (!message)
|
||||
return
|
||||
|
||||
var/message_a = say_quote(message)
|
||||
var/rendered = "<i><span class='game say'>Drone Talk, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
|
||||
|
||||
for (var/mob/living/S in living_mob_list)
|
||||
if(istype(S, /mob/living/silicon/robot/drone))
|
||||
S.show_message(rendered, 2)
|
||||
|
||||
for (var/mob/S in dead_mob_list)
|
||||
if(!istype(S,/mob/new_player) && !istype(S,/mob/living/carbon/brain))
|
||||
var/rendered2 = "<i><span class='game say'>Drone Talk, <span class='name'>[name]</span> <a href='byond://?src=\ref[S];follow2=\ref[S];follow=\ref[src]'>(Follow)</a> <span class='message'>[message_a]</span></span></i>"
|
||||
S.show_message(rendered2, 2)
|
||||
|
||||
//Drones cannot be upgraded with borg modules so we need to catch some items before they get used in ..().
|
||||
/mob/living/silicon/robot/drone/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
|
||||
|
||||
@@ -80,6 +80,8 @@
|
||||
spark_system = new /datum/effect/effect/system/spark_spread()
|
||||
spark_system.set_up(5, 0, src)
|
||||
spark_system.attach(src)
|
||||
|
||||
add_language("Robot Talk", 1)
|
||||
|
||||
robot_modules_background = new()
|
||||
robot_modules_background.icon_state = "block"
|
||||
@@ -174,6 +176,13 @@
|
||||
rbPDA.set_name_and_job(custom_name,braintype)
|
||||
if(hiddenborg)
|
||||
rbPDA.hidden = 1
|
||||
|
||||
/mob/living/silicon/robot/binarycheck()
|
||||
if(is_component_functioning("comms"))
|
||||
var/datum/robot_component/RC = get_component("comms")
|
||||
use_power(RC.energy_consumption)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//If there's an MMI in the robot, have it ejected when the mob goes away. --NEO
|
||||
//Improved /N
|
||||
@@ -197,7 +206,6 @@
|
||||
modtype = input("Please, select a module!", "Robot", null, null) in modules
|
||||
designation = modtype
|
||||
var/module_sprites[0] //Used to store the associations between sprite names and sprite index.
|
||||
var/channels = list()
|
||||
|
||||
if(module)
|
||||
return
|
||||
@@ -205,14 +213,14 @@
|
||||
switch(modtype)
|
||||
if("Standard")
|
||||
module = new /obj/item/weapon/robot_module/standard(src)
|
||||
channels = list("Service" = 1)
|
||||
module.channels = list("Service" = 1)
|
||||
module_sprites["Basic"] = "robot_old"
|
||||
module_sprites["Android"] = "droid"
|
||||
module_sprites["Default"] = "robot"
|
||||
|
||||
if("Service")
|
||||
module = new /obj/item/weapon/robot_module/butler(src)
|
||||
channels = list("Service" = 1)
|
||||
module.channels = list("Service" = 1)
|
||||
module_sprites["Waitress"] = "Service"
|
||||
module_sprites["Kent"] = "toiletbot"
|
||||
module_sprites["Bro"] = "Brobot"
|
||||
@@ -221,7 +229,7 @@
|
||||
/*
|
||||
if("Clerical")
|
||||
module = new /obj/item/weapon/robot_module/clerical(src)
|
||||
channels = list("Service" = 1)
|
||||
module.channels = list("Service" = 1)
|
||||
module_sprites["Waitress"] = "Service"
|
||||
module_sprites["Kent"] = "toiletbot"
|
||||
module_sprites["Bro"] = "Brobot"
|
||||
@@ -230,7 +238,7 @@
|
||||
*/
|
||||
if("Miner")
|
||||
module = new /obj/item/weapon/robot_module/miner(src)
|
||||
channels = list("Supply" = 1)
|
||||
module.channels = list("Supply" = 1)
|
||||
if(camera && "Robots" in camera.network)
|
||||
camera.network.Add("MINE")
|
||||
module_sprites["Basic"] = "Miner_old"
|
||||
@@ -239,7 +247,7 @@
|
||||
|
||||
if("Medical")
|
||||
module = new /obj/item/weapon/robot_module/medical(src)
|
||||
channels = list("Medical" = 1)
|
||||
module.channels = list("Medical" = 1)
|
||||
if(camera && "Robots" in camera.network)
|
||||
camera.network.Add("Medical")
|
||||
module_sprites["Basic"] = "Medbot"
|
||||
@@ -249,7 +257,7 @@
|
||||
|
||||
if("Security")
|
||||
module = new /obj/item/weapon/robot_module/security(src)
|
||||
channels = list("Security" = 1)
|
||||
module.channels = list("Security" = 1)
|
||||
module_sprites["Basic"] = "secborg"
|
||||
module_sprites["Red Knight"] = "Security"
|
||||
module_sprites["Black Knight"] = "securityrobot"
|
||||
@@ -257,7 +265,7 @@
|
||||
|
||||
if("Engineering")
|
||||
module = new /obj/item/weapon/robot_module/engineering(src)
|
||||
channels = list("Engineering" = 1)
|
||||
module.channels = list("Engineering" = 1)
|
||||
if(camera && "Robots" in camera.network)
|
||||
camera.network.Add("Engineering")
|
||||
module_sprites["Basic"] = "Engineering"
|
||||
@@ -266,14 +274,15 @@
|
||||
|
||||
if("Janitor")
|
||||
module = new /obj/item/weapon/robot_module/janitor(src)
|
||||
module.channels = list("Service" = 1)
|
||||
module_sprites["Basic"] = "JanBot2"
|
||||
module_sprites["Mopbot"] = "janitorrobot"
|
||||
module_sprites["Mop Gear Rex"] = "mopgearrex"
|
||||
|
||||
if("Combat")
|
||||
module = new /obj/item/weapon/robot_module/combat(src)
|
||||
module.channels = list("Security" = 1)
|
||||
module_sprites["Combat Android"] = "droidcombat"
|
||||
channels = list("Security" = 1)
|
||||
|
||||
if("Hunter")
|
||||
updatename(module)
|
||||
@@ -283,7 +292,9 @@
|
||||
icon_state = "xenoborg-state-a"
|
||||
modtype = "Xeno-Hu"
|
||||
feedback_inc("xeborg_hunter",1)
|
||||
|
||||
|
||||
//languages
|
||||
module.add_languages(src)
|
||||
|
||||
//Custom_sprite check and entry
|
||||
if (custom_sprite == 1)
|
||||
@@ -297,7 +308,7 @@
|
||||
status_flags &= ~CANPUSH
|
||||
|
||||
choose_icon(6,module_sprites)
|
||||
radio.config(channels)
|
||||
radio.config(module.channels)
|
||||
notify_ai(2)
|
||||
|
||||
/mob/living/silicon/robot/proc/updatename(var/prefix as text)
|
||||
@@ -1467,6 +1478,16 @@
|
||||
laws = new /datum/ai_laws/syndicate_override()
|
||||
|
||||
Namepick()
|
||||
|
||||
/mob/living/silicon/robot/syndicate/canUseTopic(atom/movable/M)
|
||||
if(stat || lockcharge || stunned || weakened)
|
||||
return
|
||||
if(z in config.admin_levels)
|
||||
return 1
|
||||
/*if(istype(M, /obj/machinery))
|
||||
var/obj/machinery/Machine = M
|
||||
return Machine.emagged*/
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/robot/proc/notify_ai(var/notifytype, var/oldname, var/newname)
|
||||
if(!connected_ai)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
var/obj/item/emag = null
|
||||
var/obj/item/borg/upgrade/jetpack = null
|
||||
var/list/stacktypes
|
||||
var/channels = list()
|
||||
|
||||
|
||||
emp_act(severity)
|
||||
@@ -55,6 +56,20 @@
|
||||
for(var/obj/O in temp_list)
|
||||
if(O)
|
||||
modules += O
|
||||
|
||||
/obj/item/weapon/robot_module/proc/add_languages(var/mob/living/silicon/robot/R)
|
||||
//full set of languages
|
||||
R.add_language("Sol Common", 1)
|
||||
R.add_language("Tradeband", 1)
|
||||
R.add_language("Sinta'unathi", 0)
|
||||
R.add_language("Siik'tajr", 0)
|
||||
R.add_language("Skrellian", 0)
|
||||
R.add_language("Vox-pidgin", 0)
|
||||
R.add_language("Rootspeak", 0)
|
||||
R.add_language("Trinary", 1)
|
||||
R.add_language("Chittin", 0)
|
||||
R.add_language("Bubblish", 0)
|
||||
R.add_language("Gutter", 0)
|
||||
|
||||
/obj/item/weapon/robot_module/standard
|
||||
name = "standard robot module"
|
||||
@@ -248,6 +263,20 @@
|
||||
if(src.emag)
|
||||
var/obj/item/weapon/reagent_containers/food/drinks/cans/beer/B = src.emag
|
||||
B.reagents.add_reagent("beer2", 2)
|
||||
|
||||
/obj/item/weapon/robot_module/butler/add_languages(var/mob/living/silicon/robot/R)
|
||||
//full set of languages
|
||||
R.add_language("Sol Common", 1)
|
||||
R.add_language("Tradeband", 1)
|
||||
R.add_language("Sinta'unathi", 1)
|
||||
R.add_language("Siik'tajr", 1)
|
||||
R.add_language("Skrellian", 1)
|
||||
R.add_language("Vox-pidgin", 1)
|
||||
R.add_language("Rootspeak", 1)
|
||||
R.add_language("Trinary", 1)
|
||||
R.add_language("Chittin", 1)
|
||||
R.add_language("Bubblish", 1)
|
||||
R.add_language("Gutter", 1)
|
||||
|
||||
/*
|
||||
/obj/item/weapon/robot_module/clerical //Whyyyyy?
|
||||
@@ -341,6 +370,10 @@
|
||||
src.emag = new /obj/item/weapon/reagent_containers/spray/alien/acid(src)
|
||||
src.emag.reagents.add_reagent("pacid", 125)
|
||||
src.emag.reagents.add_reagent("sacid", 125)
|
||||
|
||||
/obj/item/weapon/robot_module/butler/add_languages(var/mob/living/silicon/robot/R)
|
||||
..()
|
||||
R.add_language("xenocommon", 1)
|
||||
|
||||
/obj/item/weapon/robot_module/drone
|
||||
name = "drone module"
|
||||
|
||||
@@ -2,79 +2,154 @@
|
||||
var/ending = copytext(text, length(text))
|
||||
|
||||
if (ending == "?")
|
||||
return "[speak_query], \"[text]\"";
|
||||
return speak_query
|
||||
else if (ending == "!")
|
||||
return "[speak_exclamation], \"[text]\"";
|
||||
return speak_exclamation
|
||||
|
||||
return "[speak_statement], \"[text]\"";
|
||||
return speak_statement
|
||||
|
||||
#define IS_AI 1
|
||||
#define IS_ROBOT 2
|
||||
#define IS_PAI 3
|
||||
|
||||
/mob/living/silicon/say_understands(var/other,var/datum/language/speaking = null)
|
||||
//These only pertain to common. Languages are handled by mob/say_understands()
|
||||
if (!speaking)
|
||||
if (istype(other, /mob/living/carbon))
|
||||
return 1
|
||||
if (istype(other, /mob/living/silicon))
|
||||
return 1
|
||||
if (istype(other, /mob/living/carbon/brain))
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/mob/living/silicon/say(var/message)
|
||||
if (!message)
|
||||
return
|
||||
return 0
|
||||
|
||||
if (src.client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
src << "You cannot send IC messages (muted)."
|
||||
return
|
||||
return 0
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
return 0
|
||||
|
||||
message = trim_strip_html_properly(message)
|
||||
|
||||
if (stat == 2)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
return say_dead(message)
|
||||
|
||||
if(copytext(message,1,2) == "*")
|
||||
return emote(copytext(message,2))
|
||||
|
||||
var/bot_type = 0 //Let's not do a fuck ton of type checks, thanks.
|
||||
if(istype(src, /mob/living/silicon/ai))
|
||||
bot_type = IS_AI
|
||||
else if(istype(src, /mob/living/silicon/robot))
|
||||
bot_type = IS_ROBOT
|
||||
else if(istype(src, /mob/living/silicon/pai))
|
||||
bot_type = IS_PAI
|
||||
|
||||
var/mob/living/silicon/ai/AI = src //and let's not declare vars over and over and over for these guys.
|
||||
var/mob/living/silicon/robot/R = src
|
||||
var/mob/living/silicon/pai/P = src
|
||||
|
||||
//Must be concious to speak
|
||||
if (stat)
|
||||
return
|
||||
return 0
|
||||
|
||||
if (length(message) >= 2)
|
||||
var/prefix = copytext(message, 1, 3)
|
||||
if (department_radio_keys[prefix] == "binary")
|
||||
if(istype(src, /mob/living/silicon/pai))
|
||||
return ..(message)
|
||||
message = copytext(message, 3)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
var/verb = say_quote(message)
|
||||
|
||||
// TODO: move the component system up to silicon so we don't have to use this ugly hack..
|
||||
if(istype(src, /mob/living/silicon/robot))
|
||||
var/mob/living/silicon/robot/R = src
|
||||
if(!R.is_component_functioning("comms"))
|
||||
src << "\red Your binary communications component isn't functional."
|
||||
return
|
||||
robot_talk(message)
|
||||
|
||||
else if (department_radio_keys[prefix] == "alientalk")
|
||||
if(!alien_talk_understand) return
|
||||
message = copytext(message, 3)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
|
||||
alien_talk(message)
|
||||
else if (department_radio_keys[prefix] == "department")
|
||||
if(isAI(src)&&client) //For patching directly into AI holopads.
|
||||
var/mob/living/silicon/ai/U = src
|
||||
message = copytext(message, 3)
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
U.holopad_talk(message)
|
||||
else //Will not allow anyone by an active AI to use this function.
|
||||
src << "This function is not available to you."
|
||||
return
|
||||
//parse radio key and consume it
|
||||
var/message_mode = parse_message_mode(message, "general")
|
||||
if (message_mode)
|
||||
if (message_mode == "general")
|
||||
message = trim(copytext(message,2))
|
||||
else
|
||||
var/mob/living/silicon/ai/AI = src
|
||||
if (isAI(src) && AI.aiRadio.disabledAi)
|
||||
src << "\red System Error - Transceiver Disabled"
|
||||
return
|
||||
else
|
||||
return ..(message)
|
||||
else
|
||||
var/mob/living/silicon/ai/AI = src
|
||||
if (isAI(src) && AI.aiRadio.disabledAi)
|
||||
src << "\red System Error - Transceiver Disabled"
|
||||
return
|
||||
message = trim(copytext(message,3))
|
||||
|
||||
//parse language key and consume it
|
||||
var/datum/language/speaking = parse_language(message)
|
||||
if (speaking)
|
||||
verb = speaking.speech_verb
|
||||
message = trim(copytext(message,2+length(speaking.key)))
|
||||
|
||||
if(speaking.flags & HIVEMIND)
|
||||
speaking.broadcast(src,trim(message))
|
||||
return 1
|
||||
|
||||
// Currently used by drones.
|
||||
if(local_transmit)
|
||||
var/list/listeners = hearers(5,src)
|
||||
listeners |= src
|
||||
|
||||
for(var/mob/living/silicon/D in listeners)
|
||||
if(D.client && istype(D,src.type))
|
||||
D << "<b>[src]</b> transmits, \"[message]\""
|
||||
|
||||
for (var/mob/M in player_list)
|
||||
if (istype(M, /mob/new_player))
|
||||
continue
|
||||
else if(M.stat == 2 && M.client.prefs.toggles & CHAT_GHOSTEARS)
|
||||
if(M.client) M << "<b>[src]</b> transmits, \"[message]\""
|
||||
return 1
|
||||
|
||||
if(message_mode && bot_type == IS_ROBOT && !R.is_component_functioning("radio"))
|
||||
src << "\red Your radio isn't functional at this time."
|
||||
return 0
|
||||
|
||||
switch(message_mode)
|
||||
if("department")
|
||||
switch(bot_type)
|
||||
if(IS_AI)
|
||||
return AI.holopad_talk(message, verb, speaking)
|
||||
if(IS_ROBOT)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
return R.radio.talk_into(src,message,message_mode,verb,speaking)
|
||||
if(IS_PAI)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
return P.radio.talk_into(src,message,message_mode,verb,speaking)
|
||||
return 0
|
||||
|
||||
if("general")
|
||||
switch(bot_type)
|
||||
if(IS_AI)
|
||||
if (AI.aiRadio.disabledAi || AI.aiRestorePowerRoutine || AI.stat)
|
||||
src << "\red System Error - Transceiver Disabled"
|
||||
return 0
|
||||
else
|
||||
log_say("[key_name(src)] : [message]")
|
||||
return AI.aiRadio.talk_into(src,message,null,verb,speaking)
|
||||
if(IS_ROBOT)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
return R.radio.talk_into(src,message,null,verb,speaking)
|
||||
if(IS_PAI)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
return P.radio.talk_into(src,message,null,verb,speaking)
|
||||
return 0
|
||||
|
||||
else
|
||||
return ..(message)
|
||||
if(message_mode)
|
||||
switch(bot_type)
|
||||
if(IS_AI)
|
||||
if (AI.aiRadio.disabledAi || AI.aiRestorePowerRoutine || AI.stat)
|
||||
src << "\red System Error - Transceiver Disabled"
|
||||
return 0
|
||||
else
|
||||
log_say("[key_name(src)] : [message]")
|
||||
return AI.aiRadio.talk_into(src,message,message_mode,verb,speaking)
|
||||
if(IS_ROBOT)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
return R.radio.talk_into(src,message,message_mode,verb,speaking)
|
||||
if(IS_PAI)
|
||||
log_say("[key_name(src)] : [message]")
|
||||
return P.radio.talk_into(src,message,message_mode,verb,speaking)
|
||||
return 0
|
||||
|
||||
return ..(message,speaking,verb)
|
||||
|
||||
//For holopads only. Usable by AI.
|
||||
/mob/living/silicon/ai/proc/holopad_talk(var/message)
|
||||
/mob/living/silicon/ai/proc/holopad_talk(var/message, verb, datum/language/speaking)
|
||||
|
||||
log_say("[key_name(src)] : [message]")
|
||||
|
||||
@@ -84,18 +159,23 @@
|
||||
return
|
||||
|
||||
var/obj/machinery/hologram/holopad/T = src.holo
|
||||
if(istype(T) && T.hologram && T.master == src)//If there is a hologram and its master is the user.
|
||||
var/message_a = say_quote(message)
|
||||
if(T && T.hologram && T.master == src)//If there is a hologram and its master is the user.
|
||||
|
||||
//Human-like, sorta, heard by those who understand humans.
|
||||
var/rendered_a = "<span class='game say'><span class='name'>[name]</span> <span class='message'>[message_a]</span></span>"
|
||||
|
||||
var/rendered_a
|
||||
//Speach distorted, heard by those who do not understand AIs.
|
||||
message = stars(message)
|
||||
var/message_b = say_quote(message)
|
||||
var/rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> <span class='message'>[message_b]</span></span>"
|
||||
var/message_stars = stars(message)
|
||||
var/rendered_b
|
||||
|
||||
if(speaking)
|
||||
rendered_a = "<span class='game say'><span class='name'>[name]</span> [speaking.format_message(message, verb)]</span>"
|
||||
rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> [speaking.format_message(message_stars, verb)]</span>"
|
||||
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [speaking.format_message(message, verb)]</span></i>"//The AI can "hear" its own message.
|
||||
else
|
||||
rendered_a = "<span class='game say'><span class='name'>[name]</span> [verb], <span class='message'>\"[message]\"</span></span>"
|
||||
rendered_b = "<span class='game say'><span class='name'>[voice_name]</span> [verb], <span class='message'>\"[message_stars]\"</span></span>"
|
||||
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> [verb], <span class='message'><span class='body'>\"[message]\"</span></span></span></i>"//The AI can "hear" its own message.
|
||||
|
||||
src << "<i><span class='game say'>Holopad transmitted, <span class='name'>[real_name]</span> <span class='message'>[message_a]</span></span></i>"//The AI can "hear" its own message.
|
||||
for(var/mob/M in hearers(T.loc))//The location is the object, default distance.
|
||||
if(M.say_understands(src))//If they understand AI speak. Humans and the like will be able to.
|
||||
M.show_message(rendered_a, 2)
|
||||
@@ -105,79 +185,37 @@
|
||||
This is another way of saying that we won't bother dealing with them.*/
|
||||
else
|
||||
src << "No holopad connected."
|
||||
return
|
||||
return
|
||||
return 1
|
||||
|
||||
/mob/living/proc/robot_talk(var/message)
|
||||
/mob/living/silicon/ai/proc/holopad_emote(var/message) //This is called when the AI uses the 'me' verb while using a holopad.
|
||||
|
||||
log_say("[key_name(src)] : [message]")
|
||||
|
||||
var/desig = "Unknown" //ezmode for taters
|
||||
if(isrobot(src))
|
||||
var/mob/living/silicon/S = src
|
||||
if(S.designation)
|
||||
desig = trim_left(S.designation)
|
||||
else
|
||||
desig = "Default"
|
||||
else if(isAI(src))
|
||||
desig = "AI"
|
||||
log_emote("[key_name(src)] : [message]")
|
||||
|
||||
message = trim(message)
|
||||
|
||||
if (!message)
|
||||
return
|
||||
|
||||
var/message_a = say_quote(message)
|
||||
var/rendered = "<i><span class='game say'>Robotic Talk, <span class='name'>[name] ([desig])</span> <span class='message'>[message_a]</span></span></i>"
|
||||
var/obj/machinery/hologram/holopad/T = src.holo
|
||||
if(T && T.hologram && T.master == src)
|
||||
var/rendered = "<span class='game say'><span class='name'>[name]</span> <span class='message'>[message]</span></span>"
|
||||
src << "<i><span class='game say'>Holopad action relayed, <span class='name'>[real_name]</span> <span class='message'>[message]</span></span></i>"
|
||||
|
||||
for (var/mob/living/S in living_mob_list)
|
||||
if(S.robot_talk_understand && (S.robot_talk_understand == robot_talk_understand)) // This SHOULD catch everything caught by the one below, but I'm not going to change it.
|
||||
if(istype(S , /mob/living/silicon/ai))
|
||||
var/renderedAI = "<i><span class='game say'>Robotic Talk, <a href='byond://?src=\ref[S];track2=\ref[S];track=\ref[src]'><span class='name'>[name] ([desig])</span></a> <span class='message'>[message_a]</span></span></i>"
|
||||
S.show_message(renderedAI, 2)
|
||||
else if(istype(S , /mob/dead/observer) && S.stat == DEAD)
|
||||
var/rendered2 = "<i><span class='game say'>Robotic Talk, <span class='name'>[name] ([desig])</span> <a href='byond://?src=\ref[S];follow2=\ref[S];follow=\ref[src]'>(Follow)</a> <span class='message'>[message_a]</span></span></i>"
|
||||
S.show_message(rendered2, 2)
|
||||
else
|
||||
S.show_message(rendered, 2)
|
||||
|
||||
|
||||
else if (S.binarycheck())
|
||||
if(istype(S , /mob/living/silicon/ai))
|
||||
var/renderedAI = "<i><span class='game say'>Robotic Talk, <a href='byond://?src=\ref[S];track2=\ref[S];track=\ref[src]'><span class='name'>[name]</span></a> <span class='message'>[message_a]</span></span></i>"
|
||||
S.show_message(renderedAI, 2)
|
||||
else if(istype(S , /mob/dead/observer) && S.stat == DEAD)
|
||||
var/rendered2 = "<i><span class='game say'>Robotic Talk, <span class='name'>[name]</span> <a href='byond://?src=\ref[S];follow2=\ref[S];follow=\ref[src]'>(Follow)</a> <span class='message'>[message_a]</span></span></i>"
|
||||
S.show_message(rendered2, 2)
|
||||
else
|
||||
S.show_message(rendered, 2)
|
||||
|
||||
var/list/listening = hearers(1, src)
|
||||
listening -= src
|
||||
listening += src
|
||||
|
||||
var/list/heard = list()
|
||||
for (var/mob/M in listening)
|
||||
if(!istype(M, /mob/living/silicon) && !M.robot_talk_understand)
|
||||
heard += M
|
||||
|
||||
if (length(heard))
|
||||
var/message_b
|
||||
|
||||
message_b = "beep beep beep"
|
||||
message_b = say_quote(message_b)
|
||||
message_b = "<i>[message_b]</i>"
|
||||
|
||||
rendered = "<i><span class='game say'><span class='name'>[voice_name]</span> <span class='message'>[message_b]</span></span></i>"
|
||||
|
||||
for (var/mob/M in heard)
|
||||
for(var/mob/M in viewers(T.loc))
|
||||
M.show_message(rendered, 2)
|
||||
else //This shouldn't occur, but better safe then sorry.
|
||||
src << "No holopad connected."
|
||||
return
|
||||
return 1
|
||||
|
||||
message = say_quote(message)
|
||||
/mob/living/silicon/ai/emote(var/act, var/type, var/message)
|
||||
var/obj/machinery/hologram/holopad/T = src.holo
|
||||
if(T && T.hologram && T.master == src) //Is the AI using a holopad?
|
||||
src.holopad_emote(message)
|
||||
else //Emote normally, then.
|
||||
..()
|
||||
|
||||
// rendered = "<i><span class='game say'>Robotic Talk, <span class='name'>[name]</span> <span class='message'>[message_a]</span></span></i>"
|
||||
rendered = null
|
||||
|
||||
for (var/mob/M in dead_mob_list)
|
||||
if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) //No meta-evesdropping
|
||||
rendered = "<i><span class='game say'>Robotic Talk, <span class='name'>[name]</span> <a href='byond://?src=\ref[M];follow2=\ref[M];follow=\ref[src]'>(Follow)</a> <span class='message'>[message_a]</span></span></i>"
|
||||
M.show_message(rendered, 2)
|
||||
#undef IS_AI
|
||||
#undef IS_ROBOT
|
||||
#undef IS_PAI
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
var/list/alarms_to_clear = list()
|
||||
immune_to_ssd = 1
|
||||
var/list/hud_list[10]
|
||||
var/list/speech_synthesizer_langs = list() //which languages can be vocalized by the speech synthesizer
|
||||
var/list/alarm_types_show = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
|
||||
var/list/alarm_types_clear = list("Motion" = 0, "Fire" = 0, "Atmosphere" = 0, "Power" = 0, "Camera" = 0)
|
||||
var/designation = ""
|
||||
@@ -20,6 +21,7 @@
|
||||
var/sensor_mode = 0 //Determines the current HUD.
|
||||
#define SEC_HUD 1 //Security HUD mode
|
||||
#define MED_HUD 2 //Medical HUD mode
|
||||
var/local_transmit //If set, can only speak to others of the same type within a short range.
|
||||
|
||||
/mob/living/silicon/proc/cancelAlarm()
|
||||
return
|
||||
@@ -205,6 +207,37 @@
|
||||
show_emergency_shuttle_eta()
|
||||
show_system_integrity()
|
||||
show_malf_ai()
|
||||
|
||||
//Silicon mob language procs
|
||||
|
||||
/mob/living/silicon/can_speak(datum/language/speaking)
|
||||
return universal_speak || (speaking in src.speech_synthesizer_langs) //need speech synthesizer support to vocalize a language
|
||||
|
||||
/mob/living/silicon/add_language(var/language, var/can_speak=1)
|
||||
if (..(language) && can_speak)
|
||||
speech_synthesizer_langs.Add(all_languages[language])
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/remove_language(var/rem_language)
|
||||
..(rem_language)
|
||||
|
||||
for (var/datum/language/L in speech_synthesizer_langs)
|
||||
if (L.name == rem_language)
|
||||
speech_synthesizer_langs -= L
|
||||
|
||||
/mob/living/silicon/check_languages()
|
||||
set name = "Check Known Languages"
|
||||
set category = "IC"
|
||||
set src = usr
|
||||
|
||||
var/dat = "<b><font size = 5>Known Languages</font></b><br/><br/>"
|
||||
|
||||
for(var/datum/language/L in languages)
|
||||
if(!(L.flags & NONGLOBAL))
|
||||
dat += "<b>[L.name] (:[L.key])</b><br/>Speech Synthesizer: <i>[(L in speech_synthesizer_langs)? "YES":"NOT SUPPORTED"]</i><br/>[L.desc]<br/><br/>"
|
||||
|
||||
src << browse(dat, "window=checklanguage")
|
||||
return
|
||||
|
||||
// this function displays the stations manifest in a separate window
|
||||
/mob/living/silicon/proc/show_station_manifest()
|
||||
@@ -257,6 +290,9 @@
|
||||
set category = "IC"
|
||||
|
||||
flavor_text = copytext(sanitize(input(usr, "Please enter your new flavour text.", "Flavour text", null) as text), 1)
|
||||
|
||||
/mob/living/silicon/binarycheck()
|
||||
return 1
|
||||
|
||||
/mob/living/silicon/proc/toggle_sensor_mode()
|
||||
var/sensor_type = input("Please select sensor type.", "Sensor Integration", null) in list("Security", "Medical","Disable")
|
||||
|
||||
@@ -100,51 +100,12 @@
|
||||
|
||||
/mob/living/simple_animal/borer/New(var/by_gamemode=0)
|
||||
..()
|
||||
add_language("Cortical Link")
|
||||
truename = "[pick("Primary","Secondary","Tertiary","Quaternary")] [rand(1000,9999)]"
|
||||
|
||||
if(!by_gamemode)
|
||||
request_player()
|
||||
|
||||
|
||||
/mob/living/simple_animal/borer/say(var/message)
|
||||
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
message = capitalize(message)
|
||||
|
||||
if(!message)
|
||||
return
|
||||
|
||||
if (stat == 2)
|
||||
return say_dead(message)
|
||||
|
||||
if (stat)
|
||||
return
|
||||
|
||||
if (src.client)
|
||||
if(client.prefs.muted & MUTE_IC)
|
||||
src << "\red You cannot speak in IC (muted)."
|
||||
return
|
||||
if (src.client.handle_spam_prevention(message,MUTE_IC))
|
||||
return
|
||||
|
||||
if (copytext(message, 1, 2) == "*")
|
||||
return emote(copytext(message, 2))
|
||||
|
||||
if (copytext(message, 1, 2) == ";") //Brain borer hivemind.
|
||||
return borer_speak(message)
|
||||
|
||||
if(!host)
|
||||
src << "You have no host to speak to."
|
||||
return //No host, no audible speech.
|
||||
|
||||
src << "You drop words into [host]'s mind: \"[message]\""
|
||||
host << "Your own thoughts speak: \"[message]\""
|
||||
|
||||
for(var/mob/M in mob_list)
|
||||
if(M.mind && (istype(M, /mob/dead/observer)))
|
||||
M << "<i>Thought-speech, <b>[truename]</b> -> <b>[host]:</b> [copytext(message, 2)]</i>"
|
||||
|
||||
|
||||
/mob/living/simple_animal/borer/Stat()
|
||||
..()
|
||||
statpanel("Status")
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
response_disarm = "gently moves aside the"
|
||||
response_harm = "swats the"
|
||||
stop_automated_movement = 1
|
||||
universal_speak = 1
|
||||
|
||||
var/parrot_state = PARROT_WANDER //Hunt for a perch when created
|
||||
var/parrot_sleep_max = 25 //The time the parrot sits while perched before looking around. Mosly a way to avoid the parrot's AI in life() being run every single tick.
|
||||
@@ -61,7 +62,7 @@
|
||||
var/list/available_channels = list()
|
||||
|
||||
//Headset for Poly to yell at engineers :)
|
||||
var/obj/item/device/radio/headset/l_ear = null
|
||||
var/obj/item/device/radio/headset/ears = null
|
||||
|
||||
//The thing the parrot is currently interested in. This gets used for items the parrot wants to pick up, mobs it wants to steal from,
|
||||
//mobs it wants to attack or mobs that have attacked it
|
||||
@@ -84,13 +85,13 @@
|
||||
|
||||
/mob/living/simple_animal/parrot/New()
|
||||
..()
|
||||
if(!l_ear)
|
||||
if(!ears)
|
||||
var/headset = pick(/obj/item/device/radio/headset/headset_sec, \
|
||||
/obj/item/device/radio/headset/headset_eng, \
|
||||
/obj/item/device/radio/headset/headset_med, \
|
||||
/obj/item/device/radio/headset/headset_sci, \
|
||||
/obj/item/device/radio/headset/headset_cargo)
|
||||
l_ear = new headset(src)
|
||||
ears = new headset(src)
|
||||
|
||||
parrot_sleep_dur = parrot_sleep_max //In case someone decides to change the max without changing the duration var
|
||||
|
||||
@@ -100,7 +101,7 @@
|
||||
/mob/living/simple_animal/parrot/proc/perch_player)
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/Die()
|
||||
/mob/living/simple_animal/parrot/death()
|
||||
if(held_item)
|
||||
held_item.loc = src.loc
|
||||
held_item = null
|
||||
@@ -119,10 +120,10 @@
|
||||
if(user.stat) return
|
||||
|
||||
var/dat = "<div align='center'><b>Inventory of [name]</b></div><p>"
|
||||
if(l_ear)
|
||||
dat += "<br><b>Headset:</b> [l_ear] (<a href='?src=\ref[src];remove_inv=l_ear'>Remove</a>)"
|
||||
if(ears)
|
||||
dat += "<br><b>Headset:</b> [ears] (<a href='?src=\ref[src];remove_inv=ears'>Remove</a>)"
|
||||
else
|
||||
dat += "<br><b>Headset:</b> <a href='?src=\ref[src];add_inv=l_ear'>Nothing</a>"
|
||||
dat += "<br><b>Headset:</b> <a href='?src=\ref[src];add_inv=ears'>Nothing</a>"
|
||||
|
||||
user << browse(dat, text("window=mob[];size=325x500", name))
|
||||
onclose(user, "mob[real_name]")
|
||||
@@ -134,21 +135,21 @@
|
||||
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
|
||||
return
|
||||
|
||||
//Is the usr's mob type able to do this? (lolaliens)
|
||||
if(ishuman(usr) || ismonkey(usr) || isrobot(usr) || isalienadult(usr))
|
||||
//Is the usr's mob type able to do this?
|
||||
if(ishuman(usr) || ismonkey(usr) || isrobot(usr))
|
||||
|
||||
//Removing from inventory
|
||||
if(href_list["remove_inv"])
|
||||
var/remove_from = href_list["remove_inv"]
|
||||
switch(remove_from)
|
||||
if("l_ear")
|
||||
if(l_ear)
|
||||
if("ears")
|
||||
if(ears)
|
||||
if(available_channels.len)
|
||||
src.say("[pick(available_channels)] BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
|
||||
else
|
||||
src.say("BAWWWWWK LEAVE THE HEADSET BAWKKKKK!")
|
||||
l_ear.loc = src.loc
|
||||
l_ear = null
|
||||
ears.loc = src.loc
|
||||
ears = null
|
||||
for(var/possible_phrase in speak)
|
||||
if(copytext(possible_phrase,1,3) in department_radio_keys)
|
||||
possible_phrase = copytext(possible_phrase,3,length(possible_phrase))
|
||||
@@ -163,8 +164,8 @@
|
||||
usr << "\red You have nothing in your hand to put on its [add_to]."
|
||||
return
|
||||
switch(add_to)
|
||||
if("l_ear")
|
||||
if(l_ear)
|
||||
if("ears")
|
||||
if(ears)
|
||||
usr << "\red It's already wearing something."
|
||||
return
|
||||
else
|
||||
@@ -180,7 +181,7 @@
|
||||
|
||||
usr.drop_item()
|
||||
headset_to_add.loc = src
|
||||
src.l_ear = headset_to_add
|
||||
src.ears = headset_to_add
|
||||
usr << "You fit the headset onto [src]."
|
||||
|
||||
clearlist(available_channels)
|
||||
@@ -214,7 +215,7 @@
|
||||
/mob/living/simple_animal/parrot/attack_hand(mob/living/carbon/M as mob)
|
||||
..()
|
||||
if(client) return
|
||||
if(!stat && M.a_intent == "harm")
|
||||
if(!stat && M.a_intent == "hurt")
|
||||
|
||||
icon_state = "parrot_fly" //It is going to be flying regardless of whether it flees or attacks
|
||||
|
||||
@@ -231,25 +232,6 @@
|
||||
drop_held_item(0)
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/parrot/attack_paw(mob/living/carbon/monkey/M as mob)
|
||||
attack_hand(M)
|
||||
|
||||
/mob/living/simple_animal/parrot/attack_alien(mob/living/carbon/monkey/M as mob)
|
||||
attack_hand(M)
|
||||
|
||||
//Simple animals
|
||||
/mob/living/simple_animal/parrot/attack_animal(mob/living/simple_animal/M as mob)
|
||||
if(client) return
|
||||
|
||||
|
||||
if(parrot_state == PARROT_PERCH)
|
||||
parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched
|
||||
|
||||
if(M.melee_damage_upper > 0)
|
||||
parrot_interest = M
|
||||
parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless
|
||||
icon_state = "parrot_fly"
|
||||
|
||||
//Mobs with objects
|
||||
/mob/living/simple_animal/parrot/attackby(var/obj/item/O as obj, var/mob/user as mob)
|
||||
..()
|
||||
@@ -335,7 +317,7 @@
|
||||
if(speak.len)
|
||||
var/list/newspeak = list()
|
||||
|
||||
if(available_channels.len && src.l_ear)
|
||||
if(available_channels.len && src.ears)
|
||||
for(var/possible_phrase in speak)
|
||||
|
||||
//50/50 chance to not use the radio at all
|
||||
@@ -496,11 +478,11 @@
|
||||
var/datum/organ/external/affecting = H.get_organ(ran_zone(pick(parrot_dam_zone)))
|
||||
|
||||
H.apply_damage(damage, BRUTE, affecting, H.run_armor_check(affecting, "melee"), sharp=1)
|
||||
emote(pick("pecks [H]'s [affecting]", "cuts [H]'s [affecting] with its talons"))
|
||||
emote(pick("pecks [H]'s [affecting].", "cuts [H]'s [affecting] with its talons."))
|
||||
|
||||
else
|
||||
L.adjustBruteLoss(damage)
|
||||
emote(pick("pecks at [L]", "claws [L]"))
|
||||
emote(pick("pecks at [L].", "claws [L]."))
|
||||
return
|
||||
|
||||
//Otherwise, fly towards the mob!
|
||||
@@ -700,6 +682,71 @@
|
||||
speak = list("Poly wanna cracker!", ":e Check the singlo, you chucklefucks!",":e Wire the solars, you lazy bums!",":e WHO TOOK THE DAMN HARDSUITS?",":e OH GOD ITS FREE CALL THE SHUTTLE")
|
||||
|
||||
/mob/living/simple_animal/parrot/Poly/New()
|
||||
l_ear = new /obj/item/device/radio/headset/headset_eng(src)
|
||||
ears = new /obj/item/device/radio/headset/headset_eng(src)
|
||||
available_channels = list(":e")
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/parrot/say(var/message)
|
||||
|
||||
if(stat)
|
||||
return
|
||||
|
||||
var/verb = "says"
|
||||
if(speak_emote.len)
|
||||
verb = pick(speak_emote)
|
||||
|
||||
var/message_mode = null
|
||||
if(copytext(message,1,2) == ";")
|
||||
message_mode = "headset"
|
||||
message = copytext(message,2)
|
||||
|
||||
if(copytext(message,1,2) == ":")
|
||||
var/channel_prefix = copytext(message, 1 ,3)
|
||||
message_mode = department_radio_keys[channel_prefix]
|
||||
var/positioncut = 3
|
||||
message = trim(copytext(message,positioncut))
|
||||
|
||||
message = capitalize(trim_left(message))
|
||||
if(message_mode)
|
||||
if(message_mode in radiochannels)
|
||||
if(ears && istype(ears,/obj/item/device/radio))
|
||||
ears.talk_into(src, message, message_mode, verb, null)
|
||||
|
||||
..(message)
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/hear_say(var/message, var/verb = "says", var/datum/language/language = null, var/alt_name = "",var/italics = 0, var/mob/speaker = null)
|
||||
if(prob(50))
|
||||
parrot_hear(message)
|
||||
..(message,verb,language,alt_name,italics,speaker)
|
||||
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/hear_radio(var/message, var/verb="says", var/datum/language/language=null, var/part_a, var/part_b, var/mob/speaker = null, var/hard_to_hear = 0)
|
||||
if(prob(50))
|
||||
parrot_hear("[pick(available_channels)] [message]")
|
||||
..(message,verb,language,part_a,part_b,speaker,hard_to_hear)
|
||||
|
||||
|
||||
/mob/living/simple_animal/parrot/proc/parrot_hear(var/message="")
|
||||
if(!message || stat)
|
||||
return
|
||||
speech_buffer.Add(message)
|
||||
|
||||
/mob/living/simple_animal/parrot/attack_paw(var/mob/user, var/damage, var/attack_message)
|
||||
|
||||
var/success = ..()
|
||||
|
||||
if(client)
|
||||
return success
|
||||
|
||||
if(parrot_state == PARROT_PERCH)
|
||||
parrot_sleep_dur = parrot_sleep_max //Reset it's sleep timer if it was perched
|
||||
|
||||
if(!success)
|
||||
return 0
|
||||
|
||||
parrot_interest = user
|
||||
parrot_state = PARROT_SWOOP | PARROT_ATTACK //Attack other animals regardless
|
||||
icon_state = "parrot_fly"
|
||||
return success
|
||||
|
||||
@@ -269,6 +269,7 @@
|
||||
for(var/mob/O in viewers(src, null))
|
||||
if ((O.client && !( O.blinded )))
|
||||
O.show_message("\blue [M] [response_help] [src].")
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
if("grab")
|
||||
if (M == src || anchored)
|
||||
@@ -288,12 +289,14 @@
|
||||
for(var/mob/O in viewers(src, null))
|
||||
if ((O.client && !( O.blinded )))
|
||||
O.show_message(text("\red [] has grabbed [] passively!", M, src), 1)
|
||||
playsound(loc, 'sound/weapons/thudswoosh.ogg', 50, 1, -1)
|
||||
|
||||
if("harm", "disarm")
|
||||
adjustBruteLoss(harm_intent_damage)
|
||||
for(var/mob/O in viewers(src, null))
|
||||
if ((O.client && !( O.blinded )))
|
||||
O.show_message("\red [M] [response_harm] [src]!")
|
||||
playsound(loc, "punch", 25, 1, -1)
|
||||
|
||||
return
|
||||
|
||||
@@ -537,3 +540,22 @@
|
||||
if (S.occupant || S.occupant2)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/mob/living/simple_animal/say(var/message)
|
||||
if(stat)
|
||||
return
|
||||
|
||||
if(copytext(message,1,2) == "*")
|
||||
return emote(copytext(message,2))
|
||||
|
||||
if(stat)
|
||||
return
|
||||
|
||||
var/verb = "says"
|
||||
|
||||
if(speak_emote.len)
|
||||
verb = pick(speak_emote)
|
||||
|
||||
message = capitalize(trim_left(message))
|
||||
|
||||
..(message, null, verb)
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
return 0
|
||||
|
||||
/mob/proc/Life()
|
||||
handle_typing_indicator()
|
||||
// if(organStructure)
|
||||
// organStructure.ProcessOrgans()
|
||||
return
|
||||
|
||||
@@ -446,3 +446,49 @@ var/list/intents = list("help","disarm","grab","harm")
|
||||
/proc/get_both_hands(mob/living/carbon/M)
|
||||
var/list/hands = list(M.l_hand, M.r_hand)
|
||||
return hands
|
||||
|
||||
|
||||
//Direct dead say used both by emote and say
|
||||
//It is somewhat messy. I don't know what to do.
|
||||
//I know you can't see the change, but I rewrote the name code. It is significantly less messy now
|
||||
/proc/say_dead_direct(var/message, var/mob/subject = null)
|
||||
var/name
|
||||
var/keyname
|
||||
if(subject && subject.client)
|
||||
var/client/C = subject.client
|
||||
keyname = (C.holder && C.holder.fakekey) ? C.holder.fakekey : C.key
|
||||
if(C.mob) //Most of the time this is the dead/observer mob; we can totally use him if there is no better name
|
||||
var/mindname
|
||||
var/realname = C.mob.real_name
|
||||
if(C.mob.mind)
|
||||
mindname = C.mob.mind.name
|
||||
if(C.mob.mind.original && C.mob.mind.original.real_name)
|
||||
realname = C.mob.mind.original.real_name
|
||||
if(mindname && mindname != realname)
|
||||
name = "[realname] died as [mindname]"
|
||||
else
|
||||
name = realname
|
||||
|
||||
for(var/mob/M in player_list)
|
||||
if(M.client && ((!istype(M, /mob/new_player) && M.stat == DEAD) || (M.client.holder && M.client.holder.rights == R_MOD)) && (M.client.prefs.toggles & CHAT_DEAD))
|
||||
var/follow
|
||||
var/lname
|
||||
if(subject)
|
||||
if(subject != M)
|
||||
follow = "(<a href='byond://?src=\ref[M];track=\ref[subject]'>follow</a>) "
|
||||
if(M.stat != DEAD && M.client.holder)
|
||||
follow = "(<a href='?src=\ref[M.client.holder];adminplayerobservejump=\ref[subject]'>JMP</a>) "
|
||||
var/mob/dead/observer/DM
|
||||
if(istype(subject, /mob/dead/observer))
|
||||
DM = subject
|
||||
if(M.client.holder) // What admins see
|
||||
lname = "[keyname][(DM && DM.anonsay) ? "*" : (DM ? "" : "^")] ([name])"
|
||||
else
|
||||
if(DM && DM.anonsay) // If the person is actually observer they have the option to be anonymous
|
||||
lname = "Ghost of [name]"
|
||||
else if(DM) // Non-anons
|
||||
lname = "[keyname] ([name])"
|
||||
else // Everyone else (dead people who didn't ghost yet, etc.)
|
||||
lname = name
|
||||
lname = "<span class='name'>[lname]</span> "
|
||||
M << "<span class='deadsay'>[lname][follow][message]</span>"
|
||||
|
||||
@@ -444,46 +444,22 @@
|
||||
proc/create_character()
|
||||
spawning = 1
|
||||
close_spawn_windows()
|
||||
|
||||
var/mob/living/carbon/human/new_character
|
||||
|
||||
var/datum/species/chosen_species
|
||||
if(client.prefs.species)
|
||||
chosen_species = all_species[client.prefs.species]
|
||||
if(chosen_species)
|
||||
// Have to recheck admin due to no usr at roundstart. Latejoins are fine though.
|
||||
if(is_species_whitelisted(chosen_species) || has_admin_rights())
|
||||
switch(chosen_species.name)
|
||||
if("Slime People")
|
||||
new_character = new /mob/living/carbon/human/slime(loc)
|
||||
if("Tajaran")
|
||||
new_character = new /mob/living/carbon/human/tajaran(loc)
|
||||
if("Unathi")
|
||||
new_character = new /mob/living/carbon/human/unathi(loc)
|
||||
if("Skrell")
|
||||
new_character = new /mob/living/carbon/human/skrell(loc)
|
||||
if("Diona")
|
||||
new_character = new /mob/living/carbon/human/diona(loc)
|
||||
if("Vox")
|
||||
new_character = new /mob/living/carbon/human/vox(loc)
|
||||
if("Vox Armalis")
|
||||
new_character = new /mob/living/carbon/human/voxarmalis(loc)
|
||||
if("Kidan")
|
||||
new_character = new /mob/living/carbon/human/kidan(loc)
|
||||
if("Grey")
|
||||
new_character = new /mob/living/carbon/human/grey(loc)
|
||||
if("Machine")
|
||||
new_character = new /mob/living/carbon/human/machine(loc)
|
||||
if("Plasmaman")
|
||||
new_character = new /mob/living/carbon/human/plasma(loc)
|
||||
if("Human")
|
||||
new_character = new /mob/living/carbon/human/human(loc)
|
||||
// new_character.set_species(client.prefs.species)
|
||||
if(chosen_species.language)
|
||||
new_character.add_language(chosen_species.language)
|
||||
else
|
||||
new_character = new /mob/living/carbon/human(loc)
|
||||
new_character = new(loc, client.prefs.species)
|
||||
|
||||
if(!new_character)
|
||||
new_character = new(loc)
|
||||
|
||||
new_character.lastarea = get_area(loc)
|
||||
|
||||
|
||||
var/datum/language/chosen_language
|
||||
if(client.prefs.language)
|
||||
chosen_language = all_languages[client.prefs.language]
|
||||
@@ -529,6 +505,8 @@
|
||||
if(client.prefs.disabilities & DISABILITY_FLAG_DEAF)
|
||||
new_character.dna.SetSEState(DEAFBLOCK,1,1)
|
||||
new_character.sdisabilities |= DEAF
|
||||
|
||||
chosen_species.handle_dna(new_character)
|
||||
|
||||
domutcheck(new_character)
|
||||
new_character.dna.UpdateSE()
|
||||
|
||||
+80
-84
@@ -9,114 +9,97 @@
|
||||
/mob/verb/say_verb(message as text)
|
||||
set name = "Say"
|
||||
set category = "IC"
|
||||
|
||||
//Let's try to make users fix their errors - we try to detect single, out-of-place letters and 'unintended' words
|
||||
/*
|
||||
var/first_letter = copytext(message,1,2)
|
||||
if((copytext(message,2,3) == " " && first_letter != "I" && first_letter != "A" && first_letter != ";") || cmptext(copytext(message,1,5), "say ") || cmptext(copytext(message,1,4), "me ") || cmptext(copytext(message,1,6), "looc ") || cmptext(copytext(message,1,5), "ooc ") || cmptext(copytext(message,2,6), "say "))
|
||||
var/response = alert(usr, "Do you really want to say this using the *say* verb?\n\n[message]\n", "Confirm your message", "Yes", "Edit message", "No")
|
||||
if(response == "Edit message")
|
||||
message = input(usr, "Please edit your message carefully:", "Edit message", message)
|
||||
if(!message)
|
||||
return
|
||||
else if(response == "No")
|
||||
return
|
||||
*/
|
||||
|
||||
set_typing_indicator(0)
|
||||
usr.say(message)
|
||||
|
||||
/mob/verb/me_verb(message as text)
|
||||
set name = "Me"
|
||||
set category = "IC"
|
||||
|
||||
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
|
||||
message = strip_html_properly(message)
|
||||
|
||||
set_typing_indicator(0)
|
||||
if(use_me)
|
||||
usr.emote("me",usr.emote_type,message)
|
||||
else
|
||||
usr.emote(message)
|
||||
|
||||
/mob/proc/say_dead(var/message)
|
||||
var/name = src.real_name
|
||||
var/alt_name = ""
|
||||
|
||||
|
||||
if(!src.client.holder)
|
||||
if(!dsay_allowed)
|
||||
src << "\red Deadchat is globally muted"
|
||||
src << "<span class='danger'>Deadchat is globally muted.</span>"
|
||||
return
|
||||
|
||||
if(client && !(client.prefs.toggles & CHAT_DEAD))
|
||||
usr << "\red You have deadchat muted."
|
||||
usr << "<span class='danger'>You have deadchat muted.</span>"
|
||||
return
|
||||
|
||||
if(mind && mind.name)
|
||||
name = "[mind.name]"
|
||||
else
|
||||
name = real_name
|
||||
if(name != real_name)
|
||||
alt_name = " (died as [real_name])"
|
||||
|
||||
message = src.say_quote(message)
|
||||
//var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[name]</span>[alt_name] <span class='message'>[message]</span></span>"
|
||||
var/rendered2 = null//edited
|
||||
for(var/mob/M in player_list)
|
||||
rendered2 = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[name]</span>[alt_name] <a href='byond://?src=\ref[M];follow2=\ref[M];follow=\ref[src]'>(Follow)</a> <span class='message'>[message]</span></span>"//edited
|
||||
if(istype(M, /mob/new_player))
|
||||
continue
|
||||
if(M.client && M.client.holder && (M.client.holder.rights & R_ADMIN|R_MOD) && (M.client.prefs.toggles & CHAT_DEAD)) // Show the message to admins/mods with deadchat toggled on
|
||||
M << rendered2 //Admins can hear deadchat, if they choose to, no matter if they're blind/deaf or not.
|
||||
|
||||
else if(M.client && M.stat == DEAD && (M.client.prefs.toggles & CHAT_DEAD)) // Show the message to regular ghosts with deadchat toggled on.
|
||||
M.show_message(rendered2, 2) //Takes into account blindness and such.
|
||||
return
|
||||
say_dead_direct("[pick("complains","moans","whines","laments","blubbers")], <span class='message'>\"[message]\"</span>", src)
|
||||
|
||||
/mob/proc/say_understands(var/mob/other,var/datum/language/speaking = null)
|
||||
|
||||
if(!other)
|
||||
return 1
|
||||
//Universal speak makes everything understandable, for obvious reasons.
|
||||
if(other.universal_speak || src.universal_speak || src.universal_understand)
|
||||
return 1
|
||||
if (src.stat == 2)
|
||||
if (src.stat == 2) //Dead
|
||||
return 1
|
||||
|
||||
if(!speaking) //Handle languages later
|
||||
if(other.universal_speak || src.universal_speak)
|
||||
//Universal speak makes everything understandable, for obvious reasons.
|
||||
else if(src.universal_speak || src.universal_understand)
|
||||
return 1
|
||||
|
||||
//Languages are handled after.
|
||||
if (!speaking)
|
||||
if(!other)
|
||||
return 1
|
||||
if(other.universal_speak)
|
||||
return 1
|
||||
if(isAI(src) && ispAI(other))
|
||||
return 1
|
||||
if (istype(other, src.type) || istype(src, other.type))
|
||||
return 1
|
||||
if (istype(other, /mob/living/carbon/human) && (istype(src, /mob/living/carbon/human) || istype(src, /mob/living/silicon/pai)))
|
||||
return 1
|
||||
if(istype(other, /mob/living/carbon/alien) && istype(src, /mob/living/carbon/alien))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
for(var/datum/language/L in src.languages) //Handling languages
|
||||
if(speaking.flags & INNATE)
|
||||
return 1
|
||||
|
||||
//Language check.
|
||||
for(var/datum/language/L in src.languages)
|
||||
if(speaking.name == L.name)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/mob/proc/say_quote(var/text,var/datum/language/speaking)
|
||||
/*
|
||||
***Deprecated***
|
||||
let this be handled at the hear_say or hear_radio proc
|
||||
This is left in for robot speaking when humans gain binary channel access until I get around to rewriting
|
||||
robot_talk() proc.
|
||||
There is no language handling build into it however there is at the /mob level so we accept the call
|
||||
for it but just ignore it.
|
||||
*/
|
||||
|
||||
if(!text)
|
||||
return "says, \"...\""; //not the best solution, but it will stop a large number of runtimes. The cause is somewhere in the Tcomms code
|
||||
//tcomms code is still runtiming somewhere here
|
||||
var/ending = copytext(text, length(text))
|
||||
/mob/proc/say_quote(var/message, var/datum/language/speaking = null)
|
||||
var/verb = "says"
|
||||
var/ending = copytext(message, length(message))
|
||||
if(ending=="!")
|
||||
verb=pick("exclaims","shouts","yells")
|
||||
else if(ending=="?")
|
||||
verb="asks"
|
||||
|
||||
var/speechverb = "<span class='say_quote'>"
|
||||
return verb
|
||||
|
||||
if (speaking)
|
||||
speechverb = "[speaking.speech_verb]</span>, \"<span class='[speaking.colour]'>"
|
||||
else if(speak_emote && speak_emote.len)
|
||||
speechverb = "[pick(speak_emote)], \""
|
||||
else if (src.stuttering)
|
||||
speechverb = "stammers, \""
|
||||
else if (src.slurring)
|
||||
speechverb = "slurrs, \""
|
||||
else if (ending == "?")
|
||||
speechverb = "asks, \""
|
||||
else if (ending == "!")
|
||||
speechverb = "exclaims, \""
|
||||
else if(isliving(src))
|
||||
var/mob/living/L = src
|
||||
if (L.getBrainLoss() >= 60)
|
||||
speechverb = "gibbers, \""
|
||||
else
|
||||
speechverb = "says, \""
|
||||
else
|
||||
speechverb = "says, \""
|
||||
|
||||
return "[speechverb][text]</span>\""
|
||||
|
||||
/mob/proc/emote(var/act, var/type, var/message)
|
||||
if(act == "me")
|
||||
@@ -133,21 +116,34 @@
|
||||
/mob/proc/say_test(var/text)
|
||||
var/ending = copytext(text, length(text))
|
||||
if (ending == "?")
|
||||
if(isalien(src))
|
||||
return "A1"
|
||||
if(isrobot(src))
|
||||
return "R1"
|
||||
else
|
||||
return "1"
|
||||
return "1"
|
||||
else if (ending == "!")
|
||||
if(isalien(src))
|
||||
return "A2"
|
||||
if(isrobot(src))
|
||||
return "R2"
|
||||
else
|
||||
return "2"
|
||||
else if(isalien(src))
|
||||
return "A0"
|
||||
else if(isrobot(src))
|
||||
return "R0"
|
||||
return "2"
|
||||
return "0"
|
||||
|
||||
//parses the message mode code (e.g. :h, :w) from text, such as that supplied to say.
|
||||
//returns the message mode string or null for no message mode.
|
||||
//standard mode is the mode returned for the special ';' radio code.
|
||||
/mob/proc/parse_message_mode(var/message, var/standard_mode="headset")
|
||||
if(length(message) >= 1 && copytext(message,1,2) == ";")
|
||||
return standard_mode
|
||||
|
||||
if(length(message) >= 2)
|
||||
var/channel_prefix = copytext(message, 1 ,3)
|
||||
return department_radio_keys[channel_prefix]
|
||||
|
||||
return null
|
||||
|
||||
//parses the language code (e.g. :j) from text, such as that supplied to say.
|
||||
//returns the language object only if the code corresponds to a language that src can speak, otherwise null.
|
||||
/mob/proc/parse_language(var/message)
|
||||
if(length(message) >= 1 && copytext(message,1,2) == "!")
|
||||
return all_languages["Noise"]
|
||||
|
||||
if(length(message) >= 2)
|
||||
var/language_prefix = lowertext(copytext(message, 1 ,3))
|
||||
var/datum/language/L = language_keys[language_prefix]
|
||||
if (can_speak(L))
|
||||
return L
|
||||
|
||||
return null
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
#define TYPING_INDICATOR_LIFETIME 30 * 10 //grace period after which typing indicator disappears regardless of text in chatbar
|
||||
|
||||
mob/var/hud_typing = 0 //set when typing in an input window instead of chatline
|
||||
mob/var/typing
|
||||
mob/var/last_typed
|
||||
mob/var/last_typed_time
|
||||
|
||||
var/global/image/typing_indicator
|
||||
|
||||
/mob/proc/set_typing_indicator(var/state)
|
||||
|
||||
if(!typing_indicator)
|
||||
typing_indicator = image('icons/mob/talk.dmi',null,"typing")
|
||||
|
||||
if(client)
|
||||
if(client.prefs.toggles & SHOW_TYPING)
|
||||
overlays -= typing_indicator
|
||||
else
|
||||
if(state)
|
||||
if(!typing)
|
||||
overlays += typing_indicator
|
||||
typing = 1
|
||||
else
|
||||
if(typing)
|
||||
overlays -= typing_indicator
|
||||
typing = 0
|
||||
return state
|
||||
|
||||
/mob/verb/say_wrapper()
|
||||
set name = ".Say"
|
||||
set hidden = 1
|
||||
|
||||
set_typing_indicator(1)
|
||||
hud_typing = 1
|
||||
var/message = input("","say (text)") as text
|
||||
hud_typing = 0
|
||||
set_typing_indicator(0)
|
||||
if(message)
|
||||
say_verb(message)
|
||||
|
||||
/mob/verb/me_wrapper()
|
||||
set name = ".Me"
|
||||
set hidden = 1
|
||||
|
||||
set_typing_indicator(1)
|
||||
hud_typing = 1
|
||||
var/message = input("","me (text)") as text
|
||||
hud_typing = 0
|
||||
set_typing_indicator(0)
|
||||
if(message)
|
||||
me_verb(message)
|
||||
|
||||
/mob/proc/handle_typing_indicator()
|
||||
if(client)
|
||||
if(!(client.prefs.toggles & SHOW_TYPING) && !hud_typing)
|
||||
var/temp = winget(client, "input", "text")
|
||||
|
||||
if (temp != last_typed)
|
||||
last_typed = temp
|
||||
last_typed_time = world.time
|
||||
|
||||
if (world.time > last_typed_time + TYPING_INDICATOR_LIFETIME)
|
||||
set_typing_indicator(0)
|
||||
return
|
||||
if(length(temp) > 5 && findtext(temp, "Say \"", 1, 7))
|
||||
set_typing_indicator(1)
|
||||
else if(length(temp) > 3 && findtext(temp, "Me ", 1, 5))
|
||||
set_typing_indicator(1)
|
||||
|
||||
else
|
||||
set_typing_indicator(0)
|
||||
|
||||
/client/verb/typing_indicator()
|
||||
set name = "Show/Hide Typing Indicator"
|
||||
set category = "Preferences"
|
||||
set desc = "Toggles showing an indicator when you are typing emote or say message."
|
||||
prefs.toggles ^= SHOW_TYPING
|
||||
prefs.save_preferences(src)
|
||||
src << "You will [(prefs.toggles & SHOW_TYPING) ? "no longer" : "now"] display a typing indicator."
|
||||
|
||||
// Clear out any existing typing indicator.
|
||||
if(prefs.toggles & SHOW_TYPING)
|
||||
if(istype(mob)) mob.set_typing_indicator(0)
|
||||
|
||||
feedback_add_details("admin_verb","TID") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
@@ -21,8 +21,6 @@ var/list/alldepartments = list()
|
||||
var/department = "Unknown" // our department
|
||||
|
||||
var/destination = "Central Command" // the department we're sending to
|
||||
|
||||
var/data[0]
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/New()
|
||||
..()
|
||||
@@ -51,6 +49,7 @@ var/list/alldepartments = list()
|
||||
user << "<span class='warning'>You swipe the card through [src], but nothing happens.</span>"
|
||||
|
||||
/obj/machinery/photocopier/faxmachine/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/data[0]
|
||||
if(scan)
|
||||
data["scan_name"] = scan.name
|
||||
else
|
||||
@@ -142,8 +141,7 @@ var/list/alldepartments = list()
|
||||
else if(istype(copyitem, /obj/item/weapon/photo))
|
||||
copyitem.name = "[(n_name ? text("[n_name]") : "photo")]"
|
||||
else if(istype(copyitem, /obj/item/weapon/paper_bundle))
|
||||
copyitem.name = "[(n_name ? text("[n_name]") : "paper")]"
|
||||
data["name"] = copyitem.name
|
||||
copyitem.name = "[(n_name ? text("[n_name]") : "paper")]"
|
||||
|
||||
nanomanager.update_uis(src)
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
build_path = /obj/item/weapon/circuitboard/bodyscanner
|
||||
category = list("Medical Machinery")
|
||||
|
||||
/datum/design/sleep_console
|
||||
/datum/design/bodyscanner_console
|
||||
name = "Machine Board (Body Scanner Console)"
|
||||
desc = "Allows for the construction of circuit boards used to build a Body Scanner Console."
|
||||
id = "bodyscanner_console"
|
||||
|
||||
@@ -196,7 +196,7 @@
|
||||
user.visible_message("\blue [user] has attached [target]'s head to the body.", \
|
||||
"\blue You have attached [target]'s head to the body.")
|
||||
affected.status = 0
|
||||
if(istype(target,/mob/living/carbon/human/machine))
|
||||
if(target.species && (target.species.flags & IS_SYNTHETIC))
|
||||
affected.status = 128
|
||||
affected.amputated = 0
|
||||
affected.destspawn = 0
|
||||
|
||||
+10
-6
@@ -711,11 +711,12 @@ var/list/TAGGERLOCATIONS = list("Disposals",
|
||||
#define CHAT_GHOSTEARS 4
|
||||
#define CHAT_GHOSTSIGHT 8
|
||||
#define CHAT_PRAYER 16
|
||||
//#define CHAT_RADIO 32
|
||||
#define CHAT_RADIO 32
|
||||
#define CHAT_ATTACKLOGS 64
|
||||
#define CHAT_DEBUGLOGS 128
|
||||
#define CHAT_LOOC 256
|
||||
#define CHAT_GHOSTRADIO 512
|
||||
#define SHOW_TYPING 1024
|
||||
|
||||
#define SOUND_ADMINHELP 1
|
||||
#define SOUND_MIDI 2
|
||||
@@ -843,12 +844,15 @@ var/list/restricted_camera_networks = list( //Those networks can only be accesse
|
||||
#define HAS_SKIN_TONE 16
|
||||
#define HAS_SKIN_COLOR 32
|
||||
|
||||
|
||||
//Language flags.
|
||||
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.
|
||||
#define RESTRICTED 2 // Language can only be accquired by spawning or an admin.
|
||||
#define NONVERBAL 4 // Language has a significant non-verbal component. Speech is garbled without line-of-sight
|
||||
#define SIGNLANG 8 // Language is completely non-verbal. Speech is displayed through emotes for those who can understand.
|
||||
#define WHITELISTED 1 // Language is available if the speaker is whitelisted.
|
||||
#define RESTRICTED 2 // Language can only be accquired by spawning or an admin.
|
||||
#define NONVERBAL 4 // Language has a significant non-verbal component. Speech is garbled without line-of-sight
|
||||
#define SIGNLANG 8 // Language is completely non-verbal. Speech is displayed through emotes for those who can understand.
|
||||
#define HIVEMIND 16 // Broadcast to all mobs with this language.
|
||||
#define NONGLOBAL 32 // Do not add to general languages list
|
||||
#define INNATE 64 // All mobs can be assumed to speak and understand this language (audible emotes)
|
||||
#define NO_TALK_MSG 128 // Do not show the "\The [speaker] talks into \the [radio]" message
|
||||
|
||||
//Flags for zone sleeping
|
||||
#define ZONE_ACTIVE 1
|
||||
|
||||
@@ -67,9 +67,18 @@ h1.alert, h2.alert {color: #000000;}
|
||||
.noticealien {color: #00c000;}
|
||||
.alertalien {color: #00c000; font-weight: bold;}
|
||||
.tajaran {color: #803B56;}
|
||||
.tajaran_signlang {color: #941C1C;}
|
||||
.skrell {color: #00CED1;}
|
||||
.soghun {color: #228B22;}
|
||||
.solcom {color: #22228B;}
|
||||
.changeling {color: #800080;}
|
||||
.vox {color: #AA00AA;}
|
||||
.diona {color: #007200;}
|
||||
.trinary {color: #727272;}
|
||||
.kidan {color: #664205;}
|
||||
.slime {color: #0077AA;}
|
||||
.rough {font-family: "Trebuchet MS", cursive, sans-serif;}
|
||||
.say_quote {font-family: Georgia, Verdana, sans-serif;}
|
||||
|
||||
.say_quote {font-family: Georgia, Verdana, sans-serif;}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user