Merge and fix conflicts with develop

This commit is contained in:
Griatch 2018-07-21 14:34:26 +02:00
commit a954f9c723
13 changed files with 3281 additions and 214 deletions

View file

@ -97,15 +97,15 @@ def funcname(a, b, c, d=False, **kwargs):
Args: Args:
a (str): This is a string argument that we can talk about a (str): This is a string argument that we can talk about
over multiple lines. over multiple lines.
b (int or str): Another argument b (int or str): Another argument.
c (list): A list argument c (list): A list argument.
d (bool, optional): An optional keyword argument d (bool, optional): An optional keyword argument.
Kwargs: Kwargs:
test (list): A test keyword test (list): A test keyword.
Returns: Returns:
e (str): The result of the function e (str): The result of the function.
Raises: Raises:
RuntimeException: If there is a critical error, RuntimeException: If there is a critical error,

View file

@ -798,7 +798,7 @@ class DefaultAccount(with_metaclass(TypeclassBase, AccountDB)):
# any was deleted in the interim. # any was deleted in the interim.
self.db._playable_characters = [char for char in self.db._playable_characters if char] self.db._playable_characters = [char for char in self.db._playable_characters if char]
self.msg(self.at_look(target=self.db._playable_characters, self.msg(self.at_look(target=self.db._playable_characters,
session=session)) session=session), session=session)
def at_failed_login(self, session, **kwargs): def at_failed_login(self, session, **kwargs):
""" """

View file

