mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-31 12:01:47 +00:00
* Move current pick_weight consumers to not pass in zeros (#62940) About The Pull Request pick_weight_allow_zero was a backwards compatible hack, so it exists alongside pick_weight. I would really like to just remove the old proc and just rename it, so I want to log what, if anything, is relying on this behavior, to see if it's a bug or if it needs to be handled especially in that case. * Move current pick_weight consumers to not pass in zeros Co-authored-by: Mothblocks <35135081+Mothblocks@users.noreply.github.com>
161 lines
5.6 KiB
Plaintext
161 lines
5.6 KiB
Plaintext
/**
|
|
* Base class for all random spawners.
|
|
*/
|
|
/obj/effect/spawner/random
|
|
icon = 'icons/effects/random_spawners.dmi'
|
|
icon_state = "loot"
|
|
layer = OBJ_LAYER
|
|
/// Stops persistent lootdrop spawns from being shoved into lockers
|
|
anchored = TRUE
|
|
/// A list of possible items to spawn e.g. list(/obj/item, /obj/structure, /obj/effect)
|
|
var/list/loot
|
|
/// The subtypes AND type to combine with the loot list
|
|
var/loot_type_path
|
|
/// The subtypes (this excludes the provided path) to combine with the loot list
|
|
var/loot_subtype_path
|
|
/// Whether the spawner should immediately spawn loot and cleanup on Initialize()
|
|
var/spawn_on_init = TRUE
|
|
/// How many items will be spawned
|
|
var/spawn_loot_count = 1
|
|
/// If the same item can be spawned twice
|
|
var/spawn_loot_double = TRUE
|
|
/// Whether the items should be distributed to offsets 0,1,-1,2,-2,3,-3.. This overrides pixel_x/y on the spawner itself
|
|
var/spawn_loot_split = FALSE
|
|
/// Whether the spawner should spawn all the loot in the list
|
|
var/spawn_all_loot = FALSE
|
|
/// The chance for the spawner to create loot (ignores spawn_loot_count)
|
|
var/spawn_loot_chance = 100
|
|
/// Determines how big of a range (in tiles) we should scatter things in.
|
|
var/spawn_scatter_radius = 0
|
|
/// Whether the items should have a random pixel_x/y offset (maxium offset distance is ±16 pixels for x/y)
|
|
var/spawn_random_offset = FALSE
|
|
|
|
/obj/effect/spawner/random/Initialize(mapload)
|
|
. = ..()
|
|
|
|
if(should_spawn_on_init())
|
|
spawn_loot()
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
/// Helper proc that returns TRUE if the spawner should spawn loot in Initialise() and FALSE otherwise. Override this to change spawning behaviour.
|
|
/obj/effect/spawner/random/proc/should_spawn_on_init()
|
|
return spawn_on_init
|
|
|
|
///If the spawner has any loot defined, randomly picks some and spawns it. Does not cleanup the spawner.
|
|
/obj/effect/spawner/random/proc/spawn_loot(lootcount_override)
|
|
if(!prob(spawn_loot_chance))
|
|
return INITIALIZE_HINT_QDEL
|
|
|
|
var/list/spawn_locations = get_spawn_locations(spawn_scatter_radius)
|
|
var/spawn_loot_count = isnull(lootcount_override) ? src.spawn_loot_count : lootcount_override
|
|
|
|
if(spawn_all_loot)
|
|
spawn_loot_count = INFINITY
|
|
spawn_loot_double = FALSE
|
|
|
|
if(loot_type_path)
|
|
loot += typesof(loot_type_path)
|
|
|
|
if(loot_subtype_path)
|
|
loot += subtypesof(loot_subtype_path)
|
|
|
|
if(loot?.len)
|
|
var/loot_spawned = 0
|
|
while((spawn_loot_count-loot_spawned) && loot.len)
|
|
var/lootspawn = pick_weight(fill_with_ones(loot))
|
|
while(islist(lootspawn))
|
|
lootspawn = pick_weight(fill_with_ones(lootspawn))
|
|
if(!spawn_loot_double)
|
|
loot.Remove(lootspawn)
|
|
if(lootspawn && (spawn_scatter_radius == 0 || spawn_locations.len))
|
|
var/turf/spawn_loc = loc
|
|
if(spawn_scatter_radius > 0)
|
|
spawn_loc = pick_n_take(spawn_locations)
|
|
|
|
var/atom/movable/spawned_loot = new lootspawn(spawn_loc)
|
|
spawned_loot.setDir(dir)
|
|
|
|
if(istype(src, /obj/effect/spawner/random/trash/graffiti))
|
|
var/obj/effect/spawner/random/trash/graffiti/G = src
|
|
G.select_graffiti(spawned_loot)
|
|
//var/obj/graffiti = new /obj/effect/decal/cleanable/crayon(get_turf(src))
|
|
|
|
if (!spawn_loot_split && !spawn_random_offset)
|
|
if (pixel_x != 0)
|
|
spawned_loot.pixel_x = pixel_x
|
|
if (pixel_y != 0)
|
|
spawned_loot.pixel_y = pixel_y
|
|
else if (spawn_random_offset)
|
|
spawned_loot.pixel_x = rand(-16, 16)
|
|
spawned_loot.pixel_y = rand(-16, 16)
|
|
else if (spawn_loot_split)
|
|
if (loot_spawned)
|
|
spawned_loot.pixel_x = spawned_loot.pixel_y = ((!(loot_spawned%2)*loot_spawned/2)*-1)+((loot_spawned%2)*(loot_spawned+1)/2*1)
|
|
loot_spawned++
|
|
|
|
///If the spawner has a spawn_scatter_radius set, this creates a list of nearby turfs available
|
|
/obj/effect/spawner/random/proc/get_spawn_locations(radius)
|
|
var/list/scatter_locations = list()
|
|
|
|
if(radius >= 0)
|
|
for(var/turf/turf_in_view in view(radius, get_turf(src)))
|
|
if(!turf_in_view.density)
|
|
scatter_locations += turf_in_view
|
|
|
|
return scatter_locations
|
|
|
|
//finds the probabilities of items spawning from a loot spawner's loot pool
|
|
/obj/item/loot_table_maker
|
|
icon = 'icons/effects/landmarks_static.dmi'
|
|
icon_state = "random_loot"
|
|
var/spawner_to_test = /obj/effect/spawner/random/maintenance //what lootdrop spawner to use the loot pool of
|
|
var/loot_count = 180 //180 is about how much maint loot spawns per map as of 11/14/2019
|
|
//result outputs
|
|
var/list/spawned_table //list of all items "spawned" and how many
|
|
var/list/stat_table //list of all items "spawned" and their occurrance probability
|
|
|
|
/obj/item/loot_table_maker/Initialize(mapload)
|
|
. = ..()
|
|
make_table()
|
|
|
|
/obj/item/loot_table_maker/attack_self(mob/user)
|
|
to_chat(user, "Loot pool re-rolled.")
|
|
make_table()
|
|
|
|
/obj/item/loot_table_maker/proc/make_table()
|
|
spawned_table = list()
|
|
stat_table = list()
|
|
var/obj/effect/spawner/random/spawner_to_table = new spawner_to_test
|
|
var/lootpool = spawner_to_table.loot
|
|
qdel(spawner_to_table)
|
|
for(var/i in 1 to loot_count)
|
|
var/loot_spawn = pick_loot(lootpool)
|
|
if(!(loot_spawn in spawned_table))
|
|
spawned_table[loot_spawn] = 1
|
|
else
|
|
spawned_table[loot_spawn] += 1
|
|
stat_table += spawned_table
|
|
for(var/item in stat_table)
|
|
stat_table[item] /= loot_count
|
|
|
|
/obj/item/loot_table_maker/proc/pick_loot(lootpool) //selects path from loot table and returns it
|
|
var/lootspawn = pick_weight(fill_with_ones(lootpool))
|
|
while(islist(lootspawn))
|
|
lootspawn = pick_weight(fill_with_ones(lootspawn))
|
|
return lootspawn
|
|
|
|
// Lets loot tables be both list(a, b, c), as well as list(a = 3, b = 2, c = 2)
|
|
/proc/fill_with_ones(list/table)
|
|
if (!islist(table))
|
|
return table
|
|
|
|
var/list/final_table = list()
|
|
|
|
for (var/key in table)
|
|
if (table[key])
|
|
final_table[key] = table[key]
|
|
else
|
|
final_table[key] = 1
|
|
|
|
return final_table
|