mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-13 17:14:47 +01:00
00ccf0c6b5
# Conflicts: # .github/CODEOWNERS # .github/workflows/compile_changelogs.yml # .github/workflows/stale.yml # SQL/database_changelog.md # _maps/map_files/CatwalkStation/CatwalkStation_2023.dmm # code/__DEFINES/atom_hud.dm # code/__DEFINES/inventory.dm # code/__DEFINES/mobs.dm # code/__DEFINES/species_clothing_paths.dm # code/__DEFINES/subsystems.dm # code/__DEFINES/surgery.dm # code/__HELPERS/global_lists.dm # code/_globalvars/lists/maintenance_loot.dm # code/_globalvars/traits/_traits.dm # code/controllers/subsystem/minor_mapping.dm # code/controllers/subsystem/processing/quirks.dm # code/controllers/subsystem/shuttle.dm # code/datums/components/palette.dm # code/datums/components/surgery_initiator.dm # code/datums/diseases/advance/advance.dm # code/datums/hud.dm # code/datums/mood.dm # code/datums/mutations/chameleon.dm # code/datums/quirks/negative_quirks/nyctophobia.dm # code/datums/status_effects/debuffs/debuffs.dm # code/datums/status_effects/debuffs/drunk.dm # code/datums/status_effects/debuffs/slime/slime_leech.dm # code/datums/weather/weather.dm # code/game/data_huds.dm # code/game/objects/items.dm # code/game/objects/items/devices/scanners/health_analyzer.dm # code/game/objects/items/frog_statue.dm # code/game/objects/items/rcd/RLD.dm # code/game/objects/items/robot/items/hypo.dm # code/game/objects/items/stacks/medical.dm # code/game/objects/items/stacks/wrap.dm # code/game/objects/items/storage/garment.dm # code/game/objects/items/tools/medical/defib.dm # code/game/objects/items/weaponry.dm # code/game/objects/items/weaponry/melee/misc.dm # code/game/objects/structures/crates_lockers/closets/secure/security.dm # code/game/objects/structures/curtains.dm # code/game/objects/structures/dresser.dm # code/game/objects/structures/girders.dm # code/game/objects/structures/maintenance.dm # code/game/objects/structures/mirror.dm # code/modules/admin/greyscale_modify_menu.dm # code/modules/admin/verbs/light_debug.dm # code/modules/antagonists/ashwalker/ashwalker.dm # code/modules/antagonists/heretic/knowledge/starting_lore.dm # code/modules/antagonists/ninja/ninjaDrainAct.dm # code/modules/art/paintings.dm # code/modules/client/preferences.dm # code/modules/client/verbs/ooc.dm # code/modules/clothing/head/wig.dm # code/modules/events/disease_outbreak.dm # code/modules/holodeck/holo_effect.dm # code/modules/jobs/job_types/head_of_security.dm # code/modules/jobs/job_types/security_officer.dm # code/modules/library/skill_learning/generic_skillchips/point.dm # code/modules/mining/lavaland/ash_flora.dm # code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm # code/modules/mob/dead/new_player/new_player.dm # code/modules/mob/living/basic/guardian/guardian.dm # code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm # code/modules/mob/living/carbon/carbon.dm # code/modules/mob/living/carbon/human/human.dm # code/modules/mob/living/carbon/human/human_defines.dm # code/modules/mob/living/carbon/life.dm # code/modules/mob/living/living.dm # code/modules/mob/living/living_defines.dm # code/modules/mob/mob.dm # code/modules/mob_spawn/ghost_roles/mining_roles.dm # code/modules/mod/mod_control.dm # code/modules/mod/modules/modules_general.dm # code/modules/modular_computers/computers/item/computer_ui.dm # code/modules/paperwork/paper.dm # code/modules/paperwork/paperbin.dm # code/modules/power/lighting/light.dm # code/modules/projectiles/guns/energy/kinetic_accelerator.dm # code/modules/projectiles/projectile.dm # code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm # code/modules/reagents/chemistry/reagents/food_reagents.dm # code/modules/reagents/chemistry/reagents/other_reagents.dm # code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm # code/modules/research/xenobiology/crossbreeding/_clothing.dm # code/modules/research/xenobiology/crossbreeding/prismatic.dm # code/modules/surgery/advanced/brainwashing.dm # code/modules/surgery/advanced/lobotomy.dm # code/modules/surgery/amputation.dm # code/modules/surgery/blood_filter.dm # code/modules/surgery/bodyparts/_bodyparts.dm # code/modules/surgery/brain_surgery.dm # code/modules/surgery/cavity_implant.dm # code/modules/surgery/coronary_bypass.dm # code/modules/surgery/gastrectomy.dm # code/modules/surgery/healing.dm # code/modules/surgery/limb_augmentation.dm # code/modules/surgery/organ_manipulation.dm # code/modules/surgery/revival.dm # code/modules/surgery/sleeper_protocol.dm # code/modules/surgery/surgery_helpers.dm # code/modules/surgery/surgery_step.dm # code/modules/unit_tests/_unit_tests.dm # code/modules/unit_tests/designs.dm # code/modules/unit_tests/icon_state_worn.dm # code/modules/unit_tests/screenshots/screenshot_antag_icons_cultist.png # code/modules/unit_tests/screenshots/screenshot_antag_icons_headrevolutionary.png # code/modules/unit_tests/screenshots/screenshot_antag_icons_provocateur.png # code/modules/unit_tests/screenshots/screenshot_husk_body.png # code/modules/unit_tests/screenshots/screenshot_husk_body_missing_limbs.png # icons/map_icons/clothing/head/_head.dmi # icons/map_icons/clothing/shoes.dmi # icons/map_icons/items/_item.dmi # icons/mob/huds/hud.dmi # icons/mob/inhands/64x64_lefthand.dmi # icons/mob/inhands/64x64_righthand.dmi # icons/obj/machines/computer.dmi # tgui/packages/tgui/interfaces/OperatingComputer.jsx # tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx # tgui/packages/tgui/interfaces/PreferencesMenu/types.ts # tgui/packages/tgui/interfaces/SurgeryInitiator.tsx # tools/icon_cutter/check.py
132 lines
5.3 KiB
Plaintext
132 lines
5.3 KiB
Plaintext
/datum/component/spawner
|
|
/// Time to wait between spawns
|
|
var/spawn_time
|
|
/// Maximum number of atoms we can have active at one time
|
|
var/max_spawned
|
|
/// Visible message to show when something spawns
|
|
var/spawn_text
|
|
/// List of atom types to spawn, picked randomly
|
|
var/list/spawn_types
|
|
/// Faction to grant to mobs (only applies to mobs)
|
|
var/list/faction
|
|
/// List of weak references to things we have already created
|
|
var/list/spawned_things = list()
|
|
/// Callback to a proc that is called when a mob is spawned. Primarily used for sentient spawners.
|
|
var/datum/callback/spawn_callback
|
|
/// How many mobs can we spawn maximum each time we try to spawn? (1 - max)
|
|
var/max_spawn_per_attempt
|
|
/// The least amount of mobs we can spawn. Good for when you dont want waves of one creature. (BUBBER ADDITION)
|
|
var/min_spawn_per_attempt
|
|
/// Distance from the spawner to spawn mobs
|
|
var/spawn_distance
|
|
/// Distance from the spawner to exclude mobs from spawning
|
|
var/spawn_distance_exclude
|
|
COOLDOWN_DECLARE(spawn_delay)
|
|
|
|
/datum/component/spawner/Initialize(spawn_types = list(), spawn_time = 30 SECONDS, max_spawned = 5, max_spawn_per_attempt = 1, min_spawn_per_attempt = 1, faction = list(FACTION_MINING), spawn_text = null, datum/callback/spawn_callback = null, spawn_distance = 1, spawn_distance_exclude = 0, initial_spawn_delay = 0 SECONDS)
|
|
if (!islist(spawn_types))
|
|
CRASH("invalid spawn_types to spawn specified for spawner component!")
|
|
src.spawn_time = spawn_time
|
|
src.spawn_types = spawn_types
|
|
src.faction = faction
|
|
src.spawn_text = spawn_text
|
|
src.max_spawned = max_spawned
|
|
src.spawn_callback = spawn_callback
|
|
src.max_spawn_per_attempt = max_spawn_per_attempt
|
|
src.min_spawn_per_attempt = min_spawn_per_attempt // BUBBER ADDITION
|
|
src.spawn_distance = spawn_distance
|
|
src.spawn_distance_exclude = spawn_distance_exclude
|
|
// If set, doesn't instantly spawn a creature when the spawner component is applied.
|
|
if(initial_spawn_delay)
|
|
COOLDOWN_START(src, spawn_delay, spawn_time)
|
|
|
|
RegisterSignal(parent, COMSIG_QDELETING, PROC_REF(stop_spawning))
|
|
RegisterSignal(parent, COMSIG_VENT_WAVE_CONCLUDED, PROC_REF(stop_spawning))
|
|
START_PROCESSING((spawn_time < 2 SECONDS ? SSfastprocess : SSprocessing), src)
|
|
|
|
/datum/component/spawner/process()
|
|
try_spawn_mob()
|
|
|
|
/// Stop spawning mobs
|
|
/datum/component/spawner/proc/stop_spawning(force)
|
|
SIGNAL_HANDLER
|
|
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
spawned_things = list()
|
|
|
|
/// Try to create a new mob
|
|
/datum/component/spawner/proc/try_spawn_mob()
|
|
if(!length(spawn_types))
|
|
return
|
|
if(!COOLDOWN_FINISHED(src, spawn_delay))
|
|
return
|
|
validate_references()
|
|
var/spawned_total = length(spawned_things)
|
|
if(spawned_total >= max_spawned)
|
|
return
|
|
var/atom/spawner = parent
|
|
COOLDOWN_START(src, spawn_delay, spawn_time)
|
|
var/chosen_mob_type = pick(spawn_types)
|
|
var/adjusted_spawn_count = 1
|
|
var/max_spawn_this_attempt = min(max_spawn_per_attempt, max_spawned - spawned_total)
|
|
var/min_spawn_this_attempt = min_spawn_per_attempt // BUBBER ADDITION
|
|
if (max_spawn_this_attempt > 1)
|
|
adjusted_spawn_count = rand(min_spawn_this_attempt, max_spawn_this_attempt) // BUBBER ADDITION - Original: adjusted_spawn_count = rand(1, max_spawn_this_attempt)
|
|
for(var/i in 1 to adjusted_spawn_count)
|
|
var/atom/created
|
|
var/turf/picked_spot
|
|
|
|
if(spawn_distance == 1)
|
|
created = new chosen_mob_type(spawner.loc)
|
|
else if(spawn_distance >= 1 && spawn_distance_exclude >= 1)
|
|
picked_spot = pick(turf_peel(spawn_distance, spawn_distance_exclude, spawner.loc, view_based = TRUE))
|
|
if(!picked_spot)
|
|
picked_spot = pick(circle_range_turfs(spawner.loc, spawn_distance))
|
|
if(picked_spot == spawner.loc)
|
|
SEND_SIGNAL(spawner, COMSIG_SPAWNER_SPAWNED_DEFAULT)
|
|
created = new chosen_mob_type(picked_spot)
|
|
else if (spawn_distance >= 1)
|
|
picked_spot = pick(circle_range_turfs(spawner.loc, spawn_distance))
|
|
created = new chosen_mob_type(picked_spot)
|
|
|
|
created.flags_1 |= (spawner.flags_1 & ADMIN_SPAWNED_1)
|
|
spawned_things += WEAKREF(created)
|
|
|
|
if (isliving(created))
|
|
var/mob/living/created_mob = created
|
|
created_mob.set_faction(faction)
|
|
RegisterSignal(created, COMSIG_MOB_STATCHANGE, PROC_REF(mob_stat_changed))
|
|
|
|
SEND_SIGNAL(src, COMSIG_SPAWNER_SPAWNED, created)
|
|
RegisterSignal(created, COMSIG_QDELETING, PROC_REF(on_deleted))
|
|
spawn_callback?.Invoke(created)
|
|
|
|
if (spawn_text)
|
|
spawner.visible_message(span_danger("A creature [spawn_text] [spawner]."))
|
|
|
|
/// Remove weakrefs to atoms which have been killed or deleted without us picking it up somehow
|
|
/datum/component/spawner/proc/validate_references()
|
|
for (var/datum/weakref/weak_thing as anything in spawned_things)
|
|
var/atom/previously_spawned = weak_thing?.resolve()
|
|
if (!previously_spawned)
|
|
spawned_things -= weak_thing
|
|
continue
|
|
if (!isliving(previously_spawned))
|
|
continue
|
|
var/mob/living/spawned_mob = previously_spawned
|
|
if (spawned_mob.stat != DEAD)
|
|
continue
|
|
spawned_things -= weak_thing
|
|
|
|
/// Called when an atom we spawned is deleted, remove it from the list
|
|
/datum/component/spawner/proc/on_deleted(atom/source)
|
|
SIGNAL_HANDLER
|
|
spawned_things -= WEAKREF(source)
|
|
|
|
/// Called when a mob we spawned dies, remove it from the list and unregister signals
|
|
/datum/component/spawner/proc/mob_stat_changed(mob/living/source)
|
|
if (source.stat != DEAD)
|
|
return
|
|
spawned_things -= WEAKREF(source)
|
|
UnregisterSignal(source, list(COMSIG_QDELETING, COMSIG_MOB_STATCHANGE))
|