Files
Alexis 88d7efe291 Fleshmind - Attempt 3 (#4914)
## About This Pull Request
Brought back based off of
https://github.com/Bubberstation/Bubberstation/pull/2007, made
functional again by myself.
Original Code: https://github.com/Skyrat-SS13/Skyrat-tg/pull/14023

Fleshmind is a PVE event that incorporates some PVP elements in the
later stages of its growth. You defeat it by destroying all its
processors. It has six stages of growth with each stage expanding on its
abilities and the structures and mobs it can deploy. It will announce to
the entire station each time it gains a level or loses a level. Each
level means it has a new processor.

- **Level 1:** The start when it spawns in. It will spawn some basic
structures.
- **Level 2:** It will begin to spawn screamers and whisperers
- **Level 3:** The wireweed is much more situated, and this is the point
where it spawns a very dangerous mech. This is the point where it
becomes very critical. It also starts to spawn Babblers (structures that
spew propaganda into comms) and Modulators. (Gives you hallucinations)
- **Level 4** No new special abilities.
- **Level 5** No new special abilities
- **Level 6** It automatically calls the emergency shuttle to hijack and
spawns a deathsquad on Centcomm. This ends the round.

**Counters:**
- Fight in groups. Carry a melee weapon. (You can still melee the
mechivers and try to kill them before they convert you)
- Wirecutters cut wireweed.
- Ion Weaponry is extremely useful. It also stuns all the mobs.
- Target the processors. If you can pick them off in space, it has
practically zero EVA abilities.
- If someone gets assimilated, should get them to medical if you kill
them.

To run it requires 35 active players and a minimum of an hour to have
passed.
## Why It's Good For The Game
With mold being disabled, there is a missing PVE element in the game,
this fills that niche while also playing around with the idea of
temporary conversion antags in a way that I think works really well.

Wireweed/fleshmind also distracts the crew and security enough to
provide clever antagonists with an opening to commit crimes and get away
with them while the crew has their hands full.

## Proof of Testing
It's been test merged for two months now, it works.
## Changelog
🆑 xPokee, StrangeWeirdKitten, Gandalf2k15
add: New midround event: Fleshmind
/🆑

---------

Co-authored-by: LT3 <83487515+lessthnthree@users.noreply.github.com>
Co-authored-by: Artur Lang <24881678+Arturlang@users.noreply.github.com>
Co-authored-by: Roxy <75404941+TealSeer@users.noreply.github.com>
2026-02-17 15:38:34 +01:00

95 lines
3.5 KiB
Plaintext

/// A component for ai-controlled atoms which plays a sound if they switch to a living target which they can attack
/datum/component/aggro_emote
/// Blackboard key in which target data is stored
var/target_key
/// If we want to limit emotes to only play at mobs
var/living_only
/// List of emotes to play
var/list/emote_list
// BUBBER EDIT - START: FLESHMIND
/// Audiable emotes to play
var/list/audible_emote_list
/// Do we taunt the target?
var/list/speak_list
/// Do we play any sounds?
var/list/sounds
// BUBBER EDIT - END
/// Chance to play an emote
var/emote_chance
/// Chance to subtract every time we play an emote (permanently)
var/subtract_chance
/// Minimum chance to play an emote
var/minimum_chance
/datum/component/aggro_emote/Initialize(
target_key = BB_BASIC_MOB_CURRENT_TARGET,
living_only = FALSE,
list/emote_list,
list/speak_list, // BUBBER EDIT - ADDITION: FLESHMIND
list/sounds, // BUBBER EDIT - ADDITION: FLESHMIND
list/audible_emote_list, // BUBBER EDIT - ADDITION: FLESHMIND
emote_chance = 30,
minimum_chance = 2,
subtract_chance = 7,
)
. = ..()
if (!isatom(parent))
return COMPONENT_INCOMPATIBLE
var/atom/atom_parent = parent
if (!atom_parent.ai_controller)
return COMPONENT_INCOMPATIBLE
src.target_key = target_key
src.emote_list = emote_list
src.speak_list = speak_list // BUBBER EDIT - ADDITION: FLESHMIND
src.sounds = sounds // BUBBER EDIT - ADDITION: FLESHMIND
src.audible_emote_list = audible_emote_list // BUBBER EDIT - ADDITION: FLESHMIND
src.emote_chance = emote_chance
src.minimum_chance = minimum_chance
src.subtract_chance = subtract_chance
/datum/component/aggro_emote/RegisterWithParent()
. = ..()
RegisterSignal(parent, COMSIG_AI_BLACKBOARD_KEY_SET(target_key), PROC_REF(on_target_changed))
/datum/component/aggro_emote/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_AI_BLACKBOARD_KEY_SET(target_key))
return ..()
/// When we get a new target, see if we want to bark at it
/datum/component/aggro_emote/proc/on_target_changed(atom/source)
SIGNAL_HANDLER
var/atom/new_target = source.ai_controller.blackboard[target_key]
// BUBBER EDIT - START: FLESHMIND
var/mob/living/mob = source
/// Used to pick and choose between emotes and audiable sounds
// Grab the number length of each list
var/emotes_length = emote_list?.len
var/audible_emote_length = audible_emote_list?.len
var/speak_emote_length = speak_list?.len
// Add them all together
var/total_choices_length = audible_emote_length + speak_emote_length + emotes_length
//Pick a random number between 1 and the total length of every list
var/random_number_in_range = rand(1, total_choices_length)
var/sound_to_play = length(sounds) > 0 ? pick(sounds) : null
// Calculate the emote chance and determin if you'll run an emote
emote_chance = max(emote_chance - subtract_chance, minimum_chance)
// BUBBER EDIT - END
if (isnull(new_target) || !prob(emote_chance))
return
if (living_only && !isliving(new_target))
return // If we don't want to bark at food items or chairs or windows
// BUBBER EDIT - START: FLESHMIND
/// Randomly choose between each emote
if(random_number_in_range <= audible_emote_length)
source.manual_emote("[pick(audible_emote_list)]")
playsound(source, sound_to_play, 80, vary = TRUE)
else if(random_number_in_range <= (audible_emote_length + emotes_length))
source.manual_emote("[pick(emote_list)] at [new_target].")
else
INVOKE_ASYNC(mob, TYPE_PROC_REF(/atom/movable, say), pick(speak_list), forced = "AI Controller")
playsound(source, sound_to_play, 80, vary = TRUE)
// BUBBER EDIT - END