diff --git a/src/caret.rs b/src/caret.rs index dc3540c..ef0940f 100644 --- a/src/caret.rs +++ b/src/caret.rs @@ -1,8 +1,9 @@ +use std::fs::read_to_string; + use crate::bitfield; use crate::common::{Condition, Direction, Rect}; use crate::engine_constants::EngineConstants; use crate::rng::RNG; -use std::fs::read_to_string; #[derive(Debug, EnumIter, PartialEq, Eq, Hash, Copy, Clone)] pub enum CaretType { @@ -83,7 +84,7 @@ impl Caret { self.anim_rect = constants.caret.projectile_dissipation_left_rects[self.anim_num as usize]; } - }, + } Direction::Up => { self.anim_counter += 1; @@ -93,7 +94,7 @@ impl Caret { let len = constants.caret.projectile_dissipation_up_rects.len(); self.anim_rect = constants.caret.projectile_dissipation_up_rects[(self.anim_num as usize / 2) % len]; - }, + } Direction::Right => { self.anim_counter += 1; if self.anim_counter > 2 { @@ -107,10 +108,10 @@ impl Caret { self.anim_rect = constants.caret.projectile_dissipation_right_rects[self.anim_num as usize]; } - }, + } Direction::Bottom => { self.cond.set_alive(false); - }, + } } } CaretType::Shoot => { @@ -198,7 +199,33 @@ impl Caret { _ => { self.anim_rect } } } - CaretType::LevelUp => {} + CaretType::LevelUp => { + self.anim_counter += 1; + + if self.anim_counter == 80 { + self.cond.set_alive(false); + } + + match self.direction { + Direction::Left => { + if self.anim_counter < 20 { + self.y -= 0x400; // 2.0fix9 + } + + let count = constants.caret.level_up_rects.len(); + self.anim_rect = constants.caret.level_up_rects[self.anim_counter as usize / 2 % count] + } + Direction::Right => { + if self.anim_counter < 20 { + self.y -= 0x200; // 2.0fix9 + } + + let count = constants.caret.level_down_rects.len(); + self.anim_rect = constants.caret.level_down_rects[self.anim_counter as usize / 2 % count] + } + _ => {} + } + } CaretType::HurtParticles => {} CaretType::Explosion => { if self.anim_counter == 0 { diff --git a/src/inventory.rs b/src/inventory.rs index 2c804d7..f020bfa 100644 --- a/src/inventory.rs +++ b/src/inventory.rs @@ -21,6 +21,12 @@ pub enum AddExperienceResult { AddStar, } +#[derive(Clone, Copy)] +pub enum TakeExperienceResult { + None, + LevelDown, +} + impl Inventory { #[allow(clippy::new_without_default)] pub fn new() -> Inventory { @@ -120,6 +126,37 @@ impl Inventory { } } + pub fn take_xp(&mut self, exp: u16, state: &mut SharedGameState) -> TakeExperienceResult { + let mut result = TakeExperienceResult::None; + + if let Some(weapon) = self.get_current_weapon_mut() { + let lvl_table = state.constants.weapon.level_table[weapon.wtype as usize]; + let mut tmp_exp = weapon.experience as isize - exp as isize; + + if tmp_exp >= 0 { + weapon.experience = tmp_exp as u16; + } else { + while tmp_exp < 0 { + if weapon.level == WeaponLevel::Level1 { + weapon.experience = 0; + tmp_exp = 0; + } else if weapon.experience < exp { + let max_level = lvl_table[weapon.level as usize - 1] as isize; + weapon.level = weapon.level.prev(); + weapon.experience = (max_level + tmp_exp.max(-max_level)) as u16; + tmp_exp += max_level; + + if weapon.wtype != WeaponType::Spur { + result = TakeExperienceResult::LevelDown; + } + } + } + } + } + + result + } + pub fn add_xp(&mut self, exp: u16, state: &mut SharedGameState) -> AddExperienceResult { let mut result = AddExperienceResult::None; diff --git a/src/player.rs b/src/player.rs index 613ed4e..0e129a5 100644 --- a/src/player.rs +++ b/src/player.rs @@ -44,6 +44,7 @@ pub struct Player { pub current_weapon: u8, pub update_target: bool, pub stars: u8, + pub damage: u16, weapon_offset_y: i8, index_x: isize, index_y: isize, @@ -91,6 +92,7 @@ impl Player { shock_counter: 0, booster_switch: 0, stars: 0, + damage: 0, bubble: 0, exp_wait: 0, exp_count: 0, @@ -523,6 +525,8 @@ impl Player { self.stars -= 1; } + self.damage = self.damage.saturating_add(hp as u16); + if self.life == 0 { state.sound_manager.play_sfx(17); self.cond.0 = 0; diff --git a/src/scene/game_scene.rs b/src/scene/game_scene.rs index 929d262..d97e54b 100644 --- a/src/scene/game_scene.rs +++ b/src/scene/game_scene.rs @@ -8,7 +8,7 @@ use crate::frame::Frame; use crate::ggez::{Context, GameResult, graphics, timer}; use crate::ggez::graphics::Color; use crate::ggez::nalgebra::clamp; -use crate::inventory::Inventory; +use crate::inventory::{Inventory, TakeExperienceResult}; use crate::npc::NPCMap; use crate::physics::PhysicalEntity; use crate::player::Player; @@ -714,6 +714,19 @@ impl Scene for GameScene { } }; self.player.tick(state, ())?; + + if self.player.damage > 0 { + let xp_loss = self.player.damage * if self.player.equip.has_arms_barrier() { 1 } else { 2 }; + match self.inventory.take_xp(xp_loss, state) { + TakeExperienceResult::LevelDown if self.player.life > 0 => { + state.create_caret(self.player.x, self.player.y, CaretType::LevelUp, Direction::Right); + } + _ => {} + } + + self.player.damage = 0; + } + for npc_id in self.npc_map.npc_ids.iter() { if let Some(npc_cell) = self.npc_map.npcs.get(npc_id) { let mut npc = npc_cell.borrow_mut(); diff --git a/src/weapon.rs b/src/weapon.rs index afa34bf..c22ffd3 100644 --- a/src/weapon.rs +++ b/src/weapon.rs @@ -40,6 +40,15 @@ impl WeaponLevel { WeaponLevel::Level3 => { WeaponLevel::Level3 } } } + + pub fn prev(self) -> WeaponLevel { + match self { + WeaponLevel::None => { WeaponLevel::Level1 } + WeaponLevel::Level1 => { WeaponLevel::Level1 } + WeaponLevel::Level2 => { WeaponLevel::Level1 } + WeaponLevel::Level3 => { WeaponLevel::Level2 } + } + } } #[derive(Clone)]