new unit tests for the new getters/remove methods. general test case improvement (+47 squashed commit)

Squashed commit:

[da8f778e1] fixed issue with buff instancing saving previous cache information

[50e381135] fixing clear to use new private method

[523196876] added new removal methods, spun boilerplate into private method

[ab2fe7a1b] misc

[4a2c2e887] added get_by_cachevalue, for arbitrary cache value comparison

[4e9199fd9] fix expired property

[cc6411eb2] added option to trigger buffs at the same time you check them

[eb112c12f] added get_by_source method to slice cache by source

[5d880d4f9] added "clear" method to remove all buffs

[49997e724] extended "expired" logic to include buffs with no stacks

[7ef357ade] docstring fixes

[306801d02] Added a little docstring bit for disconnecting autopause from signals and moving it to object puppet hooks

[7a120a2f8] fixed the sample buff for poison to demonstrate how playtime buff pause hooks happen (as at_pause fires after the object is moved to None, you can't message the None-room's contents)

[ada4457d1] made the pause variable assignments more verbose

[d64369908] nomenclature change: uid -> buffkey

[e5dd9a352] fixing places where the handler property name change from "db" to "buffcache" broke stuff on the buff class

[553d12b4b] lots of docstring updates and comments; also made conditional hook work with ticking

[b8d79583f] ran black autoformatter

[d5550f331] changing all the default dictionary assignments to None instead

[88c9a4889] sample buff of stat customizer

[72323a19e] added sample buff which allows stat customization, and unit test to cover it

[02453a79f] adding procgen ids for non-unique, non-refresh (ie, each time the buff is applied, it is as a full instance with a separate key)

[c72e5f2d7] added to_filter argument to slice methods, letting you slice an arbitrary dictionary as well as the main cache

[d8996f3a3] stress test for batch read/trigger

[f06f74463] last bit of cacheing, docstring update

[538afc676] fixing tests to not use __getattr__ on the handler

[905cfd6bb] removing __getattr__

[e588742ea] hooking caching into the buff instancing process

[7555ebae9] added method to instance entire cache, refactored dict-comprehension properties to use new method. should be more efficient?

[45f15fc46] fix to reapply logic; stacking and old cache

[d2460c9e6] docstring support for to_cache arg

[62f3f27d8] added to_cache arg for buff application, allows you to store arbitrary info in the buff cache

[6c2046497] general cleanup

[357945459] forgot to finish the mod for the "sated" moodlet sample buff

[b4b3ac48a] clamp minimum multiplier to 0

[da3e67fa6] allowing multiple stacks, cruft cleanup

[62110fd00] sample buffs

[77f6a56e8] fixing tests to work with new naming

[a9202f67c] misc cleanup

[887d9734b] allow infinite stacks

[887fb4b29] change duration setter

[da4277e2c] add at_pre_check

[6009469bc] fix pickling errors with handler properties

[89a2d02ee] allo ticking buffs to autopause

[a77bded93] fix flavor return

[60fcaa36f] swapping on_ to at_ for hooks to match evennia style

