Files
Paradise/code/datums/components/spawner.dm
PollardTheDragon 088f038e68 Incursion Expansion and Rebalance (#30835)
* Adjusts spawn times

* Incursion Adjustment Part 1

* Skelecurity

* Skeleton Officer and Mobster

* Skeleton mob drops

* Rattle em

* New mobs, AI, removed volatile

* Nerfs spider

* Trait

* Config fix

* Nerfs juggernauts

* Rune effect while reanimating

* Linters

* Fleshspider Retaliate

* Update skeleton_mob.dm

* Projectile changes

* Event tracker for giant spiders and better tracking for skeletons

* Oops

* Linter

* Apply suggestions from code review

Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com>
Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>

* Lints

* Small fix, tries to revive the original player first before selecting dchat

* Linters

* Fixes mobs not gibbing often enough

* Improves incursion rally, undeerifies it

* Oops

* Update incursion_ai.dm

* Removes incursion skeletons from xenobio mobs

* No gold core flesh spiders

---------

Signed-off-by: PollardTheDragon <144391971+PollardTheDragon@users.noreply.github.com>
Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com>
2025-11-26 00:25:15 +00:00

99 lines
3.3 KiB
Plaintext

/datum/component/spawner
var/mob_types = list(/mob/living/basic/carp)
var/spawn_time = 300 //30 seconds default
var/list/spawned_mobs = list()
var/spawn_delay = 0
var/max_mobs = 5
var/spawn_text = "emerges from"
var/list/faction = list("mining")
COOLDOWN_DECLARE(last_rally)
/datum/component/spawner/Initialize(_mob_types, _spawn_time, _faction, _spawn_text, _max_mobs)
if(_spawn_time)
spawn_time=_spawn_time
if(_mob_types)
mob_types=_mob_types
if(_faction)
faction=_faction
if(_spawn_text)
spawn_text=_spawn_text
if(_max_mobs)
max_mobs=_max_mobs
RegisterSignal(parent, list(COMSIG_PARENT_QDELETING), PROC_REF(stop_spawning))
RegisterSignal(parent, COMSIG_SPAWNER_SET_TARGET, PROC_REF(rally_spawned_mobs))
START_PROCESSING(SSprocessing, src)
/datum/component/spawner/process()
try_spawn_mob()
/datum/component/spawner/proc/stop_spawning(force)
STOP_PROCESSING(SSprocessing, src)
for(var/mob/living/simple_animal/L in spawned_mobs)
if(L.nest == src)
L.nest = null
for(var/mob/living/basic/L in spawned_mobs)
if(L.nest == src)
L.nest = null
spawned_mobs = null
/datum/component/spawner/proc/try_spawn_mob()
var/atom/P = parent
if(length(spawned_mobs) >= max_mobs)
return
if(spawn_delay > world.time)
return
spawn_delay = world.time + spawn_time
var/chosen_mob_type = pickweight(mob_types)
var/mob/living/simple_animal/L = new chosen_mob_type(P.loc)
L.admin_spawned = P.admin_spawned
spawned_mobs += L
L.nest = src
L.faction = src.faction
ADD_TRAIT(L, TRAIT_FROM_TENDRIL, INNATE_TRAIT)
P.visible_message("<span class='danger'>[L] [spawn_text] [P].</span>")
P.on_mob_spawn(L)
return L
/datum/component/spawner/proc/rally_spawned_mobs(parent, mob/living/target)
SIGNAL_HANDLER // COMSIG_SPAWNER_SET_TARGET
if(!(COOLDOWN_FINISHED(src, last_rally) && length(spawned_mobs)))
return
// start the cooldown first, because a rallied mob might fire on
// ourselves while this is happening, causing confusion
COOLDOWN_START(src, last_rally, 30 SECONDS)
for(var/mob/living/rallied as anything in spawned_mobs)
if(istype(rallied, /mob/living/basic))
var/mob/living/basic/basic = rallied
basic.ai_controller.cancel_actions()
basic.ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target)
if(istype(rallied, /mob/living/simple_animal/hostile))
var/mob/living/simple_animal/hostile/simple = rallied
INVOKE_ASYNC(simple, TYPE_PROC_REF(/mob/living/simple_animal/hostile, aggro_fast), target)
/datum/component/spawner/demon_incursion_portal
/datum/component/spawner/demon_incursion_portal/try_spawn_mob()
var/atom/result = ..()
if(result && istype(result.ai_controller))
result.ai_controller.set_blackboard_key(BB_INCURSION_HOME_PORTAL, parent)
return result
/datum/component/spawner/demon_incursion_portal/rally_spawned_mobs(parent, mob/living/target)
if(!(COOLDOWN_FINISHED(src, last_rally)))
return
COOLDOWN_START(src, last_rally, 30 SECONDS)
for(var/mob/living/basic/rallied as anything in spawned_mobs)
if(rallied.ventcrawler == VENTCRAWLER_ALWAYS)
return // Don't rally ventcrawlers - they might have to walk the entire station!
rallied.ai_controller.cancel_actions()
rallied.ai_controller.set_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET, target)
rallied.ai_controller.queue_behavior(/datum/ai_behavior/return_to_portal, BB_INCURSION_HOME_PORTAL)