Files
Bubberstation/code/datums/mutations/olfaction.dm
T
carlarctgandGitHub ff836e10be First Genetics Content in 5 Years (Adds new positive mutations!) (#83652)
## About The Pull Request

Sister PR to #83439, that needs to be merged before this.

Adds a plethora of new positive mutations to the game!

Mutations now have a variable that directly adds and removes traits
instead of manually doing so for idk

Tripled cryobeam range.

Made the mushroom hallucinogen's code more readable.

- Adrenaline Rush
Trigger your body's adrenaline response, granting you 10 * P units of
pump-up, synaptizine, and determination. After 25 seconds, you crash,
recieving 7 * S units of tiring and dizzying solution. Can be Energized,
Powered, and Synchronized.
- Mending Touch
Transfer injuries from the target to yourself! Heal 35 * P damage,
recieving up to 35 * S damage in turn. Transfers moderate wounds, fire
stacks, and attempts to parallel limb-to-limb damage. Has bonuses for
pacifist players. Can be Energized, Powered, and Synchronized.
- Elastic Arms
Your arms become floppy and you can interact with things as if you were
adjacent to them from one tile further! Does not work through walls or
dense objects, and you become unable to lift huge items, pull large
corpses, and you get chunky fingers.

Split temperature adaptation into three:
- Cold Adaptation
Gain cold immunity, gain ice slip immunity!
- Heat Adaptation
Gain heat and ash storm immunity 
- Thermal Adaptation
Resist both cold and heat, but no extra fancies. The sprite is green
now!
Pressure Adapt has a purple sprite.

You can mix the cold mutations with Fiery Sweat to make these new ones:

- Cindikinesis
Instead of summoning snow, you can now summon... ash. Wow. Very cool.
- Pyrokinesis
You can fire fire now! Fires beams of heat that, unlike the temperature
gun, actually ignite on hit. Higher instability cost than its sister
mutation.

The changes have been themed primarily around classic superhero
gimmicks. Genetics feels like a natural spawning point for superheroes,
and its mutations show this via the good ol' 'radiation made me fire eye
lasers' hero backstory. Adding more ways to be a superhero is fun.

Also, added two new speech mutations:
- Trichromatic Larynx
Every word you say is now either red, green, or blue!
- Heckacious Larynx (Trichromatic Larynx x Wacky)
You sound, well. Absolutely ridiculous. Spectacularly silly. Profoundly
wacky. Don't give it to the clown.
Unlocked the Elvis mutation as well.

## Why It's Good For The Game

> Adds a plethora of new positive mutations to the game!

Genetics is in desperate need of new content, all it's had for years is
a slow gutting and removal of the few things it does have. Hulk is,
being real, stupid, dumb, stagnated, and overpowered, but it's been
begrudgingly accepted because genetics is quite literally just, nothing
without it. I'm here to add the somethings to genetics and add some more
variety (and no i'm not touching hulk)

> Mutations now have a variable that directly adds and removes traits
instead of manually doing so for every mutation.

Less stupid

> Tripled cryobeam range.

Shit joke mutation is now long-range shit joke mutation!

> Made the mushroom hallucinogen's code more readable.

Slightly OOS because I was going to add color blind mutations but
decided not to creep. This piece o shit code has been hurting my head
for years and now that I've finally understood it I want to make sure
others don't go through that pani.

> - Adrenaline Rush
A quick burst of some mild chemicals at the cost of eventual nausea,
sounds like a fair trade to me! If you're already on the ground, this
isn't going to do anything.
> - Mending Touch
Healing is something that's lacking from the mutations, and this puts a
fun spin on it, making the caster a damage pincushion as they heal and
absorb damage.
> - Elastic Arms
Classic superhero power, very funny, lots of silly and sandbox
potential. Has innate drawbacks because 1. thematic and 2. it's pretty
strong

> Split temperature adaptation into three:
They combine into the same thing it used to be, so don't freak out. This
just adds some separation between the immune types, for things like
themed superheroes.

> - Cold Adaptation
Perhaps mildly concerning, but I think this might be a fun spin on it?
TODO: make hiking boots effect?
> - Heat Adaptation
Nothing to say. It's cool.
> - Thermal Adaptation
Nothing wrong with this mutation so it stays in

> You can mix the cold mutations with Fiery Sweat to make these new
ones:
How can we have frozone and not, uh human torch or something. why are
there no heavy hitter fire superheroes in marvel or dc???
> - Cindikinesis
Can't really summon an equivalent to snow that's actually useful, so
here's this instead. Clown might like it, or maybe the chemist.
> - Pyrokinesis
The ignition effect is fairly weak and mostly a deterrent. I think this
is the most dangerous ranged mutation in the game, which is kinda sad.

> - Trichromatic Larynx
Colors are fun! We have speech mutations that change words but none that
change their color. Though, to be fair, this was mostly added for the
mutation below's combination.
> - Heckacious Larynx (Trichromatic Larynx x Wacky)
I felt that Wacky wasn't nearly wacky enough. It just made your speech
comic sans. That's great and all, but. It's not much? This will be a
truly clownly mutation, the Genetics equivalent of a HONK mech. I made
it a combination mutation specifically to restrain its power level.
> Unlocked the Elvis mutation as well.
Was there a reason to lock this?

## Changelog

🆑
add: Added tons of new mutations to Genetics, alongside some recipes!
add: Thermal Adaptation has been made a combination mutation from the
stronger but narrower Cold and Heat adaptations.
balance: Cryobeams have 9 tile range, and fiery sweat doesn't cause
spread on contact.
image: Added some neat new sprites for the new mutations, and added a
greyscale version of the magic hand sprites.
code: Infinitesmally improved mutation code.
/🆑
2024-06-28 17:52:09 -04:00

147 lines
5.6 KiB
Plaintext

/datum/mutation/human/olfaction
name = "Transcendent Olfaction"
desc = "Your sense of smell is comparable to that of a canine."
quality = POSITIVE
difficulty = 12
text_gain_indication = span_notice("Smells begin to make more sense...")
text_lose_indication = span_notice("Your sense of smell goes back to normal.")
power_path = /datum/action/cooldown/spell/olfaction
instability = POSITIVE_INSTABILITY_MODERATE
synchronizer_coeff = 1
/datum/mutation/human/olfaction/modify()
. = ..()
var/datum/action/cooldown/spell/olfaction/to_modify = .
if(!istype(to_modify)) // null or invalid
return
to_modify.sensitivity = GET_MUTATION_SYNCHRONIZER(src)
/datum/action/cooldown/spell/olfaction
name = "Remember the Scent"
desc = "Get a scent off of the item you're currently holding to track it. \
With an empty hand, you'll track the scent you've remembered."
button_icon_state = "nose"
cooldown_time = 10 SECONDS
spell_requirements = NONE
/// Weakref to the mob we're tracking
var/datum/weakref/tracking_ref
/// Our nose's sensitivity
var/sensitivity = 1
/datum/action/cooldown/spell/olfaction/is_valid_target(atom/cast_on)
if(!isliving(cast_on))
return FALSE
var/mob/living/living_cast_on = cast_on
if(ishuman(living_cast_on) && !living_cast_on.get_bodypart(BODY_ZONE_HEAD))
to_chat(owner, span_warning("You have no nose!"))
return FALSE
if(HAS_TRAIT(living_cast_on, TRAIT_ANOSMIA)) //Anosmia quirk holders can't smell anything
to_chat(owner, span_warning("You can't smell!"))
return FALSE
return TRUE
/datum/action/cooldown/spell/olfaction/cast(mob/living/cast_on)
. = ..()
// Can we sniff? is there miasma in the air?
var/datum/gas_mixture/air = cast_on.loc.return_air()
var/list/cached_gases = air.gases
if(cached_gases[/datum/gas/miasma])
cast_on.adjust_disgust(sensitivity * 45)
to_chat(cast_on, span_warning("With your overly sensitive nose, \
you get a whiff of stench and feel sick! Try moving to a cleaner area!"))
return
var/atom/sniffed = cast_on.get_active_held_item()
if(sniffed)
pick_up_target(cast_on, sniffed)
else
follow_target(cast_on)
/// Attempt to pick up a new target based on the fingerprints on [sniffed].
/datum/action/cooldown/spell/olfaction/proc/pick_up_target(mob/living/caster, atom/sniffed)
var/mob/living/carbon/old_target = tracking_ref?.resolve()
var/list/possibles = list()
var/list/prints = GET_ATOM_FINGERPRINTS(sniffed)
if(prints)
for(var/mob/living/carbon/to_check as anything in GLOB.carbon_list)
if(prints[md5(to_check.dna?.unique_identity)])
possibles |= to_check
// There are no finger prints on the atom, so nothing to track
if(!length(possibles))
to_chat(caster, span_warning("Despite your best efforts, there are no scents to be found on [sniffed]..."))
return
var/mob/living/carbon/new_target = tgui_input_list(caster, "Scent to remember", "Scent Tracking", sort_names(possibles))
if(QDELETED(src) || QDELETED(caster))
return
if(QDELETED(new_target))
// We don't have a new target OR an old target
if(QDELETED(old_target))
to_chat(caster, span_warning("You decide against remembering any scents. \
Instead, you notice your own nose in your peripheral vision. \
This goes on to remind you of that one time you started breathing manually and couldn't stop. \
What an awful day that was."))
tracking_ref = null
// We don't have a new target, but we have an old target to fall back on
else
to_chat(caster, span_notice("You return to tracking [old_target]. The hunt continues."))
on_the_trail(caster)
return
// We have a new target to track
to_chat(caster, span_notice("You pick up the scent of [new_target]. The hunt begins."))
tracking_ref = WEAKREF(new_target)
on_the_trail(caster)
/// Attempt to follow our current tracking target.
/datum/action/cooldown/spell/olfaction/proc/follow_target(mob/living/caster)
var/mob/living/carbon/current_target = tracking_ref?.resolve()
// Either our weakref failed to resolve (our target's gone),
// or we never had a target in the first place
if(QDELETED(current_target))
to_chat(caster, span_warning("You're not holding anything to smell, \
and you haven't smelled anything you can track. You smell your skin instead; it's kinda salty."))
tracking_ref = null
return
on_the_trail(caster)
/// Actually go through and give the user a hint of the direction our target is.
/datum/action/cooldown/spell/olfaction/proc/on_the_trail(mob/living/caster)
var/mob/living/carbon/current_target = tracking_ref?.resolve()
//Using get_turf to deal with those pesky closets that put your x y z to 0
var/turf/current_target_turf = get_turf(current_target)
var/turf/caster_turf = get_turf(caster)
if(!current_target)
to_chat(caster, span_warning("You're not tracking a scent, but the game thought you were. \
Something's gone wrong! Report this as a bug."))
stack_trace("[type] - on_the_trail was called when no tracking target was set.")
tracking_ref = null
return
if(current_target == caster)
to_chat(caster, span_warning("You smell out the trail to yourself. Yep, it's you."))
return
if(caster_turf.z < current_target_turf.z)
to_chat(caster, span_warning("The trail leads... way up above you? Huh. They must be really, really far away."))
return
else if(caster_turf.z > current_target_turf.z)
to_chat(caster, span_warning("The trail leads... way down below you? Huh. They must be really, really far away."))
return
var/direction_text = span_bold("[dir2text(get_dir(caster_turf, current_target_turf))]")
if(direction_text)
to_chat(caster, span_notice("You consider [current_target]'s scent. The trail leads [direction_text]."))