@ -33,7 +33,7 @@ from evennia.prototypes import prototypes as protlib
# set up signal here since we are not starting the server # set up signal here since we are not starting the server
_RE = re.compile(r"^\+|-+\+|\+-+|--*|\|(?:\s|$)", re.MULTILINE) _RE = re.compile(r"^\+|-+\+|\+-+|--+|\|(?:\s|$)", re.MULTILINE)
# ------------------------------------------------------------ # ------------------------------------------------------------
@ -112,8 +112,11 @@ class CommandTest(EvenniaTest):
# Get the first element of a tuple if msg received a tuple instead of a string # Get the first element of a tuple if msg received a tuple instead of a string
stored_msg = [smsg[0] if isinstance(smsg, tuple) else smsg for smsg in stored_msg] stored_msg = [smsg[0] if isinstance(smsg, tuple) else smsg for smsg in stored_msg]
if msg is not None: if msg is not None:
returned_msg = "||".join(_RE.sub("", str(mess)) for mess in stored_msg) # set our separator for returned messages based on parsing ansi or not
returned_msg = ansi.parse_ansi(returned_msg, strip_ansi=noansi).strip() msg_sep = "|" if noansi else "||"
# Have to strip ansi for each returned message for the regex to handle it correctly
returned_msg = msg_sep.join(_RE.sub("", ansi.parse_ansi(mess, strip_ansi=noansi))
for mess in stored_msg).strip()
if msg == "" and returned_msg or not returned_msg.startswith(msg.strip()): if msg == "" and returned_msg or not returned_msg.startswith(msg.strip()):
sep1 = "\n" + "=" * 30 + "Wanted message" + "=" * 34 + "\n" sep1 = "\n" + "=" * 30 + "Wanted message" + "=" * 34 + "\n"
sep2 = "\n" + "=" * 30 + "Returned message" + "=" * 32 + "\n" sep2 = "\n" + "=" * 30 + "Returned message" + "=" * 32 + "\n"
@ -147,11 +150,11 @@ class TestGeneral(CommandTest):
def test_nick(self): def test_nick(self):
self.call(general.CmdNick(), "testalias = testaliasedstring1", self.call(general.CmdNick(), "testalias = testaliasedstring1",
"Inputlinenick 'testalias' mapped to 'testaliasedstring1'.") "Inputline-nick 'testalias' mapped to 'testaliasedstring1'.")
self.call(general.CmdNick(), "/account testalias = testaliasedstring2", self.call(general.CmdNick(), "/account testalias = testaliasedstring2",
"Accountnick 'testalias' mapped to 'testaliasedstring2'.") "Account-nick 'testalias' mapped to 'testaliasedstring2'.")
self.call(general.CmdNick(), "/object testalias = testaliasedstring3", self.call(general.CmdNick(), "/object testalias = testaliasedstring3",
"Objectnick 'testalias' mapped to 'testaliasedstring3'.") "Object-nick 'testalias' mapped to 'testaliasedstring3'.")
self.assertEqual(u"testaliasedstring1", self.char1.nicks.get("testalias")) self.assertEqual(u"testaliasedstring1", self.char1.nicks.get("testalias"))
self.assertEqual(u"testaliasedstring2", self.char1.nicks.get("testalias", category="account")) self.assertEqual(u"testaliasedstring2", self.char1.nicks.get("testalias", category="account"))
self.assertEqual(None, self.char1.account.nicks.get("testalias", category="account")) self.assertEqual(None, self.char1.account.nicks.get("testalias", category="account"))
@ -214,7 +217,7 @@ class TestSystem(CommandTest):
self.call(system.CmdPy(), "1+2", ">>> 1+2|3") self.call(system.CmdPy(), "1+2", ">>> 1+2|3")
def test_scripts(self): def test_scripts(self):
self.call(system.CmdScripts(), "", "| dbref |") self.call(system.CmdScripts(), "", "dbref ")
def test_objects(self): def test_objects(self):
self.call(system.CmdObjects(), "", "Object subtype totals") self.call(system.CmdObjects(), "", "Object subtype totals")
@ -238,14 +241,14 @@ class TestAdmin(CommandTest):
self.call(admin.CmdWall(), "Test", "Announcing to all connected sessions ...") self.call(admin.CmdWall(), "Test", "Announcing to all connected sessions ...")
def test_ban(self): def test_ban(self):
self.call(admin.CmdBan(), "Char", "NameBan char was added.") self.call(admin.CmdBan(), "Char", "Name-Ban char was added.")
class TestAccount(CommandTest): class TestAccount(CommandTest):
def test_ooc_look(self): def test_ooc_look(self):
if settings.MULTISESSION_MODE < 2: if settings.MULTISESSION_MODE < 2:
self.call(account.CmdOOCLook(), "", "You are outofcharacter (OOC).", caller=self.account) self.call(account.CmdOOCLook(), "", "You are out-of-character (OOC).", caller=self.account)
if settings.MULTISESSION_MODE == 2: if settings.MULTISESSION_MODE == 2:
self.call(account.CmdOOCLook(), "", "Account TestAccount (you are OutofCharacter)", caller=self.account) self.call(account.CmdOOCLook(), "", "Account TestAccount (you are OutofCharacter)", caller=self.account)
@ -302,8 +305,8 @@ class TestBuilding(CommandTest):
def test_attribute_commands(self): def test_attribute_commands(self):
self.call(building.CmdSetAttribute(), "Obj/test1=\"value1\"", "Created attribute Obj/test1 = 'value1'") self.call(building.CmdSetAttribute(), "Obj/test1=\"value1\"", "Created attribute Obj/test1 = 'value1'")
self.call(building.CmdSetAttribute(), "Obj2/test2=\"value2\"", "Created attribute Obj2/test2 = 'value2'") self.call(building.CmdSetAttribute(), "Obj2/test2=\"value2\"", "Created attribute Obj2/test2 = 'value2'")
self.call(building.CmdMvAttr(), "Obj2/test2 = Obj/test3", "Moved Obj2.test2 > Obj.test3") self.call(building.CmdMvAttr(), "Obj2/test2 = Obj/test3", "Moved Obj2.test2 -> Obj.test3")
self.call(building.CmdCpAttr(), "Obj/test1 = Obj2/test3", "Copied Obj.test1 > Obj2.test3") self.call(building.CmdCpAttr(), "Obj/test1 = Obj2/test3", "Copied Obj.test1 -> Obj2.test3")
self.call(building.CmdWipe(), "Obj2/test2/test3", "Wiped attributes test2,test3 on Obj2.") self.call(building.CmdWipe(), "Obj2/test2/test3", "Wiped attributes test2,test3 on Obj2.")
def test_name(self): def test_name(self):
@ -329,7 +332,7 @@ class TestBuilding(CommandTest):
def test_exit_commands(self): def test_exit_commands(self):
self.call(building.CmdOpen(), "TestExit1=Room2", "Created new Exit 'TestExit1' from Room to Room2") self.call(building.CmdOpen(), "TestExit1=Room2", "Created new Exit 'TestExit1' from Room to Room2")
self.call(building.CmdLink(), "TestExit1=Room", "Link created TestExit1 > Room (one way).") self.call(building.CmdLink(), "TestExit1=Room", "Link created TestExit1 -> Room (one way).")
self.call(building.CmdUnLink(), "TestExit1", "Former exit TestExit1 no longer links anywhere.") self.call(building.CmdUnLink(), "TestExit1", "Former exit TestExit1 no longer links anywhere.")
def test_set_home(self): def test_set_home(self):
@ -348,8 +351,8 @@ class TestBuilding(CommandTest):
def test_find(self): def test_find(self):
self.call(building.CmdFind(), "oom2", "One Match") self.call(building.CmdFind(), "oom2", "One Match")
expect = "One Match(#1#7, loc):\n " +\ expect = "One Match(#1-#7, loc):\n " +\
"Char2(#7) evennia.objects.objects.DefaultCharacter (location: Room(#1))" "Char2(#7) - evennia.objects.objects.DefaultCharacter (location: Room(#1))"
self.call(building.CmdFind(), "Char2", expect, cmdstring="locate") self.call(building.CmdFind(), "Char2", expect, cmdstring="locate")
self.call(building.CmdFind(), "/ex Char2", # /ex is an ambiguous switch self.call(building.CmdFind(), "/ex Char2", # /ex is an ambiguous switch
"locate: Ambiguous switch supplied: Did you mean /exit or /exact?|" + expect, "locate: Ambiguous switch supplied: Did you mean /exit or /exact?|" + expect,
@ -365,7 +368,7 @@ class TestBuilding(CommandTest):
def test_teleport(self): def test_teleport(self):
self.call(building.CmdTeleport(), "/quiet Room2", "Room2(#2)\n|Teleported to Room2.") self.call(building.CmdTeleport(), "/quiet Room2", "Room2(#2)\n|Teleported to Room2.")
self.call(building.CmdTeleport(), "/t", # /t switch is abbreviated form of /tonone self.call(building.CmdTeleport(), "/t", # /t switch is abbreviated form of /tonone
"Cannot teleport a puppeted object (Char, puppeted by TestAccount(account 1)) to a Nonelocation.") "Cannot teleport a puppeted object (Char, puppeted by TestAccount(account 1)) to a None-location.")
self.call(building.CmdTeleport(), "/l Room2", # /l switch is abbreviated form of /loc self.call(building.CmdTeleport(), "/l Room2", # /l switch is abbreviated form of /loc
"Destination has no location.") "Destination has no location.")
self.call(building.CmdTeleport(), "/q me to Room2", # /q switch is abbreviated form of /quiet self.call(building.CmdTeleport(), "/q me to Room2", # /q switch is abbreviated form of /quiet
@ -392,7 +395,7 @@ class TestBuilding(CommandTest):
"'typeclass':'evennia.objects.objects.DefaultCharacter'}", "'typeclass':'evennia.objects.objects.DefaultCharacter'}",
"Saved prototype: testprot", inputs=['y']) "Saved prototype: testprot", inputs=['y'])
self.call(building.CmdSpawn(), "/list", "| Key ") self.call(building.CmdSpawn(), "/list", "Key ")
self.call(building.CmdSpawn(), 'testprot', "Spawned Test Char") self.call(building.CmdSpawn(), 'testprot', "Spawned Test Char")
# Tests that the spawned object's location is the same as the caharacter's location, since # Tests that the spawned object's location is the same as the caharacter's location, since
@ -455,7 +458,7 @@ class TestBuilding(CommandTest):
self.call(building.CmdSpawn(), "'NO_EXIST'", "No prototype named 'NO_EXIST'") self.call(building.CmdSpawn(), "'NO_EXIST'", "No prototype named 'NO_EXIST'")
# Test listing commands # Test listing commands
self.call(building.CmdSpawn(), "/list", "| Key ") self.call(building.CmdSpawn(), "/list", "Key ")
class TestComms(CommandTest): class TestComms(CommandTest):
@ -512,7 +515,7 @@ class TestBatchProcess(CommandTest):
def test_batch_commands(self): def test_batch_commands(self):
# cannot test batchcode here, it must run inside the server process # cannot test batchcode here, it must run inside the server process
self.call(batchprocess.CmdBatchCommands(), "example_batch_cmds", self.call(batchprocess.CmdBatchCommands(), "example_batch_cmds",
"Running Batchcommand processor Automatic mode for example_batch_cmds") "Running Batch-command processor - Automatic mode for example_batch_cmds")
# we make sure to delete the button again here to stop the running reactor # we make sure to delete the button again here to stop the running reactor
confirm = building.CmdDestroy.confirm confirm = building.CmdDestroy.confirm
building.CmdDestroy.confirm = False building.CmdDestroy.confirm = False
@ -542,5 +545,5 @@ class TestUnconnectedCommand(CommandTest):
expected = "## BEGIN INFO 1.1\nName: %s\nUptime: %s\nConnected: %d\nVersion: Evennia %s\n## END INFO" % ( expected = "## BEGIN INFO 1.1\nName: %s\nUptime: %s\nConnected: %d\nVersion: Evennia %s\n## END INFO" % (
settings.SERVERNAME, settings.SERVERNAME,
datetime.datetime.fromtimestamp(gametime.SERVER_START_TIME).ctime(), datetime.datetime.fromtimestamp(gametime.SERVER_START_TIME).ctime(),
SESSIONS.account_count(), utils.get_evennia_version().replace("-", "")) SESSIONS.account_count(), utils.get_evennia_version())
self.call(unloggedin.CmdUnconnectedInfo(), "", expected) self.call(unloggedin.CmdUnconnectedInfo(), "", expected)

View file

@ -97,7 +97,8 @@ class DefaultChannel(with_metaclass(TypeclassBase, ChannelDB)):
@property @property
def wholist(self): def wholist(self):
subs = self.subscriptions.all() subs = self.subscriptions.all()
listening = [ob for ob in subs if ob.is_connected and ob not in self.mutelist] muted = list(self.mutelist)
listening = [ob for ob in subs if ob.is_connected and ob not in muted]
if subs: if subs:
# display listening subscribers in bold # display listening subscribers in bold
string = ", ".join([account.key if account not in listening else "|w%s|n" % account.key for account in subs]) string = ", ".join([account.key if account not in listening else "|w%s|n" % account.key for account in subs])

View file

@ -723,9 +723,9 @@ class TestMapBuilder(CommandTest):
"evennia.contrib.mapbuilder.EXAMPLE2_MAP evennia.contrib.mapbuilder.EXAMPLE2_LEGEND", "evennia.contrib.mapbuilder.EXAMPLE2_MAP evennia.contrib.mapbuilder.EXAMPLE2_LEGEND",
"""Creating Map...|≈ ≈ ≈ ≈ ≈ """Creating Map...|≈ ≈ ≈ ≈ ≈
--
--
|Creating Landmass...|""") |Creating Landmass...|""")
@ -768,8 +768,8 @@ from evennia.contrib import simpledoor
class TestSimpleDoor(CommandTest): class TestSimpleDoor(CommandTest):
def test_cmdopen(self): def test_cmdopen(self):
self.call(simpledoor.CmdOpen(), "newdoor;door:contrib.simpledoor.SimpleDoor,backdoor;door = Room2", self.call(simpledoor.CmdOpen(), "newdoor;door:contrib.simpledoor.SimpleDoor,backdoor;door = Room2",
"Created new Exit 'newdoor' from Room to Room2 (aliases: door).|Note: A doortype exit was " "Created new Exit 'newdoor' from Room to Room2 (aliases: door).|Note: A door-type exit was "
"created ignored eventual custom returnexit type.|Created new Exit 'newdoor' from Room2 to Room (aliases: door).") "created - ignored eventual custom return-exit type.|Created new Exit 'newdoor' from Room2 to Room (aliases: door).")
self.call(simpledoor.CmdOpenCloseDoor(), "newdoor", "You close newdoor.", cmdstring="close") self.call(simpledoor.CmdOpenCloseDoor(), "newdoor", "You close newdoor.", cmdstring="close")
self.call(simpledoor.CmdOpenCloseDoor(), "newdoor", "newdoor is already closed.", cmdstring="close") self.call(simpledoor.CmdOpenCloseDoor(), "newdoor", "newdoor is already closed.", cmdstring="close")
self.call(simpledoor.CmdOpenCloseDoor(), "newdoor", "You open newdoor.", cmdstring="open") self.call(simpledoor.CmdOpenCloseDoor(), "newdoor", "You open newdoor.", cmdstring="open")
@ -953,13 +953,13 @@ class TestTutorialWorldRooms(CommandTest):
# test turnbattle # test turnbattle
from evennia.contrib.turnbattle import tb_basic, tb_equip, tb_range from evennia.contrib.turnbattle import tb_basic, tb_equip, tb_range, tb_items, tb_magic
from evennia.objects.objects import DefaultRoom from evennia.objects.objects import DefaultRoom
class TestTurnBattleCmd(CommandTest): class TestTurnBattleBasicCmd(CommandTest):
# Test combat commands # Test basic combat commands
def test_turnbattlecmd(self): def test_turnbattlecmd(self):
self.call(tb_basic.CmdFight(), "", "You can't start a fight if you've been defeated!") self.call(tb_basic.CmdFight(), "", "You can't start a fight if you've been defeated!")
self.call(tb_basic.CmdAttack(), "", "You can only do that in combat. (see: help fight)") self.call(tb_basic.CmdAttack(), "", "You can only do that in combat. (see: help fight)")
@ -967,13 +967,19 @@ class TestTurnBattleCmd(CommandTest):
self.call(tb_basic.CmdDisengage(), "", "You can only do that in combat. (see: help fight)") self.call(tb_basic.CmdDisengage(), "", "You can only do that in combat. (see: help fight)")
self.call(tb_basic.CmdRest(), "", "Char rests to recover HP.") self.call(tb_basic.CmdRest(), "", "Char rests to recover HP.")
class TestTurnBattleEquipCmd(CommandTest):
def setUp(self):
super(TestTurnBattleEquipCmd, self).setUp()
self.testweapon = create_object(tb_equip.TBEWeapon, key="test weapon")
self.testarmor = create_object(tb_equip.TBEArmor, key="test armor")
self.testweapon.move_to(self.char1)
self.testarmor.move_to(self.char1)
# Test equipment commands # Test equipment commands
def test_turnbattleequipcmd(self): def test_turnbattleequipcmd(self):
# Start with equip module specific commands. # Start with equip module specific commands.
testweapon = create_object(tb_equip.TBEWeapon, key="test weapon")
testarmor = create_object(tb_equip.TBEArmor, key="test armor")
testweapon.move_to(self.char1)
testarmor.move_to(self.char1)
self.call(tb_equip.CmdWield(), "weapon", "Char wields test weapon.") self.call(tb_equip.CmdWield(), "weapon", "Char wields test weapon.")
self.call(tb_equip.CmdUnwield(), "", "Char lowers test weapon.") self.call(tb_equip.CmdUnwield(), "", "Char lowers test weapon.")
self.call(tb_equip.CmdDon(), "armor", "Char dons test armor.") self.call(tb_equip.CmdDon(), "armor", "Char dons test armor.")
@ -985,6 +991,8 @@ class TestTurnBattleCmd(CommandTest):
self.call(tb_equip.CmdDisengage(), "", "You can only do that in combat. (see: help fight)") self.call(tb_equip.CmdDisengage(), "", "You can only do that in combat. (see: help fight)")
self.call(tb_equip.CmdRest(), "", "Char rests to recover HP.") self.call(tb_equip.CmdRest(), "", "Char rests to recover HP.")
class TestTurnBattleRangeCmd(CommandTest):
# Test range commands # Test range commands
def test_turnbattlerangecmd(self): def test_turnbattlerangecmd(self):
# Start with range module specific commands. # Start with range module specific commands.
@ -999,258 +1007,531 @@ class TestTurnBattleCmd(CommandTest):
self.call(tb_range.CmdDisengage(), "", "You can only do that in combat. (see: help fight)") self.call(tb_range.CmdDisengage(), "", "You can only do that in combat. (see: help fight)")
self.call(tb_range.CmdRest(), "", "Char rests to recover HP.") self.call(tb_range.CmdRest(), "", "Char rests to recover HP.")
class TestTurnBattleItemsCmd(CommandTest):
class TestTurnBattleFunc(EvenniaTest): def setUp(self):
super(TestTurnBattleItemsCmd, self).setUp()
self.testitem = create_object(key="test item")
self.testitem.move_to(self.char1)
# Test item commands
def test_turnbattleitemcmd(self):
self.call(tb_items.CmdUse(), "item", "'Test item' is not a usable item.")
# Also test the commands that are the same in the basic module
self.call(tb_items.CmdFight(), "", "You can't start a fight if you've been defeated!")
self.call(tb_items.CmdAttack(), "", "You can only do that in combat. (see: help fight)")
self.call(tb_items.CmdPass(), "", "You can only do that in combat. (see: help fight)")
self.call(tb_items.CmdDisengage(), "", "You can only do that in combat. (see: help fight)")
self.call(tb_items.CmdRest(), "", "Char rests to recover HP.")
class TestTurnBattleMagicCmd(CommandTest):
# Test magic commands
def test_turnbattlemagiccmd(self):
self.call(tb_magic.CmdStatus(), "", "You have 100 / 100 HP and 20 / 20 MP.")
self.call(tb_magic.CmdLearnSpell(), "test spell", "There is no spell with that name.")
self.call(tb_magic.CmdCast(), "", "Usage: cast <spell name> = <target>, <target2>")
# Also test the commands that are the same in the basic module
self.call(tb_magic.CmdFight(), "", "There's nobody here to fight!")
self.call(tb_magic.CmdAttack(), "", "You can only do that in combat. (see: help fight)")
self.call(tb_magic.CmdPass(), "", "You can only do that in combat. (see: help fight)")
self.call(tb_magic.CmdDisengage(), "", "You can only do that in combat. (see: help fight)")
self.call(tb_magic.CmdRest(), "", "Char rests to recover HP and MP.")
class TestTurnBattleBasicFunc(EvenniaTest):
def setUp(self):
super(TestTurnBattleBasicFunc, self).setUp()
self.testroom = create_object(DefaultRoom, key="Test Room")
self.attacker = create_object(tb_basic.TBBasicCharacter, key="Attacker", location=self.testroom)
self.defender = create_object(tb_basic.TBBasicCharacter, key="Defender", location=self.testroom)
self.joiner = create_object(tb_basic.TBBasicCharacter, key="Joiner", location=None)
def tearDown(self):
super(TestTurnBattleBasicFunc, self).tearDown()
self.attacker.delete()
self.defender.delete()
self.joiner.delete()
self.testroom.delete()
self.turnhandler.stop()
# Test combat functions # Test combat functions
def test_tbbasicfunc(self): def test_tbbasicfunc(self):
attacker = create_object(tb_basic.TBBasicCharacter, key="Attacker")
defender = create_object(tb_basic.TBBasicCharacter, key="Defender")
testroom = create_object(DefaultRoom, key="Test Room")
attacker.location = testroom
defender.loaction = testroom
# Initiative roll # Initiative roll
initiative = tb_basic.roll_init(attacker) initiative = tb_basic.roll_init(self.attacker)
self.assertTrue(initiative >= 0 and initiative <= 1000) self.assertTrue(initiative >= 0 and initiative <= 1000)
# Attack roll # Attack roll
attack_roll = tb_basic.get_attack(attacker, defender) attack_roll = tb_basic.get_attack(self.attacker, self.defender)
self.assertTrue(attack_roll >= 0 and attack_roll <= 100) self.assertTrue(attack_roll >= 0 and attack_roll <= 100)
# Defense roll # Defense roll
defense_roll = tb_basic.get_defense(attacker, defender) defense_roll = tb_basic.get_defense(self.attacker, self.defender)
self.assertTrue(defense_roll == 50) self.assertTrue(defense_roll == 50)
# Damage roll # Damage roll
damage_roll = tb_basic.get_damage(attacker, defender) damage_roll = tb_basic.get_damage(self.attacker, self.defender)
self.assertTrue(damage_roll >= 15 and damage_roll <= 25) self.assertTrue(damage_roll >= 15 and damage_roll <= 25)
# Apply damage # Apply damage
defender.db.hp = 10 self.defender.db.hp = 10
tb_basic.apply_damage(defender, 3) tb_basic.apply_damage(self.defender, 3)
self.assertTrue(defender.db.hp == 7) self.assertTrue(self.defender.db.hp == 7)
# Resolve attack # Resolve attack
defender.db.hp = 40 self.defender.db.hp = 40
tb_basic.resolve_attack(attacker, defender, attack_value=20, defense_value=10) tb_basic.resolve_attack(self.attacker, self.defender, attack_value=20, defense_value=10)
self.assertTrue(defender.db.hp < 40) self.assertTrue(self.defender.db.hp < 40)
# Combat cleanup # Combat cleanup
attacker.db.Combat_attribute = True self.attacker.db.Combat_attribute = True
tb_basic.combat_cleanup(attacker) tb_basic.combat_cleanup(self.attacker)
self.assertFalse(attacker.db.combat_attribute) self.assertFalse(self.attacker.db.combat_attribute)
# Is in combat # Is in combat
self.assertFalse(tb_basic.is_in_combat(attacker)) self.assertFalse(tb_basic.is_in_combat(self.attacker))
# Set up turn handler script for further tests # Set up turn handler script for further tests
attacker.location.scripts.add(tb_basic.TBBasicTurnHandler) self.attacker.location.scripts.add(tb_basic.TBBasicTurnHandler)
turnhandler = attacker.db.combat_TurnHandler self.turnhandler = self.attacker.db.combat_TurnHandler
self.assertTrue(attacker.db.combat_TurnHandler) self.assertTrue(self.attacker.db.combat_TurnHandler)
# Set the turn handler's interval very high to keep it from repeating during tests. # Set the turn handler's interval very high to keep it from repeating during tests.
turnhandler.interval = 10000 self.turnhandler.interval = 10000
# Force turn order # Force turn order
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
# Test is turn # Test is turn
self.assertTrue(tb_basic.is_turn(attacker)) self.assertTrue(tb_basic.is_turn(self.attacker))
# Spend actions # Spend actions
attacker.db.Combat_ActionsLeft = 1 self.attacker.db.Combat_ActionsLeft = 1
tb_basic.spend_action(attacker, 1, action_name="Test") tb_basic.spend_action(self.attacker, 1, action_name="Test")
self.assertTrue(attacker.db.Combat_ActionsLeft == 0) self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(attacker.db.Combat_LastAction == "Test") self.assertTrue(self.attacker.db.Combat_LastAction == "Test")
# Initialize for combat # Initialize for combat
attacker.db.Combat_ActionsLeft = 983 self.attacker.db.Combat_ActionsLeft = 983
turnhandler.initialize_for_combat(attacker) self.turnhandler.initialize_for_combat(self.attacker)
self.assertTrue(attacker.db.Combat_ActionsLeft == 0) self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(attacker.db.Combat_LastAction == "null") self.assertTrue(self.attacker.db.Combat_LastAction == "null")
# Start turn # Start turn
defender.db.Combat_ActionsLeft = 0 self.defender.db.Combat_ActionsLeft = 0
turnhandler.start_turn(defender) self.turnhandler.start_turn(self.defender)
self.assertTrue(defender.db.Combat_ActionsLeft == 1) self.assertTrue(self.defender.db.Combat_ActionsLeft == 1)
# Next turn # Next turn
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
turnhandler.next_turn() self.turnhandler.next_turn()
self.assertTrue(turnhandler.db.turn == 1) self.assertTrue(self.turnhandler.db.turn == 1)
# Turn end check # Turn end check
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
attacker.db.Combat_ActionsLeft = 0 self.attacker.db.Combat_ActionsLeft = 0
turnhandler.turn_end_check(attacker) self.turnhandler.turn_end_check(self.attacker)
self.assertTrue(turnhandler.db.turn == 1) self.assertTrue(self.turnhandler.db.turn == 1)
# Join fight # Join fight
joiner = create_object(tb_basic.TBBasicCharacter, key="Joiner") self.joiner.location = self.testroom
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
turnhandler.join_fight(joiner) self.turnhandler.join_fight(self.joiner)
self.assertTrue(turnhandler.db.turn == 1) self.assertTrue(self.turnhandler.db.turn == 1)
self.assertTrue(turnhandler.db.fighters == [joiner, attacker, defender]) self.assertTrue(self.turnhandler.db.fighters == [self.joiner, self.attacker, self.defender])
# Remove the script at the end
turnhandler.stop()
class TestTurnBattleEquipFunc(EvenniaTest):
def setUp(self):
super(TestTurnBattleEquipFunc, self).setUp()
self.testroom = create_object(DefaultRoom, key="Test Room")
self.attacker = create_object(tb_equip.TBEquipCharacter, key="Attacker", location=self.testroom)
self.defender = create_object(tb_equip.TBEquipCharacter, key="Defender", location=self.testroom)
self.joiner = create_object(tb_equip.TBEquipCharacter, key="Joiner", location=None)
def tearDown(self):
super(TestTurnBattleEquipFunc, self).tearDown()
self.attacker.delete()
self.defender.delete()
self.joiner.delete()
self.testroom.delete()
self.turnhandler.stop()
# Test the combat functions in tb_equip too. They work mostly the same. # Test the combat functions in tb_equip too. They work mostly the same.
def test_tbequipfunc(self): def test_tbequipfunc(self):
attacker = create_object(tb_equip.TBEquipCharacter, key="Attacker")
defender = create_object(tb_equip.TBEquipCharacter, key="Defender")
testroom = create_object(DefaultRoom, key="Test Room")
attacker.location = testroom
defender.loaction = testroom
# Initiative roll # Initiative roll
initiative = tb_equip.roll_init(attacker) initiative = tb_equip.roll_init(self.attacker)
self.assertTrue(initiative >= 0 and initiative <= 1000) self.assertTrue(initiative >= 0 and initiative <= 1000)
# Attack roll # Attack roll
attack_roll = tb_equip.get_attack(attacker, defender) attack_roll = tb_equip.get_attack(self.attacker, self.defender)
self.assertTrue(attack_roll >= -50 and attack_roll <= 150) self.assertTrue(attack_roll >= -50 and attack_roll <= 150)
# Defense roll # Defense roll
defense_roll = tb_equip.get_defense(attacker, defender) defense_roll = tb_equip.get_defense(self.attacker, self.defender)
self.assertTrue(defense_roll == 50) self.assertTrue(defense_roll == 50)
# Damage roll # Damage roll
damage_roll = tb_equip.get_damage(attacker, defender) damage_roll = tb_equip.get_damage(self.attacker, self.defender)
self.assertTrue(damage_roll >= 0 and damage_roll <= 50) self.assertTrue(damage_roll >= 0 and damage_roll <= 50)
# Apply damage # Apply damage
defender.db.hp = 10 self.defender.db.hp = 10
tb_equip.apply_damage(defender, 3) tb_equip.apply_damage(self.defender, 3)
self.assertTrue(defender.db.hp == 7) self.assertTrue(self.defender.db.hp == 7)
# Resolve attack # Resolve attack
defender.db.hp = 40 self.defender.db.hp = 40
tb_equip.resolve_attack(attacker, defender, attack_value=20, defense_value=10) tb_equip.resolve_attack(self.attacker, self.defender, attack_value=20, defense_value=10)
self.assertTrue(defender.db.hp < 40) self.assertTrue(self.defender.db.hp < 40)
# Combat cleanup # Combat cleanup
attacker.db.Combat_attribute = True self.attacker.db.Combat_attribute = True
tb_equip.combat_cleanup(attacker) tb_equip.combat_cleanup(self.attacker)
self.assertFalse(attacker.db.combat_attribute) self.assertFalse(self.attacker.db.combat_attribute)
# Is in combat # Is in combat
self.assertFalse(tb_equip.is_in_combat(attacker)) self.assertFalse(tb_equip.is_in_combat(self.attacker))
# Set up turn handler script for further tests # Set up turn handler script for further tests
attacker.location.scripts.add(tb_equip.TBEquipTurnHandler) self.attacker.location.scripts.add(tb_equip.TBEquipTurnHandler)
turnhandler = attacker.db.combat_TurnHandler self.turnhandler = self.attacker.db.combat_TurnHandler
self.assertTrue(attacker.db.combat_TurnHandler) self.assertTrue(self.attacker.db.combat_TurnHandler)
# Set the turn handler's interval very high to keep it from repeating during tests. # Set the turn handler's interval very high to keep it from repeating during tests.
turnhandler.interval = 10000 self.turnhandler.interval = 10000
# Force turn order # Force turn order
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
# Test is turn # Test is turn
self.assertTrue(tb_equip.is_turn(attacker)) self.assertTrue(tb_equip.is_turn(self.attacker))
# Spend actions # Spend actions
attacker.db.Combat_ActionsLeft = 1 self.attacker.db.Combat_ActionsLeft = 1
tb_equip.spend_action(attacker, 1, action_name="Test") tb_equip.spend_action(self.attacker, 1, action_name="Test")
self.assertTrue(attacker.db.Combat_ActionsLeft == 0) self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(attacker.db.Combat_LastAction == "Test") self.assertTrue(self.attacker.db.Combat_LastAction == "Test")
# Initialize for combat # Initialize for combat
attacker.db.Combat_ActionsLeft = 983 self.attacker.db.Combat_ActionsLeft = 983
turnhandler.initialize_for_combat(attacker) self.turnhandler.initialize_for_combat(self.attacker)
self.assertTrue(attacker.db.Combat_ActionsLeft == 0) self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(attacker.db.Combat_LastAction == "null") self.assertTrue(self.attacker.db.Combat_LastAction == "null")
# Start turn # Start turn
defender.db.Combat_ActionsLeft = 0 self.defender.db.Combat_ActionsLeft = 0
turnhandler.start_turn(defender) self.turnhandler.start_turn(self.defender)
self.assertTrue(defender.db.Combat_ActionsLeft == 1) self.assertTrue(self.defender.db.Combat_ActionsLeft == 1)
# Next turn # Next turn
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
turnhandler.next_turn() self.turnhandler.next_turn()
self.assertTrue(turnhandler.db.turn == 1) self.assertTrue(self.turnhandler.db.turn == 1)
# Turn end check # Turn end check
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
attacker.db.Combat_ActionsLeft = 0 self.attacker.db.Combat_ActionsLeft = 0
turnhandler.turn_end_check(attacker) self.turnhandler.turn_end_check(self.attacker)
self.assertTrue(turnhandler.db.turn == 1) self.assertTrue(self.turnhandler.db.turn == 1)
# Join fight # Join fight
joiner = create_object(tb_equip.TBEquipCharacter, key="Joiner") self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.turn = 0
turnhandler.db.turn = 0 self.turnhandler.join_fight(self.joiner)
turnhandler.join_fight(joiner) self.assertTrue(self.turnhandler.db.turn == 1)
self.assertTrue(turnhandler.db.turn == 1) self.assertTrue(self.turnhandler.db.fighters == [self.joiner, self.attacker, self.defender])
self.assertTrue(turnhandler.db.fighters == [joiner, attacker, defender])
# Remove the script at the end
turnhandler.stop() class TestTurnBattleRangeFunc(EvenniaTest):
def setUp(self):
super(TestTurnBattleRangeFunc, self).setUp()
self.testroom = create_object(DefaultRoom, key="Test Room")
self.attacker = create_object(tb_range.TBRangeCharacter, key="Attacker", location=self.testroom)
self.defender = create_object(tb_range.TBRangeCharacter, key="Defender", location=self.testroom)
self.joiner = create_object(tb_range.TBRangeCharacter, key="Joiner", location=self.testroom)
def tearDown(self):
super(TestTurnBattleRangeFunc, self).tearDown()
self.attacker.delete()
self.defender.delete()
self.joiner.delete()
self.testroom.delete()
self.turnhandler.stop()
# Test combat functions in tb_range too. # Test combat functions in tb_range too.
def test_tbrangefunc(self): def test_tbrangefunc(self):
testroom = create_object(DefaultRoom, key="Test Room")
attacker = create_object(tb_range.TBRangeCharacter, key="Attacker", location=testroom)
defender = create_object(tb_range.TBRangeCharacter, key="Defender", location=testroom)
# Initiative roll # Initiative roll
initiative = tb_range.roll_init(attacker) initiative = tb_range.roll_init(self.attacker)
self.assertTrue(initiative >= 0 and initiative <= 1000) self.assertTrue(initiative >= 0 and initiative <= 1000)
# Attack roll # Attack roll
attack_roll = tb_range.get_attack(attacker, defender, "test") attack_roll = tb_range.get_attack(self.attacker, self.defender, "test")
self.assertTrue(attack_roll >= 0 and attack_roll <= 100) self.assertTrue(attack_roll >= 0 and attack_roll <= 100)
# Defense roll # Defense roll
defense_roll = tb_range.get_defense(attacker, defender, "test") defense_roll = tb_range.get_defense(self.attacker, self.defender, "test")
self.assertTrue(defense_roll == 50) self.assertTrue(defense_roll == 50)
# Damage roll # Damage roll
damage_roll = tb_range.get_damage(attacker, defender) damage_roll = tb_range.get_damage(self.attacker, self.defender)
self.assertTrue(damage_roll >= 15 and damage_roll <= 25) self.assertTrue(damage_roll >= 15 and damage_roll <= 25)
# Apply damage # Apply damage
defender.db.hp = 10 self.defender.db.hp = 10
tb_range.apply_damage(defender, 3) tb_range.apply_damage(self.defender, 3)
self.assertTrue(defender.db.hp == 7) self.assertTrue(self.defender.db.hp == 7)
# Resolve attack # Resolve attack
defender.db.hp = 40 self.defender.db.hp = 40
tb_range.resolve_attack(attacker, defender, "test", attack_value=20, defense_value=10) tb_range.resolve_attack(self.attacker, self.defender, "test", attack_value=20, defense_value=10)
self.assertTrue(defender.db.hp < 40) self.assertTrue(self.defender.db.hp < 40)
# Combat cleanup # Combat cleanup
attacker.db.Combat_attribute = True self.attacker.db.Combat_attribute = True
tb_range.combat_cleanup(attacker) tb_range.combat_cleanup(self.attacker)
self.assertFalse(attacker.db.combat_attribute) self.assertFalse(self.attacker.db.combat_attribute)
# Is in combat # Is in combat
self.assertFalse(tb_range.is_in_combat(attacker)) self.assertFalse(tb_range.is_in_combat(self.attacker))
# Set up turn handler script for further tests # Set up turn handler script for further tests
attacker.location.scripts.add(tb_range.TBRangeTurnHandler) self.attacker.location.scripts.add(tb_range.TBRangeTurnHandler)
turnhandler = attacker.db.combat_TurnHandler self.turnhandler = self.attacker.db.combat_TurnHandler
self.assertTrue(attacker.db.combat_TurnHandler) self.assertTrue(self.attacker.db.combat_TurnHandler)
# Set the turn handler's interval very high to keep it from repeating during tests. # Set the turn handler's interval very high to keep it from repeating during tests.
turnhandler.interval = 10000 self.turnhandler.interval = 10000
# Force turn order # Force turn order
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
# Test is turn # Test is turn
self.assertTrue(tb_range.is_turn(attacker)) self.assertTrue(tb_range.is_turn(self.attacker))
# Spend actions # Spend actions
attacker.db.Combat_ActionsLeft = 1 self.attacker.db.Combat_ActionsLeft = 1
tb_range.spend_action(attacker, 1, action_name="Test") tb_range.spend_action(self.attacker, 1, action_name="Test")
self.assertTrue(attacker.db.Combat_ActionsLeft == 0) self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(attacker.db.Combat_LastAction == "Test") self.assertTrue(self.attacker.db.Combat_LastAction == "Test")
# Initialize for combat # Initialize for combat
attacker.db.Combat_ActionsLeft = 983 self.attacker.db.Combat_ActionsLeft = 983
turnhandler.initialize_for_combat(attacker) self.turnhandler.initialize_for_combat(self.attacker)
self.assertTrue(attacker.db.Combat_ActionsLeft == 0) self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(attacker.db.Combat_LastAction == "null") self.assertTrue(self.attacker.db.Combat_LastAction == "null")
# Set up ranges again, since initialize_for_combat clears them # Set up ranges again, since initialize_for_combat clears them
attacker.db.combat_range = {} self.attacker.db.combat_range = {}
attacker.db.combat_range[attacker] = 0 self.attacker.db.combat_range[self.attacker] = 0
attacker.db.combat_range[defender] = 1 self.attacker.db.combat_range[self.defender] = 1
defender.db.combat_range = {} self.defender.db.combat_range = {}
defender.db.combat_range[defender] = 0 self.defender.db.combat_range[self.defender] = 0
defender.db.combat_range[attacker] = 1 self.defender.db.combat_range[self.attacker] = 1
# Start turn # Start turn
defender.db.Combat_ActionsLeft = 0 self.defender.db.Combat_ActionsLeft = 0
turnhandler.start_turn(defender) self.turnhandler.start_turn(self.defender)
self.assertTrue(defender.db.Combat_ActionsLeft == 2) self.assertTrue(self.defender.db.Combat_ActionsLeft == 2)
# Next turn # Next turn
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
turnhandler.next_turn() self.turnhandler.next_turn()
self.assertTrue(turnhandler.db.turn == 1) self.assertTrue(self.turnhandler.db.turn == 1)
# Turn end check # Turn end check
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.turn = 0 self.turnhandler.db.turn = 0
attacker.db.Combat_ActionsLeft = 0 self.attacker.db.Combat_ActionsLeft = 0
turnhandler.turn_end_check(attacker) self.turnhandler.turn_end_check(self.attacker)
self.assertTrue(turnhandler.db.turn == 1) self.assertTrue(self.turnhandler.db.turn == 1)
# Join fight # Join fight
joiner = create_object(tb_range.TBRangeCharacter, key="Joiner", location=testroom) self.turnhandler.db.fighters = [self.attacker, self.defender]
turnhandler.db.fighters = [attacker, defender] self.turnhandler.db.turn = 0
turnhandler.db.turn = 0 self.turnhandler.join_fight(self.joiner)
turnhandler.join_fight(joiner) self.assertTrue(self.turnhandler.db.turn == 1)
self.assertTrue(turnhandler.db.turn == 1) self.assertTrue(self.turnhandler.db.fighters == [self.joiner, self.attacker, self.defender])
self.assertTrue(turnhandler.db.fighters == [joiner, attacker, defender])
# Now, test for approach/withdraw functions # Now, test for approach/withdraw functions
self.assertTrue(tb_range.get_range(attacker, defender) == 1) self.assertTrue(tb_range.get_range(self.attacker, self.defender) == 1)
# Approach # Approach
tb_range.approach(attacker, defender) tb_range.approach(self.attacker, self.defender)
self.assertTrue(tb_range.get_range(attacker, defender) == 0) self.assertTrue(tb_range.get_range(self.attacker, self.defender) == 0)
# Withdraw # Withdraw
tb_range.withdraw(attacker, defender) tb_range.withdraw(self.attacker, self.defender)
self.assertTrue(tb_range.get_range(attacker, defender) == 1) self.assertTrue(tb_range.get_range(self.attacker, self.defender) == 1)
# Remove the script at the end
turnhandler.stop()
class TestTurnBattleItemsFunc(EvenniaTest):
@patch("evennia.contrib.turnbattle.tb_items.tickerhandler", new=MagicMock())
def setUp(self):
super(TestTurnBattleItemsFunc, self).setUp()
self.testroom = create_object(DefaultRoom, key="Test Room")
self.attacker = create_object(tb_items.TBItemsCharacter, key="Attacker", location=self.testroom)
self.defender = create_object(tb_items.TBItemsCharacter, key="Defender", location=self.testroom)
self.joiner = create_object(tb_items.TBItemsCharacter, key="Joiner", location=self.testroom)
self.user = create_object(tb_items.TBItemsCharacter, key="User", location=self.testroom)
self.test_healpotion = create_object(key="healing potion")
self.test_healpotion.db.item_func = "heal"
self.test_healpotion.db.item_uses = 3
def tearDown(self):
super(TestTurnBattleItemsFunc, self).tearDown()
self.attacker.delete()
self.defender.delete()
self.joiner.delete()
self.user.delete()
self.testroom.delete()
self.turnhandler.stop()
# Test functions in tb_items.
def test_tbitemsfunc(self):
# Initiative roll
initiative = tb_items.roll_init(self.attacker)
self.assertTrue(initiative >= 0 and initiative <= 1000)
# Attack roll
attack_roll = tb_items.get_attack(self.attacker, self.defender)
self.assertTrue(attack_roll >= 0 and attack_roll <= 100)
# Defense roll
defense_roll = tb_items.get_defense(self.attacker, self.defender)
self.assertTrue(defense_roll == 50)
# Damage roll
damage_roll = tb_items.get_damage(self.attacker, self.defender)
self.assertTrue(damage_roll >= 15 and damage_roll <= 25)
# Apply damage
self.defender.db.hp = 10
tb_items.apply_damage(self.defender, 3)
self.assertTrue(self.defender.db.hp == 7)
# Resolve attack
self.defender.db.hp = 40
tb_items.resolve_attack(self.attacker, self.defender, attack_value=20, defense_value=10)
self.assertTrue(self.defender.db.hp < 40)
# Combat cleanup
self.attacker.db.Combat_attribute = True
tb_items.combat_cleanup(self.attacker)
self.assertFalse(self.attacker.db.combat_attribute)
# Is in combat
self.assertFalse(tb_items.is_in_combat(self.attacker))
# Set up turn handler script for further tests
self.attacker.location.scripts.add(tb_items.TBItemsTurnHandler)
self.turnhandler = self.attacker.db.combat_TurnHandler
self.assertTrue(self.attacker.db.combat_TurnHandler)
# Set the turn handler's interval very high to keep it from repeating during tests.
self.turnhandler.interval = 10000
# Force turn order
self.turnhandler.db.fighters = [self.attacker, self.defender]
self.turnhandler.db.turn = 0
# Test is turn
self.assertTrue(tb_items.is_turn(self.attacker))
# Spend actions
self.attacker.db.Combat_ActionsLeft = 1
tb_items.spend_action(self.attacker, 1, action_name="Test")
self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(self.attacker.db.Combat_LastAction == "Test")
# Initialize for combat
self.attacker.db.Combat_ActionsLeft = 983
self.turnhandler.initialize_for_combat(self.attacker)
self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(self.attacker.db.Combat_LastAction == "null")
# Start turn
self.defender.db.Combat_ActionsLeft = 0
self.turnhandler.start_turn(self.defender)
self.assertTrue(self.defender.db.Combat_ActionsLeft == 1)
# Next turn
self.turnhandler.db.fighters = [self.attacker, self.defender]
self.turnhandler.db.turn = 0
self.turnhandler.next_turn()
self.assertTrue(self.turnhandler.db.turn == 1)
# Turn end check
self.turnhandler.db.fighters = [self.attacker, self.defender]
self.turnhandler.db.turn = 0
self.attacker.db.Combat_ActionsLeft = 0
self.turnhandler.turn_end_check(self.attacker)
self.assertTrue(self.turnhandler.db.turn == 1)
# Join fight
self.turnhandler.db.fighters = [self.attacker, self.defender]
self.turnhandler.db.turn = 0
self.turnhandler.join_fight(self.joiner)
self.assertTrue(self.turnhandler.db.turn == 1)
self.assertTrue(self.turnhandler.db.fighters == [self.joiner, self.attacker, self.defender])
# Now time to test item stuff.
# Spend item use
tb_items.spend_item_use(self.test_healpotion, self.user)
self.assertTrue(self.test_healpotion.db.item_uses == 2)
# Use item
self.user.db.hp = 2
tb_items.use_item(self.user, self.test_healpotion, self.user)
self.assertTrue(self.user.db.hp > 2)
# Add contition
tb_items.add_condition(self.user, self.user, "Test", 5)
self.assertTrue(self.user.db.conditions == {"Test":[5, self.user]})
# Condition tickdown
tb_items.condition_tickdown(self.user, self.user)
self.assertTrue(self.user.db.conditions == {"Test":[4, self.user]})
# Test item functions now!
# Item heal
self.user.db.hp = 2
tb_items.itemfunc_heal(self.test_healpotion, self.user, self.user)
# Item add condition
self.user.db.conditions = {}
tb_items.itemfunc_add_condition(self.test_healpotion, self.user, self.user)
self.assertTrue(self.user.db.conditions == {"Regeneration":[5, self.user]})
# Item cure condition
self.user.db.conditions = {"Poisoned":[5, self.user]}
tb_items.itemfunc_cure_condition(self.test_healpotion, self.user, self.user)
self.assertTrue(self.user.db.conditions == {})
class TestTurnBattleMagicFunc(EvenniaTest):
def setUp(self):
super(TestTurnBattleMagicFunc, self).setUp()
self.testroom = create_object(DefaultRoom, key="Test Room")
self.attacker = create_object(tb_magic.TBMagicCharacter, key="Attacker", location=self.testroom)
self.defender = create_object(tb_magic.TBMagicCharacter, key="Defender", location=self.testroom)
self.joiner = create_object(tb_magic.TBMagicCharacter, key="Joiner", location=self.testroom)
def tearDown(self):
super(TestTurnBattleMagicFunc, self).tearDown()
self.attacker.delete()
self.defender.delete()
self.joiner.delete()
self.testroom.delete()
self.turnhandler.stop()
# Test combat functions in tb_magic.
def test_tbbasicfunc(self):
# Initiative roll
initiative = tb_magic.roll_init(self.attacker)
self.assertTrue(initiative >= 0 and initiative <= 1000)
# Attack roll
attack_roll = tb_magic.get_attack(self.attacker, self.defender)
self.assertTrue(attack_roll >= 0 and attack_roll <= 100)
# Defense roll
defense_roll = tb_magic.get_defense(self.attacker, self.defender)
self.assertTrue(defense_roll == 50)
# Damage roll
damage_roll = tb_magic.get_damage(self.attacker, self.defender)
self.assertTrue(damage_roll >= 15 and damage_roll <= 25)
# Apply damage
self.defender.db.hp = 10
tb_magic.apply_damage(self.defender, 3)
self.assertTrue(self.defender.db.hp == 7)
# Resolve attack
self.defender.db.hp = 40
tb_magic.resolve_attack(self.attacker, self.defender, attack_value=20, defense_value=10)
self.assertTrue(self.defender.db.hp < 40)
# Combat cleanup
self.attacker.db.Combat_attribute = True
tb_magic.combat_cleanup(self.attacker)
self.assertFalse(self.attacker.db.combat_attribute)
# Is in combat
self.assertFalse(tb_magic.is_in_combat(self.attacker))
# Set up turn handler script for further tests
self.attacker.location.scripts.add(tb_magic.TBMagicTurnHandler)
self.turnhandler = self.attacker.db.combat_TurnHandler
self.assertTrue(self.attacker.db.combat_TurnHandler)
# Set the turn handler's interval very high to keep it from repeating during tests.
self.turnhandler.interval = 10000
# Force turn order
self.turnhandler.db.fighters = [self.attacker, self.defender]
self.turnhandler.db.turn = 0
# Test is turn
self.assertTrue(tb_magic.is_turn(self.attacker))
# Spend actions
self.attacker.db.Combat_ActionsLeft = 1
tb_magic.spend_action(self.attacker, 1, action_name="Test")
self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(self.attacker.db.Combat_LastAction == "Test")
# Initialize for combat
self.attacker.db.Combat_ActionsLeft = 983
self.turnhandler.initialize_for_combat(self.attacker)
self.assertTrue(self.attacker.db.Combat_ActionsLeft == 0)
self.assertTrue(self.attacker.db.Combat_LastAction == "null")
# Start turn
self.defender.db.Combat_ActionsLeft = 0
self.turnhandler.start_turn(self.defender)
self.assertTrue(self.defender.db.Combat_ActionsLeft == 1)
# Next turn
self.turnhandler.db.fighters = [self.attacker, self.defender]
self.turnhandler.db.turn = 0
self.turnhandler.next_turn()
self.assertTrue(self.turnhandler.db.turn == 1)
# Turn end check
self.turnhandler.db.fighters = [self.attacker, self.defender]
self.turnhandler.db.turn = 0
self.attacker.db.Combat_ActionsLeft = 0
self.turnhandler.turn_end_check(self.attacker)
self.assertTrue(self.turnhandler.db.turn == 1)
# Join fight
self.turnhandler.db.fighters = [self.attacker, self.defender]
self.turnhandler.db.turn = 0
self.turnhandler.join_fight(self.joiner)
self.assertTrue(self.turnhandler.db.turn == 1)
self.assertTrue(self.turnhandler.db.fighters == [self.joiner, self.attacker, self.defender])
# Test tree select # Test tree select
@ -1263,6 +1544,7 @@ Bar
--Baz 2 --Baz 2
-Qux""" -Qux"""
class TestTreeSelectFunc(EvenniaTest): class TestTreeSelectFunc(EvenniaTest):
def test_tree_functions(self): def test_tree_functions(self):

