diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm
index d9286a76577..d59ce9f34c9 100644
--- a/code/__DEFINES/dcs/signals.dm
+++ b/code/__DEFINES/dcs/signals.dm
@@ -772,6 +772,8 @@
///from base of obj/item/equipped(): (/mob/equipper, slot)
#define COMSIG_ITEM_EQUIPPED "item_equip"
+/// A mob has just equipped an item. Called on [/mob] from base of [/obj/item/equipped()]: (/obj/item/equipped_item, slot)
+#define COMSIG_MOB_EQUIPPED_ITEM "mob_equipped_item"
///called on [/obj/item] before unequip from base of [mob/proc/doUnEquip]: (force, atom/newloc, no_move, invdrop, silent)
#define COMSIG_ITEM_PRE_UNEQUIP "item_pre_unequip"
///only the pre unequip can be cancelled
diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm
index 9ed95e77ef8..7bfa62733df 100644
--- a/code/__DEFINES/inventory.dm
+++ b/code/__DEFINES/inventory.dm
@@ -219,3 +219,20 @@ GLOBAL_LIST_INIT(security_wintercoat_allowed, typecacheof(list(
/obj/item/reagent_containers/spray/pepper,
/obj/item/restraints/handcuffs,
)))
+
+/// String for items placed into the left pocket.
+#define LOCATION_LPOCKET "in your left pocket"
+/// String for items placed into the right pocket
+#define LOCATION_RPOCKET "in your right pocket"
+/// String for items placed into the backpack.
+#define LOCATION_BACKPACK "in your backpack"
+/// String for items placed into the hands.
+#define LOCATION_HANDS "in your hands"
+/// String for items placed in the glove slot.
+#define LOCATION_GLOVES "on your hands"
+/// String for items placed in the eye/glasses slot.
+#define LOCATION_EYES "covering your eyes"
+/// String for items placed on the head/hat slot.
+#define LOCATION_HEAD "on your head"
+/// String for items placed in the neck slot.
+#define LOCATION_NECK "around your neck"
diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm
index 9f47245254e..e3539d2c3a5 100644
--- a/code/__DEFINES/traits.dm
+++ b/code/__DEFINES/traits.dm
@@ -486,6 +486,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define ROUNDSTART_TRAIT "roundstart"
#define JOB_TRAIT "job"
#define CYBORG_ITEM_TRAIT "cyborg-item"
+/// Any traits granted by quirks.
+#define QUIRK_TRAIT "quirk_trait"
/// (B)admins only.
#define ADMIN_TRAIT "admin"
#define CHANGELING_TRAIT "changeling"
diff --git a/code/controllers/subsystem/processing/quirks.dm b/code/controllers/subsystem/processing/quirks.dm
index 4a508559291..dbd7b7e1834 100644
--- a/code/controllers/subsystem/processing/quirks.dm
+++ b/code/controllers/subsystem/processing/quirks.dm
@@ -13,7 +13,6 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
var/list/quirks = list() //Assoc. list of all roundstart quirk datum types; "name" = /path/
var/list/quirk_points = list() //Assoc. list of quirk names and their "point cost"; positive numbers are good traits, and negative ones are bad
- var/list/quirk_objects = list() //A list of all quirk objects in the game, since some may process
var/list/quirk_blacklist = list() //A list of quirks that can not be used with each other. Format: list(quirk1,quirk2),list(quirk3,quirk4)
///An assoc list of quirks that can be obtained as a hardcore character, and their hardcore value.
var/list/hardcore_quirks = list()
@@ -36,23 +35,27 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
// Sort by Positive, Negative, Neutral; and then by name
var/list/quirk_list = sortList(subtypesof(/datum/quirk), /proc/cmp_quirk_asc)
- for(var/V in quirk_list)
- var/datum/quirk/T = V
- quirks[initial(T.name)] = T
- quirk_points[initial(T.name)] = initial(T.value)
+ for(var/type in quirk_list)
+ var/datum/quirk/quirk_type = type
- var/hardcore_value = initial(T.hardcore_value)
+ if(initial(quirk_type.abstract_parent_type) == type)
+ continue
+
+ quirks[initial(quirk_type.name)] = quirk_type
+ quirk_points[initial(quirk_type.name)] = initial(quirk_type.value)
+
+ var/hardcore_value = initial(quirk_type.hardcore_value)
if(!hardcore_value)
continue
- hardcore_quirks[T] += hardcore_value
+ hardcore_quirks[quirk_type] += hardcore_value
-/datum/controller/subsystem/processing/quirks/proc/AssignQuirks(mob/living/user, client/cli, spawn_effects)
+/datum/controller/subsystem/processing/quirks/proc/AssignQuirks(mob/living/user, client/cli)
var/badquirk = FALSE
for(var/V in cli.prefs.all_quirks)
var/datum/quirk/Q = quirks[V]
if(Q)
- user.add_quirk(Q, spawn_effects)
+ user.add_quirk(Q)
else
stack_trace("Invalid quirk \"[V]\" in client [cli.ckey] preferences")
cli.prefs.all_quirks -= V
@@ -65,14 +68,14 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
human.hardcore_survival_score = cli.prefs.hardcore_survival_score //Only do this if we actually asign quirks, to prevent sillicons etc from getting the points.
// Assign wayfinding pinpointer granting quirk if they're new
- if(cli.get_exp_living(TRUE) < EXP_ASSIGN_WAYFINDER && !user.has_quirk(/datum/quirk/needswayfinder))
- user.add_quirk(/datum/quirk/needswayfinder, TRUE)
+ if(cli.get_exp_living(TRUE) < EXP_ASSIGN_WAYFINDER && !user.has_quirk(/datum/quirk/item_quirk/needswayfinder))
+ user.add_quirk(/datum/quirk/item_quirk/needswayfinder)
/*
*Randomises the quirks for a specified mob
*/
/datum/controller/subsystem/processing/quirks/proc/randomise_quirks(mob/living/user)
- var/bonus_quirks = max((length(user.roundstart_quirks) + rand(-RANDOM_QUIRK_BONUS, RANDOM_QUIRK_BONUS)), MINIMUM_RANDOM_QUIRKS)
+ var/bonus_quirks = max((length(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 //Maximum of 6 good perks
@@ -122,14 +125,14 @@ PROCESSING_SUBSYSTEM_DEF(quirks)
score += quirk_points[quirk]
quirks_to_add += quirk
- for(var/datum/quirk/quirk as anything in user.roundstart_quirks)
+ for(var/datum/quirk/quirk as anything in user.quirks)
if(quirk.name in quirks_to_add) //Don't delete ones we keep
quirks_to_add -= quirk.name //Already there, no need to add.
continue
user.remove_quirk(quirk.type) //these quirks are objects
for(var/datum/quirk/quirk as anything in quirks_to_add)
- user.add_quirk(quirks[quirk], spawn_effects = TRUE)//these are typepaths converted from string
+ user.add_quirk(quirks[quirk]) //these are typepaths converted from string
#undef RANDOM_QUIRK_BONUS
#undef MINIMUM_RANDOM_QUIRKS
diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm
index ccda4edc811..0e69292de5b 100755
--- a/code/controllers/subsystem/ticker.dm
+++ b/code/controllers/subsystem/ticker.dm
@@ -388,7 +388,7 @@ SUBSYSTEM_DEF(ticker)
if(player_assigned_role != new_player_human.mind.special_role)
SSjob.EquipRank(new_player_mob, player_assigned_role, FALSE, player_is_captain)
if(CONFIG_GET(flag/roundstart_traits) && ishuman(new_player_human))
- SSquirks.AssignQuirks(new_player_human, new_player_mob.client, TRUE)
+ SSquirks.AssignQuirks(new_player_human, new_player_mob.client)
CHECK_TICK
if(captainless)
diff --git a/code/datums/components/footstep.dm b/code/datums/components/footstep.dm
index ff9a56a5e6a..01be6039a9e 100644
--- a/code/datums/components/footstep.dm
+++ b/code/datums/components/footstep.dm
@@ -107,6 +107,14 @@
if(HAS_TRAIT(parent, TRAIT_SILENT_FOOTSTEPS))
return
+
+ var/volume_multiplier = 1
+ var/range_adjustment = 0
+
+ if(HAS_TRAIT(parent, TRAIT_LIGHT_STEP))
+ volume_multiplier = 0.6
+ range_adjustment = -2
+
var/turf/open/T = prepare_step()
if(!T)
return
@@ -115,17 +123,17 @@
if ((H.wear_suit?.body_parts_covered | H.w_uniform?.body_parts_covered | H.shoes?.body_parts_covered) & FEET)
// we are wearing shoes
playsound(T, pick(GLOB.footstep[T.footstep][1]),
- GLOB.footstep[T.footstep][2] * volume,
+ GLOB.footstep[T.footstep][2] * volume * volume_multiplier,
TRUE,
- GLOB.footstep[T.footstep][3] + e_range, falloff_distance = 1, vary = sound_vary)
+ GLOB.footstep[T.footstep][3] + e_range + range_adjustment, falloff_distance = 1, vary = sound_vary)
else
if(H.dna.species.special_step_sounds)
playsound(T, pick(H.dna.species.special_step_sounds), 50, TRUE, falloff_distance = 1, vary = sound_vary)
else
playsound(T, pick(GLOB.barefootstep[T.barefootstep][1]),
- GLOB.barefootstep[T.barefootstep][2] * volume,
+ GLOB.barefootstep[T.barefootstep][2] * volume * volume_multiplier,
TRUE,
- GLOB.barefootstep[T.barefootstep][3] + e_range, falloff_distance = 1, vary = sound_vary)
+ GLOB.barefootstep[T.barefootstep][3] + e_range + range_adjustment, falloff_distance = 1, vary = sound_vary)
///Prepares a footstep for machine walking
diff --git a/code/datums/quirks/_quirk.dm b/code/datums/quirks/_quirk.dm
index 2aeb2867f91..0431ff999ba 100644
--- a/code/datums/quirks/_quirk.dm
+++ b/code/datums/quirks/_quirk.dm
@@ -10,30 +10,92 @@
var/medical_record_text //This text will appear on medical records for the trait. Not yet implemented
var/mood_quirk = FALSE //if true, this quirk affects mood and is unavailable if moodlets are disabled
var/mob_trait //if applicable, apply and remove this mob trait
- ///Amount of points this trait is worth towards the hardcore character mode; minus points implies a positive quirk, positive means its hard. This is used to pick the quirks assigned to a hardcore character. 0 means its not available to hardcore draws.
+ /// Amount of points this trait is worth towards the hardcore character mode; minus points implies a positive quirk, positive means its hard. This is used to pick the quirks assigned to a hardcore character. 0 means its not available to hardcore draws.
var/hardcore_value = 0
var/mob/living/quirk_holder
+ /// This quirk should START_PROCESSING when added and STOP_PROCESSING when removed.
+ var/processing_quirk = FALSE
+ /// When making an abstract quirk (in OOP terms), don't forget to set this var to the type path for that abstract quirk.
+ var/abstract_parent_type = /datum/quirk
+
+/datum/quirk/Destroy()
+ if(quirk_holder)
+ remove_from_current_holder()
+
+ return ..()
+
+/// Called when quirk_holder is qdeleting. Simply qdels this datum and lets Destroy() handle the rest.
+/datum/quirk/proc/on_holder_qdeleting(mob/living/source, force)
+ SIGNAL_HANDLER
+ qdel(src)
+
+/**
+ * Adds the quirk to a new quirk_holder.
+ *
+ * Performs logic to make sure new_holder is a valid holder of this quirk.
+ * Returns FALSEy if there was some kind of error. Returns TRUE otherwise.
+ * Arguments:
+ * * new_holder - The mob to add this quirk to.
+ * * quirk_transfer - If this is being added to the holder as part of a quirk transfer. Quirks can use this to decide not to spawn new items or apply any other one-time effects.
+ */
+/datum/quirk/proc/add_to_holder(mob/living/new_holder, quirk_transfer = FALSE)
+ if(!new_holder)
+ CRASH("Quirk attempted to be added to null mob.")
+
+ if(human_only && !ishuman(new_holder))
+ CRASH("Human only quirk attempted to be added to non-human mob.")
+
+ if(new_holder.has_quirk(type))
+ CRASH("Quirk attempted to be added to mob which already had this quirk.")
+
+ if(quirk_holder)
+ CRASH("Attempted to add quirk to a holder when it already has a holder.")
+
+ quirk_holder = new_holder
+ quirk_holder.quirks += src
-/datum/quirk/New(mob/living/quirk_mob, spawn_effects)
- ..()
- if(!quirk_mob || (human_only && !ishuman(quirk_mob)) || quirk_mob.has_quirk(type))
- qdel(src)
- return
- quirk_holder = quirk_mob
- SSquirks.quirk_objects += src
- to_chat(quirk_holder, gain_text)
- quirk_holder.roundstart_quirks += src
if(mob_trait)
- ADD_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
- START_PROCESSING(SSquirks, src)
- add()
- if(spawn_effects)
- on_spawn()
- if(quirk_holder.client)
- post_add()
- else
- RegisterSignal(quirk_holder, COMSIG_MOB_LOGIN, .proc/on_quirk_holder_first_login)
+ ADD_TRAIT(quirk_holder, mob_trait, QUIRK_TRAIT)
+ add()
+
+ if(processing_quirk)
+ START_PROCESSING(SSquirks, src)
+
+ if(!quirk_transfer)
+ to_chat(quirk_holder, gain_text)
+ add_unique()
+
+ if(quirk_holder.client)
+ post_add()
+ else
+ RegisterSignal(quirk_holder, COMSIG_MOB_LOGIN, .proc/on_quirk_holder_first_login)
+
+ RegisterSignal(quirk_holder, COMSIG_PARENT_QDELETING, .proc/on_holder_qdeleting)
+
+ return TRUE
+
+/// Removes the quirk from the current quirk_holder.
+/datum/quirk/proc/remove_from_current_holder(quirk_transfer = FALSE)
+ if(!quirk_holder)
+ CRASH("Attempted to remove quirk from the current holder when it has no current holder.")
+
+ UnregisterSignal(quirk_holder, list(COMSIG_MOB_LOGIN, COMSIG_PARENT_QDELETING))
+
+ quirk_holder.quirks -= src
+
+ if(!quirk_transfer)
+ to_chat(quirk_holder, lose_text)
+
+ if(mob_trait)
+ REMOVE_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
+
+ if(processing_quirk)
+ STOP_PROCESSING(SSquirks, src)
+
+ remove()
+
+ quirk_holder = null
/**
* On client connection set quirk preferences.
@@ -48,41 +110,59 @@
UnregisterSignal(source, COMSIG_MOB_LOGIN)
post_add()
-/datum/quirk/Destroy()
- STOP_PROCESSING(SSquirks, src)
- remove()
- if(quirk_holder)
- to_chat(quirk_holder, lose_text)
- quirk_holder.roundstart_quirks -= src
- if(mob_trait)
- REMOVE_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
- SSquirks.quirk_objects -= src
- return ..()
+/// Any effect that should be applied every single time the quirk is added to any mob, even when transferred.
+/datum/quirk/proc/add()
+/// Any effects from the proc that should not be done multiple times if the quirk is transferred between mobs. Put stuff like spawning items in here.
+/datum/quirk/proc/add_unique()
+/// Removal of any reversible effects added by the quirk.
+/datum/quirk/proc/remove()
+/// Any special effects or chat messages which should be applied. This proc is guaranteed to run if the mob has a client when the quirk is added. Otherwise, it runs once on the next COMSIG_MOB_LOGIN.
+/datum/quirk/proc/post_add()
-/datum/quirk/proc/transfer_mob(mob/living/to_mob)
- quirk_holder.roundstart_quirks -= src
- to_mob.roundstart_quirks += src
- if(mob_trait)
- REMOVE_TRAIT(quirk_holder, mob_trait, ROUNDSTART_TRAIT)
- ADD_TRAIT(to_mob, mob_trait, ROUNDSTART_TRAIT)
- quirk_holder = to_mob
- on_transfer()
+/// Subtype quirk that has some bonus logic to spawn items for the player.
+/datum/quirk/item_quirk
+ /// Lazylist of strings describing where all the quirk items have been spawned.
+ var/list/where_items_spawned
+ /// If true, the backpack automatically opens on post_add(). Usually set to TRUE when an item is equipped inside the player's backpack.
+ var/open_backpack = FALSE
+ abstract_parent_type = /datum/quirk/item_quirk
-/datum/quirk/proc/add() //special "on add" effects
-/datum/quirk/proc/on_spawn() //these should only trigger when the character is being created for the first time, i.e. roundstart/latejoin
-/datum/quirk/proc/remove() //special "on remove" effects
-/datum/quirk/proc/on_process() //process() has some special checks, so this is the actual process
-/datum/quirk/proc/post_add() //for text, disclaimers etc. given after you spawn in with the trait
-/datum/quirk/proc/on_transfer() //code called when the trait is transferred to a new mob
+/**
+ * Handles inserting an item in any of the valid slots provided, then allows for post_add notification.
+ *
+ * If no valid slot is available for an item, the item is left at the mob's feet.
+ * Arguments:
+ * * quirk_item - The item to give to the quirk holder. If the item is a path, the item will be spawned in first on the player's turf.
+ * * valid_slots - Assoc list of descriptive location strings to item slots that is fed into [/mob/living/carbon/proc/equip_in_one_of_slots]. list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK)
+ * * flavour_text - Optional flavour text to append to the where_items_spawned string after the item's location.
+ * * default_location - If the item isn't possible to equip in a valid slot, this is a description of where the item was spawned.
+ * * notify_player - If TRUE, adds strings to where_items_spawned list to be output to the player in [/datum/quirk/item_quirk/post_add()]
+ */
+/datum/quirk/item_quirk/proc/give_item_to_holder(quirk_item, list/valid_slots, flavour_text = null, default_location = "at your feet", notify_player = TRUE)
+ if(ispath(quirk_item))
+ quirk_item = new quirk_item(get_turf(quirk_holder))
-/datum/quirk/process(delta_time)
- if(QDELETED(quirk_holder))
- quirk_holder = null
- qdel(src)
- return
- if(quirk_holder.stat == DEAD)
- return
- on_process(delta_time)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+
+ var/where = human_holder.equip_in_one_of_slots(quirk_item, valid_slots, qdel_on_fail = FALSE) || default_location
+
+ if(where == LOCATION_BACKPACK)
+ open_backpack = TRUE
+
+ if(notify_player)
+ LAZYADD(where_items_spawned, "You have \a [quirk_item] [where]. [flavour_text]")
+
+/datum/quirk/item_quirk/post_add()
+ if(open_backpack)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ // post_add() can be called via delayed callback. Check they still have a backpack equipped before trying to open it.
+ if(human_holder.back)
+ SEND_SIGNAL(human_holder.back, COMSIG_TRY_STORAGE_SHOW, human_holder)
+
+ for(var/chat_string in where_items_spawned)
+ to_chat(quirk_holder, chat_string)
+
+ where_items_spawned = null
/**
* get_quirk_string() is used to get a printable string of all the quirk traits someone has for certain criteria
@@ -95,24 +175,24 @@
var/list/dat = list()
switch(category)
if(CAT_QUIRK_ALL)
- for(var/V in roundstart_quirks)
+ for(var/V in quirks)
var/datum/quirk/T = V
dat += medical ? T.medical_record_text : T.name
//Major Disabilities
if(CAT_QUIRK_MAJOR_DISABILITY)
- for(var/V in roundstart_quirks)
+ for(var/V in quirks)
var/datum/quirk/T = V
if(T.value < -4)
dat += medical ? T.medical_record_text : T.name
//Minor Disabilities
if(CAT_QUIRK_MINOR_DISABILITY)
- for(var/V in roundstart_quirks)
+ for(var/V in quirks)
var/datum/quirk/T = V
if(T.value >= -4 && T.value < 0)
dat += medical ? T.medical_record_text : T.name
//Neutral and Positive quirks
if(CAT_QUIRK_NOTES)
- for(var/V in roundstart_quirks)
+ for(var/V in quirks)
var/datum/quirk/T = V
if(T.value > -1)
dat += medical ? T.medical_record_text : T.name
@@ -121,51 +201,11 @@
return medical ? dat.Join("
") : dat.Join(", ")
/mob/living/proc/cleanse_trait_datums() //removes all trait datums
- for(var/V in roundstart_quirks)
+ for(var/V in quirks)
var/datum/quirk/T = V
qdel(T)
/mob/living/proc/transfer_trait_datums(mob/living/to_mob)
- for(var/V in roundstart_quirks)
- var/datum/quirk/T = V
- T.transfer_mob(to_mob)
-
-/*
-
-Commented version of Nearsighted to help you add your own traits
-Use this as a guideline
-
-/datum/quirk/nearsighted
- name = "Nearsighted"
- ///The trait's name
-
- desc = "You are nearsighted without prescription glasses, but spawn with a pair."
- ///Short description, shows next to name in the trait panel
-
- value = -1
- ///If this is above 0, it's a positive trait; if it's not, it's a negative one; if it's 0, it's a neutral
-
- mob_trait = TRAIT_NEARSIGHT
- ///This define is in __DEFINES/traits.dm and is the actual "trait" that the game tracks
- ///You'll need to use "HAS_TRAIT_FROM(src, X, sources)" checks around the code to check this; for instance, the Ageusia trait is checked in taste code
- ///If you need help finding where to put it, the declaration finder on GitHub is the best way to locate it
-
- gain_text = "Things far away from you start looking blurry."
- lose_text = "You start seeing faraway things normally again."
- medical_record_text = "Subject has permanent nearsightedness."
- ///These three are self-explanatory
-
-/datum/quirk/nearsighted/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/clothing/glasses/regular/glasses = new(get_turf(H))
- H.put_in_hands(glasses)
- H.equip_to_slot(glasses, ITEM_SLOT_EYES)
- H.regenerate_icons()
-
-//This whole proc is called automatically
-//It spawns a set of prescription glasses on the user, then attempts to put it into their hands, then attempts to make them equip it.
-//This means that if they fail to equip it, they glasses spawn in their hands, and if they fail to be put into the hands, they spawn on the ground
-//Hooray for fallbacks!
-//If you don't need any special effects like spawning glasses, then you don't need an add()
-
-*/
+ for(var/datum/quirk/quirk as anything in quirks)
+ quirk.remove_from_current_holder(quirk_transfer = TRUE)
+ quirk.add_to_holder(to_mob, quirk_transfer = TRUE)
diff --git a/code/datums/quirks/good.dm b/code/datums/quirks/good.dm
index 388de274960..5c6d65954ef 100644
--- a/code/datums/quirks/good.dm
+++ b/code/datums/quirks/good.dm
@@ -23,10 +23,9 @@
mood.mood_modifier -= 0.2
/datum/quirk/apathetic/remove()
- if(quirk_holder)
- var/datum/component/mood/mood = quirk_holder.GetComponent(/datum/component/mood)
- if(mood)
- mood.mood_modifier += 0.2
+ var/datum/component/mood/mood = quirk_holder.GetComponent(/datum/component/mood)
+ if(mood)
+ mood.mood_modifier += 0.2
/datum/quirk/drunkhealing
name = "Drunken Resilience"
@@ -36,19 +35,20 @@
gain_text = "You feel like a drink would do you good."
lose_text = "You no longer feel like drinking would ease your pain."
medical_record_text = "Patient has unusually efficient liver metabolism and can slowly regenerate wounds by drinking alcoholic beverages."
+ processing_quirk = TRUE
-/datum/quirk/drunkhealing/on_process(delta_time)
- var/mob/living/carbon/C = quirk_holder
- switch(C.drunkenness)
+/datum/quirk/drunkhealing/process(delta_time)
+ var/mob/living/carbon/carbon_holder = quirk_holder
+ switch(carbon_holder.drunkenness)
if (6 to 40)
- C.adjustBruteLoss(-0.1*delta_time, FALSE)
- C.adjustFireLoss(-0.05*delta_time, FALSE)
+ carbon_holder.adjustBruteLoss(-0.1*delta_time, FALSE)
+ carbon_holder.adjustFireLoss(-0.05*delta_time, FALSE)
if (41 to 60)
- C.adjustBruteLoss(-0.4*delta_time, FALSE)
- C.adjustFireLoss(-0.2*delta_time, FALSE)
+ carbon_holder.adjustBruteLoss(-0.4*delta_time, FALSE)
+ carbon_holder.adjustFireLoss(-0.2*delta_time, FALSE)
if (61 to INFINITY)
- C.adjustBruteLoss(-0.8*delta_time, FALSE)
- C.adjustFireLoss(-0.4*delta_time, FALSE)
+ carbon_holder.adjustBruteLoss(-0.8*delta_time, FALSE)
+ carbon_holder.adjustFireLoss(-0.4*delta_time, FALSE)
/datum/quirk/empath
name = "Empath"
@@ -59,7 +59,7 @@
lose_text = "You feel isolated from others."
medical_record_text = "Patient is highly perceptive of and sensitive to social cues, or may possibly have ESP. Further testing needed."
-/datum/quirk/fan_clown
+/datum/quirk/item_quirk/fan_clown
name = "Clown Fan"
desc = "You enjoy clown antics and get a mood boost from wearing your clown pin."
value = 2
@@ -68,18 +68,14 @@
lose_text = "The clown doesn't seem so great."
medical_record_text = "Patient reports being a big fan of clowns."
-/datum/quirk/fan_clown/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/clothing/accessory/fan_clown_pin/B = new(get_turf(H))
- var/list/slots = list (
- "backpack" = ITEM_SLOT_BACKPACK,
- "hands" = ITEM_SLOT_HANDS,
- )
- H.equip_in_one_of_slots(B, slots , qdel_on_fail = TRUE)
- var/datum/atom_hud/fan = GLOB.huds[DATA_HUD_FAN]
- fan.add_hud_to(H)
+/datum/quirk/item_quirk/fan_clown/add_unique()
+ give_item_to_holder(/obj/item/clothing/accessory/fan_clown_pin, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
-/datum/quirk/fan_mime
+/datum/quirk/item_quirk/fan_clown/add()
+ var/datum/atom_hud/fan = GLOB.huds[DATA_HUD_FAN]
+ fan.add_hud_to(quirk_holder)
+
+/datum/quirk/item_quirk/fan_mime
name = "Mime Fan"
desc = "You enjoy mime antics and get a mood boost from wearing your mime pin."
value = 2
@@ -88,16 +84,12 @@
lose_text = "The mime doesn't seem so great."
medical_record_text = "Patient reports being a big fan of mimes."
-/datum/quirk/fan_mime/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/clothing/accessory/fan_mime_pin/B = new(get_turf(H))
- var/list/slots = list (
- "backpack" = ITEM_SLOT_BACKPACK,
- "hands" = ITEM_SLOT_HANDS,
- )
- H.equip_in_one_of_slots(B, slots , qdel_on_fail = TRUE)
+/datum/quirk/item_quirk/fan_mime/add_unique()
+ give_item_to_holder(/obj/item/clothing/accessory/fan_mime_pin, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
+
+/datum/quirk/item_quirk/fan_mime/add()
var/datum/atom_hud/fan = GLOB.huds[DATA_HUD_FAN]
- fan.add_hud_to(H)
+ fan.add_hud_to(quirk_holder)
/datum/quirk/freerunning
name = "Freerunning"
@@ -135,13 +127,7 @@
lose_text = "You start tromping around like a barbarian."
medical_record_text = "Patient's dexterity belies a strong capacity for stealth."
-/datum/quirk/light_step/on_spawn()
- var/datum/component/footstep/C = quirk_holder.GetComponent(/datum/component/footstep)
- if(C)
- C.volume *= 0.6
- C.e_range -= 2
-
-/datum/quirk/musician
+/datum/quirk/item_quirk/musician
name = "Musician"
desc = "You can tune handheld musical instruments to play melodies that clear certain negative effects and soothe the soul."
value = 2
@@ -150,14 +136,8 @@
lose_text = "You forget how musical instruments work."
medical_record_text = "Patient brain scans show a highly-developed auditory pathway."
-/datum/quirk/musician/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/choice_beacon/music/B = new(get_turf(H))
- var/list/slots = list (
- "backpack" = ITEM_SLOT_BACKPACK,
- "hands" = ITEM_SLOT_HANDS,
- )
- H.equip_in_one_of_slots(B, slots , qdel_on_fail = TRUE)
+/datum/quirk/item_quirk/musician/add_unique()
+ give_item_to_holder(/obj/item/choice_beacon/music, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
/datum/quirk/night_vision
name = "Night Vision"
@@ -168,12 +148,19 @@
lose_text = "Everything seems a little darker."
medical_record_text = "Patient's eyes show above-average acclimation to darkness."
-/datum/quirk/night_vision/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/organ/eyes/eyes = H.getorgan(/obj/item/organ/eyes)
+/datum/quirk/night_vision/add()
+ refresh_quirk_holder_eyes()
+
+/datum/quirk/night_vision/remove()
+ refresh_quirk_holder_eyes()
+
+/datum/quirk/night_vision/proc/refresh_quirk_holder_eyes()
+ var/mob/living/carbon/human/human_quirk_holder = quirk_holder
+ var/obj/item/organ/eyes/eyes = human_quirk_holder.getorgan(/obj/item/organ/eyes)
if(!eyes || eyes.lighting_alpha)
return
- eyes.refresh() //refresh their eyesight and vision
+ // We've either added or removed TRAIT_NIGHT_VISION before calling this proc. Just refresh the eyes.
+ eyes.refresh()
/datum/quirk/selfaware
name = "Self-Aware"
@@ -189,7 +176,7 @@
mob_trait = TRAIT_SKITTISH
medical_record_text = "Patient demonstrates a high aversion to danger and has described hiding in containers out of fear."
-/datum/quirk/spiritual
+/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."
value = 4
@@ -198,12 +185,11 @@
lose_text = "You lose faith!"
medical_record_text = "Patient reports a belief in a higher power."
-/datum/quirk/spiritual/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- H.equip_to_slot_or_del(new /obj/item/storage/fancy/candle_box(H), ITEM_SLOT_BACKPACK)
- H.equip_to_slot_or_del(new /obj/item/storage/box/matches(H), ITEM_SLOT_BACKPACK)
+/datum/quirk/item_quirk/spiritual/add_unique()
+ give_item_to_holder(/obj/item/storage/fancy/candle_box, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
+ give_item_to_holder(/obj/item/storage/box/matches, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
-/datum/quirk/tagger
+/datum/quirk/item_quirk/tagger
name = "Tagger"
desc = "You're an experienced artist. People will actually be impressed by your graffiti, and you can get twice as many uses out of drawing supplies."
value = 4
@@ -212,12 +198,8 @@
lose_text = "You forget how to tag walls properly."
medical_record_text = "Patient was recently seen for possible paint huffing incident."
-/datum/quirk/tagger/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/toy/crayon/spraycan/spraycan = new(get_turf(H))
- H.put_in_hands(spraycan)
- H.equip_to_slot(spraycan, ITEM_SLOT_BACKPACK)
- H.regenerate_icons()
+/datum/quirk/item_quirk/tagger/add_unique()
+ give_item_to_holder(/obj/item/toy/crayon/spraycan, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
/datum/quirk/voracious
name = "Voracious"
diff --git a/code/datums/quirks/negative.dm b/code/datums/quirks/negative.dm
index bbd68a2b26a..2fc3cfdaea3 100644
--- a/code/datums/quirks/negative.dm
+++ b/code/datums/quirks/negative.dm
@@ -1,11 +1,5 @@
//predominantly negative traits
-/// Defines for locations of items being added to your inventory on spawn
-#define LOCATION_LPOCKET "in your left pocket"
-#define LOCATION_RPOCKET "in your right pocket"
-#define LOCATION_BACKPACK "in your backpack"
-#define LOCATION_HANDS "in your hands"
-
/datum/quirk/badback
name = "Bad Back"
desc = "Thanks to your poor posture, backpacks and other bags never sit right on your back. More evently weighted objects are fine, though."
@@ -15,14 +9,46 @@
lose_text = "Your back feels better."
medical_record_text = "Patient scans indicate severe and chronic back pain."
hardcore_value = 4
+ var/datum/weakref/backpack
-/datum/quirk/badback/on_process()
- var/mob/living/carbon/human/H = quirk_holder
- if(H.back && istype(H.back, /obj/item/storage/backpack))
+/datum/quirk/badback/add()
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/obj/item/storage/backpack/equipped_backpack = human_holder.back
+ if(istype(equipped_backpack))
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "back_pain", /datum/mood_event/back_pain)
+ RegisterSignal(human_holder.back, COMSIG_ITEM_POST_UNEQUIP, .proc/on_unequipped_backpack)
else
+ RegisterSignal(quirk_holder, COMSIG_MOB_EQUIPPED_ITEM, .proc/on_equipped_item)
+
+/datum/quirk/badback/remove()
+ UnregisterSignal(quirk_holder, COMSIG_MOB_EQUIPPED_ITEM)
+
+ var/obj/item/storage/equipped_backpack = backpack?.resolve()
+ if(equipped_backpack)
+ UnregisterSignal(equipped_backpack, COMSIG_ITEM_POST_UNEQUIP)
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "back_pain")
+/// Signal handler for when the quirk_holder equips an item. If it's a backpack, adds the back_pain mood event.
+/datum/quirk/badback/proc/on_equipped_item(mob/living/source, obj/item/equipped_item, slot)
+ SIGNAL_HANDLER
+
+ if((slot != ITEM_SLOT_BACK) || !istype(equipped_item, /obj/item/storage/backpack))
+ return
+
+ SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "back_pain", /datum/mood_event/back_pain)
+ RegisterSignal(equipped_item, COMSIG_ITEM_POST_UNEQUIP, .proc/on_unequipped_backpack)
+ UnregisterSignal(quirk_holder, COMSIG_MOB_EQUIPPED_ITEM)
+ backpack = WEAKREF(equipped_item)
+
+/// Signal handler for when the quirk_holder unequips an equipped backpack. Removes the back_pain mood event.
+/datum/quirk/badback/proc/on_unequipped_backpack(obj/item/source, force, atom/newloc, no_move, invdrop, silent)
+ SIGNAL_HANDLER
+
+ UnregisterSignal(source, COMSIG_ITEM_POST_UNEQUIP)
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "back_pain")
+ backpack = null
+ RegisterSignal(quirk_holder, COMSIG_MOB_EQUIPPED_ITEM, .proc/on_equipped_item)
+
/datum/quirk/blooddeficiency
name = "Blood Deficiency"
desc = "Your body can't produce enough blood to sustain itself."
@@ -31,8 +57,12 @@
lose_text = "You feel vigorous again."
medical_record_text = "Patient requires regular treatment for blood loss due to low production of blood."
hardcore_value = 8
+ processing_quirk = TRUE
+
+/datum/quirk/blooddeficiency/process(delta_time)
+ if(quirk_holder.stat == DEAD)
+ return
-/datum/quirk/blooddeficiency/on_process(delta_time)
var/mob/living/carbon/human/H = quirk_holder
if(NOBLOOD in H.dna.species.species_traits) //can't lose blood if your species doesn't have any
return
@@ -40,7 +70,7 @@
if (H.blood_volume > (BLOOD_VOLUME_SAFE - 25)) // just barely survivable without treatment
H.blood_volume -= 0.275 * delta_time
-/datum/quirk/blindness
+/datum/quirk/item_quirk/blindness
name = "Blind"
desc = "You are completely blind, nothing can counteract this."
value = -16
@@ -49,21 +79,21 @@
medical_record_text = "Patient has permanent blindness."
hardcore_value = 15
-/datum/quirk/blindness/add()
- quirk_holder.become_blind(ROUNDSTART_TRAIT)
+/datum/quirk/item_quirk/blindness/add_unique()
+ give_item_to_holder(/obj/item/clothing/glasses/blindfold/white, list(LOCATION_EYES = ITEM_SLOT_EYES, LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
-/datum/quirk/blindness/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/clothing/glasses/blindfold/white/B = new(get_turf(H))
- if(!H.equip_to_slot_if_possible(B, ITEM_SLOT_EYES, bypass_equip_delay_self = TRUE)) //if you can't put it on the user's eyes, put it in their hands, otherwise put it on their eyes
- H.put_in_hands(B)
+/datum/quirk/item_quirk/blindness/add()
+ quirk_holder.become_blind(QUIRK_TRAIT)
+
+/datum/quirk/item_quirk/blindness/remove()
+ quirk_holder.cure_blind(QUIRK_TRAIT)
/* A couple of brain tumor stats for anyone curious / looking at this quirk for balancing:
* - It takes less 16 minute 40 seconds to die from brain death due to a brain tumor.
* - It takes 1 minutes 40 seconds to take 10% (20 organ damage) brain damage.
* - 5u mannitol will heal 12.5% (25 organ damage) brain damage
*/
-/datum/quirk/brainproblems
+/datum/quirk/item_quirk/brainproblems
name = "Brain Tumor"
desc = "You have a little friend in your brain that is slowly destroying it. Better bring some mannitol!"
value = -12
@@ -71,30 +101,27 @@
lose_text = "You feel wrinkled again."
medical_record_text = "Patient has a tumor in their brain that is slowly driving them to brain death."
hardcore_value = 12
- /// Location of the bottle of pills on spawn
- var/where
+ processing_quirk = TRUE
-/datum/quirk/brainproblems/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/pills = new /obj/item/storage/pill_bottle/mannitol/braintumor()
- var/list/slots = list(
- LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
- LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
- LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
- LOCATION_HANDS = ITEM_SLOT_HANDS
+/datum/quirk/item_quirk/brainproblems/add_unique()
+ give_item_to_holder(
+ /obj/item/storage/pill_bottle/mannitol/braintumor,
+ list(
+ LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
+ LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
+ LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
+ LOCATION_HANDS = ITEM_SLOT_HANDS,
+ ),
+ flavour_text = "These will keep you alive until you can secure a supply of medication. Don't rely on them too much!",
)
- where = H.equip_in_one_of_slots(pills, slots, FALSE) || "at your feet"
-/datum/quirk/brainproblems/post_add()
- if(where == LOCATION_BACKPACK)
- var/mob/living/carbon/human/H = quirk_holder
- SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
+/datum/quirk/item_quirk/brainproblems/process(delta_time)
+ if(quirk_holder.stat == DEAD)
+ return
- to_chat(quirk_holder, "There is a bottle of mannitol pills [where] to keep you alive until you can secure a supply of medication. Don't rely on it too much!")
-
-/datum/quirk/brainproblems/on_process(delta_time)
if(HAS_TRAIT(quirk_holder, TRAIT_TUMOR_SUPPRESSED))
return
+
quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2 * delta_time)
/datum/quirk/deafness
@@ -118,30 +145,27 @@
mood_quirk = TRUE
hardcore_value = 2
-/datum/quirk/family_heirloom
+/datum/quirk/item_quirk/family_heirloom
name = "Family Heirloom"
desc = "You are the current owner of an heirloom, passed down for generations. You have to keep it safe!"
value = -2
mood_quirk = TRUE
medical_record_text = "Patient demonstrates an unnatural attachment to a family heirloom."
hardcore_value = 1
- /// A reference to our heirloom.
- var/obj/item/heirloom
- /// Where our heirloom is spawning.
- var/heirloom_spawn_loc
+ processing_quirk = TRUE
+ /// A weak reference to our heirloom.
+ var/datum/weakref/heirloom
-/datum/quirk/family_heirloom/on_spawn()
- /// The quirk holder, casted to human
+/datum/quirk/item_quirk/family_heirloom/add_unique()
var/mob/living/carbon/human/human_holder = quirk_holder
- /// The heirloom we will spawn
var/obj/item/heirloom_type
- /// The quirk holder's species - we have a 50% chance, if we have a species with a set heirloom, to choose a species heirloom.
+ // The quirk holder's species - we have a 50% chance, if we have a species with a set heirloom, to choose a species heirloom.
var/datum/species/holder_species = human_holder.dna?.species
if(holder_species && LAZYLEN(holder_species.family_heirlooms) && prob(50))
heirloom_type = pick(holder_species.family_heirlooms)
else
- /// Our quirk holder's job
+ // Our quirk holder's job
var/datum/job/holder_job = SSjob.GetJob(human_holder.mind?.assigned_role)
if(holder_job && LAZYLEN(holder_job.family_heirlooms))
heirloom_type = pick(holder_job.family_heirlooms)
@@ -150,39 +174,49 @@
if(!heirloom_type)
heirloom_type = pick(/obj/item/toy/cards/deck, /obj/item/lighter, /obj/item/dice/d20)
- heirloom = new heirloom_type(get_turf(quirk_holder))
- var/list/slots = list(
- LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
- LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
- LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
- LOCATION_HANDS = ITEM_SLOT_HANDS
+ var/obj/new_heirloom = new heirloom_type(get_turf(human_holder))
+ heirloom = WEAKREF(new_heirloom)
+
+ give_item_to_holder(
+ new_heirloom,
+ list(
+ LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
+ LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
+ LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
+ LOCATION_HANDS = ITEM_SLOT_HANDS,
+ ),
+ flavour_text = "This is a precious family heirloom, passed down from generation to generation. Keep it safe!",
)
- heirloom_spawn_loc = human_holder.equip_in_one_of_slots(heirloom, slots, FALSE) || "at your feet"
-
-/datum/quirk/family_heirloom/post_add()
- if(heirloom_spawn_loc == LOCATION_BACKPACK)
- var/mob/living/carbon/human/H = quirk_holder
- SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
-
- to_chat(quirk_holder, "There is a precious family [heirloom.name] [heirloom_spawn_loc], passed down from generation to generation. Keep it safe!")
+/datum/quirk/item_quirk/family_heirloom/post_add()
var/list/names = splittext(quirk_holder.real_name, " ")
var/family_name = names[names.len]
- heirloom.AddComponent(/datum/component/heirloom, quirk_holder.mind, family_name)
+ var/obj/family_heirloom = heirloom?.resolve()
+ if(!family_heirloom)
+ to_chat(quirk_holder, "A wave of existential dread runs over you as you realise your precious family heirloom is missing. Perhaps the Gods will show mercy on your cursed soul?")
+ return
-/datum/quirk/family_heirloom/on_process()
- if(heirloom in quirk_holder.GetAllContents())
+ family_heirloom.AddComponent(/datum/component/heirloom, quirk_holder.mind, family_name)
+
+ return ..()
+
+/datum/quirk/item_quirk/family_heirloom/process()
+ if(quirk_holder.stat == DEAD)
+ return
+
+ var/obj/family_heirloom = heirloom?.resolve()
+
+ if(family_heirloom && (family_heirloom in quirk_holder.GetAllContents()))
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom_missing")
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "family_heirloom", /datum/mood_event/family_heirloom)
else
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom")
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "family_heirloom_missing", /datum/mood_event/family_heirloom_missing)
-/datum/quirk/family_heirloom/remove()
- if(quirk_holder) // if the holder is still exists lets remove moods
- SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom_missing")
- SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom")
+/datum/quirk/item_quirk/family_heirloom/remove()
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom_missing")
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "family_heirloom")
/datum/quirk/frail
name = "Frail"
@@ -219,10 +253,9 @@
mood.mood_modifier += 0.5
/datum/quirk/hypersensitive/remove()
- if(quirk_holder)
- var/datum/component/mood/mood = quirk_holder.GetComponent(/datum/component/mood)
- if(mood)
- mood.mood_modifier -= 0.5
+ var/datum/component/mood/mood = quirk_holder.GetComponent(/datum/component/mood)
+ if(mood)
+ mood.mood_modifier -= 0.5
/datum/quirk/light_drinker
name = "Light Drinker"
@@ -234,7 +267,7 @@
medical_record_text = "Patient demonstrates a low tolerance for alcohol. (Wimp)"
hardcore_value = 3
-/datum/quirk/nearsighted //t. errorage
+/datum/quirk/item_quirk/nearsighted
name = "Nearsighted"
desc = "You are nearsighted without prescription glasses, but spawn with a pair."
value = -4
@@ -243,14 +276,14 @@
medical_record_text = "Patient requires prescription glasses in order to counteract nearsightedness."
hardcore_value = 5
-/datum/quirk/nearsighted/add()
- quirk_holder.become_nearsighted(ROUNDSTART_TRAIT)
+/datum/quirk/item_quirk/nearsighted/add_unique()
+ give_item_to_holder(/obj/item/clothing/glasses/regular, list(LOCATION_EYES = ITEM_SLOT_EYES, LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
-/datum/quirk/nearsighted/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/clothing/glasses/regular/glasses = new(get_turf(H))
- if(!H.equip_to_slot_if_possible(glasses, ITEM_SLOT_EYES, bypass_equip_delay_self = TRUE))
- H.put_in_hands(glasses)
+/datum/quirk/item_quirk/nearsighted/add()
+ quirk_holder.become_nearsighted(QUIRK_TRAIT)
+
+/datum/quirk/item_quirk/nearsighted/remove()
+ quirk_holder.cure_nearsighted(QUIRK_TRAIT)
/datum/quirk/nyctophobia
name = "Nyctophobia"
@@ -259,19 +292,37 @@
medical_record_text = "Patient demonstrates a fear of the dark. (Seriously?)"
hardcore_value = 5
-/datum/quirk/nyctophobia/on_process()
- var/mob/living/carbon/human/H = quirk_holder
- if(H.dna.species.id in list("shadow", "nightmare"))
- return //we're tied with the dark, so we don't get scared of it; don't cleanse outright to avoid cheese
- var/turf/T = get_turf(quirk_holder)
- var/lums = T.get_lumcount()
- if(lums <= 0.2)
- if(quirk_holder.m_intent == MOVE_INTENT_RUN)
- to_chat(quirk_holder, "Easy, easy, take it slow... you're in the dark...")
- quirk_holder.toggle_move_intent()
- SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
- else
+/datum/quirk/nyctophobia/add()
+ RegisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED, .proc/on_holder_moved)
+
+/datum/quirk/nyctophobia/remove()
+ UnregisterSignal(quirk_holder, COMSIG_MOVABLE_MOVED)
+ SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
+
+/// Called when the quirk holder moves. Updates the quirk holder's mood.
+/datum/quirk/nyctophobia/proc/on_holder_moved(/mob/living/source, atom/old_loc, dir, forced)
+ SIGNAL_HANDLER
+
+ if(quirk_holder.stat == DEAD)
+ return
+
+ var/mob/living/carbon/human/human_holder = quirk_holder
+
+ if(human_holder.dna?.species.id in list("shadow", "nightmare"))
+ return
+
+ var/turf/holder_turf = get_turf(quirk_holder)
+
+ var/lums = holder_turf.get_lumcount()
+
+ if(lums > 0.2)
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "nyctophobia")
+ return
+
+ if(quirk_holder.m_intent == MOVE_INTENT_RUN)
+ to_chat(quirk_holder, "Easy, easy, take it slow... You're in the dark...")
+ quirk_holder.toggle_move_intent()
+ SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "nyctophobia", /datum/mood_event/nyctophobia)
/datum/quirk/nonviolent
name = "Pacifist"
@@ -293,23 +344,18 @@
medical_record_text = "Patient has an untreatable impairment in motor function in the lower extremities."
hardcore_value = 15
-/datum/quirk/paraplegic/add()
- var/datum/brain_trauma/severe/paralysis/paraplegic/T = new()
- var/mob/living/carbon/human/H = quirk_holder
- H.gain_trauma(T, TRAUMA_RESILIENCE_ABSOLUTE)
-
-/datum/quirk/paraplegic/on_spawn()
+/datum/quirk/paraplegic/add_unique()
if(quirk_holder.buckled) // Handle late joins being buckled to arrival shuttle chairs.
quirk_holder.buckled.unbuckle_mob(quirk_holder)
- var/turf/T = get_turf(quirk_holder)
- var/obj/structure/chair/spawn_chair = locate() in T
+ var/turf/holder_turf = get_turf(quirk_holder)
+ var/obj/structure/chair/spawn_chair = locate() in holder_turf
var/obj/vehicle/ridden/wheelchair/wheels
if(quirk_holder.client?.get_award_status(HARDCORE_RANDOM_SCORE) >= 5000) //More than 5k score? you unlock the gamer wheelchair.
- wheels = new /obj/vehicle/ridden/wheelchair/gold(T)
+ wheels = new /obj/vehicle/ridden/wheelchair/gold(holder_turf)
else
- wheels = new(T)
+ wheels = new(holder_turf)
if(spawn_chair) // Makes spawning on the arrivals shuttle more consistent looking
wheels.setDir(spawn_chair.dir)
@@ -317,10 +363,17 @@
// During the spawning process, they may have dropped what they were holding, due to the paralysis
// So put the things back in their hands.
+ for(var/obj/item/dropped_item in holder_turf)
+ if(dropped_item.fingerprintslast == quirk_holder.ckey)
+ quirk_holder.put_in_hands(dropped_item)
- for(var/obj/item/I in T)
- if(I.fingerprintslast == quirk_holder.ckey)
- quirk_holder.put_in_hands(I)
+/datum/quirk/paraplegic/add()
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ human_holder.gain_trauma(/datum/brain_trauma/severe/paralysis/paraplegic, TRAUMA_RESILIENCE_ABSOLUTE)
+
+/datum/quirk/paraplegic/remove()
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ human_holder.cure_trauma_type(/datum/brain_trauma/severe/paralysis/paraplegic, TRAUMA_RESILIENCE_ABSOLUTE)
/datum/quirk/poor_aim
name = "Stormtrooper Aim"
@@ -346,10 +399,10 @@
medical_record_text = "During physical examination, patient was found to have a prosthetic limb."
hardcore_value = 3
-/datum/quirk/prosthetic_limb/on_spawn()
+/datum/quirk/prosthetic_limb/add_unique()
var/limb_slot = pick(BODY_ZONE_L_ARM, BODY_ZONE_R_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_LEG)
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/bodypart/old_part = H.get_bodypart(limb_slot)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/obj/item/bodypart/old_part = human_holder.get_bodypart(limb_slot)
var/obj/item/bodypart/prosthetic
switch(limb_slot)
if(BODY_ZONE_L_ARM)
@@ -364,9 +417,9 @@
if(BODY_ZONE_R_LEG)
prosthetic = new/obj/item/bodypart/r_leg/robot/surplus(quirk_holder)
slot_string = "right leg"
- prosthetic.replace_limb(H)
+ prosthetic.replace_limb(human_holder)
qdel(old_part)
- H.regenerate_icons()
+ human_holder.regenerate_icons()
/datum/quirk/prosthetic_limb/post_add()
to_chat(quirk_holder, "Your [slot_string] has been replaced with a surplus prosthetic. It is fragile and will easily come apart under duress. Additionally, \
@@ -391,16 +444,14 @@
lose_text = "You feel in tune with the world again."
medical_record_text = "Patient suffers from acute Reality Dissociation Syndrome and experiences vivid hallucinations."
hardcore_value = 6
+ processing_quirk = TRUE
-/datum/quirk/insanity/on_process(delta_time)
- if(quirk_holder.reagents.has_reagent(/datum/reagent/toxin/mindbreaker, needs_metabolizing = TRUE))
- quirk_holder.hallucination = 0
+/datum/quirk/insanity/process(delta_time)
+ if(quirk_holder.stat == DEAD)
return
- if(DT_PROB(2, delta_time)) //we'll all be mad soon enough
- madness()
-/datum/quirk/insanity/proc/madness()
- quirk_holder.hallucination += rand(10, 25)
+ if(DT_PROB(2, delta_time))
+ quirk_holder.hallucination += rand(10, 25)
/datum/quirk/insanity/post_add() //I don't /think/ we'll need this but for newbies who think "roleplay as insane" = "license to kill" it's probably a good thing to have
if(!quirk_holder.mind || quirk_holder.mind.special_role)
@@ -534,13 +585,14 @@
mood_change = -5
timeout = 3 MINUTES
-/datum/quirk/junkie
+/datum/quirk/item_quirk/junkie
name = "Junkie"
desc = "You can't get enough of hard drugs."
value = -6
gain_text = "You suddenly feel the craving for drugs."
medical_record_text = "Patient has a history of hard drugs."
hardcore_value = 4
+ processing_quirk = TRUE
var/drug_list = list(/datum/reagent/drug/crank, /datum/reagent/drug/krokodil, /datum/reagent/medicine/morphine, /datum/reagent/drug/happiness, /datum/reagent/drug/methamphetamine) //List of possible IDs
var/datum/reagent/reagent_type //!If this is defined, reagent_id will be unused and the defined reagent type will be instead.
var/datum/reagent/reagent_instance //! actual instanced version of the reagent
@@ -550,71 +602,78 @@
var/obj/item/accessory_type //! If this is null, an accessory won't be spawned.
var/process_interval = 30 SECONDS //! how frequently the quirk processes
var/next_process = 0 //! ticker for processing
+ var/drug_flavour_text = "Better hope you don't run out..."
-/datum/quirk/junkie/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- if (!reagent_type)
+/datum/quirk/item_quirk/junkie/add_unique()
+ var/mob/living/carbon/human/human_holder = quirk_holder
+
+ if(!reagent_type)
reagent_type = pick(drug_list)
+
reagent_instance = new reagent_type()
+
for(var/addiction in reagent_instance.addiction_types)
- H.mind.add_addiction_points(addiction, 1000) ///Max that shit out
+ human_holder.mind.add_addiction_points(addiction, 1000)
+
var/current_turf = get_turf(quirk_holder)
- if (!drug_container_type)
+
+ if(!drug_container_type)
drug_container_type = /obj/item/storage/pill_bottle
+
var/obj/item/drug_instance = new drug_container_type(current_turf)
- if (istype(drug_instance, /obj/item/storage/pill_bottle))
+ if(istype(drug_instance, /obj/item/storage/pill_bottle))
var/pill_state = "pill[rand(1,20)]"
for(var/i in 1 to 7)
- var/obj/item/reagent_containers/pill/P = new(drug_instance)
- P.icon_state = pill_state
- P.reagents.add_reagent(reagent_type, 3)
+ var/obj/item/reagent_containers/pill/pill = new(drug_instance)
+ pill.icon_state = pill_state
+ pill.reagents.add_reagent(reagent_type, 3)
- var/obj/item/accessory_instance
- if (accessory_type)
- accessory_instance = new accessory_type(current_turf)
- var/list/slots = list(
- LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
- LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
- LOCATION_BACKPACK = ITEM_SLOT_BACKPACK
+ give_item_to_holder(
+ drug_instance,
+ list(
+ LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
+ LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
+ LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
+ LOCATION_HANDS = ITEM_SLOT_HANDS,
+ ),
+ flavour_text = drug_flavour_text,
)
- where_drug = H.equip_in_one_of_slots(drug_instance, slots, FALSE) || "at your feet"
- if (accessory_instance)
- where_accessory = H.equip_in_one_of_slots(accessory_instance, slots, FALSE) || "at your feet"
- announce_drugs()
-/datum/quirk/junkie/post_add()
- if(where_drug == LOCATION_BACKPACK || where_accessory == LOCATION_BACKPACK)
- var/mob/living/carbon/human/H = quirk_holder
- SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
+ if(accessory_type)
+ give_item_to_holder(
+ accessory_type,
+ list(
+ LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
+ LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
+ LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
+ LOCATION_HANDS = ITEM_SLOT_HANDS,
+ )
+ )
-/datum/quirk/junkie/remove()
+/datum/quirk/item_quirk/junkie/remove()
if(quirk_holder && reagent_instance)
for(var/addiction_type in subtypesof(/datum/addiction))
- quirk_holder.mind.remove_addiction_points(addiction_type, MAX_ADDICTION_POINTS) //chat feedback here. No need of lose_text.
+ quirk_holder.mind.remove_addiction_points(addiction_type, MAX_ADDICTION_POINTS)
-/datum/quirk/junkie/proc/announce_drugs()
- to_chat(quirk_holder, "There is a [initial(drug_container_type.name)] of [initial(reagent_type.name)] [where_drug]. Better hope you don't run out...")
-
-/datum/quirk/junkie/on_process()
+/datum/quirk/item_quirk/junkie/process(delta_time)
if(HAS_TRAIT(quirk_holder, TRAIT_NOMETABOLISM))
return
- var/mob/living/carbon/human/H = quirk_holder
+ var/mob/living/carbon/human/human_holder = quirk_holder
if(world.time > next_process)
next_process = world.time + process_interval
var/deleted = QDELETED(reagent_instance)
var/missing_addiction = FALSE
for(var/addiction_type in reagent_instance.addiction_types)
- if(!LAZYACCESS(H.mind.active_addictions, addiction_type))
+ if(!LAZYACCESS(human_holder.mind.active_addictions, addiction_type))
missing_addiction = TRUE
if(deleted || missing_addiction)
if(deleted)
reagent_instance = new reagent_type()
to_chat(quirk_holder, "You thought you kicked it, but you feel like you're falling back onto bad habits..")
for(var/addiction in reagent_instance.addiction_types)
- H.mind.add_addiction_points(addiction, 1000) ///Max that shit out
+ human_holder.mind.add_addiction_points(addiction, 1000) ///Max that shit out
-
-/datum/quirk/junkie/smoker
+/datum/quirk/item_quirk/junkie/smoker
name = "Smoker"
desc = "Sometimes you just really want a smoke. Probably not great for your lungs."
value = -4
@@ -623,28 +682,29 @@
reagent_type = /datum/reagent/drug/nicotine
accessory_type = /obj/item/lighter/greyscale
hardcore_value = 1
+ drug_flavour_text = "Make sure you get your favorite brand when you run out."
-/datum/quirk/junkie/smoker/on_spawn()
+/datum/quirk/item_quirk/junkie/smoker/New()
drug_container_type = pick(/obj/item/storage/fancy/cigarettes,
/obj/item/storage/fancy/cigarettes/cigpack_midori,
/obj/item/storage/fancy/cigarettes/cigpack_uplift,
/obj/item/storage/fancy/cigarettes/cigpack_robust,
/obj/item/storage/fancy/cigarettes/cigpack_robustgold,
/obj/item/storage/fancy/cigarettes/cigpack_carp)
- quirk_holder?.mind?.store_memory("Your favorite cigarette packets are [initial(drug_container_type.name)]s.")
+
+ return ..()
+
+/datum/quirk/item_quirk/junkie/smoker/post_add()
. = ..()
+ quirk_holder.mind.store_memory("Your favorite cigarette packets are [initial(drug_container_type.name)]s.")
-/datum/quirk/junkie/smoker/announce_drugs()
- to_chat(quirk_holder, "There is a [initial(drug_container_type.name)] [where_drug], and a lighter [where_accessory]. Make sure you get your favorite brand when you run out.")
-
-
-/datum/quirk/junkie/smoker/on_process()
+/datum/quirk/item_quirk/junkie/smoker/process(delta_time)
. = ..()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/I = H.get_item_by_slot(ITEM_SLOT_MASK)
- if (istype(I, /obj/item/clothing/mask/cigarette))
- var/obj/item/storage/fancy/cigarettes/C = drug_container_type
- if(istype(I, initial(C.spawn_type)))
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/obj/item/mask_item = human_holder.get_item_by_slot(ITEM_SLOT_MASK)
+ if (istype(mask_item, /obj/item/clothing/mask/cigarette))
+ var/obj/item/storage/fancy/cigarettes/cigarettes = drug_container_type
+ if(istype(mask_item, initial(cigarettes.spawn_type)))
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "wrong_cigs")
return
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "wrong_cigs", /datum/mood_event/wrong_brand)
@@ -659,7 +719,7 @@
medical_record_text = "Patient's mind is in a vulnerable state, and cannot recover from traumatic events."
hardcore_value = 9
-/datum/quirk/allergic
+/datum/quirk/item_quirk/allergic
name = "Extreme Medicine Allergy"
desc = "Ever since you were a kid, you've been allergic to certain chemicals..."
value = -6
@@ -667,45 +727,43 @@
lose_text = "You feel your immune system phase back into perfect shape."
medical_record_text = "Patient's immune system responds violently to certain chemicals."
hardcore_value = 3
+ processing_quirk = TRUE
var/list/allergies = list()
var/list/blacklist = list(/datum/reagent/medicine/c2,/datum/reagent/medicine/epinephrine,/datum/reagent/medicine/adminordrazine,/datum/reagent/medicine/omnizine/godblood,/datum/reagent/medicine/cordiolis_hepatico,/datum/reagent/medicine/synaphydramine,/datum/reagent/medicine/diphenhydramine)
+ var/allergy_string
-/datum/quirk/allergic/on_spawn()
+/datum/quirk/item_quirk/allergic/add_unique()
var/list/chem_list = subtypesof(/datum/reagent/medicine) - blacklist
+ var/list/allergy_chem_names = list()
for(var/i in 0 to 5)
- var/chem = pick(chem_list)
- chem_list -= chem
- allergies += chem
+ var/datum/reagent/medicine/chem_type = pick_n_take(chem_list)
+ allergies += chem_type
+ allergy_chem_names += initial(chem_type.name)
+
+ allergy_string = allergy_chem_names.Join(", ")
+ name = "Extreme [allergy_string] Allergies"
+ medical_record_text = "Patient's immune system responds violently to [allergy_string]"
-/datum/quirk/allergic/post_add()
- var/display = ""
- for(var/C in allergies)
- var/datum/reagent/chemical = C
- display += initial(chemical.name) + ", "
- name = "Extreme " + display +"Allergies"
- medical_record_text = "Patient's immune system responds violently to [display]"
- quirk_holder?.mind.store_memory("You are allergic to [display]")
- to_chat(quirk_holder, "You are allergic to [display]make sure not to consume any of it!")
- if(!ishuman(quirk_holder))
- return
var/mob/living/carbon/human/human_holder = quirk_holder
var/obj/item/clothing/accessory/allergy_dogtag/dogtag = new(get_turf(human_holder))
- var/list/slots = list (
- "backpack" = ITEM_SLOT_BACKPACK,
- "hands" = ITEM_SLOT_HANDS
- )
- dogtag.display = display
- human_holder.equip_in_one_of_slots(dogtag, slots , qdel_on_fail = TRUE)
+ dogtag.display = allergy_string
-/datum/quirk/allergic/on_process(delta_time)
- . = ..()
+ give_item_to_holder(dogtag, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS), flavour_text = "Make sure medical staff can see this...")
+
+/datum/quirk/item_quirk/allergic/post_add()
+ quirk_holder.mind.store_memory("You are allergic to [allergy_string]")
+ to_chat(quirk_holder, "You are allergic to [allergy_string], make sure not to consume any of these!")
+
+/datum/quirk/item_quirk/allergic/process(delta_time)
if(!iscarbon(quirk_holder))
return
+
if(IS_IN_STASIS(quirk_holder))
return
+
var/mob/living/carbon/carbon_quirk_holder = quirk_holder
- for(var/M in allergies)
- var/datum/reagent/instantiated_med = carbon_quirk_holder.reagents.has_reagent(M)
+ for(var/allergy in allergies)
+ var/datum/reagent/instantiated_med = carbon_quirk_holder.reagents.has_reagent(allergy)
if(!instantiated_med)
continue
//Just halts the progression, I'd suggest you run to medbay asap to get it fixed
@@ -745,8 +803,3 @@
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "bad_touch", /datum/mood_event/very_bad_touch)
else
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "bad_touch", /datum/mood_event/bad_touch)
-
-#undef LOCATION_LPOCKET
-#undef LOCATION_RPOCKET
-#undef LOCATION_BACKPACK
-#undef LOCATION_HANDS
diff --git a/code/datums/quirks/neutral.dm b/code/datums/quirks/neutral.dm
index 64a6dea04e6..23b52fd37a4 100644
--- a/code/datums/quirks/neutral.dm
+++ b/code/datums/quirks/neutral.dm
@@ -37,16 +37,16 @@
medical_record_text = "Patient does not speak Galactic Common and may require an interpreter."
/datum/quirk/foreigner/add()
- var/mob/living/carbon/human/H = quirk_holder
- H.add_blocked_language(/datum/language/common)
- if(ishumanbasic(H))
- H.grant_language(/datum/language/uncommon)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ human_holder.add_blocked_language(/datum/language/common)
+ if(ishumanbasic(human_holder))
+ human_holder.grant_language(/datum/language/uncommon)
/datum/quirk/foreigner/remove()
- var/mob/living/carbon/human/H = quirk_holder
- H.remove_blocked_language(/datum/language/common)
- if(ishumanbasic(H))
- H.remove_language(/datum/language/uncommon)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ human_holder.remove_blocked_language(/datum/language/common)
+ if(ishumanbasic(human_holder))
+ human_holder.remove_language(/datum/language/uncommon)
/datum/quirk/vegetarian
name = "Vegetarian"
@@ -57,19 +57,19 @@
medical_record_text = "Patient reports a vegetarian diet."
/datum/quirk/vegetarian/add()
- var/mob/living/carbon/human/H = quirk_holder
- var/datum/species/species = H.dna.species
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/datum/species/species = human_holder.dna.species
species.liked_food &= ~MEAT
species.disliked_food |= MEAT
/datum/quirk/vegetarian/remove()
- var/mob/living/carbon/human/H = quirk_holder
- if(H)
- var/datum/species/species = H.dna.species
- if(initial(species.liked_food) & MEAT)
- species.liked_food |= MEAT
- if(!(initial(species.disliked_food) & MEAT))
- species.disliked_food &= ~MEAT
+ var/mob/living/carbon/human/human_holder = quirk_holder
+
+ var/datum/species/species = human_holder.dna.species
+ if(initial(species.liked_food) & MEAT)
+ species.liked_food |= MEAT
+ if(!(initial(species.disliked_food) & MEAT))
+ species.disliked_food &= ~MEAT
/datum/quirk/snob
name = "Snob"
@@ -89,15 +89,14 @@
medical_record_text = "Patient demonstrates a pathological love of pineapple."
/datum/quirk/pineapple_liker/add()
- var/mob/living/carbon/human/H = quirk_holder
- var/datum/species/species = H.dna.species
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/datum/species/species = human_holder.dna.species
species.liked_food |= PINEAPPLE
/datum/quirk/pineapple_liker/remove()
- var/mob/living/carbon/human/H = quirk_holder
- if(H)
- var/datum/species/species = H.dna.species
- species.liked_food &= ~PINEAPPLE
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/datum/species/species = human_holder.dna.species
+ species.liked_food &= ~PINEAPPLE
/datum/quirk/pineapple_hater
name = "Ananas Aversion"
@@ -108,15 +107,14 @@
medical_record_text = "Patient is correct to think that pineapple is disgusting."
/datum/quirk/pineapple_hater/add()
- var/mob/living/carbon/human/H = quirk_holder
- var/datum/species/species = H.dna.species
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/datum/species/species = human_holder.dna.species
species.disliked_food |= PINEAPPLE
/datum/quirk/pineapple_hater/remove()
- var/mob/living/carbon/human/H = quirk_holder
- if(H)
- var/datum/species/species = H.dna.species
- species.disliked_food &= ~PINEAPPLE
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/datum/species/species = human_holder.dna.species
+ species.disliked_food &= ~PINEAPPLE
/datum/quirk/deviant_tastes
name = "Deviant Tastes"
@@ -127,18 +125,17 @@
medical_record_text = "Patient demonstrates irregular nutrition preferences."
/datum/quirk/deviant_tastes/add()
- var/mob/living/carbon/human/H = quirk_holder
- var/datum/species/species = H.dna.species
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/datum/species/species = human_holder.dna.species
var/liked = species.liked_food
species.liked_food = species.disliked_food
species.disliked_food = liked
/datum/quirk/deviant_tastes/remove()
- var/mob/living/carbon/human/H = quirk_holder
- if(H)
- var/datum/species/species = H.dna.species
- species.liked_food = initial(species.liked_food)
- species.disliked_food = initial(species.disliked_food)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/datum/species/species = human_holder.dna.species
+ species.liked_food = initial(species.liked_food)
+ species.disliked_food = initial(species.disliked_food)
/datum/quirk/monochromatic
name = "Monochromacy"
@@ -155,59 +152,52 @@
quirk_holder.playsound_local(quirk_holder, 'sound/ambience/ambidet1.ogg', 50, FALSE)
/datum/quirk/monochromatic/remove()
- if(quirk_holder)
- quirk_holder.remove_client_colour(/datum/client_colour/monochrome)
+ quirk_holder.remove_client_colour(/datum/client_colour/monochrome)
/datum/quirk/phobia
name = "Phobia"
desc = "You are irrationally afraid of something."
value = 0
medical_record_text = "Patient has an irrational fear of something."
+ var/phobia
+
+/datum/quirk/phobia/add()
+ if(!phobia && quirk_holder.client?.prefs.phobia)
+ phobia = quirk_holder.client?.prefs.phobia
+
+ if(phobia)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ human_holder.gain_trauma(new /datum/brain_trauma/mild/phobia(phobia), TRAUMA_RESILIENCE_ABSOLUTE)
/datum/quirk/phobia/post_add()
- var/mob/living/carbon/human/H = quirk_holder
- H.gain_trauma(new /datum/brain_trauma/mild/phobia(H.client?.prefs.phobia), TRAUMA_RESILIENCE_ABSOLUTE)
+ if(!phobia)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ phobia = human_holder.client.prefs.phobia
+ human_holder.gain_trauma(new /datum/brain_trauma/mild/phobia(phobia), TRAUMA_RESILIENCE_ABSOLUTE)
/datum/quirk/phobia/remove()
- var/mob/living/carbon/human/H = quirk_holder
- if(H)
- H.cure_trauma_type(/datum/brain_trauma/mild/phobia, TRAUMA_RESILIENCE_ABSOLUTE)
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ human_holder.cure_trauma_type(/datum/brain_trauma/mild/phobia, TRAUMA_RESILIENCE_ABSOLUTE)
-/datum/quirk/needswayfinder
+/datum/quirk/item_quirk/needswayfinder
name = "Navigationally Challenged"
desc = "Lacking familiarity with certain stations, you start with a wayfinding pinpointer where available."
value = 0
medical_record_text = "Patient demonstrates a keen ability to get lost."
- var/obj/item/pinpointer/wayfinding/wayfinder
- var/where
-
-/datum/quirk/needswayfinder/on_spawn()
+/datum/quirk/item_quirk/needswayfinder/add_unique()
if(!GLOB.wayfindingbeacons.len)
return
- var/mob/living/carbon/human/H = quirk_holder
- wayfinder = new /obj/item/pinpointer/wayfinding
- wayfinder.owner = H.real_name
- wayfinder.roundstart = TRUE
+ var/mob/living/carbon/human/human_holder = quirk_holder
- var/list/slots = list(
- "in your left pocket" = ITEM_SLOT_LPOCKET,
- "in your right pocket" = ITEM_SLOT_RPOCKET,
- "in your backpack" = ITEM_SLOT_BACKPACK
- )
- where = H.equip_in_one_of_slots(wayfinder, slots, FALSE) || "at your feet"
+ var/obj/item/pinpointer/wayfinding/wayfinder = new(get_turf(quirk_holder))
+ wayfinder.owner = human_holder.real_name
+ wayfinder.from_quirk = TRUE
-/datum/quirk/needswayfinder/post_add()
- if(!GLOB.wayfindingbeacons.len)
- return
- if(where == "in your backpack")
- var/mob/living/carbon/human/H = quirk_holder
- SEND_SIGNAL(H.back, COMSIG_TRY_STORAGE_SHOW, H)
+ give_item_to_holder(wayfinder, list(LOCATION_LPOCKET = ITEM_SLOT_LPOCKET, LOCATION_RPOCKET = ITEM_SLOT_RPOCKET, LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
- to_chat(quirk_holder, "There is a pinpointer [where], which can help you find your way around. Click in-hand to activate.")
-
-/datum/quirk/bald
+/datum/quirk/item_quirk/bald
name = "Smooth-Headed"
desc = "You have no hair and are quite insecure about it! Keep your wig on, or at least your head covered up."
value = 0
@@ -215,41 +205,39 @@
gain_text = "Your head is as smooth as can be, it's terrible."
lose_text = "Your head itches, could it be... growing hair?!"
medical_record_text = "Patient starkly refused to take off headwear during examination."
- ///The user's starting hairstyle
+ /// The user's starting hairstyle
var/old_hair
-/datum/quirk/bald/add()
- var/mob/living/carbon/human/H = quirk_holder
- old_hair = H.hairstyle
- H.hairstyle = "Bald"
- H.update_hair()
- RegisterSignal(H, COMSIG_CARBON_EQUIP_HAT, .proc/equip_hat)
- RegisterSignal(H, COMSIG_CARBON_UNEQUIP_HAT, .proc/unequip_hat)
+/datum/quirk/item_quirk/bald/add()
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ old_hair = human_holder.hairstyle
+ human_holder.hairstyle = "Bald"
+ human_holder.update_hair()
+ RegisterSignal(human_holder, COMSIG_CARBON_EQUIP_HAT, .proc/equip_hat)
+ RegisterSignal(human_holder, COMSIG_CARBON_UNEQUIP_HAT, .proc/unequip_hat)
-/datum/quirk/bald/remove()
- var/mob/living/carbon/human/H = quirk_holder
- H.hairstyle = old_hair
- H.update_hair()
- UnregisterSignal(H, list(COMSIG_CARBON_EQUIP_HAT, COMSIG_CARBON_UNEQUIP_HAT))
- SEND_SIGNAL(H, COMSIG_CLEAR_MOOD_EVENT, "bad_hair_day")
+/datum/quirk/item_quirk/bald/add_unique()
+ var/obj/item/clothing/head/wig/natural/baldie_wig = new(get_turf(quirk_holder))
-/datum/quirk/bald/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/clothing/head/wig/natural/W = new(get_turf(H))
if (old_hair == "Bald")
- W.hairstyle = pick(GLOB.hairstyles_list - "Bald")
+ baldie_wig.hairstyle = pick(GLOB.hairstyles_list - "Bald")
else
- W.hairstyle = old_hair
- W.update_appearance()
- var/list/slots = list (
- "head" = ITEM_SLOT_HEAD,
- "backpack" = ITEM_SLOT_BACKPACK,
- "hands" = ITEM_SLOT_HANDS,
- )
- H.equip_in_one_of_slots(W, slots , qdel_on_fail = TRUE)
+ baldie_wig.hairstyle = old_hair
+
+ baldie_wig.update_appearance()
+
+ give_item_to_holder(baldie_wig, list(LOCATION_HEAD = ITEM_SLOT_HEAD, LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
+
+/datum/quirk/item_quirk/bald/remove()
+ . = ..()
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ human_holder.hairstyle = old_hair
+ human_holder.update_hair()
+ UnregisterSignal(human_holder, list(COMSIG_CARBON_EQUIP_HAT, COMSIG_CARBON_UNEQUIP_HAT))
+ SEND_SIGNAL(human_holder, COMSIG_CLEAR_MOOD_EVENT, "bad_hair_day")
///Checks if the headgear equipped is a wig and sets the mood event accordingly
-/datum/quirk/bald/proc/equip_hat(mob/user, obj/item/hat)
+/datum/quirk/item_quirk/bald/proc/equip_hat(mob/user, obj/item/hat)
SIGNAL_HANDLER
if(istype(hat, /obj/item/clothing/head/wig))
@@ -258,34 +246,32 @@
SEND_SIGNAL(quirk_holder, COMSIG_CLEAR_MOOD_EVENT, "bad_hair_day") //Our head is covered
///Applies a bad moodlet for having an uncovered head
-/datum/quirk/bald/proc/unequip_hat(mob/user, obj/item/clothing, force, newloc, no_move, invdrop, silent)
+/datum/quirk/item_quirk/bald/proc/unequip_hat(mob/user, obj/item/clothing, force, newloc, no_move, invdrop, silent)
SIGNAL_HANDLER
SEND_SIGNAL(quirk_holder, COMSIG_ADD_MOOD_EVENT, "bad_hair_day", /datum/mood_event/bald)
-
-/datum/quirk/tongue_tied
+/datum/quirk/item_quirk/tongue_tied
name = "Tongue Tied"
desc = "Due to a past incident, your ability to communicate has been relegated to your hands."
value = 0
medical_record_text = "During physical examination, patient's tongue was found to be uniquely damaged."
-//Adds tongue & gloves
-/datum/quirk/tongue_tied/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/organ/tongue/old_tongue = locate() in H.internal_organs
- var/obj/item/organ/tongue/tied/new_tongue = new(get_turf(H))
- var/obj/item/clothing/gloves/radio/gloves = new(get_turf(H))
- old_tongue.Remove(H)
- new_tongue.Insert(H)
+/datum/quirk/item_quirk/tongue_tied/add_unique()
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/obj/item/organ/tongue/old_tongue = human_holder.getorganslot(ORGAN_SLOT_TONGUE)
+ old_tongue.Remove(human_holder)
qdel(old_tongue)
- if(!H.equip_to_slot_if_possible(gloves, ITEM_SLOT_GLOVES, bypass_equip_delay_self = TRUE))
- H.put_in_hands(gloves)
-/datum/quirk/tongue_tied/post_add()
+ var/obj/item/organ/tongue/tied/new_tongue = new(get_turf(human_holder))
+ new_tongue.Insert(human_holder)
+
+ give_item_to_holder(/obj/item/clothing/gloves/radio, list(LOCATION_GLOVES = ITEM_SLOT_GLOVES, LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
+
+/datum/quirk/item_quirk/tongue_tied/post_add()
to_chat(quirk_holder, "Because you speak with your hands, having them full hinders your ability to communicate!")
-/datum/quirk/photographer
+/datum/quirk/item_quirk/photographer
name = "Photographer"
desc = "You carry your camera and personal photo album everywhere you go, and your scrapbooks are legendary among your coworkers."
value = 0
@@ -294,37 +280,30 @@
lose_text = "You forget how photo cameras work."
medical_record_text = "Patient mentions photography as a stress-relieving hobby."
-/datum/quirk/photographer/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/storage/photo_album/personal/photo_album = new(get_turf(H))
- var/list/album_slots = list (
- "backpack" = ITEM_SLOT_BACKPACK,
- "hands" = ITEM_SLOT_HANDS
- )
- H.equip_in_one_of_slots(photo_album, album_slots , qdel_on_fail = TRUE)
- photo_album.persistence_id = "personal_[H.mind.key]" // this is a persistent album, the ID is tied to the account's key to avoid tampering
+/datum/quirk/item_quirk/photographer/add_unique()
+ var/mob/living/carbon/human/human_holder = quirk_holder
+ var/obj/item/storage/photo_album/personal/photo_album = new(get_turf(human_holder))
+ photo_album.persistence_id = "personal_[human_holder.mind.key]" // this is a persistent album, the ID is tied to the account's key to avoid tampering
photo_album.persistence_load()
- photo_album.name = "[H.real_name]'s photo album"
- var/obj/item/camera/camera = new(get_turf(H))
- var/list/camera_slots = list (
- "neck" = ITEM_SLOT_NECK,
- "left pocket" = ITEM_SLOT_LPOCKET,
- "right pocket" = ITEM_SLOT_RPOCKET,
- "backpack" = ITEM_SLOT_BACKPACK,
- "hands" = ITEM_SLOT_HANDS
- )
- H.equip_in_one_of_slots(camera, camera_slots , qdel_on_fail = TRUE)
- H.regenerate_icons()
+ photo_album.name = "[human_holder.real_name]'s photo album"
-/datum/quirk/colorist
+ give_item_to_holder(photo_album, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
+ give_item_to_holder(
+ /obj/item/camera,
+ list(
+ LOCATION_NECK = ITEM_SLOT_NECK,
+ LOCATION_LPOCKET = ITEM_SLOT_LPOCKET,
+ LOCATION_RPOCKET = ITEM_SLOT_RPOCKET,
+ LOCATION_BACKPACK = ITEM_SLOT_BACKPACK,
+ LOCATION_HANDS = ITEM_SLOT_HANDS
+ )
+ )
+
+/datum/quirk/item_quirk/colorist
name = "Colorist"
desc = "You like carrying around a hair dye spray to quickly apply color patterns to your hair."
value = 0
medical_record_text = "Patient enjoys dyeing their hair with pretty colors."
-/datum/quirk/colorist/on_spawn()
- var/mob/living/carbon/human/H = quirk_holder
- var/obj/item/dyespray/spraycan = new(get_turf(H))
- H.put_in_hands(spraycan)
- H.equip_to_slot(spraycan, ITEM_SLOT_BACKPACK)
- H.regenerate_icons()
+/datum/quirk/item_quirk/colorist/add_unique()
+ give_item_to_holder(/obj/item/dyespray, list(LOCATION_BACKPACK = ITEM_SLOT_BACKPACK, LOCATION_HANDS = ITEM_SLOT_HANDS))
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 216bf867a28..72811e66e5f 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -599,6 +599,7 @@ GLOBAL_DATUM_INIT(fire_overlay, /mutable_appearance, mutable_appearance('icons/e
SHOULD_CALL_PARENT(TRUE)
visual_equipped(user, slot, initial)
SEND_SIGNAL(src, COMSIG_ITEM_EQUIPPED, user, slot)
+ SEND_SIGNAL(user, COMSIG_MOB_EQUIPPED_ITEM, src, slot)
for(var/X in actions)
var/datum/action/A = X
if(item_action_slot_check(slot, user)) //some items only give their actions buttons when in a specific slot.
diff --git a/code/game/objects/items/devices/scanners.dm b/code/game/objects/items/devices/scanners.dm
index 348db7e77b4..2d1921ddfb6 100644
--- a/code/game/objects/items/devices/scanners.dm
+++ b/code/game/objects/items/devices/scanners.dm
@@ -232,7 +232,7 @@ GENE SCANNER
trauma_desc += B.scan_desc
trauma_text += trauma_desc
render_list += "Cerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)].\n"
- if(C.roundstart_quirks.len)
+ if(C.quirks.len)
render_list += "Subject Major Disabilities: [C.get_quirk_string(FALSE, CAT_QUIRK_MAJOR_DISABILITY)].\n"
if(advanced)
render_list += "Subject Minor Disabilities: [C.get_quirk_string(FALSE, CAT_QUIRK_MINOR_DISABILITY)].\n"
diff --git a/code/game/objects/items/wayfinding.dm b/code/game/objects/items/wayfinding.dm
index 9ed5bd11b3d..c799266fd27 100644
--- a/code/game/objects/items/wayfinding.dm
+++ b/code/game/objects/items/wayfinding.dm
@@ -169,7 +169,7 @@
itsmypinpointer = FALSE
var/is_a_thing = "are [refund_amt] credit\s."
- if(refund_amt > 0 && synth_acc.has_money(refund_amt) && !attacking_pinpointer.roundstart)
+ if(refund_amt > 0 && synth_acc.has_money(refund_amt) && !attacking_pinpointer.from_quirk)
synth_acc.adjust_money(-refund_amt)
var/obj/item/holochip/holochip = new (user.loc)
holochip.credits = refund_amt
@@ -241,7 +241,7 @@
worn_icon_state = "pinpointer_way"
var/owner = null
var/list/beacons = list()
- var/roundstart = FALSE
+ var/from_quirk = FALSE
/obj/item/pinpointer/wayfinding/attack_self(mob/living/user)
if(active)
diff --git a/code/modules/antagonists/creep/creep.dm b/code/modules/antagonists/creep/creep.dm
index 8e325e2ffeb..5442e2af377 100644
--- a/code/modules/antagonists/creep/creep.dm
+++ b/code/modules/antagonists/creep/creep.dm
@@ -48,17 +48,19 @@
var/datum/objective/assassinate/obsessed/kill = new
kill.owner = owner
kill.target = obsessionmind
- var/datum/quirk/family_heirloom/family_heirloom
+ var/obj/family_heirloom
- for(var/datum/quirk/quirky in obsessionmind.current.roundstart_quirks)
- if(istype(quirky, /datum/quirk/family_heirloom))
- family_heirloom = quirky
+ for(var/datum/quirk/quirky in obsessionmind.current.quirks)
+ if(istype(quirky, /datum/quirk/item_quirk/family_heirloom))
+ var/datum/quirk/item_quirk/family_heirloom/heirloom_quirk = quirky
+ family_heirloom = heirloom_quirk.heirloom?.resolve()
break
- if(family_heirloom)//oh, they have an heirloom? Well you know we have to steal that.
+ if(family_heirloom)
objectives_left += "heirloom"
+ // If they have no coworkers, jealousy will pick someone else on the station. This will never be a free objective.
if(obsessionmind.assigned_role && obsessionmind.assigned_role != "Captain")
- objectives_left += "jealous"//if they have no coworkers, jealousy will pick someone else on the station. this will never be a free objective, nice.
+ objectives_left += "jealous"
for(var/i in 1 to 3)
var/chosen_objective = pick(objectives_left)
@@ -83,7 +85,7 @@
var/datum/objective/steal/heirloom_thief/heirloom_thief = new
heirloom_thief.owner = owner
heirloom_thief.target = obsessionmind//while you usually wouldn't need this for stealing, we need the name of the obsession
- heirloom_thief.steal_target = family_heirloom.heirloom
+ heirloom_thief.steal_target = family_heirloom
objectives += heirloom_thief
if("jealous")
var/datum/objective/assassinate/jealous/jealous = new
diff --git a/code/modules/mob/dead/new_player/new_player.dm b/code/modules/mob/dead/new_player/new_player.dm
index 99c4d8a7331..77c7a1801cc 100644
--- a/code/modules/mob/dead/new_player/new_player.dm
+++ b/code/modules/mob/dead/new_player/new_player.dm
@@ -375,7 +375,7 @@
SSticker.mode.make_antag_chance(humanc)
if(humanc && CONFIG_GET(flag/roundstart_traits))
- SSquirks.AssignQuirks(humanc, humanc.client, TRUE)
+ SSquirks.AssignQuirks(humanc, humanc.client)
log_manifest(character.mind.key,character.mind,character,latejoin = TRUE)
diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm
index abe82f32b95..16308e68a1f 100644
--- a/code/modules/mob/living/blood.dm
+++ b/code/modules/mob/living/blood.dm
@@ -253,7 +253,7 @@
blood_data["features"] = dna.features
blood_data["factions"] = faction
blood_data["quirks"] = list()
- for(var/V in roundstart_quirks)
+ for(var/V in quirks)
var/datum/quirk/T = V
blood_data["quirks"] += T.type
return blood_data
diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm
index 391c1debb07..2c6f09aeb48 100644
--- a/code/modules/mob/living/carbon/human/human.dm
+++ b/code/modules/mob/living/carbon/human/human.dm
@@ -816,22 +816,26 @@
return
var/list/options = list("Clear"="Clear")
- for(var/x in subtypesof(/datum/quirk))
- var/datum/quirk/T = x
- var/qname = initial(T.name)
- options[has_quirk(T) ? "[qname] (Remove)" : "[qname] (Add)"] = T
+ for(var/type in subtypesof(/datum/quirk))
+ var/datum/quirk/quirk_type = type
+
+ if(initial(quirk_type.abstract_parent_type) == type)
+ continue
+
+ var/qname = initial(quirk_type.name)
+ options[has_quirk(quirk_type) ? "[qname] (Remove)" : "[qname] (Add)"] = quirk_type
var/result = input(usr, "Choose quirk to add/remove","Quirk Mod") as null|anything in sortList(options)
if(result)
if(result == "Clear")
- for(var/datum/quirk/q in roundstart_quirks)
+ for(var/datum/quirk/q in quirks)
remove_quirk(q.type)
else
var/T = options[result]
if(has_quirk(T))
remove_quirk(T)
else
- add_quirk(T,TRUE)
+ add_quirk(T)
if(href_list[VV_HK_MAKE_MONKEY])
if(!check_rights(R_SPAWN))
return
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index f714b7f0663..f92aefafdde 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -865,7 +865,7 @@
damaged_message += D
combined_msg += "Your [damaged_message] [damaged_plural ? "are" : "is"] hurt."
- if(roundstart_quirks.len)
+ if(quirks.len)
combined_msg += "You have these quirks: [get_quirk_string(FALSE, CAT_QUIRK_ALL)]."
to_chat(src, combined_msg.Join("\n"))
diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm
index 05ec2d751fd..baee489db08 100644
--- a/code/modules/mob/living/living_defines.dm
+++ b/code/modules/mob/living/living_defines.dm
@@ -62,7 +62,7 @@
*/
var/incorporeal_move = FALSE
- var/list/roundstart_quirks = list()
+ var/list/quirks = list()
var/list/surgeries = list() ///a list of surgery datums. generally empty, they're added when the player wants them.
///Mob specific surgery speed modifier
diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm
index 5820b1f9bd9..34404c8d254 100644
--- a/code/modules/mob/living/status_procs.dm
+++ b/code/modules/mob/living/status_procs.dm
@@ -421,27 +421,29 @@
priority_absorb_key["stuns_absorbed"] += amount
return TRUE
-/////////////////////////////////// DISABILITIES ////////////////////////////////////
-/mob/living/proc/add_quirk(quirktype, spawn_effects) //separate proc due to the way these ones are handled
+/mob/living/proc/add_quirk(quirktype) //separate proc due to the way these ones are handled
if(HAS_TRAIT(src, quirktype))
return
- var/datum/quirk/T = quirktype
- var/qname = initial(T.name)
+ var/datum/quirk/quirk = quirktype
+ var/qname = initial(quirk.name)
if(!SSquirks || !SSquirks.quirks[qname])
return
- new quirktype (src, spawn_effects)
- return TRUE
+ quirk = new quirktype()
+ if(quirk.add_to_holder(src))
+ return TRUE
+ qdel(quirk)
+ return FALSE
/mob/living/proc/remove_quirk(quirktype)
- for(var/datum/quirk/Q in roundstart_quirks)
- if(Q.type == quirktype)
- qdel(Q)
+ for(var/datum/quirk/quirk in quirks)
+ if(quirk.type == quirktype)
+ qdel(quirk)
return TRUE
return FALSE
/mob/living/proc/has_quirk(quirktype)
- for(var/datum/quirk/Q in roundstart_quirks)
- if(Q.type == quirktype)
+ for(var/datum/quirk/quirk in quirks)
+ if(quirk.type == quirktype)
return TRUE
return FALSE
diff --git a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
index 6e6109a8ecb..b9d0bc22b42 100644
--- a/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
+++ b/code/modules/reagents/chemistry/reagents/toxin_reagents.dm
@@ -301,8 +301,11 @@
addiction_types = list(/datum/addiction/hallucinogens = 18) //7.2 per 2 seconds
/datum/reagent/toxin/mindbreaker/on_mob_life(mob/living/carbon/M, delta_time, times_fired)
- if(!HAS_TRAIT(M, TRAIT_INSANITY))
+ if(HAS_TRAIT(M, TRAIT_INSANITY))
+ M.hallucination = 0
+ else
M.hallucination += 5 * REM * delta_time
+
return ..()
/datum/reagent/toxin/plantbgone