Accentuate the positive with **Personality**: A (soft) mood rework (#92941)

Co-authored-by: SmArtKar <44720187+SmArtKar@users.noreply.github.com>
This commit is contained in:
MrMelbert
2025-10-02 19:00:13 +00:00
committed by GitHub
co-authored by SmArtKar
parent 0124adacc7
commit 3ea7b03369
110 changed files with 2557 additions and 314 deletions
@@ -34,6 +34,7 @@
antagonist.greet()
log_game("[key_name(antagonist)] has developed an obsession with [key_name(obsession)].")
RegisterSignal(owner, COMSIG_CARBON_HELPED, PROC_REF(on_hug))
ADD_TRAIT(owner, TRAIT_DESENSITIZED, REF(src))
/datum/brain_trauma/special/obsessed/on_life(seconds_per_tick, times_fired)
if(!obsession || obsession.stat == DEAD)
@@ -71,6 +72,7 @@
if(obsession)
log_game("[key_name(owner)] is no longer obsessed with [key_name(obsession)].")
UnregisterSignal(obsession, COMSIG_MOB_EYECONTACT)
REMOVE_TRAIT(owner, TRAIT_DESENSITIZED, REF(src))
/datum/brain_trauma/special/obsessed/handle_speech(datum/source, list/speech_args)
if(!viewing)
+2
View File
@@ -463,12 +463,14 @@
owner.add_mood_event("combat_ptsd", /datum/mood_event/desentized)
owner.mob_mood?.mood_modifier -= 1 //Basically nothing can change your mood
owner.mob_mood?.sanity_level = SANITY_DISTURBED //Makes sanity on a unstable level unless cured
ADD_TRAIT(owner, TRAIT_DESENSITIZED, REF(src))
. = ..()
/datum/brain_trauma/special/ptsd/on_lose()
owner.clear_mood_event("combat_ptsd")
owner.mob_mood?.mood_modifier += 1
owner.mob_mood?.sanity_level = SANITY_GREAT
REMOVE_TRAIT(owner, TRAIT_DESENSITIZED, REF(src))
return ..()
/datum/brain_trauma/special/primal_instincts
+15 -3
View File
@@ -84,7 +84,19 @@
overriden_handlers[override_type] = list()
overriden_handlers[override_type][handler_type] = TRUE
/datum/component/fearful/proc/get_fear_multiplier()
var/multiplier = 1
var/mob/living/parent_mob = parent
if(HAS_PERSONALITY(parent_mob, /datum/personality/cowardly))
multiplier *= 1.25
if(HAS_PERSONALITY(parent_mob, /datum/personality/paranoid))
multiplier *= 1.10
if(HAS_PERSONALITY(parent_mob, /datum/personality/brave))
multiplier *= 0.75
return multiplier
/datum/component/fearful/process(seconds_per_tick)
var/fear_modifier = get_fear_multiplier()
var/terror_adjustment = 0
var/list/tick_later = list()
for (var/datum/terror_handler/handler as anything in terror_handlers)
@@ -94,12 +106,12 @@
tick_later += handler
continue
var/adjustment = handler.tick(seconds_per_tick, terror_buildup)
terror_buildup = clamp(terror_buildup + adjustment, 0, TERROR_BUILDUP_MAXIMUM)
terror_buildup = clamp(terror_buildup + (adjustment * fear_modifier), 0, TERROR_BUILDUP_MAXIMUM)
terror_adjustment += adjustment
for (var/datum/terror_handler/handler as anything in tick_later)
var/adjustment = handler.tick(seconds_per_tick, terror_buildup)
terror_buildup = clamp(terror_buildup + adjustment, 0, TERROR_BUILDUP_MAXIMUM)
terror_buildup = clamp(terror_buildup + (adjustment * fear_modifier), 0, TERROR_BUILDUP_MAXIMUM)
terror_adjustment += adjustment
// If we gained terror in any way, don't tick it down
@@ -109,7 +121,7 @@
// Tick terror down while we're not being actively spooked
if (terror_buildup > 0)
terror_buildup = max(terror_buildup - TERROR_BUILDUP_PASSIVE_DECREASE, 0)
terror_buildup = max(terror_buildup - (TERROR_BUILDUP_PASSIVE_DECREASE * (1 / fear_modifier)) * seconds_per_tick, 0)
last_tick_buildup = terror_buildup
/datum/component/fearful/proc/on_examine(mob/living/source, mob/user, list/examine_list)
+1 -4
View File
@@ -632,10 +632,7 @@ Behavior that's still missing from this component that original food items had t
var/atom/owner = parent
var/timeout_mod = owner.reagents.get_average_purity(/datum/reagent/consumable) * 2 // mood event duration is 100% at average purity of 50%
var/datum/mood_event/event = GLOB.food_quality_events[food_quality]
event = new event.type
event.timeout *= timeout_mod
gourmand.add_mood_event("quality_food", event)
gourmand.add_mood_event("quality_food", /datum/mood_event/food, food_quality, timeout_mod)
gourmand.adjust_disgust(-5 + -2 * food_quality * fraction)
var/quality_label = GLOB.food_quality_description[food_quality]
to_chat(gourmand, span_notice("That's \an [quality_label] meal."))
+12
View File
@@ -493,6 +493,8 @@
CRASH("set_assigned_role called with invalid role: [isnull(new_role) ? "null" : new_role]")
. = assigned_role
assigned_role = new_role
if(!isnull(current))
SEND_SIGNAL(current, COMSIG_MOB_MIND_SET_ROLE, new_role)
///Sets your holy role, giving/taking away traits related to if you're gaining/losing it.
/datum/mind/proc/set_holy_role(new_holy_role)
@@ -531,3 +533,13 @@
/mob/dead/observer/sync_mind()
return
/// Iterates over this mind's assigned role's departments and returns a list of their primary work areas.
/datum/mind/proc/get_work_areas()
var/list/work_areas = list()
for(var/department in assigned_role.departments_list)
var/datum/job_department/dep = SSjob.joinable_departments_by_type[department]
if(dep.primary_work_area)
work_areas += dep.primary_work_area
return work_areas
+50 -40
View File
@@ -18,8 +18,18 @@
var/sanity = SANITY_NEUTRAL
/// the total combined value of all visible moodlets for the mob
var/shown_mood
/// Moodlet value modifier
/// Multiplier to the sum total of mood the mob is experiencing
var/mood_modifier = 1
/// Multiplier to positive moodlet values. Stacks with mood_modifier
var/positive_mood_modifier = 1
/// Multiplier to negative moodlet values. Stacks with mood_modifier
var/negative_mood_modifier = 1
/// Multiplier to the length of positive moodlets.
/// Please don't set this to 0
var/positive_moodlet_length_modifier = 1
/// Multiplier to the length of negative moodlets.
/// Please don't set this to 0
var/negative_moodlet_length_modifier = 1
/// Used to track what stage of moodies they're on (1-9)
var/mood_level = MOOD_LEVEL_NEUTRAL
/// To track what stage of sanity they're on (1-6)
@@ -144,48 +154,46 @@
* * category - (text) category of the mood event - see /datum/mood_event for category explanation
* * type - (path) any /datum/mood_event
*/
/datum/mood/proc/add_mood_event(category, type, ...)
// we may be passed an instantiated mood datum with a modified timeout
// it is to be used as a vehicle to copy data from and then cleaned up afterwards.
// why do it this way? because the params list may contain numbers, and we may not necessarily want those to be interpreted as a timeout modifier.
// this is only used by the food quality system currently
var/datum/mood_event/mood_to_copy_from
if (istype(type, /datum/mood_event))
mood_to_copy_from = type
type = mood_to_copy_from.type
if (!ispath(type, /datum/mood_event))
CRASH("A non path ([type]), was used to add a mood event. This shouldn't be happening.")
/datum/mood/proc/add_mood_event(category, new_type, ...)
if (!ispath(new_type, /datum/mood_event))
CRASH("A non path ([new_type]), was used to add a mood event. This shouldn't be happening.")
if (!istext(category))
category = REF(category)
var/datum/mood_event/the_event
if (mood_events[category])
the_event = mood_events[category]
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)
the_event = new type(arglist(params))
if (QDELETED(the_event)) // the mood event has been deleted for whatever reason (requires a job, etc)
var/datum/mood_event/new_event = new new_type(category)
if(!new_event.can_effect_mob(arglist(list(src, mob_parent) + params)))
qdel(new_event)
return
the_event.category = category
if (!isnull(mood_to_copy_from))
the_event.timeout = mood_to_copy_from.timeout
qdel(mood_to_copy_from)
mood_events[category] = the_event
update_mood()
var/datum/mood_event/existing_event = mood_events[category]
if(existing_event)
var/continue_adding = FALSE
if(existing_event.type == new_event.type)
continue_adding = existing_event.be_refreshed(arglist(list(src) + params))
else
continue_adding = existing_event.be_replaced(arglist(list(src, new_event) + params))
if(!continue_adding)
update_mood()
qdel(new_event)
return
clear_mood_event(category)
if (the_event.timeout)
addtimer(CALLBACK(src, PROC_REF(clear_mood_event), category), the_event.timeout, (TIMER_UNIQUE|TIMER_OVERRIDE))
new_event.on_add(src, mob_parent, params)
mood_events[category] = new_event
update_mood()
if(new_event.mood_change == 0 || new_event.hidden)
return
if(new_event.mood_change > 0)
add_personality_mood_to_viewers(mob_parent, "other_good_moodlet", list(
/datum/personality/empathetic = /datum/mood_event/empathetic_happy,
/datum/personality/misanthropic = /datum/mood_event/misanthropic_sad
), range = 4)
else
add_personality_mood_to_viewers(mob_parent, "other_bad_moodlet", list(
/datum/personality/empathetic = /datum/mood_event/empathetic_sad,
/datum/personality/misanthropic = /datum/mood_event/misanthropic_happy
), range = 4)
/**
* Removes a mood event from the mob
@@ -218,12 +226,14 @@
for(var/category in mood_events)
var/datum/mood_event/the_event = mood_events[category]
mood += the_event.mood_change
var/event_mood = the_event.mood_change
event_mood *= max((event_mood > 0) ? positive_mood_modifier : negative_mood_modifier, 0)
mood += event_mood
if (!the_event.hidden)
shown_mood += the_event.mood_change
shown_mood += event_mood
mood *= mood_modifier
shown_mood *= mood_modifier
mood *= max(mood_modifier, 0)
shown_mood *= max(mood_modifier, 0)
switch(mood)
if (-INFINITY to MOOD_SAD4)
+110 -11
View File
@@ -12,7 +12,10 @@
* is active while another mood event (from the same category) is triggered it will remove
* the effects of the current mood event and replace it with the new one
*/
var/category
VAR_FINAL/category
/// Flags that determine what kind of event this is
/// For example, you might have a "EVENT_FEAR" flag that denotes this mood event relates to being afraid of something
var/event_flags = NONE
/// Icon state of the unique mood event icon, if applicable
var/special_screen_obj
/// if false, it will be an overlay instead
@@ -22,21 +25,117 @@
/// List of required jobs for this mood event
var/list/required_job
/datum/mood_event/New(mob/living/emotional_mob, ...)
owner = emotional_mob
var/list/params = args.Copy(2)
if (LAZYLEN(required_job) && !is_type_in_list(owner.mind?.assigned_role, required_job))
qdel(src)
return
add_effects(arglist(params))
/datum/mood_event/New(category)
src.category = category
/datum/mood_event/Destroy()
remove_effects()
owner = null
if(owner)
remove_effects()
owner = null
return ..()
/datum/mood_event/proc/add_effects(param)
/**
* Called when this datum is created, checks if the passed mob can experience this mood event
*
* * who - the mob to check
*
* Return TRUE if the mob can experience this mood event
* Return FALSE if the mob should be unaffected
*/
/datum/mood_event/proc/can_effect_mob(datum/mood/home, mob/living/who, ...)
SHOULD_CALL_PARENT(TRUE)
if(LAZYLEN(required_job) && !is_type_in_list(who.mind?.assigned_role, required_job))
return FALSE
if((event_flags & MOOD_EVENT_WHIMSY))
// Whimsical people get positive whimsical moodlets
// Non-whimsical people get negative whimsical moodlets
var/is_whimsical = HAS_PERSONALITY(who, /datum/personality/whimsical)
if(mood_change >= 0 && !is_whimsical)
return FALSE
if(mood_change < 0 && is_whimsical)
return FALSE
if((event_flags & MOOD_EVENT_ART) && HAS_PERSONALITY(who, /datum/personality/unimaginative))
return FALSE
if((event_flags & MOOD_EVENT_PAIN) && HAS_TRAIT(who, TRAIT_ANALGESIA))
return FALSE
return TRUE
/**
* Wrapper for the mood event being added to a mob
*/
/datum/mood_event/proc/on_add(datum/mood/home, mob/living/who, list/mood_args)
SHOULD_NOT_OVERRIDE(TRUE)
owner = who
if((event_flags & MOOD_EVENT_ART) && HAS_PERSONALITY(who, /datum/personality/creative))
mood_change *= 1.2
if((event_flags & MOOD_EVENT_SPIRITUAL) && !HAS_TRAIT(who, TRAIT_SPIRITUAL))
mood_change *= 0.2
if(event_flags & MOOD_EVENT_FOOD)
if(HAS_PERSONALITY(owner, /datum/personality/ascetic))
mood_change *= 0.75
if(HAS_PERSONALITY(owner, /datum/personality/gourmand))
mood_change *= 1.25
if(event_flags & MOOD_EVENT_FEAR)
if(HAS_PERSONALITY(owner, /datum/personality/cowardly))
mood_change *= 1.25
if(HAS_PERSONALITY(owner, /datum/personality/brave))
mood_change *= 0.75
add_effects(arglist(mood_args))
mood_change = floor(mood_change)
timeout *= max((mood_change > 0) ? home.positive_moodlet_length_modifier : home.negative_moodlet_length_modifier, 0.1)
if(timeout)
addtimer(CALLBACK(home, TYPE_PROC_REF(/datum/mood, clear_mood_event), category), timeout, (TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT))
/**
* Called when added to a mob
*
* * ... - Any arguments passed to add_mood_event after the typepath are passed here
*/
/datum/mood_event/proc/add_effects(...)
return
/**
* Called when the event is cleared from a mob
*/
/datum/mood_event/proc/remove_effects()
return
/**
* Called when we get added to a mood datum, but a mood of our type in our category already
*
* * home - the mood datum we are being added to
* * ... - any other arguments that are passed to the mood event
*
* Return BLOCK_NEW_MOOD to stop the new mood event from being added
* Return ALLOW_NEW_MOOD to allow the new mood event to be added - note this implicitly deletes [src]
*/
/datum/mood_event/proc/be_refreshed(datum/mood/home, ...)
// Base behavior is refresh the timer
if(timeout)
addtimer(CALLBACK(home, TYPE_PROC_REF(/datum/mood, clear_mood_event), category), timeout, (TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT))
return BLOCK_NEW_MOOD
/**
* Called when we get added to a mood datum, but a mood of a different type is in our category
*
* * home - the mood datum we are being added to
* * new_event - the new mood event that is being added
* * ... - any other arguments that are passed to the mood event
*
* Return BLOCK_NEW_MOOD to stop the new mood event from being added
* Return ALLOW_NEW_MOOD to allow the new mood event to be added - note this implicitly deletes [src]
*/
/datum/mood_event/proc/be_replaced(datum/mood/home, datum/mood_event/new_event, ...)
return ALLOW_NEW_MOOD
@@ -2,6 +2,7 @@
description = "Heh heh. \"It's on the mouse\". What a play on words."
mood_change = 1
timeout = 2 MINUTES
event_flags = MOOD_EVENT_WHIMSY
/datum/mood_event/gondola_serenity
description = "There's a lot that could be on your mind right now. But this feeling of contentedness, a universal calling to simply sit back and observe is washing over you..."
+10
View File
@@ -31,12 +31,22 @@
if(90 to INFINITY)
mood_change = 3 // crash out
description = "You're my BESSST frien'... You and me agains' th' world, buddy. Le's get another drink."
if(HAS_PERSONALITY(owner, /datum/personality/teetotal))
mood_change *= -1.5
description = "I don't like drinking... It makes me feel horrible."
if(HAS_PERSONALITY(owner, /datum/personality/bibulous))
mood_change *= 1.5
if(old_mood != mood_change)
owner.mob_mood.update_mood()
/datum/mood_event/drunk/remove_effects()
QDEL_NULL(blush_overlay)
/datum/mood_event/drunk_after
mood_change = 2
description = "The buzz might be gone, but I still feel good."
timeout = 5 MINUTES
/datum/mood_event/wrong_brandy
description = "I hate that type of drink."
mood_change = -2
+27 -20
View File
@@ -2,55 +2,62 @@
description = "I really enjoyed eating that."
mood_change = 5
timeout = 4 MINUTES
event_flags = MOOD_EVENT_FOOD
/datum/mood_event/gross_food
description = "I really didn't like that food."
mood_change = -2
timeout = 4 MINUTES
event_flags = MOOD_EVENT_FOOD
/datum/mood_event/disgusting_food
description = "That food was disgusting!"
mood_change = -6
timeout = 4 MINUTES
event_flags = MOOD_EVENT_FOOD
/datum/mood_event/allergic_food
description = "My throat itches."
mood_change = -2
timeout = 4 MINUTES
event_flags = MOOD_EVENT_FOOD
/datum/mood_event/breakfast
description = "Nothing like a hearty breakfast to start the shift."
mood_change = 2
timeout = 10 MINUTES
event_flags = MOOD_EVENT_FOOD
/datum/mood_event/food
timeout = 5 MINUTES
var/quality = FOOD_QUALITY_NORMAL
event_flags = MOOD_EVENT_FOOD
/datum/mood_event/food/New(mob/M, ...)
. = ..()
mood_change = 2 + 2 * quality
/datum/mood_event/food/add_effects(quality = FOOD_QUALITY_NORMAL, timeout_mod = 1)
mood_change = calculate_mood_change(quality)
timeout *= timeout_mod
description = "That food was [GLOB.food_quality_description[quality]]."
/datum/mood_event/food/nice
quality = FOOD_QUALITY_NICE
/datum/mood_event/food/be_refreshed(datum/mood/home, quality, timeout_mod)
var/old_mood = mood_change
// updates timeout (which is handled in parent call) and mood
timeout = max(timeout, initial(timeout) * timeout_mod)
mood_change = max(mood_change, calculate_mood_change(quality))
// if mood_change is the same, we don't need to update the description
if(old_mood != mood_change)
description = "That food was [GLOB.food_quality_description[quality]]."
return ..()
/datum/mood_event/food/good
quality = FOOD_QUALITY_GOOD
/datum/mood_event/food/verygood
quality = FOOD_QUALITY_VERYGOOD
/datum/mood_event/food/fantastic
quality = FOOD_QUALITY_FANTASTIC
/datum/mood_event/food/amazing
quality = FOOD_QUALITY_AMAZING
/datum/mood_event/food/top
quality = FOOD_QUALITY_TOP
/datum/mood_event/food/proc/calculate_mood_change(base_quality)
var/quality = 1 + 1.5 * base_quality
if(HAS_PERSONALITY(owner, /datum/personality/ascetic))
quality *= 0.5
if(HAS_PERSONALITY(owner, /datum/personality/gourmand))
if(quality <= FOOD_QUALITY_GOOD)
quality = FOOD_QUALITY_NORMAL
return ceil(quality)
/datum/mood_event/pacifist_eating_fish_item
description = "I shouldn't be eating living creatures..."
mood_change = -1 //The disgusting food moodlet already has a pretty big negative value, this is just for context.
timeout = 4 MINUTES
event_flags = MOOD_EVENT_FOOD
@@ -10,10 +10,12 @@
/datum/mood_event/on_fire
description = "I'M ON FIRE!!!"
mood_change = -12
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/suffocation
description = "CAN'T... BREATHE..."
mood_change = -12
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/burnt_thumb
description = "I shouldn't play with lighters..."
@@ -32,6 +34,7 @@
description = "I've been creamed. Tastes like pie flavor."
mood_change = -2
timeout = 3 MINUTES
event_flags = MOOD_EVENT_WHIMSY // if whimsical, no penalty
/datum/mood_event/inked
description = "I've been splashed with squid ink. Tastes like salt."
@@ -42,6 +45,7 @@
description = "I slipped. I should be more careful next time..."
mood_change = -2
timeout = 3 MINUTES
event_flags = MOOD_EVENT_WHIMSY // if whimsical, no penalty
/datum/mood_event/eye_stab
description = "I used to be an adventurer like you, until I took a screwdriver to the eye."
@@ -81,12 +85,7 @@
description = "Ouch! My limb feels like I fell asleep on it."
mood_change = -3
timeout = 2 MINUTES
/datum/mood_event/reattachment/New(mob/M, ...)
if(HAS_TRAIT(M, TRAIT_ANALGESIA))
qdel(src)
return
return ..()
event_flags = MOOD_EVENT_PAIN
/datum/mood_event/reattachment/add_effects(obj/item/bodypart/limb)
if(limb)
@@ -117,12 +116,7 @@
description = "That fucking table, man that hurts..."
mood_change = -3
timeout = 3 MINUTES
/datum/mood_event/table_limbsmash/New(mob/M, ...)
if(HAS_TRAIT(M, TRAIT_ANALGESIA))
qdel(src)
return
return ..()
event_flags = MOOD_EVENT_PAIN
/datum/mood_event/table_limbsmash/add_effects(obj/item/bodypart/banged_limb)
if(banged_limb)
@@ -147,15 +141,18 @@
/datum/mood_event/photophobia
description = "The lights are too bright..."
mood_change = -3
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/nyctophobia
description = "It sure is dark around here..."
mood_change = -3
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/claustrophobia
description = "Why do I feel trapped?! Let me out!!!"
mood_change = -7
timeout = 1 MINUTES
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/bright_light
description = "I hate it in the light... I need to find a darker place..."
@@ -177,9 +174,14 @@
description = "I'm nervous and on edge and I can't stand still!!"
mood_change = -2
/datum/mood_event/jittery/add_effects(...)
if(HAS_PERSONALITY(owner, /datum/personality/paranoid))
mood_change -= 1
/datum/mood_event/choke
description = "I CAN'T BREATHE!!!"
mood_change = -10
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/vomit
description = "I just threw up. Gross."
@@ -195,27 +197,25 @@
description = "Medicine may be good for me but right now it stings like hell."
mood_change = -5
timeout = 60 SECONDS
/datum/mood_event/painful_medicine/New(mob/M, ...)
if(HAS_TRAIT(M, TRAIT_ANALGESIA))
qdel(src)
return
return ..()
event_flags = MOOD_EVENT_PAIN
/datum/mood_event/startled
description = "Hearing that word made me think about something scary."
mood_change = -1
timeout = 1 MINUTES
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/phobia
description = "I saw something very frightening."
description = "I saw something very frightening!"
mood_change = -4
timeout = 4 MINUTES
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/spooked
description = "The rattling of those bones... It still haunts me."
mood_change = -4
timeout = 4 MINUTES
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/notcreeping
description = "The voices are not happy, and they painfully contort my thoughts into getting back on task."
@@ -243,12 +243,7 @@
/datum/mood_event/back_pain
description = "Bags never sit right on my back, this hurts like hell!"
mood_change = -15
/datum/mood_event/back_pain/New(mob/M, ...)
if(HAS_TRAIT(M, TRAIT_ANALGESIA))
qdel(src)
return
return ..()
event_flags = MOOD_EVENT_PAIN
/datum/mood_event/sad_empath
description = "Someone seems upset..."
@@ -262,11 +257,18 @@
description = "Those darn savages!"
mood_change = -5
timeout = 2 MINUTES
event_flags = MOOD_EVENT_SPIRITUAL
/datum/mood_event/artbad
description = "I've produced better art than that from my ass."
mood_change = -2
timeout = 2 MINUTES
event_flags = MOOD_EVENT_ART
/datum/mood_event/artbad/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/creative))
mood_change = 0
description = "Everyone has to start their art journey somewhere!"
/datum/mood_event/graverobbing
description = "I just desecrated someone's grave... I can't believe I did that..."
@@ -280,6 +282,7 @@
/datum/mood_event/gunpoint
description = "This guy is insane! I better be careful..."
mood_change = -10
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/tripped
description = "I can't believe I fell for the oldest trick in the book!"
@@ -295,6 +298,7 @@
description = "I HAD A GLIMPSE OF THE HORROR BEYOND THIS WORLD. REALITY UNCOILED BEFORE MY EYES!"
mood_change = -25
timeout = 4 MINUTES
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/high_five_full_hand
description = "Oh god, I don't even know how to high-five correctly..."
@@ -320,6 +324,7 @@
/datum/mood_event/surgery
description = "THEY'RE CUTTING ME OPEN!!"
mood_change = -8
event_flags = MOOD_EVENT_FEAR
var/surgery_completed = FALSE
/datum/mood_event/surgery/success
@@ -423,16 +428,19 @@
/datum/mood_event/gamer_withdrawal
description = "I wish I was gaming right now..."
mood_change = -5
event_flags = MOOD_EVENT_GAMING
/datum/mood_event/gamer_lost
description = "If I'm not good at video games, can I truly call myself a gamer?"
mood_change = -10
mood_change = -6
timeout = 10 MINUTES
event_flags = MOOD_EVENT_GAMING
/datum/mood_event/lost_52_card_pickup
description = "This is really embarrassing! I'm ashamed to pick up all these cards off the floor..."
mood_change = -3
timeout = 3 MINUTES
event_flags = MOOD_EVENT_WHIMSY | MOOD_EVENT_GAMING
/datum/mood_event/russian_roulette_lose_cheater
description = "I gambled and lost! Good thing I wasn't aiming for my head..."
@@ -444,6 +452,12 @@
mood_change = -20
timeout = 10 MINUTES
/datum/mood_event/russian_roulette_lose/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/gambler))
mood_change *= 0.5
description = "I gambled my life and lost! Truth is, the game was rigged from the start..."
return
/datum/mood_event/bad_touch_bear_hug
description = "I just got squeezed way too hard."
mood_change = -1
@@ -473,11 +487,17 @@
description = "THE MOON JUDGES AND FINDS ME WANTING!!!"
mood_change = -3
timeout = 5 MINUTES
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/moon_insanity/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/spiritual))
mood_change *= 2
/datum/mood_event/amulet_insanity
description = "I sEe THe LiGHt, It mUsT BE stOPPed"
description = "I sEe THe LiGHt, It mUsT BE stOPPed!"
mood_change = -6
timeout = 5 MINUTES
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/mallet_humiliation
description = "Getting hit by such a stupid weapon feels rather humiliating..."
@@ -535,7 +555,183 @@
description = "Blowing smoke in my face, really?"
mood_change = 0
/datum/mood_event/see_death
description = "I just saw someone die. How horrible..."
mood_change = -8
timeout = 5 MINUTES
/// Message variant for callous people
var/dont_care_message = "Oh, %DEAD_MOB% died. Shame, I guess."
/// Message variant for people who care about animals
var/pet_message = "%DEAD_MOB% just died!!"
/// Message variant for desensitized people (security, medical, cult with halo, etc)
var/desensitized_message = "I saw %DEAD_MOB% die."
var/normal_message = "I just saw %DEAD_MOB% die. How horrible..."
/datum/mood_event/see_death/add_effects(mob/dead_mob)
if(isnull(dead_mob))
return
if(HAS_TRAIT(owner, TRAIT_CULT_HALO) && !HAS_TRAIT(dead_mob, TRAIT_CULT_HALO))
// When cultists get halos, they stop caring about death
mood_change = 4
description = "More souls for the Geometer!"
return
var/ispet = istype(dead_mob, /mob/living/basic/pet) || ismonkey(dead_mob)
if(HAS_PERSONALITY(owner, /datum/personality/callous) || (ispet && HAS_PERSONALITY(owner, /datum/personality/animal_disliker)))
description = replacetext(dont_care_message, "%DEAD_MOB%", get_descriptor(dead_mob))
mood_change = 0
timeout *= 0.5
return
// future todo : make the hop care about ian, cmo runtime, etc.
if(ispet)
description = replacetext(pet_message, "%DEAD_MOB%", capitalize(dead_mob.name)) // doesn't use a descriptor, so it says "Ian died"
if(HAS_PERSONALITY(owner, /datum/personality/animal_friend))
mood_change *= 1.5
timeout *= 1.25
else if(!HAS_PERSONALITY(owner, /datum/personality/compassionate))
mood_change *= 0.25
timeout *= 0.5
return
if(HAS_PERSONALITY(owner, /datum/personality/compassionate))
mood_change *= 1.5
timeout *= 1.5
if(HAS_TRAIT(owner, TRAIT_DESENSITIZED))
mood_change *= 0.5
timeout *= 0.5
description = replacetext(desensitized_message, "%DEAD_MOB%", get_descriptor(dead_mob))
return
description = replacetext(normal_message, "%DEAD_MOB%", get_descriptor(dead_mob))
/datum/mood_event/see_death/be_refreshed(datum/mood/home, ...)
// Every time we get refreshed we get worse if not desensitized
if(!HAS_TRAIT(owner, TRAIT_DESENSITIZED))
mood_change *= 1.5
return ..()
/datum/mood_event/see_death/be_replaced(datum/mood/home, datum/mood_event/new_event, ...)
// Only be replaced if the incoming event's base mood is worse than our base mood
// (IE: replace normal death events with gib events, but not the other way around)
if(initial(new_event.mood_change) > initial(mood_change))
new_event.mood_change = max(new_event.mood_change, mood_change * 1.5)
return ..()
// Otherwise if it's equivalent or worse, refresh it instead
return be_refreshed(home)
/// Changes "I saw Joe x" to "I saw the engineer x"
/datum/mood_event/see_death/proc/get_descriptor(mob/dead_mob)
if(isnull(dead_mob))
return "something"
if(dead_mob.name != "Unknown" && dead_mob.mind?.assigned_role?.job_flags & JOB_CREW_MEMBER)
return "the [LOWER_TEXT(dead_mob.mind?.assigned_role.title)]"
return "someone"
/datum/mood_event/see_death/gibbed
description = "Someone just exploded in front of me!!"
mood_change = -12
timeout = 10 MINUTES
dont_care_message = "Oh, %DEAD_MOB% exploded. Now I have to get the mop."
pet_message = "%DEAD_MOB% just exploded!!"
desensitized_message = "I saw %DEAD_MOB% explode."
normal_message = "%DEAD_MOB% just exploded in front of me!!"
/datum/mood_event/see_death/dusted
description = "Someone was just vaporized in front of me!! I don't feel so good..."
mood_change = -12
timeout = 10 MINUTES
dont_care_message = "Oh, %DEAD_MOB% was vaporized. Now I have to get the dustpan."
pet_message = "%DEAD_MOB% just vaporized!!"
desensitized_message = "I saw %DEAD_MOB% get vaporized."
normal_message = "%DEAD_MOB% was just vaporized in front of me!!"
/datum/mood_event/slots/loss
description = "Aww dang it!"
mood_change = -2
timeout = 5 MINUTES
event_flags = MOOD_EVENT_GAMING
/datum/mood_event/slots/loss/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/gambler))
mood_change = 0
description = "Aww dang it."
if(HAS_PERSONALITY(owner, /datum/personality/industrious) || HAS_PERSONALITY(owner, /datum/personality/slacking/diligent))
mood_change *= 1.5
/datum/mood_event/lost_control_of_life
description = "I've lost control of my life."
mood_change = -5
timeout = 5 MINUTES
/datum/mood_event/empathetic_sad
description = "Seeing sad people makes me sad."
mood_change = -2
timeout = 3 MINUTES
/datum/mood_event/misanthropic_sad
description = "Seeing happy people makes me uneasy."
mood_change = -2
timeout = 3 MINUTES
/datum/mood_event/paranoid/one_on_one
description = "I'm alone with someone - what if they want to kill me?"
mood_change = -3
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/paranoid/large_group
description = "There are so many people around - any one of them could be out to get me!"
mood_change = -3
event_flags = MOOD_EVENT_FEAR
/datum/mood_event/nt_disillusioned
description = "I hate the company, and everything it stands for."
mood_change = -2
/datum/mood_event/disillusioned_revs_lost
description = "The revolution was defeated... greaaaat."
mood_change = -2
timeout = 10 MINUTES
/datum/mood_event/loyalist_revs_win
description = "The revolution was a success... This will hurt quarterly profits."
mood_change = -2
timeout = 10 MINUTES
/datum/mood_event/slacking_off_diligent
description = "I should get back to work."
mood_change = -1
/datum/mood_event/unimaginative_patronage
description = "That felt like a waste of money."
mood_change = -2
timeout = 5 MINUTES
/datum/mood_event/unimaginative_framing
description = "I could've hung something more useful there."
mood_change = -2
timeout = 5 MINUTES
/datum/mood_event/unimaginative_sculpting
description = "That felt like a waste of materials."
mood_change = -2
timeout = 5 MINUTES
/datum/mood_event/splattered_with_blood
description = "Eugh, I just got coated in blood!"
mood_change = -4
timeout = 4 MINUTES
/datum/mood_event/splattered_with_blood/can_effect_mob(datum/mood/home, mob/living/who, ...)
if(isvampire(who))
return FALSE
return ..()
/datum/mood_event/splattered_with_blood/add_effects(...)
if(HAS_TRAIT(owner, TRAIT_CULT_HALO))
mood_change = 2
description = "Blood, blood! The Geometer will be pleased."
return
if(HAS_TRAIT(owner, TRAIT_MORBID) || HAS_TRAIT(owner, TRAIT_EVIL))
mood_change = 0
description = "I just got coated in blood. Fascinating!"
return
@@ -3,17 +3,53 @@
mood_change = 1
timeout = 2 MINUTES
/datum/mood_event/hug/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/aromantic))
mood_change = -1
description = "A hug? Call HR!"
return
if(HAS_PERSONALITY(owner, /datum/personality/aloof))
mood_change = -1
description = "I would prefer not to be touched."
return
if(HAS_PERSONALITY(owner, /datum/personality/callous))
mood_change = 0
description = "I hate hugs."
return
/datum/mood_event/bear_hug
description = "I got squeezed very tightly, but it was quite nice."
mood_change = 1
timeout = 2 MINUTES
/datum/mood_event/bear_hug/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/aromantic) \
|| HAS_PERSONALITY(owner, /datum/personality/aloof) \
|| HAS_PERSONALITY(owner, /datum/personality/callous) \
)
mood_change = -2
description = "They're squeezing me too tightly!"
return
/datum/mood_event/betterhug
description = "Someone was very nice to me."
mood_change = 3
timeout = 4 MINUTES
/datum/mood_event/betterhug/add_effects(mob/friend)
if(HAS_PERSONALITY(owner, /datum/personality/aromantic))
mood_change = 1
description = "[friend.name] is nice, but that's it."
return
if(HAS_PERSONALITY(owner, /datum/personality/aloof))
mood_change = 1
description = "[friend.name] is nice, but I wish they'd stop touching me."
return
if(HAS_PERSONALITY(owner, /datum/personality/callous))
mood_change = 0
description = "[friend.name] is way too nice for this station."
return
description = "[friend.name] was very nice to me."
/datum/mood_event/besthug
@@ -22,6 +58,19 @@
timeout = 4 MINUTES
/datum/mood_event/besthug/add_effects(mob/friend)
if(HAS_PERSONALITY(owner, /datum/personality/aromantic))
mood_change = 2
description = "[friend.name] is great to be around, but that's it."
return
if(HAS_PERSONALITY(owner, /datum/personality/aloof))
mood_change = 2
description = "[friend.name] is great to be around, but I wish they'd stop touching me."
return
if(HAS_PERSONALITY(owner, /datum/personality/callous))
mood_change = 0
description = "[friend.name] is way too nice for this station."
return
description = "[friend.name] is great to be around, [friend.p_they()] makes me feel so happy!"
/datum/mood_event/warmhug
@@ -29,20 +78,49 @@
mood_change = 1
timeout = 2 MINUTES
/datum/mood_event/warmhug/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/aromantic))
mood_change = 0
description = "I don't like hugs, but the warmth is nice...."
return
if(HAS_PERSONALITY(owner, /datum/personality/aloof))
mood_change = 0
description = "I would prefer not to be touched, but the warmth is nice...."
return
if(HAS_PERSONALITY(owner, /datum/personality/callous))
mood_change = 0
description = "I hate hugs. I can warm myself up."
return
/datum/mood_event/tailpulled
description = "I love getting my tail pulled!"
mood_change = 1
timeout = 2 MINUTES
/datum/mood_event/tailpulled/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/aloof) \
|| HAS_PERSONALITY(owner, /datum/personality/aromantic) \
|| HAS_PERSONALITY(owner, /datum/personality/callous) \
)
mood_change = -2
description = "Who the hell is touching my tail?"
/datum/mood_event/arcade
description = "I beat the arcade game!"
mood_change = 3
timeout = 8 MINUTES
event_flags = MOOD_EVENT_GAMING
/datum/mood_event/arcade/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/industrious) || HAS_PERSONALITY(owner, /datum/personality/slacking/diligent))
mood_change = -1
description = "Wow, I beat the game. I could've been doing anything productive instead."
/datum/mood_event/blessing
description = "I've been blessed."
mood_change = 3
mood_change = 1
timeout = 8 MINUTES
event_flags = MOOD_EVENT_SPIRITUAL
/datum/mood_event/maintenance_adaptation
mood_change = 8
@@ -55,21 +133,67 @@
mood_change = 1
timeout = 5 MINUTES
/datum/mood_event/book_nerd/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/erudite))
mood_change = 2
description = "I love reading books!"
if(HAS_PERSONALITY(owner, /datum/personality/uneducated))
mood_change = -1
description = "Who cares about books?"
/datum/mood_event/exercise
description = "Working out releases those endorphins!"
mood_change = 1
/datum/mood_event/exercise/add_effects(fitness_level)
mood_change = fitness_level // the more fit you are, the more you like to work out
return ..()
if(HAS_PERSONALITY(owner, /datum/personality/slacking/lazy))
mood_change *= -0.5
description = "Working out, what a chore!"
else if(!HAS_PERSONALITY(owner, /datum/personality/athletic))
mood_change *= 0.5
description = "Working out is a bit of a chore, but it is pretty fulfilling."
/datum/mood_event/pet_animal
description = "Animals are adorable! I can't stop petting them!"
mood_change = 2
timeout = 5 MINUTES
/// Tracks the typepath of animal we last petted
var/animal_type
/datum/mood_event/pet_animal/add_effects(mob/animal)
description = "\The [animal.name] is adorable! I can't stop petting [animal.p_them()]!"
animal_type = animal?.type
if(HAS_PERSONALITY(owner, /datum/personality/animal_disliker))
mood_change = -1
description = "Ewww, [animal.name] is so dirty! I don't want to touch it!"
return
var/dog_fan = HAS_PERSONALITY(owner, /datum/personality/dog_fan)
var/isdog = istype(animal, /mob/living/basic/pet/dog)
var/cat_fan = HAS_PERSONALITY(owner, /datum/personality/cat_fan)
var/iscat = istype(animal, /mob/living/basic/pet/cat)
if((dog_fan && isdog) || (cat_fan && iscat) || HAS_PERSONALITY(owner, /datum/personality/animal_friend))
mood_change = 3
description = "I love [animal.name] so much, [animal.p_theyre()] so adorable! I can't stop petting [animal.p_them()]!"
return
if(dog_fan && iscat)
mood_change = -1
description = "I don't like [animal.name]! I prefer dogs!"
return
if(cat_fan && isdog)
mood_change = -1
description = "I don't like [animal.name]! I prefer cats!"
return
mood_change = 1
description = "[animal.name] is adorable!"
// Change the moodlet if we get refreshed (we may have pet another type of animal)
/datum/mood_event/pet_animal/be_refreshed(datum/mood/home, mob/animal)
. = ..()
if(animal_type == animal?.type)
return
add_effects(animal)
/datum/mood_event/honk
description = "I've been honked!"
@@ -77,12 +201,21 @@
timeout = 4 MINUTES
special_screen_obj = "honked_nose"
special_screen_replace = FALSE
event_flags = MOOD_EVENT_WHIMSY
/datum/mood_event/saved_life
description = "It feels good to save a life."
mood_change = 6
timeout = 8 MINUTES
/datum/mood_event/saved_life/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/callous))
mood_change = 0
description = "I don't care much for saving lives."
if(HAS_PERSONALITY(owner, /datum/personality/misanthropic))
mood_change = -1
description = "Saving lives is a waste of time."
/datum/mood_event/oblivious
description = "What a lovely day."
mood_change = 3
@@ -94,16 +227,21 @@
/datum/mood_event/focused
description = "I have a goal, and I will reach it, whatever it takes!" //Used for syndies, nukeops etc so they can focus on their goals
mood_change = 4
mood_change = 8
hidden = TRUE
/datum/mood_event/badass_antag
description = "I'm a fucking badass and everyone around me knows it. Just look at them; they're all fucking shaking at the mere thought of having me around."
mood_change = 7
mood_change = 8
hidden = TRUE
special_screen_obj = "badass_sun"
special_screen_replace = FALSE
/datum/mood_event/ling
description = "We have a goal, and we will reach it, whatever it takes!"
mood_change = 12
hidden = TRUE
/datum/mood_event/creeping
description = "The voices have released their hooks on my mind! I feel free again!" //creeps get it when they are around their obsession
mood_change = 18
@@ -117,17 +255,17 @@
/datum/mood_event/cult
description = "I have seen the truth, praise the almighty one!"
mood_change = 10 //maybe being a cultist isn't that bad after all
mood_change = 12 //maybe being a cultist isn't that bad after all
hidden = TRUE
/datum/mood_event/heretics
description = "THE HIGHER I RISE, THE MORE I SEE."
mood_change = 10 //maybe being a heretic isnt that bad after all
mood_change = 12 //maybe being a heretic isnt that bad after all
hidden = TRUE
/datum/mood_event/rift_fishing
description = "THE MORE I FISH, THE HIGHER I RISE."
mood_change = 7
mood_change = 6
timeout = 5 MINUTES
/datum/mood_event/family_heirloom
@@ -146,6 +284,7 @@
description = "There is something soothing about this music."
mood_change = 3
timeout = 60 SECONDS
event_flags = MOOD_EVENT_ART
/datum/mood_event/chemical_euphoria
description = "Heh...hehehe...hehe..."
@@ -165,30 +304,35 @@
description = "I feel comforted by the presence of a holy person."
mood_change = 3
timeout = 5 MINUTES
event_flags = MOOD_EVENT_SPIRITUAL
/datum/mood_event/clownshoes
description = "The shoes are a clown's legacy, I never want to take them off!"
mood_change = 5
mood_change = 3
/datum/mood_event/sacrifice_good
description = "The gods are pleased with this offering!"
mood_change = 5
timeout = 3 MINUTES
event_flags = MOOD_EVENT_SPIRITUAL
/datum/mood_event/artok
description = "It's nice to see people are making art around here."
mood_change = 2
timeout = 5 MINUTES
event_flags = MOOD_EVENT_ART
/datum/mood_event/artgood
description = "What a thought-provoking piece of art. I'll remember that for a while."
mood_change = 4
timeout = 5 MINUTES
event_flags = MOOD_EVENT_ART
/datum/mood_event/artgreat
description = "That work of art was so great it made me believe in the goodness of humanity. Says a lot in a place like this."
mood_change = 6
timeout = 5 MINUTES
event_flags = MOOD_EVENT_ART
/datum/mood_event/bottle_flip
description = "The bottle landing like that was satisfying."
@@ -199,6 +343,12 @@
description = "What a peculiar emblem. It makes me feel hopeful for my future."
mood_change = 6
/datum/mood_event/hope_lavaland/add_effects(...)
if(HAS_PERSONALITY(owner, /datum/personality/pessimistic))
mood_change = 0
description = "This emblem is a lie. There is no hope for me."
return
/datum/mood_event/confident_mane
description = "I'm feeling confident with a head full of hair."
mood_change = 2
@@ -215,27 +365,45 @@
/datum/mood_event/helped_up
description = "Helping them up felt good!"
mood_change = 2
timeout = 45 SECONDS
/datum/mood_event/helped_up/can_effect_mob(datum/mood/home, mob/living/who, ...)
if(!HAS_PERSONALITY(owner, /datum/personality/compassionate) \
&& !HAS_PERSONALITY(owner, /datum/personality/callous) \
&& !HAS_PERSONALITY(owner, /datum/personality/misanthropic))
return FALSE
return ..()
/datum/mood_event/helped_up/add_effects(mob/other_person, helper)
if(!other_person)
return
if(helper)
description = "Helping [other_person] up felt good!"
else
description = "[other_person] helped me up, how nice of [other_person.p_them()]!"
if(HAS_PERSONALITY(owner, /datum/personality/callous) || HAS_PERSONALITY(owner, /datum/personality/misanthropic))
mood_change = -2
if(helper)
description = "They should have helped themselves."
else
description = "I could've gotten up myself."
else if(HAS_PERSONALITY(owner, /datum/personality/compassionate))
mood_change = 2
if(helper)
description = "Helping [other_person] up felt good!"
else
description = "[other_person] helped me up, how nice of [other_person.p_them()]!"
/datum/mood_event/high_ten
description = "AMAZING! A HIGH-TEN!"
mood_change = 3
timeout = 45 SECONDS
event_flags = MOOD_EVENT_WHIMSY
/datum/mood_event/down_low
description = "HA! What a rube, they never stood a chance..."
mood_change = 4
timeout = 90 SECONDS
event_flags = MOOD_EVENT_WHIMSY
/datum/mood_event/aquarium_positive
description = "Watching fish in an aquarium is calming."
@@ -252,6 +420,10 @@
timeout = 2 MINUTES
/datum/mood_event/kiss/add_effects(mob/beau, direct)
if(HAS_PERSONALITY(owner, /datum/personality/aromantic))
mood_change = -2
description = "A kiss? Call HR!"
return
if(!beau)
return
if(direct)
@@ -277,6 +449,7 @@
description = "Ahaha! It's always funny to see someone get sprayed by a can of soda."
mood_change = 2
timeout = 30 SECONDS
event_flags = MOOD_EVENT_WHIMSY
/datum/mood_event/observed_soda_spill/add_effects(mob/spilled_mob, atom/soda_can)
if(!spilled_mob)
@@ -288,17 +461,29 @@
description = "I'm enjoying a nice gaming session!"
mood_change = 2
timeout = 30 SECONDS
event_flags = MOOD_EVENT_GAMING
/datum/mood_event/gaming/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/industrious) || HAS_PERSONALITY(owner, /datum/personality/slacking/diligent))
mood_change = -1
description = "Is now really the time to be playing games? I should be working."
/datum/mood_event/gamer_won
description = "I love winning video games!"
mood_change = 10
mood_change = 6
timeout = 5 MINUTES
event_flags = MOOD_EVENT_GAMING
/datum/mood_event/love_reagent
description = "This food reminds me of the good ol' days."
mood_change = 5
/datum/mood_event/love_reagent/add_effects(duration)
if(HAS_PERSONALITY(owner, /datum/personality/pessimistic))
mood_change = 0
description = "This food is okay, I guess."
return
if(isnum(duration))
timeout = duration
@@ -306,11 +491,13 @@
description = "HA! That loser will be picking cards up for a long time!"
mood_change = 3
timeout = 3 MINUTES
event_flags = MOOD_EVENT_WHIMSY | MOOD_EVENT_GAMING
/datum/mood_event/playing_cards
description = "I'm enjoying playing cards with other people!"
mood_change = 2
timeout = 3 MINUTES
event_flags = MOOD_EVENT_GAMING
/datum/mood_event/playing_cards/add_effects(param)
var/card_players = 1
@@ -334,7 +521,8 @@
timeout = 5 MINUTES
/datum/mood_event/russian_roulette_win/add_effects(loaded_rounds)
mood_change = 2 ** loaded_rounds
var/base = HAS_PERSONALITY(owner, /datum/personality/gambler) ? 2 : 1.8
mood_change = round(base ** loaded_rounds, 1)
/datum/mood_event/fishing
description = "Fishing is relaxing."
@@ -359,6 +547,7 @@
description = "It felt nice to pet the fish."
mood_change = 2
timeout = 2 MINUTES
event_flags = MOOD_EVENT_WHIMSY
/datum/mood_event/fish_petting/add_effects(obj/item/fish/fish, morbid)
if(!morbid)
@@ -391,11 +580,13 @@
description = "Swish! Nothing but net."
mood_change = 2
timeout = 5 MINUTES
event_flags = MOOD_EVENT_WHIMSY | MOOD_EVENT_GAMING
/datum/mood_event/basketball_dunk
description = "Slam dunk! Boom, shakalaka!"
mood_change = 2
timeout = 5 MINUTES
event_flags = MOOD_EVENT_WHIMSY | MOOD_EVENT_GAMING
/datum/mood_event/moon_smile
description = "THE MOON SHOWS ME THE TRUTH AND ITS SMILE IS FACED TOWARDS ME!!!"
@@ -410,3 +601,103 @@
/datum/mood_event/prophat
description = "This hat fills me with whimsical joy!"
mood_change = 2
event_flags = MOOD_EVENT_WHIMSY
/datum/mood_event/slots
description = "Let's go gambling!"
mood_change = 1
timeout = 1 MINUTES
event_flags = MOOD_EVENT_GAMING
/datum/mood_event/slots/add_effects()
if(HAS_PERSONALITY(owner, /datum/personality/gambler))
mood_change *= 2
else if(HAS_PERSONALITY(owner, /datum/personality/industrious) || HAS_PERSONALITY(owner, /datum/personality/slacking/diligent))
mood_change *= -1
description = "Why am I gambling my time and money away?"
/datum/mood_event/slots/win
description = "Aw yeah I won!"
mood_change = 2
timeout = 5 MINUTES
event_flags = MOOD_EVENT_GAMING
/datum/mood_event/slots/win/be_replaced(datum/mood/home, datum/mood_event/new_event, ...)
if(new_event.mood_change < mood_change)
return BLOCK_NEW_MOOD
return ..()
/datum/mood_event/slots/win/big
mood_change = 3
timeout = 10 MINUTES
/datum/mood_event/slots/win/jackpot
description = "JACKPOT! AW YEAH!"
mood_change = 6
timeout = 30 MINUTES
/datum/mood_event/empathetic_happy
description = "Seeing happy people makes me happy."
mood_change = 2
timeout = 2 MINUTES
/datum/mood_event/misanthropic_happy
description = "Seeing sad people makes me glad."
mood_change = 2
timeout = 2 MINUTES
/datum/mood_event/paranoid/alone
description = "Peace and quiet, no one around to threaten me."
mood_change = 1
/datum/mood_event/paranoid/small_group
description = "I feel safer in this small group. We've got each other's backs."
mood_change = 2
/datum/mood_event/nt_loyalist
description = "I feel proud to be part of the NT™ family!"
mood_change = 2
/datum/mood_event/loyalist_revs_lost
description = "The revolution was defeated! Long live the Nanotrasen!"
mood_change = 4
timeout = 10 MINUTES
/datum/mood_event/disillusioned_revs_win
description = "The revolution was a success! Viva la revolution!"
mood_change = 4
timeout = 10 MINUTES
/datum/mood_event/enjoying_department_area
description = "I love my job."
mood_change = 1
/datum/mood_event/slacking_off_lazy
description = "Boss makes a dollar, I make a dime. That's why I slack on job time."
mood_change = 1
/datum/mood_event/working_diligent
description = "Working hard is its own reward."
mood_change = 1
/datum/mood_event/creative_patronage
description = "Support artists!"
mood_change = 2
timeout = 5 MINUTES
/datum/mood_event/creative_framing
description = "Hanging up art really ties the room together."
mood_change = 2
timeout = 5 MINUTES
/datum/mood_event/creative_sculpting
description = "Sculpting is a great creative outlet."
mood_change = 2
timeout = 5 MINUTES
/datum/mood_event/whimsical_slip
description = "Haha! That guy fell over!"
mood_change = 3
timeout = 2 MINUTES
event_flags = MOOD_EVENT_WHIMSY
+8
View File
@@ -74,6 +74,14 @@
mood_change = -6
timeout = 4 MINUTES
/datum/mood_event/disgust/dirty_food/add_effects(...)
if(HAS_PERSONALITY(owner, /datum/personality/ascetic))
mood_change *= 0.25
description = "That food was dirty, but edible."
if(HAS_PERSONALITY(owner, /datum/personality/gourmand))
mood_change *= 1.5
description = "That food was filthy, was it made in a dumpster?!"
//Generic needs events
/datum/mood_event/shower
description = "I have recently had a nice shower."
+100
View File
@@ -0,0 +1,100 @@
/**
* ## Personality Singleton
*
* Contains information about a personaility.
*
* A personality is designed to be a small modifier to the way a mob reacts to moodlets or world events.
*
* For example, a mob with the Callous personality would not receive a positive moodlet for saving someone's life.
*
* They're not meant to be full blown quirks that hold state and such.
* If you NEED state, consider making a quirk, or moving your behavior into a component the personality applies.
*/
/datum/personality
/// Required: Name of the personality
var/name
/// Required: Description of the personality.
/// Phrased to be "In character" - i.e. "I like to help people!"
/// Rather than OOC 0 i.e. "When helping people, I get a positive moodlet."
var/desc
/// Optional: Short blurb on what positive effects this personality has on gameplay, for ui
var/pos_gameplay_desc
/// Optional: Short blurb on what negative effects this personality has on gameplay, for ui
var/neg_gameplay_desc
/// Optional: Short blurb on what neutral effects this personality has on gameplay, for ui
var/neut_gameplay_desc
/// Easy way to apply a trait as a part of a personality.
var/personality_trait
/// Required: The key to use when saving this personality to a savefile.
/// Don't change it once it's set unless you want to write migration code
var/savefile_key
/// What groups does this personality belong to?
/// Personalities in the same group are mutually exclusive.
var/list/groups
/// Does this personality need to process every tick?
/// If true, you'll need to override on_tick() with logic
var/processes = FALSE
/datum/personality/New()
. = ..()
if(processes)
SSpersonalities.processing_personalities[src] = list()
START_PROCESSING(SSpersonalities, src)
/datum/personality/Destroy(force)
if(force)
STOP_PROCESSING(SSpersonalities, src)
SSpersonalities.processing_personalities -= src
SSpersonalities.personalities_by_type -= type
SSpersonalities.personalities_by_key -= savefile_key
return ..()
stack_trace("qdel called on a personality singleton!")
return QDEL_HINT_LETMELIVE
/**
* Called when applying this personality to a mob.
*
* * who - The mob to apply this personality to.
* This mob is asserted to have `mob_mood`.
*/
/datum/personality/proc/apply_to_mob(mob/living/who)
SHOULD_CALL_PARENT(TRUE)
if(personality_trait)
ADD_TRAIT(who, personality_trait, PERSONALITY_TRAIT)
LAZYSET(who.personalities, type, TRUE)
if(processes)
SSpersonalities.processing_personalities[src] += who
/**
* Called when removing this personality from a mob.
*
* This is not called as a part of the mob being deleted.
*
* * who - The mob to remove this personality from.
* This mob is asserted to have `mob_mood`.
*/
/datum/personality/proc/remove_from_mob(mob/living/who)
SHOULD_CALL_PARENT(TRUE)
if(personality_trait)
REMOVE_TRAIT(who, personality_trait, PERSONALITY_TRAIT)
LAZYREMOVE(who.personalities, type)
if(processes)
SSpersonalities.processing_personalities[src] -= who
/datum/personality/process(seconds_per_tick)
for(var/mob/living/subject as anything in SSpersonalities.processing_personalities[src])
if(subject.stat >= UNCONSCIOUS || HAS_TRAIT(subject, TRAIT_NO_TRANSFORM))
continue
if(on_tick(subject, seconds_per_tick) != PROCESS_KILL)
continue
stack_trace("Personality [type] processed but did not override on_tick().")
SSpersonalities.processing_personalities -= src // stop tracking if we're done processing
return PROCESS_KILL
return null
/// Called every SSpersonality tick if `processes` is TRUE.
/// Don't call parent if you override this, that's for error checking
/datum/personality/proc/on_tick(mob/living/subject, seconds_per_tick)
return PROCESS_KILL
@@ -0,0 +1,41 @@
// These defines are for indicating incompatible personalities by group
/// General Modification to moodlet length
#define PERSONALITY_GROUP_MOOD_LENGTH "reaction_to_thought"
/// General modification to moodlet power
#define PERSONALITY_GROUP_MOOD_POWER "general_reaction"
/// Changes how the person views death
#define PERSONALITY_GROUP_DEATH "reaction_to_death"
/// Changes how the person feels when generally afraid
#define PERSONALITY_GROUP_GENERAL_FEAR "reaction_to_fear"
/// Are we afraid of other people specifically
#define PERSONALITY_GROUP_PEOPLE_FEAR "reaction_to_fear_others"
/// Preferred department / job location
#define PERSONALITY_GROUP_DEPARTMENT "reaction_to_department"
/// Changes how the person views animals, specific or general
#define PERSONALITY_GROUP_ANIMALS "reaction_to_animals"
/// How they view Nanotrasen itself
#define PERSONALITY_GROUP_NT "reaction_to_nt"
/// Opinion of other crewmembers
#define PERSONALITY_GROUP_OTHERS "reaction_to_others"
/// What type of interactions they prefer
#define PERSONALITY_GROUP_INTERACTION "reaction_to_interaction"
/// How they feel about slacking off
#define PERSONALITY_GROUP_RECREATION "reaction_to_recreation"
/// How they feel about the opposite of slacking off
#define PERSONALITY_GROUP_WORK "reaction_to_work"
/// Changes how they react to imbibing alcohol
#define PERSONALITY_GROUP_ALCOHOL "reaction_to_alcohol"
/// Modifies moodlets from food
#define PERSONALITY_GROUP_FOOD "reaction_to_food"
/// How hopeful vs pessimistic they are
#define PERSONALITY_GROUP_HOPE "reaction_to_hope"
/// Specifically how they feel about humanity
#define PERSONALITY_GROUP_MISANTHROPY "reaction_to_misanthropy"
/// Whether they enjoy working out or not
#define PERSONALITY_GROUP_ATHLETICS "reaction_to_athletics"
/// Whether they enjoy art out or not
#define PERSONALITY_GROUP_ART "reaction_to_art"
/// Whether they enjoy reading out or not
#define PERSONALITY_GROUP_READING "reaction_to_reading"
@@ -0,0 +1,43 @@
/datum/preference/personality
savefile_key = "personalities"
savefile_identifier = PREFERENCE_CHARACTER
can_randomize = TRUE
randomize_by_default = FALSE
/datum/preference/personality/apply_to_human(mob/living/carbon/human/target, value)
if(isdummy(target) || !ishuman(target) || isnull(target.mob_mood))
return
if(CONFIG_GET(flag/disable_human_mood) || !CONFIG_GET(flag/roundstart_traits))
return
for(var/personality_key in value)
var/datum/personality/personality = SSpersonalities.personalities_by_key[personality_key]
personality.apply_to_mob(target)
/datum/preference/personality/is_valid(value)
return islist(value) || isnull(value)
/datum/preference/personality/deserialize(input, datum/preferences/preferences)
if(!LAZYLEN(input))
return null
var/list/input_sanitized
for(var/personality_key in input)
var/datum/personality/personality = SSpersonalities.personalities_by_key[personality_key]
if(!istype(personality))
continue
if(SSpersonalities.is_incompatible(input_sanitized, personality.type))
continue
if(LAZYLEN(input_sanitized) >= CONFIG_GET(number/max_personalities))
break
LAZYADD(input_sanitized, personality_key)
return input_sanitized
/datum/preference/personality/create_default_value()
return null
/datum/preference/personality/create_random_value(datum/preferences/preferences)
var/list/random_personalities
for(var/datum/personality/personality_type as anything in SSpersonalities.select_random_personalities())
LAZYADD(random_personalities, initial(personality_type.savefile_key))
return random_personalities
+102
View File
@@ -0,0 +1,102 @@
/datum/personality/apathetic
savefile_key = "apathetic"
name = "Apathetic"
desc = "I don't care about much. Not the good, nor the bad, and certainly not the ugly."
neut_gameplay_desc = "All moodlets affect you less"
groups = list(PERSONALITY_GROUP_MOOD_POWER)
/datum/personality/apathetic/apply_to_mob(mob/living/who)
. = ..()
who.mob_mood?.mood_modifier -= 0.2
/datum/personality/apathetic/remove_from_mob(mob/living/who)
. = ..()
who.mob_mood?.mood_modifier += 0.2
/datum/personality/sensitive
savefile_key = "sensitive"
name = "Sensitive"
desc = "I am easily influenced by the world around me."
neut_gameplay_desc = "All moodlets affect you more"
groups = list(PERSONALITY_GROUP_MOOD_POWER)
/datum/personality/sensitive/apply_to_mob(mob/living/who)
. = ..()
who.mob_mood?.mood_modifier += 0.2
/datum/personality/sensitive/remove_from_mob(mob/living/who)
. = ..()
who.mob_mood?.mood_modifier -= 0.2
/datum/personality/resilient
savefile_key = "resilient"
name = "Resilient"
desc = "It's whatever. I can take it!"
pos_gameplay_desc = "Negative moodlets expire faster"
groups = list(PERSONALITY_GROUP_MOOD_LENGTH)
/datum/personality/resilient/apply_to_mob(mob/living/who)
. = ..()
who.mob_mood?.negative_moodlet_length_modifier -= 0.2
/datum/personality/resilient/remove_from_mob(mob/living/who)
. = ..()
who.mob_mood?.negative_moodlet_length_modifier += 0.2
/datum/personality/brooding
savefile_key = "brooding"
name = "Brooding"
desc = "Everything gets to me and I can't help but think about it."
neg_gameplay_desc = "Negative moodlets last longer"
groups = list(PERSONALITY_GROUP_MOOD_LENGTH)
/datum/personality/brooding/apply_to_mob(mob/living/who)
. = ..()
who.mob_mood?.negative_moodlet_length_modifier += 0.2
/datum/personality/brooding/remove_from_mob(mob/living/who)
. = ..()
who.mob_mood?.negative_moodlet_length_modifier -= 0.2
/datum/personality/hopeful
savefile_key = "hopeful"
name = "Hopeful"
desc = "I believe things will always get better."
pos_gameplay_desc = "Positive moodlets last longer"
groups = list(PERSONALITY_GROUP_HOPE)
/datum/personality/hopeful/apply_to_mob(mob/living/who)
. = ..()
who.mob_mood?.positive_moodlet_length_modifier += 0.2
/datum/personality/hopeful/remove_from_mob(mob/living/who)
. = ..()
who.mob_mood?.positive_moodlet_length_modifier -= 0.2
/datum/personality/pessimistic
savefile_key = "pessimistic"
name = "Pessimistic"
desc = "I believe our best days are behind us."
neg_gameplay_desc = "Positive moodlets last shorter"
groups = list(PERSONALITY_GROUP_HOPE)
/datum/personality/pessimistic/apply_to_mob(mob/living/who)
. = ..()
who.mob_mood?.positive_moodlet_length_modifier -= 0.2
/datum/personality/pessimistic/remove_from_mob(mob/living/who)
. = ..()
who.mob_mood?.positive_moodlet_length_modifier += 0.2
/datum/personality/whimsical
savefile_key = "whimsical"
name = "Whimsical"
desc = "This station is too serious sometimes, lighten up!"
pos_gameplay_desc = "Likes ostensibly pointless but silly things, and does not mind clownish pranks"
/datum/personality/snob
savefile_key = "snob"
name = "Snobbish"
desc = "I expect only the best out of this station - anything less is unacceptable!"
neut_gameplay_desc = "Room quality affects your mood"
personality_trait = TRAIT_SNOB
@@ -0,0 +1,30 @@
/datum/personality/animal_friend
savefile_key = "animal_friend"
name = "Animal Friend"
desc = "I love animals! They'll never leave my side."
pos_gameplay_desc = "Likes being around pets"
neg_gameplay_desc = "Seeing a pet's death affects your mood more"
groups = list(PERSONALITY_GROUP_ANIMALS)
/datum/personality/cat_fan
savefile_key = "cat_fan"
name = "Cat Person"
desc = "Cats are so cute!"
pos_gameplay_desc = "Likes being around cats"
neg_gameplay_desc = "Dislikes being around dogs"
groups = list(PERSONALITY_GROUP_ANIMALS)
/datum/personality/dog_fan
savefile_key = "dog_fan"
name = "Dog Person"
desc = "Dogs are the best!"
pos_gameplay_desc = "Likes being around dogs"
neg_gameplay_desc = "Dislikes being around cats"
groups = list(PERSONALITY_GROUP_ANIMALS)
/datum/personality/animal_disliker
savefile_key = "animal_disliker"
name = "Animal Averse"
desc = "We can barely survive on this station, and you want to keep a pet?"
neg_gameplay_desc = "Dislikes being around pets"
groups = list(PERSONALITY_GROUP_ANIMALS)
@@ -0,0 +1,13 @@
/datum/personality/creative
savefile_key = "creative"
name = "Creative"
desc = "I like expressing myself, especially in a chaotic place like this."
pos_gameplay_desc = "Likes making and seeing art or playing music"
groups = list(PERSONALITY_GROUP_ART)
/datum/personality/unimaginative
savefile_key = "unimaginative"
name = "Unimaginative"
desc = "I'm not good at thinking outside the box. The box is there for a reason."
neg_gameplay_desc = "Ignores art or music and dislikes making new art"
groups = list(PERSONALITY_GROUP_ART)
@@ -0,0 +1,13 @@
/datum/personality/brave
savefile_key = "brave"
name = "Brave"
desc = "It'll take a lot more than a little blood to scare me."
pos_gameplay_desc = "Accumulate fear slower, and moodlets related to fear are weaker"
groups = list(PERSONALITY_GROUP_GENERAL_FEAR, PERSONALITY_GROUP_PEOPLE_FEAR)
/datum/personality/cowardly
savefile_key = "cowardly"
name = "Cowardly"
desc = "Everything is a danger around here! Even the air!"
neg_gameplay_desc = "Accumulate fear faster, and moodlets related to fear are stronger"
groups = list(PERSONALITY_GROUP_GENERAL_FEAR)
@@ -0,0 +1,29 @@
/datum/personality/ascetic
savefile_key = "ascetic"
name = "Ascetic"
desc = "I don't care much for luxurious foods - It's all fuel for the body."
pos_gameplay_desc = "Sorrow from eating disliked food is reduced"
neg_gameplay_desc = "Enjoyment from eating liked food is limited"
groups = list(PERSONALITY_GROUP_FOOD)
/datum/personality/gourmand
savefile_key = "gourmand"
name = "Gourmand"
desc = "Food means everything to me!"
pos_gameplay_desc = "Enjoyment from eating liked food is strengthened"
neg_gameplay_desc = "Sadness from eating food you dislike is increased, and mediocre food is less enjoyable"
groups = list(PERSONALITY_GROUP_FOOD)
/datum/personality/teetotal
savefile_key = "teetotal"
name = "Teetotaler"
desc = "Alcohol isn't for me."
neg_gameplay_desc = "Dislikes drinking alcohol"
groups = list(PERSONALITY_GROUP_ALCOHOL)
/datum/personality/bibulous
savefile_key = "bibulous"
name = "Bibulous"
desc = "I'll always go for another round of drinks!"
pos_gameplay_desc = "Fulfillment from drinking lasts longer, even after you are no longer drunk"
groups = list(PERSONALITY_GROUP_ALCOHOL)
@@ -0,0 +1,56 @@
/datum/personality/introvert
savefile_key = "introvert"
name = "Introverted"
desc = "I prefer to be alone, reading or painting in the library."
pos_gameplay_desc = "Likes being in the library"
// neg_gameplay_desc = "Dislikes large groups"
personality_trait = TRAIT_INTROVERT
groups = list(PERSONALITY_GROUP_INTERACTION)
/datum/personality/extrovert
savefile_key = "extrovert"
name = "Extroverted"
desc = "I prefer to be surrounded by people, having a drink at the Bar."
pos_gameplay_desc = "Likes being in the bar"
// neg_gameplay_desc = "Dislikes being alone"
personality_trait = TRAIT_EXTROVERT
groups = list(PERSONALITY_GROUP_INTERACTION, PERSONALITY_GROUP_OTHERS)
/datum/personality/paranoid
savefile_key = "paranoid"
name = "Paranoid"
desc = "Everyone and everything is out to get me! This place is a deathtrap!"
pos_gameplay_desc = "Likes being alone or in moderately-sized groups"
neg_gameplay_desc = "Stressed when with one other person, or in large groups"
processes = TRUE
groups = list(PERSONALITY_GROUP_PEOPLE_FEAR)
/datum/personality/paranoid/remove_from_mob(mob/living/who)
. = ..()
who.clear_mood_event("paranoia_personality")
/datum/personality/paranoid/on_tick(mob/living/subject, seconds_per_tick)
var/list/nearby_people = list()
for(var/mob/living/carbon/human/nearby in view(subject, 5))
if(nearby == subject || !is_dangerous_mob(subject, nearby))
continue
nearby_people += nearby
switch(length(nearby_people))
if(0)
subject.add_mood_event("paranoia_personality", /datum/mood_event/paranoid/alone)
if(1)
subject.add_mood_event("paranoia_personality", /datum/mood_event/paranoid/one_on_one)
if(2 to 6) // 6 people is roughly the size of the larger jobs like meddoc or secoff
subject.add_mood_event("paranoia_personality", /datum/mood_event/paranoid/small_group)
else
subject.add_mood_event("paranoia_personality", /datum/mood_event/paranoid/large_group)
/datum/personality/paranoid/proc/is_dangerous_mob(mob/living/subject, mob/living/carbon/human/target)
if(target.stat >= UNCONSCIOUS)
return FALSE
if(target.invisibility > subject.see_invisible || target.alpha < 20)
return FALSE
// things that are threatening: other players
// things that are also threatening: monkeys
return TRUE
@@ -0,0 +1,45 @@
/datum/personality/department
groups = list(PERSONALITY_GROUP_DEPARTMENT)
/// List of areas this personality applies to
var/list/applicable_areas
/datum/personality/department/apply_to_mob(mob/living/who)
. = ..()
RegisterSignals(who, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_SET_ROLE), PROC_REF(update_effect))
// Unfortunate side effect here in that IC job changes, IE HoP are missed
who.apply_status_effect(/datum/status_effect/moodlet_in_area, /datum/mood_event/enjoying_department_area, applicable_areas & who.mind?.get_work_areas())
/datum/personality/department/remove_from_mob(mob/living/who)
. = ..()
UnregisterSignal(who, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_SET_ROLE))
who.remove_status_effect(/datum/status_effect/moodlet_in_area, /datum/mood_event/enjoying_department_area)
/// Signal handler to update our status effect when our job changes
/datum/personality/department/proc/update_effect(mob/living/source, ...)
SIGNAL_HANDLER
source.remove_status_effect(/datum/status_effect/moodlet_in_area, /datum/mood_event/enjoying_department_area)
source.apply_status_effect(/datum/status_effect/moodlet_in_area, /datum/mood_event/enjoying_department_area, applicable_areas & source.mind.get_work_areas())
/datum/personality/department/analytical
savefile_key = "analytical"
name = "Analytical"
desc = "When it comes to making decisions, I tend to be more impersonal."
neut_gameplay_desc = "Prefers working in systemic environments like engineering, research, or medical"
applicable_areas = list(
/datum/job_department/engineering::primary_work_area,
/datum/job_department/science::primary_work_area,
/datum/job_department/medical::primary_work_area,
)
/datum/personality/department/impulsive
savefile_key = "impulsive"
name = "Impulsive"
desc = "I'm better making stuff up as I go along."
neut_gameplay_desc = "Prefers working in social environments like cargo, command, security, or service"
applicable_areas = list(
/datum/job_department/cargo::primary_work_area,
/datum/job_department/command::primary_work_area,
/datum/job_department/security::primary_work_area,
/datum/job_department/service::primary_work_area,
)
+38
View File
@@ -0,0 +1,38 @@
/datum/personality/nt
groups = list(PERSONALITY_GROUP_NT)
processes = TRUE
/// What mood event to apply when seeing NT propaganda
var/mood_event_type
/datum/personality/nt/proc/can_see_nt_propaganda(mob/living/subject)
for(var/obj/structure/sign/nearby in view(subject, 5))
if(istype(nearby, /obj/structure/sign/nanotrasen))
return TRUE
if(istype(nearby, /obj/structure/sign/poster/official/nanotrasen_logo))
return TRUE
return FALSE
/datum/personality/nt/on_tick(mob/living/subject, seconds_per_tick)
if(can_see_nt_propaganda(subject))
subject.add_mood_event("nt_personality", mood_event_type)
else
subject.clear_mood_event("nt_personality")
/datum/personality/nt/remove_from_mob(mob/living/who)
. = ..()
who.clear_mood_event("nt_personality")
/datum/personality/nt/loyalist
savefile_key = "loyalist"
name = "Loyal"
desc = "I believe in the station and in Central Command, till the very end!"
pos_gameplay_desc = "Likes company posters and signs"
mood_event_type = /datum/mood_event/nt_loyalist
/datum/personality/nt/disillusioned
savefile_key = "disillusioned"
name = "Disillusioned"
desc = "Nanotrasen isn't what it used to be. This isn't what I signed up for."
neg_gameplay_desc = "Dislikes company posters and signs"
mood_event_type = /datum/mood_event/nt_disillusioned
@@ -0,0 +1,66 @@
/datum/personality/callous
savefile_key = "callous"
name = "Callous"
desc = "I don't care much about what happens to other people."
pos_gameplay_desc = "Does not mind seeing death"
neg_gameplay_desc = "Prefers not to help people"
groups = list(PERSONALITY_GROUP_DEATH)
/datum/personality/compassionate
savefile_key = "compassionate"
name = "Compassionate"
desc = "I like giving a hand to those in need."
pos_gameplay_desc = "Likes helping people"
neg_gameplay_desc = "Seeing death affects your mood more"
groups = list(PERSONALITY_GROUP_DEATH, PERSONALITY_GROUP_MISANTHROPY)
/datum/personality/empathetic
savefile_key = "empathetic"
name = "Empathetic" // according to google "empathic" means you understand other people, while "empathetic" means you feel what they feel
desc = "Other people's feelings are important to me."
pos_gameplay_desc = "Likes seeing other people happy"
neg_gameplay_desc = "Dislikes seeing other people sad"
groups = list(PERSONALITY_GROUP_OTHERS)
/datum/personality/misanthropic
savefile_key = "misanthropic"
name = "Misanthropic"
desc = "We should have never entered the stars."
pos_gameplay_desc = "Likes seeing other people sad"
neg_gameplay_desc = "Dislikes seeing other people happy"
groups = list(PERSONALITY_GROUP_OTHERS, PERSONALITY_GROUP_MISANTHROPY)
/datum/personality/aloof
savefile_key = "aloof"
name = "Aloof"
desc = "Why is everyone so touchy? I'd rather be left alone."
neg_gameplay_desc = "Dislikes being grabbed, touched, or hugged"
personality_trait = TRAIT_BADTOUCH
/datum/personality/aloof/apply_to_mob(mob/living/who)
. = ..()
RegisterSignals(who, list(COMSIG_LIVING_GET_PULLED, COMSIG_CARBON_HELP_ACT), PROC_REF(uncomfortable_touch))
/datum/personality/aloof/remove_from_mob(mob/living/who)
. = ..()
UnregisterSignal(who, list(COMSIG_LIVING_GET_PULLED, COMSIG_CARBON_HELP_ACT))
/// Causes a negative moodlet to our quirk holder on signal
/datum/personality/aloof/proc/uncomfortable_touch(mob/living/source)
SIGNAL_HANDLER
if(source.stat == DEAD)
return
new /obj/effect/temp_visual/annoyed(source.loc)
if(source.mob_mood.sanity <= SANITY_NEUTRAL)
source.add_mood_event("bad_touch", /datum/mood_event/very_bad_touch)
else
source.add_mood_event("bad_touch", /datum/mood_event/bad_touch)
/datum/personality/aromantic
savefile_key = "aromantic"
name = "Aromantic"
desc = "Romance has no place on the station."
neg_gameplay_desc = "Dislikes kisses and hugs"
personality_trait = TRAIT_BADTOUCH
@@ -0,0 +1,109 @@
/datum/personality/gambler
savefile_key = "gambler"
name = "Gambler"
desc = "Throwing the dice is always worth it!"
pos_gameplay_desc = "Likes gambling and card games, and content with losing when gambling"
/datum/personality/slacking
/// Areas which are considered "slacking off"
var/list/slacker_areas = list(
/area/station/commons/fitness,
/area/station/commons/lounge,
/area/station/service/bar,
/area/station/service/cafeteria,
/area/station/service/library,
/area/station/service/minibar,
/area/station/service/theater,
)
/// Mood event applied when in a slacking area
var/mood_event_type
/datum/personality/slacking/apply_to_mob(mob/living/who)
. = ..()
who.apply_status_effect(/datum/status_effect/moodlet_in_area, mood_event_type, slacker_areas, CALLBACK(src, PROC_REF(is_slacking)))
/datum/personality/slacking/remove_from_mob(mob/living/who)
. = ..()
who.remove_status_effect(/datum/status_effect/moodlet_in_area, mood_event_type)
/// Callback for the moodlet_in_area status effect to determine if we're slacking off
/datum/personality/slacking/proc/is_slacking(mob/living/who, area/new_area)
if(!istype(new_area, /area/station/service))
return TRUE
// Service workers don't slack in service
if(who.mind?.assigned_role.departments_bitflags & DEPARTMENT_SERVICE)
return FALSE
return TRUE
/datum/personality/slacking/lazy
savefile_key = "lazy"
name = "Lazy"
desc = "I don't really feel like working today."
pos_gameplay_desc = "Happy in the bar or recreation areas"
mood_event_type = /datum/mood_event/slacking_off_lazy
groups = list(PERSONALITY_GROUP_INTERACTION, PERSONALITY_GROUP_WORK, PERSONALITY_GROUP_ATHLETICS)
/datum/personality/slacking/diligent
savefile_key = "diligent"
name = "Diligent"
desc = "Things need to get done around here!"
pos_gameplay_desc = "Happy when in their department"
neg_gameplay_desc = "Unhappy when slacking off in the bar or recreation areas"
mood_event_type = /datum/mood_event/slacking_off_diligent
groups = list(PERSONALITY_GROUP_INTERACTION)
/datum/personality/slacking/diligent/apply_to_mob(mob/living/who)
. = ..()
RegisterSignals(who, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_SET_ROLE), PROC_REF(update_effect))
// Unfortunate side effect here in that IC job changes, IE HoP are missed
who.apply_status_effect(/datum/status_effect/moodlet_in_area, /datum/mood_event/working_diligent, who.mind?.get_work_areas())
/datum/personality/slacking/diligent/remove_from_mob(mob/living/who)
. = ..()
UnregisterSignal(who, list(COMSIG_MOB_MIND_TRANSFERRED_INTO, COMSIG_MOB_MIND_SET_ROLE))
who.remove_status_effect(/datum/status_effect/moodlet_in_area, /datum/mood_event/working_diligent)
/// Signal handler to update our status effect when our job changes
/datum/personality/slacking/diligent/proc/update_effect(mob/living/source, ...)
SIGNAL_HANDLER
source.remove_status_effect(/datum/status_effect/moodlet_in_area, /datum/mood_event/working_diligent)
source.apply_status_effect(/datum/status_effect/moodlet_in_area, /datum/mood_event/working_diligent, source.mind.get_work_areas())
/datum/personality/industrious
savefile_key = "industrious"
name = "Industrious"
desc = "Everyone needs to be working - otherwise we're all wasting our time."
neg_gameplay_desc = "Dislikes playing games"
groups = list(PERSONALITY_GROUP_WORK)
/datum/personality/athletic
savefile_key = "athletic"
name = "Athletic"
desc = "Can't just sit around all day! Have to keep moving."
pos_gameplay_desc = "Likes exercising"
neg_gameplay_desc = "Dislikes being lazy"
groups = list(PERSONALITY_GROUP_ATHLETICS)
/datum/personality/erudite
savefile_key = "erudite"
name = "Erudite"
desc = "Knowledge is power. Especially this deep in space."
pos_gameplay_desc = "Likes reading books"
groups = list(PERSONALITY_GROUP_READING)
/datum/personality/uneducated
savefile_key = "uneducated"
name = "Uneducated"
desc = "I don't care much for books - I already know everything I need to know."
neg_gameplay_desc = "Dislikes reading books"
groups = list(PERSONALITY_GROUP_READING)
/datum/personality/spiritual
savefile_key = "spiritual"
name = "Spiritual"
desc = "I believe in a higher power."
pos_gameplay_desc = "Likes the Chapel and the Chaplain, and has special prayers"
neg_gameplay_desc = "Dislikes unholy things"
personality_trait = TRAIT_SPIRITUAL
+3 -3
View File
@@ -80,7 +80,7 @@
CRASH("Attempted to add quirk to a holder when it already has a holder.")
quirk_holder = new_holder
quirk_holder.quirks += src
LAZYADD(quirk_holder.quirks, src)
// If we weren't passed a client source try to use a present one
client_source ||= quirk_holder.client
@@ -121,7 +121,7 @@
if(process_update_signals)
UnregisterSignal(quirk_holder, process_update_signals)
quirk_holder.quirks -= src
LAZYREMOVE(quirk_holder.quirks, src)
if(!quirk_transfer && lose_text)
to_chat(quirk_holder, lose_text)
@@ -278,7 +278,7 @@
return medical ? dat.Join("<br>") : dat.Join(", ")
/mob/living/proc/cleanse_quirk_datums() //removes all trait datums
QDEL_LIST(quirks)
QDEL_LAZYLIST(quirks)
/mob/living/proc/transfer_quirk_datums(mob/living/to_mob)
// We could be done before the client was moved or after the client was moved
@@ -1,31 +0,0 @@
/datum/quirk/bad_touch
name = "Bad Touch"
desc = "You don't like hugs. You'd really prefer if people just left you alone."
icon = "tg-bad-touch"
mob_trait = TRAIT_BADTOUCH
value = -1
gain_text = span_danger("You just want people to leave you alone.")
lose_text = span_notice("You could use a big hug.")
medical_record_text = "Patient has disdain for being touched. Potentially has undiagnosed haphephobia."
quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_MOODLET_BASED
hardcore_value = 1
mail_goodies = list(/obj/item/reagent_containers/spray/pepper) // show me on the doll where the bad man touched you
/datum/quirk/bad_touch/add(client/client_source)
RegisterSignals(quirk_holder, list(COMSIG_LIVING_GET_PULLED, COMSIG_CARBON_HELP_ACT), PROC_REF(uncomfortable_touch))
/datum/quirk/bad_touch/remove()
UnregisterSignal(quirk_holder, list(COMSIG_LIVING_GET_PULLED, COMSIG_CARBON_HELP_ACT))
/// Causes a negative moodlet to our quirk holder on signal
/datum/quirk/bad_touch/proc/uncomfortable_touch(datum/source)
SIGNAL_HANDLER
if(quirk_holder.stat == DEAD)
return
new /obj/effect/temp_visual/annoyed(quirk_holder.loc)
if(quirk_holder.mob_mood.sanity <= SANITY_NEUTRAL)
quirk_holder.add_mood_event("bad_touch", /datum/mood_event/very_bad_touch)
else
quirk_holder.add_mood_event("bad_touch", /datum/mood_event/bad_touch)
@@ -0,0 +1,60 @@
/datum/quirk/erratic
name = "Erratic"
desc = "You mood swings like a pendulum, causing your personality to change on a whim every so often."
icon = FA_ICON_MASKS_THEATER
value = -3
gain_text = span_danger("You feel erratic.") // say that again?
lose_text = span_notice("You feel more stable.")
medical_record_text = "Patient has a bipolar personality disorder."
quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_MOODLET_BASED|QUIRK_PROCESSES
hardcore_value = 3
mail_goodies = list(/obj/item/storage/pill_bottle/psicodine)
/// Cooldown between personality randomizations
COOLDOWN_DECLARE(randomize_cooldown)
/// Personalities before the quirk was applied
VAR_PRIVATE/list/base_personalities
/// Every other randomization, revert to base personality
var/random_index = 0
/datum/quirk/erratic/add(client/client_source)
base_personalities = LAZYCOPY(quirk_holder.personalities)
COOLDOWN_START(src, randomize_cooldown, rand(5, 10) MINUTES)
/datum/quirk/erratic/remove()
replace_personalities(base_personalities)
if(!QDELING(quirk_holder))
announce_personality_change()
/datum/quirk/erratic/process(seconds_per_tick)
if(!COOLDOWN_FINISHED(src, randomize_cooldown))
return
if(HAS_TRAIT(quirk_holder, TRAIT_FEARLESS) || quirk_holder.stat >= UNCONSCIOUS)
return
COOLDOWN_START(src, randomize_cooldown, rand(6, 12) MINUTES)
randomize_personalities()
/datum/quirk/erratic/proc/randomize_personalities()
random_index += 1
if(random_index % 2 == 0)
random_index = 0
replace_personalities(base_personalities)
to_chat(quirk_holder, span_notice("You feel... normal."))
announce_personality_change()
return
var/max = CONFIG_GET(number/max_personalities)
var/list/new_personality = prob(1) ? list() : SSpersonalities.select_random_personalities(max - 2, max + 1)
replace_personalities(new_personality)
to_chat(quirk_holder, span_notice("You feel... different."))
announce_personality_change()
/datum/quirk/erratic/proc/replace_personalities(list/new_personalities)
quirk_holder.clear_personalities()
quirk_holder.add_personalities(new_personalities)
/datum/quirk/erratic/proc/announce_personality_change()
var/list/new_personality = list()
for(var/datum/personality/personality_type as anything in quirk_holder.personalities)
new_personality += initial(personality_type.name)
to_chat(quirk_holder, span_green("Your personality is now: [english_list(new_personality)]."))
@@ -1,10 +0,0 @@
/datum/quirk/extrovert
name = "Extrovert"
desc = "You are energized by talking to others, and enjoy spending your free time in the bar."
icon = FA_ICON_USERS
value = 0
mob_trait = TRAIT_EXTROVERT
gain_text = span_notice("You feel like hanging out with other people.")
lose_text = span_danger("You feel like you're over the bar scene.")
medical_record_text = "Patient will not shut the hell up."
mail_goodies = list(/obj/item/reagent_containers/cup/glass/flask)
@@ -1,10 +0,0 @@
/datum/quirk/introvert
name = "Introvert"
desc = "You are energized by having time to yourself, and enjoy spending your free time in the library."
icon = FA_ICON_BOOK_READER
value = 0
mob_trait = TRAIT_INTROVERT
gain_text = span_notice("You feel like reading a good book quietly.")
lose_text = span_danger("You feel like libraries are boring.")
medical_record_text = "Patient doesn't seem to say much."
mail_goodies = list(/obj/item/book/random)
-10
View File
@@ -1,10 +0,0 @@
/datum/quirk/snob
name = "Snob"
desc = "You care about the finer things, if a room doesn't look nice it's just not really worth it, is it?"
icon = FA_ICON_USER_TIE
value = 0
gain_text = span_notice("You feel like you understand what things should look like.")
lose_text = span_notice("Well who cares about deco anyways?")
medical_record_text = "Patient seems to be rather stuck up."
mob_trait = TRAIT_SNOB
mail_goodies = list(/obj/item/chisel, /obj/item/paint_palette)
@@ -1,14 +0,0 @@
/datum/quirk/apathetic
name = "Apathetic"
desc = "You just don't care as much as other people. That's nice to have in a place like this, I guess."
icon = FA_ICON_MEH
value = 4
quirk_flags = QUIRK_HUMAN_ONLY|QUIRK_MOODLET_BASED
medical_record_text = "Patient was administered the Apathy Evaluation Scale but did not bother to complete it."
mail_goodies = list(/obj/item/hourglass)
/datum/quirk/apathetic/add(client/client_source)
quirk_holder.mob_mood?.mood_modifier -= 0.2
/datum/quirk/apathetic/remove()
quirk_holder.mob_mood?.mood_modifier += 0.2
@@ -1,20 +0,0 @@
/datum/quirk/item_quirk/spiritual
name = "Spiritual"
desc = "You hold a spiritual belief, whether in God, nature or the arcane rules of the universe. You gain comfort from the presence of holy people, and believe that your prayers are more special than others. Being in the chapel makes you happy."
icon = FA_ICON_BIBLE
value = 4
mob_trait = TRAIT_SPIRITUAL
gain_text = span_notice("You have faith in a higher power.")
lose_text = span_danger("You lose faith!")
medical_record_text = "Patient reports a belief in a higher power."
mail_goodies = list(
/obj/item/book/bible/booze,
/obj/item/reagent_containers/cup/glass/bottle/holywater,
/obj/item/bedsheet/chaplain,
/obj/item/toy/cards/deck/tarot,
/obj/item/storage/fancy/candle_box,
)
/datum/quirk/item_quirk/spiritual/add_unique(client/client_source)
give_item_to_holder(/obj/item/storage/fancy/candle_box, list(LOCATION_BACKPACK, LOCATION_HANDS))
give_item_to_holder(/obj/item/storage/box/matches, list(LOCATION_BACKPACK, LOCATION_HANDS))
+1 -1
View File
@@ -179,7 +179,7 @@
/// Called before being fully removed (before on_remove)
/// Returning FALSE will cancel removal
/datum/status_effect/proc/before_remove()
/datum/status_effect/proc/before_remove(...)
return TRUE
/// Called when a status effect of status_type STATUS_EFFECT_REFRESH
@@ -108,6 +108,7 @@
. = ..()
owner.sound_environment_override = SOUND_ENVIRONMENT_PSYCHOTIC
owner.add_mood_event(id, /datum/mood_event/drunk, drunk_value)
owner.clear_mood_event("[id]_after")
RegisterSignal(owner, COMSIG_MOB_FIRED_GUN, PROC_REF(drunk_gun_fired))
/datum/status_effect/inebriated/drunk/on_remove()
@@ -122,6 +123,8 @@
/// Clears any side effects we set due to being drunk.
/datum/status_effect/inebriated/drunk/proc/clear_effects()
owner.clear_mood_event(id)
if(!QDELING(owner) && HAS_PERSONALITY(owner, /datum/personality/bibulous))
owner.add_mood_event("[id]_after", /datum/mood_event/drunk_after)
if(owner.sound_environment_override == SOUND_ENVIRONMENT_PSYCHOTIC)
owner.sound_environment_override = SOUND_ENVIRONMENT_NONE
@@ -88,7 +88,6 @@
icon_state = "paralysis"
/datum/mood_event/spacer
category = "spacer"
/datum/mood_event/spacer/in_space
description = "Space is long and dark and empty, but it's my home."
+50
View File
@@ -801,3 +801,53 @@
id = "divine_spotlight"
#undef BEAM_ALPHA
/datum/status_effect/moodlet_in_area
id = "moodlet_in_area"
duration = STATUS_EFFECT_PERMANENT
tick_interval = STATUS_EFFECT_NO_TICK
status_type = STATUS_EFFECT_MULTIPLE
alert_type = null
/// Moodlet to apply while in the area
VAR_PRIVATE/moodlet_type
/// Typecache of areas that will trigger the moodlet while in them
VAR_PRIVATE/list/allowed_areas
/// Optional callback to run when checking if the moodlet should be applied. Should return TRUE to apply, FALSE to not.
VAR_PRIVATE/datum/callback/special_check
/datum/status_effect/moodlet_in_area/on_creation(mob/living/new_owner, moodlet_type, list/allowed_areas, datum/callback/special_check)
src.moodlet_type = moodlet_type
src.allowed_areas = typecacheof(allowed_areas)
src.special_check = special_check
return ..()
/datum/status_effect/moodlet_in_area/before_remove(moodlet_type, ...)
return moodlet_type == src.moodlet_type
/datum/status_effect/moodlet_in_area/on_apply()
if(!length(allowed_areas))
return FALSE
for(var/datum/status_effect/moodlet_in_area/other_effect in owner.status_effects)
if(other_effect.moodlet_type == moodlet_type)
return FALSE
owner.become_area_sensitive("[id]_[moodlet_type]")
RegisterSignal(owner, COMSIG_ENTER_AREA, PROC_REF(check_area))
return TRUE
/datum/status_effect/moodlet_in_area/on_remove()
UnregisterSignal(owner, COMSIG_ENTER_AREA)
owner.lose_area_sensitivity("[id]_[moodlet_type]")
owner.clear_mood_event("[id]_[moodlet_type]")
/datum/status_effect/moodlet_in_area/proc/check_area(datum/source, area/new_area)
SIGNAL_HANDLER
if(special_check && !special_check.Invoke(owner, new_area))
return
if(is_type_in_typecache(new_area, allowed_areas))
owner.add_mood_event("[id]_[moodlet_type]", moodlet_type)
else
owner.clear_mood_event("[id]_[moodlet_type]")