[MIRROR] Trait Upports & Tweaks (#11941)

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-11-11 00:19:39 +01:00
committed by GitHub
co-authored by Cameron Lennox Kashargul
parent f37d1ba4fa
commit dcdaf14079
35 changed files with 823 additions and 776 deletions
@@ -0,0 +1,37 @@
//Honestly this could be an element, but I don't want to aggressively refactor traits in an upport and cleanup PR.
/datum/component/absorbent
/datum/component/absorbent/Initialize()
if(!ishuman(parent))
return COMPONENT_INCOMPATIBLE
/datum/component/absorbent/RegisterWithParent()
RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(process_component))
/datum/component/absorbent/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_MOVABLE_MOVED))
/datum/component/absorbent/proc/process_component()
SIGNAL_HANDLER
var/mob/living/carbon/human/H = parent
var/turf/T = get_turf(H)
if(istype(T))
if(!(H.shoes || (H.wear_suit && (H.wear_suit.body_parts_covered & FEET))))
//We do this first as it gives nutrition for each item on the turf.
for(var/obj/O in T)
if(O.wash(CLEAN_WASH))
H.adjust_nutrition(rand(5, 15))
//Secondly, we check if the turf is a sim turf. If it's dirty, we get nutrition.
//The T.wash() below will clean it and set the dirt to 0.
if(istype(T, /turf/simulated))
var/turf/simulated/turf_to_clean = T
if(turf_to_clean.dirt >= 50)
H.adjust_nutrition(rand(10, 20))
//Third, we clean the turf itself.
if(T.wash(CLEAN_WASH))
H.adjust_nutrition(rand(10, 20))
//Lastly, we clean ourself and all the items on us.
if(H.wash(CLEAN_WASH))
H.adjust_nutrition(rand(5, 15))
+7 -8
View File
@@ -1,5 +1,4 @@
/datum/component/burninlight
var/mob/living/owner
// This is a merge of the old shadow species light burning life code, and Zaddat's handle_environment_special() proc.
// It handles both cases, but shadows behave more like Zaddat do now. By default this code follows Zaddat damage with no healing.
var/threshold = 0.2 // percent from 0 to 1
@@ -15,12 +14,17 @@
/datum/component/burninlight/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/burninlight/RegisterWithParent()
RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/burninlight/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_LIVING_LIFE))
/datum/component/burninlight/proc/process_component()
if(QDELETED(parent))
return
var/mob/living/owner = parent
if(owner.stat == DEAD)
return
if(owner.is_incorporeal())
@@ -51,8 +55,3 @@
// heal in the dark, if possible
else if(heal_rate > 0)
owner.heal_overall_damage(heal_rate,heal_rate)
/datum/component/burninlight/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_LIVING_LIFE)
owner = null
. = ..()
@@ -22,10 +22,14 @@
if(!ishuman(parent))
return COMPONENT_INCOMPATIBLE
human_parent = parent
RegisterSignal(human_parent, COMSIG_LIVING_LIFE, PROC_REF(handle_life))
/datum/component/crowd_detection/RegisterWithParent()
RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(handle_life))
/datum/component/crowd_detection/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_LIVING_LIFE))
/datum/component/crowd_detection/Destroy(force = FALSE)
UnregisterSignal(human_parent, COMSIG_LIVING_LIFE)
human_parent = null
. = ..()
+4 -5
View File
@@ -3,13 +3,16 @@
var/blood_color = "#A10808"
/datum/component/drippy/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
/datum/component/drippy/RegisterWithParent()
RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(process_component))
RegisterSignal(parent, COMSIG_HUMAN_DNA_FINALIZED, PROC_REF(create_color))
/datum/component/drippy/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_LIVING_LIFE, COMSIG_HUMAN_DNA_FINALIZED))
/datum/component/drippy/proc/process_component()
SIGNAL_HANDLER
var/mob/living/living_guy = parent
@@ -65,7 +68,3 @@
if(ishuman(parent))
var/mob/living/carbon/human/temp_human = parent
blood_color = rgb(temp_human.r_skin,temp_human.g_skin,temp_human.b_skin)
/datum/component/drippy/Destroy(force = FALSE)
UnregisterSignal(parent, list(COMSIG_LIVING_LIFE, COMSIG_HUMAN_DNA_FINALIZED))
. = ..()
+2 -1
View File
@@ -33,7 +33,8 @@
UnregisterSignal(parent, COMSIG_GARGOYLE_PAUSE)
UnregisterSignal(parent, COMSIG_GARGOYLE_CHECK_ENERGY)
UnregisterSignal(parent, COMSIG_LIVING_LIFE)
UnregisterSignal(parent, COMSIG_MOVABLE_MOVED) //happens if gargoyle_pause is used
if(paused)
UnregisterSignal(parent, COMSIG_MOVABLE_MOVED) //happens if gargoyle_pause is used
/datum/component/gargoyle/proc/process_component()
if(QDELETED(gargoyle))
@@ -0,0 +1,86 @@
///The schizophrenia / 'episodic hallucinations' trait, but componentized.
///There is a lot of math that I don't even want to try to fathom in this.
///There was also almost 0 commentation.
/datum/component/schizophrenia
///The maximum amount of hallucinations we can have.
var/hallucination_max = 60
///The amount of hallucinations to increase by each tick during an episode.
var/hallucination_increase = 3
var/episode_length_nomeds_avg = 4000
var/episode_length_nomeds_dev = 100
var/episode_length_meds_avg = 2000
var/episode_length_meds_dev = 500
var/break_length_nomeds_avg = 3000
var/break_length_nomeds_dev = 600
var/break_length_meds_avg = 30000
var/break_length_meds_dev = 7000
//Holds the info if we're in an episode, when then next one will begin, and when it will end.
var/list/episode = list("in_episode" = FALSE)
/datum/component/schizophrenia/Initialize()
if(!ishuman(parent))
return COMPONENT_INCOMPATIBLE
episode["next_episode_begin"] = world.time + 6000
episode["next_episode_end"] = world.time + 9000
/datum/component/schizophrenia/RegisterWithParent()
RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/schizophrenia/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_LIVING_LIFE))
/datum/component/schizophrenia/proc/process_component()
SIGNAL_HANDLER
var/mob/living/carbon/human/human_guy = parent
if(QDELETED(parent))
return
///How much medication we currently have in our system.
var/med_vol = get_med_volume(human_guy)
if(!episode["in_episode"])
if(world.time > episode["next_episode_begin"])
episode["meds_at_beginning"] = med_vol
episode["in_episode"] = TRUE
else if(episode["meds_at_end"] && !med_vol) //Meds ran out
var/new_episode_begin = world.time + (episode["next_episode_begin"] - world.time)/10
episode["next_episode_end"] = new_episode_begin + (episode["next_episode_end"] - episode["next_episode_begin"])
episode["next_episode_begin"] = new_episode_begin
episode["meds_at_end"] = FALSE
else if(!episode["meds_at_end"] && med_vol) //Meds were taken between episodes
var/new_episode_begin = world.time + (episode["next_episode_begin"] - world.time)*10
episode["next_episode_end"] = new_episode_begin + (episode["next_episode_end"] - episode["next_episode_begin"])
episode["next_episode_begin"] = new_episode_begin
episode["meds_at_end"] = TRUE
else
if(world.time > episode["next_episode_end"])
episode["meds_at_end"] = med_vol
episode["in_episode"] = FALSE
var/break_length_dev = med_vol ? break_length_meds_dev : break_length_nomeds_dev
var/break_length_avg = med_vol ? break_length_meds_avg : break_length_nomeds_avg
var/episode_length_dev = med_vol ? episode_length_meds_dev : episode_length_nomeds_dev
var/episode_length_avg = med_vol ? episode_length_meds_avg : episode_length_nomeds_avg
episode["next_episode_begin"] = world.time + max(120,GAUSSIAN_RANDOM() * break_length_dev + break_length_avg)
episode["next_episode_end"] = episode["next_episode_begin"] + max(120,GAUSSIAN_RANDOM() * episode_length_dev + episode_length_avg)
else
if(!episode["meds_at_beginning"] && med_vol)
episode["next_episode_end"] = world.time + (episode["next_episode_end"] - world.time)/8
human_guy.hallucination = min(hallucination_max,human_guy.hallucination + hallucination_increase)
///Checks to see if we have tercozolam in our systeem and returns how much if so.
/datum/component/schizophrenia/proc/get_med_volume(mob/living/carbon/human/human_guy)
var/total_vol = 0
for(var/datum/reagent/reagent in human_guy.bloodstr.reagent_list)
if(istype(reagent,/datum/reagent/tercozolam))
total_vol += reagent.volume
for(var/datum/reagent/reagent in human_guy.ingested.reagent_list)
if(istype(reagent,/datum/reagent/tercozolam))
total_vol += reagent.volume
return total_vol
@@ -0,0 +1,38 @@
///Component that gives negative effects when at low nutrition.
/datum/component/diabetic
var/nutrition_threshold = 200
var/nutrition_weak = 100
var/nutrition_danger = 50
var/nutrition_critical = 25
/datum/component/diabetic/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
/datum/component/diabetic/RegisterWithParent()
RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/diabetic/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_LIVING_LIFE))
/datum/component/diabetic/proc/process_component()
SIGNAL_HANDLER
var/mob/living/living_guy = parent
if(living_guy.nutrition > nutrition_threshold || isbelly(living_guy.loc))
return
if((living_guy.nutrition < nutrition_threshold) && prob(5))
if(living_guy.nutrition > nutrition_weak)
to_chat(living_guy, span_warning("You start to feel noticeably weak as your stomach rumbles, begging for more food. Maybe you should eat something to keep your blood sugar up"))
else if(living_guy.nutrition > nutrition_danger)
to_chat(living_guy, span_warning("You begin to feel rather weak, and your stomach rumbles loudly. You feel lightheaded and it's getting harder to think. You really need to eat something."))
else if(living_guy.nutrition > nutrition_critical)
to_chat(living_guy, span_danger("You're feeling very weak and lightheaded, and your stomach continously rumbles at you. You really need to eat something!"))
else
to_chat(living_guy,span_critical("You're feeling extremely weak and lightheaded. You feel as though you might pass out any moment and your stomach is screaming for food by now! You should really find something to eat!"))
if((living_guy.nutrition < nutrition_weak) && prob(10))
living_guy.Confuse(10)
if((living_guy.nutrition < nutrition_danger) && prob(25))
living_guy.hallucination = max(30,living_guy.hallucination+8)
if((living_guy.nutrition < nutrition_critical) && prob(5))
living_guy.drowsyness = max(100,living_guy.drowsyness+30)
+7 -8
View File
@@ -1,16 +1,20 @@
// If a mob has this component, every life tick it will gain nutrition if it's standing in light up to nutrition_max.
// Extremely good tutorial component if you need an example with no special bells and whistles, and no "gotcha" behaviors.
/datum/component/photosynth
var/mob/living/owner
var/nutrition_max = 1000
/datum/component/photosynth/Initialize()
if(!isliving(parent))
return COMPONENT_INCOMPATIBLE
owner = parent
RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/photosynth/RegisterWithParent()
RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/photosynth/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_LIVING_LIFE))
/datum/component/photosynth/proc/process_component()
var/mob/living/owner = parent
if(QDELETED(parent))
return
if(owner.stat == DEAD)
@@ -25,8 +29,3 @@
return
var/turf/T = owner.loc
owner.adjust_nutrition(T.get_lumcount() / 10)
/datum/component/photosynth/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_LIVING_LIFE)
owner = null
. = ..()
+6 -2
View File
@@ -22,20 +22,24 @@
add_verb(owner, /mob/living/carbon/human/proc/enter_cocoon)
//Processing
RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/weaver/proc/process_component()
if (QDELETED(parent))
return
process_weaver_silk()
/datum/component/weaver/Destroy(force = FALSE)
UnregisterSignal(owner, COMSIG_LIVING_LIFE) //IF we registered a signal, we need to unregister it.
remove_verb(owner, /mob/living/proc/weaver_control_panel)
if(ishuman(parent))
remove_verb(owner, /mob/living/carbon/human/proc/enter_cocoon)
owner = null
. = ..()
/datum/component/weaver/RegisterWithParent()
RegisterSignal(parent, COMSIG_LIVING_LIFE, PROC_REF(process_component))
/datum/component/weaver/UnregisterFromParent()
UnregisterSignal(parent, list(COMSIG_LIVING_LIFE))
/datum/component/weaver/proc/process_weaver_silk()
if(silk_reserve < silk_max_reserve && silk_production == TRUE && owner.nutrition > 100)
silk_reserve = min(silk_reserve + silk_generation_amount, silk_max_reserve)