mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-01-28 10:12:01 +00:00
This is sorta bulky on the changes since it includes a lot of shuffled documentation, so I'll try to thoroughly summarise here. - Introduces 'preferential' temperature and light values to plants. This means that, while a plant is _within_ 5K and 2 lumens of their ideal heat and ideal light, they will grow faster than otherwise. In the current implementation, the base growth is a 15% chance of age being increased, plus another 15% if you're within preferential temps, and another 5% if within preferential lumens for a maximum of 35%. This is intended to incentivise engaging with temperature mechanics to grow plants with unusual requirements. - This is different to the existing tolerance values, which instead check whether the plant is _outside_ of them - if they are, it damages them. Tolerances cause the plant to die if they're too far from their ideals, preferences cause the plant to grow faster if they're very close to their ideals. The range of preferences should always be inside tolerances. - To work better with this, the ideals of a few kinds of plant have been tweaked. Mushrooms, Adhomian plants, and molluscs will all **not** be in their preferences at room temperature - they will need to be cooled, which can currently be done in D1 hydroponics. A few warmer plants, such as sugarcane, will need to be warmed up to reach their preferences. - None of these will go outside of their tolerances at room temperature - they won't die, they'll just grow slower. - Most plants will be within all their preferences without any action by the gardener. There's also a few assorted QoL changes to hydrotrays, see the changelog. --------- Signed-off-by: hazelrat <83198434+hazelrat@users.noreply.github.com> Co-authored-by: SleepyGemmy <99297919+SleepyGemmy@users.noreply.github.com>
956 lines
34 KiB
Plaintext
956 lines
34 KiB
Plaintext
/datum/plantgene
|
|
/// Label used when applying trait.
|
|
var/genetype
|
|
/// Values to copy into the target seed datum.
|
|
var/list/values
|
|
|
|
/datum/seed
|
|
//Tracking.
|
|
/// Unique identifier
|
|
var/uid
|
|
/// Index for global list
|
|
var/name
|
|
/// Plant name for seed packet
|
|
var/seed_name
|
|
/// Descriptor for packet
|
|
var/seed_noun = SEED_NOUN_SEEDS
|
|
/// Prettier name
|
|
var/display_name
|
|
|
|
/// If set, seed will not display variety number
|
|
var/roundstart
|
|
/// Only used for the random seed packets.
|
|
var/mysterious
|
|
/// Mostly used for living mobs
|
|
var/can_self_harvest = 0
|
|
/// Number of stages the plant passes through before it is mature
|
|
var/growth_stages = 0
|
|
|
|
/// Initialized in New()
|
|
var/list/traits = list()
|
|
/// Possible predefined mutant varieties, if any
|
|
var/list/mutants
|
|
/// Chemicals that plant produces in products/injects into victim
|
|
var/list/chems
|
|
/// The plant will absorb these gasses during its life
|
|
var/list/consume_gasses
|
|
/// The plant will exude these gasses during its life
|
|
var/list/exude_gasses
|
|
|
|
/// Used by the reagent grinder
|
|
var/kitchen_tag
|
|
/// Garbage item produced when eaten
|
|
var/trash_type
|
|
/// Graffiti decal
|
|
var/splat_type = /obj/effect/decal/cleanable/fruit_smudge
|
|
var/product_type = /obj/item/reagent_containers/food/snacks/grown
|
|
/// If set, overrides the description of the product (What the produce looks like for example)
|
|
var/product_desc
|
|
/// If set, overrides the extended scription of the product (Useful to describe the 'lore')
|
|
var/product_desc_extended
|
|
|
|
var/force_layer
|
|
var/hydrotray_only
|
|
|
|
/datum/seed/proc/setup_traits()
|
|
|
|
/datum/seed/New()
|
|
set_trait(TRAIT_SPOROUS, 0)
|
|
set_trait(TRAIT_IMMUTABLE, 0)
|
|
set_trait(TRAIT_HARVEST_REPEAT, 0)
|
|
set_trait(TRAIT_PRODUCES_POWER, 0)
|
|
set_trait(TRAIT_JUICY, 0)
|
|
set_trait(TRAIT_EXPLOSIVE, 0)
|
|
set_trait(TRAIT_CARNIVOROUS, 0)
|
|
set_trait(TRAIT_PARASITE, 0)
|
|
set_trait(TRAIT_STINGS, 0)
|
|
set_trait(TRAIT_YIELD, 0)
|
|
set_trait(TRAIT_SPREAD, 0)
|
|
set_trait(TRAIT_MATURATION, 0)
|
|
set_trait(TRAIT_PRODUCTION, 0)
|
|
set_trait(TRAIT_TELEPORTING, 0)
|
|
set_trait(TRAIT_BIOLUM, 0)
|
|
set_trait(TRAIT_ALTER_TEMP, 0)
|
|
set_trait(TRAIT_PRODUCT_ICON, 0)
|
|
set_trait(TRAIT_PLANT_ICON, 0)
|
|
set_trait(TRAIT_PRODUCT_COLOUR, 0)
|
|
set_trait(TRAIT_BIOLUM_COLOUR, 0)
|
|
set_trait(TRAIT_BIOLUM_PWR, 1)
|
|
set_trait(TRAIT_POTENCY, 1)
|
|
set_trait(TRAIT_REQUIRES_NUTRIENTS, 1)
|
|
set_trait(TRAIT_REQUIRES_WATER, 1)
|
|
set_trait(TRAIT_WATER_CONSUMPTION, 3)
|
|
set_trait(TRAIT_LIGHT_TOLERANCE, 3) // Plants will begin to die if the light levels are three or more lumens from their ideal.
|
|
set_trait(TRAIT_TOXINS_TOLERANCE, 5)
|
|
set_trait(TRAIT_PEST_TOLERANCE, 5)
|
|
set_trait(TRAIT_WEED_TOLERANCE, 5)
|
|
set_trait(TRAIT_IDEAL_LIGHT, 5)
|
|
set_trait(TRAIT_HEAT_TOLERANCE, 20) // Plants will begin to die if they're twenty or more degrees from their ideal temperature.
|
|
set_trait(TRAIT_LOWKPA_TOLERANCE, 25) // Plants survive all the way down to a quarter of an atmosphere!
|
|
set_trait(TRAIT_ENDURANCE, 100)
|
|
set_trait(TRAIT_HIGHKPA_TOLERANCE, 200)
|
|
set_trait(TRAIT_IDEAL_HEAT, 293)
|
|
set_trait(TRAIT_NUTRIENT_CONSUMPTION, 0.25)
|
|
set_trait(TRAIT_PLANT_COLOUR, "#46B543")
|
|
set_trait(TRAIT_LARGE, 0)
|
|
set_trait(TRAIT_HEAT_PREFERENCE, 5) // By default, plants grow faster in a temperature within five degrees of their ideal.
|
|
set_trait(TRAIT_LIGHT_PREFERENCE, 2) // Similarly, they grow faster under lumens within two of their ideal.
|
|
|
|
setup_traits()
|
|
|
|
update_growth_stages()
|
|
|
|
/datum/seed/proc/get_trait(var/trait)
|
|
return traits["[trait]"]
|
|
|
|
/datum/seed/proc/get_trash_type()
|
|
return trash_type
|
|
|
|
/datum/seed/proc/set_trait(var/trait,var/nval,var/ubound,var/lbound, var/degrade)
|
|
if(!isnull(degrade)) nval *= degrade
|
|
if(!isnull(ubound)) nval = min(nval,ubound)
|
|
if(!isnull(lbound)) nval = max(nval,lbound)
|
|
traits["[trait]"] = nval
|
|
|
|
/datum/seed/proc/create_spores(var/turf/T)
|
|
if(!T)
|
|
return
|
|
if(!istype(T))
|
|
T = get_turf(T)
|
|
if(!T)
|
|
return
|
|
|
|
var/datum/reagents/R = new/datum/reagents(100)
|
|
if(chems.len)
|
|
for(var/rid in chems)
|
|
var/injecting = max(1,get_trait(TRAIT_POTENCY)/5)
|
|
R.add_reagent(rid,injecting)
|
|
|
|
var/datum/effect/effect/system/smoke_spread/chem/spores/S = new(name)
|
|
S.attach(T)
|
|
S.set_up(R, round(get_trait(TRAIT_POTENCY)/4), 0, T, 40)
|
|
S.start()
|
|
|
|
/// Does brute damage to a target.
|
|
/datum/seed/proc/do_thorns(var/mob/living/carbon/human/target, var/obj/item/fruit, var/target_limb)
|
|
|
|
if(!get_trait(TRAIT_CARNIVOROUS))
|
|
return
|
|
|
|
if(!istype(target))
|
|
if(israt(target))
|
|
new /obj/effect/decal/remains/rat(get_turf(target))
|
|
qdel(target)
|
|
else if(istype(target, /mob/living/simple_animal/lizard))
|
|
new /obj/effect/decal/remains/lizard(get_turf(target))
|
|
qdel(target)
|
|
return
|
|
|
|
|
|
if(!target_limb) target_limb = pick(BP_L_FOOT,BP_R_FOOT,BP_L_LEG,BP_R_LEG,BP_L_HAND,BP_R_HAND,BP_L_ARM, BP_R_ARM,BP_HEAD,BP_CHEST,BP_GROIN)
|
|
var/obj/item/organ/external/affecting = target.get_organ(target_limb)
|
|
var/damage = 0
|
|
|
|
if(get_trait(TRAIT_CARNIVOROUS))
|
|
if(get_trait(TRAIT_CARNIVOROUS) == 2)
|
|
if(affecting)
|
|
to_chat(target, SPAN_DANGER("\The [fruit]'s thorns pierce your [affecting.name] greedily!"))
|
|
else
|
|
to_chat(target, SPAN_DANGER("\The [fruit]'s thorns pierce your flesh greedily!"))
|
|
damage = get_trait(TRAIT_POTENCY)/2
|
|
else
|
|
if(affecting)
|
|
to_chat(target, SPAN_DANGER("\The [fruit]'s thorns dig deeply into your [affecting.name]!"))
|
|
else
|
|
to_chat(target, SPAN_DANGER("\The [fruit]'s thorns dig deeply into your flesh!"))
|
|
damage = get_trait(TRAIT_POTENCY)/5
|
|
else
|
|
return
|
|
|
|
if(affecting)
|
|
affecting.take_damage(damage, 0)
|
|
affecting.add_autopsy_data("Thorns",damage)
|
|
else
|
|
target.adjustBruteLoss(damage)
|
|
target.UpdateDamageIcon()
|
|
target.updatehealth()
|
|
|
|
/// Adds reagents to a target.
|
|
/datum/seed/proc/do_sting(var/mob/living/carbon/human/target, var/obj/item/fruit)
|
|
if(!get_trait(TRAIT_STINGS))
|
|
return
|
|
if(chems && chems.len)
|
|
|
|
var/body_coverage = HEAD|FACE|EYES|UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
|
|
|
for(var/obj/item/clothing/clothes in target)
|
|
if(target.l_hand == clothes|| target.r_hand == clothes)
|
|
continue
|
|
body_coverage &= ~(clothes.body_parts_covered)
|
|
|
|
if(!body_coverage)
|
|
return
|
|
|
|
to_chat(target, SPAN_DANGER("You are stung by \the [fruit]!"))
|
|
for(var/rid in chems)
|
|
var/injecting = min(5,max(1,get_trait(TRAIT_POTENCY)/5))
|
|
target.reagents.add_reagent(rid,injecting)
|
|
|
|
/// Splatter a turf.
|
|
/datum/seed/proc/splatter(var/turf/T,var/obj/item/thrown)
|
|
if(splat_type && !(locate(/obj/effect/plant) in T))
|
|
var/obj/effect/plant/splat = new splat_type(T, src)
|
|
if(!istype(splat)) // Plants handle their own stuff.
|
|
splat.name = "[thrown.name] [pick("smear","smudge","splatter")]"
|
|
if(get_trait(TRAIT_BIOLUM))
|
|
var/pwr
|
|
if(get_trait(TRAIT_BIOLUM_PWR) == 0)
|
|
pwr = get_trait(TRAIT_BIOLUM)
|
|
else
|
|
pwr = get_trait(TRAIT_BIOLUM_PWR)
|
|
var/clr
|
|
if(get_trait(TRAIT_BIOLUM_COLOUR))
|
|
clr = get_trait(TRAIT_BIOLUM_COLOUR)
|
|
splat.set_light(get_trait(TRAIT_POTENCY)/10, pwr, clr)
|
|
addtimer(CALLBACK(splat, TYPE_PROC_REF(/atom, set_light), 0), rand(3 MINUTES, 5 MINUTES))
|
|
var/flesh_colour = get_trait(TRAIT_FLESH_COLOUR)
|
|
if(!flesh_colour) flesh_colour = get_trait(TRAIT_PRODUCT_COLOUR)
|
|
if(flesh_colour) splat.color = get_trait(TRAIT_PRODUCT_COLOUR)
|
|
|
|
if(chems)
|
|
for(var/mob/living/M in T.contents)
|
|
if(!M.reagents)
|
|
continue
|
|
for(var/chem in chems)
|
|
var/injecting = min(5,max(1,get_trait(TRAIT_POTENCY)/3))
|
|
M.reagents.add_reagent(chem,injecting)
|
|
|
|
/// Applies an effect to a target atom.
|
|
/datum/seed/proc/thrown_at(var/obj/item/thrown,var/atom/target, var/force_explode)
|
|
|
|
var/splatted
|
|
var/turf/origin_turf = get_turf(target)
|
|
|
|
if(force_explode || get_trait(TRAIT_EXPLOSIVE))
|
|
|
|
create_spores(origin_turf)
|
|
|
|
var/flood_dist = min(10,max(1,get_trait(TRAIT_POTENCY)/15))
|
|
var/list/open_turfs = list()
|
|
var/list/closed_turfs = list()
|
|
var/list/valid_turfs = list()
|
|
open_turfs |= origin_turf
|
|
|
|
// Flood fill to get affected turfs.
|
|
while(open_turfs.len)
|
|
var/turf/T = pick(open_turfs)
|
|
open_turfs -= T
|
|
closed_turfs |= T
|
|
valid_turfs |= T
|
|
|
|
for(var/dir in GLOB.alldirs)
|
|
var/turf/neighbor = get_step(T,dir)
|
|
if(!neighbor || (neighbor in closed_turfs) || (neighbor in open_turfs))
|
|
continue
|
|
if(neighbor.density || get_dist(neighbor,origin_turf) > flood_dist || istype(neighbor,/turf/space))
|
|
closed_turfs |= neighbor
|
|
continue
|
|
// Check for windows.
|
|
var/no_los
|
|
var/turf/last_turf = origin_turf
|
|
for(var/turf/target_turf in getline(origin_turf,neighbor))
|
|
if(!last_turf.Enter(target_turf) || target_turf.density)
|
|
no_los = 1
|
|
break
|
|
last_turf = target_turf
|
|
if(!no_los && !origin_turf.Enter(neighbor))
|
|
no_los = 1
|
|
if(no_los)
|
|
closed_turfs |= neighbor
|
|
continue
|
|
open_turfs |= neighbor
|
|
|
|
for(var/turf/T in valid_turfs)
|
|
for(var/mob/living/M in T.contents)
|
|
apply_special_effect(M)
|
|
splatter(T,thrown)
|
|
if(origin_turf)
|
|
origin_turf.visible_message(SPAN_DANGER("The [thrown.name] explodes!"))
|
|
qdel(thrown)
|
|
return
|
|
|
|
if(istype(target,/mob/living))
|
|
splatted = apply_special_effect(target,thrown)
|
|
else if(istype(target,/turf))
|
|
splatted = 1
|
|
for(var/mob/living/M in target.contents)
|
|
apply_special_effect(M)
|
|
|
|
if(get_trait(TRAIT_JUICY) && splatted)
|
|
splatter(origin_turf,thrown)
|
|
if(origin_turf)
|
|
origin_turf.visible_message(SPAN_DANGER("The [thrown.name] splatters against [target]!"))
|
|
qdel(thrown)
|
|
|
|
if(get_trait(TRAIT_TELEPORTING))
|
|
|
|
var/outer_teleport_radius = get_trait(TRAIT_POTENCY)/5
|
|
var/inner_teleport_radius = get_trait(TRAIT_POTENCY)/15
|
|
|
|
var/list/turfs = list()
|
|
if(inner_teleport_radius > 0)
|
|
for(var/turf/T in orange(target,outer_teleport_radius))
|
|
if(get_dist(target,T) >= inner_teleport_radius)
|
|
turfs |= T
|
|
|
|
if(turfs.len)
|
|
var/turf/picked = get_turf(pick(turfs))
|
|
var/obj/effect/portal/P = new /obj/effect/portal(get_turf(target))
|
|
P.set_target(picked)
|
|
P.creator = null
|
|
|
|
/// Checks the plant's environment. If anything is improper, adds to a value that will ultimately be used to damage the plant.
|
|
/datum/seed/proc/handle_environment(var/turf/current_turf, var/datum/gas_mixture/environment, var/light_supplied, var/check_only)
|
|
var/health_change = 0
|
|
// Handle gas consumption.
|
|
if(consume_gasses && consume_gasses.len)
|
|
var/missing_gas = 0
|
|
for(var/gas in consume_gasses)
|
|
if(environment && environment.gas && environment.gas[gas] && \
|
|
environment.gas[gas] >= consume_gasses[gas])
|
|
if(!check_only)
|
|
environment.adjust_gas(gas,-consume_gasses[gas],1)
|
|
else
|
|
missing_gas++
|
|
|
|
if(missing_gas > 0)
|
|
health_change += missing_gas * HYDRO_SPEED_MULTIPLIER
|
|
|
|
// Process it.
|
|
var/pressure = environment.return_pressure()
|
|
if(pressure < get_trait(TRAIT_LOWKPA_TOLERANCE)|| pressure > get_trait(TRAIT_HIGHKPA_TOLERANCE))
|
|
health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER
|
|
|
|
// We take the absolute value of the environment's temperature minus the ideal heat - closer to 0 is better, in this case.
|
|
// If that value is greater than the heat tolerance, we apply some damage to the plant.
|
|
if(abs(environment.temperature - get_trait(TRAIT_IDEAL_HEAT)) > get_trait(TRAIT_HEAT_TOLERANCE))
|
|
health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER
|
|
|
|
// Handle gas production.
|
|
if(exude_gasses && exude_gasses.len && !check_only)
|
|
for(var/gas in exude_gasses)
|
|
environment.adjust_gas(gas, max(1,round((exude_gasses[gas]*(get_trait(TRAIT_POTENCY)/5))/exude_gasses.len)))
|
|
|
|
// Handle light requirements.
|
|
if(!light_supplied)
|
|
if (TURF_IS_DYNAMICALLY_LIT(current_turf))
|
|
light_supplied = current_turf.get_lumcount(0, 3) * 10
|
|
else
|
|
light_supplied = 5
|
|
|
|
if(light_supplied)
|
|
if(abs(light_supplied - get_trait(TRAIT_IDEAL_LIGHT)) > get_trait(TRAIT_LIGHT_TOLERANCE))
|
|
health_change += rand(1,3) * HYDRO_SPEED_MULTIPLIER
|
|
|
|
return health_change
|
|
|
|
/datum/seed/proc/apply_special_effect(var/mob/living/target,var/obj/item/thrown)
|
|
|
|
var/impact = 1
|
|
do_sting(target,thrown)
|
|
do_thorns(target,thrown)
|
|
|
|
return impact
|
|
|
|
/datum/seed/proc/generate_name()
|
|
var/prefix = ""
|
|
var/name = ""
|
|
if(prob(50)) //start with a prefix.
|
|
//These are various plant/mushroom genuses.
|
|
//I realize these might not be entirely accurate, but it could facilitate RP.
|
|
var/list/possible_prefixes
|
|
if(seed_noun == SEED_NOUN_CUTTINGS || seed_noun == SEED_NOUN_SEEDS || (seed_noun == SEED_NOUN_NODES && prob(50)))
|
|
possible_prefixes = list("amelanchier", "saskatoon",
|
|
"magnolia", "angiosperma", "osmunda", "scabiosa", "spigelia", "psydrax", "chastetree",
|
|
"strychnos", "treebine", "caper", "justica", "ragwortus", "everlasting", "combretum",
|
|
"loganiaceae", "gelsemium", "logania", "sabadilla", "neuburgia", "canthium", "rytigynia",
|
|
"chaste", "vitex", "cissus", "capparis", "senecio", "curry", "cycad", "liverwort", "charophyta",
|
|
"glaucophyte", "pinidae", "vascular", "embryophyte", "lillopsida")
|
|
else
|
|
possible_prefixes = list("bisporus", "bitorquis", "campestris", "crocodilinus", "agaricus",
|
|
"armillaria", "matsutake", "mellea", "ponderosa", "auricularia", "auricala",
|
|
"polytricha", "boletus", "badius", "edulis", "mirabilis", "zelleri",
|
|
"calvatia", "gigantea", "clitopilis", "prumulus", "entoloma", "abortivum",
|
|
"suillus", "tuber", "aestivum", "volvacea", "delica", "russula", "rozites")
|
|
possible_prefixes |= list("butter", "shad", "sugar", "june", "wild", "rigus", "curry", "hard", "soft", "dark", "brick", "stone", "red", "brown",
|
|
"black", "white", "paper", "slippery", "honey", "bitter")
|
|
prefix = pick(possible_prefixes)
|
|
var/num = rand(2,5)
|
|
var/list/possible_name = list("rhon", "cus", "quam", "met", "eget", "was", "reg", "zor", "fra", "rat", "sho", "ghen", "pa",
|
|
"eir", "lip", "sum", "lor", "em", "tem", "por", "invi", "dunt", "ut", "la", "bore", "mag", "na",
|
|
"al", "i", "qu", "yam", "er", "at", "sed", "di", "am", "vol", "up", "tua", "at", "ve", "ro", "eos",
|
|
"et", "ac", "cus")
|
|
for(var/i in 1 to num)
|
|
var/syl = pick(possible_name)
|
|
possible_name -= syl
|
|
name += syl
|
|
if(prefix)
|
|
name = "[prefix] [name]"
|
|
seed_name = name
|
|
display_name = name
|
|
display_name = "[name] plant"
|
|
|
|
/// Creates a random seed. MAKE SURE THE LINE HAS DIVERGED BEFORE THIS IS CALLED.
|
|
/datum/seed/proc/randomize(var/list/native_gases = list(GAS_OXYGEN, GAS_NITROGEN, GAS_CO2, GAS_PHORON, GAS_HYDROGEN))
|
|
roundstart = FALSE
|
|
mysterious = TRUE
|
|
|
|
seed_noun = pick(SEED_NOUN_SEEDS, SEED_NOUN_PITS, SEED_NOUN_NODES, SEED_NOUN_CUTTINGS)
|
|
|
|
set_trait(TRAIT_POTENCY,rand(5,30),200,0)
|
|
set_trait(TRAIT_PRODUCT_ICON,pick(SSplants.plant_product_sprites))
|
|
set_trait(TRAIT_PLANT_ICON,pick(SSplants.plant_sprites))
|
|
set_trait(TRAIT_PLANT_COLOUR,get_random_colour(0,75,190))
|
|
set_trait(TRAIT_PRODUCT_COLOUR,get_random_colour(0,75,190))
|
|
update_growth_stages()
|
|
|
|
if(prob(20))
|
|
set_trait(TRAIT_HARVEST_REPEAT,1)
|
|
|
|
if(prob(15))
|
|
if(prob(15))
|
|
set_trait(TRAIT_JUICY,2)
|
|
else
|
|
set_trait(TRAIT_JUICY,1)
|
|
|
|
if(prob(5))
|
|
set_trait(TRAIT_STINGS,1)
|
|
|
|
if(prob(5))
|
|
set_trait(TRAIT_PRODUCES_POWER,1)
|
|
|
|
if(prob(1))
|
|
set_trait(TRAIT_EXPLOSIVE,1)
|
|
else if(prob(1))
|
|
set_trait(TRAIT_TELEPORTING,1)
|
|
|
|
if(prob(5))
|
|
consume_gasses = list()
|
|
var/gas = pick_n_take(native_gases)
|
|
consume_gasses[gas] = rand(3,9)
|
|
|
|
if(prob(5))
|
|
exude_gasses = list()
|
|
var/gas = pick_n_take(native_gases)
|
|
exude_gasses[gas] = rand(3,9)
|
|
|
|
chems = list()
|
|
if(prob(80))
|
|
chems[/singleton/reagent/nutriment] = list(rand(1,10),rand(10,20))
|
|
|
|
var/additional_chems = rand(0,5)
|
|
|
|
if(additional_chems)
|
|
var/list/possible_chems = list(
|
|
/singleton/reagent/acetone,
|
|
/singleton/reagent/alkysine,
|
|
/singleton/reagent/bicaridine,
|
|
/singleton/reagent/butazoline,
|
|
/singleton/reagent/blood,
|
|
/singleton/reagent/cryoxadone,
|
|
/singleton/reagent/drugs/cryptobiolin,
|
|
/singleton/reagent/toxin/cyanide,
|
|
/singleton/reagent/dermaline,
|
|
/singleton/reagent/dexalin,
|
|
/singleton/reagent/ethylredoxrazine,
|
|
/singleton/reagent/hydrazine,
|
|
/singleton/reagent/hyperzine,
|
|
/singleton/reagent/hyronalin,
|
|
/singleton/reagent/drugs/impedrezene,
|
|
/singleton/reagent/mercury,
|
|
/singleton/reagent/drugs/mindbreaker,
|
|
/singleton/reagent/inaprovaline,
|
|
/singleton/reagent/peridaxon,
|
|
/singleton/reagent/toxin/phoron,
|
|
/singleton/reagent/toxin/plasticide,
|
|
/singleton/reagent/potassium,
|
|
/singleton/reagent/radium,
|
|
/singleton/reagent/rezadone,
|
|
/singleton/reagent/ryetalyn,
|
|
/singleton/reagent/slimejelly,
|
|
/singleton/reagent/drugs/mms,
|
|
/singleton/reagent/soporific,
|
|
/singleton/reagent/sugar,
|
|
/singleton/reagent/synaptizine,
|
|
/singleton/reagent/thermite,
|
|
/singleton/reagent/toxin,
|
|
/singleton/reagent/mortaphenyl,
|
|
/singleton/reagent/water,
|
|
/singleton/reagent/woodpulp,
|
|
/singleton/reagent/drugs/ambrosia_extract,
|
|
/singleton/reagent/drugs/skrell_nootropic,
|
|
/singleton/reagent/toxin/berserk
|
|
)
|
|
|
|
for(var/x=1;x<=additional_chems;x++)
|
|
if(!possible_chems.len)
|
|
break
|
|
var/new_chem = pick(possible_chems)
|
|
possible_chems -= new_chem
|
|
chems[new_chem] = list(rand(1,10),rand(10,20))
|
|
|
|
if(prob(90))
|
|
set_trait(TRAIT_REQUIRES_NUTRIENTS,1)
|
|
set_trait(TRAIT_NUTRIENT_CONSUMPTION,rand(25)/25)
|
|
else
|
|
set_trait(TRAIT_REQUIRES_NUTRIENTS,0)
|
|
|
|
if(prob(90))
|
|
set_trait(TRAIT_REQUIRES_WATER,1)
|
|
set_trait(TRAIT_WATER_CONSUMPTION,rand(10))
|
|
else
|
|
set_trait(TRAIT_REQUIRES_WATER,0)
|
|
|
|
set_trait(TRAIT_IDEAL_HEAT, rand(100,400))
|
|
set_trait(TRAIT_HEAT_TOLERANCE, rand(10,30))
|
|
set_trait(TRAIT_IDEAL_LIGHT, rand(2,10))
|
|
set_trait(TRAIT_LIGHT_TOLERANCE, rand(2,7))
|
|
set_trait(TRAIT_TOXINS_TOLERANCE, rand(2,7))
|
|
set_trait(TRAIT_PEST_TOLERANCE, rand(2,7))
|
|
set_trait(TRAIT_WEED_TOLERANCE, rand(2,7))
|
|
set_trait(TRAIT_LOWKPA_TOLERANCE, rand(10,50))
|
|
set_trait(TRAIT_HIGHKPA_TOLERANCE,rand(100,300))
|
|
|
|
if(prob(5))
|
|
set_trait(TRAIT_ALTER_TEMP,rand(-5,5))
|
|
|
|
if(prob(1))
|
|
set_trait(TRAIT_IMMUTABLE,-1)
|
|
|
|
var/carnivore_prob = rand(100)
|
|
if(carnivore_prob < 5)
|
|
set_trait(TRAIT_CARNIVOROUS,2)
|
|
else if(carnivore_prob < 10)
|
|
set_trait(TRAIT_CARNIVOROUS,1)
|
|
|
|
if(prob(10))
|
|
set_trait(TRAIT_PARASITE,1)
|
|
|
|
var/vine_prob = rand(100)
|
|
if(vine_prob < 5)
|
|
set_trait(TRAIT_SPREAD,2)
|
|
else if(vine_prob < 10)
|
|
set_trait(TRAIT_SPREAD,1)
|
|
|
|
if(prob(5))
|
|
set_trait(TRAIT_BIOLUM,1)
|
|
set_trait(TRAIT_BIOLUM_COLOUR,get_random_colour(0,75,190))
|
|
if(prob(5))
|
|
set_trait(TRAIT_BIOLUM_PWR,rand(0,-5)-rand())
|
|
else
|
|
set_trait(TRAIT_BIOLUM_PWR,rand(0,5)+rand())
|
|
|
|
if(prob(5))
|
|
set_trait(TRAIT_SPOROUS,1)
|
|
|
|
set_trait(TRAIT_ENDURANCE,rand(60,100))
|
|
set_trait(TRAIT_YIELD,rand(3,15))
|
|
set_trait(TRAIT_MATURATION,rand(5,15))
|
|
set_trait(TRAIT_PRODUCTION,get_trait(TRAIT_MATURATION)+rand(2,5))
|
|
|
|
generate_name()
|
|
|
|
/// Returns a key corresponding to an entry in the global seed list.
|
|
/datum/seed/proc/get_mutant_variant()
|
|
if(!mutants || !mutants.len || get_trait(TRAIT_IMMUTABLE) > 0) return 0
|
|
return pick(mutants)
|
|
|
|
/// Mutates the plant overall (randomly).
|
|
/datum/seed/proc/mutate(var/degree,var/turf/source_turf)
|
|
|
|
if(!degree || get_trait(TRAIT_IMMUTABLE) > 0) return
|
|
|
|
source_turf.visible_message(SPAN_NOTICE("\The [display_name] quivers!"))
|
|
|
|
//This looks like shit, but it's a lot easier to read/change this way.
|
|
var/total_mutations = rand(1,1+degree)
|
|
for(var/i = 0;i<total_mutations;i++)
|
|
switch(rand(0,11))
|
|
if(0) //Plant cancer!
|
|
set_trait(TRAIT_ENDURANCE,get_trait(TRAIT_ENDURANCE)-rand(10,20),null,0)
|
|
source_turf.visible_message(SPAN_DANGER("\The [display_name] withers rapidly!"))
|
|
if(1)
|
|
set_trait(TRAIT_NUTRIENT_CONSUMPTION,get_trait(TRAIT_NUTRIENT_CONSUMPTION)+rand(-(degree*0.1),(degree*0.1)),5,0)
|
|
set_trait(TRAIT_WATER_CONSUMPTION, get_trait(TRAIT_WATER_CONSUMPTION) +rand(-degree,degree),50,0)
|
|
set_trait(TRAIT_JUICY, !get_trait(TRAIT_JUICY))
|
|
set_trait(TRAIT_STINGS, !get_trait(TRAIT_STINGS))
|
|
if(2)
|
|
set_trait(TRAIT_IDEAL_HEAT, get_trait(TRAIT_IDEAL_HEAT) + (rand(-5,5)*degree),800,70)
|
|
set_trait(TRAIT_HEAT_TOLERANCE, get_trait(TRAIT_HEAT_TOLERANCE) + (rand(-5,5)*degree),800,70)
|
|
set_trait(TRAIT_LOWKPA_TOLERANCE, get_trait(TRAIT_LOWKPA_TOLERANCE)+ (rand(-5,5)*degree),80,0)
|
|
set_trait(TRAIT_HIGHKPA_TOLERANCE, get_trait(TRAIT_HIGHKPA_TOLERANCE)+(rand(-5,5)*degree),500,110)
|
|
set_trait(TRAIT_EXPLOSIVE,1)
|
|
if(3)
|
|
set_trait(TRAIT_IDEAL_LIGHT, get_trait(TRAIT_IDEAL_LIGHT)+(rand(-1,1)*degree),30,0)
|
|
set_trait(TRAIT_LIGHT_TOLERANCE, get_trait(TRAIT_LIGHT_TOLERANCE)+(rand(-2,2)*degree),10,0)
|
|
if(4)
|
|
set_trait(TRAIT_TOXINS_TOLERANCE, get_trait(TRAIT_TOXINS_TOLERANCE)+(rand(-2,2)*degree),10,0)
|
|
if(5)
|
|
set_trait(TRAIT_WEED_TOLERANCE, get_trait(TRAIT_WEED_TOLERANCE)+(rand(-2,2)*degree),10, 0)
|
|
if(prob(degree*5))
|
|
set_trait(TRAIT_CARNIVOROUS, get_trait(TRAIT_CARNIVOROUS)+rand(-degree,degree),2, 0)
|
|
if(get_trait(TRAIT_CARNIVOROUS))
|
|
source_turf.visible_message(SPAN_NOTICE("\The [display_name] shudders hungrily."))
|
|
if(6)
|
|
set_trait(TRAIT_WEED_TOLERANCE, get_trait(TRAIT_WEED_TOLERANCE)+(rand(-2,2)*degree),10, 0)
|
|
if(prob(degree*5))
|
|
set_trait(TRAIT_PARASITE,!get_trait(TRAIT_PARASITE))
|
|
if(7)
|
|
if(get_trait(TRAIT_YIELD) != -1)
|
|
set_trait(TRAIT_YIELD, get_trait(TRAIT_YIELD)+(rand(-2,2)*degree),10,0)
|
|
if(8)
|
|
set_trait(TRAIT_ENDURANCE, get_trait(TRAIT_ENDURANCE)+(rand(-5,5)*degree),100,10)
|
|
set_trait(TRAIT_PRODUCTION, get_trait(TRAIT_PRODUCTION)+(rand(-1,1)*degree),10, 1)
|
|
set_trait(TRAIT_POTENCY, get_trait(TRAIT_POTENCY)+(rand(-20,20)*degree),200, 0)
|
|
if(prob(degree*5))
|
|
set_trait(TRAIT_SPREAD, get_trait(TRAIT_SPREAD)+rand(-1,1),2, 0)
|
|
source_turf.visible_message(SPAN_NOTICE("\The [display_name] spasms visibly, shifting in the tray."))
|
|
if(prob(degree*5))
|
|
set_trait(TRAIT_SPOROUS, !get_trait(TRAIT_SPOROUS))
|
|
if(9)
|
|
set_trait(TRAIT_MATURATION, get_trait(TRAIT_MATURATION)+(rand(-1,1)*degree),30, 0)
|
|
if(prob(degree*5))
|
|
set_trait(TRAIT_HARVEST_REPEAT, !get_trait(TRAIT_HARVEST_REPEAT))
|
|
if(10)
|
|
if(prob(degree*2))
|
|
set_trait(TRAIT_BIOLUM, !get_trait(TRAIT_BIOLUM))
|
|
if(get_trait(TRAIT_BIOLUM))
|
|
source_turf.visible_message(SPAN_NOTICE("\The [display_name] begins to glow!"))
|
|
if(prob(degree*2))
|
|
set_trait(TRAIT_BIOLUM_COLOUR,get_random_colour(0,75,190))
|
|
source_turf.visible_message("<span class='notice'>\The [display_name]'s glow </span><font color='[get_trait(TRAIT_BIOLUM_COLOUR)]'>changes colour</font>!")
|
|
else
|
|
source_turf.visible_message(SPAN_NOTICE("\The [display_name]'s glow dims..."))
|
|
if(11)
|
|
set_trait(TRAIT_TELEPORTING,1)
|
|
|
|
return
|
|
|
|
/// Mutates a specific trait/set of traits.
|
|
/datum/seed/proc/apply_gene(var/datum/plantgene/gene)
|
|
|
|
if(!gene || !gene.values || get_trait(TRAIT_IMMUTABLE) > 0) return
|
|
|
|
// Splicing products has some detrimental effects on yield and lifespan.
|
|
// We handle this before we do the rest of the looping, as normal traits don't really include lists.
|
|
switch(gene.genetype)
|
|
if(GENE_BIOCHEMISTRY)
|
|
for(var/trait in list(TRAIT_YIELD, TRAIT_ENDURANCE))
|
|
if(get_trait(trait) > 0) set_trait(trait,get_trait(trait),null,1,0.85)
|
|
|
|
if(!chems) chems = list()
|
|
|
|
var/list/gene_value = gene.values["[TRAIT_CHEMS]"]
|
|
for(var/rid in gene_value)
|
|
|
|
var/list/gene_chem = gene_value[rid]
|
|
|
|
if(!chems[rid])
|
|
chems[rid] = gene_chem.Copy()
|
|
continue
|
|
|
|
for(var/i=1;i<=gene_chem.len;i++)
|
|
|
|
if(isnull(gene_chem[i])) gene_chem[i] = 0
|
|
|
|
if(chems[rid][i])
|
|
chems[rid][i] = max(1,round((gene_chem[i] + chems[rid][i])/2))
|
|
else
|
|
chems[rid][i] = gene_chem[i]
|
|
|
|
var/list/new_gasses = gene.values["[TRAIT_EXUDE_GASSES]"]
|
|
if(islist(new_gasses))
|
|
if(!exude_gasses) exude_gasses = list()
|
|
exude_gasses |= new_gasses
|
|
for(var/gas in exude_gasses)
|
|
exude_gasses[gas] = max(1,round(exude_gasses[gas]*0.8))
|
|
|
|
gene.values["[TRAIT_EXUDE_GASSES]"] = null
|
|
gene.values["[TRAIT_CHEMS]"] = null
|
|
|
|
if(GENE_DIET)
|
|
var/list/new_gasses = gene.values["[TRAIT_CONSUME_GASSES]"]
|
|
consume_gasses |= new_gasses
|
|
gene.values["[TRAIT_CONSUME_GASSES]"] = null
|
|
if(GENE_METABOLISM)
|
|
product_type = gene.values["product_type"]
|
|
gene.values["product_type"] = null
|
|
|
|
for(var/trait in gene.values)
|
|
set_trait(trait,gene.values["[trait]"])
|
|
|
|
update_growth_stages()
|
|
|
|
/// Returns a list of the desired trait values.
|
|
/datum/seed/proc/get_gene(var/genetype)
|
|
|
|
if(!genetype) return 0
|
|
|
|
var/list/traits_to_copy
|
|
var/datum/plantgene/P = new()
|
|
P.genetype = genetype
|
|
P.values = list()
|
|
|
|
switch(genetype)
|
|
if(GENE_BIOCHEMISTRY)
|
|
P.values["[TRAIT_CHEMS]"] = chems
|
|
P.values["[TRAIT_EXUDE_GASSES]"] = exude_gasses
|
|
traits_to_copy = list(TRAIT_POTENCY)
|
|
if(GENE_OUTPUT)
|
|
traits_to_copy = list(TRAIT_PRODUCES_POWER,TRAIT_BIOLUM, TRAIT_BIOLUM_PWR)
|
|
if(GENE_ATMOSPHERE)
|
|
traits_to_copy = list(TRAIT_HEAT_TOLERANCE,TRAIT_LOWKPA_TOLERANCE,TRAIT_HIGHKPA_TOLERANCE)
|
|
if(GENE_HARDINESS)
|
|
traits_to_copy = list(TRAIT_TOXINS_TOLERANCE,TRAIT_PEST_TOLERANCE,TRAIT_WEED_TOLERANCE,TRAIT_ENDURANCE)
|
|
if(GENE_METABOLISM)
|
|
P.values["product_type"] = product_type
|
|
traits_to_copy = list(TRAIT_REQUIRES_NUTRIENTS,TRAIT_REQUIRES_WATER,TRAIT_ALTER_TEMP)
|
|
if(GENE_VIGOUR)
|
|
traits_to_copy = list(TRAIT_PRODUCTION,TRAIT_MATURATION,TRAIT_YIELD,TRAIT_SPREAD)
|
|
if(GENE_DIET)
|
|
P.values["[TRAIT_CONSUME_GASSES]"] = consume_gasses
|
|
traits_to_copy = list(TRAIT_CARNIVOROUS,TRAIT_PARASITE,TRAIT_NUTRIENT_CONSUMPTION,TRAIT_WATER_CONSUMPTION)
|
|
if(GENE_ENVIRONMENT)
|
|
traits_to_copy = list(TRAIT_IDEAL_HEAT,TRAIT_IDEAL_LIGHT,TRAIT_LIGHT_TOLERANCE)
|
|
if(GENE_PIGMENT)
|
|
traits_to_copy = list(TRAIT_PLANT_COLOUR,TRAIT_PRODUCT_COLOUR,TRAIT_BIOLUM_COLOUR,TRAIT_LEAVES_COLOUR)
|
|
if(GENE_STRUCTURE)
|
|
traits_to_copy = list(TRAIT_PLANT_ICON,TRAIT_PRODUCT_ICON,TRAIT_HARVEST_REPEAT, TRAIT_SPOROUS, TRAIT_LARGE)
|
|
if(GENE_FRUIT)
|
|
traits_to_copy = list(TRAIT_STINGS,TRAIT_EXPLOSIVE,TRAIT_FLESH_COLOUR,TRAIT_JUICY)
|
|
if(GENE_SPECIAL)
|
|
traits_to_copy = list(TRAIT_TELEPORTING)
|
|
|
|
for(var/trait in traits_to_copy)
|
|
P.values["[trait]"] = get_trait(trait)
|
|
return (P ? P : 0)
|
|
|
|
/// Place the plant products at the feet of the user.
|
|
/datum/seed/proc/harvest(var/mob/user,var/yield_mod,var/harvest_sample,var/force_amount)
|
|
if(!user)
|
|
return
|
|
|
|
if(!force_amount && get_trait(TRAIT_YIELD) == 0 && !harvest_sample)
|
|
if(istype(user)) to_chat(user, SPAN_DANGER("You fail to harvest anything useful."))
|
|
else
|
|
if(istype(user)) to_chat(user, "You [harvest_sample ? "take a sample" : "harvest"] from the [display_name].")
|
|
|
|
//This may be a new line. Update the global if it is.
|
|
if(name == "new line" || !(name in SSplants.seeds))
|
|
uid = SSplants.seeds.len + 1
|
|
name = "[uid]"
|
|
SSplants.seeds[name] = src
|
|
|
|
if(harvest_sample)
|
|
var/obj/item/seeds/seeds = new(get_turf(user))
|
|
seeds.seed_type = name
|
|
seeds.update_seed()
|
|
return
|
|
|
|
var/total_yield = 0
|
|
if(!isnull(force_amount))
|
|
total_yield = force_amount
|
|
else
|
|
if(get_trait(TRAIT_YIELD) > -1)
|
|
if(isnull(yield_mod) || yield_mod < 1)
|
|
yield_mod = 0
|
|
total_yield = get_trait(TRAIT_YIELD)
|
|
else
|
|
total_yield = get_trait(TRAIT_YIELD) + rand(yield_mod)
|
|
total_yield = max(1,total_yield)
|
|
|
|
for(var/i = 0;i<total_yield;i++)
|
|
spawn_seed(get_turf(user))
|
|
|
|
/datum/seed/proc/spawn_seed(var/turf/spawning_loc)
|
|
var/obj/item/product = new product_type(spawning_loc, name)
|
|
// Set descriptions
|
|
if(product_desc)
|
|
product.desc = product_desc
|
|
if(product_desc_extended)
|
|
product.desc_extended = product_desc_extended
|
|
|
|
if(get_trait(TRAIT_PRODUCT_COLOUR))
|
|
if(istype(product, /obj/item/reagent_containers/food))
|
|
var/obj/item/reagent_containers/food/food = product
|
|
food.color = get_trait(TRAIT_PRODUCT_COLOUR)
|
|
food.filling_color = get_trait(TRAIT_PRODUCT_COLOUR)
|
|
|
|
if(mysterious)
|
|
product.name += "?"
|
|
product.desc += " On second thought, something about this one looks strange."
|
|
|
|
if(get_trait(TRAIT_BIOLUM))
|
|
var/pwr
|
|
if(get_trait(TRAIT_BIOLUM_PWR) == 0)
|
|
pwr = get_trait(TRAIT_BIOLUM)
|
|
else
|
|
pwr = get_trait(TRAIT_BIOLUM_PWR)
|
|
var/clr
|
|
if(get_trait(TRAIT_BIOLUM_COLOUR))
|
|
clr = get_trait(TRAIT_BIOLUM_COLOUR)
|
|
product.set_light(get_trait(TRAIT_POTENCY)/10, pwr, clr)
|
|
addtimer(CALLBACK(product, TYPE_PROC_REF(/atom, set_light), 0), rand(5 MINUTES, 7 MINUTES))
|
|
|
|
//Handle spawning in living, mobile products (like dionaea).
|
|
if(istype(product,/mob/living))
|
|
product.visible_message(SPAN_NOTICE("The pod disgorges [product]!"))
|
|
handle_living_product(product)
|
|
if(istype(product,/mob/living/simple_animal/mushroom)) // Gross.
|
|
var/mob/living/simple_animal/mushroom/mush = product
|
|
mush.seed = src
|
|
|
|
/** When the seed in this machine mutates/is modified, the tray seed value
|
|
is set to a new datum copied from the original. This datum won't actually
|
|
be put into the global datum list until the product is harvested, though. */
|
|
/datum/seed/proc/diverge(var/modified)
|
|
|
|
if(get_trait(TRAIT_IMMUTABLE) > 0) return
|
|
|
|
//Set up some basic information.
|
|
var/datum/seed/new_seed = new
|
|
new_seed.name = "new line"
|
|
new_seed.uid = 0
|
|
new_seed.roundstart = 0
|
|
new_seed.can_self_harvest = can_self_harvest
|
|
new_seed.kitchen_tag = kitchen_tag
|
|
new_seed.trash_type = trash_type
|
|
new_seed.product_type = product_type
|
|
//Copy over everything else.
|
|
if(mutants) new_seed.mutants = mutants.Copy()
|
|
if(chems) new_seed.chems = chems.Copy()
|
|
if(consume_gasses) new_seed.consume_gasses = consume_gasses.Copy()
|
|
if(exude_gasses) new_seed.exude_gasses = exude_gasses.Copy()
|
|
|
|
new_seed.seed_name = "[(roundstart ? "[(modified ? "modified" : "mutant")] " : "")][seed_name]"
|
|
new_seed.display_name = "[(roundstart ? "[(modified ? "modified" : "mutant")] " : "")][display_name]"
|
|
new_seed.seed_noun = seed_noun
|
|
new_seed.traits = traits.Copy()
|
|
new_seed.update_growth_stages()
|
|
return new_seed
|
|
|
|
/datum/seed/proc/update_growth_stages()
|
|
if(get_trait(TRAIT_PLANT_ICON))
|
|
growth_stages = SSplants.plant_sprites[get_trait(TRAIT_PLANT_ICON)]
|
|
else
|
|
growth_stages = 0
|
|
|
|
/datum/seed/proc/get_growth_type()
|
|
SHOULD_NOT_SLEEP(TRUE)
|
|
SHOULD_BE_PURE(TRUE)
|
|
|
|
if(get_trait(TRAIT_SPREAD) == 2)
|
|
switch(seed_noun)
|
|
if(SEED_NOUN_CUTTINGS)
|
|
return GROWTH_WORMS
|
|
if(SEED_NOUN_NODES)
|
|
return GROWTH_BIOMASS
|
|
if(SEED_NOUN_SPORES)
|
|
return GROWTH_MOLD
|
|
else
|
|
return GROWTH_VINES
|
|
return 0
|
|
|
|
/**
|
|
* A list of seed icons, to avoid regenerating images like there's no tomorrow
|
|
*
|
|
* Only access this by using the `SEED_ICON_CACHE_KEY` macro
|
|
*
|
|
* The structure is an associative list with the result of `SEED_ICON_CACHE_KEY` as the key
|
|
* and an `/image` as the value
|
|
*/
|
|
GLOBAL_LIST_INIT(seed_icon_cache, list())
|
|
|
|
///Generates a text hash that works as the key for the `seed_icon_cache` GLOB list
|
|
#define SEED_ICON_CACHE_KEY(file, state, color, leaves_overlay) "[file]|||[state]|||[color]|||[leaves_overlay]"
|
|
|
|
/datum/seed/proc/get_icon(growth_stage)
|
|
SHOULD_NOT_SLEEP(TRUE)
|
|
RETURN_TYPE(/image)
|
|
|
|
if(isnull(growth_stage))
|
|
crash_with("No growth stage was supplied when getting the icon!")
|
|
|
|
/* Setup a bunch of shit that should have been done in a very different way but alas */
|
|
|
|
//The icon of the plant
|
|
var/icon_trait = get_trait(TRAIT_PLANT_ICON)
|
|
//The type of growth
|
|
var/growth_type = get_growth_type()
|
|
//If it's a vine
|
|
var/is_vine = (get_trait(TRAIT_SPREAD) == 2)
|
|
//If the icon is a large one
|
|
var/is_large_icon = get_trait(TRAIT_LARGE)
|
|
//The color of the leaves, if any
|
|
var/leaves_color = get_trait(TRAIT_LEAVES_COLOUR)
|
|
|
|
/* The part where we select what to request */
|
|
|
|
//Pick what file we want
|
|
var/icon_file_to_request
|
|
if(is_vine)
|
|
icon_file_to_request = 'icons/obj/hydroponics_vines.dmi'
|
|
else if(is_large_icon)
|
|
icon_file_to_request = 'icons/obj/hydroponics_large.dmi'
|
|
else
|
|
icon_file_to_request = 'icons/obj/hydroponics_growing.dmi'
|
|
|
|
//Pick what icon state to request
|
|
var/icon_state_to_request = (is_vine) ? "[growth_type]-[growth_stage]" : "[icon_trait]-[growth_stage]"
|
|
|
|
//Pick the color to assign to the image
|
|
var/color_to_request = get_trait(TRAIT_PLANT_COLOUR)
|
|
|
|
//The leaves color overlay to request
|
|
var/leaves_overlay_to_request = (leaves_color) ? "[icon_trait]-[growth_stage]-leaves" : null
|
|
|
|
/* Find or generate the image and return it */
|
|
|
|
//See if we have this in our cache
|
|
if(SEED_ICON_CACHE_KEY(icon_file_to_request, icon_state_to_request, color_to_request, leaves_overlay_to_request) in GLOB.seed_icon_cache)
|
|
return GLOB.seed_icon_cache[SEED_ICON_CACHE_KEY(icon_file_to_request, icon_state_to_request, color_to_request, leaves_overlay_to_request)]
|
|
|
|
//No luck, it's not in the cache, time to generate it
|
|
else
|
|
|
|
//Check that there's a valid icon state we can use, abort otherwise
|
|
var/valid_icon_states = icon_states(icon_file_to_request, 2)
|
|
if(!(icon_state_to_request in valid_icon_states))
|
|
crash_with("A seed icon was requested with an invalid icon state! Icon file: [icon_file_to_request] ---- Icon state: [icon_state_to_request]")
|
|
|
|
var/image/generated_image = image(icon_file_to_request, icon_state_to_request)
|
|
|
|
//Assign the requested
|
|
generated_image.color = color_to_request
|
|
|
|
//If it's a large icon, offset it
|
|
if(is_large_icon)
|
|
generated_image.pixel_x = -8
|
|
generated_image.pixel_y = -16
|
|
|
|
//If leaves are requested, add them as overlays
|
|
if(leaves_overlay_to_request)
|
|
var/image/leaves_image = image(icon_file_to_request, leaves_overlay_to_request)
|
|
leaves_image.color = leaves_color
|
|
leaves_image.appearance_flags = RESET_COLOR
|
|
//Add ourself as overlays to the generated image
|
|
generated_image.AddOverlays(leaves_image)
|
|
|
|
//Store the image in the cache, so we won't have to keep generating it
|
|
GLOB.seed_icon_cache[SEED_ICON_CACHE_KEY(icon_file_to_request, icon_state_to_request, color_to_request, leaves_overlay_to_request)] = generated_image
|
|
|
|
//Return the image
|
|
return generated_image
|
|
|
|
#undef SEED_ICON_CACHE_KEY
|