mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-15 12:11:45 +00:00
* Auto doc'd much of grown botany food and plant traits and renamed a buncha variables and parameters to match modern contribution guidelines. * Cleaned up a good bit of plant gene code left over from the prior refactor and modernized some of it. All plant effects that were once unique to a plant are now un-graftable, un-mutatable, un-shearable plant traits - called IMMUTABLE traits. The ultimate goal of this PR was to make all of the hidden, arcane traits that are spread through botany's various plants and add a way to figure out they exist in game. Take omega-weed, for example, which has a maximum volume of 420 units. What does this mean for the enterprising botanist? In most cases, all the plants should act the same way. None of the immutable traits are graftable from any of the plants, they cannot be sheared off of the plant, and they cannot be mutated randomly from strange seeds or high instability mutations. Though, in refactoring these traits, two things have been fixed: Novaflower's on hit and Deathnettle's on hit now proc again. If you aren't aware, Novaflowers apply firestacks and Deathnettles paralyze on hit. They've been in an unreachable code segment for a few years now and i'm not sure if they should be "fixed" or not, since I think they don't need any buffs. A few other things have changed: * Liquid Contents can no longer be applied to plants with Hypodermic Prickles, and visa-versa. They already didn't work together, but this means you need to go through an extra step to make LC-deathnettles. * Killer Tomatos no longer have liquid contents. Didn't really make sense, anyways. Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
114 lines
4.0 KiB
Plaintext
114 lines
4.0 KiB
Plaintext
/// -- Plant backfire element --
|
|
/// Certain high-danger plants, like death-nettles, will backfire and harm the holder if they're not properly protected.
|
|
/// If a user is protected with something like leather gloves, they can handle them normally.
|
|
/// If they're not protected properly, we invoke a callback on the user, harming or inconveniencing them.
|
|
/datum/element/plant_backfire
|
|
element_flags = ELEMENT_BESPOKE | ELEMENT_DETACH
|
|
id_arg_index = 2
|
|
/// Whether we stop the current action if backfire is triggered (EX: returning CANCEL_ATTACK_CHAIN)
|
|
var/cancel_action = FALSE
|
|
/// The callback of the backfire effect of the plant.
|
|
var/datum/callback/backfire_callback
|
|
/// Any extra traits we want to check in addition to TRAIT_PLANT_SAFE. Mobs with a trait in this list will be considered safe. List of traits.
|
|
var/extra_traits
|
|
/// Any plant genes we want to check that are required for our plant to be dangerous. Plants without a gene in this list will be considered safe. List of typepaths.
|
|
var/extra_genes
|
|
|
|
/datum/element/plant_backfire/Attach(datum/target, backfire_callback, cancel_action = FALSE, extra_traits, extra_genes)
|
|
. = ..()
|
|
if(!isitem(target))
|
|
return ELEMENT_INCOMPATIBLE
|
|
|
|
src.cancel_action = cancel_action
|
|
src.extra_traits = extra_traits
|
|
src.extra_genes = extra_genes
|
|
src.backfire_callback = backfire_callback
|
|
|
|
RegisterSignal(target, COMSIG_ITEM_PRE_ATTACK, .proc/attack_safety_check)
|
|
RegisterSignal(target, COMSIG_ITEM_PICKUP, .proc/pickup_safety_check)
|
|
RegisterSignal(target, COMSIG_MOVABLE_PRE_THROW, .proc/throw_safety_check)
|
|
|
|
/datum/element/plant_backfire/Detach(datum/target)
|
|
. = ..()
|
|
UnregisterSignal(target, list(COMSIG_ITEM_PRE_ATTACK, COMSIG_ITEM_PICKUP, COMSIG_MOVABLE_PRE_THROW))
|
|
|
|
/*
|
|
* Checks before we attack if we're okay to continue.
|
|
*
|
|
* source - our plant
|
|
* user - the mob wielding our [source]
|
|
*/
|
|
/datum/element/plant_backfire/proc/attack_safety_check(datum/source, atom/target, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(plant_safety_check(source, user))
|
|
return
|
|
backfire_callback.Invoke(source, user)
|
|
if(cancel_action)
|
|
return COMPONENT_CANCEL_ATTACK_CHAIN
|
|
|
|
/*
|
|
* Checks before we pick up the plant if we're okay to continue.
|
|
*
|
|
* source - our plant
|
|
* user - the mob picking our [source]
|
|
*/
|
|
/datum/element/plant_backfire/proc/pickup_safety_check(datum/source, mob/user)
|
|
SIGNAL_HANDLER
|
|
|
|
if(plant_safety_check(source, user))
|
|
return
|
|
backfire_callback.Invoke(source, user)
|
|
|
|
/*
|
|
* Checks before we throw the plant if we're okay to continue.
|
|
*
|
|
* source - our plant
|
|
* thrower - the mob throwing our [source]
|
|
*/
|
|
/datum/element/plant_backfire/proc/throw_safety_check(datum/source, list/arguments)
|
|
SIGNAL_HANDLER
|
|
|
|
var/mob/living/thrower = arguments[4] // 4th arg = mob/thrower
|
|
if(plant_safety_check(source, thrower))
|
|
return
|
|
backfire_callback.Invoke(source, thrower)
|
|
if(cancel_action)
|
|
return COMPONENT_CANCEL_THROW
|
|
|
|
/*
|
|
* Actually checks if our user is safely handling our plant.
|
|
*
|
|
* Checks for TRAIT_PLANT_SAFE, and returns TRUE if we have it.
|
|
* Then, any extra traits we need to check (Like TRAIT_PIERCEIMMUNE for nettles) and returns TRUE if we have one of them.
|
|
* Then, any extra genes we need to check (Like liquid contents for bluespace tomatos) and returns TRUE if we don't have the gene.
|
|
*
|
|
* source - our plant
|
|
* user - the carbon handling our [source]
|
|
*
|
|
* returns FALSE if none of the checks are successful.
|
|
*/
|
|
/datum/element/plant_backfire/proc/plant_safety_check(datum/source, mob/living/carbon/user)
|
|
if(!istype(user))
|
|
return TRUE
|
|
|
|
if(HAS_TRAIT(user, TRAIT_PLANT_SAFE))
|
|
return TRUE
|
|
|
|
for(var/checked_trait in extra_traits)
|
|
if(HAS_TRAIT(user, checked_trait))
|
|
return TRUE
|
|
|
|
var/obj/item/parent_item = source
|
|
var/obj/item/seeds/our_seed = parent_item.get_plant_seed()
|
|
if(our_seed)
|
|
for(var/checked_gene in extra_genes)
|
|
if(!our_seed.get_gene(checked_gene))
|
|
return TRUE
|
|
|
|
for(var/obj/item/clothing/worn_item in user.get_equipped_items())
|
|
if((worn_item.body_parts_covered & HANDS) && (worn_item.clothing_flags & THICKMATERIAL))
|
|
return TRUE
|
|
|
|
return FALSE
|