More work on tech demo area
This commit is contained in:
parent
1ed7ffa095
commit
afadb1001e
16 changed files with 275 additions and 252 deletions
|
|
@ -172,6 +172,8 @@ Up requirements to Django 4.0+, Twisted 22+, Python 3.9 or 3.10
|
||||||
now return `None` instead of `.db.desc` if no sdesc is set; fallback in hook (inspectorCaracal)
|
now return `None` instead of `.db.desc` if no sdesc is set; fallback in hook (inspectorCaracal)
|
||||||
- Reworked text2html parser to avoid problems with stateful color tags (inspectorCaracal)
|
- Reworked text2html parser to avoid problems with stateful color tags (inspectorCaracal)
|
||||||
- Simplified `EvMenu.options_formatter` hook to use `EvColumn` and f-strings (inspectorcaracal)
|
- Simplified `EvMenu.options_formatter` hook to use `EvColumn` and f-strings (inspectorcaracal)
|
||||||
|
- Allow `# CODE`, `# HEADER` etc as well as `#CODE`/`#HEADER` in batchcode
|
||||||
|
files - this works better with black linting.
|
||||||
|
|
||||||
|
|
||||||
## Evennia 0.9.5
|
## Evennia 0.9.5
|
||||||
|
|
|
||||||
|
|
@ -4,19 +4,17 @@ The base Command class.
|
||||||
All commands in Evennia inherit from the 'Command' class in this module.
|
All commands in Evennia inherit from the 'Command' class in this module.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import re
|
|
||||||
import math
|
|
||||||
import inspect
|
import inspect
|
||||||
|
import math
|
||||||
|
import re
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.text import slugify
|
from django.utils.text import slugify
|
||||||
|
|
||||||
from evennia.locks.lockhandler import LockHandler
|
from evennia.locks.lockhandler import LockHandler
|
||||||
from evennia.utils.utils import is_iter, fill, lazy_property, make_iter
|
|
||||||
from evennia.utils.evtable import EvTable
|
|
||||||
from evennia.utils.ansi import ANSIString
|
from evennia.utils.ansi import ANSIString
|
||||||
|
from evennia.utils.evtable import EvTable
|
||||||
|
from evennia.utils.utils import fill, is_iter, lazy_property, make_iter
|
||||||
|
|
||||||
CMD_IGNORE_PREFIXES = settings.CMD_IGNORE_PREFIXES
|
CMD_IGNORE_PREFIXES = settings.CMD_IGNORE_PREFIXES
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
"""
|
||||||
|
EvAdventure - a complete game in Evennia.
|
||||||
|
|
||||||
|
This is an implementation of, and reference code to, the game created in the
|
||||||
|
documentation's beginner tutorial.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
@ -15,45 +15,69 @@ You can also build/rebuild individiaul #CODE blocks in the `batchcode/interactiv
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
#HEADER
|
# HEADER
|
||||||
|
|
||||||
# this is loaded at the top of every #CODE block
|
# this is loaded at the top of every #CODE block
|
||||||
|
|
||||||
from evennia import create_object, search_object
|
from evennia import DefaultExit, create_object, search_object
|
||||||
from evennia import DefaultExit
|
|
||||||
from evennia.contrib.tutorials import evadventure
|
from evennia.contrib.tutorials import evadventure
|
||||||
from evennia.contrib.tutorials.evadventure.objects import (
|
|
||||||
EvAdventureObject, EvAdventureRunestone, EvAdventureRunestone, EvAdventureConsumable,
|
|
||||||
EvAdventureObjectFiller)
|
|
||||||
from evennia.contrib.tutorials.evadventure.rooms import EvAdventureRoom
|
|
||||||
from evennia.contrib.tutorials.evadventure.combat_turnbasedA import EvAdventureCombatHandler
|
|
||||||
from evennia.contrib.tutorials.evadventure import npcs
|
from evennia.contrib.tutorials.evadventure import npcs
|
||||||
|
from evennia.contrib.tutorials.evadventure.combat_turnbased import EvAdventureCombatHandler
|
||||||
|
from evennia.contrib.tutorials.evadventure.objects import (
|
||||||
|
EvAdventureConsumable,
|
||||||
|
EvAdventureObject,
|
||||||
|
EvAdventureObjectFiller,
|
||||||
|
EvAdventureRunestone,
|
||||||
|
)
|
||||||
|
from evennia.contrib.tutorials.evadventure.rooms import EvAdventureRoom
|
||||||
|
|
||||||
#CODE
|
# CODE
|
||||||
|
|
||||||
# Hub room evtechdemo#00
|
# Hub room evtechdemo#00
|
||||||
# for other test areas to link back to. Connects in turn back to Limbo.
|
# for other test areas to link back to. Connects in turn back to Limbo.
|
||||||
|
|
||||||
limbo = search_object("Limbo")
|
limbo = search_object("Limbo")[0]
|
||||||
hub_room = create_object(EvAdventureRoom, key="Techdemo Hub", aliases=("evtechdemo#00",),
|
hub_room = create_object(
|
||||||
attributes=[("desc", "Central hub for EvAdventure tech demo.")])
|
EvAdventureRoom,
|
||||||
create_object(DefaultExit, key="EvAdventure Techdemo", aliases=("techdemo",),
|
key="Techdemo Hub",
|
||||||
location=limbo, destination=hub_room)
|
aliases=("evtechdemo#00",),
|
||||||
create_object(DefaultExit, key="Back to Limbo", aliases=("limbo", "back"),
|
attributes=[("desc", "Central hub for EvAdventure tech demo.")],
|
||||||
location=hub_room, destination=limbo)
|
)
|
||||||
|
create_object(
|
||||||
|
DefaultExit,
|
||||||
|
key="EvAdventure Techdemo",
|
||||||
|
aliases=("techdemo", "demo", "evadventure"),
|
||||||
|
location=limbo,
|
||||||
|
destination=hub_room,
|
||||||
|
)
|
||||||
|
create_object(
|
||||||
|
DefaultExit,
|
||||||
|
key="Back to Limbo",
|
||||||
|
aliases=("limbo", "back"),
|
||||||
|
location=hub_room,
|
||||||
|
destination=limbo,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
#CODE
|
# CODE
|
||||||
|
|
||||||
# A combat room evtechdemo#01
|
# A combat room evtechdemo#01
|
||||||
# with a static enemy
|
# with a static enemy
|
||||||
|
|
||||||
combat_room = create_object(EvAdventureRoom, key="Combat Arena", aliases=("evtechdemo#01",))
|
combat_room = create_object(EvAdventureRoom, key="Combat Arena", aliases=("evtechdemo#01",))
|
||||||
combat_room_enemy = create_object(npcs.EvadventureMob, key="Training Dummy")
|
combat_room_enemy = create_object(
|
||||||
|
npcs.EvadventureMob, key="Training Dummy", aliases=("dummy",), location=combat_room
|
||||||
|
)
|
||||||
|
|
||||||
# link to/back to hub
|
# link to/back to hub
|
||||||
hub_room = search_object("evtechdemo#00")
|
hub_room = search_object("evtechdemo#00")[0]
|
||||||
create_object(DefaultExit, key="Back to Hub", aliases=("back", "hub"),
|
create_object(
|
||||||
location=combat_room, destination=hub_room)
|
DefaultExit, key="combat test", aliases=("combat",), location=hub_room, destination=combat_room
|
||||||
create_object(DefaultExit, key="combat test", aliases=("combat"),
|
)
|
||||||
location=combat_room, destination=hub_room)
|
create_object(
|
||||||
|
DefaultExit,
|
||||||
|
key="Back to Hub",
|
||||||
|
aliases=("back", "hub"),
|
||||||
|
location=combat_room,
|
||||||
|
destination=hub_room,
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,11 @@ Base Character and NPCs.
|
||||||
|
|
||||||
from evennia.objects.objects import DefaultCharacter, DefaultObject
|
from evennia.objects.objects import DefaultCharacter, DefaultObject
|
||||||
from evennia.typeclasses.attributes import AttributeProperty
|
from evennia.typeclasses.attributes import AttributeProperty
|
||||||
from evennia.utils.utils import lazy_property, int2str
|
from evennia.utils.utils import int2str, lazy_property
|
||||||
from .objects import EvAdventureObject
|
|
||||||
from . import rules
|
from . import rules
|
||||||
from .enums import Ability, WieldLocation
|
from .enums import Ability, WieldLocation
|
||||||
|
from .objects import EvAdventureObject
|
||||||
|
|
||||||
|
|
||||||
class EquipmentError(TypeError):
|
class EquipmentError(TypeError):
|
||||||
|
|
@ -290,11 +291,12 @@ class EquipmentHandler:
|
||||||
in the list after all).
|
in the list after all).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return [obj for obj in slots[WieldLocation.BACKPACK]
|
return [
|
||||||
if obj.inventory_use_slot in (
|
obj
|
||||||
WieldLocation.WEAPON_HAND,
|
for obj in slots[WieldLocation.BACKPACK]
|
||||||
WieldLocation.TWO_HANDS,
|
if obj.inventory_use_slot
|
||||||
WieldLocation.SHIELD_HAND)]
|
in (WieldLocation.WEAPON_HAND, WieldLocation.TWO_HANDS, WieldLocation.SHIELD_HAND)
|
||||||
|
]
|
||||||
|
|
||||||
def get_wearable_objects_from_backpack(self):
|
def get_wearable_objects_from_backpack(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -307,11 +309,11 @@ class EquipmentHandler:
|
||||||
in the list after all).
|
in the list after all).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return [obj for obj in slots[WieldLocation.BACKPACK]
|
return [
|
||||||
if obj.inventory_use_slot in (
|
obj
|
||||||
WieldLocation.BODY,
|
for obj in slots[WieldLocation.BACKPACK]
|
||||||
WieldLocation.HEAD
|
if obj.inventory_use_slot in (WieldLocation.BODY, WieldLocation.HEAD)
|
||||||
)]
|
]
|
||||||
|
|
||||||
def get_usable_objects_from_backpack(self):
|
def get_usable_objects_from_backpack(self):
|
||||||
"""
|
"""
|
||||||
|
|
@ -327,7 +329,7 @@ class EquipmentHandler:
|
||||||
|
|
||||||
class LivingMixin:
|
class LivingMixin:
|
||||||
"""
|
"""
|
||||||
Helpers shared between all living things.
|
Mixin class to use for all living things.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
@ -488,64 +490,3 @@ class EvAdventureCharacter(LivingMixin, DefaultCharacter):
|
||||||
Called when character dies.
|
Called when character dies.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
class EvAdventureNPC(LivingMixin, DefaultCharacter):
|
|
||||||
"""
|
|
||||||
This is the base class for all non-player entities, including monsters. These
|
|
||||||
generally don't advance in level but uses a simplified, abstract measure of how
|
|
||||||
dangerous or competent they are - the 'hit dice' (HD).
|
|
||||||
|
|
||||||
HD indicates how much health they have and how hard they hit. In _Knave_, HD also
|
|
||||||
defaults to being the bonus for all abilities. HP is 4 x Hit die (this can then be
|
|
||||||
customized per-entity of course).
|
|
||||||
|
|
||||||
Morale is set explicitly per-NPC, usually between 7 and 9.
|
|
||||||
|
|
||||||
Monsters don't use equipment in the way PCs do, instead they have a fixed armor
|
|
||||||
value, and their Abilities are dynamically generated from the HD (hit_dice).
|
|
||||||
|
|
||||||
If wanting monsters or NPCs that can level and work the same as PCs, base them off the
|
|
||||||
EvAdventureCharacter class instead.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
hit_dice = AttributeProperty(default=1)
|
|
||||||
armor = AttributeProperty(default=11)
|
|
||||||
morale = AttributeProperty(default=9)
|
|
||||||
hp = AttributeProperty(default=8)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def strength(self):
|
|
||||||
return self.hit_dice
|
|
||||||
|
|
||||||
@property
|
|
||||||
def dexterity(self):
|
|
||||||
return self.hit_dice
|
|
||||||
|
|
||||||
@property
|
|
||||||
def constitution(self):
|
|
||||||
return self.hit_dice
|
|
||||||
|
|
||||||
@property
|
|
||||||
def intelligence(self):
|
|
||||||
return self.hit_dice
|
|
||||||
|
|
||||||
@property
|
|
||||||
def wisdom(self):
|
|
||||||
return self.hit_dice
|
|
||||||
|
|
||||||
@property
|
|
||||||
def charisma(self):
|
|
||||||
return self.hit_dice
|
|
||||||
|
|
||||||
@property
|
|
||||||
def hp_max(self):
|
|
||||||
return self.hit_dice * 4
|
|
||||||
|
|
||||||
def at_object_creation(self):
|
|
||||||
"""
|
|
||||||
Start with max health.
|
|
||||||
|
|
||||||
"""
|
|
||||||
self.hp = self.hp_max
|
|
||||||
|
|
|
||||||
|
|
@ -99,15 +99,16 @@ Choose who to block:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
from evennia.scripts.scripts import DefaultScript
|
from evennia.scripts.scripts import DefaultScript
|
||||||
from evennia.typeclasses.attributes import AttributeProperty
|
from evennia.typeclasses.attributes import AttributeProperty
|
||||||
|
from evennia.utils import dbserialize, delay, evmenu, evtable
|
||||||
from evennia.utils.utils import make_iter
|
from evennia.utils.utils import make_iter
|
||||||
from evennia.utils import evtable, dbserialize, delay, evmenu
|
|
||||||
from .enums import Ability
|
|
||||||
from . import rules
|
|
||||||
|
|
||||||
|
from . import rules
|
||||||
|
from .enums import Ability
|
||||||
|
|
||||||
COMBAT_HANDLER_KEY = "evadventure_turnbased_combathandler"
|
COMBAT_HANDLER_KEY = "evadventure_turnbased_combathandler"
|
||||||
COMBAT_HANDLER_INTERVAL = 60
|
COMBAT_HANDLER_INTERVAL = 60
|
||||||
|
|
@ -242,7 +243,7 @@ class CombatActionAttack(CombatAction):
|
||||||
# figure out disadvantage (gained by enemy stunts/actions)
|
# figure out disadvantage (gained by enemy stunts/actions)
|
||||||
disadvantage = bool(self.combathandler.disadvantage_matrix[attacker].pop(defender, False))
|
disadvantage = bool(self.combathandler.disadvantage_matrix[attacker].pop(defender, False))
|
||||||
|
|
||||||
is_hit, quality = rules.EvAdventureRollEngine.opposed_saving_throw(
|
is_hit, quality = rules.dice.opposed_saving_throw(
|
||||||
attacker,
|
attacker,
|
||||||
defender,
|
defender,
|
||||||
attack_type=attacker.weapon.attack_type,
|
attack_type=attacker.weapon.attack_type,
|
||||||
|
|
@ -295,9 +296,9 @@ class CombatActionStunt(CombatAction):
|
||||||
# quality doesn't matter for stunts, they are either successful or not
|
# quality doesn't matter for stunts, they are either successful or not
|
||||||
|
|
||||||
attacker = self.combatant
|
attacker = self.combatant
|
||||||
advantage, disadvantage = False
|
advantage, disadvantage = False, False
|
||||||
|
|
||||||
is_success, _ = rules.EvAdventureRollEngine.opposed_saving_throw(
|
is_success, _ = rules.dice.opposed_saving_throw(
|
||||||
attacker,
|
attacker,
|
||||||
defender,
|
defender,
|
||||||
attack_type=self.attack_type,
|
attack_type=self.attack_type,
|
||||||
|
|
@ -333,6 +334,7 @@ class CombatActionUseItem(CombatAction):
|
||||||
combat_post_use
|
combat_post_use
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
key = "Use Item"
|
key = "Use Item"
|
||||||
desc = "[U]se item"
|
desc = "[U]se item"
|
||||||
aliases = ("u", "item", "use item")
|
aliases = ("u", "item", "use item")
|
||||||
|
|
@ -406,7 +408,7 @@ class CombatActionBlock(CombatAction):
|
||||||
advantage = bool(self.advantage_matrix[combatant].pop(fleeing_target, False))
|
advantage = bool(self.advantage_matrix[combatant].pop(fleeing_target, False))
|
||||||
disadvantage = bool(self.disadvantage_matrix[combatant].pop(fleeing_target, False))
|
disadvantage = bool(self.disadvantage_matrix[combatant].pop(fleeing_target, False))
|
||||||
|
|
||||||
is_success, _ = rules.EvAdventureRollEngine.opposed_saving_throw(
|
is_success, _ = rules.dice.opposed_saving_throw(
|
||||||
combatant,
|
combatant,
|
||||||
fleeing_target,
|
fleeing_target,
|
||||||
attack_type=self.attack_type,
|
attack_type=self.attack_type,
|
||||||
|
|
@ -427,12 +429,23 @@ class CombatActionSwapWieldedWeaponOrSpell(CombatAction):
|
||||||
Swap Wielded weapon or spell.
|
Swap Wielded weapon or spell.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
key = "Swap weapon/rune/shield"
|
key = "Swap weapon/rune/shield"
|
||||||
desc = "Swap currently wielded weapon, shield or spell-rune."
|
desc = "Swap currently wielded weapon, shield or spell-rune."
|
||||||
aliases = ("s", "swap", "draw", "swap weapon", "draw weapon",
|
aliases = (
|
||||||
"swap rune", "draw rune", "swap spell", "draw spell")
|
"s",
|
||||||
help_text = ("Draw a new weapon or spell-rune from your inventory, "
|
"swap",
|
||||||
"replacing your current loadout")
|
"draw",
|
||||||
|
"swap weapon",
|
||||||
|
"draw weapon",
|
||||||
|
"swap rune",
|
||||||
|
"draw rune",
|
||||||
|
"swap spell",
|
||||||
|
"draw spell",
|
||||||
|
)
|
||||||
|
help_text = (
|
||||||
|
"Draw a new weapon or spell-rune from your inventory, replacing your current loadout"
|
||||||
|
)
|
||||||
|
|
||||||
next_menu_node = "node_select_wield_from_inventory"
|
next_menu_node = "node_select_wield_from_inventory"
|
||||||
|
|
||||||
|
|
@ -448,6 +461,7 @@ class CombatActionUseItem(CombatAction):
|
||||||
Use an item from inventory.
|
Use an item from inventory.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
key = "Use an item from backpack"
|
key = "Use an item from backpack"
|
||||||
desc = "Use an item from your inventory."
|
desc = "Use an item from your inventory."
|
||||||
aliases = ("u", "use", "use item")
|
aliases = ("u", "use", "use item")
|
||||||
|
|
@ -543,6 +557,29 @@ class EvAdventureCombatHandler(DefaultScript):
|
||||||
self._end_turn()
|
self._end_turn()
|
||||||
self._start_turn()
|
self._start_turn()
|
||||||
|
|
||||||
|
def _init_menu(self, combatant, session=None):
|
||||||
|
"""
|
||||||
|
Make sure combatant is in the menu. This is safe to call on a combatant already in a menu.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if not combatant.ndb._evmenu:
|
||||||
|
# re-joining the menu is useful during testing
|
||||||
|
evmenu.EvMenu(
|
||||||
|
combatant,
|
||||||
|
{
|
||||||
|
"node_wait_start": node_wait_start,
|
||||||
|
"node_select_target": node_select_target,
|
||||||
|
"node_select_action": node_select_action,
|
||||||
|
"node_wait_turn": node_wait_turn,
|
||||||
|
},
|
||||||
|
startnode="node_wait_turn",
|
||||||
|
auto_quit=True,
|
||||||
|
persistent=True,
|
||||||
|
cmdset_mergetype="Union",
|
||||||
|
session=session,
|
||||||
|
combathandler=self, # makes this available as combatant.ndb._evmenu.combathandler
|
||||||
|
)
|
||||||
|
|
||||||
def _reset_menu(self):
|
def _reset_menu(self):
|
||||||
"""
|
"""
|
||||||
Move menu to the action-selection node.
|
Move menu to the action-selection node.
|
||||||
|
|
@ -577,10 +614,12 @@ class EvAdventureCombatHandler(DefaultScript):
|
||||||
# set -1 for unit tests
|
# set -1 for unit tests
|
||||||
warning_time = 15
|
warning_time = 15
|
||||||
self._warn_time_task = delay(
|
self._warn_time_task = delay(
|
||||||
self.interval - warning_time, self._warn_time, warning_time)
|
self.interval - warning_time, self._warn_time, warning_time
|
||||||
|
)
|
||||||
|
|
||||||
for combatant in self.combatants:
|
for combatant in self.combatants:
|
||||||
# cycle combat menu
|
# cycle combat menu
|
||||||
|
self._init_menu(combatant)
|
||||||
combatant.ndb._evmenu.goto("node_select_action", "")
|
combatant.ndb._evmenu.goto("node_select_action", "")
|
||||||
|
|
||||||
def _end_turn(self):
|
def _end_turn(self):
|
||||||
|
|
@ -633,12 +672,12 @@ class EvAdventureCombatHandler(DefaultScript):
|
||||||
for combatant in self.combatants:
|
for combatant in self.combatants:
|
||||||
new_advantage_matrix[combatant] = {
|
new_advantage_matrix[combatant] = {
|
||||||
target: set_at_turn
|
target: set_at_turn
|
||||||
for target, set_at_turn in advantage_matrix.items()
|
for target, set_at_turn in advantage_matrix[combatant].items()
|
||||||
if set_at_turn > oldest_stunt_age
|
if set_at_turn > oldest_stunt_age
|
||||||
}
|
}
|
||||||
new_disadvantage_matrix[combatant] = {
|
new_disadvantage_matrix[combatant] = {
|
||||||
target: set_at_turn
|
target: set_at_turn
|
||||||
for target, set_at_turn in disadvantage_matrix.items()
|
for target, set_at_turn in disadvantage_matrix[combatant].items()
|
||||||
if set_at_turn > oldest_stunt_age
|
if set_at_turn > oldest_stunt_age
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -676,23 +715,7 @@ class EvAdventureCombatHandler(DefaultScript):
|
||||||
action_class.key: action_class(self, combatant)
|
action_class.key: action_class(self, combatant)
|
||||||
for action_class in self.default_action_classes + custom_action_classes
|
for action_class in self.default_action_classes + custom_action_classes
|
||||||
}
|
}
|
||||||
|
self._init_menu(combatant, session=session)
|
||||||
# start evmenu (menu node definitions at the end of this module)
|
|
||||||
|
|
||||||
evmenu.EvMenu(
|
|
||||||
combatant,
|
|
||||||
{
|
|
||||||
"node_wait_start": node_wait_start,
|
|
||||||
"node_select_target": node_select_target,
|
|
||||||
"node_select_action": node_select_action,
|
|
||||||
"node_wait_turn": node_wait_turn,
|
|
||||||
},
|
|
||||||
startnode="node_wait_turn",
|
|
||||||
auto_quit=False,
|
|
||||||
persistent=True,
|
|
||||||
session=session,
|
|
||||||
combathandler=self # makes this available as combatant.ndb._evmenu.combathandler
|
|
||||||
)
|
|
||||||
|
|
||||||
def remove_combatant(self, combatant):
|
def remove_combatant(self, combatant):
|
||||||
"""
|
"""
|
||||||
|
|
@ -823,9 +846,9 @@ class EvAdventureCombatHandler(DefaultScript):
|
||||||
"""
|
"""
|
||||||
weapon_dmg_roll = attacker.weapon.damage_roll
|
weapon_dmg_roll = attacker.weapon.damage_roll
|
||||||
|
|
||||||
dmg = rules.EvAdventureRollEngine.roll(weapon_dmg_roll)
|
dmg = rules.dice.roll(weapon_dmg_roll)
|
||||||
if critical:
|
if critical:
|
||||||
dmg += rules.EvAdventureRollEngine.roll(weapon_dmg_roll)
|
dmg += rules.dice.roll(weapon_dmg_roll)
|
||||||
|
|
||||||
defender.hp -= dmg
|
defender.hp -= dmg
|
||||||
|
|
||||||
|
|
@ -834,7 +857,7 @@ class EvAdventureCombatHandler(DefaultScript):
|
||||||
|
|
||||||
if defender.hp <= 0:
|
if defender.hp <= 0:
|
||||||
# roll on death table. This may or may not kill you
|
# roll on death table. This may or may not kill you
|
||||||
rules.EvAdventureRollEngine.roll_death(self)
|
rules.dice.roll_death(self)
|
||||||
|
|
||||||
# tell everyone
|
# tell everyone
|
||||||
self.msg(defender.defeat_message(attacker, dmg))
|
self.msg(defender.defeat_message(attacker, dmg))
|
||||||
|
|
@ -870,8 +893,7 @@ class EvAdventureCombatHandler(DefaultScript):
|
||||||
"""
|
"""
|
||||||
# get the instantiated action for this combatant
|
# get the instantiated action for this combatant
|
||||||
action = self.combatant_actions[combatant].get(
|
action = self.combatant_actions[combatant].get(
|
||||||
action_key,
|
action_key, CombatActionDoNothing(self, combatant)
|
||||||
CombatActionDoNothing(self, combatant)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# store the action in the queue
|
# store the action in the queue
|
||||||
|
|
@ -912,13 +934,13 @@ def _register_action(caller, raw_string, **kwargs):
|
||||||
Register action with handler.
|
Register action with handler.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
action_key = kwargs.get["action_key"]
|
action_key = kwargs.pop("action_key")
|
||||||
action_args = kwargs["action_args"]
|
action_args = kwargs["action_args"]
|
||||||
action_kwargs = kwargs["action_kwargs"]
|
action_kwargs = kwargs["action_kwargs"]
|
||||||
action_target = kwargs.get("action_target")
|
action_target = kwargs.pop("action_target", None)
|
||||||
combat_handler = caller._evmenu.combathandler
|
combat_handler = caller.ndb._evmenu.combathandler
|
||||||
combat_handler.register_action(
|
print("action_args", action_args, "action_kwargs", action_kwargs)
|
||||||
caller, action_key, action_target, *action_args, **action_kwargs)
|
combat_handler.register_action(caller, action_key, action_target, *action_args, **action_kwargs)
|
||||||
|
|
||||||
# move into waiting
|
# move into waiting
|
||||||
return "node_wait_turn"
|
return "node_wait_turn"
|
||||||
|
|
@ -930,41 +952,22 @@ def node_select_target(caller, raw_string, **kwargs):
|
||||||
with all other actions.
|
with all other actions.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
action_key = kwargs.get("action_key")
|
|
||||||
action_args = kwargs.get("action_args")
|
|
||||||
action_kwargs = kwargs.get("action_kwargs")
|
|
||||||
combat = caller.ndb._evmenu.combathandler
|
combat = caller.ndb._evmenu.combathandler
|
||||||
text = "Select target for |w{action_key}|n."
|
text = "Select target for |w{action_key}|n."
|
||||||
|
|
||||||
# make the apply-self option always the first one, give it key 0
|
# make the apply-self option always the first one, give it key 0
|
||||||
kwargs["action_target"] = caller
|
kwargs["action_target"] = caller
|
||||||
options = [
|
options = [{"key": "0", "desc": "(yourself)", "goto": (_register_action, kwargs)}]
|
||||||
{
|
|
||||||
"key": "0",
|
|
||||||
"desc": "(yourself)",
|
|
||||||
"goto": (_register_action, kwargs)
|
|
||||||
}
|
|
||||||
]
|
|
||||||
# filter out ourselves and then make options for everyone else
|
# filter out ourselves and then make options for everyone else
|
||||||
combatants = [combatant for combatant in combat.combatants if combatant is not caller]
|
combatants = [combatant for combatant in combat.combatants if combatant is not caller]
|
||||||
for combatant in combatants:
|
for inum, combatant in enumerate(combatants):
|
||||||
# automatic menu numbering starts from 1
|
|
||||||
kwargs["action_target"] = combatant
|
kwargs["action_target"] = combatant
|
||||||
options.append(
|
options.append(
|
||||||
{
|
{"key": str(inum + 1), "desc": combatant.key, "goto": (_register_action, kwargs)}
|
||||||
"desc": combatant.key,
|
|
||||||
"goto": (_register_action, kwargs)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# add ability to cancel
|
# add ability to cancel
|
||||||
options.append(
|
options.append({"key": "_default", "goto": "node_select_action"})
|
||||||
{
|
|
||||||
"key": "_default",
|
|
||||||
"desc": "(No input to Abort and go back)",
|
|
||||||
"goto": "node_select_action"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
@ -981,8 +984,10 @@ def node_select_wield_from_inventory(caller, raw_string, **kwargs):
|
||||||
"""
|
"""
|
||||||
combat = caller.ndb._evmenu.combathandler
|
combat = caller.ndb._evmenu.combathandler
|
||||||
loadout = caller.inventory.display_loadout()
|
loadout = caller.inventory.display_loadout()
|
||||||
text = (f"{loadout}\nSelect weapon, spell or shield to draw. It will swap out "
|
text = (
|
||||||
"anything already in the same hand (you can't change armor or helmet in combat).")
|
f"{loadout}\nSelect weapon, spell or shield to draw. It will swap out "
|
||||||
|
"anything already in the same hand (you can't change armor or helmet in combat)."
|
||||||
|
)
|
||||||
|
|
||||||
# get a list of all suitable weapons/spells/shields
|
# get a list of all suitable weapons/spells/shields
|
||||||
options = []
|
options = []
|
||||||
|
|
@ -997,21 +1002,12 @@ def node_select_wield_from_inventory(caller, raw_string, **kwargs):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# normally working item
|
# normally working item
|
||||||
kwargs['action_args'] = (obj,)
|
kwargs["action_args"] = (obj,)
|
||||||
options.append(
|
options.append({"desc": str(obj), "goto": (_register_action, kwargs)})
|
||||||
{
|
|
||||||
"desc": str(obj),
|
|
||||||
"goto": (_register_action, kwargs)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# add ability to cancel
|
# add ability to cancel
|
||||||
options.append(
|
options.append(
|
||||||
{
|
{"key": "_default", "desc": "(No input to Abort and go back)", "goto": "node_select_action"}
|
||||||
"key": "_default",
|
|
||||||
"desc": "(No input to Abort and go back)",
|
|
||||||
"goto": "node_select_action"
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
@ -1038,21 +1034,12 @@ def node_select_use_item_from_inventory(caller, raw_string, **kwargs):
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
# normally working item
|
# normally working item
|
||||||
kwargs['action_args'] = (obj,)
|
kwargs["action_args"] = (obj,)
|
||||||
options.append(
|
options.append({"desc": str(obj), "goto": (_register_action, kwargs)})
|
||||||
{
|
|
||||||
"desc": str(obj),
|
|
||||||
"goto": (_register_action, kwargs)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# add ability to cancel
|
# add ability to cancel
|
||||||
options.append(
|
options.append(
|
||||||
{
|
{"key": "_default", "desc": "(No input to Abort and go back)", "goto": "node_select_action"}
|
||||||
"key": "_default",
|
|
||||||
"desc": "(No input to Abort and go back)",
|
|
||||||
"goto": "node_select_action"
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
@ -1063,8 +1050,8 @@ def _action_unavailable(caller, raw_string, **kwargs):
|
||||||
Selecting an unavailable action.
|
Selecting an unavailable action.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
action_key = kwargs.get["action_key"]
|
action_key = kwargs["action_key"]
|
||||||
caller.msg(f"Action '{action_key}' is currently not available.")
|
caller.msg(f"|rAction |w{action_key}|r is currently not available.|n")
|
||||||
# go back to previous node
|
# go back to previous node
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
@ -1093,12 +1080,7 @@ def node_select_action(caller, raw_string, **kwargs):
|
||||||
{
|
{
|
||||||
"key": key,
|
"key": key,
|
||||||
"desc": desc,
|
"desc": desc,
|
||||||
"goto": (
|
"goto": (_action_unavailable, {"action_key": action.key}),
|
||||||
_action_unavailable,
|
|
||||||
{
|
|
||||||
"action_key": action.key
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
elif action.next_menu_node is None:
|
elif action.next_menu_node is None:
|
||||||
|
|
@ -1113,7 +1095,7 @@ def node_select_action(caller, raw_string, **kwargs):
|
||||||
{
|
{
|
||||||
"action_key": action.key,
|
"action_key": action.key,
|
||||||
"action_args": (),
|
"action_args": (),
|
||||||
"action_kwargs": kwargs,
|
"action_kwargs": {},
|
||||||
"action_target": None,
|
"action_target": None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
@ -1130,7 +1112,8 @@ def node_select_action(caller, raw_string, **kwargs):
|
||||||
{
|
{
|
||||||
"action_key": action.key,
|
"action_key": action.key,
|
||||||
"action_args": (),
|
"action_args": (),
|
||||||
"action_kwargs": kwargs,
|
"action_kwargs": {},
|
||||||
|
"action_target": None,
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
@ -1139,8 +1122,7 @@ def node_select_action(caller, raw_string, **kwargs):
|
||||||
options.append(
|
options.append(
|
||||||
{
|
{
|
||||||
"key": "_default",
|
"key": "_default",
|
||||||
"desc": "(No input to Abort and go back)",
|
"goto": "node_select_action",
|
||||||
"goto": "node_select_action"
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1160,7 +1142,7 @@ def node_wait_turn(caller, raw_string, **kwargs):
|
||||||
options = {
|
options = {
|
||||||
"key": "_default",
|
"key": "_default",
|
||||||
"desc": "(next round will start automatically)",
|
"desc": "(next round will start automatically)",
|
||||||
"goto": "node_wait_turn"
|
"goto": "node_wait_turn",
|
||||||
}
|
}
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
@ -1177,7 +1159,7 @@ def node_wait_start(caller, raw_string, **kwargs):
|
||||||
options = {
|
options = {
|
||||||
"key": "_default",
|
"key": "_default",
|
||||||
"desc": "(combat will start automatically)",
|
"desc": "(combat will start automatically)",
|
||||||
"goto": "node_wait_start"
|
"goto": "node_wait_start",
|
||||||
}
|
}
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
|
|
@ -1218,10 +1200,13 @@ def join_combat(caller, *targets, session=None):
|
||||||
combathandler = location.scripts.add(EvAdventureCombatHandler, autostart=False)
|
combathandler = location.scripts.add(EvAdventureCombatHandler, autostart=False)
|
||||||
created = True
|
created = True
|
||||||
|
|
||||||
|
if not hasattr(caller, "hp"):
|
||||||
|
raise CombatFailure("You have no hp and so can't attack anyone.")
|
||||||
|
|
||||||
# it's safe to add a combatant to the same combat more than once
|
# it's safe to add a combatant to the same combat more than once
|
||||||
combathandler.add_combatant(caller, session=session)
|
combathandler.add_combatant(caller, session=session)
|
||||||
for target in targets:
|
for target in targets:
|
||||||
combathandler.add_combatant(target, session=session)
|
combathandler.add_combatant(target)
|
||||||
|
|
||||||
if created:
|
if created:
|
||||||
combathandler.start_combat()
|
combathandler.start_combat()
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
"""
|
"""
|
||||||
EvAdventure commands and cmdsets.
|
nextEvAdventure commands and cmdsets.
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from evennia import Command, default_cmds
|
from evennia import Command, default_cmds
|
||||||
from . combat_turnbased import join_combat
|
|
||||||
|
from .combat_turnbased import CombatFailure, join_combat
|
||||||
|
|
||||||
|
|
||||||
class EvAdventureCommand(Command):
|
class EvAdventureCommand(Command):
|
||||||
|
|
@ -17,6 +17,7 @@ class EvAdventureCommand(Command):
|
||||||
where whitespace around the argument(s) are stripped.
|
where whitespace around the argument(s) are stripped.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
self.args = self.args.strip()
|
self.args = self.args.strip()
|
||||||
|
|
||||||
|
|
@ -38,6 +39,9 @@ class CmdAttackTurnBased(EvAdventureCommand):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
key = "attack"
|
||||||
|
aliases = ("hit",)
|
||||||
|
|
||||||
def parse(self):
|
def parse(self):
|
||||||
super().parse()
|
super().parse()
|
||||||
self.targets = [name.strip() for name in self.args.split(",")]
|
self.targets = [name.strip() for name in self.args.split(",")]
|
||||||
|
|
@ -49,10 +53,15 @@ class CmdAttackTurnBased(EvAdventureCommand):
|
||||||
target_objs = []
|
target_objs = []
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
target_obj = self.caller.search(target)
|
target_obj = self.caller.search(target)
|
||||||
if target_obj:
|
if not target_obj:
|
||||||
# show a warning but don't abort
|
# show a warning but don't abort
|
||||||
continue
|
continue
|
||||||
target_objs.append(target_obj)
|
target_objs.append(target_obj)
|
||||||
|
|
||||||
if target_objs:
|
if target_objs:
|
||||||
join_combat(self.caller, *target_objs, session=self.session)
|
try:
|
||||||
|
join_combat(self.caller, *target_objs, session=self.session)
|
||||||
|
except CombatFailure as err:
|
||||||
|
self.caller.msg(f"|r{err}|n")
|
||||||
|
else:
|
||||||
|
self.caller.msg("|rFound noone to attack.|n")
|
||||||
|
|
|
||||||
|
|
@ -3,15 +3,72 @@ EvAdventure NPCs. This includes both friends and enemies, only separated by thei
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .characters import EvAdventureCharacter
|
from evennia import DefaultCharacter
|
||||||
|
from evennia.typeclasses.attributes import AttributeProperty
|
||||||
|
|
||||||
class EvAdventureNPC(EvAdventureCharacter):
|
from .characters import LivingMixin
|
||||||
|
|
||||||
|
|
||||||
|
class EvAdventureNPC(LivingMixin, DefaultCharacter):
|
||||||
"""
|
"""
|
||||||
Base typeclass for NPCs. They have the features of a Character except
|
This is the base class for all non-player entities, including monsters. These
|
||||||
they have tooling for AI and for acting as quest-gives and shop-keepers.
|
generally don't advance in level but uses a simplified, abstract measure of how
|
||||||
|
dangerous or competent they are - the 'hit dice' (HD).
|
||||||
|
|
||||||
|
HD indicates how much health they have and how hard they hit. In _Knave_, HD also
|
||||||
|
defaults to being the bonus for all abilities. HP is 4 x Hit die (this can then be
|
||||||
|
customized per-entity of course).
|
||||||
|
|
||||||
|
Morale is set explicitly per-NPC, usually between 7 and 9.
|
||||||
|
|
||||||
|
Monsters don't use equipment in the way PCs do, instead they have a fixed armor
|
||||||
|
value, and their Abilities are dynamically generated from the HD (hit_dice).
|
||||||
|
|
||||||
|
If wanting monsters or NPCs that can level and work the same as PCs, base them off the
|
||||||
|
EvAdventureCharacter class instead.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
hit_dice = AttributeProperty(default=1)
|
||||||
|
armor = AttributeProperty(default=11)
|
||||||
|
morale = AttributeProperty(default=9)
|
||||||
|
hp = AttributeProperty(default=8)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def strength(self):
|
||||||
|
return self.hit_dice
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dexterity(self):
|
||||||
|
return self.hit_dice
|
||||||
|
|
||||||
|
@property
|
||||||
|
def constitution(self):
|
||||||
|
return self.hit_dice
|
||||||
|
|
||||||
|
@property
|
||||||
|
def intelligence(self):
|
||||||
|
return self.hit_dice
|
||||||
|
|
||||||
|
@property
|
||||||
|
def wisdom(self):
|
||||||
|
return self.hit_dice
|
||||||
|
|
||||||
|
@property
|
||||||
|
def charisma(self):
|
||||||
|
return self.hit_dice
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hp_max(self):
|
||||||
|
return self.hit_dice * 4
|
||||||
|
|
||||||
|
def at_object_creation(self):
|
||||||
|
"""
|
||||||
|
Start with max health.
|
||||||
|
|
||||||
|
"""
|
||||||
|
self.hp = self.hp_max
|
||||||
|
|
||||||
|
|
||||||
class EvAdventureShopKeeper(EvAdventureNPC):
|
class EvAdventureShopKeeper(EvAdventureNPC):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ Tags.
|
||||||
from evennia.objects.objects import DefaultObject
|
from evennia.objects.objects import DefaultObject
|
||||||
from evennia.typeclasses.attributes import AttributeProperty
|
from evennia.typeclasses.attributes import AttributeProperty
|
||||||
|
|
||||||
from .enums import WieldLocation, Ability
|
from .enums import Ability, WieldLocation
|
||||||
|
|
||||||
|
|
||||||
class EvAdventureObject(DefaultObject):
|
class EvAdventureObject(DefaultObject):
|
||||||
|
|
@ -44,6 +44,7 @@ class EvAdventureObjectFiller(EvAdventureObject):
|
||||||
meaning it's unusable.
|
meaning it's unusable.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
quality = AttributeProperty(0)
|
quality = AttributeProperty(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -53,6 +54,7 @@ class EvAdventureConsumable(EvAdventureObject):
|
||||||
have a limited usage in this way.
|
have a limited usage in this way.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
inventory_use_slot = AttributeProperty(WieldLocation.BACKPACK)
|
inventory_use_slot = AttributeProperty(WieldLocation.BACKPACK)
|
||||||
size = AttributeProperty(0.25)
|
size = AttributeProperty(0.25)
|
||||||
uses = AttributeProperty(1)
|
uses = AttributeProperty(1)
|
||||||
|
|
@ -91,6 +93,7 @@ class EvAdventureRunestone(EvAdventureWeapon):
|
||||||
they are quite powerful (and scales with caster level).
|
they are quite powerful (and scales with caster level).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
inventory_use_slot = AttributeProperty(WieldLocation.TWO_HANDS)
|
inventory_use_slot = AttributeProperty(WieldLocation.TWO_HANDS)
|
||||||
|
|
||||||
attack_type = AttributeProperty(Ability.INT)
|
attack_type = AttributeProperty(Ability.INT)
|
||||||
|
|
|
||||||
|
|
@ -23,14 +23,13 @@ This module presents several singletons to import
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from random import randint
|
from random import randint
|
||||||
|
|
||||||
from evennia.utils.evform import EvForm
|
from evennia.utils.evform import EvForm
|
||||||
from evennia.utils.evtable import EvTable
|
from evennia.utils.evtable import EvTable
|
||||||
from .enums import Ability
|
|
||||||
from .random_tables import (
|
|
||||||
character_generation as chargen_table,
|
|
||||||
death_and_dismemberment as death_table,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
from .enums import Ability
|
||||||
|
from .random_tables import character_generation as chargen_table
|
||||||
|
from .random_tables import death_and_dismemberment as death_table
|
||||||
|
|
||||||
# Basic rolls
|
# Basic rolls
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,9 @@ class EvAdventureMixin:
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
super().setUp()
|
super().setUp()
|
||||||
self.location = create.create_object(EvAdventureRoom, key="testroom")
|
self.location = create.create_object(EvAdventureRoom, key="testroom")
|
||||||
self.character = create.create_object(EvAdventureCharacter, key="testchar",
|
self.character = create.create_object(
|
||||||
location=self.location)
|
EvAdventureCharacter, key="testchar", location=self.location
|
||||||
|
)
|
||||||
self.helmet = create.create_object(
|
self.helmet = create.create_object(
|
||||||
EvAdventureObject,
|
EvAdventureObject,
|
||||||
key="helmet",
|
key="helmet",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ class EvAdventureTurnbasedCombatHandlerTest(EvAdventureMixin, BaseEvenniaTest):
|
||||||
Test the turn-based combat-handler implementation.
|
Test the turn-based combat-handler implementation.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
maxDiff = None
|
maxDiff = None
|
||||||
|
|
||||||
@patch(
|
@patch(
|
||||||
|
|
@ -52,10 +53,7 @@ class EvAdventureTurnbasedCombatHandlerTest(EvAdventureMixin, BaseEvenniaTest):
|
||||||
|
|
||||||
self.combathandler.register_action(self.combatant, action.key)
|
self.combathandler.register_action(self.combatant, action.key)
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(self.combathandler.action_queue[self.combatant], (action, (), {}))
|
||||||
self.combathandler.action_queue[self.combatant],
|
|
||||||
(action, (), {})
|
|
||||||
)
|
|
||||||
|
|
||||||
action.use = MagicMock()
|
action.use = MagicMock()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,6 @@ from collections import defaultdict
|
||||||
import inflect
|
import inflect
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from evennia.commands import cmdset
|
from evennia.commands import cmdset
|
||||||
from evennia.commands.cmdsethandler import CmdSetHandler
|
from evennia.commands.cmdsethandler import CmdSetHandler
|
||||||
from evennia.objects.manager import ObjectManager
|
from evennia.objects.manager import ObjectManager
|
||||||
|
|
@ -22,15 +21,9 @@ from evennia.scripts.scripthandler import ScriptHandler
|
||||||
from evennia.typeclasses.attributes import ModelAttributeBackend, NickHandler
|
from evennia.typeclasses.attributes import ModelAttributeBackend, NickHandler
|
||||||
from evennia.typeclasses.models import TypeclassBase
|
from evennia.typeclasses.models import TypeclassBase
|
||||||
from evennia.utils import ansi, create, funcparser, logger, search
|
from evennia.utils import ansi, create, funcparser, logger, search
|
||||||
from evennia.utils.utils import (
|
from evennia.utils.utils import (class_from_module, is_iter, lazy_property,
|
||||||
class_from_module,
|
list_to_string, make_iter, to_str,
|
||||||
is_iter,
|
variable_from_module)
|
||||||
lazy_property,
|
|
||||||
list_to_string,
|
|
||||||
make_iter,
|
|
||||||
to_str,
|
|
||||||
variable_from_module,
|
|
||||||
)
|
|
||||||
|
|
||||||
_INFLECT = inflect.engine()
|
_INFLECT = inflect.engine()
|
||||||
_MULTISESSION_MODE = settings.MULTISESSION_MODE
|
_MULTISESSION_MODE = settings.MULTISESSION_MODE
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
from evennia.utils.test_resources import BaseEvenniaTest, EvenniaTestCase
|
from evennia import DefaultCharacter, DefaultExit, DefaultObject, DefaultRoom
|
||||||
from evennia import DefaultObject, DefaultCharacter, DefaultRoom, DefaultExit
|
|
||||||
from evennia.typeclasses.attributes import AttributeProperty
|
|
||||||
from evennia.typeclasses.tags import TagProperty, AliasProperty, PermissionProperty
|
|
||||||
from evennia.objects.models import ObjectDB
|
from evennia.objects.models import ObjectDB
|
||||||
from evennia.objects.objects import DefaultObject
|
from evennia.objects.objects import DefaultObject
|
||||||
|
from evennia.typeclasses.attributes import AttributeProperty
|
||||||
|
from evennia.typeclasses.tags import (AliasProperty, PermissionProperty,
|
||||||
|
TagProperty)
|
||||||
from evennia.utils import create
|
from evennia.utils import create
|
||||||
|
from evennia.utils.test_resources import BaseEvenniaTest, EvenniaTestCase
|
||||||
|
|
||||||
|
|
||||||
class DefaultObjectTest(BaseEvenniaTest):
|
class DefaultObjectTest(BaseEvenniaTest):
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ class ScriptHandler(object):
|
||||||
"""
|
"""
|
||||||
return ScriptDB.objects.get_all_scripts_on_obj(self.obj, key=key)
|
return ScriptDB.objects.get_all_scripts_on_obj(self.obj, key=key)
|
||||||
|
|
||||||
def delete(self, key=None):
|
def remove(self, key=None):
|
||||||
"""
|
"""
|
||||||
Forcibly delete a script from this object.
|
Forcibly delete a script from this object.
|
||||||
|
|
||||||
|
|
@ -149,7 +149,8 @@ class ScriptHandler(object):
|
||||||
num += 1
|
num += 1
|
||||||
return num
|
return num
|
||||||
|
|
||||||
# alias to delete
|
# legacy aliases to remove
|
||||||
|
delete = remove
|
||||||
stop = delete
|
stop = delete
|
||||||
|
|
||||||
def all(self):
|
def all(self):
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@ ability to run timers.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
from django.utils.translation import gettext as _
|
||||||
|
from evennia.scripts.manager import ScriptManager
|
||||||
|
from evennia.scripts.models import ScriptDB
|
||||||
|
from evennia.typeclasses.models import TypeclassBase
|
||||||
|
from evennia.utils import create, logger
|
||||||
from twisted.internet.defer import Deferred, maybeDeferred
|
from twisted.internet.defer import Deferred, maybeDeferred
|
||||||
from twisted.internet.task import LoopingCall
|
from twisted.internet.task import LoopingCall
|
||||||
from django.utils.translation import gettext as _
|
|
||||||
from evennia.typeclasses.models import TypeclassBase
|
|
||||||
from evennia.scripts.models import ScriptDB
|
|
||||||
from evennia.scripts.manager import ScriptManager
|
|
||||||
from evennia.utils import create, logger
|
|
||||||
|
|
||||||
__all__ = ["DefaultScript", "DoNothing", "Store"]
|
__all__ = ["DefaultScript", "DoNothing", "Store"]
|
||||||
|
|
||||||
|
|
@ -366,7 +366,11 @@ class ScriptBase(ScriptDB, metaclass=TypeclassBase):
|
||||||
return
|
return
|
||||||
|
|
||||||
# call hook
|
# call hook
|
||||||
self.at_repeat()
|
try:
|
||||||
|
self.at_repeat()
|
||||||
|
except Exception:
|
||||||
|
logger.log_trace()
|
||||||
|
raise
|
||||||
|
|
||||||
# check repeats
|
# check repeats
|
||||||
if self.ndb._task:
|
if self.ndb._task:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue