Merge branch 'master' into upstream-merge-33213

This commit is contained in:
deathride58
2017-12-04 21:39:30 +00:00
committed by GitHub
51 changed files with 982 additions and 271 deletions

View File

@@ -44126,7 +44126,6 @@
/area/maintenance/aft)
"cdM" = (
/obj/machinery/atmospherics/pipe/simple/scrubbers/hidden,
/mob/living/simple_animal/mouse,
/turf/open/floor/plating,
/area/maintenance/aft)
"cdN" = (

View File

@@ -5716,7 +5716,6 @@
/turf/open/floor/plating,
/area/maintenance/department/security/brig)
"apA" = (
/mob/living/simple_animal/mouse/gray,
/turf/open/floor/plating{
icon_state = "platingdmg3"
},
@@ -14612,7 +14611,6 @@
/turf/open/floor/plating,
/area/maintenance/department/cargo)
"aKo" = (
/mob/living/simple_animal/mouse/gray,
/turf/open/floor/plating{
burnt = 1;
icon_state = "panelscorched"
@@ -24725,7 +24723,6 @@
/obj/machinery/atmospherics/pipe/simple/supply/hidden{
dir = 4
},
/mob/living/simple_animal/mouse/gray,
/turf/open/floor/plating,
/area/maintenance/department/cargo)
"biB" = (

View File

@@ -189,3 +189,5 @@ GLOBAL_LIST_INIT(glass_sheet_types, typecacheof(list(
/obj/item/stack/sheet/plasmarglass)))
#define is_glass_sheet(O) (is_type_in_typecache(O, GLOB.glass_sheet_types))
#define isblobmonster(O) (istype(O, /mob/living/simple_animal/hostile/blob))

View File

@@ -49,4 +49,10 @@
#define LOGCHAT "chat"
#define LOGASAY "adminsay"
#define LOGCOMMENT "comment"
#define LOGOOC "ooc"
#define LOGOOC "ooc"
#define LINGHIVE_NONE 0
#define LINGHIVE_OUTSIDER 1
#define LINGHIVE_LING 2
#define LINGHIVE_LINK 3

View File

@@ -110,6 +110,7 @@
icon = 'icons/obj/custom.dmi'
icon_state = "festive-w"
item_state = "festive-i"
icon = 'icons/obj/custom.dmi'
w_class = WEIGHT_CLASS_SMALL
body_parts_covered = CHEST|GROIN|LEGS|ARMS

View File

@@ -3,6 +3,13 @@ SUBSYSTEM_DEF(radio)
flags = SS_NO_FIRE|SS_NO_INIT
var/list/datum/radio_frequency/frequencies = list()
var/list/saymodes = list()
/datum/controller/subsystem/radio/PreInit(timeofday)
for(var/_SM in subtypesof(/datum/saymode))
var/datum/saymode/SM = new _SM()
saymodes[SM.key] = SM
return ..()
/datum/controller/subsystem/radio/proc/add_object(obj/device, new_frequency as num, filter = null as text|null)
var/f_text = num2text(new_frequency)

View File

@@ -357,6 +357,9 @@ SUBSYSTEM_DEF(timer)
wait = max(wait, 0)
if(wait >= INFINITY)
CRASH("Attempted to create timer with INFINITY delay")
var/hash
if (flags & TIMER_UNIQUE)

View File

@@ -134,11 +134,11 @@
/datum/antagonist/rev/farewell()
if(ishuman(owner.current))
owner.current.visible_message("[owner.current] looks like they just remembered their real allegiance!", \
"<span class='userdanger'><FONT size = 3>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</FONT></span>")
owner.current.visible_message("[owner.current] looks like they just remembered their real allegiance!")
to_chat(owner, "<span class='userdanger'><FONT size = 3>You are no longer a brainwashed revolutionary! Your memory is hazy from the time you were a rebel...the only thing you remember is the name of the one who brainwashed you...</FONT></span>")
else if(issilicon(owner.current))
owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.", \
"<span class='userdanger'><FONT size = 3>The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.</FONT></span>")
owner.current.visible_message("The frame beeps contentedly, purging the hostile memory engram from the MMI before initalizing it.")
to_chat(owner, "<span class='userdanger'><FONT size = 3>The frame's firmware detects and deletes your neural reprogramming! You remember nothing but the name of the one who flashed you.</FONT></span>")
/datum/antagonist/rev/proc/remove_revolutionary(borged, deconverter)
log_attack("[owner.current] (Key: [key_name(owner.current)]) has been deconverted from the revolution by [deconverter] (Key: [key_name(deconverter)])!")

View File

@@ -29,7 +29,8 @@
icon = beam_icon
icon_state = beam_icon_state
beam_type = btype
addtimer(CALLBACK(src,.proc/End), time)
if(time < INFINITY)
addtimer(CALLBACK(src,.proc/End), time)
/datum/beam/proc/Start()
Draw()

View File

@@ -34,7 +34,7 @@ Stands have a lot of procs which mimic mob procs. Rather than inserting hooks fo
* Lazy associated list of type -> component/list of components.
1. `/datum/component/var/enabled` (protected, boolean)
* If the component is enabled. If not, it will not react to signals
* `TRUE` by default
* `FALSE` by default, set to `TRUE` when a signal is registered
1. `/datum/component/var/dupe_mode` (protected, enum)
* How duplicate component types are handled when added to the datum.
* `COMPONENT_DUPE_HIGHLANDER` (default): Old component will be deleted, new component will first have `/datum/component/proc/InheritComponent(datum/component/old, FALSE)` on it

View File

@@ -1,5 +1,5 @@
/datum/component
var/enabled = TRUE
var/enabled = FALSE
var/dupe_mode = COMPONENT_DUPE_HIGHLANDER
var/dupe_type
var/list/signal_procs
@@ -133,6 +133,8 @@
if(!istype(proc_or_callback, /datum/callback)) //if it wasnt a callback before, it is now
proc_or_callback = CALLBACK(src, proc_or_callback)
procs[sig_type] = proc_or_callback
enabled = TRUE
/datum/component/proc/InheritComponent(datum/component/C, i_am_original)
return
@@ -172,8 +174,7 @@
var/datum/component/C = target
if(!C.enabled)
return NONE
var/list/sps = C.signal_procs
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
var/datum/callback/CB = C.signal_procs[sigtype]
if(!CB)
return NONE
. = CB.InvokeAsync(arglist(arguments))
@@ -185,9 +186,8 @@
for(var/I in target)
var/datum/component/C = I
if(!C.enabled)
continue
var/list/sps = C.signal_procs
var/datum/callback/CB = LAZYACCESS(sps, sigtype)
continue
var/datum/callback/CB = C.signal_procs[sigtype]
if(!CB)
continue
var/retval = CB.InvokeAsync(arglist(arguments))

View File

@@ -1,5 +1,14 @@
#define HOLOPAD_MAX_DIAL_TIME 200
#define HOLORECORD_DELAY "delay"
#define HOLORECORD_SAY "say"
#define HOLORECORD_SOUND "sound"
#define HOLORECORD_LANGUAGE "lang"
#define HOLORECORD_PRESET "preset"
#define HOLORECORD_RENAME "rename"
#define HOLORECORD_MAX_LENGTH 200
/mob/camera/aiEye/remote/holo/setLoc()
. = ..()
var/obj/machinery/holopad/H = origin
@@ -184,3 +193,122 @@
/datum/action/innate/end_holocall/Activate()
hcall.Disconnect(hcall.calling_holopad)
//RECORDS
/datum/holorecord
var/caller_name = "Unknown" //Caller name
var/image/caller_image
var/list/entries = list()
var/language = /datum/language/common //Initial language, can be changed by HOLORECORD_LANGUAGE entries
/obj/item/disk/holodisk
name = "holorecord disk"
desc = "Stores recorder holocalls."
icon_state = "holodisk"
var/datum/holorecord/record
//Preset variables
var/preset_image_type
var/preset_record_text
/obj/item/disk/holodisk/Initialize(mapload)
. = ..()
if(preset_record_text)
build_record()
/obj/item/disk/holodisk/Destroy()
QDEL_NULL(record)
return ..()
/obj/item/disk/holodisk/proc/build_record()
record = new
var/list/lines = splittext(preset_record_text,"\n")
for(var/line in lines)
var/prepared_line = trim(line)
if(!length(prepared_line))
continue
var/splitpoint = findtext(prepared_line," ")
if(!splitpoint)
continue
var/command = copytext(prepared_line,1,splitpoint)
var/value = copytext(prepared_line,splitpoint+1)
switch(command)
if("DELAY")
var/delay_value = text2num(value)
if(!delay_value)
continue
record.entries += list(list(HOLORECORD_DELAY,delay_value))
if("NAME")
if(!record.caller_name)
record.caller_name = value
else
record.entries += list(list(HOLORECORD_RENAME,value))
if("SAY")
record.entries += list(list(HOLORECORD_SAY,value))
if("SOUND")
record.entries += list(list(HOLORECORD_SOUND,value))
if("LANGUAGE")
var/lang_type = text2path(value)
if(ispath(lang_type,/datum/language))
record.entries += list(list(HOLORECORD_LANGUAGE,lang_type))
if("PRESET")
var/preset_type = text2path(value)
if(ispath(preset_type,/datum/preset_holoimage))
record.entries += list(list(HOLORECORD_PRESET,preset_type))
if(!preset_image_type)
record.caller_image = image('icons/mob/animal.dmi',"old")
else
var/datum/preset_holoimage/H = new preset_image_type
record.caller_image = H.build_image()
//These build caller image from outfit and some additional data, for use by mappers for ruin holorecords
/datum/preset_holoimage
var/nonhuman_mobtype //Fill this if you just want something nonhuman
var/outfit_type
var/species_type = /datum/species/human
/datum/preset_holoimage/proc/build_image()
if(nonhuman_mobtype)
var/mob/living/L = nonhuman_mobtype
. = image(initial(L.icon),initial(L.icon_state))
else
var/mob/living/carbon/human/dummy/mannequin = generate_or_wait_for_human_dummy("HOLODISK_PRESET")
if(species_type)
mannequin.set_species(species_type)
if(outfit_type)
mannequin.equipOutfit(outfit_type,TRUE)
mannequin.setDir(SOUTH)
COMPILE_OVERLAYS(mannequin)
. = getFlatIcon(mannequin)
unset_busy_human_dummy("HOLODISK_PRESET")
/obj/item/disk/holodisk/example
preset_image_type = /datum/preset_holoimage/clown
preset_record_text = {"
NAME Clown
DELAY 10
SAY Why did the chaplain cross the maint ?
DELAY 20
SAY He wanted to get to the other side!
SOUND clownstep
DELAY 30
LANGUAGE /datum/language/narsie
SAY Helped him get there!
DELAY 10
SAY ALSO IM SECRETLY A GORILLA
DELAY 10
PRESET /datum/preset_holoimage/gorilla
NAME Gorilla
LANGUAGE /datum/language/common
SAY OOGA
DELAY 20"}
/datum/preset_holoimage/engineer
outfit_type = /datum/outfit/job/engineer/gloved/rig
/datum/preset_holoimage/gorilla
nonhuman_mobtype = /mob/living/simple_animal/hostile/gorilla
/datum/preset_holoimage/clown
outfit_type = /datum/outfit/job/clown

112
code/datums/saymode.dm Normal file
View File

@@ -0,0 +1,112 @@
/datum/saymode
var/key
var/mode
//Return FALSE if you have handled the message. Otherwise, return TRUE and saycode will continue doing saycode things.
//user = whoever said the message
//message = the message
//language = the language.
/datum/saymode/proc/handle_message(mob/living/user, message, datum/language/language)
return TRUE
/datum/saymode/changeling
key = "g"
mode = MODE_CHANGELING
/datum/saymode/changeling/handle_message(mob/living/user, message, datum/language/language)
switch(user.lingcheck())
if(LINGHIVE_LINK)
var/msg = "<i><font color=#800040><b>[user.mind]:</b> [message]</font></i>"
for(var/_M in GLOB.mob_list)
var/mob/M = _M
if(M in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(M, user)
to_chat(M, "[link] [msg]")
else
switch(M.lingcheck())
if(LINGHIVE_LINK, LINGHIVE_LING)
to_chat(M, msg)
if(LINGHIVE_OUTSIDER)
if(prob(40))
to_chat(M, "<i><font color=#800080>We can faintly sense an outsider trying to communicate through the hivemind...</font></i>")
if(LINGHIVE_LING)
var/datum/antagonist/changeling/changeling = user.mind.has_antag_datum(/datum/antagonist/changeling)
var/msg = "<i><font color=#800080><b>[changeling.changelingID]:</b> [message]</font></i>"
log_talk(src,"[changeling.changelingID]/[user.key] : [message]",LOGSAY)
for(var/_M in GLOB.mob_list)
var/mob/M = _M
if(M in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(M, user)
to_chat(M, "[link] [msg]")
else
switch(M.lingcheck())
if(LINGHIVE_LINK)
to_chat(M, msg)
if(LINGHIVE_LING)
to_chat(M, msg)
if(LINGHIVE_OUTSIDER)
if(prob(40))
to_chat(M, "<i><font color=#800080>We can faintly sense another of our kind trying to communicate through the hivemind...</font></i>")
if(LINGHIVE_OUTSIDER)
to_chat(user, "<i><font color=#800080>Our senses have not evolved enough to be able to communicate this way...</font></i>")
return FALSE
/datum/saymode/xeno
key = "a"
mode = MODE_ALIEN
/datum/saymode/xeno/handle_message(mob/living/user, message, datum/language/language)
if(user.hivecheck())
user.alien_talk(message)
return FALSE
/datum/saymode/vocalcords
key = "x"
mode = MODE_VOCALCORDS
/datum/saymode/vocalcords/handle_message(mob/living/user, message, datum/language/language)
if(iscarbon(user))
var/mob/living/carbon/C = user
var/obj/item/organ/vocal_cords/V = C.getorganslot(ORGAN_SLOT_VOICE)
if(V && V.can_speak_with())
V.handle_speech(message) //message
V.speak_with(message) //action
return FALSE
/datum/saymode/binary //everything that uses .b (silicons, drones, blobbernauts/spores, swarmers)
key = "b"
mode = MODE_BINARY
/datum/saymode/binary/handle_message(mob/living/user, message, datum/language/language)
if(isswarmer(user))
var/mob/living/simple_animal/hostile/swarmer/S = user
S.swarmer_chat(message)
return FALSE
if(isblobmonster(user))
var/mob/living/simple_animal/hostile/blob/B = user
B.blob_chat(message)
return FALSE
if(isdrone(user))
var/mob/living/simple_animal/drone/D = user
D.drone_chat(message)
return FALSE
if(user.binarycheck())
user.robot_talk(message)
return FALSE
return FALSE
/datum/saymode/holopad
key = "h"
mode = MODE_HOLOPAD
/datum/saymode/holopad/handle_message(mob/living/user, message, datum/language/language)
if(isAI(user))
var/mob/living/silicon/ai/AI = user
AI.holopad_talk(message, language)
return FALSE
return FALSE

View File

@@ -20,10 +20,11 @@
overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only
immunity_type = "lava"
/datum/weather/floor_is_lava/weather_act(mob/living/L)
for(var/obj/structure/O in L.loc)
if(O.density)
for(var/obj/structure/O in L.loc)
if(O.density || (L in O.buckled_mobs && istype(O, /obj/structure/bed)))
return
if(L.loc.density)
return

View File

@@ -56,13 +56,6 @@
return 1
return ..()
/mob/living/simple_animal/hostile/blob/handle_inherent_channels(message, message_mode)
if(message_mode == MODE_BINARY)
blob_chat(message)
return 1
else
..()
/mob/living/simple_animal/hostile/blob/proc/blob_chat(msg)
var/spanned_message = say_quote(msg, get_spans())
var/rendered = "<font color=\"#EE4000\"><b>\[Blob Telepathy\] [real_name]</b> [spanned_message]</font>"

View File

@@ -50,7 +50,7 @@
to_chat(target, "<span class='userdanger'>A migraine throbs behind your eyes, you hear yourself screaming - but your mouth has not opened!</span>")
for(var/mi in GLOB.mob_list)
var/mob/M = mi
if(M.lingcheck() == 2)
if(M.lingcheck() == LINGHIVE_LING)
to_chat(M, "<i><font color=#800080>We can sense a foreign presence in the hivemind...</font></i>")
target.mind.linglink = 1
target.say(":g AAAAARRRRGGGGGHHHHH!!")

View File

@@ -121,13 +121,6 @@
if(statpanel("Status"))
stat("Resources:",resources)
/mob/living/simple_animal/hostile/swarmer/handle_inherent_channels(message, message_mode)
if(message_mode == MODE_BINARY)
swarmer_chat(message)
return ITALICS | REDUCE_RANGE
else
. = ..()
/mob/living/simple_animal/hostile/swarmer/get_spans()
return ..() | SPAN_ROBOT

View File

@@ -47,6 +47,12 @@ Possible to do for anyone motivated enough:
var/temp = ""
var/list/holo_calls //array of /datum/holocalls
var/datum/holocall/outgoing_call //do not modify the datums only check and call the public procs
var/obj/item/disk/holodisk/disk //Record disk
var/replay_mode = FALSE //currently replaying a recording
var/record_mode = FALSE //currently recording
var/record_start = 0 //recording start time
var/record_user //user that inititiated the recording
var/obj/effect/overlay/holo_pad_hologram/replay_holo //replay hologram
var/static/force_answer_call = FALSE //Calls will be automatically answered after a couple rings, here for debugging
var/static/list/holopads = list()
@@ -64,6 +70,14 @@ Possible to do for anyone motivated enough:
for (var/I in masters)
clear_holo(I)
if(replay_mode)
replay_stop()
if(record_mode)
record_stop()
QDEL_NULL(disk)
holopads -= src
return ..()
@@ -72,6 +86,10 @@ Possible to do for anyone motivated enough:
stat &= ~NOPOWER
else
stat |= NOPOWER
if(replay_mode)
replay_stop()
if(record_mode)
record_stop()
if(outgoing_call)
outgoing_call.ConnectionFailure(src)
@@ -101,6 +119,18 @@ Possible to do for anyone motivated enough:
if(default_deconstruction_crowbar(P))
return
if(istype(P,/obj/item/disk/holodisk))
if(disk)
to_chat(user,"<span class='notice'>There's already a disk inside [src]</span>")
return
if (!user.transferItemToLoc(P,src))
return
to_chat(user,"<span class='notice'>You insert [P] into [src]</span>")
disk = P
updateDialog()
return
return ..()
/obj/machinery/holopad/AltClick(mob/living/carbon/human/user)
@@ -122,6 +152,17 @@ Possible to do for anyone motivated enough:
else
dat = "<a href='?src=[REF(src)];AIrequest=1'>Request an AI's presence.</a><br>"
dat += "<a href='?src=[REF(src)];Holocall=1'>Call another holopad.</a><br>"
if(disk)
if(disk.record)
//Replay
dat += "<a href='?src=[REF(src)];replay_start=1'>Replay disk recording.</a><br>"
//Clear
dat += "<a href='?src=[REF(src)];record_clear=1'>Clear disk recording.</a><br>"
else
//Record
dat += "<a href='?src=[REF(src)];record_start=1'>Start new recording.</a><br>"
//Eject
dat += "<a href='?src=[REF(src)];disk_eject=1'>Eject disk.</a><br>"
if(LAZYLEN(holo_calls))
dat += "=====================================================<br>"
@@ -145,7 +186,7 @@ Possible to do for anyone motivated enough:
dat += "<a href='?src=[REF(src)];disconnectcall=[REF(HC)]'>Disconnect call from [HC.user].</a><br>"
var/datum/browser/popup = new(user, "holopad", name, 300, 130)
var/datum/browser/popup = new(user, "holopad", name, 300, 150)
popup.set_content(dat)
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.open()
@@ -215,6 +256,22 @@ Possible to do for anyone motivated enough:
temp = ""
if(outgoing_call)
outgoing_call.Disconnect()
else if(href_list["disk_eject"])
if(disk && !replay_mode)
disk.forceMove(drop_location())
disk = null
else if(href_list["replay_stop"])
replay_stop()
else if(href_list["replay_start"])
replay_start()
else if(href_list["record_start"])
record_start(usr)
else if(href_list["record_stop"])
record_stop()
else if(href_list["record_clear"])
record_clear()
updateDialog()
@@ -269,6 +326,7 @@ Possible to do for anyone motivated enough:
else
playsound(src, 'sound/machines/twobeep.ogg', 100) //bring, bring!
/obj/machinery/holopad/proc/activate_holo(mob/living/user)
var/mob/living/silicon/ai/AI = user
if(!istype(AI))
@@ -321,15 +379,24 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
if(outgoing_call && speaker == outgoing_call.user)
outgoing_call.hologram.say(raw_message)
if(record_mode && speaker == record_user)
record_message(speaker,raw_message,message_language)
/obj/machinery/holopad/proc/SetLightsAndPower()
var/total_users = masters.len + LAZYLEN(holo_calls)
use_power = total_users > 0 ? ACTIVE_POWER_USE : IDLE_POWER_USE
active_power_usage = HOLOPAD_PASSIVE_POWER_USAGE + (HOLOGRAM_POWER_USAGE * total_users)
if(total_users)
if(total_users || replay_mode)
set_light(2)
icon_state = "holopad1"
else
set_light(0)
update_icon()
/obj/machinery/holopad/update_icon()
var/total_users = masters.len + LAZYLEN(holo_calls)
if(total_users || replay_mode)
icon_state = "holopad1"
else
icon_state = "holopad0"
/obj/machinery/holopad/proc/set_holo(mob/living/user, var/obj/effect/overlay/holo_pad_hologram/h)
@@ -365,6 +432,128 @@ For the other part of the code, check silicon say.dm. Particularly robot talk.*/
clear_holo(user)
return TRUE
// RECORDED MESSAGES
/obj/machinery/holopad/proc/setup_replay_holo(datum/holorecord/record)
var/obj/effect/overlay/holo_pad_hologram/Hologram = new(loc)//Spawn a blank effect at the location.
Hologram.add_overlay(record.caller_image)
Hologram.alpha = 170
Hologram.add_atom_colour("#77abff", FIXED_COLOUR_PRIORITY)
Hologram.dir = SOUTH //for now
Hologram.grant_all_languages(omnitongue=TRUE)
var/datum/language_holder/holder = Hologram.get_language_holder()
holder.selected_default_language = record.language
Hologram.mouse_opacity = MOUSE_OPACITY_TRANSPARENT//So you can't click on it.
Hologram.layer = FLY_LAYER//Above all the other objects/mobs. Or the vast majority of them.
Hologram.anchored = TRUE//So space wind cannot drag it.
Hologram.name = "[record.caller_name] (Hologram)"//If someone decides to right click.
Hologram.set_light(2) //hologram lighting
visible_message("<span class='notice'>A holographic image of [record.caller_name] flickers to life before your eyes!</span>")
return Hologram
/obj/machinery/holopad/proc/replay_start()
if(!replay_mode)
replay_mode = TRUE
replay_holo = setup_replay_holo(disk.record)
temp = "Replaying...<br>"
temp += "<A href='?src=[REF(src)];replay_stop=1'>End replay.</A>"
SetLightsAndPower()
replay_entry(1)
return
/obj/machinery/holopad/proc/replay_stop()
if(replay_mode)
replay_mode = FALSE
temp = null
QDEL_NULL(replay_holo)
SetLightsAndPower()
updateDialog()
/obj/machinery/holopad/proc/record_start(mob/living/user)
if(!user || !disk || disk.record)
return
disk.record = new
record_mode = TRUE
record_start = world.time
record_user = user
disk.record.caller_image = get_record_icon(user)
temp = "Recording...<br>"
temp += "<A href='?src=[REF(src)];record_stop=1'>End recording.</A>"
/obj/machinery/holopad/proc/get_record_icon(mob/living/user)
var/olddir = user.dir
user.setDir(SOUTH)
. = getFlatIcon(user)
user.setDir(olddir)
/obj/machinery/holopad/proc/record_message(mob/living/speaker,message,language)
if(!record_mode)
return
//make this command so you can have multiple languages in single record
if(!disk.record.caller_name && istype(speaker))
disk.record.caller_name = speaker.name
if(!disk.record.language)
disk.record.language = language
else if(language != disk.record.language)
disk.record.entries += list(list(HOLORECORD_LANGUAGE,language))
var/current_delay = 0
for(var/E in disk.record.entries)
var/list/entry = E
if(entry[1] != HOLORECORD_DELAY)
continue
current_delay += entry[2]
var/time_delta = world.time - record_start - current_delay
if(time_delta >= 1)
disk.record.entries += list(list(HOLORECORD_DELAY,time_delta))
disk.record.entries += list(list(HOLORECORD_SAY,message))
if(disk.record.entries.len >= HOLORECORD_MAX_LENGTH)
record_stop()
/obj/machinery/holopad/proc/replay_entry(entry_number)
if(!replay_mode)
return
if(disk.record.entries.len < entry_number)
replay_stop()
return
var/list/entry = disk.record.entries[entry_number]
var/command = entry[1]
switch(command)
if(HOLORECORD_SAY)
var/message = entry[2]
if(replay_holo)
replay_holo.say(message)
if(HOLORECORD_SOUND)
playsound(src,entry[2],50,1)
if(HOLORECORD_DELAY)
addtimer(CALLBACK(src,.proc/replay_entry,entry_number+1),entry[2])
return
if(HOLORECORD_LANGUAGE)
var/datum/language_holder/holder = replay_holo.get_language_holder()
holder.selected_default_language = entry[2]
if(HOLORECORD_PRESET)
var/preset_type = entry[2]
var/datum/preset_holoimage/H = new preset_type
replay_holo.cut_overlays()
replay_holo.add_overlay(H.build_image())
if(HOLORECORD_RENAME)
replay_holo.name = entry[2] + " (Hologram)"
.(entry_number+1)
/obj/machinery/holopad/proc/record_stop()
if(record_mode)
record_mode = FALSE
temp = null
record_user = null
updateDialog()
/obj/machinery/holopad/proc/record_clear()
if(disk && disk.record)
QDEL_NULL(disk.record)
updateDialog()
/obj/effect/overlay/holo_pad_hologram
var/mob/living/Impersonation
var/datum/holocall/HC

View File

@@ -242,15 +242,17 @@
user.changeNext_move(CLICK_CD_MELEE)
var/obj/item/weldingtool/WT = W
if(obj_integrity<max_integrity)
if (WT.remove_fuel(0,user))
if(WT.remove_fuel(1, user))
if (internal_damage & MECHA_INT_TANK_BREACH)
clearInternalDamage(MECHA_INT_TANK_BREACH)
to_chat(user, "<span class='notice'>You repair the damaged gas tank.</span>")
else
user.visible_message("<span class='notice'>[user] repairs some damage to [name].</span>")
user.visible_message("<span class='notice'>[user] repairs some damage to [name].</span>", "<span class='notice'>You repair some damage to [src].</span>")
obj_integrity += min(10, max_integrity-obj_integrity)
if(obj_integrity == max_integrity)
to_chat(user, "<span class='notice'>It looks to be fully repaired now.</span>")
else
to_chat(user, "<span class='warning'>The welder must be on for this task!</span>")
to_chat(user, "<span class='warning'>[WT] needs to be on for this task!</span>")
return 1
else
to_chat(user, "<span class='warning'>The [name] is at full integrity!</span>")

View File

@@ -545,6 +545,7 @@
H.set_heartattack(FALSE)
H.revive()
H.emote("gasp")
H.Jitter(100)
if(tplus > tloss)
H.setBrainLoss( max(0, min(99, ((tlimit - tplus) / tlimit * 100))))
add_logs(user, H, "revived", defib)

View File

@@ -9,13 +9,91 @@
var/list/squeak_override //Weighted list; If you want your plush to have different squeak sounds use this
var/stuffed = TRUE //If the plushie has stuffing in it
var/obj/item/grenade/grenade //You can remove the stuffing from a plushie and add a grenade to it for *nefarious uses*
//--love ~<3--
gender = NEUTER
var/obj/item/toy/plush/lover
var/obj/item/toy/plush/partner
var/obj/item/toy/plush/plush_child
var/obj/item/toy/plush/paternal_parent //who initiated creation
var/obj/item/toy/plush/maternal_parent //who owns, see love()
var/list/scorned = list() //who the plush hates
var/list/scorned_by = list() //who hates the plush, to remove external references on Destroy()
var/heartbroken = FALSE
var/vowbroken = FALSE
var/young = FALSE
var/mood_message
var/list/love_message
var/list/partner_message
var/list/heartbroken_message
var/list/vowbroken_message
var/list/parent_message
var/normal_desc
//--end of love :'(--
/obj/item/toy/plush/Initialize()
. = ..()
AddComponent(/datum/component/squeak, squeak_override)
//have we decided if Pinocchio goes in the blue or pink aisle yet?
if(gender == NEUTER)
if(prob(50))
gender = FEMALE
else
gender = MALE
love_message = list("\n[src] is so happy, \he could rip a seam!")
partner_message = list("\n[src] has a ring on \his finger! It says bound to my dear [partner].")
heartbroken_message = list("\n[src] looks so sad.")
vowbroken_message = list("\n[src] lost \his ring...")
parent_message = list("\n[src] can't remember what sleep is.")
normal_desc = desc
/obj/item/toy/plush/Destroy()
QDEL_NULL(grenade)
//inform next of kin and... acquaintances
if(partner)
partner.bad_news(src)
partner = null
lover = null
else if(lover)
lover.bad_news(src)
lover = null
if(paternal_parent)
paternal_parent.bad_news(src)
paternal_parent = null
if(maternal_parent)
maternal_parent.bad_news(src)
maternal_parent = null
if(plush_child)
plush_child.bad_news(src)
plush_child = null
var/i
var/obj/item/toy/plush/P
for(i=1, i<=scorned.len, i++)
P = scorned[i]
P.bad_news(src)
scorned = null
for(i=1, i<=scorned_by.len, i++)
P = scorned_by[i]
P.bad_news(src)
scorned_by = null
//null remaining lists
squeak_override = null
love_message = null
partner_message = null
heartbroken_message = null
vowbroken_message = null
parent_message = null
return ..()
/obj/item/toy/plush/handle_atom_del(atom/A)
@@ -66,8 +144,221 @@
var/turf/T = get_turf(user)
log_game("[key_name(user)] added a grenade ([I.name]) to [src] at [COORD(T)].")
return
if(istype(I, /obj/item/toy/plush))
love(I, user)
return
return ..()
/obj/item/toy/plush/proc/love(obj/item/toy/plush/Kisser, mob/living/user) //~<3
var/chance = 100 //to steal a kiss, surely there's a 100% chance no-one would reject a plush such as I?
var/concern = 20 //perhaps something might cloud true love with doubt
var/loyalty = 30 //why should another get between us?
var/duty = 50 //conquering another's is what I live for
//we are not catholic
if(young == TRUE || Kisser.young == TRUE)
user.show_message("<span class='notice'>[src] plays tag with [Kisser].</span>", 1,
"<span class='notice'>They're happy.</span>", 0)
Kisser.cheer_up()
cheer_up()
//never again
else if(Kisser in scorned)
//message, visible, alternate message, neither visible nor audible
user.show_message("<span class='notice'>[src] rejects the advances of [Kisser]!</span>", 1,
"<span class='notice'>That didn't feel like it worked.</span>", 0)
else if(src in Kisser.scorned)
user.show_message("<span class='notice'>[Kisser] realises who [src] is and turns away.</span>", 1,
"<span class='notice'>That didn't feel like it worked.</span>", 0)
//first comes love
else if(Kisser.lover != src && Kisser.partner != src) //cannot be lovers or married
if(Kisser.lover) //if the initiator has a lover
Kisser.lover.heartbreak(Kisser) //the old lover can get over the kiss-and-run whilst the kisser has some fun
chance -= concern //one heart already broken, what does another mean?
if(lover) //if the recipient has a lover
chance -= loyalty //mustn't... but those lips
if(partner) //if the recipient has a partner
chance -= duty //do we mate for life?
if(prob(chance)) //did we bag a date?
user.visible_message("<span class='notice'>[user] makes [Kisser] kiss [src]!</span>",
"<span class='notice'>You make [Kisser] kiss [src]!</span>")
if(lover) //who cares for the past, we live in the present
lover.heartbreak(src)
new_lover(Kisser)
Kisser.new_lover(src)
else
user.show_message("<span class='notice'>[src] rejects the advances of [Kisser], maybe next time?</span>", 1,
"<span class='notice'>That didn't feel like it worked, this time.</span>", 0)
//then comes marriage
else if(Kisser.lover == src && Kisser.partner != src) //need to be lovers (assumes loving is a two way street) but not married (also assumes similar)
user.visible_message("<span class='notice'>[user] pronounces [Kisser] and [src] married! D'aw.</span>",
"<span class='notice'>You pronounce [Kisser] and [src] married!</span>")
new_partner(Kisser)
Kisser.new_partner(src)
//then comes a baby in a baby's carriage, or an adoption in an adoption's orphanage
else if(Kisser.partner == src && !plush_child) //the one advancing does not take ownership of the child and we have a one child policy in the toyshop
user.visible_message("<span class='notice'>[user] is going to break [Kisser] and [src] by bashing them like that.</span>",
"<span class='notice'>[Kisser] passionately embraces [src] in your hands. Look away you perv!</span>")
plop(Kisser)
user.visible_message("<span class='notice'>Something drops at the feet of [user].</span>",
"<span class='notice'>The miracle of oh god did that just come out of [src]?!</span>")
//then comes protection, or abstinence if we are catholic
else if(Kisser.partner == src && plush_child)
user.visible_message("<span class='notice'>[user] makes [Kisser] nuzzle [src]!</span>",
"<span class='notice'>You make [Kisser] nuzzle [src]!</span>")
//then oh fuck something unexpected happened
else
user.show_message("<span class='warning'>[Kisser] and [src] don't know what to do with one another.</span>", 0)
/obj/item/toy/plush/proc/heartbreak(obj/item/toy/plush/Brutus)
if(lover != Brutus)
to_chat(world, "lover != Brutus")
return //why are we considering someone we don't love?
scorned.Add(Brutus)
Brutus.scorned_by(src)
lover = null
Brutus.lover = null //feeling's mutual
heartbroken = TRUE
mood_message = pick(heartbroken_message)
if(partner == Brutus) //oh dear...
partner = null
Brutus.partner = null //it'd be weird otherwise
vowbroken = TRUE
mood_message = pick(vowbroken_message)
update_desc()
/obj/item/toy/plush/proc/scorned_by(obj/item/toy/plush/Outmoded)
scorned_by.Add(Outmoded)
/obj/item/toy/plush/proc/new_lover(obj/item/toy/plush/Juliet)
if(lover == Juliet)
return //nice try
lover = Juliet
cheer_up()
lover.cheer_up()
mood_message = pick(love_message)
update_desc()
if(partner) //who?
partner = null //more like who cares
/obj/item/toy/plush/proc/new_partner(obj/item/toy/plush/Apple_of_my_eye)
if(partner == Apple_of_my_eye)
return //double marriage is just insecurity
if(lover != Apple_of_my_eye)
return //union not born out of love will falter
partner = Apple_of_my_eye
heal_memories()
partner.heal_memories()
mood_message = pick(partner_message)
update_desc()
/obj/item/toy/plush/proc/plop(obj/item/toy/plush/Daddy)
if(partner != Daddy)
return //we do not have bastards in our toyshop
if(prob(50)) //it has my eyes
plush_child = new type(get_turf(loc))
else //it has your eyes
plush_child = new Daddy.type(get_turf(loc))
plush_child.make_young(src, Daddy)
/obj/item/toy/plush/proc/make_young(obj/item/toy/plush/Mama, obj/item/toy/plush/Dada)
if(Mama == Dada)
return //cloning is reserved for plants and spacemen
maternal_parent = Mama
paternal_parent = Dada
young = TRUE
name = "[Mama] Jr" //Icelandic naming convention pending
normal_desc = "[src] is a little baby of [maternal_parent] and [paternal_parent]!" //original desc won't be used so the child can have moods
update_desc()
Mama.mood_message = pick(Mama.parent_message)
Mama.update_desc()
Dada.mood_message = pick(Dada.parent_message)
Dada.update_desc()
/obj/item/toy/plush/proc/bad_news(obj/item/toy/plush/Deceased) //cotton to cotton, sawdust to sawdust
var/is_that_letter_for_me = FALSE
if(partner == Deceased) //covers marriage
is_that_letter_for_me = TRUE
partner = null
lover = null
else if(lover == Deceased) //covers lovers
is_that_letter_for_me = TRUE
lover = null
//covers children
if(maternal_parent == Deceased)
is_that_letter_for_me = TRUE
maternal_parent = null
if(paternal_parent == Deceased)
is_that_letter_for_me = TRUE
paternal_parent = null
//covers parents
if(plush_child == Deceased)
is_that_letter_for_me = TRUE
plush_child = null
//covers bad memories
if(Deceased in scorned)
scorned.Remove(Deceased)
cheer_up() //what cold button eyes you have
if(Deceased in scorned_by)
scorned_by.Remove(Deceased)
//all references to the departed should be cleaned up by now
if(is_that_letter_for_me)
heartbroken = TRUE
mood_message = pick(heartbroken_message)
update_desc()
/obj/item/toy/plush/proc/cheer_up() //it'll be all right
if(!heartbroken)
return //you cannot make smile what is already
if(vowbroken)
return //it's a pretty big deal
heartbroken = !heartbroken
if(mood_message in heartbroken_message)
mood_message = null
update_desc()
/obj/item/toy/plush/proc/heal_memories() //time fixes all wounds
if(!vowbroken)
vowbroken = !vowbroken
if(mood_message in vowbroken_message)
mood_message = null
cheer_up()
/obj/item/toy/plush/proc/update_desc()
desc = normal_desc
if(mood_message)
desc += mood_message
/obj/item/toy/plush/carpplushie
name = "space carp plushie"
desc = "An adorable stuffed toy that resembles a space carp."
@@ -88,6 +379,7 @@
desc = "An adorable plushie of the clockwork justiciar himself with new and improved spring arm action."
icon_state = "plushvar"
var/obj/item/toy/plush/narplush/clash_target
gender = MALE //he's a boy, right?
/obj/item/toy/plush/plushvar/Moved()
. = ..()
@@ -173,6 +465,7 @@
desc = "A small stuffed doll of the elder god nar'sie. Who thought this was a good children's toy?"
icon_state = "narplush"
var/clashing
gender = FEMALE //it's canon if the toy is
/obj/item/toy/plush/narplush/Moved()
. = ..()
@@ -198,7 +491,7 @@
/obj/item/toy/plush/nukeplushie
name = "operative plushie"
desc = "An stuffed toy that resembles a syndicate nuclear operative. The tag claims operatives to be purely fictitious."
desc = "A stuffed toy that resembles a syndicate nuclear operative. The tag claims operatives to be purely fictitious."
icon_state = "plushie_nuke"
item_state = "plushie_nuke"
attack_verb = list("shot", "nuked", "detonated")
@@ -210,4 +503,5 @@
icon_state = "plushie_slime"
item_state = "plushie_slime"
attack_verb = list("blorbled", "slimed", "absorbed")
squeak_override = list('sound/effects/blobattack.ogg' = 1)
squeak_override = list('sound/effects/blobattack.ogg' = 1)
gender = FEMALE //given all the jokes and drawings, I'm not sure the xenobiologists would make a slimeboy

View File

@@ -40,14 +40,14 @@
icon_state = "pod_g"
/obj/structure/showcase/machinery/oldpod
name = "damaged cyrogenic pod"
desc = "A damaged cyrogenic pod long since lost to time, including its former occupant..."
name = "damaged cryogenic pod"
desc = "A damaged cryogenic pod long since lost to time, including its former occupant..."
icon = 'icons/obj/cryogenic2.dmi'
icon_state = "sleeper-open"
/obj/structure/showcase/machinery/oldpod/used
name = "opened cyrogenic pod"
desc = "Cyrogenic pod that has recently discharged its occupand. The pod appears non-functional."
name = "opened cryogenic pod"
desc = "A cryogenic pod that has recently discharged its occupant. The pod appears non-functional."
/obj/structure/showcase/cyborg/old
name = "Cyborg Statue"

View File

@@ -177,8 +177,8 @@
else
return ..()
/obj/structure/statue/plasma/proc/PlasmaBurn()
atmos_spawn_air("plasma=400;TEMP=1000")
/obj/structure/statue/plasma/proc/PlasmaBurn(exposed_temperature)
atmos_spawn_air("plasma=[oreAmount*10];TEMP=[exposed_temperature]")
deconstruct(FALSE)
/obj/structure/statue/plasma/proc/ignite(exposed_temperature)

View File

@@ -1,4 +1,4 @@
/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, frequency = null, channel = 0, pressure_affected = TRUE)
/proc/playsound(atom/source, soundin, vol as num, vary, extrarange as num, falloff, frequency = null, channel = 0, pressure_affected = TRUE, ignore_walls = TRUE)
if(isarea(source))
throw EXCEPTION("playsound(): source is an area")
return
@@ -11,7 +11,10 @@
// Looping through the player list has the added bonus of working for mobs inside containers
var/sound/S = sound(get_sfx(soundin))
var/maxdistance = (world.view + extrarange) * 3
for(var/P in GLOB.player_list)
var/list/listeners = GLOB.player_list
if(!ignore_walls) //these sounds don't carry through walls
listeners = listeners & hearers(maxdistance,turf_source)
for(var/P in listeners)
var/mob/M = P
if(!M || !M.client)
continue

View File

@@ -214,7 +214,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(heard_by_no_admins && usr && usr.ckey != initiator_ckey)
heard_by_no_admins = FALSE
send2irc(initiator_ckey, "Ticket #[id]: Answered by [key_name(usr)]")
_interactions += "[gameTimestamp()]: [formatted_message]"
_interactions += "[time_stamp()]: [formatted_message]"
//Removes the ahelp verb and returns it after 2 minutes
/datum/admin_help/proc/TimeoutVerb()

View File

@@ -196,10 +196,6 @@
for(var/I in assembly_components)
var/obj/item/integrated_circuit/IC = I
IC.external_examine(user)
if(istype(IC, /obj/item/integrated_circuit/output/screen))
var/obj/item/integrated_circuit/output/screen/S
if(S.stuff_to_display)
to_chat(user, "There's a little screen labeled '[S]', which displays '[S.stuff_to_display]'.")
if(opened)
interact(user)

View File

@@ -6,8 +6,8 @@
desc = "This somewhat complicated system allows one to slot in a gun, direct it towards a position, and remotely fire it."
extended_desc = "The firing mechanism can slot in any energy weapon. \
The first and second inputs need to be numbers. They are coordinates for the gun to fire at, relative to the machine itself. \
The 'fire' activator will cause the mechanism to attempt to fire the weapon at the coordinates, if possible. Mode is switch between\
letal(TRUE) or stun(FALSE) modes.It uses internal battery of weapon."
The 'fire' activator will cause the mechanism to attempt to fire the weapon at the coordinates, if possible. Mode is switch between \
lethal (TRUE) or stun (FALSE) modes.It uses internal battery of weapon."
complexity = 20
w_class = WEIGHT_CLASS_SMALL
size = 3
@@ -302,15 +302,15 @@
var/max_items = 10
/obj/item/integrated_circuit/manipulation/grabber/do_work()
var/turf/T = get_turf(src)
var/atom/movable/acting_object = get_object()
var/turf/T = get_turf(acting_object)
var/obj/item/AM = get_pin_data_as_type(IC_INPUT, 1, /obj/item)
if(AM)
var/turf/P = get_turf(AM)
var/mode = get_pin_data(IC_INPUT, 2)
if(mode == 1)
if(P.Adjacent(T))
if((contents.len < max_items) && AM && (AM.w_class <= max_w_class))
if(AM.Adjacent(acting_object) && isturf(AM.loc))
if((contents.len < max_items) && (!max_w_class || AM.w_class <= max_w_class))
AM.forceMove(src)
if(mode == 0)
if(contents.len)
@@ -372,11 +372,14 @@
var/target_y_rel = round(get_pin_data(IC_INPUT, 2))
var/obj/item/A = get_pin_data_as_type(IC_INPUT, 3, /obj/item)
if(!A || A.anchored || (A.w_class > max_w_class))
if(!A || A.anchored || A.throwing)
return
if(max_w_class && (A.w_class > max_w_class))
return
var/atom/movable/acting_object = get_object()
if(!A.Adjacent(acting_object) && !(A in acting_object.GetAllContents()))
if(!(A.Adjacent(acting_object) && isturf(A.loc)) && !(A in acting_object.GetAllContents()))
return
var/turf/T = get_turf(acting_object)

View File

@@ -17,7 +17,11 @@
stuff_to_display = null
/obj/item/integrated_circuit/output/screen/any_examine(mob/user)
to_chat(user, "There is a little screen labeled '[name]', which displays [!isnull(stuff_to_display) ? "'[stuff_to_display]'" : "nothing"].")
var/shown_label = ""
if(displayed_name && displayed_name != name)
shown_label = " labeled '[displayed_name]'"
to_chat(user, "There is \a [src][shown_label], which displays [!isnull(stuff_to_display) ? "'[stuff_to_display]'" : "nothing"].")
/obj/item/integrated_circuit/output/screen/do_work()
var/datum/integrated_io/I = inputs[1]

View File

@@ -21,7 +21,7 @@
return ITALICS | REDUCE_RANGE
/mob/living/brain/lingcheck()
return 0
return LINGHIVE_NONE
/mob/living/brain/treat_message(message)
message = capitalize(message)

View File

@@ -453,9 +453,9 @@ GLOBAL_LIST_EMPTY(roundstart_races)
var/obj/item/bodypart/head/HD = H.get_bodypart("head")
if(!(H.disabilities & HUSK))
if(HD && !(H.disabilities & HUSK))
// lipstick
if(H.lip_style && (LIPS in species_traits) && HD)
if(H.lip_style && (LIPS in species_traits))
var/mutable_appearance/lip_overlay = mutable_appearance('icons/mob/human_face.dmi', "lips_[H.lip_style]", -BODY_LAYER)
lip_overlay.color = H.lip_color
if(OFFSET_FACE in H.dna.species.offset_features)
@@ -464,13 +464,18 @@ GLOBAL_LIST_EMPTY(roundstart_races)
standing += lip_overlay
// eyes
if((EYECOLOR in species_traits) && HD)
var/mutable_appearance/eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER)
var/has_eyes = H.getorganslot(ORGAN_SLOT_EYES)
var/mutable_appearance/eye_overlay
if(!has_eyes)
eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes_missing", -BODY_LAYER)
else
eye_overlay = mutable_appearance('icons/mob/human_face.dmi', "eyes", -BODY_LAYER)
if((EYECOLOR in species_traits) && has_eyes)
eye_overlay.color = "#" + H.eye_color
if(OFFSET_FACE in H.dna.species.offset_features)
eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
standing += eye_overlay
if(OFFSET_FACE in H.dna.species.offset_features)
eye_overlay.pixel_x += H.dna.species.offset_features[OFFSET_FACE][1]
eye_overlay.pixel_y += H.dna.species.offset_features[OFFSET_FACE][2]
standing += eye_overlay
//Underwear, Undershirts & Socks
if(!(NO_UNDERWEAR in species_traits))

View File

@@ -1022,4 +1022,15 @@
/mob/living/proc/add_abilities_to_panel()
for(var/obj/effect/proc_holder/A in abilities)
statpanel("[A.panel]",A.get_panel_text(),A)
statpanel("[A.panel]",A.get_panel_text(),A)
/mob/living/lingcheck()
if(mind)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling)
if(changeling.changeling_speak)
return LINGHIVE_LING
return LINGHIVE_OUTSIDER
if(mind && mind.linglink)
return LINGHIVE_LINK
return LINGHIVE_NONE

View File

@@ -72,6 +72,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
/mob/living/say(message, bubble_type,var/list/spans = list(), sanitize = TRUE, datum/language/language = null, ignore_spam = FALSE)
var/static/list/crit_allowed_modes = list(MODE_WHISPER = TRUE, MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
var/static/list/unconscious_allowed_modes = list(MODE_CHANGELING = TRUE, MODE_ALIEN = TRUE)
var/key = get_key(message)
var/static/list/one_character_prefix = list(MODE_HEADSET = TRUE, MODE_ROBOT = TRUE, MODE_WHISPER = TRUE)
@@ -134,8 +135,11 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
// AIs use inherent channels for the holopad. Most inherent channels
// ignore the language argument however.
if(handle_inherent_channels(message, message_mode, language)) //Hiveminds, binary chat & holopad.
return
var/datum/saymode/SM = SSradio.saymodes[key]
if(key && SM)
if(!SM.handle_message(src, message, language))
return
if(!can_speak_vocal(message))
to_chat(src, "<span class='warning'>You find yourself unable to speak!</span>")
@@ -264,7 +268,7 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
INVOKE_ASYNC(GLOBAL_PROC, /.proc/flick_overlay, I, speech_bubble_recipients, 30)
/mob/proc/binarycheck()
return 0
return FALSE
/mob/living/can_speak(message) //For use outside of Say()
if(can_speak_basic(message) && can_speak_vocal(message))
@@ -307,6 +311,11 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
var/key_symbol = lowertext(copytext(message, 2, 3))
return GLOB.department_radio_keys[key_symbol]
/mob/living/proc/get_key(message)
var/key = copytext(message, 1, 2)
if(key in GLOB.department_radio_prefixes)
return lowertext(copytext(message, 2, 3))
/mob/living/proc/get_message_language(message)
if(copytext(message, 1, 2) == ",")
var/key = copytext(message, 2, 3)
@@ -316,60 +325,6 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return LD
return null
/mob/living/proc/handle_inherent_channels(message, message_mode)
if(message_mode == MODE_CHANGELING)
switch(lingcheck())
if(3)
var/msg = "<i><font color=#800040><b>[src.mind]:</b> [message]</font></i>"
for(var/_M in GLOB.mob_list)
var/mob/M = _M
if(M in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [msg]")
else
switch(M.lingcheck())
if(3)
to_chat(M, msg)
if(2)
to_chat(M, msg)
if(1)
if(prob(40))
to_chat(M, "<i><font color=#800080>We can faintly sense an outsider trying to communicate through the hivemind...</font></i>")
if(2)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
var/msg = "<i><font color=#800080><b>[changeling.changelingID]:</b> [message]</font></i>"
log_talk(src,"[changeling.changelingID]/[key] : [message]",LOGSAY)
for(var/_M in GLOB.mob_list)
var/mob/M = _M
if(M in GLOB.dead_mob_list)
var/link = FOLLOW_LINK(M, src)
to_chat(M, "[link] [msg]")
else
switch(M.lingcheck())
if(3)
to_chat(M, msg)
if(2)
to_chat(M, msg)
if(1)
if(prob(40))
to_chat(M, "<i><font color=#800080>We can faintly sense another of our kind trying to communicate through the hivemind...</font></i>")
if(1)
to_chat(src, "<i><font color=#800080>Our senses have not evolved enough to be able to communicate this way...</font></i>")
return TRUE
if(message_mode == MODE_ALIEN)
if(hivecheck())
alien_talk(message)
return TRUE
if(message_mode == MODE_VOCALCORDS)
if(iscarbon(src))
var/mob/living/carbon/C = src
var/obj/item/organ/vocal_cords/V = C.getorganslot(ORGAN_SLOT_VOICE)
if(V && V.can_speak_with())
V.handle_speech(message) //message
V.speak_with(message) //action
return TRUE
return FALSE
/mob/living/proc/treat_message(message)
if(getBrainLoss() >= 60)
message = derpspeech(message, stuttering)
@@ -408,22 +363,9 @@ GLOBAL_LIST_INIT(department_radio_keys, list(
return ITALICS | REDUCE_RANGE
if(MODE_BINARY)
if(binarycheck())
robot_talk(message)
return ITALICS | REDUCE_RANGE //Does not return 0 since this is only reached by humans, not borgs or AIs.
return 0
/mob/living/lingcheck() //1 is ling w/ no hivemind. 2 is ling w/hivemind. 3 is ling victim being linked into hivemind.
if(mind)
var/datum/antagonist/changeling/changeling = mind.has_antag_datum(/datum/antagonist/changeling)
if(changeling)
if(changeling.changeling_speak)
return 2
return 1
if(mind && mind.linglink)
return 3
return 0
/mob/living/say_mod(input, message_mode)
if(message_mode == MODE_WHISPER)
. = verb_whisper

View File

@@ -31,15 +31,6 @@
else
return ..()
/mob/living/silicon/ai/handle_inherent_channels(message, message_mode, language)
. = ..()
if(.)
return .
if(message_mode == MODE_HOLOPAD)
holopad_talk(message, language)
return 1
//For holopads only. Usable by AI.
/mob/living/silicon/ai/proc/holopad_talk(message, language)

View File

@@ -57,14 +57,3 @@
return MODE_ROBOT
else
return .
/mob/living/silicon/handle_inherent_channels(message, message_mode)
. = ..()
if(.)
return .
if(message_mode == MODE_BINARY)
if(binarycheck())
robot_talk(message)
return 1
return 0

View File

@@ -3,14 +3,6 @@
/////////////
//Drone speach
/mob/living/simple_animal/drone/handle_inherent_channels(message, message_mode)
if(message_mode == MODE_BINARY)
drone_chat(message)
return 1
else
..()
/mob/living/simple_animal/drone/get_spans()
return ..() | SPAN_ROBOT

View File

@@ -1,83 +1,82 @@
//Speech verbs.
/mob/verb/say_verb(message as text)
set name = "Say"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
usr.say(message)
/mob/verb/whisper_verb(message as text)
set name = "Whisper"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
whisper(message)
/mob/proc/whisper(message, datum/language/language=null)
say(message, language) //only living mobs actually whisper, everything else just talks
/mob/verb/me_verb(message as message)
set name = "Me"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
var/list/replace_chars = list("\n"=" ","\t"=" ")
message = copytext(sanitize(message, replace_chars), 1, (MAX_MESSAGE_LEN*2))
usr.emote("me",1,message)
/mob/proc/say_dead(var/message)
var/name = real_name
var/alt_name = ""
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
if(jobban_isbanned(src, "OOC"))
to_chat(src, "<span class='danger'>You have been banned from deadchat.</span>")
return
if (src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<span class='danger'>You cannot talk in deadchat (muted).</span>")
return
if(src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
return
var/mob/dead/observer/O = src
if(isobserver(src) && O.deadchat_name)
name = "[O.deadchat_name]"
else
if(mind && mind.name)
name = "[mind.name]"
else
name = real_name
if(name != real_name)
alt_name = " (died as [real_name])"
var/K
if(key)
K = src.key
message = src.say_quote(message, get_spans())
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[name]</span>[alt_name] <span class='message'>[message]</span></span>"
deadchat_broadcast(rendered, follow_target = src, speaker_key = K)
/mob/proc/emote(var/act)
return
/mob/proc/hivecheck()
return 0
/mob/proc/lingcheck()
return 0
//Speech verbs.
/mob/verb/say_verb(message as text)
set name = "Say"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
usr.say(message)
/mob/verb/whisper_verb(message as text)
set name = "Whisper"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
whisper(message)
/mob/proc/whisper(message, datum/language/language=null)
say(message, language) //only living mobs actually whisper, everything else just talks
/mob/verb/me_verb(message as text)
set name = "Me"
set category = "IC"
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
message = trim(copytext(sanitize(message), 1, MAX_MESSAGE_LEN))
usr.emote("me",1,message)
/mob/proc/say_dead(var/message)
var/name = real_name
var/alt_name = ""
if(GLOB.say_disabled) //This is here to try to identify lag problems
to_chat(usr, "<span class='danger'>Speech is currently admin-disabled.</span>")
return
if(jobban_isbanned(src, "OOC"))
to_chat(src, "<span class='danger'>You have been banned from deadchat.</span>")
return
if (src.client)
if(src.client.prefs.muted & MUTE_DEADCHAT)
to_chat(src, "<span class='danger'>You cannot talk in deadchat (muted).</span>")
return
if(src.client.handle_spam_prevention(message,MUTE_DEADCHAT))
return
var/mob/dead/observer/O = src
if(isobserver(src) && O.deadchat_name)
name = "[O.deadchat_name]"
else
if(mind && mind.name)
name = "[mind.name]"
else
name = real_name
if(name != real_name)
alt_name = " (died as [real_name])"
var/K
if(key)
K = src.key
message = src.say_quote(message, get_spans())
var/rendered = "<span class='game deadsay'><span class='prefix'>DEAD:</span> <span class='name'>[name]</span>[alt_name] <span class='message'>[message]</span></span>"
deadchat_broadcast(rendered, follow_target = src, speaker_key = K)
/mob/proc/emote(var/act)
return
/mob/proc/hivecheck()
return 0
/mob/proc/lingcheck()
return LINGHIVE_NONE

View File

@@ -344,10 +344,10 @@
/obj/machinery/computer/turbine_computer/ui_data(mob/user)
var/list/data = list()
data["working"] = (compressor.starter && compressor && compressor.turbine && !compressor.stat && !compressor.turbine.stat)
data["connected"] = (compressor && compressor.turbine) ? TRUE : FALSE
data["compressor_broke"] = (!compressor || compressor.stat) ? TRUE : FALSE
data["turbine_broke"] = (!compressor || compressor.turbine.stat) ? TRUE : FALSE
data["compressor_broke"] = (!compressor || (compressor.stat & BROKEN)) ? TRUE : FALSE
data["turbine_broke"] = (!compressor || !compressor.turbine || (compressor.turbine.stat & BROKEN)) ? TRUE : FALSE
data["broken"] = (data["compressor_broke"] || data["turbine_broke"])
data["online"] = compressor.starter
data["power"] = DisplayPower(compressor.turbine.lastgen)
@@ -360,9 +360,13 @@
if(..())
return
switch(action)
if("power")
if("power-on")
if(compressor && compressor.turbine)
compressor.starter = !compressor.starter
compressor.starter = TRUE
. = TRUE
if("power-off")
if(compressor && compressor.turbine)
compressor.starter = FALSE
. = TRUE
if("reconnect")
locate_machinery()

View File

@@ -807,3 +807,11 @@
materials = list(MAT_GLASS = 20)
build_path = /obj/item/stock_parts/cell/emergency_light
category = list("initial", "Electronics")
/datum/design/holodisk
name = "Holodisk"
id = "holodisk"
build_type = AUTOLATHE
materials = list(MAT_METAL = 1000)
build_path = /obj/item/disk/holodisk
category = list("initial", "Misc")

View File

@@ -0,0 +1,4 @@
author: "psykzz"
delete-after: True
changes:
- bugfix: "Fixing the broken turbine computer"

View File

@@ -0,0 +1,4 @@
author: "CosmicScientist"
delete-after: True
changes:
- rscadd: "You can make plushies kiss one another!"

View File

@@ -0,0 +1,5 @@
author: "BeeSting12"
delete-after: True
changes:
- spellcheck: "Occupand ---> Occupant on opened cryogenic pods."
- spellcheck: "Cyrogenic ---> Cryogenic on opened cryogenic pods."

View File

@@ -0,0 +1,4 @@
author: "zennerx"
delete-after: True
changes:
- spellcheck: "fixed some typos in the weapon firing mechanism description"

View File

@@ -0,0 +1,4 @@
author: "CitadelStationBot"
delete-after: True
changes:
- bugfix: "You can now lay (buckle!) yourself to a bed to avoid being burnt to a crisp during \"the floor is lava\" event."

View File

@@ -0,0 +1,4 @@
author: "Robustin"
delete-after: True
changes:
- tweak: "Igniting plasma statues no longer ignores ignition temperature and only creates as much plasma as was used in its creation."

View File

@@ -0,0 +1,4 @@
author: "Xhuis"
delete-after: True
changes:
- bugfix: "You now need fuel in your welder to repair mechs."

View File

@@ -0,0 +1,5 @@
author: "CitadelStationBot"
delete-after: True
changes:
- rscadd: "You can now record and replay holopad messages using holodisks."
- rscadd: "Holodisks are printable in autolathes."

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -308,6 +308,7 @@
#include "code\datums\recipe.dm"
#include "code\datums\riding.dm"
#include "code\datums\ruins.dm"
#include "code\datums\saymode.dm"
#include "code\datums\shuttles.dm"
#include "code\datums\soullink.dm"
#include "code\datums\spawners_menu.dm"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -13,20 +13,20 @@ component.exports = {
<ui-notice>
<ui-section label='Reconnect'>
<div style='float:right'>
<ui-button icon='refresh' action='reconnect' state='{{data.connected}}'>Reconnect</ui-button>
<ui-button icon='refresh' action='reconnect'>Reconnect</ui-button>
</div>
</ui-section>
</ui-notice>
<ui-display title='Turbine Controller'>
<ui-section label='Status'>
{{#if data.working}}
<span class='{{powerState(data.online)}}'>{{data.online && !(data.compressor_broke || data.turbine_broke) ? "Online" : "Offline"}}</span>
{{else}}
{{#if data.broken}}
<span class='bad'>Broken</span>
{{else}}
<span class='{{powerState(data.online)}}'>{{data.online && !(data.compressor_broke || data.turbine_broke) ? "Online" : "Offline"}}</span>
{{/if}}
<div style='float:right'>
<ui-button icon='power-off' action='power' state='{{data.working}}' style='{{data.online ? "selected" : ""}}'>On</ui-button>
<ui-button icon='close' action='power' state='{{data.working}}' style='{{data.online ? "" : "selected"}}'>Off</ui-button>
<ui-button icon='power-off' action='power-on' state='{{data.broken}}' style='{{data.online ? "selected" : ""}}'>On</ui-button>
<ui-button icon='close' action='power-off' state='{{data.broken}}' style='{{data.online ? "" : "selected"}}'>Off</ui-button>
</div>
{{#if data.compressor_broke}}
<br>
@@ -40,12 +40,12 @@ component.exports = {
</ui-display>
<ui-display title='Status'>
<ui-section label='Turbine Speed'>
<span>{{data.working ? data.rpm : "--"}} RPM</span>
<span>{{data.broken ? "--" : data.rpm}} RPM</span>
</ui-section>
<ui-section label='Internal Temp'>
<span>{{data.working ? data.temp : "--"}} K</span>
<span>{{data.broken ? "--" : data.temp}} K</span>
</ui-section>
<ui-section label='Generated Power'>
<span>{{data.working ? data.power : "--"}}</span>
<span>{{data.broken ? "--" : data.power}}</span>
</ui-section>
</ui-display>