diff --git a/copyright b/copyright index 41a1306..7259680 100644 --- a/copyright +++ b/copyright @@ -7,6 +7,7 @@ Comment: N.M.I. == No More Information (about) Files: * Copyright: Cromha bane-of-wargs contributors (see credits.txt) + R.I.P. ASCII art of mount death was made by mfj. License: GPL-3+ Files: data/* diff --git a/credits.txt b/credits.txt index 1eb4e02..af0c60f 100644 --- a/credits.txt +++ b/credits.txt @@ -53,6 +53,7 @@ Artwork jah (GPL-3+) jrei (GPL-3+) mga (GPL-3+) + mfj (GPL-3+) nic (GPL-3+) sk (GPL-3+) valkyrie (GPL-3+) diff --git a/data/mounts.yaml b/data/mounts.yaml index c87b758..b7c0526 100644 --- a/data/mounts.yaml +++ b/data/mounts.yaml @@ -28,12 +28,14 @@ Warg: stats: agility addition: .35 resistance addition: .15 + health: 200 levels: max level: 25 level stat additions: agility addition: .025 resistance addition: .015 mph addition: .25 + health addition: 12 description: "Wargs are at first Orks mounts but they can be tamed and then used to fight against Orks. Wargs are fast and agile mounts." White Warg: name: White Warg @@ -52,12 +54,14 @@ White Warg: stats: agility addition: .27 resistance addition: .24 + health: 250 levels: max level: 55 level stat additions: agility addition: .015 resistance addition: .01 mph addition: .2 + health addition: 6 description: "Wargs are at first Orks mounts but they can be tamed and then used to fight against Ork. Wargs are fast and agile mounts." Bear: name: Bear @@ -75,12 +79,14 @@ Bear: stats: agility addition: -0.15 resistance addition: .25 + health: 300 levels: max level: 8 level stat additions: agility addition: .015 resistance addition: .15 mph addition: .2 + health addition: 25 description: "Bears are very big and powerful animals that are very hard to train; they required lot of work." Goat Steed: name: Goat Steed @@ -100,12 +106,14 @@ Goat Steed: stats: agility addition: .15 resistance addition: .15 + health: 150 levels: max level: 17 level stat additions: agility addition: .015 resistance addition: .015 mph addition: .25 + health addition: 8 description: > For a long time, dwarfs have been training and breeding goats, in order to make them a cavalry mount. These goats are a unique breed between goats and wild boars. @@ -127,12 +135,14 @@ Dwarf Boar: stats: agility addition: .1 resistance addition: .2 + health: 300 levels: max level: 15 level stat additions: agility addition: .01 resistance addition: .02 mph addition: .1 + health addition: 15 description: > Wild boars have been since a long time ago, been trained and bred by dwarfs, making them one of their favorite cavalry mount. They often use boars for long travels in mountains. @@ -153,12 +163,14 @@ Horse: stats: agility addition: .1 resistance addition: .23 + health: 170 levels: max level: 13 level stat additions: agility addition: .015 resistance addition: .005 mph addition: .25 + health addition: 10 description: "There are many different species of horses that you can find in the Kathallion Plains. This is a generic horse that you can find almost anywhere in the Kathallion Plains." Friesian Horse: name: Friesian Horse @@ -176,12 +188,14 @@ Friesian Horse: stats: agility addition: .14 resistance addition: .31 + health: 200 levels: max level: 18 level stat additions: agility addition: .016 resistance addition: .007 mph addition: .26 + health addition: 13 description: "Friesian Horses are breeds who are known for their docile ,energetic and swift high-stepping trot. They are often used by knights." Shire Horse: name: Shire Horse @@ -199,12 +213,14 @@ Shire Horse: stats: agility addition: .14 resistance addition: .31 + health: 200 levels: max level: 17 level stat additions: agility addition: .015 resistance addition: .02 mph addition: .15 + health addition: 13 description: "Shire Horses are tall horses that are often used by farmers to labor their lands. Despite that, they are also great horses for knights. " Camel: name: Camel @@ -224,12 +240,14 @@ Camel: stats: agility addition: .07 resistance addition: .38 + health: 200 levels: max level: 10 level stat additions: agility addition: .011 resistance addition: .023 mph addition: .1 + health addition: 20 description: > Camels are mounts used by the merchants of the Gerud Valleys, who often need to cross the whole Gerud Desert and sometimes the Badlands to get to their destination. @@ -249,12 +267,14 @@ Donkey: stats: agility addition: .09 resistance addition: .35 + health: 100 levels: max level: 15 level stat additions: agility addition: .01 resistance addition: .021 mph addition: .13 + health addition: 8 description: > Donkeys are not from the Stall Island, but some explorer brought them a few centuries ago and they're now often used by merchants that want to cross the difficult Goro Mounts or the wild Mangrove Wastes. diff --git a/schemas/mounts.yaml b/schemas/mounts.yaml index 5d1f1f7..537056e 100644 --- a/schemas/mounts.yaml +++ b/schemas/mounts.yaml @@ -11,10 +11,12 @@ stable: stats: agility addition: num() resistance addition: num() + health: int() levels: max level: int() level stat additions: agility addition: num() resistance addition: num() mph addition: num() + health addition: int() description: str() diff --git a/source/battle.py b/source/battle.py index 5f874b5..a9f181e 100644 --- a/source/battle.py +++ b/source/battle.py @@ -15,6 +15,7 @@ # source imports import text_handling import item_handling +import logger_sys from colors import * from terminal_handling import cout, cinput # external imports @@ -805,6 +806,19 @@ def fight( player["health"] += random.randint(0, 3) enemies_remaining -= 1 cout(f"You killed {text_handling.a_an_check(enemy_singular)}!") + if player["current mount"] != " ": + current_mount = str(player["current mount"]) + current_mount_type = str(player["mounts"][current_mount]["mount"]) + player["mounts"][current_mount]["last day health automatically reduced"] = round( + player["elapsed time game days"], 2 + ) + to_be_removed = round( + mounts[current_mount_type]["feed"]["feed needs"] * 1.75 + ) + player["mounts"][current_mount]["current health"] -= to_be_removed + logger_sys.log_message( + f"INFO: removed {to_be_removed} health points from player current mount {current_mount}" + ) time.sleep(2) still_playing = False turn = True diff --git a/source/main.py b/source/main.py index 8a39bdb..62355d4 100644 --- a/source/main.py +++ b/source/main.py @@ -1089,33 +1089,119 @@ def run(play): player["mounts"][str(player["current mount"])]["level"] = mounts[current_mount_type]["levels"]["max level"] logger_sys.log_message("INFO: Updating player ridden mount stats following its level") - # update player current mount stats following its level - if player["current mount"] in player["mounts"]: - current_mount_data = player["mounts"][str(player["current mount"])] + # update every player's mounts stats following its level + for current_mount in player["mounts"]: + current_mount_data = player["mounts"][current_mount] current_mount_type = str(current_mount_data["mount"]) - if current_mount_data["level"] >= 1: + player["mounts"][ + current_mount + ]["stats"]["agility addition"] = round( + mounts[current_mount_type]["stats"]["agility addition"] + + (mounts[current_mount_type]["levels"][ + "level stat additions" + ]["agility addition"] * (round(current_mount_data["level"]) - 1)), 3 + ) + player["mounts"][ + current_mount + ]["stats"]["resistance addition"] = round( + mounts[current_mount_type]["stats"]["resistance addition"] + + (mounts[current_mount_type]["levels"][ + "level stat additions" + ]["resistance addition"] * (round(current_mount_data["level"]) - 1)), 3 + ) + player["mounts"][ + current_mount + ]["mph"] = ( + mounts[current_mount_type]["mph"] + mounts[current_mount_type]["levels"][ + "level stat additions" + ]["mph addition"] * round(current_mount_data["level"] - 1) + ) + player["mounts"][ + current_mount + ]["health"] = ( + round(mounts[current_mount_type]["stats"]["health"] + mounts[current_mount_type]["levels"][ + "level stat additions" + ]["health addition"] * round(current_mount_data["level"] - 1)) + ) + # Transition from version 0.24-alpha to 0.25-alpha, where new stats were added + if "current health" not in player["mounts"][current_mount]: player["mounts"][ - str(player["current mount"]) - ]["stats"]["agility addition"] = round( - mounts[current_mount_type]["stats"]["agility addition"] + - (mounts[current_mount_type]["levels"][ + current_mount + ]["current health"] = ( + round(mounts[current_mount_type]["stats"]["health"] + mounts[current_mount_type]["levels"][ "level stat additions" - ]["agility addition"] * (round(current_mount_data["level"]) - 1)), 3 + ]["health addition"] * round(current_mount_data["level"] - 1)) + ) + logger_sys.log_message( + f"WARNING: Transitioning mount '{current_mount}' stats `current health` to new version" ) + if "last day health automatically reduced" not in player["mounts"][current_mount]: player["mounts"][ - str(player["current mount"]) - ]["stats"]["resistance addition"] = round( - mounts[current_mount_type]["stats"]["resistance addition"] + - (mounts[current_mount_type]["levels"][ - "level stat additions" - ]["resistance addition"] * (round(current_mount_data["level"]) - 1)), 3 + current_mount + ]["last day health automatically reduced"] = round(player["elapsed time game days"], 2) + logger_sys.log_message( + f"WARNING: Transitioning mount '{current_mount}' stats `current health` to new version" ) + if "last day health recovered" not in player["mounts"][current_mount]: player["mounts"][ - str(player["current mount"]) - ]["mph"] = ( - mounts[current_mount_type]["mph"] + mounts[current_mount_type]["levels"][ - "level stat additions" - ]["mph addition"] * round(current_mount_data["level"] - 1) + current_mount + ]["last day health recovered"] = round(player["elapsed time game days"], 2) + logger_sys.log_message( + f"WARNING: Transitioning mount '{current_mount}' stats `current health` to new version" + ) + + # Make sure the mount's health isn't over its max health + if ( + player["mounts"][current_mount]["current health"] > + player["mounts"][current_mount]["health"] + ): + player["mounts"][ + current_mount + ]["current health"] = player["mounts"][current_mount]["health"] + + # If the mount isn't deposited, and a day has just passed, + # remove some of that mount's health + if ( + not player["mounts"][current_mount]["is deposited"] and + ( + round(player["elapsed time game days"], 2) - + player["mounts"][current_mount]["last day health automatically reduced"] + ) >= 1 + ): + player["mounts"][current_mount]["last day health automatically reduced"] = round( + player["elapsed time game days"], 2 + ) + to_be_removed = round( + mounts[current_mount_type]["feed"]["feed needs"] * 2.15 + ) + player["mounts"][current_mount]["current health"] -= to_be_removed + logger_sys.log_message( + f"INFO: Removed {to_be_removed} health points to mount '{current_mount}' because a new day passed" + ) + # If the mount is deposited, and its current health is not + # at its max, and a quarter of a day has just passed, + # recover 15% of its max health. + if ( + player["mounts"][current_mount]["is deposited"] and + ( + round(player["elapsed time game days"], 2) - + player["mounts"][current_mount]["last day health recovered"] + ) >= .25 and + ( + player["mounts"][current_mount]["current health"] + < player["mounts"][current_mount]["health"] + ) + ): + player["mounts"][current_mount]["last day health recovered"] = round( + player["elapsed time game days"], 2 + ) + to_be_added = round( + player["mounts"][current_mount]["health"] * .15 + ) + player["mounts"][current_mount]["current health"] += to_be_added + logger_sys.log_message( + f"INFO: Recovered {to_be_added} health points to mount '{current_mount}' " + + "because it rested for a quarter of a day at a stable" ) logger_sys.log_message("INFO: Verifying player equipped equipment is in the player's inventory") @@ -2149,6 +2235,78 @@ def run(play): f.write(dumped) logger_sys.log_message(f"INFO: Dumping player preferences to file '" + program_dir + "/preferences.yaml'") + # If the player's mount's health is at 0%, it dies (T-T) + # ELSE: + # Warn the player about its current mount's health status at: + # below 50%, below 25%, below 10%, below 5% + if player["current mount"] in player["mounts"]: + current_mount_data = player["mounts"][str(player["current mount"])] + current_mount_type = str(current_mount_data["mount"]) + + if current_mount_data["current health"] <= 0: + cout( + COLOR_STYLE_BRIGHT + COLOR_BACK_BLACK + COLOR_RED + + "Warning: your current mount died ! (T-T)" + COLOR_RESET_ALL + ) + cout(COLOR_BLUE + "R.I.P " + current_mount_data["name"] + COLOR_RESET_ALL) + cout(""" _____ _____ + < `/ | + > ( + | _ _ | + | |_) | |_) | + | | \\ | | | + | | + ______.______%_| |__________ _____ + _/ \\| |""") + cout( + " " * 14 + "|" + int(48 / 2 - len(current_mount_data["name"]) / 2) * " " + + current_mount_data["name"].upper() + + int(48 / 2 - len(current_mount_data["name"]) / 2) * " " + "<" + ) + cout(""" |_____.-._________ ____/|___________| + | * you'll | + | be rememb- | + | -ered | + | | + | _ < + |__/ | + / `--. | + %| |% + |/.%%| -< @%%% + `\\%`@| v |@@%@%% + .%%%@@@|% | % @@@%%@%%%% + _.%%%%%%@@@@@@%%_/%\\_%@@%%@@@@@@@%%%%%%""") + logger_sys.log_message(f"INFO: Player mount '{str(player["current mount"])}' died") + player["mounts"].pop(str(player["current mount"])) + player["current mount"] = " " + else: + if ( + 100 * current_mount_data["current health"] / current_mount_data["health"] + ) <= 5: + cout( + COLOR_STYLE_BRIGHT + COLOR_BACK_BLACK + COLOR_RED + + "Warning: your current mount's health is below 5% !" + COLOR_RESET_ALL + ) + cout("Deposit your mount for it to recover health") + elif ( + 100 * current_mount_data["current health"] / current_mount_data["health"] + ) <= 10: + cout( + COLOR_STYLE_BRIGHT + COLOR_RED + "Warning: your current mount's health is below 10% !" + + COLOR_RESET_ALL + ) + cout("Deposit your mount for it to recover health") + elif ( + 100 * current_mount_data["current health"] / current_mount_data["health"] + ) <= 25: + cout(COLOR_ORANGE_5 + "Warning: your current mount's health is below 25% !" + COLOR_RESET_ALL) + cout("Deposit your mount for it to recover health") + elif ( + 100 * current_mount_data["current health"] / current_mount_data["health"] + ) <= 50: + cout(COLOR_YELLOW + "Warning: your current mount's health is below 50% !" + COLOR_RESET_ALL) + cout("Deposit your mount for it to recover health") + command = cinput(COLOR_GREEN + COLOR_STYLE_BRIGHT + "> " + COLOR_RESET_ALL) cout(" ") @@ -3288,6 +3446,29 @@ def run(play): cout("PLURAL: " + mounts[which_mount_data["mount"]]["plural"]) cout(" ") + mount_max = which_mount_data["health"] + mount_health = which_mount_data["current health"] + remaining_health_bars = round(mount_health / mount_max * 20) + lost_health_bars = 20 - remaining_health_bars + + if remaining_health_bars > 20: + remaining_health_bars = 20 + + if mount_health > .66 * mount_max: + health_color = COLOR_BLUE + elif mount_health > .33 * mount_max: + health_color = COLOR_CYAN + else: + health_color = COLOR_MAGENTA + + cout(f"HEALTH of {which_mount_data["name"]}: {mount_health} / {mount_max}") + cout( + f"|{health_color}{remaining_health_bars * "█"}" + + f"{lost_health_bars * "_"}{COLOR_RESET}|" + ) + + cout(" ") + which_mount_location = ( "(" + COLOR_GREEN + COLOR_STYLE_BRIGHT + str(map[which_mount_data["location"]]["x"]) + COLOR_RESET_ALL + diff --git a/source/zone_handling.py b/source/zone_handling.py index e278b74..3e4b6d1 100644 --- a/source/zone_handling.py +++ b/source/zone_handling.py @@ -741,7 +741,11 @@ def interaction_stable(map_zone, zone, player, item, drinks, mounts, map_locatio "mount": str(which_mount), "name": str(new_mount_name), "stats": mount_stats, - "mph": mounts[which_mount]["mph"] + "mph": mounts[which_mount]["mph"], + "health": mounts[which_mount]["stats"]["health"], + "current health": mounts[which_mount]["stats"]["health"], + "last day health automatically reduced": round(player["elapsed time game days"], 2), + "last day health recovered": round(player["elapsed time game days"], 2) } logger_sys.log_message(f"INFO: Created new mount stats: '{mount_dict}'") player["mounts"][generated_mount_uuid] = mount_dict @@ -802,6 +806,17 @@ def interaction_stable(map_zone, zone, player, item, drinks, mounts, map_locatio train.training_loop( current_mount_uuid, player, item, mounts, zone[map_zone], time_elapsing_coefficient, dropoff ) + player["mounts"][current_mount_uuid]["last day health automatically reduced"] = round( + player["elapsed time game days"], 2 + ) + to_be_removed = round( + mounts[current_mount_type]["feed"]["feed needs"] * 1.015 + ) + player["mounts"][current_mount_uuid]["current health"] -= to_be_removed + logger_sys.log_message( + f"INFO: Removed {to_be_removed} health points to mount '{current_mount_uuid}' " + + "because it's finished training" + ) else: logger_sys.log_message( f"INFO: Aborting mount training of mount '{current_mount_uuid}' " +