mirror of
https://github.com/Citadel-Station-13/Citadel-Station-13-RP.git
synced 2025-12-10 08:37:04 +00:00
Merge pull request #3681 from FreeStylaLT/chimera_spellification
Xenochimera Update
This commit is contained in:
@@ -218,3 +218,12 @@
|
||||
|
||||
spell.perform(usr)
|
||||
update_charge(1)
|
||||
|
||||
|
||||
|
||||
//Xenochimera, literally just different icons
|
||||
/obj/screen/movable/spell_master/chimera
|
||||
name = "Chimera Abilities"
|
||||
icon_state = "cult_spell_ready"
|
||||
open_state = "genetics_open"
|
||||
closed_state = "genetics_closed"
|
||||
|
||||
@@ -155,19 +155,6 @@
|
||||
return 1
|
||||
|
||||
/mob/living/carbon/brain/handle_regular_hud_updates()
|
||||
if (stat == 2 || (XRAY in src.mutations))
|
||||
sight |= SEE_TURFS
|
||||
sight |= SEE_MOBS
|
||||
sight |= SEE_OBJS
|
||||
see_in_dark = 8
|
||||
see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
else if (stat != 2)
|
||||
sight &= ~SEE_TURFS
|
||||
sight &= ~SEE_MOBS
|
||||
sight &= ~SEE_OBJS
|
||||
see_in_dark = 2
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
|
||||
if (healths)
|
||||
if (stat != 2)
|
||||
switch(health)
|
||||
@@ -187,19 +174,6 @@
|
||||
healths.icon_state = "health6"
|
||||
else
|
||||
healths.icon_state = "health7"
|
||||
|
||||
if (stat == 2 || (XRAY in src.mutations))
|
||||
sight |= SEE_TURFS
|
||||
sight |= SEE_MOBS
|
||||
sight |= SEE_OBJS
|
||||
see_in_dark = 8
|
||||
see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
else if (stat != 2)
|
||||
sight &= ~SEE_TURFS
|
||||
sight &= ~SEE_MOBS
|
||||
sight &= ~SEE_OBJS
|
||||
see_in_dark = 2
|
||||
see_invisible = SEE_INVISIBLE_LIVING
|
||||
if (client)
|
||||
client.screen.Remove(GLOB.global_hud.blurry,GLOB.global_hud.druggy,GLOB.global_hud.vimpaired)
|
||||
|
||||
|
||||
@@ -1390,8 +1390,6 @@
|
||||
|
||||
/mob/living/carbon/human/handle_vision()
|
||||
if(stat == DEAD)
|
||||
sight |= SEE_TURFS|SEE_MOBS|SEE_OBJS|SEE_SELF
|
||||
see_in_dark = 8
|
||||
if(client)
|
||||
if(client.view != world.view) // If mob dies while zoomed in with device, unzoom them.
|
||||
for(var/obj/item/item in contents)
|
||||
@@ -1400,7 +1398,6 @@
|
||||
break
|
||||
|
||||
else //We aren't dead
|
||||
sight &= ~(SEE_TURFS|SEE_MOBS|SEE_OBJS)
|
||||
see_invisible = see_in_dark>2 ? SEE_INVISIBLE_LEVEL_ONE : see_invisible_default
|
||||
|
||||
if(XRAY in mutations)
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
var/has_glowing_eyes = 0 // Whether the eyes are shown above all lighting
|
||||
var/water_movement = 0 // How much faster or slower the species is in water
|
||||
var/snow_movement = 0 // How much faster or slower the species is on snow
|
||||
var/infect_wounds = 0 // Whether the species can infect wounds, only works with claws / bites
|
||||
|
||||
|
||||
var/item_slowdown_mod = 1 // How affected by item slowdown the species is.
|
||||
@@ -419,7 +420,6 @@ GLOBAL_LIST_INIT(species_oxygen_tank_by_gas, list(
|
||||
for(var/spell_to_add in inherent_spells)
|
||||
var/spell/S = new spell_to_add(H)
|
||||
H.add_spell(S)
|
||||
return
|
||||
|
||||
/datum/species/proc/remove_inherent_spells(var/mob/living/carbon/human/H)
|
||||
H.spellremove()
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
tail = "tail" //Scree's tail. Can be disabled in the vore tab by choosing "hide species specific tail sprite"
|
||||
icobase_tail = 1
|
||||
inherent_verbs = list(
|
||||
/mob/living/carbon/human/proc/reconstitute_form,
|
||||
/mob/living/carbon/human/proc/sonar_ping,
|
||||
/mob/living/carbon/human/proc/succubus_drain,
|
||||
/mob/living/carbon/human/proc/succubus_drain_finalize,
|
||||
@@ -53,9 +52,25 @@
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_wings,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears,
|
||||
/mob/living/carbon/human/proc/regenerate,
|
||||
/mob/living/carbon/human/proc/commune) //Xenochimera get all the special verbs since they can't select traits.
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_shape,
|
||||
/mob/living/carbon/human/proc/commune
|
||||
) //Xenochimera get all the special verbs since they can't select traits.
|
||||
|
||||
inherent_spells = list(
|
||||
/spell/targeted/chimera/thermal_sight,
|
||||
/spell/targeted/chimera/voice_mimic,
|
||||
/spell/targeted/chimera/regenerate,
|
||||
/spell/targeted/chimera/hatch,
|
||||
/spell/targeted/chimera/no_breathe
|
||||
)
|
||||
|
||||
var/list/feral_spells = list(
|
||||
/spell/aoe_turf/dissonant_shriek
|
||||
)
|
||||
|
||||
var/list/removable_spells = list()
|
||||
|
||||
var/has_feral_spells = FALSE
|
||||
virus_immune = 1 // They practically ARE one.
|
||||
min_age = 18
|
||||
max_age = 200
|
||||
@@ -102,7 +117,7 @@
|
||||
"Akula","Nevrean","Highlander Zorren",
|
||||
"Flatland Zorren", "Vulpkanin", "Vasilissan",
|
||||
"Rapala", "Neaera", "Stok", "Farwa", "Sobaka",
|
||||
"Wolpin", "Saru", "Sparra")
|
||||
"Wolpin", "Saru", "Sparra", "Vox")
|
||||
|
||||
//primitive_form = "Farwa"
|
||||
|
||||
@@ -123,6 +138,7 @@
|
||||
)
|
||||
|
||||
heal_rate = 0.5
|
||||
infect_wounds = 1
|
||||
flesh_color = "#AFA59E"
|
||||
base_color = "#333333"
|
||||
blood_color = "#14AD8B"
|
||||
@@ -158,6 +174,47 @@
|
||||
H.eye_blurry = max(5,H.eye_blurry)
|
||||
..()
|
||||
|
||||
/datum/species/shapeshifter/xenochimera/add_inherent_spells(var/mob/living/carbon/human/H)
|
||||
var/master_type = /obj/screen/movable/spell_master/chimera
|
||||
var/obj/screen/movable/spell_master/chimera/new_spell_master = new master_type
|
||||
|
||||
if(!H.spell_masters)
|
||||
H.spell_masters = list()
|
||||
|
||||
if(H.client)
|
||||
H.client.screen += new_spell_master
|
||||
new_spell_master.spell_holder = H
|
||||
H.spell_masters.Add(new_spell_master)
|
||||
|
||||
for(var/spell_to_add in inherent_spells)
|
||||
var/spell/S = new spell_to_add(H)
|
||||
H.add_spell(S, "cult", master_type)
|
||||
|
||||
/datum/species/shapeshifter/xenochimera/proc/add_feral_spells(var/mob/living/carbon/human/H)
|
||||
if(!has_feral_spells)
|
||||
var/check = FALSE
|
||||
var/master_type = /obj/screen/movable/spell_master/chimera
|
||||
for(var/spell/S as anything in feral_spells)
|
||||
var/spell/spell_to_add = new S(H)
|
||||
check = H.add_spell(spell_to_add, "cult", master_type)
|
||||
removable_spells += spell_to_add
|
||||
if(check)
|
||||
has_feral_spells = TRUE
|
||||
else
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
/datum/species/shapeshifter/xenochimera/proc/remove_feral_spells(var/mob/living/carbon/human/H)
|
||||
for(var/spell/S as anything in removable_spells)
|
||||
S.remove_self(H)
|
||||
removable_spells.Cut()
|
||||
has_feral_spells = FALSE
|
||||
|
||||
/datum/species/shapeshifter/xenochimera/handle_post_spawn(mob/living/carbon/human/H)
|
||||
..()
|
||||
for(var/spell/S as anything in feral_spells)
|
||||
S = new S(H)
|
||||
|
||||
/datum/species/shapeshifter/xenochimera/proc/handle_feralness(var/mob/living/carbon/human/H)
|
||||
|
||||
@@ -238,6 +295,10 @@
|
||||
//we're feral
|
||||
feral_state = TRUE
|
||||
|
||||
//We check if the current spell list already has feral spells.
|
||||
if(!has_feral_spells)
|
||||
add_feral_spells(H)
|
||||
|
||||
//Shock due to mostly halloss. More feral.
|
||||
if(shock && 2.5*H.halloss >= H.traumatic_shock)
|
||||
danger = TRUE
|
||||
@@ -266,6 +327,8 @@
|
||||
//Did we just finish being feral?
|
||||
if(!feral)
|
||||
feral_state = FALSE
|
||||
if(has_feral_spells)
|
||||
remove_feral_spells(H)
|
||||
to_chat(H,"<span class='info'>Your thoughts start clearing, your feral urges having passed - for the time being, at least.</span>")
|
||||
log_and_message_admins("is no longer feral.", H)
|
||||
update_xenochimera_hud(H, danger, feral_state)
|
||||
@@ -423,7 +486,7 @@
|
||||
/mob/living/carbon/human/proc/resp_biomorph(mob/living/carbon/human/target in view(1))
|
||||
set name = "Respiratory Biomorph"
|
||||
set desc = "Changes the gases we need to breathe."
|
||||
set category = "Abilities"
|
||||
set category = "Chimera"
|
||||
|
||||
var/list/gas_choices = list(
|
||||
"oxygen" = /datum/gas/oxygen,
|
||||
@@ -465,7 +528,7 @@
|
||||
if(target == src)
|
||||
to_chat("<span class = 'Notice'>It is done.</span>")
|
||||
else
|
||||
if(prob(80))
|
||||
if(prob(10))
|
||||
var/datum/disease2/disease/virus2 = new /datum/disease2/disease
|
||||
virus2.makerandom()
|
||||
infect_virus2(target, virus2)
|
||||
@@ -476,7 +539,7 @@
|
||||
/mob/living/carbon/human/proc/biothermic_adapt(mob/living/carbon/human/target in view(1))
|
||||
set name = "Biothermic Adaptation"
|
||||
set desc = "Changes our core body temperature."
|
||||
set category = "Abilities"
|
||||
set category = "Chimera"
|
||||
|
||||
var/list/temperature_options = list(
|
||||
"warm-blooded",
|
||||
@@ -560,7 +623,7 @@
|
||||
if(target == src)
|
||||
to_chat(src, "<span class = 'Notice'>It is done.</span>")
|
||||
else
|
||||
if(prob(80))
|
||||
if(prob(10))
|
||||
var/datum/disease2/disease/virus2 = new /datum/disease2/disease
|
||||
virus2.makerandom()
|
||||
infect_virus2(target, virus2)
|
||||
@@ -570,7 +633,7 @@
|
||||
/mob/living/carbon/human/proc/atmos_biomorph(mob/living/carbon/human/target in view(1))
|
||||
set name = "Atmospheric Biomorph"
|
||||
set desc = "Changes our sensitivity to atmospheric pressure."
|
||||
set category = "Abilities"
|
||||
set category = "Chimera"
|
||||
|
||||
|
||||
var/list/pressure_options = list(
|
||||
@@ -609,7 +672,7 @@
|
||||
if(target == src)
|
||||
to_chat(src, "<span class = 'notice'>It is done.</span>")
|
||||
else
|
||||
if(prob(80))
|
||||
if(prob(10))
|
||||
var/datum/disease2/disease/virus2 = new /datum/disease2/disease
|
||||
virus2.makerandom()
|
||||
infect_virus2(target, virus2)
|
||||
@@ -620,7 +683,7 @@
|
||||
/mob/living/carbon/human/proc/vocal_biomorph()
|
||||
set name = "Vocalization Biomorph"
|
||||
set desc = "Changes our speech pattern."
|
||||
set category = "Abilities"
|
||||
set category = "Chimera"
|
||||
|
||||
var/vocal_biomorph = input(src, "How should we adjust our speech?") as null|anything in list("common", "unathi", "tajaran")
|
||||
if(!vocal_biomorph)
|
||||
|
||||
@@ -10,6 +10,7 @@ var/global/list/sparring_attack_cache = list()
|
||||
var/shredding = 0 // Calls the old attack_alien() behavior on objects/mobs when on harm intent.
|
||||
var/sharp = 0
|
||||
var/edge = 0
|
||||
var/infected_wound_probability = 10
|
||||
|
||||
var/damage_type = BRUTE
|
||||
var/sparring_variant_type = /datum/unarmed_attack/light_strike
|
||||
@@ -89,6 +90,30 @@ var/global/list/sparring_attack_cache = list()
|
||||
target.visible_message("<span class='danger'>[target] has been weakened!</span>")
|
||||
target.apply_effect(3, WEAKEN, armour)
|
||||
|
||||
if(user.species.infect_wounds) //Creates a pre-damaged, pre-infected wound. As nasty as this code.
|
||||
if(prob(infected_wound_probability))
|
||||
var/obj/item/organ/external/affecting = target.get_organ(zone)
|
||||
var/attack_message
|
||||
var/datum/wound/W
|
||||
if(edge)
|
||||
W = new /datum/wound/cut/small(5)
|
||||
W.force_infect()
|
||||
attack_message = "leaves behind infested residue in [target]!"
|
||||
else
|
||||
W = new /datum/wound/bruise(5)
|
||||
W.force_infect()
|
||||
attack_message = "scratches and pummels, their infested fluids mixing with [target]!"
|
||||
if(LAZYLEN(affecting.wounds))
|
||||
for(var/datum/wound/other in affecting.wounds)
|
||||
if(other.can_merge(W))
|
||||
other.merge_wound(W)
|
||||
W = null
|
||||
break
|
||||
if(W)
|
||||
affecting.wounds += W
|
||||
|
||||
target.visible_message("<span class='danger'><i>[user] [attack_message]</i></span>")
|
||||
|
||||
/datum/unarmed_attack/proc/show_attack(var/mob/living/carbon/human/user, var/mob/living/carbon/human/target, var/zone, var/attack_damage)
|
||||
var/obj/item/organ/external/affecting = target.get_organ(zone)
|
||||
user.visible_message("<span class='warning'>[user] [pick(attack_verb)] [target] in the [affecting.name]!</span>")
|
||||
|
||||
@@ -19,11 +19,11 @@
|
||||
var/min_damage = 0
|
||||
|
||||
// is the wound bandaged?
|
||||
var/bandaged = 0
|
||||
var/bandaged = FALSE
|
||||
// Similar to bandaged, but works differently
|
||||
var/clamped = 0
|
||||
var/clamped = FALSE
|
||||
// is the wound salved?
|
||||
var/salved = 0
|
||||
var/salved = FALSE
|
||||
// is the wound disinfected?
|
||||
var/disinfected = 0
|
||||
var/created = 0
|
||||
@@ -37,7 +37,7 @@
|
||||
// stages such as "cut", "deep cut", etc.
|
||||
var/list/stages
|
||||
// internal wounds can only be fixed through surgery
|
||||
var/internal = 0
|
||||
var/internal = FALSE
|
||||
// maximum stage at which bleeding should still happen. Beyond this stage bleeding is prevented.
|
||||
var/max_bleeding_stage = 0
|
||||
// one of CUT, PIERCE, BRUISE, BURN
|
||||
@@ -46,7 +46,8 @@
|
||||
// the maximum amount of damage that this wound can have and still autoheal
|
||||
var/autoheal_cutoff = 10
|
||||
|
||||
|
||||
// whether this wound starts infected regardless of damage level
|
||||
var/forced_infected = FALSE
|
||||
|
||||
|
||||
// helper lists
|
||||
@@ -119,19 +120,29 @@
|
||||
src.germ_level = max(src.germ_level, other.germ_level)
|
||||
src.created = max(src.created, other.created) //take the newer created time
|
||||
|
||||
//forces an infection, and bleeding regardless of damage or stage
|
||||
proc/force_infect()
|
||||
bleed_threshold = 4 //Will always start bleeding, making the infection worse if untreated
|
||||
forced_infected = TRUE
|
||||
germ_level = INFECTION_LEVEL_ONE + 1
|
||||
// checks if wound is considered open for external infections
|
||||
// untreated cuts (and bleeding bruises) and burns are possibly infectable, chance higher if wound is bigger
|
||||
proc/infection_check()
|
||||
if (damage < 10) //small cuts, tiny bruises, and moderate burns shouldn't be infectable.
|
||||
return 0
|
||||
if (is_treated() && damage < 25) //anything less than a flesh wound (or equivalent) isn't infectable if treated properly
|
||||
return 0
|
||||
if (disinfected)
|
||||
if(germ_level > INFECTION_LEVEL_ONE)
|
||||
germ_level = 0 //reset this, just in case
|
||||
return 0
|
||||
|
||||
forced_infected = FALSE
|
||||
return FALSE
|
||||
if (damage < 10 && !forced_infected) //small cuts, tiny bruises, and moderate burns shouldn't be infectable.
|
||||
return FALSE
|
||||
if (is_treated() && damage < 25) //anything less than a flesh wound (or equivalent) isn't infectable if treated properly
|
||||
return FALSE
|
||||
if (damage_type == BRUISE && !bleeding()) //bruises only infectable if bleeding
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
|
||||
if(forced_infected) //This wound is forced to be infected, circumventing damage requirements, check after making sure it's not bleeding and isn't disinfected
|
||||
return TRUE
|
||||
|
||||
var/dam_coef = round(damage/10)
|
||||
switch (damage_type)
|
||||
@@ -142,7 +153,7 @@
|
||||
if (CUT)
|
||||
return prob(dam_coef*20)
|
||||
|
||||
return 0
|
||||
return FALSE
|
||||
|
||||
proc/bandage()
|
||||
bandaged = 1
|
||||
@@ -295,7 +306,7 @@
|
||||
max_bleeding_stage = 3
|
||||
stages = list("big gaping wound" = 60, "healing gaping wound" = 40, "large blood soaked clot" = 25, "large angry scar" = 10, "large straight scar" = 0)
|
||||
|
||||
datum/wound/cut/massive
|
||||
/datum/wound/cut/massive
|
||||
max_bleeding_stage = 3
|
||||
stages = list("massive wound" = 70, "massive healing wound" = 50, "massive blood soaked clot" = 25, "massive angry scar" = 10, "massive jagged scar" = 0)
|
||||
|
||||
@@ -365,7 +376,7 @@ datum/wound/puncture/massive
|
||||
|
||||
/** INTERNAL BLEEDING **/
|
||||
/datum/wound/internal_bleeding
|
||||
internal = 1
|
||||
internal = TRUE
|
||||
stages = list("severed artery" = 30, "cut artery" = 20, "damaged artery" = 10, "bruised artery" = 5)
|
||||
autoheal_cutoff = 5
|
||||
max_bleeding_stage = 4 //all stages bleed. It's called internal bleeding after all.
|
||||
@@ -399,4 +410,4 @@ datum/wound/puncture/massive
|
||||
..(damage_amt)
|
||||
|
||||
/datum/wound/lost_limb/can_merge(var/datum/wound/other)
|
||||
return 0 //cannot be merged
|
||||
return FALSE //cannot be merged
|
||||
|
||||
@@ -340,3 +340,6 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
|
||||
if(!user || (!(spell_flags & (STATALLOWED|GHOSTCAST)) && user.stat != originalstat) || !(user.loc == Location))
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/spell/proc/remove_self(mob/user = usr)
|
||||
user.remove_spell(src)
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
/mob/proc/add_spell(var/spell/spell_to_add, var/spell_base = "wiz_spell_ready", var/master_type = /obj/screen/movable/spell_master)
|
||||
if(!spell_masters)
|
||||
spell_masters = list()
|
||||
|
||||
if(spell_masters.len)
|
||||
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
|
||||
if(spell_master.type == master_type)
|
||||
|
||||
383
code/modules/spells/targeted/chimera_spells.dm
Normal file
383
code/modules/spells/targeted/chimera_spells.dm
Normal file
@@ -0,0 +1,383 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// These are spells meant to be used by the Xenochimera species //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/spell/targeted/chimera
|
||||
name = "A Chimera Spell"
|
||||
desc = "You shouldn't be seeing this."
|
||||
|
||||
charge_max = 50
|
||||
spell_flags = INCLUDEUSER
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 1
|
||||
max_targets = 1
|
||||
cooldown_min = 0
|
||||
duration = 0
|
||||
still_recharging_msg = "<span class='notice'>We are not yet ready to use this.</span>"
|
||||
hud_state = "wiz_jaunt"
|
||||
override_base = "cult"
|
||||
var/nutrition_cost_minimum = 50
|
||||
var/nutrition_cost_proportional = 20 //percentage of nutriment it should cost if it's higher than the minimum
|
||||
|
||||
/spell/targeted/chimera/cast(list/targets, mob/user)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
var/nut = (H.nutrition * nutrition_cost_proportional) / 100
|
||||
var/final_cost
|
||||
if(nut > nutrition_cost_minimum)
|
||||
final_cost = nut
|
||||
else
|
||||
final_cost = nutrition_cost_minimum
|
||||
|
||||
if((H.nutrition - final_cost) >= 0)
|
||||
H.nutrition -= final_cost
|
||||
else
|
||||
H.nutrition = 0 //We're already super starved, and feral, so cast it for free, you're likely using it to get food at this point.
|
||||
else
|
||||
return
|
||||
|
||||
////////////////////////
|
||||
//Timed thermal sight.//
|
||||
////////////////////////
|
||||
/spell/targeted/chimera/thermal_sight
|
||||
name = "Thermal Sight"
|
||||
desc = "We focus ourselves, able to sense prey and threat through walls or mist. We cannot sustain this for long."
|
||||
|
||||
spell_flags = INCLUDEUSER
|
||||
hud_state = "ling_augmented_eyesight"
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
charge_max = 35 SECONDS
|
||||
duration = 30 SECONDS
|
||||
nutrition_cost_minimum = 15 //The hungrier you get the less it will cost
|
||||
nutrition_cost_proportional = 10
|
||||
var/active = FALSE
|
||||
|
||||
|
||||
/spell/targeted/chimera/thermal_sight/cast(list/targets, mob/user = usr)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
toggle_sight(user)
|
||||
addtimer(CALLBACK(src, .proc/toggle_sight,H), duration, TIMER_UNIQUE)
|
||||
..()
|
||||
|
||||
/spell/targeted/chimera/thermal_sight/proc/toggle_sight(mob/living/carbon/human/H)
|
||||
if(!active)
|
||||
to_chat(H, "<span class='notice'>We focus outward, gaining a keen sense of all those around us.</span>")
|
||||
H.species.vision_flags |= SEE_MOBS
|
||||
H.species.has_glowing_eyes = TRUE
|
||||
active = TRUE
|
||||
else
|
||||
to_chat(H, "<span class='notice'>Our senses dull.</span>")
|
||||
H.species.vision_flags &= ~SEE_MOBS
|
||||
H.species.has_glowing_eyes = FALSE
|
||||
active = FALSE
|
||||
H.update_eyes()
|
||||
|
||||
///////////////
|
||||
//Voice Mimic//
|
||||
///////////////
|
||||
//It's a toggle, but doesn't cost nutriment to be toggled off
|
||||
/spell/targeted/chimera/voice_mimic
|
||||
name = "Voice Mimicry"
|
||||
desc = "We shape our throat and tongue to imitate a person, or a sound. This ability is a toggle."
|
||||
|
||||
spell_flags = INCLUDEUSER
|
||||
hud_state = "ling_mimic_voice"
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
charge_max = 5 SECONDS
|
||||
duration = 0
|
||||
nutrition_cost_minimum = 25
|
||||
nutrition_cost_proportional = 5
|
||||
var/active = FALSE
|
||||
|
||||
/spell/targeted/chimera/voice_mimic/cast(list/targets, mob/user = usr)
|
||||
if(user.stat != DEAD)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(!active)
|
||||
var/mimic_voice = sanitize(input(usr, "Enter a name to mimic. Leave blank to cancel.", "Mimic Voice", null), MAX_NAME_LEN)
|
||||
if(!mimic_voice)
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>We shift and morph our tongues, ready to reverberate as: <b>[mimic_voice]</b>.</span>")
|
||||
H.SetSpecialVoice(mimic_voice)
|
||||
active = TRUE
|
||||
..() //Processes nutriment cost
|
||||
else
|
||||
to_chat(user, "<span class='notice'>We return our voice to our normal identity.</span>")
|
||||
H.UnsetSpecialVoice()
|
||||
active = FALSE
|
||||
else
|
||||
return
|
||||
|
||||
|
||||
////////////////
|
||||
//Regeneration//
|
||||
////////////////
|
||||
//Huge cooldown, huge cost, but will actually heal most of your issues.
|
||||
|
||||
/spell/targeted/chimera/regenerate
|
||||
name = "Regeneration"
|
||||
desc = "We shed our skin, purging it of damage, regrowing limbs."
|
||||
|
||||
spell_flags = INCLUDEUSER
|
||||
hud_state = "ling_fleshmend"
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
charge_max = 10 MINUTES
|
||||
duration = 0
|
||||
nutrition_cost_minimum = 500
|
||||
nutrition_cost_proportional = 75
|
||||
var/healing_amount = 60
|
||||
var/delay = 1 MINUTE
|
||||
|
||||
|
||||
/spell/targeted/chimera/regenerate/cast_check(skipcharge = 0,mob/user = usr)
|
||||
if(..())
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if((nutrition_cost_minimum > H.nutrition) || nutrition_cost_minimum > ((H.nutrition * nutrition_cost_proportional) / 100) )
|
||||
to_chat(H,"<span class = 'notice'>We don't have enough nutriment. This ability is costly...</span>")
|
||||
return FALSE
|
||||
else return TRUE
|
||||
|
||||
/spell/targeted/chimera/regenerate/cast(list/targets, mob/user = usr)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(do_after(H, delay, null, FALSE, TRUE, INCAPACITATION_DISABLED))
|
||||
H.restore_blood()
|
||||
H.species.create_organs(H)
|
||||
H.restore_all_organs()
|
||||
H.adjustBruteLoss(-healing_amount)
|
||||
H.adjustFireLoss(-healing_amount)
|
||||
H.adjustOxyLoss(-healing_amount)
|
||||
H.adjustCloneLoss(-healing_amount)
|
||||
H.adjustBrainLoss(-healing_amount)
|
||||
H.blinded = FALSE
|
||||
H.SetBlinded(FALSE)
|
||||
H.eye_blurry = FALSE
|
||||
H.ear_deaf = FALSE
|
||||
H.ear_damage = FALSE
|
||||
|
||||
H.regenerate_icons()
|
||||
|
||||
playsound(H, 'sound/effects/blobattack.ogg', 30, 1)
|
||||
var/T = get_turf(src)
|
||||
new /obj/effect/gibspawner/human(T, H.dna,H.dna.blood_color,H.dna.blood_color)
|
||||
H.visible_message("<span class='warning'>With a sickening squish, [src] reforms their whole body, casting their old parts on the floor!</span>",
|
||||
"<span class='notice'>We reform our body. We are whole once more.</span>",
|
||||
"<span class='italics'>You hear organic matter ripping and tearing!</span>")
|
||||
..()
|
||||
else
|
||||
to_chat(user,"<span class = 'warning'>We were interrupted!</span>")
|
||||
charge_counter = 9.8 MINUTES
|
||||
|
||||
|
||||
////////////////
|
||||
//Revive spell//
|
||||
////////////////
|
||||
//Will incapacitate you for 10 minutes, and then you can revive.
|
||||
/spell/targeted/chimera/hatch
|
||||
name = "Hatch Stasis"
|
||||
desc = "We attempt to grow an entirely new body from scratch, or death."
|
||||
|
||||
spell_flags = INCLUDEUSER | GHOSTCAST
|
||||
hud_state = "ling_regenerative_stasis"
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
charge_max = 60 MINUTES
|
||||
duration = 0 SECONDS
|
||||
nutrition_cost_minimum = 1
|
||||
nutrition_cost_proportional = 1
|
||||
|
||||
|
||||
/spell/targeted/chimera/hatch/cast_check(skipcharge, mob/user = usr)
|
||||
if(..())
|
||||
if(!ishuman(user))
|
||||
to_chat(user,"Non-humans can't use this!")
|
||||
return FALSE
|
||||
|
||||
var/confirmation = alert("You will begin a lengthy process of around ten minutes you cannot cancel- Is this what you want?","Hatching Prompt","Yes", "No")
|
||||
if(confirmation != "Yes")
|
||||
to_chat(user, "<span class = 'notice'> Hatching cancelled. </span>")
|
||||
return FALSE
|
||||
else return TRUE
|
||||
|
||||
/spell/targeted/chimera/hatch/cast(list/targets, mob/user = usr)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.stat == DEAD)
|
||||
H.visible_message("<span class = 'warning'> [H] lays eerily still. Something about them seems off, even when dead.</span>","<span class = 'notice'>We begin to gather up whatever is left to begin regrowth.</span>")
|
||||
else
|
||||
H.visible_message("<span class = 'warning'> [H] suddenly collapses, seizing up and going eerily still. </span>", "<span class = 'notice'>We begin the regrowth process to start anew.</span>")
|
||||
H.SetParalysis(8000) //admin style self-stun
|
||||
|
||||
//These are only messages to give the player and everyone around them an idea of which stage they're at
|
||||
//visible_message doesn't seem to relay selfmessages if you're paralysed, so we use to_chat
|
||||
addtimer(CALLBACK(H, /atom/.proc/visible_message,"<span class = 'warning'> [H]'s skin begins to ripple and move, as if something was crawling underneath.</span>"), 4 MINUTES)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat,H,"<span class = 'notice'>We begin to recycle the dead tissue.</span>"),4 MINUTES)
|
||||
|
||||
addtimer(CALLBACK(H, /atom/.proc/visible_message,"<span class = 'warning'> <i>[H]'s body begins to lose its shape, skin sloughing off and melting, losing form and composure.</i></span>","<span class = 'notice'>There is little left. We will soon be ready.</span>"), 8 SECONDS)
|
||||
addtimer(CALLBACK(GLOBAL_PROC, .proc/to_chat,H,"<span class = 'notice'>There is little left. We will soon be ready.</span>"), 8 MINUTES)
|
||||
|
||||
addtimer(CALLBACK(src, .proc/add_pop,H,), 10 MINUTES)
|
||||
|
||||
/spell/targeted/chimera/hatch/proc/add_pop(mob/user = usr)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.visible_message("<span class = 'warning'> <b>[H] looks ready to burst!</b></span>")
|
||||
to_chat(H,"<span class = 'notice'><b>We are ready.</b></span>")
|
||||
var/spell/targeted/chimera/hatch_pop/S = new /spell/targeted/chimera/hatch_pop(H)
|
||||
var/master_type = /obj/screen/movable/spell_master/chimera
|
||||
H.add_spell(S, "cult", master_type)
|
||||
|
||||
|
||||
///////////////////////
|
||||
//Actual Revive Spell//
|
||||
///////////////////////
|
||||
//Not to be used normally. Given by the 'hatch' spell
|
||||
/spell/targeted/chimera/hatch_pop
|
||||
name = "Emerge"
|
||||
desc = "We emerge in our new form."
|
||||
|
||||
spell_flags = INCLUDEUSER | GHOSTCAST
|
||||
hud_state = "ling_revive"
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
charge_max = 10 SECONDS //It gets removed after_cast anyway
|
||||
duration = 0
|
||||
nutrition_cost_minimum = 1
|
||||
nutrition_cost_proportional = 1
|
||||
|
||||
/spell/targeted/chimera/hatch_pop/cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/H = user
|
||||
|
||||
var/braindamage = (H.brainloss * 0.6) //Can only heal half brain damage.
|
||||
|
||||
H.revive()
|
||||
LAZYREMOVE(H.mutations, HUSK)
|
||||
H.nutrition = 50 //Hungy, also guarantees ferality without any other tweaking
|
||||
H.setBrainLoss(braindamage)
|
||||
|
||||
//Drop everything
|
||||
for(var/obj/item/W in H)
|
||||
H.drop_from_inventory(W)
|
||||
H.visible_message("<span class = 'warning'>[H] emerges from a cloud of viscera!</b>")
|
||||
H.SetParalysis(0)
|
||||
//Unfreeze some things
|
||||
H.does_not_breathe = FALSE
|
||||
H.update_canmove()
|
||||
H.weakened = 2
|
||||
//Visual effects
|
||||
var/T = get_turf(H)
|
||||
new /obj/effect/gibspawner/human(T, H.dna,H.dna.blood_color,H.dna.blood_color)
|
||||
playsound(T, 'sound/effects/splat.ogg')
|
||||
|
||||
/spell/targeted/chimera/hatch_pop/after_cast(list/targets, mob/user = usr)
|
||||
var/mob/living/carbon/human/H = user
|
||||
H.remove_spell(src)
|
||||
qdel(src)
|
||||
|
||||
|
||||
////////////////////
|
||||
//Timed No Breathe//
|
||||
////////////////////
|
||||
//Same principle as thermal sight. Could be status effects?
|
||||
/spell/targeted/chimera/no_breathe
|
||||
name = "Stop Respiration"
|
||||
desc = "We change our form to no longer need to breathe at all. We cannot sustain this for long."
|
||||
|
||||
spell_flags = INCLUDEUSER
|
||||
hud_state = "ling_toggle_breath"
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
charge_max = 125 SECONDS //5 seconds inbetween uses
|
||||
duration = 120 SECONDS
|
||||
nutrition_cost_minimum = 100
|
||||
nutrition_cost_proportional = 20 //Costly.
|
||||
var/active = FALSE
|
||||
|
||||
|
||||
/spell/targeted/chimera/no_breathe/cast(list/targets, mob/user = usr)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
toggle_breath(user)
|
||||
addtimer(CALLBACK(src, .proc/toggle_breath,H), duration, TIMER_UNIQUE)
|
||||
..()
|
||||
|
||||
/spell/targeted/chimera/no_breathe/proc/toggle_breath(mob/living/carbon/human/H)
|
||||
if(!active)
|
||||
to_chat(H, "<span class='notice'>We preserve the air we have, no longer needing to breathe.</span>")
|
||||
H.does_not_breathe = TRUE
|
||||
active = TRUE
|
||||
else
|
||||
to_chat(H, "<span class='notice'>Our reserves are drained.</span>")
|
||||
H.does_not_breathe = FALSE
|
||||
active = FALSE
|
||||
|
||||
|
||||
///////////////
|
||||
//EMP Shriek //
|
||||
///////////////
|
||||
//Only to be used during feral state, has a very long cooldown. Mostly to get away.
|
||||
|
||||
/spell/aoe_turf/dissonant_shriek
|
||||
name = "Dissonant Shriek"
|
||||
desc = "We shift our vocal cords to release a high-frequency sound that overloads nearby electronics."
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
hud_state = "ling_resonant_shriek"
|
||||
spell_flags = INCLUDEUSER
|
||||
range = 8
|
||||
still_recharging_msg = "<span class='notice'>We have shrieked already! It tires us! Get away!</span>"
|
||||
//Slightly more potent than an EMP grenade
|
||||
var/emp_heavy = 3
|
||||
var/emp_med = 6
|
||||
var/emp_light = 9
|
||||
var/emp_long = 12
|
||||
smoke_spread = 1
|
||||
smoke_amt = 1
|
||||
override_base = "cult"
|
||||
charge_max = 5 MINUTES //Let's not be able to spam this
|
||||
|
||||
|
||||
/spell/aoe_turf/dissonant_shriek/before_cast(list/targets, mob/user = usr)
|
||||
if(ishuman(user))
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.is_muzzled())
|
||||
to_chat(src, "<span class='danger'>Mmmf mrrfff!</span>")
|
||||
return
|
||||
|
||||
if(H.silent)
|
||||
to_chat(src, "<span class='danger'>You can't speak!</span>")
|
||||
return
|
||||
|
||||
if(!isturf(H.loc))
|
||||
to_chat(src, "<span class='warning'>Shrieking here would be a bad idea.</span>")
|
||||
return
|
||||
..()
|
||||
else
|
||||
return
|
||||
|
||||
/spell/aoe_turf/dissonant_shriek/cast(list/targets, mob/user = usr)
|
||||
for(var/mob/living/T in targets)
|
||||
if(iscarbon(T))
|
||||
if(T.mind)
|
||||
if(T.get_ear_protection() >= 2 || T == user)
|
||||
continue
|
||||
to_chat(T, "<span class='danger'>You hear an extremely loud screeching sound! It slightly \
|
||||
[pick("confuses","confounds","perturbs","befuddles","dazes","unsettles","disorients")] you.</span>")
|
||||
T.Confuse(10)
|
||||
playsound(get_turf(user),'sound/effects/screech.ogg', 75, TRUE)
|
||||
|
||||
empulse(get_turf(user), emp_heavy, emp_med, emp_light, emp_long)
|
||||
|
||||
user.visible_message("<span class='danger'>[user] vibrates and bubbles, letting out an inhuman shriek, reverberating through your ears!</span>")
|
||||
|
||||
add_attack_logs(user,null,"Used dissonant shriek (Xenochimera) ")
|
||||
|
||||
for(var/obj/machinery/light/L in range(range, src))
|
||||
L.on = 1
|
||||
L.broken()
|
||||
@@ -3391,6 +3391,7 @@
|
||||
#include "code\modules\spells\aoe_turf\conjure\forcewall.dm"
|
||||
#include "code\modules\spells\general\area_teleport.dm"
|
||||
#include "code\modules\spells\general\rune_write.dm"
|
||||
#include "code\modules\spells\targeted\chimera_spells.dm"
|
||||
#include "code\modules\spells\targeted\ethereal_jaunt.dm"
|
||||
#include "code\modules\spells\targeted\genetic.dm"
|
||||
#include "code\modules\spells\targeted\harvest.dm"
|
||||
|
||||
Reference in New Issue
Block a user