diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index dcfad59c629..efbbf17e9ac 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -309,6 +309,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_RECENTLY_BLOCKED_MAGIC "recently_blocked_magic" /// The user can do things like use magic staffs without penalty #define TRAIT_MAGICALLY_GIFTED "magically_gifted" +/// This object innately spawns with fantasy variables already applied (the magical component is given to it on initialize), and thus we never want to give it the component again. +#define TRAIT_INNATELY_FANTASTICAL_ITEM "innately_fantastical_item" #define TRAIT_DEPRESSION "depression" #define TRAIT_BLOOD_DEFICIENCY "blood_deficiency" #define TRAIT_JOLLY "jolly" diff --git a/code/datums/components/fantasy/_fantasy.dm b/code/datums/components/fantasy/_fantasy.dm index 31f969e6193..98796d52bc1 100644 --- a/code/datums/components/fantasy/_fantasy.dm +++ b/code/datums/components/fantasy/_fantasy.dm @@ -14,7 +14,7 @@ ///affixes expects an initialized list /datum/component/fantasy/Initialize(quality, list/affixes = list(), canFail=FALSE, announce=FALSE) - if(!isitem(parent)) + if(!isitem(parent) || HAS_TRAIT(parent, TRAIT_INNATELY_FANTASTICAL_ITEM)) return COMPONENT_INCOMPATIBLE src.quality = quality diff --git a/code/datums/components/slippery.dm b/code/datums/components/slippery.dm index 7288ae0e275..d0add3b77eb 100644 --- a/code/datums/components/slippery.dm +++ b/code/datums/components/slippery.dm @@ -73,6 +73,7 @@ knockdown_time = source.reset_fantasy_variable("knockdown_time", knockdown_time) paralyze_time = source.reset_fantasy_variable("paralyze_time", paralyze_time) var/previous_lube_flags = LAZYACCESS(source.fantasy_modifications, "lube_flags") + LAZYREMOVE(source.fantasy_modifications, "lube_flags") if(!isnull(previous_lube_flags)) lube_flags = previous_lube_flags diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index 44061746eaf..fcef1b5d3d8 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -332,10 +332,12 @@ Unless you know what you're doing, only use the first three numbers. They're in . = ..() if(isitem(source)) source.AddComponent(/datum/component/fantasy) + ADD_TRAIT(source, TRAIT_INNATELY_FANTASTICAL_ITEM, REF(src)) // DO THIS LAST OR WE WILL NEVER GET OUR BONUSES!!! /datum/material/mythril/on_removed_obj(atom/source, amount, material_flags) . = ..() if(isitem(source)) + REMOVE_TRAIT(source, TRAIT_INNATELY_FANTASTICAL_ITEM, REF(src)) // DO THIS FIRST OR WE WILL NEVER GET OUR BONUSES DELETED!!! qdel(source.GetComponent(/datum/component/fantasy)) /datum/material/mythril/on_accidental_mat_consumption(mob/living/carbon/victim, obj/item/source_item) diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 0ca75c35850..4cc3a963b5f 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -224,7 +224,7 @@ // SKYRAT EDIT ADDITION END /// A lazylist used for applying fantasy values, contains the actual modification applied to a variable. - var/list/fantasy_modifications + var/list/fantasy_modifications = null /obj/item/Initialize(mapload) if(attack_verb_continuous) @@ -1658,8 +1658,13 @@ /// Modifies the fantasy variable /obj/item/proc/modify_fantasy_variable(variable_key, value, bonus, minimum = 0) - if(LAZYACCESS(fantasy_modifications, variable_key) != null) + var/result = LAZYACCESS(fantasy_modifications, variable_key) + if(!isnull(result)) + if(HAS_TRAIT(src, TRAIT_INNATELY_FANTASTICAL_ITEM)) + return result // we are immune to your foul magicks you inferior wizard, we keep our bonuses + stack_trace("modify_fantasy_variable was called twice for the same key '[variable_key]' on type '[type]' before reset_fantasy_variable could be called!") + var/intended_target = value + bonus value = max(minimum, intended_target) @@ -1671,9 +1676,14 @@ /// Returns the original fantasy variable value /obj/item/proc/reset_fantasy_variable(variable_key, current_value) var/modification = LAZYACCESS(fantasy_modifications, variable_key) + + if(isnum(modification) && HAS_TRAIT(src, TRAIT_INNATELY_FANTASTICAL_ITEM)) + return modification // we are immune to your foul magicks you inferior wizard, we keep our bonuses the way they are + LAZYREMOVE(fantasy_modifications, variable_key) - if(!modification) + if(isnull(modification)) return current_value + return current_value - modification /obj/item/proc/apply_fantasy_bonuses(bonus) diff --git a/code/game/objects/items/storage/storage.dm b/code/game/objects/items/storage/storage.dm index 8063778f413..501d3d2624b 100644 --- a/code/game/objects/items/storage/storage.dm +++ b/code/game/objects/items/storage/storage.dm @@ -12,6 +12,9 @@ /obj/item/storage/apply_fantasy_bonuses(bonus) . = ..() + if(isnull(atom_storage)) // some abstract types of storage (yes i know) don't get a datum + return + atom_storage.max_slots = modify_fantasy_variable("max_slots", atom_storage.max_slots, round(bonus/2)) atom_storage.max_total_storage = modify_fantasy_variable("max_total_storage", atom_storage.max_total_storage, round(bonus/2)) LAZYSET(fantasy_modifications, "max_specific_storage", atom_storage.max_specific_storage) @@ -25,9 +28,13 @@ atom_storage.max_specific_storage = WEIGHT_CLASS_TINY /obj/item/storage/remove_fantasy_bonuses(bonus) + if(isnull(atom_storage)) // some abstract types of storage (yes i know) don't get a datum + return ..() + atom_storage.max_slots = reset_fantasy_variable("max_slots", atom_storage.max_slots) atom_storage.max_total_storage = reset_fantasy_variable("max_total_storage", atom_storage.max_total_storage) var/previous_max_storage = LAZYACCESS(fantasy_modifications, "max_specific_storage") + LAZYREMOVE(fantasy_modifications, "max_specific_storage") if(previous_max_storage) atom_storage.max_specific_storage = previous_max_storage return ..() diff --git a/code/modules/projectiles/guns/energy/beam_rifle.dm b/code/modules/projectiles/guns/energy/beam_rifle.dm index 702da95f701..68479abbf47 100644 --- a/code/modules/projectiles/guns/energy/beam_rifle.dm +++ b/code/modules/projectiles/guns/energy/beam_rifle.dm @@ -78,7 +78,7 @@ . = ..() delay = modify_fantasy_variable("delay", delay, -bonus * 2) aiming_time = modify_fantasy_variable("aiming_time", aiming_time, -bonus * 2) - recoil = modify_fantasy_variable("aiming_time", aiming_time, round(-bonus / 2)) + recoil = modify_fantasy_variable("recoil", recoil, round(-bonus / 2)) /obj/item/gun/energy/beam_rifle/remove_fantasy_bonuses(bonus) delay = reset_fantasy_variable("delay", delay) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 1a7de246d5a..1ec215745cc 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -179,6 +179,7 @@ #include "missing_icons.dm" #include "mob_faction.dm" #include "mob_spawn.dm" +#include "modify_fantasy_variable.dm" #include "modsuit.dm" #include "modular_map_loader.dm" #include "monkey_business.dm" diff --git a/code/modules/unit_tests/create_and_destroy.dm b/code/modules/unit_tests/create_and_destroy.dm index b0979d78aee..e0e763ebb85 100644 --- a/code/modules/unit_tests/create_and_destroy.dm +++ b/code/modules/unit_tests/create_and_destroy.dm @@ -7,121 +7,6 @@ GLOBAL_VAR_INIT(running_create_and_destroy, FALSE) /datum/unit_test/create_and_destroy/Run() //We'll spawn everything here var/turf/spawn_at = run_loc_floor_bottom_left - var/list/ignore = list( - //Never meant to be created, errors out the ass for mobcode reasons - /mob/living/carbon, - //Nother template type, doesn't like being created with no seed - /obj/item/food/grown, - //And another - /obj/item/slimecross/recurring, - //This should be obvious - /obj/machinery/doomsday_device, - //Yet more templates - /obj/machinery/restaurant_portal, - //Template type - /obj/effect/mob_spawn, - //Template type - /obj/structure/holosign/robot_seat, - //Singleton - /mob/dview, - //Template type - /obj/item/bodypart, - //This is meant to fail extremely loud every single time it occurs in any environment in any context, and it falsely alarms when this unit test iterates it. Let's not spawn it in. - /obj/merge_conflict_marker, - //briefcase launchpads erroring - /obj/machinery/launchpad/briefcase, - //Both are abstract types meant to scream bloody murder if spawned in raw - /obj/item/organ/external, - /obj/item/organ/external/wings, - ) - //Say it with me now, type template - ignore += typesof(/obj/effect/mapping_helpers) - //This turf existing is an error in and of itself - ignore += typesof(/turf/baseturf_skipover) - ignore += typesof(/turf/baseturf_bottom) - //This demands a borg, so we'll let if off easy - ignore += typesof(/obj/item/modular_computer/pda/silicon) - //This one demands a computer, ditto - ignore += typesof(/obj/item/modular_computer/processor) - //Very finiky, blacklisting to make things easier - ignore += typesof(/obj/item/poster/wanted) - //This expects a seed, we can't pass it - ignore += typesof(/obj/item/food/grown) - //Needs clients / mobs to observe it to exist. Also includes hallucinations. - ignore += typesof(/obj/effect/client_image_holder) - //Same to above. Needs a client / mob / hallucination to observe it to exist. - ignore += typesof(/obj/projectile/hallucination) - ignore += typesof(/obj/item/hallucinated) - //We don't have a pod - ignore += typesof(/obj/effect/pod_landingzone_effect) - ignore += typesof(/obj/effect/pod_landingzone) - //We have a baseturf limit of 10, adding more than 10 baseturf helpers will kill CI, so here's a future edge case to fix. - ignore += typesof(/obj/effect/baseturf_helper) - //No tauma to pass in - ignore += typesof(/mob/camera/imaginary_friend) - //No pod to gondola - ignore += typesof(/mob/living/simple_animal/pet/gondola/gondolapod) - //No heart to give - ignore += typesof(/obj/structure/ethereal_crystal) - //No linked console - ignore += typesof(/mob/camera/ai_eye/remote/base_construction) - //See above - ignore += typesof(/mob/camera/ai_eye/remote/shuttle_docker) - //Hangs a ref post invoke async, which we don't support. Could put a qdeleted check but it feels hacky - ignore += typesof(/obj/effect/anomaly/grav/high) - //See above - ignore += typesof(/obj/effect/timestop) - //Invoke async in init, skippppp - ignore += typesof(/mob/living/silicon/robot/model) - //This lad also sleeps - ignore += typesof(/obj/item/hilbertshotel) - //this boi spawns turf changing stuff, and it stacks and causes pain. Let's just not - ignore += typesof(/obj/effect/sliding_puzzle) - //Stacks baseturfs, can't be tested here - ignore += typesof(/obj/effect/temp_visual/lava_warning) - //Stacks baseturfs, can't be tested here - ignore += typesof(/obj/effect/landmark/ctf) - //Our system doesn't support it without warning spam from unregister calls on things that never registered - ignore += typesof(/obj/docking_port) - //Asks for a shuttle that may not exist, let's leave it alone - ignore += typesof(/obj/item/pinpointer/shuttle) - //This spawns beams as a part of init, which can sleep past an async proc. This hangs a ref, and fucks us. It's only a problem here because the beam sleeps with CHECK_TICK - ignore += typesof(/obj/structure/alien/resin/flower_bud) - //Needs a linked mecha - ignore += typesof(/obj/effect/skyfall_landingzone) - //Expects a mob to holderize, we have nothing to give - ignore += typesof(/obj/item/clothing/head/mob_holder) - //Needs cards passed into the initilazation args - ignore += typesof(/obj/item/toy/cards/cardhand) - - //SKYRAT EDIT ADDITION - OUR IGNORES DOWN HERE - //Not designed to be spawned without a turf. - ignore += typesof(/obj/effect/abstract/liquid_turf) - //Not designed to be spawned individually. - ignore += typesof(/obj/structure/mold) - //Unused - not supposed to be spawned without SSliquids - ignore += typesof(/turf/open/openspace/ocean) - //Baseturf editors can only go up to ten, stop this. - ignore += typesof(/obj/effect/baseturf_helper) - // It's the abstract base type, it shouldn't be spawned. - ignore += /obj/item/organ/external/genital - // These two are locked to one type only, and shouldn't be widely available, hence why they runtime otherwise. - // Can't be bothered adding more to them. - ignore += list(/obj/item/organ/external/neck_accessory, /obj/item/organ/external/head_accessory) - //SKYRAT EDIT END - //Needs cards passed into the initilazation args - ignore += typesof(/obj/item/toy/cards/cardhand) - //Needs a holodeck area linked to it which is not guarenteed to exist and technically is supposed to have a 1:1 relationship with computer anyway. - ignore += typesof(/obj/machinery/computer/holodeck) - //runtimes if not paired with a landmark - ignore += typesof(/obj/structure/industrial_lift) - // Runtimes if the associated machinery does not exist, but not the base type - ignore += subtypesof(/obj/machinery/airlock_controller) - // Always ought to have an associated escape menu. Any references it could possibly hold would need one regardless. - ignore += subtypesof(/atom/movable/screen/escape_menu) - // Can't spawn openspace above nothing, it'll get pissy at me - ignore += typesof(/turf/open/space/openspace) - ignore += typesof(/turf/open/openspace) var/list/cached_contents = spawn_at.contents.Copy() var/original_turf_type = spawn_at.type @@ -129,7 +14,7 @@ GLOBAL_VAR_INIT(running_create_and_destroy, FALSE) var/original_baseturf_count = length(original_baseturfs) GLOB.running_create_and_destroy = TRUE - for(var/type_path in typesof(/atom/movable, /turf) - ignore) //No areas please + for(var/type_path in typesof(/atom/movable, /turf) - uncreatables) //No areas please if(ispath(type_path, /turf)) spawn_at.ChangeTurf(type_path) //We change it back to prevent baseturfs stacking and hitting the limit diff --git a/code/modules/unit_tests/modify_fantasy_variable.dm b/code/modules/unit_tests/modify_fantasy_variable.dm index d78c1d1dac7..72dc776af32 100644 --- a/code/modules/unit_tests/modify_fantasy_variable.dm +++ b/code/modules/unit_tests/modify_fantasy_variable.dm @@ -1,21 +1,46 @@ // Unit test to make sure that there are no duplicate keys when modify_fantasy_variable is called when applying fantasy bonuses. // Also to make sure the fantasy_modifications list is null when fantasy bonuses are removed. -/datum/unit_test/modify_fantasy_variable/Run() +/datum/unit_test/modify_fantasy_variable + priority = TEST_LONGER - for(var/obj/item/path as anything in subtypesof(/obj/item)) +/datum/unit_test/modify_fantasy_variable/Run() + var/list/applicable_types = subtypesof(/obj/item) - uncreatables + + for(var/obj/item/path as anything in applicable_types) var/obj/item/object = allocate(path) + // objects will have fantasy bonuses inherent to their type (like butterdogs and the slippery component), so we need to take this into account + var/number_of_extant_bonuses = LAZYLEN(object.fantasy_modifications) + +#define TEST_SUCCESS LAZYLEN(object.fantasy_modifications) == number_of_extant_bonuses + // Try positive object.apply_fantasy_bonuses(bonus = 5) object.remove_fantasy_bonuses(bonus = 5) - TEST_ASSERT_NULL(object.fantasy_modifications) + TEST_ASSERT(TEST_SUCCESS, generate_failure_message(object)) + // Then negative object.apply_fantasy_bonuses(bonus = -5) object.remove_fantasy_bonuses(bonus = -5) - TEST_ASSERT_NULL(object.fantasy_modifications) + TEST_ASSERT(TEST_SUCCESS, generate_failure_message(object)) + // Now try the extremes of each object.apply_fantasy_bonuses(bonus = 500) object.remove_fantasy_bonuses(bonus = 500) - TEST_ASSERT_NULL(object.fantasy_modifications) + TEST_ASSERT(TEST_SUCCESS, generate_failure_message(object)) + object.apply_fantasy_bonuses(bonus = -500) object.remove_fantasy_bonuses(bonus = -500) - TEST_ASSERT_NULL(object.fantasy_modifications) + TEST_ASSERT(TEST_SUCCESS, generate_failure_message(object)) + +/// Returns a string that we use to describe the failure of the test. +/datum/unit_test/modify_fantasy_variable/proc/generate_failure_message(obj/item/failed_object) + var/list/cached_modifications = failed_object.fantasy_modifications + var/length_of_modifications = LAZYLEN(cached_modifications) + var/list/failure_messages = list("Error found when adding+removing fantasy bonuses for [failed_object.type].") + failure_messages += "The length of the fantasy_modifications list was [length_of_modifications]." + if(length_of_modifications) + failure_messages += "The fantasy_modifications list was [cached_modifications.Join(", ")]." + + return failure_messages.Join(" ") + +#undef TEST_SUCCESS diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index 3fef3d985f7..c552902775a 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -50,6 +50,9 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) /// Do not instantiate if type matches this var/abstract_type = /datum/unit_test + /// List of atoms that we don't want to ever initialize in an agnostic context, like for Create and Destroy. Stored on the base datum for usability in other relevant tests that need this data. + var/static/list/uncreatables = null + var/static/datum/space_level/reservation /proc/cmp_unit_test_priority(datum/unit_test/a, datum/unit_test/b) @@ -60,6 +63,9 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) var/datum/map_template/unit_tests/template = new reservation = template.load_new_z() + if (isnull(uncreatables)) + uncreatables = build_list_of_uncreatables() + allocated = new run_loc_floor_bottom_left = get_turf(locate(/obj/effect/landmark/unit_test_bottom_left) in GLOB.landmarks_list) run_loc_floor_top_right = get_turf(locate(/obj/effect/landmark/unit_test_top_right) in GLOB.landmarks_list) @@ -209,6 +215,129 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) qdel(test) +/// Builds (and returns) a list of atoms that we shouldn't initialize in generic testing, like Create and Destroy. +/// It is appreciated to add the reason why the atom shouldn't be initialized if you add it to this list. +/datum/unit_test/proc/build_list_of_uncreatables() + RETURN_TYPE(/list) + var/list/returnable_list = list() + // The following are just generic, singular types. + returnable_list = list( + //Never meant to be created, errors out the ass for mobcode reasons + /mob/living/carbon, + //And another + /obj/item/slimecross/recurring, + //This should be obvious + /obj/machinery/doomsday_device, + //Yet more templates + /obj/machinery/restaurant_portal, + //Template type + /obj/effect/mob_spawn, + //Template type + /obj/structure/holosign/robot_seat, + //Singleton + /mob/dview, + //Template type + /obj/item/bodypart, + //This is meant to fail extremely loud every single time it occurs in any environment in any context, and it falsely alarms when this unit test iterates it. Let's not spawn it in. + /obj/merge_conflict_marker, + //briefcase launchpads erroring + /obj/machinery/launchpad/briefcase, + //Both are abstract types meant to scream bloody murder if spawned in raw + /obj/item/organ/external, + /obj/item/organ/external/wings, + ) + + // Everything that follows is a typesof() check. + + //Say it with me now, type template + returnable_list += typesof(/obj/effect/mapping_helpers) + //This turf existing is an error in and of itself + returnable_list += typesof(/turf/baseturf_skipover) + returnable_list += typesof(/turf/baseturf_bottom) + //This demands a borg, so we'll let if off easy + returnable_list += typesof(/obj/item/modular_computer/pda/silicon) + //This one demands a computer, ditto + returnable_list += typesof(/obj/item/modular_computer/processor) + //Very finiky, blacklisting to make things easier + returnable_list += typesof(/obj/item/poster/wanted) + //This expects a seed, we can't pass it + returnable_list += typesof(/obj/item/food/grown) + //Needs clients / mobs to observe it to exist. Also includes hallucinations. + returnable_list += typesof(/obj/effect/client_image_holder) + //Same to above. Needs a client / mob / hallucination to observe it to exist. + returnable_list += typesof(/obj/projectile/hallucination) + returnable_list += typesof(/obj/item/hallucinated) + //We don't have a pod + returnable_list += typesof(/obj/effect/pod_landingzone_effect) + returnable_list += typesof(/obj/effect/pod_landingzone) + //We have a baseturf limit of 10, adding more than 10 baseturf helpers will kill CI, so here's a future edge case to fix. + returnable_list += typesof(/obj/effect/baseturf_helper) + //No tauma to pass in + returnable_list += typesof(/mob/camera/imaginary_friend) + //No pod to gondola + returnable_list += typesof(/mob/living/simple_animal/pet/gondola/gondolapod) + //No heart to give + returnable_list += typesof(/obj/structure/ethereal_crystal) + //No linked console + returnable_list += typesof(/mob/camera/ai_eye/remote/base_construction) + //See above + returnable_list += typesof(/mob/camera/ai_eye/remote/shuttle_docker) + //Hangs a ref post invoke async, which we don't support. Could put a qdeleted check but it feels hacky + returnable_list += typesof(/obj/effect/anomaly/grav/high) + //See above + returnable_list += typesof(/obj/effect/timestop) + //Invoke async in init, skippppp + returnable_list += typesof(/mob/living/silicon/robot/model) + //This lad also sleeps + returnable_list += typesof(/obj/item/hilbertshotel) + //this boi spawns turf changing stuff, and it stacks and causes pain. Let's just not + returnable_list += typesof(/obj/effect/sliding_puzzle) + //Stacks baseturfs, can't be tested here + returnable_list += typesof(/obj/effect/temp_visual/lava_warning) + //Stacks baseturfs, can't be tested here + returnable_list += typesof(/obj/effect/landmark/ctf) + //Our system doesn't support it without warning spam from unregister calls on things that never registered + returnable_list += typesof(/obj/docking_port) + //Asks for a shuttle that may not exist, let's leave it alone + returnable_list += typesof(/obj/item/pinpointer/shuttle) + //This spawns beams as a part of init, which can sleep past an async proc. This hangs a ref, and fucks us. It's only a problem here because the beam sleeps with CHECK_TICK + returnable_list += typesof(/obj/structure/alien/resin/flower_bud) + //Needs a linked mecha + returnable_list += typesof(/obj/effect/skyfall_landingzone) + //Expects a mob to holderize, we have nothing to give + returnable_list += typesof(/obj/item/clothing/head/mob_holder) + //Needs cards passed into the initilazation args + returnable_list += typesof(/obj/item/toy/cards/cardhand) + //Needs a holodeck area linked to it which is not guarenteed to exist and technically is supposed to have a 1:1 relationship with computer anyway. + returnable_list += typesof(/obj/machinery/computer/holodeck) + //runtimes if not paired with a landmark + returnable_list += typesof(/obj/structure/industrial_lift) + // Runtimes if the associated machinery does not exist, but not the base type + returnable_list += subtypesof(/obj/machinery/airlock_controller) + // Always ought to have an associated escape menu. Any references it could possibly hold would need one regardless. + returnable_list += subtypesof(/atom/movable/screen/escape_menu) + // Can't spawn openspace above nothing, it'll get pissy at me + returnable_list += typesof(/turf/open/space/openspace) + returnable_list += typesof(/turf/open/openspace) + + //SKYRAT EDIT ADDITION START - OUR UNCREATABLES DOWN HERE + //Not designed to be spawned without a turf. + returnable_list += typesof(/obj/effect/abstract/liquid_turf) + //Not designed to be spawned individually. + returnable_list += typesof(/obj/structure/mold) + //Unused - not supposed to be spawned without SSliquids + returnable_list += typesof(/turf/open/openspace/ocean) + //Baseturf editors can only go up to ten, stop this. + returnable_list += typesof(/obj/effect/baseturf_helper) + // It's the abstract base type, it shouldn't be spawned. + returnable_list += /obj/item/organ/external/genital + // These two are locked to one type only, and shouldn't be widely available, hence why they runtime otherwise. + // Can't be bothered adding more to them. + returnable_list += list(/obj/item/organ/external/neck_accessory, /obj/item/organ/external/head_accessory) + //SKYRAT EDIT ADDITION END + + return returnable_list + /proc/RunUnitTests() CHECK_TICK diff --git a/tools/ticked_file_enforcement/ticked_file_enforcement.py b/tools/ticked_file_enforcement/ticked_file_enforcement.py index 59ac016b753..86c399c7355 100644 --- a/tools/ticked_file_enforcement/ticked_file_enforcement.py +++ b/tools/ticked_file_enforcement/ticked_file_enforcement.py @@ -37,7 +37,7 @@ for excluded_file in excluded_files: post_error(f"Excluded file {full_file_path} does not exist, please remove it!") sys.exit(1) -file_extensions = (".dm", ".dmf") +file_extensions = ("dm", "dmf") reading = False lines = [] @@ -64,7 +64,12 @@ fail_no_include = False scannable_files = [] for file_extension in file_extensions: - scannable_files += glob.glob(scannable_directory + f"**/*.{file_extension}", recursive=True) + compiled_directory = f"{scannable_directory}/**/*.{file_extension}" + scannable_files += glob.glob(compiled_directory, recursive=True) + +if len(scannable_files) == 0: + post_error(f"No files were found in {scannable_directory}. Ticked File Enforcement has failed!") + sys.exit(1) for code_file in scannable_files: dm_path = "" @@ -148,4 +153,4 @@ for (index, line) in enumerate(lines): post_error(f"The include at line {index + offset} is out of order ({line}, expected {sorted_lines[index]})") sys.exit(1) -print(green(f"Ticked File Enforcement: [{file_reference}] All includes are in order!")) +print(green(f"Ticked File Enforcement: [{file_reference}] All includes (for {len(scannable_files)} scanned files) are in order!"))