diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index 4def9ee12b8..6acfe8589b1 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 e43f1da1c03..a1c041b8c8a 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 735545d0558..dc6b37620a7 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