Compare commits
8 commits
Author | SHA1 | Date | |
---|---|---|---|
6e55242fb5 | |||
b8ffa7871d | |||
dce622c7b3 | |||
761a23da8a | |||
a98cc869dd | |||
17a444d0b5 | |||
d39971b852 | |||
01077b14bb |
|
@ -7,10 +7,6 @@ meta: # make sure every key is in lowercase
|
|||
atk: 3
|
||||
starter: true
|
||||
name: "Iron Sword"
|
||||
- wood_sword:
|
||||
atk: 1
|
||||
starter: true
|
||||
name: "Wooden Sword"
|
||||
- chainmail:
|
||||
def: 2
|
||||
name: "Chainmail Armor"
|
||||
|
|
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!"
|
||||
|
52
lib/fight.py
52
lib/fight.py
|
@ -1,4 +1,5 @@
|
|||
import math
|
||||
from lib.item import Item
|
||||
|
||||
from lib.menu import MenuManager
|
||||
|
||||
|
@ -43,10 +44,16 @@ class FightHandler:
|
|||
def show(self):
|
||||
system("cls||clear")
|
||||
p = math.trunc(self.hp/self.max*10)
|
||||
h = "🟥"*p
|
||||
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()
|
||||
|
@ -78,29 +85,49 @@ class FightHandler:
|
|||
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 not str:
|
||||
if(i == len(self.inventory)):
|
||||
s += f"- {item.name}"
|
||||
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:
|
||||
s += f"- {item.name}\n"
|
||||
op.append(f"- {item.name}")
|
||||
items.append(item)
|
||||
else:
|
||||
if(i == len(self.inventory)):
|
||||
if(i == len(self.inventory)): # poslední, nepřidávat newline
|
||||
s += f"- {item}"
|
||||
else:
|
||||
s += f"- {item}\n"
|
||||
FightMenu([self.lang["return"]],f" {self.lang['inside_inv']} \n{s}")
|
||||
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 = self.equipped["weapon"].attack
|
||||
playerDef = self.equipped["armor"].defense
|
||||
self.hp -= playerAtk - enemyDef # zásah nepříteli
|
||||
self.my -= enemyAtk - playerDef # zásah hráči
|
||||
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):
|
||||
|
@ -108,10 +135,11 @@ class FightHandler:
|
|||
|
||||
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()
|
||||
self.show_menu()
|
||||
|
|
10
lib/game.py
10
lib/game.py
|
@ -38,6 +38,7 @@ class Game: # Hlavní třída, uchovává údaje o hře
|
|||
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"]:
|
||||
|
@ -67,6 +68,7 @@ class Game: # Hlavní třída, uchovává údaje o hře
|
|||
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()
|
||||
|
@ -145,6 +147,8 @@ class Game: # Hlavní třída, uchovává údaje o hř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"]))
|
||||
|
@ -152,7 +156,7 @@ class Game: # Hlavní třída, uchovává údaje o hře
|
|||
self.current = self.nodes[self.current]["actions"][0] # Přesune na první akci
|
||||
self.print_text()
|
||||
else:
|
||||
# Hráč byl poražen TODO: Otestovat
|
||||
# Hráč byl poražen
|
||||
print(self.lang["defeat"].replace("$enemy",enemy["name"]))
|
||||
sleep(3)
|
||||
self.print_text()
|
||||
|
@ -165,6 +169,7 @@ class Game: # Hlavní třída, uchovává údaje o hře
|
|||
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:
|
||||
|
@ -200,6 +205,7 @@ class Game: # Hlavní třída, uchovává údaje o hře
|
|||
# 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
|
||||
|
@ -214,7 +220,7 @@ class Game: # Hlavní třída, uchovává údaje o hře
|
|||
return newText
|
||||
|
||||
def load(file_path,lang): # Načte hru z YAML souboru
|
||||
with open(file_path) as f:
|
||||
with open(file_path, encoding="utf-8") as f:
|
||||
data = yaml.load(f,Loader=SafeLoader)
|
||||
g = Game(data,lang)
|
||||
return g
|
|
@ -33,6 +33,7 @@ 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'
|
||||
|
|
|
@ -33,6 +33,7 @@ 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.'
|
||||
|
|
25
lib/save.py
25
lib/save.py
|
@ -9,7 +9,8 @@ class SaveManager: # Spravuje ukládání
|
|||
self.id = gid # ID hry
|
||||
self.currentPrompt = "" # Aktuální node
|
||||
self.inventory = [] # Předměty v inventáři
|
||||
self.version = 1
|
||||
self.equipped = {"weapon":None,"armor":None} # Výbava
|
||||
self.version = 2
|
||||
self.lang = lang
|
||||
|
||||
def load(self):
|
||||
|
@ -21,12 +22,20 @@ class SaveManager: # Spravuje ukládání
|
|||
system("cls||clear")
|
||||
print(self.lang["no_comp"])
|
||||
sleep(5)
|
||||
inv = []
|
||||
self.inventory = []
|
||||
for item in data["inventory"]: # Zpracovat inventář (zvlášť pouze text a zvlášť vybavitelné)
|
||||
if type(item) is str:
|
||||
inv.append(item)
|
||||
self.inventory.append(item)
|
||||
else:
|
||||
inv.append(Item(item["name"],item["atk"],item["def"]))
|
||||
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
|
||||
|
||||
|
@ -38,6 +47,12 @@ class SaveManager: # Spravuje ukládání
|
|||
else:
|
||||
# Pro vybavitelné předměty
|
||||
inv.append({"name":item.name,"atk":item.attack,"def":item.defense})
|
||||
data = {"id":self.id,"currentPrompt":self.currentPrompt,"inventory":self.inventory,"version":1}
|
||||
|
||||
# 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)
|
||||
|
|
Reference in a new issue