[130e600ea] import cleanup
This commit is contained in:
Tegiminis 2022-07-12 01:33:57 -07:00
parent f340d4c6e4
commit 3a52913bbb
3 changed files with 1088 additions and 522 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,141 @@
import random
from .buff import BaseBuff, Mod
class Exploit(BaseBuff):
key = "exploit"
name = "Exploit"
flavor = "You are learning your opponent's weaknesses."
duration = -1
maxstacks = 20
triggers = ["hit"]
stack_msg = {
1: "You begin to notice flaws in your opponent's defense.",
10: "You've begun to match the battle's rhythm.",
20: "You've found a gap in the guard!",
}
def conditional(self, *args, **kwargs):
if self.handler.get_by_type(Exploited):
return False
return True
def at_trigger(self, trigger: str, *args, **kwargs):
chance = self.stacks / 20
roll = random.random()
if chance > roll:
self.handler.add(Exploited)
self.owner.msg("An opportunity presents itself!")
elif chance < roll:
self.handler.add(Exploit)
if self.stacks in self.stack_msg:
self.owner.msg(self.stack_msg[self.stacks])
class Exploited(BaseBuff):
key = "exploited"
name = "Exploited"
flavor = "You have sensed your target's vulnerability, and are poised to strike."
duration = 30
mods = [Mod("damage", "add", 100)]
def at_post_check(self, *args, **kwargs):
self.owner.msg("You ruthlessly exploit your target's weakness!")
self.remove(quiet=True)
def at_remove(self, *args, **kwargs):
self.owner.msg("You have waited too long; the opportunity passes.")
class Leeching(BaseBuff):
key = "leeching"
name = "Leeching"
flavor = "Attacking this target fills you with vigor."
duration = 30
triggers = ["taken_damage"]
def at_trigger(self, trigger: str, attacker=None, damage=None, *args, **kwargs):
if not attacker or not damage:
return
attacker.msg("You have been healed for {heal} life!".format(heal=damage * 0.1))
class Poison(BaseBuff):
key = "poison"
name = "Poison"
flavor = "A poison wracks this body with painful spasms."
duration = 120
maxstacks = 5
tickrate = 5
dmg = 5
playtime = True
def at_pause(self, *args, **kwargs):
self.owner.db.prelogout_location.msg_contents(
"{actor} stops twitching, their flesh a deathly pallor.".format(actor=self.owner.named)
)
def at_unpause(self, *args, **kwargs):
self.owner.location.msg_contents(
"{actor} begins to twitch again, their cheeks flushing red with blood.".format(
actor=self.owner.named
)
)
def at_tick(self, initial=True, *args, **kwargs):
_dmg = self.dmg * self.stacks
if not initial:
self.owner.location.msg_contents(
"Poison courses through {actor}'s body, dealing {damage} damage.".format(
actor=self.owner.named, damage=_dmg
)
)
class Sated(BaseBuff):
key = "sated"
name = "Sated"
flavor = "You have eaten a great meal!"
duration = 180
maxstacks = 3
mods = [Mod("mood", "add", 15)]
class StatBuff(BaseBuff):
"""Customize the stat this buff affects by feeding a list in the order [stat, mod, base, perstack] to the cache argument when added"""
key = "statbuff"
name = "statbuff"
flavor = "This buff affects the following stats: {stats}"
maxstacks = 0
refresh = True
unique = False
cache = {"modgen": ["foo", "add", 0, 0]}
def __init__(self, handler, buffkey, cache={}) -> None:
super().__init__(handler, buffkey, cache)
# Finds our "modgen" cache value, which we pass on application
modgen = list(self.cache["modgen"])
if modgen:
self.mods = [Mod(*modgen)]
msg = ""
_msg = [mod.stat for mod in self.mods]
for stat in _msg:
msg += stat
self.flavor = self.flavor.format(stats=msg)

View file

