Compare commits

...

8 commits
1.0.0 ... main

Author SHA1 Message Date
Matyáš Caras 6e55242fb5
fix: saving equipped items 2022-05-24 09:40:21 +02:00
Matyáš Caras b8ffa7871d Merge branch 'main' of https://github.com/hernikplays/texty 2022-05-17 17:03:28 +02:00
Matyáš Caras dce622c7b3 Fix saves and equipping inside fight (Closes #2) 2022-05-17 17:03:25 +02:00
Matyáš Caras 761a23da8a
Update example.yml 2022-05-16 19:05:26 +00:00
Matyáš Caras a98cc869dd Fix health 2022-05-16 21:00:45 +02:00
Matyáš Caras 17a444d0b5 Trailing spaces 2022-05-16 17:52:20 +02:00
Matyáš Caras d39971b852 Add player health 2022-05-16 17:51:17 +02:00
Matyáš Caras 01077b14bb Czech example 2022-05-16 16:14:21 +02:00
7 changed files with 158 additions and 23 deletions

View file

@ -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
View 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!"

View file

@ -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()

View file

@ -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

View file

@ -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'

View file

@ -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.'

View file

@ -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)