From 5d95b50db99a030ec7365296e6b5ef782ffefe6f Mon Sep 17 00:00:00 2001 From: Cameron Lennox Date: Thu, 15 May 2025 03:59:47 -0400 Subject: [PATCH] Component Traits. (#17665) * Drippy component * Converts disabilities to components. * Makes weaver a component * living * Update vorestation.dme * Update weaver.dm * yeah tis * no spawn * yes * signals hell yeah * Teaching * yeaaah * makes gargoyle follow the law * whoops * return properly * wah * Update station.dm --- code/__defines/dcs/signals.dm | 24 +++ code/__defines/dna.dm | 6 - .../components/disabilities/coughing.dm | 28 +++ .../components/disabilities/epilepsy.dm | 32 +++ .../datums/components/disabilities/gibbing.dm | 40 ++++ .../components/disabilities/nervousness.dm | 29 +++ .../datums/components/disabilities/rotting.dm | 41 ++++ .../components/disabilities/tourettes.dm | 34 +++ .../components/traits/_trait_template.dm | 67 ++++++ code/datums/components/traits/drippy.dm | 67 ++++++ .../components/{ => traits}/gargoyle.dm | 65 +++--- code/datums/components/traits/weaver.dm | 193 ++++++++++++++++++ code/modules/mob/living/carbon/human/human.dm | 1 - code/modules/mob/living/carbon/human/life.dm | 66 +----- .../mob/living/carbon/human/life_vr.dm | 8 - .../living/carbon/human/species/species.dm | 7 - .../carbon/human/species/station/station.dm | 13 +- .../station/station_special_abilities.dm | 147 ------------- .../species/station/traits/negative_genes.dm | 14 +- .../human/species/station/traits/neutral.dm | 5 +- .../species/station/traits/neutral_genes.dm | 2 +- .../human/species/station/traits/positive.dm | 19 +- .../human/species/station/traits/trait.dm | 7 + .../species/station/traits/weaver_objs.dm | 14 +- code/modules/mob/living/life.dm | 5 +- code/modules/mob/living/living.dm | 44 ---- vorestation.dme | 10 +- 27 files changed, 646 insertions(+), 342 deletions(-) create mode 100644 code/datums/components/disabilities/coughing.dm create mode 100644 code/datums/components/disabilities/epilepsy.dm create mode 100644 code/datums/components/disabilities/gibbing.dm create mode 100644 code/datums/components/disabilities/nervousness.dm create mode 100644 code/datums/components/disabilities/rotting.dm create mode 100644 code/datums/components/disabilities/tourettes.dm create mode 100644 code/datums/components/traits/_trait_template.dm create mode 100644 code/datums/components/traits/drippy.dm rename code/datums/components/{ => traits}/gargoyle.dm (52%) create mode 100644 code/datums/components/traits/weaver.dm diff --git a/code/__defines/dcs/signals.dm b/code/__defines/dcs/signals.dm index a5a18e2b3e4..7e1dc3c3640 100644 --- a/code/__defines/dcs/signals.dm +++ b/code/__defines/dcs/signals.dm @@ -377,6 +377,10 @@ #define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" ///sent from borg mobs to itself, for tools to catch an upcoming destroy() due to safe decon (rather than detonation) #define COMSIG_BORG_SAFE_DECONSTRUCT "borg_safe_decon" +///From living/Life(). +#define COMSIG_LIVING_LIFE "living_life" +///From /living/handle_disabilities(). +#define COMSIG_HANDLE_DISABILITIES "handle_disabilities" //ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! @@ -829,6 +833,26 @@ /// COMSIG used to get messages where they need to go #define COMSIG_VISIBLE_MESSAGE "visible_message" +// Weaver Component +///from /mob/living/proc/check_silk_amount() +#define COMSIG_CHECK_SILK_AMOUNT "check_silk_amount" +///from /mob/living/proc/weave_structure() +#define COMSIG_WEAVE_STRUCTURE "weave_structure" +///from /mob/living/proc/toggle_silk_production() +#define COMSIG_TOGGLE_SILK_PRODUCTION "toggle_silk_production" +///from /mob/living/proc/weave_item() +#define COMSIG_WEAVE_ITEM "weave_item" +///from /mob/living/proc/set_silk_color() +#define COMSIG_SET_SILK_COLOR "set_silk_color" + +// Gargoyle Component +///from /mob/living/carbon/human/proc/gargoyle_transformation() +#define COMSIG_GARGOYLE_TRANSFORMATION "gargoyle_transformation" +///from /mob/living/carbon/human/proc/gargoyle_pause() +#define COMSIG_GARGOYLE_PAUSE "gargoyle_pause" +///from /mob/living/carbon/human/proc/gargoyle_checkenergy() +#define COMSIG_GARGOYLE_CHECK_ENERGY "gargoyle_check_energy" + // Species Components ///from /datum/species/xenochimera/handle_environment_special() #define COMSIG_XENOCHIMERA_COMPONENT "xenochimera_component" diff --git a/code/__defines/dna.dm b/code/__defines/dna.dm index 63959efa07d..c7ee3eceec0 100644 --- a/code/__defines/dna.dm +++ b/code/__defines/dna.dm @@ -33,17 +33,11 @@ // disabilities #define NEARSIGHTED 0x1 -#define EPILEPSY 0x2 -#define COUGHING 0x4 -#define TOURETTES 0x8 -#define NERVOUS 0x10 /* #define DEPRESSION 0x20 // Roleplay drugs #define SCHIZOPHRENIA 0x40 // Roleplay drugs */ #define WINGDINGS 0x80 // Better handling as disability -#define DETERIORATE 0x100 // Body melts slowly, medical loves you! -#define GIBBING 0x200 // Landmine for genetics to find #define CENSORED 0x400 // Cannot swear // sdisabilities #define BLIND 0x1 diff --git a/code/datums/components/disabilities/coughing.dm b/code/datums/components/disabilities/coughing.dm new file mode 100644 index 00000000000..fd98dcd2cdc --- /dev/null +++ b/code/datums/components/disabilities/coughing.dm @@ -0,0 +1,28 @@ +/datum/component/coughing_disability + var/mob/living/owner + var/cough_chance = 5 + +/datum/component/coughing_disability/Initialize() + if (!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + owner = parent + RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component)) + +/datum/component/coughing_disability/proc/process_component() + if (QDELETED(parent)) + return + if(isbelly(owner.loc)) + return + if(owner.stat != CONSCIOUS) + return + if(owner.transforming) + return + if((prob(cough_chance) && owner.paralysis <= 1)) + owner.drop_item() + owner.emote("cough") + +/datum/component/coughing_disability/Destroy(force = FALSE) + UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES) + owner = null + . = ..() diff --git a/code/datums/components/disabilities/epilepsy.dm b/code/datums/components/disabilities/epilepsy.dm new file mode 100644 index 00000000000..37127d5fff6 --- /dev/null +++ b/code/datums/components/disabilities/epilepsy.dm @@ -0,0 +1,32 @@ +/datum/component/epilepsy_disability + var/mob/living/owner + +/datum/component/epilepsy_disability/Initialize() + if (!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + owner = parent + RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component)) + +/datum/component/epilepsy_disability/proc/process_component() + if (QDELETED(parent)) + return + if(isbelly(owner.loc)) + return + if(owner.stat != CONSCIOUS) + return + if(owner.transforming) + return + if((prob(1) && prob(1) && owner.paralysis < 1)) + to_chat(owner, span_red("You have a seizure!")) + for(var/mob/O in viewers(owner, null)) + if(O == owner) + continue + O.show_message(span_danger("[owner] starts having a seizure!"), 1) + owner.Paralyse(10) + owner.make_jittery(1000) + +/datum/component/epilepsy_disability/Destroy(force = FALSE) + UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES) + owner = null + . = ..() diff --git a/code/datums/components/disabilities/gibbing.dm b/code/datums/components/disabilities/gibbing.dm new file mode 100644 index 00000000000..53972cdd0e2 --- /dev/null +++ b/code/datums/components/disabilities/gibbing.dm @@ -0,0 +1,40 @@ +/datum/component/gibbing_disability + var/mob/living/owner + var/gutdeathpressure = 0 + var/death_time = FALSE + dupe_mode = COMPONENT_DUPE_UNIQUE + +/datum/component/gibbing_disability/Initialize() + if (!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + owner = parent + RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component)) + +/datum/component/gibbing_disability/proc/process_component() + if(QDELETED(parent)) + return + if(isbelly(owner.loc)) + return + if(owner.transforming) + return + if(death_time) + if(death_time < 4) + owner.emote(pick("whimper","belch","shiver")) + death_time++ + return + else + owner.emote(pick("belch")) + owner.gib() + return + gutdeathpressure += 0.01 + if(gutdeathpressure > 0 && prob(gutdeathpressure)) + owner.emote(pick("whimper","belch","belch","belch","choke","shiver")) + owner.Weaken(gutdeathpressure / 3) + if((gutdeathpressure/3) >= 1 && prob(gutdeathpressure/3)) + death_time = TRUE + +/datum/component/gibbing_disability/Destroy(force = FALSE) + UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES) + owner = null + . = ..() diff --git a/code/datums/components/disabilities/nervousness.dm b/code/datums/components/disabilities/nervousness.dm new file mode 100644 index 00000000000..30045e96bd7 --- /dev/null +++ b/code/datums/components/disabilities/nervousness.dm @@ -0,0 +1,29 @@ +/datum/component/nervousness_disability + var/mob/owner + var/gutdeathpressure = 0 + +/datum/component/nervousness_disability/Initialize() + if (!ishuman(parent)) + return COMPONENT_INCOMPATIBLE + + owner = parent + RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component)) + +/datum/component/nervousness_disability/proc/process_component() + if(QDELETED(parent)) + return + if(isbelly(owner.loc)) + return + if(owner.stat != CONSCIOUS) + return + if(owner.transforming) + return + if(prob(5) && prob(7)) + owner.stuttering = max(15, owner.stuttering) + if(owner.jitteriness < 50) + owner.make_jittery(65) + +/datum/component/nervousness_disability/Destroy(force = FALSE) + UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES) + owner = null + . = ..() diff --git a/code/datums/components/disabilities/rotting.dm b/code/datums/components/disabilities/rotting.dm new file mode 100644 index 00000000000..dcd0b82a5b1 --- /dev/null +++ b/code/datums/components/disabilities/rotting.dm @@ -0,0 +1,41 @@ +/datum/component/rotting_disability + var/mob/living/carbon/human/owner + +/datum/component/rotting_disability/Initialize() + if (!ishuman(parent)) + return COMPONENT_INCOMPATIBLE + + owner = parent + RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component)) + +/datum/component/rotting_disability/proc/process_component() + if (QDELETED(parent)) + return + if(isbelly(owner.loc)) + return + if(owner.transforming) + return + if(prob(2) && prob(3)) // stacked percents for rarity + // random strange symptoms from organ/limb + owner.automatic_custom_emote(VISIBLE_MESSAGE, "flinches slightly.", check_stat = TRUE) + switch(rand(1,4)) + if(1) + owner.adjustToxLoss(rand(2,8)) + if(2) + owner.adjustCloneLoss(rand(1,2)) + if(3) + owner.add_chemical_effect(CE_PAINKILLER, rand(8,28)) + else + owner.adjustOxyLoss(rand(13,26)) + // external organs need to fall off if damaged enough + var/obj/item/organ/O = pick(owner.organs) + if(O && !(O.organ_tag == BP_GROIN || O.organ_tag == BP_TORSO) && istype(O,/obj/item/organ/external)) + var/obj/item/organ/external/E = O + if(O.damage >= O.min_broken_damage && O.robotic <= ORGAN_ASSISTED && prob(70)) + owner.add_chemical_effect(CE_PAINKILLER, 120) // what limb? Extreme nerve damage. Can't feel a thing + shock + E.droplimb(TRUE, DROPLIMB_ACID) + +/datum/component/rotting_disability/Destroy(force = FALSE) + UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES) + owner = null + . = ..() diff --git a/code/datums/components/disabilities/tourettes.dm b/code/datums/components/disabilities/tourettes.dm new file mode 100644 index 00000000000..5aa12e2492b --- /dev/null +++ b/code/datums/components/disabilities/tourettes.dm @@ -0,0 +1,34 @@ +/datum/component/tourettes_disability + var/mob/living/owner + var/gutdeathpressure = 0 + +/datum/component/tourettes_disability/Initialize() + if (!ishuman(parent)) + return COMPONENT_INCOMPATIBLE + + owner = parent + RegisterSignal(owner, COMSIG_HANDLE_DISABILITIES, PROC_REF(process_component)) + +/datum/component/tourettes_disability/proc/process_component() + if(QDELETED(parent)) + return + if(isbelly(owner.loc)) + return + if(owner.stat != CONSCIOUS) + return + if(owner.transforming) + return + if((prob(1) && prob(2) && owner.paralysis <= 1)) + owner.Stun(10) + owner.make_jittery(100) + switch(rand(1, 3)) + if(1) + owner.emote("twitch") + if(2 to 3) + owner.say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]") + + +/datum/component/tourettes_disability/Destroy(force = FALSE) + UnregisterSignal(owner, COMSIG_HANDLE_DISABILITIES) + owner = null + . = ..() diff --git a/code/datums/components/traits/_trait_template.dm b/code/datums/components/traits/_trait_template.dm new file mode 100644 index 00000000000..53e6052a7be --- /dev/null +++ b/code/datums/components/traits/_trait_template.dm @@ -0,0 +1,67 @@ +//Some notes: +//How you APPLY a component: Call LoadComponent(/datum/component/template) on the thing you want to apply it to. +//How you CHECK a component: var/datum/component/template/comp = GetComponent(/datum/component/template) +//You can CHECK VARIABLES on a component and adjust them by doing the above and then doing something like: if(comp.energy < 50) comp.energy += 1 +//How you GET RID of a component: Just qdel() it. It'll remove itself from the owner and then delete nicely. + + +//BIG NOTE: As the README.md notes: Using GetComponent is a crutch and should be avoided. +//Traits shouldn't NEED for external code to check for their components. It should be self-contained. +//However, for something more complex like xenochimera or shadekin, signals should be used...But we aren't at that point yet, so we're using GetComponent + +/datum/component/template + //Insert variables here if you require them. Using energy and cooldown as examples. + var/energy = 100 + var/cooldown + + //Reference to our owner (the person that possesses us) + //This can be anything that is our owner that we want to reference. Swap out with mob/living/carbon/human/owner as needed. + var/mob/living/owner //easy reference + + //dupe_mode = COMPONENT_DUPE_HIGHLANDER //Default mode. See flags.dm + +/datum/component/template/Initialize() + + if (!isliving(parent)) //When we get created, parent is 'whatever we are being applied to' This can be ANYTHING. For this trait, we're doing living only. + return COMPONENT_INCOMPATIBLE //If it's not a living mob, we tell the component 'We can't be applied to this' and don't get applied. + + //We then get a reference to the thing we're applied to. In this case, a living mob. + owner = parent + + add_verb(owner,/mob/living/proc/example_proc) //We can add verbs to our owner. + RegisterSignal(owner, COMSIG_EXAMPLE_SIGNAL, PROC_REF(example_proc)) //To put this easily: Owner is the person we're attached to, COMSIG_EXAMPLE_SIGNAL is the signal we expect them to send out when they want us to use our 'example_proc' + + //Register this to a signal that is sent out whenever you want this to be called. For example: We want this trait to happen every life() tick, so we register it to the COMSIG_LIVING_LIFE signal that is sent every time life() is called on a /mob. + RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(process)) + +/datum/component/template/process() + if (QDELETED(parent)) + return + energy = min(100, energy+1) //Add one energy per tick, up to 100 + +/datum/component/template/Destroy(force = FALSE) + UnregisterSignal(owner, COMSIG_LIVING_LIFE) //IF we registered a signal, we need to unregister it. + UnregisterSignal(owner, COMSIG_EXAMPLE_SIGNAL) //MAKE SURE TO UNREGISTER YOUR SIGNALS. SERIOUSLY. OR THE SERVER WILL DIE. + owner = null //MAKE SURE TO CLEAR YOUR REFS! + . = ..() + +/mob/living/proc/example_proc() + set name = "Example proc" + set category = "Abilities" + set desc = "See example." + SEND_SIGNAL(src, COMSIG_EXAMPLE_SIGNAL) + //This sends a signal to the world saying 'We did this thing!' This is then interpreed by the component and the component calls whatever proc it needs to. + + +/datum/component/template/proc/example_proc() + if (stat == DEAD) + return + if (energy <= 0) //Check a variable on the component. + to_chat(owner, span_danger("You currently have no energy!")) + else if (cooldown > world.time) //Check the cooldown variable on the component and compare it. + var/time_to_wait = (cooldown - world.time) / (1 SECONDS) //Simple cooldown + to_chat(owner, span_warning("You're currently on cooldown! Wait for another [round(time_to_wait,0.1)] seconds!")) + return + else + cooldown = world.time + 5 SECONDS //Set the component on a 5 second cooldown. + to_chat(owner, span_warning("You successfully used the example proc!")) diff --git a/code/datums/components/traits/drippy.dm b/code/datums/components/traits/drippy.dm new file mode 100644 index 00000000000..313d3a09cd0 --- /dev/null +++ b/code/datums/components/traits/drippy.dm @@ -0,0 +1,67 @@ +/datum/component/drippy + var/drip_chance = 5 + var/blood_color = "#A10808" + + var/mob/living/owner + +/datum/component/drippy/Initialize() + + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + owner = parent + + if(ishuman(parent)) + var/mob/living/carbon/human/temp_owner = parent + blood_color = rgb(temp_owner.r_skin,temp_owner.g_skin,temp_owner.b_skin) + + RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(process_component)) + +/datum/component/drippy/proc/process_component() + if(QDELETED(parent)) + return + if(!prob(drip_chance)) + return + if(owner.stat == DEAD) + return + var/turf/T = get_turf(owner.loc) + if(!isturf(T)) + return + var/obj/effect/decal/cleanable/blood/B + var/decal_type = /obj/effect/decal/cleanable/blood/splatter + + // Are we dripping or splattering? + var/list/drips = list() + // Only a certain number of drips (or one large splatter) can be on a given turf. + for(var/obj/effect/decal/cleanable/blood/drip/drop in T) + drips |= drop.drips + qdel(drop) + if(drips.len < 4) + decal_type = /obj/effect/decal/cleanable/blood/drip + + // Find a blood decal or create a new one. + B = locate(decal_type) in T + if(!B) + B = new decal_type(T) + + var/obj/effect/decal/cleanable/blood/drip/drop = B + if(istype(drop) && drips && drips.len) + drop.add_overlay(drips) + drop.drips |= drips + + B.basecolor = blood_color + B.update_icon() + if(istype(B, drop)) //We're a drop. + B.name = "drips of something" + else //We're a puddle. + B.name = "puddle of something" + B.desc = "It's thick and gooey. Perhaps it's the chef's cooking?" + B.dryname = "dried something" + B.drydesc = "It's dry and crusty. The janitor isn't doing their job." + B.fluorescent = 0 + B.invisibility = INVISIBILITY_NONE + + +/datum/component/drippy/Destroy(force = FALSE) + owner = null + . = ..() diff --git a/code/datums/components/gargoyle.dm b/code/datums/components/traits/gargoyle.dm similarity index 52% rename from code/datums/components/gargoyle.dm rename to code/datums/components/traits/gargoyle.dm index 618c2e97e03..1b252e4f9b7 100644 --- a/code/datums/components/gargoyle.dm +++ b/code/datums/components/traits/gargoyle.dm @@ -21,10 +21,13 @@ add_verb(gargoyle,/mob/living/carbon/human/proc/gargoyle_transformation) add_verb(gargoyle,/mob/living/carbon/human/proc/gargoyle_pause) add_verb(gargoyle,/mob/living/carbon/human/proc/gargoyle_checkenergy) + RegisterSignal(gargoyle, COMSIG_GARGOYLE_TRANSFORMATION, PROC_REF(gargoyle_transformation)) + RegisterSignal(gargoyle, COMSIG_GARGOYLE_PAUSE, PROC_REF(gargoyle_pause)) + RegisterSignal(gargoyle, COMSIG_GARGOYLE_CHECK_ENERGY, PROC_REF(gargoyle_checkenergy)) - START_PROCESSING(SSprocessing, src) + RegisterSignal(gargoyle, COMSIG_LIVING_LIFE, PROC_REF(process_component)) -/datum/component/gargoyle/process() +/datum/component/gargoyle/proc/process_component() if (QDELETED(gargoyle)) return if (paused && gargoyle.loc != paused_loc) @@ -40,6 +43,15 @@ statue.damage(-0.5) energy = min(energy+0.3, 100) +/datum/component/gargoyle/Destroy(force = FALSE) + UnregisterSignal(gargoyle, COMSIG_GARGOYLE_TRANSFORMATION) + UnregisterSignal(gargoyle, COMSIG_GARGOYLE_PAUSE) + UnregisterSignal(gargoyle, COMSIG_GARGOYLE_CHECK_ENERGY) + UnregisterSignal(gargoyle, COMSIG_LIVING_LIFE) + gargoyle = null + statue = null + . = ..() + /datum/component/gargoyle/proc/unpause() if (!paused || transformed) paused = FALSE @@ -59,43 +71,44 @@ set name = "Gargoyle - Petrification" set category = "Abilities.Gargoyle" set desc = "Turn yourself into (or back from) being a gargoyle." + SEND_SIGNAL(src, COMSIG_GARGOYLE_TRANSFORMATION) - if (stat == DEAD) + +/datum/component/gargoyle/proc/gargoyle_transformation() + if (gargoyle.stat == DEAD) return - - var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle) - if (comp) - if (comp.energy <= 0 && isturf(loc)) - to_chat(src, span_danger("You suddenly turn into a [comp.identifier] as you run out of energy!")) - else if (comp.cooldown > world.time) - var/time_to_wait = (comp.cooldown - world.time) / (1 SECONDS) - to_chat(src, span_warning("You can't transform just yet again! Wait for another [round(time_to_wait,0.1)] seconds!")) - return - if (istype(loc, /obj/structure/gargoyle)) - qdel(loc) - else if (isturf(loc)) - new /obj/structure/gargoyle(loc, src) + if (energy <= 0 && isturf(gargoyle.loc)) + to_chat(gargoyle, span_danger("You suddenly turn into a [identifier] as you run out of energy!")) + else if (cooldown > world.time) + var/time_to_wait = (cooldown - world.time) / (1 SECONDS) + to_chat(gargoyle, span_warning("You can't transform just yet again! Wait for another [round(time_to_wait,0.1)] seconds!")) + return + if (istype(gargoyle.loc, /obj/structure/gargoyle)) + qdel(gargoyle.loc) + else if (isturf(gargoyle.loc)) + new /obj/structure/gargoyle(gargoyle.loc, gargoyle) /mob/living/carbon/human/proc/gargoyle_pause() set name = "Gargoyle - Pause" set category = "Abilities.Gargoyle" set desc = "Pause your energy while standing still, so you don't use up any more, though you will lose a small amount upon moving again." + SEND_SIGNAL(src, COMSIG_GARGOYLE_PAUSE) - if (stat) +/datum/component/gargoyle/proc/gargoyle_pause() + if (gargoyle.stat) return - var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle) - if (comp && !comp.transformed && !comp.paused) - comp.paused = TRUE - comp.paused_loc = loc - comp.RegisterSignal(src, COMSIG_ATOM_ENTERING, /datum/component/gargoyle/proc/unpause) - to_chat(src, span_notice("You start conserving your energy.")) + if (!transformed && !paused) + paused = TRUE + paused_loc = gargoyle.loc + RegisterSignal(gargoyle, COMSIG_ATOM_ENTERING, /datum/component/gargoyle/proc/unpause) + to_chat(gargoyle, span_notice("You start conserving your energy.")) /mob/living/carbon/human/proc/gargoyle_checkenergy() set name = "Gargoyle - Check Energy" set category = "Abilities.Gargoyle" set desc = "Check how much energy you have remaining as a gargoyle." + SEND_SIGNAL(src, COMSIG_GARGOYLE_CHECK_ENERGY) - var/datum/component/gargoyle/comp = GetComponent(/datum/component/gargoyle) - if (comp) - to_chat(src, span_notice("You have [round(comp.energy,0.01)] energy remaining. It is currently [comp.paused ? "stable" : (comp.transformed ? "increasing" : "decreasing")].")) +/datum/component/gargoyle/proc/gargoyle_checkenergy() + to_chat(gargoyle, span_notice("You have [round(energy,0.01)] energy remaining. It is currently [paused ? "stable" : (transformed ? "increasing" : "decreasing")].")) diff --git a/code/datums/components/traits/weaver.dm b/code/datums/components/traits/weaver.dm new file mode 100644 index 00000000000..8133acc57f2 --- /dev/null +++ b/code/datums/components/traits/weaver.dm @@ -0,0 +1,193 @@ + +/datum/component/weaver + var/silk_reserve = 100 + var/silk_max_reserve = 500 + var/silk_color = "#FFFFFF" + var/silk_production = FALSE + var/silk_generation_amount = 2 + var/nutrtion_per_silk = 0.2 + + var/mob/living/owner + + dupe_mode = COMPONENT_DUPE_UNIQUE + +/datum/component/weaver/Initialize() + + if (!isliving(parent)) + return COMPONENT_INCOMPATIBLE + + owner = parent + add_verb(owner, /mob/living/proc/check_silk_amount) + add_verb(owner, /mob/living/proc/toggle_silk_production) + add_verb(owner, /mob/living/proc/weave_structure) + add_verb(owner, /mob/living/proc/weave_item) + add_verb(owner, /mob/living/proc/set_silk_color) + + //Processing + RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(process_component)) + + //When procs are used + RegisterSignal(owner, COMSIG_CHECK_SILK_AMOUNT, PROC_REF(check_silk_amount)) + RegisterSignal(owner, COMSIG_WEAVE_STRUCTURE, PROC_REF(weave_structure)) + RegisterSignal(owner, COMSIG_TOGGLE_SILK_PRODUCTION, PROC_REF(weave_item)) + RegisterSignal(owner, COMSIG_WEAVE_ITEM, PROC_REF(weave_item)) + RegisterSignal(owner, COMSIG_SET_SILK_COLOR, PROC_REF(set_silk_color)) + +/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. + UnregisterSignal(owner, COMSIG_CHECK_SILK_AMOUNT) + UnregisterSignal(owner, COMSIG_WEAVE_STRUCTURE) + UnregisterSignal(owner, COMSIG_TOGGLE_SILK_PRODUCTION) + UnregisterSignal(owner, COMSIG_WEAVE_ITEM) + UnregisterSignal(owner, COMSIG_SET_SILK_COLOR) + remove_verb(owner, /mob/living/proc/check_silk_amount) + remove_verb(owner, /mob/living/proc/toggle_silk_production) + remove_verb(owner, /mob/living/proc/weave_structure) + remove_verb(owner, /mob/living/proc/weave_item) + remove_verb(owner, /mob/living/proc/set_silk_color) + owner = null + . = ..() + +/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) + owner.adjust_nutrition(-(nutrtion_per_silk*silk_generation_amount)) + + +/mob/living/proc/check_silk_amount() + set name = "Check Silk Amount" + set category = "Abilities.Weaver" + SEND_SIGNAL(src, COMSIG_CHECK_SILK_AMOUNT) + +/datum/component/weaver/proc/check_silk_amount() + to_chat(owner, "Your silk reserves are at [silk_reserve]/[silk_max_reserve].") + +/mob/living/proc/toggle_silk_production() + set name = "Toggle Silk Production" + set category = "Abilities.Weaver" + SEND_SIGNAL(src, COMSIG_TOGGLE_SILK_PRODUCTION) + +/datum/component/weaver/proc/toggle_silk_production() + silk_production = !(silk_production) + to_chat(owner, "You are [silk_production ? "now" : "no longer"] producing silk.") + +/mob/living/proc/weave_structure() + set name = "Weave Structure" + set category = "Abilities.Weaver" + SEND_SIGNAL(src, COMSIG_WEAVE_STRUCTURE) + +/datum/component/weaver/proc/weave_structure() + + var/choice + var/datum/weaver_recipe/structure/desired_result + var/finalized = "No" + + while(finalized == "No" && owner.client) + choice = tgui_input_list(owner,"What would you like to weave?", "Weave Choice", GLOB.weavable_structures) + desired_result = GLOB.weavable_structures[choice] + if(!desired_result || !istype(desired_result)) + return + + if(choice) + finalized = tgui_alert(owner, "Are you sure you want to weave [desired_result.title]? It will cost you [desired_result.cost] silk.","Confirmation",list("Yes","No")) + + if(!desired_result || !istype(desired_result)) + return + + if(desired_result.cost > silk_reserve) + to_chat(owner, span_warning("You don't have enough silk to weave that!")) + return + + if(owner.stat) + to_chat(owner, span_warning("You can't do that in your current state!")) + return + + if(locate(desired_result.result_type) in owner.loc) + to_chat(owner, span_warning("You can't create another weaversilk [desired_result.title] here!")) + return + + if(!isturf(owner.loc)) + to_chat(owner, span_warning("You can't weave here!")) + return + + if(do_after(owner, desired_result.time, exclusive = TASK_USER_EXCLUSIVE)) + if(desired_result.cost > silk_reserve) + to_chat(owner, span_warning("You don't have enough silk to weave that!")) + return + + if(locate(desired_result.result_type) in owner.loc) + to_chat(owner, span_warning("You can't create another weaversilk [desired_result.title] here!")) + return + + if(!isturf(owner.loc)) + to_chat(owner, span_warning("You can't weave here!")) + return + + silk_reserve = max(silk_reserve - desired_result.cost, 0) + + var/atom/O = new desired_result.result_type(owner.loc) + O.color = silk_color + + +/mob/living/proc/weave_item() + set name = "Weave Item" + set category = "Abilities.Weaver" + SEND_SIGNAL(src, COMSIG_WEAVE_ITEM) + +/datum/component/weaver/proc/weave_item() + var/choice + var/datum/weaver_recipe/item/desired_result + var/finalized = "No" + + while(finalized == "No" && owner.client) + choice = tgui_input_list(owner,"What would you like to weave?", "Weave Choice", GLOB.weavable_items) + desired_result = GLOB.weavable_items[choice] + if(!desired_result || !istype(desired_result)) + return + + if(choice) + finalized = tgui_alert(owner, "Are you sure you want to weave [desired_result.title]? It will cost you [desired_result.cost] silk.","Confirmation",list("Yes","No")) + + if(!desired_result || !istype(desired_result)) + return + + if(desired_result.cost > silk_reserve) + to_chat(owner, span_warning("You don't have enough silk to weave that!")) + return + + if(owner.stat) + to_chat(owner, span_warning("You can't do that in your current state!")) + return + + if(!isturf(owner.loc)) + to_chat(owner, span_warning("You can't weave here!")) + return + + if(do_after(owner, desired_result.time, exclusive = TASK_USER_EXCLUSIVE)) + if(desired_result.cost > silk_reserve) + to_chat(owner, span_warning("You don't have enough silk to weave that!")) + return + + if(!isturf(owner.loc)) + to_chat(owner, span_warning("You can't weave here!")) + return + + silk_reserve = max(silk_reserve - desired_result.cost, 0) + + var/atom/O = new desired_result.result_type(owner.loc) + O.color = silk_color + +/mob/living/proc/set_silk_color() + set name = "Set Silk Color" + set category = "Abilities.Weaver" + SEND_SIGNAL(src, COMSIG_SET_SILK_COLOR) + +/datum/component/weaver/proc/set_silk_color() + var/new_silk_color = tgui_color_picker(owner, "Pick a color for your woven products:","Silk Color", silk_color) + if(new_silk_color) + silk_color = new_silk_color diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 91a947253cc..9915e1017d3 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -31,7 +31,6 @@ var/list/teleporters = list() //Used for lleill abilities var/rest_dir = 0 //To lay down in a specific direction - var/gutdeathpressure = 0 //For GIBBING trait var/list/datum/genetics/side_effect/genetic_side_effects = list() //For any genetic side effects we currently have. /mob/living/carbon/human/Initialize(mapload, var/new_species = null) diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm index df03f5fc2ed..67026766cdf 100644 --- a/code/modules/mob/living/carbon/human/life.dm +++ b/code/modules/mob/living/carbon/human/life.dm @@ -61,7 +61,6 @@ handle_organs() stabilize_body_temperature() //Body temperature adjusts itself (self-regulation) weightgain() - process_weaver_silk() handle_shock() handle_pain() @@ -183,69 +182,8 @@ if(stat != CONSCIOUS) //Let's not worry about tourettes if you're not conscious. return - if (disabilities & EPILEPSY) - if ((prob(1) && prob(1) && paralysis < 1)) - to_chat(src, span_red("You have a seizure!")) - for(var/mob/O in viewers(src, null)) - if(O == src) - continue - O.show_message(span_danger("[src] starts having a seizure!"), 1) - Paralyse(10) - make_jittery(1000) - if (disabilities & COUGHING) - if ((prob(5) && paralysis <= 1)) - drop_item() - emote("cough") - if(dna) - if(disabilities & DETERIORATE && prob(2) && prob(3)) // stacked percents for rarity - // random strange symptoms from organ/limb - automatic_custom_emote(VISIBLE_MESSAGE, "flinches slightly.", check_stat = TRUE) - switch(rand(1,4)) - if(1) - adjustToxLoss(rand(2,8)) - if(2) - adjustCloneLoss(rand(1,2)) - if(3) - add_chemical_effect(CE_PAINKILLER, rand(8,28)) - else - adjustOxyLoss(rand(13,26)) - // external organs need to fall off if damaged enough - var/obj/item/organ/O = pick(organs) - if(O && !(O.organ_tag == BP_GROIN || O.organ_tag == BP_TORSO) && istype(O,/obj/item/organ/external)) - var/obj/item/organ/external/E = O - if(O.damage >= O.min_broken_damage && O.robotic <= ORGAN_ASSISTED && prob(70)) - add_chemical_effect(CE_PAINKILLER, 120) // what limb? Extreme nerve damage. Can't feel a thing + shock - E.droplimb(TRUE, DROPLIMB_ACID) - if(disabilities & GIBBING) - gutdeathpressure += 0.01 - if(gutdeathpressure > 0 && prob(gutdeathpressure)) - emote(pick("whimper","belch","belch","belch","choke","shiver")) - Weaken(gutdeathpressure / 3) - if((gutdeathpressure/3) >= 1 && prob(gutdeathpressure/3)) - gutdeathpressure = 0 // to stop retriggering - spawn(1) - emote(pick("whimper","shiver")) - spawn(3) - emote(pick("whimper","belch","shiver")) - spawn(4) - emote(pick("whimper","shiver")) - spawn(6) - emote(pick("belch")) - gib() - if (disabilities & TOURETTES) - if ((prob(1) && prob(2) && paralysis <= 1)) - Stun(10) - make_jittery(100) - switch(rand(1, 3)) - if(1) - emote("twitch") - if(2 to 3) - say("[prob(50) ? ";" : ""][pick("SHIT", "PISS", "FUCK", "CUNT", "COCKSUCKER", "MOTHERFUCKER", "TITS")]") - if (disabilities & NERVOUS) - if (prob(5) && prob(7)) - stuttering = max(15, stuttering) - if(jitteriness < 50) - make_jittery(65) + if(isbelly(loc)) //Let's not have you seizing, coughing, or falling apart if you're in a belly. + return var/rn = rand(0, 200) if(getBrainLoss() >= 5) diff --git a/code/modules/mob/living/carbon/human/life_vr.dm b/code/modules/mob/living/carbon/human/life_vr.dm index 31ff8b83912..d3eaf3eb2cc 100644 --- a/code/modules/mob/living/carbon/human/life_vr.dm +++ b/code/modules/mob/living/carbon/human/life_vr.dm @@ -6,14 +6,6 @@ else if (nutrition <= MAX_NUTRITION_TO_LOSE && stat != 2 && weight > MIN_MOB_WEIGHT && weight_loss) weight -= species.metabolism*(0.01*weight_loss) // starvation weight loss -/mob/living/carbon/human/proc/process_weaver_silk() - if(!species || !(species.is_weaver)) - return - - if(species.silk_reserve < species.silk_max_reserve && species.silk_production == TRUE && nutrition > 100) - species.silk_reserve = min(species.silk_reserve + 2, species.silk_max_reserve) - adjust_nutrition(-0.4) - //Our call for the NIF to do whatever /mob/living/carbon/human/proc/handle_nif() if(!nif) return diff --git a/code/modules/mob/living/carbon/human/species/species.dm b/code/modules/mob/living/carbon/human/species/species.dm index 2a60d6ea77a..3546079f47a 100644 --- a/code/modules/mob/living/carbon/human/species/species.dm +++ b/code/modules/mob/living/carbon/human/species/species.dm @@ -244,7 +244,6 @@ var/gluttonous // Can eat some mobs. 1 for mice, 2 for monkeys, 3 for people. var/soft_landing = FALSE // Can fall down and land safely on small falls. - var/drippy = FALSE // If we drip or not. Primarily for goo beings. var/photosynthesizing = FALSE // If we get nutrition from light or not. var/shrinks = FALSE // If we shrink when we have no nutrition. Not added but here for downstream's sake. var/grows = FALSE // Same as above but if we grow when >1000 nutrition. @@ -348,12 +347,6 @@ var/bloodsucker = FALSE // Allows safely getting nutrition from blood. var/bloodsucker_controlmode = "always loud" //Allows selecting between bloodsucker control modes. Always Loud corresponds to original implementation. - var/is_weaver = FALSE - var/silk_production = FALSE - var/silk_reserve = 100 - var/silk_max_reserve = 500 - var/silk_color = "#FFFFFF" - var/list/traits = list() //Vars that need to be copied when producing a copy of species. var/list/copy_vars = list("base_species", "icobase", "deform", "tail", "tail_animation", "icobase_tail", "color_mult", "primitive_form", "appearance_flags", "flesh_color", "base_color", "blood_mask", "damage_mask", "damage_overlays", "move_trail", "has_floating_eyes") diff --git a/code/modules/mob/living/carbon/human/species/station/station.dm b/code/modules/mob/living/carbon/human/species/station/station.dm index 5ff3e3b71d1..eac2591dac2 100644 --- a/code/modules/mob/living/carbon/human/species/station/station.dm +++ b/code/modules/mob/living/carbon/human/species/station/station.dm @@ -1547,13 +1547,10 @@ tail = "tail" //Spider tail. icobase_tail = 1 + species_component = /datum/component/weaver + inherent_verbs = list( - /mob/living/carbon/human/proc/check_silk_amount, - /mob/living/carbon/human/proc/toggle_silk_production, - /mob/living/carbon/human/proc/weave_structure, - /mob/living/carbon/human/proc/weave_item, - /mob/living/carbon/human/proc/set_silk_color, - /mob/living/carbon/human/proc/tie_hair) + /mob/living/carbon/human/proc/tie_hair) min_age = 18 max_age = 80 @@ -1585,10 +1582,6 @@ base_color = "#333333" //Blackish-gray blood_color = "#0952EF" //Spiders have blue blood. - is_weaver = TRUE - silk_reserve = 500 - silk_max_reserve = 1000 - climb_mult = 0.75 /datum/species/spider/handle_environment_special(var/mob/living/carbon/human/H) diff --git a/code/modules/mob/living/carbon/human/species/station/station_special_abilities.dm b/code/modules/mob/living/carbon/human/species/station/station_special_abilities.dm index 0fc12ec3e1e..7de1d50c005 100644 --- a/code/modules/mob/living/carbon/human/species/station/station_special_abilities.dm +++ b/code/modules/mob/living/carbon/human/species/station/station_special_abilities.dm @@ -615,151 +615,6 @@ pass_flags ^= PASSTABLE //I dunno what this fancy ^= is but Aronai gave it to me. to_chat(src, "You [pass_flags&PASSTABLE ? "will" : "will NOT"] move over tables/railings/trays!") -/mob/living/carbon/human/proc/check_silk_amount() - set name = "Check Silk Amount" - set category = "Abilities.Weaver" - - if(species.is_weaver) - to_chat(src, "Your silk reserves are at [species.silk_reserve]/[species.silk_max_reserve].") - else - to_chat(src, span_warning("You are not a weaver! How are you doing this? Tell a developer!")) - -/mob/living/carbon/human/proc/toggle_silk_production() - set name = "Toggle Silk Production" - set category = "Abilities.Weaver" - - if(species.is_weaver) - species.silk_production = !(species.silk_production) - to_chat(src, "You are [species.silk_production ? "now" : "no longer"] producing silk.") - else - to_chat(src, span_warning("You are not a weaver! How are you doing this? Tell a developer!")) - -/mob/living/carbon/human/proc/weave_structure() - set name = "Weave Structure" - set category = "Abilities.Weaver" - - if(!(species.is_weaver)) - to_chat(src, span_warning("You are not a weaver! How are you doing this? Tell a developer!")) - return - - var/choice - var/datum/weaver_recipe/structure/desired_result - var/finalized = "No" - - while(finalized == "No" && src.client) - choice = tgui_input_list(src,"What would you like to weave?", "Weave Choice", GLOB.weavable_structures) - desired_result = GLOB.weavable_structures[choice] - if(!desired_result || !istype(desired_result)) - return - - if(choice) - finalized = tgui_alert(src, "Are you sure you want to weave [desired_result.title]? It will cost you [desired_result.cost] silk.","Confirmation",list("Yes","No")) - - if(!desired_result || !istype(desired_result)) - return - - if(desired_result.cost > species.silk_reserve) - to_chat(src, span_warning("You don't have enough silk to weave that!")) - return - - if(stat) - to_chat(src, span_warning("You can't do that in your current state!")) - return - - if(locate(desired_result.result_type) in src.loc) - to_chat(src, span_warning("You can't create another weaversilk [desired_result.title] here!")) - return - - if(!isturf(src.loc)) - to_chat(src, span_warning("You can't weave here!")) - return - - if(do_after(src, desired_result.time, exclusive = TASK_USER_EXCLUSIVE)) - if(desired_result.cost > species.silk_reserve) - to_chat(src, span_warning("You don't have enough silk to weave that!")) - return - - if(locate(desired_result.result_type) in src.loc) - to_chat(src, span_warning("You can't create another weaversilk [desired_result.title] here!")) - return - - if(!isturf(src.loc)) - to_chat(src, span_warning("You can't weave here!")) - return - - species.silk_reserve = max(species.silk_reserve - desired_result.cost, 0) - - //new desired_result.result_type(src.loc) - var/atom/O = new desired_result.result_type(src.loc) - O.color = species.silk_color - - -/mob/living/carbon/human/proc/weave_item() - set name = "Weave Item" - set category = "Abilities.Weaver" - - if(!(species.is_weaver)) - return - - var/choice - var/datum/weaver_recipe/item/desired_result - var/finalized = "No" - - while(finalized == "No" && src.client) - choice = tgui_input_list(src,"What would you like to weave?", "Weave Choice", GLOB.weavable_items) - desired_result = GLOB.weavable_items[choice] - if(!desired_result || !istype(desired_result)) - return - - if(choice) - finalized = tgui_alert(src, "Are you sure you want to weave [desired_result.title]? It will cost you [desired_result.cost] silk.","Confirmation",list("Yes","No")) - - if(!desired_result || !istype(desired_result)) - return - - if(!(species.is_weaver)) - to_chat(src, span_warning("You are not a weaver! How are you doing this? Tell a developer!")) - return - - if(desired_result.cost > species.silk_reserve) - to_chat(src, span_warning("You don't have enough silk to weave that!")) - return - - if(stat) - to_chat(src, span_warning("You can't do that in your current state!")) - return - - if(!isturf(src.loc)) - to_chat(src, span_warning("You can't weave here!")) - return - - if(do_after(src, desired_result.time, exclusive = TASK_USER_EXCLUSIVE)) - if(desired_result.cost > species.silk_reserve) - to_chat(src, span_warning("You don't have enough silk to weave that!")) - return - - if(!isturf(src.loc)) - to_chat(src, span_warning("You can't weave here!")) - return - - species.silk_reserve = max(species.silk_reserve - desired_result.cost, 0) - - //new desired_result.result_type(src.loc) - var/atom/O = new desired_result.result_type(src.loc) - O.color = species.silk_color - -/mob/living/carbon/human/proc/set_silk_color() - set name = "Set Silk Color" - set category = "Abilities.Weaver" - - if(!(species.is_weaver)) - to_chat(src, span_warning("You are not a weaver! How are you doing this? Tell a developer!")) - return - - var/new_silk_color = tgui_color_picker(src, "Pick a color for your woven products:","Silk Color", species.silk_color) - if(new_silk_color) - species.silk_color = new_silk_color - /mob/living/carbon/human/proc/toggle_eye_glow() set name = "Toggle Eye Glowing" set category = "Abilities.General" @@ -768,8 +623,6 @@ update_eyes() to_chat(src, "Your eyes [species.has_glowing_eyes ? "are now" : "are no longer"] glowing.") - - /mob/living/carbon/human/proc/enter_cocoon() set name = "Spin Cocoon" set category = "Abilities.Weaver" diff --git a/code/modules/mob/living/carbon/human/species/station/traits/negative_genes.dm b/code/modules/mob/living/carbon/human/species/station/traits/negative_genes.dm index 247689fa2cc..131d99abeb4 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits/negative_genes.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits/negative_genes.dm @@ -24,9 +24,10 @@ is_genetrait = TRUE hidden = FALSE - disability=EPILEPSY activation_message="You get a headache." primitive_expression_messages=list("shudders and twitches.") + added_component_path = /datum/component/epilepsy_disability + /datum/trait/negative/disability_cough name = "Coughing Fits" @@ -37,8 +38,8 @@ is_genetrait = TRUE hidden = FALSE - disability=COUGHING activation_message="You start coughing." + added_component_path = /datum/component/coughing_disability /datum/trait/negative/disability_clumsy name = "Clumsy" @@ -49,7 +50,6 @@ is_genetrait = TRUE hidden = FALSE - mutation=CLUMSY activation_message="You feel lightheaded." primitive_expression_messages=list("trips.") @@ -62,9 +62,9 @@ is_genetrait = FALSE //VOREStation Note: TRAITGENETICS - Disabled on VS hidden = TRUE //VOREStation Note: TRAITGENETICS - Disabled on VS - disability=TOURETTES activation_message="You twitch." primitive_expression_messages=list("twitches and chitters.") + added_component_path = /datum/component/tourettes_disability /* Replaced by /datum/trait/negative/blindness /datum/trait/negative/disability_blind @@ -165,9 +165,10 @@ is_genetrait = FALSE //VOREStation Note: TRAITGENETICS - Disabled on VS hidden = TRUE //VOREStation Note: TRAITGENETICS - Disabled on VS - disability=DETERIORATE activation_message="You feel sore..." primitive_expression_messages=list("shudders.","gasps.","chokes.") + added_component_path = /datum/component/rotting_disability + /datum/trait/negative/disability_gibbing name = "Gibbingtons" @@ -178,9 +179,10 @@ is_genetrait = TRUE hidden = TRUE - disability=GIBBING activation_message="You feel bloated..." primitive_expression_messages=list("shudders.","gasps.","chokes.") + added_component_path = /datum/component/gibbing_disability + /datum/trait/negative/disability_damagedspine name = "Lumbar Impairment" diff --git a/code/modules/mob/living/carbon/human/species/station/traits/neutral.dm b/code/modules/mob/living/carbon/human/species/station/traits/neutral.dm index 537422f74dc..43fdd2a0a8e 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits/neutral.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits/neutral.dm @@ -1441,10 +1441,11 @@ "tint" = list(TRAIT_PREF_TYPE_COLOR, "Statue color", TRAIT_NO_VAREDIT_TARGET, "#FFFFFF"), "adjective" = list(TRAIT_PREF_TYPE_STRING, "Adjective", TRAIT_NO_VAREDIT_TARGET, "hardens")/*, "pickupable" = list(TRAIT_PREF_TYPE_BOOLEAN, "Can be picked up", TRAIT_NO_VAREDIT_TARGET, FALSE)*/) + added_component_path = /datum/component/gargoyle /datum/trait/neutral/gargoyle/apply(var/datum/species/S,var/mob/living/carbon/human/H, var/list/trait_prefs) ..() - var/datum/component/gargoyle/G = H.LoadComponent(/datum/component/gargoyle) + var/datum/component/gargoyle/G = H.GetComponent(added_component_path) if (trait_prefs) G.tint = trait_prefs["tint"] G.material = lowertext(trait_prefs["material"]) @@ -1479,7 +1480,6 @@ name = "Drippy" desc = "You cannot hold your form together, or produce a constant film of sludge that drips off of your body. Hope the station has a janitor." cost = 0 - var_changes = list("drippy" = 1) // Traitgenes Made into a genetrait is_genetrait = TRUE @@ -1487,6 +1487,7 @@ activation_message="You feel softer..." primitive_expression_messages=list("drips.") + added_component_path = /datum/component/drippy /datum/trait/neutral/mudking name = "Mudking" diff --git a/code/modules/mob/living/carbon/human/species/station/traits/neutral_genes.dm b/code/modules/mob/living/carbon/human/species/station/traits/neutral_genes.dm index 911f9c27c1e..b7444391cf6 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits/neutral_genes.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits/neutral_genes.dm @@ -23,6 +23,6 @@ is_genetrait = TRUE hidden = FALSE - disability=NERVOUS activation_message="You feel nervous." primitive_expression_messages=list("nervously chitters.") + added_component_path = /datum/component/nervousness_disability diff --git a/code/modules/mob/living/carbon/human/species/station/traits/positive.dm b/code/modules/mob/living/carbon/human/species/station/traits/positive.dm index 8854a653fdf..091923f4e6a 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits/positive.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits/positive.dm @@ -190,19 +190,20 @@ name = "Weaver" desc = "You can produce silk and create various articles of clothing and objects." cost = 2 - var_changes = list("is_weaver" = 1) allowed_species = list(SPECIES_HANNER, SPECIES_CUSTOM) //So it only shows up for custom species and hanner custom_only = FALSE - has_preferences = list("silk_production" = list(TRAIT_PREF_TYPE_BOOLEAN, "Silk production on spawn", TRAIT_VAREDIT_TARGET_SPECIES), \ - "silk_color" = list(TRAIT_PREF_TYPE_COLOR, "Silk color", TRAIT_VAREDIT_TARGET_SPECIES)) + has_preferences = list("silk_production" = list(TRAIT_PREF_TYPE_BOOLEAN, "Silk production on spawn", TRAIT_NO_VAREDIT_TARGET), \ + "silk_color" = list(TRAIT_PREF_TYPE_COLOR, "Silk color", TRAIT_NO_VAREDIT_TARGET)) + added_component_path = /datum/component/weaver -/datum/trait/positive/weaver/apply(var/datum/species/S,var/mob/living/carbon/human/H) +/datum/trait/positive/weaver/apply(var/datum/species/S,var/mob/living/carbon/human/H, var/list/trait_prefs) ..() - add_verb(H, /mob/living/carbon/human/proc/check_silk_amount) - add_verb(H, /mob/living/carbon/human/proc/toggle_silk_production) - add_verb(H, /mob/living/carbon/human/proc/weave_structure) - add_verb(H, /mob/living/carbon/human/proc/weave_item) - add_verb(H, /mob/living/carbon/human/proc/set_silk_color) + var/datum/component/weaver/W = H.GetComponent(added_component_path) + if(S.get_bodytype() == SPECIES_VASILISSAN) + W.silk_reserve = 500 + W.silk_max_reserve = 1000 + W.silk_production = trait_prefs["silk_production"] + W.silk_color = lowertext(trait_prefs["silk_color"]) /datum/trait/positive/aquatic name = "Aquatic" diff --git a/code/modules/mob/living/carbon/human/species/station/traits/trait.dm b/code/modules/mob/living/carbon/human/species/station/traits/trait.dm index 6e6d1aa5b6b..319ba9b420c 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits/trait.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits/trait.dm @@ -16,6 +16,7 @@ var/varchange_type = TRAIT_VARCHANGE_ALWAYS_OVERRIDE //Mostly used for non-custom species. var/has_preferences //if set, should be a list of the preferences for this trait in the format: list("identifier/name of var to edit" = list(typeofpref, "text to display in prefs", TRAIT_NO_VAREDIT_TARGET/TRAIT_VAREDIT_TARGET_SPECIES/etc, (optional: default value)), etc) typeofpref should follow the defines in _traits.dm (eg. TRAIT_PREF_TYPE_BOOLEAN) var/special_env = FALSE + var/added_component_path //What component this trait applies, if any. @@ -73,6 +74,8 @@ add_verb(H, /mob/living/carbon/human/proc/trait_tutorial) if(special_env) S.env_traits += src + if(added_component_path) + H.AddComponent(added_component_path) return // Traitgenes Disabling traits, genes can be turned off after all! @@ -102,6 +105,10 @@ H.sdisabilities &= ~sdisability // bitflag if(special_env) S.env_traits -= src + if(added_component_path) + var/datum/component/C = H.GetComponent(added_component_path) + if(C) + qdel(C) return /datum/trait/proc/send_message(var/mob/living/carbon/human/H, var/enabled) diff --git a/code/modules/mob/living/carbon/human/species/station/traits/weaver_objs.dm b/code/modules/mob/living/carbon/human/species/station/traits/weaver_objs.dm index 14ecc5929ae..f3cbffa1272 100644 --- a/code/modules/mob/living/carbon/human/species/station/traits/weaver_objs.dm +++ b/code/modules/mob/living/carbon/human/species/station/traits/weaver_objs.dm @@ -57,10 +57,9 @@ icon_state = pick(possible_icon_states) /obj/effect/weaversilk/wall/CanPass(atom/movable/mover, turf/target) - if(ishuman(mover)) - var/mob/living/carbon/human/H = mover - if(H.species.is_weaver) - return TRUE + var/datum/component/weaver/comp = mover.GetComponent(/datum/component/weaver) + if(comp) + return ..() /obj/structure/bed/double/weaversilk_nest @@ -94,10 +93,9 @@ /obj/effect/weaversilk/trap/Crossed(atom/movable/AM as mob|obj) if(AM.is_incorporeal()) return - if(ishuman(AM)) - var/mob/living/carbon/human/H = AM - if(H.species.is_weaver) - return + var/datum/component/weaver/comp = AM.GetComponent(/datum/component/weaver) + if(comp) + return if(isliving(AM) && trap_active) var/mob/living/L = AM if(L.m_intent == I_RUN) diff --git a/code/modules/mob/living/life.dm b/code/modules/mob/living/life.dm index 6e80f1ea505..406ec072cd4 100644 --- a/code/modules/mob/living/life.dm +++ b/code/modules/mob/living/life.dm @@ -2,6 +2,8 @@ set invisibility = INVISIBILITY_NONE set background = BACKGROUND_ENABLED + SEND_SIGNAL(src, COMSIG_LIVING_LIFE) + ..() if (transforming) @@ -84,8 +86,6 @@ handle_tf_holder() - handle_dripping() - handle_vr_derez() /mob/living/proc/handle_breathing() @@ -203,6 +203,7 @@ return confused /mob/living/proc/handle_disabilities() + SEND_SIGNAL(src, COMSIG_HANDLE_DISABILITIES) //Eyes if(sdisabilities & BLIND || stat) //blindness from disability or unconsciousness doesn't get better on its own SetBlinded(1) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 2ff99635a6f..e6be682838a 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1456,50 +1456,6 @@ if(toggled_sleeping) Sleeping(1) -/mob/living/proc/handle_dripping() - if(prob(95)) - return - if(!isturf(src.loc)) - return - if(ishuman(src)) - var/mob/living/carbon/human/H = src - if(H.species && H.species.drippy) - // drip body color if human - var/obj/effect/decal/cleanable/blood/B - var/decal_type = /obj/effect/decal/cleanable/blood/splatter - var/turf/T = get_turf(src.loc) - - // Are we dripping or splattering? - var/list/drips = list() - // Only a certain number of drips (or one large splatter) can be on a given turf. - for(var/obj/effect/decal/cleanable/blood/drip/drop in T) - drips |= drop.drips - qdel(drop) - if(drips.len < 6) - decal_type = /obj/effect/decal/cleanable/blood/drip - - // Find a blood decal or create a new one. - B = locate(decal_type) in T - if(!B) - B = new decal_type(T) - - var/obj/effect/decal/cleanable/blood/drip/drop = B - if(istype(drop) && drips && drips.len) - drop.add_overlay(drips) - drop.drips |= drips - - // Update appearance. - drop.basecolor = rgb(H.r_skin,H.g_skin,H.b_skin) - drop.update_icon() - drop.name = "drips of something" - drop.desc = "It's thick and gooey. Perhaps it's the chef's cooking?" - drop.dryname = "dried something" - drop.drydesc = "It's dry and crusty. The janitor isn't doing their job." - drop.fluorescent = 0 - drop.invisibility = INVISIBILITY_NONE - //else - // come up with drips for other mobs someday - /mob/living/proc/set_metainfo_favs(var/mob/user, var/reopen = TRUE) if(user != src) return diff --git a/vorestation.dme b/vorestation.dme index de68f4840ea..010f7f18555 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -494,7 +494,6 @@ #include "code\datums\components\_component.dm" #include "code\datums\components\connect_loc_behalf.dm" #include "code\datums\components\connect_mob_behalf.dm" -#include "code\datums\components\gargoyle.dm" #include "code\datums\components\material_container.dm" #include "code\datums\components\orbiter.dm" #include "code\datums\components\overlay_lighting.dm" @@ -508,6 +507,15 @@ #include "code\datums\components\crafting\recipes\primitive.dm" #include "code\datums\components\crafting\recipes\survival.dm" #include "code\datums\components\crafting\recipes\weapons.dm" +#include "code\datums\components\disabilities\coughing.dm" +#include "code\datums\components\disabilities\epilepsy.dm" +#include "code\datums\components\disabilities\gibbing.dm" +#include "code\datums\components\disabilities\nervousness.dm" +#include "code\datums\components\disabilities\rotting.dm" +#include "code\datums\components\disabilities\tourettes.dm" +#include "code\datums\components\traits\drippy.dm" +#include "code\datums\components\traits\gargoyle.dm" +#include "code\datums\components\traits\weaver.dm" #include "code\datums\components\species\shadekin.dm" #include "code\datums\components\species\xenochimera.dm" #include "code\datums\diseases\_disease.dm"