diff --git a/.vscode/launch.json b/.vscode/launch.json index 7c48476..7f944c1 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "type": "python", "request": "launch", "program": "${workspaceFolder}/__main__.py", - "console": "externalTerminal", + "console": "integratedTerminal", "justMyCode": true, } ] diff --git a/games/example.yml b/games/example.yml index 5d8ef9d..769d49b 100644 --- a/games/example.yml +++ b/games/example.yml @@ -9,6 +9,18 @@ meta: # make sure every key is in lowercase - chainmail: def: 2 starter: true + enemies: + - john: + name: "John" + hp: 20 + def: 1 + attacks: + - slash: + atk: 2 + name: "Slash" + - boom: + atk: 1 + name: "Boom" game: # here goes all the game logic start: # the starting point always HAS to be named "start" (lowercase), the order and name of the rest does not matter @@ -51,5 +63,20 @@ game: # here goes all the game logic - leave leave: description: "Leave" - text: "You decide to leave." + text: "You decide to leave. But John Doe blocks your way!" + fight: john + actions: + - af + af: + description: "Continue" + text: "&cJohn&r: I'm really sorry for attacking you, I don't know what I was doing!" + actions: + - idc + - ok + idc: + description: "Leave silently" + text: "You decide to turn around and leave without saying a word." + ok: + description: "Accept apology" + text: "&cJohn&r: Oh, thank you, kind sir!" diff --git a/lib/fight.py b/lib/fight.py index 1374619..7dc2f24 100644 --- a/lib/fight.py +++ b/lib/fight.py @@ -1,26 +1,27 @@ import math -from lib.game import Item from .ascii import * from colorama import Fore import keyboard from random import randrange class FightHandler: - def __init__(self,message:str,name:str,hp:int,attacks:dict,lang:dict,eq:Item,img:str="") -> None: + def __init__(self,message:str,name:str,hp:int,defense:int,attacks:dict,lang:dict,eq:dict,img:str="") -> None: self.selected = 0 keyboard.add_hotkey("up",self.up) keyboard.add_hotkey("down",self.down) keyboard.add_hotkey("enter",self.attack) self.name = name - self.max = hp # starting HP - self.hp = self.max # current HP + self.max = hp # starting ENEMY HP + self.hp = self.max # current ENEMY HP + self.enemyDef = defense # ENEMY DEF + self.my = 30 # starting PLAYER HP TODO: maybe make this a variable self.attacks = attacks self.img = img self.lang = lang self.message = message self.equipped = eq - input() + self.show() def up(self): if self.selected == 0: @@ -51,11 +52,21 @@ class FightHandler: anim.play() s = [self.lang["attack"],self.lang["defend"],self.lang["inventory"]] for selection in s: - if(self.selected == self.selections.index(selection)): + if(self.selected == s.index(selection)): print(f"{Fore.RED}⚔{Fore.RESET} {selection}") else: print(f" {selection}") def attack(self): - self.hp -= self.attacks[randrange(len(self.attacks))][atk]. - input() + p = randrange(len(self.attacks)) + name = list(self.attacks[p].keys())[0] + enemyAtk = self.attacks[p][name]["atk"] + enemyDef = self.enemyDef + playerAtk = self.equipped["weapon"].attack + playerDef = self.equipped["armor"].defense + self.hp -= playerAtk - enemyDef # enemy takes damage + self.my -= enemyAtk - playerDef # player takes damage + self.message = f"{self.lang['enemydmg'].replace('$atk',str(playerAtk - enemyDef)).replace('$name',self.name)}\n{self.lang['playerdmg'].replace('$atk',str(enemyAtk - playerDef)).replace('$name',self.attacks[p][name]['name'])}" + + def defend(self): + self.message = self.lang["defended"] diff --git a/lib/game.py b/lib/game.py index 4572e2c..b36a52e 100644 --- a/lib/game.py +++ b/lib/game.py @@ -6,6 +6,7 @@ import re from lib.menu import HasItemDialogue, MenuManager from .save import SaveManager from .ascii import AsciiAnimation +from .fight import * from time import sleep from os import system @@ -19,6 +20,7 @@ class Game: # the game class keeps information about the loaded game self.id = data["meta"]["id"] # Game ID self.save = SaveManager(self.id) # saving self.equipped = {"weapon":None,"armor":None} # Items equipped by player + self.enemies = {} # Enemies if "equippable" in data["meta"].keys(): self.equippable = [] # Items that can be equipped by player for item in data["meta"]["equippable"]: @@ -34,7 +36,11 @@ class Game: # the game class keeps information about the loaded game i = next((x for x in self.equippable if x.name == list(item.keys())[0])) self.inventory.append(i) self.equipped[i.type] = i - + if "enemies" in data["meta"].keys(): + # Load enemies + for en in data["meta"]["enemies"]: + name = list(en.keys())[0] + self.enemies[name] = {"name":en["name"],"hp":en["hp"],"attacks":en["attacks"],"def":en["def"]} for k in data["game"]: self.nodes.update({k:data["game"][k]}) @@ -120,12 +126,18 @@ class Game: # the game class keeps information about the loaded game need_item.extend([None, None]) # we need to check if user has item m = HasItemDialogue(actions_desc,self.parse_colors(self.nodes[self.current]["text"]),self.inventory,need_item) - # TODO: Remove item from inventory after using it? while need_item[m.selected] != None and all(element not in self.inventory for element in need_item[m.selected]): # until user selects an available prompt, re-prompt again m = HasItemDialogue(actions_desc,self.parse_colors(self.nodes[self.current]["text"]),self.inventory,need_item) if m.selected <= len(actions_desc)-3 and "has_item" in self.nodes[self.nodes[self.current]["actions"][m.selected]].keys(): for item in need_item[m.selected]: self.inventory.remove(item) + elif "fight" in self.nodes[self.current].keys(): + # Initiate a fight + 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) + while s.hp > 0: + s.show() + input() else: m = MenuManager(actions_desc,self.parse_colors(self.nodes[self.current]["text"])) sel = m.selected diff --git a/lib/lang/cz.yml b/lib/lang/cz.yml index f8feb64..fb110fd 100644 --- a/lib/lang/cz.yml +++ b/lib/lang/cz.yml @@ -24,5 +24,11 @@ selection: 'Vyberte zadáním čísla:' not_number: 'Nezadali jste číslo' invalid: 'Neplatný výběr' +attack: "Útočit" +defend: "Bránit se" +enemydmg: "$name dostal zásah 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." + error_loading: 'Při načítání YAML souboru nastala chyba:' no_action: 'Chyba: žádná akce "$action" nenalezena v souboru hry' diff --git a/lib/lang/en.yml b/lib/lang/en.yml index 7646e0d..8314b32 100644 --- a/lib/lang/en.yml +++ b/lib/lang/en.yml @@ -26,6 +26,9 @@ invalid: 'Invalid selection' attack: "Attack" defend: "Defend" +enemydmg: "$name took $atk damage!" +playerdmg: "The enemy used $name to damage you by $atk" +defended: "You decide to defend yourself and take no damage." 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 newline at end of file