Import blues from be69d5ea
This commit is contained in:
parent
1592f7ef80
commit
2345fb7fe4
2
Makefile
2
Makefile
|
@ -4,7 +4,7 @@ SDL_LIBS := `sdl2-config --libs`
|
||||||
|
|
||||||
BB := decode.c game.c level.c objects.c resource.c screen.c sound.c staticres.c tiles.c unpack.c
|
BB := decode.c game.c level.c objects.c resource.c screen.c sound.c staticres.c tiles.c unpack.c
|
||||||
JA := game.c level.c resource.c screen.c sound.c staticres.c unpack.c
|
JA := game.c level.c resource.c screen.c sound.c staticres.c unpack.c
|
||||||
P2 := game.c level.c monsters.c resource.c screen.c sound.c staticres.c unpack.c
|
P2 := bosses.c game.c level.c monsters.c resource.c screen.c sound.c staticres.c unpack.c
|
||||||
|
|
||||||
BB_SRCS := $(foreach f,$(BB),bb/$f)
|
BB_SRCS := $(foreach f,$(BB),bb/$f)
|
||||||
JA_SRCS := $(foreach f,$(JA),ja/$f)
|
JA_SRCS := $(foreach f,$(JA),ja/$f)
|
||||||
|
|
|
@ -5,7 +5,7 @@ This is a rewrite of the [Blues Brothers](https://www.mobygames.com/game/blues-b
|
||||||
|
|
||||||
![Screenshot1](blues1.png) ![Screenshot2](bbja2.png)
|
![Screenshot1](blues1.png) ![Screenshot2](bbja2.png)
|
||||||
|
|
||||||
There is also some support for [Prehistorik 2](https://www.mobygames.com/game/prehistorik-2).
|
There is also support for [Prehistorik 2](https://www.mobygames.com/game/prehistorik-2).
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,846 @@
|
||||||
|
|
||||||
|
/* bosses logic : gorilla, tree, minotaur */
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "resource.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
static void level_update_objects_boss_energy(int count) {
|
||||||
|
if (count > 8) {
|
||||||
|
count = 8;
|
||||||
|
}
|
||||||
|
if (count != 0) {
|
||||||
|
play_music(13);
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
struct object_t *obj = &g_vars.objects_tbl[108 + i];
|
||||||
|
obj->spr_num = 0x135;
|
||||||
|
obj->x_pos = 8 + i * 5;
|
||||||
|
obj->y_pos = 170;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = count; i < 8; ++i) {
|
||||||
|
g_vars.objects_tbl[108 + i].spr_num = 0xFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_objects_boss_hit_player() {
|
||||||
|
--g_vars.bonus_energy_counter;
|
||||||
|
if (g_vars.bonus_energy_counter < 0) {
|
||||||
|
g_vars.bonus_energy_counter = 5;
|
||||||
|
if ((g_options.cheats & CHEATS_UNLIMITED_ENERGY) == 0) {
|
||||||
|
--g_vars.player_energy;
|
||||||
|
if (g_vars.player_energy < 0) {
|
||||||
|
level_player_die();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_vars.current_bonus.x_pos = g_vars.objects_tbl[1].x_pos;
|
||||||
|
g_vars.current_bonus.y_pos = g_vars.objects_tbl[1].y_pos - 48;
|
||||||
|
g_vars.current_bonus.spr_num = 0x2046; /* bones */
|
||||||
|
const int x_vel = (g_vars.bonus_energy_counter & 1) != 0 ? -48 : 48;
|
||||||
|
const int y_vel = -128;
|
||||||
|
level_add_object23_bonus(x_vel, y_vel, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_gorilla_collide_proj(struct object_t *obj_player, struct object_t *obj) {
|
||||||
|
if (obj->spr_num == 0xFFFF || (obj->spr_num & 0x2000) == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!level_objects_collide(obj_player, obj)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const int count = 4 - g_res.level.boss_speed;
|
||||||
|
if (g_vars.boss.change_counter < count) {
|
||||||
|
g_vars.boss.change_counter = 0;
|
||||||
|
} else {
|
||||||
|
g_vars.boss.change_counter -= count;
|
||||||
|
}
|
||||||
|
if (g_options.cheats & CHEATS_NO_HIT) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
level_update_objects_boss_hit_player();
|
||||||
|
obj_player->hit_counter = 44;
|
||||||
|
g_vars.player_anim_0x40_flag = 0;
|
||||||
|
obj_player->data.p.y_velocity = -128;
|
||||||
|
obj_player->x_friction = 3;
|
||||||
|
obj_player->x_velocity = (g_vars.objects_tbl[1].x_pos >= g_res.level.boss_x_pos) ? 128 : -128;
|
||||||
|
g_vars.player_gravity_flag = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_gorilla_hit_player() {
|
||||||
|
if (g_vars.restart_level_flag != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
level_update_boss_gorilla_collide_proj(&g_vars.objects_tbl[1], g_vars.boss.obj2);
|
||||||
|
level_update_boss_gorilla_collide_proj(&g_vars.objects_tbl[1], g_vars.boss.obj1);
|
||||||
|
if (level_objects_collide(&g_vars.objects_tbl[1], g_vars.boss.obj3)) {
|
||||||
|
if (g_vars.player_jump_monster_flag != 0) {
|
||||||
|
g_vars.objects_tbl[1].data.p.y_velocity = (g_vars.input.key_up != 0) ? -128 : -64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_gorilla_tick() {
|
||||||
|
if (g_vars.boss.change_counter < UCHAR_MAX) {
|
||||||
|
++g_vars.boss.change_counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint16_t level_update_boss_gorilla_find_pos(uint16_t num1, uint16_t num2) {
|
||||||
|
const uint16_t *p = boss_gorilla_spr_tbl;
|
||||||
|
const uint16_t *end = &boss_gorilla_spr_tbl[138];
|
||||||
|
while (p + 3 <= end) {
|
||||||
|
if (p[0] == num1 && p[1] == num2) {
|
||||||
|
return p[2]; /* dy,dx packed as a uint16_t */
|
||||||
|
}
|
||||||
|
p += 3;
|
||||||
|
}
|
||||||
|
print_warning("boss_gorilla spr range (%d,%d) not found", num1, num2);
|
||||||
|
return 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_gorilla_init_objects(const uint16_t *p) {
|
||||||
|
g_vars.boss.parts[0].spr_num = *p++;
|
||||||
|
g_vars.boss.parts[1].spr_num = *p++;
|
||||||
|
uint16_t d;
|
||||||
|
int8_t dx, dy;
|
||||||
|
|
||||||
|
d = level_update_boss_gorilla_find_pos(g_vars.boss.parts[0].spr_num, g_vars.boss.parts[1].spr_num);
|
||||||
|
dx = d & 255;
|
||||||
|
if (g_vars.boss.hdir) {
|
||||||
|
dx = -dx;
|
||||||
|
}
|
||||||
|
g_vars.boss.parts[1].x_pos = dx + g_vars.boss.parts[0].x_pos;
|
||||||
|
dy = d >> 8;
|
||||||
|
g_vars.boss.parts[1].y_pos = dy + g_vars.boss.parts[0].y_pos;
|
||||||
|
for (int i = 2; i <= 4; ++i) {
|
||||||
|
g_vars.boss.parts[i].spr_num = *p++;
|
||||||
|
d = level_update_boss_gorilla_find_pos(g_vars.boss.parts[1].spr_num, g_vars.boss.parts[i].spr_num);
|
||||||
|
dx = d & 255;
|
||||||
|
if (g_vars.boss.hdir) {
|
||||||
|
dx = -dx;
|
||||||
|
}
|
||||||
|
g_vars.boss.parts[i].x_pos = dx + g_vars.boss.parts[1].x_pos;
|
||||||
|
dy = d >> 8;
|
||||||
|
g_vars.boss.parts[i].y_pos = dy + g_vars.boss.parts[1].y_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_vars.boss.anim_num & 0x40) {
|
||||||
|
g_vars.boss.parts[1].y_pos += 2;
|
||||||
|
++g_vars.boss.parts[2].y_pos;
|
||||||
|
++g_vars.boss.parts[4].y_pos;
|
||||||
|
++g_vars.boss.parts[3].y_pos;
|
||||||
|
}
|
||||||
|
if (g_vars.boss.hdir) {
|
||||||
|
g_vars.boss.parts[0].spr_num |= 0x8000;
|
||||||
|
g_vars.boss.parts[1].spr_num |= 0x8000;
|
||||||
|
g_vars.boss.parts[2].spr_num |= 0x8000;
|
||||||
|
g_vars.boss.parts[3].spr_num |= 0x8000;
|
||||||
|
g_vars.boss.parts[4].spr_num |= 0x8000;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
struct object_t *obj = &g_vars.objects_tbl[103 + i];
|
||||||
|
const uint16_t addr = *p++;
|
||||||
|
if (addr == 0xA609) {
|
||||||
|
g_vars.boss.obj1 = obj;
|
||||||
|
}
|
||||||
|
if (addr == 0xA60F) {
|
||||||
|
g_vars.boss.obj2 = obj;
|
||||||
|
}
|
||||||
|
if (addr == 0xA603) {
|
||||||
|
g_vars.boss.obj3 = obj;
|
||||||
|
}
|
||||||
|
assert(addr == 0xA5F7 || addr == 0xA5FD || addr == 0xA603 || addr == 0xA609 || addr == 0xA60F);
|
||||||
|
const int num = (addr - 0xA5F7) / 6;
|
||||||
|
obj->x_pos = g_vars.boss.parts[num].x_pos;
|
||||||
|
obj->y_pos = g_vars.boss.parts[num].y_pos;
|
||||||
|
obj->spr_num = g_vars.boss.parts[num].spr_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool level_update_boss_gorilla_collides_obj3(struct object_t *obj) {
|
||||||
|
if (obj->spr_num == 0xFFFF) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const int spr_num = g_vars.boss.obj1->spr_num & 0x1FFF;
|
||||||
|
if ((spr_num == 0x196 || spr_num == 0x195) && level_objects_collide(obj, g_vars.boss.obj1)) {
|
||||||
|
obj->spr_num = 0xFFFF;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return level_objects_collide(obj, g_vars.boss.obj3);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_gorilla_helper2() {
|
||||||
|
for (int i = 0; i < 6; ++i) {
|
||||||
|
if (i == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
struct object_t *obj = &g_vars.objects_tbl[i];
|
||||||
|
if (!level_update_boss_gorilla_collides_obj3(obj)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (abs(g_vars.level_draw_counter - g_vars.boss.draw_counter) <= 22) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
g_vars.boss.draw_counter = g_vars.level_draw_counter;
|
||||||
|
for (int j = 103; j <= 107; ++j) {
|
||||||
|
g_vars.objects_tbl[j].spr_num |= 0x4000;
|
||||||
|
}
|
||||||
|
g_vars.player_flying_flag = 0;
|
||||||
|
level_update_boss_gorilla_tick();
|
||||||
|
g_res.level.boss_energy -= g_vars.player_club_power;
|
||||||
|
if (g_res.level.boss_energy < 0) {
|
||||||
|
g_res.level.boss_state = 6;
|
||||||
|
g_vars.boss.y_velocity = -240;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (g_vars.player_club_power > 20) {
|
||||||
|
g_vars.boss.x_velocity = (g_res.level.boss_x_pos >= g_vars.objects_tbl[1].x_pos) ? 48 : -48;
|
||||||
|
g_vars.boss.y_velocity = (g_vars.boss.y_velocity > 0) ? -128 : -64;
|
||||||
|
g_res.level.boss_state = 5;
|
||||||
|
}
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
obj->spr_num = 0xFFFF;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_gorilla() {
|
||||||
|
if (g_vars.objects_tbl[103].spr_num == 0xFFFF || g_res.level.boss_state == 6 || (g_vars.objects_tbl[103].spr_num & 0x2000) == 0) {
|
||||||
|
level_update_objects_boss_energy(0);
|
||||||
|
} else {
|
||||||
|
level_update_objects_boss_energy(g_res.level.boss_energy >> 3);
|
||||||
|
}
|
||||||
|
const int x = (g_vars.boss.x_velocity >> 4) + g_res.level.boss_x_pos;
|
||||||
|
if (x >= 0) {
|
||||||
|
if (g_res.level.boss_xmin <= x && g_res.level.boss_xmax >= x) {
|
||||||
|
g_res.level.boss_x_pos = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_res.level.boss_y_pos += (g_vars.boss.y_velocity >> 4);
|
||||||
|
if (g_vars.boss.y_velocity >= 0) {
|
||||||
|
const uint16_t pos = ((g_res.level.boss_y_pos >> 4) << 8) | (g_res.level.boss_x_pos >> 4);
|
||||||
|
const uint8_t tile_num = level_get_tile(pos);
|
||||||
|
if (g_res.level.tile_attributes1[tile_num] != 0) {
|
||||||
|
g_res.level.boss_y_pos &= ~15;
|
||||||
|
if (g_vars.boss.y_velocity != 0) {
|
||||||
|
g_vars.shake_screen_counter = 7;
|
||||||
|
}
|
||||||
|
g_vars.boss.y_velocity = 0;
|
||||||
|
g_vars.boss.x_velocity = 0;
|
||||||
|
} else {
|
||||||
|
if (g_vars.boss.y_velocity < 224) {
|
||||||
|
g_vars.boss.y_velocity += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (g_vars.boss.y_velocity < 224) {
|
||||||
|
g_vars.boss.y_velocity += 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_vars.boss.hdir = (g_res.level.boss_x_pos < g_vars.objects_tbl[1].x_pos);
|
||||||
|
g_vars.boss.x_dist = abs(g_vars.objects_tbl[1].x_pos - g_res.level.boss_x_pos);
|
||||||
|
if (g_vars.boss.x_dist > 400) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (abs(g_vars.objects_tbl[1].y_pos - g_res.level.boss_y_pos) > 250) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (g_res.level.boss_state == 0) { /* waiting player to be near */
|
||||||
|
if (g_vars.boss.x_dist >= 250) {
|
||||||
|
g_vars.boss.change_counter = 0;
|
||||||
|
static const uint8_t data_st0[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xF4
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st0;
|
||||||
|
} else {
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
g_res.level.boss_state = 1;
|
||||||
|
}
|
||||||
|
} else if (g_res.level.boss_state == 1) {
|
||||||
|
if (g_vars.boss.x_dist >= 250) {
|
||||||
|
g_res.level.boss_state = 0;
|
||||||
|
} else {
|
||||||
|
++g_vars.boss.state_counter;
|
||||||
|
if (g_res.level.boss_energy < 60) {
|
||||||
|
g_res.level.boss_state = 2;
|
||||||
|
} else {
|
||||||
|
static const uint8_t data_st1[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0xFA
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st1;
|
||||||
|
if (g_vars.boss.state_counter >= 110) {
|
||||||
|
g_res.level.boss_state = 2;
|
||||||
|
level_update_boss_gorilla_tick();
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
} else if (g_vars.player_anim_0x40_flag != 0 && (g_vars.level_draw_counter & 7) == 0) {
|
||||||
|
level_update_boss_gorilla_tick();
|
||||||
|
} else if (g_vars.boss.change_counter >= 10) {
|
||||||
|
g_res.level.boss_state = 3;
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
} else if (g_vars.boss.change_counter > 3) {
|
||||||
|
g_res.level.boss_state = 2;
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (g_res.level.boss_state == 2) {
|
||||||
|
++g_vars.boss.state_counter;
|
||||||
|
if (g_vars.boss.state_counter != 44) {
|
||||||
|
if (g_vars.boss.state_counter > 44) {
|
||||||
|
if (g_vars.boss.y_velocity > 0) {
|
||||||
|
static const uint8_t data_st2a[] = {
|
||||||
|
0x04, 0xFF
|
||||||
|
};
|
||||||
|
static const uint8_t data_st2b[] = {
|
||||||
|
0x07, 0xFF
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = (g_res.level.boss_energy >= 100) ? data_st2a : data_st2b;
|
||||||
|
}
|
||||||
|
if (g_vars.boss.x_dist <= 80) {
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
g_res.level.boss_state = 3;
|
||||||
|
g_vars.boss.change_counter = 11;
|
||||||
|
} else if (g_vars.boss.state_counter == 88) {
|
||||||
|
static const uint8_t data_st2[] = {
|
||||||
|
0x03, 0xFF
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st2;
|
||||||
|
int dx = g_res.level.boss_x_pos - g_vars.objects_tbl[1].x_pos;
|
||||||
|
int x_vel = 48;
|
||||||
|
int y_vel = abs(dx);
|
||||||
|
if (y_vel > g_res.level.boss_speed * 80) {
|
||||||
|
y_vel = -96;
|
||||||
|
} else {
|
||||||
|
y_vel = (y_vel / 14) << 4;
|
||||||
|
x_vel = y_vel >> 1;
|
||||||
|
y_vel = -y_vel;
|
||||||
|
}
|
||||||
|
g_vars.boss.y_velocity = y_vel;
|
||||||
|
if (dx >= 0) {
|
||||||
|
x_vel = -x_vel;
|
||||||
|
}
|
||||||
|
g_vars.boss.x_velocity = x_vel;
|
||||||
|
} else if (g_vars.boss.state_counter > 88) {
|
||||||
|
if (g_vars.boss.y_velocity == 0) {
|
||||||
|
g_vars.boss.change_counter = 3;
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
g_res.level.boss_state = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
level_update_boss_gorilla_hit_player();
|
||||||
|
if (g_vars.boss.x_dist < 75) {
|
||||||
|
g_res.level.boss_state = 3;
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
} else {
|
||||||
|
static const uint8_t data_st2[] = {
|
||||||
|
0x10, 0x50, 0x10, 0x11, 0x51, 0x11, 0x10, 0x50, 0x10, 0x11,
|
||||||
|
0x51, 0x11, 0x10, 0x50, 0x10, 0x11, 0x51, 0x11, 0x00, 0x00,
|
||||||
|
0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40,
|
||||||
|
0x00, 0x00, 0x40, 0x40, 0xDE
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
level_update_boss_gorilla_hit_player();
|
||||||
|
g_vars.boss.y_velocity = -224;
|
||||||
|
if (g_res.level.boss_energy < 40 && g_vars.boss.x_dist < 80) {
|
||||||
|
g_res.level.boss_state = 4;
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
}
|
||||||
|
static const uint8_t data_st2[] = {
|
||||||
|
0x03, 0xFF
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st2;
|
||||||
|
}
|
||||||
|
} else if (g_res.level.boss_state == 3) { /* attack player */
|
||||||
|
level_update_boss_gorilla_hit_player();
|
||||||
|
const int counter = (abs(g_res.level.boss_energy - 50) > 25) ? 66 : 154;
|
||||||
|
if (g_vars.boss.state_counter > counter) {
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
g_res.level.boss_state = 2;
|
||||||
|
} else {
|
||||||
|
if (g_vars.boss.y_velocity == 0) {
|
||||||
|
if (g_vars.boss.x_dist < 100) {
|
||||||
|
if (g_vars.boss.x_dist <= 25) {
|
||||||
|
static const uint8_t data_st3[] = {
|
||||||
|
0x0D, 0x0D, 0x0E, 0x0E, 0xFC
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st3;
|
||||||
|
} else if (g_vars.boss.x_dist <= 35) {
|
||||||
|
g_res.level.boss_state = 4;
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
} else {
|
||||||
|
if (g_vars.boss.change_counter == 0) {
|
||||||
|
g_res.level.boss_state = 7;
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
}
|
||||||
|
static const uint8_t data_st3[] = {
|
||||||
|
0x0D, 0x0D, 0x0C, 0x0C, 0xFC
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st3;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_vars.boss.y_velocity = -81;
|
||||||
|
g_vars.boss.x_velocity = (g_vars.objects_tbl[1].x_pos > g_res.level.boss_x_pos) ? 80 : -80;
|
||||||
|
}
|
||||||
|
} else if (g_vars.boss.y_velocity < 0) {
|
||||||
|
static const uint8_t data_st3[] = {
|
||||||
|
0x03, 0xFF
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st3;
|
||||||
|
} else {
|
||||||
|
static const uint8_t data_st3[] = {
|
||||||
|
0x0D, 0x0D, 0x0D, 0x0E, 0x0E, 0x0E, 0xFA
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (g_res.level.boss_state == 4) {
|
||||||
|
level_update_boss_gorilla_hit_player();
|
||||||
|
++g_vars.boss.state_counter;
|
||||||
|
if (g_vars.boss.state_counter > 66) {
|
||||||
|
g_res.level.boss_state = 3;
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
} else {
|
||||||
|
static const uint8_t data_st4[] = {
|
||||||
|
0x12, 0x12, 0x52, 0x12, 0x0E, 0x0E, 0x4E, 0x0E, 0xF8
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st4;
|
||||||
|
if (g_vars.boss.y_velocity == 0) {
|
||||||
|
g_vars.shake_screen_counter = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (g_res.level.boss_state == 5) { /* hit by player */
|
||||||
|
++g_vars.boss.state_counter;
|
||||||
|
if (g_vars.boss.state_counter > 19) {
|
||||||
|
g_vars.boss.state_counter = 0;
|
||||||
|
g_res.level.boss_state = 1;
|
||||||
|
} else {
|
||||||
|
static const uint8_t data_st5[] = {
|
||||||
|
0x05, 0xFF
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st5;
|
||||||
|
}
|
||||||
|
} else if (g_res.level.boss_state == 6) { /* defeated */
|
||||||
|
static const uint8_t data_st6[] = {
|
||||||
|
0x05, 0x05, 0x0F, 0x0F, 0xFC
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st6;
|
||||||
|
if (g_vars.boss.y_velocity >= 0) {
|
||||||
|
g_res.level.boss_state = 0xFF;
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
g_vars.objects_tbl[103 + i].spr_num = 0xFFFF;
|
||||||
|
}
|
||||||
|
g_vars.current_bonus.x_pos = g_vars.objects_tbl[103].x_pos;
|
||||||
|
g_vars.current_bonus.y_pos = g_vars.objects_tbl[103].y_pos;
|
||||||
|
level_add_bonuses_4x();
|
||||||
|
g_vars.current_bonus.x_pos += 32;
|
||||||
|
g_vars.current_bonus.y_pos += 32;
|
||||||
|
level_add_bonuses_4x();
|
||||||
|
g_vars.current_bonus.x_pos -= 64;
|
||||||
|
level_add_bonuses_4x();
|
||||||
|
g_vars.current_bonus.x_pos -= 32;
|
||||||
|
g_vars.current_bonus.y_pos -= 64;
|
||||||
|
level_add_bonuses_4x();
|
||||||
|
g_vars.current_bonus.spr_num = 99; /* end of level lighter */
|
||||||
|
level_add_object23_bonus(0, 0, 1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (g_res.level.boss_state == 7) {
|
||||||
|
++g_vars.boss.state_counter;
|
||||||
|
if (g_vars.boss.state_counter > 44) {
|
||||||
|
g_res.level.boss_state = 1;
|
||||||
|
} else {
|
||||||
|
static const uint8_t data_st7[] = {
|
||||||
|
0x03, 0xFF
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st7;
|
||||||
|
if (g_vars.boss.y_velocity == 0) {
|
||||||
|
g_vars.boss.y_velocity = -97;
|
||||||
|
g_vars.boss.x_velocity = (g_vars.objects_tbl[1].x_pos > g_res.level.boss_x_pos) ? -48 : 48;
|
||||||
|
} else if (g_vars.boss.y_velocity > 0) {
|
||||||
|
static const uint8_t data_st7[] = {
|
||||||
|
0x04, 0xFF
|
||||||
|
};
|
||||||
|
g_vars.boss.next_anim = data_st7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (g_vars.boss.prev_anim != g_vars.boss.next_anim) {
|
||||||
|
g_vars.boss.prev_anim = g_vars.boss.next_anim;
|
||||||
|
g_vars.boss.current_anim = g_vars.boss.next_anim;
|
||||||
|
}
|
||||||
|
const uint8_t *p = g_vars.boss.current_anim;
|
||||||
|
while (1) {
|
||||||
|
const uint8_t num = *p;
|
||||||
|
if (num & 0x80) {
|
||||||
|
p += (int8_t)num;
|
||||||
|
} else {
|
||||||
|
g_vars.boss.current_anim = p + 1;
|
||||||
|
g_vars.boss.anim_num = num;
|
||||||
|
g_vars.boss.parts[0].x_pos = g_res.level.boss_x_pos;
|
||||||
|
g_vars.boss.parts[0].y_pos = g_res.level.boss_y_pos;
|
||||||
|
const uint16_t *p = &boss_gorilla_data[(num & ~0x40) * 20 / sizeof(uint16_t)];
|
||||||
|
level_update_boss_gorilla_init_objects(p);
|
||||||
|
level_update_boss_gorilla_helper2();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_tree() {
|
||||||
|
level_update_objects_boss_energy((2 - g_vars.boss_level5.state) << 1);
|
||||||
|
struct object_t *obj_player = &g_vars.objects_tbl[1];
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
struct boss_level5_leaf_t *leaf = &g_vars.boss_level5.leaf_tbl[i];
|
||||||
|
struct object_t *obj = &g_vars.objects_tbl[98 + i];
|
||||||
|
if (leaf->spr_num == 0xFFFF) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (g_vars.restart_level_flag == 0 && level_objects_collide(obj_player, obj)) {
|
||||||
|
obj_player->hit_counter = 44;
|
||||||
|
g_vars.player_anim_0x40_flag = 0;
|
||||||
|
obj_player->data.p.y_velocity = -128;
|
||||||
|
obj_player->x_friction = 3;
|
||||||
|
obj_player->x_velocity = -128;
|
||||||
|
level_update_objects_boss_hit_player();
|
||||||
|
leaf->spr_num = 0xFFFF;
|
||||||
|
obj->spr_num = 0xFFFF;
|
||||||
|
} else {
|
||||||
|
leaf->y_pos += leaf->y_delta >> 4;
|
||||||
|
leaf->x_delta += leaf->dir;
|
||||||
|
int dx = leaf->x_delta;
|
||||||
|
if (dx >= 32 || dx < -32) {
|
||||||
|
leaf->dir = -leaf->dir;
|
||||||
|
}
|
||||||
|
uint16_t spr_num = leaf->spr_num;
|
||||||
|
dx >>= 4;
|
||||||
|
if (dx != 0) {
|
||||||
|
spr_num += (dx > 0) ? 1 : 2;
|
||||||
|
}
|
||||||
|
leaf->x_pos += dx;
|
||||||
|
obj->x_pos = leaf->x_pos;
|
||||||
|
obj->y_pos = leaf->y_pos;
|
||||||
|
if (obj->y_pos > 2008) {
|
||||||
|
leaf->spr_num = 0xFFFF;
|
||||||
|
obj->spr_num = 0xFFFF;
|
||||||
|
} else {
|
||||||
|
obj->spr_num = spr_num;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_vars.objects_tbl[105].spr_num = 0xFFFF;
|
||||||
|
g_vars.objects_tbl[104].spr_num = 0xFFFF;
|
||||||
|
if (g_vars.boss_level5.state < 2) {
|
||||||
|
static const uint16_t pos2_data[] = {
|
||||||
|
0x3D5, 0x7C1, 0x1AA, 0x3FA, 0x7B6, 0x1AB, 0x3E8, 0x7A8, 0x1AC,
|
||||||
|
0x3FF, 0x788, 0x1AD, 0x3D9, 0x79B, 0x1AE, 0x3FF, 0x7A8, 0x1AF,
|
||||||
|
0x405, 0x7A9, 0x1B7, 0, 0, 0xFFFF
|
||||||
|
};
|
||||||
|
const uint16_t *p = &pos2_data[g_vars.boss_level5.state * 6];
|
||||||
|
g_vars.objects_tbl[105].x_pos = p[0];
|
||||||
|
g_vars.objects_tbl[105].y_pos = p[1];
|
||||||
|
g_vars.objects_tbl[105].spr_num = p[2];
|
||||||
|
g_vars.objects_tbl[104].x_pos = p[3];
|
||||||
|
g_vars.objects_tbl[104].y_pos = p[4];
|
||||||
|
g_vars.objects_tbl[104].spr_num = p[5];
|
||||||
|
}
|
||||||
|
static const uint16_t pos1_data[] = {
|
||||||
|
0x3A9, 0x7D4, 0x1A4, 0x3D1, 0x7B9, 0x1A5, 0x3A2, 0x7A6, 0x1A6,
|
||||||
|
0x3B4, 0x79F, 0x1A7, 0x396, 0x78A, 0x1A8, 0x3B6, 0x79C, 0x1A9,
|
||||||
|
0x3E0, 0x795, 0x1B6, 0, 0, 0xFFFF
|
||||||
|
};
|
||||||
|
const uint16_t *p = &pos1_data[g_vars.boss_level5.spr106_pos * 6];
|
||||||
|
g_vars.objects_tbl[107].x_pos = p[0];
|
||||||
|
g_vars.objects_tbl[107].y_pos = p[1];
|
||||||
|
g_vars.objects_tbl[107].spr_num = p[2];
|
||||||
|
g_vars.objects_tbl[106].x_pos = p[3];
|
||||||
|
g_vars.objects_tbl[106].y_pos = p[4];
|
||||||
|
g_vars.objects_tbl[106].spr_num = p[5];
|
||||||
|
static const uint16_t pos3_data[] = {
|
||||||
|
0x3E3, 0x773, 0x1B0, 0x3E4, 0x771, 0x1B1, 0x3E4, 0x773, 0x1B2
|
||||||
|
};
|
||||||
|
const uint16_t *q = &pos3_data[g_vars.boss_level5.spr103_pos * 3];
|
||||||
|
g_vars.objects_tbl[103].x_pos = q[0];
|
||||||
|
g_vars.objects_tbl[103].y_pos = q[1];
|
||||||
|
g_vars.objects_tbl[103].spr_num = (g_vars.boss_level5.state != 0) ? 0xFFFF : q[2];
|
||||||
|
if ((g_vars.level_draw_counter & 3) == 0) {
|
||||||
|
++g_vars.boss_level5.spr103_pos;
|
||||||
|
if (g_vars.boss_level5.spr103_pos > 2) {
|
||||||
|
g_vars.boss_level5.spr103_pos = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (g_vars.boss_level5.unk1 >= 1) {
|
||||||
|
if (g_vars.boss_level5.unk1 == 1) {
|
||||||
|
g_vars.boss_level5.unk6 = 2;
|
||||||
|
--g_vars.boss_level5.spr106_pos;
|
||||||
|
g_vars.boss_level5.tick_counter += 5;
|
||||||
|
}
|
||||||
|
--g_vars.boss_level5.unk1;
|
||||||
|
} else if (g_vars.boss_level5.tick_counter == 0) {
|
||||||
|
++g_vars.boss_level5.unk6;
|
||||||
|
if (g_vars.boss_level5.unk6 > 2) {
|
||||||
|
g_vars.boss_level5.unk6 = 0;
|
||||||
|
}
|
||||||
|
++g_vars.boss_level5.spr106_pos;
|
||||||
|
if (g_vars.boss_level5.spr106_pos > 2) {
|
||||||
|
g_vars.boss_level5.spr106_pos = 0;
|
||||||
|
}
|
||||||
|
uint8_t ah = 1;
|
||||||
|
if (g_vars.boss_level5.spr106_pos != 0) {
|
||||||
|
ah = 3;
|
||||||
|
g_vars.shake_screen_counter = 4;
|
||||||
|
obj_player->x_pos += 2;
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
struct boss_level5_leaf_t *leaf = &g_vars.boss_level5.leaf_tbl[i];
|
||||||
|
if (leaf->spr_num == 0xFFFF) {
|
||||||
|
leaf->spr_num = 0x1B3;
|
||||||
|
leaf->y_pos = obj_player->y_pos - 150;
|
||||||
|
const uint8_t r = random_get_number();
|
||||||
|
const int dx = r & 0x7C;
|
||||||
|
leaf->x_pos = obj_player->x_pos + (((r & 4) != 0) ? dx : -dx);
|
||||||
|
leaf->y_delta = ((r & 3) + 1) << 4;
|
||||||
|
leaf->x_delta = 0;
|
||||||
|
leaf->dir = 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g_vars.boss_level5.tick_counter = ah;
|
||||||
|
--g_vars.boss_level5.idle_counter;
|
||||||
|
if (g_vars.boss_level5.idle_counter == 0) {
|
||||||
|
g_vars.boss_level5.idle_counter = (random_get_number() & 15) << 3;
|
||||||
|
g_vars.boss_level5.tick_counter = 64 + ((random_get_number() & 15) << 3);
|
||||||
|
g_vars.boss_level5.unk6 = 0;
|
||||||
|
}
|
||||||
|
if (g_vars.restart_level_flag == 0) {
|
||||||
|
if (level_objects_collide(obj_player, &g_vars.objects_tbl[107]) || level_objects_collide(obj_player, &g_vars.objects_tbl[106])) {
|
||||||
|
if (obj_player->y_pos <= 1979) {
|
||||||
|
obj_player->data.p.y_velocity = -160;
|
||||||
|
} else {
|
||||||
|
obj_player->data.p.y_velocity = -160;
|
||||||
|
obj_player->hit_counter = 44;
|
||||||
|
g_vars.player_anim_0x40_flag = 0;
|
||||||
|
obj_player->x_friction = 3;
|
||||||
|
obj_player->x_velocity = -128;
|
||||||
|
level_update_objects_boss_hit_player();
|
||||||
|
level_update_objects_boss_hit_player();
|
||||||
|
level_update_objects_boss_hit_player();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (g_vars.restart_level_flag == 0) {
|
||||||
|
if (level_objects_collide(obj_player, &g_vars.objects_tbl[107]) && g_vars.player_jump_monster_flag) {
|
||||||
|
obj_player->data.p.y_velocity = g_vars.input.key_up ? -128 : -64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (g_vars.restart_level_flag == 0) {
|
||||||
|
struct object_t *_si = &g_vars.objects_tbl[103 + g_vars.boss_level5.state * 2];
|
||||||
|
for (int i = 0; i < 6; ++i) {
|
||||||
|
struct object_t *_di = &g_vars.objects_tbl[i];
|
||||||
|
if (_di->spr_num == 0xFFFF || _di == obj_player) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
g_vars.player_using_club_flag = 1;
|
||||||
|
const bool ret = level_objects_collide(_si, _di);
|
||||||
|
g_vars.player_using_club_flag = 0;
|
||||||
|
if (ret) {
|
||||||
|
_si->spr_num ^= 0x4000;
|
||||||
|
if (g_vars.boss_level5.state != 0) {
|
||||||
|
_si[-1].spr_num ^= 0x4000;
|
||||||
|
}
|
||||||
|
_di->spr_num = 0xFFFF;
|
||||||
|
g_vars.boss_level5.unk1 = 6;
|
||||||
|
if (g_vars.boss_level5.state < 2) {
|
||||||
|
g_vars.boss_level5.unk6 = 3;
|
||||||
|
g_vars.boss_level5.spr106_pos = 3;
|
||||||
|
}
|
||||||
|
--g_vars.boss_level5.energy;
|
||||||
|
if (g_vars.boss_level5.energy == 0) {
|
||||||
|
g_vars.boss_level5.energy = 7;
|
||||||
|
++g_vars.boss_level5.state;
|
||||||
|
if (g_vars.boss_level5.state == 3) {
|
||||||
|
/* boss defeated */
|
||||||
|
g_vars.current_bonus.x_pos = g_vars.objects_tbl[103].x_pos - 200;
|
||||||
|
g_vars.current_bonus.y_pos = g_vars.objects_tbl[103].y_pos;
|
||||||
|
level_add_bonuses_4x();
|
||||||
|
g_vars.current_bonus.x_pos += 32;
|
||||||
|
g_vars.current_bonus.y_pos += 32;
|
||||||
|
level_add_bonuses_4x();
|
||||||
|
g_vars.current_bonus.x_pos -= 64;
|
||||||
|
level_add_bonuses_4x();
|
||||||
|
g_vars.current_bonus.x_pos -= 32;
|
||||||
|
g_vars.current_bonus.y_pos -= 64;
|
||||||
|
level_add_bonuses_4x();
|
||||||
|
g_vars.current_bonus.spr_num = 99; /* end of level lighter */
|
||||||
|
level_add_object23_bonus(0, 0, 1);
|
||||||
|
for (int i = 0; i < 5; ++i) {
|
||||||
|
g_vars.objects_tbl[98 + i].spr_num = 0xFFFF;
|
||||||
|
g_vars.objects_tbl[103 + i].spr_num = 0xFFFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj_player->x_pos > 984) {
|
||||||
|
obj_player->hit_counter = 44;
|
||||||
|
g_vars.player_anim_0x40_flag = 0;
|
||||||
|
obj_player->data.p.y_velocity = -144;
|
||||||
|
obj_player->x_friction = 3;
|
||||||
|
obj_player->x_velocity = -160;
|
||||||
|
level_update_objects_boss_hit_player();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (g_vars.boss_level5.tick_counter > 0) {
|
||||||
|
--g_vars.boss_level5.tick_counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_minotaur_set_frame(int num) {
|
||||||
|
const int offset = (num * 6 + 20);
|
||||||
|
for (int y = 0; y < 7; ++y) {
|
||||||
|
for (int x = 0; x < 6; ++x) {
|
||||||
|
g_res.leveldat[(y << 8) + 12 + x] = g_res.leveldat[(y << 8) + offset + x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_minotaur_add_spr_0x137() { /* boss defeated, bonus */
|
||||||
|
g_vars.current_bonus.x_pos = 185;
|
||||||
|
g_vars.current_bonus.y_pos = 30;
|
||||||
|
g_vars.current_bonus.spr_num = 0x2137;
|
||||||
|
int x_vel = 32;
|
||||||
|
int y_vel = -160;
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
level_add_object23_bonus(x_vel, y_vel, 1);
|
||||||
|
x_vel = -x_vel;
|
||||||
|
if (x_vel >= 0) {
|
||||||
|
x_vel -= 16;
|
||||||
|
y_vel -= 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_minotaur_add_spr_0x1CA() { /* rock */
|
||||||
|
for (int i = 0; i < 32; ++i) {
|
||||||
|
struct object_t *obj = &g_vars.objects_tbl[23 + i];
|
||||||
|
if (obj->spr_num != 0xFFFF) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
obj->spr_num = 0x1CA;
|
||||||
|
obj->x_pos = 200;
|
||||||
|
obj->y_pos = 88;
|
||||||
|
obj->hit_counter = 0;
|
||||||
|
obj->data.t.counter = 132;
|
||||||
|
obj->data.t.ref = 0;
|
||||||
|
obj->x_velocity = -((random_get_number() & 15) << 3);
|
||||||
|
obj->data.t.y_velocity = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_minotaur_add_spr_0x1CB() { /* ceiling chandelier */
|
||||||
|
for (int i = 0; i < 32; ++i) {
|
||||||
|
struct object_t *obj = &g_vars.objects_tbl[23 + i];
|
||||||
|
if (obj->spr_num != 0xFFFF) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
obj->spr_num = 0x1CB;
|
||||||
|
obj->x_pos = (random_get_number() & 0x7F) - 16;
|
||||||
|
obj->y_pos = 0;
|
||||||
|
obj->hit_counter = 0;
|
||||||
|
obj->data.t.counter = 66;
|
||||||
|
obj->data.t.ref = 0;
|
||||||
|
obj->x_velocity = 0;
|
||||||
|
obj->data.t.y_velocity = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void level_update_boss_minotaur() {
|
||||||
|
static const uint16_t data[] = {
|
||||||
|
0xA70F, 5, 0xA74E, 1, 0xA70F, 3, 0xA74E, 2, 0xA70F, 2, 0xA734, 1, 0xFFFF
|
||||||
|
};
|
||||||
|
if (!g_vars.boss_level9.seq) {
|
||||||
|
g_vars.boss_level9.anim = data;
|
||||||
|
g_vars.boss_level9.energy = 24;
|
||||||
|
g_vars.boss_level9.seq_counter = 0;
|
||||||
|
g_vars.boss_level9.hit_counter = 3;
|
||||||
|
}
|
||||||
|
level_update_objects_boss_energy(g_vars.boss_level9.energy >> 2);
|
||||||
|
if (g_vars.boss_level9.energy == 0) {
|
||||||
|
level_update_boss_minotaur_set_frame(2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (g_vars.boss_level9.seq_counter == 0) {
|
||||||
|
const uint16_t *p = g_vars.boss_level9.anim;
|
||||||
|
if (p[0] == 0xFFFF) {
|
||||||
|
p = data;
|
||||||
|
}
|
||||||
|
assert(p[0] >= 0xA70F);
|
||||||
|
g_vars.boss_level9.seq = &boss_minotaur_seq_data[p[0] - 0xA70F];
|
||||||
|
g_vars.boss_level9.seq_counter = p[1];
|
||||||
|
g_vars.boss_level9.anim = p + 2;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
struct object_t *obj = &g_vars.objects_tbl[2 + i];
|
||||||
|
if (obj->spr_num == 0xFFFF) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (obj->x_pos >= 235 || obj->y_pos >= 80) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
g_vars.boss_level9.seq = &boss_minotaur_seq_data[0x19];
|
||||||
|
if (g_vars.boss_level9.energy > 0) {
|
||||||
|
--g_vars.boss_level9.energy;
|
||||||
|
}
|
||||||
|
if (g_vars.boss_level9.energy == 0) {
|
||||||
|
level_update_boss_minotaur_add_spr_0x137();
|
||||||
|
}
|
||||||
|
++g_vars.boss_level9.hit_counter;
|
||||||
|
g_vars.boss_level9.hit_counter &= 3;
|
||||||
|
if (g_vars.boss_level9.hit_counter == 0) {
|
||||||
|
g_vars.boss_level9.seq = &boss_minotaur_seq_data[0x25];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const uint8_t *p = g_vars.boss_level9.seq;
|
||||||
|
while (1) {
|
||||||
|
if (*p == 0xFF) {
|
||||||
|
level_update_boss_minotaur_add_spr_0x1CA();
|
||||||
|
++p;
|
||||||
|
} else if (*p == 0xFE) {
|
||||||
|
level_update_boss_minotaur_add_spr_0x1CB();
|
||||||
|
++p;
|
||||||
|
} else if (*p == 0xFD) {
|
||||||
|
play_sound(2);
|
||||||
|
++p;
|
||||||
|
} else if ((*p & 0x80) == 0) {
|
||||||
|
++g_vars.boss_level9.seq;
|
||||||
|
level_update_boss_minotaur_set_frame(*p);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
if (g_vars.boss_level9.seq_counter > 0) {
|
||||||
|
--g_vars.boss_level9.seq_counter;
|
||||||
|
}
|
||||||
|
p += (int8_t)*p;
|
||||||
|
g_vars.boss_level9.seq = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void boss_update() {
|
||||||
|
if (g_res.level.boss_state != 0xFF) {
|
||||||
|
level_update_boss_gorilla();
|
||||||
|
}
|
||||||
|
if (g_vars.level_num == 5 && (g_res.level.scrolling_mask & ~1) == 0) {
|
||||||
|
level_update_boss_tree();
|
||||||
|
}
|
||||||
|
if (g_vars.level_num == 9) {
|
||||||
|
level_update_boss_minotaur();
|
||||||
|
}
|
||||||
|
}
|
42
p2/game.h
42
p2/game.h
|
@ -85,26 +85,27 @@ struct object_t {
|
||||||
108 8 : boss energy bars
|
108 8 : boss energy bars
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct boss_level5_proj_t {
|
struct boss_level5_leaf_t {
|
||||||
int16_t x_pos, y_pos;
|
int16_t x_pos;
|
||||||
|
int16_t y_pos;
|
||||||
uint16_t spr_num;
|
uint16_t spr_num;
|
||||||
uint16_t unk6;
|
int16_t y_delta;
|
||||||
uint16_t unk8;
|
int16_t x_delta;
|
||||||
int8_t dir;
|
int8_t dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rotation_t {
|
struct orb_t {
|
||||||
uint16_t x_pos;
|
uint16_t x_pos;
|
||||||
uint16_t y_pos;
|
uint16_t y_pos;
|
||||||
uint8_t index_tbl; /* cos_/sin_tbl */
|
uint8_t index_tbl; /* cos_/sin_tbl */
|
||||||
uint8_t radius;
|
uint8_t radius;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct collision_t {
|
struct fly_t {
|
||||||
uint16_t x_pos;
|
uint16_t x_pos;
|
||||||
uint16_t y_pos;
|
uint16_t y_pos;
|
||||||
uint8_t unk4;
|
int8_t x_delta;
|
||||||
uint8_t unk5;
|
int8_t y_delta;
|
||||||
uint8_t unk6;
|
uint8_t unk6;
|
||||||
uint8_t unk7;
|
uint8_t unk7;
|
||||||
};
|
};
|
||||||
|
@ -173,11 +174,11 @@ struct vars_t {
|
||||||
uint8_t level_bonuses_count_tbl[80];
|
uint8_t level_bonuses_count_tbl[80];
|
||||||
uint8_t bonus_energy_counter;
|
uint8_t bonus_energy_counter;
|
||||||
|
|
||||||
int16_t level_current_object_decor_x_pos, level_current_object_decor_y_pos;
|
int16_t current_platform_dx, current_platform_dy;
|
||||||
uint16_t decor_tile0_offset; /* decor tile below the player */
|
uint16_t decor_tile0_offset; /* decor tile below the player */
|
||||||
|
|
||||||
struct collision_t collision_tbl[20]; /* reset by bonus 145 */
|
struct fly_t fly_tbl[20];
|
||||||
struct rotation_t rotation_tbl[20];
|
struct orb_t orb_tbl[20]; /* spider webs */
|
||||||
struct object_t *current_hit_object;
|
struct object_t *current_hit_object;
|
||||||
struct object_t objects_tbl[OBJECTS_COUNT];
|
struct object_t objects_tbl[OBJECTS_COUNT];
|
||||||
|
|
||||||
|
@ -196,6 +197,8 @@ struct vars_t {
|
||||||
uint8_t tile_tbl3[256]; /* animated tile state 3 */
|
uint8_t tile_tbl3[256]; /* animated tile state 3 */
|
||||||
uint8_t animated_tile_flag_tbl[256]; /* 1 if tile is animated */
|
uint8_t animated_tile_flag_tbl[256]; /* 1 if tile is animated */
|
||||||
|
|
||||||
|
uint8_t columns_tiles_buf[256];
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int16_t x, y;
|
int16_t x, y;
|
||||||
int16_t prev_x, prev_y;
|
int16_t prev_x, prev_y;
|
||||||
|
@ -214,7 +217,7 @@ struct vars_t {
|
||||||
} monster;
|
} monster;
|
||||||
struct {
|
struct {
|
||||||
uint16_t draw_counter;
|
uint16_t draw_counter;
|
||||||
uint8_t unk_counter;
|
uint8_t change_counter;
|
||||||
int16_t x_velocity, y_velocity;
|
int16_t x_velocity, y_velocity;
|
||||||
bool hdir; /* facing to the right */
|
bool hdir; /* facing to the right */
|
||||||
int16_t x_dist; /* horizontal distance from player */
|
int16_t x_dist; /* horizontal distance from player */
|
||||||
|
@ -238,12 +241,12 @@ struct vars_t {
|
||||||
uint8_t spr103_pos;
|
uint8_t spr103_pos;
|
||||||
uint8_t spr106_pos;
|
uint8_t spr106_pos;
|
||||||
uint8_t unk6;
|
uint8_t unk6;
|
||||||
uint8_t counter;
|
uint8_t tick_counter;
|
||||||
uint8_t unk8;
|
uint8_t idle_counter;
|
||||||
struct boss_level5_proj_t proj_tbl[5];
|
struct boss_level5_leaf_t leaf_tbl[5];
|
||||||
} boss_level5; /* tree */
|
} boss_level5; /* tree */
|
||||||
struct {
|
struct {
|
||||||
uint16_t energy;
|
int16_t energy;
|
||||||
uint8_t seq_counter;
|
uint8_t seq_counter;
|
||||||
uint8_t hit_counter;
|
uint8_t hit_counter;
|
||||||
const uint8_t *seq;
|
const uint8_t *seq;
|
||||||
|
@ -307,6 +310,11 @@ extern void game_main();
|
||||||
|
|
||||||
/* level.c */
|
/* level.c */
|
||||||
extern void do_level();
|
extern void do_level();
|
||||||
|
extern uint8_t level_get_tile(uint16_t offset);
|
||||||
|
extern void level_player_die();
|
||||||
|
extern bool level_objects_collide(const struct object_t *, const struct object_t *);
|
||||||
|
extern void level_add_object23_bonus(int x_vel, int y_vel, int count);
|
||||||
|
extern void level_add_bonuses_4x();
|
||||||
|
|
||||||
/* monsters.c */
|
/* monsters.c */
|
||||||
extern void monster_change_next_anim(struct object_t *obj);
|
extern void monster_change_next_anim(struct object_t *obj);
|
||||||
|
@ -324,11 +332,11 @@ extern void video_draw_string2(int offset, const char *str);
|
||||||
extern void video_draw_tile(const uint8_t *src, int x, int y);
|
extern void video_draw_tile(const uint8_t *src, int x, int y);
|
||||||
extern void video_convert_tiles(uint8_t *data, int len);
|
extern void video_convert_tiles(uint8_t *data, int len);
|
||||||
extern void video_load_front_tiles();
|
extern void video_load_front_tiles();
|
||||||
extern void video_wait_vbl();
|
|
||||||
extern void video_transition_close();
|
extern void video_transition_close();
|
||||||
extern void video_transition_open();
|
extern void video_transition_open();
|
||||||
extern void video_load_sprites();
|
extern void video_load_sprites();
|
||||||
extern void video_draw_sprite(int num, int x, int y, int flag);
|
extern void video_draw_sprite(int num, int x, int y, int flag);
|
||||||
|
extern void video_put_pixel(int x, int y, uint8_t color);
|
||||||
|
|
||||||
/* sound.c */
|
/* sound.c */
|
||||||
extern void sound_init();
|
extern void sound_init();
|
||||||
|
|
1106
p2/level.c
1106
p2/level.c
File diff suppressed because it is too large
Load Diff
|
@ -61,9 +61,9 @@ void monster_change_prev_anim(struct object_t *obj) {
|
||||||
obj->data.m.anim = p;
|
obj->data.m.anim = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rotation_t *find_rotation() {
|
static struct orb_t *find_orb() {
|
||||||
for (int i = 0; i < 20; ++i) {
|
for (int i = 0; i < 20; ++i) {
|
||||||
struct rotation_t *r = &g_vars.rotation_tbl[i];
|
struct orb_t *r = &g_vars.orb_tbl[i];
|
||||||
if (r->x_pos == 0xFFFF) {
|
if (r->x_pos == 0xFFFF) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
@ -71,11 +71,11 @@ static struct rotation_t *find_rotation() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monster_rotate_tiles(struct level_monster_t *m, int index, int step) {
|
static void monster_add_orb(struct level_monster_t *m, int index, int step) {
|
||||||
step >>= 2;
|
step >>= 2;
|
||||||
uint8_t radius = step;
|
uint8_t radius = step;
|
||||||
for (int i = 0; i < 3; ++i) {
|
for (int i = 0; i < 3; ++i) {
|
||||||
struct rotation_t *r = find_rotation();
|
struct orb_t *r = find_orb();
|
||||||
if (r) {
|
if (r) {
|
||||||
r->x_pos = m->x_pos;
|
r->x_pos = m->x_pos;
|
||||||
r->y_pos = m->y_pos - 24;
|
r->y_pos = m->y_pos - 24;
|
||||||
|
@ -89,7 +89,7 @@ static void monster_rotate_tiles(struct level_monster_t *m, int index, int step)
|
||||||
static void monster_rotate_pos(struct object_t *obj, struct level_monster_t *m) {
|
static void monster_rotate_pos(struct object_t *obj, struct level_monster_t *m) {
|
||||||
obj->x_pos = m->x_pos + ((m->type4.radius * (((int8_t)cos_tbl[m->type4.angle]) >> 2)) >> 4);
|
obj->x_pos = m->x_pos + ((m->type4.radius * (((int8_t)cos_tbl[m->type4.angle]) >> 2)) >> 4);
|
||||||
obj->y_pos = m->y_pos + ((m->type4.radius * (((int8_t)sin_tbl[m->type4.angle]) >> 2)) >> 4);
|
obj->y_pos = m->y_pos + ((m->type4.radius * (((int8_t)sin_tbl[m->type4.angle]) >> 2)) >> 4);
|
||||||
monster_rotate_tiles(m, m->type4.angle, m->type4.radius);
|
monster_add_orb(m, m->type4.angle, m->type4.radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void monster_update_y_velocity(struct object_t *obj, struct level_monster_t *m) {
|
static void monster_update_y_velocity(struct object_t *obj, struct level_monster_t *m) {
|
||||||
|
@ -134,7 +134,7 @@ static void monster_func1_type2(struct object_t *obj) {
|
||||||
struct level_monster_t *m = obj->data.m.ref;
|
struct level_monster_t *m = obj->data.m.ref;
|
||||||
const uint8_t state = obj->data.m.state;
|
const uint8_t state = obj->data.m.state;
|
||||||
if (state < 2) {
|
if (state < 2) {
|
||||||
monster_rotate_tiles(m, 0, obj->y_pos - m->y_pos);
|
monster_add_orb(m, 0, obj->y_pos - m->y_pos);
|
||||||
if (state == 0) {
|
if (state == 0) {
|
||||||
obj->data.m.y_velocity = m->type2.unkE << 4;
|
obj->data.m.y_velocity = m->type2.unkE << 4;
|
||||||
const int dy = obj->y_pos - m->y_pos;
|
const int dy = obj->y_pos - m->y_pos;
|
||||||
|
@ -174,7 +174,7 @@ static void monster_func1_type3(struct object_t *obj) {
|
||||||
obj->data.m.y_velocity = 32;
|
obj->data.m.y_velocity = 32;
|
||||||
monster_change_next_anim(obj);
|
monster_change_next_anim(obj);
|
||||||
} else if (state == 1) {
|
} else if (state == 1) {
|
||||||
monster_rotate_tiles(m, 0, obj->y_pos - m->y_pos);
|
monster_add_orb(m, 0, obj->y_pos - m->y_pos);
|
||||||
const uint16_t pos = ((obj->y_pos >> 4) << 8) | (obj->x_pos >> 4);
|
const uint16_t pos = ((obj->y_pos >> 4) << 8) | (obj->x_pos >> 4);
|
||||||
const uint8_t tile_num = g_res.leveldat[pos];
|
const uint8_t tile_num = g_res.leveldat[pos];
|
||||||
if (g_res.level.tile_attributes1[tile_num] == 0) {
|
if (g_res.level.tile_attributes1[tile_num] == 0) {
|
||||||
|
@ -205,7 +205,7 @@ static void monster_func1_type4(struct object_t *obj) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const int dy = obj->y_pos - m->y_pos;
|
const int dy = obj->y_pos - m->y_pos;
|
||||||
monster_rotate_tiles(m, 0, dy);
|
monster_add_orb(m, 0, dy);
|
||||||
if (m->type4.radius > dy) {
|
if (m->type4.radius > dy) {
|
||||||
obj->y_pos += 2;
|
obj->y_pos += 2;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -104,15 +104,15 @@ void load_leveldat(const uint8_t *p, struct level_t *level) {
|
||||||
gate->dst_pos = READ_LE_UINT16(p); p += 2;
|
gate->dst_pos = READ_LE_UINT16(p); p += 2;
|
||||||
gate->scroll_flag = *p++;
|
gate->scroll_flag = *p++;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < MAX_LEVEL_UNKS; ++i) {
|
for (int i = 0; i < MAX_LEVEL_COLUMNS; ++i) {
|
||||||
struct level_unk_t *unk = &g_res.level.unks_tbl[i];
|
struct level_column_t *column = &g_res.level.columns_tbl[i];
|
||||||
unk->tilemap_pos = READ_LE_UINT16(p); p += 2;
|
column->tilemap_pos = READ_LE_UINT16(p); p += 2;
|
||||||
unk->w = *p++;
|
column->w = *p++;
|
||||||
unk->h = *p++;
|
column->h = *p++;
|
||||||
unk->unk4 = READ_LE_UINT16(p); p += 2;
|
column->trigger_pos = READ_LE_UINT16(p); p += 2;
|
||||||
unk->unk6 = READ_LE_UINT16(p); p += 2;
|
column->tiles_offset_buf = READ_LE_UINT16(p); p += 2;
|
||||||
unk->unk8 = *p++;
|
column->y_target = *p++;
|
||||||
unk->unk9 = *p++;
|
column->unk9 = *p++;
|
||||||
}
|
}
|
||||||
const uint8_t *monster_attr = p;
|
const uint8_t *monster_attr = p;
|
||||||
int monsters_count = 0;
|
int monsters_count = 0;
|
||||||
|
@ -251,7 +251,7 @@ void load_leveldat(const uint8_t *p, struct level_t *level) {
|
||||||
}
|
}
|
||||||
g_res.level.boss_xmin = READ_LE_UINT16(p); p += 2;
|
g_res.level.boss_xmin = READ_LE_UINT16(p); p += 2;
|
||||||
g_res.level.boss_xmax = READ_LE_UINT16(p); p += 2;
|
g_res.level.boss_xmax = READ_LE_UINT16(p); p += 2;
|
||||||
g_res.level.boss_counter = *p++;
|
g_res.level.boss_speed = *p++;
|
||||||
g_res.level.boss_energy = READ_LE_UINT16(p); p += 2;
|
g_res.level.boss_energy = READ_LE_UINT16(p); p += 2;
|
||||||
g_res.level.boss_state = *p++;
|
g_res.level.boss_state = *p++;
|
||||||
g_res.level.boss_x_pos = READ_LE_UINT16(p); p += 2;
|
g_res.level.boss_x_pos = READ_LE_UINT16(p); p += 2;
|
||||||
|
|
|
@ -11,13 +11,13 @@ struct level_gate_t {
|
||||||
uint8_t scroll_flag;
|
uint8_t scroll_flag;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct level_unk_t {
|
struct level_column_t {
|
||||||
uint16_t tilemap_pos;
|
uint16_t tilemap_pos; /* current column tilemap pos */
|
||||||
uint8_t w;
|
uint8_t w;
|
||||||
uint8_t h;
|
uint8_t h;
|
||||||
uint16_t unk4;
|
uint16_t trigger_pos; /* compared with player pos */
|
||||||
uint16_t unk6;
|
uint16_t tiles_offset_buf;
|
||||||
uint8_t unk8;
|
uint8_t y_target; /* final y pos */
|
||||||
uint8_t unk9;
|
uint8_t unk9;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ struct level_monster_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_LEVEL_GATES 20
|
#define MAX_LEVEL_GATES 20
|
||||||
#define MAX_LEVEL_UNKS 15
|
#define MAX_LEVEL_COLUMNS 15
|
||||||
#define MAX_LEVEL_BONUSES 80
|
#define MAX_LEVEL_BONUSES 80
|
||||||
#define MAX_LEVEL_ITEMS 70
|
#define MAX_LEVEL_ITEMS 70
|
||||||
#define MAX_LEVEL_PLATFORMS 16
|
#define MAX_LEVEL_PLATFORMS 16
|
||||||
|
@ -140,7 +140,7 @@ struct level_t {
|
||||||
uint16_t scrolling_mask; /* 4: screen scroll down 1 line, 2: no horizontal scrolling, 1: wider vertical scrolling */
|
uint16_t scrolling_mask; /* 4: screen scroll down 1 line, 2: no horizontal scrolling, 1: wider vertical scrolling */
|
||||||
uint16_t front_tiles_lut[256];
|
uint16_t front_tiles_lut[256];
|
||||||
struct level_gate_t gates_tbl[MAX_LEVEL_GATES];
|
struct level_gate_t gates_tbl[MAX_LEVEL_GATES];
|
||||||
struct level_unk_t unks_tbl[MAX_LEVEL_UNKS];
|
struct level_column_t columns_tbl[MAX_LEVEL_COLUMNS];
|
||||||
struct level_monster_t monsters_tbl[MAX_LEVEL_MONSTERS];
|
struct level_monster_t monsters_tbl[MAX_LEVEL_MONSTERS];
|
||||||
uint8_t monsters_count;
|
uint8_t monsters_count;
|
||||||
uint16_t items_spr_num_offset;
|
uint16_t items_spr_num_offset;
|
||||||
|
@ -151,8 +151,8 @@ struct level_t {
|
||||||
struct level_platform_t platforms_tbl[MAX_LEVEL_PLATFORMS];
|
struct level_platform_t platforms_tbl[MAX_LEVEL_PLATFORMS];
|
||||||
uint16_t boss_xmin;
|
uint16_t boss_xmin;
|
||||||
uint16_t boss_xmax;
|
uint16_t boss_xmax;
|
||||||
uint8_t boss_counter;
|
uint8_t boss_speed; /* 0..4 */
|
||||||
uint16_t boss_energy;
|
int16_t boss_energy;
|
||||||
uint8_t boss_state; /* !=255: has boss */
|
uint8_t boss_state; /* !=255: has boss */
|
||||||
uint16_t boss_x_pos;
|
uint16_t boss_x_pos;
|
||||||
uint16_t boss_y_pos;
|
uint16_t boss_y_pos;
|
||||||
|
|
|
@ -195,9 +195,6 @@ void video_load_front_tiles() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void video_wait_vbl() {
|
|
||||||
}
|
|
||||||
|
|
||||||
void video_transition_close() {
|
void video_transition_close() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,3 +269,7 @@ void video_load_sprites() {
|
||||||
void video_draw_sprite(int num, int x, int y, int flag) {
|
void video_draw_sprite(int num, int x, int y, int flag) {
|
||||||
g_sys.render_add_sprite(RENDER_SPR_GAME, num, x, y, flag != 0);
|
g_sys.render_add_sprite(RENDER_SPR_GAME, num, x, y, flag != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void video_put_pixel(int x, int y, uint8_t color) {
|
||||||
|
g_res.vga[y * GAME_SCREEN_W + x] = color;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue