1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-27 13:34:28 +00:00

#2, #3, #4 and #5: Implement multi target commands

This commit is contained in:
Steffo 2020-03-16 23:21:24 +01:00
parent 3a596805e7
commit f425be7c95
13 changed files with 131 additions and 159 deletions

View file

@ -2,7 +2,7 @@
[tool.poetry] [tool.poetry]
name = "rpgpack" name = "rpgpack"
version = "5.4" version = "5.5"
description = "A Royalnet Pack to play role-playing-games" description = "A Royalnet Pack to play role-playing-games"
authors = ["Stefano Pigozzi <ste.pigozzi@gmail.com>"] authors = ["Stefano Pigozzi <ste.pigozzi@gmail.com>"]
license = "AGPL-3.0+" license = "AGPL-3.0+"

View file

@ -0,0 +1,5 @@
from .dndbattletarget import DndBattleTargetCommand
__all__ = [
"DndBattleTargetCommand",
]

View file

@ -0,0 +1,30 @@
import abc
from typing import *
import royalnet
import royalnet.commands as rc
import royalnet.utils as ru
from ...tables import DndBattleUnit
from ...utils import get_targets
class DndBattleTargetCommand(rc.Command, abc.ABC):
@abc.abstractmethod
async def _change(self, unit: DndBattleUnit, args: List[str]):
...
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
target = args[0]
units = await get_targets(data, target)
if len(units) == 0:
raise rc.InvalidInputError(f"No targets found matching [c]{target}[/c].")
for unit in units:
await self._change(unit, args[1:])
await data.session_commit()
message = []
for unit in units:
message.append(f"{unit}")
await data.reply("\n\n".join(message))

View file

@ -1,34 +1,18 @@
from typing import * from typing import *
import royalnet
import royalnet.commands as rc
import royalnet.utils as ru
from ..tables import DndBattleUnit from ..tables import DndBattleUnit
from ..utils import find_unit_in_current_battle from .abstract import DndBattleTargetCommand
class DnddamageCommand(rc.Command): class DnddamageCommand(DndBattleTargetCommand):
name: str = "dnddamage" name: str = "dnddamage"
description: str = "Damage a unit in the currently active battle." description: str = "Damage a target in the currently active battle."
syntax: str = "[name] {damage}" syntax: str = "{target} {damage}"
aliases = ["dmg", "ddmg", "dnddmg", "damage", "ddamage"] aliases = ["damage", "ddamage", "dd"]
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None:
if len(args) > 1:
name = args[0]
damage = int(args[1])
else:
name = None
damage = int(args[0])
unit = await find_unit_in_current_battle(data, name)
if unit is None:
raise rc.InvalidInputError("No such unit is fighting in the currently active battle.")
async def _change(self, unit: DndBattleUnit, args: List[str]):
health = unit.health health = unit.health
health.change(-damage) health.change(-int(args[0]))
unit.health = health unit.health = health
await data.session_commit()
await data.reply(f"{unit}")

View file

@ -1,40 +1,24 @@
from typing import * from typing import *
import royalnet
import royalnet.commands as rc import royalnet.commands as rc
import royalnet.utils as ru
from ..tables import DndBattleUnit from ..tables import DndBattleUnit
from ..utils import find_unit_in_current_battle from .abstract import DndBattleTargetCommand
class DnddeathsaveCommand(rc.Command): class DnddeathsaveCommand(DndBattleTargetCommand):
name: str = "dnddeathsave" name: str = "dnddeathsave"
description: str = "Add a death save result to a unit in the currently active battle." description: str = "Add a death save result to a target in the currently active battle."
syntax: str = "[name] {s|f}" syntax: str = "{target} {s|f}"
aliases = ["deathsave", "ddeathsave", "ds", "dds", "dndds"] aliases = ["deathsave", "ddeathsave", "ds", "dds", "dndds"]
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def _change(self, unit: DndBattleUnit, args: List[str]):
if len(args) > 1:
name = args[0]
result = args[1].lower()
else:
name = None
result = args[0].lower()
unit = await find_unit_in_current_battle(data, name)
if unit is None:
raise rc.InvalidInputError("No such unit is fighting in the currently active battle.")
health = unit.health health = unit.health
if result[0] == "s": if args[0][0] == "s":
health.deathsave_success() health.deathsave_success()
elif result[0] == "f": elif args[0][0] == "f":
health.deathsave_failure() health.deathsave_failure()
else: else:
raise rc.InvalidInputError("Unknown result type") raise rc.InvalidInputError(f"Unknown result type [c]{args[0][0]}[/c].")
unit.health = health unit.health = health
await data.session_commit()
await data.reply(f"{unit}")

