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 14:00:13 -05:00
committed by GitHub
parent 0124adacc7
commit 3ea7b03369
110 changed files with 2557 additions and 314 deletions
+2
View File
@@ -20,6 +20,8 @@
#define IMMUNE_TO_GETTING_WET (1<<5)
/// Disables the function of attacking random body zones
#define PRECISE_ATTACK_ZONES (1<<6)
/// People would be sad to see this mob die
#define SENDS_DEATH_MOODLETS (1<<7)
/// Temporary trait applied when an attack forecast animation has completed
#define TRAIT_BASIC_ATTACK_FORECAST "trait_basic_attack_forecast"
@@ -82,6 +82,8 @@
///signal sent when a mob has their holy role set. Sent to the mob having their role changed.
#define COMSIG_MOB_MIND_SET_HOLY_ROLE "mob_mind_set_holy_role"
///signal sent when a mob has their job role set. Sent to the mob having their role changed.
#define COMSIG_MOB_MIND_SET_ROLE "mob_mind_set_role"
///from base of obj/allowed(mob/M): (/obj) returns ACCESS_ALLOWED if mob has id access to the obj
#define COMSIG_MOB_TRIED_ACCESS "tried_access"
-11
View File
@@ -131,17 +131,6 @@ GLOBAL_LIST_INIT(food_quality_description, list(
FOOD_QUALITY_TOP = "godlike",
))
/// Mood events for food quality
GLOBAL_LIST_INIT(food_quality_events, list(
FOOD_QUALITY_NORMAL = /datum/mood_event/food,
FOOD_QUALITY_NICE = /datum/mood_event/food/nice,
FOOD_QUALITY_GOOD = /datum/mood_event/food/good,
FOOD_QUALITY_VERYGOOD = /datum/mood_event/food/verygood,
FOOD_QUALITY_FANTASTIC = /datum/mood_event/food/fantastic,
FOOD_QUALITY_AMAZING = /datum/mood_event/food/amazing,
FOOD_QUALITY_TOP = /datum/mood_event/food/top,
))
/// Weighted lists of crafted food buffs randomly given according to crafting_complexity unless the food has a specific buff
GLOBAL_LIST_INIT(food_buffs, list(
FOOD_COMPLEXITY_1 = list(
+2
View File
@@ -285,3 +285,5 @@ DEFINE_BITFIELD(job_flags, list(
/// Mind traits that should be shared by every head of staff. has to be this way cause byond lists lol
#define HEAD_OF_STAFF_MIND_TRAITS TRAIT_FAST_TYING, TRAIT_HIGH_VALUE_RANSOM
#define MEDICAL_MIND_TRAITS TRAIT_DESENSITIZED
#define SECURITY_MIND_TRAITS TRAIT_DESENSITIZED
+23
View File
@@ -75,3 +75,26 @@
#define PANIC_ATTACK_TERROR_AMOUNT 50
/// How much terror being hugged reduces, or increases if its done by a nightmare or someone you're afraid of
#define HUG_TERROR_AMOUNT 90
/// Relates to fear or resisting fear
#define MOOD_EVENT_FEAR (1<<0)
/// Relates to art
#define MOOD_EVENT_ART (1<<1)
/// Relates to being a generally silly guy
#define MOOD_EVENT_WHIMSY (1<<2)
/// Playing games and goofing off
#define MOOD_EVENT_GAMING (1<<3)
/// Relates to food
#define MOOD_EVENT_FOOD (1<<4)
/// Relates to being in pain
#define MOOD_EVENT_PAIN (1<<5)
/// Relates to spirituality
#define MOOD_EVENT_SPIRITUAL (1<<6)
/// Checks if the mob has the given personality typepath
#define HAS_PERSONALITY(mob, personality) (LAZYACCESS(mob.personalities, personality))
/// Return from /be_replaced or /be_refreshed to actually go prevent the new mood event from being added
#define BLOCK_NEW_MOOD FALSE
/// Return from /be_replaced or /be_refreshed to actually go through and allow the new mood event to be added
#define ALLOW_NEW_MOOD TRUE
+3
View File
@@ -1563,6 +1563,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
/// Trait that allows an item to perform holy rites akin to a nullrod
#define TRAIT_NULLROD_ITEM "nullrod_item"
/// Mob gets far less severe negative moodlets from seeing death / blood
#define TRAIT_DESENSITIZED "desensitized"
/// Trait specifying that an AI has a remote connection to an integrated circuit
#define TRAIT_CONNECTED_TO_CIRCUIT "connected_to_circuit"
+2
View File
@@ -26,6 +26,8 @@
#define JOB_TRAIT "job"
/// Any traits granted by quirks.
#define QUIRK_TRAIT "quirk_trait"
/// Trait source for personality traits
#define PERSONALITY_TRAIT "personality_trait"
/// (B)admins only.
#define ADMIN_TRAIT "admin"
/// Any traits given through a smite.
+17
View File
@@ -839,3 +839,20 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
else
. = invoked_callback.Invoke()
usr = temp
/**
* Iterates over all mobs that can see the passed movable and adds specific mood events to them based on their personalities.
*
* * source: String source for the mood event
* * personality_to_mood: A list mapping personality types to mood event types. Example: list(/datum/personality/chill = /datum/mood_event/chill_guy)
* * range: The range in which to check for viewers. Default is view range.
* * additional args may be supplied to pass into the mood event constructor.
*/
/proc/add_personality_mood_to_viewers(atom/movable/source, mood_key, list/personality_to_mood, range, ...)
for(var/mob/living/nearby in viewers(range, source))
if(nearby.stat >= UNCONSCIOUS || nearby.is_blind())
continue
for(var/personality in personality_to_mood)
if(HAS_PERSONALITY(nearby, personality))
nearby.add_mood_event(arglist( list("[mood_key]_[personality]", personality_to_mood[personality]) + args.Copy(4) ))
break
+5 -4
View File
@@ -196,9 +196,9 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_BORN_MONKEY" = TRAIT_BORN_MONKEY,
"TRAIT_BOT_PATH_HUD" = TRAIT_BOT_PATH_HUD,
"TRAIT_BOXING_READY" = TRAIT_BOXING_READY,
"TRAIT_BUGKILLER_DEATH" = TRAIT_BUGKILLER_DEATH,
"TRAIT_BRAINWASHING" = TRAIT_BRAINWASHING,
"TRAIT_BRAWLING_KNOCKDOWN_BLOCKED" = TRAIT_BRAWLING_KNOCKDOWN_BLOCKED,
"TRAIT_BUGKILLER_DEATH" = TRAIT_BUGKILLER_DEATH,
"TRAIT_BYPASS_EARLY_IRRADIATED_CHECK" = TRAIT_BYPASS_EARLY_IRRADIATED_CHECK,
"TRAIT_BYPASS_MEASURES" = TRAIT_BYPASS_MEASURES,
"TRAIT_CANNOT_BE_UNBUCKLED" = TRAIT_CANNOT_BE_UNBUCKLED,
@@ -236,18 +236,19 @@ GLOBAL_LIST_INIT(traits_by_type, list(
"TRAIT_DEAF" = TRAIT_DEAF,
"TRAIT_DEATHCOMA" = TRAIT_DEATHCOMA,
"TRAIT_DEFIB_BLACKLISTED" = TRAIT_DEFIB_BLACKLISTED,
"TRAIT_DESENSITIZED" = TRAIT_DESENSITIZED,
"TRAIT_DESIGNATED_TARGET" = TRAIT_DESIGNATED_TARGET,
"TRAIT_DETECTIVES_TASTE" = TRAIT_DETECTIVES_TASTE,
"TRAIT_DETECT_STORM" = TRAIT_DETECT_STORM,
"TRAIT_DIAGNOSTIC_HUD" = TRAIT_DIAGNOSTIC_HUD,
"TRAIT_DISCOORDINATED_TOOL_USER" = TRAIT_DISCOORDINATED_TOOL_USER,
"TRAIT_DISEASELIKE_SEVERITY_MEDIUM" = TRAIT_DISEASELIKE_SEVERITY_MEDIUM,
"TRAIT_DISCO_DANCER" = TRAIT_DISCO_DANCER,
"TRAIT_DISEASELIKE_SEVERITY_HIGH" = TRAIT_DISEASELIKE_SEVERITY_HIGH,
"TRAIT_DISEASELIKE_SEVERITY_MEDIUM" = TRAIT_DISEASELIKE_SEVERITY_MEDIUM,
"TRAIT_DISFIGURED" = TRAIT_DISFIGURED,
"TRAIT_DISGUISED" = TRAIT_DISGUISED,
"TRAIT_DISPLAY_JOB_IN_BINARY" = TRAIT_DISPLAY_JOB_IN_BINARY,
"TRAIT_DISCO_DANCER" = TRAIT_DISCO_DANCER,
"TRAIT_DISK_VERIFIER" = TRAIT_DISK_VERIFIER,
"TRAIT_DISPLAY_JOB_IN_BINARY" = TRAIT_DISPLAY_JOB_IN_BINARY,
"TRAIT_DISSECTED" = TRAIT_DISSECTED,
"TRAIT_DONT_WRITE_MEMORY" = TRAIT_DONT_WRITE_MEMORY,
"TRAIT_DOUBLE_TAP" = TRAIT_DOUBLE_TAP,
+7 -6
View File
@@ -55,22 +55,23 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_BEAST_EMPATHY" = TRAIT_BEAST_EMPATHY,
"TRAIT_BLOB_ALLY" = TRAIT_BLOB_ALLY,
"TRAIT_BLOCK_SHUTTLE_MOVEMENT" = TRAIT_BLOCK_SHUTTLE_MOVEMENT,
"TRAIT_BLOOD_CLANS" = TRAIT_BLOOD_CLANS,
"TRAIT_BLOODSHOT_EYES" = TRAIT_BLOODSHOT_EYES,
"TRAIT_BLOOD_CLANS" = TRAIT_BLOOD_CLANS,
"TRAIT_BOMBIMMUNE" = TRAIT_BOMBIMMUNE,
"TRAIT_BONSAI" = TRAIT_BONSAI,
"TRAIT_BOOZE_SLIDER" = TRAIT_BOOZE_SLIDER,
"TRAIT_BOT_PATH_HUD" = TRAIT_BOT_PATH_HUD,
"TRAIT_BYPASS_MEASURES" = TRAIT_BYPASS_MEASURES,
"TRAIT_CANNOT_BE_UNBUCKLED" = TRAIT_CANNOT_BE_UNBUCKLED,
"TRAIT_CANNOT_OPEN_PRESENTS" = TRAIT_CANNOT_OPEN_PRESENTS,
"TRAIT_CAN_HOLD_ITEMS" = TRAIT_CAN_HOLD_ITEMS,
"TRAIT_CAN_STRIP" = TRAIT_CAN_STRIP,
"TRAIT_CAN_THROW_ITEMS" = TRAIT_CAN_THROW_ITEMS,
"TRAIT_CAN_USE_NUKE" = TRAIT_CAN_USE_NUKE,
"TRAIT_CANNOT_BE_UNBUCKLED" = TRAIT_CANNOT_BE_UNBUCKLED,
"TRAIT_CANNOT_OPEN_PRESENTS" = TRAIT_CANNOT_OPEN_PRESENTS,
"TRAIT_CATLIKE_GRACE" = TRAIT_CATLIKE_GRACE,
"TRAIT_CHASM_DESTROYED" = TRAIT_CHASM_DESTROYED,
"TRAIT_CHUNKYFINGERS_IGNORE_BATON" = TRAIT_CHUNKYFINGERS_IGNORE_BATON,
"TRAIT_CHUNKYFINGERS" = TRAIT_CHUNKYFINGERS,
"TRAIT_CHUNKYFINGERS_IGNORE_BATON" = TRAIT_CHUNKYFINGERS_IGNORE_BATON,
"TRAIT_CLEANBOT_WHISPERER" = TRAIT_CLEANBOT_WHISPERER,
"TRAIT_CLIFF_WALKER" = TRAIT_CLIFF_WALKER,
"TRAIT_CLOWN_ENJOYER" = TRAIT_CLOWN_ENJOYER,
@@ -84,9 +85,9 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_DEAF" = TRAIT_DEAF,
"TRAIT_DEATHCOMA" = TRAIT_DEATHCOMA,
"TRAIT_DEFIB_BLACKLISTED" = TRAIT_DEFIB_BLACKLISTED,
"TRAIT_DESENSITIZED" = TRAIT_DESENSITIZED,
"TRAIT_DETECT_STORM" = TRAIT_DETECT_STORM,
"TRAIT_DIAGNOSTIC_HUD" = TRAIT_DIAGNOSTIC_HUD,
"TRAIT_BOT_PATH_HUD" = TRAIT_BOT_PATH_HUD,
"TRAIT_DISCOORDINATED_TOOL_USER" = TRAIT_DISCOORDINATED_TOOL_USER,
"TRAIT_DISFIGURED" = TRAIT_DISFIGURED,
"TRAIT_DISK_VERIFIER" = TRAIT_DISK_VERIFIER,
@@ -99,12 +100,12 @@ GLOBAL_LIST_INIT(admin_visible_traits, list(
"TRAIT_EMOTEMUTE" = TRAIT_EMOTEMUTE,
"TRAIT_EMPATH" = TRAIT_EMPATH,
"TRAIT_ENTRAILS_READER" = TRAIT_ENTRAILS_READER,
"TRAIT_EVIL" = TRAIT_EVIL,
"TRAIT_EXAMINE_FISHING_SPOT" = TRAIT_EXAMINE_FISHING_SPOT,
"TRAIT_EXAMINE_FITNESS" = TRAIT_EXAMINE_FITNESS,
"TRAIT_EXPANDED_FOV" = TRAIT_EXPANDED_FOV,
"TRAIT_EXPERT_FISHER" = TRAIT_EXPERT_FISHER,
"TRAIT_EXTROVERT" = TRAIT_EXTROVERT,
"TRAIT_EVIL" = TRAIT_EVIL,
"TRAIT_FACE_COVERED" = TRAIT_FACE_COVERED,
"TRAIT_FAKEDEATH" = TRAIT_FAKEDEATH,
"TRAIT_FASTMED" = TRAIT_FASTMED,
@@ -485,6 +485,15 @@
default = 6
min_val = -1
/// Freebie quirk points. Can't go negative because we have no way of enforcing a person has a quirk before they join.
/datum/config_entry/number/default_quirk_points
default = 2
min_val = 0
/// Max personalities you can have at once
/datum/config_entry/number/max_personalities
default = 5
/**
* A config that skews with the random spawners weights
* If the value is lower than 1, it'll tend to even out the odds
@@ -0,0 +1,80 @@
PROCESSING_SUBSYSTEM_DEF(personalities)
name = "Personalities"
runlevels = RUNLEVEL_GAME
flags = SS_BACKGROUND|SS_POST_FIRE_TIMING
wait = 3 SECONDS
/// All personality singletons indexed by their type
VAR_FINAL/list/datum/personality/personalities_by_type
/// All personality singletons indexed by their savefile key
VAR_FINAL/list/datum/personality/personalities_by_key
/// Assoc list of personality group to list of personality typepaths in that group
VAR_FINAL/list/incompatibilities_by_group
/// For personalities which process, this tracks all mobs we need to process for
VAR_FINAL/list/processing_personalities
/datum/controller/subsystem/processing/personalities/Initialize()
init_personalities()
return SS_INIT_SUCCESS
/// Initialized personality singletons
/datum/controller/subsystem/processing/personalities/proc/init_personalities()
personalities_by_type = list()
personalities_by_key = list()
incompatibilities_by_group = list()
processing_personalities = list()
for(var/datum/personality/personality_type as anything in subtypesof(/datum/personality))
var/personality_key = personality_type::savefile_key
if(isnull(personality_key))
// Abstract personality, ignore
continue
if(personalities_by_key[personality_key])
stack_trace("Personality save key collision! \
key: [personality_key] - \
new: [personality_type::name] - \
old: [personalities_by_key[personality_key].name]")
continue
var/datum/personality/personality = new personality_type()
personalities_by_type[personality_type] = personality
personalities_by_key[personality.savefile_key] = personality
for(var/group in personality.groups)
incompatibilities_by_group[group] ||= list()
incompatibilities_by_group[group] += personality_type
/// Helper to check if the new personality type is incompatible with the passed list of personality types
/datum/controller/subsystem/processing/personalities/proc/is_incompatible(list/personality_types, new_personality_type)
if(!length(incompatibilities_by_group))
stack_trace("Checking personality incompatibilities before the incompatibility list was initialized?")
return FALSE
if(length(personality_types))
// No incompatibilities possible with no personalities
return FALSE
var/datum/personality/new_personality = personalities_by_type[new_personality_type]
if(!length(new_personality.groups))
// No groups, so no incompatibilities
return FALSE
// Filters all incompatibily groups against the new personality's groups
for(var/group, incompatibility_list in incompatibilities_by_group & new_personality.groups)
// Then checks if any personality type in the list is also in the group
if(length(incompatibility_list & personality_types))
return TRUE
return FALSE
/// Helper to select a random list of personalities, respecting incompatibilities. REturns a list of typepaths
/datum/controller/subsystem/processing/personalities/proc/select_random_personalities(lower_end = 1, upper_end = CONFIG_GET(number/max_personalities))
var/list/personality_pool = personalities_by_type.Copy()
var/list/selected_personalities = list()
var/num = rand(lower_end, upper_end)
var/i = 1
while(i <= num)
if(!length(personality_pool))
break
var/picked_type = pick(personality_pool)
if(is_incompatible(selected_personalities, picked_type))
continue
selected_personalities += picked_type
personality_pool -= picked_type
i += 1
return selected_personalities
@@ -8,13 +8,11 @@ GLOBAL_LIST_INIT_TYPED(quirk_blacklist, /list/datum/quirk, list(
list(/datum/quirk/item_quirk/blindness, /datum/quirk/item_quirk/scarred_eye),
list(/datum/quirk/item_quirk/blindness, /datum/quirk/item_quirk/fluoride_stare),
list(/datum/quirk/item_quirk/blindness, /datum/quirk/touchy),
list(/datum/quirk/jolly, /datum/quirk/depression, /datum/quirk/apathetic, /datum/quirk/hypersensitive),
list(/datum/quirk/jolly, /datum/quirk/depression, /datum/quirk/hypersensitive),
list(/datum/quirk/no_taste, /datum/quirk/vegetarian, /datum/quirk/deviant_tastes, /datum/quirk/gamer),
list(/datum/quirk/pineapple_liker, /datum/quirk/pineapple_hater, /datum/quirk/gamer),
list(/datum/quirk/alcohol_tolerance, /datum/quirk/light_drinker),
list(/datum/quirk/item_quirk/clown_enjoyer, /datum/quirk/item_quirk/mime_fan),
list(/datum/quirk/bad_touch, /datum/quirk/friendly),
list(/datum/quirk/extrovert, /datum/quirk/introvert),
list(/datum/quirk/prosthetic_limb, /datum/quirk/quadruple_amputee, /datum/quirk/body_purist),
list(/datum/quirk/transhumanist, /datum/quirk/body_purist),
list(/datum/quirk/prosthetic_organ, /datum/quirk/tin_man, /datum/quirk/body_purist),
@@ -107,7 +105,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
*Randomises the quirks for a specified mob
*/
/datum/controller/subsystem/processing/quirks/proc/randomise_quirks(mob/living/user)
var/bonus_quirks = max((length(user.quirks) + rand(-RANDOM_QUIRK_BONUS, RANDOM_QUIRK_BONUS)), MINIMUM_RANDOM_QUIRKS)
var/bonus_quirks = max((LAZYLEN(user.quirks) + rand(-RANDOM_QUIRK_BONUS, RANDOM_QUIRK_BONUS)), MINIMUM_RANDOM_QUIRKS)
var/added_quirk_count = 0 //How many we've added
var/list/quirks_to_add = list() //Quirks we're adding
var/good_count = 0
@@ -181,7 +179,7 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
var/list/positive_quirks = list()
var/points_enabled = !CONFIG_GET(flag/disable_quirk_points)
var/max_positive_quirks = CONFIG_GET(number/max_positive_quirks)
var/balance = 0
var/balance = -CONFIG_GET(number/default_quirk_points)
var/list/all_quirks = get_quirks()
+9 -4
View File
@@ -546,10 +546,15 @@ SUBSYSTEM_DEF(ticker)
var/acting_captain = !is_captain_job(player_assigned_role)
SSjob.promote_to_captain(new_player_living, acting_captain)
OnRoundstart(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(minor_announce), player_assigned_role.get_captaincy_announcement(new_player_living)))
if((player_assigned_role.job_flags & JOB_ASSIGN_QUIRKS) && ishuman(new_player_living) && CONFIG_GET(flag/roundstart_traits))
if(new_player_mob.client?.prefs?.should_be_random_hardcore(player_assigned_role, new_player_living.mind))
new_player_mob.client.prefs.hardcore_random_setup(new_player_living)
SSquirks.AssignQuirks(new_player_living, new_player_mob.client)
if(ishuman(new_player_living))
if(player_assigned_role.job_flags & JOB_ASSIGN_QUIRKS)
if(CONFIG_GET(flag/roundstart_traits))
if(new_player_mob.client?.prefs?.should_be_random_hardcore(player_assigned_role, new_player_living.mind))
new_player_mob.client.prefs.hardcore_random_setup(new_player_living)
SSquirks.AssignQuirks(new_player_living, new_player_mob.client)
else // clear any personalities the prefs added since our job clearly does not want them
new_player_living.clear_personalities()
if(ishuman(new_player_living))
SEND_SIGNAL(new_player_living, COMSIG_HUMAN_CHARACTER_SETUP_FINISHED)
CHECK_TICK
@@ -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]")
+1 -1
View File
@@ -112,7 +112,7 @@
/area/station/service/chapel
name = "\improper Chapel"
icon_state = "chapel"
mood_bonus = 5
mood_bonus = 4
mood_message = "Being in the chapel brings me peace."
mood_trait = TRAIT_SPIRITUAL
ambience_index = AMBIENCE_HOLY
@@ -107,8 +107,19 @@
AddElement(/datum/element/noticable_organ, "%PRONOUN_Their teeth are oddly shaped and yellowing.", BODY_ZONE_PRECISE_MOUTH)
AddElement(/datum/element/organ_set_bonus, /datum/status_effect/organ_set_bonus/rat)
/obj/item/organ/tongue/rat/proc/whimsy_check(mob/living/checking)
if(check_holidays(APRIL_FOOLS))
return TRUE
if(HAS_PERSONALITY(checking, /datum/personality/whimsical))
return TRUE
if(prob(1))
return TRUE
return FALSE
/obj/item/organ/tongue/rat/modify_speech(datum/source, list/speech_args)
. = ..()
if(!whimsy_check(source))
return
var/message = LOWER_TEXT(speech_args[SPEECH_MESSAGE])
if(message == "hi" || message == "hi.")
speech_args[SPEECH_MESSAGE] = "Cheesed to meet you!"
@@ -125,6 +136,8 @@
/obj/item/organ/tongue/rat/proc/on_item_given(mob/living/carbon/offerer, mob/living/taker, obj/item/given)
SIGNAL_HANDLER
if(!whimsy_check(offerer))
return
INVOKE_ASYNC(src, PROC_REF(its_on_the_mouse), offerer, taker)
/obj/item/organ/tongue/rat/proc/its_on_the_mouse(mob/living/carbon/offerer, mob/living/taker)
+12 -4
View File
@@ -220,11 +220,14 @@
cut_overlays()
update_appearance()
set_light(0)
if(isliving(user))
var/mob/living/living_user = user
living_user.add_mood_event("roulette", /datum/mood_event/slots)
var/rolled_number = rand(0, 36)
playsound(src, 'sound/machines/roulette/roulettewheel.ogg', 50)
addtimer(CALLBACK(src, PROC_REF(finish_play), player_id, bet_type, bet_amount, payout, rolled_number), 34) //4 deciseconds more so the animation can play
addtimer(CALLBACK(src, PROC_REF(finish_play), player_id, bet_type, bet_amount, payout, rolled_number, user), 34) //4 deciseconds more so the animation can play
addtimer(CALLBACK(src, PROC_REF(finish_play_animation)), 3 SECONDS)
use_energy(active_power_usage)
@@ -235,7 +238,7 @@
playsound(src, 'sound/machines/piston/piston_lower.ogg', 70)
///Ran after a while to check if the player won or not.
/obj/machinery/roulette/proc/finish_play(obj/item/card/id/player_id, bet_type, bet_amount, potential_payout, rolled_number)
/obj/machinery/roulette/proc/finish_play(obj/item/card/id/player_id, bet_type, bet_amount, potential_payout, rolled_number, mob/user)
last_spin = rolled_number
var/is_winner = check_win(bet_type, bet_amount, rolled_number) //Predetermine if we won
@@ -249,8 +252,11 @@
handle_color_light(color)
if(!is_winner)
say("You lost! Better luck next time")
say("You lost! Better luck next time.")
playsound(src, 'sound/machines/synth/synth_no.ogg', 50)
if(isliving(user) && (user in viewers(src)))
var/mob/living/living_user = user
living_user.add_mood_event("roulette", /datum/mood_event/slots/loss)
return FALSE
// Prevents money generation exploits. Doesn't prevent the owner being a scrooge and running away with the money.
@@ -259,7 +265,9 @@
say("You have won [potential_payout] credits! Congratulations!")
playsound(src, 'sound/machines/synth/synth_yes.ogg', 50)
if(isliving(user) && (user in viewers(src)))
var/mob/living/living_user = user
living_user.add_mood_event("roulette", potential_payout >= ROULETTE_JACKPOT_AMOUNT ? /datum/mood_event/slots/win/jackpot : /datum/mood_event/slots/win/big)
dispense_prize(potential_payout)
///Fills a list of coins that should be dropped.
+15
View File
@@ -227,6 +227,9 @@
if(user)
the_name = user.real_name
visible_message(span_notice("[user] pulls the lever and the slot machine starts spinning!"))
if(isliving(user))
var/mob/living/living_user = user
living_user.add_mood_event("slots_spin", /datum/mood_event/slots)
else
the_name = "Exaybachay"
@@ -308,6 +311,9 @@
var/prize = money + JACKPOT
visible_message("<b>[src]</b> says, 'JACKPOT! You win [prize] credits!'")
priority_announce("Congratulations to [user ? user.real_name : usrname] for winning the jackpot at the slot machine in [get_area(src)]!")
if(isliving(user) && (user in viewers(src)))
var/mob/living/living_user = user
living_user.add_mood_event("slots", /datum/mood_event/slots/win/jackpot)
jackpots += 1
money = 0
if(paymode == HOLOCHIP)
@@ -323,10 +329,16 @@
else if(linelength == 5)
visible_message("<b>[src]</b> says, 'Big Winner! You win a thousand credits!'")
give_money(BIG_PRIZE)
if(isliving(user) && (user in viewers(src)))
var/mob/living/living_user = user
living_user.add_mood_event("slots", /datum/mood_event/slots/win/big)
else if(linelength == 4)
visible_message("<b>[src]</b> says, 'Winner! You win four hundred credits!'")
give_money(SMALL_PRIZE)
if(isliving(user) && (user in viewers(src)))
var/mob/living/living_user = user
living_user.add_mood_event("slots", /datum/mood_event/slots/win)
else if(linelength == 3)
to_chat(user, span_notice("You win three free games!"))
@@ -337,6 +349,9 @@
balloon_alert(user, "no luck!")
playsound(src, 'sound/machines/buzz/buzz-sigh.ogg', 50)
did_player_win = FALSE
if(isliving(user) && (user in viewers(src)))
var/mob/living/living_user = user
living_user.add_mood_event("slots", /datum/mood_event/slots/loss)
if(did_player_win)
add_filter("jackpot_rays", 3, ray_filter)
@@ -852,6 +852,9 @@
if(splatter_strength <= 0)
break
iter_atom.add_blood_DNA(GET_ATOM_BLOOD_DNA(src))
if(isliving(iter_atom))
var/mob/living/splatted = iter_atom
splatted.add_mood_event("splattered_with_blood", /datum/mood_event/splattered_with_blood)
splatter_strength--
// we used all our blood so go away
@@ -105,8 +105,6 @@
/datum/mood_event/poster_mood
description = "That poster is really motivating me!"
mood_change = 2
category = POSTER_MOOD_CAT
// random posters
-1
View File
@@ -457,7 +457,6 @@
playsound(slipper.loc, 'sound/misc/slip.ogg', 50, TRUE, -3)
SEND_SIGNAL(slipper, COMSIG_ON_CARBON_SLIP)
slipper.add_mood_event("slipped", /datum/mood_event/slipped)
if(force_drop && iscarbon(slipper)) //carbon specific behavior that living doesn't have
var/mob/living/carbon/carbon = slipper
for(var/obj/item/item in slipper.held_items)
@@ -6,7 +6,7 @@
roundend_category = "changelings"
antagpanel_category = "Changeling"
pref_flag = ROLE_CHANGELING
antag_moodlet = /datum/mood_event/focused
antag_moodlet = /datum/mood_event/ling
antag_hud_name = "changeling"
hijack_speed = 0.5
ui_name = "AntagInfoChangeling"
@@ -58,6 +58,7 @@
SEND_SOUND(mind.current, 'sound/music/antag/bloodcult/bloodcult_eyes.ogg')
to_chat(mind.current, span_cult_large(span_warning("The veil weakens as your cult grows, your eyes begin to glow...")))
mind.current.AddElement(/datum/element/cult_eyes)
ADD_TRAIT(mind.current, TRAIT_DESENSITIZED, CULT_TRAIT)
cult_risen = TRUE
log_game("The blood cult has risen with [cultplayers] players.")
@@ -65,6 +65,7 @@
if(cult_team.cult_risen)
current.AddElement(/datum/element/cult_eyes, initial_delay = 0 SECONDS)
ADD_TRAIT(current, TRAIT_DESENSITIZED, CULT_TRAIT)
if(cult_team.cult_ascendent)
current.AddElement(/datum/element/cult_halo, initial_delay = 0 SECONDS)
@@ -87,7 +88,8 @@
if (HAS_TRAIT(current, TRAIT_CULT_HALO))
current.RemoveElement(/datum/element/cult_halo)
REMOVE_TRAIT(owner.current, TRAIT_HEALS_FROM_CULT_PYLONS, CULT_TRAIT)
REMOVE_TRAIT(current, TRAIT_DESENSITIZED, CULT_TRAIT)
REMOVE_TRAIT(current, TRAIT_HEALS_FROM_CULT_PYLONS, CULT_TRAIT)
/datum/antagonist/cult/on_mindshield(mob/implanter)
if(!silent)
+8
View File
@@ -36,6 +36,14 @@
equipERT()
. = ..()
/datum/antagonist/ert/apply_innate_effects(mob/living/mob_override)
var/mob/living/carbon/human/officer = mob_override || owner.current
ADD_TRAIT(officer, TRAIT_DESENSITIZED, REF(src))
/datum/antagonist/ert/remove_innate_effects(mob/living/mob_override)
var/mob/living/carbon/human/officer = mob_override || owner.current
REMOVE_TRAIT(officer, TRAIT_DESENSITIZED, REF(src))
/datum/antagonist/ert/get_team()
return ert_team
@@ -606,6 +606,7 @@
if(!isnull(ascension_achievement))
user.client?.give_award(ascension_achievement, user)
heretic_datum.increase_rust_strength()
ADD_TRAIT(user, TRAIT_DESENSITIZED, type)
return TRUE
/datum/heretic_knowledge/ultimate/cleanup_atoms(list/selected_atoms)
@@ -62,6 +62,7 @@
on_made_callback?.Invoke(human_target)
ADD_TRAIT(human_target, TRAIT_FAKEDEATH, TRAIT_STATUS_EFFECT(id))
ADD_TRAIT(human_target, TRAIT_HERETIC_SUMMON, TRAIT_STATUS_EFFECT(id))
ADD_TRAIT(human_target, TRAIT_DESENSITIZED, TRAIT_STATUS_EFFECT(id))
human_target.become_husk(TRAIT_STATUS_EFFECT(id))
human_target.faction |= FACTION_HERETIC
@@ -92,6 +93,7 @@
on_lost_callback?.Invoke(human_target)
REMOVE_TRAIT(human_target, TRAIT_FAKEDEATH, TRAIT_STATUS_EFFECT(id))
REMOVE_TRAIT(human_target, TRAIT_HERETIC_SUMMON, TRAIT_STATUS_EFFECT(id))
REMOVE_TRAIT(human_target, TRAIT_DESENSITIZED, TRAIT_STATUS_EFFECT(id))
human_target.cure_husk(TRAIT_STATUS_EFFECT(id))
human_target.faction -= FACTION_HERETIC
human_target.mind?.remove_antag_datum(/datum/antagonist/heretic_monster)
@@ -8,12 +8,13 @@
antag_flags = ANTAG_FAKE|ANTAG_SKIP_GLOBAL_LIST
/// Traits we apply/remove to our target on-demand.
var/static/list/applicable_traits = list(
TRAIT_DESENSITIZED,
TRAIT_NOBREATH,
TRAIT_NODISMEMBER,
TRAIT_NOFIRE,
TRAIT_NOGUNS,
TRAIT_TOSS_GUN_HARD,
TRAIT_SHOCKIMMUNE,
TRAIT_TOSS_GUN_HARD,
)
/datum/antagonist/highlander/apply_innate_effects(mob/living/mob_override)
@@ -17,6 +17,14 @@
forge_objectives()
. = ..()
/datum/antagonist/nightmare/apply_innate_effects(mob/living/mob_override)
var/mob/living/nightmare = mob_override || owner.current
nightmare.mob_mood.mood_modifier -= 1
/datum/antagonist/nightmare/remove_innate_effects(mob/living/mob_override)
var/mob/living/nightmare = mob_override || owner.current
nightmare.mob_mood.mood_modifier += 1
/datum/outfit/nightmare
name = "Nightmare (Preview only)"
@@ -40,6 +40,7 @@
/datum/antagonist/nukeop/on_gain()
give_alias()
forge_objectives()
owner.current.add_personality(/datum/personality/callous)
. = ..()
owner.set_assigned_role(SSjob.get_job_type(job_type))
equip_op()
@@ -129,6 +130,7 @@
var/mob/living/carbon/human/operative = owner.current
ADD_TRAIT(operative, TRAIT_NOFEAR_HOLDUPS, INNATE_TRAIT)
ADD_TRAIT(operative, TRAIT_DESENSITIZED, INNATE_TRAIT)
if(!nukeop_outfit) // this variable is null in instances where an antagonist datum is granted via enslaving the mind (/datum/mind/proc/enslave_mind_to_creator), like in golems.
return
+3 -2
View File
@@ -46,11 +46,12 @@
var/datum/language_holder/holder = owner_mob.get_language_holder()
holder.grant_language(/datum/language/piratespeak, source = LANGUAGE_PIRATE)
holder.selected_language = /datum/language/piratespeak
ADD_TRAIT(owner_mob, TRAIT_DESENSITIZED, REF(src))
/datum/antagonist/pirate/remove_innate_effects(mob/living/mob_override)
var/mob/living/owner_mob = mob_override || owner.current
if (owner_mob)
owner_mob.remove_language(/datum/language/piratespeak, source = LANGUAGE_PIRATE)
owner_mob.remove_language(/datum/language/piratespeak, source = LANGUAGE_PIRATE)
REMOVE_TRAIT(owner_mob, TRAIT_DESENSITIZED, REF(src))
/datum/team/pirate
name = "\improper Pirate crew"
@@ -73,6 +73,10 @@ GLOBAL_DATUM(revolution_handler, /datum/revolution_handler)
if(isnull(real_headrev))
continue
add_memory_in_range(real_headrev, 5, /datum/memory/revolution_rev_victory, protagonist = real_headrev)
add_personality_mood_to_viewers(real_headrev, "revwin", list(
/datum/personality/nt/loyalist = /datum/mood_event/loyalist_revs_win,
/datum/personality/nt/disillusioned = /datum/mood_event/disillusioned_revs_win,
), range = 5)
result = REVOLUTION_VICTORY
@@ -99,6 +103,10 @@ GLOBAL_DATUM(revolution_handler, /datum/revolution_handler)
var/mob/living/head_of_staff = head_tracker.target?.current
if(!isnull(head_of_staff))
add_memory_in_range(head_of_staff, 5, /datum/memory/revolution_heads_victory, protagonist = head_of_staff)
add_personality_mood_to_viewers(head_of_staff, "revlost", list(
/datum/personality/nt/loyalist = /datum/mood_event/loyalist_revs_lost,
/datum/personality/nt/disillusioned = /datum/mood_event/disillusioned_revs_lost
), range = 5)
priority_announce("It appears the mutiny has been quelled. Please return yourself and your incapacitated colleagues to work. \
We have remotely blacklisted the head revolutionaries in your medical records to prevent accidental revival.", null, null, null, "[command_name()] Loyalty Monitoring Division")
@@ -15,6 +15,14 @@
///Whether or not this ninja will obtain objectives
var/give_objectives = TRUE
/datum/antagonist/ninja/apply_innate_effects(mob/living/mob_override)
var/mob/ninja = mob_override || owner.current
ADD_TRAIT(ninja, TRAIT_DESENSITIZED, REF(src))
/datum/antagonist/ninja/remove_innate_effects(mob/living/mob_override)
var/mob/ninja = mob_override || owner.current
REMOVE_TRAIT(ninja, TRAIT_DESENSITIZED, REF(src))
/**
* Proc that equips the space ninja outfit on a given individual. By default this is the owner of the antagonist datum.
*
+2 -1
View File
@@ -84,7 +84,8 @@ GLOBAL_LIST_EMPTY(wizard_spellbook_purchases_by_key)
CRASH("Wizard datum with no owner.")
assign_ritual()
equip_wizard()
owner.current.add_quirk(/datum/quirk/introvert, announce = FALSE)
owner.current.add_personality(/datum/personality/introvert)
owner.current.add_personality(/datum/personality/callous) // no sense of right and wrong
if(give_objectives)
create_objectives()
if(move_to_lair)
+11 -3
View File
@@ -275,7 +275,7 @@
#define CURATOR_PERCENTILE_CUT 0.225
#define SERVICE_PERCENTILE_CUT 0.125
/obj/item/canvas/proc/patron(mob/user)
/obj/item/canvas/proc/patron(mob/living/user)
if(!finalized || !isliving(user))
return
if(!painting_metadata.loaded_from_json)
@@ -327,6 +327,10 @@
last_patron = WEAKREF(user.mind)
to_chat(user, span_notice("Nanotrasen Trust Foundation thanks you for your contribution. You're now an official patron of this painting."))
if(HAS_PERSONALITY(user, /datum/personality/creative))
user.add_mood_event("creative_patronage", /datum/mood_event/creative_patronage)
if(HAS_PERSONALITY(user, /datum/personality/unimaginative))
user.add_mood_event("unimaginative_patronage", /datum/mood_event/unimaginative_patronage)
var/list/possible_frames = SSpersistent_paintings.get_available_frames(offer_amount)
if(possible_frames.len <= 1) // Not much room for choices here.
return
@@ -770,7 +774,7 @@
INVOKE_ASYNC(current_canvas, TYPE_PROC_REF(/obj/item/canvas, select_new_frame), user)
return CLICK_ACTION_SUCCESS
/obj/structure/sign/painting/proc/frame_canvas(mob/user, obj/item/canvas/new_canvas)
/obj/structure/sign/painting/proc/frame_canvas(mob/living/user, obj/item/canvas/new_canvas)
if(!(new_canvas.type in accepted_canvas_types))
to_chat(user, span_warning("[new_canvas] won't fit in this frame."))
return FALSE
@@ -781,6 +785,10 @@
to_chat(user,span_notice("You frame [current_canvas]."))
add_art_element()
update_appearance()
if(HAS_PERSONALITY(user, /datum/personality/creative))
user.add_mood_event("creative_framing", /datum/mood_event/creative_framing)
if(HAS_PERSONALITY(user, /datum/personality/unimaginative))
user.add_mood_event("unimaginative_framing", /datum/mood_event/unimaginative_framing)
return TRUE
return FALSE
@@ -971,7 +979,7 @@
if(EAST)
bound_height = 64
/obj/structure/sign/painting/large/frame_canvas(mob/user, obj/item/canvas/new_canvas)
/obj/structure/sign/painting/large/frame_canvas(mob/living/user, obj/item/canvas/new_canvas)
. = ..()
if(.)
set_painting_offsets()
+4
View File
@@ -401,6 +401,10 @@ Moving interrupts
if(!interrupted && !QDELETED(prepared_block))
prepared_block.create_statue()
user.balloon_alert(user, "statue finished")
if(HAS_PERSONALITY(user, /datum/personality/creative))
user.add_mood_event("creative_sculpting", /datum/mood_event/creative_sculpting)
if(HAS_PERSONALITY(user, /datum/personality/unimaginative))
user.add_mood_event("unimaginative_sculpting", /datum/mood_event/unimaginative_sculpting)
stop_sculpting(silent = !interrupted)
/// To setup the sculpting target for the carving block
+1 -1
View File
@@ -417,7 +417,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
return TRUE
/datum/preferences/proc/GetQuirkBalance()
var/bal = 0
var/bal = CONFIG_GET(number/default_quirk_points)
for(var/V in all_quirks)
var/datum/quirk/T = SSquirks.quirks[V]
bal -= initial(T.value)
@@ -0,0 +1,66 @@
/datum/preference_middleware/personality
action_delegations = list(
"handle_personality" = PROC_REF(handle_personality),
"clear_personalities" = PROC_REF(clear_personalities),
)
/datum/preference_middleware/personality/proc/handle_personality(list/params, mob/user)
var/datum/personality/personality_type = text2path(params["personality_type"])
if(!ispath(personality_type, /datum/personality))
return FALSE
var/personality_key = initial(personality_type.savefile_key)
var/list/personalities = preferences.read_preference(/datum/preference/personality)
if(personality_key in personalities)
LAZYREMOVE(personalities, personality_key)
else
if(LAZYLEN(personalities) >= CONFIG_GET(number/max_personalities))
return TRUE
if(SSpersonalities.is_incompatible(personalities, personality_type))
return TRUE
LAZYADD(personalities, personality_key)
preferences.update_preference(GLOB.preference_entries[/datum/preference/personality], personalities)
return TRUE
/datum/preference_middleware/personality/proc/clear_personalities(list/params, mob/user)
preferences.update_preference(GLOB.preference_entries[/datum/preference/personality], null)
return TRUE
/datum/preference_middleware/personality/get_constant_data()
var/list/data = list()
data["personalities"] = list()
for(var/datum/personality/personality_type as anything in SSpersonalities.personalities_by_type)
var/datum/personality/personality = SSpersonalities.personalities_by_type[personality_type]
data["personalities"] += list(list(
"description" = personality.desc,
"pos_gameplay_description" = personality.pos_gameplay_desc,
"neg_gameplay_description" = personality.neg_gameplay_desc,
"neut_gameplay_description" = personality.neut_gameplay_desc,
"name" = personality.name,
"path" = personality_type,
"groups" = personality.groups,
))
data["personality_incompatibilities"] = SSpersonalities.incompatibilities_by_group
return data
/datum/preference_middleware/personality/get_ui_static_data(mob/user)
var/list/data = list()
var/max = CONFIG_GET(number/max_personalities)
data["max_personalities"] = max >= length(SSpersonalities.personalities_by_type) ? -1 : max
data["mood_enabled"] = !CONFIG_GET(flag/disable_human_mood)
return data
/datum/preference_middleware/personality/get_ui_data(mob/user)
var/list/data = list()
data["selected_personalities"] = list()
for(var/personality_key in preferences.read_preference(/datum/preference/personality))
var/datum/personality/personality = SSpersonalities.personalities_by_key[personality_key]
data["selected_personalities"] += personality.type
return data
@@ -49,6 +49,7 @@
var/list/data = list()
data["selected_quirks"] = get_selected_quirks()
data["default_quirk_balance"] = CONFIG_GET(number/default_quirk_points)
data["species_disallowed_quirks"] = get_species_compatibility()
return data
@@ -0,0 +1,16 @@
/**
* Replace a quirk with a personality
*
* If this is accompanied with removal of a quirk,
* you don't need to worry about handling that here -
* quirk sanitization happens AFTER migration
*/
/datum/preferences/proc/migrate_quirk_to_personality(quirk_to_migrate, datum/personality/new_typepath)
ASSERT(istext(quirk_to_migrate) && ispath(new_typepath, /datum/personality))
if(!(quirk_to_migrate in all_quirks))
return
var/list/personalities = read_preference(/datum/preference/personality)
if(LAZYLEN(personalities) >= CONFIG_GET(number/max_personalities))
return
LAZYADD(personalities, initial(new_typepath.savefile_key))
write_preference(GLOB.preference_entries[/datum/preference/personality], personalities)
+26 -1
View File
@@ -13,7 +13,7 @@
/// You do not need to raise this if you are adding new values that have sane defaults.
/// Only raise this value when changing the meaning/format/name/layout of an existing value
/// where you would want the updater procs below to run
#define SAVEFILE_VERSION_MAX 49
#define SAVEFILE_VERSION_MAX 50
#define IS_DATA_OBSOLETE(version) (version == SAVE_DATA_OBSOLETE)
#define SHOULD_UPDATE_DATA(version) (version >= SAVE_DATA_NO_ERROR && version < SAVEFILE_VERSION_MAX)
@@ -137,6 +137,31 @@ SAVEFILE UPDATING/VERSIONING - 'Simplified', or rather, more coder-friendly ~Car
quirk_to_migrate = "Cyborg Pre-screened dogtag",
new_typepath = /obj/item/clothing/accessory/dogtag/borg_ready,
)
if(current_version < 50)
migrate_quirk_to_personality(
quirk_to_migrate = "Extrovert",
new_typepath = /datum/personality/extrovert,
)
migrate_quirk_to_personality(
quirk_to_migrate = "Introvert",
new_typepath = /datum/personality/introvert,
)
migrate_quirk_to_personality(
quirk_to_migrate = "Bad Touch",
new_typepath = /datum/personality/aloof,
)
migrate_quirk_to_personality(
quirk_to_migrate = "Apathetic",
new_typepath = /datum/personality/apathetic,
)
migrate_quirk_to_personality(
quirk_to_migrate = "Snob",
new_typepath = /datum/personality/snob,
)
migrate_quirk_to_personality(
quirk_to_migrate = "Spiritual",
new_typepath = /datum/personality/spiritual,
)
/// checks through keybindings for outdated unbound keys and updates them
/datum/preferences/proc/check_keybindings()
+10 -1
View File
@@ -18,6 +18,8 @@
var/list/department_jobs = list()
/// For separatists, what independent name prefix does their nation get named?
var/list/nation_prefixes = list()
/// Root type for the area that people in this department primarily work in.
var/primary_work_area
/// List of /area types that are considered part of this department's "delivery" area.
/// Acts as a priority system, where first items are picked first.
var/list/department_delivery_areas = list()
@@ -68,6 +70,7 @@
department_name = DEPARTMENT_CAPTAIN
department_bitflags = DEPARTMENT_BITFLAG_CAPTAIN
department_head = /datum/job/captain
primary_work_area = /area/station/command
/datum/job_department/command
department_name = DEPARTMENT_COMMAND
@@ -77,7 +80,7 @@
display_order = 1
label_class = "command"
ui_color = "#6681a5"
primary_work_area = /area/station/command
/datum/job_department/security
department_name = DEPARTMENT_SECURITY
@@ -88,6 +91,7 @@
label_class = "security"
ui_color = "#d46a78"
nation_prefixes = list("Securi", "Beepski", "Shitcuri", "Red", "Stunba", "Flashbango", "Flasha", "Stanfordi")
primary_work_area = /area/station/security
department_delivery_areas = list(
/area/station/security/office,
/area/station/security/brig,
@@ -110,6 +114,7 @@
label_class = "engineering"
ui_color = "#dfb567"
nation_prefixes = list("Atomo", "Engino", "Power", "Teleco")
primary_work_area = /area/station/engineering
department_delivery_areas = list(
/area/station/engineering/main,
/area/station/engineering/lobby,
@@ -127,6 +132,7 @@
label_class = "medical"
ui_color = "#65b2bd"
nation_prefixes = list("Mede", "Healtha", "Recova", "Chemi", "Viro", "Psych")
primary_work_area = /area/station/medical
department_delivery_areas = list(
/area/station/medical/medbay/central,
/area/station/medical/medbay,
@@ -146,6 +152,7 @@
label_class = "science"
ui_color = "#c973c9"
nation_prefixes = list("Sci", "Griffa", "Geneti", "Explosi", "Mecha", "Xeno", "Nani", "Cyto")
primary_work_area = /area/station/science
department_delivery_areas = list(
/area/station/science/research,
/area/station/science/lobby,
@@ -165,6 +172,7 @@
label_class = "supply"
ui_color = "#cf9c6c"
nation_prefixes = list("Cargo", "Guna", "Suppli", "Mule", "Crate", "Ore", "Mini", "Shaf")
primary_work_area = /area/station/cargo
head_of_staff_access = ACCESS_QM
department_access = REGION_ACCESS_SUPPLY
@@ -177,6 +185,7 @@
label_class = "service"
ui_color = "#7cc46a"
nation_prefixes = list("Honka", "Boozo", "Fatu", "Danka", "Mimi", "Libra", "Jani", "Religi")
primary_work_area = /area/station/service
department_delivery_areas = list(/area/station/hallway/secondary/service, /area/station/service/bar/atrium)
associated_cargo_groups = list("Service", "Food & Hydroponics", "Livestock", "Costumes & Toys")
head_of_staff_access = ACCESS_HOP
+1 -1
View File
@@ -23,7 +23,7 @@
paycheck = PAYCHECK_COMMAND
paycheck_department = ACCOUNT_SEC
mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS)
mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS, TRAIT_DESENSITIZED)
liver_traits = list(TRAIT_ROYAL_METABOLISM)
display_order = JOB_DISPLAY_ORDER_CAPTAIN
@@ -13,6 +13,8 @@
outfit = /datum/outfit/job/chaplain
plasmaman_outfit = /datum/outfit/plasmaman/chaplain
mind_traits = list(TRAIT_SPIRITUAL, TRAIT_DESENSITIZED)
paycheck = PAYCHECK_CREW
paycheck_department = ACCOUNT_SRV
@@ -27,7 +27,7 @@
paycheck = PAYCHECK_COMMAND
paycheck_department = ACCOUNT_MED
mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS)
mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS, MEDICAL_MIND_TRAITS)
liver_traits = list(TRAIT_MEDICAL_METABOLISM, TRAIT_ROYAL_METABOLISM)
display_order = JOB_DISPLAY_ORDER_CHIEF_MEDICAL_OFFICER
+1
View File
@@ -16,6 +16,7 @@
paycheck = PAYCHECK_CREW
paycheck_department = ACCOUNT_SRV
mind_traits = list(TRAIT_DESENSITIZED) // butcher
liver_traits = list(TRAIT_CULINARY_METABOLISM)
display_order = JOB_DISPLAY_ORDER_COOK
+1 -1
View File
@@ -13,7 +13,7 @@
outfit = /datum/outfit/job/coroner
plasmaman_outfit = /datum/outfit/plasmaman/coroner
mind_traits = list(TRAIT_MORBID)
mind_traits = list(TRAIT_MORBID, MEDICAL_MIND_TRAITS)
liver_traits = list(TRAIT_CORONER_METABOLISM)
paycheck = PAYCHECK_CREW
+1
View File
@@ -23,6 +23,7 @@
paycheck = PAYCHECK_CREW
paycheck_department = ACCOUNT_SEC
mind_traits = list(SECURITY_MIND_TRAITS)
liver_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM)
display_order = JOB_DISPLAY_ORDER_DETECTIVE
@@ -24,7 +24,7 @@
/datum/job_department/command,
)
mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS)
mind_traits = list(HEAD_OF_STAFF_MIND_TRAITS, SECURITY_MIND_TRAITS)
liver_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM, TRAIT_ROYAL_METABOLISM)
paycheck = PAYCHECK_COMMAND
@@ -16,6 +16,7 @@
paycheck = PAYCHECK_CREW
paycheck_department = ACCOUNT_MED
mind_traits = list(MEDICAL_MIND_TRAITS)
liver_traits = list(TRAIT_MEDICAL_METABOLISM)
display_order = JOB_DISPLAY_ORDER_MEDICAL_DOCTOR
+1
View File
@@ -16,6 +16,7 @@
paycheck = PAYCHECK_CREW
paycheck_department = ACCOUNT_MED
mind_traits = list(MEDICAL_MIND_TRAITS)
liver_traits = list(TRAIT_MEDICAL_METABOLISM)
display_order = JOB_DISPLAY_ORDER_PARAMEDIC
@@ -20,6 +20,7 @@
paycheck = PAYCHECK_CREW
paycheck_department = ACCOUNT_SEC
mind_traits = list(SECURITY_MIND_TRAITS)
liver_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM)
display_order = JOB_DISPLAY_ORDER_SECURITY_OFFICER
+1
View File
@@ -21,6 +21,7 @@
paycheck = PAYCHECK_CREW
paycheck_department = ACCOUNT_SEC
mind_traits = list(SECURITY_MIND_TRAITS)
liver_traits = list(TRAIT_LAW_ENFORCEMENT_METABOLISM, TRAIT_PRETENDER_ROYAL_METABOLISM)
display_order = JOB_DISPLAY_ORDER_WARDEN
@@ -352,3 +352,7 @@
UnregisterSignal(source, COMSIG_HUMAN_CHARACTER_SETUP_FINISHED)
var/datum/record/crew/record = find_record(source.real_name)
record?.medical_notes += new /datum/medical_note("Central Command", "Patient is a registered brain donor for Robotics research.", null)
/datum/loadout_item/pocket_items/candles
name = "Box of Candles"
item_path = /obj/item/storage/fancy/candle_box
@@ -254,16 +254,14 @@
if(!weapon.use_tool(src, user, delay = 15, volume = 40))
return TRUE
var/is_chill_with_robbing = HAS_MIND_TRAIT(user, TRAIT_MORBID) || HAS_PERSONALITY(user, /datum/personality/callous) || HAS_PERSONALITY(user, /datum/personality/misanthropic)
if(opened)
dug_closed = TRUE
close(user)
else if(open(user, force = TRUE) && affect_mood)
if(HAS_MIND_TRAIT(user, TRAIT_MORBID))
user.add_mood_event("morbid_graverobbing", /datum/mood_event/morbid_graverobbing)
else
user.add_mood_event("graverobbing", /datum/mood_event/graverobbing)
user.add_mood_event("graverobbing", is_chill_with_robbing ? /datum/mood_event/morbid_graverobbing : /datum/mood_event/graverobbing)
if(lead_tomb && first_open)
if(HAS_MIND_TRAIT(user, TRAIT_MORBID))
if(is_chill_with_robbing)
to_chat(user, span_notice("Did someone say something? I'm sure it was nothing."))
else
user.gain_trauma(/datum/brain_trauma/magic/stalker)
@@ -235,8 +235,12 @@
if(CONFIG_GET(flag/allow_latejoin_antagonists) && !EMERGENCY_PAST_POINT_OF_NO_RETURN && humanc) //Borgs aren't allowed to be antags. Will need to be tweaked if we get true latejoin ais.
SSdynamic.on_latejoin(humanc)
if((job.job_flags & JOB_ASSIGN_QUIRKS) && humanc && CONFIG_GET(flag/roundstart_traits))
SSquirks.AssignQuirks(humanc, humanc.client)
if(humanc)
if(job.job_flags & JOB_ASSIGN_QUIRKS)
if(CONFIG_GET(flag/roundstart_traits))
SSquirks.AssignQuirks(humanc, humanc.client)
else // clear any personalities the prefs added since our job clearly does not want them
humanc.clear_personalities()
if(humanc) // Quirks may change manifest datapoints, so inject only after assigning quirks
GLOB.manifest.inject(humanc)
@@ -27,7 +27,7 @@
//Gondolas aren't affected by cold.
unsuitable_atmos_damage = 0
basic_mob_flags = DEL_ON_DEATH
basic_mob_flags = SENDS_DEATH_MOODLETS|DEL_ON_DEATH
///List of loot drops on death, since it deletes itself on death (like trooper).
var/list/loot = list(
+1 -7
View File
@@ -3,12 +3,6 @@
mob_size = MOB_SIZE_SMALL
mob_biotypes = MOB_ORGANIC|MOB_BEAST
blood_volume = BLOOD_VOLUME_NORMAL
basic_mob_flags = SENDS_DEATH_MOODLETS
/// if the mob is protected from being renamed by collars.
var/unique_pet = FALSE
/mob/living/basic/pet/death(gibbed)
. = ..()
add_memory_in_range(src, 7, /datum/memory/pet_died, deuteragonist = src) //Protagonist is the person memorizing it
-3
View File
@@ -4,8 +4,6 @@
losebreath = 0
breathing_loop.stop() //This would've happened eventually but it's nice to make it stop immediatelly in this case
if(!gibbed)
add_memory_in_range(src, 7, /datum/memory/witnessed_death, protagonist = src)
reagents.end_metabolization(src)
. = ..()
@@ -18,7 +16,6 @@
BT.on_death()
/mob/living/carbon/gib(drop_bitflags=NONE)
add_memory_in_range(src, 7, /datum/memory/witness_gib, protagonist = src)
if(drop_bitflags & DROP_ITEMS)
for(var/obj/item/W in src)
if(dropItemToGround(W))
+1 -1
View File
@@ -230,7 +230,7 @@
living_user.add_mood_event("encountered_evil", /datum/mood_event/encountered_evil)
living_user.set_jitter_if_lower(15 SECONDS)
if(HAS_TRAIT(user, TRAIT_SPIRITUAL) && mind?.holy_role)
if(HAS_TRAIT(user, TRAIT_SPIRITUAL) && mind?.holy_role && user != src)
. += "[t_He] [t_has] a holy aura about [t_him]."
living_user.add_mood_event("religious_comfort", /datum/mood_event/religiously_comforted)
@@ -306,6 +306,9 @@
for(var/datum/quirk/original_quircks as anything in quirks)
clone.add_quirk(original_quircks.type, override_client = client, announce = FALSE)
for(var/personality_type in personalities)
clone.add_personality(personality_type)
clone.updateappearance(mutcolor_update = TRUE, mutations_overlay_update = TRUE)
return clone
+48 -2
View File
@@ -17,6 +17,7 @@
if(stat != DEAD)
death(TRUE)
send_death_moodlets(/datum/mood_event/see_death)
ghostize()
spill_organs(drop_bitflags)
@@ -102,6 +103,8 @@
// keep us upright so the animation fits.
ADD_TRAIT(src, TRAIT_FORCED_STANDING, TRAIT_GENERIC)
send_death_moodlets(/datum/mood_event/see_death/dusted)
if(drop_items)
unequip_everything()
@@ -160,6 +163,47 @@
ash.pixel_z = -5
ash.pixel_w = rand(-1, 1)
/**
* Sends a moodlet to all nearby living mobs that are not blind or unconscious
* to indicate that they saw this mob die (and thus feel bad about it)
*
* Note: If the mob already has a death moodlet, and the same moodlet is applied, the existing moodlet will simply worsen.
* Note: If the mob has a death moodlet, and a worse moodlet is applied, the worse moodlet will take priority.
*
* Arguments:
* * moodlet - The type of moodlet to send. Defaults to [/datum/mood_event/see_death]
*/
/mob/living/proc/send_death_moodlets(datum/mood_event/moodlet = /datum/mood_event/see_death)
if(flags_1 & HOLOGRAM_1)
return
for(var/mob/living/nearby in viewers(src))
if(nearby.stat >= UNCONSCIOUS || nearby.is_blind())
continue
nearby.add_mood_event("saw_death", moodlet, src)
/mob/living/silicon/send_death_moodlets(datum/mood_event/moodlet)
return // You are a machine
/mob/living/basic/send_death_moodlets(datum/mood_event/moodlet)
if(!(basic_mob_flags & SENDS_DEATH_MOODLETS))
return
. = ..()
add_memory_in_range(src, 7, /datum/memory/pet_died, deuteragonist = src) //Protagonist is the person memorizing it
/mob/living/simple_animal/send_death_moodlets(datum/mood_event/moodlet)
return // I don't care about you anymore
/mob/living/carbon/human/send_death_moodlets(datum/mood_event/moodlet)
for(var/datum/surgery/organ_manipulation/manipulation in surgeries)
// This check exists so debraining someone doesn't make the surgeon super sad
if(manipulation.location == BODY_ZONE_HEAD && body_position == LYING_DOWN)
return
. = ..()
var/memory_type = ispath(moodlet, /datum/mood_event/see_death/gibbed) ? /datum/memory/witness_gib : /datum/memory/witnessed_death
add_memory_in_range(src, 7, memory_type, protagonist = src)
/*
* Called when the mob dies. Can also be called manually to kill a mob.
*
@@ -170,8 +214,10 @@
if(stat == DEAD)
return FALSE
if(!gibbed && (death_sound || death_message || (living_flags & ALWAYS_DEATHGASP)))
INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "deathgasp")
if(!gibbed)
if(death_sound || death_message || (living_flags & ALWAYS_DEATHGASP))
INVOKE_ASYNC(src, TYPE_PROC_REF(/mob, emote), "deathgasp")
send_death_moodlets(/datum/mood_event/see_death)
set_stat(DEAD)
timeofdeath = world.time

Some files were not shown because too many files have changed in this diff Show More