Merge branch 'master' into feature/controller
This commit is contained in:
commit
e7b3475f6a
|
@ -11,16 +11,18 @@ layout (std140) uniform Globals {
|
|||
|
||||
layout (std140) uniform WaterShaderParams {
|
||||
vec2 u_Resolution;
|
||||
vec2 u_FramePos;
|
||||
float u_Tick;
|
||||
};
|
||||
|
||||
void main() {
|
||||
vec2 wave = v_Uv;
|
||||
wave.x += sin(v_Uv.x * 40.0 + u_Tick / 20.0) * (sin(u_Tick / 10.0) * 0.01);
|
||||
wave.y -= cos(v_Uv.y * 20.0 + u_Tick / 5.0) * (sin(u_Tick / 20.0) * 0.01);
|
||||
wave.x += sin((-u_FramePos.y / u_Resolution.y + v_Uv.x * 16.0) + u_Tick / 20.0) * 2.0 / u_Resolution.x;
|
||||
wave.y -= cos((-u_FramePos.x / u_Resolution.x + v_Uv.y * 16.0) + u_Tick / 5.0) * 2.0 / u_Resolution.y;
|
||||
float off = 0.4 / u_Resolution.y;
|
||||
vec4 color = texture(t_Texture, wave);
|
||||
color.r = texture(t_Texture, wave + off).r;
|
||||
color.b = texture(t_Texture, wave - off).b;
|
||||
Target0 = vec4(0.7, 0.8, 1.2, 1.0) * color * v_Color;
|
||||
|
||||
Target0 = (vec4(0.4, 0.6, 0.8, 1.0) * 0.3) + (color * v_Color * 0.7);
|
||||
}
|
||||
|
|
|
@ -605,8 +605,8 @@ impl PhysicalEntity for Bullet {
|
|||
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = x * 16 * 0x200;
|
||||
npc.y = y * 16 * 0x200;
|
||||
npc.x = (x * 16 + 8) * 0x200;sta
|
||||
npc.y = (y * 16 + 8) * 0x200;
|
||||
|
||||
for _ in 0..4 {
|
||||
npc.vel_x = state.game_rng.range(-0x200..0x200) as isize;
|
||||
|
|
|
@ -24,15 +24,24 @@ bitfield! {
|
|||
pub struct Flag(u32);
|
||||
impl Debug;
|
||||
|
||||
pub hit_left_wall, set_hit_left_wall: 0; // 0x01
|
||||
pub hit_top_wall, set_hit_top_wall: 1; // 0x02
|
||||
pub hit_right_wall, set_hit_right_wall: 2; // 0x04
|
||||
pub hit_bottom_wall, set_hit_bottom_wall: 3; // 0x08
|
||||
pub hit_right_slope, set_hit_right_slope: 4; // 0x10
|
||||
pub hit_left_slope, set_hit_left_slope: 5; // 0x20
|
||||
pub snack_destroy, set_snack_destroy: 6; // 0x40
|
||||
pub flag_x80, set_flag_x80: 7; // 0x80
|
||||
pub in_water, set_in_water: 8; // 0x100
|
||||
/// Set if left wall was hit. (corresponds to flag & 0x01)
|
||||
pub hit_left_wall, set_hit_left_wall: 0;
|
||||
/// Set if top wall was hit. (corresponds to flag & 0x02)
|
||||
pub hit_top_wall, set_hit_top_wall: 1;
|
||||
/// Set if right wall was hit. (corresponds to flag & 0x04)
|
||||
pub hit_right_wall, set_hit_right_wall: 2;
|
||||
/// Set if bottom wall was hit. (corresponds to flag & 0x08)
|
||||
pub hit_bottom_wall, set_hit_bottom_wall: 3;
|
||||
/// Set if entity stays on right slope. (corresponds to flag & 0x10)
|
||||
pub hit_right_slope, set_hit_right_slope: 4;
|
||||
/// Set if entity stays on left slope. (corresponds to flag & 0x20)
|
||||
pub hit_left_slope, set_hit_left_slope: 5;
|
||||
/// Unknown purpose (corresponds to flag & 0x40)
|
||||
pub flag_x40, set_flag_x40: 6;
|
||||
/// Unknown purpose (corresponds to flag & 0x80)
|
||||
pub flag_x80, set_flag_x80: 7;
|
||||
/// Set if entity is in water. (corresponds to flag & 0x100)
|
||||
pub in_water, set_in_water: 8;
|
||||
pub weapon_hit_block, set_weapon_hit_block: 9; // 0x200
|
||||
pub hit_by_spike, set_hit_by_spike: 10; // 0x400
|
||||
pub water_splash_facing_right, set_water_splash_facing_right: 11; // 0x800
|
||||
|
|
|
@ -35,10 +35,10 @@ impl NPC {
|
|||
for _ in 0..3 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -104,7 +104,7 @@ impl NPC {
|
|||
npc.y = self.y + 4 * 0x200; // 4.0fix9
|
||||
|
||||
let mut angle = ((self.y + 4 * 0x200 - player.y) as f64 / (self.x - player.y) as f64).atan();
|
||||
angle += state.game_rng.range(-16..16) as f64 * std::f64::consts::FRAC_PI_8;
|
||||
angle += self.rng.range(-16..16) as f64 * std::f64::consts::FRAC_PI_8;
|
||||
npc.vel_x = (angle.cos() * 512.0) as isize; // 1.0fix9
|
||||
npc.vel_y = (angle.sin() * 512.0) as isize;
|
||||
|
||||
|
@ -221,7 +221,7 @@ impl NPC {
|
|||
self.anim_num = 0;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..100) == 0 {
|
||||
if self.rng.range(0..100) == 0 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -294,10 +294,10 @@ impl NPC {
|
|||
for _ in 0..3 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -516,14 +516,14 @@ impl NPC {
|
|||
_ => {}
|
||||
}
|
||||
|
||||
if self.target_x != 0 && state.game_rng.range(0..10) == 0 {
|
||||
if self.target_x != 0 && self.rng.range(0..10) == 0 {
|
||||
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -557,10 +557,10 @@ impl NPC {
|
|||
for _ in 0..16 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -595,7 +595,7 @@ impl NPC {
|
|||
}
|
||||
}
|
||||
3 => {
|
||||
if state.game_rng.range(0..100) == 0 {
|
||||
if self.rng.range(0..100) == 0 {
|
||||
self.action_num = 4;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -681,7 +681,7 @@ impl NPC {
|
|||
self.action_counter = 0;
|
||||
|
||||
let angle = f64::atan2((self.y - player.y) as f64, (self.x - player.x) as f64)
|
||||
+ state.game_rng.range(-16..16) as f64 * CDEG_RAD;
|
||||
+ self.rng.range(-16..16) as f64 * CDEG_RAD;
|
||||
|
||||
let mut npc = NPCMap::create_npc(11, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
|
@ -765,17 +765,17 @@ impl NPC {
|
|||
for _ in 0..8 {
|
||||
npc_smoke.cond.set_alive(true);
|
||||
npc_smoke.direction = Direction::Left;
|
||||
npc_smoke.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc_smoke.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc_smoke.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc_smoke.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc_smoke.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc_smoke.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc_smoke.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc_smoke.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
npc_proj.cond.set_alive(true);
|
||||
npc_proj.direction = Direction::Left;
|
||||
npc_proj.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc_proj.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc_proj.vel_x = state.game_rng.range(-0x400..0x400) as isize;
|
||||
npc_proj.vel_y = state.game_rng.range(-0x400..0) as isize;
|
||||
npc_proj.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc_proj.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc_proj.vel_x = self.rng.range(-0x400..0x400) as isize;
|
||||
npc_proj.vel_y = self.rng.range(-0x400..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc_smoke);
|
||||
state.new_npcs.push(npc_proj);
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
use ggez::GameResult;
|
||||
|
||||
use crate::npc::NPC;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::common::Direction;
|
||||
|
||||
impl NPC {
|
||||
pub(crate) fn tick_n113_professor_booster(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.anim_num = 0;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 8 {
|
||||
self.action_num = 1;
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
3 | 4 => {
|
||||
if self.action_num == 3 {
|
||||
self.action_num = 4;
|
||||
self.anim_num = 2;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
self.animate(5, 2, 5);
|
||||
|
||||
self.x += self.direction.vector_x() * 0x200;
|
||||
}
|
||||
5 => {
|
||||
self.anim_num = 6;
|
||||
}
|
||||
30 | 31 => {
|
||||
if self.action_num == 30 {
|
||||
self.action_num = 31;
|
||||
self.anim_num = 0;
|
||||
self.anim_counter = 0;
|
||||
self.hit_bounds.bottom = 16 * 0x200;
|
||||
self.x -= 16 * 0x200;
|
||||
self.y += 8 * 0x200;
|
||||
}
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter == 64 {
|
||||
self.action_num = 32;
|
||||
self.action_counter = 0;
|
||||
}
|
||||
}
|
||||
32 => {
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 20 {
|
||||
self.action_num = 33;
|
||||
self.anim_num = 1;
|
||||
self.hit_bounds.bottom = 8 * 0x200;
|
||||
}
|
||||
}
|
||||
33 => {
|
||||
if self.flags.hit_bottom_wall() {
|
||||
self.action_num = 34;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.vel_y += 0x40;
|
||||
self.y += self.vel_y;
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 7 };
|
||||
|
||||
self.anim_rect = state.constants.npc.n113_professor_booster[self.anim_num as usize + dir_offset];
|
||||
|
||||
if self.action_num == 31 {
|
||||
self.anim_rect.bottom = self.action_counter / 4 + self.anim_rect.top;
|
||||
if self.action_counter / 2 % 2 != 0 {
|
||||
self.anim_rect.left += 1;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -77,10 +77,10 @@ impl BossNPC {
|
|||
for _ in 0..8 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -164,8 +164,8 @@ impl BossNPC {
|
|||
|
||||
let mut npc = NPCMap::create_npc(110, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = state.game_rng.range(4..16) as isize * 16 * 0x200;
|
||||
npc.y = state.game_rng.range(0..4) as isize * 16 * 0x200;
|
||||
npc.x = self.parts[0].rng.range(4..16) as isize * 16 * 0x200;
|
||||
npc.y = self.parts[0].rng.range(0..4) as isize * 16 * 0x200;
|
||||
npc.direction = Direction::FacingPlayer;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
|
@ -175,10 +175,10 @@ impl BossNPC {
|
|||
for _ in 0..4 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ impl BossNPC {
|
|||
let py = self.parts[0].y - 8 * 0x200 - player.y;
|
||||
|
||||
let deg = f64::atan2(py as f64, px as f64)
|
||||
+ state.game_rng.range(-16..16) as f64 * CDEG_RAD;
|
||||
+ self.parts[0].rng.range(-16..16) as f64 * CDEG_RAD;
|
||||
// todo rand
|
||||
|
||||
let mut npc = NPCMap::create_npc(108, &state.npc_table);
|
||||
|
@ -322,8 +322,8 @@ impl BossNPC {
|
|||
let mut npc = NPCMap::create_npc(104, &state.npc_table);
|
||||
for _ in 0..2 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = state.game_rng.range(4..16) as isize * 16 * 0x200;
|
||||
npc.y = state.game_rng.range(0..4) as isize * 16 * 0x200;
|
||||
npc.x = self.parts[0].rng.range(4..16) as isize * 16 * 0x200;
|
||||
npc.y = self.parts[0].rng.range(0..4) as isize * 16 * 0x200;
|
||||
npc.direction = Direction::FacingPlayer;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
|
@ -332,8 +332,8 @@ impl BossNPC {
|
|||
let mut npc = NPCMap::create_npc(110, &state.npc_table);
|
||||
for _ in 0..6 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = state.game_rng.range(4..16) as isize * 16 * 0x200;
|
||||
npc.y = state.game_rng.range(0..4) as isize * 16 * 0x200;
|
||||
npc.x = self.parts[0].rng.range(4..16) as isize * 16 * 0x200;
|
||||
npc.y = self.parts[0].rng.range(0..4) as isize * 16 * 0x200;
|
||||
npc.direction = Direction::FacingPlayer;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
|
@ -342,10 +342,10 @@ impl BossNPC {
|
|||
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||
for _ in 0..8 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].hit_bounds.bottom as isize;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.direction = Direction::Left;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
|
@ -380,10 +380,10 @@ impl BossNPC {
|
|||
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||
for _ in 0..8 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.direction = Direction::Left;
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -393,10 +393,10 @@ impl BossNPC {
|
|||
if (self.parts[0].action_counter % 5) == 0 {
|
||||
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.direction = Direction::Left;
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -435,10 +435,10 @@ impl BossNPC {
|
|||
if (self.parts[0].action_counter % 9) == 0 {
|
||||
let mut npc = NPCMap::create_npc(4, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.parts[0].x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.parts[0].x + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.parts[0].y + self.parts[0].rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.parts[0].rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.parts[0].rng.range(-0x600..0) as isize;
|
||||
npc.direction = Direction::Left;
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ impl NPC {
|
|||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
|
|
@ -96,7 +96,7 @@ impl NPC {
|
|||
self.vel_x = 0;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -235,14 +235,14 @@ impl NPC {
|
|||
self.anim_rect = state.constants.npc.n062_kazuma_computer[self.anim_num as usize];
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..80) == 1 {
|
||||
if self.rng.range(0..80) == 1 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
self.anim_rect = state.constants.npc.n062_kazuma_computer[self.anim_num as usize];
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 3;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 2;
|
||||
|
@ -282,7 +282,7 @@ impl NPC {
|
|||
self.vel_x = 0;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -331,12 +331,42 @@ impl NPC {
|
|||
self.x += self.vel_x;
|
||||
self.y += self.vel_y;
|
||||
|
||||
if self.direction == Direction::Left {
|
||||
self.anim_rect = state.constants.npc.n074_jack[self.anim_num as usize];
|
||||
} else {
|
||||
self.anim_rect = state.constants.npc.n074_jack[self.anim_num as usize + 6];
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 6 };
|
||||
|
||||
self.anim_rect = state.constants.npc.n074_jack[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n151_blue_robot_standing(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0{
|
||||
self.action_num = 1;
|
||||
self.anim_num = 0;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
if self.rng.range(0..100) == 0 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
}
|
||||
}
|
||||
2 => {
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 16 {
|
||||
self.action_num = 1;
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
_ =>{}
|
||||
}
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 2 };
|
||||
|
||||
self.anim_rect = state.constants.npc.n151_blue_robot_standing[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -619,7 +619,7 @@ impl NPC {
|
|||
self.action_counter2 += 1;
|
||||
if (self.action_counter2 % 8) == 0 && abs(self.x - player.x) < 160 * 0x200 {
|
||||
let angle = ((self.y - player.y) as f64 / (self.x - player.x) as f64).atan()
|
||||
+ (state.game_rng.range(-6..6) as u8) as f64 * CDEG_RAD;
|
||||
+ (self.rng.range(-6..6) as u8) as f64 * CDEG_RAD;
|
||||
|
||||
let mut npc = NPCMap::create_npc(84, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
|
|
|
@ -189,7 +189,7 @@ impl NPC {
|
|||
self.target_y = self.y;
|
||||
|
||||
self.action_num = 1;
|
||||
self.action_counter = state.game_rng.range(0..50) as u16;
|
||||
self.action_counter = self.rng.range(0..50) as u16;
|
||||
}
|
||||
|
||||
self.action_counter += 1;
|
||||
|
|
|
@ -98,14 +98,7 @@ impl NPC {
|
|||
state.sound_manager.play_sfx(110);
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 0 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 5 {
|
||||
self.anim_num = 3;
|
||||
}
|
||||
}
|
||||
self.animate(0, 3, 5);
|
||||
}
|
||||
}
|
||||
5 => {
|
||||
|
@ -148,11 +141,11 @@ impl NPC {
|
|||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
let angle = state.game_rng.range(0..0xff);
|
||||
let angle = self.rng.range(0..0xff);
|
||||
self.vel_x = ((angle as f64 * 1.40625).cos() * 512.0) as isize;
|
||||
self.target_x = self.x + ((angle as f64 * 1.40625 + std::f64::consts::FRAC_2_PI).cos() * 8.0 * 512.0) as isize;
|
||||
|
||||
let angle = state.game_rng.range(0..0xff);
|
||||
let angle = self.rng.range(0..0xff);
|
||||
self.vel_y = ((angle as f64 * 1.40625).sin() * 512.0) as isize;
|
||||
self.target_y = self.y + ((angle as f64 * 1.40625 + std::f64::consts::FRAC_2_PI).sin() * 8.0 * 512.0) as isize;
|
||||
|
||||
|
@ -203,14 +196,7 @@ impl NPC {
|
|||
if self.action_num == 3 {
|
||||
self.anim_num = 3;
|
||||
} else {
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 1 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 2 {
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
self.animate(1, 0, 2);
|
||||
}
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 4 };
|
||||
|
@ -312,14 +298,7 @@ impl NPC {
|
|||
self.vel_y = -0x200;
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 0 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 5 {
|
||||
self.anim_num = 3;
|
||||
}
|
||||
}
|
||||
self.animate(0, 3, 5);
|
||||
}
|
||||
}
|
||||
5 => {
|
||||
|
@ -364,7 +343,7 @@ impl NPC {
|
|||
self.action_num = 1;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -413,15 +392,7 @@ impl NPC {
|
|||
}
|
||||
}
|
||||
5 => {
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 1 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 4 {
|
||||
self.anim_num = 2;
|
||||
}
|
||||
}
|
||||
|
||||
self.animate(1, 2, 4);
|
||||
self.direction = if player.x < self.x { Direction::Left } else { Direction::Right };
|
||||
|
||||
self.vel_x += (player.x - self.x).signum() * 0x10;
|
||||
|
@ -620,7 +591,7 @@ impl NPC {
|
|||
0 | 1 | 10 => {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.action_counter = state.game_rng.range(0..50) as u16;
|
||||
self.action_counter = self.rng.range(0..50) as u16;
|
||||
self.target_x = self.x;
|
||||
self.target_y = self.y;
|
||||
|
||||
|
@ -721,15 +692,7 @@ impl NPC {
|
|||
}
|
||||
|
||||
pub(crate) fn tick_n101_malco_screen(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 3 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 2 {
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
self.animate(3, 0, 2);
|
||||
self.anim_rect = state.constants.npc.n101_malco_screen[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
|
@ -741,15 +704,7 @@ impl NPC {
|
|||
self.y += 8 * 0x200;
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 0 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 3 {
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
|
||||
self.animate(0, 0, 3);
|
||||
self.anim_rect = state.constants.npc.n102_malco_computer_wave[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
|
@ -762,14 +717,7 @@ impl NPC {
|
|||
|
||||
self.vel_x += self.direction.vector_x() * 0x20;
|
||||
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 0 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 2 {
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
self.animate(0, 0, 2);
|
||||
|
||||
self.x += self.vel_x;
|
||||
|
||||
|
@ -800,7 +748,7 @@ impl NPC {
|
|||
self.vel_y = 0;
|
||||
|
||||
if self.tsc_direction == 4 {
|
||||
self.direction = if (state.game_rng.next() & 1) == 0 { Direction::Left } else { Direction::Right };
|
||||
self.direction = if (self.rng.next_u16() & 1) == 0 { Direction::Left } else { Direction::Right };
|
||||
self.tsc_direction = self.direction as u16;
|
||||
self.action_num = 3;
|
||||
self.anim_num = 2;
|
||||
|
@ -811,7 +759,7 @@ impl NPC {
|
|||
|
||||
self.action_counter += 1;
|
||||
|
||||
if state.game_rng.range(0..50) == 1 {
|
||||
if self.rng.range(0..50) == 1 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 0;
|
||||
|
@ -821,7 +769,7 @@ impl NPC {
|
|||
1 => {
|
||||
self.action_counter += 1;
|
||||
|
||||
if state.game_rng.range(0..50) == 1 {
|
||||
if self.rng.range(0..50) == 1 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 0;
|
||||
|
@ -830,15 +778,7 @@ impl NPC {
|
|||
}
|
||||
2 => {
|
||||
self.action_counter += 1;
|
||||
self.anim_counter += 1;
|
||||
|
||||
if self.anim_counter > 2 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 1 {
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
self.animate(2, 0, 1);
|
||||
|
||||
if self.action_counter > 18 {
|
||||
self.action_num = 1;
|
||||
|
@ -884,7 +824,7 @@ impl NPC {
|
|||
&& ((self.shock > 0)
|
||||
|| (abs(self.x - player.x) < 160 * 0x200
|
||||
&& abs(self.y - player.y) < 64 * 0x200)
|
||||
&& state.game_rng.range(0..50) == 2) {
|
||||
&& self.rng.range(0..50) == 2) {
|
||||
self.direction = if self.x >= player.x {
|
||||
Direction::Left
|
||||
} else {
|
||||
|
@ -931,8 +871,8 @@ impl NPC {
|
|||
npc.cond.set_alive(true);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -996,8 +936,8 @@ impl NPC {
|
|||
npc.cond.set_alive(true);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -1036,8 +976,8 @@ impl NPC {
|
|||
npc.cond.set_alive(true);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -1059,14 +999,7 @@ impl NPC {
|
|||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 4 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 9 {
|
||||
self.anim_num = 6;
|
||||
}
|
||||
}
|
||||
self.animate(4, 6, 9);
|
||||
}
|
||||
110 => {
|
||||
self.cond.set_drs_destroyed(true);
|
||||
|
@ -1094,7 +1027,7 @@ impl NPC {
|
|||
self.action_counter = 0;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -1125,8 +1058,8 @@ impl NPC {
|
|||
npc.direction = Direction::Left;
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -1159,7 +1092,7 @@ impl NPC {
|
|||
self.vel_y = 0;
|
||||
|
||||
if self.tsc_direction == 4 {
|
||||
self.direction = if (state.game_rng.next() & 1) == 0 { Direction::Left } else { Direction::Right };
|
||||
self.direction = if (self.rng.next_u16() & 1) == 0 { Direction::Left } else { Direction::Right };
|
||||
self.tsc_direction = self.direction as u16;
|
||||
self.action_num = 3;
|
||||
self.anim_num = 2;
|
||||
|
@ -1170,7 +1103,7 @@ impl NPC {
|
|||
|
||||
self.action_counter += 1;
|
||||
|
||||
if state.game_rng.range(0..50) == 1 {
|
||||
if self.rng.range(0..50) == 1 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 0;
|
||||
|
@ -1180,7 +1113,7 @@ impl NPC {
|
|||
1 => {
|
||||
self.action_counter += 1;
|
||||
|
||||
if state.game_rng.range(0..50) == 1 {
|
||||
if self.rng.range(0..50) == 1 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 0;
|
||||
|
@ -1189,15 +1122,8 @@ impl NPC {
|
|||
}
|
||||
2 => {
|
||||
self.action_counter += 1;
|
||||
self.anim_counter += 1;
|
||||
|
||||
if self.anim_counter > 2 {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 1 {
|
||||
self.anim_num = 0;
|
||||
}
|
||||
}
|
||||
self.animate(2, 0, 1);
|
||||
|
||||
if self.action_counter > 18 {
|
||||
self.action_num = 1;
|
||||
|
@ -1243,7 +1169,7 @@ impl NPC {
|
|||
&& ((self.shock > 0)
|
||||
|| (abs(self.x - player.x) < 160 * 0x200
|
||||
&& abs(self.y - player.y) < 64 * 0x200)
|
||||
&& state.game_rng.range(0..50) == 2) {
|
||||
&& self.rng.range(0..50) == 2) {
|
||||
self.direction = if self.x >= player.x {
|
||||
Direction::Left
|
||||
} else {
|
||||
|
@ -1297,8 +1223,8 @@ impl NPC {
|
|||
self.target_y = self.y;
|
||||
}
|
||||
|
||||
self.x = self.target_x + state.game_rng.range(-1..1) as isize * 0x200;
|
||||
self.y = self.target_y + state.game_rng.range(-1..1) as isize * 0x200;
|
||||
self.x = self.target_x + self.rng.range(-1..1) as isize * 0x200;
|
||||
self.y = self.target_y + self.rng.range(-1..1) as isize * 0x200;
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 30 {
|
||||
|
@ -1318,7 +1244,7 @@ impl NPC {
|
|||
|
||||
self.vel_x += 0x20;
|
||||
self.x += self.vel_x;
|
||||
self.y = self.target_y + state.game_rng.range(-1..1) as isize * 0x200;
|
||||
self.y = self.target_y + self.rng.range(-1..1) as isize * 0x200;
|
||||
self.action_counter += 1;
|
||||
|
||||
if self.action_counter > 10 {
|
||||
|
|
|
@ -203,10 +203,10 @@ impl NPC {
|
|||
for _ in 0..4 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -233,7 +233,7 @@ impl NPC {
|
|||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter > 100 && self.action_counter % 6 == 1 {
|
||||
let deg = (if self.direction == Direction::Left { 0x88 } else { 0xf8 } + state.game_rng.range(-16..16)) as f64 * CDEG_RAD;
|
||||
let deg = (if self.direction == Direction::Left { 0x88 } else { 0xf8 } + self.rng.range(-16..16)) as f64 * CDEG_RAD;
|
||||
let vel_x = (deg.cos() * 1536.0) as isize;
|
||||
let vel_y = (deg.sin() * 1536.0) as isize;
|
||||
|
||||
|
@ -289,10 +289,10 @@ impl NPC {
|
|||
for _ in 0..8 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -309,10 +309,10 @@ impl NPC {
|
|||
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -349,10 +349,10 @@ impl NPC {
|
|||
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ impl NPC {
|
|||
self.anim_rect = state.constants.npc.n069_pignon[self.anim_num as usize + dir_offset];
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..100) == 1 {
|
||||
if self.rng.range(0..100) == 1 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -32,7 +32,7 @@ impl NPC {
|
|||
}
|
||||
|
||||
|
||||
if state.game_rng.range(0..150) == 1 {
|
||||
if self.rng.range(0..150) == 1 {
|
||||
self.action_num = 3;
|
||||
self.action_counter = 50;
|
||||
self.anim_num = 0;
|
||||
|
@ -185,7 +185,7 @@ impl NPC {
|
|||
|
||||
match self.action_num {
|
||||
1 => {
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -219,7 +219,7 @@ impl NPC {
|
|||
}
|
||||
2 => {
|
||||
self.anim_num = 0;
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 3;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -374,7 +374,7 @@ impl NPC {
|
|||
self.anim_rect = state.constants.npc.n081_giant_pignon[self.anim_num as usize + dir_offset];
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..100) == 1 {
|
||||
if self.rng.range(0..100) == 1 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -383,7 +383,7 @@ impl NPC {
|
|||
}
|
||||
|
||||
|
||||
if state.game_rng.range(0..150) == 1 {
|
||||
if self.rng.range(0..150) == 1 {
|
||||
self.action_num = 3;
|
||||
self.action_counter = 50;
|
||||
self.anim_num = 0;
|
||||
|
|
148
src/npc/misc.rs
148
src/npc/misc.rs
|
@ -48,13 +48,13 @@ impl NPC {
|
|||
pub(crate) fn tick_n004_smoke(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.anim_num = state.game_rng.range(0..4) as u16;
|
||||
self.anim_counter = state.game_rng.range(0..3) as u16;
|
||||
self.anim_num = self.rng.range(0..4) as u16;
|
||||
self.anim_counter = self.rng.range(0..3) as u16;
|
||||
|
||||
if self.direction == Direction::Left || self.direction == Direction::Up {
|
||||
let angle = state.game_rng.range(0..31415) as f32 / 5000.0;
|
||||
self.vel_x = (angle.cos() * state.game_rng.range(0x200..0x5ff) as f32) as isize;
|
||||
self.vel_y = (angle.sin() * state.game_rng.range(0x200..0x5ff) as f32) as isize;
|
||||
let angle = self.rng.range(0..31415) as f32 / 5000.0;
|
||||
self.vel_x = (angle.cos() * self.rng.range(0x200..0x5ff) as f32) as isize;
|
||||
self.vel_y = (angle.sin() * self.rng.range(0x200..0x5ff) as f32) as isize;
|
||||
}
|
||||
} else {
|
||||
self.vel_x = (self.vel_x * 20) / 21;
|
||||
|
@ -147,10 +147,10 @@ impl NPC {
|
|||
for _ in 0..4 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ impl NPC {
|
|||
}
|
||||
|
||||
self.anim_num = 0;
|
||||
if state.game_rng.range(0..30) == 0 {
|
||||
if self.rng.range(0..30) == 0 {
|
||||
self.action_num = 2;
|
||||
}
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ impl NPC {
|
|||
|
||||
match self.action_num {
|
||||
1 => {
|
||||
let rand = state.game_rng.range(0..30);
|
||||
let rand = self.rng.range(0..30);
|
||||
|
||||
if rand < 10 {
|
||||
self.action_num = 2;
|
||||
|
@ -238,7 +238,7 @@ impl NPC {
|
|||
self.action_num = 4;
|
||||
}
|
||||
|
||||
self.action_counter = state.game_rng.range(0x10..0x40) as u16;
|
||||
self.action_counter = self.rng.range(0x10..0x40) as u16;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
2 => {
|
||||
|
@ -308,8 +308,8 @@ impl NPC {
|
|||
npc.direction = Direction::Left;
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ impl NPC {
|
|||
self.action_num = 1;
|
||||
self.anim_counter = 0;
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 8;
|
||||
self.anim_rect = state.constants.npc.n030_hermit_gunsmith[1];
|
||||
|
@ -572,13 +572,13 @@ impl NPC {
|
|||
droplet.direction = Direction::Left;
|
||||
droplet.x = self.x;
|
||||
droplet.y = self.y;
|
||||
droplet.vel_x = 2 * state.game_rng.range(-0x200..0x200) as isize;
|
||||
droplet.vel_y = 3 * state.game_rng.range(-0x200..0x80) as isize;
|
||||
droplet.vel_x = 2 * self.rng.range(-0x200..0x200) as isize;
|
||||
droplet.vel_y = 3 * self.rng.range(-0x200..0x80) as isize;
|
||||
state.new_npcs.push(droplet);
|
||||
|
||||
if self.action_counter % 2 == 0 {
|
||||
droplet.vel_x = 2 * state.game_rng.range(-0x200..0x200) as isize;
|
||||
droplet.vel_y = 3 * state.game_rng.range(-0x200..0x80) as isize;
|
||||
droplet.vel_x = 2 * self.rng.range(-0x200..0x200) as isize;
|
||||
droplet.vel_y = 3 * self.rng.range(-0x200..0x80) as isize;
|
||||
state.new_npcs.push(droplet);
|
||||
}
|
||||
}
|
||||
|
@ -590,7 +590,7 @@ impl NPC {
|
|||
pub(crate) fn tick_n073_water_droplet(&mut self, state: &mut SharedGameState, stage: &Stage) -> GameResult {
|
||||
self.vel_y += 0x20;
|
||||
|
||||
self.anim_rect = state.constants.npc.n073_water_droplet[state.game_rng.range(0..4) as usize];
|
||||
self.anim_rect = state.constants.npc.n073_water_droplet[self.rng.range(0..4) as usize];
|
||||
|
||||
if self.vel_y > 0x5ff {
|
||||
self.vel_y = 0x5ff;
|
||||
|
@ -694,12 +694,12 @@ impl NPC {
|
|||
{
|
||||
let i = self.get_closest_player_idx_mut(&players);
|
||||
if abs(players[i].x - self.x) < 480 * 0x200 && abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& state.game_rng.range(0..5) == 1 {
|
||||
&& self.rng.range(0..5) == 1 {
|
||||
let mut particle = NPCMap::create_npc(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Left;
|
||||
particle.x = self.x;
|
||||
particle.y = self.y + (state.game_rng.range(-8..8) * 0x200) as isize;
|
||||
particle.y = self.y + (self.rng.range(-8..8) * 0x200) as isize;
|
||||
state.new_npcs.push(particle);
|
||||
}
|
||||
}
|
||||
|
@ -747,11 +747,11 @@ impl NPC {
|
|||
{
|
||||
let i = self.get_closest_player_idx_mut(&players);
|
||||
if abs(players[i].x - self.x) < 480 * 0x200 && abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& state.game_rng.range(0..5) == 1 {
|
||||
&& self.rng.range(0..5) == 1 {
|
||||
let mut particle = NPCMap::create_npc(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Up;
|
||||
particle.x = self.x + (state.game_rng.range(-8..8) * 0x200) as isize;
|
||||
particle.x = self.x + (self.rng.range(-8..8) * 0x200) as isize;
|
||||
particle.y = self.y;
|
||||
state.new_npcs.push(particle);
|
||||
}
|
||||
|
@ -799,12 +799,12 @@ impl NPC {
|
|||
{
|
||||
let i = self.get_closest_player_idx_mut(&players);
|
||||
if abs(players[i].x - self.x) < 480 * 0x200 && abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& state.game_rng.range(0..5) == 1 {
|
||||
&& self.rng.range(0..5) == 1 {
|
||||
let mut particle = NPCMap::create_npc(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Right;
|
||||
particle.x = self.x;
|
||||
particle.y = self.y + (state.game_rng.range(-8..8) * 0x200) as isize;
|
||||
particle.y = self.y + (self.rng.range(-8..8) * 0x200) as isize;
|
||||
state.new_npcs.push(particle);
|
||||
}
|
||||
}
|
||||
|
@ -848,11 +848,11 @@ impl NPC {
|
|||
{
|
||||
let i = self.get_closest_player_idx_mut(&players);
|
||||
if abs(players[i].x - self.x) < 480 * 0x200 && abs(players[i].y - self.y) < 240 * 0x200
|
||||
&& state.game_rng.range(0..5) == 1 {
|
||||
&& self.rng.range(0..5) == 1 {
|
||||
let mut particle = NPCMap::create_npc(199, &state.npc_table);
|
||||
particle.cond.set_alive(true);
|
||||
particle.direction = Direction::Bottom;
|
||||
particle.x = self.x + (state.game_rng.range(-8..8) * 0x200) as isize;
|
||||
particle.x = self.x + (self.rng.range(-8..8) * 0x200) as isize;
|
||||
particle.y = self.y;
|
||||
state.new_npcs.push(particle);
|
||||
}
|
||||
|
@ -944,8 +944,8 @@ impl NPC {
|
|||
npc.cond.set_alive(true);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -976,6 +976,41 @@ impl NPC {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n125_hidden_item(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.life < 990 {
|
||||
self.cond.set_drs_destroyed(true);
|
||||
match self.direction {
|
||||
/// hidden heart
|
||||
Direction::Left => {
|
||||
let mut npc = NPCMap::create_npc(87, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.direction = Direction::Right;
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
/// hidden missile
|
||||
Direction::Right => {
|
||||
let mut npc = NPCMap::create_npc(86, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.direction = Direction::Right;
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
match self.direction {
|
||||
Direction::Left => self.anim_rect = state.constants.npc.n125_hidden_item[0],
|
||||
Direction::Right => self.anim_rect = state.constants.npc.n125_hidden_item[1],
|
||||
_ => {}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n149_horizontal_moving_block(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
match self.action_num {
|
||||
0 => {
|
||||
|
@ -1014,10 +1049,10 @@ impl NPC {
|
|||
for _ in 0..3 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -1063,10 +1098,10 @@ impl NPC {
|
|||
for _ in 0..3 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -1135,10 +1170,10 @@ impl NPC {
|
|||
for _ in 0..3 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -1184,10 +1219,10 @@ impl NPC {
|
|||
for _ in 0..3 {
|
||||
npc.cond.set_alive(true);
|
||||
npc.direction = Direction::Left;
|
||||
npc.x = self.x + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + state.game_rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.x = self.x + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.y = self.y + self.rng.range(-12..12) as isize * 0x200;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -1232,9 +1267,9 @@ impl NPC {
|
|||
pub(crate) fn tick_n199_wind_particles(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.anim_num = state.game_rng.range(0..2) as u16;
|
||||
self.vel_x = self.direction.vector_x() * (state.game_rng.range(4..8) * 0x200 / 2) as isize;
|
||||
self.vel_y = self.direction.vector_y() * (state.game_rng.range(4..8) * 0x200 / 2) as isize;
|
||||
self.anim_num = self.rng.range(0..2) as u16;
|
||||
self.vel_x = self.direction.vector_x() * (self.rng.range(4..8) * 0x200 / 2) as isize;
|
||||
self.vel_y = self.direction.vector_y() * (self.rng.range(4..8) * 0x200 / 2) as isize;
|
||||
}
|
||||
|
||||
self.anim_counter += 1;
|
||||
|
@ -1265,4 +1300,19 @@ impl NPC {
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n234_red_flowers_picked(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.y += 16 * 0x200;
|
||||
|
||||
match self.direction {
|
||||
Direction::Left => self.anim_rect = state.constants.npc.n234_red_flowers_picked[0],
|
||||
Direction::Right => self.anim_rect = state.constants.npc.n234_red_flowers_picked[1],
|
||||
_ => self.anim_rect = state.constants.npc.n234_red_flowers_picked[1],
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,7 +104,7 @@ impl NPC {
|
|||
state.sound_manager.play_sfx(29);
|
||||
}
|
||||
|
||||
self.x = self.target_x + state.game_rng.range(-1..1) as isize * 0x200;
|
||||
self.x = self.target_x + self.rng.range(-1..1) as isize * 0x200;
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.action_counter >= 32 {
|
||||
|
@ -240,7 +240,7 @@ impl NPC {
|
|||
self.anim_num = 2;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 3;
|
||||
|
@ -354,7 +354,7 @@ impl NPC {
|
|||
npc.x = self.x + 8 * 0x200;
|
||||
npc.y = self.y - 8 * 0x200;
|
||||
npc.vel_x = 0x600;
|
||||
npc.vel_y = state.game_rng.range(-0x200..0) as isize;
|
||||
npc.vel_y = self.rng.range(-0x200..0) as isize;
|
||||
npc.cond.set_alive(true);
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
|
@ -376,7 +376,7 @@ impl NPC {
|
|||
self.anim_counter -= 1;
|
||||
self.anim_num = 1;
|
||||
} else {
|
||||
if state.game_rng.range(0..100) == 1 {
|
||||
if self.rng.range(0..100) == 1 {
|
||||
self.anim_counter = 30;
|
||||
}
|
||||
|
||||
|
@ -391,7 +391,7 @@ impl NPC {
|
|||
self.action_counter -= 1;
|
||||
self.anim_num = 3;
|
||||
} else {
|
||||
if state.game_rng.range(0..100) == 1 {
|
||||
if self.rng.range(0..100) == 1 {
|
||||
self.anim_counter = 30;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ use std::cell::RefCell;
|
|||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::io;
|
||||
use std::io::Cursor;
|
||||
use std::ops::DerefMut;
|
||||
|
||||
use bitvec::vec::BitVec;
|
||||
use byteorder::{LE, ReadBytesExt};
|
||||
|
@ -20,11 +19,13 @@ use crate::map::NPCData;
|
|||
use crate::npc::boss::BossNPC;
|
||||
use crate::physics::PhysicalEntity;
|
||||
use crate::player::Player;
|
||||
use crate::rng::Xoroshiro32PlusPlus;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
use crate::stage::Stage;
|
||||
use crate::str;
|
||||
|
||||
pub mod balrog;
|
||||
pub mod booster;
|
||||
pub mod boss;
|
||||
pub mod chaco;
|
||||
pub mod characters;
|
||||
|
@ -112,9 +113,10 @@ pub struct NPC {
|
|||
pub action_counter2: u16,
|
||||
pub anim_counter: u16,
|
||||
pub anim_rect: Rect<u16>,
|
||||
pub rng: Xoroshiro32PlusPlus,
|
||||
}
|
||||
|
||||
static PARTICLE_NPCS: [u16; 11] = [1, 4, 11, 73, 84, 86, 87, 108, 129, 199, 355];
|
||||
static PARTICLE_NPCS: [u16; 12] = [1, 4, 11, 45, 73, 84, 86, 87, 108, 129, 199, 355];
|
||||
|
||||
impl NPC {
|
||||
pub fn get_start_index(&self) -> u16 {
|
||||
|
@ -160,6 +162,7 @@ impl NPC {
|
|||
action_counter2: 0,
|
||||
anim_counter: 0,
|
||||
anim_rect: Rect { left: 0, top: 0, right: 0, bottom: 0 },
|
||||
rng: Xoroshiro32PlusPlus::new(0),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -211,7 +214,10 @@ impl GameEntity<([&mut Player; 2], &BTreeMap<u16, RefCell<NPC>>, &mut Stage)> fo
|
|||
41 => self.tick_n041_busted_door(state),
|
||||
42 => self.tick_n042_sue(state, players, map),
|
||||
43 => self.tick_n043_chalkboard(state),
|
||||
44 => self.tick_n044_polish(state),
|
||||
45 => self.tick_n045_baby(state),
|
||||
46 => self.tick_n046_hv_trigger(players),
|
||||
47 => self.tick_n047_sandcroc(state, players),
|
||||
52 => self.tick_n052_sitting_blue_robot(state),
|
||||
55 => self.tick_n055_kazuma(state),
|
||||
58 => self.tick_n058_basu(state, players),
|
||||
|
@ -268,10 +274,14 @@ impl GameEntity<([&mut Player; 2], &BTreeMap<u16, RefCell<NPC>>, &mut Stage)> fo
|
|||
110 => self.tick_n110_puchi(state, players),
|
||||
111 => self.tick_n111_quote_teleport_out(state, players),
|
||||
112 => self.tick_n112_quote_teleport_in(state, players),
|
||||
113 => self.tick_n113_professor_booster(state),
|
||||
114 => self.tick_n114_press(state, players),
|
||||
124 => self.tick_n124_sunstone(state),
|
||||
125 => self.tick_n125_hidden_item(state),
|
||||
129 => self.tick_n129_fireball_snake_trail(state),
|
||||
149 => self.tick_n149_horizontal_moving_block(state, players),
|
||||
150 => self.tick_n150_quote(state, players),
|
||||
151 => self.tick_n151_blue_robot_standing(state),
|
||||
154 => self.tick_n154_gaudi_dead(state),
|
||||
157 => self.tick_n157_vertical_moving_block(state, players),
|
||||
192 => self.tick_n192_scooter(state),
|
||||
|
@ -279,6 +289,7 @@ impl GameEntity<([&mut Player; 2], &BTreeMap<u16, RefCell<NPC>>, &mut Stage)> fo
|
|||
194 => self.tick_n194_broken_blue_robot(state),
|
||||
199 => self.tick_n199_wind_particles(state),
|
||||
211 => self.tick_n211_small_spikes(state),
|
||||
234 => self.tick_n234_red_flowers_picked(state),
|
||||
298 => self.tick_n298_intro_doctor(state),
|
||||
299 => self.tick_n299_intro_balrog_misery(state),
|
||||
300 => self.tick_n300_intro_demon_crown(state),
|
||||
|
@ -472,6 +483,11 @@ impl NPCMap {
|
|||
action_counter2: 0,
|
||||
anim_counter: 0,
|
||||
anim_rect: Rect::new(0, 0, 0, 0),
|
||||
rng: Xoroshiro32PlusPlus::new((data.id as u32)
|
||||
.wrapping_sub(data.npc_type as u32)
|
||||
.wrapping_add(data.flag_num as u32)
|
||||
.wrapping_mul(214013)
|
||||
.wrapping_add(2531011) >> 5),
|
||||
};
|
||||
|
||||
let cell = RefCell::new(npc);
|
||||
|
@ -524,6 +540,7 @@ impl NPCMap {
|
|||
action_counter2: 0,
|
||||
anim_counter: 0,
|
||||
anim_rect: Rect::new(0, 0, 0, 0),
|
||||
rng: Xoroshiro32PlusPlus::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -700,6 +717,12 @@ impl NPCMap {
|
|||
};
|
||||
}
|
||||
|
||||
npc.rng = Xoroshiro32PlusPlus::new((npc.id as u32)
|
||||
.wrapping_sub(npc.npc_type as u32)
|
||||
.wrapping_add(npc.flag_num as u32)
|
||||
.wrapping_mul(214013)
|
||||
.wrapping_add(2531011) >> 5);
|
||||
|
||||
self.ids.insert(id);
|
||||
self.npcs.insert(id, RefCell::new(*npc));
|
||||
}
|
||||
|
|
|
@ -4,6 +4,18 @@ use crate::npc::NPC;
|
|||
use crate::player::Player;
|
||||
|
||||
impl NPC {
|
||||
pub fn animate(&mut self, ticks_between_frames: u16, start_frame: u16, end_frame: u16) {
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > ticks_between_frames {
|
||||
self.anim_counter = 0;
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > end_frame {
|
||||
self.anim_num = start_frame;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns index of player that's closest to the current NPC.
|
||||
pub fn get_closest_player_idx_mut<'a>(&self, players: &[&'a mut Player; 2]) -> usize {
|
||||
let mut max_dist = f64::MAX;
|
||||
let mut player_idx = 0;
|
||||
|
@ -26,25 +38,10 @@ impl NPC {
|
|||
player_idx
|
||||
}
|
||||
|
||||
/// Returns a reference to closest player.
|
||||
pub fn get_closest_player_mut<'a>(&self, players: [&'a mut Player; 2]) -> &'a mut Player {
|
||||
let mut max_dist = f64::MAX;
|
||||
let mut player_idx = 0;
|
||||
let idx = self.get_closest_player_idx_mut(&players);
|
||||
|
||||
for (idx, player) in players.iter().enumerate() {
|
||||
if !player.cond.alive() || player.cond.hidden() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let dist_x = abs(self.x - player.x) as f64;
|
||||
let dist_y = abs(self.y - player.y) as f64;
|
||||
let dist = (dist_x * dist_x + dist_y * dist_y).sqrt();
|
||||
|
||||
if dist < max_dist {
|
||||
max_dist = dist;
|
||||
player_idx = idx;
|
||||
}
|
||||
}
|
||||
|
||||
players[player_idx]
|
||||
players[idx]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@ impl NPC {
|
|||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
|
||||
self.vel_x = state.game_rng.range(-0x80..0x80) as isize;
|
||||
self.vel_y = state.game_rng.range(-0x7f..0x100) as isize;
|
||||
self.vel_x = self.rng.range(-0x80..0x80) as isize;
|
||||
self.vel_y = self.rng.range(-0x7f..0x100) as isize;
|
||||
}
|
||||
|
||||
self.vel_x -= 0x8;
|
||||
|
@ -40,12 +40,12 @@ impl NPC {
|
|||
} else {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.anim_num = state.game_rng.range(0..4) as u16;
|
||||
self.anim_num = self.rng.range(0..4) as u16;
|
||||
|
||||
self.vel_x = state.game_rng.range(-0x200..0x200) as isize;
|
||||
self.vel_y = state.game_rng.range(-0x400..0) as isize;
|
||||
self.vel_x = self.rng.range(-0x200..0x200) as isize;
|
||||
self.vel_y = self.rng.range(-0x400..0) as isize;
|
||||
|
||||
self.direction = if state.game_rng.range(0..1) != 0 {
|
||||
self.direction = if self.rng.range(0..1) != 0 {
|
||||
Direction::Left
|
||||
} else {
|
||||
Direction::Right
|
||||
|
@ -161,8 +161,8 @@ impl NPC {
|
|||
if state.control_flags.wind() {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.vel_x = state.game_rng.range(0x7f..0x100) as isize;
|
||||
self.vel_y = state.game_rng.range(-0x20..0x20) as isize;
|
||||
self.vel_x = self.rng.range(0x7f..0x100) as isize;
|
||||
self.vel_y = self.rng.range(-0x20..0x20) as isize;
|
||||
}
|
||||
|
||||
self.vel_x -= 0x08;
|
||||
|
@ -229,8 +229,8 @@ impl NPC {
|
|||
if state.control_flags.wind() {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.vel_x = state.game_rng.range(0x7f..0x100) as isize;
|
||||
self.vel_y = state.game_rng.range(-0x20..0x20) as isize;
|
||||
self.vel_x = self.rng.range(0x7f..0x100) as isize;
|
||||
self.vel_y = self.rng.range(-0x20..0x20) as isize;
|
||||
}
|
||||
|
||||
self.vel_x -= 0x08;
|
||||
|
|
|
@ -164,8 +164,8 @@ impl NPC {
|
|||
npc.direction = Direction::Left;
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
npc.vel_x = state.game_rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = state.game_rng.range(-0x600..0) as isize;
|
||||
npc.vel_x = self.rng.range(-0x155..0x155) as isize;
|
||||
npc.vel_y = self.rng.range(-0x600..0) as isize;
|
||||
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
|
@ -213,8 +213,8 @@ impl NPC {
|
|||
}
|
||||
|
||||
self.target_y += 0x100;
|
||||
self.x = self.target_x + state.game_rng.range(-1..1) as isize * 0x200;
|
||||
self.y = self.target_y + state.game_rng.range(-1..1) as isize * 0x200;
|
||||
self.x = self.target_x + self.rng.range(-1..1) as isize * 0x200;
|
||||
self.y = self.target_y + self.rng.range(-1..1) as isize * 0x200;
|
||||
}
|
||||
70 | 71 => {
|
||||
if self.action_num == 70 {
|
||||
|
|
|
@ -0,0 +1,327 @@
|
|||
use ggez::GameResult;
|
||||
use num_traits::{abs, clamp};
|
||||
|
||||
use crate::common::Direction;
|
||||
use crate::npc::{NPC, NPCMap};
|
||||
use crate::player::Player;
|
||||
use crate::shared_game_state::SharedGameState;
|
||||
|
||||
impl NPC {
|
||||
pub(crate) fn tick_n044_polish(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
self.anim_num = 0;
|
||||
self.action_num = match self.direction {
|
||||
Direction::Left => 8,
|
||||
Direction::Right => 2,
|
||||
_ => 8,
|
||||
};
|
||||
}
|
||||
2 => {
|
||||
self.vel_y += 0x20;
|
||||
if self.vel_y > 0 && self.flags.hit_bottom_wall() {
|
||||
self.vel_y = -0x100;
|
||||
self.vel_x += 0x100;
|
||||
}
|
||||
|
||||
if self.flags.hit_right_wall() {
|
||||
self.action_num = 3;
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
self.vel_x += 0x20;
|
||||
if self.vel_x > 0 && self.flags.hit_right_wall() {
|
||||
self.vel_x = -0x100;
|
||||
self.vel_y -= 0x100;
|
||||
}
|
||||
|
||||
if self.flags.hit_top_wall() {
|
||||
self.action_num = 4;
|
||||
}
|
||||
}
|
||||
4 => {
|
||||
self.vel_y -= 0x20;
|
||||
if self.vel_y < 0 && self.flags.hit_top_wall() {
|
||||
self.vel_y = 0x100;
|
||||
self.vel_x -= 0x100;
|
||||
}
|
||||
|
||||
if self.flags.hit_left_wall() {
|
||||
self.action_num = 5;
|
||||
}
|
||||
}
|
||||
5 => {
|
||||
self.vel_x -= 0x20;
|
||||
if self.vel_x < 0 && self.flags.hit_left_wall() {
|
||||
self.vel_x = 0x100;
|
||||
self.vel_y += 0x100;
|
||||
}
|
||||
|
||||
if self.flags.hit_bottom_wall() {
|
||||
self.action_num = 2;
|
||||
}
|
||||
}
|
||||
6 => {
|
||||
self.vel_y += 0x20;
|
||||
if self.vel_y > 0 && self.flags.hit_bottom_wall() {
|
||||
self.vel_y = -0x100;
|
||||
self.vel_x -= 0x100;
|
||||
}
|
||||
|
||||
if self.flags.hit_left_wall() {
|
||||
self.action_num = 7;
|
||||
}
|
||||
}
|
||||
7 => {
|
||||
self.vel_x -= 0x20;
|
||||
if self.vel_x < 0 && self.flags.hit_left_wall() {
|
||||
self.vel_x = 0x100;
|
||||
self.vel_y -= 0x100;
|
||||
}
|
||||
|
||||
if self.flags.hit_top_wall() {
|
||||
self.action_num = 8;
|
||||
}
|
||||
}
|
||||
8 => {
|
||||
self.vel_y -= 0x20;
|
||||
if self.vel_y < 0 && self.flags.hit_top_wall() {
|
||||
self.vel_y = 0x100;
|
||||
self.vel_x += 0x100;
|
||||
}
|
||||
|
||||
if self.flags.hit_right_wall() {
|
||||
self.action_num = 9;
|
||||
}
|
||||
}
|
||||
9 => {
|
||||
self.vel_x += 0x20;
|
||||
if self.vel_x > 0 && self.flags.hit_right_wall() {
|
||||
self.vel_x = -0x100;
|
||||
self.vel_y += 0x100;
|
||||
}
|
||||
|
||||
if self.flags.hit_bottom_wall() {
|
||||
self.action_num = 6;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if self.life <= 100 {
|
||||
self.cond.set_drs_destroyed(true);
|
||||
state.sound_manager.play_sfx(25);
|
||||
|
||||
let mut npc = NPCMap::create_npc(45, &state.npc_table);
|
||||
npc.cond.set_alive(true);
|
||||
npc.x = self.x;
|
||||
npc.y = self.y;
|
||||
for _ in 0..9 {
|
||||
state.new_npcs.push(npc);
|
||||
}
|
||||
}
|
||||
|
||||
self.vel_x = clamp(self.vel_x, -0x200, 0x200);
|
||||
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;
|
||||
}
|
||||
|
||||
if self.action_num > 1 && self.action_num <= 9 {
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 2 {
|
||||
self.anim_num = 1;
|
||||
}
|
||||
}
|
||||
|
||||
let dir_offset = if self.direction == Direction::Left { 0 } else { 3 };
|
||||
|
||||
self.anim_rect = state.constants.npc.n044_polish[self.anim_num as usize + dir_offset];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n045_baby(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 2;
|
||||
self.vel_x = if self.rng.next_u16() & 1 != 0 {
|
||||
self.rng.range(-0x200..-0x100) as isize
|
||||
} else {
|
||||
self.rng.range(0x100..0x200) as isize
|
||||
};
|
||||
self.vel_y = if self.rng.next_u16() & 1 != 0 {
|
||||
self.rng.range(-0x200..-0x100) as isize
|
||||
} else {
|
||||
self.rng.range(0x100..0x200) as isize
|
||||
};
|
||||
self.vel_x2 = self.vel_x;
|
||||
self.vel_y2 = self.vel_y;
|
||||
}
|
||||
|
||||
match self.action_num {
|
||||
1 | 2 => {
|
||||
self.anim_num += 1;
|
||||
if self.anim_num > 2 {
|
||||
self.anim_num = 1;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if self.vel_x2 < 0 && self.flags.hit_left_wall() {
|
||||
self.vel_x2 = -self.vel_x2;
|
||||
}
|
||||
|
||||
if self.vel_x2 > 0 && self.flags.hit_right_wall() {
|
||||
self.vel_x2 = -self.vel_x2;
|
||||
}
|
||||
|
||||
if self.vel_y2 < 0 && self.flags.hit_top_wall() {
|
||||
self.vel_y2 = -self.vel_y2;
|
||||
}
|
||||
|
||||
if self.vel_y2 > 0 && self.flags.hit_bottom_wall() {
|
||||
self.vel_y2 = -self.vel_y2;
|
||||
}
|
||||
|
||||
self.vel_x2 = clamp(self.vel_x2, -0x200, 0x200);
|
||||
self.vel_y2 = clamp(self.vel_y2, -0x200, 0x200);
|
||||
|
||||
if self.shock > 0 {
|
||||
self.x += self.vel_x2 / 2;
|
||||
self.y += self.vel_y2 / 2;
|
||||
} else {
|
||||
self.x += self.vel_x2;
|
||||
self.y += self.vel_y2;
|
||||
}
|
||||
|
||||
self.anim_rect = state.constants.npc.n045_baby[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n047_sandcroc(&mut self, state: &mut SharedGameState, players: [&mut Player; 2]) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num == 0 {
|
||||
self.action_num = 1;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 0;
|
||||
self.target_y = self.y;
|
||||
self.npc_flags.set_shootable(false);
|
||||
self.npc_flags.set_ignore_solidity(false);
|
||||
self.npc_flags.set_invulnerable(false);
|
||||
self.npc_flags.set_solid_soft(false);
|
||||
}
|
||||
|
||||
let player = self.get_closest_player_mut(players);
|
||||
if abs(self.x - player.x) < 8 * 0x200 && player.y > self.y && player.y < self.y + 8 * 0x200 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
state.sound_manager.play_sfx(102);
|
||||
}
|
||||
|
||||
self.x += (player.x - self.x).signum() * 2 * 0x200;
|
||||
}
|
||||
2 => {
|
||||
self.anim_counter += 1;
|
||||
if self.anim_counter > 3 {
|
||||
self.anim_num += 1;
|
||||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
match self.anim_num {
|
||||
3 => self.damage = 10,
|
||||
4 => {
|
||||
self.action_num = 3;
|
||||
self.action_counter = 0;
|
||||
self.npc_flags.set_shootable(true);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
3 => {
|
||||
self.damage = 0;
|
||||
self.npc_flags.set_solid_soft(true);
|
||||
|
||||
self.action_counter += 1;
|
||||
if self.shock > 0 {
|
||||
self.action_num = 4;
|
||||
self.action_counter = 0;
|
||||
}
|
||||
}
|
||||
4 => {
|
||||
self.npc_flags.set_ignore_solidity(true);
|
||||
self.y += 0x200;
|
||||
self.action_counter += 1;
|
||||
if self.action_counter == 32 {
|
||||
self.action_num = 5;
|
||||
self.action_counter = 0;
|
||||
self.npc_flags.set_solid_soft(false);
|
||||
self.npc_flags.set_shootable(false);
|
||||
}
|
||||
}
|
||||
5 => {
|
||||
if self.action_counter > 99 {
|
||||
self.y = self.target_y;
|
||||
self.action_num = 0;
|
||||
self.anim_num = 0;
|
||||
} else {
|
||||
self.action_counter += 1;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
self.anim_rect = state.constants.npc.n047_sandcroc[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn tick_n124_sunstone(&mut self, state: &mut SharedGameState) -> GameResult {
|
||||
match self.action_num {
|
||||
0 | 1 => {
|
||||
if self.action_num ==0 {
|
||||
self.action_num = 1;
|
||||
self.x += 8 * 0x200;
|
||||
self.y += 8 * 0x200;
|
||||
}
|
||||
|
||||
self.npc_flags.set_ignore_solidity(false);
|
||||
self.anim_num = 0;
|
||||
}
|
||||
10 | 11 => {
|
||||
if self.action_num == 10 {
|
||||
self.action_num = 11;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
||||
self.npc_flags.set_ignore_solidity(true);
|
||||
}
|
||||
|
||||
match self.direction {
|
||||
Direction::Left => self.x -= 0x80,
|
||||
Direction::Up => self.y -= 0x80,
|
||||
Direction::Right => self.x += 0x80,
|
||||
Direction::Bottom => self.y += 0x80,
|
||||
Direction::FacingPlayer => {}
|
||||
}
|
||||
|
||||
state.quake_counter= 20;
|
||||
if self.action_counter % 8 == 0 {
|
||||
state.sound_manager.play_sfx(26);
|
||||
}
|
||||
}
|
||||
_ =>{}
|
||||
}
|
||||
|
||||
self.anim_rect = state.constants.npc.n124_sunstone[self.anim_num as usize];
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@ impl NPC {
|
|||
self.anim_counter = 0;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 0 {
|
||||
if self.rng.range(0..120) == 0 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
|
|
@ -20,7 +20,7 @@ impl NPC {
|
|||
self.vel_x = 0;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
@ -254,13 +254,13 @@ impl NPC {
|
|||
}
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..80) == 1 {
|
||||
if self.rng.range(0..80) == 1 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 3;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 2;
|
||||
|
|
|
@ -17,7 +17,7 @@ impl NPC {
|
|||
self.vel_x = 0;
|
||||
}
|
||||
|
||||
if state.game_rng.range(0..120) == 10 {
|
||||
if self.rng.range(0..120) == 10 {
|
||||
self.action_num = 2;
|
||||
self.action_counter = 0;
|
||||
self.anim_num = 1;
|
||||
|
|
|
@ -318,6 +318,10 @@ impl Player {
|
|||
}
|
||||
|
||||
pub fn tick_npc_collisions(&mut self, id: TargetPlayer, state: &mut SharedGameState, npc_map: &mut NPCMap, inventory: &mut Inventory) {
|
||||
if !self.cond.alive() {
|
||||
return;
|
||||
}
|
||||
|
||||
for npc_cell in npc_map.npcs.values() {
|
||||
let mut npc = npc_cell.borrow_mut();
|
||||
if !npc.cond.alive() { continue; }
|
||||
|
|
50
src/rng.rs
50
src/rng.rs
|
@ -3,16 +3,6 @@ use std::cell::Cell;
|
|||
/// Deterministic XorShift-based random number generator
|
||||
pub struct RNG(Cell<(u64, u64, u64, u64)>);
|
||||
|
||||
#[inline]
|
||||
fn rol64(x: u64, shift: u64) -> u64
|
||||
{
|
||||
if shift == 0 || shift == 64 {
|
||||
x
|
||||
} else {
|
||||
(x << shift) | (x >> (64 - shift))
|
||||
}
|
||||
}
|
||||
|
||||
impl RNG {
|
||||
pub fn new(seed: i32) -> Self {
|
||||
Self(Cell::new((seed as u64,
|
||||
|
@ -24,7 +14,7 @@ impl RNG {
|
|||
|
||||
pub fn next_u64(&self) -> i32 {
|
||||
let mut state = self.0.get();
|
||||
let result = rol64(state.1.wrapping_mul(5), 7).wrapping_mul(9);
|
||||
let result = state.1.wrapping_mul(5).rotate_left(5).wrapping_mul(9);
|
||||
let t = state.1 << 17;
|
||||
|
||||
state.2 ^= state.0;
|
||||
|
@ -33,7 +23,7 @@ impl RNG {
|
|||
state.0 ^= state.3;
|
||||
|
||||
state.2 ^= t;
|
||||
state.3 = rol64(state.3, 45);
|
||||
state.3 = state.3.rotate_left(45);
|
||||
|
||||
self.0.replace(state);
|
||||
result as i32
|
||||
|
@ -61,3 +51,39 @@ impl RNG {
|
|||
range.start.wrapping_add((self.next_u32() >> 2) as i32 % (range.end.wrapping_sub(range.start).wrapping_add(1)))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct Xoroshiro32PlusPlus(u16, u16);
|
||||
|
||||
impl Xoroshiro32PlusPlus {
|
||||
pub fn new(seed: u32) -> Xoroshiro32PlusPlus {
|
||||
Xoroshiro32PlusPlus(
|
||||
(seed & 0xffff) as u16,
|
||||
(seed >> 16 & 0xffff) as u16
|
||||
)
|
||||
}
|
||||
|
||||
pub fn next_u16(&mut self) -> u16 {
|
||||
let mut result = (self.0.wrapping_add(self.1)).rotate_left(9).wrapping_add(self.0);
|
||||
|
||||
self.1 ^= self.0;
|
||||
self.0 = self.0.rotate_left(13) ^ self.1 ^ (self.1 << 5);
|
||||
self.1 = self.1.rotate_left(10);
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn dump_state(&self) -> u32 {
|
||||
(self.0 as u32) | (self.1 as u32) << 16
|
||||
}
|
||||
|
||||
pub fn load_state(&mut self, state: u32) {
|
||||
self.0 = (state & 0xffff) as u16;
|
||||
self.1 = ((state >> 16) & 0xffff) as u16;
|
||||
}
|
||||
|
||||
pub fn range(&mut self, range: std::ops::Range<i32>) -> i32 {
|
||||
let num = ((self.next_u16() as u32) << 16 | self.next_u16() as u32) >> 2;
|
||||
range.start.wrapping_add(num as i32 % (range.end.wrapping_sub(range.start).wrapping_add(1)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -649,8 +649,11 @@ impl GameScene {
|
|||
}
|
||||
|
||||
fn draw_water(&self, state: &mut SharedGameState, ctx: &mut Context) -> GameResult {
|
||||
let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time, state.scale);
|
||||
|
||||
{
|
||||
state.shaders.water_shader_params.resolution = [state.canvas_size.0, state.canvas_size.1];
|
||||
state.shaders.water_shader_params.frame_pos = [frame_x, frame_y];
|
||||
state.shaders.water_shader_params.t = self.tick as f32;
|
||||
let _lock = graphics::use_shader(ctx, &state.shaders.water_shader);
|
||||
state.shaders.water_shader.send(ctx, state.shaders.water_shader_params)?;
|
||||
|
@ -666,8 +669,6 @@ impl GameScene {
|
|||
// cheap, clones a reference underneath
|
||||
let mut tmp_batch = SpriteBatch::new(state.tmp_canvas.image().clone());
|
||||
|
||||
let (frame_x, frame_y) = self.frame.xy_interpolated(state.frame_time, state.scale);
|
||||
|
||||
let tile_start_x = clamp(self.frame.x / 0x200 / 16, 0, self.stage.map.width as isize) as usize;
|
||||
let tile_start_y = clamp(self.frame.y / 0x200 / 16, 0, self.stage.map.height as isize) as usize;
|
||||
let tile_end_x = clamp((self.frame.x / 0x200 + 8 + state.canvas_size.0 as isize) / 16 + 1, 0, self.stage.map.width as isize) as usize;
|
||||
|
|
|
@ -5,6 +5,7 @@ use ggez::{Context, GameResult};
|
|||
gfx_defines! {
|
||||
constant WaterShaderParams {
|
||||
resolution: [f32; 2] = "u_Resolution",
|
||||
frame_pos: [f32; 2] = "u_FramePos",
|
||||
t: f32 = "u_Tick",
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +20,7 @@ impl Shaders {
|
|||
let water_shader_params = WaterShaderParams {
|
||||
t: 0.0,
|
||||
resolution: [0.0, 0.0],
|
||||
frame_pos: [0.0, 0.0],
|
||||
};
|
||||
|
||||
Ok(Shaders {
|
||||
|
|
Loading…
Reference in New Issue