Files
Bubberstation/code/datums/components/fantasy/suffixes.dm
Tim fd85f5c67f Buff scythes, goats, and plantbgone vs PLANT biotypes (#72889)
## About The Pull Request
This buffs scythes, goats, and plantbgone vs PLANT biotypes:

- Scythes now deal x1.5 damage to venus flytraps (3 hits to kill)
- Scythes now target the flower bud vines
- Goats now target flower bud vines and deal 15 damage to PLANT biotypes
- Goats have a eating sound whenever they bite PLANT biotypes
- Plantbgone now does 2 dmg per unit to PLANT biotypes (10 dmg per
spray)
- Plantbgone now has a 75% chance to remove weeds and deals large damage
to flower buds
- Weed control crates now come with a pair of leather gloves
- Golems are immune to thorn effects
- Any kind of thick glove material will prevent thorn effects when
attacking
- Flower buds will now take x4 damage from fire and sharp weapons
(unless they have fire trait)
- Regular scythes are now a sharp object

Also this fixes a few runtimes with spacevines and nulls. The bane
element now accepts `mob_biotypes` bitflags as an argument.

## Why It's Good For The Game
Before my changes:

- Plant-b-gone was doing 0.4 dmg per unit to PLANT biotypes (2 dmg per
spray)
- Scythes took 5 hits to kill venus flytraps
- Goats only affected podpeople
- Flower bud vines were being ignored by weed killing code
- Plantbgone only had a 50% chance to remove weeds (and this was very
inconsistent due to RNG)
- Botanical gloves and thick gloves didn't protect from thorns
- Golems were getting pierced by thorns despite having pierce immunity
- Flower buds were not taking the x4 damage like they should have been
- Regular scythes were not a sharp object, but other scythes
(chaplain's, megafauna loot) were sharp

This makes the weed killer crate more effective since people were
complaining about it being worthless vs vines and flower buds. These
changes give people more options to respond to threats vs plants.

## Changelog
🆑
add: Add a pair of leather gloves to weed control crate
balance: Mobs with the PLANT biotypes (venus flytraps, pod people,
killer tomatoes) are now much weaker vs scythes, goats, and plantbgone.
balance: Plantbgone is now more effective at destroying weeds.
balance: Regular scythes are now a sharp object
fix: Fixed scythes, goats, and plantbgone not affecting flower bud
vines.
fix: Thick and botanical gloves not protecting from thorns
fix: Golems not having pierce immunity from thorns
fix: Runtime where vines tried to spread into null turf
fix: Runtime where null vines that were destroyed were trying to spread
to nearby turfs
soundadd: Add eat food sound when goats eat plants
code: Improved goat targeting code
code: The bane element now accepts `mob_biotypes` bitflags as an
argument.
/🆑
2023-01-26 14:29:48 -08:00

211 lines
7.2 KiB
Plaintext

/datum/fantasy_affix/cosmetic_suffixes
name = "purely cosmetic suffix"
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD | AFFIX_EVIL
var/list/goodSuffixes
var/list/badSuffixes
/datum/fantasy_affix/cosmetic_suffixes/New()
goodSuffixes = list(
"dexterity",
"constitution",
"intelligence",
"wisdom",
"charisma",
"the forest",
"the hills",
"the plains",
"the sea",
"the sun",
"the moon",
"the void",
"the world",
"many secrets",
"many tales",
"many colors",
"rending",
"sundering",
"the night",
"the day",
)
badSuffixes = list(
"draining",
"burden",
"discomfort",
"awkwardness",
"poor hygiene",
"timidity",
)
weight = (length(goodSuffixes) + length(badSuffixes)) * 10
/datum/fantasy_affix/cosmetic_suffixes/apply(datum/component/fantasy/comp, newName)
if(comp.quality > 0 || (comp.quality == 0 && prob(50)))
return "[newName] of [pick(goodSuffixes)]"
else
return "[newName] of [pick(badSuffixes)]"
//////////// Good suffixes
/datum/fantasy_affix/bane
name = "of <mobtype> slaying (random species, carbon or simple animal)"
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD
var/list/target_types_by_comp = list()
/datum/fantasy_affix/bane/apply(datum/component/fantasy/comp, newName)
. = ..()
// This is set up to be easy to add to these lists as I expect it will need modifications
var/static/list/possible_mobtypes
if(!possible_mobtypes)
// The base list of allowed mob/species types
possible_mobtypes = zebra_typecacheof(list(
/mob/living/simple_animal = TRUE,
/mob/living/carbon = TRUE,
/datum/species = TRUE,
// Some types to remove them and their subtypes
/mob/living/carbon/human/species = FALSE,
))
// Some particular types to disallow if they're too broad/abstract
// Not in the above typecache generator because it includes subtypes and this doesn't.
possible_mobtypes -= list(
/mob/living/simple_animal/hostile,
)
var/mob/picked_mobtype = pick(possible_mobtypes)
// This works even with the species picks since we're only accessing the name
var/obj/item/master = comp.parent
master.AddElement(/datum/element/bane, target_type = picked_mobtype)
target_types_by_comp[comp] = picked_mobtype
return "[newName] of [initial(picked_mobtype.name)] slaying"
/datum/fantasy_affix/bane/remove(datum/component/fantasy/comp)
var/picked_mobtype = target_types_by_comp[comp]
var/obj/item/master = comp.parent
master.RemoveElement(/datum/element/bane, picked_mobtype)
target_types_by_comp -= comp
/datum/fantasy_affix/summoning
name = "of <mobtype> summoning (dangerous, can pick all but megafauna tier stuff)"
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD
weight = 5
/datum/fantasy_affix/summoning/apply(datum/component/fantasy/comp, newName)
. = ..()
// This is set up to be easy to add to these lists as I expect it will need modifications
var/static/list/possible_mobtypes
if(!possible_mobtypes)
// The base list of allowed mob/species types
possible_mobtypes = zebra_typecacheof(list(
/mob/living/simple_animal = TRUE,
/mob/living/carbon = TRUE,
/datum/species = TRUE,
// Some types to remove them and their subtypes
/mob/living/carbon/human/species = FALSE,
/mob/living/simple_animal/hostile/asteroid/elite = FALSE,
/mob/living/simple_animal/hostile/megafauna = FALSE,
))
// Some particular types to disallow if they're too broad/abstract
// Not in the above typecache generator because it includes subtypes and this doesn't.
possible_mobtypes -= list(
/mob/living/simple_animal/hostile,
)
var/mob/picked_mobtype = pick(possible_mobtypes)
// This works even with the species picks since we're only accessing the name
var/obj/item/master = comp.parent
var/max_mobs = max(CEILING(comp.quality/2, 1), 1)
var/spawn_delay = 300 - 30 * comp.quality
comp.appliedComponents += master.AddComponent(/datum/component/summoning, list(picked_mobtype), 100, max_mobs, spawn_delay)
return "[newName] of [initial(picked_mobtype.name)] summoning"
/datum/fantasy_affix/shrapnel
name = "shrapnel"
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD
/datum/fantasy_affix/shrapnel/validate(obj/item/attached)
if(isgun(attached))
return TRUE
return FALSE
/datum/fantasy_affix/shrapnel/apply(datum/component/fantasy/comp, newName)
. = ..()
// higher means more likely
var/list/weighted_projectile_types = list(/obj/projectile/meteor = 1,
/obj/projectile/energy/nuclear_particle = 1,
/obj/projectile/beam/pulse = 1,
/obj/projectile/bullet/honker = 15,
/obj/projectile/temp = 15,
/obj/projectile/ion = 15,
/obj/projectile/magic/door = 15,
/obj/projectile/magic/locker = 15,
/obj/projectile/magic/fetch = 15,
/obj/projectile/beam/emitter = 15,
/obj/projectile/magic/flying = 15,
/obj/projectile/energy/net = 15,
/obj/projectile/bullet/incendiary/c9mm = 15,
/obj/projectile/temp/hot = 15,
/obj/projectile/beam/disabler = 15)
var/obj/projectile/picked_projectiletype = pick_weight(weighted_projectile_types)
var/obj/item/master = comp.parent
comp.appliedComponents += master.AddComponent(/datum/component/mirv, picked_projectiletype)
return "[newName] of [initial(picked_projectiletype.name)] shrapnel"
/datum/fantasy_affix/strength
name = "of strength (knockback)"
placement = AFFIX_SUFFIX
alignment = AFFIX_GOOD
/datum/fantasy_affix/strength/apply(datum/component/fantasy/comp, newName)
. = ..()
var/obj/item/master = comp.parent
master.AddElement(/datum/element/knockback, CEILING(comp.quality/2, 1), FLOOR(comp.quality/10, 1))
return "[newName] of strength"
/datum/fantasy_affix/strength/remove(datum/component/fantasy/comp)
var/obj/item/master = comp.parent
master.RemoveElement(/datum/element/knockback, CEILING(comp.quality/2, 1), FLOOR(comp.quality/10, 1))
//////////// Bad suffixes
/datum/fantasy_affix/fool
name = "of the fool (honking)"
placement = AFFIX_SUFFIX
alignment = AFFIX_EVIL
/datum/fantasy_affix/fool/apply(datum/component/fantasy/comp, newName)
. = ..()
var/obj/item/master = comp.parent
comp.appliedComponents += master.AddComponent(/datum/component/squeak, list('sound/items/bikehorn.ogg' = 1), 50, falloff_exponent = 20)
return "[newName] of the fool"
/datum/fantasy_affix/curse_of_hunger
name = "curse of hunger"
placement = AFFIX_SUFFIX
alignment = AFFIX_EVIL
/datum/fantasy_affix/curse_of_hunger/validate(obj/item/attached)
//curse of hunger that attaches onto food has the ability to eat itself. it's hilarious.
if(!IS_EDIBLE(attached))
return TRUE
return TRUE
/datum/fantasy_affix/curse_of_hunger/apply(datum/component/fantasy/comp, newName)
. = ..()
var/obj/item/master = comp.parent
var/filter_color = "#8a0c0ca1" //clarified args
var/new_name = pick(", eternally hungry", " of the glutton", " cursed with hunger", ", consumer of all", " of the feast")
master.AddElement(/datum/element/curse_announcement, "[master] is cursed with the curse of hunger!", filter_color, new_name, comp)
comp.appliedComponents += master.AddComponent(/datum/component/curse_of_hunger)
return newName //no spoilers!
/datum/fantasy_affix/curse_of_hunger/remove(datum/component/fantasy/comp)
var/obj/item/master = comp.parent
master.RemoveElement(/datum/element/curse_announcement) //just in case