View file

@ -1,33 +1,16 @@
from typing import * from typing import *
import royalnet
import royalnet.commands as rc
import royalnet.utils as ru
from ..tables import DndBattleUnit from ..tables import DndBattleUnit
from ..utils import find_unit_in_current_battle from .abstract import DndBattleTargetCommand
class DndextraCommand(rc.Command): class DndextraCommand(DndBattleTargetCommand):
name: str = "dndextra" name: str = "dndextra"
description: str = "Change the extras for a unit in the current battle." description: str = "Change the extras for a target in the current battle."
syntax: str = "[name] {extra}" syntax: str = "{target} {extra}"
aliases = ["extra", "dextra"] aliases = ["extra", "dextra"]
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def _change(self, unit: DndBattleUnit, args: List[str]):
name = args.optional(0) unit.extra = " ".join(args)
extra = " ".join(args[1:])
if name is not None:
unit: Optional[DndBattleUnit] = await find_unit_in_current_battle(data, name)
else:
unit = None
if unit is None:
extra = " ".join(args)
unit: Optional[DndBattleUnit] = await find_unit_in_current_battle(data, None)
unit.extra = extra
await data.session_commit()
await data.reply(f"{unit}")

View file

@ -1,34 +1,18 @@
from typing import * from typing import *
import royalnet
import royalnet.commands as rc
import royalnet.utils as ru
from ..tables import DndBattleUnit from ..tables import DndBattleUnit
from ..utils import find_unit_in_current_battle from .abstract import DndBattleTargetCommand
class DndhealCommand(rc.Command): class DndhealCommand(DndBattleTargetCommand):
name: str = "dndheal" name: str = "dndheal"
description: str = "Heal a unit in the currently active battle." description: str = "Heal a target in the currently active battle."
syntax: str = "[name] {heal}" syntax: str = "{target} {heal}"
aliases = ["heal", "dheal"] aliases = ["heal", "dheal"]
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def _change(self, unit: DndBattleUnit, args: List[str]):
if len(args) > 1:
name = args[0]
heal = int(args[1])
else:
name = None
heal = int(args[0])
unit = await find_unit_in_current_battle(data, name)
if unit is None:
raise rc.InvalidInputError("No such unit is fighting in the currently active battle.")
health = unit.health health = unit.health
health.change(heal) health.change(int(args[0]))
unit.health = health unit.health = health
await data.session_commit()
await data.reply(f"{unit}")

View file

@ -1,34 +1,16 @@
from typing import * from typing import *
import royalnet
import royalnet.commands as rc
import royalnet.utils as ru
from ..tables import DndBattleUnit from ..tables import DndBattleUnit
from ..utils import find_unit_in_current_battle from .abstract import DndBattleTargetCommand
class DndstatusCommand(rc.Command): class DndstatusCommand(DndBattleTargetCommand):
name: str = "dndstatus" name: str = "dndstatus"
description: str = "Change the status for a unit in the current battle." description: str = "Change the target for a unit in the current battle."
syntax: str = "[name] {status}" syntax: str = "{target} {status}"
aliases = ["status", "dstatus"] aliases = ["status", "dstatus"]
async def run(self, args: rc.CommandArgs, data: rc.CommandData) -> None: async def _change(self, unit: DndBattleUnit, args: List[str]):
name = args.optional(0) unit.status = " ".join(args)
status = " ".join(args[1:])
if name is not None:
unit: Optional[DndBattleUnit] = await find_unit_in_current_battle(data, name)
else:
unit = None
if unit is None:
status = " ".join(args)
unit: Optional[DndBattleUnit] = await find_unit_in_current_battle(data, None)
unit.status = status
await data.session_commit()
await data.reply(f"{unit}")

