From fd2fc3287d756574b8343d8159966be384cfe37a Mon Sep 17 00:00:00 2001 From: coiax Date: Sat, 17 Jul 2021 16:15:20 +0100 Subject: [PATCH] Rework maintenance loot spawners to fire at roundstart (#59913) Maintenance loot spawners now fire at roundstart, rather than during the initialization of the Atoms subsystem. Maintenance loot spawners do not qdel themselves during the spawning process, but persist, and merely hide themselves from living players. As a cute side effect, this lets preround observers look at the colourful maintenance loot dice icons before the round starts. Observers can continue to see the loot dice post-round, but they are deliberately very faint. --- code/_globalvars/lists/maintenance_loot.dm | 3 + code/controllers/subsystem/mapping.dm | 8 +++ .../game/objects/effects/spawners/lootdrop.dm | 55 +++++++++++++++++-- 3 files changed, 62 insertions(+), 4 deletions(-) diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index 4def9ee12b808..6acfe8589b1f0 100644 --- a/code/_globalvars/lists/maintenance_loot.dm +++ b/code/_globalvars/lists/maintenance_loot.dm @@ -348,3 +348,6 @@ GLOBAL_LIST_INIT(ratking_coins, list(//Coins: Used by the regal rat mob when spa /obj/item/coin/silver, /obj/item/coin/plastic, /obj/item/coin/titanium)) + +// List of all maintenance loot spawners, for easy finding at roundstart. +GLOBAL_LIST_EMPTY(maintenance_loot_spawners) diff --git a/code/controllers/subsystem/mapping.dm b/code/controllers/subsystem/mapping.dm index e43f1da1c0360..a1c041b8c8a3c 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -127,6 +127,7 @@ SUBSYSTEM_DEF(mapping) setup_map_transitions() generate_station_area_list() initialize_reserved_level(transit.z_value) + SSticker.OnRoundstart(CALLBACK(src, .proc/spawn_maintenance_loot)) return ..() /datum/controller/subsystem/mapping/proc/wipe_reservations(wipe_safety_delay = 100) @@ -590,3 +591,10 @@ GLOBAL_LIST_EMPTY(the_station_areas) isolated_ruins_z = add_new_zlevel("Isolated Ruins/Reserved", list(ZTRAIT_RESERVED = TRUE, ZTRAIT_ISOLATED_RUINS = TRUE)) initialize_reserved_level(isolated_ruins_z.z_value) return isolated_ruins_z.z_value + +/datum/controller/subsystem/mapping/proc/spawn_maintenance_loot() + for(var/obj/effect/spawner/lootdrop/maintenance/spawner as anything in GLOB.maintenance_loot_spawners) + CHECK_TICK + + spawner.spawn_loot() + spawner.hide() diff --git a/code/game/objects/effects/spawners/lootdrop.dm b/code/game/objects/effects/spawners/lootdrop.dm index 735545d0558b4..dc6b37620a70d 100644 --- a/code/game/objects/effects/spawners/lootdrop.dm +++ b/code/game/objects/effects/spawners/lootdrop.dm @@ -2,13 +2,25 @@ icon = 'icons/effects/landmarks_static.dmi' icon_state = "random_loot" layer = OBJ_LAYER + anchored = TRUE // Stops persistent lootdrop spawns from being shoved into lockers var/lootcount = 1 //how many items will be spawned var/lootdoubles = TRUE //if the same item can be spawned twice var/list/loot //a list of possible items to spawn e.g. list(/obj/item, /obj/structure, /obj/effect) var/fan_out_items = FALSE //Whether the items should be distributed to offsets 0,1,-1,2,-2,3,-3.. This overrides pixel_x/y on the spawner itself + /// Whether the spawner should immediately spawn loot and cleanup on Initialize() + var/spawn_on_init = TRUE /obj/effect/spawner/lootdrop/Initialize(mapload) - ..() + . = ..() + + if(spawn_on_init) + spawn_loot() + return INITIALIZE_HINT_QDEL + +///If the spawner has any loot defined, randomly picks some and spawns it. Does not cleanup the spawner. +/obj/effect/spawner/lootdrop/proc/spawn_loot(lootcount_override) + var/lootcount = isnull(lootcount_override) ? src.lootcount : lootcount_override + if(loot?.len) var/loot_spawned = 0 while((lootcount-loot_spawned) && loot.len) @@ -29,7 +41,6 @@ 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++ - return INITIALIZE_HINT_QDEL /obj/effect/spawner/lootdrop/donkpockets name = "donk pocket box spawner" @@ -240,19 +251,55 @@ /obj/effect/spawner/lootdrop/maintenance name = "maintenance loot spawner" + desc = "Come on Lady Luck, spawn me a pair of sunglasses." + spawn_on_init = FALSE // see code/_globalvars/lists/maintenance_loot.dm for loot table +/obj/effect/spawner/lootdrop/maintenance/examine(mob/user) + . = ..() + . += span_info("This spawner has an effective loot count of [get_effective_lootcount()].") + /obj/effect/spawner/lootdrop/maintenance/Initialize(mapload) + . = ..() + // There is a single callback in SSmapping to spawn all delayed maintenance loot + // so we don't just make one callback per loot spawner + GLOB.maintenance_loot_spawners += src loot = GLOB.maintenance_loot + // Late loaded templates like shuttles can have maintenance loot + if(SSticker.current_state >= GAME_STATE_SETTING_UP) + spawn_loot() + hide() + +/obj/effect/spawner/lootdrop/maintenance/Destroy() + GLOB.maintenance_loot_spawners -= src + return ..() + +/obj/effect/spawner/lootdrop/maintenance/proc/hide() + invisibility = INVISIBILITY_OBSERVER + alpha = 100 + +/obj/effect/spawner/lootdrop/maintenance/proc/get_effective_lootcount() + var/effective_lootcount = lootcount + if(HAS_TRAIT(SSstation, STATION_TRAIT_FILLED_MAINT)) - lootcount = FLOOR(lootcount * 1.5, 1) + effective_lootcount = FLOOR(lootcount * 1.5, 1) else if(HAS_TRAIT(SSstation, STATION_TRAIT_EMPTY_MAINT)) - lootcount = FLOOR(lootcount * 0.5, 1) + effective_lootcount = FLOOR(lootcount * 0.5, 1) + + return effective_lootcount +/obj/effect/spawner/lootdrop/maintenance/spawn_loot(lootcount_override) + if(isnull(lootcount_override)) + lootcount_override = get_effective_lootcount() . = ..() + // In addition, closets that are closed will have the maintenance loot inserted inside. + for(var/obj/structure/closet/closet in get_turf(src)) + if(!closet.opened) + closet.take_contents() + /obj/effect/spawner/lootdrop/maintenance/two name = "2 x maintenance loot spawner" lootcount = 2