Complete fighting and squash bugs

This commit is contained in:
Matyáš Caras 2022-05-04 10:16:30 +02:00 committed by GitHub
parent 04538bae36
commit 860b98f1a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 127 additions and 31 deletions

View file

@ -1,16 +1,16 @@
import math import math
from lib.menu import MenuManager
from .ascii import * from .ascii import *
from colorama import Fore from colorama import Fore
import keyboard import keyboard
from random import randrange from random import randrange
class FightHandler: class FightHandler:
def __init__(self,message:str,name:str,hp:int,defense:int,attacks:dict,lang:dict,eq:dict,img:str="") -> None: def __init__(self,message:str,name:str,hp:int,defense:int,attacks:dict,lang:dict,eq:dict,inv:list,img:str="") -> None:
self.selected = 0 self.selected = 0
keyboard.add_hotkey("up",self.up) self.rebind()
keyboard.add_hotkey("down",self.down)
keyboard.add_hotkey("enter",self.attack)
self.name = name self.name = name
self.max = hp # starting ENEMY HP self.max = hp # starting ENEMY HP
self.hp = self.max # current ENEMY HP self.hp = self.max # current ENEMY HP
@ -21,6 +21,7 @@ class FightHandler:
self.lang = lang self.lang = lang
self.message = message self.message = message
self.equipped = eq self.equipped = eq
self.inventory = inv
self.show() self.show()
def up(self): def up(self):
@ -40,6 +41,7 @@ class FightHandler:
self.show() self.show()
def show(self): def show(self):
system("cls||clear")
p = math.trunc(self.hp/self.max*10) p = math.trunc(self.hp/self.max*10)
h = "🟥"*p h = "🟥"*p
if str(p).endswith(".5"): if str(p).endswith(".5"):
@ -57,6 +59,39 @@ class FightHandler:
else: else:
print(f" {selection}") print(f" {selection}")
def make_selection(self) -> None:
if self.selected == 0:
self.attack()
elif self.selected == 1:
self.defend()
elif self.selected == 2:
self.show_inventory()
def rebind(self):
keyboard.remove_all_hotkeys()
keyboard.add_hotkey("up",self.up)
keyboard.add_hotkey("down",self.down)
keyboard.add_hotkey("enter",self.make_selection)
def show_inventory(self): # Basically `Game` show_inventory
system("cls||clear")
if len(self.inventory) == 0:
FightMenu([self.lang["return"]],f" {self.lang['inside_inv']} \n")
else:
s = ""
for i,item in enumerate(self.inventory):
if type(item) is not str:
if(i == len(self.inventory)): # last item
s += f"- {item.name}"
else:
s += f"- {item.name}\n"
else:
if(i == len(self.inventory)): # last item
s += f"- {item}"
else:
s += f"- {item}\n"
FightMenu([self.lang["return"]],f" {self.lang['inside_inv']} \n{s}")
def attack(self): def attack(self):
p = randrange(len(self.attacks)) p = randrange(len(self.attacks))
name = list(self.attacks[p].keys())[0] name = list(self.attacks[p].keys())[0]
@ -70,3 +105,13 @@ class FightHandler:
def defend(self): def defend(self):
self.message = self.lang["defended"] self.message = self.lang["defended"]
class FightMenu(MenuManager):
def __init__(self,selections:list,additional:str):
self.selected = 0 # current selection
self.selections = selections # available selections
self.additional = additional # additional text to display above the menu
keyboard.add_hotkey("up",self.up)
keyboard.add_hotkey("down",self.down)
keyboard.add_hotkey("enter",self.make_selection)
self.show_menu()

View file

