Adds some positive mutations (#90393)

## About The Pull Request

- Hypermetabolic Blood
   - You bleed 1.5x more, but regenerate blood 6x faster. 
- For reference: A moderate slash wound is ~2 blood loss per tick, a
crit slash wound is ~4 blood loss per tick, and you regenerate ~0.25
blood per tick.
- For weak bleed wounds, you will net lose less blood per tick with the
mutation than without.
- However, for strong bleed wounds you will net lose more blood per tick
with the mutation.
- Ultimately, you will (obviously) recover much faster once closing the
wound.
   - Affected by synchronizer and power
- Rock Eater
 	- You can eat materials like a golem.
- Rock Absorber
- You can eat materials like a golem, and you will also gain golem buffs
from them.
	- Combination gene from "Rock Eater" and "Stoner" 
- I didn't (deeply) vet if any of these effects would be OP combined
with other genes, but I'm chalking it up to emergent gameplay if I miss
something
- Farsight
	- Gives you an action button which lets you expand your view range
	- Affected by power
 - Inexorable
- Disables soft crit, but entering the threshold for soft crit will
cause ticking brute/toxin damage and force you to whisper.
       - No slimepeople can't cheese this 
    - Also is an innate "painkiller".
    - Affected by synchronizer

## Why It's Good For The Game

Just some random mutation ideas I had, for more genetics shenanigans.
They're all relatively unobtrusive but have some niche potential
(Bleeding more for Blood Cult? Farsight + Thermals? Inexorable +
Martyrdom?)

## Changelog

🆑 Melbert
add: "Hypermetabolic Blood" Mutation
add: "Rock Eater" Mutation
add: "Rock Absorber" Combination Mutation
add: "Farsight" Mutation
add: "Inexorable" Mutation
/🆑
This commit is contained in:
MrMelbert
2025-04-12 14:02:53 +10:00
committed by GitHub
parent f0c6772a4f
commit e99048d37f
10 changed files with 233 additions and 76 deletions
+5
View File
@@ -68,3 +68,8 @@
input_one = /datum/mutation/human/hulk
input_two = /datum/mutation/human/clumsy
result = /datum/mutation/human/hulk/ork
/datum/generecipe/rock_absorber
input_one = /datum/mutation/human/rock_eater
input_two = /datum/mutation/human/stoner
result = /datum/mutation/human/rock_absorber
+1 -1
View File
@@ -248,7 +248,7 @@
new_power.base_background_icon_state = new_power.background_icon_state
new_power.active_background_icon_state = "[new_power.base_background_icon_state]_active"
new_power.overlay_icon_state = "bg_tech_blue_border"
new_power.active_overlay_icon_state = null
new_power.active_overlay_icon_state = "bg_spell_border_active_blue"
new_power.panel = "Genetic"
new_power.Grant(owner)
+127 -57
View File
@@ -198,17 +198,7 @@
instability = NEGATIVE_STABILITY_MAJOR
quality = MINOR_NEGATIVE
text_gain_indication = span_danger("You feel lightheaded.")
/datum/mutation/human/clumsy/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
ADD_TRAIT(owner, TRAIT_CLUMSY, GENETIC_MUTATION)
/datum/mutation/human/clumsy/on_losing(mob/living/carbon/human/owner)
if(..())
return
REMOVE_TRAIT(owner, TRAIT_CLUMSY, GENETIC_MUTATION)
mutation_traits = list(TRAIT_CLUMSY)
//Tourettes causes you to randomly stand in place and shout.
/datum/mutation/human/tourettes
@@ -239,17 +229,7 @@
instability = NEGATIVE_STABILITY_MAJOR
quality = NEGATIVE
text_gain_indication = span_danger("You can't seem to hear anything.")
/datum/mutation/human/deaf/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
ADD_TRAIT(owner, TRAIT_DEAF, GENETIC_MUTATION)
/datum/mutation/human/deaf/on_losing(mob/living/carbon/human/owner)
if(..())
return
REMOVE_TRAIT(owner, TRAIT_DEAF, GENETIC_MUTATION)
mutation_traits = list(TRAIT_DEAF)
//Monified turns you into a monkey.
/datum/mutation/human/race
@@ -344,19 +324,7 @@
text_gain_indication = span_notice("You feel strong.")
instability = POSITIVE_INSTABILITY_MINI
difficulty = 16
/datum/mutation/human/strong/on_acquiring(mob/living/carbon/human/owner)
. = ..()
if(.)
return
ADD_TRAIT(owner, TRAIT_STRENGTH, GENETIC_MUTATION)
/datum/mutation/human/strong/on_losing(mob/living/carbon/human/owner)
. = ..()
if(.)
return
REMOVE_TRAIT(owner, TRAIT_STRENGTH, GENETIC_MUTATION)
mutation_traits = list(TRAIT_STRENGTH)
/datum/mutation/human/stimmed
name = "Stimmed"
@@ -365,18 +333,7 @@
instability = POSITIVE_INSTABILITY_MINI
text_gain_indication = span_notice("You feel stimmed.")
difficulty = 16
/datum/mutation/human/stimmed/on_acquiring(mob/living/carbon/human/owner)
. = ..()
if(.)
return
ADD_TRAIT(owner, TRAIT_STIMMED, GENETIC_MUTATION)
/datum/mutation/human/stimmed/on_losing(mob/living/carbon/human/owner)
. = ..()
if(.)
return
REMOVE_TRAIT(owner, TRAIT_STIMMED, GENETIC_MUTATION)
mutation_traits = list(TRAIT_STIMMED)
/datum/mutation/human/insulated
name = "Insulated"
@@ -386,16 +343,7 @@
text_lose_indication = span_notice("Your fingertips regain feeling.")
difficulty = 16
instability = POSITIVE_INSTABILITY_MODERATE
/datum/mutation/human/insulated/on_acquiring(mob/living/carbon/human/owner)
if(..())
return
ADD_TRAIT(owner, TRAIT_SHOCKIMMUNE, GENETIC_MUTATION)
/datum/mutation/human/insulated/on_losing(mob/living/carbon/human/owner)
if(..())
return
REMOVE_TRAIT(owner, TRAIT_SHOCKIMMUNE, GENETIC_MUTATION)
mutation_traits = list(TRAIT_SHOCKIMMUNE)
/datum/mutation/human/fire
name = "Fiery Sweat"
@@ -627,3 +575,125 @@
if(istype(new_limb, /obj/item/bodypart/head))
return COMPONENT_NO_ATTACH
// You bleed faster but regenerate blood faster
/datum/mutation/human/bloodier
name = "Hypermetabolic Blood"
desc = "The subject's blood is hypermetabolic, causing it to be produced at a much faster rate."
quality = POSITIVE
instability = POSITIVE_INSTABILITY_MINOR
text_gain_indication = span_notice("You can feel your heartbeat pick up.")
text_lose_indication = span_notice("You heartbeat slows back down.")
difficulty = 16
synchronizer_coeff = 1
power_coeff = 1
/// Modifies the bleed rate of the owner
var/bleed_rate = 1.5
/// Modifies the blood regeneration rate of the owner
var/blood_regen_rate = 6
/// Tracks if we've modified the physiology of the owner
VAR_PRIVATE/physiology_modified = FALSE
/datum/mutation/human/bloodier/on_acquiring(mob/living/carbon/human/owner)
. = ..()
if(.)
return
if(!physiology_modified)
owner.physiology.bleed_mod *= bleed_rate
owner.physiology.blood_regen_mod *= blood_regen_rate
physiology_modified = TRUE
/datum/mutation/human/bloodier/on_losing(mob/living/carbon/human/owner)
. = ..()
if(.)
return
if(physiology_modified)
owner.physiology.bleed_mod /= bleed_rate
owner.physiology.blood_regen_mod /= blood_regen_rate
physiology_modified = FALSE // just in case
/datum/mutation/human/bloodier/modify()
if(owner && physiology_modified)
owner.physiology.bleed_mod /= bleed_rate
owner.physiology.blood_regen_mod /= blood_regen_rate
physiology_modified = FALSE
bleed_rate = clamp(initial(bleed_rate) * GET_MUTATION_SYNCHRONIZER(src) * GET_MUTATION_POWER(src), 1, 2)
blood_regen_rate = clamp(initial(blood_regen_rate) * GET_MUTATION_POWER(src), 4, 12)
if(owner && !physiology_modified) // redundant but just in case
owner.physiology.bleed_mod *= bleed_rate
owner.physiology.blood_regen_mod *= blood_regen_rate
physiology_modified = TRUE
return TRUE
// You eat rocks
/datum/mutation/human/rock_eater
name = "Rock Eater"
desc = "The subject's body is able to digest rocks and minerals."
quality = POSITIVE
instability = POSITIVE_INSTABILITY_MINI
text_gain_indication = span_notice("You feel a craving for rocks.")
text_lose_indication = span_notice("You could go for a normal meal.")
difficulty = 12
mutation_traits = list(TRAIT_ROCK_EATER)
conflicts = list(/datum/mutation/human/rock_absorber)
// You eat rock but also get buffs from them
/datum/mutation/human/rock_absorber
name = "Rock Absorber"
desc = "The subject's body is able to digest rocks and minerals, taking on their properties."
quality = POSITIVE
instability = POSITIVE_INSTABILITY_MAJOR
text_gain_indication = span_notice("You feel a supreme craving for rocks.")
text_lose_indication = span_notice("You could go for a normal meal.")
mutation_traits = list(TRAIT_ROCK_EATER, TRAIT_ROCK_METAMORPHIC)
conflicts = list(/datum/mutation/human/rock_eater)
locked = TRUE
// Soft crit is disabed
/datum/mutation/human/inexorable
name = "Inexorable"
desc = "Your body can push on beyond the limits of normal human endurance. \
However, pushing it too far can cause severe damage to your body."
quality = POSITIVE
instability = POSITIVE_INSTABILITY_MODERATE
text_gain_indication = span_notice("You feel inexorable.")
text_lose_indication = span_notice("You suddenly feel more human.")
difficulty = 24
synchronizer_coeff = 1
mutation_traits = list(TRAIT_NOSOFTCRIT, TRAIT_ANALGESIA)
/datum/mutation/human/inexorable/on_acquiring(mob/living/carbon/human/acquirer)
. = ..()
if(.)
return
RegisterSignal(acquirer, COMSIG_LIVING_HEALTH_UPDATE, PROC_REF(check_health))
check_health()
/datum/mutation/human/inexorable/on_losing(mob/living/carbon/human/owner)
. = ..()
if(.)
return
UnregisterSignal(owner, COMSIG_LIVING_HEALTH_UPDATE)
REMOVE_TRAIT(owner, TRAIT_SOFTSPOKEN, REF(src))
/datum/mutation/human/inexorable/proc/check_health(...)
SIGNAL_HANDLER
if(owner.health > owner.crit_threshold || owner.stat != CONSCIOUS)
REMOVE_TRAIT(owner, TRAIT_SOFTSPOKEN, REF(src))
else
ADD_TRAIT(owner, TRAIT_SOFTSPOKEN, REF(src))
/datum/mutation/human/inexorable/on_life(seconds_per_tick, times_fired)
if(owner.health > owner.crit_threshold || owner.stat != CONSCIOUS || HAS_TRAIT(owner, TRAIT_STASIS))
return
// Gives you 30 seconds of being in soft crit... give or take
if(HAS_TRAIT(owner, TRAIT_TOXIMMUNE) || HAS_TRAIT(owner, TRAIT_TOXINLOVER))
owner.adjustBruteLoss(1 * seconds_per_tick * GET_MUTATION_SYNCHRONIZER(src), forced = TRUE)
else
owner.adjustToxLoss(0.5 * seconds_per_tick * GET_MUTATION_SYNCHRONIZER(src), forced = TRUE)
owner.adjustBruteLoss(0.5 * seconds_per_tick * GET_MUTATION_SYNCHRONIZER(src), forced = TRUE)
// Offsets suffocation but not entirely
owner.adjustOxyLoss(-0.5 * seconds_per_tick, forced = TRUE)
+61
View File
@@ -0,0 +1,61 @@
/datum/mutation/human/farsight
name = "Farsight"
desc = "The subject's eyes are able to see further than normal."
quality = POSITIVE
instability = POSITIVE_INSTABILITY_MINOR
text_gain_indication = span_notice("You feel your eyes tingle.")
text_lose_indication = span_notice("Your eyes feel normal.")
difficulty = 16
power_coeff = 1
power_path = /datum/action/cooldown/spell/farsight
/datum/mutation/human/farsight/modify()
. = ..()
var/datum/action/cooldown/spell/farsight/to_modify = .
if(istype(to_modify))
to_modify.set_sight_range(initial(to_modify.sight_range) * (GET_MUTATION_POWER(src) == 1 ? 1 : 3))
/datum/action/cooldown/spell/farsight
name = "Farsight"
desc = "You can see further than normal."
button_icon = 'icons/mob/actions/actions_ecult.dmi'
button_icon_state = "eye"
school = SCHOOL_TRANSMUTATION
cooldown_time = 8 SECONDS
invocation_type = INVOCATION_NONE
spell_requirements = NONE
antimagic_flags = NONE
/// How much to expand the view size by
var/sight_range = 1
/// If we are currently active
VAR_PRIVATE/active = FALSE
/datum/action/cooldown/spell/farsight/vv_edit_var(var_name, var_value)
. = ..()
if(var_name == NAMEOF(src, sight_range))
set_sight_range(sight_range)
/datum/action/cooldown/spell/farsight/proc/set_sight_range(new_value)
if(sight_range == new_value)
return
sight_range = new_value
if(active)
owner?.client?.view_size.setTo(sight_range)
/datum/action/cooldown/spell/farsight/cast(atom/cast_on)
. = ..()
var/mob/living/caster = cast_on
if(active)
caster.client?.view_size.resetToDefault()
active = FALSE
cooldown_time *= 2
else
caster.client?.view_size.setTo(sight_range)
active = TRUE
cooldown_time *= 0.5
build_all_button_icons(UPDATE_BUTTON_STATUS)
/datum/action/cooldown/spell/farsight/is_action_active(atom/movable/screen/movable/action_button/current_button)
return active
@@ -18,6 +18,8 @@
var/alert_icon_state = "sheet-monkey"
/// Tooltip to display when hovering over the alert
var/alert_desc = "Something went wrong and this tooltip is not displaying correctly."
/// If we are not a golem what color does the filter glow?
var/filter_color = LIGHT_COLOR_DEFAULT
/atom/movable/screen/alert/status_effect/golem_status
name = "Metamorphic %SOMETHING%"
@@ -73,14 +75,23 @@
to_chat(owner, span_notice(applied_fluff))
if (!overlay_state_prefix || !iscarbon(owner))
return TRUE
var/mob/living/carbon/golem_owner = owner
for (var/obj/item/bodypart/part in golem_owner.bodyparts)
if (part.limb_id != SPECIES_GOLEM)
continue
var/datum/bodypart_overlay/simple/golem_overlay/overlay = new()
overlay.add_to_bodypart(overlay_state_prefix, part)
active_overlays += overlay
golem_owner.update_body_parts()
if(isgolem(owner))
var/mob/living/carbon/golem_owner = owner
for (var/obj/item/bodypart/part in golem_owner.bodyparts)
// these overlays won't look good on anything but golem limbs
if (part.limb_id != SPECIES_GOLEM)
continue
var/datum/bodypart_overlay/simple/golem_overlay/overlay = new()
overlay.add_to_bodypart(overlay_state_prefix, part)
active_overlays += overlay
golem_owner.update_body_parts()
else
owner.add_filter("[id]_filter", 2, outline_filter("color" = filter_color, "size" = 1.25))
var/the_filter = owner.get_filter("[id]_filter")
animate(the_filter, alpha = 0) // start at 0 alpha
animate(the_filter, alpha = 150, time = 7.5 SECONDS, loop = -1, easing = SINE_EASING) // fade in and out
animate(alpha = 50, time = 7.5 SECONDS, loop = -1, easing = SINE_EASING)
return TRUE
/datum/status_effect/golem/on_creation(mob/living/new_owner)
@@ -93,6 +104,7 @@
/datum/status_effect/golem/on_remove()
to_chat(owner, span_warning("The effect of the [mineral_name] fades."))
QDEL_LIST(active_overlays)
owner.remove_filter("[id]_filter")
return ..()
/datum/status_effect/golem/get_examine_text()
@@ -124,6 +136,7 @@
applied_fluff = "Glowing crystals sprout from your body. You feel energised!"
alert_icon_state = "sheet-uranium"
alert_desc = "Internal radiation is providing all of your nutritional needs."
filter_color = LIGHT_COLOR_GREEN
/datum/status_effect/golem/uranium/on_apply()
. = ..()
@@ -145,6 +158,7 @@
applied_fluff = "Shining plates grace your shoulders. You feel holy!"
alert_icon_state = "sheet-silver"
alert_desc = "Your body repels supernatural influences."
filter_color = LIGHT_COLOR_FAINT_BLUE
/datum/status_effect/golem/silver/on_apply()
. = ..()
@@ -169,6 +183,7 @@
applied_fluff = "Plasma cooling rods sprout from your body. You can take the heat!"
alert_icon_state = "sheet-plasma"
alert_desc = "You are protected from high pressure and can convert heat damage into power."
filter_color = LIGHT_COLOR_PINK
/datum/status_effect/golem/plasma/on_apply()
. = ..()
@@ -220,6 +235,7 @@
applied_fluff = "Plasteel plates seal you tight. You feel insulated!"
alert_icon_state = "sheet-plasteel"
alert_desc = "You are sealed against the cold, and against low pressure environments."
filter_color = LIGHT_COLOR_DEFAULT
/datum/status_effect/golem/plasteel/on_apply()
. = ..()
@@ -239,6 +255,7 @@
applied_fluff = "Shining plates form across your body. You feel reflective!"
alert_icon_state = "sheet-gold_2"
alert_desc = "Your shining body reflects energy weapons."
filter_color = LIGHT_COLOR_DIM_YELLOW
/datum/status_effect/golem/gold/on_apply()
. = ..()
@@ -259,6 +276,7 @@
tick_interval = 0.25 SECONDS
alert_icon_state = "sheet-diamond"
alert_desc = "Light is bending around you, making you hard to see while still and faster while moving."
filter_color = LIGHT_COLOR_ELECTRIC_CYAN
/// Alpha to remove per second while stood still
var/alpha_per_tick = 20
/// Alpha to apply while moving
@@ -276,8 +294,6 @@
var/mob/living/carbon/carbon_owner = owner
for (var/obj/item/bodypart/arm/arm in carbon_owner.bodyparts)
if (arm.limb_id != SPECIES_GOLEM)
continue
set_arm_fluff(arm)
return TRUE
@@ -330,6 +346,7 @@
applied_fluff = "Titanium rings burst from your arms. You feel ready to take on the world!"
alert_icon_state = "sheet-titanium"
alert_desc = "You are more resistant to physical blows, and pack more of a punch yourself."
filter_color = LIGHT_COLOR_HALOGEN
/// Amount to reduce brute damage by
var/brute_modifier = 0.7
/// How much extra damage do we do with our fists?
@@ -347,8 +364,6 @@
RegisterSignal(human_owner, COMSIG_LIVING_UNARMED_ATTACK, PROC_REF(on_punched))
human_owner.physiology.brute_mod *= brute_modifier
for (var/obj/item/bodypart/arm/arm in human_owner.bodyparts)
if (arm.limb_id != SPECIES_GOLEM)
continue
buff_arm(arm)
/// Give mining mobs an extra slap
@@ -397,6 +412,7 @@
applied_fluff = "Bananium veins ooze from your crags. You feel a little funny!"
alert_icon_state = "sheet-bananium"
alert_desc = "You feel kind of funny."
filter_color = LIGHT_COLOR_BRIGHT_YELLOW
/// The slipperiness component which we have applied
var/datum/component/slippery/slipperiness
+1 -1
View File
@@ -23,7 +23,7 @@
if(satiety > 80)
nutrition_ratio *= 1.25
adjust_nutrition(-nutrition_ratio * HUNGER_FACTOR * seconds_per_tick)
blood_volume = min(blood_volume + (BLOOD_REGEN_FACTOR * nutrition_ratio * seconds_per_tick), BLOOD_VOLUME_NORMAL)
blood_volume = min(blood_volume + (BLOOD_REGEN_FACTOR * physiology.blood_regen_mod * nutrition_ratio * seconds_per_tick), BLOOD_VOLUME_NORMAL)
//Bloodloss from wounds
var/temp_bleed = 0
@@ -34,7 +34,11 @@
/// Multiplied aplpied to just knockdowns, stacks with above multiplicatively
var/knockdown_mod = 1
var/bleed_mod = 1 // % bleeding modifier
/// Modifier to amount of blood lost when bleeding (both on life ticks and from flat bleed calls)
var/bleed_mod = 1
/// Modifier to amount blood regenerated per life tick
var/blood_regen_mod = 1
var/datum/armor/armor // internal armor datum
var/hunger_mod = 1 //% of hunger rate taken per tick.
@@ -65,13 +65,13 @@
return HANDLE_BLOOD_HANDLED
if(slime.blood_volume <= 0)
slime.blood_volume += JELLY_REGEN_RATE_EMPTY * seconds_per_tick
slime.blood_volume += JELLY_REGEN_RATE_EMPTY * slime.physiology.blood_regen_mod * seconds_per_tick
slime.adjustBruteLoss(2.5 * seconds_per_tick)
to_chat(slime, span_danger("You feel empty!"))
if(slime.blood_volume < BLOOD_VOLUME_NORMAL)
if(slime.nutrition >= NUTRITION_LEVEL_STARVING)
slime.blood_volume += JELLY_REGEN_RATE * seconds_per_tick
slime.blood_volume += JELLY_REGEN_RATE * slime.physiology.blood_regen_mod * seconds_per_tick
if(slime.blood_volume <= BLOOD_VOLUME_LOSE_NUTRITION) // don't lose nutrition if we are above a certain threshold, otherwise slimes on IV drips will still lose nutrition
slime.adjust_nutrition(-1.25 * seconds_per_tick)
@@ -97,7 +97,7 @@
consumed_limb.drop_limb()
to_chat(H, span_userdanger("Your [consumed_limb] is drawn back into your body, unable to maintain its shape!"))
qdel(consumed_limb)
H.blood_volume += 20
H.blood_volume += 20 * H.physiology.blood_regen_mod
/datum/species/jelly/get_species_description()
return "Jellypeople are a strange and alien species with three eyes, made entirely out of gel."
@@ -1214,7 +1214,7 @@
/datum/reagent/iron/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
. = ..()
if(affected_mob.blood_volume < BLOOD_VOLUME_NORMAL)
affected_mob.blood_volume += 0.25 * seconds_per_tick
affected_mob.blood_volume += BLOOD_REGEN_FACTOR * seconds_per_tick
/datum/reagent/gold
name = "Gold"
+1
View File
@@ -1760,6 +1760,7 @@
#include "code\datums\mutations\body.dm"
#include "code\datums\mutations\chameleon.dm"
#include "code\datums\mutations\cold.dm"
#include "code\datums\mutations\farsight.dm"
#include "code\datums\mutations\fire_breath.dm"
#include "code\datums\mutations\hot.dm"
#include "code\datums\mutations\hulk.dm"