Sets up RPG system as a Redbot cog with core mechanics Implements character creation, class selection, and stat management Adds action commands for attacking and healing Provides inventory and shop functionality for item management Introduces interactive UI menus for user engagement
126 lines
5.3 KiB
Python
126 lines
5.3 KiB
Python
import asyncio
|
|
import random
|
|
import discord
|
|
from .check import Check
|
|
from redbot.core import commands, Config
|
|
from .inventory import RPGInventory
|
|
from typing import Literal
|
|
|
|
class RPGActions:
|
|
"""
|
|
Implements the core RPG mechanics and actions.
|
|
"""
|
|
|
|
def __init__(self, rpg_cog):
|
|
self.rpg_cog = rpg_cog
|
|
self.inventory = RPGInventory(rpg_cog)
|
|
|
|
async def create_character(self, interaction: discord.Interaction, user, character_name):
|
|
"""
|
|
Creates a new character for the user.
|
|
"""
|
|
|
|
# Character Name Validation
|
|
check = Check(interaction, length=30)
|
|
if not check.length_under(interaction.message) or not character_name.isalnum():
|
|
return await self.rpg_cog.send_message(interaction, "Invalid character name. Please choose a name between 2 and 30 characters long, containing only letters and numbers.")
|
|
|
|
# Retrieve the 'characters' group
|
|
characters_group = self.rpg_cog.config.member(user).characters
|
|
|
|
# Then, get all characters within that group (await the .all() call)
|
|
existing_characters = await characters_group.all()
|
|
|
|
# Check for duplicate character names (case-insensitive)
|
|
if any(existing_name.lower() == character_name.lower() for existing_name in existing_characters):
|
|
return await self.rpg_cog.send_message(interaction, f"You already have a character named '{character_name}'. Choose another name.")
|
|
|
|
# Retrieve available classes from config
|
|
try:
|
|
available_classes = await self.rpg_cog.config.guild(user.guild).get_raw("classes", default=[])
|
|
except KeyError:
|
|
return await self.rpg_cog.send_message(interaction, "No classes have been configured yet. Please contact an admin.")
|
|
|
|
if not available_classes:
|
|
return await self.rpg_cog.send_message(interaction, "No classes are available yet. Please contact an admin.")
|
|
|
|
# Prompt user to choose a class
|
|
class_options = "\n".join([f"{i+1}. {class_name}" for i, class_name in enumerate(available_classes)])
|
|
await self.rpg_cog.send_message(interaction, f"Choose a class for your character:\n{class_options}")
|
|
|
|
def check(m):
|
|
return m.author == user and m.channel == interaction.channel and m.content.isdigit() and 1 <= int(m.content) <= len(available_classes)
|
|
|
|
try:
|
|
class_choice = await self.rpg_cog.bot.wait_for("message", check=check, timeout=30.0)
|
|
except asyncio.TimeoutError:
|
|
return await self.rpg_cog.send_message(interaction, "Class selection timed out. Character creation canceled.")
|
|
|
|
selected_class = available_classes[int(class_choice.content) - 1]
|
|
|
|
# Retrieve default stats for the selected class
|
|
try:
|
|
default_stats = await self.rpg_cog.config.guild(user.guild).get_raw("characters", "classes", selected_class, "stats")
|
|
except KeyError:
|
|
return await self.rpg_cog.send_message(interaction, f"Default stats for class '{selected_class}' haven't been configured yet. Please contact an admin.")
|
|
|
|
# Create character data
|
|
character_data = {
|
|
"name": character_name,
|
|
"class": [selected_class], # Store the selected class
|
|
"level": 1,
|
|
"experience": 0,
|
|
"stats": default_stats.copy(),
|
|
"inventory": [],
|
|
"equipment": {},
|
|
"skills": [],
|
|
"gold": 0,
|
|
"max_health": 100,
|
|
"health": 100,
|
|
"mana": 50,
|
|
"max_mana": 50,
|
|
}
|
|
|
|
# Store character data in config
|
|
await characters_group.set_raw(character_name, value=character_data)
|
|
await self.rpg_cog.config.member(user).active_character.set(character_name)
|
|
|
|
await interaction.response.send_message(interaction, f"Character '{character_name}' (Class: {selected_class}) created for {user.mention}!")
|
|
|
|
async def attack(self, ctx, attacker, target):
|
|
"""
|
|
Handles the attack action.
|
|
"""
|
|
# Check if attacker and target have active characters
|
|
if not await self._has_active_character(ctx, attacker):
|
|
return
|
|
if not await self._has_active_character(ctx, target):
|
|
return
|
|
|
|
attacker_data = await self.rpg_cog.config.member(attacker).active_character
|
|
target_data = await self.rpg_cog.config.member(target).active_character
|
|
|
|
# ... (rest of the attack logic)
|
|
|
|
async def heal(self, ctx, user):
|
|
"""
|
|
Handles the heal action.
|
|
"""
|
|
# ... (rest of the heal logic)
|
|
|
|
# Helper function to check if a user has an active character
|
|
async def _has_active_character(self, ctx, user):
|
|
active_character = await self.rpg_cog.config.member(user).active_character
|
|
if not active_character:
|
|
await self.rpg_cog.send_message(ctx, f"{user.mention}, you don't have an active character. Create one using `[p]create_character <name>`.")
|
|
return False
|
|
return True
|
|
|
|
async def use_item(self, ctx, user, item_name):
|
|
"""
|
|
Handles the use of an item from the inventory.
|
|
"""
|
|
# ... (logic to check if the user has the item and handle its effects)
|
|
|
|
# Remove the used item from the inventory
|
|
await self.inventory.remove_item(ctx, user, item_name) |