@ -2,6 +2,7 @@ import yaml
from yaml.loader import SafeLoader from yaml.loader import SafeLoader
from colorama import Fore, Back from colorama import Fore, Back
import re import re
from lib.item import Item
from lib.menu import HasItemDialogue, MenuManager from lib.menu import HasItemDialogue, MenuManager
from .save import SaveManager from .save import SaveManager
@ -11,14 +12,15 @@ from time import sleep
from os import system from os import system
class Game: # the game class keeps information about the loaded game class Game: # the game class keeps information about the loaded game
def __init__(self,data:dict): def __init__(self,data:dict,lang):
self.name = data["meta"]["name"] # Game name self.name = data["meta"]["name"] # Game name
self.author = data["meta"]["creator"] # Game creator self.author = data["meta"]["creator"] # Game creator
self.current = "start" # Current prompt self.current = "start" # Current prompt
self.nodes = {} # All nodes self.nodes = {} # All nodes
self.inventory = [] # Player's inventory self.inventory = [] # Player's inventory
self.id = data["meta"]["id"] # Game ID self.id = data["meta"]["id"] # Game ID
self.save = SaveManager(self.id) # saving self.lang = lang # Language strings
self.save = SaveManager(self.id,self.lang) # saving
self.equipped = {"weapon":None,"armor":None} # Items equipped by player self.equipped = {"weapon":None,"armor":None} # Items equipped by player
self.enemies = {} # Enemies self.enemies = {} # Enemies
if "equippable" in data["meta"].keys(): if "equippable" in data["meta"].keys():
@ -134,10 +136,27 @@ class Game: # the game class keeps information about the loaded game
elif "fight" in self.nodes[self.current].keys(): elif "fight" in self.nodes[self.current].keys():
# Initiate a fight # Initiate a fight
enemy = self.enemies[self.nodes[self.current]["fight"]] # TODO: Complete after fight actions enemy = self.enemies[self.nodes[self.current]["fight"]] # TODO: Complete after fight actions
s = FightHandler(self.nodes[self.current]["text"],enemy["name"],enemy["hp"],enemy["def"],enemy["attacks"],self.lang,self.equipped) m = FightHandler(self.nodes[self.current]["text"],enemy["name"],enemy["hp"],enemy["def"],enemy["attacks"],self.lang,self.equipped,self.inventory)
while s.hp > 0: input()
s.show() while m.hp > 0 and m.my > 0:
m.show()
m.rebind() # rebind due to MenuManager in show_inventory
input() input()
system("cls||clear")
keyboard.remove_all_hotkeys()
if m.hp < 1:
# Enemy defeated
print(self.lang["defeated"].replace("$enemy",enemy["name"]))
sleep(5)
self.current = self.nodes[self.current]["actions"][0] # move to the first action
self.print_text()
return
else:
# Player defeated
print(self.lang["defeat"].replace("$enemy",enemy["name"]))
sleep(5)
self.print_text()
return
else: else:
m = MenuManager(actions_desc,self.parse_colors(self.nodes[self.current]["text"])) m = MenuManager(actions_desc,self.parse_colors(self.nodes[self.current]["text"]))
sel = m.selected sel = m.selected
@ -161,10 +180,16 @@ class Game: # the game class keeps information about the loaded game
else: else:
s = "" s = ""
for i,item in enumerate(self.inventory): for i,item in enumerate(self.inventory):
if(i == len(self.inventory)): # last item if type(item) is Item:
s += f"- {item}" if(i == len(self.inventory)): # last item
s += f"- {item.name}"
else:
s += f"- {item.name}\n"
else: else:
s += f"- {item}\n" if(i == len(self.inventory)): # last item
s += f"- {item}"
else:
s += f"- {item}\n"
MenuManager([self.lang["return"]],f" {self.lang['inside_inv']} \n{s}") MenuManager([self.lang["return"]],f" {self.lang['inside_inv']} \n{s}")
self.print_text() self.print_text()
@ -183,20 +208,9 @@ def load(file_path,lang): # starts to load the game from YAML
try: try:
with open(file_path) as f: with open(file_path) as f:
data = yaml.load(f,Loader=SafeLoader) data = yaml.load(f,Loader=SafeLoader)
g = Game(data) g = Game(data,lang)
g.lang = lang
return g return g
except Exception as e: except Exception as e:
print(f"{Back.RED}{Fore.WHITE}ERROR{Fore.RESET}{Back.RESET}") print(f"{Back.RED}{Fore.WHITE}ERROR{Fore.RESET}{Back.RESET}")
print(e) print(e)
return None return None
class Item:
def __init__(self,name:str,attack:int = 0,defense:int = 0) -> None:
self.name = name
if attack == 0 and defense > 0:
self.type = "armor"
else:
self.type = "weapon"
self.attack = attack
self.defense = defense

9
lib/item.py Normal file
View file

@ -0,0 +1,9 @@
class Item:
def __init__(self,name:str,attack:int = 0,defense:int = 0) -> None:
self.name = name
if attack == 0 and defense > 0:
self.type = "armor"
else:
self.type = "weapon"
self.attack = attack
self.defense = defense

