Compare commits
38 commits
Author | SHA1 | Date | |
---|---|---|---|
6e55242fb5 | |||
b8ffa7871d | |||
dce622c7b3 | |||
761a23da8a | |||
a98cc869dd | |||
17a444d0b5 | |||
d39971b852 | |||
01077b14bb | |||
b9a3d5c5d4 | |||
71e430f61d | |||
15ba06b4aa | |||
4696cfc621 | |||
7dd83c7ca0 | |||
362caee205 | |||
860b98f1a9 | |||
04538bae36 | |||
f0eae367b1 | |||
1cb78c4b8a | |||
8d58c9647a | |||
3e9cd33e98 | |||
3251dbe4a6 | |||
b347fd7585 | |||
5a530c7d88 | |||
322980c704 | |||
90358c73c7 | |||
7361882831 | |||
997475aef1 | |||
111e918c93 | |||
efaf74111b | |||
2240dd0c0b | |||
5d87c3a221 | |||
a398bbd5dc | |||
5ff4eb2b4a | |||
3a35468cd7 | |||
1a02220ffc | |||
e83e273569 | |||
07260d794e | |||
0d1646e0ff |
9
.vscode/launch.json
vendored
9
.vscode/launch.json
vendored
|
@ -5,12 +5,13 @@
|
|||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Start with example game",
|
||||
"name": "Python: Start main (verbose)",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${workspaceRoot}/__main__.py",
|
||||
"args": ["./example.yml"],
|
||||
"console": "integratedTerminal"
|
||||
"program": "${workspaceFolder}/__main__.py",
|
||||
"args": ["-v"],
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": true,
|
||||
}
|
||||
]
|
||||
}
|
24
README.md
24
README.md
|
@ -1,16 +1,16 @@
|
|||
# texty
|
||||
An extremely simple text-adventure game ~~engine(?)~~ player
|
||||
<div align="center">
|
||||
<h1>texty</h1>
|
||||
|
||||
## What is this?
|
||||
I was bored
|
||||
"Jednoduchý" přehrávač textových RPG her
|
||||
|
||||
![spaghetti code](https://img.shields.io/badge/spaghetti%20code-certified-success) [![wakatime](https://wakatime.com/badge/user/17178fab-a33c-430f-a764-7b3f26c7b966/project/cd3b8d2e-460d-4a8f-952b-dc3c1b869158.svg)](https://wakatime.com/badge/user/17178fab-a33c-430f-a764-7b3f26c7b966/project/cd3b8d2e-460d-4a8f-952b-dc3c1b869158) [![CodeFactor](https://www.codefactor.io/repository/github/hernikplays/texty/badge)](https://www.codefactor.io/repository/github/hernikplays/texty)
|
||||
</div>
|
||||
|
||||
## How do I make a game
|
||||
Check out the `example.yml` file, all games are in the `YAML` format.
|
||||
## Co to je
|
||||
Ročníková práce
|
||||
|
||||
## How do I use this
|
||||
Download/clone the repo and run the `__main__.py` file with the path to a game in `YAML` format as the first argument.
|
||||
## Jak se s tím pracuje
|
||||
TODO
|
||||
|
||||
## TODO
|
||||
- Colors
|
||||
- Catching errors while parsing YAML
|
||||
- Maybe a welcome screen instead of the need to enter the path as argument
|
||||
## Pozor
|
||||
Kvůli limitacím a/nebo bezpečnostním opatřením systému je na **MacOS** a **Linuxu** nutné spouštět jako sudo!
|
68
__main__.py
68
__main__.py
|
@ -1,17 +1,61 @@
|
|||
from sys import argv
|
||||
from genericpath import isdir
|
||||
import sys
|
||||
from lib.game import *
|
||||
from colorama import init
|
||||
from colorama import init, Back, Fore
|
||||
from os import mkdir, listdir, path
|
||||
|
||||
def main(): # TODO: Maybe a menu for available text games?
|
||||
init()
|
||||
if len(argv)<2:
|
||||
print("You need to specify a path to a YAML file")
|
||||
exit(1)
|
||||
def lang():
|
||||
lang = "en"
|
||||
if not (path.exists("./saves/lang")):
|
||||
mkdir("./saves")
|
||||
with open("./saves/lang","w") as f:
|
||||
f.write("en")
|
||||
else:
|
||||
game = load(argv[1])
|
||||
if(game is None):
|
||||
exit(1)
|
||||
game.main_menu()
|
||||
with open("./saves/lang","r") as f:
|
||||
lang = f.read()
|
||||
if lang == "cz":
|
||||
lang = "cz"
|
||||
data = ""
|
||||
with open(f"./lib/lang/{lang}.yml",encoding="utf-8") as f:
|
||||
data = yaml.load(f,Loader=SafeLoader)
|
||||
return data
|
||||
|
||||
def main():
|
||||
l = lang()
|
||||
init()
|
||||
if(not isdir("./games")):
|
||||
mkdir("./games")
|
||||
games = []
|
||||
for file in listdir("./games"):
|
||||
if file.endswith("yml") or file.endswith("yaml"):
|
||||
# hledá hry
|
||||
if len(sys.argv) > 1 and (sys.argv[1] == "-v" or sys.argv[1] == "--verbose"): # nepoužívá try/except pro vypsání celé chybové hlášky (debugování)
|
||||
g = load(f"./games/{file}",l)
|
||||
if g is not None:
|
||||
games.append(g)
|
||||
else:
|
||||
try:
|
||||
# parsuje
|
||||
g = load(f"./games/{file}",l)
|
||||
if g is not None:
|
||||
games.append(g)
|
||||
except Exception as e:
|
||||
print(f"{Back.RED}{Fore.WHITE}{l['error_loading']} {file}{Fore.RESET}{Back.RESET}:")
|
||||
print(e)
|
||||
print(l['enter'])
|
||||
input()
|
||||
|
||||
# výpis menu
|
||||
if len(games) < 1:
|
||||
print(l['no_games'])
|
||||
else:
|
||||
names = []
|
||||
for n in games:
|
||||
if(n is not None):
|
||||
names.append(n.name)
|
||||
m = MenuManager(names,f" TEXTY \n{l['available']}")
|
||||
games[m.selected].main_menu()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
main()
|
||||
|
|
28
example.yml
28
example.yml
|
@ -1,28 +0,0 @@
|
|||
meta: # make sure every key is in lowercase
|
||||
name: "My Text Adventure" # Game name
|
||||
id: "examplegame" # An original game ID (please try to be original)
|
||||
creator: "hernik" # Your name as a creator
|
||||
|
||||
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
|
||||
text: "&bYou arrive to a small tavern in the middle of nowhere.\nYou are greeted with a non-welcoming look on the faces of all the customers." # here is the text, which gets printed
|
||||
actions: # here you add a list of actions that are inside of `game`, the user can select them
|
||||
- wave
|
||||
- sit
|
||||
wave:
|
||||
description: "Wave" # this appears in the selection box, if no description is supplied
|
||||
text: "&bYou wave at the customers to signal your arrival. &rThey all ignore you and look away."
|
||||
sit: # if no `actions` are supplied, the game exits
|
||||
description: "Sit down"
|
||||
text: "You quietly sit down and check the menu."
|
||||
actions:
|
||||
- beer
|
||||
- nothing
|
||||
beer:
|
||||
description: "Order beer"
|
||||
text: "You order some &ebeer"
|
||||
add_inventory: "Beer" # add something to inventory
|
||||
nothing:
|
||||
description: "Do nothing"
|
||||
text: "You sit and wait..."
|
||||
|
84
games/example.yml
Normal file
84
games/example.yml
Normal file
|
@ -0,0 +1,84 @@
|
|||
meta: # make sure every key is in lowercase
|
||||
name: "My Text Adventure" # Game name
|
||||
id: "examplegame" # An original game ID (please try to be original)
|
||||
creator: "hernik" # Your name as a creator
|
||||
equippable:
|
||||
- iron_sword:
|
||||
atk: 3
|
||||
starter: true
|
||||
name: "Iron Sword"
|
||||
- chainmail:
|
||||
def: 2
|
||||
name: "Chainmail Armor"
|
||||
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
|
||||
text: "&bYou arrive to a small tavern in the middle of nowhere.\nYou are greeted with a non-welcoming look on the faces of all the customers." # here is the text, which gets printed
|
||||
actions: # here you add a list of actions that are inside of `game`, the user can select them
|
||||
- wave
|
||||
- sit
|
||||
wave:
|
||||
description: "Wave" # this appears in the selection box, if no description is supplied
|
||||
text: "&bYou wave at the customers to signal your arrival. &rThey all ignore you and look away."
|
||||
sit: # if no `actions` are supplied, the game exits
|
||||
description: "Sit down"
|
||||
text: "You quietly sit down and check the menu."
|
||||
actions:
|
||||
- beer
|
||||
- nothing
|
||||
beer:
|
||||
description: "Order beer"
|
||||
text: "You order some &ebeer"
|
||||
add_item: "Beer" # add something to inventory
|
||||
actions:
|
||||
- do_something
|
||||
nothing:
|
||||
description: "Do nothing"
|
||||
text: "You sit and wait..."
|
||||
actions:
|
||||
- drink
|
||||
- leave
|
||||
do_something:
|
||||
description: "Continue"
|
||||
text: "You start to feel bored."
|
||||
actions:
|
||||
- drink
|
||||
- leave
|
||||
drink:
|
||||
has_item: ["Beer"] # item names are case-sensitive
|
||||
description: "Drink beer"
|
||||
text: "You take a sip of your cold &eBeer"
|
||||
actions:
|
||||
- leave
|
||||
leave:
|
||||
description: "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!"
|
||||
|
88
games/example_cz.yml
Normal file
88
games/example_cz.yml
Normal file
|
@ -0,0 +1,88 @@
|
|||
meta: # Klíče musí být malým písmem
|
||||
name: "Moje Textové Dobrodružství" # Název hry
|
||||
id: "priklad" # Originální ID hry, používá se pro ukládání
|
||||
creator: "hernik" # Vaše jméno
|
||||
equippable: # Zde vložíte předměty, které si hráč může vybavit
|
||||
- iron_sword:
|
||||
atk: 3 # atk udává hodnotu poškození
|
||||
starter: true # Hodnota starter udává, jestli hráč dostane věci na začátku hry
|
||||
name: "Železný meč"
|
||||
- wood_sword:
|
||||
atk: 1
|
||||
starter: true
|
||||
name: "Dřevěný meč"
|
||||
- chainmail:
|
||||
def: 2 # def udává hodnotu brnění
|
||||
name: "Kroužková zbroj"
|
||||
starter: true
|
||||
enemies: # zde můžete vložit seznam nepřátel, které může hráč potkat
|
||||
- john:
|
||||
name: "Josef"
|
||||
hp: 20
|
||||
def: 1
|
||||
attacks: # zde vložíte seznam útoků, je nutný alespoň jeden útok
|
||||
- slash:
|
||||
atk: 2
|
||||
name: "Švih"
|
||||
- boom:
|
||||
atk: 1
|
||||
name: "Bumprásk"
|
||||
|
||||
game: # game obsahuje všechnu herní logiku a nody
|
||||
start: # hra musí začínat vždy u "start" (malým písmem)
|
||||
text: "&bDorazil jsi do malé krčmy uprostřed pustiny.\nUvnitř tě přivítá nepřátelský pohled zákazníků." # here is the text, which gets printed
|
||||
actions: # zde přidáš akce, tj. klíče nodů, které může hráč vybrat
|
||||
- wave
|
||||
- sit
|
||||
wave:
|
||||
description: "Zamávat" # Tento text se zobrazí ve výběru
|
||||
text: "&bZamáváš všem. &rVšichni tě ignorují."
|
||||
sit: # V případě, že nejsou zadány žádné akce, hra končí
|
||||
description: "Posadit se"
|
||||
text: "Potichu usedneš a podíváš se na jídelní lístek."
|
||||
actions:
|
||||
- beer
|
||||
- nothing
|
||||
beer:
|
||||
description: "Objednat pivo"
|
||||
text: "Objednáš si jedno &epivo"
|
||||
add_item: "Pivo" # přidá předmět do inventáře
|
||||
actions:
|
||||
- do_something
|
||||
nothing:
|
||||
description: "Nedělat nic"
|
||||
text: "Rozhodl ses nic nedělat a tak jen sedíš..."
|
||||
actions:
|
||||
- drink
|
||||
- leave
|
||||
do_something:
|
||||
description: "Pokračovat"
|
||||
text: "Začínáš se nudit."
|
||||
actions:
|
||||
- drink
|
||||
- leave
|
||||
drink:
|
||||
has_item: ["Pivo"] # názvy předmětů musí být doslovně, včetně malých a velkých písmen
|
||||
description: "Napít se"
|
||||
text: "Napil ses svého &ePiva"
|
||||
actions:
|
||||
- leave
|
||||
leave:
|
||||
description: "Odejít"
|
||||
text: "Rozhodl ses odejít. Ale Josef ti zablokoval cestu!"
|
||||
fight: john # klíč "fight" spouští souboj s postavou, kterou jsi definoval výše
|
||||
actions:
|
||||
- af
|
||||
af:
|
||||
description: "Pokračovat"
|
||||
text: "&cJosef&r: Opravdu se omlouvám, nevím, co to do mě vjelo!"
|
||||
actions:
|
||||
- idc
|
||||
- ok
|
||||
idc:
|
||||
description: "Mlčky odejít"
|
||||
text: "Otočil ses na místě a beze slova odešel."
|
||||
ok:
|
||||
description: "Přijmout omluvu"
|
||||
text: "&cJosef&r: Och, děkují, rozumný pane!"
|
||||
|
25
lib/ascii.py
25
lib/ascii.py
|
@ -1,6 +1,7 @@
|
|||
from tempfile import TemporaryDirectory
|
||||
from time import sleep
|
||||
from zipfile import ZipFile
|
||||
from os import listdir
|
||||
from os import listdir, system
|
||||
import yaml
|
||||
class AsciiAnimation:
|
||||
def __init__(self) -> None:
|
||||
|
@ -9,18 +10,26 @@ class AsciiAnimation:
|
|||
|
||||
def load_ascii(self,name:str):
|
||||
"""
|
||||
Returns ASCII by name
|
||||
Loads art from .asc file
|
||||
"""
|
||||
|
||||
with TemporaryDirectory() as tmpdir: # we enter a temporary directory
|
||||
with ZipFile(f"./assets/{name}.asc","r") as z: # extract the asc file
|
||||
with TemporaryDirectory() as tmpdir: # Vytvoříme dočasnou složku
|
||||
with ZipFile(f"./assets/{name}.asc","r") as z: # Extrahujeme asc soubor
|
||||
z.extractall(f"{tmpdir}/ascii/{name}")
|
||||
for f in listdir(f"{tmpdir}/ascii/{name}"): # read all the files
|
||||
for f in listdir(f"{tmpdir}/ascii/{name}"): # Přečte soubory
|
||||
if f == "config.yml":
|
||||
with open(f"{tmpdir}/ascii/{name}/{f}",encoding="utf-8") as c:
|
||||
data = yaml.load(c,Loader=yaml.SafeLoader)
|
||||
if(data["speed"] != None):
|
||||
self.speed = data["speed"]
|
||||
pass
|
||||
with open(f"{tmpdir}/ascii/{name}/{f}",encoding="utf-8") as f: # add all frames into list
|
||||
self.frames.append(f.read())
|
||||
with open(f"{tmpdir}/ascii/{name}/{f}",encoding="utf-8") as f: # Přidá všechny snímky do seznamu
|
||||
self.frames.append(f.read())
|
||||
|
||||
def play(self):
|
||||
"""
|
||||
Plays the animation frame by frame
|
||||
"""
|
||||
for frame in self.frames:
|
||||
system("cls||clear")
|
||||
print(frame)
|
||||
sleep(self.speed)
|
145
lib/fight.py
Normal file
145
lib/fight.py
Normal file
|
@ -0,0 +1,145 @@
|
|||
import math
|
||||
from lib.item import Item
|
||||
|
||||
from lib.menu import MenuManager
|
||||
|
||||
from .ascii import *
|
||||
from colorama import Fore
|
||||
import keyboard
|
||||
from random import randrange
|
||||
|
||||
class FightHandler:
|
||||
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.rebind()
|
||||
self.name = name
|
||||
self.max = hp # životy nepřítele
|
||||
self.hp = self.max # AKTUÁLNÍ životy nepřítele
|
||||
self.enemyDef = defense # Obrana nepřítele
|
||||
self.my = 30 # životy hráče TODO: maybe make this a variable
|
||||
self.attacks = attacks
|
||||
self.img = img
|
||||
self.lang = lang
|
||||
self.message = message
|
||||
self.equipped = eq
|
||||
self.inventory = inv
|
||||
self.show()
|
||||
|
||||
def up(self):
|
||||
if self.selected == 0:
|
||||
self.selected = 2
|
||||
else:
|
||||
self.selected -= 1
|
||||
system("cls||clear")
|
||||
self.show()
|
||||
|
||||
def down(self):
|
||||
if self.selected == 2:
|
||||
self.selected = 0
|
||||
else:
|
||||
self.selected += 1
|
||||
system("cls||clear")
|
||||
self.show()
|
||||
|
||||
def show(self):
|
||||
system("cls||clear")
|
||||
p = math.trunc(self.hp/self.max*10)
|
||||
h = f"{Fore.RED}■{Fore.RESET}"*p
|
||||
|
||||
j = math.trunc(self.my/30*10)
|
||||
a = f"{Fore.GREEN}■{Fore.RESET}"*j
|
||||
if str(p).endswith(".5"):
|
||||
h += "◾"
|
||||
if str(a).endswith(".5"):
|
||||
a += "◾"
|
||||
print(self.message)
|
||||
print(f"{self.lang['you']} {a} {self.my}/30")
|
||||
print(f"{self.name} {h} {self.hp}/{self.max}")
|
||||
if self.img != "":
|
||||
anim = AsciiAnimation()
|
||||
anim.load_ascii(self.img)
|
||||
anim.play()
|
||||
s = [self.lang["attack"],self.lang["defend"],self.lang["inventory"]]
|
||||
for selection in s:
|
||||
if(self.selected == s.index(selection)):
|
||||
print(f"{Fore.RED}⚔{Fore.RESET} {selection}")
|
||||
else:
|
||||
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): # Zobrazuje inventář TODO: Možná taky equipovat?
|
||||
system("cls||clear")
|
||||
if len(self.inventory) == 0:
|
||||
FightMenu([self.lang["return"]],f" {self.lang['inside_inv']} \n")
|
||||
else:
|
||||
op = []
|
||||
items = []
|
||||
s = ""
|
||||
for i,item in enumerate(self.inventory):
|
||||
if type(item) is Item: # Pokud je předmět třídy Item, zobrazit zda-li je vybaven nebo ne
|
||||
if self.equipped["weapon"] == item or self.equipped["armor"] == item:
|
||||
op.append(f"- {item.name} | {self.lang['equipped']}")
|
||||
else:
|
||||
op.append(f"- {item.name}")
|
||||
items.append(item)
|
||||
else:
|
||||
if(i == len(self.inventory)): # poslední, nepřidávat newline
|
||||
s += f"- {item}"
|
||||
else:
|
||||
s += f"- {item}\n"
|
||||
items.append(None)
|
||||
op.append(self.lang["return"])
|
||||
m = FightMenu(op,f" {self.lang['inside_inv']} \n{s}")
|
||||
if(m.selected != len(op)-1):
|
||||
# Vybavit
|
||||
i = items[m.selected]
|
||||
self.equipped[i.type] = i
|
||||
|
||||
def attack(self): # Provede útok vypočítáním ze statů útoku a obrany
|
||||
p = randrange(len(self.attacks))
|
||||
name = list(self.attacks[p].keys())[0]
|
||||
enemyAtk = self.attacks[p][name]["atk"]
|
||||
enemyDef = self.enemyDef
|
||||
playerAtk = 0
|
||||
playerDef = 0
|
||||
if self.equipped["weapon"] is not None:
|
||||
playerAtk = self.equipped["weapon"].attack
|
||||
if self.equipped["armor"] is not None:
|
||||
playerDef = self.equipped["armor"].defense
|
||||
|
||||
c = enemyAtk - playerDef
|
||||
e = playerAtk - enemyDef
|
||||
if c < 0:
|
||||
c = 0
|
||||
if e < 0:
|
||||
e = 0
|
||||
self.hp -= e # zásah nepříteli
|
||||
self.my -= c # zásah hráči
|
||||
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'])}" # Změnit zprávu
|
||||
|
||||
def defend(self):
|
||||
self.message = self.lang["defended"]
|
||||
|
||||
class FightMenu(MenuManager): # Upravené menu, které nemá input na konci, protože to jinak buguje
|
||||
def __init__(self,selections:list,additional:str):
|
||||
keyboard.remove_all_hotkeys()
|
||||
self.selected = 0
|
||||
self.selections = selections
|
||||
self.additional = additional
|
||||
keyboard.add_hotkey("up",self.up)
|
||||
keyboard.add_hotkey("down",self.down)
|
||||
keyboard.add_hotkey("enter",self.make_selection)
|
||||
self.show_menu()
|
300
lib/game.py
300
lib/game.py
|
@ -1,162 +1,226 @@
|
|||
import yaml
|
||||
from yaml.loader import SafeLoader
|
||||
from colorama import Fore, Back, Style
|
||||
from colorama import Fore, Back
|
||||
import re
|
||||
from lib.item import Item
|
||||
|
||||
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, path, mkdir
|
||||
from os import system
|
||||
|
||||
class Game: # the game class keeps information about the loaded game
|
||||
def __init__(self,data:dict):
|
||||
self.name = data["meta"]["name"]
|
||||
self.author = data["meta"]["creator"]
|
||||
self.current = "start"
|
||||
self.nodes = {}
|
||||
self.inventory = []
|
||||
self.save = SaveManager()
|
||||
self.id = data["meta"]["id"]
|
||||
for k in data["game"]:
|
||||
class Game: # Hlavní třída, uchovává údaje o hře
|
||||
def __init__(self,data:dict,lang):
|
||||
self.name = data["meta"]["name"] # Název hry
|
||||
self.author = data["meta"]["creator"] # Název tvůrce
|
||||
self.current = "start" # Aktuální node
|
||||
self.nodes = {} # Seznam všech
|
||||
self.inventory = [] # Hráčův inventář
|
||||
self.id = data["meta"]["id"] # "Unikátní" ID hry
|
||||
self.lang = lang # Řetězce pro vybraný jazyk
|
||||
self.save = SaveManager(self.id,self.lang) # Systém ukládání
|
||||
self.equipped = {"weapon":None,"armor":None} # Předměty vybavené hráčem
|
||||
self.enemies = {} # Seznam všech nepřátel
|
||||
if "equippable" in data["meta"].keys():
|
||||
self.equippable = [] # Předměty, které si hráč může vybavit
|
||||
for item in data["meta"]["equippable"]:
|
||||
name = list(item.keys())[0]
|
||||
if "def" in item[name].keys() and "atk" in item[name].keys():
|
||||
self.equippable.append(Item(item[name]["name"],item[name]["atk"],item[name]["def"]))
|
||||
elif "def" in item[name].keys():
|
||||
self.equippable.append(Item(name=item[name]["name"],defense=item[name]["def"]))
|
||||
elif "atk" in item[name].keys():
|
||||
self.equippable.append(Item(item[name]["name"],item[name]["atk"]))
|
||||
if("starter" in item[name].keys()): # Pokud je starter, přidáme hráčí na začátku do inventáře
|
||||
if item[name]["starter"]:
|
||||
i = next((x for x in self.equippable if x.name == item[name]["name"])) # V případě, že nenalezne předmět, vrací None
|
||||
self.inventory.append(i)
|
||||
self.equipped[i.type] = i
|
||||
self.save.equipped[i.type]
|
||||
if "enemies" in data["meta"].keys():
|
||||
# Načte nepřátele
|
||||
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"]: # načte všechny nody
|
||||
self.nodes.update({k:data["game"][k]})
|
||||
|
||||
def main_menu(self): # displays the main menu
|
||||
def main_menu(self): # Zobrazí hlavní menu
|
||||
l = self.save.load()
|
||||
if not l:
|
||||
# New game
|
||||
print(self.name)
|
||||
print(f"A game by {self.author}")
|
||||
print("")
|
||||
print("1 - Start")
|
||||
print("2 - Options")
|
||||
print("0 - Quit")
|
||||
selection = self.make_selection(3)
|
||||
# V případě nové hry
|
||||
m = MenuManager([self.lang['start'],self.lang['options'],self.lang['quit']],f"{self.name}\n{self.lang['game_by'].replace('$author',self.author)}")
|
||||
selection = m.selected
|
||||
system("cls||clear")
|
||||
if(selection == 1): # start new game
|
||||
if(selection == 0): # Začít
|
||||
self.print_text()
|
||||
elif(selection == 2):
|
||||
elif(selection == 1): # Nastavení
|
||||
self.settings_menu()
|
||||
elif(selection == 0):
|
||||
print("Quitting")
|
||||
elif(selection == 2): # Vypnout
|
||||
print(self.lang['quitting'])
|
||||
exit()
|
||||
else: # Display continue
|
||||
print(self.name)
|
||||
print(f"A game by {self.author}")
|
||||
print("")
|
||||
print("1 - Continue")
|
||||
print("2 - New game")
|
||||
print("3 - Options")
|
||||
print("0 - Quit")
|
||||
selection = self.make_selection(3)
|
||||
else: # V případě uložené hry zobrazí "Pokračovat"
|
||||
m = MenuManager([self.lang['continue'],self.lang['new_game'],self.lang['options'],self.lang['quit']],f"{self.name}\n{self.lang['game_by'].replace('$author',self.author)}")
|
||||
selection = m.selected
|
||||
system("cls||clear")
|
||||
if(selection == 1):
|
||||
if(selection == 0):
|
||||
self.current = self.save.currentPrompt
|
||||
self.inventory = self.save.inventory
|
||||
self.equipped = self.save.equipped
|
||||
self.print_text()
|
||||
elif(selection == 1):
|
||||
self.print_text()
|
||||
elif(selection == 2):
|
||||
self.print_text()
|
||||
elif(selection == 3):
|
||||
self.settings_menu()
|
||||
elif(selection == 0):
|
||||
print("Quitting")
|
||||
elif(selection == 3):
|
||||
print(self.lang['quitting'])
|
||||
exit()
|
||||
|
||||
def settings_menu(self): # displays the settings menu
|
||||
print("Options")
|
||||
print("")
|
||||
print("1 - Language")
|
||||
print("0 - Back")
|
||||
selection = self.make_selection(1)
|
||||
if(selection == 1):
|
||||
print("Language")
|
||||
print("")
|
||||
print("1 - English")
|
||||
print("2 - Czech")
|
||||
print("0 - Back")
|
||||
selection = self.make_selection(2)
|
||||
def settings_menu(self): # Zobrazí nastavení
|
||||
m = MenuManager([self.lang['lang'],self.lang['back']],self.lang['options'])
|
||||
selection = m.selected
|
||||
if(selection == 0):
|
||||
m = MenuManager(["English","Česky",self.lang['back']],self.lang['lang'])
|
||||
selection = m.selected
|
||||
system("cls||clear")
|
||||
if(selection == 1):
|
||||
if(selection == 0):
|
||||
with open("./saves/lang","w") as f:
|
||||
f.write("en")
|
||||
elif(selection == 2):
|
||||
elif(selection == 1):
|
||||
with open("./saves/lang","w") as f:
|
||||
f.write("cz")
|
||||
self.settings_menu()
|
||||
else:
|
||||
self.main_menu()
|
||||
|
||||
def make_selection(self, length=0) -> int: # this method makes sure a valid selection is made and returns the selection as a number
|
||||
# TODO: replace with selection by keyboard(?)
|
||||
l = length # sets the length
|
||||
if(l == 0): # if no length was set, we get it from nodes
|
||||
l = len(self.nodes[self.current]["actions"])-1
|
||||
y = False
|
||||
selection = 0
|
||||
# TODO: Check for "has_item"
|
||||
while y == False: # while the selection is not correct
|
||||
try:
|
||||
selection = int(input("Make a selection (number): ")) # ask for selection
|
||||
except ValueError: # handle wrong input type
|
||||
print("Not a number selection")
|
||||
if(selection > l or selection < 0): # if the number is bigger than the length or smaller than 0, print error
|
||||
print("Invalid selection")
|
||||
else:
|
||||
y = True # else return the selection
|
||||
return selection
|
||||
|
||||
def print_text(self): # Prints out the current prompt
|
||||
def print_text(self): # Zobrazí hráči aktuální node
|
||||
system("cls||clear")
|
||||
animated = re.search(r"(?!{).+(?=})",self.nodes[self.current]["text"]) # find the animated text
|
||||
if "add_item" in self.nodes[self.current].keys(): # V případě, že máme přidat hráči věc do inventáře
|
||||
item = self.nodes[self.current]['add_item']
|
||||
for i in self.equippable:
|
||||
if i.name == item: # Pokud lze vybavit, změnit na instanci třídy Item
|
||||
item = i
|
||||
if item not in self.inventory:
|
||||
self.inventory.append(item)
|
||||
print(self.inventory)
|
||||
system("clear||cls")
|
||||
print(f"{self.lang['acquire'].replace('$item',f'{Fore.CYAN}{item}{Fore.RESET}')}")
|
||||
sleep(3)
|
||||
system("clear||cls")
|
||||
animated = re.search(r"(?!{).+(?=})",self.nodes[self.current]["text"]) # Hledá kód pro vložení animovaného textu
|
||||
if(animated != None):
|
||||
self.print_animated(animated.group(0))
|
||||
self.nodes[self.current]["text"] = self.nodes[self.current]["text"].replace("{"+animated.group(0)+"}","") # remove the animated text from the text prompt
|
||||
print(self.parse_colors(self.nodes[self.current]["text"]))
|
||||
print("")
|
||||
ostring = ""
|
||||
self.nodes[self.current]["text"] = self.nodes[self.current]["text"].replace("{"+animated.group(0)+"}","") # Odstraní kód z textu
|
||||
if("actions" in self.nodes[self.current].keys()):
|
||||
for i,option in enumerate(self.nodes[self.current]["actions"]):
|
||||
ostring+=f"{i} - {self.nodes[option]['description']}\n"
|
||||
print(ostring)
|
||||
sel = self.make_selection()
|
||||
if "add_item" in self.nodes[self.current]: # if there is an add_inventory key in the node,
|
||||
# add item to inventory
|
||||
self.inventory.append(self.nodes[self.current]["add_inventory"])
|
||||
self.current = self.nodes[self.current]["actions"][sel]
|
||||
self.save.currentPrompt = self.current # save the current prompt
|
||||
self.print_text()
|
||||
actions_desc = [] # uchovává text nodu, abychom jej nemuseli hledat v MenuManager
|
||||
need_item = [] # pomáhá implementovat kontrolu potřebného předmětu
|
||||
for option in self.nodes[self.current]["actions"]:
|
||||
try:
|
||||
actions_desc.append(self.nodes[option]["description"])
|
||||
if "has_item" in self.nodes[option].keys():
|
||||
need_item.append(self.nodes[option]["has_item"])
|
||||
else:
|
||||
need_item.append(None)
|
||||
except Exception:
|
||||
print(f"{Back.RED}{Fore.WHITE}{self.lang['no_action'].replace('$action',option)}{Fore.RESET}")
|
||||
exit(1)
|
||||
m = ""
|
||||
actions_desc.extend([self.lang['inventory'],self.lang['quit']])
|
||||
if(all(element == None for element in need_item) is False): # Pokud platí, musíme zkontrolovat, jestli hráč má předmět
|
||||
need_item.extend([None, None])
|
||||
m = HasItemDialogue(actions_desc,self.parse_colors(self.nodes[self.current]["text"]),self.inventory,need_item)
|
||||
while need_item[m.selected] != None and all(element not in self.inventory for element in need_item[m.selected]): # Opakovat, dokud uživatel nevybere platný výběr
|
||||
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():
|
||||
# Spustí boj
|
||||
enemy = self.enemies[self.nodes[self.current]["fight"]] # Získá info o nepříteli
|
||||
m = FightHandler(self.nodes[self.current]["text"],enemy["name"],enemy["hp"],enemy["def"],enemy["attacks"],self.lang,self.equipped,self.inventory)
|
||||
input()
|
||||
while m.hp > 0 and m.my > 0:
|
||||
m.show()
|
||||
m.rebind() # Znovu nastavuje klávesy, kvůli MenuManageru uvnitř show_inventory, který je maže
|
||||
input()
|
||||
system("cls||clear")
|
||||
keyboard.remove_all_hotkeys()
|
||||
self.equipped = m.equipped
|
||||
self.save.equipped = m.equipped
|
||||
if m.hp < 1:
|
||||
# Nepřítel byl poražen
|
||||
print(self.lang["defeated"].replace("$enemy",enemy["name"]))
|
||||
sleep(3)
|
||||
self.current = self.nodes[self.current]["actions"][0] # Přesune na první akci
|
||||
self.print_text()
|
||||
else:
|
||||
# Hráč byl poražen
|
||||
print(self.lang["defeat"].replace("$enemy",enemy["name"]))
|
||||
sleep(3)
|
||||
self.print_text()
|
||||
return
|
||||
else:
|
||||
m = MenuManager(actions_desc,self.parse_colors(self.nodes[self.current]["text"]))
|
||||
sel = m.selected
|
||||
if(sel == len(actions_desc)-2): # Zobrazit inventář
|
||||
self.show_inventory()
|
||||
elif (sel == len(actions_desc)-1): # Uložit a ukončit
|
||||
self.save.currentPrompt = self.current
|
||||
self.save.inventory = self.inventory
|
||||
self.save.equipped = self.equipped
|
||||
self.save.save()
|
||||
exit(0)
|
||||
else:
|
||||
self.current = self.nodes[self.current]["actions"][sel]
|
||||
self.print_text()
|
||||
else:
|
||||
print(self.parse_colors(self.nodes[self.current]["text"]))
|
||||
print("")
|
||||
|
||||
def print_animated(self,animid): # prinst the first found occurence of an ascii animation
|
||||
def show_inventory(self): # Zobrazí hráčův inventář
|
||||
if len(self.inventory) == 0:
|
||||
MenuManager([self.lang["return"]],f" {self.lang['inside_inv']} \n")
|
||||
else:
|
||||
s = ""
|
||||
op = []
|
||||
items = []
|
||||
for i,item in enumerate(self.inventory):
|
||||
if type(item) is Item: # Pokud je předmět třídy Item, zobrazit zda-li je vybaven nebo ne
|
||||
if self.equipped["weapon"] == item or self.equipped["armor"] == item:
|
||||
op.append(f"- {item.name} | {self.lang['equipped']}")
|
||||
else:
|
||||
op.append(f"- {item.name}")
|
||||
items.append(item)
|
||||
else:
|
||||
if(i == len(self.inventory)): # poslední, nepřidávat newline
|
||||
s += f"- {item}"
|
||||
else:
|
||||
s += f"- {item}\n"
|
||||
items.append(None)
|
||||
op.append(self.lang["return"])
|
||||
m = MenuManager(op,f" {self.lang['inside_inv']} \n{s}")
|
||||
if(m.selected != len(op)-1):
|
||||
# Vybavit
|
||||
i = items[m.selected]
|
||||
self.equipped[i.type] = i
|
||||
self.save.equipped[i.type] = i
|
||||
self.print_text()
|
||||
|
||||
def print_animated(self,animid): # Zobrazí animaci
|
||||
animation = AsciiAnimation()
|
||||
animation.load_ascii(animid)
|
||||
for frame in animation.frames:
|
||||
system("cls||clear")
|
||||
print(frame)
|
||||
sleep(animation.speed)
|
||||
animation.play()
|
||||
print()
|
||||
|
||||
def parse_colors(self,text:str) -> str: # Converts color codes into terminal colors
|
||||
def parse_colors(self,text:str) -> str: # Převádí kód na barvy v terminálu
|
||||
newText = text.replace("&b",Fore.CYAN).replace("&c",Fore.RED).replace("&e", Fore.YELLOW).replace("&a",Fore.GREEN).replace("&9",Fore.BLUE).replace("&r",Fore.RESET).replace("&f",Fore.WHITE).replace("&5",Fore.MAGENTA).replace("\n",Fore.RESET + "\n") # replace color codes and newlines with colorama
|
||||
newText += Fore.RESET # reset color at the end of the text
|
||||
newText += Fore.RESET # resetovat na konci
|
||||
return newText
|
||||
|
||||
|
||||
def load(file_path): # starts to load the game from YAML
|
||||
lang = "en"
|
||||
if not (path.exists("./saves/lang")):
|
||||
mkdir("./saves")
|
||||
with open("./saves/lang","w") as f:
|
||||
f.write("en")
|
||||
else:
|
||||
with open("./saves/lang","r") as f:
|
||||
lang = f.read()
|
||||
if lang == "cz":
|
||||
lang = "cz"
|
||||
try:
|
||||
with open(file_path) as f:
|
||||
data = yaml.load(f,Loader=SafeLoader)
|
||||
g = Game(data)
|
||||
g.lang = lang
|
||||
return g
|
||||
except Exception as e:
|
||||
print(f"{Back.RED}{Fore.WHITE}An exception has occured while loading the game from the YAML file:{Fore.RESET}{Back.RESET}")
|
||||
print(e)
|
||||
return None
|
||||
def load(file_path,lang): # Načte hru z YAML souboru
|
||||
with open(file_path, encoding="utf-8") as f:
|
||||
data = yaml.load(f,Loader=SafeLoader)
|
||||
g = Game(data,lang)
|
||||
return g
|
9
lib/item.py
Normal file
9
lib/item.py
Normal file
|
@ -0,0 +1,9 @@
|
|||
class Item: # Reprezentuje vybavitelný předmět
|
||||
def __init__(self,name:str,attack:int = 0,defense:int = 0) -> None:
|
||||
self.name = name # Název, jak je zobrazován hráči
|
||||
if attack == 0 and defense > 0: # Nastaví typ předmětu
|
||||
self.type = "armor"
|
||||
else:
|
||||
self.type = "weapon"
|
||||
self.attack = attack # Stat útoku
|
||||
self.defense = defense # Stat obrany
|
|
@ -1,3 +1,7 @@
|
|||
available: 'Dostupné hry:'
|
||||
no_games: 'Žádné hry nenalezeny'
|
||||
enter: 'Stiskněte Enter pro pokračování'
|
||||
|
||||
yaml_unspecified: 'Musíte specifikovat YAML soubor'
|
||||
game_by: 'Vytvořil $author'
|
||||
start: 'Start'
|
||||
|
@ -6,6 +10,12 @@ quit: 'Vypnout'
|
|||
quitting: 'Vypínám'
|
||||
continue: 'Pokračovat'
|
||||
new_game: 'Nová hra'
|
||||
inventory: 'Zobrazit inventář'
|
||||
acquire: 'Získal jsi $item'
|
||||
|
||||
inside_inv: "VÁŠ INVENTÁŘ"
|
||||
return: "Vrátit se"
|
||||
equipped: "VYBAVENO"
|
||||
|
||||
lang: 'Jazyk'
|
||||
back: 'Zpět'
|
||||
|
@ -16,4 +26,15 @@ selection: 'Vyberte zadáním čísla:'
|
|||
not_number: 'Nezadali jste číslo'
|
||||
invalid: 'Neplatný výběr'
|
||||
|
||||
error_loading: 'Při načítání YAML souboru nastala chyba:'
|
||||
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."
|
||||
defeated: "Porazil jsi $enemy."
|
||||
defeat: "$enemy tě zabil. Budeš to muset zkusit znovu."
|
||||
you: "Ty"
|
||||
|
||||
error_loading: 'Při načítání YAML souboru nastala chyba:'
|
||||
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í!"
|
|
@ -1,3 +1,7 @@
|
|||
available: 'Available games:'
|
||||
no_games: 'No games found'
|
||||
enter: 'Press Enter to continue'
|
||||
|
||||
yaml_unspecified: 'You need to specify a path to a YAML file'
|
||||
game_by: 'A game by $author'
|
||||
start: 'Start'
|
||||
|
@ -6,6 +10,12 @@ quit: 'Quit'
|
|||
quitting: 'Quitting'
|
||||
continue: 'Continue'
|
||||
new_game: 'New game'
|
||||
inventory: 'Show inventory'
|
||||
acquire: 'You acquired $item'
|
||||
|
||||
inside_inv: "YOUR INVENTORY"
|
||||
return: "Return"
|
||||
equipped: "EQUIPPED"
|
||||
|
||||
lang: 'Language'
|
||||
back: 'Back'
|
||||
|
@ -16,4 +26,15 @@ selection: 'Make a selection (number):'
|
|||
not_number: 'Not a number selection'
|
||||
invalid: 'Invalid selection'
|
||||
|
||||
error_loading: 'An exception has occured while loading the game from the YAML file:'
|
||||
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."
|
||||
defeated: "You have defeated $enemy."
|
||||
defeat: "$enemy has slain you. You'll have to try again."
|
||||
you: "You"
|
||||
|
||||
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_comp: "WARNING: This save is for an older version of the engine and may not be compatible!"
|
80
lib/menu.py
Normal file
80
lib/menu.py
Normal file
|
@ -0,0 +1,80 @@
|
|||
from os import system
|
||||
import keyboard
|
||||
from colorama import Fore
|
||||
class MenuManager:
|
||||
'''
|
||||
Vytváří navigovatelná textová menu
|
||||
'''
|
||||
def __init__(self,selections:list,additional:str):
|
||||
self.selected = 0 # aktuální výběr
|
||||
self.selections = selections # Dostupné možnosti
|
||||
self.additional = additional # Text, který se zobrazí nad menu
|
||||
keyboard.add_hotkey("up",self.up)
|
||||
keyboard.add_hotkey("down",self.down)
|
||||
keyboard.add_hotkey("enter",self.make_selection)
|
||||
self.show_menu()
|
||||
input()
|
||||
|
||||
def make_selection(self) -> None:
|
||||
keyboard.remove_all_hotkeys()
|
||||
|
||||
def up(self):
|
||||
if self.selected == 0:
|
||||
self.selected = len(self.selections)-1
|
||||
else:
|
||||
self.selected -= 1
|
||||
system("cls||clear")
|
||||
self.show_menu()
|
||||
|
||||
def down(self):
|
||||
if self.selected == len(self.selections)-1:
|
||||
self.selected = 0
|
||||
else:
|
||||
self.selected += 1
|
||||
system("cls||clear")
|
||||
self.show_menu()
|
||||
|
||||
def show_menu(self):
|
||||
system("cls||clear")
|
||||
print(self.additional)
|
||||
for selection in self.selections:
|
||||
if(self.selected == self.selections.index(selection)):
|
||||
print(f"{Fore.RED}->{Fore.RESET} {selection}")
|
||||
else:
|
||||
print(f" {selection}")
|
||||
|
||||
class HasItemDialogue(MenuManager):
|
||||
'''
|
||||
Odvozená třída pro kontrolu, zda-li má hráč předmět
|
||||
'''
|
||||
def __init__(self, selections: list, additional: str,inv:list,need_item:list):
|
||||
system("cls||clear")
|
||||
self.inventory = inv
|
||||
self.need_items = need_item
|
||||
super().__init__(selections, additional)
|
||||
|
||||
def show_menu(self):
|
||||
print(self.additional)
|
||||
|
||||
for i,selection in enumerate(self.selections):
|
||||
if(self.need_items[i] != None and all(element not in self.inventory for element in self.need_items[i])):
|
||||
c = ""
|
||||
for i,item in enumerate(self.need_items[i]):
|
||||
if item not in self.inventory:
|
||||
if i == len(self.need_items)-self.need_items.count(None)-1: # last item, don't add a comma
|
||||
c+=f"{item} "
|
||||
else:
|
||||
c+=f"{item}, "
|
||||
# user does not have the needed item
|
||||
if(self.selected == i):
|
||||
print(f"{Fore.RED}-> {Fore.CYAN}{selection}{Fore.RESET} (Need {c})")
|
||||
else:
|
||||
print(f" {Fore.CYAN}{selection}{Fore.RESET}")
|
||||
else:
|
||||
# we don't need to change color for an item user doesn't have
|
||||
if(self.selected == i):
|
||||
print(f"{Fore.RED}->{Fore.RESET} {selection}")
|
||||
else:
|
||||
print(f" {selection}")
|
||||
def make_selection(self) -> int:
|
||||
keyboard.remove_all_hotkeys()
|
57
lib/save.py
57
lib/save.py
|
@ -1,23 +1,58 @@
|
|||
from os import path
|
||||
from time import sleep
|
||||
from os import path, system
|
||||
import yaml
|
||||
|
||||
class SaveManager: # manages save and configuration files
|
||||
def __init__(self):
|
||||
self.id = "" # game ID
|
||||
self.currentPrompt = "" # Current prompt
|
||||
self.lang = "" # Selected language
|
||||
self.inventory = [] # Items in inventory
|
||||
from lib.game import Item
|
||||
|
||||
class SaveManager: # Spravuje ukládání
|
||||
def __init__(self,gid:str,lang):
|
||||
self.id = gid # ID hry
|
||||
self.currentPrompt = "" # Aktuální node
|
||||
self.inventory = [] # Předměty v inventáři
|
||||
self.equipped = {"weapon":None,"armor":None} # Výbava
|
||||
self.version = 2
|
||||
self.lang = lang
|
||||
|
||||
def load(self):
|
||||
if(path.exists(f"./saves/{self.id}.yml")):
|
||||
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) # Načteme z YAMLu
|
||||
self.currentPrompt = data["currentPrompt"]
|
||||
self.inventory = data["inventory"]
|
||||
if(data["version"] < self.version): # V případě nekompatibility zobrazit varování
|
||||
system("cls||clear")
|
||||
print(self.lang["no_comp"])
|
||||
sleep(5)
|
||||
self.inventory = []
|
||||
for item in data["inventory"]: # Zpracovat inventář (zvlášť pouze text a zvlášť vybavitelné)
|
||||
if type(item) is str:
|
||||
self.inventory.append(item)
|
||||
else:
|
||||
i = Item(item["name"],item["atk"],item["def"])
|
||||
self.inventory.append(i)
|
||||
# Přidat stejnou kopii jako vybavenou pokud je vybavena
|
||||
if(data["equipped"]["weapon"] is not None):
|
||||
if(data["equipped"]["weapon"]["name"] == i.name):
|
||||
self.equipped["weapon"] = i
|
||||
if(data["equipped"]["armor"] is not None):
|
||||
if(data["equipped"]["armor"]["name"] == i.name):
|
||||
self.equipped["armor"] = i
|
||||
return True
|
||||
return False
|
||||
|
||||
def save(self):
|
||||
data = {"id":self.id,"currentPrompt":self.currentPrompt,"inventory":self.inventory,"lang":self.lang}
|
||||
inv = []
|
||||
for item in self.inventory:
|
||||
if type(item) is str:
|
||||
inv.append(item)
|
||||
else:
|
||||
# Pro vybavitelné předměty
|
||||
inv.append({"name":item.name,"atk":item.attack,"def":item.defense})
|
||||
|
||||
# Zpracovat vybavené předměty
|
||||
if(self.equipped["weapon"] is not None):
|
||||
self.equipped["weapon"] = {"name":self.equipped["weapon"].name,"atk":self.equipped["weapon"].attack}
|
||||
if(self.equipped["armor"] is not None):
|
||||
self.equipped["armor"] = {"name":self.equipped["armor"].name,"def":self.equipped["armor"].defense}
|
||||
data = {"id":self.id,"currentPrompt":self.currentPrompt,"inventory":inv,"version":self.version,"equipped":self.equipped}
|
||||
with open(f"./saves/{self.id}.yml",mode="w",encoding="utf-8") as f:
|
||||
yaml.dump(data,f)
|
||||
yaml.dump(data,f)
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
pyyaml==6.0
|
||||
colorama==0.4.4
|
||||
colorama==0.4.4
|
||||
keyboard==0.13.5
|
Reference in a new issue