mirror of
https://github.com/doukutsu-rs/doukutsu-rs
synced 2025-11-30 08:08:18 +00:00
jellies and fixes for dumb bugs
This commit is contained in:
parent
c4a87f5a64
commit
ff723c728b
|
|
@ -109,6 +109,12 @@ impl Game {
|
||||||
self.loops += 1;
|
self.loops += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.loops == 10 {
|
||||||
|
log::warn!("Frame skip is way too high, a long system lag occurred?");
|
||||||
|
self.next_tick = self.start_time.elapsed().as_nanos();
|
||||||
|
self.loops = 0;
|
||||||
|
}
|
||||||
|
|
||||||
for _ in 0..self.loops {
|
for _ in 0..self.loops {
|
||||||
scene.tick(&mut self.state, ctx)?;
|
scene.tick(&mut self.state, ctx)?;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -347,7 +347,205 @@ impl NPC {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick_n104_frog(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
pub(crate) fn tick_n094_kulala(&mut self, state: &SharedGameState, player: &Player) -> GameResult {
|
||||||
|
match self.action_num {
|
||||||
|
0 => {
|
||||||
|
self.anim_num = 4;
|
||||||
|
if self.shock > 0 {
|
||||||
|
self.anim_num = 0;
|
||||||
|
self.action_num = 10;
|
||||||
|
self.action_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
10 => {
|
||||||
|
self.npc_flags.set_shootable(true);
|
||||||
|
self.npc_flags.set_invulnerable(false);
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 40 {
|
||||||
|
self.action_num = 11;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
11 => {
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 5 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num > 2 {
|
||||||
|
self.action_num = 12;
|
||||||
|
self.anim_num = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
12 => {
|
||||||
|
self.vel_y = -0x155;
|
||||||
|
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 20 {
|
||||||
|
self.action_num = 10;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
20 => {
|
||||||
|
self.vel_x /= 2;
|
||||||
|
self.vel_y += 0x10;
|
||||||
|
|
||||||
|
if self.shock == 0 {
|
||||||
|
self.action_num = 10;
|
||||||
|
self.action_counter = 30;
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.shock > 0 {
|
||||||
|
self.action_counter2 += 1;
|
||||||
|
if self.action_counter2 > 12 {
|
||||||
|
self.action_num = 20;
|
||||||
|
self.anim_num = 4;
|
||||||
|
self.npc_flags.set_shootable(false);
|
||||||
|
self.npc_flags.set_invulnerable(true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.action_counter2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.action_num >= 10 {
|
||||||
|
if self.flags.hit_left_wall() {
|
||||||
|
self.vel_x2 = 50;
|
||||||
|
self.direction = Direction::Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.flags.hit_right_wall() {
|
||||||
|
self.vel_x2 = 50;
|
||||||
|
self.direction = Direction::Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.vel_x2 > 0 {
|
||||||
|
self.vel_x2 -= 1;
|
||||||
|
|
||||||
|
self.vel_x += self.direction.vector_x() * 0x80;
|
||||||
|
} else {
|
||||||
|
self.vel_x2 = 50;
|
||||||
|
self.direction = if self.x > player.x {
|
||||||
|
Direction::Left
|
||||||
|
} else {
|
||||||
|
Direction::Right
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vel_y += 0x10;
|
||||||
|
|
||||||
|
if self.flags.hit_bottom_wall() {
|
||||||
|
self.vel_y = -2 * 0x200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vel_x = clamp(self.vel_x, -0x100, 0x100);
|
||||||
|
self.vel_y = clamp(self.vel_y, -0x300, 0x300);
|
||||||
|
|
||||||
|
self.x += self.vel_x;
|
||||||
|
self.y += self.vel_y;
|
||||||
|
|
||||||
|
self.anim_rect = state.constants.npc.n094_kulala[self.anim_num as usize];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n095_jelly(&mut self, state: &SharedGameState) -> GameResult {
|
||||||
|
match self.action_num {
|
||||||
|
0 | 1 | 10 => {
|
||||||
|
if self.action_num == 0 {
|
||||||
|
self.action_num = 1;
|
||||||
|
self.action_counter = state.game_rng.range(0..50) as u16;
|
||||||
|
self.target_x = self.x;
|
||||||
|
self.target_y = self.y;
|
||||||
|
|
||||||
|
self.vel_x = -self.direction.vector_x() * 0x200;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.action_num == 1 {
|
||||||
|
if self.action_counter > 0 {
|
||||||
|
self.action_counter -= 1;
|
||||||
|
} else {
|
||||||
|
self.action_num = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.action_num == 10 {
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 10 {
|
||||||
|
self.action_num = 11;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
11 => {
|
||||||
|
self.anim_counter += 1;
|
||||||
|
if self.anim_counter > 5 {
|
||||||
|
self.anim_counter = 0;
|
||||||
|
self.anim_num += 1;
|
||||||
|
if self.anim_num == 2 {
|
||||||
|
self.vel_x += self.direction.vector_x() * 0x100;
|
||||||
|
self.vel_y -= 0x200;
|
||||||
|
} else if self.anim_num > 2 {
|
||||||
|
self.action_num = 12;
|
||||||
|
self.anim_num = 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
12 => {
|
||||||
|
self.action_counter += 1;
|
||||||
|
if self.action_counter > 10 && self.y > self.target_y {
|
||||||
|
self.action_num = 10;
|
||||||
|
self.action_counter = 0;
|
||||||
|
self.anim_num = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.direction = if self.x <= self.target_x { Direction::Right } else { Direction::Left };
|
||||||
|
|
||||||
|
if self.flags.hit_left_wall() {
|
||||||
|
self.action_counter2 = 50;
|
||||||
|
self.direction = Direction::Right;
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.flags.hit_right_wall() {
|
||||||
|
self.action_counter2 = 50;
|
||||||
|
self.direction = Direction::Left;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vel_y += 0x20;
|
||||||
|
if self.flags.hit_bottom_wall() {
|
||||||
|
self.vel_y = -2 * 0x200;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.vel_x = clamp(self.vel_x, -0x100, 0x100);
|
||||||
|
self.vel_y = clamp(self.vel_y, -0x200, 0x200);
|
||||||
|
|
||||||
|
if self.shock > 0 {
|
||||||
|
self.x += self.vel_x / 2;
|
||||||
|
self.y += self.vel_y / 2;
|
||||||
|
} else {
|
||||||
|
self.x += self.vel_x;
|
||||||
|
self.y += self.vel_y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
let dir_offset = if self.direction == Direction::Left { 0 } else { 4 };
|
||||||
|
self.anim_rect = state.constants.npc.n095_jelly[self.anim_num as usize + dir_offset];
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn tick_n104_frog(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
||||||
match self.action_num {
|
match self.action_num {
|
||||||
0 => {
|
0 => {
|
||||||
self.action_num = 1;
|
self.action_num = 1;
|
||||||
|
|
@ -467,7 +665,7 @@ impl NPC {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tick_n110_puchi(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
pub(crate) fn tick_n110_puchi(&mut self, state: &mut SharedGameState, player: &Player) -> GameResult {
|
||||||
match self.action_num {
|
match self.action_num {
|
||||||
0 => {
|
0 => {
|
||||||
self.action_num = 1;
|
self.action_num = 1;
|
||||||
|
|
|
||||||
|
|
@ -238,6 +238,8 @@ impl GameEntity<(&mut Player, &HashMap<u16, RefCell<NPC>>, &mut Stage)> for NPC
|
||||||
86 => self.tick_n086_missile_pickup(state),
|
86 => self.tick_n086_missile_pickup(state),
|
||||||
87 => self.tick_n087_heart_pickup(state),
|
87 => self.tick_n087_heart_pickup(state),
|
||||||
91 => self.tick_n091_mimiga_cage(state),
|
91 => self.tick_n091_mimiga_cage(state),
|
||||||
|
94 => self.tick_n094_kulala(state, player),
|
||||||
|
95 => self.tick_n095_jelly(state),
|
||||||
96 => self.tick_n096_fan_left(state, player),
|
96 => self.tick_n096_fan_left(state, player),
|
||||||
97 => self.tick_n097_fan_up(state, player),
|
97 => self.tick_n097_fan_up(state, player),
|
||||||
98 => self.tick_n098_fan_right(state, player),
|
98 => self.tick_n098_fan_right(state, player),
|
||||||
|
|
@ -685,14 +687,19 @@ impl NPCMap {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_alive(&self, npc_id: u16) -> bool {
|
/// Returns true if at least one NPC with specified type is alive.
|
||||||
if let Some(npc_cell) = self.npcs.get(&npc_id) {
|
pub fn is_alive_by_type(&self, npc_type: u16) -> bool {
|
||||||
return npc_cell.borrow().cond.alive();
|
for npc_cell in self.npcs.values() {
|
||||||
|
let npc = npc_cell.borrow();
|
||||||
|
if npc.cond.alive() && npc.npc_type == npc_type {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns true if at least one NPC with specified event is alive.
|
||||||
pub fn is_alive_by_event(&self, event_num: u16) -> bool {
|
pub fn is_alive_by_event(&self, event_num: u16) -> bool {
|
||||||
for npc_cell in self.npcs.values() {
|
for npc_cell in self.npcs.values() {
|
||||||
let npc = npc_cell.borrow();
|
let npc = npc_cell.borrow();
|
||||||
|
|
|
||||||
|
|
@ -586,7 +586,7 @@ impl GameScene {
|
||||||
if !self.player.cond.hidden() && self.inventory.get_current_weapon().is_some() {
|
if !self.player.cond.hidden() && self.inventory.get_current_weapon().is_some() {
|
||||||
self.draw_light(fix9_scale(self.player.x - self.frame.x, scale),
|
self.draw_light(fix9_scale(self.player.x - self.frame.x, scale),
|
||||||
fix9_scale(self.player.y - self.frame.y, scale),
|
fix9_scale(self.player.y - self.frame.y, scale),
|
||||||
2.5, (225, 225, 225), batch);
|
4.0, (140, 140, 140), batch);
|
||||||
}
|
}
|
||||||
|
|
||||||
for bullet in self.bullet_manager.bullets.iter() {
|
for bullet in self.bullet_manager.bullets.iter() {
|
||||||
|
|
|
||||||
|
|
@ -185,7 +185,7 @@ pub enum OpCode {
|
||||||
NCJ,
|
NCJ,
|
||||||
/// <ECJxxxx:yyyy, Jumps to event xxxx if NPC tagged with event yyyy is alive
|
/// <ECJxxxx:yyyy, Jumps to event xxxx if NPC tagged with event yyyy is alive
|
||||||
ECJ,
|
ECJ,
|
||||||
/// <FLJxxxx:yyyy, Jumps to event xxxx if flag yyyy is set
|
/// <FLJxxxx:yyyy, Jumps to event yyyy if flag xxxx is set
|
||||||
FLJ,
|
FLJ,
|
||||||
/// <FLJxxxx:yyyy, Jumps to event xxxx if player has item yyyy
|
/// <FLJxxxx:yyyy, Jumps to event xxxx if player has item yyyy
|
||||||
ITJ,
|
ITJ,
|
||||||
|
|
@ -852,10 +852,10 @@ impl TextScriptVM {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
OpCode::NCJ => {
|
OpCode::NCJ => {
|
||||||
let npc_id = read_cur_varint(&mut cursor)? as u16;
|
let npc_type = read_cur_varint(&mut cursor)? as u16;
|
||||||
let event_num = read_cur_varint(&mut cursor)? as u16;
|
let event_num = read_cur_varint(&mut cursor)? as u16;
|
||||||
|
|
||||||
if game_scene.npc_map.is_alive(npc_id) {
|
if game_scene.npc_map.is_alive_by_type(npc_type) {
|
||||||
exec_state = TextScriptExecutionState::Running(event_num, 0);
|
exec_state = TextScriptExecutionState::Running(event_num, 0);
|
||||||
} else {
|
} else {
|
||||||
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue