Skip to content

Commit

Permalink
adds TG mutations (pyrokinesis, adrenaline, mending touch)
Browse files Browse the repository at this point in the history
  • Loading branch information
Gboster-0 committed Jan 15, 2025
1 parent 2b7a107 commit e93ffc4
Show file tree
Hide file tree
Showing 12 changed files with 285 additions and 0 deletions.
4 changes: 4 additions & 0 deletions code/datums/mutations/_combined.dm
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
required = "/datum/mutation/human/insulated; /datum/mutation/human/radioactive"
result = /datum/mutation/human/shock

/datum/generecipe/pyrokinesis
required = "/datum/mutation/human/cryokinesis; /datum/mutation/human/fire_breath"
result = /datum/mutation/human/cryokinesis/pyrokinesis

/datum/generecipe/antiglow
required = "/datum/mutation/human/glow; /datum/mutation/human/void"
result = /datum/mutation/human/glow/anti
Expand Down
50 changes: 50 additions & 0 deletions code/datums/mutations/active.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/datum/mutation/human/adrenaline_rush
name = "Adrenaline Rush"
desc = "Allows the host to trigger their body's adrenaline response at will."
quality = POSITIVE
text_gain_indication = span_notice("You feel pumped up!")
// instability = POSITIVE_INSTABILITY_MODERATE // MONKESTATION EDIT OLD
instability = 25 // MONKESTATION EDIT NEW -- AWAITING TG#83439
power_path = /datum/action/cooldown/adrenaline

energy_coeff = 1
synchronizer_coeff = 1
power_coeff = 1

/datum/mutation/human/adrenaline_rush/modify()
. = ..()
var/datum/action/cooldown/adrenaline/to_modify = .
if(!istype(to_modify)) // null or invalid
return

to_modify.adrenaline_amount = 10 * GET_MUTATION_POWER(src)
to_modify.comedown_amount = 7 / GET_MUTATION_SYNCHRONIZER(src)

/datum/action/cooldown/adrenaline
name = "Adrenaline!"
desc = "Energize yourself, pushing your body to its limits!"
button_icon = 'icons/mob/actions/actions_genetic.dmi'
button_icon_state = "adrenaline"

cooldown_time = 2 MINUTES
check_flags = AB_CHECK_CONSCIOUS
/// How many units of each positive reagent injected during adrenaline.
var/adrenaline_amount = 10
/// How many units of each negative reagent injected after comedown.
var/comedown_amount = 7


/datum/action/cooldown/adrenaline/Activate(mob/living/carbon/cast_on)
. = ..()
to_chat(cast_on, span_userdanger("You feel pumped up! It's time to GO!"))
cast_on.reagents.add_reagent(/datum/reagent/drug/pumpup, adrenaline_amount)
cast_on.reagents.add_reagent(/datum/reagent/medicine/synaptizine, adrenaline_amount)
cast_on.reagents.add_reagent(/datum/reagent/determination, adrenaline_amount)
addtimer(CALLBACK(src, PROC_REF(get_tired), cast_on), 25 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
return TRUE

/datum/action/cooldown/adrenaline/proc/get_tired(mob/living/carbon/cast_on)
to_chat(cast_on, span_danger("Your adrenaline rush makes way for a bout of nausea and a deep feeling of exhaustion in your muscles."))
cast_on.reagents.add_reagent(/datum/reagent/peaceborg/tire, comedown_amount)
cast_on.reagents.add_reagent(/datum/reagent/peaceborg/confuse, comedown_amount)
cast_on.set_dizzy_if_lower(10 SECONDS)
17 changes: 17 additions & 0 deletions code/datums/mutations/hot.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/datum/mutation/human/cryokinesis/pyrokinesis
name = "Pyrokinesis"
desc = "Draws positive energy from the surroundings to heat surrounding temperatures at subject's will."
text_gain_indication = span_notice("Your hand feels hot!")
locked = TRUE
power_path = /datum/action/cooldown/spell/pointed/projectile/cryo/pyro

/datum/action/cooldown/spell/pointed/projectile/cryo/pyro
name = "Pyrobeam"
desc = "This power fires a heated bolt at a target."
button_icon_state = "firebeam"
base_icon_state = "firebeam"
cooldown_time = 30 SECONDS

active_msg = "You focus your pyrokinesis!"
deactive_msg = "You cool down."
projectile_type = /obj/projectile/temp/pyro
191 changes: 191 additions & 0 deletions code/datums/mutations/touch.dm
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,194 @@
icon = 'icons/obj/weapons/hand.dmi'
icon_state = "zapper"
inhand_icon_state = "zapper"

/datum/mutation/human/lay_on_hands
name = "Mending Touch"
desc = "The affected can lay their hands on other people to transfer a small amount of their injuries to themselves."
quality = POSITIVE
locked = FALSE
difficulty = 16
text_gain_indication = span_notice("Your hand feels blessed!")
text_lose_indication = span_notice("Your hand feels secular once more.")
power_path = /datum/action/cooldown/spell/touch/lay_on_hands
// instability = POSITIVE_INSTABILITY_MAJOR // MONKESTATION EDIT OLD
instability = 35 // MONKESTATION EDIT NEW -- AWAITING TG#83439
energy_coeff = 1
power_coeff = 1
synchronizer_coeff = 1

/datum/mutation/human/lay_on_hands/modify()
. = ..()
var/datum/action/cooldown/spell/touch/lay_on_hands/to_modify =.

if(!istype(to_modify)) // null or invalid
return

// More healing if powered up.
to_modify.heal_multiplier = GET_MUTATION_POWER(src)
// Less pain if synchronized.
to_modify.pain_multiplier = GET_MUTATION_SYNCHRONIZER(src)

/datum/action/cooldown/spell/touch/lay_on_hands
name = "Mending Touch"
desc = "You can now lay your hands on other people to transfer a small amount of their physical injuries to yourself."
button_icon = 'icons/mob/actions/actions_genetic.dmi'
button_icon_state = "mending_touch"
sound = 'sound/magic/staff_healing.ogg'
cooldown_time = 12 SECONDS
school = SCHOOL_RESTORATION
invocation_type = INVOCATION_NONE
spell_requirements = NONE
antimagic_flags = NONE

hand_path = /obj/item/melee/touch_attack/lay_on_hands
draw_message = span_notice("You ready your hand to transfer injuries to yourself.")
drop_message = span_notice("You lower your hand.")
/// Multiplies the amount healed, without increasing the received damage.
var/heal_multiplier = 1
/// Multiplies the incoming pain from healing.
var/pain_multiplier = 1
/// Icon used for beaming effect
var/beam_icon = "blood"

/datum/action/cooldown/spell/touch/lay_on_hands/cast_on_hand_hit(obj/item/melee/touch_attack/hand, atom/victim, mob/living/carbon/mendicant)

var/mob/living/hurtguy = victim

// Heal more, hurt a bit more.
// If you crunch the numbers it sounds crazy good,
// but I think that's a fair reward for combining the efforts of Genetics, Medbay, and Mining to reach a hidden mechanic.
// if(HAS_TRAIT_FROM(mendicant, TRAIT_HIPPOCRATIC_OATH, HIPPOCRATIC_OATH_TRAIT)) // MONKESTATION EDIT OLD
if(mendicant.has_status_effect(/datum/status_effect/hippocratic_oath)) // MONKESTATION EDIT NEW -- God knows why TRAIT_HIPPOCRATIC_OATH is commented out
heal_multiplier *= 2
pain_multiplier *= 0.5
to_chat(mendicant, span_green("You can feel the magic of the Rod of Aesculapius aiding your efforts!"))
beam_icon = "sendbeam"
var/obj/item/rod_of_asclepius/rod = locate() in mendicant.contents
if(rod)
rod.add_filter("cool_glow", 2, list("type" = "outline", "color" = COLOR_VERY_PALE_LIME_GREEN, "size" = 1.25))
addtimer(CALLBACK(rod, TYPE_PROC_REF(/datum, remove_filter), "cool_glow"), 6 SECONDS)


// If a normal pacifist, heal and hurt more!
else if(HAS_TRAIT(mendicant, TRAIT_PACIFISM))
heal_multiplier *= 1.75
pain_multiplier *= 1.75
to_chat(mendicant, span_green("Your peaceful nature helps you guide all the pain to yourself."))

var/success
if(iscarbon(hurtguy))
success = do_complicated_heal(mendicant, hurtguy, heal_multiplier, pain_multiplier)
else
success = do_simple_heal(mendicant, hurtguy, heal_multiplier, pain_multiplier)

// Both types can be ignited (technically at least), so we can just do this here.
if(hurtguy.has_status_effect(/datum/status_effect/fire_handler/fire_stacks))
mendicant.set_fire_stacks(hurtguy.fire_stacks * pain_multiplier, remove_wet_stacks = TRUE)
if(hurtguy.on_fire)
mendicant.ignite_mob()
hurtguy.extinguish_mob()

// No healies in the end, cancel
if(!success)
return FALSE

mendicant.Beam(hurtguy, icon_state = beam_icon, time = 0.5 SECONDS)
beam_icon = initial(beam_icon)

hurtguy.update_damage_overlays()
mendicant.update_damage_overlays()

hurtguy.visible_message(span_notice("[mendicant] lays hands on [hurtguy]!"))
to_chat(target, span_boldnotice("[mendicant] lays hands on you, healing you!"))
new /obj/effect/temp_visual/heal(get_turf(hurtguy), COLOR_VERY_PALE_LIME_GREEN)
return success

/datum/action/cooldown/spell/touch/lay_on_hands/proc/do_simple_heal(mob/living/carbon/mendicant, mob/living/hurtguy, heal_multiplier, pain_multiplier)
// Did the transfer work?
. = FALSE

// Damage to heal
var/brute_to_heal = min(hurtguy.getBruteLoss(), 35 * heal_multiplier)
// no double dipping
var/burn_to_heal = min(hurtguy.getFireLoss(), (35 - brute_to_heal) * heal_multiplier)

// Get at least organic limb to transfer the damage to
var/list/mendicant_organic_limbs = list()
for(var/obj/item/bodypart/possible_limb in mendicant.bodyparts)
if(IS_ORGANIC_LIMB(possible_limb))
mendicant_organic_limbs += possible_limb
// None? Gtfo
if(isnull(mendicant_organic_limbs))
return .

// Try to use our active hand, otherwise pick at random
var/obj/item/bodypart/mendicant_transfer_limb = mendicant.get_active_hand()
if(!(mendicant_transfer_limb in mendicant_organic_limbs))
mendicant_transfer_limb = pick(mendicant_organic_limbs)
mendicant_transfer_limb.receive_damage(brute_to_heal * pain_multiplier, burn_to_heal * pain_multiplier, forced = TRUE, wound_bonus = CANT_WOUND)

if(brute_to_heal)
hurtguy.adjustBruteLoss(brute_to_heal)
. = TRUE

if(burn_to_heal)
hurtguy.adjustFireLoss(burn_to_heal)
. = TRUE

return .

/datum/action/cooldown/spell/touch/lay_on_hands/proc/do_complicated_heal(mob/living/carbon/mendicant, mob/living/carbon/hurtguy, heal_multiplier, pain_multiplier)

// Did the transfer work?
. = FALSE
// Get the hurtguy's limbs and the mendicant's limbs to attempt a 1-1 transfer.
var/list/hurt_limbs = hurtguy.get_damaged_bodyparts(1, 1, BODYTYPE_ORGANIC) + hurtguy.get_wounded_bodyparts(BODYTYPE_ORGANIC)
var/list/mendicant_organic_limbs = list()
for(var/obj/item/bodypart/possible_limb in mendicant.bodyparts)
if(IS_ORGANIC_LIMB(possible_limb))
mendicant_organic_limbs += possible_limb

// If we have no organic available limbs just give up.
if(!length(mendicant_organic_limbs) || !length(hurt_limbs))
return

// Counter to make sure we don't take too much from separate limbs
var/total_damage_healed = 0
// Transfer damage from one limb to the mendicant's counterpart.
for(var/obj/item/bodypart/affected_limb as anything in hurt_limbs)
var/obj/item/bodypart/mendicant_transfer_limb = mendicant.get_bodypart(affected_limb.body_zone)
// If the compared limb isn't organic, skip it and pick a random one.
if(!(mendicant_transfer_limb in mendicant_organic_limbs))
mendicant_transfer_limb = pick(mendicant_organic_limbs)

// Transfer at most 35 damage by default.
var/brute_damage = min(affected_limb.brute_dam, 35 * heal_multiplier)
// no double dipping
var/burn_damage = min(affected_limb.burn_dam, (35 * heal_multiplier) - brute_damage)
if((brute_damage || burn_damage) && total_damage_healed < (35 * heal_multiplier))
total_damage_healed = brute_damage + burn_damage
. = TRUE
// Heal!
affected_limb.heal_damage(brute_damage * heal_multiplier, burn_damage * heal_multiplier, required_bodytype = BODYTYPE_ORGANIC)
// Hurt!
mendicant_transfer_limb.receive_damage(brute_damage * pain_multiplier, burn_damage * pain_multiplier, forced = TRUE, wound_bonus = CANT_WOUND)

// Force light wounds onto you.
for(var/datum/wound/iter_wound as anything in affected_limb.wounds)
if(iter_wound.severity > WOUND_SEVERITY_MODERATE)
continue
. = TRUE
iter_wound.remove_wound()
iter_wound.apply_wound(mendicant_transfer_limb)


return .

/obj/item/melee/touch_attack/lay_on_hands
name = "mending touch"
desc = "Unlike in your favorite tabletop games, you sadly can't cast this on yourself, so you can't use that as a Scapegoat." // mayus is reference. if you get it youre cool
icon = 'icons/obj/weapons/hand.dmi'
icon_state = "greyscale"
color = COLOR_VERY_PALE_LIME_GREEN
inhand_icon_state = "greyscale"
21 changes: 21 additions & 0 deletions code/modules/projectiles/projectile/special/temperature.dm
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,24 @@
var/turf/open/O = T
O.freeze_turf()
return ..()

/obj/projectile/temp/pyro
name = "hot beam"
icon_state = "firebeam" // sets on fire, diff sprite!
range = 9
temperature = 240

/obj/projectile/temp/pyro/on_hit(atom/target, blocked, pierce_hit)
. = ..()
if(!.)
return
var/mob/living/living_target = target
if(!istype(living_target))
return
living_target.adjust_fire_stacks(2)
living_target.ignite_mob()

/obj/projectile/temp/pyro/on_range()
var/turf/location = get_turf(src)
new /obj/effect/hotspot(location)
location.hotspot_expose(700, 50, 1)
Binary file modified icons/mob/actions/actions_genetic.dmi
Binary file not shown.
Binary file modified icons/mob/actions/actions_spells.dmi
Binary file not shown.
Binary file modified icons/mob/inhands/items/touchspell_lefthand.dmi
Binary file not shown.
Binary file modified icons/mob/inhands/items/touchspell_righthand.dmi
Binary file not shown.
Binary file modified icons/obj/weapons/guns/projectiles.dmi
Binary file not shown.
Binary file modified icons/obj/weapons/hand.dmi
Binary file not shown.
2 changes: 2 additions & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -1605,13 +1605,15 @@
#include "code\datums\mood_events\needs_events.dm"
#include "code\datums\mutations\_combined.dm"
#include "code\datums\mutations\_mutations.dm"
#include "code\datums\mutations\active.dm"
#include "code\datums\mutations\adaptation.dm"
#include "code\datums\mutations\antenna.dm"
#include "code\datums\mutations\autotomy.dm"
#include "code\datums\mutations\body.dm"
#include "code\datums\mutations\chameleon.dm"
#include "code\datums\mutations\cold.dm"
#include "code\datums\mutations\fire_breath.dm"
#include "code\datums\mutations\hot.dm"
#include "code\datums\mutations\hulk.dm"
#include "code\datums\mutations\olfaction.dm"
#include "code\datums\mutations\passive.dm"
Expand Down

0 comments on commit e93ffc4

Please sign in to comment.