View file

@ -21,6 +21,19 @@ implemented and customized:
the battle system, including commands for wielding weapons and the battle system, including commands for wielding weapons and
donning armor, and modifiers to accuracy and damage based on donning armor, and modifiers to accuracy and damage based on
currently used equipment. currently used equipment.
tb_items.py - Adds usable items and conditions/status effects, and gives
a lot of examples for each. Items can perform nearly any sort of
function, including healing, adding or curing conditions, or
being used to attack. Conditions affect a fighter's attributes
and options in combat and persist outside of fights, counting
down per turn in combat and in real time outside combat.
tb_magic.py - Adds a spellcasting system, allowing characters to cast
spells with a variety of effects by spending MP. Spells are
linked to functions, and as such can perform any sort of action
the developer can imagine - spells for attacking, healing and
conjuring objects are included as examples.
tb_range.py - Adds a system for abstract positioning and movement, which tb_range.py - Adds a system for abstract positioning and movement, which
tracks the distance between different characters and objects in tracks the distance between different characters and objects in

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -674,7 +674,7 @@ class CrumblingWall(TutorialObject, DefaultExit):
# we found the button by moving the roots # we found the button by moving the roots
result = ["Having moved all the roots aside, you find that the center of the wall, " result = ["Having moved all the roots aside, you find that the center of the wall, "
"previously hidden by the vegetation, hid a curious square depression. It was maybe once " "previously hidden by the vegetation, hid a curious square depression. It was maybe once "
"concealed and made to look a part of the wall, but with the crumbling of stone around it," "concealed and made to look a part of the wall, but with the crumbling of stone around it, "
"it's now easily identifiable as some sort of button."] "it's now easily identifiable as some sort of button."]
elif self.db.exit_open: elif self.db.exit_open:
# we pressed the button; the exit is open # we pressed the button; the exit is open

