mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-24 16:13:20 +00:00
## About The Pull Request Further continous organizing and cleaning the Icons folder. There are still some minior nitpicks left to do, but I reached my daily sanity expenses limit again, and the faster these get in the less issues for both me and others later. Also cleans some mess I caused by my blindness last PR. ## Why It's Good For The Game Saner spriters = better sprites
945 lines
35 KiB
Plaintext
945 lines
35 KiB
Plaintext
/// Plant gene datums - things that build and modify a plant or seed.
|
|
/datum/plant_gene
|
|
/// The name of the gene.
|
|
var/name
|
|
/// The font awesome icon name representing the gene in the seed extractor UI
|
|
var/icon = "dna"
|
|
/// Flags that determine if a gene can be modified.
|
|
var/mutability_flags
|
|
|
|
/*
|
|
* Returns the formatted name of the plant gene.
|
|
*
|
|
* Overridden by the various subtypes of plant genes to format their respective names.
|
|
*/
|
|
/datum/plant_gene/proc/get_name()
|
|
return name
|
|
|
|
/*
|
|
* Check if the seed can accept this plant gene.
|
|
*
|
|
* our_seed - the seed we're adding the gene to
|
|
*
|
|
* Returns TRUE if the seed can take the gene, and FALSE otherwise.
|
|
*/
|
|
/datum/plant_gene/proc/can_add(obj/item/seeds/our_seed)
|
|
return !istype(our_seed, /obj/item/seeds/sample) // Samples can't accept new genes.
|
|
|
|
/// Copies over vars and information about our current gene to a new gene and returns the new instance of gene.
|
|
/datum/plant_gene/proc/Copy()
|
|
var/datum/plant_gene/new_gene = new type
|
|
new_gene.mutability_flags = mutability_flags
|
|
return new_gene
|
|
|
|
/*
|
|
* on_new_seed is called when seed genes are initialized on the /obj/seed.
|
|
*
|
|
* new_seed - the seed being created
|
|
*/
|
|
/datum/plant_gene/proc/on_new_seed(obj/item/seeds/new_seed)
|
|
return // Not implemented
|
|
|
|
/*
|
|
* on_removed is called when the gene is removed from a seed.
|
|
* Also called when a seed is qdel'd (and all the genes are removed and deleted).
|
|
*
|
|
* old_seed - our seed, before being removed
|
|
*/
|
|
/datum/plant_gene/proc/on_removed(obj/item/seeds/old_seed)
|
|
return // Not implemented
|
|
|
|
/// Reagent genes store a reagent ID and reagent ratio.
|
|
/datum/plant_gene/reagent
|
|
name = "UNKNOWN"
|
|
mutability_flags = PLANT_GENE_REMOVABLE
|
|
/// The typepath of the actual reagent that this gene is tied to.
|
|
var/reagent_id = /datum/reagent/consumable/nutriment
|
|
/// The amount of reagent generated by the plant. The equation is [1 + ((max_volume*(potency/100)) * rate)]
|
|
var/rate = 0.04
|
|
|
|
/datum/plant_gene/reagent/get_name()
|
|
var/formatted_name
|
|
if(!(mutability_flags & PLANT_GENE_REMOVABLE))
|
|
formatted_name += "Fragile "
|
|
formatted_name += "[name] production [rate*100]%"
|
|
return formatted_name
|
|
|
|
/*
|
|
* Set our reagent's ID and name to the passed reagent.
|
|
*
|
|
* new_reagent_id - typepath of the reagent we're setting this gene to
|
|
*/
|
|
/datum/plant_gene/reagent/proc/set_reagent(new_reagent_id)
|
|
reagent_id = new_reagent_id
|
|
|
|
var/datum/reagent/found_reagent = GLOB.chemical_reagents_list[new_reagent_id]
|
|
if(found_reagent?.type == reagent_id)
|
|
name = found_reagent.name
|
|
|
|
/datum/plant_gene/reagent/New(new_reagent_id, new_reagent_rate = 0.04)
|
|
. = ..()
|
|
if(new_reagent_id)
|
|
set_reagent(new_reagent_id)
|
|
rate = new_reagent_rate
|
|
|
|
/datum/plant_gene/reagent/Copy()
|
|
. = ..()
|
|
var/datum/plant_gene/reagent/new_reagent_gene = .
|
|
new_reagent_gene.name = name
|
|
new_reagent_gene.reagent_id = reagent_id
|
|
new_reagent_gene.rate = rate
|
|
return
|
|
|
|
/datum/plant_gene/reagent/can_add(obj/item/seeds/our_seed)
|
|
. = ..()
|
|
if(!.)
|
|
return FALSE
|
|
for(var/datum/plant_gene/reagent/seed_reagent in our_seed.genes)
|
|
if(seed_reagent.reagent_id == reagent_id && seed_reagent.rate <= rate)
|
|
return FALSE // We can upgrade reagent genes if our rate is greater than the one already in the plant.
|
|
return TRUE
|
|
|
|
/**
|
|
* Intends to compare a reagent gene with a set of seeds, and if the seeds contain the same gene, with more production rate, upgrades the rate to the highest of the two.
|
|
*
|
|
* Called when plants are crossbreeding, this looks for two matching reagent_ids, where the rates are greater, in order to upgrade.
|
|
*/
|
|
/datum/plant_gene/reagent/proc/try_upgrade_gene(obj/item/seeds/seed)
|
|
for(var/datum/plant_gene/reagent/reagent in seed.genes)
|
|
if(reagent.reagent_id != reagent_id || reagent.rate <= rate)
|
|
continue
|
|
rate = reagent.rate
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/// Traits that affect the grown product.
|
|
/datum/plant_gene/trait
|
|
/// The rate at which this trait affects something. This can be anything really - why? I dunno.
|
|
var/rate = 0.05
|
|
/// Bonus lines displayed on examine.
|
|
var/description = ""
|
|
/// Flag - Traits that share an ID cannot be placed on the same plant.
|
|
var/trait_ids
|
|
/// Flag - Modifications made to the final product.
|
|
var/trait_flags
|
|
/// A blacklist of seeds that a trait cannot be attached to.
|
|
var/list/obj/item/seeds/seed_blacklist
|
|
|
|
/datum/plant_gene/trait/Copy()
|
|
. = ..()
|
|
var/datum/plant_gene/trait/new_trait_gene = .
|
|
new_trait_gene.rate = rate
|
|
return
|
|
|
|
/datum/plant_gene/trait/get_name() // Used for manipulator display and gene disk name.
|
|
var/formatted_name
|
|
if(!(mutability_flags & PLANT_GENE_REMOVABLE))
|
|
if(!(mutability_flags & PLANT_GENE_GRAFTABLE))
|
|
formatted_name += "Immutable "
|
|
else
|
|
formatted_name += "Essential "
|
|
formatted_name += name
|
|
return formatted_name
|
|
|
|
/*
|
|
* Checks if we can add the trait to the seed in question.
|
|
*
|
|
* source_seed - the seed genes we're adding the trait too
|
|
*/
|
|
/datum/plant_gene/trait/can_add(obj/item/seeds/source_seed)
|
|
. = ..()
|
|
if(!.)
|
|
return FALSE
|
|
|
|
for(var/obj/item/seeds/found_seed as anything in seed_blacklist)
|
|
if(istype(source_seed, found_seed))
|
|
return FALSE
|
|
|
|
for(var/datum/plant_gene/trait/trait in source_seed.genes)
|
|
if(trait_ids & trait.trait_ids)
|
|
return FALSE
|
|
if(type == trait.type)
|
|
return FALSE
|
|
|
|
return TRUE
|
|
|
|
/*
|
|
* on_new_plant is called for every plant trait on an /obj/item/grown or /obj/item/food/grown when initialized.
|
|
*
|
|
* our_plant - the source plant being created
|
|
* newloc - the loc of the plant
|
|
*/
|
|
/datum/plant_gene/trait/proc/on_new_plant(obj/item/our_plant, newloc)
|
|
// Plants should always have seeds, but if a plant gene is somehow being instantiated on a plant with no seed, stop initializing genes
|
|
// (Plants hold their genes on their seeds, so we can't really add them to something that doesn't exist)
|
|
if(isnull(our_plant.get_plant_seed()))
|
|
stack_trace("[our_plant] ([our_plant.type]) has a nulled seed value while trying to initialize [src]!")
|
|
return FALSE
|
|
|
|
// Add on any bonus lines on examine
|
|
if(description)
|
|
RegisterSignal(our_plant, COMSIG_ATOM_EXAMINE, PROC_REF(examine))
|
|
return TRUE
|
|
|
|
/// Add on any unique examine text to the plant's examine text.
|
|
/datum/plant_gene/trait/proc/examine(obj/item/our_plant, mob/examiner, list/examine_list)
|
|
SIGNAL_HANDLER
|
|
|
|
examine_list += span_info("[description]")
|
|
|
|
/// Allows the plant to be squashed when thrown or slipped on, leaving a colored mess and trash type item behind.
|
|
/datum/plant_gene/trait/squash
|
|
name = "Liquid Contents"
|
|
icon = "droplet"
|
|
description = "It may burst open from the internal pressure on impact."
|
|
trait_ids = THROW_IMPACT_ID | REAGENT_TRANSFER_ID | ATTACK_SELF_ID
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
// Register a signal that our plant can be squashed on add.
|
|
/datum/plant_gene/trait/squash/on_new_plant(obj/item/food/grown/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
RegisterSignal(our_plant, COMSIG_PLANT_ON_SLIP, PROC_REF(squash_plant))
|
|
RegisterSignal(our_plant, COMSIG_MOVABLE_IMPACT, PROC_REF(squash_plant))
|
|
RegisterSignal(our_plant, COMSIG_ITEM_ATTACK_SELF, PROC_REF(squash_plant))
|
|
|
|
/*
|
|
* Signal proc to squash the plant this trait belongs to, causing a smudge, exposing the target to reagents, and deleting it,
|
|
*
|
|
* Arguments
|
|
* our_plant - the plant this trait belongs to.
|
|
* target - the atom being hit by this squashed plant.
|
|
*/
|
|
/datum/plant_gene/trait/squash/proc/squash_plant(obj/item/food/grown/our_plant, atom/target)
|
|
SIGNAL_HANDLER
|
|
|
|
var/turf/our_turf = get_turf(target)
|
|
our_plant.forceMove(our_turf)
|
|
if(istype(our_plant))
|
|
if(ispath(our_plant.splat_type, /obj/effect/decal/cleanable/food/plant_smudge))
|
|
var/obj/plant_smudge = new our_plant.splat_type(our_turf)
|
|
plant_smudge.name = "[our_plant.name] smudge"
|
|
if(our_plant.filling_color)
|
|
plant_smudge.color = our_plant.filling_color
|
|
else if(our_plant.splat_type)
|
|
new our_plant.splat_type(our_turf)
|
|
else
|
|
var/obj/effect/decal/cleanable/food/plant_smudge/misc_smudge = new(our_turf)
|
|
misc_smudge.name = "[our_plant.name] smudge"
|
|
misc_smudge.color = "#82b900"
|
|
|
|
our_plant.visible_message(span_warning("[our_plant] is squashed."),span_hear("You hear a smack."))
|
|
SEND_SIGNAL(our_plant, COMSIG_PLANT_ON_SQUASH, target)
|
|
|
|
our_plant.reagents?.expose(our_turf)
|
|
for(var/things in our_turf)
|
|
our_plant.reagents?.expose(things)
|
|
|
|
qdel(our_plant)
|
|
|
|
/*
|
|
* Makes plant slippery, unless it has a grown-type trash. Then the trash gets slippery.
|
|
* Applies other trait effects (teleporting, etc) to the target by signal.
|
|
*/
|
|
/datum/plant_gene/trait/slip
|
|
name = "Slippery Skin"
|
|
description = "Watch your step around this."
|
|
icon = "person-falling"
|
|
rate = 1.6
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/slip/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
var/obj/item/food/grown/grown_plant = our_plant
|
|
if(istype(grown_plant) && ispath(grown_plant.trash_type, /obj/item/grown))
|
|
return
|
|
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
var/stun_len = our_seed.potency * rate
|
|
|
|
if(!istype(our_plant, /obj/item/grown/bananapeel) && (!our_plant.reagents || !our_plant.reagents.has_reagent(/datum/reagent/lube)))
|
|
stun_len /= 3
|
|
|
|
our_plant.AddComponent(/datum/component/slippery, min(stun_len, 140), NONE, CALLBACK(src, PROC_REF(handle_slip), our_plant))
|
|
|
|
/// On slip, sends a signal that our plant was slipped on out.
|
|
/datum/plant_gene/trait/slip/proc/handle_slip(obj/item/food/grown/our_plant, mob/slipped_target)
|
|
SEND_SIGNAL(our_plant, COMSIG_PLANT_ON_SLIP, slipped_target)
|
|
|
|
/*
|
|
* Cell recharging trait. Charges all mob's power cells to (potency*rate)% mark when eaten.
|
|
* Generates sparks on squash.
|
|
* Small (potency * rate) chance to shock squish or slip target for (potency * rate) damage.
|
|
* Also affects plant batteries see capatative cell production datum
|
|
*/
|
|
/datum/plant_gene/trait/cell_charge
|
|
name = "Electrical Activity"
|
|
description = "It can electrocute on interaction or recharge batteries when eaten."
|
|
icon = "bolt"
|
|
rate = 0.2
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/cell_charge/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
if(our_seed.get_gene(/datum/plant_gene/trait/squash))
|
|
// If we have the squash gene, let that handle slipping
|
|
RegisterSignal(our_plant, COMSIG_PLANT_ON_SQUASH, PROC_REF(zap_target))
|
|
else
|
|
RegisterSignal(our_plant, COMSIG_PLANT_ON_SLIP, PROC_REF(zap_target))
|
|
|
|
RegisterSignal(our_plant, COMSIG_FOOD_EATEN, PROC_REF(recharge_cells))
|
|
|
|
/*
|
|
* Zaps the target with a stunning shock.
|
|
*
|
|
* our_plant - our source plant, shocking the target
|
|
* target - the atom being zapped by our plant
|
|
*/
|
|
/datum/plant_gene/trait/cell_charge/proc/zap_target(obj/item/our_plant, atom/target)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!iscarbon(target))
|
|
return
|
|
|
|
our_plant.investigate_log("zapped [key_name(target)] at [AREACOORD(target)]. Last touched by: [our_plant.fingerprintslast].", INVESTIGATE_BOTANY)
|
|
var/mob/living/carbon/target_carbon = target
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
var/power = our_seed.potency * rate
|
|
if(prob(power))
|
|
target_carbon.electrocute_act(round(power), our_plant, 1, SHOCK_NOGLOVES)
|
|
|
|
/*
|
|
* Recharges every cell the person is holding for a bit based on plant potency.
|
|
*
|
|
* our_plant - our source plant, that we consumed to charge the cells
|
|
* eater - the mob that bit the plant
|
|
* feeder - the mob that feed the eater the plant
|
|
*/
|
|
/datum/plant_gene/trait/cell_charge/proc/recharge_cells(obj/item/our_plant, mob/living/eater, mob/feeder)
|
|
SIGNAL_HANDLER
|
|
|
|
to_chat(eater, span_notice("You feel energized as you bite into [our_plant]."))
|
|
var/batteries_recharged = FALSE
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
for(var/obj/item/stock_parts/cell/found_cell in eater.get_all_contents())
|
|
var/newcharge = min(our_seed.potency * 0.01 * found_cell.maxcharge, found_cell.maxcharge)
|
|
if(found_cell.charge < newcharge)
|
|
found_cell.charge = newcharge
|
|
if(isobj(found_cell.loc))
|
|
var/obj/cell_location = found_cell.loc
|
|
cell_location.update_appearance() //update power meters and such
|
|
found_cell.update_appearance()
|
|
batteries_recharged = TRUE
|
|
if(batteries_recharged)
|
|
to_chat(eater, span_notice("Your batteries are recharged!"))
|
|
|
|
/*
|
|
* Makes the plant glow. Makes the plant in tray glow, too.
|
|
* Adds (1.4 + potency * rate) light range and (potency * (rate + 0.01)) light_power to products.
|
|
*/
|
|
/datum/plant_gene/trait/glow
|
|
name = "Bioluminescence"
|
|
icon = "lightbulb"
|
|
rate = 0.03
|
|
description = "It emits a soft glow."
|
|
trait_ids = GLOW_ID
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
/// The color of our bioluminescence.
|
|
var/glow_color = COLOR_BIOLUMINESCENCE_STANDARD
|
|
|
|
/datum/plant_gene/trait/glow/proc/glow_range(obj/item/seeds/seed)
|
|
return 1.4 + seed.potency * rate
|
|
|
|
/datum/plant_gene/trait/glow/proc/glow_power(obj/item/seeds/seed)
|
|
return max(seed.potency * (rate + 0.01), 0.1)
|
|
|
|
/datum/plant_gene/trait/glow/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
our_plant.light_system = MOVABLE_LIGHT
|
|
our_plant.AddComponent(/datum/component/overlay_lighting, glow_range(our_seed), glow_power(our_seed), glow_color)
|
|
|
|
/*
|
|
* Makes plant emit darkness. (Purple-ish shadows)
|
|
* Adds - (potency * (rate * 0.2)) light power to products.
|
|
*/
|
|
/datum/plant_gene/trait/glow/shadow
|
|
name = "Shadow Emission"
|
|
icon = "lightbulb-o"
|
|
rate = 0.04
|
|
glow_color = COLOR_BIOLUMINESCENCE_SHADOW
|
|
|
|
/datum/plant_gene/trait/glow/shadow/glow_power(obj/item/seeds/seed)
|
|
return -max(seed.potency*(rate*0.2), 0.2)
|
|
|
|
/// Colored versions of bioluminescence.
|
|
|
|
/// White
|
|
/datum/plant_gene/trait/glow/white
|
|
name = "White Bioluminescence"
|
|
glow_color = COLOR_WHITE
|
|
|
|
/// Red
|
|
/datum/plant_gene/trait/glow/red
|
|
name = "Red Bioluminescence"
|
|
glow_color = COLOR_RED_LIGHT
|
|
|
|
/// Yellow (not the disgusting glowshroom yellow hopefully)
|
|
/datum/plant_gene/trait/glow/yellow
|
|
name = "Yellow Bioluminescence"
|
|
glow_color = COLOR_BIOLUMINESCENCE_YELLOW
|
|
|
|
/// Green (oh no, now i'm radioactive)
|
|
/datum/plant_gene/trait/glow/green
|
|
name = "Green Bioluminescence"
|
|
glow_color = COLOR_BIOLUMINESCENCE_GREEN
|
|
|
|
/// Blue (the best one)
|
|
/datum/plant_gene/trait/glow/blue
|
|
name = "Blue Bioluminescence"
|
|
glow_color = COLOR_BIOLUMINESCENCE_BLUE
|
|
|
|
/// Purple (did you know that notepad++ doesnt think bioluminescence is a word) (was the person who wrote this using notepad++ for dm?)
|
|
/datum/plant_gene/trait/glow/purple
|
|
name = "Purple Bioluminescence"
|
|
glow_color = COLOR_BIOLUMINESCENCE_PURPLE
|
|
|
|
// Pink (gay tide station pride)
|
|
/datum/plant_gene/trait/glow/pink
|
|
name = "Pink Bioluminescence"
|
|
glow_color = COLOR_BIOLUMINESCENCE_PINK
|
|
|
|
/*
|
|
* Makes plant teleport people when squashed or slipped on.
|
|
* Teleport radius is roughly potency / 10.
|
|
*/
|
|
/datum/plant_gene/trait/teleport
|
|
name = "Bluespace Activity"
|
|
description = "It causes people to teleport on interaction."
|
|
icon = "right-left"
|
|
rate = 0.1
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/teleport/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
if(our_seed.get_gene(/datum/plant_gene/trait/squash))
|
|
// If we have the squash gene, let that handle slipping
|
|
RegisterSignal(our_plant, COMSIG_PLANT_ON_SQUASH, PROC_REF(squash_teleport))
|
|
else
|
|
RegisterSignal(our_plant, COMSIG_PLANT_ON_SLIP, PROC_REF(slip_teleport))
|
|
|
|
/*
|
|
* When squashed, makes the target teleport.
|
|
*
|
|
* our_plant - our plant, being squashed, and teleporting the target
|
|
* target - the atom targeted by the squash
|
|
*/
|
|
/datum/plant_gene/trait/teleport/proc/squash_teleport(obj/item/our_plant, atom/target)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!isliving(target))
|
|
return
|
|
|
|
our_plant.investigate_log("squash-teleported [key_name(target)] at [AREACOORD(target)]. Last touched by: [our_plant.fingerprintslast].", INVESTIGATE_BOTANY)
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
var/teleport_radius = max(round(our_seed.potency / 10), 1)
|
|
var/turf/T = get_turf(target)
|
|
new /obj/effect/decal/cleanable/molten_object(T) //Leave a pile of goo behind for dramatic effect...
|
|
do_teleport(target, T, teleport_radius, channel = TELEPORT_CHANNEL_BLUESPACE)
|
|
|
|
/*
|
|
* When slipped on, makes the target teleport and either teleport the source again or delete it.
|
|
*
|
|
* our_plant - our plant being slipped on
|
|
* target - the carbon targeted that was slipped and was teleported
|
|
*/
|
|
/datum/plant_gene/trait/teleport/proc/slip_teleport(obj/item/our_plant, mob/living/carbon/target)
|
|
SIGNAL_HANDLER
|
|
|
|
our_plant.investigate_log("slip-teleported [key_name(target)] at [AREACOORD(target)]. Last touched by: [our_plant.fingerprintslast].", INVESTIGATE_BOTANY)
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
var/teleport_radius = max(round(our_seed.potency / 10), 1)
|
|
var/turf/T = get_turf(target)
|
|
to_chat(target, span_warning("You slip through spacetime!"))
|
|
do_teleport(target, T, teleport_radius, channel = TELEPORT_CHANNEL_BLUESPACE)
|
|
if(prob(50))
|
|
do_teleport(our_plant, T, teleport_radius, channel = TELEPORT_CHANNEL_BLUESPACE)
|
|
else
|
|
new /obj/effect/decal/cleanable/molten_object(T) //Leave a pile of goo behind for dramatic effect...
|
|
qdel(our_plant)
|
|
|
|
/**
|
|
* A plant trait that causes the plant's capacity to double.
|
|
*
|
|
* When harvested, the plant's individual capacity is set to double it's default.
|
|
* However, the plant's maximum yield is also halved, only up to 5.
|
|
*/
|
|
/datum/plant_gene/trait/maxchem
|
|
name = "Densified Chemicals"
|
|
description = "The reagent volume is doubled, halving the plant yield instead."
|
|
icon = "flask-vial"
|
|
rate = 2
|
|
trait_flags = TRAIT_HALVES_YIELD
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/maxchem/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
var/obj/item/food/grown/grown_plant = our_plant
|
|
if(istype(grown_plant, /obj/item/food/grown))
|
|
//Grown foods use the edible component so we need to change their max_volume var
|
|
grown_plant.max_volume *= rate
|
|
else
|
|
//Grown inedibles however just use a reagents holder, so.
|
|
our_plant.reagents?.maximum_volume *= rate
|
|
|
|
/// Allows a plant to be harvested multiple times.
|
|
/datum/plant_gene/trait/repeated_harvest
|
|
name = "Perennial Growth"
|
|
description = "It may be harvested multiple times from the same plant."
|
|
icon = "cubes-stacked"
|
|
/// Don't allow replica pods to be multi harvested, please.
|
|
seed_blacklist = list(/obj/item/seeds/replicapod)
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/*
|
|
* Allows a plant to be turned into a battery when cabling is applied.
|
|
* 100 potency plants are made into 2 mj batteries.
|
|
* Plants with electrical activity has their capacities massively increased (up to 40 mj at 100 potency)
|
|
*/
|
|
/datum/plant_gene/trait/battery
|
|
name = "Capacitive Cell Production"
|
|
description = "It can work like a power cell when wired properly."
|
|
icon = "car-battery"
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
/// The number of cables needed to make a battery.
|
|
var/cables_needed_per_battery = 5
|
|
|
|
/datum/plant_gene/trait/battery/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
our_plant.flags_1 |= HAS_CONTEXTUAL_SCREENTIPS_1
|
|
RegisterSignal(our_plant, COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM, PROC_REF(on_requesting_context_from_item))
|
|
RegisterSignal(our_plant, COMSIG_ATOM_ATTACKBY, PROC_REF(make_battery))
|
|
|
|
/*
|
|
* Signal proc for [COMSIG_ATOM_REQUESTING_CONTEXT_FROM_ITEM] to add context to plant batteries.
|
|
*/
|
|
/datum/plant_gene/trait/battery/proc/on_requesting_context_from_item(
|
|
obj/item/source,
|
|
list/context,
|
|
obj/item/held_item,
|
|
mob/living/user,
|
|
)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!istype(held_item, /obj/item/stack/cable_coil))
|
|
return NONE
|
|
|
|
var/obj/item/stack/cable_coil/cabling = held_item
|
|
if(cabling.amount < cables_needed_per_battery)
|
|
return NONE
|
|
|
|
context[SCREENTIP_CONTEXT_LMB] = "Make [source.name] battery"
|
|
return CONTEXTUAL_SCREENTIP_SET
|
|
|
|
/*
|
|
* When a plant with this gene is hit (attackby) with cables, we turn it into a battery.
|
|
*
|
|
* our_plant - our plant being hit
|
|
* hit_item - the item we're hitting the plant with
|
|
* user - the person hitting the plant with an item
|
|
*/
|
|
/datum/plant_gene/trait/battery/proc/make_battery(obj/item/our_plant, obj/item/hit_item, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!istype(hit_item, /obj/item/stack/cable_coil))
|
|
return
|
|
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
var/obj/item/stack/cable_coil/cabling = hit_item
|
|
if(!cabling.use(cables_needed_per_battery))
|
|
to_chat(user, span_warning("You need five lengths of cable to make a [our_plant] battery!"))
|
|
return
|
|
|
|
to_chat(user, span_notice("You add some cable to [our_plant] and slide it inside the battery encasing."))
|
|
var/obj/item/stock_parts/cell/potato/pocell = new /obj/item/stock_parts/cell/potato(user.loc)
|
|
pocell.icon = our_plant.icon // Just in case the plant icons get spread out in different files eventually, this trait won't cause error sprites (also yay downstreams)
|
|
pocell.icon_state = our_plant.icon_state
|
|
pocell.maxcharge = our_seed.potency * 20
|
|
|
|
// The secret of potato supercells!
|
|
var/datum/plant_gene/trait/cell_charge/electrical_gene = our_seed.get_gene(/datum/plant_gene/trait/cell_charge)
|
|
if(electrical_gene) // Cell charge max is now 40MJ or otherwise known as 400KJ (Same as bluespace power cells)
|
|
pocell.maxcharge *= (electrical_gene.rate * 100)
|
|
|
|
pocell.charge = pocell.maxcharge
|
|
pocell.name = "[our_plant.name] battery"
|
|
pocell.desc = "A rechargeable plant-based power cell. This one has a rating of [display_energy(pocell.maxcharge)], and you should not swallow it."
|
|
|
|
if(our_plant.reagents.has_reagent(/datum/reagent/toxin/plasma, 2))
|
|
pocell.rigged = TRUE
|
|
|
|
qdel(our_plant)
|
|
|
|
/*
|
|
* Injects a number of chemicals from the plant when you throw it at someone or they slip on it.
|
|
* At 0 potency it can inject 1 unit of its chemicals, while at 100 potency it can inject 20 units.
|
|
*/
|
|
/datum/plant_gene/trait/stinging
|
|
name = "Hypodermic Prickles"
|
|
description = "It stings, passing some reagents in the process."
|
|
icon = "syringe"
|
|
trait_ids = REAGENT_TRANSFER_ID
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/stinging/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
RegisterSignal(our_plant, COMSIG_PLANT_ON_SLIP, PROC_REF(prickles_inject))
|
|
RegisterSignal(our_plant, COMSIG_MOVABLE_IMPACT, PROC_REF(prickles_inject))
|
|
|
|
/*
|
|
* Injects a target with a number of reagents from our plant.
|
|
*
|
|
* our_plant - our plant that's injecting someone
|
|
* target - the atom being hit on thrown or slipping on our plant
|
|
*/
|
|
/datum/plant_gene/trait/stinging/proc/prickles_inject(obj/item/our_plant, atom/target)
|
|
SIGNAL_HANDLER
|
|
|
|
if(!isliving(target) || !our_plant.reagents?.total_volume)
|
|
return
|
|
|
|
var/mob/living/living_target = target
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
if(living_target.reagents && living_target.can_inject())
|
|
var/injecting_amount = max(1, our_seed.potency * 0.2) // Minimum of 1, max of 20
|
|
our_plant.reagents.trans_to(living_target, injecting_amount, methods = INJECT)
|
|
to_chat(target, span_danger("You are pricked by [our_plant]!"))
|
|
log_combat(our_plant, living_target, "pricked and attempted to inject reagents from [our_plant] to [living_target]. Last touched by: [our_plant.fingerprintslast].")
|
|
our_plant.investigate_log("pricked and injected [key_name(living_target)] and injected [injecting_amount] reagents at [AREACOORD(living_target)]. Last touched by: [our_plant.fingerprintslast].", INVESTIGATE_BOTANY)
|
|
|
|
/// Explodes into reagent-filled smoke when squashed.
|
|
/datum/plant_gene/trait/smoke
|
|
name = "Gaseous Decomposition"
|
|
description = "It can be smashed to turn its Liquid Contents into smoke."
|
|
icon = "cloud"
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/smoke/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
RegisterSignal(our_plant, COMSIG_PLANT_ON_SQUASH, PROC_REF(make_smoke))
|
|
|
|
/*
|
|
* Makes a cloud of reagent smoke.
|
|
*
|
|
* our_plant - our plant being squashed and smoked
|
|
* target - the atom the plant was squashed on
|
|
*/
|
|
/datum/plant_gene/trait/smoke/proc/make_smoke(obj/item/our_plant, atom/target)
|
|
SIGNAL_HANDLER
|
|
|
|
our_plant.investigate_log("made smoke at [AREACOORD(target)]. Last touched by: [our_plant.fingerprintslast].", INVESTIGATE_BOTANY)
|
|
var/datum/effect_system/fluid_spread/smoke/chem/smoke = new ()
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
var/splat_location = get_turf(target)
|
|
var/range = sqrt(our_seed.potency * 0.1)
|
|
smoke.attach(splat_location)
|
|
smoke.set_up(round(range), holder = our_plant, location = splat_location, carry = our_plant.reagents, silent = FALSE)
|
|
smoke.start(log = TRUE)
|
|
our_plant.reagents.clear_reagents()
|
|
|
|
/// Makes the plant and its seeds fireproof. From lavaland plants.
|
|
/datum/plant_gene/trait/fire_resistance
|
|
name = "Fire Resistance"
|
|
description = "Makes the seeds, plant and produce fireproof."
|
|
icon = "fire"
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/fire_resistance/on_new_seed(obj/item/seeds/new_seed)
|
|
if(!(new_seed.resistance_flags & FIRE_PROOF))
|
|
new_seed.resistance_flags |= FIRE_PROOF
|
|
|
|
/datum/plant_gene/trait/fire_resistance/on_removed(obj/item/seeds/old_seed)
|
|
if(old_seed.resistance_flags & FIRE_PROOF)
|
|
old_seed.resistance_flags &= ~FIRE_PROOF
|
|
|
|
/datum/plant_gene/trait/fire_resistance/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
if(!(our_plant.resistance_flags & FIRE_PROOF))
|
|
our_plant.resistance_flags |= FIRE_PROOF
|
|
|
|
/// Invasive spreading lets the plant jump to other trays, and the spreading plant won't replace plants of the same type.
|
|
/datum/plant_gene/trait/invasive
|
|
name = "Invasive Spreading"
|
|
description = "It attempts to spread around if not contained."
|
|
icon = "virus"
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/invasive/on_new_seed(obj/item/seeds/new_seed)
|
|
RegisterSignal(new_seed, COMSIG_SEED_ON_GROW, PROC_REF(try_spread))
|
|
|
|
/datum/plant_gene/trait/invasive/on_removed(obj/item/seeds/old_seed)
|
|
UnregisterSignal(old_seed, COMSIG_SEED_ON_GROW)
|
|
|
|
/*
|
|
* Attempt to find an adjacent tray we can spread to.
|
|
*
|
|
* our_seed - our plant's seed, what spreads to other trays
|
|
* our_tray - the hydroponics tray we're currently in
|
|
*/
|
|
/datum/plant_gene/trait/invasive/proc/try_spread(obj/item/seeds/our_seed, obj/machinery/hydroponics/our_tray)
|
|
SIGNAL_HANDLER
|
|
|
|
if(prob(100 - (5 * (11 - our_seed.production))))
|
|
return
|
|
|
|
for(var/step_dir in GLOB.alldirs)
|
|
var/obj/machinery/hydroponics/spread_tray = locate() in get_step(our_tray, step_dir)
|
|
if(spread_tray && prob(15))
|
|
if(!our_tray.Adjacent(spread_tray))
|
|
continue //Don't spread through things we can't go through.
|
|
|
|
spread_seed(spread_tray, our_tray)
|
|
|
|
/*
|
|
* Actually spread the plant to the tray we found in try_spread.
|
|
*
|
|
* target_tray - the tray we're spreading to
|
|
* origin_tray - the tray we're currently in
|
|
*/
|
|
/datum/plant_gene/trait/invasive/proc/spread_seed(obj/machinery/hydroponics/target_tray, obj/machinery/hydroponics/origin_tray)
|
|
if(target_tray.myseed) // Check if there's another seed in the next tray.
|
|
if(target_tray.myseed.type == origin_tray.myseed.type && target_tray.plant_status != HYDROTRAY_PLANT_DEAD)
|
|
return FALSE // It should not destroy its own kind.
|
|
target_tray.visible_message(span_warning("The [target_tray.myseed.plantname] is overtaken by [origin_tray.myseed.plantname]!"))
|
|
QDEL_NULL(target_tray.myseed)
|
|
target_tray.set_seed(origin_tray.myseed.Copy())
|
|
target_tray.age = 0
|
|
target_tray.set_plant_health(target_tray.myseed.endurance)
|
|
target_tray.lastcycle = world.time
|
|
target_tray.set_weedlevel(0, update_icon = FALSE) // Reset
|
|
target_tray.set_pestlevel(0) // Reset
|
|
target_tray.visible_message(span_warning("The [origin_tray.myseed.plantname] spreads!"))
|
|
if(target_tray.myseed)
|
|
target_tray.name = "[initial(target_tray.name)] ([target_tray.myseed.plantname])"
|
|
else
|
|
target_tray.name = initial(target_tray.name)
|
|
|
|
return TRUE
|
|
|
|
/**
|
|
* A plant trait that causes the plant's food reagents to ferment instead.
|
|
*
|
|
* In practice, it replaces the plant's nutriment and vitamins with half as much of it's fermented reagent.
|
|
* This exception is executed in seeds.dm under 'prepare_result'.
|
|
*
|
|
* Incompatible with auto-juicing composition.
|
|
*/
|
|
/datum/plant_gene/trait/brewing
|
|
name = "Auto-Distilling Composition"
|
|
description = "Its nutriments undergo fermentation."
|
|
icon = "wine-glass"
|
|
trait_ids = CONTENTS_CHANGE_ID
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/**
|
|
* Similar to auto-distilling, but instead of brewing the plant's contents it juices it.
|
|
*
|
|
* Incompatible with auto-distilling composition.
|
|
*/
|
|
/datum/plant_gene/trait/juicing
|
|
name = "Auto-Juicing Composition"
|
|
description = "Its nutriments turn into juice."
|
|
icon = "glass-water"
|
|
trait_ids = CONTENTS_CHANGE_ID
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/**
|
|
* Plays a laughter sound when someone slips on it.
|
|
* Like the sitcom component but for plants.
|
|
* Just like slippery skin, if we have a trash type this only functions on that. (Banana peels)
|
|
*/
|
|
/datum/plant_gene/trait/plant_laughter
|
|
name = "Hallucinatory Feedback"
|
|
description = "Makes sounds when people slip on it."
|
|
icon = "face-laugh-squint"
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
/// Sounds that play when this trait triggers
|
|
var/list/sounds = list('sound/items/SitcomLaugh1.ogg', 'sound/items/SitcomLaugh2.ogg', 'sound/items/SitcomLaugh3.ogg')
|
|
|
|
/datum/plant_gene/trait/plant_laughter/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
var/obj/item/food/grown/grown_plant = our_plant
|
|
if(istype(grown_plant) && ispath(grown_plant.trash_type, /obj/item/grown))
|
|
return
|
|
|
|
RegisterSignal(our_plant, COMSIG_PLANT_ON_SLIP, PROC_REF(laughter))
|
|
|
|
/*
|
|
* Play a sound effect from our plant.
|
|
*
|
|
* our_plant - the source plant that was slipped on
|
|
* target - the atom that slipped on the plant
|
|
*/
|
|
/datum/plant_gene/trait/plant_laughter/proc/laughter(obj/item/our_plant, atom/target)
|
|
SIGNAL_HANDLER
|
|
|
|
our_plant.audible_message(span_notice("[our_plant] lets out burst of laughter."))
|
|
playsound(our_plant, pick(sounds), 100, FALSE, SHORT_RANGE_SOUND_EXTRARANGE)
|
|
|
|
/**
|
|
* A plant trait that causes the plant to gain aesthetic googly eyes.
|
|
*
|
|
* Has no functional purpose outside of causing japes, adds eyes over the plant's sprite, which are adjusted for size by potency.
|
|
*/
|
|
/datum/plant_gene/trait/eyes
|
|
name = "Oculary Mimicry"
|
|
description = "It will watch after you."
|
|
icon = "eye"
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
/// Our googly eyes appearance.
|
|
var/mutable_appearance/googly
|
|
|
|
/datum/plant_gene/trait/eyes/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
googly = mutable_appearance('icons/obj/service/hydroponics/harvest.dmi', "eyes")
|
|
googly.appearance_flags = RESET_COLOR
|
|
our_plant.add_overlay(googly)
|
|
|
|
/// Makes the plant embed on thrown impact.
|
|
/datum/plant_gene/trait/sticky
|
|
name = "Prickly Adhesion"
|
|
description = "It sticks to people when thrown, also passing reagents if stingy."
|
|
icon = "bandage"
|
|
trait_ids = THROW_IMPACT_ID
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/sticky/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
var/obj/item/seeds/our_seed = our_plant.get_plant_seed()
|
|
if(our_seed.get_gene(/datum/plant_gene/trait/stinging))
|
|
our_plant.embedding = EMBED_POINTY
|
|
else
|
|
our_plant.embedding = EMBED_HARMLESS
|
|
our_plant.updateEmbedding()
|
|
our_plant.throwforce = (our_seed.potency/20)
|
|
|
|
/**
|
|
* This trait automatically heats up the plant's chemical contents when harvested.
|
|
* This requires nutriment to fuel. 1u nutriment = 25 K.
|
|
*/
|
|
/datum/plant_gene/trait/chem_heating
|
|
name = "Exothermic Activity"
|
|
description = "It consumes nutriments to heat up other reagents, halving the yield."
|
|
icon = "temperatyre-arrow-up"
|
|
trait_ids = TEMP_CHANGE_ID
|
|
trait_flags = TRAIT_HALVES_YIELD
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/**
|
|
* This trait is the opposite of above - it cools down the plant's chemical contents on harvest.
|
|
* This requires nutriment to fuel. 1u nutriment = -5 K.
|
|
*/
|
|
/datum/plant_gene/trait/chem_cooling
|
|
name = "Endothermic Activity"
|
|
description = "It consumes nutriments to cool down other reagents, halving the yield."
|
|
icon = "temperature-arrow-down"
|
|
trait_ids = TEMP_CHANGE_ID
|
|
trait_flags = TRAIT_HALVES_YIELD
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/// Prevents species mutation, while still allowing wild mutation harvest and Floral Somatoray species mutation. Trait acts as a tag for hydroponics.dm to recognise.
|
|
/datum/plant_gene/trait/never_mutate
|
|
name = "Prosophobic Inclination"
|
|
description = "The plant does not mutate normally, but may give a mutated produce."
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/// Prevents stat mutation caused by instability. Trait acts as a tag for hydroponics.dm to recognise.
|
|
/datum/plant_gene/trait/stable_stats
|
|
name = "Symbiotic Resilience"
|
|
description = "High instability does not affect the plant stats."
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/// Traits for flowers, makes plants not decompose.
|
|
/datum/plant_gene/trait/preserved
|
|
name = "Natural Insecticide"
|
|
description = "It does not attract ants or decompose."
|
|
icon = "bug-slash"
|
|
mutability_flags = PLANT_GENE_REMOVABLE | PLANT_GENE_MUTATABLE | PLANT_GENE_GRAFTABLE
|
|
|
|
/datum/plant_gene/trait/preserved/on_new_plant(obj/item/our_plant, newloc)
|
|
. = ..()
|
|
if(!.)
|
|
return
|
|
|
|
var/obj/item/food/grown/grown_plant = our_plant
|
|
if(istype(grown_plant))
|
|
grown_plant.preserved_food = TRUE
|
|
|
|
/datum/plant_gene/trait/carnivory
|
|
name = "Obligate Carnivory"
|
|
description = "Pests have positive effect on the plant health."
|
|
icon = "spider"
|
|
|
|
/// Plant type traits. Incompatible with one another.
|
|
/datum/plant_gene/trait/plant_type
|
|
name = "you shouldn't see this"
|
|
trait_ids = PLANT_TYPE_ID
|
|
mutability_flags = PLANT_GENE_GRAFTABLE
|
|
|
|
/// Weeds don't get annoyed by weeds in their tray.
|
|
/datum/plant_gene/trait/plant_type/weed_hardy
|
|
name = "Weed Adaptation"
|
|
description = "It is a weed that needs no nutrients and doesn't suffer from other weeds."
|
|
icon = "seedling"
|
|
|
|
/// Mushrooms need less light and have a minimum yield.
|
|
/datum/plant_gene/trait/plant_type/fungal_metabolism
|
|
name = "Fungal Vitality"
|
|
description = "It is a mushroom that needs no water, less light and can't be overtaken by weeds."
|
|
icon = "droplet-slash"
|
|
|
|
/// Currently unused and does nothing. Appears in strange seeds.
|
|
/datum/plant_gene/trait/plant_type/alien_properties
|
|
name ="?????"
|
|
icon = "reddit-alien"
|