diff --git a/code/__DEFINES/dcs/signals/signals_closet.dm b/code/__DEFINES/dcs/signals/signals_closet.dm new file mode 100644 index 00000000000..fb78d69b8a1 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_closet.dm @@ -0,0 +1,2 @@ +/// Called in /obj/structure/closet/PopulateContents() +#define COMSIG_CLOSET_POPULATE_CONTENTS "closet_populate_contents" diff --git a/code/__DEFINES/loot.dm b/code/__DEFINES/loot.dm new file mode 100644 index 00000000000..3dd7d94808e --- /dev/null +++ b/code/__DEFINES/loot.dm @@ -0,0 +1,13 @@ +/// The loot table for spawning a random crate +#define RANDOM_CRATE_LOOT list( \ + /obj/structure/closet/crate = 20, \ + /obj/structure/closet/crate/wooden = 1, \ + /obj/structure/closet/crate/internals = 1, \ + /obj/structure/closet/crate/medical = 1, \ + /obj/structure/closet/crate/freezer = 1, \ + /obj/structure/closet/crate/radiation = 1, \ + /obj/structure/closet/crate/hydroponics = 1, \ + /obj/structure/closet/crate/engineering = 1, \ + /obj/structure/closet/crate/engineering/electrical = 1, \ + /obj/structure/closet/crate/science = 1, \ +) diff --git a/code/__DEFINES/~skyrat_defines/maintenance_loot.dm b/code/__DEFINES/~skyrat_defines/maintenance_loot.dm index 73eb9a3d231..9bf486982de 100644 --- a/code/__DEFINES/~skyrat_defines/maintenance_loot.dm +++ b/code/__DEFINES/~skyrat_defines/maintenance_loot.dm @@ -22,6 +22,3 @@ #define MAINT_ODD_WEIGHT 1 //1 out of 10,000 would give metastation (180 spawns) a 2 in 111 chance of spawning an oddity per round, similar to xeno egg. #define MAINT_HOLIDAY_WEIGHT 3500 // When holiday loot is enabled, it'll give every loot item a 25% chance of being a holiday item. #define maint_holiday_weight MAINT_HOLIDAY_WEIGHT - -// List of all maintenance loot spawners, for easy finding at roundstart. -GLOBAL_LIST_EMPTY(maintenance_loot_spawners) diff --git a/code/_globalvars/lists/maintenance_loot.dm b/code/_globalvars/lists/maintenance_loot.dm index e4ffdff8592..9c7ffb606f5 100644 --- a/code/_globalvars/lists/maintenance_loot.dm +++ b/code/_globalvars/lists/maintenance_loot.dm @@ -394,7 +394,4 @@ GLOBAL_LIST_INIT(ratking_coins, list(//Coins: Used by the regal rat mob when spa /obj/item/coin/silver, /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 f5825c64db1..31ed0c5ebb9 100644 --- a/code/controllers/subsystem/mapping.dm +++ b/code/controllers/subsystem/mapping.dm @@ -110,7 +110,6 @@ SUBSYSTEM_DEF(mapping) setup_map_transitions() generate_station_area_list() initialize_reserved_level(transit.z_value) - SSticker.OnRoundstart(CALLBACK(src, .proc/spawn_maintenance_loot)) generate_z_level_linkages() calculate_default_z_level_gravities() @@ -666,10 +665,3 @@ 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/random/maintenance/spawner as anything in GLOB.maintenance_loot_spawners) - CHECK_TICK - - spawner.spawn_loot() - qdel(spawner) diff --git a/code/game/objects/effects/decals/decal.dm b/code/game/objects/effects/decals/decal.dm index 68e446c9d42..85bdeffd9ad 100644 --- a/code/game/objects/effects/decals/decal.dm +++ b/code/game/objects/effects/decals/decal.dm @@ -35,6 +35,7 @@ icon = 'icons/turf/decals.dmi' icon_state = "warningline" layer = TURF_DECAL_LAYER + anchored = TRUE /obj/effect/turf_decal/Initialize(mapload) . = ..() diff --git a/code/game/objects/effects/spawners/random/maintenance.dm b/code/game/objects/effects/spawners/random/maintenance.dm index d685e448368..8652bc3c5d0 100644 --- a/code/game/objects/effects/spawners/random/maintenance.dm +++ b/code/game/objects/effects/spawners/random/maintenance.dm @@ -2,7 +2,6 @@ name = "maintenance loot spawner" desc = "Come on Lady Luck, spawn me a pair of sunglasses." icon_state = "loot" - spawn_on_init = FALSE // see code/_globalvars/lists/maintenance_loot.dm for loot table /obj/effect/spawner/random/maintenance/examine(mob/user) @@ -14,22 +13,6 @@ . = ..() - GLOB.maintenance_loot_spawners += src - -/obj/effect/spawner/random/maintenance/should_spawn_on_init() - . = ..() - - if(.) - return - - // Late loaded templates like shuttles can have maintenance loot. - // Once the game state progresses to roundstart, new maint loot spawners should just instantly pop. - return (SSticker.current_state >= GAME_STATE_SETTING_UP) - -/obj/effect/spawner/random/maintenance/Destroy() - GLOB.maintenance_loot_spawners -= src - return ..() - /obj/effect/spawner/random/maintenance/proc/hide() invisibility = INVISIBILITY_OBSERVER alpha = 100 diff --git a/code/game/objects/effects/spawners/random/structure.dm b/code/game/objects/effects/spawners/random/structure.dm index 2d5e4966cf6..2d65d944dfc 100644 --- a/code/game/objects/effects/spawners/random/structure.dm +++ b/code/game/objects/effects/spawners/random/structure.dm @@ -85,21 +85,11 @@ /obj/structure/tank_holder/extinguisher/advanced = 1, ) + /obj/effect/spawner/random/structure/crate_empty name = "empty crate spawner" icon_state = "crate" - loot = list( - /obj/structure/closet/crate = 20, - /obj/structure/closet/crate/wooden = 1, - /obj/structure/closet/crate/internals = 1, - /obj/structure/closet/crate/medical = 1, - /obj/structure/closet/crate/freezer = 1, - /obj/structure/closet/crate/radiation = 1, - /obj/structure/closet/crate/hydroponics = 1, - /obj/structure/closet/crate/engineering = 1, - /obj/structure/closet/crate/engineering/electrical = 1, - /obj/structure/closet/crate/science = 1, - ) + loot = RANDOM_CRATE_LOOT /obj/effect/spawner/random/structure/crate_empty/make_item(spawn_loc, type_path_to_make) var/obj/structure/closet/crate/peek_a_boo = ..() diff --git a/code/game/objects/structures/crates_lockers/closets.dm b/code/game/objects/structures/crates_lockers/closets.dm index dd4131a10eb..d7dbb0a784d 100644 --- a/code/game/objects/structures/crates_lockers/closets.dm +++ b/code/game/objects/structures/crates_lockers/closets.dm @@ -68,14 +68,14 @@ var/obj/item/electronics/airlock/electronics var/can_install_electronics = TRUE + var/contents_initialized = FALSE + /obj/structure/closet/Initialize(mapload) if(mapload && !opened) // if closed, any item at the crate's loc is put in the contents addtimer(CALLBACK(src, .proc/take_contents, TRUE), 0) . = ..() update_appearance() - PopulateContents() - if(QDELETED(src)) //It turns out populate contents has a 1 in 100 chance of qdeling src on /obj/structure/closet/emcloset - return //Why + populate_contents_immediate() var/static/list/loc_connections = list( COMSIG_CARBON_DISARM_COLLIDE = .proc/locker_carbon, COMSIG_ATOM_MAGICALLY_UNLOCKED = .proc/on_magic_unlock, @@ -84,6 +84,11 @@ //USE THIS TO FILL IT, NOT INITIALIZE OR NEW /obj/structure/closet/proc/PopulateContents() + SEND_SIGNAL(src, COMSIG_CLOSET_POPULATE_CONTENTS) + +/// Populate the closet with stuff that needs to be added before it is opened. +/// This is useful for things like traitor objectives. +/obj/structure/closet/proc/populate_contents_immediate() return /obj/structure/closet/Destroy() @@ -231,6 +236,10 @@ return TRUE /obj/structure/closet/dump_contents() + if (!contents_initialized) + contents_initialized = TRUE + PopulateContents() + var/atom/L = drop_location() for(var/atom/movable/AM in src) AM.forceMove(L) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm index 38e67d543a2..ab584d86bdc 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/cargo.dm @@ -26,8 +26,13 @@ new /obj/item/circuitboard/machine/techfab/department/cargo(src) new /obj/item/storage/photo_album/qm(src) new /obj/item/circuitboard/machine/ore_silo(src) - new /obj/item/card/id/departmental_budget/car(src) new /obj/item/clothing/suit/hooded/wintercoat/cargo/qm(src) new /obj/item/gun/ballistic/rifle/boltaction/brand_new/quartermaster(src) // SKYRAT EDIT - The QM's 'special' head item. It spawns loaded, but you have to find more ammo if you run out and get ready to manually load rounds in! new /obj/item/cargo_teleporter(src) // SKYRAT EDIT - Adds a cargo teleporter to QM locker, so they can intice others to research it new /obj/item/clothing/glasses/hud/gun_permit/sunglasses(src) //SKYRAT EDIT - GUN CARGO + +/obj/structure/closet/secure_closet/quartermaster/populate_contents_immediate() + . = ..() + + // Traitor steal objective + new /obj/item/card/id/departmental_budget/car(src) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm index b2b95f5adff..2ed6269e6fb 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/engineering.dm @@ -10,7 +10,6 @@ new /obj/item/computer_hardware/hard_drive/portable/command/ce(src) new /obj/item/radio/headset/heads/ce(src) new /obj/item/megaphone/command(src) - new /obj/item/areaeditor/blueprints(src) new /obj/item/holosign_creator/atmos(src) new /obj/item/assembly/flash/handheld(src) new /obj/item/door_remote/chief_engineer(src) @@ -23,6 +22,12 @@ new /obj/item/construction/plumbing/engineering(src) //SKYRAT EDIT ADDITION new /obj/item/circuitboard/machine/rodstopper(src) //SKYRAT EDIT ADDITION +/obj/structure/closet/secure_closet/engineering_chief/populate_contents_immediate() + . = ..() + + // Traitor steal objective + new /obj/item/areaeditor/blueprints(src) + /obj/structure/closet/secure_closet/engineering_electrical name = "electrical supplies locker" req_access = list(ACCESS_ENGINE_EQUIP) diff --git a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm index 4326aead034..0925483fe41 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/medical.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/medical.dm @@ -84,9 +84,7 @@ new /obj/item/defibrillator/compact/loaded(src) new /obj/item/healthanalyzer/advanced(src) new /obj/item/assembly/flash/handheld(src) - new /obj/item/storage/briefcase/medicalgunset/cmo(src) //SKYRAT ADDITON MEDIGUNS// - // new /obj/item/reagent_containers/hypospray/cmo(src) - SKYRAT REMOVAL - New Hyposprays - new /obj/item/storage/hypospraykit/cmo(src) //SKYRAT ADDITION - New Hyposprays + new /obj/item/storage/briefcase/medicalgunset/cmo(src) //SKYRAT EDIT ADDITION MEDIGUNS new /obj/item/autosurgeon/medical_hud(src) new /obj/item/door_remote/chief_medical_officer(src) new /obj/item/clothing/neck/petcollar(src) @@ -96,6 +94,12 @@ new /obj/item/storage/photo_album/cmo(src) new /obj/item/storage/lockbox/medal/med(src) +/obj/structure/closet/secure_closet/chief_medical/populate_contents_immediate() + . = ..() + + // Traitor steal objective + //new /obj/item/reagent_containers/hypospray/cmo(src) - ORIGINAL + new /obj/item/storage/hypospraykit/cmo(src) //SKYRAT EDIT ADDITION - New Hyposprays /obj/structure/closet/secure_closet/animal name = "animal control" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/misc.dm b/code/game/objects/structures/crates_lockers/closets/secure/misc.dm index 91f1690858a..78faa05eaaf 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/misc.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/misc.dm @@ -8,7 +8,6 @@ ..() new /obj/item/storage/medkit/regular(src) new /obj/item/storage/box/handcuffs(src) - new /obj/item/aicard(src) new /obj/item/assembly/flash/handheld(src) if(prob(50)) new /obj/item/ammo_box/magazine/m50(src) @@ -19,6 +18,12 @@ new /obj/item/ammo_box/a357(src) new /obj/item/gun/ballistic/revolver/mateba(src) +/obj/structure/closet/secure_closet/ert_com/populate_contents_immediate() + . = ..() + + // Traitor steal objective + new /obj/item/aicard(src) + /obj/structure/closet/secure_closet/ert_sec name = "emergency response team security locker" desc = "A storage unit containing equipment for an Emergency Response Team Security Officer." diff --git a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm index afd09bcefc1..8634f16b6f9 100755 --- a/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/scientist.dm @@ -13,15 +13,18 @@ new /obj/item/radio/headset/heads/rd(src) new /obj/item/megaphone/command(src) new /obj/item/storage/lockbox/medal/sci(src) - new /obj/item/clothing/suit/armor/reactive/teleport(src) new /obj/item/assembly/flash/handheld(src) - new /obj/item/laser_pointer(src) new /obj/item/door_remote/research_director(src) new /obj/item/circuitboard/machine/techfab/department/science(src) new /obj/item/storage/photo_album/rd(src) new /obj/item/storage/box/skillchips/science(src) +/obj/structure/closet/secure_closet/research_director/populate_contents_immediate() + . = ..() + // Traitor steal objectives + new /obj/item/clothing/suit/armor/reactive/teleport(src) + new /obj/item/laser_pointer(src) /obj/structure/closet/secure_closet/cytology name = "cytology equipment locker" diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 60fbe2c3d3b..4e3e9856219 100755 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -63,11 +63,16 @@ new /obj/item/storage/box/flashbangs(src) new /obj/item/shield/riot/tele(src) new /obj/item/storage/belt/security/full(src) - new /obj/item/gun/energy/e_gun/hos(src) - new /obj/item/pinpointer/nuke(src) new /obj/item/circuitboard/machine/techfab/department/security(src) new /obj/item/storage/photo_album/hos(src) +/obj/structure/closet/secure_closet/hos/populate_contents_immediate() + . = ..() + + // Traitor steal objectives + new /obj/item/gun/energy/e_gun/hos(src) + new /obj/item/pinpointer/nuke(src) + /obj/structure/closet/secure_closet/warden name = "\proper warden's locker" req_access = list(ACCESS_ARMORY) @@ -321,7 +326,6 @@ /obj/structure/closet/secure_closet/armory1/PopulateContents() ..() - new /obj/item/clothing/suit/hooded/ablative(src) for(var/i in 1 to 3) new /obj/item/clothing/suit/armor/riot(src) for(var/i in 1 to 3) @@ -329,6 +333,12 @@ for(var/i in 1 to 3) new /obj/item/shield/riot(src) +/obj/structure/closet/secure_closet/armory1/populate_contents_immediate() + . = ..() + + // Traitor steal objective + new /obj/item/clothing/suit/hooded/ablative(src) + /obj/structure/closet/secure_closet/armory2 name = "armory ballistics locker" req_access = list(ACCESS_ARMORY) diff --git a/code/game/objects/structures/crates_lockers/closets/syndicate.dm b/code/game/objects/structures/crates_lockers/closets/syndicate.dm index 918b2eaf8ee..60d9fa87da7 100644 --- a/code/game/objects/structures/crates_lockers/closets/syndicate.dm +++ b/code/game/objects/structures/crates_lockers/closets/syndicate.dm @@ -32,8 +32,9 @@ /obj/structure/closet/syndicate/resources desc = "An old, dusty locker." -/obj/structure/closet/syndicate/resources/PopulateContents() - ..() +// A lot of this stuff is objective items, and it's also only used for debugging, so init times don't matter here. +/obj/structure/closet/syndicate/resources/populate_contents_immediate() + . = ..() var/common_min = 30 //Minimum amount of minerals in the stack for common minerals var/common_max = 50 //Maximum amount of HONK in the stack for HONK common minerals var/rare_min = 5 //Minimum HONK of HONK in the stack HONK HONK rare minerals @@ -97,7 +98,8 @@ desc = "It's an emergency storage closet for repairs." storage_capacity = 60 // This is gonna be used for debug. -/obj/structure/closet/syndicate/resources/everything/PopulateContents() +// A lot of this stuff is objective items, and it's also only used for debugging, so init times don't matter here. +/obj/structure/closet/syndicate/resources/everything/populate_contents_immediate() var/list/resources = list( /obj/item/stack/sheet/iron, /obj/item/stack/sheet/glass, diff --git a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm index 3f6e65c528e..0d5183f4e45 100644 --- a/code/game/objects/structures/crates_lockers/closets/utility_closets.dm +++ b/code/game/objects/structures/crates_lockers/closets/utility_closets.dm @@ -20,13 +20,19 @@ /obj/structure/closet/emcloset/anchored anchored = TRUE +/obj/structure/closet/emcloset/Initialize(mapload) + . = ..() + + if (prob(1)) + return INITIALIZE_HINT_QDEL + /obj/structure/closet/emcloset/PopulateContents() // SKYRAT EDIT OVERRIDE - emergency_spacesuit.dm ..() if (prob(40)) new /obj/item/storage/toolbox/emergency(src) - switch (pick_weight(list("small" = 35, "aid" = 30, "tank" = 20, "both" = 10, "nothing" = 4, "delete" = 1))) + switch (pick_weight(list("small" = 35, "aid" = 30, "tank" = 20, "both" = 10, "nothing" = 4))) if ("small") new /obj/item/tank/internals/emergency_oxygen(src) new /obj/item/tank/internals/emergency_oxygen(src) @@ -48,10 +54,7 @@ if ("nothing") // doot - - // teehee //Fuck you - if ("delete") - qdel(src) + pass() /* * Fire Closet diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm index 5da4142cec5..6c981c60653 100644 --- a/code/game/objects/structures/crates_lockers/crates.dm +++ b/code/game/objects/structures/crates_lockers/crates.dm @@ -113,12 +113,23 @@ /obj/structure/closet/crate/maint/Initialize(mapload) ..() + + var/static/list/possible_crates = RANDOM_CRATE_LOOT + + var/crate_path = pick_weight(possible_crates) + + var/obj/structure/closet/crate = new crate_path(loc) + crate.RegisterSignal(crate, COMSIG_CLOSET_POPULATE_CONTENTS, /obj/structure/closet/.proc/populate_with_random_maint_loot) + if (prob(50)) + crate.opened = TRUE + crate.update_appearance() + return INITIALIZE_HINT_QDEL -/obj/structure/closet/crate/maint/PopulateContents() - . = ..() - new /obj/effect/spawner/random/structure/crate_empty(loc) - for(var/i in 1 to rand(2,6)) +/obj/structure/closet/proc/populate_with_random_maint_loot() + SIGNAL_HANDLER + + for (var/i in 1 to rand(2,6)) new /obj/effect/spawner/random/maintenance(src) /obj/structure/closet/crate/trashcart/Initialize(mapload) @@ -270,9 +281,14 @@ /obj/structure/closet/crate/goldcrate/PopulateContents() ..() + new /obj/item/storage/belt/champion(src) + +/obj/structure/closet/crate/goldcrate/populate_contents_immediate() + . = ..() + + // /datum/objective_item/stack/gold for(var/i in 1 to 3) new /obj/item/stack/sheet/mineral/gold(src, 1, FALSE) - new /obj/item/storage/belt/champion(src) /obj/structure/closet/crate/silvercrate name = "silver crate" diff --git a/code/modules/unit_tests/closets.dm b/code/modules/unit_tests/closets.dm index 2e3b18aa6f8..b7f0d5e94c4 100644 --- a/code/modules/unit_tests/closets.dm +++ b/code/modules/unit_tests/closets.dm @@ -1,4 +1,5 @@ -/// Checks that the length of the initial contents of a closet doesn't exceed its storage capacity +/// Checks that the length of the initial contents of a closet doesn't exceed its storage capacity. +/// Also checks that nothing inside that isn't immediate is a steal objective. /datum/unit_test/closets /datum/unit_test/closets/Run() @@ -8,6 +9,16 @@ for(var/closet_type in all_closets) var/obj/structure/closet/closet = allocate(closet_type) + + // Copy is necessary otherwise closet.contents - immediate_contents returns an empty list + var/list/immediate_contents = closet.contents.Copy() + + closet.PopulateContents() var/contents_len = length(closet.contents) + if(contents_len > closet.storage_capacity) - Fail("Initial Contents of [closet.type] ([contents_len]) exceed its storage capacity ([closet.storage_capacity]).") + TEST_FAIL("Initial Contents of [closet.type] ([contents_len]) exceed its storage capacity ([closet.storage_capacity]).") + + for (var/obj/item/item in closet.contents - immediate_contents) + if (item.type in GLOB.steal_item_handler.objectives_by_path) + TEST_FAIL("[closet_type] contains a steal objective [item.type] in PopulateContents(). Move it to populate_contents_immediate().") diff --git a/tgstation.dme b/tgstation.dme index 63a3182391c..04a65873b92 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -105,6 +105,7 @@ #include "code\__DEFINES\lighting.dm" #include "code\__DEFINES\living.dm" #include "code\__DEFINES\logging.dm" +#include "code\__DEFINES\loot.dm" #include "code\__DEFINES\machines.dm" #include "code\__DEFINES\magic.dm" #include "code\__DEFINES\maps.dm" @@ -217,6 +218,7 @@ #include "code\__DEFINES\dcs\signals\signals_changeling.dm" #include "code\__DEFINES\dcs\signals\signals_circuit.dm" #include "code\__DEFINES\dcs\signals\signals_client.dm" +#include "code\__DEFINES\dcs\signals\signals_closet.dm" #include "code\__DEFINES\dcs\signals\signals_clothing.dm" #include "code\__DEFINES\dcs\signals\signals_container.dm" #include "code\__DEFINES\dcs\signals\signals_customizable.dm"