Files
Bubberstation/code/modules/unit_tests/organ_set_bonus.dm
T
Time-GreenandGitHub 54ab1e3936 Organ movement refactor *Un-nullspaces your organs* (#79687)
<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

closes #53931, #70916, #53931

## About The Pull Request

Organs were previously stored in nullspace. Now they are stored in their
prospective bodyparts. Bodyparts are now stored in the mob.

I've also had to refactor a lot of code concerning organ movement.
Previously, organs were only moved into bodyparts once the bodyparts
were removed. To accomodate this change, two major distinctions have
been made:

**Bodypart removal/insertion**
Called only when an organ is taken out of a bodypart. Bodypart overlays,
damage modifiers or other changes that should affect a bodypart itself
goes here.

**Mob insertion/removal**
Called when an organ is removed from a mob. This can either be directly,
by taking the organ out of a mob, or by removing the bodypart that
contains the organ. This lets you add and remove organ effects safely
without having to worry about the bodypart.

Now that we controle the movement of bodyparts and organs, we can fuck
around with them more. Summoning someones head or chest or heart will
actually kill them now (and quite violently I must say (chest summoning
gibs lol)).


https://github.com/tgstation/tgstation/assets/7501474/5efc9dd3-cfd5-4ce4-b70f-d0d74894626e

I´ve also added a unit test that violently tears apart and reconstructs
a person in different ways to see if they get put toghether the right
way

This will definitely need a testmerge. I've done a lot of testing to
make sure interactions work, but more niche stuff or my own incompetence
can always slip through.

## Why It's Good For The Game

<!-- Argue for the merits of your changes and how they benefit the game,
especially if they are controversial and/or far reaching. If you can't
actually explain WHY what you are doing will improve the game, then it
probably isn't good for the game in the first place. -->

A lot of organ work is quite restricted. You can't C4 someones heart,
you cant summon their organs and a lot of exceptions have to be made to
keep organs in nullspace. This lets organs (and bodyparts) play more
nicely with the rest of the game. This also makes it a lot easier to
move away from extorgans since a lot of their unique movement code has
been removed and or generalized.

I don't like making PRs of this size (I'm so sorry reviewers), but I was
in a unique position to replace the entire system in a way I couldn't
have done conveniently in multiple PRs

## Changelog

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and it's effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->

🆑
refactor: Your organs are now inside your body. Please report any issues
with bodypart and organ movement, including exotic organ, on github and
scream at me
fix: Cases of unexpected organ movement, such as teleporting bodyparts
and organs with spells, now invokes a proper reaction (usually violent
death)
runtime: Fixes HARS runtiming on activation/deactivation
fix: Fixes lag when species swapping
/🆑

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
2023-12-09 17:50:46 +00:00

76 lines
4.6 KiB
Plaintext

/// Checks that all "organ_set_bonus" status effects have unique "id" vars.
/// Required to ensure that the status effects are treated as "unique".
/datum/unit_test/organ_set_bonus_id
/datum/unit_test/organ_set_bonus_id/Run()
var/list/bonus_effects = typesof(/datum/status_effect/organ_set_bonus)
var/list/existing_ids = list()
for(var/datum/status_effect/organ_set_bonus/bonus_effect as anything in bonus_effects)
var/effect_id = initial(bonus_effect.id)
TEST_ASSERT(!(effect_id in existing_ids), "The ID of [bonus_effect] was duplicated in another status effect.")
existing_ids += effect_id
/// Checks that all implantable DNA Infuser organs are set up correctly and without error.
/// Tests the "organ set bonus" Elements and Status Effects, which are for the DNA Infuser.
/// This test ensures that the "organ_set_bonus" status effects activate and deactivate when expected.
/datum/unit_test/organ_set_bonus_sanity
/datum/unit_test/organ_set_bonus_sanity/Run()
/// List of infuser_entry typepaths which contain species-changing organs.
/// Species change swaps out all the organs, making test_organ un-usable after insertion.
var/list/species_changing_entries = typecacheof(list(
/datum/infuser_entry/fly,
))
// Fetch the globally instantiated DNA Infuser entries.
for(var/datum/infuser_entry/infuser_entry as anything in GLOB.infuser_entries)
var/output_organs = infuser_entry.output_organs
var/mob/living/carbon/human/lab_rat = allocate(/mob/living/carbon/human/consistent)
var/list/obj/item/organ/inserted_organs = list()
// Attempt to insert entire list of mutant organs for the given infusion_entry.
for(var/obj/item/organ/organ as anything in output_organs)
organ = new organ()
TEST_ASSERT(organ.Insert(lab_rat, special = TRUE, movement_flags = DELETE_IF_REPLACED), "The organ `[organ.type]` for `[infuser_entry.type]` was not inserted in the mob when expected, Insert() returned falsy when TRUE was expected.")
inserted_organs += organ
// Search for added Status Effect.
var/datum/status_effect/organ_set_bonus/added_status = locate(/datum/status_effect/organ_set_bonus) in lab_rat.status_effects
// If threshold_desc is filled-in, it implies the organ_set_bonus Status Effect should be activated.
// Without it, we'll assume there isn't a Status Effect to look for.
var/has_threshold = (infuser_entry.threshold_desc != DNA_INFUSION_NO_THRESHOLD)
// How many organs the Status Effect requires to be inserted before it will activate.
var/total_organs_needed = added_status?.organs_needed || 0
// How many organs are available from the infuser entry.
var/total_organs = length(infuser_entry.output_organs)
// Quantity of successfully inserted organs.
var/total_inserted = length(inserted_organs)
// If Status Effect exists, ensure it has a matching threshold description and vice versa.
// Otherwise, ensure both are falsy.
TEST_ASSERT((added_status && has_threshold) || (!added_status && !has_threshold), "The threshold_desc variable for `[infuser_entry.type]` was an empty string when a description was expected.")
if(has_threshold)
TEST_ASSERT(added_status, "The `/datum/status_effect/organ_set_bonus` for `[infuser_entry.type]` was not added to the mob when expected.")
TEST_ASSERT(total_organs_needed, "The `needed_organs` variable for `[added_status.type]` should be a positive number.")
TEST_ASSERT(total_organs_needed <= total_organs, "The `output_organs` list for `[infuser_entry.type]` had a length of `[length(infuser_entry.output_organs)]` when a minimum of at least [total_organs_needed] organs was specified in `[added_status.type]`.")
TEST_ASSERT(added_status.bonus_active, "The `[added_status.type]` bonus was not activated after inserting [total_inserted] of the [total_organs_needed] required organs in the mob, when it was expected.")
// Nothing to do.
if(total_inserted == 0)
continue
// Bonus of the Fly mutation swaps out all the organs, making it rather permanent.
// As a result, the inserted_organs list is un-usable by this point.
if(species_changing_entries[infuser_entry.type])
continue
// Remove all the organs which were just added.
for(var/obj/item/organ/test_organ as anything in inserted_organs)
test_organ.Remove(lab_rat, special = TRUE)
var/datum/status_effect/organ_set_bonus/removed_status = (locate(/datum/status_effect/organ_set_bonus) in lab_rat.status_effects)
// Search for added Status Effect.
TEST_ASSERT(!removed_status || !added_status.bonus_active, "The `[added_status.type]` bonus was not deactivated after removing [total_inserted] of the [total_organs_needed] required organs from the mob, when it was expected.")