View file

@ -18,6 +18,17 @@ from future.utils import with_metaclass
__all__ = ["DefaultScript", "DoNothing", "Store"] __all__ = ["DefaultScript", "DoNothing", "Store"]
FLUSHING_INSTANCES = False # whether we're in the process of flushing scripts from the cache
SCRIPT_FLUSH_TIMERS = {} # stores timers for scripts that are currently being flushed
def restart_scripts_after_flush():
"""After instances are flushed, validate scripts so they're not dead for a long period of time"""
global FLUSHING_INSTANCES
ScriptDB.objects.validate()
FLUSHING_INSTANCES = False
class ExtendedLoopingCall(LoopingCall): class ExtendedLoopingCall(LoopingCall):
""" """
LoopingCall that can start at a delay different LoopingCall that can start at a delay different
@ -358,6 +369,27 @@ class DefaultScript(ScriptBase):
return max(0, self.db_repeats - task.callcount) return max(0, self.db_repeats - task.callcount)
return None return None
def at_idmapper_flush(self):
"""If we're flushing this object, make sure the LoopingCall is gone too"""
ret = super(DefaultScript, self).at_idmapper_flush()
if ret and self.ndb._task:
try:
from twisted.internet import reactor
global FLUSHING_INSTANCES
# store the current timers for the _task and stop it to avoid duplicates after cache flush
paused_time = self.ndb._task.next_call_time()
callcount = self.ndb._task.callcount
self._stop_task()
SCRIPT_FLUSH_TIMERS[self.id] = (paused_time, callcount)
# here we ensure that the restart call only happens once, not once per script
if not FLUSHING_INSTANCES:
FLUSHING_INSTANCES = True
reactor.callLater(2, restart_scripts_after_flush)
except Exception:
import traceback
traceback.print_exc()
return ret
def start(self, force_restart=False): def start(self, force_restart=False):
""" """
Called every time the script is started (for persistent Called every time the script is started (for persistent
@ -374,9 +406,19 @@ class DefaultScript(ScriptBase):
started or not. Used in counting. started or not. Used in counting.
""" """
if self.is_active and not force_restart: if self.is_active and not force_restart:
# script already runs and should not be restarted. # The script is already running, but make sure we have a _task if this is after a cache flush
if not self.ndb._task and self.db_interval >= 0:
self.ndb._task = ExtendedLoopingCall(self._step_task)
try:
start_delay, callcount = SCRIPT_FLUSH_TIMERS[self.id]
del SCRIPT_FLUSH_TIMERS[self.id]
now = False
except (KeyError, ValueError, TypeError):
now = not self.db_start_delay
start_delay = None
callcount = 0
self.ndb._task.start(self.db_interval, now=now, start_delay=start_delay, count_start=callcount)
return 0 return 0
obj = self.obj obj = self.obj

View file

@ -142,7 +142,7 @@ LOCKWARNING_LOG_FILE = os.path.join(LOG_DIR, 'lockwarnings.log')
CYCLE_LOGFILES = True CYCLE_LOGFILES = True
# Number of lines to append to rotating channel logs when they rotate # Number of lines to append to rotating channel logs when they rotate
CHANNEL_LOG_NUM_TAIL_LINES = 20 CHANNEL_LOG_NUM_TAIL_LINES = 20
# Max size of channel log files before they rotate # Max size (in bytes) of channel log files before they rotate
CHANNEL_LOG_ROTATE_SIZE = 1000000 CHANNEL_LOG_ROTATE_SIZE = 1000000
# Local time zone for this installation. All choices can be found here: # Local time zone for this installation. All choices can be found here:
# http://www.postgresql.org/docs/8.0/interactive/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE # http://www.postgresql.org/docs/8.0/interactive/datetime-keywords.html#DATETIME-TIMEZONE-SET-TABLE

View file

@ -653,6 +653,42 @@ class TypeclassManager(TypedObjectManager):
""" """
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).count() return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).count()
def annotate(self, *args, **kwargs):
"""
Overload annotate method to filter on typeclass before annotating.
Args:
*args (any): Positional arguments passed along to queryset annotate method.
**kwargs (any): Keyword arguments passed along to queryset annotate method.
Returns:
Annotated queryset.
"""
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).annotate(*args, **kwargs)
def values(self, *args, **kwargs):
"""
Overload values method to filter on typeclass first.
Args:
*args (any): Positional arguments passed along to values method.
**kwargs (any): Keyword arguments passed along to values method.
Returns:
Queryset of values dictionaries, just filtered by typeclass first.
"""
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).values(*args, **kwargs)
def values_list(self, *args, **kwargs):
"""
Overload values method to filter on typeclass first.
Args:
*args (any): Positional arguments passed along to values_list method.
**kwargs (any): Keyword arguments passed along to values_list method.
Returns:
Queryset of value_list tuples, just filtered by typeclass first.
"""
return super(TypeclassManager, self).filter(db_typeclass_path=self.model.path).values_list(*args, **kwargs)
def _get_subclasses(self, cls): def _get_subclasses(self, cls):
""" """
Recursively get all subclasses to a class. Recursively get all subclasses to a class.

View file

@ -237,10 +237,13 @@ class _SaverList(_SaverMutable, MutableSequence):
self._data = list() self._data = list()
@_save @_save
def __add__(self, otherlist): def __iadd__(self, otherlist):
self._data = self._data.__add__(otherlist) self._data = self._data.__add__(otherlist)
return self._data return self._data
def __add__(self, otherlist):
return list(self._data) + otherlist
@_save @_save
def insert(self, index, value): def insert(self, index, value):
self._data.insert(index, self._convert_mutables(value)) self._data.insert(index, self._convert_mutables(value))