mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2025-12-24 00:51:26 +00:00
The defines now create a subtype under cargo_master for every spawner proc and use that to define probability and register the spawner instead of making tons of proc overrides. This also allows for more flexibility when defining the spawners if desired.
279 lines
9.9 KiB
Plaintext
279 lines
9.9 KiB
Plaintext
|
|
//See Setup.dm for the configuration vars:
|
|
//TOTAL_STOCK
|
|
//STOCK_UNCOMMON_PROB
|
|
//STOCK_RARE_PROB
|
|
//STOCK_LARGE_PROB
|
|
|
|
//Their values are set there
|
|
|
|
/*
|
|
At roundstart, some items will spawn in the cargo warehouse. MANY items in fact.
|
|
|
|
Generally, 20-40 items of various sorts will spawn.
|
|
|
|
Most of them (70-90%) will be chosen from the common items list. These items are designed to be fairly
|
|
useful and likely to be helpful to the station. They will help cement cargo's supply role - as the
|
|
place to go when you want to find things you lack.
|
|
|
|
A smaller amount will be from the uncommon items. This is a combination of more powerful items, and
|
|
useless but interesting curios. The uncommon category tends towards interestingness and niche use
|
|
|
|
Rare items will spawn fairly infrequently, These are things that can have a significant
|
|
effect on the round, and most of the spawnable weapons are in these categories. Many of the rare
|
|
items are prime targets for an antag raiding cargo, or a desperate crew looking for things to fight with
|
|
|
|
Large items are a more broadly weighted category with a variety of rare and common items. The main
|
|
defining criteria of this category is that they are dense, and usually structures or machinery, and
|
|
thus require a dedicated tile for themselves to spawn in.
|
|
|
|
Many items which draw from random pools, like meds/aid/signs/figures/plushies/booze/etc,
|
|
have been given higher probabilitiesthan those which simply spawn preset items. This encourages
|
|
more variety, and keeps the odds of any one specific item to be about the same
|
|
|
|
Actual definitions for possible items go in the files in `./random_stock`. Use the macros `STOCK_ITEM_COMMON(id,prob)`, `STOCK_ITEM_UNCOMMON(id,prob)`, `STOCK_ITEM_RARE(id,prob)`,
|
|
and `STOCK_ITEM_LARGE(id,prob)` to declare your spawn, and put your spawn code under the define like you're defining a proc. IDs must be unique within a category (common, large, etc),
|
|
but can be duplicated across categories. Available parameters are `atom/L` (loc the object should be spawned at), and for large objects, `datum/cargospawner/CS` (a ref to the parent cargospawner)
|
|
|
|
Example:
|
|
|
|
STOCK_ITEM_COMMON(bees, 2)
|
|
if (prob(95))
|
|
new /mob/living/bees(L)
|
|
else
|
|
new /mob/living/bees/evil(L)
|
|
|
|
*/
|
|
|
|
// The cargo_master datum is used to hold metadata about the cargo spawners. All subtypes are instantiated in misc_early to generate the cargo lists (as Atoms runs before Cargo).
|
|
// This also means that if you want to do something fancy with the spawning probability you can directly create a custom sub-datum of this
|
|
// instead of using the macros and override the get_probability proc or even the register_spawner proc.
|
|
/datum/cargo_master
|
|
var/category = null
|
|
var/probability = 0
|
|
var/spawner_proc = null
|
|
|
|
/datum/cargo_master/proc/get_probability()
|
|
return src.probability
|
|
|
|
/datum/cargo_master/proc/register_spawner()
|
|
var/P = src.get_probability()
|
|
if(P <= 0)
|
|
return 0
|
|
switch(src.category)
|
|
if("common")
|
|
return global.random_stock_common[src.spawner_proc] = P
|
|
if("uncommon")
|
|
return global.random_stock_uncommon[src.spawner_proc] = P
|
|
if("rare")
|
|
return global.random_stock_rare[src.spawner_proc] = P
|
|
if("large")
|
|
return global.random_stock_large[src.spawner_proc] = P
|
|
throw EXCEPTION("Cargo spawner definition '[src.type]' has invalid category '[src.category]'. Please fix your definition.")
|
|
|
|
/proc/setup_cargo_spawn_lists()
|
|
var/i
|
|
for(var/type in subtypesof(/datum/cargo_master))
|
|
var/datum/cargo_master/def = new type()
|
|
def.register_spawner()
|
|
i++
|
|
log_debug("Registered [i] cargo spawners.")
|
|
|
|
// These lists are populated by the files in `./random_stock` using the above procs.
|
|
var/list/global/random_stock_common = list()
|
|
var/list/global/random_stock_uncommon = list()
|
|
var/list/global/random_stock_rare = list()
|
|
var/list/global/random_stock_large = list()
|
|
|
|
/proc/spawn_cargo_stock()
|
|
var/start_time = world.timeofday
|
|
new /datum/cargospawner()
|
|
admin_notice("<span class='danger'>Cargo Stock generation completed in [round(0.1*(world.timeofday-start_time),0.1)] seconds.</span>", R_DEBUG)
|
|
|
|
/datum/cargospawner
|
|
var/list/containers = list()
|
|
var/list/tables = list()
|
|
var/list/full_containers = list()//Used to hold references to crates we filled up
|
|
var/area/warehouse
|
|
var/list/warehouseturfs = list()
|
|
|
|
var/list/infest_mobs_minor = list(
|
|
/mob/living/simple_animal/rat = 1,
|
|
/mob/living/simple_animal/lizard = 0.5,
|
|
/mob/living/simple_animal/yithian = 0.7,
|
|
/mob/living/simple_animal/tindalos = 0.6,
|
|
/mob/living/bot/secbot = 0.1)
|
|
|
|
var/list/infest_mobs_moderate = list(
|
|
/mob/living/simple_animal/bee/standalone = 1,
|
|
/mob/living/simple_animal/hostile/diyaab = 1,
|
|
/mob/living/simple_animal/hostile/viscerator = 1,
|
|
/mob/living/simple_animal/hostile/scarybat = 1)
|
|
|
|
var/list/infest_mobs_severe = list(
|
|
/mob/living/simple_animal/hostile/giant_spider/hunter = 1,
|
|
/mob/living/simple_animal/hostile/shantak = 0.7,
|
|
/mob/living/simple_animal/hostile/bear = 0.5,
|
|
/mob/living/simple_animal/hostile/carp = 1.5,
|
|
/mob/living/simple_animal/hostile/carp/russian = 0.3,
|
|
"cratey" = 1
|
|
)
|
|
|
|
/datum/cargospawner/New()
|
|
//First lets get the reference to our warehouse
|
|
for(var/areapath in typesof(/area/quartermaster/storage))
|
|
warehouse = locate(areapath)
|
|
if (warehouse)
|
|
for (var/turf/simulated/floor/T in warehouse)
|
|
warehouseturfs += T
|
|
for (var/obj/structure/closet/crate/C in warehouse)
|
|
containers |= C
|
|
for (var/obj/structure/table/B in warehouse)
|
|
if(B.no_cargo)
|
|
continue
|
|
tables |= B
|
|
|
|
/datum/cargospawner/proc/start()
|
|
if (!warehouse || !warehouseturfs.len)
|
|
admin_notice("<span class='danger'>ERROR: Cargo spawner failed to locate warehouse. Terminating.</span>", R_DEBUG)
|
|
qdel(src)
|
|
return
|
|
|
|
//First, we spawn the larger items
|
|
//Large objects are spawned on preset locations around cargo
|
|
//These locations are designated by large stock marker objects, which are manually mapped in
|
|
for (var/obj/effect/large_stock_marker/LSM in world)
|
|
if (prob(STOCK_LARGE_PROB))
|
|
var/type = pickweight(random_stock_large)
|
|
if (type)
|
|
call(type)(get_turf(LSM))
|
|
qdel(LSM)
|
|
|
|
//Now we spawn the smaller items
|
|
//These are spawned inside the cargo warehouse, in crates and on tables.
|
|
for (var/i in 1 to TOTAL_STOCK)
|
|
var/atom/spawnloc = get_location()
|
|
var/spawntype = get_spawntype()
|
|
if (spawntype)
|
|
call(spawntype)(spawnloc, src)
|
|
|
|
handle_infestation()
|
|
shuffle_items()
|
|
|
|
/datum/cargospawner/proc/get_location()
|
|
var/cratespawn = 0
|
|
var/obj/structure/closet/crate/emptiest
|
|
if (prob(70))//We'll usually put items in crates
|
|
var/minweight = 1000000000 //We will distribute items somewhat evenly among crates
|
|
//by selecting the least-filled one for each spawn
|
|
|
|
for (var/obj/structure/closet/crate/C in containers)
|
|
if (C.stored_weight() < minweight && C.stored_weight() < C.storage_capacity)
|
|
minweight = C.stored_weight()
|
|
emptiest = C
|
|
cratespawn = 1
|
|
|
|
if (cratespawn)
|
|
return emptiest
|
|
else if (length(tables))
|
|
//If cratespawn is zero, we either failed to find a crate to spawn in, or didnt select
|
|
//crate spawning with the random check.
|
|
var/turf/clearest
|
|
var/min_items = 999999999
|
|
for (var/B in tables)//As with crates, we attempt to distribute items evenly. Pick least-filled
|
|
var/TB = get_turf(B)
|
|
var/numitems = 0
|
|
for (var/obj/item in TB)
|
|
numitems++
|
|
if (numitems <= min_items)
|
|
clearest = TB
|
|
min_items = numitems
|
|
|
|
|
|
if (!clearest)//This should never happen
|
|
clearest = get_turf(pick(tables))
|
|
|
|
return clearest
|
|
|
|
/datum/cargospawner/proc/get_spawntype()
|
|
var/list/spawntypes = list("1" = STOCK_RARE_PROB, "2" = STOCK_UNCOMMON_PROB, "3" = (100 - (STOCK_RARE_PROB + STOCK_UNCOMMON_PROB)))
|
|
var/stocktype = pickweight(spawntypes)
|
|
switch (stocktype)
|
|
if ("1")
|
|
return pickweight(random_stock_rare)
|
|
if ("2")
|
|
return pickweight(random_stock_uncommon)
|
|
if ("3")
|
|
return pickweight(random_stock_common)
|
|
|
|
//Minor and moderate mobs are checked per crate
|
|
#define INFEST_PROB_MINOR 6
|
|
#define INFEST_PROB_MODERATE 3
|
|
|
|
#define INFEST_PROB_SEVERE 3//Severe is once per round, not per crate
|
|
|
|
/datum/cargospawner/proc/handle_infestation()
|
|
for (var/obj/O in containers)
|
|
if (prob(INFEST_PROB_MINOR))
|
|
//No admin message for the minor mobs, because they are friendly and harmless
|
|
var/ctype = pickweight(infest_mobs_minor)
|
|
new ctype(O)
|
|
else if (prob(INFEST_PROB_MODERATE))
|
|
var/ctype = pickweight(infest_mobs_moderate)
|
|
new ctype(O)
|
|
msg_admin_attack("Common cargo warehouse critter [ctype] spawned inside [O.name] coords (<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[O.x];Y=[O.y];Z=[O.z]'>JMP</a>)")
|
|
|
|
//This is checked only once per round. ~3% chance to spawn a scary monster infesting the warehouse
|
|
if (prob(INFEST_PROB_SEVERE))
|
|
//Find a tile to spawn the thing
|
|
var/list/turfs = list()
|
|
var/turf/T
|
|
for (var/turf/t in warehouseturfs)
|
|
T = t//Failsafe incase none are clear
|
|
if (turf_clear(T))
|
|
turfs |= t
|
|
|
|
if (turfs.len)
|
|
T = pick(turfs)
|
|
|
|
var/ctype = pickweight(infest_mobs_severe)
|
|
|
|
if (ctype == "cratey")
|
|
var/obj/C = pick(containers)
|
|
|
|
var/mob/living/simple_animal/hostile/mimic/copy/cratey
|
|
|
|
cratey = new /mob/living/simple_animal/hostile/mimic/copy(C.loc, C, null)
|
|
|
|
|
|
//Cratey is kinda tough but slow, easy to run away from
|
|
cratey.name = "Cratey"
|
|
cratey.health = 150
|
|
cratey.maxHealth = 150
|
|
cratey.melee_damage_lower = 7
|
|
cratey.melee_damage_upper = 18
|
|
cratey.knockdown_people = 1
|
|
cratey.move_to_delay = 12
|
|
|
|
msg_admin_attack("Cratey spawned coords (<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[cratey.x];Y=[cratey.y];Z=[cratey.z]'>JMP</a>)")
|
|
|
|
else
|
|
new ctype(T)
|
|
msg_admin_attack("Rare cargo warehouse critter [ctype] spawned coords (<a href='?_src_=holder;adminplayerobservecoodjump=1;X=[T.x];Y=[T.y];Z=[T.z]'>JMP</a>)")
|
|
return
|
|
|
|
/datum/cargospawner/proc/shuffle_items()
|
|
for (var/obj/O in containers)
|
|
O.contents = shuffle(O.contents)
|
|
|
|
for (var/obj/a in tables)
|
|
var/turf/T = get_turf(a)
|
|
T.contents = shuffle(T.contents)
|
|
|
|
|
|
/obj/effect/large_stock_marker
|
|
name = "Large Stock Marker"
|
|
desc = "This marks a place where a large object could spawn in cargo"
|
|
icon = 'icons/mob/screen/generic.dmi'
|
|
icon_state = "x3"
|