diff --git a/code/__defines/mapping.dm b/code/__defines/mapping.dm index 5cf7407fb5e..d8219fb0c6e 100644 --- a/code/__defines/mapping.dm +++ b/code/__defines/mapping.dm @@ -36,3 +36,5 @@ if(other_init) { \ #define MAP_TEMPLATE_CATEGORY_EXOPLANET "exoplanet_template" #define MAP_TEMPLATE_CATEGORY_SPACE "space_template" #define MAP_TEMPLATE_CATEGORY_AWAYSITE "awaysite_template" +///PS13 Template that is spawned as part of the main map, and shouldn't be considered an away site during unit tests. +#define MAP_TEMPLATE_CATEGORY_MAIN_SITE "main_site_template" diff --git a/code/__defines/misc.dm b/code/__defines/misc.dm index 07f7005f433..2996f20e2bb 100644 --- a/code/__defines/misc.dm +++ b/code/__defines/misc.dm @@ -7,9 +7,20 @@ #define TURF_IS_HOLOMAP_PATH BITFLAG(4) #define TURF_IS_HOLOMAP_ROCK BITFLAG(5) -#define TRANSITIONEDGE 7 // Distance from edge to move to another z-level. +///Width or height of a transition edge area along the map's borders where transition edge turfs are placed to connect levels together. +#define TRANSITIONEDGE 7 +///Extra spacing needed between any random ruins and the transition edge of a level. #define RUIN_MAP_EDGE_PAD 15 +///Enum value for a level edge that's to be untouched +#define LEVEL_EDGE_NONE 0 +///Enum value for a level edge that's to be looped with the opposite edge +#define LEVEL_EDGE_LOOP 1 +///Enum value for a level edge that's to be filled with a wall filler turfs +#define LEVEL_EDGE_WALL 2 +///Enum value for a level edge that's to be connected with another z-level +#define LEVEL_EDGE_CON 3 + // Invisibility constants. #define INVISIBILITY_LIGHTING 20 #define INVISIBILITY_LEVEL_ONE 35 diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 88e5450eb9c..77fa63d52ad 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -928,7 +928,12 @@ var/global/list/gamemode_cache = list() config.withdraw_period = value DAYS if("interest_period") config.interest_period = value DAYS - + if("grant_default_darksight") + config.grant_default_darksight = TRUE + if("default_darksight_range") + config.default_darksight_range = max(text2num(value), 0) + if("default_darksight_effectiveness") + config.default_darksight_effectiveness = clamp(text2num(value), 0, 1) if("interest_mod_delay") config.interest_mod_delay = value DAYS if("withdraw_mod_delay") diff --git a/code/controllers/subsystems/ambience.dm b/code/controllers/subsystems/ambience.dm index 6bbe3b27fea..879c6584d8c 100644 --- a/code/controllers/subsystems/ambience.dm +++ b/code/controllers/subsystems/ambience.dm @@ -41,7 +41,7 @@ SUBSYSTEM_DEF(ambience) if(lit) // Grab what we need to set ambient light from our level handler. - var/obj/abstract/level_data/level_data = SSmapping.levels_by_z[z] + var/datum/level_data/level_data = SSmapping.levels_by_z[z] if(level_data?.ambient_light_level) set_ambient_light(level_data.ambient_light_color, level_data.ambient_light_level) return TRUE diff --git a/code/controllers/subsystems/mapping.dm b/code/controllers/subsystems/mapping.dm index 2aac24ed7eb..38d84944812 100644 --- a/code/controllers/subsystems/mapping.dm +++ b/code/controllers/subsystems/mapping.dm @@ -81,6 +81,8 @@ SUBSYSTEM_DEF(mapping) // This needs to be non-null even if the overmap isn't created for this map. overmap_event_handler = GET_DECL(/decl/overmap_event_handler) + //PS13 Build main map sites templates + global.using_map.build_main_sites() // Build away sites. global.using_map.build_away_sites() @@ -89,9 +91,9 @@ SUBSYSTEM_DEF(mapping) config.generate_map = TRUE #endif for(var/z = 1 to world.maxz) - var/obj/abstract/level_data/level = levels_by_z[z] + var/datum/level_data/level = levels_by_z[z] if(!istype(level)) - level = new /obj/abstract/level_data/space(locate(round(world.maxx*0.5), round(world.maxy*0.5), z)) + level = new /datum/level_data/space(z) PRINT_STACK_TRACE("Missing z-level data object for z[num2text(z)]!") level.setup_level_data() @@ -141,9 +143,10 @@ SUBSYSTEM_DEF(mapping) // Z-Level procs after this point. /datum/controller/subsystem/mapping/proc/get_gps_level_name(var/z) if(z) - var/obj/abstract/level_data/level = levels_by_z[z] - if(level?.name) - return level.get_gps_level_name() + var/datum/level_data/level = levels_by_z[z] + . = level.get_display_name() + if(length(.)) + return . return "Unknown Sector" /datum/controller/subsystem/mapping/proc/reindex_lists() @@ -162,24 +165,72 @@ SUBSYSTEM_DEF(mapping) PRINT_STACK_TRACE("Missing z-level data type for z["[world.maxz]"]!") return - var/obj/abstract/level_data/level = new new_level_type(locate(round(world.maxx*0.5), round(world.maxy*0.5), world.maxz), defer_setup) - level.initialize_level() + var/datum/level_data/level = new new_level_type(world.maxz, defer_setup) + level.initialize_new_level() return level /datum/controller/subsystem/mapping/proc/get_connected_levels(z) if(z <= 0 || z > length(levels_by_z)) CRASH("Invalid z-level supplied to get_connected_levels: [isnull(z) ? "NULL" : z]") - . = list(z) + var/list/root_stack = list(z) // Traverse up and down to get the multiz stack. for(var/level = z, HasBelow(level), level--) - . |= level-1 + root_stack |= level-1 for(var/level = z, HasAbove(level), level++) - . |= level+1 + root_stack |= level+1 + . = list() // Check stack for any laterally connected neighbors. - for(var/tz in .) - var/obj/abstract/level_data/level = levels_by_z[tz] + for(var/tz in root_stack) + var/datum/level_data/level = levels_by_z[tz] if(level) - level.find_connected_levels(.) + var/list/cur_connected = level.get_all_connected_level_z() + if(length(cur_connected)) + . |= cur_connected + . |= root_stack + +///Returns a list of all the level data of all the connected z levels to the given z.DBColumn +/datum/controller/subsystem/mapping/proc/get_connected_levels_data(z) + if(z <= 0 || z > length(levels_by_z)) + CRASH("Invalid z-level supplied to get_connected_levels_data: [isnull(z) ? "NULL" : z]") + var/list/root_lvl_data = list(levels_by_z[z]) + + // Traverse up and down to get the multiz stack. + for(var/level = z, HasBelow(level), level--) + root_lvl_data |= levels_by_z[level - 1] + for(var/level = z, HasAbove(level), level++) + root_lvl_data |= levels_by_z[level + 1] + + . = list() + // Check stack for any laterally connected neighbors. + for(var/datum/level_data/L in root_lvl_data) + var/list/cur_connected = L.get_all_connected_level_data() + if(length(cur_connected)) + . |= cur_connected + . |= root_lvl_data + +/datum/controller/subsystem/mapping/proc/get_connected_levels_ids(z) + if(z <= 0 || z > length(levels_by_z)) + CRASH("Invalid z-level supplied to get_connected_levels_ids: [isnull(z) ? "NULL" : z]") + var/datum/level_data/LD = levels_by_z[z] + var/list/root_lvl_ids = list(LD.level_id) + + // Traverse up and down to get the multiz stack. + for(var/level = z, HasBelow(level), level--) + var/datum/level_data/L = levels_by_z[level - 1] + root_lvl_ids |= L.level_id + for(var/level = z, HasAbove(level), level++) + var/datum/level_data/L = levels_by_z[level + 1] + root_lvl_ids |= L.level_id + + . = list() + // Check stack for any laterally connected neighbors. + for(var/id in root_lvl_ids) + var/datum/level_data/level = levels_by_id[id] + if(level) + var/list/cur_connected = level.get_all_connected_level_ids() + if(length(cur_connected)) + . |= cur_connected + . |= root_lvl_ids /datum/controller/subsystem/mapping/proc/are_connected_levels(var/zA, var/zB) if (zA <= 0 || zB <= 0 || zA > world.maxz || zB > world.maxz) @@ -196,3 +247,56 @@ SUBSYSTEM_DEF(mapping) connected_z_cache.len = zA connected_z_cache[zA] = new_entry return new_entry[zB] + +/// Registers all the needed infos from a level_data into the mapping subsystem +/datum/controller/subsystem/mapping/proc/register_level_data(var/datum/level_data/LD) + if(levels_by_z.len < LD.level_z) + levels_by_z.len = max(levels_by_z.len, LD.level_z) + PRINT_STACK_TRACE("Attempting to initialize a z-level([LD.level_z]) that has not incremented world.maxz.") + + //Assign level z + var/datum/level_data/old_level = levels_by_z[LD.level_z] + levels_by_z[LD.level_z] = LD + + if(old_level) + // Swap out the old one but preserve any relevant references etc. + old_level.replace_with(LD) + QDEL_NULL(old_level) + + //Setup ID ref + if(isnull(LD.level_id)) + PRINT_STACK_TRACE("Null level_id specified for z[LD.level_z].") + else if(LD.level_id in levels_by_id) + PRINT_STACK_TRACE("Duplicate level_id '[LD.level_id]' for z[LD.level_z].") + else + levels_by_id[LD.level_id] = LD + + //Always add base turf for Z. It'll get replaced as needed. + base_turf_by_z[LD.level_z] = LD.base_turf || world.turf + + //Add to level flags lookup lists + if(LD.level_flags & ZLEVEL_STATION) + station_levels |= LD.level_z + if(LD.level_flags & ZLEVEL_ADMIN) + admin_levels |= LD.level_z + if(LD.level_flags & ZLEVEL_CONTACT) + contact_levels |= LD.level_z + if(LD.level_flags & ZLEVEL_PLAYER) + player_levels |= LD.level_z + if(LD.level_flags & ZLEVEL_SEALED) + sealed_levels |= LD.level_z + return TRUE + +/datum/controller/subsystem/mapping/proc/unregister_level_data(var/datum/level_data/LD) + if(levels_by_z[LD.level_z] == LD) + //Clear the level data ref from the list if we're in it. + levels_by_z[LD.level_z] = null + levels_by_id -= LD.level_id + + base_turf_by_z[LD.level_z] = world.turf + station_levels -= LD.level_z + admin_levels -= LD.level_z + contact_levels -= LD.level_z + player_levels -= LD.level_z + sealed_levels -= LD.level_z + return TRUE \ No newline at end of file diff --git a/code/controllers/subsystems/zcopy.dm b/code/controllers/subsystems/zcopy.dm index fdadc76814b..058afaa1f3d 100644 --- a/code/controllers/subsystems/zcopy.dm +++ b/code/controllers/subsystems/zcopy.dm @@ -432,10 +432,11 @@ SUBSYSTEM_DEF(zcopy) qo_idex = 1 /datum/controller/subsystem/zcopy/proc/flush_z_state(turf/T) - if (T.below.mimic_above_copy) - QDEL_NULL(T.below.mimic_above_copy) - if (T.below.mimic_proxy) - QDEL_NULL(T.below.mimic_proxy) + if(T.below) + if (T.below.mimic_above_copy) + QDEL_NULL(T.below.mimic_above_copy) + if (T.below.mimic_proxy) + QDEL_NULL(T.below.mimic_proxy) for (var/atom/movable/openspace/OO in T) if (istype(OO, /atom/movable/openspace/mimic)) qdel(OO) diff --git a/code/datums/trading/traders/ai.dm b/code/datums/trading/traders/ai.dm index b14cc79939f..a698401b6ed 100644 --- a/code/datums/trading/traders/ai.dm +++ b/code/datums/trading/traders/ai.dm @@ -75,48 +75,49 @@ They sell generic supplies and ask for generic supplies. origin = "Mining Beacon" possible_trading_items = list( - /obj/item/stack/material/ore = TRADER_SUBTYPES_ONLY, - /obj/item/stack/material/pane/mapped/glass = TRADER_ALL, - /obj/item/stack/material/pane/mapped/glass/fifty = TRADER_BLACKLIST, - /obj/item/stack/material/ingot/mapped/iron = TRADER_THIS_TYPE, - /obj/item/stack/material/brick/mapped/sandstone = TRADER_THIS_TYPE, - /obj/item/stack/material/brick/mapped/marble = TRADER_THIS_TYPE, - /obj/item/stack/material/gemstone/mapped/diamond = TRADER_THIS_TYPE, - /obj/item/stack/material/puck/mapped/uranium = TRADER_THIS_TYPE, - /obj/item/stack/material/panel/mapped/plastic = TRADER_THIS_TYPE, - /obj/item/stack/material/ingot/mapped/gold = TRADER_THIS_TYPE, - /obj/item/stack/material/ingot/mapped/silver = TRADER_THIS_TYPE, - /obj/item/stack/material/ingot/mapped/platinum = TRADER_THIS_TYPE, - /obj/item/stack/material/segment/mapped/mhydrogen = TRADER_THIS_TYPE, - /obj/item/stack/material/aerogel/mapped/tritium = TRADER_THIS_TYPE, - /obj/item/stack/material/ingot/mapped/osmium = TRADER_THIS_TYPE, - /obj/item/stack/material/sheet/mapped/steel = TRADER_THIS_TYPE, + /obj/item/stack/material/ore = TRADER_SUBTYPES_ONLY, + /obj/item/stack/material/pane/mapped/glass = TRADER_ALL, + /obj/item/stack/material/pane/mapped/glass/fifty = TRADER_BLACKLIST, + /obj/item/stack/material/ingot/mapped/iron = TRADER_THIS_TYPE, + /obj/item/stack/material/brick/mapped/sandstone = TRADER_THIS_TYPE, + /obj/item/stack/material/brick/mapped/marble = TRADER_THIS_TYPE, + /obj/item/stack/material/gemstone/mapped/diamond = TRADER_THIS_TYPE, + /obj/item/stack/material/puck/mapped/uranium = TRADER_THIS_TYPE, + /obj/item/stack/material/panel/mapped/plastic = TRADER_THIS_TYPE, + /obj/item/stack/material/ingot/mapped/gold = TRADER_THIS_TYPE, + /obj/item/stack/material/ingot/mapped/silver = TRADER_THIS_TYPE, + /obj/item/stack/material/ingot/mapped/platinum = TRADER_THIS_TYPE, + /obj/item/stack/material/segment/mapped/mhydrogen = TRADER_THIS_TYPE, + /obj/item/stack/material/aerogel/mapped/tritium = TRADER_THIS_TYPE, + /obj/item/stack/material/ingot/mapped/osmium = TRADER_THIS_TYPE, + /obj/item/stack/material/sheet/mapped/steel = TRADER_THIS_TYPE, /obj/item/stack/material/reinforced/mapped/plasteel = TRADER_THIS_TYPE, - /obj/machinery/mining = TRADER_SUBTYPES_ONLY + /obj/machinery/mining = TRADER_SUBTYPES_ONLY ) /datum/trader/trading_beacon/manufacturing origin = "Manifacturing Beacon" - possible_trading_items = list(/obj/structure/aicore = TRADER_THIS_TYPE, - /obj/structure/girder = TRADER_THIS_TYPE, - /obj/structure/grille = TRADER_THIS_TYPE, - /obj/structure/mopbucket = TRADER_THIS_TYPE, - /obj/structure/ore_box = TRADER_THIS_TYPE, - /obj/structure/coatrack = TRADER_THIS_TYPE, - /obj/structure/bookcase = TRADER_THIS_TYPE, - /obj/item/bee_pack = TRADER_THIS_TYPE, - /obj/item/bee_smoker = TRADER_THIS_TYPE, - /obj/item/beehive_assembly = TRADER_THIS_TYPE, - /obj/item/glass_jar = TRADER_THIS_TYPE, - /obj/item/honey_frame = TRADER_THIS_TYPE, - /obj/item/target = TRADER_ALL, - /obj/structure/tank_rack = TRADER_SUBTYPES_ONLY, - /obj/structure/filing_cabinet = TRADER_THIS_TYPE, - /obj/structure/safe = TRADER_THIS_TYPE, - /obj/structure/plushie = TRADER_SUBTYPES_ONLY, - /obj/structure/sign = TRADER_SUBTYPES_ONLY, - /obj/structure/sign/double = TRADER_BLACKLIST_ALL, - /obj/structure/sign/goldenplaque = TRADER_BLACKLIST_ALL, - /obj/structure/sign/poster = TRADER_BLACKLIST - ) \ No newline at end of file + possible_trading_items = list( + /obj/structure/aicore = TRADER_THIS_TYPE, + /obj/structure/girder = TRADER_THIS_TYPE, + /obj/structure/grille = TRADER_THIS_TYPE, + /obj/structure/mopbucket = TRADER_THIS_TYPE, + /obj/structure/ore_box = TRADER_THIS_TYPE, + /obj/structure/coatrack = TRADER_THIS_TYPE, + /obj/structure/bookcase = TRADER_THIS_TYPE, + /obj/item/bee_pack = TRADER_THIS_TYPE, + /obj/item/bee_smoker = TRADER_THIS_TYPE, + /obj/item/beehive_assembly = TRADER_THIS_TYPE, + /obj/item/glass_jar = TRADER_THIS_TYPE, + /obj/item/honey_frame = TRADER_THIS_TYPE, + /obj/item/target = TRADER_ALL, + /obj/structure/tank_rack = TRADER_SUBTYPES_ONLY, + /obj/structure/filing_cabinet = TRADER_THIS_TYPE, + /obj/structure/safe = TRADER_THIS_TYPE, + /obj/structure/plushie = TRADER_SUBTYPES_ONLY, + /obj/structure/sign = TRADER_SUBTYPES_ONLY, + /obj/structure/sign/double = TRADER_BLACKLIST_ALL, + /obj/structure/sign/goldenplaque = TRADER_BLACKLIST_ALL, + /obj/structure/sign/poster = TRADER_BLACKLIST + ) \ No newline at end of file diff --git a/code/datums/trading/traders/books.dm b/code/datums/trading/traders/books.dm index 37868196b8a..5bc123f0fa1 100644 --- a/code/datums/trading/traders/books.dm +++ b/code/datums/trading/traders/books.dm @@ -6,27 +6,29 @@ possible_wanted_items = list() price_rng = 30 - possible_trading_items = list(/obj/item/book/skill/organizational/literacy = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/organizational/finance = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/general/eva = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/general/mech = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/general/pilot = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/general/hauling = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/general/computer = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/service/botany = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/service/cooking = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/security/combat = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/security/weapons = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/security/forensics = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/engineering/construction = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/engineering/electrical = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/engineering/atmos = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/engineering/engines = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/research/devices = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/research/science = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/medical/chemistry = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/medical/medicine = TRADER_SUBTYPES_ONLY, - /obj/item/book/skill/medical/anatomy = TRADER_SUBTYPES_ONLY) + possible_trading_items = list( + /obj/item/book/skill/organizational/literacy = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/organizational/finance = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/general/eva = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/general/mech = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/general/pilot = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/general/hauling = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/general/computer = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/service/botany = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/service/cooking = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/security/combat = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/security/weapons = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/security/forensics = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/engineering/construction = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/engineering/electrical = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/engineering/atmos = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/engineering/engines = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/research/devices = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/research/science = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/medical/chemistry = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/medical/medicine = TRADER_SUBTYPES_ONLY, + /obj/item/book/skill/medical/anatomy = TRADER_SUBTYPES_ONLY + ) speech = list("hail_generic" = "Yes hello hello! Many fine paperstacks for sale! Please buy!", "hail_deny" = "Not in! I'm not here! Go away!!", diff --git a/code/datums/trading/traders/food.dm b/code/datums/trading/traders/food.dm index 49fa1e9b218..6325df8a7f4 100644 --- a/code/datums/trading/traders/food.dm +++ b/code/datums/trading/traders/food.dm @@ -5,7 +5,7 @@ possible_origins = list("Papa Joe's", "Pizza Ship", "Dominator Pizza", "Little Kaezars", "Pizza Planet", "Cheese Louise", "Little Taste o' Neo-Italy", "Pizza Gestapo") trade_flags = TRADER_MONEY possible_wanted_items = list() //They are a pizza shop, not a bargainer. - possible_trading_items = list(/obj/item/chems/food/sliceable/pizza = TRADER_SUBTYPES_ONLY) + possible_trading_items = list(/obj/item/chems/food/sliceable/pizza = TRADER_SUBTYPES_ONLY) speech = list("hail_generic" = "Hello! Welcome to ORIGIN, may I take your order?", "hail_deny" = "Beeeep... I'm sorry, your connection has been severed.", @@ -40,14 +40,15 @@ possible_origins = list("888 Shanghai Kitchen", "Mr. Lee's Greater Hong Kong", "The House of the Venerable and Inscrutable Colonel", "Lucky Dragon") trade_flags = TRADER_MONEY possible_wanted_items = list() - possible_trading_items = list(/obj/item/chems/food/meatkabob = TRADER_THIS_TYPE, - /obj/item/chems/food/monkeysdelight = TRADER_THIS_TYPE, - /obj/item/chems/food/ricepudding = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/xenomeatbread/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/soydope = TRADER_THIS_TYPE, - /obj/item/chems/food/stewedsoymeat = TRADER_THIS_TYPE, - /obj/item/chems/drinks/dry_ramen = TRADER_THIS_TYPE - ) + possible_trading_items = list( + /obj/item/chems/food/meatkabob = TRADER_THIS_TYPE, + /obj/item/chems/food/monkeysdelight = TRADER_THIS_TYPE, + /obj/item/chems/food/ricepudding = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/xenomeatbread/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/soydope = TRADER_THIS_TYPE, + /obj/item/chems/food/stewedsoymeat = TRADER_THIS_TYPE, + /obj/item/chems/drinks/dry_ramen = TRADER_THIS_TYPE + ) var/list/fortunes = list("Today it's up to you to create the peacefulness you long for.", "If you refuse to accept anything but the best, you very often get it.", @@ -92,19 +93,20 @@ possible_origins = list("HyTee", "Kreugars", "Spaceway", "Privaxs", "FutureValue", "Phyvendyme", "Seller's Market") trade_flags = TRADER_MONEY - possible_trading_items = list(/obj/item/chems/food = TRADER_SUBTYPES_ONLY, - /obj/item/chems/drinks/cans = TRADER_SUBTYPES_ONLY, - /obj/item/chems/drinks/bottle = TRADER_SUBTYPES_ONLY, - /obj/item/chems/drinks/bottle/small = TRADER_BLACKLIST, - /obj/item/chems/food/checker = TRADER_BLACKLIST_ALL, - /obj/item/chems/food/fruit_slice = TRADER_BLACKLIST, - /obj/item/chems/food/slice = TRADER_BLACKLIST_ALL, - /obj/item/chems/food/grown = TRADER_BLACKLIST_ALL, - /obj/item/chems/food/human = TRADER_BLACKLIST_ALL, - /obj/item/chems/food/sliceable/braincake = TRADER_BLACKLIST, - /obj/item/chems/food/meat/human = TRADER_BLACKLIST, - /obj/item/chems/food/variable = TRADER_BLACKLIST_ALL - ) + possible_trading_items = list( + /obj/item/chems/food = TRADER_SUBTYPES_ONLY, + /obj/item/chems/drinks/cans = TRADER_SUBTYPES_ONLY, + /obj/item/chems/drinks/bottle = TRADER_SUBTYPES_ONLY, + /obj/item/chems/drinks/bottle/small = TRADER_BLACKLIST, + /obj/item/chems/food/checker = TRADER_BLACKLIST_ALL, + /obj/item/chems/food/fruit_slice = TRADER_BLACKLIST, + /obj/item/chems/food/slice = TRADER_BLACKLIST_ALL, + /obj/item/chems/food/grown = TRADER_BLACKLIST_ALL, + /obj/item/chems/food/human = TRADER_BLACKLIST_ALL, + /obj/item/chems/food/sliceable/braincake = TRADER_BLACKLIST, + /obj/item/chems/food/meat/human = TRADER_BLACKLIST, + /obj/item/chems/food/variable = TRADER_BLACKLIST_ALL + ) speech = list("hail_generic" = "Hello, welcome to ORIGIN, grocery store of the future!", "hail_deny" = "I'm sorry, we've blacklisted your communications due to rude behavior.", @@ -145,20 +147,22 @@ "bribe_refusal" = "Oh ho ho! I'd never think of taking ORIGIN on the road!", ) - possible_trading_items = list(/obj/item/chems/food/slice/birthdaycake/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/carrotcake/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/cheesecake/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/chocolatecake/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/lemoncake/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/limecake/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/orangecake/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/plaincake/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/pumpkinpie/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/slice/bananabread/filled = TRADER_THIS_TYPE, - /obj/item/chems/food/sliceable = TRADER_SUBTYPES_ONLY, - /obj/item/chems/food/sliceable/pizza = TRADER_BLACKLIST_ALL, - /obj/item/chems/food/sliceable/xenomeatbread = TRADER_BLACKLIST, - /obj/item/chems/food/sliceable/flatdough = TRADER_BLACKLIST, - /obj/item/chems/food/sliceable/braincake = TRADER_BLACKLIST, - /obj/item/chems/food/pie = TRADER_THIS_TYPE, - /obj/item/chems/food/applepie = TRADER_THIS_TYPE) \ No newline at end of file + possible_trading_items = list( + /obj/item/chems/food/slice/birthdaycake/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/carrotcake/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/cheesecake/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/chocolatecake/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/lemoncake/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/limecake/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/orangecake/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/plaincake/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/pumpkinpie/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/slice/bananabread/filled = TRADER_THIS_TYPE, + /obj/item/chems/food/sliceable = TRADER_SUBTYPES_ONLY, + /obj/item/chems/food/sliceable/pizza = TRADER_BLACKLIST_ALL, + /obj/item/chems/food/sliceable/xenomeatbread = TRADER_BLACKLIST, + /obj/item/chems/food/sliceable/flatdough = TRADER_BLACKLIST, + /obj/item/chems/food/sliceable/braincake = TRADER_BLACKLIST, + /obj/item/chems/food/pie = TRADER_THIS_TYPE, + /obj/item/chems/food/applepie = TRADER_THIS_TYPE + ) \ No newline at end of file diff --git a/code/datums/trading/traders/goods.dm b/code/datums/trading/traders/goods.dm index bc35fc9aece..4a10c72202e 100644 --- a/code/datums/trading/traders/goods.dm +++ b/code/datums/trading/traders/goods.dm @@ -71,24 +71,26 @@ "bribe_accept" = "Why not! Glad to be here for a few more minutes.", ) - possible_trading_items = list(/obj/item/stock_parts/computer/battery_module = TRADER_SUBTYPES_ONLY, - /obj/item/stock_parts/circuitboard = TRADER_SUBTYPES_ONLY, - /obj/item/stock_parts/circuitboard/telecomms = TRADER_BLACKLIST, - /obj/item/stock_parts/circuitboard/unary_atmos = TRADER_BLACKLIST, - /obj/item/stock_parts/circuitboard/arcade = TRADER_BLACKLIST, - /obj/item/stock_parts/circuitboard/broken = TRADER_BLACKLIST, - /obj/item/stack/cable_coil = TRADER_SUBTYPES_ONLY, - /obj/item/stack/cable_coil/cyborg = TRADER_BLACKLIST, - /obj/item/stack/cable_coil/random = TRADER_BLACKLIST, - /obj/item/stack/cable_coil/cut = TRADER_BLACKLIST, - /obj/item/stock_parts/circuitboard/air_alarm = TRADER_THIS_TYPE, - /obj/item/stock_parts/circuitboard/airlock_electronics = TRADER_ALL, - /obj/item/cell = TRADER_THIS_TYPE, - /obj/item/cell/crap = TRADER_THIS_TYPE, - /obj/item/cell/high = TRADER_THIS_TYPE, - /obj/item/cell/super = TRADER_THIS_TYPE, - /obj/item/cell/hyper = TRADER_THIS_TYPE, - /obj/item/tracker_electronics = TRADER_THIS_TYPE) + possible_trading_items = list( + /obj/item/stock_parts/computer/battery_module = TRADER_SUBTYPES_ONLY, + /obj/item/stock_parts/circuitboard = TRADER_SUBTYPES_ONLY, + /obj/item/stock_parts/circuitboard/telecomms = TRADER_BLACKLIST, + /obj/item/stock_parts/circuitboard/unary_atmos = TRADER_BLACKLIST, + /obj/item/stock_parts/circuitboard/arcade = TRADER_BLACKLIST, + /obj/item/stock_parts/circuitboard/broken = TRADER_BLACKLIST, + /obj/item/stack/cable_coil = TRADER_SUBTYPES_ONLY, + /obj/item/stack/cable_coil/cyborg = TRADER_BLACKLIST, + /obj/item/stack/cable_coil/random = TRADER_BLACKLIST, + /obj/item/stack/cable_coil/cut = TRADER_BLACKLIST, + /obj/item/stock_parts/circuitboard/air_alarm = TRADER_THIS_TYPE, + /obj/item/stock_parts/circuitboard/airlock_electronics = TRADER_ALL, + /obj/item/cell = TRADER_THIS_TYPE, + /obj/item/cell/crap = TRADER_THIS_TYPE, + /obj/item/cell/high = TRADER_THIS_TYPE, + /obj/item/cell/super = TRADER_THIS_TYPE, + /obj/item/cell/hyper = TRADER_THIS_TYPE, + /obj/item/tracker_electronics = TRADER_THIS_TYPE + ) /* Clothing stores: each a different type. A hat/glove store, a shoe store, and a jumpsuit store. */ @@ -117,60 +119,66 @@ "bribe_accept" = "Hm.... sure! We'll have a few minutes of 'engine troubles'.", ) - possible_trading_items = list(/obj/item/clothing/under = TRADER_SUBTYPES_ONLY, - /obj/item/clothing/under/chameleon = TRADER_BLACKLIST, - /obj/item/clothing/under/color = TRADER_BLACKLIST, - /obj/item/clothing/under/dress = TRADER_BLACKLIST, - /obj/item/clothing/under/gimmick = TRADER_BLACKLIST_ALL, - /obj/item/clothing/under/lawyer = TRADER_BLACKLIST, - /obj/item/clothing/under/pj = TRADER_BLACKLIST, - /obj/item/clothing/under = TRADER_BLACKLIST, - /obj/item/clothing/pants/shorts = TRADER_BLACKLIST, - /obj/item/clothing/under/mankini = TRADER_BLACKLIST_ALL, - /obj/item/clothing/under/syndicate = TRADER_BLACKLIST_ALL, - /obj/item/clothing/under/tactical = TRADER_BLACKLIST, - /obj/item/clothing/under/waiter/monke = TRADER_BLACKLIST, - /obj/item/clothing/under/wedding = TRADER_BLACKLIST, - /obj/item/clothing/pants/casual/mustangjeans/monke = TRADER_BLACKLIST) + possible_trading_items = list( + /obj/item/clothing/under = TRADER_SUBTYPES_ONLY, + /obj/item/clothing/under/chameleon = TRADER_BLACKLIST, + /obj/item/clothing/under/color = TRADER_BLACKLIST, + /obj/item/clothing/under/dress = TRADER_BLACKLIST, + /obj/item/clothing/under/gimmick = TRADER_BLACKLIST_ALL, + /obj/item/clothing/under/lawyer = TRADER_BLACKLIST, + /obj/item/clothing/under/pj = TRADER_BLACKLIST, + /obj/item/clothing/under = TRADER_BLACKLIST, + /obj/item/clothing/pants/shorts = TRADER_BLACKLIST, + /obj/item/clothing/under/mankini = TRADER_BLACKLIST_ALL, + /obj/item/clothing/under/syndicate = TRADER_BLACKLIST_ALL, + /obj/item/clothing/under/tactical = TRADER_BLACKLIST, + /obj/item/clothing/under/waiter/monke = TRADER_BLACKLIST, + /obj/item/clothing/under/wedding = TRADER_BLACKLIST, + /obj/item/clothing/pants/casual/mustangjeans/monke = TRADER_BLACKLIST + ) /datum/trader/ship/clothingshop/shoes possible_origins = list("Foot Safe", "Paysmall", "Popular Footwear", "Grimbly's Shoes", "Right Steps") - possible_trading_items = list(/obj/item/clothing/shoes = TRADER_SUBTYPES_ONLY, - /obj/item/clothing/shoes/chameleon = TRADER_BLACKLIST, - /obj/item/clothing/shoes/jackboots/swat/combat = TRADER_BLACKLIST, - /obj/item/clothing/shoes/clown_shoes = TRADER_BLACKLIST, - /obj/item/clothing/shoes/cult = TRADER_BLACKLIST, - /obj/item/clothing/shoes/lightrig = TRADER_BLACKLIST_ALL, - /obj/item/clothing/shoes/magboots = TRADER_BLACKLIST_ALL, - /obj/item/clothing/shoes/jackboots/swat = TRADER_BLACKLIST, - /obj/item/clothing/shoes/syndigaloshes = TRADER_BLACKLIST) + possible_trading_items = list( + /obj/item/clothing/shoes = TRADER_SUBTYPES_ONLY, + /obj/item/clothing/shoes/chameleon = TRADER_BLACKLIST, + /obj/item/clothing/shoes/jackboots/swat/combat = TRADER_BLACKLIST, + /obj/item/clothing/shoes/clown_shoes = TRADER_BLACKLIST, + /obj/item/clothing/shoes/cult = TRADER_BLACKLIST, + /obj/item/clothing/shoes/lightrig = TRADER_BLACKLIST_ALL, + /obj/item/clothing/shoes/magboots = TRADER_BLACKLIST_ALL, + /obj/item/clothing/shoes/jackboots/swat = TRADER_BLACKLIST, + /obj/item/clothing/shoes/syndigaloshes = TRADER_BLACKLIST + ) /datum/trader/ship/clothingshop/hatglovesaccessories possible_origins = list("Baldie's Hats and Accessories", "The Right Fit", "Like a Glove", "Space Fashion") - possible_trading_items = list(/obj/item/clothing/accessory = TRADER_ALL, - /obj/item/clothing/accessory/badge = TRADER_BLACKLIST_ALL, - /obj/item/clothing/accessory/storage/holster = TRADER_BLACKLIST_ALL, - /obj/item/clothing/accessory/medal = TRADER_BLACKLIST_ALL, - /obj/item/clothing/accessory/storage = TRADER_BLACKLIST_ALL, - /obj/item/clothing/gloves = TRADER_SUBTYPES_ONLY, - /obj/item/clothing/gloves/lightrig = TRADER_BLACKLIST_ALL, - /obj/item/clothing/gloves/rig = TRADER_BLACKLIST_ALL, - /obj/item/clothing/gloves/thick/swat = TRADER_BLACKLIST, - /obj/item/clothing/gloves/chameleon = TRADER_BLACKLIST, - /obj/item/clothing/head = TRADER_SUBTYPES_ONLY, - /obj/item/clothing/head/HoS = TRADER_BLACKLIST_ALL, - /obj/item/clothing/head/bio_hood = TRADER_BLACKLIST_ALL, - /obj/item/clothing/head/bomb_hood = TRADER_BLACKLIST_ALL, - /obj/item/clothing/head/caphat = TRADER_BLACKLIST_ALL, - /obj/item/clothing/head/centhat = TRADER_BLACKLIST, - /obj/item/clothing/head/chameleon = TRADER_BLACKLIST, - /obj/item/clothing/head/collectable = TRADER_BLACKLIST, - /obj/item/clothing/head/culthood = TRADER_BLACKLIST_ALL, - /obj/item/clothing/head/helmet = TRADER_BLACKLIST_ALL, - /obj/item/clothing/head/lightrig = TRADER_BLACKLIST_ALL, - /obj/item/clothing/head/radiation = TRADER_BLACKLIST, - /obj/item/clothing/head/warden = TRADER_BLACKLIST, - /obj/item/clothing/head/welding = TRADER_BLACKLIST) + possible_trading_items = list( + /obj/item/clothing/accessory = TRADER_ALL, + /obj/item/clothing/accessory/badge = TRADER_BLACKLIST_ALL, + /obj/item/clothing/accessory/storage/holster = TRADER_BLACKLIST_ALL, + /obj/item/clothing/accessory/medal = TRADER_BLACKLIST_ALL, + /obj/item/clothing/accessory/storage = TRADER_BLACKLIST_ALL, + /obj/item/clothing/gloves = TRADER_SUBTYPES_ONLY, + /obj/item/clothing/gloves/lightrig = TRADER_BLACKLIST_ALL, + /obj/item/clothing/gloves/rig = TRADER_BLACKLIST_ALL, + /obj/item/clothing/gloves/thick/swat = TRADER_BLACKLIST, + /obj/item/clothing/gloves/chameleon = TRADER_BLACKLIST, + /obj/item/clothing/head = TRADER_SUBTYPES_ONLY, + /obj/item/clothing/head/HoS = TRADER_BLACKLIST_ALL, + /obj/item/clothing/head/bio_hood = TRADER_BLACKLIST_ALL, + /obj/item/clothing/head/bomb_hood = TRADER_BLACKLIST_ALL, + /obj/item/clothing/head/caphat = TRADER_BLACKLIST_ALL, + /obj/item/clothing/head/centhat = TRADER_BLACKLIST, + /obj/item/clothing/head/chameleon = TRADER_BLACKLIST, + /obj/item/clothing/head/collectable = TRADER_BLACKLIST, + /obj/item/clothing/head/culthood = TRADER_BLACKLIST_ALL, + /obj/item/clothing/head/helmet = TRADER_BLACKLIST_ALL, + /obj/item/clothing/head/lightrig = TRADER_BLACKLIST_ALL, + /obj/item/clothing/head/radiation = TRADER_BLACKLIST, + /obj/item/clothing/head/warden = TRADER_BLACKLIST, + /obj/item/clothing/head/welding = TRADER_BLACKLIST + ) @@ -182,43 +190,45 @@ Sells devices, odds and ends, and medical stuff name_language = TRADER_DEFAULT_NAME origin = "Drugstore" possible_origins = list("Buy 'n Save", "Drug Carnival", "C&B", "Fentles", "Dr. Goods", "Beevees", "McGillicuddy's") - possible_trading_items = list(/obj/item/flashlight = TRADER_ALL, - /obj/item/kit/paint = TRADER_SUBTYPES_ONLY, - /obj/item/aicard = TRADER_THIS_TYPE, - /obj/item/binoculars = TRADER_THIS_TYPE, - /obj/item/cable_painter = TRADER_THIS_TYPE, - /obj/item/flash = TRADER_THIS_TYPE, - /obj/item/paint_sprayer = TRADER_THIS_TYPE, - /obj/item/multitool = TRADER_THIS_TYPE, - /obj/item/lightreplacer = TRADER_THIS_TYPE, - /obj/item/megaphone = TRADER_THIS_TYPE, - /obj/item/paicard = TRADER_THIS_TYPE, - /obj/item/scanner/health = TRADER_THIS_TYPE, - /obj/item/scanner/breath = TRADER_THIS_TYPE, - /obj/item/scanner/gas = TRADER_ALL, - /obj/item/scanner/spectrometer = TRADER_ALL, - /obj/item/scanner/reagent = TRADER_ALL, - /obj/item/scanner/xenobio = TRADER_THIS_TYPE, - /obj/item/suit_cooling_unit = TRADER_THIS_TYPE, - /obj/item/t_scanner = TRADER_THIS_TYPE, - /obj/item/taperecorder = TRADER_THIS_TYPE, - /obj/item/batterer = TRADER_THIS_TYPE, - /obj/item/synthesized_instrument/violin = TRADER_THIS_TYPE, - /obj/item/hailer = TRADER_THIS_TYPE, - /obj/item/uv_light = TRADER_THIS_TYPE, - /obj/item/mmi = TRADER_ALL, - /obj/item/robotanalyzer = TRADER_THIS_TYPE, - /obj/item/chems/toner_cartridge = TRADER_THIS_TYPE, - /obj/item/camera_film = TRADER_THIS_TYPE, - /obj/item/camera = TRADER_THIS_TYPE, - /obj/item/destTagger = TRADER_THIS_TYPE, - /obj/item/gps = TRADER_THIS_TYPE, - /obj/item/measuring_tape = TRADER_THIS_TYPE, - /obj/item/ano_scanner = TRADER_THIS_TYPE, - /obj/item/core_sampler = TRADER_THIS_TYPE, - /obj/item/depth_scanner = TRADER_THIS_TYPE, - /obj/item/pinpointer/radio = TRADER_THIS_TYPE, - /obj/item/stack/medical/advanced = TRADER_BLACKLIST) + possible_trading_items = list( + /obj/item/flashlight = TRADER_ALL, + /obj/item/kit/paint = TRADER_SUBTYPES_ONLY, + /obj/item/aicard = TRADER_THIS_TYPE, + /obj/item/binoculars = TRADER_THIS_TYPE, + /obj/item/cable_painter = TRADER_THIS_TYPE, + /obj/item/flash = TRADER_THIS_TYPE, + /obj/item/paint_sprayer = TRADER_THIS_TYPE, + /obj/item/multitool = TRADER_THIS_TYPE, + /obj/item/lightreplacer = TRADER_THIS_TYPE, + /obj/item/megaphone = TRADER_THIS_TYPE, + /obj/item/paicard = TRADER_THIS_TYPE, + /obj/item/scanner/health = TRADER_THIS_TYPE, + /obj/item/scanner/breath = TRADER_THIS_TYPE, + /obj/item/scanner/gas = TRADER_ALL, + /obj/item/scanner/spectrometer = TRADER_ALL, + /obj/item/scanner/reagent = TRADER_ALL, + /obj/item/scanner/xenobio = TRADER_THIS_TYPE, + /obj/item/suit_cooling_unit = TRADER_THIS_TYPE, + /obj/item/t_scanner = TRADER_THIS_TYPE, + /obj/item/taperecorder = TRADER_THIS_TYPE, + /obj/item/batterer = TRADER_THIS_TYPE, + /obj/item/synthesized_instrument/violin = TRADER_THIS_TYPE, + /obj/item/hailer = TRADER_THIS_TYPE, + /obj/item/uv_light = TRADER_THIS_TYPE, + /obj/item/mmi = TRADER_ALL, + /obj/item/robotanalyzer = TRADER_THIS_TYPE, + /obj/item/chems/toner_cartridge = TRADER_THIS_TYPE, + /obj/item/camera_film = TRADER_THIS_TYPE, + /obj/item/camera = TRADER_THIS_TYPE, + /obj/item/destTagger = TRADER_THIS_TYPE, + /obj/item/gps = TRADER_THIS_TYPE, + /obj/item/measuring_tape = TRADER_THIS_TYPE, + /obj/item/ano_scanner = TRADER_THIS_TYPE, + /obj/item/core_sampler = TRADER_THIS_TYPE, + /obj/item/depth_scanner = TRADER_THIS_TYPE, + /obj/item/pinpointer/radio = TRADER_THIS_TYPE, + /obj/item/stack/medical/advanced = TRADER_BLACKLIST + ) speech = list("hail_generic" = "Hello, hello! Bits and bobs and everything in between, I hope you find what you're looking for!", "hail_silicon" = "Ah! Hello, robot. We only sell things that, ah.... people can hold in their hands, unfortunately. You are still allowed to buy, though!", "hail_deny" = "Oh no. I don't want to deal with YOU.", @@ -243,10 +253,11 @@ Sells devices, odds and ends, and medical stuff origin = "Robot Store" possible_origins = list("AI for the Straight Guy", "Mechanical Buddies", "Bot Chop Shop", "Omni Consumer Projects") possible_trading_items = list( - /obj/item/bot_kit = TRADER_THIS_TYPE, - /obj/item/paicard = TRADER_THIS_TYPE, - /obj/item/aicard = TRADER_THIS_TYPE, - /mob/living/bot = TRADER_SUBTYPES_ONLY) + /obj/item/bot_kit = TRADER_THIS_TYPE, + /obj/item/paicard = TRADER_THIS_TYPE, + /obj/item/aicard = TRADER_THIS_TYPE, + /mob/living/bot = TRADER_SUBTYPES_ONLY + ) speech = list("hail_generic" = "Welcome to ORIGIN! Let me walk you through our fine robotic selection!", "hail_silicon" = "Welcome to ORIGIN! Let- oh, you're a synth! Well, your money is good anyway. Welcome, welcome!", "hail_deny" = "ORIGIN no longer wants to speak to you.", @@ -287,18 +298,21 @@ Sells devices, odds and ends, and medical stuff "insult_bad" = "I have traded dogs with more bark than that.", ) - possible_wanted_items = list(/mob/living/simple_animal/tindalos = TRADER_THIS_TYPE, - /mob/living/simple_animal/tomato = TRADER_THIS_TYPE, - /mob/living/simple_animal/yithian = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/beast/diyaab = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/beast/shantak= TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/beast/samak= TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/carp = TRADER_THIS_TYPE) - - possible_trading_items = list(/mob/living/simple_animal/hostile/carp= TRADER_THIS_TYPE, - /obj/item/dociler = TRADER_THIS_TYPE, - /obj/item/beartrap = TRADER_THIS_TYPE, - /obj/item/scanner/xenobio = TRADER_THIS_TYPE) + possible_wanted_items = list( + /mob/living/simple_animal/tindalos = TRADER_THIS_TYPE, + /mob/living/simple_animal/tomato = TRADER_THIS_TYPE, + /mob/living/simple_animal/yithian = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/beast/diyaab = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/beast/shantak = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/beast/samak = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/carp = TRADER_THIS_TYPE + ) + possible_trading_items = list( + /mob/living/simple_animal/hostile/carp = TRADER_THIS_TYPE, + /obj/item/dociler = TRADER_THIS_TYPE, + /obj/item/beartrap = TRADER_THIS_TYPE, + /obj/item/scanner/xenobio = TRADER_THIS_TYPE + ) /datum/trader/medical name = "Medical Supplier" @@ -323,35 +337,37 @@ Sells devices, odds and ends, and medical stuff "insult_bad" = "*muffled laughter* Sorry, was that you trying to talk shit? Adorable.", ) - possible_wanted_items = list(/obj/item/chems/drinks/bottle = TRADER_THIS_TYPE, - /obj/item/organ/internal/liver = TRADER_THIS_TYPE, - /obj/item/organ/internal/kidneys = TRADER_THIS_TYPE, - /obj/item/organ/internal/lungs = TRADER_THIS_TYPE, - /obj/item/organ/internal/heart = TRADER_THIS_TYPE, - /obj/item/storage/fancy/cigarettes = TRADER_ALL - ) - - possible_trading_items = list(/obj/item/storage/pill_bottle = TRADER_SUBTYPES_ONLY, - /obj/item/storage/firstaid/fire = TRADER_THIS_TYPE, - /obj/item/storage/firstaid/toxin = TRADER_THIS_TYPE, - /obj/item/storage/firstaid/adv = TRADER_THIS_TYPE, - /obj/item/storage/box/bloodpacks = TRADER_THIS_TYPE, - /obj/item/chems/ivbag = TRADER_SUBTYPES_ONLY, - /obj/item/retractor = TRADER_THIS_TYPE, - /obj/item/hemostat = TRADER_THIS_TYPE, - /obj/item/cautery = TRADER_THIS_TYPE, - /obj/item/surgicaldrill = TRADER_THIS_TYPE, - /obj/item/scalpel = TRADER_THIS_TYPE, - /obj/item/incision_manager = TRADER_THIS_TYPE, - /obj/item/circular_saw = TRADER_THIS_TYPE, - /obj/item/bonegel = TRADER_THIS_TYPE, - /obj/item/bonesetter = TRADER_THIS_TYPE, - /obj/item/chems/glass/bottle/stabilizer = TRADER_THIS_TYPE, - /obj/item/chems/glass/bottle/sedatives = TRADER_THIS_TYPE, - /obj/item/chems/glass/bottle/antitoxin = TRADER_THIS_TYPE, - /obj/item/bodybag/cryobag = TRADER_THIS_TYPE, - /obj/item/sign/medipolma = TRADER_THIS_TYPE - ) + possible_wanted_items = list( + /obj/item/chems/drinks/bottle = TRADER_THIS_TYPE, + /obj/item/organ/internal/liver = TRADER_THIS_TYPE, + /obj/item/organ/internal/kidneys = TRADER_THIS_TYPE, + /obj/item/organ/internal/lungs = TRADER_THIS_TYPE, + /obj/item/organ/internal/heart = TRADER_THIS_TYPE, + /obj/item/storage/fancy/cigarettes = TRADER_ALL + ) + + possible_trading_items = list( + /obj/item/storage/pill_bottle = TRADER_SUBTYPES_ONLY, + /obj/item/storage/firstaid/fire = TRADER_THIS_TYPE, + /obj/item/storage/firstaid/toxin = TRADER_THIS_TYPE, + /obj/item/storage/firstaid/adv = TRADER_THIS_TYPE, + /obj/item/storage/box/bloodpacks = TRADER_THIS_TYPE, + /obj/item/chems/ivbag = TRADER_SUBTYPES_ONLY, + /obj/item/retractor = TRADER_THIS_TYPE, + /obj/item/hemostat = TRADER_THIS_TYPE, + /obj/item/cautery = TRADER_THIS_TYPE, + /obj/item/surgicaldrill = TRADER_THIS_TYPE, + /obj/item/scalpel = TRADER_THIS_TYPE, + /obj/item/incision_manager = TRADER_THIS_TYPE, + /obj/item/circular_saw = TRADER_THIS_TYPE, + /obj/item/bonegel = TRADER_THIS_TYPE, + /obj/item/bonesetter = TRADER_THIS_TYPE, + /obj/item/chems/glass/bottle/stabilizer = TRADER_THIS_TYPE, + /obj/item/chems/glass/bottle/sedatives = TRADER_THIS_TYPE, + /obj/item/chems/glass/bottle/antitoxin = TRADER_THIS_TYPE, + /obj/item/bodybag/cryobag = TRADER_THIS_TYPE, + /obj/item/sign/medipolma = TRADER_THIS_TYPE + ) /datum/trader/mining name = "Rock'n'Drill Mining Inc" @@ -377,19 +393,19 @@ Sells devices, odds and ends, and medical stuff ) possible_wanted_items = list( - /obj/item/stack/material/ore = TRADER_SUBTYPES_ONLY, - /obj/item/disk/survey = TRADER_THIS_TYPE, - /obj/item/stack/material/ore/slag = TRADER_BLACKLIST + /obj/item/stack/material/ore = TRADER_SUBTYPES_ONLY, + /obj/item/disk/survey = TRADER_THIS_TYPE, + /obj/item/stack/material/ore/slag = TRADER_BLACKLIST ) possible_trading_items = list( - /obj/machinery/mining/drill = TRADER_THIS_TYPE, - /obj/machinery/mining/brace = TRADER_THIS_TYPE, - /obj/machinery/floodlight = TRADER_THIS_TYPE, - /obj/item/storage/box/greenglowsticks = TRADER_THIS_TYPE, + /obj/machinery/mining/drill = TRADER_THIS_TYPE, + /obj/machinery/mining/brace = TRADER_THIS_TYPE, + /obj/machinery/floodlight = TRADER_THIS_TYPE, + /obj/item/storage/box/greenglowsticks = TRADER_THIS_TYPE, /obj/item/clothing/suit/space/void/engineering/salvage/prepared = TRADER_THIS_TYPE, - /obj/item/stack/material/puck/mapped/uranium/ten = TRADER_THIS_TYPE, - /obj/item/stack/material/reinforced/mapped/plasteel/fifty = TRADER_THIS_TYPE, - /obj/item/stack/material/sheet/mapped/steel/fifty = TRADER_THIS_TYPE, - /obj/item/stack/material/ingot/mapped/copper/fifty = TRADER_THIS_TYPE + /obj/item/stack/material/puck/mapped/uranium/ten = TRADER_THIS_TYPE, + /obj/item/stack/material/reinforced/mapped/plasteel/fifty = TRADER_THIS_TYPE, + /obj/item/stack/material/sheet/mapped/steel/fifty = TRADER_THIS_TYPE, + /obj/item/stack/material/ingot/mapped/copper/fifty = TRADER_THIS_TYPE ) diff --git a/code/datums/trading/traders/misc.dm b/code/datums/trading/traders/misc.dm index e53ed1417c8..80b69e2dbb5 100644 --- a/code/datums/trading/traders/misc.dm +++ b/code/datums/trading/traders/misc.dm @@ -23,47 +23,51 @@ "bribe_accept" = "Hm. It'll be good for the animals, so sure.", ) - possible_wanted_items = list(/mob/living/simple_animal/corgi = TRADER_THIS_TYPE, - /mob/living/simple_animal/cat = TRADER_THIS_TYPE, - /mob/living/simple_animal/crab = TRADER_THIS_TYPE, - /mob/living/simple_animal/lizard = TRADER_THIS_TYPE, - /mob/living/simple_animal/mouse = TRADER_THIS_TYPE, - /mob/living/simple_animal/mushroom = TRADER_THIS_TYPE, - /mob/living/simple_animal/tindalos = TRADER_THIS_TYPE, - /mob/living/simple_animal/tomato = TRADER_THIS_TYPE, - /mob/living/simple_animal/cow = TRADER_THIS_TYPE, - /mob/living/simple_animal/chick = TRADER_THIS_TYPE, - /mob/living/simple_animal/chicken = TRADER_THIS_TYPE, - /mob/living/simple_animal/yithian = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/beast/diyaab = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/bear= TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/beast/shantak= TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/parrot = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/beast/samak= TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/goat = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/carp = TRADER_THIS_TYPE) + possible_wanted_items = list( + /mob/living/simple_animal/corgi = TRADER_THIS_TYPE, + /mob/living/simple_animal/cat = TRADER_THIS_TYPE, + /mob/living/simple_animal/crab = TRADER_THIS_TYPE, + /mob/living/simple_animal/lizard = TRADER_THIS_TYPE, + /mob/living/simple_animal/mouse = TRADER_THIS_TYPE, + /mob/living/simple_animal/mushroom = TRADER_THIS_TYPE, + /mob/living/simple_animal/tindalos = TRADER_THIS_TYPE, + /mob/living/simple_animal/tomato = TRADER_THIS_TYPE, + /mob/living/simple_animal/cow = TRADER_THIS_TYPE, + /mob/living/simple_animal/chick = TRADER_THIS_TYPE, + /mob/living/simple_animal/chicken = TRADER_THIS_TYPE, + /mob/living/simple_animal/yithian = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/beast/diyaab = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/bear = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/beast/shantak = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/parrot = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/beast/samak = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/goat = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/carp = TRADER_THIS_TYPE + ) - possible_trading_items = list(/mob/living/simple_animal/corgi = TRADER_THIS_TYPE, - /mob/living/simple_animal/cat = TRADER_THIS_TYPE, - /mob/living/simple_animal/crab = TRADER_THIS_TYPE, - /mob/living/simple_animal/lizard = TRADER_THIS_TYPE, - /mob/living/simple_animal/mouse = TRADER_THIS_TYPE, - /mob/living/simple_animal/mushroom = TRADER_THIS_TYPE, - /mob/living/simple_animal/tindalos = TRADER_THIS_TYPE, - /mob/living/simple_animal/tomato = TRADER_THIS_TYPE, - /mob/living/simple_animal/cow = TRADER_THIS_TYPE, - /mob/living/simple_animal/chick = TRADER_THIS_TYPE, - /mob/living/simple_animal/chicken = TRADER_THIS_TYPE, - /mob/living/simple_animal/yithian = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/beast/diyaab = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/bear= TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/beast/shantak= TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/parrot = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/beast/samak= TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/retaliate/goat = TRADER_THIS_TYPE, - /mob/living/simple_animal/hostile/carp= TRADER_THIS_TYPE, - /obj/item/dociler = TRADER_THIS_TYPE, - /obj/structure/dogbed = TRADER_THIS_TYPE) + possible_trading_items = list( + /mob/living/simple_animal/corgi = TRADER_THIS_TYPE, + /mob/living/simple_animal/cat = TRADER_THIS_TYPE, + /mob/living/simple_animal/crab = TRADER_THIS_TYPE, + /mob/living/simple_animal/lizard = TRADER_THIS_TYPE, + /mob/living/simple_animal/mouse = TRADER_THIS_TYPE, + /mob/living/simple_animal/mushroom = TRADER_THIS_TYPE, + /mob/living/simple_animal/tindalos = TRADER_THIS_TYPE, + /mob/living/simple_animal/tomato = TRADER_THIS_TYPE, + /mob/living/simple_animal/cow = TRADER_THIS_TYPE, + /mob/living/simple_animal/chick = TRADER_THIS_TYPE, + /mob/living/simple_animal/chicken = TRADER_THIS_TYPE, + /mob/living/simple_animal/yithian = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/beast/diyaab = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/bear = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/beast/shantak = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/parrot = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/beast/samak = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/retaliate/goat = TRADER_THIS_TYPE, + /mob/living/simple_animal/hostile/carp = TRADER_THIS_TYPE, + /obj/item/dociler = TRADER_THIS_TYPE, + /obj/structure/dogbed = TRADER_THIS_TYPE + ) /datum/trader/ship/prank_shop name = "Prank Shop Owner" @@ -89,21 +93,23 @@ "bribe_refusal" = "We are sorry, but we cannot accept.", "bribe_accept" = "We are happy to say that we accept this bribe.", ) - possible_trading_items = list(/obj/item/clothing/mask/gas/clown_hat = TRADER_THIS_TYPE, - /obj/item/clothing/mask/gas/mime = TRADER_THIS_TYPE, - /obj/item/clothing/shoes/clown_shoes = TRADER_THIS_TYPE, - /obj/item/clothing/under/clown = TRADER_THIS_TYPE, - /obj/item/stamp/clown = TRADER_THIS_TYPE, - /obj/item/storage/backpack/clown = TRADER_THIS_TYPE, - /obj/item/bananapeel = TRADER_THIS_TYPE, - /obj/item/gun/launcher/money = TRADER_THIS_TYPE, - /obj/item/chems/food/pie = TRADER_THIS_TYPE, - /obj/item/bikehorn = TRADER_THIS_TYPE, - /obj/item/chems/spray/waterflower = TRADER_THIS_TYPE, - /obj/item/gun/launcher/pneumatic/small = TRADER_THIS_TYPE, - /obj/item/gun/projectile/revolver/capgun = TRADER_THIS_TYPE, - /obj/item/clothing/mask/fakemoustache = TRADER_THIS_TYPE, - /obj/item/grenade/spawnergrenade/fake_carp = TRADER_THIS_TYPE) + possible_trading_items = list( + /obj/item/clothing/mask/gas/clown_hat = TRADER_THIS_TYPE, + /obj/item/clothing/mask/gas/mime = TRADER_THIS_TYPE, + /obj/item/clothing/shoes/clown_shoes = TRADER_THIS_TYPE, + /obj/item/clothing/under/clown = TRADER_THIS_TYPE, + /obj/item/stamp/clown = TRADER_THIS_TYPE, + /obj/item/storage/backpack/clown = TRADER_THIS_TYPE, + /obj/item/bananapeel = TRADER_THIS_TYPE, + /obj/item/gun/launcher/money = TRADER_THIS_TYPE, + /obj/item/chems/food/pie = TRADER_THIS_TYPE, + /obj/item/bikehorn = TRADER_THIS_TYPE, + /obj/item/chems/spray/waterflower = TRADER_THIS_TYPE, + /obj/item/gun/launcher/pneumatic/small = TRADER_THIS_TYPE, + /obj/item/gun/projectile/revolver/capgun = TRADER_THIS_TYPE, + /obj/item/clothing/mask/fakemoustache = TRADER_THIS_TYPE, + /obj/item/grenade/spawnergrenade/fake_carp = TRADER_THIS_TYPE + ) /datum/trader/ship/replica_shop name = "Replica Store Owner" @@ -127,27 +133,29 @@ "bribe_refusal" = "Alas, traveler - I could stay all eve, but I've an client in waiting, and they are not known for patience.", "bribe_accept" = "Mayhaps I could set a spell longer, and rest my weary feet.", ) - possible_trading_items = list(/obj/item/clothing/head/wizard/magus = TRADER_THIS_TYPE, - /obj/item/shield/buckler = TRADER_THIS_TYPE, - /obj/item/clothing/head/redcoat = TRADER_THIS_TYPE, - /obj/item/clothing/head/powdered_wig = TRADER_THIS_TYPE, - /obj/item/clothing/head/hasturhood = TRADER_THIS_TYPE, - /obj/item/clothing/head/helmet/gladiator=TRADER_THIS_TYPE, - /obj/item/clothing/head/plaguedoctorhat= TRADER_THIS_TYPE, - /obj/item/clothing/glasses/eyepatch/monocle = TRADER_THIS_TYPE, - /obj/item/clothing/mask/smokable/pipe = TRADER_THIS_TYPE, - /obj/item/clothing/mask/gas/plaguedoctor=TRADER_THIS_TYPE, - /obj/item/clothing/suit/hastur = TRADER_THIS_TYPE, - /obj/item/clothing/suit/imperium_monk = TRADER_THIS_TYPE, - /obj/item/clothing/suit/judgerobe = TRADER_THIS_TYPE, - /obj/item/clothing/suit/wizrobe/magusred=TRADER_THIS_TYPE, - /obj/item/clothing/suit/wizrobe/magusblue=TRADER_THIS_TYPE, - /obj/item/clothing/under/gladiator = TRADER_THIS_TYPE, - /obj/item/clothing/under/kilt = TRADER_THIS_TYPE, - /obj/item/clothing/under/redcoat = TRADER_THIS_TYPE, - /obj/item/clothing/under/soviet = TRADER_THIS_TYPE, - /obj/item/harpoon = TRADER_THIS_TYPE, - /obj/item/sword = TRADER_ALL, - /obj/item/scythe = TRADER_THIS_TYPE, - /obj/item/star = TRADER_THIS_TYPE, - /obj/item/twohanded/baseballbat = TRADER_THIS_TYPE) \ No newline at end of file + possible_trading_items = list( + /obj/item/clothing/head/wizard/magus = TRADER_THIS_TYPE, + /obj/item/shield/buckler = TRADER_THIS_TYPE, + /obj/item/clothing/head/redcoat = TRADER_THIS_TYPE, + /obj/item/clothing/head/powdered_wig = TRADER_THIS_TYPE, + /obj/item/clothing/head/hasturhood = TRADER_THIS_TYPE, + /obj/item/clothing/head/helmet/gladiator = TRADER_THIS_TYPE, + /obj/item/clothing/head/plaguedoctorhat = TRADER_THIS_TYPE, + /obj/item/clothing/glasses/eyepatch/monocle = TRADER_THIS_TYPE, + /obj/item/clothing/mask/smokable/pipe = TRADER_THIS_TYPE, + /obj/item/clothing/mask/gas/plaguedoctor = TRADER_THIS_TYPE, + /obj/item/clothing/suit/hastur = TRADER_THIS_TYPE, + /obj/item/clothing/suit/imperium_monk = TRADER_THIS_TYPE, + /obj/item/clothing/suit/judgerobe = TRADER_THIS_TYPE, + /obj/item/clothing/suit/wizrobe/magusred = TRADER_THIS_TYPE, + /obj/item/clothing/suit/wizrobe/magusblue = TRADER_THIS_TYPE, + /obj/item/clothing/under/gladiator = TRADER_THIS_TYPE, + /obj/item/clothing/under/kilt = TRADER_THIS_TYPE, + /obj/item/clothing/under/redcoat = TRADER_THIS_TYPE, + /obj/item/clothing/under/soviet = TRADER_THIS_TYPE, + /obj/item/harpoon = TRADER_THIS_TYPE, + /obj/item/sword = TRADER_ALL, + /obj/item/scythe = TRADER_THIS_TYPE, + /obj/item/star = TRADER_THIS_TYPE, + /obj/item/twohanded/baseballbat = TRADER_THIS_TYPE + ) \ No newline at end of file diff --git a/code/datums/trading/traders/unique.dm b/code/datums/trading/traders/unique.dm index 66b3d8b6732..b4a4cc110c8 100644 --- a/code/datums/trading/traders/unique.dm +++ b/code/datums/trading/traders/unique.dm @@ -30,13 +30,14 @@ origin = "SGS Severance" possible_wanted_items = list( - /obj/item/chems/food/human = TRADER_SUBTYPES_ONLY, - /obj/item/chems/food/meat/human = TRADER_THIS_TYPE, - /mob/living/carbon/human = TRADER_ALL - ) + /obj/item/chems/food/human = TRADER_SUBTYPES_ONLY, + /obj/item/chems/food/meat/human = TRADER_THIS_TYPE, + /mob/living/carbon/human = TRADER_ALL + ) - possible_trading_items = list(/obj/item/gun/projectile/automatic = TRADER_SUBTYPES_ONLY - ) + possible_trading_items = list( + /obj/item/gun/projectile/automatic = TRADER_SUBTYPES_ONLY + ) blacklisted_trade_items = null @@ -62,9 +63,13 @@ name = "Bobo" origin = "Floating rock" - possible_wanted_items = list(/obj/item/stack/material/ore = TRADER_ALL) - possible_trading_items = list(/obj/machinery/power/supermatter = TRADER_ALL, - /obj/item/aiModule = TRADER_SUBTYPES_ONLY) + possible_wanted_items = list( + /obj/item/stack/material/ore = TRADER_ALL + ) + possible_trading_items = list( + /obj/machinery/power/supermatter = TRADER_ALL, + /obj/item/aiModule = TRADER_SUBTYPES_ONLY + ) want_multiplier = 5000 speech = list("hail_generic" = "Blub am MERCHANT. Blub hunger for things. Boo bring them to blub, yes?", @@ -91,25 +96,27 @@ possible_origins = list("An indistinct location", "Unknown location", "The Diamond Sphere", "Beyond the Veil", "Deadverse") name_language = TRADER_DEFAULT_NAME - possible_wanted_items = list(/mob/living/simple_animal/construct = TRADER_SUBTYPES_ONLY, - /obj/item/sword/cultblade = TRADER_THIS_TYPE, - /obj/item/clothing/head/culthood = TRADER_ALL, - /obj/item/clothing/suit/space/cult = TRADER_ALL, - /obj/item/clothing/suit/cultrobes = TRADER_ALL, - /obj/item/clothing/head/helmet/space/cult = TRADER_ALL, - /obj/structure/cult = TRADER_SUBTYPES_ONLY, - /obj/structure/constructshell = TRADER_ALL, - /mob/living/simple_animal/familiar = TRADER_SUBTYPES_ONLY, - /mob/living/simple_animal/familiar/pet = TRADER_BLACKLIST, - /mob/living/simple_animal/hostile/mimic = TRADER_ALL) - - possible_trading_items = list(/obj/item/clothing/gloves/wizard = TRADER_THIS_TYPE, - /obj/item/clothing/head/helmet/space/void/wizard = TRADER_THIS_TYPE, - /obj/item/clothing/head/wizard = TRADER_ALL, - /obj/item/clothing/suit/space/void/wizard = TRADER_THIS_TYPE, - /obj/item/toy/figure/wizard = TRADER_THIS_TYPE, - /obj/item/staff = TRADER_ALL, - ) //Probably see about getting some more wizard based shit + possible_wanted_items = list( + /mob/living/simple_animal/construct = TRADER_SUBTYPES_ONLY, + /obj/item/sword/cultblade = TRADER_THIS_TYPE, + /obj/item/clothing/head/culthood = TRADER_ALL, + /obj/item/clothing/suit/space/cult = TRADER_ALL, + /obj/item/clothing/suit/cultrobes = TRADER_ALL, + /obj/item/clothing/head/helmet/space/cult = TRADER_ALL, + /obj/structure/cult = TRADER_SUBTYPES_ONLY, + /obj/structure/constructshell = TRADER_ALL, + /mob/living/simple_animal/familiar = TRADER_SUBTYPES_ONLY, + /mob/living/simple_animal/familiar/pet = TRADER_BLACKLIST, + /mob/living/simple_animal/hostile/mimic = TRADER_ALL + ) + possible_trading_items = list( + /obj/item/clothing/gloves/wizard = TRADER_THIS_TYPE, + /obj/item/clothing/head/helmet/space/void/wizard = TRADER_THIS_TYPE, + /obj/item/clothing/head/wizard = TRADER_ALL, + /obj/item/clothing/suit/space/void/wizard = TRADER_THIS_TYPE, + /obj/item/toy/figure/wizard = TRADER_THIS_TYPE, + /obj/item/staff = TRADER_ALL, + ) //Probably see about getting some more wizard based shit speech = list("hail_generic" = "Hello! Are you here on pleasure or business?", "hail_Golem" = "Interesting... how incredibly interesting... come! Let us do business!", diff --git a/code/datums/trading/traders/weaponry.dm b/code/datums/trading/traders/weaponry.dm index 1d2872f219a..2f9d25d5c04 100644 --- a/code/datums/trading/traders/weaponry.dm +++ b/code/datums/trading/traders/weaponry.dm @@ -18,15 +18,17 @@ "insult_bad" = "If I had my gun I'd shoot you!" ) - possible_trading_items = list(/obj/item/gun/projectile/pistol/holdout = TRADER_ALL, - /obj/item/gun/projectile/shotgun/pump= TRADER_SUBTYPES_ONLY, - /obj/item/ammo_magazine = TRADER_SUBTYPES_ONLY, - /obj/item/ammo_magazine/rifle/empty = TRADER_BLACKLIST, - /obj/item/ammo_magazine/pistol/small/empty = TRADER_BLACKLIST, - /obj/item/ammo_magazine/pistol/empty = TRADER_BLACKLIST, - /obj/item/ammo_magazine/box/pistol/empty = TRADER_BLACKLIST, - /obj/item/ammo_magazine/smg/empty = TRADER_BLACKLIST, - /obj/item/clothing/accessory/storage/holster = TRADER_ALL) + possible_trading_items = list( + /obj/item/gun/projectile/pistol/holdout = TRADER_ALL, + /obj/item/gun/projectile/shotgun/pump = TRADER_SUBTYPES_ONLY, + /obj/item/ammo_magazine = TRADER_SUBTYPES_ONLY, + /obj/item/ammo_magazine/rifle/empty = TRADER_BLACKLIST, + /obj/item/ammo_magazine/pistol/small/empty = TRADER_BLACKLIST, + /obj/item/ammo_magazine/pistol/empty = TRADER_BLACKLIST, + /obj/item/ammo_magazine/box/pistol/empty = TRADER_BLACKLIST, + /obj/item/ammo_magazine/smg/empty = TRADER_BLACKLIST, + /obj/item/clothing/accessory/storage/holster = TRADER_ALL + ) /datum/trader/ship/egunshop name = "Energy Gun Shop Employee" @@ -48,16 +50,18 @@ "insult_bad" = "That's... very mean. I won't think twice about blacklisting your channel, so stop." ) - possible_trading_items = list(/obj/item/gun/energy/taser = TRADER_THIS_TYPE, - /obj/item/gun/energy/xray = TRADER_THIS_TYPE, - /obj/item/gun/energy/laser = TRADER_THIS_TYPE, - /obj/item/gun/energy/gun = TRADER_THIS_TYPE, - /obj/item/cell = TRADER_THIS_TYPE, - /obj/item/cell/crap = TRADER_THIS_TYPE, - /obj/item/cell/high = TRADER_THIS_TYPE, - /obj/item/cell/super = TRADER_THIS_TYPE, - /obj/item/cell/hyper = TRADER_THIS_TYPE, - /obj/item/clothing/accessory/storage/holster = TRADER_ALL) + possible_trading_items = list( + /obj/item/gun/energy/taser = TRADER_THIS_TYPE, + /obj/item/gun/energy/xray = TRADER_THIS_TYPE, + /obj/item/gun/energy/laser = TRADER_THIS_TYPE, + /obj/item/gun/energy/gun = TRADER_THIS_TYPE, + /obj/item/cell = TRADER_THIS_TYPE, + /obj/item/cell/crap = TRADER_THIS_TYPE, + /obj/item/cell/high = TRADER_THIS_TYPE, + /obj/item/cell/super = TRADER_THIS_TYPE, + /obj/item/cell/hyper = TRADER_THIS_TYPE, + /obj/item/clothing/accessory/storage/holster = TRADER_ALL + ) /datum/trader/dogan name = "Dogan" @@ -79,8 +83,10 @@ compliment_increase = 0 insult_drop = 0 - possible_trading_items = list(/obj/item/gun/projectile/zipgun = TRADER_THIS_TYPE, - /obj/item/gun/projectile/bolt_action/sniper/ant = TRADER_THIS_TYPE, - /obj/item/gun/energy/laser/dogan = TRADER_THIS_TYPE, - /obj/item/gun/projectile/automatic/smg/usi = TRADER_THIS_TYPE, - /obj/item/clothing/accessory/storage/holster = TRADER_ALL) \ No newline at end of file + possible_trading_items = list( + /obj/item/gun/projectile/zipgun = TRADER_THIS_TYPE, + /obj/item/gun/projectile/bolt_action/sniper/ant = TRADER_THIS_TYPE, + /obj/item/gun/energy/laser/dogan = TRADER_THIS_TYPE, + /obj/item/gun/projectile/automatic/smg/usi = TRADER_THIS_TYPE, + /obj/item/clothing/accessory/storage/holster = TRADER_ALL + ) diff --git a/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm b/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm index fae76f7aadc..ebb26b19070 100644 --- a/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm +++ b/code/game/gamemodes/endgame/ftl_jump/ftl_jump.dm @@ -9,12 +9,12 @@ affected_levels = zlevels /datum/universal_state/jump/OnEnter() - var/obj/abstract/level_data/space_zlevel = SSmapping.increment_world_z_size(/obj/abstract/level_data/space) //get a place for stragglers + var/datum/level_data/space_zlevel = SSmapping.increment_world_z_size(/datum/level_data/space) //get a place for stragglers for(var/mob/living/M in SSmobs.mob_list) if(M.z in affected_levels) var/area/A = get_area(M) if(istype(A,/area/space)) //straggler - var/turf/T = locate(M.x, M.y, space_zlevel.my_z) + var/turf/T = locate(M.x, M.y, space_zlevel.level_z) if(T) M.forceMove(T) else diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm index 912119325ee..2b6ca88221d 100644 --- a/code/game/machinery/cryopod.dm +++ b/code/game/machinery/cryopod.dm @@ -222,8 +222,8 @@ if(length(possible_locations)) newz = pick(possible_locations) if(!newz) - var/obj/abstract/level_data/level = SSmapping.increment_world_z_size(/obj/abstract/level_data/space) - newz = level?.my_z + var/datum/level_data/level = SSmapping.increment_world_z_size(/datum/level_data/space) + newz = level.level_z if(newz) var/turf/nloc = locate(rand(TRANSITIONEDGE, world.maxx-TRANSITIONEDGE), rand(TRANSITIONEDGE, world.maxy-TRANSITIONEDGE), newz) diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index 96d124af584..218e980f804 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -186,6 +186,9 @@ /obj/item/storage/box/ammo/shotgunammo/WillContain() return list(/obj/item/ammo_magazine/shotholder = 2) +/obj/item/storage/box/ammo/shotgunammo/large/WillContain() + return list(/obj/item/ammo_magazine/shotholder = 4) + /obj/item/storage/box/ammo/shotgunshells name = "box of shotgun shells" /obj/item/storage/box/ammo/shotgunshells/WillContain() @@ -201,6 +204,9 @@ /obj/item/storage/box/ammo/stunshells/WillContain() return list(/obj/item/ammo_magazine/shotholder/stun = 2) +/obj/item/storage/box/ammo/stunshells/large/WillContain() + return list(/obj/item/ammo_magazine/shotholder/stun = 4) + /obj/item/storage/box/ammo/sniperammo name = "box of sniper shells" /obj/item/storage/box/ammo/sniperammo/WillContain() diff --git a/code/game/turfs/exterior/_exterior.dm b/code/game/turfs/exterior/_exterior.dm index 57812497ba0..d61c708ab9e 100644 --- a/code/game/turfs/exterior/_exterior.dm +++ b/code/game/turfs/exterior/_exterior.dm @@ -18,8 +18,9 @@ // Bit faster than return_air() for exoplanet exterior turfs /turf/exterior/get_air_graphic() - var/obj/abstract/level_data/level = SSmapping.levels_by_z[z] - return level?.exterior_atmosphere?.graphic + var/datum/level_data/level = SSmapping.levels_by_z[z] + var/datum/gas_mixture/atmos = level?.get_exterior_atmosphere() + return atmos?.graphic /turf/exterior/Initialize(mapload, no_update_icon = FALSE) @@ -82,7 +83,7 @@ . = ..() /turf/exterior/return_air() - var/obj/abstract/level_data/level = SSmapping.levels_by_z[z] + var/datum/level_data/level = SSmapping.levels_by_z[z] var/datum/gas_mixture/gas = level?.get_exterior_atmosphere() if(!gas) return diff --git a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm index eb02821ccad..6cb202ff7f3 100644 --- a/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm +++ b/code/modules/fabrication/designs/imprinter/designs_misc_circuits.dm @@ -505,3 +505,6 @@ /datum/fabricator_recipe/imprinter/circuit/holomap path = /obj/item/stock_parts/circuitboard/holomap + +/datum/fabricator_recipe/imprinter/circuit/geothermal_generator + path = /obj/item/stock_parts/circuitboard/geothermal \ No newline at end of file diff --git a/code/modules/maps/_map_template.dm b/code/modules/maps/_map_template.dm index cb5ffa982f1..8acc9e73fb1 100644 --- a/code/modules/maps/_map_template.dm +++ b/code/modules/maps/_map_template.dm @@ -114,7 +114,6 @@ var/list/bounds = list(1.#INF, 1.#INF, 1.#INF, -1.#INF, -1.#INF, -1.#INF) var/list/atoms_to_initialise = list() var/shuttle_state = pre_init_shuttles() - var/map_hash = modify_tag_vars && "[sequential_id("map_id")]" ASSERT(isnull(global._preloader.current_map_hash)) // Recursive maploading is possible, but not from this block: recursive loads should be triggered in Initialize, from init_atoms below. global._preloader.current_map_hash = map_hash @@ -135,7 +134,7 @@ init_shuttles(shuttle_state, map_hash, initialized_areas_by_type) after_load() for(var/z_index = bounds[MAP_MINZ] to bounds[MAP_MAXZ]) - var/obj/abstract/level_data/level = SSmapping.levels_by_z[z_index] + var/datum/level_data/level = SSmapping.levels_by_z[z_index] level.post_template_load(src) if(SSlighting.initialized) SSlighting.InitializeZlev(z_index) diff --git a/code/modules/maps/reader.dm b/code/modules/maps/reader.dm index 66640af2f4c..f25242d5c23 100644 --- a/code/modules/maps/reader.dm +++ b/code/modules/maps/reader.dm @@ -57,7 +57,7 @@ var/global/dmm_suite/preloader/_preloader = new #endif Master.StopLoadingMap() -/dmm_suite/proc/load_map_impl(dmm_file, x_offset, y_offset, z_offset, cropMap, measureOnly, no_changeturf, clear_contents, x_lower = -INFINITY, x_upper = INFINITY, y_lower = -INFINITY, y_upper = INFINITY, initialized_areas_by_type, level_data_type = /obj/abstract/level_data/space) +/dmm_suite/proc/load_map_impl(dmm_file, x_offset, y_offset, z_offset, cropMap, measureOnly, no_changeturf, clear_contents, x_lower = -INFINITY, x_upper = INFINITY, y_lower = -INFINITY, y_upper = INFINITY, initialized_areas_by_type, level_data_type = /datum/level_data/space) var/tfile = dmm_file//the map file we're creating if(isfile(tfile)) tfile = safe_file2text(tfile, FALSE) diff --git a/code/modules/materials/geology/_strata.dm b/code/modules/materials/geology/_strata.dm index 80c930392e4..c72506db47f 100644 --- a/code/modules/materials/geology/_strata.dm +++ b/code/modules/materials/geology/_strata.dm @@ -7,8 +7,9 @@ var/maximum_temperature = INFINITY /decl/strata/proc/is_valid_exoplanet_strata(var/obj/effect/overmap/visitable/sector/exoplanet/planet) - var/obj/abstract/level_data/level_data = planet?.zlevels[1] - var/check_temp = level_data?.exterior_atmosphere?.temperature || 0 + var/datum/level_data/level_data = planet? SSmapping.levels_by_z[planet.map_z[1]] : null + var/datum/gas_mixture/atmos = level_data?.get_exterior_atmosphere() + var/check_temp = atmos?.temperature || 0 . = check_temp <= maximum_temperature /decl/strata/Initialize() diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm index 6f5f80de575..8c828148b34 100644 --- a/code/modules/mining/mine_turfs.dm +++ b/code/modules/mining/mine_turfs.dm @@ -31,12 +31,12 @@ if(prob(20)) overlay_detail = "asteroid[rand(0,9)]" . = ..() - var/obj/abstract/level_data/mining_level/level = SSmapping.levels_by_z[z] + var/datum/level_data/mining_level/level = SSmapping.levels_by_z[z] if(istype(level)) LAZYADD(level.mining_turfs, src) /turf/simulated/floor/asteroid/Destroy() - var/obj/abstract/level_data/mining_level/level = SSmapping.levels_by_z[z] + var/datum/level_data/mining_level/level = SSmapping.levels_by_z[z] if(istype(level)) LAZYREMOVE(level.mining_turfs, src) return ..() diff --git a/code/modules/multiz/level_data.dm b/code/modules/multiz/level_data.dm index fc85ce6c010..d0294cab20c 100644 --- a/code/modules/multiz/level_data.dm +++ b/code/modules/multiz/level_data.dm @@ -1,132 +1,237 @@ -/obj/abstract/level_data - /// Name displayed on GPS when this sector is shown. - var/gps_name - /// z-level associated with this datum - var/my_z - /// A unique identifier for the level, used for SSmapping looup +/// Returns all the turfs within a zlevel's transition edge, on a given direction. +/// If include corners is true, the corners of the map will be included. +/proc/get_transition_edge_turfs(var/z, var/dir_edge, var/include_corners = FALSE) + var/datum/level_data/LD = SSmapping.levels_by_z[z] + + //minimum and maximum corners making up the box, between which the transition edge is + var/min_x = 1 //X of lower left corner of the edge + var/min_y = 1 //Y of lower left corner of the edge + var/max_x = 1 //X of upper right corner of the edge + var/max_y = 1 //Y of upper right corner of the edge + + //Pos before or after the transition edge on either ends of each axis of the level. (Including corners or not) + var/x_bef_transit = include_corners? (LD.level_inner_min_x - TRANSITIONEDGE) : (LD.level_inner_min_x) + var/x_aft_transit = include_corners? (LD.level_inner_max_x + TRANSITIONEDGE) : (LD.level_inner_max_x) + var/y_bef_transit = include_corners? (LD.level_inner_min_y - TRANSITIONEDGE) : (LD.level_inner_min_y) + var/y_aft_transit = include_corners? (LD.level_inner_max_y + TRANSITIONEDGE) : (LD.level_inner_max_y) + + switch(dir_edge) + if(NORTH) + min_x = x_bef_transit + min_y = LD.level_inner_max_y + 1 //Add one so we're outside the inner area (inner min/max are inclusive) + max_x = x_aft_transit + max_y = LD.level_inner_max_y + TRANSITIONEDGE //End of the transition edge on that axis + if(SOUTH) + min_x = x_bef_transit + min_y = LD.level_inner_min_y - TRANSITIONEDGE + max_x = x_aft_transit + max_y = LD.level_inner_min_y - 1 + if(EAST) + min_x = LD.level_inner_max_x + 1 + min_y = y_bef_transit + max_x = LD.level_inner_max_x + TRANSITIONEDGE + max_y = y_aft_transit + if(WEST) + min_x = LD.level_inner_min_x - TRANSITIONEDGE + min_y = y_bef_transit + max_x = LD.level_inner_min_x - 1 + max_y = y_aft_transit + + return block( + locate(min_x, min_y, LD.level_z), + locate(max_x, max_y, LD.level_z) + ) + +///Returns all the turfs from all 4 corners of the transition border of a level. +/proc/get_transition_edge_corner_turfs(var/z) + var/datum/level_data/LD = SSmapping.levels_by_z[z] + //South-West + . = block( + locate(LD.level_inner_min_x - TRANSITIONEDGE, LD.level_inner_min_y - TRANSITIONEDGE, LD.level_z), + locate(LD.level_inner_min_x - 1, LD.level_inner_min_y - 1, LD.level_z)) + //South-East + . |= block( + locate(LD.level_inner_max_x + 1, LD.level_inner_min_y - TRANSITIONEDGE, LD.level_z), + locate(LD.level_inner_max_x + TRANSITIONEDGE, LD.level_inner_min_y - 1, LD.level_z)) + //North-West + . |= block( + locate(LD.level_inner_min_x - TRANSITIONEDGE, LD.level_inner_max_y + 1, LD.level_z), + locate(LD.level_inner_min_x - 1, LD.level_inner_max_y + TRANSITIONEDGE, LD.level_z)) + //North-East + . |= block( + locate(LD.level_inner_max_x + 1, LD.level_inner_max_y + 1, LD.level_z), + locate(LD.level_inner_max_x + TRANSITIONEDGE, LD.level_inner_max_y + TRANSITIONEDGE, LD.level_z)) + +///Keeps details on how to generate, maintain and access a zlevel. +/datum/level_data + ///Name displayed to the player to refer to this level in user interfaces and etc. If null, one will be generated. + var/name + + /// The z-level that was assigned to this level_data + var/level_z + /// A unique string identifier for this particular z-level. Used to fetch a level without knowing its z-level. var/level_id - /// The base turf of the level (space, rock, etc) - var/base_turf - /// A list of ids that this level connects to horizontally. - var/list/connects_to /// Various flags indicating what this level functions as. - var/level_flags - /// Temperature of standard exterior atmosphere. - var/exterior_atmos_temp = T20C - /// Gaxmix datum returned to exterior return_air. Set to assoc list of material to moles to initialize the gas datum. - var/datum/gas_mixture/exterior_atmosphere - /// Default turf for this level on creation (if created via z-level incrementing) - var/created_base_turf_type = /turf/space - /// Default area for this level on creation (as above) - var/created_base_area_type = /area/space - /// Set to false to leave dark - var/take_starlight_ambience = TRUE - /// This default makes turfs not generate light. Adjust to have exterior areas be lit. + var/level_flags = 0 + /// The desired width of the level, including the TRANSITIONEDGE. + ///If world.maxx is bigger, the exceeding area will be filled with turfs of "border_filler" type if defined, or base_turf otherwise. + var/level_max_width + /// The desired height of the level, including the TRANSITIONEDGE. + ///If world.maxy is bigger, the exceeding area will be filled with turfs of "border_filler" type if defined, or base_turf otherwise. + var/level_max_height + + /// Filled by map gen on init. Indicates where the accessible level area starts past the transition edge. + var/level_inner_min_x + /// Filled by map gen on init. Indicates where the accessible level area starts past the transition edge. + var/level_inner_min_y + /// Filled by map gen on init. Indicates where the accessible level area starts past the transition edge. + var/level_inner_max_x + /// Filled by map gen on init. Indicates where the accessible level area starts past the transition edge. + var/level_inner_max_y + + /// Filled by map gen on init. Indicates the width of the accessible area within the transition edges. + var/level_inner_width + /// Filled by map gen on init.Indicates the height of the accessible area within the transition edges. + var/level_inner_height + + // *** Lighting *** + /// Set to false to override with our own. + var/use_global_exterior_ambience = TRUE + /// Ambient lighting light intensity turfs on this level should have. Value from 0 to 1. var/ambient_light_level = 0 - /// Colour of ambient light. + /// Colour of ambient light for turfs on this level. var/ambient_light_color = COLOR_WHITE -INITIALIZE_IMMEDIATE(/obj/abstract/level_data) -/obj/abstract/level_data/Initialize(var/ml, var/defer_level_setup = FALSE) - . = ..() + // *** Level Gen *** + ///The default base turf type for the whole level. It will be the base turf type for the z level, unless loaded by map. + /// filler_turf overrides what turfs the level will be created with. + var/base_turf = /turf/space + /// When the level is created dynamically, all turfs on the map will be changed to this one type. If null, will use the base_turf instead. + var/filler_turf + ///The default area type for the whole level. It will be applied to all turfs in the level on creation, unless loaded by map. + var/base_area = /area/space + ///The turf to fill the border area beyond the bounds of the level with. + /// If null, nothing will be placed in the border area. (This is also placed when a border cannot be looped if loop_unconnected_borders is TRUE) + var/border_filler// = /turf/unsimulated/mineral + ///If set we will put a looping edge on every unconnected edge of the map. If null, will not loop unconnected edges. + /// If an unconnected edge is facing a connected edge, it will be instead filled with "border_filler" instead, if defined. + var/loop_turf_type// = /turf/unsimulated/mimc_edge/transition/loop + /// The turf type to use for zlevel lateral connections + var/transition_turf_type = /turf/unsimulated/mimic_edge/transition + + // *** Atmos *** + /// Temperature of standard exterior atmosphere. + var/exterior_atmos_temp = T20C + /// Gas mixture datum returned to exterior return_air. Set to assoc list of material to moles to initialize the gas datum. + var/datum/gas_mixture/exterior_atmosphere - my_z = z - forceMove(null) + // *** Connections *** + ///A list of all level_ids, and a direction. Indicates what direction of the map connects to what level + var/list/connected_levels + ///A cached list of connected directions to their connected level id. Filled up at runtime. + var/tmp/list/cached_connections - if(SSmapping.levels_by_z.len < my_z) - SSmapping.levels_by_z.len = max(SSmapping.levels_by_z.len, my_z) - PRINT_STACK_TRACE("Attempting to initialize a z-level that has not incremented world.maxz.") + ///A list of /datum/random_map types to apply to this level if we're running level generation. + /// Those are run before any parents/map_templates map generators. + var/list/level_generators - // Swap out the old one but preserve any relevant references etc. - if(SSmapping.levels_by_z[my_z]) - var/obj/abstract/level_data/old_level = SSmapping.levels_by_z[my_z] - old_level.replace_with(src) - qdel(old_level) + ///Whether the level data was setup already. + var/_level_setup_completed = FALSE - SSmapping.levels_by_z[my_z] = src - if(!level_id) - level_id = "leveldata_[my_z]_[sequential_id(/obj/abstract/level_data)]" - if(level_id in SSmapping.levels_by_id) - PRINT_STACK_TRACE("Duplicate level_id '[level_id]' for z[my_z].") - else - SSmapping.levels_by_id[level_id] = src +/datum/level_data/New(var/_z_level, var/defer_level_setup = FALSE) + . = ..() + level_z = _z_level + if(isnull(_z_level)) + PRINT_STACK_TRACE("Attempting to initialize a null z-level.") + initialize_level_id() + SSmapping.register_level_data(src) if(SSmapping.initialized && !defer_level_setup) setup_level_data() -/obj/abstract/level_data/proc/post_template_load(var/datum/map_template/template) - if(template.accessibility_weight) - SSmapping.accessible_z_levels[num2text(my_z)] = template.accessibility_weight - SSmapping.player_levels |= my_z +/datum/level_data/Destroy(force) + log_debug("Level data datum being destroyed: [log_info_line(src)]") + //Since this is a datum that lives inside the SSmapping subsystem, I'm not sure if we really need to prevent deletion. + // It was fine for the obj version of this, but not much point now? + SSmapping.unregister_level_data(src) + . = ..() -/obj/abstract/level_data/Destroy(var/force) - if(force) - new type(locate(round(world.maxx/2), round(world.maxy/2), my_z)) - return ..() - return QDEL_HINT_LETMELIVE +///Generates a level_id if none were specified in the datum definition. +/datum/level_data/proc/initialize_level_id() + if(level_id) + return + level_id = "leveldata_[level_z]_[sequential_id(/datum/level_data)]" -/obj/abstract/level_data/proc/replace_with(var/obj/abstract/level_data/new_level) +///Handle a new level_data datum overwriting us. +/datum/level_data/proc/replace_with(var/datum/level_data/new_level) new_level.copy_from(src) -/obj/abstract/level_data/proc/copy_from(var/obj/abstract/level_data/old_level) +///Handle copying data from a previous level_data we're replacing. +/datum/level_data/proc/copy_from(var/datum/level_data/old_level) return -/obj/abstract/level_data/proc/initialize_level() - var/change_turf = (created_base_turf_type && created_base_turf_type != world.turf) - var/change_area = (created_base_area_type && created_base_area_type != world.area) +///Initialize the turfs on the z-level. +/datum/level_data/proc/initialize_new_level() + //#TODO: Is it really necessary to do this for any and all levels? Seems mainly useful for space levels? + var/picked_turf = filler_turf || base_turf //Pick the filler_turf for filling if it's set, otherwise use the base_turf + var/change_turf = (picked_turf && picked_turf != world.turf) + var/change_area = (base_area && base_area != world.area) if(!change_turf && !change_area) return - var/corner_start = locate(1, 1, my_z) - var/corner_end = locate(world.maxx, world.maxy, my_z) - var/area/A = change_area ? new created_base_area_type : null + var/corner_start = locate(1, 1, level_z) + var/corner_end = locate(world.maxx, world.maxy, level_z) + var/area/A = change_area ? get_base_area_instance() : null for(var/turf/T as anything in block(corner_start, corner_end)) if(change_turf) - T = T.ChangeTurf(created_base_turf_type) + T = T.ChangeTurf(picked_turf) if(change_area) ChangeArea(T, A) -/obj/abstract/level_data/proc/setup_level_data() - - if(take_starlight_ambience) - ambient_light_level = config.exterior_ambient_light - ambient_light_color = SSskybox.background_color - if(base_turf) - SSmapping.base_turf_by_z[my_z] = base_turf - if(level_flags & ZLEVEL_STATION) - SSmapping.station_levels |= my_z - if(level_flags & ZLEVEL_ADMIN) - SSmapping.admin_levels |= my_z - if(level_flags & ZLEVEL_CONTACT) - SSmapping.contact_levels |= my_z - if(level_flags & ZLEVEL_PLAYER) - SSmapping.player_levels |= my_z - if(level_flags & ZLEVEL_SEALED) - SSmapping.sealed_levels |= my_z - - build_exterior_atmosphere() - if(config.generate_map) - build_level() - -/obj/abstract/level_data/proc/build_level() - return - -/obj/abstract/level_data/proc/find_connected_levels(var/list/found) - for(var/other_id in connects_to) - var/obj/abstract/level_data/neighbor = SSmapping.levels_by_id[other_id] - neighbor.add_connected_levels(found) - -/obj/abstract/level_data/proc/add_connected_levels(var/list/found) - . = found - if((my_z in found)) +///Prepare level for being used. Setup borders, lateral z connections, ambient lighting, atmosphere, etc.. +/datum/level_data/proc/setup_level_data() + if(_level_setup_completed) + return //Since we can defer setup, make sure we only setup once + + setup_level_bounds() + setup_ambient() + setup_exterior_atmosphere() + generate_level() + after_generate_level() + _level_setup_completed = TRUE + +///Calculate the bounds of the level, the border area, and the inner accessible area. +/datum/level_data/proc/setup_level_bounds() + level_max_width = level_max_width ? level_max_width : world.maxx + level_max_height = level_max_height ? level_max_height : world.maxy + var/x_origin = round((world.maxx - level_max_width) / 2) + var/y_origin = round((world.maxy - level_max_height) / 2) + + //The first x/y that's within the accessible level + level_inner_min_x = x_origin + TRANSITIONEDGE + 1 + level_inner_min_y = y_origin + TRANSITIONEDGE + 1 + + //The last x/y that's within the accessible level + level_inner_max_x = (level_max_width - level_inner_min_x) + 1 + level_inner_max_y = (level_max_height - level_inner_min_y) + 1 + + //The width of the accessible inner area of the level + level_inner_width = level_max_width - (2 * TRANSITIONEDGE) + level_inner_height = level_max_height - (2 * TRANSITIONEDGE) + +///Setup ambient lighting for the level +/datum/level_data/proc/setup_ambient() + if(!use_global_exterior_ambience) return - LAZYADD(found, my_z) - if(!length(connects_to)) + ambient_light_level = config.exterior_ambient_light + ambient_light_color = SSskybox.background_color + +///Setup/generate atmosphere for exterior turfs on the level. +/datum/level_data/proc/setup_exterior_atmosphere() + //Skip setup if we've been set to a ref already + if(istype(exterior_atmosphere)) + exterior_atmosphere.update_values() //Might as well update + exterior_atmosphere.check_tile_graphic() return - for(var/other_id in connects_to) - var/obj/abstract/level_data/neighbor = SSmapping.levels_by_id[other_id] - neighbor.add_connected_levels(found) - -/obj/abstract/level_data/proc/build_exterior_atmosphere() var/list/exterior_atmos_composition = exterior_atmosphere exterior_atmosphere = new if(islist(exterior_atmos_composition)) @@ -136,80 +241,306 @@ INITIALIZE_IMMEDIATE(/obj/abstract/level_data) exterior_atmosphere.update_values() exterior_atmosphere.check_tile_graphic() -/obj/abstract/level_data/proc/get_exterior_atmosphere() - if(isnull(exterior_atmosphere) || islist(exterior_atmosphere)) //#FIXME: remove once we get the level_data improvements in - build_exterior_atmosphere() +// +// Level Load/Gen +// + +///Called when setting up the level. Apply generators and anything that modifies the turfs of the level. +/datum/level_data/proc/generate_level() + var/origx = level_inner_min_x + var/origy = level_inner_min_y + var/endx = level_inner_min_x + level_inner_width + var/endy = level_inner_min_y + level_inner_height + for(var/gen_type in level_generators) + new gen_type(origx, origy, level_z, endx, endy, FALSE, TRUE, get_base_area_instance()) + +///Apply the parent entity's map generators. (Planets generally) +///This proc is to give a chance to level_data subtypes to individually chose to ignore the parent generators. +/datum/level_data/proc/apply_map_generators(var/list/map_gen) + var/origx = level_inner_min_x + var/origy = level_inner_min_y + var/endx = level_inner_min_x + level_inner_width + var/endy = level_inner_min_y + level_inner_height + for(var/gen_type in map_gen) + new gen_type(origx, origy, level_z, endx, endy, FALSE, TRUE, get_base_area_instance()) + +///Called during level setup. Run anything that should happen only after the map is fully generated. +/datum/level_data/proc/after_generate_level() + build_border() + +///Changes anything named we may need to rename accordingly to the parent location name. For instance, exoplanets levels. +/datum/level_data/proc/adapt_location_name(var/location_name) + SHOULD_CALL_PARENT(TRUE) + if(!base_area || ispath(base_area, /area/space)) + return FALSE + return TRUE + +///Called after a map_template has been loaded on our z-level. Only apply to templates loaded onto new z-levels. +/datum/level_data/proc/post_template_load(var/datum/map_template/template) + if(template.accessibility_weight) + SSmapping.accessible_z_levels[num2text(level_z)] = template.accessibility_weight + SSmapping.player_levels |= level_z + +///Builds the map's transition edge if applicable +/datum/level_data/proc/build_border() + var/list/edge_states = compute_level_edges_states() + for(var/edge_dir in global.cardinal) + build_border_edge(edge_states[edge_dir], edge_dir) + + //Now prepare the corners of the border + build_border_corners() + +///Loop through the edges of the level and determine if they're connected, looping, filled, or untouched. +/datum/level_data/proc/compute_level_edges_states() + var/list/edge_states = list() + edge_states.len = 8 //Largest cardinal direction is WEST or 8 + var/should_loop_edges = ispath(loop_turf_type) + var/has_filler_edge = ispath(border_filler) + + //First determine and validate the borders + for(var/adir in global.cardinal) + //First check for connections, or loop + if(get_connected_level_id(adir)) + edge_states[adir] = LEVEL_EDGE_CON + var/reverse = global.reverse_dir[adir] + //When facing a connected edge that wasn't set yet, make sure we don't put a loop edge opposite of it. + if(should_loop_edges && ((edge_states[reverse] == LEVEL_EDGE_LOOP) || !edge_states[reverse])) + edge_states[reverse] = has_filler_edge? LEVEL_EDGE_WALL : LEVEL_EDGE_NONE + + if(edge_states[adir]) + continue //Skip edges which either connect to another z-level, or have been forced to a specific type already + if(should_loop_edges) + edge_states[adir] = LEVEL_EDGE_LOOP + else if(ispath(border_filler)) + edge_states[adir] = LEVEL_EDGE_WALL //Apply filler wall last if we have no connections or loop + else + edge_states[adir] = LEVEL_EDGE_NONE + + return edge_states + +///Apply the specified edge type to the specified edge's turfs +/datum/level_data/proc/build_border_edge(var/edge_type, var/edge_dir) + if(edge_type == LEVEL_EDGE_NONE) + return + + var/list/edge_turfs + switch(edge_type) + if(LEVEL_EDGE_LOOP) + edge_turfs = get_transition_edge_turfs(level_z, edge_dir, FALSE) + for(var/turf/T in edge_turfs) + T.ChangeTurf(loop_turf_type) + if(LEVEL_EDGE_CON) + edge_turfs = get_transition_edge_turfs(level_z, edge_dir, FALSE) + for(var/turf/T in edge_turfs) + T.ChangeTurf(transition_turf_type) + if(LEVEL_EDGE_WALL) + edge_turfs = get_transition_edge_turfs(level_z, edge_dir, TRUE) + for(var/turf/T in edge_turfs) + T.ChangeTurf(border_filler) + +///Handle preparing the level's border's corners after we've stup the edges. +/datum/level_data/proc/build_border_corners() + //Now prepare the corners of the border + var/list/all_corner_turfs = get_transition_edge_corner_turfs(level_z) + for(var/turf/T in all_corner_turfs) + //In case we got filler turfs for borders, make sure to fill the corners with it + if(border_filler) + T.ChangeTurf(border_filler) + //Force corner turfs to be solid, so nothing end up being lost/stuck in there + T.set_density(TRUE) + +// +// Accessors +// +/datum/level_data/proc/get_exterior_atmosphere() + if(!istype(exterior_atmosphere)) //#FIXME: Temporary measure until the exoplanet gen stuff is moved out of overmap markers + setup_exterior_atmosphere() if(exterior_atmosphere) var/datum/gas_mixture/gas = new gas.copy_from(exterior_atmosphere) return gas -/obj/abstract/level_data/proc/get_gps_level_name() - if(!gps_name) - var/obj/effect/overmap/overmap_entity = global.overmap_sectors[num2text(z)] +/datum/level_data/proc/get_display_name() + if(!name) + var/obj/effect/overmap/overmap_entity = global.overmap_sectors[num2text(level_z)] if(overmap_entity?.name) - gps_name = overmap_entity.name - else if(name) - gps_name = name + name = overmap_entity.name else - gps_name = "Sector #[my_z]" - return gps_name + name = "Sector #[level_z]" + return name + +/datum/level_data/proc/get_connected_level_id(var/direction) + if(!length(cached_connections)) + //Build a list that we can access with the direction value instead of having to do string conversions + cached_connections = list() + cached_connections.len = DOWN //Down is the largest of the directional values + for(var/lvlid in connected_levels) + cached_connections[connected_levels[lvlid]] = lvlid + + if(istext(direction)) + CRASH("Direction must be a direction flag.") + return cached_connections[direction] + +///Returns recursively a list of level_data for each connected levels. +/datum/level_data/proc/get_all_connected_level_data(var/list/_connected_siblings) + . = list() + //Since levels may refer to eachothers, make sure we're in the siblings list to avoid infinite recursion + LAZYDISTINCTADD(_connected_siblings, src) + for(var/id in connected_levels) + var/datum/level_data/LD = SSmapping.levels_by_id[id] + if(LD in _connected_siblings) + continue + . |= LD + var/list/cur_con = LD.get_all_connected_level_data(_connected_siblings) + if(length(cur_con)) + . |= cur_con + +///Returns recursively a list of level_ids for each connected levels. +/datum/level_data/proc/get_all_connected_level_ids(var/list/_connected_siblings) + . = list() + //Since levels may refer to eachothers, make sure we're in the siblings list to avoid infinite recursion + LAZYDISTINCTADD(_connected_siblings, level_id) + for(var/id in connected_levels) + var/datum/level_data/LD = SSmapping.levels_by_id[id] + if(LD.level_id in _connected_siblings) + continue + . |= LD.level_id + var/list/cur_con = LD.get_all_connected_level_ids(_connected_siblings) + if(length(cur_con)) + . |= cur_con + +///Returns recursively a list of z-level indices for each connected levels. Parameter is to keep trakc +/datum/level_data/proc/get_all_connected_level_z(var/list/_connected_siblings) + . = list() + //Since levels may refer to eachothers, make sure we're in the siblings list to avoid infinite recursion + LAZYDISTINCTADD(_connected_siblings, level_z) + for(var/id in connected_levels) + var/datum/level_data/LD = SSmapping.levels_by_id[id] + if(LD.level_z in _connected_siblings) + continue + . |= LD.level_z + var/list/cur_con = LD.get_all_connected_level_z(_connected_siblings) + if(length(cur_con)) + . |= cur_con + + +/datum/level_data/proc/find_connected_levels(var/list/found) + LAZYDISTINCTADD(found, level_z) + for(var/other_id in connected_levels) + var/datum/level_data/neighbor = SSmapping.levels_by_id[other_id] + if(neighbor.level_z in found) + continue + LAZYADD(found, neighbor.level_z) + if(!length(neighbor.connected_levels)) + continue + neighbor.find_connected_levels(found) + +///Returns the instance of the base area for this level +/datum/level_data/proc/get_base_area_instance() + var/area/found = locate(base_area) + if(found) + return found + if(ispath(base_area)) + return new base_area + return locate(world.area) + +//////////////////////////////////////////// +// Level Data Spawner +//////////////////////////////////////////// + +/// Mapper helper for spawning a specific level_data datum with the map as it gets loaded +/obj/abstract/level_data_spawner + name = "level data spawner" + var/level_data_type = /datum/level_data/space + +INITIALIZE_IMMEDIATE(/obj/abstract/level_data_spawner) +/obj/abstract/level_data_spawner/Initialize() + var/datum/level_data/LD = new level_data_type(z) + //Let the mapper forward a level name for the level_data, if none was defined + if(!length(LD.name) && length(name)) + LD.name = name + ..() + return INITIALIZE_HINT_QDEL + +//////////////////////////////////////////// +// Mapper Templates +//////////////////////////////////////////// +/obj/abstract/level_data_spawner/player + level_data_type = /datum/level_data/player_level + +/obj/abstract/level_data_spawner/main_level + level_data_type = /datum/level_data/main_level + +/obj/abstract/level_data_spawner/admin_level + level_data_type = /datum/level_data/admin_level + +/obj/abstract/level_data_spawner/debug + level_data_type = /datum/level_data/debug + +/obj/abstract/level_data_spawner/mining_level + level_data_type = /datum/level_data/mining_level -/* - * Mappable subtypes. - */ -/obj/abstract/level_data/debug +/obj/abstract/level_data_spawner/exoplanet + level_data_type = /datum/level_data/exoplanet + +//////////////////////////////////////////// +// Level Data Implementations +//////////////////////////////////////////// +/datum/level_data/space + +/datum/level_data/debug name = "Debug Level" -/obj/abstract/level_data/main_level +/datum/level_data/main_level level_flags = (ZLEVEL_STATION|ZLEVEL_CONTACT|ZLEVEL_PLAYER) -/obj/abstract/level_data/admin_level +/datum/level_data/admin_level level_flags = (ZLEVEL_ADMIN|ZLEVEL_SEALED) -/obj/abstract/level_data/player_level +/datum/level_data/player_level level_flags = (ZLEVEL_CONTACT|ZLEVEL_PLAYER) -/obj/abstract/level_data/space - -/obj/abstract/level_data/exoplanet +/datum/level_data/exoplanet exterior_atmosphere = list( /decl/material/gas/oxygen = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD ) exterior_atmos_temp = T20C level_flags = (ZLEVEL_PLAYER|ZLEVEL_SEALED) - take_starlight_ambience = FALSE // This is set up by the exoplanet object. + use_global_exterior_ambience = FALSE // This is set up by the exoplanet object. -/obj/abstract/level_data/unit_test +/datum/level_data/unit_test level_flags = (ZLEVEL_CONTACT|ZLEVEL_PLAYER|ZLEVEL_SEALED) -// Used to generate mining ores etc. -/obj/abstract/level_data/mining_level +/datum/level_data/overmap + name = "Sensor Display" + level_flags = ZLEVEL_SEALED + use_global_exterior_ambience = FALSE // Overmap doesn't care about ambient lighting + +//#TODO: This seems like it could be generalized in a much better way? +// Used specifically by /turf/simulated/floor/asteroid, and some away sites to generate mining turfs +/datum/level_data/mining_level level_flags = (ZLEVEL_PLAYER|ZLEVEL_SEALED) var/list/mining_turfs -/obj/abstract/level_data/mining_level/Destroy() +/datum/level_data/mining_level/Destroy() mining_turfs = null return ..() -/obj/abstract/level_data/mining_level/asteroid +/datum/level_data/mining_level/asteroid base_turf = /turf/simulated/floor/asteroid -/obj/abstract/level_data/mining_level/post_template_load() - ..() - new /datum/random_map/automata/cave_system(1, 1, my_z, world.maxx, world.maxy) - new /datum/random_map/noise/ore(1, 1, my_z, world.maxx, world.maxy) +/datum/level_data/mining_level/generate_level() + //#FIXME: This config option is very ambiguous. Most RNG stuff doesn't care about it. Might be worth removing? + if(!config.generate_map) + return + new /datum/random_map/automata/cave_system(1, 1, level_z, world.maxx, world.maxy) + new /datum/random_map/noise/ore(1, 1, level_z, world.maxx, world.maxy) refresh_mining_turfs() -/obj/abstract/level_data/mining_level/proc/refresh_mining_turfs() +/datum/level_data/mining_level/proc/refresh_mining_turfs() set waitfor = FALSE for(var/turf/simulated/floor/asteroid/mining_turf as anything in mining_turfs) mining_turf.updateMineralOverlays() CHECK_TICK mining_turfs = null - -// Used as a dummy z-level for the overmap. -/obj/abstract/level_data/overmap - name = "Sensor Display" - take_starlight_ambience = FALSE // Overmap doesn't care about ambient lighting diff --git a/code/modules/multiz/turf_mimic_edge.dm b/code/modules/multiz/turf_mimic_edge.dm new file mode 100644 index 00000000000..b8f28194f42 --- /dev/null +++ b/code/modules/multiz/turf_mimic_edge.dm @@ -0,0 +1,366 @@ +#define MIMIC_EDGE_NAME "world's edge" +#define MIMIC_EDGE_DESC "Flatearther's nightmare." + +//////////////////////////////// +// Mimic Edges +//////////////////////////////// + +///Dummy mouse-opaque overlay to prevent people turning/shooting towards ACTUAL location of vis_content thing +/obj/effect/overlay/click_bait + name = "distant terrain" + desc = "You need to come over there to take a better look." + mouse_opacity = 2 + +//////////////////////////////// +// Simulated Mimic Edges +//////////////////////////////// + +///Simulated turf meant to replicate the appearence of another. +/turf/simulated/mimic_edge + name = MIMIC_EDGE_NAME + desc = MIMIC_EDGE_DESC + icon = null + icon_state = null + density = FALSE + permit_ao = FALSE //would need AO proxy + blocks_air = TRUE //would need air zone proxy + dynamic_lighting = FALSE //Would need lighting proxy + + ///Mimicked turf's x position + var/mimic_x + ///Mimicked turf's y position + var/mimic_y + ///Mimicked turf's z position + var/mimic_z + ///Ref to the dummy overlay + var/obj/effect/overlay/click_bait/click_eater + +/turf/simulated/mimic_edge/Initialize(ml) + . = ..() + //Clear ourselves from the ambient queue + SSambience.queued -= src + //Need to put a mouse-opaque overlay there to prevent people turning/shooting towards ACTUAL location of vis_content things + click_eater = new(src) + setup_mimic() + +/turf/simulated/mimic_edge/Destroy() + QDEL_NULL(click_eater) //Make sure we get rid of it if the turf is somehow replaced by map gen to prevent them accumulating. + return ..() + +//Properly install itself, and allow overriding how the target turf is picked +/turf/simulated/mimic_edge/proc/setup_mimic() + return + +/turf/simulated/mimic_edge/on_update_icon() + return + +/turf/simulated/mimic_edge/get_vis_contents_to_add() + . = ..() + var/turf/NT = mimic_x && mimic_y && mimic_z && locate(mimic_x, mimic_y, mimic_z) + if(NT) + opacity = NT.opacity + //log_debug("[src]([x],[y],[z]) mirroring [NT]([NT.x],[NT.y],[NT.z])") + LAZYADD(., NT) + +/turf/simulated/mimic_edge/proc/set_mimic_turf(var/_x, var/_y, var/_z) + mimic_z = _z? _z : z + mimic_x = _x + mimic_y = _y + refresh_vis_contents() + +//Prevent ambient completely, we're not a real turf +/turf/simulated/mimic_edge/set_ambient_light(color, multiplier) + return +/turf/simulated/mimic_edge/update_ambient_light(no_corner_update) + return +/turf/simulated/mimic_edge/update_ambient_light_from_z() + return +/turf/simulated/mimic_edge/lighting_build_overlay(now) + return + +//////////////////////////////// +// Unsimulated Mimic Edges +//////////////////////////////// + +///Unsimulated turf meant to replicate the appearence of another. +/turf/unsimulated/mimic_edge + name = MIMIC_EDGE_NAME + desc = MIMIC_EDGE_DESC + icon = null + icon_state = null + density = FALSE + permit_ao = FALSE + blocks_air = TRUE + dynamic_lighting = FALSE + + ///Mimicked turf's x position + var/mimic_x + ///Mimicked turf's y position + var/mimic_y + ///Mimicked turf's z position + var/mimic_z + ///Ref to the dummy overlay + var/obj/effect/overlay/click_bait/click_eater + +/turf/unsimulated/mimic_edge/Initialize(ml) + . = ..() + //Clear ourselves from the ambient queue + SSambience.queued -= src + //Need to put a mouse-opaque overlay there to prevent people turning/shooting towards ACTUAL location of vis_content things + click_eater = new(src) + setup_mimic() + +/turf/unsimulated/mimic_edge/Destroy() + QDEL_NULL(click_eater) + return ..() + +//Properly install itself, and allow overriding how the target turf is picked +/turf/unsimulated/mimic_edge/proc/setup_mimic() + return + +/turf/unsimulated/mimic_edge/on_update_icon() + return + +/turf/unsimulated/mimic_edge/get_vis_contents_to_add() + . = ..() + var/turf/NT = mimic_x && mimic_y && mimic_z && locate(mimic_x, mimic_y, mimic_z) + if(NT) + opacity = NT.opacity + //log_debug("[src]([x],[y],[z]) mirroring [NT]([NT.x],[NT.y],[NT.z])") + LAZYADD(., NT) + +/turf/unsimulated/mimic_edge/proc/set_mimic_turf(var/_x, var/_y, var/_z) + mimic_z = _z? _z : z + mimic_x = _x + mimic_y = _y + refresh_vis_contents() + +//Prevent ambient completely, we're not a real turf +/turf/unsimulated/mimic_edge/set_ambient_light(color, multiplier) + return +/turf/unsimulated/mimic_edge/update_ambient_light(no_corner_update) + return +/turf/unsimulated/mimic_edge/update_ambient_light_from_z() + return +/turf/unsimulated/mimic_edge/lighting_build_overlay(now) + return + +//////////////////////////////// +// Exterior Mimic Edges +//////////////////////////////// + +///Exterior turf meant to replicate the appearence of another. +/turf/exterior/mimic_edge + name = MIMIC_EDGE_NAME + desc = MIMIC_EDGE_DESC + icon = null + icon_state = null + density = FALSE + permit_ao = FALSE + blocks_air = TRUE + dynamic_lighting = FALSE + + ///Mimicked turf's x position + var/mimic_x + ///Mimicked turf's y position + var/mimic_y + ///Mimicked turf's z position + var/mimic_z + ///Ref to the dummy overlay + var/obj/effect/overlay/click_bait/click_eater + +/turf/exterior/mimic_edge/Initialize(ml) + . = ..() + //Clear ourselves from the ambient queue + SSambience.queued -= src + //Need to put a mouse-opaque overlay there to prevent people turning/shooting towards ACTUAL location of vis_content things + click_eater = new(src) + setup_mimic() + +/turf/exterior/mimic_edge/Destroy() + QDEL_NULL(click_eater) + return ..() + +//Properly install itself, and allow overriding how the target turf is picked +/turf/exterior/mimic_edge/proc/setup_mimic() + return + +/turf/exterior/mimic_edge/on_update_icon() + return + +/turf/exterior/mimic_edge/get_vis_contents_to_add() + . = ..() + var/turf/NT = mimic_x && mimic_y && mimic_z && locate(mimic_x, mimic_y, mimic_z) + if(NT) + opacity = NT.opacity + //log_debug("[src]([x],[y],[z]) mirroring [NT]([NT.x],[NT.y],[NT.z])") + LAZYADD(., NT) + +/turf/exterior/mimic_edge/proc/set_mimic_turf(var/_x, var/_y, var/_z) + mimic_z = _z? _z : z + mimic_x = _x + mimic_y = _y + refresh_vis_contents() + +//Prevent ambient completely, we're not a real turf +/turf/exterior/mimic_edge/set_ambient_light(color, multiplier) + return +/turf/exterior/mimic_edge/update_ambient_light(no_corner_update) + return +/turf/exterior/mimic_edge/update_ambient_light_from_z() + return +/turf/exterior/mimic_edge/lighting_build_overlay(now) + return + +//////////////////////////////// +// Transition Edges Shared +//////////////////////////////// + +///Returns the a cardinal direction for a turf on the map that's beyond the transition edge +/proc/get_turf_transition_edge_direction(var/turf/T, var/datum/level_data/target_ldat) + var/within_west_transit = T.x < target_ldat.level_inner_min_x //Is the turf X within the west transition edge? + var/within_east_transit = T.x > target_ldat.level_inner_max_x //Is the turf X within the east transition edge? + var/within_south_transit = T.y < target_ldat.level_inner_min_y //Is the turf Y within the south transition edge? + var/within_north_transit = T.y > target_ldat.level_inner_max_y //Is the turf Y within the north transition edge? + + //Filter out corners, since we can't mimic those properly + if(within_west_transit && !within_south_transit && !within_north_transit) + return WEST + if(within_east_transit && !within_south_transit && !within_north_transit) + return EAST + if(within_south_transit && !within_west_transit && !within_east_transit) + return SOUTH + if(within_north_transit && !within_west_transit && !within_east_transit) + return NORTH + + //Corners return null + return null + +/// Returns the turf that's opposite to the specified turf, on the level specified. +/proc/shared_transition_edge_get_coordinates_turf_to_mimic(var/turf/T, var/datum/level_data/target_ldat) + var/translate_from_dir = get_turf_transition_edge_direction(T, target_ldat) + if(isnull(translate_from_dir)) + //In this case we're in the corners of the map. We shouldn't mimic. + log_warning("Transition turf '[T]' at ([T.x], [T.y], [T.z]) was in a corner of the map. That's likely a mistake, since we can't mimic corners properly!") + return list(T.x, T.y, T.z) + + var/newx = T.x + var/newy = T.y + switch(translate_from_dir) + if(NORTH) + newy = (target_ldat.level_inner_min_y - 1) + (T.y - target_ldat.level_inner_max_y) //The level_inner coords are inclusive, so we need to +- 1 + if(SOUTH) + newy = (target_ldat.level_inner_max_y + 1) - (target_ldat.level_inner_min_y - T.y) + if(EAST) + newx = (target_ldat.level_inner_min_x - 1) + (T.x - target_ldat.level_inner_max_x) + if(WEST) + newx = (target_ldat.level_inner_max_x + 1) - (target_ldat.level_inner_min_x - T.x) + + return list(newx, newy, target_ldat.level_z) + +///Grab the connected level data for the level connected in the direction the 'T' turf is in. +/proc/shared_transition_edge_get_valid_level_data(var/turf/T) + var/datum/level_data/LD = SSmapping.levels_by_z[T.z] + var/edge_dir = get_turf_transition_edge_direction(T, LD) + var/connected_lvl_id = LD.get_connected_level_id(edge_dir) + if(!connected_lvl_id) + var/dirname = dir2text(edge_dir) + CRASH("Got transition_edge turf '[T]' ([T.x], [T.y], [T.z]), in direction '[dirname]', but there is no connections in level_data '[LD]' for '[dirname]'!") + return SSmapping.levels_by_id[connected_lvl_id] + +///Handles teleporting an atom that touches a transition edge/loop edge. +/proc/shared_transition_edge_bumped(var/turf/T, var/atom/movable/AM, var/mimic_z) + var/datum/level_data/LDsrc = SSmapping.levels_by_z[T.z] + var/datum/level_data/LDdst = SSmapping.levels_by_z[mimic_z] + var/new_x = AM.x + var/new_y = AM.y + + //Get the position inside the destination level's bounds to teleport the thing to + if(T.x <= LDsrc.level_inner_min_x) + new_x = LDdst.level_inner_max_x + else if (T.x >= LDsrc.level_inner_max_x) + new_x = LDdst.level_inner_min_x + else if (T.y <= LDsrc.level_inner_min_y) + new_y = LDdst.level_inner_max_y + else if (T.y >= LDsrc.level_inner_max_y) + new_y = LDdst.level_inner_min_y + else + return //If we're teleporting into the same spot just quit early + + //Teleport to the turf + var/turf/dest = locate(new_x, new_y, mimic_z) + if(!dest) + CRASH("Turf '[T]' failed to teleport '[AM]' to [new_x], [new_y], [mimic_z]. Couldn't locate turf!") + if(dest.density) + return //If the target turf is dense, just siltently do nothing. + + AM.forceMove(dest) + //Move grabbed things + if(isliving(AM)) + var/mob/living/L = AM + for(var/obj/item/grab/G in L.get_active_grabs()) + G.affecting.forceMove(dest) + +//////////////////////////////// +// Transition Edges +//////////////////////////////// + +///When soemthing touches this turf, it gets transported to the connected level matching the direction of the edge on the map +/turf/simulated/mimic_edge/transition/setup_mimic() + var/list/coord = shared_transition_edge_get_coordinates_turf_to_mimic(src, shared_transition_edge_get_valid_level_data(src)) + set_mimic_turf(coord[1], coord[2], coord[3]) +/turf/simulated/mimic_edge/transition/Entered(atom/movable/AM, atom/old_loc) + . = ..() + if(!AM.simulated || AM.anchored || istype(AM, /obj/effect/overlay)) + return + if(istype(AM, /obj/effect/projectile)) //#FIXME: Once we support projectiles going through levels properly remove this + return + shared_transition_edge_bumped(src, AM, mimic_z) + +/turf/unsimulated/mimic_edge/transition/setup_mimic() + var/list/coord = shared_transition_edge_get_coordinates_turf_to_mimic(src, shared_transition_edge_get_valid_level_data(src)) + set_mimic_turf(coord[1], coord[2], coord[3]) +/turf/unsimulated/mimic_edge/transition/Entered(atom/movable/AM, atom/old_loc) + . = ..() + if(!AM.simulated || AM.anchored || istype(AM, /obj/effect/overlay)) + return + if(istype(AM, /obj/effect/projectile)) //#FIXME: Once we support projectiles going through levels properly remove this + return + shared_transition_edge_bumped(src, AM, mimic_z) + +/turf/exterior/mimic_edge/transition/setup_mimic() + var/list/coord = shared_transition_edge_get_coordinates_turf_to_mimic(src, shared_transition_edge_get_valid_level_data(src)) + set_mimic_turf(coord[1], coord[2], coord[3]) +/turf/exterior/mimic_edge/transition/Entered(atom/movable/AM, atom/old_loc) + . = ..() + if(!AM.simulated || AM.anchored || istype(AM, /obj/effect/overlay)) + return + if(istype(AM, /obj/effect/projectile)) //#FIXME: Once we support projectiles going through levels properly remove this + return + shared_transition_edge_bumped(src, AM, mimic_z) + +//////////////////////////////// +// Loop Edges +//////////////////////////////// + +///When something touches this turf, it gets transported to the symmetrically opposite turf it's mimicking. +/turf/simulated/mimic_edge/transition/loop/set_mimic_turf(_x, _y, _z) + . = ..(_x, _y) +/turf/simulated/mimic_edge/transition/loop/setup_mimic() + var/list/coord = shared_transition_edge_get_coordinates_turf_to_mimic(src, SSmapping.levels_by_z[src.z]) + set_mimic_turf(coord[1], coord[2], coord[3]) + +/turf/unsimulated/mimic_edge/transition/loop/set_mimic_turf(_x, _y, _z) + . = ..(_x, _y) +/turf/unsimulated/mimic_edge/transition/loop/setup_mimic() + var/list/coord = shared_transition_edge_get_coordinates_turf_to_mimic(src, SSmapping.levels_by_z[src.z]) + set_mimic_turf(coord[1], coord[2], coord[3]) + +/turf/exterior/mimic_edge/transition/loop/set_mimic_turf(_x, _y, _z) + . = ..(_x, _y) +/turf/exterior/mimic_edge/transition/loop/setup_mimic() + var/list/coord = shared_transition_edge_get_coordinates_turf_to_mimic(src, SSmapping.levels_by_z[src.z]) + set_mimic_turf(coord[1], coord[2], coord[3]) + +#undef MIMIC_EDGE_NAME +#undef MIMIC_EDGE_DESC \ No newline at end of file diff --git a/code/modules/overmap/_overmap.dm b/code/modules/overmap/_overmap.dm index e13d9884286..bb91f801571 100644 --- a/code/modules/overmap/_overmap.dm +++ b/code/modules/overmap/_overmap.dm @@ -9,7 +9,7 @@ var/overmap_edge_type = /turf/unsimulated/map/edge var/overmap_turf_type = /turf/unsimulated/map var/overmap_area_type = /area/overmap - var/empty_level_type = /obj/abstract/level_data/space + var/empty_level_type = /datum/level_data/space var/list/valid_event_types @@ -56,7 +56,7 @@ /datum/overmap/proc/generate_overmap() testing("Building overmap [name]...") - SSmapping.increment_world_z_size(/obj/abstract/level_data/overmap) + SSmapping.increment_world_z_size(/datum/level_data/overmap) assigned_z = world.maxz testing("Putting [name] on [assigned_z].") populate_overmap() @@ -143,8 +143,8 @@ return res // Create a new one. - var/obj/abstract/level_data/level = SSmapping.increment_world_z_size(empty_level_type) - return new /obj/effect/overmap/visitable/sector/temporary(null, x, y, level.my_z) + var/datum/level_data/level = SSmapping.increment_world_z_size(empty_level_type) + return new /obj/effect/overmap/visitable/sector/temporary(null, x, y, level.level_z) /datum/overmap/proc/discard_temporary_sector(var/obj/effect/overmap/visitable/sector/temporary/sector) if(!length(cached_temporary_sectors[empty_level_type])) diff --git a/code/modules/overmap/exoplanets/_exoplanet.dm b/code/modules/overmap/exoplanets/_exoplanet.dm index de817dc4ee1..87fe9e379a9 100644 --- a/code/modules/overmap/exoplanets/_exoplanet.dm +++ b/code/modules/overmap/exoplanets/_exoplanet.dm @@ -110,7 +110,8 @@ var/planet_name = generate_planet_name() SetName("[planet_name], \a [name]") - planetary_area = new planetary_area() + if(ispath(planetary_area)) + planetary_area = new planetary_area() global.using_map.area_purity_test_exempt_areas += planetary_area.type planetary_area.SetName("Surface of [planet_name]") @@ -173,13 +174,13 @@ update_daynight() /obj/effect/overmap/visitable/sector/exoplanet/proc/update_daynight() - var/obj/abstract/level_data/level_data = SSmapping.levels_by_z[map_z[1]] + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] var/light = 0.1 if(!night) light = level_data.ambient_light_level for(var/turf/exterior/T in block(locate(daycolumn,1,min(map_z)),locate(daycolumn,maxy,max(map_z)))) if (light) - T.set_ambient_light(COLOR_WHITE, light) + T.set_ambient_light(COLOR_WHITE, light) //#FIXME: Use the ambient color from the level!! else T.clear_ambient_light() daycolumn++ @@ -221,7 +222,7 @@ spawned_features = seed_ruins(map_z, features_budget, /area/exoplanet, possible_features, maxx, maxy) /obj/effect/overmap/visitable/sector/exoplanet/proc/generate_daycycle() - var/obj/abstract/level_data/level_data = zlevels[1] + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] if(level_data.ambient_light_level) night = FALSE //we start with a day if we have light. @@ -264,8 +265,8 @@ /obj/effect/overmap/visitable/sector/exoplanet/get_scan_data(mob/user) . = ..() var/list/extra_data = list("
") - var/obj/abstract/level_data/level_data = zlevels[1] - var/datum/gas_mixture/atmosphere = level_data.exterior_atmosphere + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] + var/datum/gas_mixture/atmosphere = level_data.get_exterior_atmosphere() if(atmosphere) if(user.skill_check(SKILL_SCIENCE, SKILL_EXPERT) || user.skill_check(SKILL_ATMOS, SKILL_EXPERT)) var/list/gases = list() diff --git a/code/modules/overmap/exoplanets/exoplanet_atmosphere.dm b/code/modules/overmap/exoplanets/exoplanet_atmosphere.dm index 1e715e9cc3a..9e5e68095e5 100644 --- a/code/modules/overmap/exoplanets/exoplanet_atmosphere.dm +++ b/code/modules/overmap/exoplanets/exoplanet_atmosphere.dm @@ -10,13 +10,13 @@ //Skip fun gas gen for perfect terran worlds if(habitability_class == HABITABILITY_IDEAL) - for(var/obj/abstract/level_data/level_data in zlevels) + for(var/datum/level_data/level_data in zlevels) level_data.exterior_atmos_temp = target_temp level_data.exterior_atmosphere = list( /decl/material/gas/oxygen = MOLES_O2STANDARD, /decl/material/gas/nitrogen = MOLES_N2STANDARD ) - level_data.setup_level_data() + level_data.setup_level_data() //#FIXME: That's not very nice! Calling this again, when it should have been called before? return var/total_moles = MOLES_CELLSTANDARD @@ -90,7 +90,7 @@ for(var/g in gas_list) var/adjusted_moles = gas_list[g] * target_moles / MOLES_CELLSTANDARD set_gasmix[g] = adjusted_moles - for(var/obj/abstract/level_data/level_data in zlevels) + for(var/datum/level_data/level_data in zlevels) level_data.exterior_atmos_temp = target_temp level_data.exterior_atmosphere = set_gasmix.Copy() level_data.setup_level_data() diff --git a/code/modules/overmap/exoplanets/exoplanet_fauna.dm b/code/modules/overmap/exoplanets/exoplanet_fauna.dm index 2ede9f2f265..d3dac597b79 100644 --- a/code/modules/overmap/exoplanets/exoplanet_fauna.dm +++ b/code/modules/overmap/exoplanets/exoplanet_fauna.dm @@ -29,8 +29,8 @@ A.SetName("alien creature") A.real_name = "alien creature" A.verbs |= /mob/living/simple_animal/proc/name_species - var/obj/abstract/level_data/level_data = zlevels[1] - if(level_data.exterior_atmosphere) + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] + if(level_data.get_exterior_atmosphere()) //Generates the atmos if uninitialized //Set up gases for living things var/list/all_gasses = decls_repository.get_decl_paths_of_subtype(/decl/material/gas) if(!LAZYLEN(breathgas)) diff --git a/code/modules/overmap/exoplanets/exoplanet_flora.dm b/code/modules/overmap/exoplanets/exoplanet_flora.dm index 2b5bed796ad..cc27c7fefe3 100644 --- a/code/modules/overmap/exoplanets/exoplanet_flora.dm +++ b/code/modules/overmap/exoplanets/exoplanet_flora.dm @@ -1,9 +1,9 @@ //Generates initial generic alien plants /obj/effect/overmap/visitable/sector/exoplanet/proc/generate_flora() - var/obj/abstract/level_data/level_data = SSmapping.levels_by_z[map_z[1]] - var/datum/gas_mixture/atmosphere = level_data?.get_exterior_atmosphere() - var/temperature = atmosphere?.temperature || T20C + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] + var/datum/gas_mixture/atmos = level_data.get_exterior_atmosphere() //#FIXME: Replace once exoplanet gen is merged + var/temperature = atmos?.temperature || T20C for(var/i = 1 to flora_diversity) var/datum/seed/S = new() @@ -44,8 +44,8 @@ //Adapts seeds to this planet's atmopshere. Any special planet-speicific adaptations should go here too /obj/effect/overmap/visitable/sector/exoplanet/proc/adapt_seed(var/datum/seed/S) - var/obj/abstract/level_data/level_data = SSmapping.levels_by_z[map_z[1]] - var/datum/gas_mixture/atmosphere = level_data?.get_exterior_atmosphere() + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] + var/datum/gas_mixture/atmosphere = level_data?.get_exterior_atmosphere() //#FIXME: Replace once exoplanet gen is merged var/atmosphere_temperature = atmosphere?.temperature || T20C var/atmosphere_pressure = atmosphere?.return_pressure() || 0 diff --git a/code/modules/overmap/exoplanets/exoplanet_skybox.dm b/code/modules/overmap/exoplanets/exoplanet_skybox.dm index cd4f02c22b2..76b5ad99ce1 100644 --- a/code/modules/overmap/exoplanets/exoplanet_skybox.dm +++ b/code/modules/overmap/exoplanets/exoplanet_skybox.dm @@ -21,9 +21,9 @@ water.transform = water.transform.Turn(rand(0,360)) skybox_image.overlays += water - var/obj/abstract/level_data/level_data = SSmapping.levels_by_z[map_z[1]] - var/datum/gas_mixture/atmosphere = level_data?.get_exterior_atmosphere() - if(atmosphere?.return_pressure() > SOUND_MINIMUM_PRESSURE) + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] + var/datum/gas_mixture/atmos = level_data.get_exterior_atmosphere() + if(atmos?.return_pressure() > SOUND_MINIMUM_PRESSURE) var/atmo_color = get_atmosphere_color() if(!atmo_color) @@ -64,9 +64,9 @@ /obj/effect/overmap/visitable/sector/exoplanet/proc/get_atmosphere_color() var/list/colors = list() - for(var/Z in map_z) - var/obj/abstract/level_data/level_data = SSmapping.levels_by_z[Z] - for(var/g in level_data.exterior_atmosphere?.gas) + for(var/datum/level_data/level_data in zlevels) + var/datum/gas_mixture/atmos = level_data.get_exterior_atmosphere() + for(var/g in atmos?.gas) var/decl/material/mat = GET_DECL(g) colors += mat.color if(colors.len) diff --git a/code/modules/overmap/exoplanets/planet_themes/radiation_bombing.dm b/code/modules/overmap/exoplanets/planet_themes/radiation_bombing.dm index 3ac6e115cbf..0d97a94343d 100644 --- a/code/modules/overmap/exoplanets/planet_themes/radiation_bombing.dm +++ b/code/modules/overmap/exoplanets/planet_themes/radiation_bombing.dm @@ -3,7 +3,7 @@ /datum/exoplanet_theme/radiation_bombing/adjust_atmosphere(obj/effect/overmap/visitable/sector/exoplanet/E) var/add_temp = rand(20, 100) - for(var/obj/abstract/level_data/level_data in E.zlevels) + for(var/datum/level_data/level_data in E.zlevels) level_data.exterior_atmos_temp += add_temp if(level_data.exterior_atmosphere) level_data.exterior_atmosphere.temperature = level_data.exterior_atmos_temp diff --git a/code/modules/overmap/exoplanets/planet_types/chlorine.dm b/code/modules/overmap/exoplanets/planet_types/chlorine.dm index 958e6bfa843..e0e251580fb 100644 --- a/code/modules/overmap/exoplanets/planet_types/chlorine.dm +++ b/code/modules/overmap/exoplanets/planet_types/chlorine.dm @@ -23,7 +23,7 @@ return "#e5f2bd" /obj/effect/overmap/visitable/sector/exoplanet/chlorine/generate_map() - var/obj/abstract/level_data/level_data = zlevels[1] + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] if(prob(50)) level_data.ambient_light_level = rand(7,10)/10 //It could be night. else diff --git a/code/modules/overmap/exoplanets/planet_types/desert.dm b/code/modules/overmap/exoplanets/planet_types/desert.dm index 63fab9ef8a1..d6097859d37 100644 --- a/code/modules/overmap/exoplanets/planet_types/desert.dm +++ b/code/modules/overmap/exoplanets/planet_types/desert.dm @@ -18,7 +18,7 @@ /obj/effect/overmap/visitable/sector/exoplanet/desert/generate_map() if(prob(70)) - var/obj/abstract/level_data/level_data = zlevels[1] + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] level_data.ambient_light_level = rand(5,10)/10 //deserts are usually :lit: ..() diff --git a/code/modules/overmap/exoplanets/planet_types/grass.dm b/code/modules/overmap/exoplanets/planet_types/grass.dm index cef84c64384..c4a3b23e5be 100644 --- a/code/modules/overmap/exoplanets/planet_types/grass.dm +++ b/code/modules/overmap/exoplanets/planet_types/grass.dm @@ -12,7 +12,7 @@ /obj/effect/overmap/visitable/sector/exoplanet/grass/generate_map() if(prob(40)) - var/obj/abstract/level_data/level_data = zlevels[1] + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] level_data.ambient_light_level = rand(1,7)/10 //give a chance of twilight jungle ..() diff --git a/code/modules/overmap/exoplanets/planet_types/meat.dm b/code/modules/overmap/exoplanets/planet_types/meat.dm index d2043b862b9..dbda6ece5ac 100644 --- a/code/modules/overmap/exoplanets/planet_types/meat.dm +++ b/code/modules/overmap/exoplanets/planet_types/meat.dm @@ -19,7 +19,7 @@ spawn_weight = 10 // meat /obj/effect/overmap/visitable/sector/exoplanet/meat/generate_map() - var/obj/abstract/level_data/level_data = zlevels[1] + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] level_data.ambient_light_level = rand(1,7)/10 ..() diff --git a/code/modules/overmap/exoplanets/planet_types/shrouded.dm b/code/modules/overmap/exoplanets/planet_types/shrouded.dm index 2e5bb86845d..0d722680658 100644 --- a/code/modules/overmap/exoplanets/planet_types/shrouded.dm +++ b/code/modules/overmap/exoplanets/planet_types/shrouded.dm @@ -20,7 +20,7 @@ // TODO check if ambient lighting handles negatives /obj/effect/overmap/visitable/sector/exoplanet/meat/generate_map() - var/obj/abstract/level_data/level_data = zlevels[1] + var/datum/level_data/level_data = SSmapping.levels_by_z[map_z[1]] level_data.ambient_light_level = -0.15 ..() diff --git a/code/modules/overmap/exoplanets/random_map.dm b/code/modules/overmap/exoplanets/random_map.dm index d95a3c36c78..64fa3ada0e5 100644 --- a/code/modules/overmap/exoplanets/random_map.dm +++ b/code/modules/overmap/exoplanets/random_map.dm @@ -37,7 +37,6 @@ plantcolors = _plant_colors ..() - SSmapping.base_turf_by_z[tz] = land_type /datum/random_map/noise/exoplanet/get_map_char(var/value) if(water_type && noise2value(value) < water_level) diff --git a/code/modules/overmap/ships/landable.dm b/code/modules/overmap/ships/landable.dm index d0e2689fa6d..ae526becd47 100644 --- a/code/modules/overmap/ships/landable.dm +++ b/code/modules/overmap/ships/landable.dm @@ -9,7 +9,7 @@ var/use_mapped_z_levels = FALSE // If true, it will use the z level block on which it's mapped as the "Open Space" block; if false it creates a new block for that. // If you use this, use /obj/effect/shuttle_landmark/ship as the landmark (set the landmark tag to match on the shuttle; no other setup needed) var/status = SHIP_STATUS_LANDED - var/level_type = /obj/abstract/level_data/space + var/level_type = /datum/level_data/space icon_state = "shuttle" moving_state = "shuttle_moving" diff --git a/code/modules/power/geothermal/_geothermal.dm b/code/modules/power/geothermal/_geothermal.dm index f6db7a6e433..9cad5e8ccd0 100644 --- a/code/modules/power/geothermal/_geothermal.dm +++ b/code/modules/power/geothermal/_geothermal.dm @@ -1,24 +1,86 @@ var/global/const/GEOTHERMAL_EFFICIENCY_MOD = 0.2 var/global/const/GEOTHERMAL_PRESSURE_LOSS = 0.3 -var/global/const/GEOTHERMAL_PRESSURE_CONSUMED_PER_TICK = 0.5 -var/global/const/GEOTHERMAL_PRESSURE_TO_POWER = 100 -var/global/const/MAX_GEOTHERMAL_PRESSURE = 2000 +var/global/const/GEOTHERMAL_PRESSURE_CONSUMED_PER_TICK = 0.05 +var/global/const/GEOTHERMAL_PRESSURE_TO_POWER = 800 +var/global/const/MAX_GEOTHERMAL_PRESSURE = 12000 +////////////////////////////////////////////////////////////////////// +// Geyser Steam Particle Emitter +////////////////////////////////////////////////////////////////////// + +///Particle emitter that emits a ~64 pixels by ~192 pixels high column of steam while active. +/particles/geyser_steam + icon_state = "smallsmoke" + icon = 'icons/effects/effects.dmi' + width = WORLD_ICON_SIZE * 2 //Particles expand a bit as they climb, so need a bit of space on the width + height = WORLD_ICON_SIZE * 6 //Needs to be really tall, because particles stop being drawn outside of the canvas. + count = 64 + spawning = 5 + lifespan = generator("num", 1 SECOND, 2.5 SECONDS, LINEAR_RAND) + fade = 3 SECONDS + fadein = 0.25 SECONDS + grow = 0.1 + velocity = generator("vector", list(0, 0), list(0, 0.2)) + position = generator("circle", -6, 6, NORMAL_RAND) + gravity = list(0, 0.40) + scale = generator("vector", list(0.3, 0.3), list(1,1), NORMAL_RAND) + rotation = generator("num", -45, 45) + spin = generator("num", -20, 20) + +////////////////////////////////////////////////////////////////////// +// Geyser Object +////////////////////////////////////////////////////////////////////// + +///A prop that periodically emit steam spouts and can have a geothermal generator placed on top to generate power. /obj/effect/geyser - name = "geothermal vent" - desc = "A crack in the ocean floor that occasionally vents gouts of superheated water and steam." - icon = 'icons/effects/geyser.dmi' + name = "geothermal vent" + desc = "A vent leading to an underground geothermally heated reservoir, which periodically spews superheated liquid." + icon = 'icons/effects/geyser.dmi' icon_state = "geyser" - anchored = TRUE - layer = TURF_LAYER + 0.01 + anchored = TRUE + layer = TURF_LAYER + 0.01 + level = 1 //Goes under floor/plating + ///The particle emitter that will generate the steam column effect for this geyser + var/particles/geyser_steam/steamfx -/obj/effect/geyser/Initialize() +/obj/effect/geyser/Initialize(ml) . = ..() if(prob(50)) var/matrix/M = matrix() M.Scale(-1, 1) transform = M set_extension(src, /datum/extension/geothermal_vent) + steamfx = new //Prepare our FX + +///Async proc that enables the particle emitter for the steam column for a few seconds +/obj/effect/geyser/proc/do_spout() + set waitfor = FALSE + particles = steamfx + particles.spawning = initial(particles.spawning) + sleep(6 SECONDS) + particles.spawning = 0 + +/obj/effect/geyser/explosion_act(severity) + . = ..() + if(!QDELETED(src) && prob(100 - (25 * severity))) + physically_destroyed() + +/obj/effect/geyser/hide(hide) + var/datum/extension/geothermal_vent/E = get_extension(src, /datum/extension/geothermal_vent) + if(istype(E)) + E.set_obstructed(hide) + . = ..() + update_icon() + +////////////////////////////////////////////////////////////////////// +// Underwater Geyser Variant +////////////////////////////////////////////////////////////////////// + +/obj/effect/geyser/underwater + desc = "A crack in the ocean floor that occasionally vents gouts of superheated water and steam." + +/obj/effect/geyser/underwater/Initialize(ml) + . = ..() for(var/turf/exterior/seafloor/T in RANGE_TURFS(loc, 5)) var/dist = get_dist(loc, T)-1 if(prob(100 - (dist * 20))) @@ -26,43 +88,125 @@ var/global/const/MAX_GEOTHERMAL_PRESSURE = 2000 if(prob(50 - (dist * 10))) new /obj/random/seaweed(T) -/obj/effect/geyser/explosion_act(severity) - . = ..() - if(!QDELETED(src) && prob(100 - (25 * severity))) - physically_destroyed() +/obj/effect/geyser/underwater/do_spout() + set waitfor = FALSE + var/turf/T = get_turf(src) + T.show_bubbles() +////////////////////////////////////////////////////////////////////// +// Geothermal Generator +////////////////////////////////////////////////////////////////////// + +///A power generator that can create power from being placed on top of a geyser. /obj/machinery/geothermal - icon = 'icons/obj/machines/power/geothermal.dmi' - icon_state = "geothermal-base" - var/tmp/neighbors = 0 - var/tmp/current_pressure = 0 - var/efficiency = 0.5 + name = "geothermal generator" + icon = 'icons/obj/machines/power/geothermal.dmi' + icon_state = "geothermal-base" + density = TRUE + anchored = TRUE + waterproof = TRUE + interact_offline = TRUE + stat_immune = NOSCREEN | NOINPUT | NOPOWER + core_skill = SKILL_ENGINES + required_interaction_dexterity = DEXTERITY_SIMPLE_MACHINES + construct_state = /decl/machine_construction/default/panel_closed + uncreated_component_parts = list( + /obj/item/stock_parts/power/terminal, + ) + stock_part_presets = list( + /decl/stock_part_preset/terminal_setup/offset_dir, + ) + var/tmp/neighbors = 0 + var/tmp/current_pressure = 0 + var/tmp/efficiency = 0.5 + var/tmp/last_generated = 0 + var/tmp/datum/extension/geothermal_vent/vent + var/tmp/obj/item/stock_parts/power/terminal/connector + var/tmp/image/glow + var/tmp/list/neighbor_connectors + var/tmp/list/neighbor_connectors_glow + +//#TODO: Maybe should cache neighbors and put listeners on them? + +/obj/machinery/geothermal/Initialize(mapload, d, populate_parts = TRUE) + . = ..() + if(get_turf(loc)) + refresh_neighbors() + propagate_refresh_neighbors() + STOP_PROCESSING_MACHINE(src, MACHINERY_PROCESS_SELF) + return INITIALIZE_HINT_LATELOAD + +/obj/machinery/geothermal/LateInitialize() + . = ..() + setup_vent() + +/obj/machinery/geothermal/Destroy() + var/atom/last_loc = loc + unset_vent() + . = ..() + if(istype(last_loc)) + propagate_refresh_neighbors(last_loc) + +///Tell all neighbors of the center atom to call update neighbors +/obj/machinery/geothermal/proc/propagate_refresh_neighbors(var/atom/center = src) + for(var/adir in global.alldirs) + var/obj/machinery/geothermal/G = locate(/obj/machinery/geothermal) in get_step(center, adir) + if(G?.anchored) + G.refresh_neighbors() + +/obj/machinery/geothermal/examine(mob/user, distance) + . = ..() + if(distance < 2) + to_chat(user, SPAN_INFO("Pressure: [current_pressure]kPa")) + to_chat(user, SPAN_INFO("Output: [last_generated]W")) + +///Attempts to connect to any existing geothermal vents in our turf. +/obj/machinery/geothermal/proc/setup_vent() + var/turf/T = get_turf(src) + for(var/obj/O in T) + var/datum/extension/geothermal_vent/GV = get_extension(O, /datum/extension/geothermal_vent) + if(!GV || QDELETED(GV)) + continue + vent = GV + vent.set_my_generator(src) + return TRUE + +///Disconnect from any geothermal vents we may be connected to +/obj/machinery/geothermal/proc/unset_vent() + if(QDELETED(vent)) + return + vent.set_my_generator(null) + vent = null /obj/machinery/geothermal/RefreshParts() ..() efficiency = clamp(total_component_rating_of_type(/obj/item/stock_parts/capacitor) * GEOTHERMAL_EFFICIENCY_MOD, GEOTHERMAL_EFFICIENCY_MOD, 1) + connector = get_component_of_type(/obj/item/stock_parts/power/terminal) /obj/machinery/geothermal/proc/add_pressure(var/pressure) current_pressure = clamp(current_pressure + pressure, 0, MAX_GEOTHERMAL_PRESSURE) - if(!is_processing) - START_PROCESSING_MACHINE(src, MACHINERY_PROCESS_SELF) + var/leftover = round(pressure - current_pressure) + if(leftover > 0) + addtimer(CALLBACK(src, .proc/propagate_pressure, leftover), 5) + update_icon() + START_PROCESSING_MACHINE(src, MACHINERY_PROCESS_SELF) /obj/machinery/geothermal/Process() - if(anchored && !(stat & BROKEN) && loc) + if(loc && anchored && !(stat & BROKEN)) var/consumed_pressure = current_pressure * GEOTHERMAL_PRESSURE_CONSUMED_PER_TICK current_pressure -= consumed_pressure var/remaining_pressure = consumed_pressure - consumed_pressure = round(consumed_pressure * efficiency) + consumed_pressure = round(consumed_pressure * efficiency, 0.01) remaining_pressure -= consumed_pressure - var/generated_power = round(consumed_pressure * GEOTHERMAL_PRESSURE_TO_POWER) - if(generated_power) - generate_power(generated_power) + last_generated = round(consumed_pressure * GEOTHERMAL_PRESSURE_TO_POWER, 0.01) + if(last_generated) + generate_power(last_generated) remaining_pressure = round(remaining_pressure * GEOTHERMAL_PRESSURE_LOSS) if(remaining_pressure) addtimer(CALLBACK(src, .proc/propagate_pressure, remaining_pressure), 5) update_icon() - if(current_pressure <= 10) + if(current_pressure <= 1) return PROCESS_KILL /obj/machinery/geothermal/proc/propagate_pressure(var/remaining_pressure) @@ -86,46 +230,41 @@ var/global/const/MAX_GEOTHERMAL_PRESSURE = 2000 if(last_neighbors != neighbors) update_icon() -/obj/machinery/geothermal/Initialize() - . = ..() - refresh_neighbors() - for(var/turf/T as anything in RANGE_TURFS(loc, 1)) - for(var/obj/machinery/geothermal/neighbor in T) - neighbor.refresh_neighbors() - STOP_PROCESSING_MACHINE(src, MACHINERY_PROCESS_SELF) - -/obj/machinery/geothermal/Destroy() - var/atom/last_loc = loc - . = ..() - if(istype(last_loc)) - for(var/turf/T as anything in RANGE_TURFS(last_loc, 1)) - for(var/obj/machinery/geothermal/neighbor in T) - neighbor.refresh_neighbors() - /obj/machinery/geothermal/on_update_icon() - - . = ..() - cut_overlays() + var/output_ratio = current_pressure / 3000 + var/glow_alpha = clamp(round((current_pressure / MAX_GEOTHERMAL_PRESSURE) * 255), 10, 255) + if(!glow) + glow = emissive_overlay(icon, "geothermal-glow") + if(!length(neighbor_connectors)) + for(var/neighbordir in global.cardinal) + LAZYSET(neighbor_connectors, "[neighbordir]", image(icon, "geothermal-connector", dir = neighbordir)) + LAZYSET(neighbor_connectors_glow, "[neighbordir]", image(icon, "geothermal-connector-glow", dir = neighbordir)) if(neighbors) for(var/neighbordir in global.cardinal) if(neighbors & neighbordir) - add_overlay(image(icon, "geothermal-connector", dir = neighbordir)) - - if(current_pressure > 0) - set_light(2, 0.5, COLOR_RED) - add_overlay(image(icon, "geothermal-turbine-[clamp(round(current_pressure / 200), 0, 3)]")) - var/glow_alpha = clamp(round((current_pressure / 500) * 255), 20, 255) - var/image/I = emissive_overlay(icon, "geothermal-glow") - I.alpha = glow_alpha - add_overlay(I) - if(neighbors) - for(var/neighbordir in global.cardinal) - if(neighbors & neighbordir) - // emissive_overlay is not setting dir and setting plane/layer directly also causes dir to break :( - I = image(icon, "geothermal-connector-glow", dir = neighbordir) - I.alpha = glow_alpha - add_overlay(I) - else + add_overlay(neighbor_connectors["[neighbordir]"]) + // emissive_overlay is not setting dir and setting plane/layer directly also causes dir to break :( + var/image/neighborglow = neighbor_connectors_glow["[neighbordir]"] + neighborglow.alpha = glow_alpha + add_overlay(neighborglow) + + if(round(current_pressure, 0.1) <= 0) set_light(0) + return + + set_light(1, clamp(output_ratio, 0.2, 1.0), COLOR_RED) + add_overlay("geothermal-turbine-[clamp(round(output_ratio * 3), 0, 3)]") + glow.alpha = glow_alpha + add_overlay(glow) + +/obj/machinery/geothermal/dismantle() + . = ..() + unset_vent() + +/obj/machinery/geothermal/get_powernet() + return connector?.terminal?.get_powernet() + +/obj/machinery/geothermal/drain_power() + return -1 \ No newline at end of file diff --git a/code/modules/power/geothermal/geothermal_circuit.dm b/code/modules/power/geothermal/geothermal_circuit.dm index 2b34cbf2224..07d451d68fa 100644 --- a/code/modules/power/geothermal/geothermal_circuit.dm +++ b/code/modules/power/geothermal/geothermal_circuit.dm @@ -1,5 +1,5 @@ /obj/item/stock_parts/circuitboard/geothermal - name = "circuitboard (geothermal turbine)" + name = "circuitboard (geothermal generator)" build_path = /obj/machinery/geothermal board_type = "machine" origin_tech = "{'magnets':3,'powerstorage':3}" @@ -8,3 +8,4 @@ /obj/item/stock_parts/manipulator = 2, /obj/item/stack/cable_coil = 5 ) + additional_spawn_components = null diff --git a/code/modules/power/geothermal/geothermal_extension.dm b/code/modules/power/geothermal/geothermal_extension.dm index 3eef52c7075..0d734d38116 100644 --- a/code/modules/power/geothermal/geothermal_extension.dm +++ b/code/modules/power/geothermal/geothermal_extension.dm @@ -1,34 +1,45 @@ /datum/extension/geothermal_vent base_type = /datum/extension/geothermal_vent - expected_type = /atom + expected_type = /obj/effect/geyser flags = EXTENSION_FLAG_IMMEDIATE var/pressure_min = 1000 var/pressure_max = 2000 - var/steam_min = 30 SECONDS - var/steam_max = 1 MINUTE + var/steam_min = 20 SECONDS + var/steam_max = 60 SECONDS var/tmp/next_steam = 0 - var/datum/effect/effect/system/steam_spread/steam + var/tmp/obstructed = FALSE + var/obj/machinery/geothermal/my_machine + var/obj/effect/geyser/my_vent -/datum/extension/geothermal_vent/New() +/datum/extension/geothermal_vent/New(datum/holder) ..() START_PROCESSING(SSprocessing, src) + my_vent = holder /datum/extension/geothermal_vent/Destroy() + my_machine = null + my_vent = null . = ..() STOP_PROCESSING(SSprocessing, src) - + +/datum/extension/geothermal_vent/proc/set_my_generator(var/obj/machinery/geothermal/G) + my_machine = G + +/datum/extension/geothermal_vent/proc/set_obstructed(var/state) + obstructed = state + if(obstructed) + STOP_PROCESSING(SSprocessing, src) + else + START_PROCESSING(SSprocessing, src) + /datum/extension/geothermal_vent/Process() - ..() + if(obstructed && !my_machine) //If we have a machine, don't care about obstruction, or it might cause problems + return PROCESS_KILL + if(world.time >= next_steam) next_steam = world.time + rand(steam_min, steam_max) - var/turf/T = get_turf(holder) - if(!istype(T)) - return - var/obj/machinery/geothermal/geothermal = locate() in T - if(geothermal?.anchored) - geothermal.add_pressure(rand(pressure_min, pressure_max)) - return - if(!steam) - steam = new - steam.set_up(5, 0, holder) - steam.start() + //If we cached something, make it work + if(my_machine?.anchored) + my_machine.add_pressure(rand(pressure_min, pressure_max)) + else + my_vent.do_spout() //Let the holder decide what to do when spewing steam diff --git a/code/modules/projectiles/ammunition/boxes.dm b/code/modules/projectiles/ammunition/boxes.dm index 090bd283b74..9eee66308bf 100644 --- a/code/modules/projectiles/ammunition/boxes.dm +++ b/code/modules/projectiles/ammunition/boxes.dm @@ -148,6 +148,10 @@ labels = list("flash") ammo_type = /obj/item/ammo_casing/pistol/flash +/obj/item/ammo_magazine/pistol/emp + labels = list("haywire") + ammo_type = /obj/item/ammo_casing/pistol/emp + /obj/item/ammo_magazine/pistol/small icon_state = "holdout" material = /decl/material/solid/metal/steel @@ -243,6 +247,14 @@ max_ammo = 7 multiple_sprites = 1 +/obj/item/ammo_magazine/speedloader/rubber + labels = list("rubber") + ammo_type = /obj/item/ammo_casing/pistol/magnum/rubber + +/obj/item/ammo_magazine/speedloader/practice + labels = list("practice") + ammo_type = /obj/item/ammo_casing/pistol/magnum/practice + /obj/item/ammo_magazine/speedloader/laser_revolver caliber = CALIBER_PISTOL_LASBULB ammo_type = /obj/item/ammo_casing/lasbulb diff --git a/code/modules/projectiles/ammunition/bullets.dm b/code/modules/projectiles/ammunition/bullets.dm index 8f727a8132a..54f6374aecf 100644 --- a/code/modules/projectiles/ammunition/bullets.dm +++ b/code/modules/projectiles/ammunition/bullets.dm @@ -63,6 +63,28 @@ projectile_type = /obj/item/projectile/bullet/pistol/strong icon = 'icons/obj/ammo/casings/magnum.dmi' +/obj/item/ammo_casing/pistol/magnum/rubber + desc = "A rubber bullet casing." + projectile_type = /obj/item/projectile/bullet/pistol/rubber/strong + bullet_color = COLOR_GRAY40 + +/obj/item/ammo_casing/pistol/magnum/practice + desc = "A practice bullet casing." + projectile_type = /obj/item/projectile/bullet/pistol/practice + bullet_color = COLOR_OFF_WHITE + marking_color = COLOR_SUN + +/obj/item/ammo_casing/pistol/magnum/stun + name = "stun round" + desc = "An energy stun cartridge." + icon_state = "stunshell" + spent_icon = "stunshell-spent" + projectile_type = /obj/item/projectile/energy/electrode/stunshot + leaves_residue = 0 + material = /decl/material/solid/metal/steel + matter = list(/decl/material/solid/glass = MATTER_AMOUNT_REINFORCEMENT) + origin_tech = "{'combat':3,'materials':3}" + /obj/item/ammo_casing/shotgun name = "shotgun slug" desc = "A shotgun slug." diff --git a/code/modules/projectiles/guns/projectile/pistol.dm b/code/modules/projectiles/guns/projectile/pistol.dm index 6122670a859..71f69f05964 100644 --- a/code/modules/projectiles/guns/projectile/pistol.dm +++ b/code/modules/projectiles/guns/projectile/pistol.dm @@ -12,6 +12,9 @@ /obj/item/gun/projectile/pistol/rubber magazine_type = /obj/item/ammo_magazine/pistol/rubber +/obj/item/gun/projectile/pistol/emp + magazine_type = /obj/item/ammo_magazine/pistol/emp + /obj/item/gun/projectile/pistol/update_base_icon() var/base_state = get_world_inventory_state() if(!length(ammo_magazine?.stored_ammo) && check_state_in_icon("[base_state]-e", icon)) diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index 71ed2ce36a3..2fdf3b7c45e 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -41,6 +41,9 @@ chamber_offset = 0 return ..() +/obj/item/gun/projectile/revolver/stun + ammo_type = /obj/item/ammo_casing/pistol/magnum/stun + /obj/item/gun/projectile/revolver/capgun name = "cap gun" desc = "Looks almost like the real thing! Ages 8 and up." diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 8b00d325258..c431df0db47 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -91,6 +91,10 @@ agony = 30 embed = 0 +/obj/item/projectile/bullet/pistol/rubber/strong + damage = 8 + agony = 38 + /obj/item/projectile/bullet/pistol/rubber/holdout agony = 20 diff --git a/code/modules/shuttles/docking_beacon.dm b/code/modules/shuttles/docking_beacon.dm index 37dcaa79577..abaac314379 100644 --- a/code/modules/shuttles/docking_beacon.dm +++ b/code/modules/shuttles/docking_beacon.dm @@ -312,13 +312,13 @@ break area_turf = get_step(area_turf, dir) - // Otherwise, use the planetary or world area. + // Otherwise, use the level or world area. if(!base_area) - var/obj/effect/overmap/visitable/sector/exoplanet/planet = global.overmap_sectors[num2text(z)] - if(istype(planet)) - base_area = ispath(planet.planetary_area) ? planet.planetary_area : planet.planetary_area.type + var/datum/level_data/LD = SSmapping.levels_by_z[z] + if(istype(LD)) + base_area = LD.get_base_area_instance() else - base_area = world.area + base_area = locate(world.area) var/turf/center_turf switch(dir) diff --git a/code/unit_tests/atmospherics_tests.dm b/code/unit_tests/atmospherics_tests.dm index 4dd84f63b92..20ab46c5c9a 100644 --- a/code/unit_tests/atmospherics_tests.dm +++ b/code/unit_tests/atmospherics_tests.dm @@ -381,7 +381,7 @@ var/fail = FALSE // make a place to test - SSmapping.increment_world_z_size(/obj/abstract/level_data/unit_test) + SSmapping.increment_world_z_size(/datum/level_data/unit_test) for(var/turf/T in block(locate(1, 1, world.maxz), locate(3, 3, world.maxz))) T.ChangeTurf(/turf/simulated/floor) var/turf/T = locate(2, 2, world.maxz) diff --git a/code/unit_tests/del_the_world.dm b/code/unit_tests/del_the_world.dm index 6beea4343c7..bbe1cc41271 100644 --- a/code/unit_tests/del_the_world.dm +++ b/code/unit_tests/del_the_world.dm @@ -26,6 +26,8 @@ // Not valid when spawned manually. /obj/effect/overmap, /obj/effect/shuttle_landmark, + // Docking controllers can only exist once with a given id_tag in the world. And some subtypes are defined with an id_tag + /obj/machinery/embedded_controller/radio/simple_docking_controller, ) + list( // Exclude only this type, since it's not meant to be spawned but its subtypes are. // TODO: Consider whether this warrants abstract_type? diff --git a/code/unit_tests/zlevel_tests.dm b/code/unit_tests/zlevel_tests.dm index 0b33829fc27..5c6829802b0 100644 --- a/code/unit_tests/zlevel_tests.dm +++ b/code/unit_tests/zlevel_tests.dm @@ -4,7 +4,7 @@ /datum/unit_test/all_zlevels_will_have_a_non_filler_data_object/start_test() var/list/failures = list() for(var/z = 1 to world.maxz) - var/obj/abstract/level_data/level_data = SSmapping.levels_by_z[z] + var/datum/level_data/level_data = SSmapping.levels_by_z[z] if(!level_data) failures += "z[z] has no level data object" if(length(failures)) diff --git a/code/unit_tests/~unit_test_subsystems.dm b/code/unit_tests/~unit_test_subsystems.dm index 57d1f69a19e..e199cb31454 100644 --- a/code/unit_tests/~unit_test_subsystems.dm +++ b/code/unit_tests/~unit_test_subsystems.dm @@ -44,6 +44,9 @@ SUBSYSTEM_DEF(unit_tests) if(MAP_TEMPLATE_CATEGORY_AWAYSITE in map_template.template_categories) report_progress("Skipping template '[map_template]' ([map_template.type]): Is an Away Site") continue + if(MAP_TEMPLATE_CATEGORY_MAIN_SITE in map_template.template_categories) + report_progress("Skipping template '[map_template]' ([map_template.type]): Is a main site template.") + continue load_template(map_template) if(map_template.template_flags & TEMPLATE_FLAG_TEST_DUPLICATES) load_template(map_template) @@ -52,7 +55,7 @@ SUBSYSTEM_DEF(unit_tests) /datum/controller/subsystem/unit_tests/proc/load_template(datum/map_template/map_template) // Suggestion: Do smart things here to squeeze as many templates as possible into the same Z-level if(map_template.tallness == 1) - SSmapping.increment_world_z_size(/obj/abstract/level_data/unit_test) + SSmapping.increment_world_z_size(/datum/level_data/unit_test) var/corner = locate(world.maxx/2, world.maxy/2, world.maxz) log_unit_test("Loading template '[map_template]' ([map_template.type]) at [log_info_line(corner)]") map_template.load(corner) diff --git a/html/changelog.html b/html/changelog.html index 90c8145dcd1..4aa45b15d62 100644 --- a/html/changelog.html +++ b/html/changelog.html @@ -88,6 +88,42 @@

18 January 2023

NataKilar updated: