1
0
Fork 0
mirror of https://github.com/doukutsu-rs/doukutsu-rs synced 2025-11-29 15:56:53 +00:00

jellies and fixes for dumb bugs

This commit is contained in:
Alula 2020-11-04 16:37:00 +01:00
parent c4a87f5a64
commit ff723c728b
No known key found for this signature in database
GPG key ID: 3E00485503A1D8BA
5 changed files with 220 additions and 9 deletions

View file

@ -109,6 +109,12 @@ impl Game {
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 {
scene.tick(&mut self.state, ctx)?;
}

View file

@ -347,7 +347,205 @@ impl NPC {
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 {
0 => {
self.action_num = 1;
@ -467,7 +665,7 @@ impl NPC {
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 {
0 => {
self.action_num = 1;

View file

@ -238,6 +238,8 @@ impl GameEntity<(&mut Player, &HashMap<u16, RefCell<NPC>>, &mut Stage)> for NPC
86 => self.tick_n086_missile_pickup(state),
87 => self.tick_n087_heart_pickup(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),
97 => self.tick_n097_fan_up(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 {
if let Some(npc_cell) = self.npcs.get(&npc_id) {
return npc_cell.borrow().cond.alive();
/// Returns true if at least one NPC with specified type is alive.
pub fn is_alive_by_type(&self, npc_type: u16) -> bool {
for npc_cell in self.npcs.values() {
let npc = npc_cell.borrow();
if npc.cond.alive() && npc.npc_type == npc_type {
return true;
}
}
false
}
/// Returns true if at least one NPC with specified event is alive.
pub fn is_alive_by_event(&self, event_num: u16) -> bool {
for npc_cell in self.npcs.values() {
let npc = npc_cell.borrow();

View file

@ -586,7 +586,7 @@ impl GameScene {
if !self.player.cond.hidden() && self.inventory.get_current_weapon().is_some() {
self.draw_light(fix9_scale(self.player.x - self.frame.x, 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() {

View file

@ -185,7 +185,7 @@ pub enum OpCode {
NCJ,
/// <ECJxxxx:yyyy, Jumps to event xxxx if NPC tagged with event yyyy is alive
ECJ,
/// <FLJxxxx:yyyy, Jumps to event xxxx if flag yyyy is set
/// <FLJxxxx:yyyy, Jumps to event yyyy if flag xxxx is set
FLJ,
/// <FLJxxxx:yyyy, Jumps to event xxxx if player has item yyyy
ITJ,
@ -852,10 +852,10 @@ impl TextScriptVM {
}
}
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;
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);
} else {
exec_state = TextScriptExecutionState::Running(event, cursor.position() as u32);