View file

@ -29,6 +29,9 @@ defend: "Bránit se"
enemydmg: "$name dostal zásah za $atk bodů!" enemydmg: "$name dostal zásah za $atk bodů!"
playerdmg: "Nepřítel použil $name a poškodil tě za $atk bodů." playerdmg: "Nepřítel použil $name a poškodil tě za $atk bodů."
defended: "Rozhodneš se bránit a nedostal jsi tak žádný zásah." defended: "Rozhodneš se bránit a nedostal jsi tak žádný zásah."
defeated: "Porazil jsi $enemy."
defeat: "$enemy tě zabil. Budeš to muset zkusit znovu."
error_loading: 'Při načítání YAML souboru nastala chyba:' error_loading: 'Při načítání YAML souboru nastala chyba:'
no_action: 'Chyba: žádná akce "$action" nenalezena v souboru hry' no_action: 'Chyba: žádná akce "$action" nenalezena v souboru hry'
no_comp: "VAROVÁNÍ: Tato uložená hra je pro starší verzi enginu a nemusí být kompatibilní!"

View file

@ -29,6 +29,9 @@ defend: "Defend"
enemydmg: "$name took $atk damage!" enemydmg: "$name took $atk damage!"
playerdmg: "The enemy used $name to damage you by $atk" playerdmg: "The enemy used $name to damage you by $atk"
defended: "You decide to defend yourself and take no damage." defended: "You decide to defend yourself and take no damage."
defeated: "You have defeated $enemy."
defeat: "$enemy has slain you. You'll have to try again."
error_loading: 'An exception has occured while loading the game from the YAML file' error_loading: 'An exception has occured while loading the game from the YAML file'
no_action: 'Error: No action "$action" found in the game file.' no_action: 'Error: No action "$action" found in the game file.'
no_comp: "WARNING: This save is for an older version of the engine and may not be compatible!"

View file

@ -15,7 +15,7 @@ class MenuManager:
self.show_menu() self.show_menu()
input() input()
def make_selection(self) -> int: def make_selection(self) -> None:
keyboard.remove_all_hotkeys() keyboard.remove_all_hotkeys()
def up(self): def up(self):

View file

@ -1,22 +1,44 @@
from os import path from time import sleep
from os import path, system
import yaml import yaml
from lib.game import Item
class SaveManager: # manages save and configuration files class SaveManager: # manages save and configuration files
def __init__(self,gid:str): def __init__(self,gid:str,lang):
self.id = gid # game ID self.id = gid # game ID
self.currentPrompt = "" # Current prompt self.currentPrompt = "" # Current prompt
self.inventory = [] # Items in inventory self.inventory = [] # Items in inventory
self.version = 1
self.lang = lang
def load(self): def load(self):
if(path.exists(f"./saves/{self.id}.yml")): if(path.exists(f"./saves/{self.id}.yml")):
with open(f"./saves/{self.id}.yml",encoding="utf-8") as f: with open(f"./saves/{self.id}.yml",encoding="utf-8") as f:
data = yaml.load(f,Loader=yaml.SafeLoader) data = yaml.load(f,Loader=yaml.SafeLoader)
self.currentPrompt = data["currentPrompt"] self.currentPrompt = data["currentPrompt"]
self.inventory = data["inventory"] if(data["version"] < self.version):
system("cls||clear")
print(self.lang["no_comp"])
sleep(5)
inv = []
for item in data["inventory"]:
if type(item) is str:
inv.append(item)
else:
# Item class
inv.append(Item(item["name"],item["atk"],item["def"]))
return True return True
return False return False
def save(self): def save(self):
data = {"id":self.id,"currentPrompt":self.currentPrompt,"inventory":self.inventory} inv = []
for item in self.inventory:
if type(item) is str:
inv.append(item)
else:
# Item class
inv.append({"name":item.name,"atk":item.attack,"def":item.defense})
data = {"id":self.id,"currentPrompt":self.currentPrompt,"inventory":self.inventory,"version":1}
with open(f"./saves/{self.id}.yml",mode="w",encoding="utf-8") as f: with open(f"./saves/{self.id}.yml",mode="w",encoding="utf-8") as f:
yaml.dump(data,f) yaml.dump(data,f)