Semi working on this but the community for Pygame GUI isn't big enough to help me as often and in the way that my lack of expertise requires.
486 lines
18 KiB
Plaintext
486 lines
18 KiB
Plaintext
import pygame
|
|
import pygame_gui
|
|
from enum import Enum, auto
|
|
from random import randint
|
|
from functions import *
|
|
|
|
|
|
class Player:
|
|
"""Character Creation"""
|
|
|
|
# Default Character
|
|
def __init__(self, name, gender, age, race, job):
|
|
# Personality
|
|
self.name = name
|
|
self.gender = gender
|
|
self.age = age
|
|
self.race = race
|
|
self.job = job
|
|
# Health
|
|
self.currentHP = 100
|
|
self.maxHP = 100
|
|
# Levels
|
|
self.level = 1
|
|
self.exp = 0
|
|
self.maxEXP = 100
|
|
# Magic
|
|
self.spells_known = []
|
|
self.spells_ready = []
|
|
# Equipment
|
|
self.weapon = rock
|
|
self.armor = tornRags
|
|
# Defence
|
|
self.ac = 0
|
|
self.elemental_resistance = {DamageType.FIRE: False, DamageType.WATER: False, DamageType.LIGHTNING: False}
|
|
self.physical_resistance = {DamageType.SLASHING: False, DamageType.CRUSHING: False, DamageType.PIERCING: False}
|
|
# Ability Scores
|
|
self.stats = {"Strength": 0,
|
|
"Dexterity": 0,
|
|
"Constitution": 0,
|
|
"Intelligence": 0,
|
|
"Wisdom": 0,
|
|
"Charisma": 0}
|
|
# Ability Modifiers
|
|
self.mods = {"Strength": 0,
|
|
"Dexterity": 0,
|
|
"Constitution": 0,
|
|
"Intelligence": 0,
|
|
"Wisdom": 0,
|
|
"Charisma": 0}
|
|
# Held items
|
|
self.inventory = {rock: {"Count": 1,
|
|
"object": Weapon,
|
|
"equipped": True
|
|
},
|
|
tornRags: {"Count": 1,
|
|
"object": Armor,
|
|
"equipped": True
|
|
},
|
|
GP1: {"Count": 10,
|
|
"object": Money,
|
|
"equipped": False
|
|
},
|
|
}
|
|
|
|
# @property
|
|
# def dexMod(self):
|
|
# return self.mods["Dexterity"]
|
|
|
|
def getModifier(self):
|
|
self.mods["Strength"] = -5 + self.stats["Strength"] // 2
|
|
self.mods["Dexterity"] = -5 + self.stats["Dexterity"] // 2
|
|
self.mods["Constitution"] = -5 + self.stats["Constitution"] // 2
|
|
self.mods["Intelligence"] = -5 + self.stats["Intelligence"] // 2
|
|
self.mods["Wisdom"] = -5 + self.stats["Wisdom"] // 2
|
|
self.mods["Charisma"] = -5 + self.stats["Charisma"] // 2
|
|
|
|
def set_stats(self):
|
|
if self.race == "elf":
|
|
self.stats["Dexterity"] += 2
|
|
self.stats["Intelligence"] += 2
|
|
elif self.race == "human":
|
|
self.stats["Strength"] += 2
|
|
self.stats["Constitution"] += 2
|
|
elif self.race == "dwarf":
|
|
self.stats["Constitution"] += 2
|
|
self.stats["Strength"] += 2
|
|
elif self.job == "warrior":
|
|
self.stats["Strength"] += 2
|
|
self.stats["Constitution"] += 1
|
|
elif self.job == "ranger":
|
|
self.stats["Dexterity"] += 2
|
|
self.stats["Charisma"] += 1
|
|
elif self.job == "mage":
|
|
self.stats["Intelligence"] += 2
|
|
self.stats["Charisma"] += 1
|
|
|
|
def introduce(self):
|
|
typingPrint("Adjusting for your race and class bonuses." + "\n", time)
|
|
time.sleep(1)
|
|
typingPrint(f'Welcome {self.name}, to Kanjin: An RPG Text Adventure.\n', time)
|
|
|
|
def current_stats(self):
|
|
"""Prints a display of the user's current statistics."""
|
|
print("Your current stats are:")
|
|
print(f'Hit Points: {self.currentHP}/{self.maxHP}')
|
|
print(f'Strength: {self.stats["Strength"]}')
|
|
print(f'Dexterity: {self.stats["Dexterity"]}')
|
|
print(f'Constitution: {self.stats["Constitution"]}')
|
|
print(f'Intelligence: {self.stats["Intelligence"]}')
|
|
print(f'Charisma: {self.stats["Charisma"]}')
|
|
|
|
def current_equip(self):
|
|
"""Prints a list of items currently equipped."""
|
|
typingPrint(f"You have equipped:<br> {self.armor.name}<br>"
|
|
f" {self.armor.description}"
|
|
f"<br>{self.weapon.name}<br>"
|
|
f" {self.weapon.description}<br>>", time)
|
|
|
|
def new_char(self):
|
|
"""Outputs final stats, armour, and inventory"""
|
|
typingPrint("We will now generate random stats for your character.<br>", time)
|
|
self.introduce()
|
|
print(' ')
|
|
time.sleep(2)
|
|
self.rollStats()
|
|
self.set_stats()
|
|
print(' ')
|
|
self.getModifier()
|
|
self.current_stats()
|
|
print(' ')
|
|
time.sleep(2)
|
|
self.current_equip()
|
|
print(' ')
|
|
current_inventory()
|
|
print(' ')
|
|
|
|
def rollStats(self):
|
|
"""Rolls stats 4d6kh3"""
|
|
# Roll stats
|
|
typingPrint("Rolling for Strength...\n", time)
|
|
self.dice_rolls("Strength")
|
|
typingPrint(f'Strength: {self.stats["Strength"]}\n', time)
|
|
time.sleep(1)
|
|
typingPrint("Rolling for Dexterity...\n", time)
|
|
self.dice_rolls("Dexterity")
|
|
typingPrint(f'Dexterity: {self.stats["Dexterity"]}\n', time)
|
|
time.sleep(1)
|
|
typingPrint("Rolling for Constitution...\n", time)
|
|
self.dice_rolls("Constitution")
|
|
typingPrint(f'Constitution: {self.stats["Constitution"]}\n', time)
|
|
time.sleep(1)
|
|
typingPrint("Rolling for Intelligence...\n", time)
|
|
self.dice_rolls("Intelligence")
|
|
typingPrint(f'Intelligence: {self.stats["Intelligence"]}\n', time)
|
|
time.sleep(1)
|
|
typingPrint("Rolling for Wisdom...\n", time)
|
|
self.dice_rolls("Wisdom")
|
|
typingPrint(f'Wisdom: {self.stats["Wisdom"]}\n', time)
|
|
time.sleep(1)
|
|
typingPrint("Rolling for Charisma...\n", time)
|
|
self.dice_rolls("Charisma")
|
|
typingPrint(f'Charisma: {self.stats["Charisma"]}\n', time)
|
|
time.sleep(1)
|
|
|
|
def health_check(self):
|
|
"""Print out current/max HP"""
|
|
print(f'You have {self.currentHP}/{self.maxHP} HP.')
|
|
|
|
def take_damage(self, DMGtype, size):
|
|
"""Define the damage type and dice size"""
|
|
damage = randint(1, size)
|
|
if DMGtype in self.elemental_resistance or DMGtype in self.physical_resistance:
|
|
damage //= 2
|
|
self.currentHP -= damage
|
|
return damage
|
|
|
|
def dice_rolls(self, attribute):
|
|
"""Rolling 4d6 to get stats for PC"""
|
|
rolls = []
|
|
# roll 4d6
|
|
for roll in range(4):
|
|
r = randint(1, 6)
|
|
rolls.append(r)
|
|
# Drop the lowest number
|
|
del rolls[rolls.index(min(rolls))]
|
|
self.stats[attribute] += sum(rolls)
|
|
return attribute
|
|
|
|
|
|
# Inventory list
|
|
def current_inventory():
|
|
"""Prints a list of items in your backpack that aren't equipped to your person."""
|
|
typingPrint(f'In your rucksack you have:\n', time)
|
|
for item_key, item_value in user.inventory.items():
|
|
for key, value in item_value.items():
|
|
if key == "equipped" and value == False:
|
|
typingPrint(f'{item_key.name}\n'
|
|
f' {item_key.description}\n', time)
|
|
|
|
|
|
def helpMenu():
|
|
helpmenu = "This is the help menu"
|
|
return helpmenu
|
|
|
|
|
|
# Equipment list
|
|
# def equipment():
|
|
|
|
# elif event.type == pygame_gui.UI_TEXT_ENTRY_FINISHED:
|
|
# a = userTextEntry.get_text()
|
|
# if a == "armor":
|
|
# return (f"<br>You currently have equipped:<br> {user.armor}<br>"
|
|
# f"Would you like to equip something new? Y/N")
|
|
#
|
|
# elif a == "weapons":
|
|
# return (f"<br>You currently have equipped:<br> {user.weapon}<br>"
|
|
# f"Would you like to equip something new? Y/N")
|
|
|
|
|
|
def equipped():
|
|
"""Print currently equipped, print a list of held armor pieces,
|
|
if input matches a held item, replace equipped condition"""
|
|
|
|
text = f"You currently have equipped: {user.armor}\n Would you like to equip something new? Y/N"
|
|
if event.type == pygame_gui.UI_BUTTON_PRESSED:
|
|
if event.ui_element == helpButton:
|
|
for item_key, item_value in user.inventory.items():
|
|
# item_info = dict
|
|
for key, value in item_value.items():
|
|
# Leather armor[items], "object"[key], Armor[value]
|
|
if key == "object" and value == Armor:
|
|
armor_list = "\n", item_key
|
|
return armor_list
|
|
else:
|
|
else_comment = "I'm sorry, I didn't understand that.\nWould you like to equip something new? Y/N"
|
|
return else_comment
|
|
return text
|
|
|
|
|
|
class DamageType(Enum):
|
|
SLASHING = auto()
|
|
CRUSHING = auto()
|
|
PIERCING = auto()
|
|
FIRE = auto()
|
|
WATER = auto()
|
|
LIGHTNING = auto()
|
|
|
|
|
|
class DamageMod(Enum):
|
|
STRENGTH = auto()
|
|
DEXTERITY = auto()
|
|
CONSTITUTION = auto()
|
|
INTELLIGENCE = auto()
|
|
WISDOM = auto()
|
|
CHARISMA = auto()
|
|
|
|
|
|
class Item:
|
|
"""The base class for all items"""
|
|
|
|
def __init__(self, name, description, value, magical):
|
|
self.name = name
|
|
self.description = description
|
|
self.value = value
|
|
self.magical = magical
|
|
|
|
def __repr__(self):
|
|
return f"{self.name}<br>=====<br>{self.description}<br>Value: {self.value}<br>"
|
|
|
|
|
|
class Money(Item):
|
|
"""The currency item used in the world of Kanjin"""
|
|
|
|
def __init__(self, name, amt, magical):
|
|
self.name = name
|
|
self.amt = amt
|
|
self.magical = magical
|
|
super().__init__(name=self.name,
|
|
description=f"A small round coin made of {self.name.lower()} "
|
|
f"with the imperial city logo stamped on the face.",
|
|
value=self.amt,
|
|
magical=self.magical)
|
|
|
|
|
|
class Weapon(Item):
|
|
"""The base class for all weapons"""
|
|
|
|
def __init__(self, name, description, value, damage1H, damage2H, dmgType, dmgMod, vers, thrown, magical):
|
|
self.damage1H = damage1H
|
|
self.damage2H = damage2H
|
|
self.dmgType = dmgType
|
|
self.dmgMod = dmgMod
|
|
self.vers = vers
|
|
self.thrown = thrown
|
|
super().__init__(name, description, value, magical)
|
|
|
|
def __repr__(self):
|
|
return f"{self.name}<br>=====<br>{self.description}<br>Value: {self.value}" \
|
|
f"<br>Damage: One Handed - {self.damage1H}" \
|
|
f"<br>Damage: Two Handed - {self.damage2H}<br>" \
|
|
f"Damage Type: {self.dmgType}<br>Magical: {self.magical}.<br>"
|
|
|
|
|
|
class Armor(Item):
|
|
"""The base class for all armor"""
|
|
|
|
def __init__(self, name, description, value, grade, ac, disadvantage, dmgRes, magical):
|
|
self.grade = grade
|
|
self.ac = ac
|
|
self.stealthDis = disadvantage
|
|
self.dmgRes = dmgRes
|
|
super().__init__(name, description, value, magical)
|
|
|
|
def __repr__(self):
|
|
if self.stealthDis:
|
|
return f"{self.name}<br>=====<br>{self.description}<br>Value: {self.value}<br>" \
|
|
f"AC: {self.ac}<br>Magical: {self.magical}"
|
|
elif not self.stealthDis:
|
|
return f"{self.name}<br>=====<br>{self.description}<br>Value: {self.value}<br>" \
|
|
f"AC: {self.ac}<br>Disadvantage on Stealth checks: {self.stealthDis}<br>Magical: {self.magical}"
|
|
|
|
|
|
# Different types of coins
|
|
GP1 = Money("Gold", 1, False)
|
|
SP1 = Money("Silver", 1, False)
|
|
CP1 = Money("Copper", 1, False)
|
|
|
|
rock = Weapon(
|
|
name="Rock",
|
|
description="A fist-sized rock, suitable for bludgeoning.",
|
|
value="No value",
|
|
damage1H=randint(1, 6),
|
|
damage2H=0,
|
|
dmgType=DamageType.CRUSHING,
|
|
dmgMod=DamageMod.STRENGTH,
|
|
vers=False,
|
|
thrown=True,
|
|
magical=False
|
|
)
|
|
tornRags = Armor(
|
|
name="Torn Rags",
|
|
description="A ripped and worn-out outfit.",
|
|
value=0,
|
|
grade="Light",
|
|
ac=0,
|
|
disadvantage=True,
|
|
dmgRes="None",
|
|
magical=False
|
|
)
|
|
|
|
user = Player("Jamie", "Male", 29, "Elf", "Mage")
|
|
pygame.init()
|
|
|
|
# Create a screen
|
|
screen = pygame.display.set_mode((1240, 720))
|
|
screen.fill("black")
|
|
|
|
# Set title and Icon
|
|
pygame.display.set_caption('Kanjin: An RPG Text Adventure')
|
|
icon = pygame.image.load("icon.png").convert_alpha()
|
|
pygame.display.set_icon(icon)
|
|
|
|
# ((size), "theme.json")
|
|
manager = pygame_gui.UIManager((1200, 720))
|
|
manager.set_visual_debug_mode(False)
|
|
|
|
# Set surface elements
|
|
# relative_rect = pygame.Rect((top left position)(UIButton size))
|
|
userInputButton = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((708, 642), (115, 33)),
|
|
text='Send',
|
|
manager=manager,
|
|
object_id="#userInputButton")
|
|
|
|
inventoryButton = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((1085, 20), (107, 100)),
|
|
text='Inventory',
|
|
manager=manager,
|
|
object_id="#inventoryButton")
|
|
|
|
equipmentButton = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((1085, 150), (107, 100)),
|
|
text='Equipment',
|
|
manager=manager,
|
|
object_id="#equipmentButton")
|
|
|
|
helpButton = pygame_gui.elements.UIButton(relative_rect=pygame.Rect((1085, 280), (107, 100)),
|
|
text='Help',
|
|
manager=manager,
|
|
object_id="#helpButton")
|
|
|
|
sceneImage_surface = pygame.Surface((1003, 242))
|
|
sceneImage_surface.fill((34, 40, 45))
|
|
sceneImage_image = pygame_gui.elements.UIImage(relative_rect=pygame.Rect((20, 20), (1003, 242)),
|
|
image_surface=icon,
|
|
manager=manager,
|
|
object_id="#sceneImage")
|
|
|
|
userTextEntry_surface = pygame.Surface((645, 33))
|
|
userTextEntry = pygame_gui.elements.UITextEntryLine(pygame.Rect((20, 642), (645, 33)),
|
|
manager=manager,
|
|
object_id="#player_input")
|
|
sceneText_surface = pygame.Surface((1003, 325))
|
|
sceneText = pygame_gui.elements.UITextBox("Test",
|
|
pygame.Rect((20, 282), (803, 325)),
|
|
manager=manager,
|
|
object_id="#scene_text")
|
|
# Typewriter Text
|
|
sceneText.set_active_effect(pygame_gui.TEXT_EFFECT_TYPING_APPEAR,
|
|
params={'time_per_letter': 0.001,
|
|
'time_per_letter_deviation': 0.0003}
|
|
|
|
)
|
|
|
|
# Set FPS
|
|
clock = pygame.time.Clock()
|
|
|
|
# Engine loop
|
|
equipmentButtonPressed = False
|
|
while True:
|
|
selection = "Not selected"
|
|
time_delta = clock.tick(60) / 1000.0
|
|
for event in pygame.event.get():
|
|
|
|
if event.type == pygame.QUIT:
|
|
quit()
|
|
|
|
if event.type == pygame_gui.UI_BUTTON_PRESSED:
|
|
if event.ui_element == userInputButton:
|
|
sceneText.append_html_text("<br>" + userTextEntry.get_text())
|
|
userTextEntry.set_text("")
|
|
|
|
if event.type == pygame_gui.UI_TEXT_ENTRY_FINISHED:
|
|
if not equipmentButtonPressed:
|
|
if userTextEntry.get_text().lower() == "clear":
|
|
sceneText = pygame_gui.elements.UITextBox("",
|
|
pygame.Rect((20, 282), (803, 325)),
|
|
manager=manager,
|
|
object_id="#scene_text")
|
|
userTextEntry.set_text("")
|
|
else:
|
|
selection = "text"
|
|
print("selection " + selection)
|
|
print(f"equip button pressed: {equipmentButtonPressed}")
|
|
sceneText.append_html_text("<br>" + userTextEntry.get_text())
|
|
userTextEntry.set_text("")
|
|
|
|
if event.type == pygame_gui.UI_TEXT_ENTRY_FINISHED:
|
|
if equipmentButtonPressed:
|
|
if userTextEntry.get_text().lower() == "armor":
|
|
selection = "armor"
|
|
sceneText.append_html_text("<br><br>" + f"You currently have equipped:<br> "
|
|
f"<b>{user.armor}</b><br>"
|
|
f"Would you like to equip something new? Y/N")
|
|
userTextEntry.set_text("")
|
|
# equipmentButtonPressed = False
|
|
|
|
elif userTextEntry.get_text().lower() == "weapons":
|
|
sceneText.append_html_text(f"<br>You currently have equipped:<br> {user.weapon}<br>"
|
|
f"Would you like to equip something new? Y/N")
|
|
userTextEntry.set_text("")
|
|
equipmentButtonPressed = False
|
|
|
|
else:
|
|
sceneText.append_html_text(f"<br>Sorry, I didn't understand that. Try again.")
|
|
userTextEntry.set_text("")
|
|
|
|
if event.type == pygame_gui.UI_BUTTON_PRESSED:
|
|
if event.ui_element == equipmentButton:
|
|
print("pressed button")
|
|
print(f"equip button pressed: {equipmentButtonPressed}")
|
|
equipmentButtonPressed = True
|
|
sceneText.append_html_text("<br>" + f"You currently have equipped: {user.armor}<br>"
|
|
f"Type 'armor' or 'weapons' to change equipment. ")
|
|
print("code executed")
|
|
print(f"equip button pressed: {equipmentButtonPressed}")
|
|
|
|
manager.process_events(event)
|
|
|
|
manager.update(time_delta)
|
|
|
|
# Blit
|
|
screen.blit(sceneText_surface, (20, 282))
|
|
screen.blit(userTextEntry_surface, (20, 642))
|
|
screen.blit(sceneImage_surface, (20, 20))
|
|
|
|
manager.draw_ui(screen)
|
|
pygame.display.update()
|