Files
Bubberstation/code/datums/components/fantasy/_fantasy.dm
san7890 63f7eb1a6a Fixes Ticked File Enforcement and Missing Unit Test (and makes said Unit Test Compile) (and genericizes the C&D list to the base unit test datum) (#77632)
Closes #77631

## About The Pull Request

Hey there,

Ticked File Enforcement simply wasn't catching files that were missed.
That's a bit stupid, so I decided to look into what the issue might be,
and whoopsie daisies I did double periods back in #76592
(020ac24053).

![image](https://github.com/tgstation/tgstation/assets/34697715/6023afe8-313d-4550-9a60-58a8bc211b4f)

I also added some debug info and some more checks to prevent such a
break from happening again on runtime of this script. I thought it was a
weird string concatenation issue (and not the simple break I thought it
was), so I rewrote how it adds `glob`s. I think it's cleaner so I'll
keep it anyhow

This PR also corrects the oversight of the missing unit test (introduced
in #77218 (69827604c4)) by reticking it in
the `_unit_tests.dm` file, and also makes it compile because it didn't
do that.

I also then had to do some more work to get the unit test to work.
* Genericizes the Create-and-Destroy "ignore" list to be a static list
on `/datum/unit_test` to allow it to be shared between these types of
tests that we need to test.
* Adds that list to C&D and the broken unit test regarding fantasy
bonuses
* Fixes some actually broken that the unit test was made to catch (beam
rifles, butterdogs and other slippery items, random ingredient boxes).
* Adds cases for things that the unit test and overall framework really
shouldn't be altering anyways (mythril), and was likely causing
inappropriate stack traces on master

## Why It's Good For The Game

Unit Tests WORK. Tools WORK.


![image](https://github.com/tgstation/tgstation/assets/34697715/9a59c0db-7a33-4546-918b-c73372a5b867)


## Changelog

🆑
fix: Beam rifles will no longer inappropriately retain any bonuses they
may gain from wizardry.
fix: Inappropriate stack traces over bonuses being applied to components
that gain bonuses innately (like Mythril stacks) should cease.
/🆑
2023-08-15 23:51:26 -07:00

154 lines
4.1 KiB
Plaintext

/datum/component/fantasy
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
var/quality
var/canFail
var/announce
var/originalName
var/list/affixes
var/list/appliedComponents
var/static/list/affixListing
///affixes expects an initialized list
/datum/component/fantasy/Initialize(quality, list/affixes = list(), canFail=FALSE, announce=FALSE)
if(!isitem(parent) || HAS_TRAIT(parent, TRAIT_INNATELY_FANTASTICAL_ITEM))
return COMPONENT_INCOMPATIBLE
src.quality = quality
if(isnull(src.quality))
src.quality = random_quality()
src.canFail = canFail
src.announce = announce
src.affixes = affixes
appliedComponents = list()
if(affixes && affixes.len)
set_affixes()
else
random_affixes()
/datum/component/fantasy/Destroy()
unmodify()
affixes = null
return ..()
/datum/component/fantasy/RegisterWithParent()
var/obj/item/master = parent
originalName = master.name
modify()
RegisterSignal(parent, COMSIG_STACK_CAN_MERGE, PROC_REF(try_merge_stack))
/datum/component/fantasy/proc/try_merge_stack(obj/item/stack/to_merge, in_hand)
SIGNAL_HANDLER
return CANCEL_STACK_MERGE
/datum/component/fantasy/UnregisterFromParent()
unmodify()
/datum/component/fantasy/InheritComponent(datum/component/fantasy/newComp, original, quality, list/affixes, canFail, announce)
unmodify()
if(newComp)
src.quality += newComp.quality
src.canFail = newComp.canFail
src.announce = newComp.announce
else
src.quality += quality
src.canFail = canFail || src.canFail
src.announce = announce || src.announce
modify()
/datum/component/fantasy/proc/random_quality()
var/quality = pick(1;15, 2;14, 2;13, 2;12, 3;11, 3;10, 3;9, 4;8, 4;7, 4;6, 5;5, 5;4, 5;3, 6;2, 6;1, 6;0)
if(prob(50))
quality = -quality
return quality
///proc on creation for random affixes
/datum/component/fantasy/proc/random_affixes(force)
var/alignment
if(quality >= 0)
alignment |= AFFIX_GOOD
if(quality <= 0)
alignment |= AFFIX_EVIL
if(!affixListing)
affixListing = list()
for(var/T in subtypesof(/datum/fantasy_affix))
var/datum/fantasy_affix/affix = new T
affixListing[affix] = affix.weight
if(length(affixes))
if(!force)
return
affixes = list()
var/usedSlots = NONE
for(var/i in 1 to max(1, abs(quality))) // We want at least 1 affix applied
var/datum/fantasy_affix/affix = pick_weight(affixListing)
if(affix.placement & usedSlots)
continue
if(!(affix.alignment & alignment))
continue
if(!affix.validate(parent))
continue
affixes += affix
usedSlots |= affix.placement
///proc on creation for specific affixes given to the fantasy component
/datum/component/fantasy/proc/set_affixes(force)
var/usedSlots = NONE
for(var/datum/fantasy_affix/affix in affixes) // We want at least 1 affix applied
if((affix.placement & usedSlots) || (!affix.validate(parent)))
affixes.Remove(affix) //bad affix (can't be added to this item)
continue
usedSlots |= affix.placement
/datum/component/fantasy/proc/modify()
var/obj/item/master = parent
master.apply_fantasy_bonuses(quality)
var/newName = originalName
for(var/i in affixes)
var/datum/fantasy_affix/affix = i
newName = affix.apply(src, newName)
if(quality != 0)
newName = "[newName] [quality > 0 ? "+" : ""][quality]"
if(canFail && prob((quality - 9)*10))
var/turf/place = get_turf(parent)
place.visible_message(span_danger("[parent] [span_blue("violently glows blue")] for a while, then evaporates."))
master.burn()
return
master.name = newName
if(announce)
announce()
/datum/component/fantasy/proc/unmodify()
var/obj/item/master = parent
for(var/i in affixes)
var/datum/fantasy_affix/affix = i
affix.remove(src)
QDEL_LIST(appliedComponents)
master.remove_fantasy_bonuses(quality)
master.name = originalName
/datum/component/fantasy/proc/announce()
var/turf/location = get_turf(parent)
var/span
var/effect_description
if(quality >= 0)
span = "<span class='notice'>"
effect_description = "<span class='heavy_brass'>shimmering golden glow</span>"
else
span = "<span class='danger'>"
effect_description = span_bold("mottled black glow")
location.visible_message("[span]The [originalName] is covered by a [effect_description] and then transforms into [parent]!</span>")