@ -3,87 +3,95 @@ from unittest.mock import Mock, patch
from evennia import DefaultObject, create_object
from evennia.utils import create
from evennia.utils.utils import lazy_property
from .samplebuffs import StatBuff
# the function we want to test
from .buff import BaseBuff, Mod, BuffHandler, BuffableProperty
from evennia.utils.test_resources import EvenniaTest
class _EmptyBuff(BaseBuff):
pass
class _TestModBuff(BaseBuff):
key = 'tmb'
name = 'tmb'
flavor = 'modderbuff'
key = "tmb"
name = "tmb"
flavor = "modderbuff"
maxstacks = 5
mods = [
Mod('stat1', 'add', 10, 5),
Mod('stat2', 'mult', 0.5)
]
mods = [Mod("stat1", "add", 10, 5), Mod("stat2", "mult", 0.5)]
class _TestModBuff2(BaseBuff):
key = 'tmb2'
name = 'tmb2'
flavor = 'modderbuff2'
key = "tmb2"
name = "tmb2"
flavor = "modderbuff2"
maxstacks = 1
mods = [
Mod('stat1', 'mult', 1.0),
Mod('stat1', 'add', 10)
]
mods = [Mod("stat1", "mult", 1.0), Mod("stat1", "add", 10)]
class _TestTrigBuff(BaseBuff):
key = 'ttb'
name = 'ttb'
flavor = 'triggerbuff'
triggers = ['test1', 'test2']
key = "ttb"
name = "ttb"
flavor = "triggerbuff"
triggers = ["test1", "test2"]
def at_trigger(self, trigger: str, *args, **kwargs):
if trigger == "test1":
self.owner.db.triggertest1 = True
if trigger == "test2":
self.owner.db.triggertest2 = True
def on_trigger(self, trigger: str, *args, **kwargs):
if trigger == 'test1': self.owner.db.triggertest1 = True
if trigger == 'test2': self.owner.db.triggertest2 = True
class _TestConBuff(BaseBuff):
key = 'tcb'
name = 'tcb'
flavor = 'condbuff'
triggers = ['condtest']
key = "tcb"
name = "tcb"
flavor = "condbuff"
triggers = ["condtest"]
def conditional(self, *args, **kwargs):
return self.owner.db.cond1
def on_trigger(self, trigger: str, attacker=None, defender=None, damage=0, *args, **kwargs):
def at_trigger(self, trigger: str, attacker=None, defender=None, damage=0, *args, **kwargs):
defender.db.att, defender.db.dmg = attacker, damage
class _TestComplexBuff(BaseBuff):
key = 'tcomb'
name = 'complex'
flavor = 'combuff'
triggers = ['comtest', 'complextest']
key = "tcomb"
name = "complex"
flavor = "combuff"
triggers = ["comtest", "complextest"]
mods = [
Mod('com1', 'add', 0, 10),
Mod('com1', 'add', 15),
Mod('com1', 'mult', 2.0),
Mod('com2', 'add', 100)
Mod("com1", "add", 0, 10),
Mod("com1", "add", 15),
Mod("com1", "mult", 2.0),
Mod("com2", "add", 100),
]
def conditional(self, cond=False, *args, **kwargs):
return not cond
def on_trigger(self, trigger: str, *args, **kwargs):
if trigger == 'comtest': self.owner.db.comtext = {'cond': True}
else: self.owner.db.comtext = {}
def at_trigger(self, trigger: str, *args, **kwargs):
if trigger == "comtest":
self.owner.db.comtext = {"cond": True}
else:
self.owner.db.comtext = {}
class _TestTimeBuff(BaseBuff):
key = 'ttib'
name = 'ttib'
flavor = 'timerbuff'
key = "ttib"
name = "ttib"
flavor = "timerbuff"
maxstacks = 1
tickrate = 1
duration = 5
mods = [Mod('timetest', 'add', 665)]
mods = [Mod("timetest", "add", 665)]
def on_tick(self, initial=True, *args, **kwargs):
def at_tick(self, initial=True, *args, **kwargs):
self.owner.db.ticktest = True
class BuffableObject(DefaultObject):
stat1 = BuffableProperty(10)
@ -95,181 +103,258 @@ class BuffableObject(DefaultObject):
self.stat1, self.buffs
return super().at_init()
class TestBuffsAndHandler(EvenniaTest):
"This tests a number of things about buffs."
def setUp(self):
super().setUp()
self.obj1.handler = BuffHandler(self.obj1, 'buffs')
self.testobj = create.create_object(BuffableObject, key="testobj")
def tearDown(self):
"""done after every test_* method below """
"""done after every test_* method below"""
self.testobj.buffs.clear()
del self.testobj
super().tearDown()
def test_addremove(self):
'''tests adding and removing buffs'''
"""tests adding and removing buffs"""
# setup
handler: BuffHandler = self.obj1.handler
handler: BuffHandler = self.testobj.buffs
# add
handler.add(_TestModBuff)
self.assertEqual( self.obj1.db.buffs['tmb']['ref'], _TestModBuff)
handler.add(_TestModBuff, to_cache={"cachetest": True})
handler.add(_TestTrigBuff)
self.assertEqual(self.testobj.db.buffs["tmb"]["ref"], _TestModBuff)
self.assertTrue(self.testobj.db.buffs["tmb"].get("cachetest"))
self.assertFalse(self.testobj.db.buffs["ttb"].get("cachetest"))
# remove
handler.remove('tmb')
self.assertEqual( self.obj1.db.buffs.get('tmb'), None)
handler.remove("tmb")
self.assertFalse(self.testobj.db.buffs.get("tmb"))
# remove by type
handler.add(_TestModBuff)
handler.remove_by_type(_TestModBuff)
self.assertEqual( self.obj1.db.buffs.get('tmb'), None)
self.assertFalse(self.testobj.db.buffs.get("tmb"))
# remove by buff instance
handler.add(_TestModBuff)
handler.all['tmb'].remove()
self.assertEqual( self.obj1.db.buffs.get('tmb'), None)
handler.all["tmb"].remove()
self.assertFalse(self.testobj.db.buffs.get("tmb"))
# remove by source
handler.add(_TestModBuff)
handler.remove_by_source(None)
self.assertFalse(self.testobj.db.buffs.get("tmb"))
# remove by cachevalue
handler.add(_TestModBuff)
handler.remove_by_cachevalue("failure", True)
self.assertTrue(self.testobj.db.buffs.get("tmb"))
# remove all
handler.add(_TestModBuff)
handler.clear()
self.assertFalse(self.testobj.db.buffs.get("tmb"))
def test_getters(self):
'''tests all built-in getters'''
"""tests all built-in getters"""
# setup
handler: BuffHandler = self.obj1.handler
handler.add(_TestModBuff)
handler.add(_TestTrigBuff)
# normal getters
self.assertEqual(isinstance(handler.tmb, _TestModBuff), True)
self.assertEqual(isinstance(handler.get('tmb'),_TestModBuff), True)
handler: BuffHandler = self.testobj.buffs
handler.add(_TestModBuff, source=self.obj2)
handler.add(_TestTrigBuff, to_cache={"ttbcache": True})
# normal getter
self.assertTrue(isinstance(handler.get("tmb"), _TestModBuff))
# stat getters
self.assertEqual(isinstance(handler.get_by_stat('stat1')['tmb'], _TestModBuff), True)
self.assertEqual(handler.get_by_stat('nullstat'), {})
self.assertTrue(isinstance(handler.get_by_stat("stat1")["tmb"], _TestModBuff))
self.assertFalse(handler.get_by_stat("nullstat"))
# trigger getters
self.assertEqual('ttb' in handler.get_by_trigger('test1').keys(), True)
self.assertEqual('ttb' in handler.get_by_trigger('nulltrig').keys(), False)
self.assertTrue("ttb" in handler.get_by_trigger("test1").keys())
self.assertFalse("ttb" in handler.get_by_trigger("nulltrig").keys())
# type getters
self.assertEqual('tmb' in handler.get_by_type(_TestModBuff), True)
self.assertEqual('tmb' in handler.get_by_type(_EmptyBuff), False)
self.assertTrue("tmb" in handler.get_by_type(_TestModBuff))
self.assertFalse("tmb" in handler.get_by_type(_EmptyBuff))
# source getter
self.assertTrue("tmb" in handler.get_by_source(self.obj2))
self.assertFalse("ttb" in handler.get_by_source(self.obj2))
# cachevalue getter
self.assertFalse(handler.get("tmb").cache.get("ttbcache"))
self.assertFalse(handler.get("ttb").cache.get("testfalse"))
self.assertFalse("tmb" in handler.get_by_cachevalue("ttbcache"))
self.assertTrue("ttb" in handler.get_by_cachevalue("ttbcache"))
self.assertTrue("ttb" in handler.get_by_cachevalue("ttbcache", True))
def test_details(self):
'''tests that buff details like name and flavor are correct'''
handler: BuffHandler = self.obj1.handler
"""tests that buff details like name and flavor are correct"""
handler: BuffHandler = self.testobj.buffs
handler.add(_TestModBuff)
handler.add(_TestTrigBuff)
self.assertEqual(handler.tmb.flavor, 'modderbuff')
self.assertEqual(handler.ttb.name, 'ttb')
self.assertEqual(handler.get("tmb").flavor, "modderbuff")
self.assertEqual(handler.get("ttb").name, "ttb")
def test_modify(self):
'''tests to ensure that values are modified correctly, and stack across mods'''
"""tests to ensure that values are modified correctly, and stack across mods"""
# setup
handler: BuffHandler = self.obj1.handler
handler: BuffHandler = self.testobj.buffs
_stat1, _stat2 = 0, 10
handler.add(_TestModBuff)
# stat1 and 2 basic mods
self.assertEqual(handler.check(_stat1, 'stat1'), 15)
self.assertEqual(handler.check(_stat2, 'stat2'), 15)
self.assertEqual(handler.check(_stat1, "stat1"), 15)
self.assertEqual(handler.check(_stat2, "stat2"), 15)
# checks can take any base value
self.assertEqual(handler.check(_stat1, 'stat2'), 0)
self.assertEqual(handler.check(_stat2, 'stat1'), 25)
self.assertEqual(handler.check(_stat1, "stat2"), 0)
self.assertEqual(handler.check(_stat2, "stat1"), 25)
# change to base stat reflected in check
_stat1 += 5
self.assertEqual(handler.check(_stat1, 'stat1'), 20)
self.assertEqual(handler.check(_stat1, "stat1"), 20)
_stat2 += 10
self.assertEqual(handler.check(_stat2, 'stat2'), 30)
self.assertEqual(handler.check(_stat2, "stat2"), 30)
# test stacking; single stack, multiple stack, max stacks
handler.add(_TestModBuff)
self.assertEqual(handler.check(_stat1, 'stat1'), 25)
self.assertEqual(handler.check(_stat1, "stat1"), 25)
handler.add(_TestModBuff, stacks=3)
self.assertEqual(handler.check(_stat1, 'stat1'), 40)
self.assertEqual(handler.check(_stat1, "stat1"), 40)
handler.add(_TestModBuff, stacks=5)
self.assertEqual(handler.check(_stat1, 'stat1'), 40)
self.assertEqual(handler.check(_stat1, "stat1"), 40)
# stat2 mod doesn't stack
self.assertEqual(handler.check(_stat2, 'stat2'), 30)
self.assertEqual(handler.check(_stat2, "stat2"), 30)
# layers with second mod
handler.add(_TestModBuff2)
self.assertEqual(handler.check(_stat1, 'stat1'), 100)
self.assertEqual(handler.check(_stat2, 'stat2'), 30)
self.assertEqual(handler.check(_stat1, "stat1"), 100)
self.assertEqual(handler.check(_stat2, "stat2"), 30)
handler.remove_by_type(_TestModBuff)
self.assertEqual(handler.check(_stat1, 'stat1'), 30)
self.assertEqual(handler.check(_stat2, 'stat2'), 20)
self.assertEqual(handler.check(_stat1, "stat1"), 30)
self.assertEqual(handler.check(_stat2, "stat2"), 20)
def test_trigger(self):
'''tests to ensure triggers correctly fire'''
"""tests to ensure triggers correctly fire"""
# setup
handler: BuffHandler = self.obj1.handler
handler: BuffHandler = self.testobj.buffs
handler.add(_TestTrigBuff)
# trigger buffs
handler.trigger('nulltest')
self.assertEqual(self.obj1.db.triggertest1, None)
self.assertEqual(self.obj1.db.triggertest2, None)
handler.trigger('test1')
self.assertEqual(self.obj1.db.triggertest1, True)
self.assertEqual(self.obj1.db.triggertest2, None)
handler.trigger('test2')
self.assertEqual(self.obj1.db.triggertest1, True)
self.assertEqual(self.obj1.db.triggertest2, True)
handler.trigger("nulltest")
self.assertFalse(self.testobj.db.triggertest1)
self.assertFalse(self.testobj.db.triggertest2)
handler.trigger("test1")
self.assertTrue(self.testobj.db.triggertest1)
self.assertFalse(self.testobj.db.triggertest2)
handler.trigger("test2")
self.assertTrue(self.testobj.db.triggertest1)
self.assertTrue(self.testobj.db.triggertest2)
def test_context_conditional(self):
'''tests to ensure context is passed to buffs, and also tests conditionals'''
"""tests to ensure context is passed to buffs, and also tests conditionals"""
# setup
handler: BuffHandler = self.obj1.handler
handler: BuffHandler = self.testobj.buffs
handler.add(_TestConBuff)
self.obj1.db.cond1, self.obj1.db.att, self.obj1.db.dmg = False, None, 0
self.testobj.db.cond1, self.testobj.db.att, self.testobj.db.dmg = False, None, 0
# context to pass, containing basic event data and a little extra to be ignored
_testcontext = {'attacker':self.obj2, 'defender':self.obj1, 'damage':5, 'overflow':10}
_testcontext = {
"attacker": self.obj2,
"defender": self.testobj,
"damage": 5,
"overflow": 10,
}
# test negative conditional
self.assertEqual(handler.get_by_type(_TestConBuff)['tcb'].conditional(**_testcontext), False)
handler.trigger('condtest', _testcontext)
self.assertEqual(self.obj1.db.att, None)
self.assertEqual(self.obj1.db.dmg, 0)
self.assertEqual(
handler.get_by_type(_TestConBuff)["tcb"].conditional(**_testcontext), False
)
handler.trigger("condtest", _testcontext)
self.assertEqual(self.testobj.db.att, None)
self.assertEqual(self.testobj.db.dmg, 0)
# test positive conditional + context passing
self.obj1.db.cond1 = True
self.assertEqual(handler.get_by_type(_TestConBuff)['tcb'].conditional(**_testcontext), True)
handler.trigger('condtest', _testcontext)
self.assertEqual(self.obj1.db.att, self.obj2)
self.assertEqual(self.obj1.db.dmg, 5)
self.testobj.db.cond1 = True
self.assertEqual(handler.get_by_type(_TestConBuff)["tcb"].conditional(**_testcontext), True)
handler.trigger("condtest", _testcontext)
self.assertEqual(self.testobj.db.att, self.obj2)
self.assertEqual(self.testobj.db.dmg, 5)
def test_complex(self):
'''tests a complex mod (conditionals, multiple triggers/mods)'''
"""tests a complex mod (conditionals, multiple triggers/mods)"""
# setup
handler: BuffHandler = self.obj1.handler
self.obj1.db.comone, self.obj1.db.comtwo, self.obj1.db.comtext = 10, 0, {}
handler: BuffHandler = self.testobj.buffs
self.testobj.db.comone, self.testobj.db.comtwo, self.testobj.db.comtext = 10, 0, {}
handler.add(_TestComplexBuff)
# stat checks work correctly and separately
self.assertEqual(self.obj1.db.comtext, {})
self.assertEqual(handler.check(self.obj1.db.comone, 'com1'), 105)
self.assertEqual(handler.check(self.obj1.db.comtwo, 'com2'), 100)
self.assertEqual(self.testobj.db.comtext, {})
self.assertEqual(handler.check(self.testobj.db.comone, "com1"), 105)
self.assertEqual(handler.check(self.testobj.db.comtwo, "com2"), 100)
# stat checks don't happen if the conditional is true
handler.trigger('comtest', self.obj1.db.comtext)
self.assertEqual(self.obj1.db.comtext, {'cond': True})
self.assertEqual(handler.get_by_type(_TestComplexBuff)['tcomb'].conditional(**self.obj1.db.comtext), False)
self.assertEqual(handler.check(self.obj1.db.comone, 'com1', context=self.obj1.db.comtext), 10)
self.assertEqual(handler.check(self.obj1.db.comtwo, 'com2', context=self.obj1.db.comtext), 0)
handler.trigger('complextest', self.obj1.db.comtext)
self.assertEqual(handler.check(self.obj1.db.comone, 'com1', context=self.obj1.db.comtext), 10)
self.assertEqual(handler.check(self.obj1.db.comtwo, 'com2', context=self.obj1.db.comtext), 0)
handler.trigger("comtest", self.testobj.db.comtext)
self.assertEqual(self.testobj.db.comtext, {"cond": True})
self.assertEqual(
handler.get_by_type(_TestComplexBuff)["tcomb"].conditional(**self.testobj.db.comtext),
False,
)
self.assertEqual(
handler.check(self.testobj.db.comone, "com1", context=self.testobj.db.comtext), 10
)
self.assertEqual(
handler.check(self.testobj.db.comtwo, "com2", context=self.testobj.db.comtext), 0
)
handler.trigger("complextest", self.testobj.db.comtext)
self.assertEqual(
handler.check(self.testobj.db.comone, "com1", context=self.testobj.db.comtext), 10
)
self.assertEqual(
handler.check(self.testobj.db.comtwo, "com2", context=self.testobj.db.comtext), 0
)
# separate trigger follows different codepath
self.obj1.db.comtext = {'cond': False}
handler.trigger('complextest', self.obj1.db.comtext)
self.assertEqual(self.obj1.db.comtext, {})
self.assertEqual(handler.check(self.obj1.db.comone, 'com1', context=self.obj1.db.comtext), 105)
self.assertEqual(handler.check(self.obj1.db.comtwo, 'com2', context=self.obj1.db.comtext), 100)
self.testobj.db.comtext = {"cond": False}
handler.trigger("complextest", self.testobj.db.comtext)
self.assertEqual(self.testobj.db.comtext, {})
self.assertEqual(
handler.check(self.testobj.db.comone, "com1", context=self.testobj.db.comtext), 105
)
self.assertEqual(
handler.check(self.testobj.db.comtwo, "com2", context=self.testobj.db.comtext), 100
)
def test_timing(self):
'''tests timing-related features, such as ticking and duration'''
"""tests timing-related features, such as ticking and duration"""
# setup
handler: BuffHandler = self.obj1.handler
handler: BuffHandler = self.testobj.buffs
handler.add(_TestTimeBuff)
self.obj1.db.timetest, self.obj1.db.ticktest = 1, False
self.testobj.db.timetest, self.testobj.db.ticktest = 1, False
# test duration and ticking
self.assertTrue(handler.ttib.ticking)
self.assertEqual(handler.get('ttib').duration, 5)
handler.get('ttib').on_tick()
self.assertTrue(self.obj1.db.ticktest)
_instance = handler.get("ttib")
self.assertTrue(_instance.ticking)
self.assertEqual(_instance.duration, 5)
_instance.at_tick()
self.assertTrue(self.testobj.db.ticktest)
# test duration modification and cleanup
handler.modify_duration('ttib', 0, set=True)
self.assertEqual(handler.get('ttib').duration, 0)
handler.set_duration("ttib", 0)
self.assertEqual(handler.get("ttib").duration, 0)
handler.cleanup()
self.assertFalse(handler.get('ttib'), None)
self.assertFalse(handler.get("ttib"), None)
def test_buffableproperty(self):
'''tests buffable properties'''
"""tests buffable properties"""
# setup
self.propobj = create.create_object(BuffableObject, key='testobj')
self.propobj.buffs.add(_TestModBuff)
self.assertEqual(self.propobj.stat1, 25)
self.propobj.buffs.remove('tmb')
self.assertEqual(self.propobj.stat1, 10)
self.testobj.buffs.add(_TestModBuff)
self.assertEqual(self.testobj.stat1, 25)
self.testobj.buffs.remove("tmb")
self.assertEqual(self.testobj.stat1, 10)
def test_stresstest(self):
"""tests large amounts of buffs, and related removal methods"""
# setup
for x in range(1, 20):
self.testobj.buffs.add(_TestModBuff, key="test" + str(x))
self.testobj.buffs.add(_TestTrigBuff, key="trig" + str(x))
self.assertEqual(self.testobj.stat1, 295)
self.testobj.buffs.trigger("test1")
self.testobj.buffs.remove_by_type(_TestModBuff)
self.assertEqual(self.testobj.stat1, 10)
self.testobj.buffs.clear()
self.assertFalse(self.testobj.buffs.all)
def test_modgen(self):
"""test generating mods on the fly"""
# setup
handler: BuffHandler = self.testobj.buffs
self.testobj.db.gentest = 5
self.assertEqual(self.testobj.db.gentest, 5)
tc = {"modgen": ["gentest", "add", 5, 0]}
handler.add(StatBuff, key="gentest", to_cache=tc)
self.assertEqual(handler.check(self.testobj.db.gentest, "gentest"), 10)
tc = {"modgen": ["gentest", "add", 10, 0]}
handler.add(StatBuff, key="gentest", to_cache=tc)
self.assertEqual(handler.check(self.testobj.db.gentest, "gentest"), 15)
self.assertEqual(
handler.get("gentest").flavor, "This buff affects the following stats: gentest"
)