View file

@ -12,3 +12,10 @@ class Faction(enum.Enum):
BLACK = "⚫️" BLACK = "⚫️"
WHITE = "⚪️" WHITE = "⚪️"
BROWN = "🟤" BROWN = "🟤"
@classmethod
def get(cls, string: str):
try:
return cls[string.upper()]
except KeyError:
return cls(string)

View file

@ -2,12 +2,12 @@ from .parse5etoolsentry import parse_5etools_entry
from .getinterfacedata import get_interface_data from .getinterfacedata import get_interface_data
from .getactivechar import get_active_character from .getactivechar import get_active_character
from .getactivebattle import get_active_battle from .getactivebattle import get_active_battle
from .findunitincurrentbattle import find_unit_in_current_battle from .gettargets import get_targets
__all__ = [ __all__ = [
"parse_5etools_entry", "parse_5etools_entry",
"get_interface_data", "get_interface_data",
"get_active_character", "get_active_character",
"get_active_battle", "get_active_battle",
"find_unit_in_current_battle" "get_targets"
] ]

View file

@ -1,39 +0,0 @@
from typing import *
import royalnet.commands as rc
import royalnet.utils as ru
from ..tables import DndBattleUnit
from .getactivebattle import get_active_battle
from .getactivechar import get_active_character
from sqlalchemy import func, and_
async def find_unit_in_current_battle(data: rc.CommandData, name: Optional[str]) -> Optional[DndBattleUnit]:
DndBattleUnitT = data._interface.alchemy.get(DndBattleUnit)
active_battle = await get_active_battle(data)
if active_battle is None:
raise rc.CommandError("No battle is active in this chat.")
if name is None:
active_character = await get_active_character(data)
if active_character is None:
raise rc.InvalidInputError("You currently have no active character.")
unit = await ru.asyncify(data.session.query(DndBattleUnitT).filter_by(
linked_character=active_character.character,
battle=active_battle.battle
).one_or_none)
if unit is None:
raise rc.InvalidInputError("Your active character is not fighting in this battle.")
else:
unit = await ru.asyncify(data.session.query(DndBattleUnitT).filter(and_(
func.lower(DndBattleUnitT.name) == func.lower(name),
DndBattleUnitT.battle == active_battle.battle
)).one_or_none)
if unit is None:
return None
return unit

View file

@ -0,0 +1,52 @@
from typing import *
import royalnet.commands as rc
import royalnet.utils as ru
from ..tables import DndBattleUnit
from .getactivebattle import get_active_battle
from .getactivechar import get_active_character
from ..types.faction import Faction
from sqlalchemy import and_
async def get_targets(data: rc.CommandData, target: Optional[str]) -> List[DndBattleUnit]:
DndBattleUnitT = data._interface.alchemy.get(DndBattleUnit)
active_battle = await get_active_battle(data)
if active_battle is None:
raise rc.CommandError("No battle is active in this chat.")
battle = active_battle.battle
# Get the active character
if not target or target.upper() == "SELF":
active_character = await get_active_character(data)
if active_character is None:
return []
char = active_character.character
return await ru.asyncify(data.session.query(DndBattleUnitT).filter_by(
linked_character=char,
battle=battle
).all)
# Get all
if target.upper() == "ALL":
return await ru.asyncify(data.session.query(DndBattleUnitT).filter_by(
battle=battle
).all)
# Get by faction
try:
faction = Faction.get(target)
except ValueError:
pass
else:
return await ru.asyncify(data.session.query(DndBattleUnitT).filter_by(
faction=faction,
battle=battle
).all)
# Get by ilike
return await ru.asyncify(data.session.query(DndBattleUnitT).filter(and_(
DndBattleUnitT.name.ilike(target),
DndBattleUnitT.battle == battle
)).all)

View file

@ -1 +1 @@
semantic = "5.4" semantic = "5.5"