mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-09 16:12:17 +00:00
497 lines
20 KiB
Plaintext
497 lines
20 KiB
Plaintext
/datum/species/alraune
|
|
name = SPECIES_ALRAUNE
|
|
name_plural = "Alraunes"
|
|
unarmed_types = list(/datum/unarmed_attack/stomp, /datum/unarmed_attack/kick, /datum/unarmed_attack/punch, /datum/unarmed_attack/bite)
|
|
num_alternate_languages = 2
|
|
slowdown = 1 //slow, they're plants. Not as slow as full diona.
|
|
total_health = 100 //standard
|
|
brute_mod = 1 //nothing special
|
|
burn_mod = 1.5 //plants don't like fire
|
|
metabolic_rate = 0.75 // slow metabolism
|
|
item_slowdown_mod = 0.25 //while they start slow, they don't get much slower
|
|
bloodloss_rate = 0.1 //While they do bleed, they bleed out VERY slowly
|
|
min_age = 18
|
|
max_age = 250
|
|
health_hud_intensity = 1.5
|
|
base_species = SPECIES_ALRAUNE
|
|
selects_bodytype = TRUE
|
|
|
|
body_temperature = T20C
|
|
breath_type = "oxygen"
|
|
poison_type = "phoron"
|
|
exhale_type = "oxygen"
|
|
|
|
// Heat and cold resistances are 20 degrees broader on the level 1 range, level 2 is default, level 3 is much weaker, halfway between L2 and normal L3.
|
|
// Essentially, they can tolerate a broader range of comfortable temperatures, but suffer more at extremes.
|
|
cold_level_1 = 240 //Default 260 - Lower is better
|
|
cold_level_2 = 200 //Default 200
|
|
cold_level_3 = 160 //Default 120
|
|
cold_discomfort_level = 260 //they start feeling uncomfortable around the point where humans take damage
|
|
|
|
heat_level_1 = 380 //Default 360 - Higher is better
|
|
heat_level_2 = 400 //Default 400
|
|
heat_level_3 = 700 //Default 1000
|
|
heat_discomfort_level = 360
|
|
|
|
breath_cold_level_1 = 240 //They don't have lungs, they breathe through their skin
|
|
breath_cold_level_2 = 180 //sadly for them, their breath tolerance is no better than anyone else's.
|
|
breath_cold_level_3 = 140 //mainly 'cause breath tolerance is more generous than body temp tolerance.
|
|
|
|
breath_heat_level_1 = 400 //slightly better heat tolerance in air though. Slightly.
|
|
breath_heat_level_2 = 450
|
|
breath_heat_level_3 = 800 //lower incineration threshold though
|
|
|
|
spawn_flags = SPECIES_CAN_JOIN
|
|
flags = NO_SCAN | IS_PLANT | NO_MINOR_CUT
|
|
appearance_flags = HAS_HAIR_COLOR | HAS_LIPS | HAS_UNDERWEAR | HAS_SKIN_COLOR | HAS_EYE_COLOR
|
|
|
|
inherent_verbs = list(
|
|
/mob/living/carbon/human/proc/succubus_drain,
|
|
/mob/living/carbon/human/proc/succubus_drain_finalize,
|
|
/mob/living/carbon/human/proc/succubus_drain_lethal,
|
|
/mob/living/carbon/human/proc/bloodsuck,
|
|
/mob/living/carbon/human/proc/alraune_fruit_select) //Give them the voremodes related to wrapping people in vines and sapping their fluids
|
|
|
|
color_mult = 1
|
|
icobase = 'icons/mob/human_races/r_human_vr.dmi'
|
|
deform = 'icons/mob/human_races/r_def_human_vr.dmi'
|
|
flesh_color = "#9ee02c"
|
|
blood_color = "#edf4d0" //sap!
|
|
base_color = "#1a5600"
|
|
|
|
reagent_tag = IS_ALRAUNE
|
|
|
|
blurb = "Alraunes are a rare sight in space. Their bodies are reminiscent of that of plants, and yet they share many\
|
|
traits with other humanoid beings.\
|
|
\
|
|
Most Alraunes are not interested in traversing space, their heavy preference for natural environments and general\
|
|
disinterest in things outside it keeps them as a species at a rather primal stage.\
|
|
\
|
|
However, after their discovery by the angels of Sanctum, many alraunes succumbed to their curiosity, and took the offer\
|
|
to learn of the world and venture out, whether it's to Sanctum, or elsewhere in the galaxy."
|
|
catalogue_data = list(/datum/category_item/catalogue/fauna/alraune)
|
|
|
|
has_limbs = list(
|
|
BP_TORSO = list("path" = /obj/item/organ/external/chest),
|
|
BP_GROIN = list("path" = /obj/item/organ/external/groin),
|
|
BP_HEAD = list("path" = /obj/item/organ/external/head),
|
|
BP_L_ARM = list("path" = /obj/item/organ/external/arm),
|
|
BP_R_ARM = list("path" = /obj/item/organ/external/arm/right),
|
|
BP_L_LEG = list("path" = /obj/item/organ/external/leg),
|
|
BP_R_LEG = list("path" = /obj/item/organ/external/leg/right),
|
|
BP_L_HAND = list("path" = /obj/item/organ/external/hand),
|
|
BP_R_HAND = list("path" = /obj/item/organ/external/hand/right),
|
|
BP_L_FOOT = list("path" = /obj/item/organ/external/foot),
|
|
BP_R_FOOT = list("path" = /obj/item/organ/external/foot/right)
|
|
)
|
|
|
|
// limited organs, 'cause they're simple
|
|
has_organ = list(
|
|
O_LIVER = /obj/item/organ/internal/liver/alraune,
|
|
O_KIDNEYS = /obj/item/organ/internal/kidneys/alraune,
|
|
O_BRAIN = /obj/item/organ/internal/brain/alraune,
|
|
O_EYES = /obj/item/organ/internal/eyes/alraune,
|
|
A_FRUIT = /obj/item/organ/internal/fruitgland,
|
|
)
|
|
|
|
/datum/species/alraune/can_breathe_water()
|
|
return TRUE //eh, why not? Aquatic plants are a thing.
|
|
|
|
|
|
/datum/species/alraune/handle_environment_special(var/mob/living/carbon/human/H)
|
|
if(H.inStasisNow()) // if they're in stasis, they won't need this stuff.
|
|
return
|
|
|
|
//setting these here 'cause ugh the defines for life are in the wrong place to compile properly
|
|
//set them back to HUMAN_MAX_OXYLOSS if we move the life defines to the defines folder at any point
|
|
var/ALRAUNE_MAX_OXYLOSS = 1 //Defines how much oxyloss humans can get per tick. A tile with no air at all (such as space) applies this value, otherwise it's a percentage of it.
|
|
var/ALRAUNE_CRIT_MAX_OXYLOSS = ( 2.0 / 6) //The amount of damage you'll get when in critical condition. We want this to be a 5 minute deal = 300s. There are 50HP to get through, so (1/6)*last_tick_duration per second. Breaths however only happen every 4 ticks. last_tick_duration = ~2.0 on average
|
|
|
|
//They don't have lungs so breathe() will just return. Instead, they breathe through their skin.
|
|
//This is mostly normal breath code with some tweaks that apply to their particular biology.
|
|
|
|
var/datum/gas_mixture/breath = null
|
|
var/fullysealed = FALSE //if they're wearing a fully sealed suit, their internals take priority.
|
|
var/environmentalair = FALSE //if no sealed suit, internals take priority in low pressure environements
|
|
|
|
if(H.wear_suit && (H.wear_suit.min_pressure_protection = 0) && H.head && (H.head.min_pressure_protection = 0))
|
|
fullysealed = TRUE
|
|
else // find out if local gas mixture is enough to override use of internals
|
|
var/datum/gas_mixture/environment = H.loc.return_air()
|
|
var/envpressure = environment.return_pressure()
|
|
if(envpressure >= hazard_low_pressure)
|
|
environmentalair = TRUE
|
|
|
|
if(fullysealed || !environmentalair)
|
|
breath = H.get_breath_from_internal()
|
|
|
|
if(!breath) //No breath from internals so let's try to get air from our location
|
|
// cut-down version of get_breath_from_environment - notably, gas masks provide no benefit
|
|
var/datum/gas_mixture/environment2
|
|
if(H.loc)
|
|
environment2 = H.loc.return_air_for_internal_lifeform(H)
|
|
|
|
if(environment2)
|
|
breath = environment2.remove_volume(BREATH_VOLUME)
|
|
H.handle_chemical_smoke(environment2) //handle chemical smoke while we're at it
|
|
|
|
// NOW a crude copypasta of handle_breath. Leaving some things out that don't apply to plants.
|
|
if(H.does_not_breathe)
|
|
H.failed_last_breath = 0
|
|
H.adjustOxyLoss(-5)
|
|
return // if somehow they don't breathe, abort breathing.
|
|
|
|
if(!breath || (breath.total_moles == 0))
|
|
H.failed_last_breath = 1
|
|
if(H.health > config.health_threshold_crit)
|
|
H.adjustOxyLoss(ALRAUNE_MAX_OXYLOSS)
|
|
else
|
|
H.adjustOxyLoss(ALRAUNE_CRIT_MAX_OXYLOSS)
|
|
|
|
H.throw_alert("pressure", /obj/screen/alert/lowpressure)
|
|
|
|
return // skip air processing if there's no air
|
|
else
|
|
H.clear_alert("pressure")
|
|
|
|
// now into the good stuff
|
|
|
|
//var/safe_pressure_min = species.minimum_breath_pressure // Minimum safe partial pressure of breathable gas in kPa
|
|
//just replace safe_pressure_min with minimum_breath_pressure, no need to declare a new var
|
|
|
|
var/safe_exhaled_max = 10
|
|
var/safe_toxins_max = 0.2
|
|
var/SA_para_min = 1
|
|
var/SA_sleep_min = 5
|
|
var/inhaled_gas_used = 0
|
|
|
|
var/breath_pressure = (breath.total_moles*R_IDEAL_GAS_EQUATION*breath.temperature)/BREATH_VOLUME
|
|
|
|
var/inhaling
|
|
var/poison
|
|
var/exhaling
|
|
|
|
var/failed_inhale = 0
|
|
var/failed_exhale = 0
|
|
|
|
inhaling = breath.gas["carbon_dioxide"]
|
|
poison = breath.gas[poison_type]
|
|
exhaling = breath.gas[exhale_type]
|
|
|
|
var/inhale_pp = (inhaling/breath.total_moles)*breath_pressure
|
|
var/toxins_pp = (poison/breath.total_moles)*breath_pressure
|
|
var/exhaled_pp = (exhaling/breath.total_moles)*breath_pressure
|
|
|
|
// Not enough to breathe
|
|
if((inhale_pp + exhaled_pp) < minimum_breath_pressure) //they can breathe either oxygen OR CO2
|
|
if(prob(20))
|
|
spawn(0) H.emote("gasp")
|
|
|
|
var/ratio = (inhale_pp + exhaled_pp)/minimum_breath_pressure
|
|
// Don't fuck them up too fast (space only does HUMAN_MAX_OXYLOSS (1) after all!)
|
|
H.adjustOxyLoss(max(ALRAUNE_MAX_OXYLOSS*(1-ratio), 0))
|
|
failed_inhale = 1
|
|
|
|
H.throw_alert("oxy", /obj/screen/alert/not_enough_co2)
|
|
else
|
|
// We're in safe limits
|
|
H.clear_alert("oxy")
|
|
|
|
inhaled_gas_used = inhaling/6
|
|
breath.adjust_gas("carbon_dioxide", -inhaled_gas_used, update = 0) //update afterwards
|
|
breath.adjust_gas_temp(exhale_type, inhaled_gas_used, H.bodytemperature, update = 0) //update afterwards
|
|
|
|
//Now we handle CO2.
|
|
if(inhale_pp > safe_exhaled_max * 0.7) // For a human, this would be too much exhaled gas in the air. But plants don't care.
|
|
H.throw_alert("co2", /obj/screen/alert/too_much_co2/plant) // Give them the alert on the HUD. They'll be aware when the good stuff is present.
|
|
else
|
|
H.clear_alert("co2")
|
|
|
|
//do the CO2 buff stuff here
|
|
|
|
var/co2buff = 0
|
|
if(inhaling)
|
|
co2buff = (CLAMP(inhale_pp, 0, minimum_breath_pressure))/minimum_breath_pressure //returns a value between 0 and 1.
|
|
|
|
var/light_amount = fullysealed ? H.getlightlevel() : H.getlightlevel()/5 // if they're covered, they're not going to get much light on them.
|
|
|
|
if(co2buff && !H.toxloss && light_amount >= 0.1) //if there's enough light and CO2 and you're not poisoned, heal. Note if you're wearing a sealed suit your heal rate will suck.
|
|
H.adjustBruteLoss(-(light_amount * co2buff * 2)) //at a full partial pressure of CO2 and full light, you'll only heal half as fast as diona.
|
|
H.adjustFireLoss(-(light_amount * co2buff)) //this won't let you tank environmental damage from fire. MAYBE cold until your body temp drops.
|
|
|
|
if(H.nutrition < (200 + 400*co2buff)) //if no CO2, a fully lit tile gives them 1/tick up to 200. With CO2, potentially up to 600.
|
|
H.adjust_nutrition(light_amount*(1+co2buff*5))
|
|
|
|
// Too much poison in the air.
|
|
if(toxins_pp > safe_toxins_max)
|
|
var/ratio = (poison/safe_toxins_max) * 10
|
|
if(H.reagents)
|
|
H.reagents.add_reagent("toxin", CLAMP(ratio, MIN_TOXIN_DAMAGE, MAX_TOXIN_DAMAGE))
|
|
breath.adjust_gas(poison_type, -poison/6, update = 0) //update after
|
|
H.throw_alert("tox_in_air", /obj/screen/alert/tox_in_air)
|
|
else
|
|
H.clear_alert("tox_in_air")
|
|
|
|
// If there's some other shit in the air lets deal with it here.
|
|
if(breath.gas["sleeping_agent"])
|
|
var/SA_pp = (breath.gas["sleeping_agent"] / breath.total_moles) * breath_pressure
|
|
|
|
// Enough to make us paralysed for a bit
|
|
if(SA_pp > SA_para_min)
|
|
|
|
// 3 gives them one second to wake up and run away a bit!
|
|
H.Paralyse(3)
|
|
|
|
// Enough to make us sleep as well
|
|
if(SA_pp > SA_sleep_min)
|
|
H.Sleeping(5)
|
|
|
|
// There is sleeping gas in their lungs, but only a little, so give them a bit of a warning
|
|
else if(SA_pp > 0.15)
|
|
if(prob(20))
|
|
spawn(0) H.emote(pick("giggle", "laugh"))
|
|
breath.adjust_gas("sleeping_agent", -breath.gas["sleeping_agent"]/6, update = 0) //update after
|
|
|
|
// Were we able to breathe?
|
|
if (failed_inhale || failed_exhale)
|
|
H.failed_last_breath = 1
|
|
else
|
|
H.failed_last_breath = 0
|
|
H.adjustOxyLoss(-5)
|
|
|
|
|
|
// Hot air hurts :(
|
|
if((breath.temperature < breath_cold_level_1 || breath.temperature > breath_heat_level_1) && !(COLD_RESISTANCE in H.mutations))
|
|
|
|
if(breath.temperature <= breath_cold_level_1)
|
|
if(prob(20))
|
|
to_chat(H, "<span class='danger'>You feel icicles forming on your skin!</span>")
|
|
else if(breath.temperature >= breath_heat_level_1)
|
|
if(prob(20))
|
|
to_chat(H, "<span class='danger'>You feel yourself smouldering in the heat!</span>")
|
|
|
|
var/bodypart = pick(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_ARM,BP_R_ARM,BP_L_HAND,BP_R_HAND,BP_TORSO,BP_GROIN,BP_HEAD)
|
|
if(breath.temperature >= breath_heat_level_1)
|
|
if(breath.temperature < breath_heat_level_2)
|
|
H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_1, BURN, bodypart, used_weapon = "Excessive Heat")
|
|
else if(breath.temperature < breath_heat_level_3)
|
|
H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_2, BURN, bodypart, used_weapon = "Excessive Heat")
|
|
else
|
|
H.apply_damage(HEAT_GAS_DAMAGE_LEVEL_3, BURN, bodypart, used_weapon = "Excessive Heat")
|
|
|
|
else if(breath.temperature <= breath_cold_level_1)
|
|
if(breath.temperature > breath_cold_level_2)
|
|
H.apply_damage(COLD_GAS_DAMAGE_LEVEL_1, BURN, bodypart, used_weapon = "Excessive Cold")
|
|
else if(breath.temperature > breath_cold_level_3)
|
|
H.apply_damage(COLD_GAS_DAMAGE_LEVEL_2, BURN, bodypart, used_weapon = "Excessive Cold")
|
|
else
|
|
H.apply_damage(COLD_GAS_DAMAGE_LEVEL_3, BURN, bodypart, used_weapon = "Excessive Cold")
|
|
|
|
|
|
//breathing in hot/cold air also heats/cools you a bit
|
|
var/temp_adj = breath.temperature - H.bodytemperature
|
|
if (temp_adj < 0)
|
|
temp_adj /= (BODYTEMP_COLD_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed
|
|
else
|
|
temp_adj /= (BODYTEMP_HEAT_DIVISOR * 5) //don't raise temperature as much as if we were directly exposed
|
|
|
|
var/relative_density = breath.total_moles / (MOLES_CELLSTANDARD * BREATH_PERCENTAGE)
|
|
temp_adj *= relative_density
|
|
|
|
if (temp_adj > BODYTEMP_HEATING_MAX) temp_adj = BODYTEMP_HEATING_MAX
|
|
if (temp_adj < BODYTEMP_COOLING_MAX) temp_adj = BODYTEMP_COOLING_MAX
|
|
//to_world("Breath: [breath.temperature], [src]: [bodytemperature], Adjusting: [temp_adj]")
|
|
H.bodytemperature += temp_adj
|
|
|
|
else if(breath.temperature >= heat_discomfort_level)
|
|
get_environment_discomfort(src,"heat")
|
|
else if(breath.temperature <= cold_discomfort_level)
|
|
get_environment_discomfort(src,"cold")
|
|
|
|
breath.update_values()
|
|
return 1
|
|
|
|
/obj/item/organ/internal/brain/alraune
|
|
icon = 'icons/mob/species/alraune/organs.dmi'
|
|
icon_state = "neurostroma"
|
|
name = "neuro-stroma"
|
|
desc = "A knot of fibrous plant matter."
|
|
parent_organ = BP_TORSO // brains in their core
|
|
|
|
/obj/item/organ/internal/eyes/alraune
|
|
icon = 'icons/mob/species/alraune/organs.dmi'
|
|
icon_state = "photoreceptors"
|
|
name = "photoreceptors"
|
|
desc = "Bulbous and fleshy plant matter."
|
|
|
|
/obj/item/organ/internal/kidneys/alraune
|
|
icon = 'icons/mob/species/alraune/organs.dmi'
|
|
icon_state = "rhyzofilter"
|
|
name = "rhyzofilter"
|
|
desc = "A tangle of root nodules."
|
|
|
|
/obj/item/organ/internal/liver/alraune
|
|
icon = 'icons/mob/species/alraune/organs.dmi'
|
|
icon_state = "phytoextractor"
|
|
name = "enzoretector"
|
|
desc = "A bulbous gourd-like structure."
|
|
|
|
//Begin fruit gland and its code.
|
|
/obj/item/organ/internal/fruitgland //Amazing name, I know.
|
|
icon = 'icons/mob/species/alraune/organs.dmi'
|
|
icon_state = "phytoextractor"
|
|
name = "fruit gland"
|
|
desc = "A bulbous gourd-like structure."
|
|
organ_tag = A_FRUIT
|
|
var/generated_reagents = list("sugar" = 2) //This actually allows them. This could be anything, but sugar seems most fitting.
|
|
var/usable_volume = 250 //Five fruit.
|
|
var/transfer_amount = 50
|
|
var/empty_message = list("Your have no fruit on you.", "You have a distinct lack of fruit..")
|
|
var/full_message = list("You have a multitude of fruit that is ready for harvest!", "You have fruit that is ready to be picked!")
|
|
var/emote_descriptor = list("fruit right off of the Alraune!", "a fruit from the Alraune!")
|
|
var/verb_descriptor = list("grabs", "snatches", "picks")
|
|
var/self_verb_descriptor = list("grab", "snatch", "pick")
|
|
var/short_emote_descriptor = list("picks", "grabs")
|
|
var/self_emote_descriptor = list("grab", "pick", "snatch")
|
|
var/fruit_type = "apple"
|
|
var/mob/living/organ_owner = null
|
|
var/gen_cost = 0.5
|
|
|
|
/obj/item/organ/internal/fruitgland/New()
|
|
..()
|
|
create_reagents(usable_volume)
|
|
|
|
|
|
/obj/item/organ/internal/fruitgland/process()
|
|
if(!owner) return
|
|
var/obj/item/organ/external/parent = owner.get_organ(parent_organ)
|
|
var/before_gen
|
|
if(parent && generated_reagents && organ_owner) //Is it in the chest/an organ, has reagents, and is 'activated'
|
|
before_gen = reagents.total_volume
|
|
if(reagents.total_volume < reagents.maximum_volume)
|
|
if(organ_owner.nutrition >= gen_cost)
|
|
do_generation()
|
|
|
|
if(reagents)
|
|
if(reagents.total_volume == reagents.maximum_volume * 0.05)
|
|
to_chat(organ_owner, "<span class='notice'>[pick(empty_message)]</span>")
|
|
else if(reagents.total_volume == reagents.maximum_volume && before_gen < reagents.maximum_volume)
|
|
to_chat(organ_owner, "<span class='warning'>[pick(full_message)]</span>")
|
|
|
|
/obj/item/organ/internal/fruitgland/proc/do_generation()
|
|
organ_owner.adjust_nutrition(-gen_cost)
|
|
for(var/reagent in generated_reagents)
|
|
reagents.add_reagent(reagent, generated_reagents[reagent])
|
|
|
|
|
|
/mob/living/carbon/human/proc/alraune_fruit_select() //So if someone doesn't want fruit/vegetables, they don't have to select one.
|
|
set name = "Select fruit"
|
|
set desc = "Select what fruit/vegetable you wish to grow."
|
|
set category = "Abilities"
|
|
var/obj/item/organ/internal/fruitgland/fruit_gland
|
|
for(var/F in contents)
|
|
if(istype(F, /obj/item/organ/internal/fruitgland))
|
|
fruit_gland = F
|
|
break
|
|
|
|
if(fruit_gland)
|
|
var/selection = input(src, "Choose your character's fruit type. Choosing nothing will result in a default of apples.", "Fruit Type", fruit_gland.fruit_type) as null|anything in acceptable_fruit_types
|
|
if(selection)
|
|
fruit_gland.fruit_type = selection
|
|
verbs |= /mob/living/carbon/human/proc/alraune_fruit_pick
|
|
verbs -= /mob/living/carbon/human/proc/alraune_fruit_select
|
|
fruit_gland.organ_owner = src
|
|
fruit_gland.emote_descriptor = list("fruit right off of [fruit_gland.organ_owner]!", "a fruit from [fruit_gland.organ_owner]!")
|
|
|
|
else
|
|
to_chat(src, "<span class='notice'>You lack the organ required to produce fruit.</span>")
|
|
return
|
|
|
|
/mob/living/carbon/human/proc/alraune_fruit_pick()
|
|
set name = "Pick Fruit"
|
|
set desc = "Pick fruit off of [src]."
|
|
set category = "Object"
|
|
set src in view(1)
|
|
|
|
//do_reagent_implant(usr)
|
|
if(!isliving(usr) || !usr.checkClickCooldown())
|
|
return
|
|
|
|
if(usr.incapacitated() || usr.stat > CONSCIOUS)
|
|
return
|
|
|
|
var/obj/item/organ/internal/fruitgland/fruit_gland
|
|
for(var/I in contents)
|
|
if(istype(I, /obj/item/organ/internal/fruitgland))
|
|
fruit_gland = I
|
|
break
|
|
if (fruit_gland) //Do they have the gland?
|
|
if(fruit_gland.reagents.total_volume < fruit_gland.transfer_amount)
|
|
to_chat(src, "<span class='notice'>[pick(fruit_gland.empty_message)]</span>")
|
|
return
|
|
|
|
var/datum/seed/S = plant_controller.seeds["[fruit_gland.fruit_type]"]
|
|
S.harvest(usr,0,0,1)
|
|
|
|
var/index = rand(0,2)
|
|
|
|
if (usr != src)
|
|
var/emote = fruit_gland.emote_descriptor[index]
|
|
var/verb_desc = fruit_gland.verb_descriptor[index]
|
|
var/self_verb_desc = fruit_gland.self_verb_descriptor[index]
|
|
usr.visible_message("<span class='notice'>[usr] [verb_desc] [emote]</span>",
|
|
"<span class='notice'>You [self_verb_desc] [emote]</span>")
|
|
else
|
|
visible_message("<span class='notice'>[src] [pick(fruit_gland.short_emote_descriptor)] a fruit.</span>",
|
|
"<span class='notice'>You [pick(fruit_gland.self_emote_descriptor)] a fruit.</span>")
|
|
|
|
fruit_gland.reagents.remove_any(fruit_gland.transfer_amount)
|
|
|
|
//End of fruit gland code.
|
|
|
|
/datum/species/alraune/proc/produceCopy(var/datum/species/to_copy,var/list/traits,var/mob/living/carbon/human/H)
|
|
ASSERT(to_copy)
|
|
ASSERT(istype(H))
|
|
|
|
if(ispath(to_copy))
|
|
to_copy = "[initial(to_copy.name)]"
|
|
if(istext(to_copy))
|
|
to_copy = GLOB.all_species[to_copy]
|
|
|
|
var/datum/species/alraune/new_copy = new()
|
|
|
|
//Initials so it works with a simple path passed, or an instance
|
|
new_copy.base_species = to_copy.name
|
|
new_copy.icobase = to_copy.icobase
|
|
new_copy.deform = to_copy.deform
|
|
new_copy.tail = to_copy.tail
|
|
new_copy.tail_animation = to_copy.tail_animation
|
|
new_copy.icobase_tail = to_copy.icobase_tail
|
|
new_copy.color_mult = to_copy.color_mult
|
|
new_copy.primitive_form = to_copy.primitive_form
|
|
new_copy.appearance_flags = to_copy.appearance_flags
|
|
new_copy.flesh_color = to_copy.flesh_color
|
|
new_copy.base_color = to_copy.base_color
|
|
new_copy.blood_mask = to_copy.blood_mask
|
|
new_copy.damage_mask = to_copy.damage_mask
|
|
new_copy.damage_overlays = to_copy.damage_overlays
|
|
|
|
//Set up a mob
|
|
H.species = new_copy
|
|
H.icon_state = lowertext(new_copy.get_bodytype())
|
|
|
|
if(new_copy.holder_type)
|
|
H.holder_type = new_copy.holder_type
|
|
|
|
if(H.dna)
|
|
H.dna.ready_dna(H)
|
|
|
|
return new_copy
|
|
|
|
/datum/species/alraune/get_bodytype()
|
|
return base_species
|
|
|
|
/datum/species/alraune/get_race_key()
|
|
var/datum/species/real = GLOB.all_species[base_species]
|
|
return real.race_key
|