diff --git a/code/__DEFINES/components.dm b/code/__DEFINES/components.dm
index bf30b547fe..b79f1c2e59 100644
--- a/code/__DEFINES/components.dm
+++ b/code/__DEFINES/components.dm
@@ -121,7 +121,15 @@
#define COMPONENT_CANCEL_THROW 1
#define COMSIG_MOVABLE_POST_THROW "movable_post_throw" //from base of atom/movable/throw_at(): (datum/thrownthing, spin)
#define COMSIG_MOVABLE_Z_CHANGED "movable_ztransit" //from base of atom/movable/onTransitZ(): (old_z, new_z)
+#define COMSIG_MOVABLE_SECLUDED_LOCATION "movable_secluded" //called when the movable is placed in an unaccessible area, used for stationloving: ()
#define COMSIG_MOVABLE_HEAR "movable_hear" //from base of atom/movable/Hear(): (message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
+ #define HEARING_MESSAGE 1
+ #define HEARING_SPEAKER 2
+// #define HEARING_LANGUAGE 3
+ #define HEARING_RAW_MESSAGE 4
+ /* #define HEARING_RADIO_FREQ 5
+ #define HEARING_SPANS 6
+ #define HEARING_MESSAGE_MODE 7 */
#define COMSIG_MOVABLE_DISPOSING "movable_disposing" //called when the movable is added to a disposal holder object for disposal movement: (obj/structure/disposalholder/holder, obj/machinery/disposal/source)
#define COMSIG_MOVABLE_TELEPORTED "movable_teleported" //from base of do_teleport(): (channel, turf/origin, turf/destination)
diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm
index 632e4adef9..f5ea8d835f 100644
--- a/code/__DEFINES/inventory.dm
+++ b/code/__DEFINES/inventory.dm
@@ -4,9 +4,9 @@
#define WEIGHT_CLASS_TINY 1 //Usually items smaller then a human hand, ex: Playing Cards, Lighter, Scalpel, Coins/Money
#define WEIGHT_CLASS_SMALL 2 //Pockets can hold small and tiny items, ex: Flashlight, Multitool, Grenades, GPS Device
#define WEIGHT_CLASS_NORMAL 3 //Standard backpacks can carry tiny, small & normal items, ex: Fire extinguisher, Stunbaton, Gas Mask, Metal Sheets
-#define WEIGHT_CLASS_BULKY 4 //Items that can be weilded or equipped but not stored in an inventory, ex: Defibrillator, Backpack, Space Suits
-#define WEIGHT_CLASS_HUGE 5 //Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons
-#define WEIGHT_CLASS_GIGANTIC 6 //Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe
+#define WEIGHT_CLASS_BULKY 4 //Items that can be weilded or equipped but not stored in a normal bag, ex: Defibrillator, Backpack, Space Suits
+#define WEIGHT_CLASS_HUGE 5 //Usually represents objects that require two hands to operate, ex: Shotgun, Two Handed Melee Weapons - Can not fit in Boh
+#define WEIGHT_CLASS_GIGANTIC 6 //Essentially means it cannot be picked up or placed in an inventory, ex: Mech Parts, Safe - Can not fit in Boh
//Inventory depth: limits how many nested storage items you can access directly.
//1: stuff in mob, 2: stuff in backpack, 3: stuff in box in backpack, etc
diff --git a/code/__DEFINES/machines.dm b/code/__DEFINES/machines.dm
index 1ce5b88945..db13c21c44 100644
--- a/code/__DEFINES/machines.dm
+++ b/code/__DEFINES/machines.dm
@@ -100,3 +100,8 @@
#define NUKE_OFF_UNLOCKED 1
#define NUKE_ON_TIMING 2
#define NUKE_ON_EXPLODING 3
+
+
+//these flags are used to tell the DNA modifier if a plant gene cannot be extracted or modified.
+#define PLANT_GENE_REMOVABLE (1<<0)
+#define PLANT_GENE_EXTRACTABLE (1<<1)
\ No newline at end of file
diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm
index ff19976cff..0f1a36d663 100644
--- a/code/__DEFINES/status_effects.dm
+++ b/code/__DEFINES/status_effects.dm
@@ -7,6 +7,8 @@
#define STATUS_EFFECT_REPLACE 2 //if it allows only one, but new instances replace
+#define STATUS_EFFECT_REFRESH 3 // if it only allows one, and new instances just instead refresh the timer
+
///////////
// BUFFS //
///////////
@@ -74,6 +76,8 @@
#define STATUS_EFFECT_ICHORIAL_STAIN /datum/status_effect/ichorial_stain //Prevents a servant from being revived by vitality matrices for one minute.
+#define STATUS_EFFECT_SPASMS /datum/status_effect/spasms //causes random muscle spasms
+
#define STATUS_EFFECT_BREASTS_ENLARGEMENT /datum/status_effect/chem/breast_enlarger //Applied slowdown due to the ominous bulk.
#define STATUS_EFFECT_PENIS_ENLARGEMENT /datum/status_effect/chem/penis_enlarger //More applied slowdown, just like the above.
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 2382e0e444..60212385f8 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -109,6 +109,7 @@
#define TRAIT_NOHARDCRIT "nohardcrit"
#define TRAIT_NOSOFTCRIT "nosoftcrit"
#define TRAIT_MINDSHIELD "mindshield"
+#define TRAIT_SIXTHSENSE "sixthsense"
#define TRAIT_DISSECTED "dissected"
#define TRAIT_FEARLESS "fearless"
#define TRAIT_UNSTABLE "unstable"
@@ -117,6 +118,7 @@
#define TRAIT_PARALYSIS_L_LEG "para-l-leg"
#define TRAIT_PARALYSIS_R_LEG "para-r-leg"
#define TRAIT_UNINTELLIGIBLE_SPEECH "unintelligible-speech"
+#define TRAIT_SOOTHED_THROAT "soothed-throat"
#define TRAIT_LAW_ENFORCEMENT_METABOLISM "law-enforcement-metabolism"
#define TRAIT_STRONG_GRABBER "strong_grabber"
#define TRAIT_CALCIUM_HEALER "calcium_healer"
@@ -179,6 +181,7 @@
#define CULT_TRAIT "cult"
#define CURSED_ITEM_TRAIT "cursed-item" // The item is magically cursed
#define ABSTRACT_ITEM_TRAIT "abstract-item"
+#define STATUS_EFFECT_TRAIT "status-effect"
#define ROUNDSTART_TRAIT "roundstart" //cannot be removed without admin intervention
// unique trait sources, still defines
@@ -213,4 +216,4 @@
#define NINJA_SUIT_TRAIT "ninja-suit"
#define ANTI_DROP_IMPLANT_TRAIT "anti-drop-implant"
#define ABDUCTOR_ANTAGONIST "abductor-antagonist"
-#define MADE_UNCLONEABLE "made-uncloneable"
+#define MADE_UNCLONEABLE "made-uncloneable"
\ No newline at end of file
diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm
index 8e7938a312..0d6345dae2 100644
--- a/code/__HELPERS/mobs.dm
+++ b/code/__HELPERS/mobs.dm
@@ -522,12 +522,14 @@ GLOBAL_LIST_EMPTY(species_list)
else
prefs = new
- var/adminoverride = 0
+ var/override = FALSE
if(M.client && M.client.holder && (prefs.chat_toggles & CHAT_DEAD))
- adminoverride = 1
- if(isnewplayer(M) && !adminoverride)
+ override = TRUE
+ if(HAS_TRAIT(M, TRAIT_SIXTHSENSE))
+ override = TRUE
+ if(isnewplayer(M) && !override)
continue
- if(M.stat != DEAD && !adminoverride)
+ if(M.stat != DEAD && !override)
continue
if(speaker_key && speaker_key in prefs.ignoring)
continue
diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm
index 0ac8a61183..e2705ad49f 100644
--- a/code/_globalvars/lists/flavor_misc.dm
+++ b/code/_globalvars/lists/flavor_misc.dm
@@ -46,10 +46,15 @@ GLOBAL_LIST_INIT(ai_core_display_screens, list(
":thinking:",
"Alien",
"Angel",
+ "Angryface",
+ "AtlantisCZE",
"Banned",
"Bliss",
"Blue",
- "Clown",
+ "Boy",
+ "Boy-Malf",
+ "Girl",
+ "Girl-Malf",
"Database",
"Dorf",
"Firewall",
@@ -61,26 +66,44 @@ GLOBAL_LIST_INIT(ai_core_display_screens, list(
"Hades",
"Heartline",
"Helios",
+ "Hotdog",
+ "Hourglass",
"House",
"Inverted",
+ "Jack",
"Matrix",
"Monochrome",
+ "Mothman",
"Murica",
"Nanotrasen",
"Not Malf",
+ "Patriot",
+ "Pirate",
"President",
- "Random",
"Rainbow",
- "Red",
+ "Clown",
+ "Random",
+ "Ravensdale",
"Red October",
+ "Red",
+ "Royal",
+ "Searif",
+ "Serithi",
+ "SilveryFerret",
+ "Smiley",
"Static",
"Syndicat Meow",
"TechDemon",
+ "Terminal",
"Text",
"Too Deep",
"Triumvirate",
"Triumvirate-M",
- "Weird"))
+ "Wasp",
+ "Weird",
+ "Xerxes",
+ "Yes-Man"
+ ))
/proc/resolve_ai_icon(input)
if(!input || !(input in GLOB.ai_core_display_screens))
diff --git a/code/_globalvars/lists/poll_ignore.dm b/code/_globalvars/lists/poll_ignore.dm
index 3a026d2aa5..e30ce1d1ed 100644
--- a/code/_globalvars/lists/poll_ignore.dm
+++ b/code/_globalvars/lists/poll_ignore.dm
@@ -13,6 +13,8 @@
#define POLL_IGNORE_GOLEM "golem"
#define POLL_IGNORE_SWARMER "swarmer"
#define POLL_IGNORE_DRONE "drone"
+#define POLL_IGNORE_IMAGINARYFRIEND "imaginary_friend"
+#define POLL_IGNORE_SPLITPERSONALITY "split_personality"
#define POLL_IGNORE_DEMON "demon"
#define POLL_IGNORE_WIZARD "wizard"
#define POLL_IGNORE_CLONE "clone"
@@ -31,6 +33,8 @@ GLOBAL_LIST_INIT(poll_ignore_desc, list(
POLL_IGNORE_GOLEM = "Golems",
POLL_IGNORE_SWARMER = "Swarmer shells",
POLL_IGNORE_DRONE = "Drone shells",
+ POLL_IGNORE_IMAGINARYFRIEND = "Imaginary Friend",
+ POLL_IGNORE_SPLITPERSONALITY = "Split Personality",
POLL_IGNORE_DEMON = "Demons",
POLL_IGNORE_WIZARD = "Wizards",
POLL_IGNORE_CLONE = "Defective/SDGF clones"
diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm
index cc183dd6d3..391e86f390 100644
--- a/code/_onclick/hud/alert.dm
+++ b/code/_onclick/hud/alert.dm
@@ -213,6 +213,12 @@ or something covering your eyes."
desc = "Whoa man, you're tripping balls! Careful you don't get addicted... if you aren't already."
icon_state = "high"
+/obj/screen/alert/hypnosis
+ name = "Hypnosis"
+ desc = "Something's hypnotizing you, but you're not really sure about what."
+ icon_state = "hypnosis"
+ var/phrase
+
/obj/screen/alert/drunk //Not implemented
name = "Drunk"
desc = "All that alcohol you've been drinking is impairing your speech, motor skills, and mental cognition. Make sure to act like it."
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index f796f75407..5f128ff76d 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -25,7 +25,7 @@
return ..()
/obj/screen/examine(mob/user)
- return
+ return list()
/obj/screen/orbit()
return
diff --git a/code/_onclick/telekinesis.dm b/code/_onclick/telekinesis.dm
index 12b1ca2784..ecd34b7840 100644
--- a/code/_onclick/telekinesis.dm
+++ b/code/_onclick/telekinesis.dm
@@ -106,9 +106,8 @@
/obj/item/tk_grab/examine(user)
if (focus)
- focus.examine(user)
- else
- ..()
+ return focus.examine(user)
+ return ..()
/obj/item/tk_grab/attack_self(mob/user)
if(!focus)
diff --git a/code/controllers/subsystem/persistence.dm b/code/controllers/subsystem/persistence.dm
index 1b7cade71f..c3db8552c6 100644
--- a/code/controllers/subsystem/persistence.dm
+++ b/code/controllers/subsystem/persistence.dm
@@ -12,6 +12,7 @@ SUBSYSTEM_DEF(persistence)
var/list/obj/structure/chisel_message/chisel_messages = list()
var/list/saved_messages = list()
var/list/saved_modes = list(1,2,3)
+ var/list/saved_threat_levels = list(1,1,1)
var/list/saved_maps
var/list/saved_trophies = list()
var/list/spawned_objects = list()
@@ -27,6 +28,7 @@ SUBSYSTEM_DEF(persistence)
LoadChiselMessages()
LoadTrophies()
LoadRecentModes()
+ LoadRecentThreats()
LoadRecentMaps()
LoadPhotoPersistence()
if(CONFIG_GET(flag/use_antag_rep))
@@ -166,6 +168,15 @@ SUBSYSTEM_DEF(persistence)
return
saved_modes = json["data"]
+/datum/controller/subsystem/persistence/proc/LoadRecentThreats()
+ var/json_file = file("data/RecentThreatLevels.json")
+ if(!fexists(json_file))
+ return
+ var/list/json = json_decode(file2text(json_file))
+ if(!json)
+ return
+ saved_threat_levels = json["data"]
+
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
var/json_file = file("data/RecentMaps.json")
if(!fexists(json_file))
@@ -216,6 +227,7 @@ SUBSYSTEM_DEF(persistence)
CollectSecretSatchels()
CollectTrophies()
CollectRoundtype()
+ CollectThreatLevel()
RecordMaps()
SavePhotoPersistence() //THIS IS PERSISTENCE, NOT THE LOGGING PORTION.
if(CONFIG_GET(flag/use_antag_rep))
@@ -372,6 +384,18 @@ SUBSYSTEM_DEF(persistence)
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
+/datum/controller/subsystem/persistence/proc/CollectThreatLevel()
+ if(istype(SSticker.mode, /datum/game_mode/dynamic))
+ var/datum/game_mode/dynamic/mode = SSticker.mode
+ saved_threat_levels[3] = saved_threat_levels[2]
+ saved_threat_levels[2] = saved_threat_levels [1]
+ saved_threat_levels[1] = mode.threat_level
+ var/json_file = file("data/RecentThreatLevels.json")
+ var/list/file_data = list()
+ file_data["data"] = saved_threat_levels
+ fdel(json_file)
+ WRITE_FILE(json_file, json_encode(file_data))
+
/datum/controller/subsystem/persistence/proc/RecordMaps()
saved_maps = saved_maps?.len ? list("[SSmapping.config.map_name]") | saved_maps : list("[SSmapping.config.map_name]")
var/json_file = file("data/RecentMaps.json")
diff --git a/code/controllers/subsystem/vote.dm b/code/controllers/subsystem/vote.dm
index 50be61f91d..dee10e4998 100644
--- a/code/controllers/subsystem/vote.dm
+++ b/code/controllers/subsystem/vote.dm
@@ -153,6 +153,10 @@ SUBSYSTEM_DEF(vote)
if(SSticker.current_state > GAME_STATE_PREGAME)//Don't change the mode if the round already started.
return message_admins("A vote has tried to change the gamemode, but the game has already started. Aborting.")
GLOB.master_mode = "dynamic"
+ if("extended" in choices)
+ if(. == "extended")
+ GLOB.dynamic_forced_extended = TRUE // we still do the rest of the stuff
+ choices[PEACE] += choices["extended"]
var/mean = 0
var/voters = 0
for(var/client/c in GLOB.clients)
@@ -253,7 +257,11 @@ SUBSYSTEM_DEF(vote)
if("roundtype") //CIT CHANGE - adds the roundstart secret/extended vote
choices.Add("secret", "extended")
if("dynamic")
- choices.Add(PEACE,CHAOS)
+ var/saved_threats = SSpersistence.saved_threat_levels
+ if((saved_threats[1]+saved_threats[2]+saved_threats[3])>150)
+ choices.Add("extended",PEACE,CHAOS)
+ else
+ choices.Add(PEACE,CHAOS)
if("custom")
question = stripped_input(usr,"What is the vote for?")
if(!question)
diff --git a/code/datums/brain_damage/brain_trauma.dm b/code/datums/brain_damage/brain_trauma.dm
index 56a3f3969b..1aa1341c9c 100644
--- a/code/datums/brain_damage/brain_trauma.dm
+++ b/code/datums/brain_damage/brain_trauma.dm
@@ -1,10 +1,12 @@
//Brain Traumas are the new actual brain damage. Brain damage itself acts as a way to acquire traumas: every time brain damage is dealt, there's a chance of receiving a trauma.
//This chance gets higher the higher the mob's brainloss is. Removing traumas is a separate thing from removing brain damage: you can get restored to full brain operativity,
-//but keep the quirks, until repaired by mannitol (for mild/special ones) or brain surgery (for severe ones).
+// but keep the quirks, until repaired by neurine, surgery, lobotomy or magic; depending on the resilience
+// of the trauma.
+
/datum/brain_trauma
var/name = "Brain Trauma"
var/desc = "A trauma caused by brain damage, which causes issues to the patient."
- var/scan_desc = "a generic brain trauma" //description when detected by a health scanner
+ var/scan_desc = "generic brain trauma" //description when detected by a health scanner
var/mob/living/carbon/owner //the poor bastard
var/obj/item/organ/brain/brain //the poor bastard's brain
var/gain_text = "You feel traumatized."
@@ -12,15 +14,21 @@
var/can_gain = TRUE
var/random_gain = TRUE //can this be gained through random traumas?
var/resilience = TRAUMA_RESILIENCE_BASIC //how hard is this to cure?
+ var/clonable = TRUE // will this transfer if the brain is cloned?
/datum/brain_trauma/Destroy()
- brain.traumas -= src
+ if(brain && brain.traumas)
+ brain.traumas -= src
if(owner)
on_lose()
brain = null
owner = null
return ..()
+/datum/brain_trauma/proc/on_clone()
+ if(clonable)
+ return new type
+
//Called on life ticks
/datum/brain_trauma/proc/on_life()
return
@@ -33,17 +41,24 @@
/datum/brain_trauma/proc/on_gain()
to_chat(owner, gain_text)
RegisterSignal(owner, COMSIG_MOB_SAY, .proc/handle_speech)
+ RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/handle_hearing)
//Called when removed from a mob
/datum/brain_trauma/proc/on_lose(silent)
if(!silent)
to_chat(owner, lose_text)
UnregisterSignal(owner, COMSIG_MOB_SAY)
+ UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
//Called when hearing a spoken message
-/datum/brain_trauma/proc/on_hear(message, speaker, message_language, raw_message, radio_freq)
- return message
+/datum/brain_trauma/proc/handle_hearing(datum/source, list/hearing_args)
+ UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
//Called when speaking
/datum/brain_trauma/proc/handle_speech(datum/source, list/speech_args)
UnregisterSignal(owner, COMSIG_MOB_SAY)
+
+
+//Called when hugging. expand into generally interacting, where future coders could switch the intent?
+/datum/brain_trauma/proc/on_hug(mob/living/hugger, mob/living/hugged)
+ return
diff --git a/code/datums/brain_damage/hypnosis.dm b/code/datums/brain_damage/hypnosis.dm
index 8909d1b85f..f937c19658 100644
--- a/code/datums/brain_damage/hypnosis.dm
+++ b/code/datums/brain_damage/hypnosis.dm
@@ -5,6 +5,7 @@
gain_text = ""
lose_text = ""
resilience = TRAUMA_RESILIENCE_SURGERY
+
var/hypnotic_phrase = ""
var/regex/target_phrase
@@ -44,18 +45,17 @@
"You feel a part of your mind repeating this over and over. You need to follow these words.",\
"Something about this sounds... right, for some reason. You feel like you should follow these words.",\
"These words keep echoing in your mind. You find yourself completely fascinated by them.")]")
- if(!HAS_TRAIT(owner, "hypnotherapy"))
- to_chat(owner, "You've been hypnotized by this sentence. You must follow these words. If it isn't a clear order, you can freely interpret how to do so,\
+ to_chat(owner, "You've been hypnotized by this sentence. You must follow these words. If it isn't a clear order, you can freely interpret how to do so,\
as long as you act like the words are your highest priority.")
- else
- to_chat(owner, "You've been hypnotized by this sentence. You feel an incredible desire to follow these words, but are able to resist it somewhat. If it isn't a clear order, you can freely interpret how to do so,\
- however this does not take precedence over your other objectives.")
+ var/obj/screen/alert/hypnosis/hypno_alert = owner.throw_alert("hypnosis", /obj/screen/alert/hypnosis)
+ hypno_alert.desc = "\"[hypnotic_phrase]\"... your mind seems to be fixated on this concept."
..()
/datum/brain_trauma/hypnosis/on_lose()
message_admins("[ADMIN_LOOKUPFLW(owner)] is no longer hypnotized with the phrase '[hypnotic_phrase]'.")
log_game("[key_name(owner)] is no longer hypnotized with the phrase '[hypnotic_phrase]'.")
- to_chat(owner, "You suddenly snap out of your fixation. The phrase '[hypnotic_phrase]' no longer feels important to you.")
+ to_chat(owner, "You suddenly snap out of your hypnosis. The phrase '[hypnotic_phrase]' no longer feels important to you.")
+ owner.clear_alert("hypnosis")
..()
/datum/brain_trauma/hypnosis/on_life()
@@ -67,6 +67,5 @@
if(2)
new /datum/hallucination/chat(owner, TRUE, FALSE, "[hypnotic_phrase]")
-/datum/brain_trauma/hypnosis/on_hear(message, speaker, message_language, raw_message, radio_freq)
- message = target_phrase.Replace(message, "$1")
- return message
+/datum/brain_trauma/hypnosis/handle_hearing(datum/source, list/hearing_args)
+ hearing_args[HEARING_MESSAGE] = target_phrase.Replace(hearing_args[HEARING_MESSAGE], "$1")
diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm
index 5bbc5de4a5..8337a8e4d5 100644
--- a/code/datums/brain_damage/imaginary_friend.dm
+++ b/code/datums/brain_damage/imaginary_friend.dm
@@ -8,6 +8,10 @@
var/friend_initialized = FALSE
/datum/brain_trauma/special/imaginary_friend/on_gain()
+ var/mob/living/M = owner
+ if(M.stat == DEAD || !M.client)
+ qdel(src)
+ return
..()
make_friend()
get_ghost()
@@ -43,7 +47,7 @@
/datum/brain_trauma/special/imaginary_friend/proc/get_ghost()
set waitfor = FALSE
- var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s imaginary friend?", ROLE_PAI, null, null, 75, friend)
+ var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s imaginary friend?", ROLE_PAI, null, null, 75, friend, POLL_IGNORE_IMAGINARYFRIEND)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
C.transfer_ckey(friend, FALSE)
@@ -74,26 +78,34 @@
/mob/camera/imaginary_friend/Login()
..()
- to_chat(src, "You are the imaginary friend of [owner]!")
- to_chat(src, "You are absolutely loyal to your friend, no matter what.")
- to_chat(src, "You cannot directly influence the world around you, but you can see what [owner] cannot.")
+ greet()
Show()
+/mob/camera/imaginary_friend/proc/greet()
+ to_chat(src, "You are the imaginary friend of [owner]!")
+ to_chat(src, "You are absolutely loyal to your friend, no matter what.")
+ to_chat(src, "You cannot directly influence the world around you, but you can see what [owner] cannot.")
+
/mob/camera/imaginary_friend/Initialize(mapload, _trauma)
. = ..()
- var/gender = pick(MALE, FEMALE)
- real_name = random_unique_name(gender)
- name = real_name
+
trauma = _trauma
owner = trauma.owner
copy_known_languages_from(owner, TRUE)
- human_image = get_flat_human_icon(null, pick(SSjob.occupations))
+
+ setup_friend()
join = new
join.Grant(src)
hide = new
hide.Grant(src)
+/mob/camera/imaginary_friend/proc/setup_friend()
+ var/gender = pick(MALE, FEMALE)
+ real_name = random_unique_name(gender)
+ name = real_name
+ human_image = get_flat_human_icon(null, pick(SSjob.occupations))
+
/mob/camera/imaginary_friend/proc/Show()
if(!client) //nobody home
return
@@ -132,7 +144,7 @@
if(client.prefs.muted & MUTE_IC)
to_chat(src, "You cannot send IC messages (muted).")
return
- if (src.client.handle_spam_prevention(message,MUTE_IC))
+ if (!(ignore_spam || forced) && src.client.handle_spam_prevention(message,MUTE_IC))
return
friend_talk(message)
@@ -218,4 +230,42 @@
var/mob/camera/imaginary_friend/I = owner
I.hidden = !I.hidden
I.Show()
- update_status()
\ No newline at end of file
+ update_status()
+
+//down here is the trapped mind
+//like imaginary friend but a lot less imagination and more like mind prison//
+
+/datum/brain_trauma/special/imaginary_friend/trapped_owner
+ name = "Trapped Victim"
+ desc = "Patient appears to be targeted by an invisible entity."
+ gain_text = ""
+ lose_text = ""
+ random_gain = FALSE
+
+/datum/brain_trauma/special/imaginary_friend/trapped_owner/make_friend()
+ friend = new /mob/camera/imaginary_friend/trapped(get_turf(owner), src)
+
+/datum/brain_trauma/special/imaginary_friend/trapped_owner/reroll_friend() //no rerolling- it's just the last owner's hell
+ if(friend.client) //reconnected
+ return
+ friend_initialized = FALSE
+ QDEL_NULL(friend)
+ qdel(src)
+
+/datum/brain_trauma/special/imaginary_friend/trapped_owner/get_ghost() //no randoms
+ return
+
+/mob/camera/imaginary_friend/trapped
+ name = "figment of imagination?"
+ real_name = "figment of imagination?"
+ desc = "The previous host of this body."
+
+/mob/camera/imaginary_friend/trapped/greet()
+ to_chat(src, "You have managed to hold on as a figment of the new host's imagination!")
+ to_chat(src, "All hope is lost for you, but at least you may interact with your host. You do not have to be loyal to them.")
+ to_chat(src, "You cannot directly influence the world around you, but you can see what the host cannot.")
+
+/mob/camera/imaginary_friend/trapped/setup_friend()
+ real_name = "[owner.real_name]?"
+ name = real_name
+ human_image = icon('icons/mob/lavaland/lavaland_monsters.dmi', icon_state = "curseblob")
diff --git a/code/datums/brain_damage/mild.dm b/code/datums/brain_damage/mild.dm
index c049a7db33..012f771a29 100644
--- a/code/datums/brain_damage/mild.dm
+++ b/code/datums/brain_damage/mild.dm
@@ -64,21 +64,21 @@
name = "Speech Impediment"
desc = "Patient is unable to form coherent sentences."
scan_desc = "communication disorder"
- gain_text = "" //mutation will handle the text
- lose_text = ""
+ gain_text = "You can't seem to form any coherent thoughts!"
+ lose_text = "Your mind feels more clear."
/datum/brain_trauma/mild/speech_impediment/on_gain()
ADD_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, TRAUMA_TRAIT)
- . = ..()
+ ..()
/datum/brain_trauma/mild/speech_impediment/on_lose()
REMOVE_TRAIT(owner, TRAIT_UNINTELLIGIBLE_SPEECH, TRAUMA_TRAIT)
- . = ..()
+ ..()
/datum/brain_trauma/mild/concussion
name = "Concussion"
desc = "Patient's brain is concussed."
- scan_desc = "a concussion"
+ scan_desc = "concussion"
gain_text = "Your head hurts!"
lose_text = "The pressure inside your head starts fading."
@@ -157,54 +157,108 @@
gain_text = "Your muscles feel oddly faint."
lose_text = "You feel in control of your muscles again."
-/datum/brain_trauma/mild/muscle_spasms/on_life()
- if(prob(7))
- switch(rand(1,5))
- if(1)
- if(owner.canmove && !isspaceturf(owner.loc))
- to_chat(owner, "Your leg spasms!")
- step(owner, pick(GLOB.cardinals))
- if(2)
- if(owner.incapacitated())
- return
- var/obj/item/I = owner.get_active_held_item()
- if(I)
- to_chat(owner, "Your fingers spasm!")
- owner.log_message("used [I] due to a Muscle Spasm", LOG_ATTACK)
- I.attack_self(owner)
- if(3)
- var/prev_intent = owner.a_intent
- owner.a_intent = INTENT_HARM
-
- var/range = 1
- if(istype(owner.get_active_held_item(), /obj/item/gun)) //get targets to shoot at
- range = 7
-
- var/list/mob/living/targets = list()
- for(var/mob/M in oview(owner, range))
- if(isliving(M))
- targets += M
- if(LAZYLEN(targets))
- to_chat(owner, "Your arm spasms!")
- owner.log_message(" attacked someone due to a Muscle Spasm") //the following attack will log itself
- owner.ClickOn(pick(targets))
- owner.a_intent = prev_intent
- if(4)
- var/prev_intent = owner.a_intent
- owner.a_intent = INTENT_HARM
- to_chat(owner, "Your arm spasms!")
- owner.log_message("attacked [owner.p_them()]self to a Muscle Spasm", LOG_ATTACK)
- owner.ClickOn(owner)
- owner.a_intent = prev_intent
- if(5)
- if(owner.incapacitated())
- return
- var/obj/item/I = owner.get_active_held_item()
- var/list/turf/targets = list()
- for(var/turf/T in oview(owner, 3))
- targets += T
- if(LAZYLEN(targets) && I)
- to_chat(owner, "Your arm spasms!")
- owner.log_message("threw [I] due to a Muscle Spasm", LOG_ATTACK)
- owner.throw_item(pick(targets))
+/datum/brain_trauma/mild/muscle_spasms/on_gain()
+ owner.apply_status_effect(STATUS_EFFECT_SPASMS)
..()
+
+/datum/brain_trauma/mild/muscle_spasms/on_lose()
+ owner.remove_status_effect(STATUS_EFFECT_SPASMS)
+ ..()
+
+/datum/brain_trauma/mild/nervous_cough
+ name = "Nervous Cough"
+ desc = "Patient feels a constant need to cough."
+ scan_desc = "nervous cough"
+ gain_text = "Your throat itches incessantly..."
+ lose_text = "Your throat stops itching."
+
+/datum/brain_trauma/mild/nervous_cough/on_life()
+ if(prob(12) && !HAS_TRAIT(owner, TRAIT_SOOTHED_THROAT))
+ if(prob(5))
+ to_chat(owner, "[pick("You have a coughing fit!", "You can't stop coughing!")]")
+ owner.Stun(20)
+ owner.emote("cough")
+ addtimer(CALLBACK(owner, /mob/.proc/emote, "cough"), 6)
+ addtimer(CALLBACK(owner, /mob/.proc/emote, "cough"), 12)
+ owner.emote("cough")
+ ..()
+
+/datum/brain_trauma/mild/expressive_aphasia
+ name = "Expressive Aphasia"
+ desc = "Patient is affected by partial loss of speech leading to a reduced vocabulary."
+ scan_desc = "inability to form complex sentences"
+ gain_text = "You lose your grasp on complex words."
+ lose_text = "You feel your vocabulary returning to normal again."
+
+ var/static/list/common_words = world.file2list("strings/1000_most_common.txt")
+
+/datum/brain_trauma/mild/expressive_aphasia/handle_speech(datum/source, list/speech_args)
+ var/message = speech_args[SPEECH_MESSAGE]
+ if(message)
+ var/list/message_split = splittext(message, " ")
+ var/list/new_message = list()
+
+ for(var/word in message_split)
+ var/suffix = copytext(word,-1)
+
+ // Check if we have a suffix and break it out of the word
+ if(suffix in list("." , "," , ";" , "!" , ":" , "?"))
+ word = copytext(word,1,-1)
+ else
+ suffix = ""
+
+ word = html_decode(word)
+
+ if(lowertext(word) in common_words)
+ new_message += word + suffix
+ else
+ if(prob(30) && message_split.len > 2)
+ new_message += pick("uh","erm")
+ break
+ else
+ var/list/charlist = string2charlist(word) // Stupid shit code
+ shuffle_inplace(charlist)
+ charlist.len = round(charlist.len * 0.5,1)
+ new_message += html_encode(jointext(charlist,"")) + suffix
+
+ message = jointext(new_message, " ")
+
+ speech_args[SPEECH_MESSAGE] = trim(message)
+
+/datum/brain_trauma/mild/mind_echo
+ name = "Mind Echo"
+ desc = "Patient's language neurons do not terminate properly, causing previous speech patterns to occasionally resurface spontaneously."
+ scan_desc = "looping neural pattern"
+ gain_text = "You feel a faint echo of your thoughts..."
+ lose_text = "The faint echo fades away."
+ var/list/hear_dejavu = list()
+ var/list/speak_dejavu = list()
+
+/datum/brain_trauma/mild/mind_echo/handle_hearing(datum/source, list/hearing_args)
+ if(owner == hearing_args[HEARING_SPEAKER])
+ return
+ if(hear_dejavu.len >= 5)
+ if(prob(25))
+ var/deja_vu = pick_n_take(hear_dejavu)
+ var/static/regex/quoted_spoken_message = regex("\".+\"", "gi")
+ hearing_args[HEARING_MESSAGE] = quoted_spoken_message.Replace(hearing_args[HEARING_MESSAGE], "\"[deja_vu]\"") //Quotes included to avoid cases where someone says part of their name
+ return
+ if(hear_dejavu.len >= 15)
+ if(prob(50))
+ popleft(hear_dejavu) //Remove the oldest
+ hear_dejavu += hearing_args[HEARING_RAW_MESSAGE]
+ else
+ hear_dejavu += hearing_args[HEARING_RAW_MESSAGE]
+
+/datum/brain_trauma/mild/mind_echo/handle_speech(datum/source, list/speech_args)
+ if(speak_dejavu.len >= 5)
+ if(prob(25))
+ var/deja_vu = pick_n_take(speak_dejavu)
+ speech_args[SPEECH_MESSAGE] = deja_vu
+ return
+ if(speak_dejavu.len >= 15)
+ if(prob(50))
+ popleft(speak_dejavu) //Remove the oldest
+ speak_dejavu += speech_args[SPEECH_MESSAGE]
+ else
+ speak_dejavu += speech_args[SPEECH_MESSAGE]
\ No newline at end of file
diff --git a/code/datums/brain_damage/phobia.dm b/code/datums/brain_damage/phobia.dm
index f802555c7e..034f2baaaf 100644
--- a/code/datums/brain_damage/phobia.dm
+++ b/code/datums/brain_damage/phobia.dm
@@ -2,8 +2,8 @@
name = "Phobia"
desc = "Patient is unreasonably afraid of something."
scan_desc = "phobia"
- gain_text = ""
- lose_text = ""
+ gain_text = "You start finding default values very unnerving..."
+ lose_text = "You no longer feel afraid of default values."
var/phobia_type
var/next_check = 0
var/next_scare = 0
@@ -14,8 +14,10 @@
var/list/trigger_turfs
var/list/trigger_species
-/datum/brain_trauma/mild/phobia/New(specific_type)
- phobia_type = specific_type
+/datum/brain_trauma/mild/phobia/New(new_phobia_type)
+ if(new_phobia_type)
+ phobia_type = new_phobia_type
+
if(!phobia_type)
phobia_type = pick(SStraumas.phobia_types)
@@ -29,6 +31,11 @@
trigger_species = SStraumas.phobia_species[phobia_type]
..()
+
+/datum/brain_trauma/mild/phobia/on_clone()
+ if(clonable)
+ return new type(phobia_type)
+
/datum/brain_trauma/mild/phobia/on_life()
..()
if(HAS_TRAIT(owner, TRAIT_FEARLESS))
@@ -44,6 +51,12 @@
if(is_type_in_typecache(O, trigger_objs))
freak_out(O)
return
+ for(var/mob/living/carbon/human/HU in seen_atoms) //check equipment for trigger items
+ for(var/X in HU.get_all_slots() | HU.held_items)
+ var/obj/I = X
+ if(!QDELETED(I) && is_type_in_typecache(I, trigger_objs))
+ freak_out(I)
+ return
if(LAZYLEN(trigger_turfs))
for(var/turf/T in seen_atoms)
@@ -51,45 +64,41 @@
freak_out(T)
return
- if(LAZYLEN(trigger_mobs) || LAZYLEN(trigger_objs))
+ seen_atoms -= owner //make sure they aren't afraid of themselves.
+ if(LAZYLEN(trigger_mobs) || LAZYLEN(trigger_species))
for(var/mob/M in seen_atoms)
if(is_type_in_typecache(M, trigger_mobs))
freak_out(M)
return
- else if(ishuman(M)) //check their equipment for trigger items
+ else if(ishuman(M)) //check their species
var/mob/living/carbon/human/H = M
if(LAZYLEN(trigger_species) && H.dna && H.dna.species && is_type_in_typecache(H.dna.species, trigger_species))
freak_out(H)
+ return
- for(var/X in H.get_all_slots() | H.held_items)
- var/obj/I = X
- if(!QDELETED(I) && is_type_in_typecache(I, trigger_objs))
- freak_out(I)
- return
-
-/datum/brain_trauma/mild/phobia/on_hear(message, speaker, message_language, raw_message, radio_freq)
+/datum/brain_trauma/mild/phobia/handle_hearing(datum/source, list/hearing_args)
if(!owner.can_hear() || world.time < next_scare) //words can't trigger you if you can't hear them *taps head*
- return message
+ return
if(HAS_TRAIT(owner, TRAIT_FEARLESS))
- return message
+ return
for(var/word in trigger_words)
- var/reg = regex("(\\b|\\A)[REGEX_QUOTE(word)]'?s*(\\b|\\Z)", "i")
+ var/regex/reg = regex("(\\b|\\A)[REGEX_QUOTE(word)]'?s*(\\b|\\Z)", "i")
- if(findtext(raw_message, reg))
+ if(findtext(hearing_args[HEARING_RAW_MESSAGE], reg))
addtimer(CALLBACK(src, .proc/freak_out, null, word), 10) //to react AFTER the chat message
+ hearing_args[HEARING_MESSAGE] = reg.Replace(hearing_args[HEARING_MESSAGE], "$1")
break
- return message
/datum/brain_trauma/mild/phobia/handle_speech(datum/source, list/speech_args)
if(HAS_TRAIT(owner, TRAIT_FEARLESS))
return
for(var/word in trigger_words)
- var/reg = regex("(\\b|\\A)[REGEX_QUOTE(word)]'?s*(\\b|\\Z)", "i")
+ var/regex/reg = regex("(\\b|\\A)[REGEX_QUOTE(word)]'?s*(\\b|\\Z)", "i")
if(findtext(speech_args[SPEECH_MESSAGE], reg))
- to_chat(owner, "You can't bring yourself to say the word \"[word]\"!")
+ to_chat(owner, "You can't bring yourself to say the word \"[word]\"!")
speech_args[SPEECH_MESSAGE] = ""
/datum/brain_trauma/mild/phobia/proc/freak_out(atom/reason, trigger_word)
@@ -125,6 +134,76 @@
owner.Jitter(10)
owner.stuttering += 10
+// Defined phobia types for badminry, not included in the RNG trauma pool to avoid diluting.
+
+/datum/brain_trauma/mild/phobia/spiders
+ phobia_type = "spiders"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/space
+ phobia_type = "space"
+ random_gain = FALSE
+
/datum/brain_trauma/mild/phobia/security
phobia_type = "security"
random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/clowns
+ phobia_type = "clowns"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/greytide
+ phobia_type = "greytide"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/lizards
+ phobia_type = "lizards"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/skeletons
+ phobia_type = "skeletons"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/snakes
+ phobia_type = "snakes"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/robots
+ phobia_type = "robots"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/doctors
+ phobia_type = "doctors"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/authority
+ phobia_type = "authority"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/supernatural
+ phobia_type = "the supernatural"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/aliens
+ phobia_type = "aliens"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/strangers
+ phobia_type = "strangers"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/birds
+ phobia_type = "birds"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/falling
+ phobia_type = "falling"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/anime
+ phobia_type = "anime"
+ random_gain = FALSE
+
+/datum/brain_trauma/mild/phobia/conspiracies
+ phobia_type = "conspiracies"
+ random_gain = FALSE
diff --git a/code/datums/brain_damage/severe.dm b/code/datums/brain_damage/severe.dm
index 890e9cf903..0e08c4cd15 100644
--- a/code/datums/brain_damage/severe.dm
+++ b/code/datums/brain_damage/severe.dm
@@ -119,7 +119,7 @@
owner.update_disabled_bodyparts()
/datum/brain_trauma/severe/paralysis/paraplegic
- //can_gain = FALSE maybe breaks.
+ random_gain = FALSE
paralysis_type = "legs"
resilience = TRAUMA_RESILIENCE_ABSOLUTE
@@ -149,7 +149,7 @@
/datum/brain_trauma/severe/monophobia
name = "Monophobia"
desc = "Patient feels sick and distressed when not around other people, leading to potentially lethal levels of stress."
- scan_desc = "severe monophobia"
+ scan_desc = "monophobia"
gain_text = ""
lose_text = "You feel like you could be safe on your own."
var/stress = 0
@@ -168,7 +168,7 @@
if(stress > 10 && (prob(5)))
stress_reaction()
else
- stress -= 4
+ stress = max(stress - 4, 0)
/datum/brain_trauma/severe/monophobia/proc/check_alone()
if(HAS_TRAIT(owner, TRAIT_BLIND))
diff --git a/code/datums/brain_damage/special.dm b/code/datums/brain_damage/special.dm
index d9e6f00643..b52c7d391c 100644
--- a/code/datums/brain_damage/special.dm
+++ b/code/datums/brain_damage/special.dm
@@ -22,6 +22,14 @@
else
speak("neutral", prob(25))
+/datum/brain_trauma/special/godwoken/on_gain()
+ ADD_TRAIT(owner, TRAIT_HOLY, TRAUMA_TRAIT)
+ ..()
+
+/datum/brain_trauma/special/godwoken/on_lose()
+ REMOVE_TRAIT(owner, TRAIT_HOLY, TRAUMA_TRAIT)
+ ..()
+
/datum/brain_trauma/special/godwoken/proc/speak(type, include_owner = FALSE)
var/message
switch(type)
@@ -36,7 +44,7 @@
else
message = pick_list_replacements(BRAIN_DAMAGE_FILE, "god_neutral")
- playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 200, 1, 5)
+ playsound(get_turf(owner), 'sound/magic/clockwork/invoke_general.ogg', 200, TRUE, 5)
voice_of_god(message, owner, list("colossus","yell"), 2.5, include_owner, FALSE)
/datum/brain_trauma/special/bluespace_prophet
@@ -134,7 +142,101 @@
/datum/brain_trauma/special/psychotic_brawling/bath_salts
name = "Chemical Violent Psychosis"
- random_gain = FALSE
+ clonable = FALSE
+
+/datum/brain_trauma/special/tenacity
+ name = "Tenacity"
+ desc = "Patient is psychologically unaffected by pain and injuries, and can remain standing far longer than a normal person."
+ scan_desc = "traumatic neuropathy"
+ gain_text = "You suddenly stop feeling pain."
+ lose_text = "You realize you can feel pain again."
+
+/datum/brain_trauma/special/tenacity/on_gain()
+ ADD_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAUMA_TRAIT)
+ ADD_TRAIT(owner, TRAIT_NOHARDCRIT, TRAUMA_TRAIT)
+ ..()
+
+/datum/brain_trauma/special/tenacity/on_lose()
+ REMOVE_TRAIT(owner, TRAIT_NOSOFTCRIT, TRAUMA_TRAIT)
+ REMOVE_TRAIT(owner, TRAIT_NOHARDCRIT, TRAUMA_TRAIT)
+ ..()
+
+/datum/brain_trauma/special/death_whispers
+ name = "Functional Cerebral Necrosis"
+ desc = "Patient's brain is stuck in a functional near-death state, causing occasional moments of lucid hallucinations, which are often interpreted as the voices of the dead."
+ scan_desc = "chronic functional necrosis"
+ gain_text = "You feel dead inside."
+ lose_text = "You feel alive again."
+ var/active = FALSE
+
+/datum/brain_trauma/special/death_whispers/on_life()
+ ..()
+ if(!active && prob(2))
+ whispering()
+
+/datum/brain_trauma/special/death_whispers/on_lose()
+ if(active)
+ cease_whispering()
+ ..()
+
+/datum/brain_trauma/special/death_whispers/proc/whispering()
+ ADD_TRAIT(owner, TRAIT_SIXTHSENSE, TRAUMA_TRAIT)
+ active = TRUE
+ addtimer(CALLBACK(src, .proc/cease_whispering), rand(50, 300))
+
+/datum/brain_trauma/special/death_whispers/proc/cease_whispering()
+ REMOVE_TRAIT(owner, TRAIT_SIXTHSENSE, TRAUMA_TRAIT)
+ active = FALSE
+
+/datum/brain_trauma/special/existential_crisis
+ name = "Existential Crisis"
+ desc = "Patient's hold on reality becomes faint, causing occasional bouts of non-existence."
+ scan_desc = "existential crisis"
+ gain_text = "You feel less real."
+ lose_text = "You feel more substantial again."
+ var/obj/effect/abstract/sync_holder/veil/veil
+ var/next_crisis = 0
+
+/datum/brain_trauma/special/existential_crisis/on_life()
+ ..()
+ if(!veil && world.time > next_crisis && prob(3))
+ if(isturf(owner.loc))
+ fade_out()
+
+/datum/brain_trauma/special/existential_crisis/on_lose()
+ if(veil)
+ fade_in()
+ ..()
+
+/datum/brain_trauma/special/existential_crisis/proc/fade_out()
+ if(veil)
+ return
+ var/duration = rand(50, 450)
+ veil = new(owner.drop_location())
+ to_chat(owner, "[pick("You stop thinking for a moment. Therefore you are not.",\
+ "To be or not to be...",\
+ "Why exist?",\
+ "You stop keeping it real.",\
+ "Your grip on existence slips.",\
+ "Do you even exist?",\
+ "You simply fade away.")]")
+ owner.forceMove(veil)
+ SEND_SIGNAL(owner, COMSIG_MOVABLE_SECLUDED_LOCATION)
+ for(var/thing in owner)
+ var/atom/movable/AM = thing
+ SEND_SIGNAL(AM, COMSIG_MOVABLE_SECLUDED_LOCATION)
+ next_crisis = world.time + 600
+ addtimer(CALLBACK(src, .proc/fade_in), duration)
+
+/datum/brain_trauma/special/existential_crisis/proc/fade_in()
+ QDEL_NULL(veil)
+ to_chat(owner, "You fade back into reality.")
+ next_crisis = world.time + 600
+
+//base sync holder is in desynchronizer.dm
+/obj/effect/abstract/sync_holder/veil
+ name = "non-existence"
+ desc = "Existence is just a state of mind."
/datum/brain_trauma/special/beepsky
name = "Criminal"
@@ -142,6 +244,7 @@
scan_desc = "criminal mind"
gain_text = "Justice is coming for you."
lose_text = "You were absolved for your crimes."
+ clonable = FALSE
random_gain = FALSE
var/obj/effect/hallucination/simple/securitron/beepsky
@@ -201,4 +304,4 @@
/obj/effect/hallucination/simple/securitron/Destroy()
STOP_PROCESSING(SSfastprocess,src)
- return ..()
\ No newline at end of file
+ return ..()
diff --git a/code/datums/brain_damage/split_personality.dm b/code/datums/brain_damage/split_personality.dm
index 1a26ea7a14..dfe63ce141 100644
--- a/code/datums/brain_damage/split_personality.dm
+++ b/code/datums/brain_damage/split_personality.dm
@@ -13,6 +13,10 @@
var/mob/living/split_personality/owner_backseat
/datum/brain_trauma/severe/split_personality/on_gain()
+ var/mob/living/M = owner
+ if(M.stat == DEAD) //No use assigning people to a corpse
+ qdel(src)
+ return
..()
make_backseats()
get_ghost()
@@ -23,7 +27,7 @@
/datum/brain_trauma/severe/split_personality/proc/get_ghost()
set waitfor = FALSE
- var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", ROLE_PAI, null, null, 75, stranger_backseat)
+ var/list/mob/dead/observer/candidates = pollCandidatesForMob("Do you want to play as [owner]'s split personality?", ROLE_PAI, null, null, 75, stranger_backseat, POLL_IGNORE_SPLITPERSONALITY)
if(LAZYLEN(candidates))
var/mob/dead/observer/C = pick(candidates)
C.transfer_ckey(stranger_backseat, FALSE)
@@ -191,13 +195,13 @@
/datum/brain_trauma/severe/split_personality/brainwashing/on_life()
return //no random switching
-/datum/brain_trauma/severe/split_personality/brainwashing/on_hear(message, speaker, message_language, raw_message, radio_freq)
- if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == speaker)
- return message
+/datum/brain_trauma/severe/split_personality/brainwashing/handle_hearing(datum/source, list/hearing_args)
+ if(HAS_TRAIT(owner, TRAIT_DEAF) || owner == hearing_args[HEARING_SPEAKER])
+ return
+ var/message = hearing_args[HEARING_MESSAGE]
if(findtext(message, codeword))
- message = replacetext(message, codeword, "[codeword]")
+ hearing_args[HEARING_MESSAGE] = replacetext(message, codeword, "[codeword]")
addtimer(CALLBACK(src, /datum/brain_trauma/severe/split_personality.proc/switch_personalities), 10)
- return message
/datum/brain_trauma/severe/split_personality/brainwashing/handle_speech(datum/source, list/speech_args)
if(findtext(speech_args[SPEECH_MESSAGE], codeword))
diff --git a/code/datums/components/armor_plate.dm b/code/datums/components/armor_plate.dm
index 53c8c280a9..975b52dcb9 100644
--- a/code/datums/components/armor_plate.dm
+++ b/code/datums/components/armor_plate.dm
@@ -29,21 +29,21 @@
var/obj/item/typecast = upgrade_item
upgrade_name = initial(typecast.name)
-/datum/component/armor_plate/proc/examine(datum/source, mob/user)
+/datum/component/armor_plate/proc/examine(datum/source, mob/user, list/examine_list)
//upgrade_item could also be typecast here instead
if(ismecha(parent))
if(amount)
if(amount < maxamount)
- to_chat(user, "Its armor is enhanced with [amount] [upgrade_name].")
+ examine_list += "Its armor is enhanced with [amount] [upgrade_name]."
else
- to_chat(user, "It's wearing a fearsome carapace entirely composed of [upgrade_name] - its pilot must be an experienced monster hunter.")
+ examine_list += "It's wearing a fearsome carapace entirely composed of [upgrade_name] - its pilot must be an experienced monster hunter."
else
- to_chat(user, "It has attachment points for strapping monster hide on for added protection.")
+ examine_list += "It has attachment points for strapping monster hide on for added protection."
else
if(amount)
- to_chat(user, "It has been strengthened with [amount]/[maxamount] [upgrade_name].")
+ examine_list += "It has been strengthened with [amount]/[maxamount] [upgrade_name]."
else
- to_chat(user, "It can be strengthened with up to [maxamount] [upgrade_name].")
+ examine_list += "It can be strengthened with up to [maxamount] [upgrade_name]."
/datum/component/armor_plate/proc/applyplate(datum/source, obj/item/I, mob/user, params)
if(!istype(I,upgrade_item))
diff --git a/code/datums/components/construction.dm b/code/datums/components/construction.dm
index 3b64d68486..01df44752c 100644
--- a/code/datums/components/construction.dm
+++ b/code/datums/components/construction.dm
@@ -19,9 +19,9 @@
RegisterSignal(parent, COMSIG_PARENT_ATTACKBY,.proc/action)
update_parent(index)
-/datum/component/construction/proc/examine(datum/source, mob/user)
+/datum/component/construction/proc/examine(datum/source, mob/user, list/examine_list)
if(desc)
- to_chat(user, desc)
+ examine_list += desc
/datum/component/construction/proc/on_step()
if(index > steps.len)
diff --git a/code/datums/components/decal.dm b/code/datums/components/decal.dm
index bdc1d3a2f6..641dbdb1cf 100644
--- a/code/datums/components/decal.dm
+++ b/code/datums/components/decal.dm
@@ -71,5 +71,5 @@
if(strength >= cleanable)
qdel(src)
-/datum/component/decal/proc/examine(datum/source, mob/user)
- to_chat(user, description)
\ No newline at end of file
+/datum/component/decal/proc/examine(datum/source, mob/user, list/examine_list)
+ examine_list += description
\ No newline at end of file
diff --git a/code/datums/components/magnetic_catch.dm b/code/datums/components/magnetic_catch.dm
index fb68b89ebf..c7e59e0ead 100644
--- a/code/datums/components/magnetic_catch.dm
+++ b/code/datums/components/magnetic_catch.dm
@@ -15,8 +15,8 @@
for(var/i in parent)
RegisterSignal(i, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react)
-/datum/component/magnetic_catch/proc/examine(datum/source, mob/user)
- to_chat(user, "It has been installed with inertia dampening to prevent coffee spills.")
+/datum/component/magnetic_catch/proc/examine(datum/source, mob/user, list/examine_list)
+ examine_list += "It has been installed with inertia dampening to prevent coffee spills."
/datum/component/magnetic_catch/proc/crossed_react(datum/source, atom/movable/thing)
RegisterSignal(thing, COMSIG_MOVABLE_PRE_THROW, .proc/throw_react, TRUE)
diff --git a/code/datums/components/material_container.dm b/code/datums/components/material_container.dm
index 48fa758db1..25094518b8 100644
--- a/code/datums/components/material_container.dm
+++ b/code/datums/components/material_container.dm
@@ -49,13 +49,13 @@
var/mat_path = possible_mats[id]
materials[id] = new mat_path()
-/datum/component/material_container/proc/OnExamine(datum/source, mob/user)
+/datum/component/material_container/proc/OnExamine(datum/source, mob/user, list/examine_list)
if(show_on_examine)
for(var/I in materials)
var/datum/material/M = materials[I]
var/amt = amount(M.id)
if(amt)
- to_chat(user, "It has [amt] units of [lowertext(M.name)] stored.")
+ examine_list += "It has [amt] units of [lowertext(M.name)] stored."
/datum/component/material_container/proc/OnAttackBy(datum/source, obj/item/I, mob/living/user)
var/list/tc = allowed_typecache
diff --git a/code/datums/components/nanites.dm b/code/datums/components/nanites.dm
index 3f7f794435..362961a24f 100644
--- a/code/datums/components/nanites.dm
+++ b/code/datums/components/nanites.dm
@@ -53,7 +53,6 @@
RegisterSignal(parent, COMSIG_MOB_ALLOWED, .proc/check_access)
RegisterSignal(parent, COMSIG_LIVING_ELECTROCUTE_ACT, .proc/on_shock)
RegisterSignal(parent, COMSIG_LIVING_MINOR_SHOCK, .proc/on_minor_shock)
- RegisterSignal(parent, COMSIG_MOVABLE_HEAR, .proc/on_hear)
RegisterSignal(parent, COMSIG_SPECIES_GAIN, .proc/check_viable_biotype)
RegisterSignal(parent, COMSIG_NANITE_SIGNAL, .proc/receive_signal)
@@ -191,11 +190,6 @@
var/datum/nanite_program/NP = X
NP.on_death(gibbed)
-/datum/component/nanites/proc/on_hear(datum/source, message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
- for(var/X in programs)
- var/datum/nanite_program/NP = X
- NP.on_hear(message, speaker, message_language, raw_message, radio_freq, spans, message_mode)
-
/datum/component/nanites/proc/receive_signal(datum/source, code, source = "an unidentified source")
for(var/X in programs)
var/datum/nanite_program/NP = X
diff --git a/code/datums/components/radioactive.dm b/code/datums/components/radioactive.dm
index bf47793f81..9dac20d94f 100644
--- a/code/datums/components/radioactive.dm
+++ b/code/datums/components/radioactive.dm
@@ -18,7 +18,7 @@
hl3_release_date = _half_life
can_contaminate = _can_contaminate
- if(istype(parent, /atom))
+ if(istype(parent, /atom))
RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/rad_examine)
if(istype(parent, /obj/item))
RegisterSignal(parent, COMSIG_ITEM_ATTACK, .proc/rad_attack)
@@ -58,7 +58,7 @@
else
strength = max(strength, arguments[1])
-/datum/component/radioactive/proc/rad_examine(datum/source, mob/user, atom/thing)
+/datum/component/radioactive/proc/rad_examine(datum/source, mob/user, list/examine_list)
var/atom/master = parent
var/list/out = list()
if(get_dist(master, user) <= 1)
@@ -72,7 +72,7 @@
out += "[out ? " and it " : "[master] "]hurts to look at."
else
out += "."
- to_chat(user, out.Join())
+ examine_list += out.Join()
/datum/component/radioactive/proc/rad_attack(datum/source, atom/movable/target, mob/living/user)
radiation_pulse(parent, strength/20)
diff --git a/code/datums/components/rotation.dm b/code/datums/components/rotation.dm
index a044ca301e..81ff2d517d 100644
--- a/code/datums/components/rotation.dm
+++ b/code/datums/components/rotation.dm
@@ -98,9 +98,9 @@
remove_verbs()
. = ..()
-/datum/component/simple_rotation/proc/ExamineMessage(datum/source, mob/user)
+/datum/component/simple_rotation/proc/ExamineMessage(datum/source, mob/user, list/examine_list)
if(rotation_flags & ROTATION_ALTCLICK)
- to_chat(user, "Alt-click to rotate it clockwise.")
+ examine_list += "Alt-click to rotate it clockwise."
/datum/component/simple_rotation/proc/HandRot(datum/source, mob/user, rotation = default_rotation_direction)
if(!can_be_rotated.Invoke(user, rotation) || !can_user_rotate.Invoke(user, rotation))
diff --git a/code/datums/components/stationloving.dm b/code/datums/components/stationloving.dm
index bbcb0d88a6..91928656e1 100644
--- a/code/datums/components/stationloving.dm
+++ b/code/datums/components/stationloving.dm
@@ -8,6 +8,7 @@
if(!ismovableatom(parent))
return COMPONENT_INCOMPATIBLE
RegisterSignal(parent, list(COMSIG_MOVABLE_Z_CHANGED), .proc/check_in_bounds)
+ RegisterSignal(parent, list(COMSIG_MOVABLE_SECLUDED_LOCATION), .proc/relocate)
RegisterSignal(parent, list(COMSIG_PARENT_PREQDELETED), .proc/check_deletion)
RegisterSignal(parent, list(COMSIG_ITEM_IMBUE_SOUL), .proc/check_soul_imbue)
src.inform_admins = inform_admins
@@ -32,6 +33,7 @@
var/atom/movable/AM = parent
AM.forceMove(targetturf)
+ to_chat(get(parent, /mob), "You can't help but feel that you just lost something back there...")
// move the disc, so ghosts remain orbiting it even if it's "destroyed"
return targetturf
@@ -40,7 +42,6 @@
return
else
var/turf/currentturf = get_turf(src)
- to_chat(get(parent, /mob), "You can't help but feel that you just lost something back there...")
var/turf/targetturf = relocate()
log_game("[parent] has been moved out of bounds in [loc_name(currentturf)]. Moving it to [loc_name(targetturf)].")
if(inform_admins)
diff --git a/code/datums/mind.dm b/code/datums/mind.dm
index 5cf03e2684..0ded5f9912 100644
--- a/code/datums/mind.dm
+++ b/code/datums/mind.dm
@@ -91,7 +91,10 @@
if(current) // remove ourself from our old body's mind variable
current.mind = null
SStgui.on_transfer(current, new_character)
-
+ if(iscarbon(current))
+ var/mob/living/carbon/C = current
+ if(C.combatmode)
+ C.toggle_combat_mode(TRUE, TRUE)
if(!language_holder)
var/datum/language_holder/mob_holder = new_character.get_language_holder(shadow = FALSE)
language_holder = mob_holder.copy(src)
diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm
index fb636f6911..84ed012b82 100644
--- a/code/datums/status_effects/debuffs.dm
+++ b/code/datums/status_effects/debuffs.dm
@@ -567,8 +567,7 @@ datum/status_effect/pacify
tick_interval = 10
examine_text = "SUBJECTPRONOUN seems slow and unfocused."
var/stun = TRUE
- var/triggered = FALSE
- alert_type = null
+ alert_type = /obj/screen/alert/status_effect/trance
/obj/screen/alert/status_effect/trance
name = "Trance"
@@ -576,17 +575,6 @@ datum/status_effect/pacify
icon_state = "high"
/datum/status_effect/trance/tick()
- if(HAS_TRAIT(owner, "hypnotherapy"))
- if(triggered == TRUE)
- UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
- RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/hypnotize)
- ADD_TRAIT(owner, TRAIT_MUTE, "trance")
- if(!owner.has_quirk(/datum/quirk/monochromatic))
- owner.add_client_colour(/datum/client_colour/monochrome)
- to_chat(owner, "[pick("You feel your thoughts slow down...", "You suddenly feel extremely dizzy...", "You feel like you're in the middle of a dream...","You feel incredibly relaxed...")]")
- triggered = FALSE
- else
- return
if(stun)
owner.Stun(60, TRUE, TRUE)
owner.dizziness = 20
@@ -594,47 +582,88 @@ datum/status_effect/pacify
/datum/status_effect/trance/on_apply()
if(!iscarbon(owner))
return FALSE
- if(HAS_TRAIT(owner, "hypnotherapy"))
- RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/listen)
- return TRUE
- alert_type = /obj/screen/alert/status_effect/trance
RegisterSignal(owner, COMSIG_MOVABLE_HEAR, .proc/hypnotize)
ADD_TRAIT(owner, TRAIT_MUTE, "trance")
- if(!owner.has_quirk(/datum/quirk/monochromatic))
- owner.add_client_colour(/datum/client_colour/monochrome)
+ owner.add_client_colour(/datum/client_colour/monochrome/trance)
owner.visible_message("[stun ? "[owner] stands still as [owner.p_their()] eyes seem to focus on a distant point." : ""]", \
"[pick("You feel your thoughts slow down...", "You suddenly feel extremely dizzy...", "You feel like you're in the middle of a dream...","You feel incredibly relaxed...")]")
return TRUE
-/datum/status_effect/trance/on_creation(mob/living/new_owner, _duration, _stun = TRUE, source_quirk = FALSE)//hypnoquirk makes no visible message, prevents self antag messages, and places phrase below objectives.
+/datum/status_effect/trance/on_creation(mob/living/new_owner, _duration, _stun = TRUE)
duration = _duration
stun = _stun
- if(source_quirk == FALSE && HAS_TRAIT(owner, "hypnotherapy"))
- REMOVE_TRAIT(owner, "hypnotherapy", ROUNDSTART_TRAIT)
return ..()
/datum/status_effect/trance/on_remove()
UnregisterSignal(owner, COMSIG_MOVABLE_HEAR)
REMOVE_TRAIT(owner, TRAIT_MUTE, "trance")
owner.dizziness = 0
- if(!owner.has_quirk(/datum/quirk/monochromatic))
- owner.remove_client_colour(/datum/client_colour/monochrome)
+ owner.remove_client_colour(/datum/client_colour/monochrome/trance)
to_chat(owner, "You snap out of your trance!")
-/datum/status_effect/trance/proc/listen(datum/source, message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
- to_chat(owner, "[speaker] accidentally sets off your implanted trigger, sending you into a hypnotic daze!")
- triggered = TRUE
-
-/datum/status_effect/trance/proc/hypnotize(datum/source, message, atom/movable/speaker, message_language, raw_message, radio_freq, list/spans, message_mode)
+/datum/status_effect/trance/proc/hypnotize(datum/source, list/hearing_args)
if(!owner.can_hear())
return
- if(speaker == owner)
+ if(hearing_args[HEARING_SPEAKER] == owner)
return
var/mob/living/carbon/C = owner
C.cure_trauma_type(/datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY) //clear previous hypnosis
- if(HAS_TRAIT(C, "hypnotherapy"))
- addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, raw_message, TRUE), 10)
- else
- addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, raw_message), 10)
+ addtimer(CALLBACK(C, /mob/living/carbon.proc/gain_trauma, /datum/brain_trauma/hypnosis, TRAUMA_RESILIENCE_SURGERY, hearing_args[HEARING_RAW_MESSAGE]), 10)
addtimer(CALLBACK(C, /mob/living.proc/Stun, 60, TRUE, TRUE), 15) //Take some time to think about it
qdel(src)
+
+/datum/status_effect/spasms
+ id = "spasms"
+ status_type = STATUS_EFFECT_MULTIPLE
+ alert_type = null
+
+/datum/status_effect/spasms/tick()
+ if(prob(15))
+ switch(rand(1,5))
+ if(1)
+ if((!owner.lying && !owner.buckled) && isturf(owner.loc))
+ to_chat(owner, "Your leg spasms!")
+ step(owner, pick(GLOB.cardinals))
+ if(2)
+ if(owner.incapacitated())
+ return
+ var/obj/item/I = owner.get_active_held_item()
+ if(I)
+ to_chat(owner, "Your fingers spasm!")
+ owner.log_message("used [I] due to a Muscle Spasm", LOG_ATTACK)
+ I.attack_self(owner)
+ if(3)
+ var/prev_intent = owner.a_intent
+ owner.a_intent = INTENT_HARM
+
+ var/range = 1
+ if(istype(owner.get_active_held_item(), /obj/item/gun)) //get targets to shoot at
+ range = 7
+
+ var/list/mob/living/targets = list()
+ for(var/mob/M in oview(owner, range))
+ if(isliving(M))
+ targets += M
+ if(LAZYLEN(targets))
+ to_chat(owner, "Your arm spasms!")
+ owner.log_message(" attacked someone due to a Muscle Spasm", LOG_ATTACK) //the following attack will log itself
+ owner.ClickOn(pick(targets))
+ owner.a_intent = prev_intent
+ if(4)
+ var/prev_intent = owner.a_intent
+ owner.a_intent = INTENT_HARM
+ to_chat(owner, "Your arm spasms!")
+ owner.log_message("attacked [owner.p_them()]self to a Muscle Spasm", LOG_ATTACK)
+ owner.ClickOn(owner)
+ owner.a_intent = prev_intent
+ if(5)
+ if(owner.incapacitated())
+ return
+ var/obj/item/I = owner.get_active_held_item()
+ var/list/turf/targets = list()
+ for(var/turf/T in oview(owner, 3))
+ targets += T
+ if(LAZYLEN(targets) && I)
+ to_chat(owner, "Your arm spasms!")
+ owner.log_message("threw [I] due to a Muscle Spasm", LOG_ATTACK)
+ owner.throw_item(pick(targets))
\ No newline at end of file
diff --git a/code/datums/status_effects/neutral.dm b/code/datums/status_effects/neutral.dm
index 655863e0e0..cb2b4174b5 100644
--- a/code/datums/status_effects/neutral.dm
+++ b/code/datums/status_effects/neutral.dm
@@ -69,3 +69,17 @@
/datum/status_effect/in_love/tick()
if(date)
new /obj/effect/temp_visual/love_heart/invisible(get_turf(date.loc), owner)
+
+/datum/status_effect/throat_soothed
+ id = "throat_soothed"
+ duration = 60 SECONDS
+ status_type = STATUS_EFFECT_REFRESH
+ alert_type = null
+
+/datum/status_effect/throat_soothed/on_apply()
+ . = ..()
+ ADD_TRAIT(owner, TRAIT_SOOTHED_THROAT, "[STATUS_EFFECT_TRAIT]_[id]")
+
+/datum/status_effect/throat_soothed/on_remove()
+ . = ..()
+ REMOVE_TRAIT(owner, TRAIT_SOOTHED_THROAT, "[STATUS_EFFECT_TRAIT]_[id]")
\ No newline at end of file
diff --git a/code/datums/status_effects/status_effect.dm b/code/datums/status_effects/status_effect.dm
index bc1cfba112..0d84aab763 100644
--- a/code/datums/status_effects/status_effect.dm
+++ b/code/datums/status_effects/status_effect.dm
@@ -64,6 +64,12 @@
owner = null
qdel(src)
+/datum/status_effect/proc/refresh()
+ var/original_duration = initial(duration)
+ if(original_duration == -1)
+ return
+ duration = world.time + original_duration
+
//clickdelay/nextmove modifiers!
/datum/status_effect/proc/nextmove_modifier()
return 1
@@ -92,6 +98,9 @@
if(S.id == initial(S1.id) && S.status_type)
if(S.status_type == STATUS_EFFECT_REPLACE)
S.be_replaced()
+ else if(S.status_type == STATUS_EFFECT_REFRESH)
+ S.refresh()
+ return
else
return
var/list/arguments = args.Copy()
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index e8651ba93d..6f633f7c6d 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -280,35 +280,35 @@
///Generate the full examine string of this atom (including icon for goonchat)
/atom/proc/get_examine_string(mob/user, thats = FALSE)
- . = "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]"
+ return "[icon2html(src, user)] [thats? "That's ":""][get_examine_name(user)]"
/atom/proc/examine(mob/user)
- to_chat(user, "[get_examine_string(user, TRUE)].")
+ . = list("[get_examine_string(user, TRUE)].")
if(desc)
- to_chat(user, desc)
+ . += desc
if(reagents)
if(reagents.reagents_holder_flags & TRANSPARENT)
- to_chat(user, "It contains:")
- if(reagents.reagent_list.len)
+ . += "It contains:"
+ if(length(reagents.reagent_list))
if(user.can_see_reagents()) //Show each individual reagent
for(var/datum/reagent/R in reagents.reagent_list)
- to_chat(user, "[R.volume] units of [R.name]")
+ . += "[R.volume] units of [R.name]"
else //Otherwise, just show the total volume
var/total_volume = 0
for(var/datum/reagent/R in reagents.reagent_list)
total_volume += R.volume
- to_chat(user, "[total_volume] units of various reagents")
+ . += "[total_volume] units of various reagents"
else
- to_chat(user, "Nothing.")
+ . += "Nothing."
else if(reagents.reagents_holder_flags & AMOUNT_VISIBLE)
if(reagents.total_volume)
- to_chat(user, "It has [reagents.total_volume] unit\s left.")
+ . += "It has [reagents.total_volume] unit\s left."
else
- to_chat(user, "It's empty.")
+ . += "It's empty."
- SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user)
+ SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, .)
/atom/proc/relaymove(mob/user)
if(buckle_message_cooldown <= world.time)
@@ -660,7 +660,7 @@
var/atom/L = loc
if(!L)
return null
- return L.AllowDrop() ? L : get_turf(L)
+ return L.AllowDrop() ? L : L.drop_location()
/atom/Entered(atom/movable/AM, atom/oldLoc)
SEND_SIGNAL(src, COMSIG_ATOM_ENTERED, AM, oldLoc)
diff --git a/code/game/gamemodes/clock_cult/clock_cult.dm b/code/game/gamemodes/clock_cult/clock_cult.dm
index 30e53cdee8..a76e8234ba 100644
--- a/code/game/gamemodes/clock_cult/clock_cult.dm
+++ b/code/game/gamemodes/clock_cult/clock_cult.dm
@@ -349,7 +349,7 @@ Credit where due:
changelog_contents += "[entry]"
info = replacetext(info, "CLOCKCULTCHANGELOG", changelog_contents)
-/obj/item/paper/servant_primer/examine(mob/user)
- if(!is_servant_of_ratvar(user) && !isobserver(user))
- to_chat(user, "You can't understand any of the words on [src].")
- ..()
+/obj/item/paper/servant_primer/oui_getcontent(mob/target)
+ if(!is_servant_of_ratvar(target) && !isobserver(target))
+ return "[name][stars(info)]
[stamps]"
+ return ..()
diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm
index 83a3debfdc..25edd0c68b 100644
--- a/code/game/gamemodes/dynamic/dynamic.dm
+++ b/code/game/gamemodes/dynamic/dynamic.dm
@@ -409,7 +409,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
message_admins("Drafting players for forced ruleset [rule.name].")
log_game("DYNAMIC: Drafting players for forced ruleset [rule.name].")
rule.mode = src
- rule.acceptable(GLOB.player_list.len, threat_level) // Assigns some vars in the modes, running it here for consistency
+ rule.acceptable(roundstart_pop_ready, threat_level) // Assigns some vars in the modes, running it here for consistency
rule.candidates = candidates.Copy()
rule.trim_candidates()
if (rule.ready(TRUE))
@@ -421,7 +421,7 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
return TRUE
var/list/drafted_rules = list()
for (var/datum/dynamic_ruleset/roundstart/rule in roundstart_rules)
- if (rule.acceptable(GLOB.player_list.len, threat_level) && threat >= rule.cost) // If we got the population and threat required
+ if (rule.acceptable(roundstart_pop_ready, threat_level) && threat >= rule.cost) // If we got the population and threat required
rule.candidates = candidates.Copy()
rule.trim_candidates()
if (rule.ready() && rule.candidates.len > 0)
@@ -429,12 +429,12 @@ GLOBAL_VAR_INIT(dynamic_forced_threat_level, -1)
if(!drafted_rules.len)
message_admins("Not enough threat level for roundstart antags!")
log_game("DYNAMIC: Not enough threat level for roundstart antags!")
- var/indice_pop = min(10,round(GLOB.player_list.len/pop_per_requirement)+1)
+ var/indice_pop = min(10,round(roundstart_pop_ready/pop_per_requirement)+1)
extra_rulesets_amount = 0
if (GLOB.dynamic_classic_secret)
extra_rulesets_amount = 0
else
- if (GLOB.player_list.len > GLOB.dynamic_high_pop_limit)
+ if (roundstart_pop_ready > GLOB.dynamic_high_pop_limit)
message_admins("High Population Override is in effect! Threat Level will have more impact on which roles will appear, and player population less.")
log_game("DYNAMIC: High Population Override is in effect! Threat Level will have more impact on which roles will appear, and player population less.")
if (threat_level > high_pop_second_rule_req)
diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
index 41de85f7ee..8cda402ebf 100644
--- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
+++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm
@@ -41,6 +41,9 @@
if (!istype(M, required_type))
trimmed_list.Remove(M)
continue
+ if (M.GetComponent(/datum/component/virtual_reality))
+ trimmed_list.Remove(M)
+ continue
if (!M.client) // Are they connected?
trimmed_list.Remove(M)
continue
diff --git a/code/game/gamemodes/meteor/meteors.dm b/code/game/gamemodes/meteor/meteors.dm
index 58f551c648..6d681f8108 100644
--- a/code/game/gamemodes/meteor/meteors.dm
+++ b/code/game/gamemodes/meteor/meteors.dm
@@ -167,7 +167,7 @@ GLOBAL_LIST_INIT(meteorsC, list(/obj/effect/meteor/dust)) //for space dust event
/obj/effect/meteor/examine(mob/user)
if(!(flags_1 & ADMIN_SPAWNED_1) && isliving(user))
SSmedals.UnlockMedal(MEDAL_METEOR, user.client)
- ..()
+ return ..()
/obj/effect/meteor/attackby(obj/item/I, mob/user, params)
if(I.tool_behaviour == TOOL_MINING)
diff --git a/code/game/machinery/Sleeper.dm b/code/game/machinery/Sleeper.dm
index 513fea4360..68f7327551 100644
--- a/code/game/machinery/Sleeper.dm
+++ b/code/game/machinery/Sleeper.dm
@@ -12,6 +12,7 @@
density = FALSE
state_open = TRUE
circuit = /obj/item/circuitboard/machine/sleeper
+ req_access = list(ACCESS_CMO) //Used for reagent deletion and addition of non medicines
var/efficiency = 1
var/min_health = -25
var/list/available_chems
@@ -28,9 +29,28 @@
/obj/machinery/sleeper/Initialize()
. = ..()
+ create_reagents(500, NO_REACT)
occupant_typecache = GLOB.typecache_living
update_icon()
reset_chem_buttons()
+ RefreshParts()
+ add_inital_chems()
+
+/obj/machinery/sleeper/Destroy()
+ var/obj/item/reagent_containers/sleeper_buffer/buffer = new /obj/item/reagent_containers/sleeper_buffer(loc)
+ buffer.volume = reagents.maximum_volume
+ buffer.reagents.maximum_volume = reagents.maximum_volume
+ reagents.trans_to(buffer.reagents, reagents.total_volume)
+ ..()
+
+/obj/machinery/sleeper/proc/add_inital_chems()
+ for(var/i in available_chems)
+ var/datum/reagent/R = reagents.has_reagent(i)
+ if(!R)
+ reagents.add_reagent(i, (20))
+ continue
+ if(R.volume < 20)
+ reagents.add_reagent(i, (20 - R.volume))
/obj/machinery/sleeper/RefreshParts()
var/E
@@ -47,6 +67,11 @@
available_chems |= possible_chems[i]
reset_chem_buttons()
+ //Total container size 500 - 2000u
+ if(reagents)
+ reagents.maximum_volume = (500*E)
+
+
/obj/machinery/sleeper/update_icon()
icon_state = initial(icon_state)
if(state_open)
@@ -81,7 +106,42 @@
if (. & EMP_PROTECT_SELF)
return
if(is_operational() && occupant)
+ var/datum/reagent/R = pick(reagents.reagent_list)
+ inject_chem(R.id, occupant)
open_machine()
+ //Is this too much?
+ if(severity == EMP_HEAVY)
+ var/chem = pick(available_chems)
+ available_chems -= chem
+ available_chems += get_random_reagent_id()
+ reset_chem_buttons()
+
+/obj/machinery/sleeper/attackby(obj/item/I, mob/user, params)
+ if(istype(I, /obj/item/reagent_containers/sleeper_buffer))
+ var/obj/item/reagent_containers/sleeper_buffer/SB = I
+ if((SB.reagents.total_volume + reagents.total_volume) < reagents.maximum_volume)
+ SB.reagents.trans_to(reagents, SB.reagents.total_volume)
+ visible_message("[user] places the [SB] into the [src].")
+ qdel(SB)
+ return
+ else
+ SB.reagents.trans_to(reagents, SB.reagents.total_volume)
+ visible_message("[user] adds as much as they can to the [src] from the [SB].")
+ return
+ if(istype(I, /obj/item/reagent_containers))
+ var/obj/item/reagent_containers/RC = I
+ if(RC.reagents.total_volume == 0)
+ to_chat(user, "The [I] is empty!")
+ for(var/datum/reagent/R in RC.reagents.reagent_list)
+ if((obj_flags & EMAGGED) || (allowed(usr)))
+ break
+ if(!istype(R, /datum/reagent/medicine))
+ visible_message("The [src] gives out a hearty boop and rejects the [I]. The Sleeper's screen flashes with a pompous \"Medicines only, please.\"")
+ return
+ RC.reagents.trans_to(reagents, 1000)
+ visible_message("[user] adds as much as they can to the [src] from the [I].")
+ return
+
/obj/machinery/sleeper/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !user.Adjacent(target) || !iscarbon(target) || !user.IsAdvancedToolUser())
@@ -130,8 +190,8 @@
open_machine()
/obj/machinery/sleeper/examine(mob/user)
- ..()
- to_chat(user, "Alt-click [src] to [state_open ? "close" : "open"] it.")
+ . = ..()
+ . += "Alt-click [src] to [state_open ? "close" : "open"] it."
/obj/machinery/sleeper/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = FALSE, \
datum/tgui/master_ui = null, datum/ui_state/state = GLOB.notcontained_state)
@@ -141,18 +201,24 @@
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
- ui = new(user, src, ui_key, "sleeper", name, 375, 550, master_ui, state)
+ ui = new(user, src, ui_key, "sleeper", name, 550, 700, master_ui, state)
ui.open()
/obj/machinery/sleeper/ui_data()
var/list/data = list()
data["occupied"] = occupant ? 1 : 0
data["open"] = state_open
+ data["efficiency"] = efficiency
+ data["current_vol"] = reagents.total_volume
+ data["tot_capacity"] = reagents.maximum_volume
data["chems"] = list()
for(var/chem in available_chems)
- var/datum/reagent/R = GLOB.chemical_reagents_list[chem]
- data["chems"] += list(list("name" = R.name, "id" = R.id, "allowed" = chem_allowed(chem)))
+ var/datum/reagent/R = reagents.has_reagent(chem)
+ R = GLOB.chemical_reagents_list[chem]
+ data["synthchems"] += list(list("name" = R.name, "id" = R.id, "synth_allowed" = synth_allowed(chem)))
+ for(var/datum/reagent/R in reagents.reagent_list)
+ data["chems"] += list(list("name" = R.name, "id" = R.id, "vol" = R.volume, "purity" = R.purity, "allowed" = chem_allowed(R.id)))
data["occupant"] = list()
var/mob/living/mob_occupant = occupant
@@ -184,8 +250,15 @@
if(mob_occupant.reagents && mob_occupant.reagents.reagent_list.len)
for(var/datum/reagent/R in mob_occupant.reagents.reagent_list)
data["occupant"]["reagents"] += list(list("name" = R.name, "volume" = R.volume))
+ data["occupant"]["failing_organs"] = list()
+ var/mob/living/carbon/C = mob_occupant
+ if(C)
+ for(var/obj/item/organ/Or in C.getFailingOrgans())
+ if(istype(Or, /obj/item/organ/brain))
+ continue
+ data["occupant"]["failing_organs"] += list(list("name" = Or.name))
+
if(mob_occupant.has_dna()) // Blood-stuff is mostly a copy-paste from the healthscanner.
- var/mob/living/carbon/C = mob_occupant
var/blood_id = C.get_blood_id()
if(blood_id)
data["occupant"]["blood"] = list() // We can start populating this list.
@@ -196,7 +269,7 @@
blood_type = R.name
else
blood_type = blood_id
- data["occupant"]["blood"]["maxBloodVolume"] = BLOOD_VOLUME_NORMAL
+ data["occupant"]["blood"]["maxBloodVolume"] = (BLOOD_VOLUME_NORMAL*C.blood_ratio)
data["occupant"]["blood"]["currentBloodVolume"] = C.blood_volume
data["occupant"]["blood"]["dangerBloodVolume"] = BLOOD_VOLUME_SAFE
data["occupant"]["blood"]["bloodType"] = blood_type
@@ -216,24 +289,49 @@
. = TRUE
if("inject")
var/chem = params["chem"]
+ var/amount = text2num(params["volume"])
if(!is_operational() || !mob_occupant)
return
if(mob_occupant.health < min_health && chem != "epinephrine")
return
- if(inject_chem(chem, usr))
+ if(inject_chem(chem, usr, amount))
. = TRUE
if(scrambled_chems && prob(5))
to_chat(usr, "Chemical system re-route detected, results may not be as expected!")
+ if("synth")
+ var/chem = params["chem"]
+ if(!is_operational())
+ return
+ reagents.add_reagent(chem_buttons[chem], 10) //other_purity = 0.75 for when the mechanics are in
+ if("purge")
+ var/chem = params["chem"]
+ if(allowed(usr))
+ if(!is_operational())
+ return
+ reagents.remove_reagent(chem, 10)
+ return
+ if(chem in available_chems)
+ if(!is_operational())
+ return
+ /*var/datum/reagent/R = reagents.has_reagent(chem) //For when purity effects are in
+ if(R.purity < 0.8)*/
+ reagents.remove_reagent(chem, 10)
+ else
+ visible_message("Access Denied.")
+ playsound(src, 'sound/machines/terminal_prompt_deny.ogg', 50, 0)
+
/obj/machinery/sleeper/emag_act(mob/user)
. = ..()
+ obj_flags |= EMAGGED
scramble_chem_buttons()
to_chat(user, "You scramble the sleeper's user interface!")
return TRUE
-/obj/machinery/sleeper/proc/inject_chem(chem, mob/user)
- if((chem in available_chems) && chem_allowed(chem))
- occupant.reagents.add_reagent(chem_buttons[chem], 10) //emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU
+//trans to
+/obj/machinery/sleeper/proc/inject_chem(chem, mob/user, volume = 10)
+ if(chem_allowed(chem))
+ reagents.trans_id_to(occupant, chem, volume)//emag effect kicks in here so that the "intended" chem is used for all checks, for extra FUUU
if(user)
log_combat(user, occupant, "injected [chem] into", addition = "via [src]")
return TRUE
@@ -246,6 +344,14 @@
var/occ_health = mob_occupant.health > min_health || chem == "epinephrine"
return amount && occ_health
+/obj/machinery/sleeper/proc/synth_allowed(chem)
+ var/datum/reagent/R = reagents.has_reagent(chem)
+ if(!R)
+ return TRUE
+ if(R.volume < 50)
+ return TRUE
+ return FALSE
+
/obj/machinery/sleeper/proc/reset_chem_buttons()
scrambled_chems = FALSE
LAZYINITLIST(chem_buttons)
diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm
index e2dcf552c1..ff7383cd9e 100644
--- a/code/game/machinery/_machinery.dm
+++ b/code/game/machinery/_machinery.dm
@@ -454,20 +454,20 @@ Class Procs:
/obj/machinery/examine(mob/user)
. = ..()
if(stat & BROKEN)
- to_chat(user, "It looks broken and non-functional.")
+ . += "It looks broken and non-functional."
if(!(resistance_flags & INDESTRUCTIBLE))
if(resistance_flags & ON_FIRE)
- to_chat(user, "It's on fire!")
+ . += "It's on fire!"
var/healthpercent = (obj_integrity/max_integrity) * 100
switch(healthpercent)
if(50 to 99)
- to_chat(user, "It looks slightly damaged.")
+ . += "It looks slightly damaged."
if(25 to 50)
- to_chat(user, "It appears heavily damaged.")
+ . += "It appears heavily damaged."
if(0 to 25)
- to_chat(user, "It's falling apart!")
+ . += "It's falling apart!"
if(user.research_scanner && component_parts)
- to_chat(user, display_parts(user, TRUE))
+ . += display_parts(user, TRUE)
//called on machinery construction (i.e from frame to machinery) but not on initialization
/obj/machinery/proc/on_construction()
diff --git a/code/game/machinery/ai_slipper.dm b/code/game/machinery/ai_slipper.dm
index cac29404d2..1703ce57d1 100644
--- a/code/game/machinery/ai_slipper.dm
+++ b/code/game/machinery/ai_slipper.dm
@@ -14,8 +14,8 @@
req_access = list(ACCESS_AI_UPLOAD)
/obj/machinery/ai_slipper/examine(mob/user)
- ..()
- to_chat(user, "It has [uses] uses of foam remaining.")
+ . = ..()
+ . += "It has [uses] uses of foam remaining."
/obj/machinery/ai_slipper/power_change()
if(stat & BROKEN)
diff --git a/code/game/machinery/aug_manipulator.dm b/code/game/machinery/aug_manipulator.dm
index 8419f5803c..b9d63e5771 100644
--- a/code/game/machinery/aug_manipulator.dm
+++ b/code/game/machinery/aug_manipulator.dm
@@ -11,9 +11,9 @@
var/static/list/style_list_icons = list("standard" = 'icons/mob/augmentation/augments.dmi', "engineer" = 'icons/mob/augmentation/augments_engineer.dmi', "security" = 'icons/mob/augmentation/augments_security.dmi', "mining" = 'icons/mob/augmentation/augments_mining.dmi')
/obj/machinery/aug_manipulator/examine(mob/user)
- ..()
+ . = ..()
if(storedpart)
- to_chat(user, "Alt-click to eject the limb.")
+ . += "Alt-click to eject the limb."
/obj/machinery/aug_manipulator/Initialize()
initial_icon_state = initial(icon_state)
diff --git a/code/game/machinery/cell_charger.dm b/code/game/machinery/cell_charger.dm
index fb384d55ae..1839e44e3b 100644
--- a/code/game/machinery/cell_charger.dm
+++ b/code/game/machinery/cell_charger.dm
@@ -24,10 +24,10 @@
add_overlay("ccharger-o[newlevel]")
/obj/machinery/cell_charger/examine(mob/user)
- ..()
- to_chat(user, "There's [charging ? "a" : "no"] cell in the charger.")
+ . = ..()
+ . += "There's [charging ? "a" : "no"] cell in the charger."
if(charging)
- to_chat(user, "Current charge: [round(charging.percent(), 1)]%.")
+ . += "Current charge: [round(charging.percent(), 1)]%."
/obj/machinery/cell_charger/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/stock_parts/cell) && !panel_open)
diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm
index e65da0fcff..e683d67be2 100644
--- a/code/game/machinery/cloning.dm
+++ b/code/game/machinery/cloning.dm
@@ -93,20 +93,20 @@
to_chat(user, "You flip the write-protect tab to [read_only ? "protected" : "unprotected"].")
/obj/item/disk/data/examine(mob/user)
- ..()
- to_chat(user, "The write-protect tab is set to [read_only ? "protected" : "unprotected"].")
+ . = ..()
+ . += "The write-protect tab is set to [read_only ? "protected" : "unprotected"]."
//Clonepod
/obj/machinery/clonepod/examine(mob/user)
- ..()
+ . = ..()
var/mob/living/mob_occupant = occupant
if(mess)
- to_chat(user, "It's filled with blood and viscera. You swear you can see it moving...")
+ . += "It's filled with blood and viscera. You swear you can see it moving..."
if(is_operational() && mob_occupant)
if(mob_occupant.stat != DEAD)
- to_chat(user, "Current clone cycle is [round(get_completion())]% complete.")
+ . += "Current clone cycle is [round(get_completion())]% complete."
/obj/machinery/clonepod/return_air()
// We want to simulate the clone not being in contact with
diff --git a/code/game/machinery/computer/arcade/orion_trail.dm b/code/game/machinery/computer/arcade/orion_trail.dm
index 023b1048ce..c8c7bc1319 100644
--- a/code/game/machinery/computer/arcade/orion_trail.dm
+++ b/code/game/machinery/computer/arcade/orion_trail.dm
@@ -762,13 +762,13 @@
var/active = 0 //if the ship is on
/obj/item/orion_ship/examine(mob/user)
- ..()
+ . = ..()
if(!(in_range(user, src)))
return
if(!active)
- to_chat(user, "There's a little switch on the bottom. It's flipped down.")
+ . += "There's a little switch on the bottom. It's flipped down."
else
- to_chat(user, "There's a little switch on the bottom. It's flipped up.")
+ . += "There's a little switch on the bottom. It's flipped up."
/obj/item/orion_ship/attack_self(mob/user) //Minibomb-level explosion. Should probably be more because of how hard it is to survive the machine! Also, just over a 5-second fuse
if(active)
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 11935e2bfc..1bafa73aaa 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -17,13 +17,7 @@
network += lowertext(i)
/obj/machinery/computer/security/check_eye(mob/user)
- if(CHECK_BITFIELD(stat, NOPOWER|BROKEN) || is_blind(user) || !in_view_range(user, src) || !user.canUseTopic(src, !issilicon(user), FALSE))
- user.unset_machine()
- return
- if(!(user in watchers))
- user.unset_machine()
- return
- if(!watchers[user])
+ if(!can_interact(user) || !(user in watchers) || !watchers[user])
user.unset_machine()
return
var/obj/machinery/camera/C = watchers[user]
@@ -41,55 +35,50 @@
M.unset_machine() //to properly reset the view of the users if the console is deleted.
return ..()
-/obj/machinery/computer/security/attack_hand(mob/user)
+/obj/machinery/computer/security/can_interact(mob/user)
+ if((!issilicon(user) && !Adjacent(user)) || is_blind(user) || !in_view_range(user, src))
+ return FALSE
+ return ..()
+
+/obj/machinery/computer/security/interact(mob/user, special_state)
. = ..()
- if(.)
- return
- if(stat)
+ if (ismob(user) && !isliving(user)) // ghosts don't need cameras
return
if (!network)
- throw EXCEPTION("No camera network")
+ CRASH("No camera network")
user.unset_machine()
- return
+ return FALSE
if (!(islist(network)))
- throw EXCEPTION("Camera network is not a list")
+ CRASH("Camera network is not a list")
user.unset_machine()
- return
- if(..())
- user.unset_machine()
- return
+ return FALSE
var/list/camera_list = get_available_cameras()
if(!(user in watchers))
for(var/Num in camera_list)
var/obj/machinery/camera/CAM = camera_list[Num]
- if(istype(CAM))
- if(CAM.can_use())
- watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants.
- break
+ if(istype(CAM) && CAM.can_use())
+ watchers[user] = CAM //let's give the user the first usable camera, and then let him change to the camera he wants.
+ break
if(!(user in watchers))
user.unset_machine() // no usable camera on the network, we disconnect the user from the computer.
- return
+ return FALSE
playsound(src, 'sound/machines/terminal_prompt.ogg', 25, 0)
use_camera_console(user)
/obj/machinery/computer/security/proc/use_camera_console(mob/user)
var/list/camera_list = get_available_cameras()
var/t = input(user, "Which camera should you change to?") as null|anything in camera_list
- if(user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine.
+ if(!src || user.machine != src) //while we were choosing we got disconnected from our computer or are using another machine.
return
- if(!t)
+ if(!t || t == "Cancel")
user.unset_machine()
playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
return
var/obj/machinery/camera/C = camera_list[t]
- if(t == "Cancel")
- user.unset_machine()
- playsound(src, 'sound/machines/terminal_off.ogg', 25, 0)
- return
- if(!C || !C.can_use() || CHECK_BITFIELD(stat, NOPOWER|BROKEN) || is_blind(user) || !in_view_range(user, src) || !user.canUseTopic(src, !issilicon(user), FALSE))
+ if(!C || !C.can_use() || !can_interact(user))
user.unset_machine()
return FALSE
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index fa0cf367d9..e8e8e1cdd6 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -63,7 +63,7 @@ GLOBAL_VAR_INIT(time_last_changed_position, 0)
/obj/machinery/computer/card/examine(mob/user)
. = ..()
if(inserted_scan_id || inserted_modify_id)
- to_chat(user, "Alt-click to eject the ID card.")
+ . += "Alt-click to eject the ID card."
/obj/machinery/computer/card/attackby(obj/I, mob/user, params)
if(isidcard(I))
diff --git a/code/game/machinery/computer/communications.dm b/code/game/machinery/computer/communications.dm
index b5cb066b3a..a8b4608b36 100755
--- a/code/game/machinery/computer/communications.dm
+++ b/code/game/machinery/computer/communications.dm
@@ -42,12 +42,6 @@
. = ..()
GLOB.shuttle_caller_list += src
-/obj/machinery/computer/communications/process()
- if(..())
- var/ai_autoupdate = aistate != STATE_STATUSDISPLAY && aistate != STATE_CALLSHUTTLE && aistate != STATE_PURCHASE && aistate != STATE_VIEWMESSAGE
- var/machine_user_autoupdate = state != STATE_STATUSDISPLAY && state != STATE_CALLSHUTTLE && state != STATE_PURCHASE && state != STATE_VIEWMESSAGE
- updateDialog(machine_user_autoupdate,ai_autoupdate)
-
/obj/machinery/computer/communications/Topic(href, href_list)
if(..())
return
@@ -586,8 +580,6 @@
popup.set_content(dat)
popup.open()
- popup.set_content(dat)
- popup.open()
/obj/machinery/computer/communications/proc/get_javascript_header(form_id)
var/dat = {"