Cleans up mood and mood-related code (#90162)

## About The Pull Request

One of my upcoming PRs affects a significant chunk of the codebase so
I'm cleaning up messes that I've found along the way.
This PR adds wrappers for adjusting sanity/checking if a mob already has
a certain moodlet, fixes an oversight where attempting to set sanity
over passed maximum would abort the change outright (instead of actually
capping it out), moved jolly and depression processing into quirks
themselves (instead of having dedicated traits for them used solely by
said quirks and nothing else that are constantly checked for by mood
datums), and rewrote how blessings return their results to move omen's
deletion on blessing effect from constantly checking mood for a blessing
moodlet to a comsig.

## Why It's Good For The Game

Less jank handling of certain mechanics, we ***really*** shouldn't be
checking for blessings every time mood of all things is updated.

## Changelog
🆑
fix: Adjusting sanity over the allowed maximum will no longer completely
halt the change, and instead actually cap it at the maximum value.
code: Cleaned up mood and mood-adjacent code.
/🆑
This commit is contained in:
SmArtKar
2025-03-24 13:53:03 +01:00
committed by GitHub
parent 6db02f5cc2
commit cf131db497
27 changed files with 236 additions and 194 deletions
@@ -319,3 +319,6 @@
/// Allows mobs to override how they perceive others when examining
#define COMSIG_LIVING_PERCEIVE_EXAMINE_NAME "living_perceive_examine_name"
#define COMPONENT_EXAMINE_NAME_OVERRIDEN (1<<0)
/// From /obj/item/book/bible/attack() : (mob/living/user, obj/item/book/bible/bible, bless_result)
#define COMSIG_LIVING_BLESSED "living_blessed"
-49
View File
@@ -236,54 +236,6 @@
#define SCREWYHUD_DEAD 2
#define SCREWYHUD_HEALTHY 3
//Threshold levels for beauty for humans
#define BEAUTY_LEVEL_HORRID -66
#define BEAUTY_LEVEL_BAD -33
#define BEAUTY_LEVEL_DECENT 33
#define BEAUTY_LEVEL_GOOD 66
#define BEAUTY_LEVEL_GREAT 100
//Moods levels for humans
#define MOOD_HAPPY4 15
#define MOOD_HAPPY3 10
#define MOOD_HAPPY2 6
#define MOOD_HAPPY1 2
#define MOOD_NEUTRAL 0
#define MOOD_SAD1 -3
#define MOOD_SAD2 -7
#define MOOD_SAD3 -15
#define MOOD_SAD4 -20
//Moods levels for humans
#define MOOD_LEVEL_HAPPY4 9
#define MOOD_LEVEL_HAPPY3 8
#define MOOD_LEVEL_HAPPY2 7
#define MOOD_LEVEL_HAPPY1 6
#define MOOD_LEVEL_NEUTRAL 5
#define MOOD_LEVEL_SAD1 4
#define MOOD_LEVEL_SAD2 3
#define MOOD_LEVEL_SAD3 2
#define MOOD_LEVEL_SAD4 1
//Sanity values for humans
#define SANITY_MAXIMUM 150
#define SANITY_GREAT 125
#define SANITY_NEUTRAL 100
#define SANITY_DISTURBED 75
#define SANITY_UNSTABLE 50
#define SANITY_CRAZY 25
#define SANITY_INSANE 0
//Sanity levels for humans
#define SANITY_LEVEL_GREAT 1
#define SANITY_LEVEL_NEUTRAL 2
#define SANITY_LEVEL_DISTURBED 3
#define SANITY_LEVEL_UNSTABLE 4
#define SANITY_LEVEL_CRAZY 5
#define SANITY_LEVEL_INSANE 6
/// Equal to the highest sanity level
#define SANITY_LEVEL_MAX SANITY_LEVEL_INSANE
//Nutrition levels for humans
#define NUTRITION_LEVEL_FAT 600
#define NUTRITION_LEVEL_FULL 550
@@ -316,7 +268,6 @@
#define ETHEREAL_CHARGE_OVERLOAD (2.5 * STANDARD_ETHEREAL_CHARGE)
#define ETHEREAL_CHARGE_DANGEROUS (3 * STANDARD_ETHEREAL_CHARGE)
#define CRYSTALIZE_COOLDOWN_LENGTH (120 SECONDS)
#define CRYSTALIZE_PRE_WAIT_TIME (40 SECONDS)
#define CRYSTALIZE_DISARM_WAIT_TIME (120 SECONDS)
+47 -1
View File
@@ -1 +1,47 @@
#define MOOD_CATEGORY_LEGION_CORE "regenerative core"
// Threshold levels for beauty for humans
#define BEAUTY_LEVEL_HORRID -66
#define BEAUTY_LEVEL_BAD -33
#define BEAUTY_LEVEL_DECENT 33
#define BEAUTY_LEVEL_GOOD 66
#define BEAUTY_LEVEL_GREAT 100
// Moods levels for humans
#define MOOD_HAPPY4 15
#define MOOD_HAPPY3 10
#define MOOD_HAPPY2 6
#define MOOD_HAPPY1 2
#define MOOD_NEUTRAL 0
#define MOOD_SAD1 -3
#define MOOD_SAD2 -7
#define MOOD_SAD3 -15
#define MOOD_SAD4 -20
// Moods levels for humans
#define MOOD_LEVEL_HAPPY4 9
#define MOOD_LEVEL_HAPPY3 8
#define MOOD_LEVEL_HAPPY2 7
#define MOOD_LEVEL_HAPPY1 6
#define MOOD_LEVEL_NEUTRAL 5
#define MOOD_LEVEL_SAD1 4
#define MOOD_LEVEL_SAD2 3
#define MOOD_LEVEL_SAD3 2
#define MOOD_LEVEL_SAD4 1
// Sanity values for humans
#define SANITY_MAXIMUM 150
#define SANITY_GREAT 125
#define SANITY_NEUTRAL 100
#define SANITY_DISTURBED 75
#define SANITY_UNSTABLE 50
#define SANITY_CRAZY 25
#define SANITY_INSANE 0
// Sanity levels for humans
#define SANITY_LEVEL_GREAT 1
#define SANITY_LEVEL_NEUTRAL 2
#define SANITY_LEVEL_DISTURBED 3
#define SANITY_LEVEL_UNSTABLE 4
#define SANITY_LEVEL_CRAZY 5
#define SANITY_LEVEL_INSANE 6
/// Equal to the highest sanity level
#define SANITY_LEVEL_MAX SANITY_LEVEL_INSANE
+7
View File
@@ -54,3 +54,10 @@
#define PUNISHMENT_LIGHTNING "lightningbolt"
///brands the sinner
#define PUNISHMENT_BRAND "brand"
/// Failed to bless the target, beat them over the head
#define BLESSING_FAILED "failed"
/// Blessed unsuccessfully, no limbs to heal, robotic limbs, etc
#define BLESSING_IGNORED "ignored"
/// Blessed successfully by healing or whatever
#define BLESSING_SUCCESS "success"
-2
View File
@@ -216,8 +216,6 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_MAGICALLY_GIFTED "magically_gifted"
/// This object innately spawns with fantasy variables already applied (the magical component is given to it on initialize), and thus we never want to give it the component again.
#define TRAIT_INNATELY_FANTASTICAL_ITEM "innately_fantastical_item"
#define TRAIT_DEPRESSION "depression"
#define TRAIT_JOLLY "jolly"
#define TRAIT_NOCRITDAMAGE "no_crit"
/// Prevents shovies and some strong blows such as unarmed punches and (unreliably) tackles the owner down
#define TRAIT_BRAWLING_KNOCKDOWN_BLOCKED "brawling_knockdown_blocked"
-2
View File
@@ -217,7 +217,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_DEAF" = TRAIT_DEAF,
"TRAIT_DEATHCOMA" = TRAIT_DEATHCOMA,
"TRAIT_DEFIB_BLACKLISTED" = TRAIT_DEFIB_BLACKLISTED,
"TRAIT_DEPRESSION" = TRAIT_DEPRESSION,
"TRAIT_DETECTIVES_TASTE" = TRAIT_DETECTIVES_TASTE,
"TRAIT_DETECT_STORM" = TRAIT_DETECT_STORM,
"TRAIT_DIAGNOSTIC_HUD" = TRAIT_DIAGNOSTIC_HUD,
@@ -328,7 +327,6 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_IN_CALL" = TRAIT_IN_CALL,
"TRAIT_IS_WET" = TRAIT_IS_WET,
"TRAIT_IWASBATONED" = TRAIT_IWASBATONED,
"TRAIT_JOLLY" = TRAIT_JOLLY,
"TRAIT_KISS_OF_DEATH" = TRAIT_KISS_OF_DEATH,
"TRAIT_SYNDIE_KISS" = TRAIT_SYNDIE_KISS,
"TRAIT_KNOCKEDOUT" = TRAIT_KNOCKEDOUT,
-2
View File
@@ -79,7 +79,6 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_DEAF" = TRAIT_DEAF,
"TRAIT_DEATHCOMA" = TRAIT_DEATHCOMA,
"TRAIT_DEFIB_BLACKLISTED" = TRAIT_DEFIB_BLACKLISTED,
"TRAIT_DEPRESSION" = TRAIT_DEPRESSION,
"TRAIT_DETECT_STORM" = TRAIT_DETECT_STORM,
"TRAIT_DIAGNOSTIC_HUD" = TRAIT_DIAGNOSTIC_HUD,
"TRAIT_BOT_PATH_HUD" = TRAIT_BOT_PATH_HUD,
@@ -152,7 +151,6 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_INTROVERT" = TRAIT_INTROVERT,
"TRAIT_INVISIBLE_MAN" = TRAIT_INVISIBLE_MAN,
"TRAIT_IWASBATONED" = TRAIT_IWASBATONED,
"TRAIT_JOLLY" = TRAIT_JOLLY,
"TRAIT_KISS_OF_DEATH" = TRAIT_KISS_OF_DEATH,
"TRAIT_KNOCKEDOUT" = TRAIT_KNOCKEDOUT,
"TRAIT_KNOW_ENGI_WIRES" = TRAIT_KNOW_ENGI_WIRES,
+4 -8
View File
@@ -66,11 +66,11 @@
/datum/component/omen/RegisterWithParent()
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(check_accident))
RegisterSignal(parent, COMSIG_ON_CARBON_SLIP, PROC_REF(check_slip))
RegisterSignal(parent, COMSIG_CARBON_MOOD_UPDATE, PROC_REF(check_bless))
RegisterSignal(parent, COMSIG_LIVING_BLESSED, PROC_REF(check_bless))
RegisterSignal(parent, COMSIG_LIVING_DEATH, PROC_REF(check_death))
/datum/component/omen/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_ON_CARBON_SLIP, COMSIG_MOVABLE_MOVED, COMSIG_CARBON_MOOD_UPDATE, COMSIG_LIVING_DEATH))
UnregisterSignal(parent, list(COMSIG_ON_CARBON_SLIP, COMSIG_MOVABLE_MOVED, COMSIG_LIVING_BLESSED, COMSIG_LIVING_DEATH))
/datum/component/omen/proc/consume_omen()
incidents_left--
@@ -218,18 +218,14 @@
return
/// Hijack the mood system to see if we get the blessing mood event to cancel the omen
/datum/component/omen/proc/check_bless(mob/living/our_guy, category)
/datum/component/omen/proc/check_bless(mob/living/our_guy, mob/living/priest, obj/item/book/bible/bible, bless_result)
SIGNAL_HANDLER
if(incidents_left == INFINITY)
return
if(!("blessing" in our_guy.mob_mood.mood_events))
if(incidents_left == INFINITY || bless_result != BLESSING_SUCCESS)
return
playsound(our_guy, 'sound/effects/pray_chaplain.ogg', 40, TRUE)
to_chat(our_guy, span_green("You feel fantastic!"))
qdel(src)
/// Severe deaths. Normally lifts the curse.
+32 -32
View File
@@ -32,10 +32,6 @@
/// List of mood events currently active on this datum
var/list/mood_events = list()
/// Tracks the last mob stat, updates on change
/// Used to stop processing SSmood
var/last_stat = CONSCIOUS
/datum/mood/New(mob/living/mob_to_make_moody)
if (!istype(mob_to_make_moody))
stack_trace("Tried to apply mood to a non-living atom!")
@@ -83,40 +79,31 @@
/datum/mood/process(seconds_per_tick)
switch(mood_level)
if(MOOD_LEVEL_SAD4)
set_sanity(sanity - 0.3 * seconds_per_tick, SANITY_INSANE)
adjust_sanity(-0.3 * seconds_per_tick, SANITY_INSANE)
if(MOOD_LEVEL_SAD3)
set_sanity(sanity - 0.15 * seconds_per_tick, SANITY_INSANE)
adjust_sanity(-0.15 * seconds_per_tick, SANITY_INSANE)
if(MOOD_LEVEL_SAD2)
set_sanity(sanity - 0.1 * seconds_per_tick, SANITY_CRAZY)
adjust_sanity(-0.1 * seconds_per_tick, SANITY_CRAZY)
if(MOOD_LEVEL_SAD1)
set_sanity(sanity - 0.05 * seconds_per_tick, SANITY_UNSTABLE)
adjust_sanity(-0.05 * seconds_per_tick, SANITY_UNSTABLE)
if(MOOD_LEVEL_NEUTRAL)
set_sanity(sanity, SANITY_UNSTABLE) //This makes sure that mood gets increased should you be below the minimum.
adjust_sanity(0, SANITY_UNSTABLE) //This makes sure that mood gets increased should you be below the minimum.
if(MOOD_LEVEL_HAPPY1)
set_sanity(sanity + 0.2 * seconds_per_tick, SANITY_UNSTABLE)
adjust_sanity(0.2 * seconds_per_tick, SANITY_UNSTABLE)
if(MOOD_LEVEL_HAPPY2)
set_sanity(sanity + 0.3 * seconds_per_tick, SANITY_UNSTABLE)
adjust_sanity(0.3 * seconds_per_tick, SANITY_UNSTABLE)
if(MOOD_LEVEL_HAPPY3)
set_sanity(sanity + 0.4 * seconds_per_tick, SANITY_NEUTRAL, SANITY_MAXIMUM)
adjust_sanity(0.4 * seconds_per_tick, SANITY_NEUTRAL, SANITY_MAXIMUM)
if(MOOD_LEVEL_HAPPY4)
set_sanity(sanity + 0.6 * seconds_per_tick, SANITY_NEUTRAL, SANITY_MAXIMUM)
adjust_sanity(0.6 * seconds_per_tick, SANITY_NEUTRAL, SANITY_MAXIMUM)
// 0.416% is 15 successes / 3600 seconds. Calculated with 2 minute
// mood runtime, so 50% average uptime across the hour.
if(HAS_TRAIT(mob_parent, TRAIT_DEPRESSION) && SPT_PROB(0.416, seconds_per_tick))
add_mood_event("depression", /datum/mood_event/depression)
if(HAS_TRAIT(mob_parent, TRAIT_JOLLY) && SPT_PROB(0.416, seconds_per_tick))
add_mood_event("jolly", /datum/mood_event/jolly)
/datum/mood/proc/handle_mob_death(datum/source)
/datum/mood/proc/handle_mob_death(datum/source, new_stat, old_stat)
SIGNAL_HANDLER
if (last_stat == DEAD && mob_parent.stat != DEAD)
if (old_stat == DEAD && new_stat != DEAD)
START_PROCESSING(SSmood, src)
else if (last_stat != DEAD && mob_parent.stat == DEAD)
else if (old_stat != DEAD && new_stat == DEAD)
STOP_PROCESSING(SSmood, src)
last_stat = mob_parent.stat
/// Handles mood given by nutrition
/datum/mood/proc/update_nutrition_moodlets()
@@ -172,15 +159,15 @@
var/datum/mood_event/the_event
if (mood_events[category])
the_event = mood_events[category]
if (the_event.type != type)
clear_mood_event(category)
else
if (the_event.type == type)
if (the_event.timeout)
if (!isnull(mood_to_copy_from))
the_event.timeout = mood_to_copy_from.timeout
addtimer(CALLBACK(src, PROC_REF(clear_mood_event), category), the_event.timeout, (TIMER_UNIQUE|TIMER_OVERRIDE))
qdel(mood_to_copy_from)
return // Don't need to update the event.
clear_mood_event(category)
var/list/params = args.Copy(3)
params.Insert(1, mob_parent)
@@ -216,6 +203,9 @@
qdel(event)
update_mood()
/datum/mood/proc/get_mood_event(category)
return mood_events[category]
/// Updates the mobs mood.
/// Called after mood events have been added/removed.
/datum/mood/proc/update_mood()
@@ -224,13 +214,12 @@
mood = 0
shown_mood = 0
SEND_SIGNAL(mob_parent, COMSIG_CARBON_MOOD_UPDATE)
for(var/category in mood_events)
var/datum/mood_event/the_event = mood_events[category]
mood += the_event.mood_change
if (!the_event.hidden)
shown_mood += the_event.mood_change
mood *= mood_modifier
shown_mood *= mood_modifier
@@ -255,6 +244,7 @@
mood_level = MOOD_LEVEL_HAPPY4
update_mood_icon()
SEND_SIGNAL(mob_parent, COMSIG_CARBON_MOOD_UPDATE)
/// Updates the mob's mood icon
/datum/mood/proc/update_mood_icon()
@@ -510,10 +500,16 @@
// If the new amount would move towards the acceptable range faster then use it instead
if(amount < minimum && sanity < minimum)
amount = sanity + 0.7
if((!override && HAS_TRAIT(mob_parent, TRAIT_UNSTABLE)) || amount > maximum)
if(!override && HAS_TRAIT(mob_parent, TRAIT_UNSTABLE))
amount = min(sanity, amount)
if (amount > maximum)
amount = min(amount, maximum)
if(amount == sanity) //Prevents stuff from flicking around.
return
sanity = amount
SEND_SIGNAL(mob_parent, COMSIG_CARBON_SANITY_UPDATE, amount)
switch(sanity)
@@ -556,6 +552,10 @@
update_mood_icon()
/// Adjusts sanity by a value
/datum/mood/proc/adjust_sanity(amount, minimum = SANITY_INSANE, maximum = SANITY_GREAT, override = FALSE)
set_sanity(sanity + amount, minimum, maximum, override)
/// Sets the insanity effect on the mob
/datum/mood/proc/set_insanity_effect(newval)
if (newval == insanity_effect)
@@ -575,7 +575,7 @@
/// Helper to forcefully drain sanity
/datum/mood/proc/direct_sanity_drain(amount)
set_sanity(sanity + amount, override = TRUE)
adjust_sanity(amount, override = TRUE)
/**
* Returns true if you already have a mood from a provided category.
@@ -80,6 +80,7 @@
/datum/quirk/all_nighter/process(seconds_per_tick)
var/happy_camper = TRUE
var/beauty_sleep = TRUE
var/all_nighter = quirk_holder.mob_mood?.get_mood_event("all_nighter")
if(quirk_holder.IsSleeping())
five_more_minutes += SLEEP_BANK_MULTIPLIER * seconds_per_tick
@@ -93,9 +94,9 @@
happy_camper = FALSE
//adjusts the mood event accordingly
if(("all_nighter" in quirk_holder.mob_mood?.mood_events) && happy_camper)
if(all_nighter && happy_camper)
quirk_holder.clear_mood_event("all_nighter", /datum/mood_event/all_nighter)
if(!("all_nighter" in quirk_holder.mob_mood?.mood_events) && !happy_camper)
if(!all_nighter && !happy_camper)
quirk_holder.add_mood_event("all_nighter", /datum/mood_event/all_nighter)
to_chat(quirk_holder, span_danger("You start feeling tired again."))
@@ -2,11 +2,19 @@
name = "Depression"
desc = "You sometimes just hate life."
icon = FA_ICON_FROWN
mob_trait = TRAIT_DEPRESSION
value = -3
gain_text = span_danger("You start feeling depressed.")
lose_text = span_notice("You no longer feel depressed.") //if only it were that easy!
medical_record_text = "Patient has a mild mood disorder causing them to experience acute episodes of depression."
quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_MOODLET_BASED
quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_MOODLET_BASED|QUIRK_PROCESSES
hardcore_value = 2
mail_goodies = list(/obj/item/storage/pill_bottle/happinesspsych)
/datum/quirk/depression/process(seconds_per_tick)
// 0.416% is 15 successes / 3600 seconds. Calculated with 2 minute
// mood runtime, so 50% average uptime across the hour.
if(SPT_PROB(0.416, seconds_per_tick))
quirk_holder.add_mood_event("depression", /datum/mood_event/depression)
/datum/quirk/depression/remove()
quirk_holder.clear_mood_event("depression")
+10 -2
View File
@@ -3,7 +3,15 @@
desc = "You sometimes just feel happy, for no reason at all."
icon = FA_ICON_GRIN
value = 4
mob_trait = TRAIT_JOLLY
quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_MOODLET_BASED
quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_MOODLET_BASED|QUIRK_PROCESSES
medical_record_text = "Patient demonstrates constant euthymia irregular for environment. It's a bit much, to be honest."
mail_goodies = list(/obj/item/clothing/mask/joy)
/datum/quirk/jolly/process(seconds_per_tick)
// 0.416% is 15 successes / 3600 seconds. Calculated with 2 minute
// mood runtime, so 50% average uptime across the hour.
if(SPT_PROB(0.416, seconds_per_tick))
quirk_holder.add_mood_event("jolly", /datum/mood_event/jolly)
/datum/quirk/jolly/remove()
quirk_holder.clear_mood_event("jolly")
@@ -162,19 +162,23 @@
if(!IS_HERETIC_OR_MONSTER(user))
user.balloon_alert(user, "you feel a presence watching you")
user.add_mood_event("Moon Amulet Insanity", /datum/mood_event/amulet_insanity)
user.mob_mood.set_sanity(user.mob_mood.sanity - 50)
user.mob_mood.adjust_sanity(-50)
return
if(hit.can_block_magic(MAGIC_RESISTANCE|MAGIC_RESISTANCE_MIND))
return
if(!hit.mob_mood)
return
if(hit.mob_mood.sanity_level > SANITY_LEVEL_UNSTABLE)
user.balloon_alert(user, "their mind is too strong!")
hit.add_mood_event("Moon Amulet Insanity", /datum/mood_event/amulet_insanity)
hit.mob_mood.set_sanity(hit.mob_mood.sanity - sanity_damage)
else
user.balloon_alert(user, "their mind bends to see the truth!")
hit.apply_status_effect(/datum/status_effect/moon_converted)
user.log_message("made [target] insane.", LOG_GAME)
hit.log_message("was driven insane by [user]")
hit.mob_mood.adjust_sanity(-sanity_damage)
return ..()
user.balloon_alert(user, "their mind bends to see the truth!")
hit.apply_status_effect(/datum/status_effect/moon_converted)
user.log_message("made [target] insane.", LOG_GAME)
hit.log_message("was driven insane by [user]")
. = ..()
@@ -62,7 +62,7 @@
var/mob/living/carbon/carbon_target = target
to_chat(carbon_target, span_danger("You hear echoing laughter from above"))
carbon_target.cause_hallucination(/datum/hallucination/delusion/preset/moon, "delusion/preset/moon hallucination caused by mansus grasp")
carbon_target.mob_mood.set_sanity(carbon_target.mob_mood.sanity-30)
carbon_target.mob_mood.adjust_sanity(-30)
/datum/heretic_knowledge/spell/moon_smile
name = "Smile of the moon"
@@ -134,7 +134,7 @@
"upgraded path of moon blades", \
)
target.emote(pick("giggle", "laugh"))
target.mob_mood.set_sanity(target.mob_mood.sanity - 10)
target.mob_mood.adjust_sanity(-10)
/datum/heretic_knowledge/spell/moon_ringleader
name = "Ringleaders Rise"
@@ -234,7 +234,6 @@
)
for(var/mob/living/carbon/carbon_view in view(5, source))
var/carbon_sanity = carbon_view.mob_mood.sanity
if(carbon_view.stat != CONSCIOUS)
continue
if(IS_HERETIC_OR_MONSTER(carbon_view))
@@ -243,11 +242,13 @@
continue
new moon_effect(get_turf(carbon_view))
carbon_view.adjust_confusion(2 SECONDS)
carbon_view.mob_mood.set_sanity(carbon_sanity - 5)
carbon_view.mob_mood.adjust_sanity(-5)
var/carbon_sanity = carbon_view.mob_mood.sanity
if(carbon_sanity < 30)
if(SPT_PROB(20, seconds_per_tick))
to_chat(carbon_view, span_warning("you feel your mind beginning to rend!"))
carbon_view.adjustOrganLoss(ORGAN_SLOT_BRAIN, 5)
if(carbon_sanity < 10)
if(SPT_PROB(20, seconds_per_tick))
to_chat(carbon_view, span_warning("it echoes through you!"))
@@ -85,7 +85,7 @@
victim.add_mood_event("Moon Insanity", /datum/mood_event/moon_insanity)
victim.cause_hallucination(/datum/hallucination/delusion/preset/moon, name)
victim.mob_mood.set_sanity(victim.mob_mood.sanity - 20)
victim.mob_mood.adjust_sanity(-20)
/obj/projectile/moon_parade/Destroy()
for(var/mob/living/leftover_mob as anything in mobs_hit)
@@ -51,7 +51,7 @@
victim.apply_status_effect(/datum/status_effect/moon_converted)
caster.log_message("made [victim] insane.", LOG_GAME)
victim.log_message("was driven insane by [caster]")
victim.mob_mood.set_sanity(victim_sanity * 0.5)
victim.mob_mood.adjust_sanity(victim_sanity * -0.5)
/obj/effect/temp_visual/moon_ringleader
@@ -51,5 +51,5 @@
if(cast_on.mob_mood.sanity < 40)
cast_on.AdjustKnockdown(2 SECONDS)
//Lowers sanity
cast_on.mob_mood.set_sanity(cast_on.mob_mood.sanity - 20)
cast_on.mob_mood.adjust_sanity(-20)
return TRUE
@@ -78,7 +78,7 @@
Noncompliance and removal of this implant is not recommended, and remember to smile for the cameras!"))
return ..()
/datum/antagonist/survivalist/battle_royale/on_removal()
if (isnull(owner.current))
return ..()
@@ -86,7 +86,7 @@
if (owner.current.stat == DEAD)
return ..()
to_chat(owner, span_notice("Your body is flooded with relief. Against all the odds, you've made it out alive."))
owner.current?.mob_mood.add_mood_event("battle_royale", /datum/mood_event/royale_survivor)
owner.current?.add_mood_event("battle_royale", /datum/mood_event/royale_survivor)
return ..()
/// Add an objective to go to a specific place.
-9
View File
@@ -83,15 +83,6 @@
soft_type = "grey"
dog_fashion = null
/* A grey baseball cap that grants TRAIT_JOLLY when it's on your head.
* Used for testing that gaining and losing the JOLLY trait behaves properly.
* Also a perfectly valid weird admin reward.
*/
/obj/item/clothing/head/soft/grey/jolly
name = "jolly grey cap"
desc = "It's a baseball hat in a sublime grey colour. Why, wearing this alone would boost a person's spirits!"
clothing_traits = list(TRAIT_JOLLY)
/obj/item/clothing/head/soft/orange
name = "orange cap"
desc = "It's a baseball hat in a tasteless orange colour."
@@ -23,7 +23,7 @@
set waitfor = FALSE
var/datum/dream/chosen_dream
if (IS_HERETIC(src) && !("mansus_dream_fatigue" in src.mob_mood.mood_events) && GLOB.reality_smash_track.smashes.len)
if (IS_HERETIC(src) && !mob_mood.get_mood_event("mansus_dream_fatigue") && GLOB.reality_smash_track.smashes.len)
chosen_dream = new /datum/dream/heretic(pick(GLOB.reality_smash_track.smashes))
else
chosen_dream = pick_weight(GLOB.dreams)
+24 -15
View File
@@ -204,25 +204,30 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
/obj/item/book/bible/proc/bless(mob/living/blessed, mob/living/user)
if(GLOB.religious_sect)
return GLOB.religious_sect.sect_bless(blessed,user)
if(!ishuman(blessed))
return
return BLESSING_FAILED
var/mob/living/carbon/human/built_in_his_image = blessed
for(var/obj/item/bodypart/bodypart as anything in built_in_his_image.bodyparts)
if(!IS_ORGANIC_LIMB(bodypart))
balloon_alert(user, "can't heal inorganic!")
return FALSE
return BLESSING_IGNORED
var/heal_amt = 10
var/list/hurt_limbs = built_in_his_image.get_damaged_bodyparts(1, 1, BODYTYPE_ORGANIC)
if(length(hurt_limbs))
for(var/obj/item/bodypart/affecting as anything in hurt_limbs)
if(affecting.heal_damage(heal_amt, heal_amt, required_bodytype = BODYTYPE_ORGANIC))
built_in_his_image.update_damage_overlays()
built_in_his_image.visible_message(span_notice("[user] heals [built_in_his_image] with the power of [deity_name]!"))
to_chat(built_in_his_image, span_boldnotice("May the power of [deity_name] compel you to be healed!"))
playsound(built_in_his_image, SFX_PUNCH, 25, TRUE, -1)
built_in_his_image.add_mood_event("blessing", /datum/mood_event/blessing)
return TRUE
if(!length(hurt_limbs))
return BLESSING_IGNORED
for(var/obj/item/bodypart/affecting as anything in hurt_limbs)
if(affecting.heal_damage(heal_amt, heal_amt, required_bodytype = BODYTYPE_ORGANIC))
built_in_his_image.update_damage_overlays()
built_in_his_image.visible_message(span_notice("[user] heals [built_in_his_image] with the power of [deity_name]!"))
to_chat(built_in_his_image, span_boldnotice("May the power of [deity_name] compel you to be healed!"))
playsound(built_in_his_image, SFX_PUNCH, 25, TRUE, -1)
built_in_his_image.add_mood_event("blessing", /datum/mood_event/blessing)
return BLESSING_SUCCESS
/obj/item/book/bible/attack(mob/living/target_mob, mob/living/carbon/human/user, params, heal_mode = TRUE)
if(!ISADVANCEDTOOLUSER(user))
@@ -244,7 +249,7 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
return ..()
if(target_mob.stat == DEAD)
if(!GLOB.religious_sect?.sect_dead_bless(target_mob, user))
if(GLOB.religious_sect?.sect_dead_bless(target_mob, user) == BLESSING_FAILED)
target_mob.visible_message(span_danger("[user] smacks [target_mob]'s lifeless corpse with [src]."))
playsound(target_mob, SFX_PUNCH, 25, TRUE, -1)
return
@@ -256,9 +261,13 @@ GLOBAL_LIST_INIT(bibleitemstates, list(
var/smack_chance = DEFAULT_SMACK_CHANCE
if(GLOB.religious_sect)
smack_chance = GLOB.religious_sect.smack_chance
var/success = !prob(smack_chance) && bless(target_mob, user)
if(success)
return
if(!prob(smack_chance))
var/bless_result = bless(target_mob, user)
if (bless_result != BLESSING_FAILED)
SEND_SIGNAL(target_mob, COMSIG_LIVING_BLESSED, user, src, bless_result)
return
if(iscarbon(target_mob))
var/mob/living/carbon/carbon_target = target_mob
if(!istype(carbon_target.head, /obj/item/clothing/head/helmet))
@@ -36,7 +36,7 @@
/// Log applications and apply moodlet.
/obj/item/organ/monster_core/regenerative_core/apply_to(mob/living/target, mob/user)
target.add_mood_event(MOOD_CATEGORY_LEGION_CORE, /datum/mood_event/healsbadman)
target.add_mood_event("legion_core", /datum/mood_event/healsbadman)
if (target != user)
target.visible_message(span_notice("[user] forces [target] to apply [src]... Black tendrils entangle and reinforce [target.p_them()]!"))
SSblackbox.record_feedback("nested tally", "hivelord_core", 1, list("[type]", "used", "other"))
@@ -60,7 +60,7 @@
UnregisterSignal(stored_mob, COMSIG_LIVING_REVIVE)
ai_controller.clear_blackboard_key(BB_LEGION_CORPSE)
stored_mob.remove_status_effect(/datum/status_effect/grouped/stasis, STASIS_LEGION_EATEN)
stored_mob.add_mood_event(MOOD_CATEGORY_LEGION_CORE, /datum/mood_event/healsbadman/long_term) // This will still probably mostly be gone before you are alive
stored_mob.add_mood_event("legion_core", /datum/mood_event/healsbadman/long_term) // This will still probably mostly be gone before you are alive
stored_mob = null
/mob/living/basic/mining/legion/death(gibbed)
@@ -72,7 +72,7 @@
return FALSE
if (target.stat <= SOFT_CRIT && !(organ_flags & ORGAN_FAILING))
target.add_mood_event(MOOD_CATEGORY_LEGION_CORE, /datum/mood_event/healsbadman)
target.add_mood_event("legion_core", /datum/mood_event/healsbadman)
target.apply_status_effect(applied_status)
if (target != user)
@@ -1611,7 +1611,7 @@
affected_mob.adjust_confusion(-6 SECONDS * REM * seconds_per_tick)
affected_mob.disgust = max(affected_mob.disgust - (6 * REM * seconds_per_tick), 0)
if(affected_mob.mob_mood != null && affected_mob.mob_mood.sanity <= SANITY_NEUTRAL) // only take effect if in negative sanity and then...
affected_mob.mob_mood.set_sanity(min(affected_mob.mob_mood.sanity + (5 * REM * seconds_per_tick), SANITY_NEUTRAL)) // set minimum to prevent unwanted spiking over neutral
affected_mob.mob_mood.adjust_sanity(5 * REM * seconds_per_tick, maximum = SANITY_NEUTRAL) // set minimum to prevent unwanted spiking over neutral
/datum/reagent/medicine/psicodine/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired)
. = ..()
+69 -46
View File
@@ -104,26 +104,29 @@
/// Replaces the bible's bless mechanic. Return TRUE if you want to not do the brain hit.
/datum/religion_sect/proc/sect_bless(mob/living/target, mob/living/chap)
if(!ishuman(target))
return FALSE
return BLESSING_FAILED
var/mob/living/carbon/human/blessed = target
for(var/obj/item/bodypart/bodypart as anything in blessed.bodyparts)
if(IS_ROBOTIC_LIMB(bodypart))
to_chat(chap, span_warning("[GLOB.deity] refuses to heal this metallic taint!"))
return TRUE
return BLESSING_IGNORED
var/heal_amt = 10
var/list/hurt_limbs = blessed.get_damaged_bodyparts(1, 1, BODYTYPE_ORGANIC)
if(hurt_limbs.len)
for(var/X in hurt_limbs)
var/obj/item/bodypart/affecting = X
if(affecting.heal_damage(heal_amt, heal_amt, required_bodytype = BODYTYPE_ORGANIC))
blessed.update_damage_overlays()
blessed.visible_message(span_notice("[chap] heals [blessed] with the power of [GLOB.deity]!"))
to_chat(blessed, span_boldnotice("May the power of [GLOB.deity] compel you to be healed!"))
playsound(chap, SFX_PUNCH, 25, TRUE, -1)
blessed.add_mood_event("blessing", /datum/mood_event/blessing)
return TRUE
if(!length(hurt_limbs))
return BLESSING_IGNORED
for(var/obj/item/bodypart/affecting as anything in hurt_limbs)
if(affecting.heal_damage(heal_amt, heal_amt, required_bodytype = BODYTYPE_ORGANIC))
blessed.update_damage_overlays()
blessed.visible_message(span_notice("[chap] heals [blessed] with the power of [GLOB.deity]!"))
to_chat(blessed, span_boldnotice("May the power of [GLOB.deity] compel you to be healed!"))
playsound(chap, SFX_PUNCH, 25, TRUE, -1)
blessed.add_mood_event("blessing", /datum/mood_event/blessing)
return BLESSING_SUCCESS
/// What happens if we bless a corpse? By default just do the default smack behavior
/datum/religion_sect/proc/sect_dead_bless(mob/living/target, mob/living/chap)
@@ -162,9 +165,11 @@
to_chat(R, span_boldnotice("You are charged by the power of [GLOB.deity]!"))
R.add_mood_event("blessing", /datum/mood_event/blessing)
playsound(chap, 'sound/effects/bang.ogg', 25, TRUE, -1)
return TRUE
return BLESSING_SUCCESS
if(!ishuman(target))
return
return BLESSING_FAILED
var/mob/living/carbon/human/blessed = target
//first we determine if we can charge them
@@ -179,12 +184,13 @@
if(IS_ORGANIC_LIMB(bodypart))
if(!did_we_charge)
to_chat(chap, span_warning("[GLOB.deity] scoffs at the idea of healing such fleshy matter!"))
else
blessed.visible_message(span_notice("[chap] charges [blessed] with the power of [GLOB.deity]!"))
to_chat(blessed, span_boldnotice("You feel charged by the power of [GLOB.deity]!"))
blessed.add_mood_event("blessing", /datum/mood_event/blessing)
playsound(chap, 'sound/machines/synth/synth_yes.ogg', 25, TRUE, -1)
return TRUE
return BLESSING_IGNORED
blessed.visible_message(span_notice("[chap] charges [blessed] with the power of [GLOB.deity]!"))
to_chat(blessed, span_boldnotice("You feel charged by the power of [GLOB.deity]!"))
blessed.add_mood_event("blessing", /datum/mood_event/blessing)
playsound(chap, 'sound/machines/synth/synth_yes.ogg', 25, TRUE, -1)
return BLESSING_SUCCESS
//charge(?) and go
if(bodypart.heal_damage(5,5,BODYTYPE_ROBOTIC))
@@ -194,7 +200,7 @@
to_chat(blessed, span_boldnotice("The inner machinations of [GLOB.deity] [did_we_charge ? "repairs and charges" : "repairs"] you!"))
playsound(chap, 'sound/effects/bang.ogg', 25, TRUE, -1)
blessed.add_mood_event("blessing", /datum/mood_event/blessing)
return TRUE
return BLESSING_SUCCESS
/datum/religion_sect/mechanical/on_sacrifice(obj/item/stock_parts/power_store/cell/power_cell, mob/living/chap)
if(!istype(power_cell))
@@ -258,33 +264,39 @@
return "In the eyes of [GLOB.deity], your wealth is your favor."
/datum/religion_sect/greed/sect_bless(mob/living/blessed_living, mob/living/chap)
if(!ishuman(blessed_living))
return BLESSING_FAILED
var/datum/bank_account/account = chap.get_bank_account()
if(!account)
to_chat(chap, span_warning("You need a way to pay for the heal!"))
return TRUE
return BLESSING_IGNORED
if(account.account_balance < GREEDY_HEAL_COST)
to_chat(chap, span_warning("Healing from [GLOB.deity] costs [GREEDY_HEAL_COST] credits for 30 health!"))
return TRUE
if(!ishuman(blessed_living))
return FALSE
return BLESSING_IGNORED
var/mob/living/carbon/human/blessed = blessed_living
for(var/obj/item/bodypart/robolimb as anything in blessed.bodyparts)
if(IS_ROBOTIC_LIMB(robolimb))
to_chat(chap, span_warning("[GLOB.deity] refuses to heal this metallic taint!"))
return TRUE
return BLESSING_IGNORED
account.adjust_money(-GREEDY_HEAL_COST, "Church Donation: Treatment")
var/heal_amt = 30
var/list/hurt_limbs = blessed.get_damaged_bodyparts(1, 1, BODYTYPE_ORGANIC)
if(hurt_limbs.len)
for(var/obj/item/bodypart/affecting as anything in hurt_limbs)
if(affecting.heal_damage(heal_amt, heal_amt, required_bodytype = BODYTYPE_ORGANIC))
blessed.update_damage_overlays()
blessed.visible_message(span_notice("[chap] barters a heal for [blessed] from [GLOB.deity]!"))
to_chat(blessed, span_boldnotice("May the power of [GLOB.deity] compel you to be healed! Thank you for choosing [GLOB.deity]!"))
playsound(chap, 'sound/effects/cashregister.ogg', 60, TRUE)
blessed.add_mood_event("blessing", /datum/mood_event/blessing)
return TRUE
if(!length(hurt_limbs))
return BLESSING_IGNORED
for(var/obj/item/bodypart/affecting as anything in hurt_limbs)
if(affecting.heal_damage(heal_amt, heal_amt, required_bodytype = BODYTYPE_ORGANIC))
blessed.update_damage_overlays()
blessed.visible_message(span_notice("[chap] barters a heal for [blessed] from [GLOB.deity]!"))
to_chat(blessed, span_boldnotice("May the power of [GLOB.deity] compel you to be healed! Thank you for choosing [GLOB.deity]!"))
playsound(chap, 'sound/effects/cashregister.ogg', 60, TRUE)
blessed.add_mood_event("blessing", /datum/mood_event/blessing)
return BLESSING_SUCCESS
#undef GREEDY_HEAL_COST
@@ -321,10 +333,12 @@
/datum/religion_sect/burden/sect_bless(mob/living/carbon/target, mob/living/carbon/chaplain)
if(!istype(target) || !istype(chaplain))
return FALSE
return BLESSING_FAILED
var/datum/brain_trauma/special/burdened/burden = chaplain.has_trauma_type(/datum/brain_trauma/special/burdened)
if(!burden)
return FALSE
return BLESSING_FAILED
var/burden_modifier = max(1 - 0.07 * burden.burden_level, 0.01)
var/transferred = FALSE
var/list/hurt_limbs = target.get_damaged_bodyparts(1, 1, BODYTYPE_ORGANIC) + target.get_wounded_bodyparts(BODYTYPE_ORGANIC)
@@ -332,6 +346,7 @@
for(var/obj/item/bodypart/possible_limb in chaplain.bodyparts)
if(IS_ORGANIC_LIMB(possible_limb))
chaplains_limbs += possible_limb
if(length(chaplains_limbs))
for(var/obj/item/bodypart/affected_limb as anything in hurt_limbs)
var/obj/item/bodypart/chaplains_limb = chaplain.get_bodypart(affected_limb.body_zone)
@@ -347,20 +362,24 @@
transferred = TRUE
iter_wound.remove_wound()
iter_wound.apply_wound(chaplains_limb)
if(HAS_TRAIT_FROM(target, TRAIT_HUSK, BURN))
transferred = TRUE
target.cure_husk(BURN)
chaplain.become_husk(BURN)
var/toxin_damage = target.getToxLoss()
if(toxin_damage && !HAS_TRAIT(chaplain, TRAIT_TOXIMMUNE))
transferred = TRUE
target.adjustToxLoss(-toxin_damage)
chaplain.adjustToxLoss(toxin_damage * burden_modifier, forced = TRUE)
var/suffocation_damage = target.getOxyLoss()
if(suffocation_damage && !HAS_TRAIT(chaplain, TRAIT_NOBREATH))
transferred = TRUE
target.adjustOxyLoss(-suffocation_damage)
chaplain.adjustOxyLoss(suffocation_damage * burden_modifier, forced = TRUE)
if(!HAS_TRAIT(chaplain, TRAIT_NOBLOOD))
if(target.blood_volume < BLOOD_VOLUME_SAFE)
var/target_blood_data = target.get_blood_data(target.get_blood_id())
@@ -371,16 +390,18 @@
chaplain.transfer_blood_to(target, transferred_blood_amount, forced = TRUE)
if(target.blood_volume > BLOOD_VOLUME_EXCESS)
target.transfer_blood_to(chaplain, target.blood_volume - BLOOD_VOLUME_EXCESS, forced = TRUE)
target.update_damage_overlays()
chaplain.update_damage_overlays()
if(transferred)
target.visible_message(span_notice("[chaplain] takes on [target]'s burden!"))
to_chat(target, span_boldnotice("May the power of [GLOB.deity] compel you to be healed!"))
playsound(chaplain, SFX_PUNCH, 25, vary = TRUE, extrarange = -1)
target.add_mood_event("blessing", /datum/mood_event/blessing)
else
to_chat(chaplain, span_warning("They hold no burden!"))
return TRUE
return BLESSING_IGNORED
target.visible_message(span_notice("[chaplain] takes on [target]'s burden!"))
to_chat(target, span_boldnotice("May the power of [GLOB.deity] compel you to be healed!"))
playsound(chaplain, SFX_PUNCH, 25, vary = TRUE, extrarange = -1)
target.add_mood_event("blessing", /datum/mood_event/blessing)
return BLESSING_SUCCESS
/datum/religion_sect/burden/sect_dead_bless(mob/living/target, mob/living/chaplain)
return sect_bless(target, chaplain)
@@ -436,17 +457,19 @@
/datum/religion_sect/maintenance/sect_bless(mob/living/blessed_living, mob/living/chap)
if(!ishuman(blessed_living))
return TRUE
return BLESSING_FAILED
var/mob/living/carbon/human/blessed = blessed_living
if(blessed.reagents.has_reagent(/datum/reagent/drug/maint/sludge))
to_chat(blessed, span_warning("[GLOB.deity] has already empowered them."))
return TRUE
return BLESSING_IGNORED
blessed.reagents.add_reagent(/datum/reagent/drug/maint/sludge, 5)
blessed.visible_message(span_notice("[chap] empowers [blessed] with the power of [GLOB.deity]!"))
to_chat(blessed, span_boldnotice("The power of [GLOB.deity] has made you harder to wound for a while!"))
playsound(chap, SFX_PUNCH, 25, TRUE, -1)
blessed.add_mood_event("blessing", /datum/mood_event/blessing)
return TRUE //trust me, you'll be feeling the pain from the maint drugs all well enough
return BLESSING_SUCCESS //trust me, you'll be feeling the pain from the maint drugs all well enough
/datum/religion_sect/maintenance/on_sacrifice(obj/item/reagent_containers/offering, mob/living/user)
if(!istype(offering))
+1 -1
View File
@@ -4269,7 +4269,7 @@
#include "code\modules\fishing\fish\types\tiziran.dm"
#include "code\modules\fishing\sources\_fish_source.dm"
#include "code\modules\fishing\sources\source_types.dm"
#include "code\modules\flufftext\Dreaming.dm"
#include "code\modules\flufftext\dreaming.dm"
#include "code\modules\food_and_drinks\pizzabox.dm"
#include "code\modules\food_and_drinks\plate.dm"
#include "code\modules\food_and_drinks\machinery\coffeemaker.dm"