mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-21 12:08:55 +01:00
+37






![tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com>](/assets/img/avatar_default.png)


Alexis
GitHub
tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com>
ArcaneMusic
MrMelbert
Rhials
rageguy505
LemonInTheDark
John Willard
Aliceee2ch
Time-Green
Tsar-Salat
SmArtKar
Maxipat
SyncIt21
deltanedas
SimplyLogan
loganuk
Leland Kemble
FalloutFalcon
Roxy
Lucy
siliconOpossum
Isratosh
TheRyeGuyWhoWillNowDie
Neocloudy
Alexander V.
ElGitificador
Twaticus
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bloop
Cameron Lennox
Tim
Iamgoofball
Layzu666
Arturlang
_0Steven
mrmanlikesbt
Ben10Omintrix
John F. Kennedy
Cursor
Josh
Josh Powell
Yobrocharlie
Hardly3D
shayoki
LT3
21b4095dfd
Upstream 04/17/2026 fixes https://github.com/Bubberstation/Bubberstation/issues/5549 --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: tgstation-ci[bot] <179393467+tgstation-ci[bot]@users.noreply.github.com> Co-authored-by: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com> Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Co-authored-by: Rhials <28870487+Rhials@users.noreply.github.com> Co-authored-by: rageguy505 <54517726+rageguy505@users.noreply.github.com> Co-authored-by: LemonInTheDark <58055496+LemonInTheDark@users.noreply.github.com> Co-authored-by: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Co-authored-by: Aliceee2ch <160794176+Aliceee2ch@users.noreply.github.com> Co-authored-by: Time-Green <7501474+Time-Green@users.noreply.github.com> Co-authored-by: Tsar-Salat <62388554+Tsar-Salat@users.noreply.github.com> Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com> Co-authored-by: Maxipat <108554989+Maxipat112@users.noreply.github.com> Co-authored-by: SyncIt21 <110812394+SyncIt21@users.noreply.github.com> Co-authored-by: deltanedas <39013340+deltanedas@users.noreply.github.com> Co-authored-by: SimplyLogan <47579821+loganuk@users.noreply.github.com> Co-authored-by: loganuk <fakeemail123@aol.com> Co-authored-by: Leland Kemble <70413276+lelandkemble@users.noreply.github.com> Co-authored-by: FalloutFalcon <86381784+FalloutFalcon@users.noreply.github.com> Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com> Co-authored-by: Lucy <lucy@absolucy.moe> Co-authored-by: siliconOpossum <138069572+siliconOpossum@users.noreply.github.com> Co-authored-by: Isratosh <Isratosh@hotmail.com> Co-authored-by: TheRyeGuyWhoWillNowDie <70169560+TheRyeGuyWhoWillNowDie@users.noreply.github.com> Co-authored-by: Neocloudy <88008002+Neocloudy@users.noreply.github.com> Co-authored-by: Alexander V. <volas@ya.ru> Co-authored-by: ElGitificador <168473461+ElGitificador@users.noreply.github.com> Co-authored-by: Twaticus <46540570+Twaticus@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com> Co-authored-by: Cameron Lennox <killer65311@gmail.com> Co-authored-by: Tim <timothymtorres@gmail.com> Co-authored-by: Iamgoofball <iamgoofball@gmail.com> Co-authored-by: Layzu666 <121319428+Layzu666@users.noreply.github.com> Co-authored-by: Arturlang <24881678+Arturlang@users.noreply.github.com> Co-authored-by: _0Steven <42909981+00-Steven@users.noreply.github.com> Co-authored-by: mrmanlikesbt <99309552+mrmanlikesbt@users.noreply.github.com> Co-authored-by: Ben10Omintrix <138636438+Ben10Omintrix@users.noreply.github.com> Co-authored-by: John F. Kennedy <54908920+MacaroniCritter@users.noreply.github.com> Co-authored-by: Cursor <102828457+theselfish@users.noreply.github.com> Co-authored-by: Josh <josh.adam.powell@gmail.com> Co-authored-by: Josh Powell <josh.powell@softwire.com> Co-authored-by: Yobrocharlie <Charliemiller5617@gmail.com> Co-authored-by: Hardly3D <66234359+Hardly3D@users.noreply.github.com> Co-authored-by: shayoki <96078776+shayoki@users.noreply.github.com> Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
269 lines
9.5 KiB
Plaintext
269 lines
9.5 KiB
Plaintext
#define DREAMING_SOURCE "dreaming_source"
|
|
|
|
/**
|
|
* Begins the dreaming process on a sleeping carbon.
|
|
*
|
|
* Checks a 10% chance and whether or not the carbon this is called on is already dreaming. If
|
|
* the prob() passes and there are no dream images left to display, a new dream is constructed.
|
|
*/
|
|
|
|
/mob/living/carbon/proc/handle_dreams()
|
|
if(!HAS_TRAIT(src, TRAIT_DREAMING) && prob(10))
|
|
dream()
|
|
|
|
/**
|
|
* Generates a dream sequence to be displayed to the sleeper.
|
|
*
|
|
* Generates the "dream" to display to the sleeper. A dream consists of a subject, a verb, and (most of the time) an object, displayed in sequence to the sleeper.
|
|
* Dreams are generated as a list of strings stored inside dream_fragments, which is passed to and displayed in dream_sequence().
|
|
* Bedsheets on the sleeper will provide a custom subject for the dream, pulled from the dream_messages on each bedsheet.
|
|
*/
|
|
|
|
/mob/living/carbon/proc/dream()
|
|
set waitfor = FALSE
|
|
var/datum/dream/chosen_dream
|
|
|
|
var/can_heretic_dream = ((IS_HERETIC(src) || HAS_TRAIT(src, TRAIT_HERETICAL_DREAMS)) && !mob_mood.get_mood_event("mansus_dream_fatigue"))
|
|
|
|
if (can_heretic_dream && GLOB.reality_smash_track.smashes.len)
|
|
/// If someone attempts to have a heretical dream and there is an avaliable influence, one is picked randomly for a dream
|
|
chosen_dream = new /datum/dream/heretic(pick(GLOB.reality_smash_track.smashes))
|
|
else if (can_heretic_dream && !IS_HERETIC(src) && !GLOB.reality_smash_track.smashes.len)
|
|
/// If a non-heretic attempts to have a heretic dream, but there aren't any influences due to there not being any real heretics, they are instead given a fake dream based on a random location.
|
|
chosen_dream = new /datum/dream/heretic(get_safe_random_station_turf_equal_weight())
|
|
else
|
|
chosen_dream = pick_weight(GLOB.dreams)
|
|
|
|
ADD_TRAIT(src, TRAIT_DREAMING, DREAMING_SOURCE)
|
|
dream_sequence(chosen_dream.GenerateDream(src), chosen_dream)
|
|
|
|
/**
|
|
* Displays the passed list of dream fragments to a sleeping carbon.
|
|
*
|
|
* Displays the first string of the passed dream fragments, then either ends the dream sequence
|
|
* or performs a callback on itself depending on if there are any remaining dream fragments to display.
|
|
*
|
|
* Arguments:
|
|
* * dream_fragments - A list of strings, in the order they will be displayed.
|
|
* * current_dream - The dream datum used for the current dream
|
|
*/
|
|
|
|
/mob/living/carbon/proc/dream_sequence(list/dream_fragments, datum/dream/current_dream)
|
|
if(stat != UNCONSCIOUS || HAS_TRAIT(src, TRAIT_CRITICAL_CONDITION))
|
|
REMOVE_TRAIT(src, TRAIT_DREAMING, DREAMING_SOURCE)
|
|
current_dream.OnDreamEnd(src)
|
|
return
|
|
var/next_message = dream_fragments[1]
|
|
dream_fragments.Cut(1,2)
|
|
|
|
if(istype(next_message, /datum/callback))
|
|
var/datum/callback/something_happens = next_message
|
|
next_message = something_happens.InvokeAsync(src)
|
|
|
|
to_chat(src, span_notice("<i>... [next_message] ...</i>"))
|
|
|
|
if(LAZYLEN(dream_fragments))
|
|
var/next_wait = rand(10, 30)
|
|
if(current_dream.sleep_until_finished)
|
|
AdjustSleeping(next_wait)
|
|
addtimer(CALLBACK(src, PROC_REF(dream_sequence), dream_fragments, current_dream), next_wait)
|
|
else
|
|
REMOVE_TRAIT(src, TRAIT_DREAMING, DREAMING_SOURCE)
|
|
current_dream.OnDreamEnd(src)
|
|
|
|
//-------------------------
|
|
// DREAM DATUMS
|
|
|
|
GLOBAL_LIST_INIT(dreams, populate_dream_list())
|
|
|
|
/proc/populate_dream_list()
|
|
var/list/output = list()
|
|
for(var/datum/dream/dream_type as anything in subtypesof(/datum/dream))
|
|
output[new dream_type] = initial(dream_type.weight)
|
|
return output
|
|
|
|
/**
|
|
* Contains all the behavior needed to play a kind of dream.
|
|
* All dream types get randomly selected from based on weight when an appropriate mobs dreams.
|
|
*/
|
|
/datum/dream
|
|
/// The relative chance this dream will be randomly selected
|
|
var/weight = 0
|
|
|
|
/// Causes the mob to sleep long enough for the dream to finish if begun
|
|
var/sleep_until_finished = FALSE
|
|
|
|
/**
|
|
* Called when beginning a new dream for the dreamer.
|
|
* Gives back a list of dream events. Events can be text or callbacks that return text.
|
|
*/
|
|
/datum/dream/proc/GenerateDream(mob/living/carbon/dreamer)
|
|
return list()
|
|
|
|
/**
|
|
* Called when the dream ends or is interrupted.
|
|
*/
|
|
/datum/dream/proc/OnDreamEnd(mob/living/carbon/dreamer)
|
|
return
|
|
|
|
/// The classic random dream of various words that might form a cohesive narrative, but usually wont
|
|
/datum/dream/random
|
|
weight = 1000
|
|
|
|
/datum/dream/random/GenerateDream(mob/living/carbon/dreamer)
|
|
var/list/custom_dream_nouns = list()
|
|
var/fragment = ""
|
|
|
|
for(var/obj/item/bedsheet/sheet in dreamer.loc)
|
|
custom_dream_nouns += sheet.dream_messages
|
|
|
|
. = list()
|
|
. += "you see"
|
|
|
|
//Subject
|
|
if(custom_dream_nouns.len && prob(90))
|
|
fragment += pick(custom_dream_nouns)
|
|
else
|
|
fragment += pick(GLOB.dream_strings)
|
|
|
|
if(prob(50)) //Replace the adjective space with an adjective, or just get rid of it
|
|
fragment = replacetext(fragment, "%ADJECTIVE%", pick(GLOB.adjectives))
|
|
else
|
|
fragment = replacetext(fragment, "%ADJECTIVE% ", "")
|
|
if(findtext(fragment, "%A% "))
|
|
fragment = "\a [replacetext(fragment, "%A% ", "")]"
|
|
. += fragment
|
|
|
|
//Verb
|
|
fragment = ""
|
|
if(prob(50))
|
|
if(prob(35))
|
|
fragment += "[pick(GLOB.adverbs)] "
|
|
fragment += pick(GLOB.ing_verbs)
|
|
else
|
|
fragment += "will "
|
|
fragment += pick(GLOB.verbs)
|
|
. += fragment
|
|
|
|
if(prob(25))
|
|
return
|
|
|
|
//Object
|
|
fragment = ""
|
|
fragment += pick(GLOB.dream_strings)
|
|
if(prob(50))
|
|
fragment = replacetext(fragment, "%ADJECTIVE%", pick(GLOB.adjectives))
|
|
else
|
|
fragment = replacetext(fragment, "%ADJECTIVE% ", "")
|
|
if(findtext(fragment, "%A% "))
|
|
fragment = "\a [replacetext(fragment, "%A% ", "")]"
|
|
. += fragment
|
|
|
|
/// Dream plays a random sound at you, chosen from all sounds in the folder
|
|
/datum/dream/hear_something
|
|
weight = 500
|
|
|
|
var/reserved_sound_channel
|
|
|
|
/datum/dream/hear_something/New()
|
|
. = ..()
|
|
RegisterSignal(SSsounds, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(ReserveSoundChannel))
|
|
|
|
/datum/dream/hear_something/GenerateDream(mob/living/carbon/dreamer)
|
|
. = ..()
|
|
. += pick("you wind up a toy", "you hear something strange", "you pick out a record to play", "you hit shuffle on your music player")
|
|
. += CALLBACK(src, PROC_REF(PlayRandomSound))
|
|
. += "it reminds you of something"
|
|
|
|
/datum/dream/hear_something/OnDreamEnd(mob/living/carbon/dreamer)
|
|
. = ..()
|
|
// In case we play some long ass music track
|
|
addtimer(CALLBACK(src, PROC_REF(StopSound), dreamer), 5 SECONDS)
|
|
|
|
/datum/dream/hear_something/proc/ReserveSoundChannel()
|
|
reserved_sound_channel = SSsounds.reserve_sound_channel(src)
|
|
UnregisterSignal(SSsounds, COMSIG_SUBSYSTEM_POST_INITIALIZE)
|
|
|
|
/datum/dream/hear_something/proc/PlayRandomSound(mob/living/carbon/dreamer)
|
|
var/sound/random_sound = sound(pick(SSsounds.all_sounds), channel=reserved_sound_channel)
|
|
random_sound.status = SOUND_STREAM
|
|
SEND_SOUND(dreamer, random_sound)
|
|
return "you hear something you weren't expecting!"
|
|
|
|
/datum/dream/hear_something/proc/StopSound(mob/living/carbon/dreamer)
|
|
SEND_SOUND(dreamer, sound(channel=reserved_sound_channel))
|
|
|
|
/// Heretics can see dreams about random machinery from the perspective of a random unused influence
|
|
/datum/dream/heretic
|
|
sleep_until_finished = TRUE
|
|
/// The location of the influence (or lack thereof in the case of a fake dream) we will be dreaming about
|
|
var/atom/dream_center
|
|
/// The distance to the objects visible from the influence during the dream
|
|
var/dream_view_range = 5
|
|
var/list/what_you_can_see = list(
|
|
/obj/item,
|
|
/obj/structure,
|
|
/obj/machinery,
|
|
)
|
|
var/static/list/what_you_cant_see = typecacheof(list(
|
|
// Underfloor stuff and default wallmounts
|
|
/obj/item/radio/intercom,
|
|
/obj/structure/cable,
|
|
/obj/structure/disposalpipe/segment,
|
|
/obj/machinery/atmospherics/pipe/smart/manifold4w,
|
|
/obj/machinery/atmospherics/components/unary/vent_scrubber,
|
|
/obj/machinery/atmospherics/components/unary/vent_pump,
|
|
/obj/machinery/duct,
|
|
/obj/machinery/navbeacon,
|
|
/obj/machinery/power/terminal,
|
|
/obj/machinery/power/apc,
|
|
/obj/machinery/light_switch,
|
|
/obj/machinery/light,
|
|
/obj/machinery/camera,
|
|
/obj/machinery/door/firedoor,
|
|
/obj/machinery/firealarm,
|
|
/obj/machinery/airalarm,
|
|
/obj/structure/window/fulltile,
|
|
/obj/structure/window/reinforced/fulltile,
|
|
))
|
|
/// Cached list of allowed typecaches for each type in what_you_can_see
|
|
var/static/list/allowed_typecaches_by_root_type = null
|
|
|
|
/datum/dream/heretic/New(atom/dream_center)
|
|
src.dream_center = dream_center
|
|
|
|
/datum/dream/heretic/GenerateDream(mob/living/carbon/dreamer)
|
|
. = list()
|
|
. += "You wander through the forest of Mansus"
|
|
. += "There is a " + pick("pond", "well", "lake", "puddle", "stream", "spring", "brook", "marsh")
|
|
|
|
dreamer.add_mood_event("mansus_dream_fatigue", /datum/mood_event/mansus_dream_fatigue)
|
|
|
|
if(isnull(allowed_typecaches_by_root_type))
|
|
allowed_typecaches_by_root_type = list()
|
|
for(var/type in what_you_can_see)
|
|
allowed_typecaches_by_root_type[type] = typecacheof(type) - what_you_cant_see
|
|
|
|
var/list/all_objects = oview(dream_view_range, dream_center)
|
|
var/something_found = FALSE
|
|
for(var/object_type in allowed_typecaches_by_root_type)
|
|
var/list/filtered_objects = typecache_filter_list(all_objects, allowed_typecaches_by_root_type[object_type])
|
|
if(filtered_objects.len)
|
|
if (!something_found)
|
|
. += "Its waters reflect"
|
|
something_found = TRUE
|
|
var/obj/found_object = pick(filtered_objects)
|
|
. += initial(found_object.name)
|
|
if(!something_found)
|
|
. += pick("It's pitch black", "The reflections are vague", "You stroll aimlessly")
|
|
else
|
|
. += "The images fade in the ripples"
|
|
. += "You feel exhausted"
|
|
|
|
/datum/mood_event/mansus_dream_fatigue
|
|
description = "I must recover before I can dream of Mansus again."
|
|
mood_change = -2
|
|
timeout = 5 MINUTES
|
|
|
|
#undef DREAMING_SOURCE
|