diff --git a/CHANGELOG.md b/CHANGELOG.md index 4913d12b..8f00f70d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,8 @@ * Show items bought and money spent in the buy command output #108 * Show mp cost in magic attacks 9f92efc * The stat command can be used to describe items and equipment #117 +* Equipment level found in chest based on distance instead of player level d22d3b9 +* Game balance related tweaks #118 ### Fixed * Reach level 50 and 100 unlock and reward 4128f75 @@ -36,6 +38,7 @@ * Missed levels with class quest completion 1ec760 * Tweak gold found in chests 0317979 83691fa * Don't add xp beyond the actual inflicted damage (prevents high xp when beating weaker enemies) 812a5f1 +* Continue moving through dirs after successful bribe/run away 570a0de ## [0.6.0](https://github.com/facundoolano/rpg-cli/releases/tag/0.6.0) - 2021-08-04 ### Added diff --git a/src/character/classes.yaml b/src/character/classes.yaml index a33a72b7..2c718b51 100644 --- a/src/character/classes.yaml +++ b/src/character/classes.yaml @@ -1,116 +1,116 @@ - name: warrior - hp: [30, 7] + hp: [50, 10] strength: [12, 3] speed: [11, 2] category: player - name: mage - hp: [20, 4] + hp: [30, 6] mp: [10, 4] strength: [10, 3] speed: [10, 2] category: player - name: thief - hp: [21, 5] + hp: [35, 7] strength: [7, 2] speed: [19, 4] category: player - name: rat - hp: [10, 3] + hp: [15, 5] strength: [5, 2] speed: [16, 2] category: common - name: wolf - hp: [15, 3] + hp: [25, 5] strength: [8, 2] speed: [12, 2] category: common - name: snake - hp: [13, 3] + hp: [23, 7] strength: [7, 2] speed: [6, 2] inflicts: [poison, 5] category: common - name: slime - hp: [80, 3] + hp: [80, 4] strength: [3, 2] speed: [4, 2] inflicts: [poison, 10] category: common - name: spider - hp: [10, 3] + hp: [16, 5] strength: [9, 2] speed: [12, 2] inflicts: [poison, 20] category: common - name: zombie - hp: [50, 3] + hp: [80, 5] strength: [8, 2] speed: [6, 2] category: rare - name: orc - hp: [35, 3] + hp: [60, 5] strength: [13, 2] speed: [12, 2] category: rare - name: skeleton - hp: [30, 3] + hp: [45, 5] strength: [10, 2] speed: [10, 2] category: rare - name: demon - hp: [50, 3] + hp: [70, 5] strength: [10, 2] speed: [18, 2] inflicts: [burn, 10] category: rare - name: vampire - hp: [50, 3] + hp: [70, 5] strength: [13, 2] speed: [10, 2] category: rare - name: dragon - hp: [100, 3] + hp: [110, 5] strength: [25, 2] speed: [8, 2] inflicts: [burn, 2] category: rare - name: golem - hp: [50, 3] + hp: [70, 5] strength: [45, 2] speed: [2, 1] category: rare - name: sorcerer - hp: [30, 3] + hp: [45, 5] mp: [13, 1] strength: [10, 2] speed: [8, 2] inflicts: [burn, 5] category: rare - name: chimera - hp: [200, 2] + hp: [250, 2] strength: [90, 2] speed: [16, 2] inflicts: [poison, 3] category: legendary - name: basilisk - hp: [150, 3] + hp: [180, 3] strength: [100, 2] speed: [18, 2] inflicts: [poison, 2] category: legendary - name: minotaur - hp: [100, 3] + hp: [120, 3] strength: [60, 2] speed: [40, 2] category: legendary - name: balrog - hp: [200, 3] + hp: [270, 3] strength: [200, 2] speed: [14, 2] inflicts: [burn, 3] category: legendary - name: phoenix - hp: [350, 3] + hp: [500, 3] strength: [180, 2] speed: [28, 2] inflicts: [burn, 3] diff --git a/src/character/enemy.rs b/src/character/enemy.rs index fa1bae6c..a25a42c6 100644 --- a/src/character/enemy.rs +++ b/src/character/enemy.rs @@ -24,6 +24,7 @@ pub fn spawn(location: &location::Location, player: &Character) -> Option Option<( class.hp.0 *= 2; class.strength.0 *= 2; class.category = Category::Legendary; - Some((class, 100)) + Some((class, player.level)) } else { None } @@ -106,7 +107,6 @@ fn spawn_random(player: &Character, distance: &location::Distance) -> (Class, i3 .clone(); let level = std::cmp::max(player.level / 10 + distance.len() - 1, 1); - let level = random().enemy_level(level); (Class::random(category).clone(), level) } diff --git a/src/character/mod.rs b/src/character/mod.rs index 3f15a223..f88336ef 100644 --- a/src/character/mod.rs +++ b/src/character/mod.rs @@ -289,7 +289,9 @@ impl Character { /// If the double beat ring is equipped, attack the receiver. pub fn maybe_double_beat(&mut self, receiver: &mut Self) { - if self.left_ring == Some(Ring::Double) || self.right_ring == Some(Ring::Double) { + if receiver.current_hp > 0 + && (self.left_ring == Some(Ring::Double) || self.right_ring == Some(Ring::Double)) + { // assuming it's always the player and we don't need to handle death let _ = self.attack(receiver); } diff --git a/src/game.rs b/src/game.rs index 5256585f..d7436fb0 100644 --- a/src/game.rs +++ b/src/game.rs @@ -98,7 +98,9 @@ impl Game { if !self.location.is_home() { if let Some(mut enemy) = enemy::spawn(&self.location, &self.player) { - return self.battle(&mut enemy, run, bribe); + if self.battle(&mut enemy, run, bribe)? { + return Ok(()); + } } } } @@ -218,19 +220,21 @@ impl Game { /// Attempt to bribe or run away according to the given options, /// and start a battle if that fails. + /// Return Ok(true) if a battle took place, Ok(false) if it was avoided, + /// Err if the character dies. pub fn battle( &mut self, enemy: &mut Character, run: bool, bribe: bool, - ) -> Result<(), character::Dead> { + ) -> Result { // don't attempt bribe and run in the same turn if bribe { let bribe_cost = self.player.gold_gained(enemy.level) / 2; if self.gold >= bribe_cost && random().bribe_succeeds() { self.gold -= bribe_cost; log::bribe(&self.player, bribe_cost); - return Ok(()); + return Ok(false); }; log::bribe(&self.player, 0); } else if run { @@ -242,13 +246,13 @@ impl Game { ); log::run_away(&self.player, success); if success { - return Ok(()); + return Ok(false); } } if let Ok(xp) = self.run_battle(enemy) { self.battle_won(enemy, xp); - Ok(()) + Ok(true) } else { self.battle_lost(); Err(character::Dead) diff --git a/src/item/chest.rs b/src/item/chest.rs index 41556441..2671156e 100644 --- a/src/item/chest.rs +++ b/src/item/chest.rs @@ -54,7 +54,7 @@ impl Chest { chest.gold = game.player.gold_gained(game.player.level + distance.len()); } if equipment_chest { - let (sword, shield) = random_equipment(game.player.rounded_level()); + let (sword, shield) = random_equipment(distance.len()); chest.sword = sword; chest.shield = shield; } @@ -170,9 +170,11 @@ fn maybe_upgrade(current: &mut Option, other: &mut Option) false } -fn random_equipment(level: i32) -> (Option, Option) { +fn random_equipment(distance: i32) -> (Option, Option) { let mut rng = rand::thread_rng(); + let level = std::cmp::max(1, (distance / 5) * 5); + vec![ (100, (Some(Equipment::sword(level)), None)), (80, (None, Some(Equipment::shield(level)))), @@ -193,11 +195,11 @@ fn random_item(level: i32) -> Box { (10, Box::new(Remedy::new())), (10, Box::new(Escape::new())), (50, Box::new(Ether::new(level))), - (10, Box::new(stone::Health)), - (10, Box::new(stone::Magic)), - (10, Box::new(stone::Power)), - (10, Box::new(stone::Speed)), - (5, Box::new(stone::Level)), + (5, Box::new(stone::Health)), + (5, Box::new(stone::Magic)), + (5, Box::new(stone::Power)), + (5, Box::new(stone::Speed)), + (1, Box::new(stone::Level)), ]; // make a separate vec with enumerated weights, then remove from the item vec diff --git a/src/randomizer.rs b/src/randomizer.rs index 4b5c55e8..0aa81713 100644 --- a/src/randomizer.rs +++ b/src/randomizer.rs @@ -170,7 +170,7 @@ impl Randomizer for DefaultRandomizer { let mut rng = rand::thread_rng(); match distance { - location::Distance::Near(_) => false, + location::Distance::Near(_) => rng.gen_ratio(1, 30), location::Distance::Mid(_) => rng.gen_ratio(3, 30), location::Distance::Far(_) => rng.gen_ratio(5, 30), } @@ -180,9 +180,9 @@ impl Randomizer for DefaultRandomizer { let mut rng = rand::thread_rng(); match distance { - location::Distance::Near(_) => rng.gen_ratio(1, 30), - location::Distance::Mid(_) => rng.gen_ratio(4, 30), - location::Distance::Far(_) => rng.gen_ratio(6, 30), + location::Distance::Near(_) => false, + location::Distance::Mid(_) => rng.gen_ratio(3, 30), + location::Distance::Far(_) => rng.gen_ratio(5, 30), } } @@ -190,9 +190,9 @@ impl Randomizer for DefaultRandomizer { let mut rng = rand::thread_rng(); match distance { - location::Distance::Near(_) => rng.gen_ratio(5, 50), - location::Distance::Mid(_) => rng.gen_ratio(10, 50), - location::Distance::Far(_) => rng.gen_ratio(16, 50), + location::Distance::Near(_) => rng.gen_ratio(1, 50), + location::Distance::Mid(_) => rng.gen_ratio(5, 50), + location::Distance::Far(_) => rng.gen_ratio(10, 50), } } }