some bullet fixes

This commit is contained in:
Alula 2021-03-12 17:53:08 +01:00
parent ecfcf57847
commit f87b791c87
No known key found for this signature in database
GPG Key ID: 3E00485503A1D8BA
3 changed files with 384 additions and 63 deletions

View File

@ -76,6 +76,7 @@ impl BulletManager {
}
}
#[derive(Clone)]
pub struct Bullet {
pub btype: u16,
pub x: i32,
@ -90,6 +91,7 @@ pub struct Bullet {
pub lifetime: u16,
pub damage: i16,
pub counter1: u16,
pub counter2: u16,
pub rng: Xoroshiro32PlusPlus,
pub owner: TargetPlayer,
pub cond: Condition,
@ -135,6 +137,7 @@ impl Bullet {
lifetime: bullet.lifetime,
damage: bullet.damage as i16,
counter1: 0,
counter2: 0,
rng: Xoroshiro32PlusPlus::new(1),
owner,
cond: Condition(0x80),
@ -668,25 +671,25 @@ impl Bullet {
return;
}
if self.action_counter == 0 {
self.action_counter = 1;
if self.action_num == 0 {
self.action_num = 1;
match self.direction {
Direction::Left => {
self.vel_x = self.rng.range(-0x400..-0x200);
self.vel_y = self.rng.range(-4..4) * 0x200 / 2;
self.vel_y = (self.rng.range(-4..4) * 0x200) / 2;
}
Direction::Up => {
self.vel_y = self.rng.range(-0x400..-0x200);
self.vel_x = self.rng.range(-4..4) * 0x200 / 2;
self.vel_x = (self.rng.range(-4..4) * 0x200) / 2;
}
Direction::Right => {
self.vel_x = self.rng.range(0x200..0x400);
self.vel_y = self.rng.range(-4..4) * 0x200 / 2;
self.vel_y = (self.rng.range(-4..4) * 0x200) / 2;
}
Direction::Bottom => {
self.vel_y = self.rng.range(0x80..0x100);
self.vel_x = self.rng.range(-4..4) * 0x200 / 2;
self.vel_x = (self.rng.range(-4..4) * 0x200) / 2;
}
Direction::FacingPlayer => unreachable!(),
}
@ -987,6 +990,178 @@ impl Bullet {
}
}
fn tick_super_missile(&mut self, state: &mut SharedGameState, players: [&Player; 2], new_bullets: &mut Vec<Bullet>) {
let player = players[self.owner.index()];
self.action_counter += 1;
if self.action_counter > self.lifetime {
self.cond.set_alive(false);
state.create_caret(self.x, self.y, CaretType::Shoot, Direction::Left);
return;
}
if match self.direction {
Direction::Left if self.flags.hit_left_wall() => true,
Direction::Left if self.flags.hit_left_slope() => true,
Direction::Left if self.flags.flag_x80() => true,
Direction::Right if self.flags.hit_right_wall() => true,
Direction::Right if self.flags.hit_right_slope() => true,
Direction::Right if self.flags.flag_x40() => true,
Direction::Up if self.flags.hit_top_wall() => true,
Direction::Bottom if self.flags.hit_bottom_wall() => true,
_ => false,
} {
let bomb_bullet = match self.btype {
28 => 31,
29 => 32,
30 => 33,
_ => unreachable!(),
};
let bullet = Bullet::new(self.x, self.y, bomb_bullet, self.owner, self.direction, &state.constants);
new_bullets.push(bullet);
self.cond.set_alive(false);
return;
}
if self.action_num == 0 {
self.action_num = 1;
match self.direction {
Direction::Left | Direction::Right => {
self.target_y = self.y;
self.enemy_hit_height = 0x1000;
self.hit_bounds.top = 0x1000;
self.hit_bounds.bottom = 0x1000;
}
Direction::Up | Direction::Bottom => {
self.target_x = self.x;
self.enemy_hit_width = 0x1000;
self.hit_bounds.left = 0x1000;
self.hit_bounds.right = 0x1000;
}
_ => {}
}
if self.btype == 30 {
match self.direction {
Direction::Left | Direction::Right => {
self.vel_y = (self.y - player.y).signum() * 0x100;
self.vel_x = self.rng.range(-0x200..0x200);
}
Direction::Up | Direction::Bottom => {
self.vel_x = (self.x - player.x).signum() * 0x100;
self.vel_y = self.rng.range(-0x200..0x200);
}
_ => {}
}
}
self.counter1 = match self.counter1 {
1 => 256,
2 => 170,
_ => 512,
};
}
match self.direction {
Direction::Left => self.vel_x -= self.counter1 as i32,
Direction::Up => self.vel_y -= self.counter1 as i32,
Direction::Right => self.vel_x += self.counter1 as i32,
Direction::Bottom => self.vel_y += self.counter1 as i32,
_ => {}
}
if self.btype == 30 {
match self.direction {
Direction::Left | Direction::Right => {
self.vel_y = (player.y - self.y).signum() * 0x40;
}
Direction::Up | Direction::Bottom => {
self.vel_x = (player.x - self.x).signum() * 0x40;
}
_ => {}
}
}
self.vel_x = clamp(self.vel_x, -0x1400, 0x1400);
self.vel_y = clamp(self.vel_y, -0x1400, 0x1400);
self.x += self.vel_x;
self.y += self.vel_y;
self.counter2 += 1;
if self.counter2 > 2 {
self.counter2 = 0;
match self.direction {
Direction::Left => {
state.create_caret(self.x + 0x1000, self.y, CaretType::Exhaust, self.direction.opposite());
}
Direction::Up => {
state.create_caret(self.x, self.y + 0x1000, CaretType::Exhaust, self.direction.opposite());
}
Direction::Right => {
state.create_caret(self.x - 0x1000, self.y, CaretType::Exhaust, self.direction.opposite());
}
Direction::Bottom => {
state.create_caret(self.x, self.y - 0x1000, CaretType::Exhaust, self.direction.opposite());
}
Direction::FacingPlayer => {}
}
}
match self.btype {
28 | 30 => {
self.anim_rect = state.constants.weapon.bullet_rects.b028_super_missile_l1[self.direction as usize];
}
29 => {
self.anim_rect = state.constants.weapon.bullet_rects.b029_super_missile_l2[self.direction as usize];
}
_ => {}
}
}
fn tick_super_missile_explosion(&mut self, state: &mut SharedGameState, npc_list: &NPCList) {
if self.action_num == 0 {
self.action_num = 1;
self.action_counter = match self.btype {
31 => 10,
32 => 14,
33 => 6,
_ => 0,
};
state.sound_manager.play_sfx(44);
}
if self.action_counter % 3 == 0 {
let radius = match self.btype {
31 => 16,
32 => 32,
33 => 40,
_ => 0,
};
npc_list.create_death_smoke_up(
self.x + self.rng.range(-radius..radius) * 0x200,
self.y + self.rng.range(-radius..radius) * 0x200,
self.enemy_hit_width as usize,
2,
state,
&self.rng,
);
}
self.action_counter -= 1;
if self.action_counter == 0 {
self.cond.set_alive(false);
}
}
fn tick_nemesis(&mut self, state: &mut SharedGameState, npc_list: &NPCList) {
self.action_counter += 1;
if self.action_counter > self.lifetime {
@ -1214,6 +1389,8 @@ impl Bullet {
25 => self.tick_blade_1(state),
26 => self.tick_blade_2(state),
27 => self.tick_blade_3(state, new_bullets),
28 | 29 | 30 => self.tick_super_missile(state, players, new_bullets),
31 | 32 | 33 => self.tick_super_missile_explosion(state, npc_list),
34 | 35 | 36 => self.tick_nemesis(state, npc_list),
37 | 38 | 39 => self.tick_spur(state, new_bullets),
40 | 41 | 42 => self.tick_spur_trail(state),

View File

@ -2,8 +2,8 @@ use crate::caret::CaretType;
use crate::common::Direction;
use crate::player::{Player, TargetPlayer};
use crate::shared_game_state::SharedGameState;
use crate::weapon::{Weapon, WeaponLevel};
use crate::weapon::bullet::BulletManager;
use crate::weapon::{Weapon, WeaponLevel};
impl Weapon {
pub(in crate::weapon) fn tick_fireball(
@ -14,60 +14,52 @@ impl Weapon {
state: &mut SharedGameState,
) {
let max_bullets = self.level as usize + 1;
if player.controller.trigger_shoot() && bullet_manager.count_bullets_multi(&[7, 8, 9], player_id) < max_bullets {
let btype = match self.level {
WeaponLevel::Level1 => 7,
WeaponLevel::Level2 => 8,
WeaponLevel::Level3 => 9,
WeaponLevel::None => {
unreachable!()
}
};
if !self.consume_ammo(1) {
// todo switch to first weapon
return;
}
if player.up {
match player.direction {
Direction::Left => {
bullet_manager.create_bullet(player.x - 0x800, player.y - 0x1000, btype, player_id, Direction::Up, &state.constants);
state.create_caret(player.x - 0x800, player.y - 0x1000, CaretType::Shoot, Direction::Left);
}
Direction::Right => {
bullet_manager.create_bullet(player.x + 0x800, player.y - 0x1000, btype, player_id, Direction::Up, &state.constants);
state.create_caret(player.x + 0x800, player.y - 0x1000, CaretType::Shoot, Direction::Left);
}
_ => {}
}
} else if player.down {
match player.direction {
Direction::Left => {
bullet_manager.create_bullet(player.x - 0x800, player.y + 0x1000, btype, player_id, Direction::Bottom, &state.constants);
state.create_caret(player.x - 0x800, player.y + 0x1000, CaretType::Shoot, Direction::Left);
}
Direction::Right => {
bullet_manager.create_bullet(player.x + 0x800, player.y + 0x1000, btype, player_id, Direction::Bottom, &state.constants);
state.create_caret(player.x + 0x800, player.y + 0x1000, CaretType::Shoot, Direction::Left);
}
_ => {}
}
} else {
match player.direction {
Direction::Left => {
bullet_manager.create_bullet(player.x - 0xc00, player.y + 0x400, btype, player_id, Direction::Left, &state.constants);
state.create_caret(player.x - 0x1800, player.y + 0x400, CaretType::Shoot, Direction::Left);
}
Direction::Right => {
bullet_manager.create_bullet(player.x + 0xc00, player.y + 0x400, btype, player_id, Direction::Right, &state.constants);
state.create_caret(player.x + 0x1800, player.y + 0x400, CaretType::Shoot, Direction::Right);
}
_ => {}
}
}
state.sound_manager.play_sfx(34)
if !player.controller.trigger_shoot() || bullet_manager.count_bullets_multi(&[7, 8, 9], player_id) >= max_bullets {
return;
}
let btype = match self.level {
WeaponLevel::Level1 => 7,
WeaponLevel::Level2 => 8,
WeaponLevel::Level3 => 9,
WeaponLevel::None => {
unreachable!()
}
};
if !self.consume_ammo(1) {
// todo switch to first weapon
return;
}
match player.direction {
Direction::Left if player.up => {
bullet_manager.create_bullet(player.x - 0x800, player.y - 0x1000, btype, player_id, Direction::Up, &state.constants);
state.create_caret(player.x - 0x800, player.y - 0x1000, CaretType::Shoot, Direction::Left);
}
Direction::Right if player.up => {
bullet_manager.create_bullet(player.x + 0x800, player.y - 0x1000, btype, player_id, Direction::Up, &state.constants);
state.create_caret(player.x + 0x800, player.y - 0x1000, CaretType::Shoot, Direction::Left);
}
Direction::Left if player.down => {
bullet_manager.create_bullet(player.x - 0x800, player.y + 0x1000, btype, player_id, Direction::Bottom, &state.constants);
state.create_caret(player.x - 0x800, player.y + 0x1000, CaretType::Shoot, Direction::Left);
}
Direction::Right if player.down => {
bullet_manager.create_bullet(player.x + 0x800, player.y + 0x1000, btype, player_id, Direction::Bottom, &state.constants);
state.create_caret(player.x + 0x800, player.y + 0x1000, CaretType::Shoot, Direction::Left);
}
Direction::Left => {
bullet_manager.create_bullet(player.x - 0xc00, player.y + 0x400, btype, player_id, Direction::Left, &state.constants);
state.create_caret(player.x - 0x1800, player.y + 0x400, CaretType::Shoot, Direction::Left);
}
Direction::Right => {
bullet_manager.create_bullet(player.x + 0xc00, player.y + 0x400, btype, player_id, Direction::Right, &state.constants);
state.create_caret(player.x + 0x1800, player.y + 0x400, CaretType::Shoot, Direction::Right);
}
_ => {}
}
state.sound_manager.play_sfx(34)
}
}

View File

@ -1,6 +1,8 @@
use crate::caret::CaretType;
use crate::common::Direction;
use crate::player::{Player, TargetPlayer};
use crate::shared_game_state::SharedGameState;
use crate::weapon::bullet::BulletManager;
use crate::weapon::bullet::{Bullet, BulletManager};
use crate::weapon::{Weapon, WeaponLevel};
impl Weapon {
@ -12,12 +14,162 @@ impl Weapon {
state: &mut SharedGameState,
) {
const BULLETS: [u16; 6] = [28, 29, 30, 31, 32, 33];
if !player.controller.trigger_shoot() {
return;
}
let btype = match self.level {
WeaponLevel::Level1 => 28,
WeaponLevel::Level2 => 29,
WeaponLevel::Level3 => 30,
WeaponLevel::None => unreachable!(),
};
match self.level {
WeaponLevel::Level1 if bullet_manager.count_bullets_multi(&BULLETS, player_id) > 0 => {
return;
}
WeaponLevel::Level2 if bullet_manager.count_bullets_multi(&BULLETS, player_id) > 1 => {
return;
}
WeaponLevel::Level3 if bullet_manager.count_bullets_multi(&BULLETS, player_id) > 3 => {
return;
}
_ => {}
}
if !self.consume_ammo(1) {
state.sound_manager.play_sfx(37);
// todo switch to first weapon
return;
}
fn increment(weapon: &mut Weapon, bullet: &mut Bullet) {
weapon.counter2 = (weapon.counter2 + 1) % 3;
bullet.counter1 = weapon.counter2;
}
match player.direction {
Direction::Left if player.up => {
let mut bullet = Bullet::new(player.x - 0x200, player.y - 0x1000, btype, player_id, Direction::Up, &state.constants);
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
state.create_caret(player.x - 0x200, player.y - 0x1000, CaretType::Shoot, Direction::Left);
if self.level == WeaponLevel::Level3 {
bullet.x = player.x - 0x600;
bullet.y = player.y;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
bullet.x = player.x + 0x600;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet);
}
}
Direction::Right if player.up => {
let mut bullet = Bullet::new(player.x + 0x200, player.y - 0x1000, btype, player_id, Direction::Up, &state.constants);
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
state.create_caret(player.x + 0x200, player.y - 0x1000, CaretType::Shoot, Direction::Left);
if self.level == WeaponLevel::Level3 {
bullet.x = player.x - 0x600;
bullet.y = player.y;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
bullet.x = player.x + 0x600;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet);
}
}
Direction::Left if player.down => {
let mut bullet = Bullet::new(player.x - 0x200, player.y + 0x1000, btype, player_id, Direction::Bottom, &state.constants);
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
state.create_caret(player.x - 0x200, player.y + 0x1000, CaretType::Shoot, Direction::Left);
if self.level == WeaponLevel::Level3 {
bullet.x = player.x - 0x600;
bullet.y = player.y;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
bullet.x = player.x + 0x600;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet);
}
}
Direction::Right if player.down => {
let mut bullet = Bullet::new(player.x + 0x200, player.y + 0x1000, btype, player_id, Direction::Bottom, &state.constants);
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
state.create_caret(player.x + 0x200, player.y + 0x1000, CaretType::Shoot, Direction::Left);
if self.level == WeaponLevel::Level3 {
bullet.x = player.x - 0x600;
bullet.y = player.y;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
bullet.x = player.x + 0x600;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet);
}
}
Direction::Left => {
let mut bullet = Bullet::new(player.x - 0xc00, player.y, btype, player_id, Direction::Left, &state.constants);
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
state.create_caret(player.x - 0x1800, player.y, CaretType::Shoot, Direction::Left);
if self.level == WeaponLevel::Level3 {
bullet.x = player.x;
bullet.y = player.y - 0x1000;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
bullet.x = player.x - 0x800;
bullet.y = player.y - 0x200;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet);
}
}
Direction::Right => {
let mut bullet = Bullet::new(player.x + 0xc00, player.y, btype, player_id, Direction::Right, &state.constants);
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
state.create_caret(player.x + 0x1800, player.y, CaretType::Shoot, Direction::Left);
if self.level == WeaponLevel::Level3 {
bullet.x = player.x;
bullet.y = player.y - 0x1000;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet.clone());
bullet.x = player.x + 0x800;
bullet.y = player.y - 0x200;
increment(self, &mut bullet);
bullet_manager.push_bullet(bullet);
}
}
_ => {}
}
state.sound_manager.play_sfx(32)
}
}