Files
CHOMPStation2/code/modules/gamemaster/event2/events/mob_spawning.dm
Atermonera 5c03273ce8 Merge pull request #6884 from Neerti/event_system_fix
Rewrites the Rewritten Event System
2020-04-06 16:23:39 -04:00

99 lines
4.2 KiB
Plaintext

// A subtype that involves spawning mobs like carp, rogue drones, spiders, etc.
/datum/event2/event/mob_spawning
var/list/spawned_mobs = list()
var/use_map_edge_with_landmarks = TRUE // Use both landmarks and spawning from the "edge" of the map. Otherise uses landmarks over map edge.
var/landmark_name = "carpspawn" // Which landmark to use for spawning.
// Spawns a specific mob from the "edge" of the map, and makes them go towards the station.
// Can also use landmarks, if desired.
/datum/event2/event/mob_spawning/proc/spawn_mobs_in_space(mob_type, number_of_groups, min_size_of_group, max_size_of_group, dir)
if(isnull(dir))
dir = pick(GLOB.cardinal)
var/list/valid_z_levels = get_location_z_levels()
valid_z_levels -= using_map.sealed_levels // Space levels only please!
// Check if any landmarks exist!
var/list/spawn_locations = list()
for(var/obj/effect/landmark/C in landmarks_list)
if(C.name == landmark_name && (C.z in valid_z_levels))
spawn_locations.Add(C.loc)
var/prioritize_landmarks = TRUE
if(use_map_edge_with_landmarks && prob(50))
prioritize_landmarks = FALSE // One in two chance to come from the edge instead.
if(spawn_locations.len && prioritize_landmarks) // Okay we've got landmarks, lets use those!
shuffle_inplace(spawn_locations)
number_of_groups = min(number_of_groups, spawn_locations.len)
var/i = 1
while (i <= number_of_groups)
var/group_size = rand(min_size_of_group, max_size_of_group)
for (var/j = 0, j < group_size, j++)
spawn_one_mob(spawn_locations[i], mob_type)
i++
return
// Okay we did *not* have any landmarks, or we're being told to do both, so lets do our best!
var/i = 1
while(i <= number_of_groups)
var/z_level = pick(valid_z_levels)
var/group_size = rand(min_size_of_group, max_size_of_group)
var/turf/map_center = locate(round(world.maxx/2), round(world.maxy/2), z_level)
var/turf/group_center = pick_random_edge_turf(dir, z_level, TRANSITIONEDGE + 2)
var/list/turfs = getcircle(group_center, 2)
for(var/j = 0, j < group_size, j++)
// On larger maps, BYOND gets in the way of letting simple_mobs path to the closest edge of the station.
// So instead we need to simulate the mob's travel, then spawn them somewhere still hopefully off screen.
// Find a turf to be the edge of the map.
var/turf/edge_of_map = turfs[(i % turfs.len) + 1]
// Now walk a straight line towards the center of the map, until we find a non-space tile.
var/turf/edge_of_station = null
var/list/space_line = list() // This holds all space tiles on the line. Will be used a bit later.
for(var/turf/T in getline(edge_of_map, map_center))
if(!T.is_space())
break // We found the station!
space_line += T
edge_of_station = T
// Now put the mob somewhere on the line, hopefully off screen.
// I wish this was higher than 8 but the BYOND internal A* algorithm gives up sometimes when using
// 16 or more.
// In the future, a new AI stance that handles long distance travel using getline() could work.
var/max_distance = 8
var/turf/spawn_turf = null
for(var/P in space_line)
var/turf/point = P
if(get_dist(point, edge_of_station) <= max_distance)
spawn_turf = P
break
if(spawn_turf)
// Finally, make the simple_mob go towards the edge of the station.
var/mob/living/simple_mob/M = spawn_one_mob(spawn_turf, mob_type)
if(edge_of_station)
M.ai_holder?.give_destination(edge_of_station) // Ask simple_mobs to fly towards the edge of the station.
i++
/datum/event2/event/mob_spawning/proc/spawn_one_mob(new_loc, mob_type)
var/mob/living/simple_mob/M = new mob_type(new_loc)
GLOB.destroyed_event.register(M, src, .proc/on_mob_destruction)
spawned_mobs += M
return M
// Counts living simple_mobs spawned by this event.
/datum/event2/event/mob_spawning/proc/count_spawned_mobs()
. = 0
for(var/I in spawned_mobs)
var/mob/living/simple_mob/M = I
if(!QDELETED(M) && M.stat != DEAD)
. += 1
// If simple_mob is bomphed, remove it from the list.
/datum/event2/event/mob_spawning/proc/on_mob_destruction(mob/M)
spawned_mobs -= M
GLOB.destroyed_event.unregister(M, src, .proc/on_mob_destruction)