Complete fighting and squash bugs
This commit is contained in:
parent
04538bae36
commit
860b98f1a9
7 changed files with 127 additions and 31 deletions
53
lib/fight.py
53
lib/fight.py
|
@ -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()
|
48
lib/game.py
48
lib/game.py
|
@ -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:
|
|
||||||
s.show()
|
|
||||||
input()
|
input()
|
||||||
|
while m.hp > 0 and m.my > 0:
|
||||||
|
m.show()
|
||||||
|
m.rebind() # rebind due to MenuManager in show_inventory
|
||||||
|
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,6 +180,12 @@ 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 type(item) is Item:
|
||||||
|
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
|
if(i == len(self.inventory)): # last item
|
||||||
s += f"- {item}"
|
s += f"- {item}"
|
||||||
else:
|
else:
|
||||||
|
@ -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
9
lib/item.py
Normal 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
|
|
@ -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í!"
|
|
@ -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!"
|
|
@ -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):
|
||||||
|
|
30
lib/save.py
30
lib/save.py
|
@ -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)
|
||||||
|
|
Reference in a new issue