mirror of
https://github.com/RYGhub/royalnet.git
synced 2024-11-23 19:44:20 +00:00
yes
This commit is contained in:
parent
d3beadef16
commit
5220201434
14 changed files with 216 additions and 26 deletions
52
.idea/codeStyles/Project.xml
Normal file
52
.idea/codeStyles/Project.xml
Normal file
|
@ -0,0 +1,52 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<DBN-PSQL>
|
||||
<case-options enabled="true">
|
||||
<option name="KEYWORD_CASE" value="lower" />
|
||||
<option name="FUNCTION_CASE" value="lower" />
|
||||
<option name="PARAMETER_CASE" value="lower" />
|
||||
<option name="DATATYPE_CASE" value="lower" />
|
||||
<option name="OBJECT_CASE" value="preserve" />
|
||||
</case-options>
|
||||
<formatting-settings enabled="false" />
|
||||
</DBN-PSQL>
|
||||
<DBN-SQL>
|
||||
<case-options enabled="true">
|
||||
<option name="KEYWORD_CASE" value="lower" />
|
||||
<option name="FUNCTION_CASE" value="lower" />
|
||||
<option name="PARAMETER_CASE" value="lower" />
|
||||
<option name="DATATYPE_CASE" value="lower" />
|
||||
<option name="OBJECT_CASE" value="preserve" />
|
||||
</case-options>
|
||||
<formatting-settings enabled="false">
|
||||
<option name="STATEMENT_SPACING" value="one_line" />
|
||||
<option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
|
||||
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
|
||||
</formatting-settings>
|
||||
</DBN-SQL>
|
||||
<DBN-PSQL>
|
||||
<case-options enabled="true">
|
||||
<option name="KEYWORD_CASE" value="lower" />
|
||||
<option name="FUNCTION_CASE" value="lower" />
|
||||
<option name="PARAMETER_CASE" value="lower" />
|
||||
<option name="DATATYPE_CASE" value="lower" />
|
||||
<option name="OBJECT_CASE" value="preserve" />
|
||||
</case-options>
|
||||
<formatting-settings enabled="false" />
|
||||
</DBN-PSQL>
|
||||
<DBN-SQL>
|
||||
<case-options enabled="true">
|
||||
<option name="KEYWORD_CASE" value="lower" />
|
||||
<option name="FUNCTION_CASE" value="lower" />
|
||||
<option name="PARAMETER_CASE" value="lower" />
|
||||
<option name="DATATYPE_CASE" value="lower" />
|
||||
<option name="OBJECT_CASE" value="preserve" />
|
||||
</case-options>
|
||||
<formatting-settings enabled="false">
|
||||
<option name="STATEMENT_SPACING" value="one_line" />
|
||||
<option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
|
||||
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
|
||||
</formatting-settings>
|
||||
</DBN-SQL>
|
||||
</code_scheme>
|
||||
</component>
|
11
.idea/dataSources.xml
Normal file
11
.idea/dataSources.xml
Normal file
|
@ -0,0 +1,11 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="royalnet@combo.steffo.eu" uuid="e1643839-41cb-4186-bf58-6d375d1420c8">
|
||||
<driver-ref>postgresql</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:postgresql://combo.steffo.eu:5432/royalnet</jdbc-url>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
9
.idea/discord.xml
Normal file
9
.idea/discord.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="true" />
|
||||
</component>
|
||||
<component name="ProjectNotificationSettings">
|
||||
<option name="askShowProject" value="false" />
|
||||
</component>
|
||||
</project>
|
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
6
.idea/inspectionProfiles/profiles_settings.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<settings>
|
||||
<option name="USE_PROJECT_PROFILE" value="false" />
|
||||
<version value="1.0" />
|
||||
</settings>
|
||||
</component>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/rpgpack.iml" filepath="$PROJECT_DIR$/.idea/rpgpack.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
|
@ -1,6 +1,8 @@
|
|||
from royalnet.commands import *
|
||||
from royalnet.utils import asyncify
|
||||
from ..tables import DndCharacter, DndActiveCharacter
|
||||
from ..utils import get_active_character, get_interface_data
|
||||
import pickle
|
||||
|
||||
|
||||
class DndactiveCommand(Command):
|
||||
|
@ -15,17 +17,20 @@ class DndactiveCommand(Command):
|
|||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||
identifier = args.optional(0)
|
||||
author = await data.get_author(error_if_none=True)
|
||||
if identifier is None:
|
||||
active_character = await get_active_character(data)
|
||||
|
||||
# Display the active character
|
||||
if author.dnd_active_character is None:
|
||||
await data.reply("ℹ️ You have no active characters.")
|
||||
if identifier is None:
|
||||
if active_character is None:
|
||||
await data.reply("ℹ️ You haven't activated any character in this chat.")
|
||||
else:
|
||||
await data.reply(f"ℹ️ You currently active character is [b]{author.dnd_active_character}[/b].")
|
||||
await data.reply(f"ℹ️ Your active character for this chat is [b]{active_character.character}[/b].")
|
||||
return
|
||||
|
||||
# Find the character by name
|
||||
try:
|
||||
identifier = int(identifier)
|
||||
except ValueError:
|
||||
# Find the character by name
|
||||
chars = await asyncify(data.session.query(self.alchemy.get(DndCharacter)).filter_by(name=identifier).all)
|
||||
if len(chars) >= 2:
|
||||
char_string = "\n".join([f"[c]{char.character_id}[/c] (LV {char.level}) by {char.creator})" for char in chars])
|
||||
|
@ -43,12 +48,16 @@ class DndactiveCommand(Command):
|
|||
if char is None:
|
||||
raise CommandError("No character found.")
|
||||
# Check if the player already has an active character
|
||||
if author.dnd_active_character is None:
|
||||
if active_character is None:
|
||||
# Create a new active character
|
||||
achar = self.alchemy.get(DndActiveCharacter)(character=char, user=author)
|
||||
achar = self.alchemy.get(DndActiveCharacter)(
|
||||
character=char,
|
||||
user=author,
|
||||
interface_name=self.interface.name,
|
||||
interface_data=pickle.dumps(get_interface_data(data)))
|
||||
data.session.add(achar)
|
||||
else:
|
||||
# Change the active character
|
||||
author.dnd_active_character.character = char
|
||||
active_character.character = char
|
||||
await data.session_commit()
|
||||
await data.reply(f"✅ Active character set to [b]{char}[/b]!")
|
||||
|
|
|
@ -2,6 +2,7 @@ import re
|
|||
from royalnet.commands import *
|
||||
from .dndnew import DndnewCommand
|
||||
from ..tables import DndCharacter
|
||||
from ..utils import get_active_character
|
||||
|
||||
|
||||
class DndeditCommand(DndnewCommand):
|
||||
|
@ -18,11 +19,10 @@ class DndeditCommand(DndnewCommand):
|
|||
await data.reply(self._syntax())
|
||||
return
|
||||
|
||||
author = await data.get_author(error_if_none=True)
|
||||
if author.dnd_active_character is None:
|
||||
active_character = await get_active_character(data)
|
||||
if active_character is None:
|
||||
raise CommandError("You don't have an active character.")
|
||||
|
||||
char: DndCharacter = author.dnd_active_character.character
|
||||
char = active_character.character
|
||||
|
||||
arguments = self._parse(character_sheet)
|
||||
for key in arguments:
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from royalnet.commands import *
|
||||
from ..tables import DndCharacter, DndActiveCharacter
|
||||
from ..utils import get_active_character
|
||||
|
||||
|
||||
class DndinfoCommand(Command):
|
||||
|
@ -13,6 +14,10 @@ class DndinfoCommand(Command):
|
|||
|
||||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||
author = await data.get_author(error_if_none=True)
|
||||
if author.dnd_active_character is None:
|
||||
|
||||
active_character = await get_active_character(data)
|
||||
char = active_character.character
|
||||
|
||||
if char is None:
|
||||
raise CommandError("You don't have an active character.")
|
||||
await data.reply(author.dnd_active_character.character.character_sheet())
|
||||
await data.reply(char.character_sheet())
|
||||
|
|
|
@ -2,6 +2,7 @@ import random
|
|||
import math
|
||||
from royalnet.commands import *
|
||||
from ..tables import DndCharacter
|
||||
from ..utils import get_active_character
|
||||
|
||||
|
||||
class DndrollCommand(Command):
|
||||
|
@ -73,14 +74,14 @@ class DndrollCommand(Command):
|
|||
"ste": "stealth",
|
||||
"nas": "stealth",
|
||||
"sur": "survival",
|
||||
"sop": "sopravvivenza",
|
||||
"sop": "survival",
|
||||
}
|
||||
|
||||
async def run(self, args: CommandArgs, data: CommandData) -> None:
|
||||
author = await data.get_author(error_if_none=True)
|
||||
if author.dnd_active_character is None:
|
||||
active_character = await get_active_character(data)
|
||||
if active_character is None:
|
||||
raise CommandError("You don't have an active character.")
|
||||
char: DndCharacter = author.dnd_active_character.character
|
||||
char = active_character.character
|
||||
|
||||
first = args[0]
|
||||
second = args.optional(1)
|
||||
|
|
|
@ -50,7 +50,7 @@ class DndspellCommand(Command):
|
|||
|
||||
@staticmethod
|
||||
def _parse_spell(spell: dict) -> str:
|
||||
string = ['✨ [b]{spell["name"]}[/b]\n']
|
||||
string = [f'✨ [b]{spell["name"]}[/b]\n']
|
||||
|
||||
# Source (manual, page)
|
||||
if "source" in spell:
|
||||
|
@ -61,10 +61,18 @@ class DndspellCommand(Command):
|
|||
string.append("\n")
|
||||
|
||||
# Level
|
||||
if spell["level"] == 0:
|
||||
string.append(f'[b]Cantrip[/b]\n')
|
||||
else:
|
||||
string.append(f'[b]{ordinalformat(spell["level"])}[/b] level\n')
|
||||
string.append({
|
||||
0: "0️⃣ [b]Cantrip[/b]\n",
|
||||
1: "1️⃣ [b]1st[/b] level\n",
|
||||
2: "2️⃣ [b]2nd[/b] level\n",
|
||||
3: "3️⃣ [b]3rd[/b] level\n",
|
||||
4: "4️⃣ [b]4th[/b] level\n",
|
||||
5: "5️⃣ [b]5th[/b] level\n",
|
||||
6: "6️⃣ [b]6th[/b] level\n",
|
||||
7: "7️⃣ [b]7th[/b] level\n",
|
||||
8: "8️⃣ [b]8th[/b] level\n",
|
||||
9: "9️⃣ [b]9th[/b] level\n",
|
||||
}[spell["level"]])
|
||||
|
||||
# School
|
||||
string.append({
|
||||
|
@ -78,6 +86,7 @@ class DndspellCommand(Command):
|
|||
"P": "Psionic",
|
||||
"T": "Transmutation",
|
||||
}[spell["school"]])
|
||||
string.append("\n\n")
|
||||
|
||||
# Cast time
|
||||
for time in spell.get("time", []):
|
||||
|
@ -98,9 +107,29 @@ class DndspellCommand(Command):
|
|||
string.append("Range: ♾ [b]Unlimited[/b]\n")
|
||||
else:
|
||||
string.append(f'Range: 🏹 [b]{spell["range"]["distance"]["amount"]}'
|
||||
f' {spell["range"]["distance"]["type"]}[/b] ({spell["range"]["type"]})\n')
|
||||
f' {spell["range"]["distance"]["type"]}[/b] (point)\n')
|
||||
elif range["type"] == "radius":
|
||||
string.append(f'Range: ⭕️ [b]{spell["range"]["distance"]["amount"]}'
|
||||
f' {spell["range"]["distance"]["type"]}[/b] (radius)\n')
|
||||
elif range["type"] == "sphere":
|
||||
string.append(f'Range: 🌕 [b]{spell["range"]["distance"]["amount"]}'
|
||||
f' {spell["range"]["distance"]["type"]}[/b] (sphere)\n')
|
||||
elif range["type"] == "cone":
|
||||
string.append(f'Range: 🍦 [b]{spell["range"]["distance"]["amount"]}'
|
||||
f' {spell["range"]["distance"]["type"]}[/b] (cone)\n')
|
||||
elif range["type"] == "line":
|
||||
string.append(f'Range: ➖ [b]{spell["range"]["distance"]["amount"]}'
|
||||
f' {spell["range"]["distance"]["type"]}[/b] (line)\n')
|
||||
elif range["type"] == "hemisphere":
|
||||
string.append(f'Range: 🌗 [b]{spell["range"]["distance"]["amount"]}'
|
||||
f' {spell["range"]["distance"]["type"]}[/b] (hemisphere)\n')
|
||||
elif range["type"] == "cube":
|
||||
string.append(f'Range: ⬜️ [b]{spell["range"]["distance"]["amount"]}'
|
||||
f' {spell["range"]["distance"]["type"]}[/b] (cube)\n')
|
||||
elif range["type"] == "special":
|
||||
string.append("Range: ⭐️ Special")
|
||||
else:
|
||||
string.append('Range: ⚠️[b]UNKNOWN[/b]')
|
||||
|
||||
# Components
|
||||
components = spell.get("components")
|
||||
|
|
|
@ -20,7 +20,15 @@ class DndActiveCharacter:
|
|||
|
||||
@declared_attr
|
||||
def user(self):
|
||||
return relationship("User", foreign_keys=self.user_id, backref=backref("dnd_active_character", uselist=False))
|
||||
return relationship("User", foreign_keys=self.user_id, backref=backref("dnd_active_characters"))
|
||||
|
||||
@declared_attr
|
||||
def interface_name(self):
|
||||
return Column(String)
|
||||
|
||||
@declared_attr
|
||||
def interface_data(self):
|
||||
return Column(LargeBinary)
|
||||
|
||||
def __repr__(self):
|
||||
return f"<{self.__class__.__qualname__} for {self.user_id}: {self.character_id}>"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
from .dndproficiencytype import DndProficiencyType
|
||||
from .parse5etoolsentry import parse_5etools_entry
|
||||
from .getactivechar import get_active_character, get_interface_data
|
||||
|
||||
__all__ = ["DndProficiencyType", "parse_5etools_entry"]
|
||||
__all__ = ["DndProficiencyType", "parse_5etools_entry", "get_active_character", "get_interface_data"]
|
||||
|
|
45
rpgpack/utils/getactivechar.py
Normal file
45
rpgpack/utils/getactivechar.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
from typing import *
|
||||
from ..tables import DndActiveCharacter
|
||||
import royalnet.utils as ru
|
||||
import royalnet.commands as rc
|
||||
import pickle
|
||||
|
||||
|
||||
def get_interface_data(data: rc.CommandData):
|
||||
if data._interface.name == "telegram":
|
||||
return data.message.chat.id
|
||||
elif data._interface.name == "discord":
|
||||
return data.message.channel.id
|
||||
else:
|
||||
raise rc.UnsupportedError("This interface isn't supported yet.")
|
||||
|
||||
|
||||
async def get_active_character(data: rc.CommandData) -> Optional[DndActiveCharacter]:
|
||||
interface = data._interface
|
||||
alchemy = interface.alchemy
|
||||
user = await data.get_author(error_if_none=True)
|
||||
idata = get_interface_data(data)
|
||||
|
||||
DndAcChT = alchemy.get(DndActiveCharacter)
|
||||
active_characters: List[DndActiveCharacter] = await ru.asyncify(
|
||||
data.session
|
||||
.query(DndAcChT)
|
||||
.filter_by(interface_name=interface.name, user=user)
|
||||
.all
|
||||
)
|
||||
|
||||
for active_character in active_characters:
|
||||
if interface.name == "telegram":
|
||||
# interface_data is chat id
|
||||
chat_id = pickle.loads(active_character.interface_data)
|
||||
if chat_id == idata:
|
||||
return active_character
|
||||
elif interface.name == "discord":
|
||||
# interface_data is channel id
|
||||
chat_id = pickle.loads(active_character.interface_data)
|
||||
if chat_id == idata:
|
||||
return active_character
|
||||
else:
|
||||
raise rc.UnsupportedError("This interface isn't supported yet.")
|
||||
|
||||
return None
|
Loading…
Reference in a new issue