2018-07-08 16:08:53 +02:00
|
|
|
|
|
|
|
/* level main loop */
|
|
|
|
|
|
|
|
#include "game.h"
|
|
|
|
#include "resource.h"
|
|
|
|
#include "sys.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
static const uint16_t _copper_data[18 * MAX_LEVELS] = {
|
|
|
|
0x190,0x00a,0x00b,0x00c,0x00d,0x00e,0x00f,0x01f,0x02f,0x03f,0x04f,0x05f,0x06f,0x07f,0x08f,0x09f,0x0af,0x0bf,
|
|
|
|
0x190,0x35c,0x15c,0x25c,0x35c,0x45c,0x55c,0x65b,0x75a,0x859,0x958,0xa57,0xb56,0xc55,0xd54,0xe53,0xf54,0xf64,
|
|
|
|
0x198,0x900,0xa00,0xb00,0xc00,0xd00,0xe00,0xf00,0xf10,0xf20,0xf30,0xf40,0xf50,0xf60,0xf70,0xf80,0xf90,0xfa0,
|
|
|
|
0x190,0x303,0x403,0x503,0x603,0x703,0x803,0x903,0xa03,0xb03,0xc03,0xd03,0xe03,0xf03,0xf04,0xf05,0xf06,0xf07,
|
|
|
|
0x19a,0x003,0x004,0x005,0x006,0x007,0x008,0x009,0x00a,0x00b,0x00c,0x00d,0x00e,0x00f,0x10f,0x20f,0x30f,0x40f,
|
|
|
|
0x198,0x400,0x500,0x600,0x700,0x800,0x900,0xa00,0xb00,0xc00,0xd00,0xe00,0xf00,0xf11,0xf22,0xf33,0xf44,0xf55
|
|
|
|
};
|
|
|
|
|
|
|
|
static const uint16_t _colors_data[16 * MAX_LEVELS] = {
|
|
|
|
0x000,0xc77,0x989,0x669,0x147,0xfda,0xdb9,0xf87,0x4af,0x050,0x091,0x111,0xbcf,0xa20,0x630,0xfff,
|
|
|
|
0x000,0xa67,0xb89,0x067,0x046,0xeb8,0xca5,0xf87,0x4af,0x660,0x980,0x111,0x59c,0xa25,0x635,0xfff,
|
|
|
|
0x000,0x744,0x989,0x669,0x147,0xfda,0xdb9,0xf87,0x3ae,0x0a2,0x0d2,0x000,0xbcf,0xf30,0x950,0xfff,
|
|
|
|
0x000,0x885,0x773,0x267,0x147,0xca8,0x75e,0xb76,0x000,0x996,0x664,0x111,0x546,0x553,0x289,0xbcf,
|
|
|
|
0x000,0xa9a,0x753,0x868,0x407,0xfaa,0xbac,0xd67,0x38c,0xd96,0x964,0x000,0xbcd,0x000,0x705,0xfff,
|
|
|
|
0x000,0x30b,0x747,0x446,0x006,0xfda,0x400,0xf87,0x37a,0x600,0xd63,0x000,0x000,0x800,0xdd0,0x98d
|
|
|
|
};
|
|
|
|
|
2018-07-12 15:17:33 +02:00
|
|
|
static const struct {
|
2018-07-08 16:08:53 +02:00
|
|
|
const char *ck1;
|
|
|
|
const char *ck2;
|
|
|
|
const char *sql;
|
|
|
|
const char *bin;
|
|
|
|
const char *avt;
|
|
|
|
const char *sqv;
|
|
|
|
const int16_t *xpos;
|
|
|
|
const int16_t *ypos;
|
|
|
|
uint8_t music;
|
2018-08-12 16:55:27 +02:00
|
|
|
uint8_t cga_dither_ck;
|
|
|
|
uint8_t cga_dither_sqv;
|
|
|
|
uint8_t cga_dither_avt;
|
2018-07-08 16:08:53 +02:00
|
|
|
} _levels[MAX_LEVELS] = {
|
2018-08-12 16:55:27 +02:00
|
|
|
{ "mag.ck1", "mag.ck2", "mag.sql", "magasin.bin", "avtmag.sqv", "enemi1.sqv", level_xpos_magasin, level_ypos_magasin, 1, 3, 4, 3 },
|
|
|
|
{ "ent.ck1", "ent.ck2", "ent.sql", "entrepot.bin", "avtent.sqv", "enemi2.sqv", level_xpos_ent, level_ypos_ent, 2, 3, 4, 3 },
|
|
|
|
{ "prison.ck1", "prison.ck2", "prison.sql", "prison.bin", "avtpris.sqv", "enemi3.sqv", level_xpos_prison, level_ypos_prison, 3, 5, 6, 5 },
|
|
|
|
{ "egou.ck1", "egou.ck2", "egou.sql", "egou.bin", "avtegou.sqv", "enemi4.sqv", level_xpos_egou, level_ypos_egou, 1, 3, 4, 3 },
|
|
|
|
{ "ville.ck1", "ville.ck2", "ville.sql", "ville.bin", "avtville.sqv", "enemi5.sqv", level_xpos_ville, level_ypos_ville, 2, 7, 4, 7 },
|
|
|
|
{ "concert.ck1", "concert.ck2", "concert.sql", "concert.bin", "", "enemi6.sqv", level_xpos_concert, level_ypos_concert, 3, 8, 4, 0 },
|
2018-07-08 16:08:53 +02:00
|
|
|
};
|
|
|
|
|
2018-07-12 15:17:33 +02:00
|
|
|
static const struct {
|
2018-07-13 14:34:11 +02:00
|
|
|
const char *blk;
|
|
|
|
const char *tbl;
|
2018-07-12 15:17:33 +02:00
|
|
|
const char *m;
|
|
|
|
const char *bin;
|
2018-07-13 14:34:11 +02:00
|
|
|
const char *ennemi;
|
2018-07-12 15:17:33 +02:00
|
|
|
} _levels_amiga[MAX_LEVELS] = {
|
2018-07-13 14:34:11 +02:00
|
|
|
{ "mag.blk", "mag.tbl", "mag.m", "magasin.bin", "ennemi1" },
|
|
|
|
{ "ent.blk", "ent.tbl", "ent.m", "entrepo.bin", "ennemi2" },
|
|
|
|
{ "prison.blk", "prison.tbl", "pris.m", "prison.bin", "ennemi3" },
|
|
|
|
{ "egout.blk", "egout.tbl", "egou.m", "egout.bin", "ennemi4" },
|
|
|
|
{ "ville.blk", "ville.tbl", "ville.m", "ville.bin", "ennemi5" },
|
|
|
|
{ "concert.blk", "concert.tbl", 0, "concert.bin", "ennemi6" },
|
2018-07-12 15:17:33 +02:00
|
|
|
};
|
|
|
|
|
2018-07-08 16:08:53 +02:00
|
|
|
void load_level_data(int num) {
|
|
|
|
print_debug(DBG_GAME, "load_level_data num %d", num);
|
2018-08-12 14:27:20 +02:00
|
|
|
if (g_res.amiga_data) {
|
2018-07-13 14:34:11 +02:00
|
|
|
load_blk(_levels_amiga[num].blk);
|
|
|
|
read_file(_levels_amiga[num].tbl, g_res.sql, 0);
|
2018-07-12 15:17:33 +02:00
|
|
|
load_bin(_levels_amiga[num].bin);
|
2018-07-20 15:51:02 +02:00
|
|
|
load_m(_levels_amiga[num].m);
|
|
|
|
// .avt
|
2018-07-13 14:34:11 +02:00
|
|
|
load_spr(_levels_amiga[num].ennemi, g_res.tmp, SPRITES_COUNT);
|
2018-07-12 15:17:33 +02:00
|
|
|
} else {
|
2018-08-12 16:55:27 +02:00
|
|
|
const int dither_pattern = g_options.cga_colors ? _levels[num].cga_dither_ck : -1;
|
2018-08-12 14:27:20 +02:00
|
|
|
if (num == 0 && g_res.dos_demo) {
|
2018-08-12 15:44:16 +02:00
|
|
|
load_ck("demomag.ck1", 0x6000, dither_pattern);
|
|
|
|
load_ck("demomag.ck2", 0x8000, dither_pattern);
|
2018-07-20 15:51:02 +02:00
|
|
|
load_sql("demomag.sql");
|
|
|
|
} else {
|
2018-08-12 15:44:16 +02:00
|
|
|
load_ck(_levels[num].ck1, 0x6000, dither_pattern);
|
|
|
|
load_ck(_levels[num].ck2, 0x8000, dither_pattern);
|
2018-07-20 15:51:02 +02:00
|
|
|
load_sql(_levels[num].sql);
|
|
|
|
}
|
|
|
|
load_bin(_levels[num].bin);
|
2018-08-12 16:55:27 +02:00
|
|
|
load_avt(_levels[num].avt, g_res.avt_sqv, 0, g_options.cga_colors ? _levels[num].cga_dither_avt : -1);
|
|
|
|
load_sqv(_levels[num].sqv, g_res.tmp, SPRITES_COUNT, g_options.cga_colors ? _levels[num].cga_dither_ck : -1);
|
2018-07-12 15:17:33 +02:00
|
|
|
}
|
2018-07-08 16:08:53 +02:00
|
|
|
memcpy(g_vars.level_xpos, _levels[num].xpos, MAX_OBJECTS * sizeof(int16_t));
|
|
|
|
memcpy(g_vars.level_ypos, _levels[num].ypos, MAX_OBJECTS * sizeof(int16_t));
|
|
|
|
if (g_vars.music_num != _levels[num].music) {
|
|
|
|
play_music(_levels[num].music);
|
|
|
|
g_vars.music_num = _levels[num].music;
|
|
|
|
}
|
2018-08-12 16:55:27 +02:00
|
|
|
if (g_options.cga_colors) {
|
|
|
|
} else if (g_options.amiga_colors) {
|
|
|
|
g_sys.set_palette_amiga(_colors_data + g_vars.level * 16, 0);
|
2018-12-16 13:34:03 +01:00
|
|
|
} else {
|
|
|
|
g_sys.set_screen_palette(g_res.palette, 0, 16, 8);
|
2018-08-12 16:55:27 +02:00
|
|
|
}
|
|
|
|
screen_load_graphics(g_options.cga_colors ? g_res.cga_lut_sqv : 0, g_options.cga_colors ? g_res.cga_lut_avt : 0);
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void init_level() {
|
2018-07-16 14:43:34 +02:00
|
|
|
static const uint16_t restart_xpos[] = { 720, 720, 912, 912, 336, 352, 288, 304, 960, 976, 64, 80 };
|
|
|
|
static const uint16_t restart_ypos[] = { 496, 496, 752, 752, 816, 816, 304, 304, 592, 592, 352, 352 };
|
|
|
|
if (g_vars.play_demo_flag) {
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].unk60 = 0;
|
|
|
|
}
|
2018-07-08 16:08:53 +02:00
|
|
|
int xpos = g_options.start_xpos16;
|
|
|
|
if (xpos < 0) {
|
2018-07-16 14:43:34 +02:00
|
|
|
xpos = g_vars.level_xpos[OBJECT_NUM_PLAYER1];
|
|
|
|
if (!g_vars.two_players_flag && (g_vars.objects[OBJECT_NUM_PLAYER1].unk60 || g_vars.objects[OBJECT_NUM_PLAYER2].unk60)) {
|
|
|
|
xpos = restart_xpos[g_vars.level * 2];
|
|
|
|
}
|
|
|
|
xpos = (xpos >> 4) - 10;
|
2018-07-08 16:08:53 +02:00
|
|
|
} else {
|
|
|
|
g_vars.level_xpos[OBJECT_NUM_PLAYER1] = (xpos << 4) + 10;
|
|
|
|
}
|
|
|
|
if (xpos < 0) {
|
|
|
|
xpos = 0;
|
|
|
|
}
|
|
|
|
g_vars.screen_tilemap_xorigin = xpos << 4;
|
|
|
|
|
|
|
|
int ypos = g_options.start_ypos16;
|
|
|
|
if (ypos < 0) {
|
2018-07-16 14:43:34 +02:00
|
|
|
ypos = g_vars.level_ypos[OBJECT_NUM_PLAYER1];
|
|
|
|
if (!g_vars.two_players_flag && (g_vars.objects[OBJECT_NUM_PLAYER1].unk60 || g_vars.objects[OBJECT_NUM_PLAYER2].unk60)) {
|
|
|
|
ypos = restart_ypos[g_vars.level * 2];
|
|
|
|
}
|
|
|
|
ypos = (ypos >> 4) - 6;
|
2018-07-08 16:08:53 +02:00
|
|
|
} else {
|
|
|
|
g_vars.level_ypos[OBJECT_NUM_PLAYER1] = (ypos << 4) + 6;
|
|
|
|
}
|
|
|
|
if (ypos < 0) {
|
|
|
|
ypos = 0;
|
|
|
|
}
|
|
|
|
g_vars.screen_tilemap_yorigin = ypos << 4;
|
|
|
|
|
|
|
|
if (g_vars.screen_tilemap_yorigin + (TILEMAP_SCREEN_H + 16) > g_vars.screen_tilemap_h) {
|
|
|
|
g_vars.screen_tilemap_yorigin = g_vars.screen_tilemap_h - (TILEMAP_SCREEN_H + 16);
|
|
|
|
} else {
|
|
|
|
g_vars.screen_tilemap_yorigin += 16;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < MAX_OBJECTS; ++i) {
|
|
|
|
if (!g_vars.two_players_flag) {
|
|
|
|
if (g_vars.player == PLAYER_JAKE) {
|
|
|
|
level_data[g_vars.level * MAX_OBJECTS + OBJECT_NUM_PLAYER1] = PLAYER_JAKE;
|
|
|
|
level_data[g_vars.level * MAX_OBJECTS + OBJECT_NUM_PLAYER2] = 100;
|
|
|
|
} else {
|
|
|
|
level_data[g_vars.level * MAX_OBJECTS + OBJECT_NUM_PLAYER1] = PLAYER_ELWOOD;
|
|
|
|
level_data[g_vars.level * MAX_OBJECTS + OBJECT_NUM_PLAYER2] = 100;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
level_data[g_vars.level * MAX_OBJECTS + OBJECT_NUM_PLAYER1] = PLAYER_JAKE;
|
|
|
|
level_data[g_vars.level * MAX_OBJECTS + OBJECT_NUM_PLAYER2] = PLAYER_ELWOOD;
|
|
|
|
}
|
|
|
|
struct object_t *obj = &g_vars.objects[i];
|
|
|
|
obj->type = level_data[g_vars.level * MAX_OBJECTS + i];
|
|
|
|
obj->anim_frame = 0;
|
|
|
|
obj->anim_num = 1;
|
|
|
|
if (obj->type != 100) {
|
|
|
|
const int num = obj->type * 116 / 4;
|
|
|
|
assert(num < 1189);
|
|
|
|
obj->animframes_ptr = animframes_059d + num;
|
|
|
|
} else {
|
|
|
|
obj->animframes_ptr = 0;
|
|
|
|
}
|
|
|
|
obj->facing_left = 0;
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
obj->xvelocity = 0;
|
|
|
|
obj->xmaxvelocity = 48;
|
|
|
|
obj->ymaxvelocity = 15;
|
|
|
|
if (obj->type < 2) {
|
|
|
|
if (obj->unk60 == 0) {
|
|
|
|
obj->xpos = g_vars.level_xpos[i];
|
|
|
|
obj->ypos = g_vars.level_ypos[i];
|
|
|
|
} else {
|
2018-07-16 14:43:34 +02:00
|
|
|
obj->xpos = restart_xpos[g_vars.level * 2 + obj->type];
|
|
|
|
obj->ypos = restart_ypos[g_vars.level * 2 + obj->type];
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
print_debug(DBG_GAME, "init_level obj #%d pos %d,%d", i, obj->xpos, obj->ypos);
|
|
|
|
} else {
|
|
|
|
obj->xpos = g_vars.level_xpos[i];
|
|
|
|
obj->ypos = g_vars.level_ypos[i];
|
|
|
|
}
|
|
|
|
obj->screen_xpos = obj->xpos - g_vars.screen_tilemap_xorigin;
|
|
|
|
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
|
|
|
|
obj->xacc = 0;
|
|
|
|
obj->yacc = 2;
|
|
|
|
obj->direction_lr = 0;
|
|
|
|
obj->direction_ud = 0;
|
|
|
|
obj->xpos16 = obj->xpos >> 4;
|
|
|
|
obj->ypos16 = obj->ypos >> 4;
|
|
|
|
obj->floor_ypos16 = 0;
|
|
|
|
// obj->unk26 = 0;
|
|
|
|
obj->yfriction = 0;
|
|
|
|
obj->unk2B = 0;
|
|
|
|
obj->sprite_type = 0;
|
|
|
|
obj->unk2D = 0;
|
|
|
|
obj->unk2E = 1;
|
|
|
|
obj->unk2F = 0;
|
|
|
|
if (obj->type != 100) {
|
|
|
|
obj->op = level_objtypes[obj->type];
|
|
|
|
} else {
|
|
|
|
obj->op = 0;
|
|
|
|
}
|
|
|
|
obj->grab_state = 0;
|
|
|
|
obj->grab_type = 0;
|
|
|
|
obj->special_anim = 0;
|
|
|
|
// obj->unk35 = 0;
|
|
|
|
obj->player_ydist = 0;
|
|
|
|
obj->player_xdist = 0;
|
|
|
|
obj->sprite3_counter = 0;
|
|
|
|
obj->visible_flag = 1;
|
|
|
|
if (obj->type == 100) {
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
}
|
|
|
|
obj->moving_direction = 0;
|
|
|
|
obj->unk3D = 0;
|
|
|
|
obj->carry_crate_flag = 0;
|
|
|
|
// obj->unk3F = 6;
|
|
|
|
// obj->unk41 = 0;
|
|
|
|
obj->unk42 = 0;
|
|
|
|
obj->tile2_flags = 0;
|
|
|
|
obj->tile1_flags = 0;
|
|
|
|
obj->tile0_flags = 0;
|
|
|
|
obj->tile012_xpos = 0;
|
|
|
|
obj->elevator_direction = -1;
|
2018-07-08 16:39:28 +02:00
|
|
|
obj->trigger3_num = 0;
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->trigger3 = 0;
|
|
|
|
obj->unk50 = 0;
|
|
|
|
// obj->unk4E = 0;
|
2018-12-16 13:34:03 +01:00
|
|
|
if (obj->restart_level_flag == 0 && obj->level_complete_flag == 0 && (g_vars.level == 0 || g_vars.play_demo_flag)) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.player1_dead_flag = 0;
|
|
|
|
g_vars.player2_scrolling_flag = 0;
|
|
|
|
obj->lifes_count = 3;
|
|
|
|
obj->data51 = 3;
|
|
|
|
obj->vinyls_count = 0;
|
2018-12-16 13:34:03 +01:00
|
|
|
} else if (obj->restart_level_flag != 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
--obj->lifes_count;
|
|
|
|
obj->data51 = 3;
|
|
|
|
obj->vinyls_count = 0;
|
|
|
|
}
|
2018-07-27 16:02:05 +02:00
|
|
|
if (g_options.cheats & CHEATS_UNLIMITED_LIFES) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->lifes_count = 3;
|
|
|
|
obj->data51 = 3;
|
|
|
|
}
|
2018-12-16 13:34:03 +01:00
|
|
|
obj->restart_level_flag = 0;
|
|
|
|
obj->level_complete_flag = 0;
|
2018-12-16 16:44:02 +01:00
|
|
|
obj->scrolling_lock_flag = 0;
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->unk54 = 0;
|
|
|
|
obj->unk55 = 0;
|
|
|
|
obj->unk56 = 0;
|
|
|
|
obj->collide_flag = 0;
|
2018-12-16 13:34:03 +01:00
|
|
|
// obj->unk5A = 0;
|
|
|
|
// obj->unk5C = 1;
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->unk5D = 0;
|
|
|
|
if (obj->ypos > g_vars.screen_tilemap_h) {
|
2018-12-16 16:44:02 +01:00
|
|
|
obj->scrolling_lock_flag = 1;
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
obj->blinking_counter = 0;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < MAX_DOORS; ++i) {
|
|
|
|
const uint8_t *p = &level_door[g_vars.level * 240 + i * 8];
|
|
|
|
g_vars.doors[i].src_x16 = READ_LE_UINT16(p);
|
|
|
|
g_vars.doors[i].src_y16 = READ_LE_UINT16(p + 2);
|
|
|
|
g_vars.doors[i].dst_x16 = READ_LE_UINT16(p + 4);
|
|
|
|
g_vars.doors[i].dst_y16 = READ_LE_UINT16(p + 6);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_redraw_tilemap(int xpos, int ypos) {
|
2018-08-12 14:27:20 +02:00
|
|
|
const int w = (TILEMAP_SCREEN_W / 16) + ((!g_options.dos_scrolling && (xpos & 15) != 0) ? 1 : 0);
|
|
|
|
const int h = (TILEMAP_SCREEN_H / 16) + ((!g_options.dos_scrolling && (ypos & 15) != 0) ? 1 : 0);
|
|
|
|
const int y = ypos >> 4;
|
|
|
|
const int x = xpos >> 4;
|
|
|
|
for (int j = 0; j < h; ++j) {
|
|
|
|
const uint8_t *ptr = lookup_sql(x, y + j);
|
|
|
|
for (int i = 0; i < w; ++i) {
|
2018-07-08 16:08:53 +02:00
|
|
|
const uint8_t num = *ptr++;
|
2018-08-12 15:44:16 +02:00
|
|
|
screen_draw_tile(g_vars.screen_tile_lut[num & 0x7F], num & 0x80, i, j);
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
g_vars.screen_tilemap_size_w = w;
|
|
|
|
g_vars.screen_tilemap_size_h = h;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_tiles_anim() {
|
|
|
|
for (int i = 0; level_tilesdata_1e8c[i]; ++i) {
|
|
|
|
uint8_t *p = level_tilesdata_1e8c[i];
|
|
|
|
if (p[0] == p[1]) {
|
|
|
|
p[0] = 1;
|
|
|
|
} else {
|
|
|
|
++p[0];
|
|
|
|
}
|
|
|
|
}
|
2018-08-12 14:27:20 +02:00
|
|
|
const int w = (TILEMAP_SCREEN_W / 16) + ((!g_options.dos_scrolling && (g_vars.screen_tilemap_xorigin & 15) != 0) ? 1 : 0);
|
|
|
|
const int h = (TILEMAP_SCREEN_H / 16) + ((!g_options.dos_scrolling && (g_vars.screen_tilemap_yorigin & 15) != 0) ? 1 : 0);
|
|
|
|
const int y = g_vars.screen_tilemap_yorigin >> 4;
|
|
|
|
const int x = g_vars.screen_tilemap_xorigin >> 4;
|
|
|
|
for (int j = 0; j < h; ++j) {
|
|
|
|
uint8_t *ptr = lookup_sql(x, y + j);
|
|
|
|
for (int i = 0; i < w; ++i, ++ptr) {
|
2018-07-08 16:08:53 +02:00
|
|
|
uint8_t num = *ptr;
|
|
|
|
struct trigger_t *t = &g_res.triggers[num];
|
|
|
|
const uint8_t *data = t->op_table2;
|
|
|
|
if (!data) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (t->tile_index != 0) {
|
|
|
|
num = data[t->tile_index];
|
|
|
|
*ptr = num;
|
|
|
|
t->unk16 = num;
|
|
|
|
} else {
|
|
|
|
const int current = data[0];
|
|
|
|
num = data[current + 1];
|
2018-07-13 14:34:11 +02:00
|
|
|
*ptr = num;
|
2018-07-08 16:08:53 +02:00
|
|
|
t->unk16 = num;
|
|
|
|
}
|
2018-08-12 15:44:16 +02:00
|
|
|
screen_draw_tile(g_vars.screen_tile_lut[num & 0x7F], num & 0x80, i, j);
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_scrolling2() {
|
|
|
|
if (g_vars.screen_scrolling_dirmask & 2) {
|
|
|
|
if (g_vars.screen_tilemap_w * 16 - TILEMAP_SCREEN_W > g_vars.screen_tilemap_xorigin) {
|
|
|
|
g_vars.screen_tilemap_xorigin += 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (g_vars.screen_scrolling_dirmask & 1) {
|
|
|
|
if (g_vars.screen_tilemap_xorigin > 0) {
|
|
|
|
g_vars.screen_tilemap_xorigin -= 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (g_vars.screen_scrolling_dirmask & 8) {
|
|
|
|
if (g_vars.screen_tilemap_yorigin > 0) {
|
|
|
|
g_vars.screen_tilemap_yorigin -= 16;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (g_vars.screen_scrolling_dirmask & 4) {
|
|
|
|
if (g_vars.screen_tilemap_h - TILEMAP_SCREEN_H > g_vars.screen_tilemap_yorigin) {
|
|
|
|
g_vars.screen_tilemap_yorigin += 16;
|
|
|
|
}
|
|
|
|
}
|
2018-12-16 16:44:02 +01:00
|
|
|
const struct object_t *obj = &g_vars.objects[OBJECT_NUM_PLAYER1];
|
|
|
|
if (!g_options.dos_scrolling && !obj->scrolling_lock_flag) {
|
2018-08-12 14:27:20 +02:00
|
|
|
const int x1 = TILEMAP_SCROLL_W * 2;
|
|
|
|
const int x2 = TILEMAP_SCREEN_W - TILEMAP_SCROLL_W * 2;
|
|
|
|
if (obj->screen_xpos > x2) {
|
|
|
|
const int dx = obj->screen_xpos - x2;
|
|
|
|
g_vars.screen_tilemap_xorigin += dx;
|
|
|
|
if (g_vars.screen_tilemap_xorigin + TILEMAP_SCREEN_W > g_vars.screen_tilemap_w * 16) {
|
|
|
|
g_vars.screen_tilemap_xorigin = g_vars.screen_tilemap_w * 16 - TILEMAP_SCREEN_W;
|
|
|
|
}
|
|
|
|
} else if (obj->screen_xpos < x1) {
|
|
|
|
const int dx = obj->screen_xpos - x1;
|
|
|
|
g_vars.screen_tilemap_xorigin += dx;
|
|
|
|
if (g_vars.screen_tilemap_xorigin < 0) {
|
|
|
|
g_vars.screen_tilemap_xorigin = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const int y1 = 64;
|
|
|
|
const int y2 = 144;
|
|
|
|
if (obj->screen_ypos > y2) {
|
|
|
|
const int dy = obj->screen_ypos - y2;
|
|
|
|
g_vars.screen_tilemap_yorigin += dy;
|
|
|
|
if (g_vars.screen_tilemap_yorigin + TILEMAP_SCREEN_H > g_vars.screen_tilemap_h) {
|
|
|
|
g_vars.screen_tilemap_yorigin = g_vars.screen_tilemap_h - TILEMAP_SCREEN_H;
|
|
|
|
}
|
|
|
|
} else if (obj->screen_ypos < y1) {
|
|
|
|
const int dy = obj->screen_ypos - y1;
|
|
|
|
g_vars.screen_tilemap_yorigin += dy;
|
|
|
|
if (g_vars.screen_tilemap_yorigin < 0) {
|
|
|
|
g_vars.screen_tilemap_yorigin = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_vars.screen_tilemap_xoffset = -(g_vars.screen_tilemap_xorigin & 15);
|
|
|
|
g_vars.screen_tilemap_yoffset = -(g_vars.screen_tilemap_yorigin & 15);
|
|
|
|
}
|
2018-07-08 16:08:53 +02:00
|
|
|
do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin);
|
2018-07-08 16:39:28 +02:00
|
|
|
if ((g_vars.level_loop_counter & 3) == 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
do_level_update_tiles_anim();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_level_drop_grabbed_object(struct object_t *obj) {
|
|
|
|
struct object_t *obj37 = &g_vars.objects[37];
|
|
|
|
if (obj->type != 0 && g_vars.two_players_flag) {
|
|
|
|
obj37 = &g_vars.objects[36];
|
|
|
|
}
|
|
|
|
if (obj37->type != 100) {
|
|
|
|
obj37->grab_state = 3;
|
|
|
|
obj->grab_state = 0;
|
|
|
|
obj->unk3D = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_add_sprite1_case0(struct object_t *obj) {
|
|
|
|
const uint8_t *anim_data = 0;
|
|
|
|
|
|
|
|
assert(obj->animframes_ptr);
|
|
|
|
|
|
|
|
if (obj->unk2F != 0 && obj->direction_ud == 0 && obj->direction_lr == 0) {
|
|
|
|
anim_data = obj->animframes_ptr[24 / 4];
|
|
|
|
} else if (triggers_get_tile_type(obj->xpos16, obj->ypos16) == 4) {
|
|
|
|
anim_data = obj->animframes_ptr[28 / 4];
|
|
|
|
} else {
|
2018-08-12 14:27:20 +02:00
|
|
|
if (abs(obj->yvelocity) > 10 && obj->yvelocity > 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
anim_data = obj->animframes_ptr[112 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[8 / 4];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->grab_state != 0) {
|
|
|
|
if (obj->grab_type == 0) {
|
|
|
|
anim_data = obj->animframes_ptr[52 / 4];
|
|
|
|
} else if (obj->grab_type == 2 || obj->grab_type == 8) {
|
|
|
|
anim_data = obj->animframes_ptr[32 / 4];
|
|
|
|
obj->xmaxvelocity = 48;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->anim_num < anim_data[0]) {
|
|
|
|
++obj->anim_num;
|
|
|
|
} else {
|
|
|
|
obj->anim_num = 1;
|
|
|
|
}
|
|
|
|
obj->anim_frame = anim_data[obj->anim_num];
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_add_sprite1_case1(struct object_t *obj) {
|
|
|
|
const uint8_t *anim_data = 0;
|
|
|
|
assert(obj->animframes_ptr);
|
|
|
|
obj->xmaxvelocity = 48;
|
|
|
|
if ((obj->direction_lr & 1) != 0) {
|
|
|
|
if (obj->unk2E == 0) {
|
|
|
|
anim_data = obj->animframes_ptr[16 / 4];
|
|
|
|
obj->xmaxvelocity = 24;
|
|
|
|
} else if (obj->grab_state != 0) {
|
|
|
|
if (obj->grab_type == 0 || obj->grab_type == 8) {
|
|
|
|
anim_data = obj->animframes_ptr[48 / 4];
|
|
|
|
} else if (obj->grab_type == 2) {
|
|
|
|
anim_data = obj->animframes_ptr[32 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[4 / 4];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[4 / 4];
|
|
|
|
}
|
|
|
|
} else if ((obj->direction_lr & 2) != 0) {
|
|
|
|
if (obj->unk2E == 0) {
|
|
|
|
anim_data = obj->animframes_ptr[16 / 4];
|
|
|
|
obj->xmaxvelocity = 24;
|
|
|
|
} else if (obj->grab_state != 0) {
|
|
|
|
if (obj->grab_type == 0 || obj->grab_type == 8) {
|
|
|
|
anim_data = obj->animframes_ptr[48 / 4];
|
|
|
|
} else if (obj->grab_type == 2) {
|
|
|
|
anim_data = obj->animframes_ptr[32 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[4 / 4];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[4 / 4];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (obj->unk2E == 0) {
|
|
|
|
anim_data = obj->animframes_ptr[12 / 4];
|
|
|
|
} else if (obj->grab_state != 0) {
|
|
|
|
if (obj->grab_type == 0 || obj->grab_type == 8) {
|
|
|
|
anim_data = obj->animframes_ptr[44 / 4];
|
|
|
|
} else if (obj->grab_type == 2) {
|
|
|
|
anim_data = obj->animframes_ptr[32 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[4 / 4];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[0];
|
|
|
|
}
|
|
|
|
if (obj->unk2D < 8) {
|
2018-08-12 14:27:20 +02:00
|
|
|
if (abs(obj->xvelocity) > 8) {
|
2018-07-08 16:08:53 +02:00
|
|
|
anim_data = obj->animframes_ptr[24 / 4];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->anim_num < anim_data[0]) {
|
|
|
|
++obj->anim_num;
|
|
|
|
} else {
|
|
|
|
obj->anim_num = 1;
|
|
|
|
}
|
|
|
|
obj->anim_frame = anim_data[obj->anim_num];
|
|
|
|
}
|
|
|
|
|
|
|
|
// ladder
|
|
|
|
static void do_level_add_sprite1_case2(struct object_t *obj) {
|
|
|
|
struct object_t *obj35 = &g_vars.objects[35];
|
|
|
|
struct object_t *obj37 = &g_vars.objects[37];
|
|
|
|
if (obj->type != 0 && g_vars.two_players_flag) {
|
|
|
|
obj35 = &g_vars.objects[34];
|
|
|
|
obj37 = &g_vars.objects[36];
|
|
|
|
}
|
|
|
|
if (obj37->type != 100 && obj37->grab_type != 0) {
|
|
|
|
do_level_drop_grabbed_object(obj);
|
|
|
|
}
|
|
|
|
if (obj->grab_type == 8) {
|
|
|
|
do_level_drop_grabbed_object(obj);
|
|
|
|
}
|
|
|
|
if (obj35->type != 100) {
|
|
|
|
obj35->type = 100;
|
|
|
|
}
|
|
|
|
const uint8_t *anim_data = 0;
|
|
|
|
obj->unk3D = 0;
|
|
|
|
int tile_num = triggers_get_tile_type(obj->xpos16, obj->ypos16);
|
|
|
|
if (obj->direction_ud != 0) {
|
|
|
|
if (tile_num == 7) {
|
|
|
|
anim_data = obj->animframes_ptr[20 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[0];
|
|
|
|
}
|
|
|
|
} else if (obj->direction_lr != 0) {
|
|
|
|
if (tile_num == 7) {
|
|
|
|
anim_data = obj->animframes_ptr[20 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[4 / 4];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (tile_num == 7) {
|
|
|
|
anim_data = obj->animframes_ptr[36 / 4];
|
|
|
|
} else if (obj->grab_state != 0) {
|
|
|
|
if (obj->grab_type == 0 || obj->grab_type == 8) {
|
|
|
|
anim_data = obj->animframes_ptr[24 / 4];
|
|
|
|
} else if (obj->grab_type == 2) {
|
|
|
|
anim_data = obj->animframes_ptr[32 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[0];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[0];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->anim_num < anim_data[0]) {
|
2018-07-08 16:39:28 +02:00
|
|
|
obj->anim_num += (g_vars.level_loop_counter & 1);
|
2018-07-08 16:08:53 +02:00
|
|
|
} else {
|
|
|
|
obj->anim_num = 1;
|
|
|
|
}
|
|
|
|
obj->anim_frame = anim_data[obj->anim_num];
|
|
|
|
}
|
|
|
|
|
2018-07-12 13:21:15 +02:00
|
|
|
static void do_level_add_sprite1_case3(struct object_t *obj) {
|
|
|
|
struct object_t *obj35 = &g_vars.objects[35];
|
|
|
|
struct object_t *obj37 = &g_vars.objects[37];
|
|
|
|
if (obj->type != 0 && g_vars.two_players_flag) {
|
|
|
|
obj35 = &g_vars.objects[34];
|
|
|
|
obj37 = &g_vars.objects[36];
|
|
|
|
}
|
|
|
|
if (obj37->type != 100 && obj37->grab_type != 0) {
|
|
|
|
do_level_drop_grabbed_object(obj);
|
|
|
|
}
|
|
|
|
obj->unk3D = 0;
|
|
|
|
if (obj35->type != 100) {
|
|
|
|
obj35->type = 100;
|
|
|
|
obj35->visible_flag = 0;
|
|
|
|
}
|
|
|
|
const uint8_t *anim_data = 0;
|
|
|
|
obj->unk3D = 0;
|
|
|
|
int tile_num = triggers_get_tile_type(obj->xpos16, obj->ypos16);
|
|
|
|
obj->xmaxvelocity = 8;
|
|
|
|
obj->xacc = 0;
|
|
|
|
obj->unk2D = 10;
|
|
|
|
if (obj->direction_lr != 0) {
|
|
|
|
if (obj->direction_ud != 0) {
|
|
|
|
if (tile_num == 6) {
|
|
|
|
anim_data = obj->animframes_ptr[56 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[0];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (tile_num == 6) {
|
|
|
|
anim_data = obj->animframes_ptr[68 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[4 / 4];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (obj->direction_ud != 0) {
|
|
|
|
if (tile_num == 6) {
|
|
|
|
anim_data = obj->animframes_ptr[56 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[0];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (tile_num == 6) {
|
|
|
|
anim_data = obj->animframes_ptr[68 / 4];
|
|
|
|
} else {
|
|
|
|
anim_data = obj->animframes_ptr[4 / 4];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->anim_num < anim_data[0]) {
|
|
|
|
obj->anim_num += (g_vars.level_loop_counter & 1);
|
|
|
|
} else {
|
|
|
|
obj->anim_num = 1;
|
|
|
|
}
|
|
|
|
obj->anim_frame = anim_data[obj->anim_num];
|
|
|
|
}
|
|
|
|
|
2018-07-08 16:08:53 +02:00
|
|
|
// swimming
|
|
|
|
static void do_level_add_sprite1_case4(struct object_t *obj) {
|
|
|
|
struct object_t *obj35 = &g_vars.objects[35];
|
|
|
|
struct object_t *obj37 = &g_vars.objects[37];
|
|
|
|
if (obj->type != 0 && g_vars.two_players_flag) {
|
|
|
|
obj35 = &g_vars.objects[34];
|
|
|
|
obj37 = &g_vars.objects[36];
|
|
|
|
}
|
|
|
|
if (obj37->type != 100) {
|
|
|
|
do_level_drop_grabbed_object(obj);
|
|
|
|
}
|
|
|
|
const uint8_t *anim_data = 0;
|
|
|
|
obj->unk2F = 0;
|
|
|
|
int tile0_num = triggers_get_tile_type(obj->xpos16, obj->ypos16 - 2);
|
|
|
|
// int tile1_num = triggers_get_tile_type(obj->xpos16, obj->ypos16 - 1);
|
|
|
|
// int tile2_num = triggers_get_tile_type(obj->xpos16, obj->ypos16);
|
|
|
|
obj->xmaxvelocity = 16;
|
|
|
|
if (obj->direction_lr != 0) {
|
|
|
|
if (obj->direction_ud == 1) {
|
|
|
|
if (tile0_num == 0) {
|
|
|
|
obj->unk3D = 1;
|
|
|
|
} else {
|
|
|
|
obj->unk3D = 2;
|
|
|
|
}
|
|
|
|
} else if (obj->direction_ud == 2) {
|
|
|
|
obj->unk3D = 0;
|
|
|
|
} else {
|
|
|
|
obj->unk3D = 1;
|
|
|
|
}
|
|
|
|
anim_data = obj->animframes_ptr[92 / 4];
|
|
|
|
} else {
|
|
|
|
if (obj->direction_ud == 1) {
|
|
|
|
if (tile0_num == 0) {
|
|
|
|
obj->unk3D = 1;
|
|
|
|
} else {
|
|
|
|
obj->unk3D = 2;
|
|
|
|
}
|
|
|
|
anim_data = obj->animframes_ptr[100 / 4];
|
|
|
|
} else if (obj->direction_ud == 2) {
|
|
|
|
obj->unk3D = 0;
|
|
|
|
anim_data = obj->animframes_ptr[100 / 4];
|
|
|
|
} else {
|
|
|
|
obj->unk3D = 1;
|
|
|
|
anim_data = obj->animframes_ptr[96 / 4];
|
|
|
|
if (triggers_get_tile_type(obj->xpos16, obj->ypos16 + 1) == 13) {
|
|
|
|
anim_data = obj->animframes_ptr[104 / 4];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->anim_num < anim_data[0]) {
|
|
|
|
++obj->anim_num;
|
|
|
|
} else {
|
|
|
|
obj->anim_num = 1;
|
|
|
|
}
|
|
|
|
obj->anim_frame = anim_data[obj->anim_num];
|
|
|
|
if (tile0_num >= 11 && obj35->type == 100) {
|
|
|
|
play_sound(SOUND_15);
|
|
|
|
obj35->type = 2;
|
|
|
|
obj35->grab_type = 7;
|
|
|
|
obj35->visible_flag = 1;
|
|
|
|
if (obj->facing_left) {
|
|
|
|
obj35->xpos = obj->xpos - 8;
|
|
|
|
obj35->screen_xpos = obj->screen_xpos - 8;
|
|
|
|
} else {
|
|
|
|
obj35->xpos = obj->xpos + 8;
|
|
|
|
obj35->screen_xpos = obj->screen_xpos + 8;
|
|
|
|
}
|
|
|
|
obj35->ypos = obj->ypos - 8;
|
|
|
|
obj35->screen_ypos = obj->screen_ypos - 8;
|
|
|
|
obj35->xpos16 = obj->xpos16;
|
|
|
|
obj35->ypos16 = obj->ypos16;
|
|
|
|
obj35->anim_num = 1;
|
2018-07-27 16:02:05 +02:00
|
|
|
obj35->animframes_ptr = animframes_059d + (obj35->type * 116 / 4);
|
2018-07-08 16:08:53 +02:00
|
|
|
} else {
|
|
|
|
obj35->unk2E = 0;
|
|
|
|
const int num = triggers_get_tile_type(obj35->xpos16, obj35->ypos16);
|
|
|
|
if (num == 11 || num == 12) {
|
|
|
|
obj35->yacc = -3;
|
|
|
|
obj35->yvelocity = -3;
|
|
|
|
obj35->ypos16 = obj35->ypos >> 4;
|
|
|
|
obj35->xpos16 = obj35->xpos >> 4;
|
|
|
|
} else {
|
|
|
|
obj35->type = 100;
|
|
|
|
obj35->visible_flag = 0;
|
|
|
|
obj35->grab_type = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_add_sprite1(struct object_t *obj) {
|
|
|
|
print_debug(DBG_GAME, "add_sprite1 obj->type %d", obj->type);
|
|
|
|
if (obj->type == 100) {
|
|
|
|
// print_warning("do_level_add_sprite1: obj.type 100");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
obj->sprite3_counter = 0;
|
|
|
|
switch (obj->sprite_type) {
|
|
|
|
case 0:
|
|
|
|
do_level_add_sprite1_case0(obj);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
do_level_add_sprite1_case1(obj);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
do_level_add_sprite1_case2(obj);
|
|
|
|
break;
|
2018-07-12 13:21:15 +02:00
|
|
|
case 3:
|
|
|
|
do_level_add_sprite1_case3(obj);
|
|
|
|
break;
|
2018-07-08 16:08:53 +02:00
|
|
|
case 4:
|
|
|
|
do_level_add_sprite1_case4(obj);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
print_warning("do_level_add_sprite1: unhandled sprite_type %d", obj->sprite_type);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (obj->type != 100) {
|
2018-07-08 16:39:28 +02:00
|
|
|
if (obj->blinking_counter != 0 && (g_vars.level_loop_counter & 1) != 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
if (obj->facing_left == 0) {
|
|
|
|
screen_add_game_sprite3(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame, obj->blinking_counter);
|
|
|
|
} else {
|
|
|
|
screen_add_game_sprite4(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame, obj->blinking_counter);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (obj->facing_left == 0) {
|
|
|
|
screen_add_game_sprite1(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame);
|
|
|
|
} else {
|
|
|
|
screen_add_game_sprite2(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_add_sprite2(struct object_t *obj) {
|
|
|
|
print_debug(DBG_GAME, "add_sprite2 obj->type %d", obj->type);
|
2018-07-27 16:02:05 +02:00
|
|
|
assert(obj->type == 2);
|
|
|
|
assert(obj->animframes_ptr);
|
2018-07-08 16:08:53 +02:00
|
|
|
const uint8_t *anim_data = obj->animframes_ptr[obj->grab_type];
|
|
|
|
if (obj->anim_num < anim_data[0]) {
|
|
|
|
++obj->anim_num;
|
|
|
|
} else {
|
|
|
|
obj->anim_num = 1;
|
|
|
|
}
|
|
|
|
obj->anim_frame = anim_data[obj->anim_num];
|
|
|
|
if (obj->grab_type >= 16 && obj->grab_type != 23) {
|
|
|
|
obj->yacc = -1;
|
|
|
|
obj->yvelocity = -1;
|
|
|
|
obj->facing_left = 0;
|
|
|
|
if (obj->data5F < 30) {
|
|
|
|
++obj->data5F;
|
|
|
|
} else {
|
|
|
|
obj->data5F = 0;
|
|
|
|
obj->type = 100;
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
obj->grab_type = 0;
|
|
|
|
obj->yacc = 0;
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->type != 100) {
|
|
|
|
if (obj->facing_left == 0) {
|
|
|
|
screen_add_game_sprite1(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame);
|
|
|
|
} else {
|
|
|
|
screen_add_game_sprite2(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_add_sprite3(struct object_t *obj) {
|
|
|
|
print_debug(DBG_GAME, "add_sprite3 obj->type %d", obj->type);
|
|
|
|
if (!obj->animframes_ptr) return;
|
|
|
|
const uint8_t *anim_data = obj->animframes_ptr[obj->special_anim];
|
|
|
|
if (obj->sprite3_counter == 0) {
|
|
|
|
obj->anim_num = 1;
|
|
|
|
obj->anim_frame = anim_data[obj->anim_num];
|
|
|
|
++obj->sprite3_counter;
|
|
|
|
} else if (obj->sprite3_counter == 1) {
|
|
|
|
if (obj->anim_num < anim_data[0]) {
|
|
|
|
if (obj->collide_flag == 0) {
|
2018-07-08 16:39:28 +02:00
|
|
|
obj->anim_num += (g_vars.level_loop_counter & 1);
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
obj->anim_frame = anim_data[obj->anim_num];
|
|
|
|
} else {
|
|
|
|
if (obj->special_anim != 16) {
|
|
|
|
obj->anim_num = 1;
|
|
|
|
obj->special_anim = 0;
|
|
|
|
obj->sprite3_counter = 0;
|
2018-12-16 13:34:03 +01:00
|
|
|
// } else if (obj->unk5A != 0) {
|
|
|
|
// obj->unk5C = 4;
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->special_anim == 18 && obj->anim_num > 8 && (g_vars.inp_key_up != 0 /* || g_inp_key_T != 0*/)) {
|
|
|
|
obj->anim_num = 1;
|
|
|
|
obj->special_anim = 0;
|
|
|
|
obj->sprite3_counter = 0;
|
2018-12-16 13:34:03 +01:00
|
|
|
// if (obj->unk5A != 0) {
|
|
|
|
// obj->unk5C = 4;
|
|
|
|
// }
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->type != 100) {
|
2018-07-08 16:39:28 +02:00
|
|
|
if (obj->blinking_counter != 0 && (g_vars.level_loop_counter & 1) != 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
if (obj->facing_left == 0) {
|
|
|
|
screen_add_game_sprite3(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame, obj->blinking_counter);
|
|
|
|
} else {
|
|
|
|
screen_add_game_sprite4(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame, obj->blinking_counter);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (obj->facing_left == 0) {
|
|
|
|
screen_add_game_sprite1(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame);
|
|
|
|
} else {
|
|
|
|
screen_add_game_sprite2(obj->screen_xpos, obj->screen_ypos + 1, obj->anim_frame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_level_update_tile(int x, int y, int num) {
|
|
|
|
uint8_t *ptr = lookup_sql(x, y);
|
|
|
|
*ptr = num;
|
2018-08-12 15:44:16 +02:00
|
|
|
screen_draw_tile(g_vars.screen_tile_lut[num & 0x7F], num & 0x80, x, y);
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_reset_tiles(struct object_t *obj, int dy) {
|
|
|
|
int i, y, var2, var4;
|
|
|
|
|
|
|
|
y = obj->ypos16 + dy;
|
|
|
|
var2 = triggers_get_next_tile_num(obj->xpos16, y);
|
|
|
|
i = 1;
|
|
|
|
do {
|
|
|
|
var4 = triggers_get_next_tile_num(obj->xpos16 + i, y);
|
|
|
|
++i;
|
|
|
|
} while (var4 == var2);
|
|
|
|
do_level_update_tile(obj->xpos16, y, var4);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int do_level_throw_crate(struct object_t *obj) {
|
|
|
|
if (obj->screen_xpos > TILEMAP_SCREEN_W + 16 || obj->screen_xpos <= -16) {
|
|
|
|
obj->moving_direction = 1;
|
|
|
|
}
|
|
|
|
if (obj->xpos < 16 || obj->xpos > g_vars.screen_tilemap_w * 16 - 16) {
|
|
|
|
obj->moving_direction = 1;
|
|
|
|
}
|
|
|
|
if (obj->moving_direction == 0) {
|
|
|
|
if (obj->facing_left == 0) {
|
|
|
|
obj->direction_lr |= 1;
|
|
|
|
obj->xvelocity = 128;
|
|
|
|
} else {
|
|
|
|
obj->direction_lr |= 2;
|
|
|
|
obj->xvelocity = -128;
|
|
|
|
}
|
|
|
|
obj->yacc = 0;
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
obj->xmaxvelocity = 128;
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
obj->type = 100;
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
obj->xvelocity = 0;
|
|
|
|
obj->unk5D = 0;
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_grabbed_object_type8(struct object_t *obj) {
|
|
|
|
obj->direction_ud = 0;
|
|
|
|
if (obj->screen_ypos < 32 || obj->ypos - 48 <= 0) {
|
|
|
|
obj->type = 100;
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
obj->grab_state = 0;
|
|
|
|
obj->grab_type = 0;
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
obj->yacc = 2;
|
|
|
|
obj->unk5D = 0;
|
|
|
|
} else {
|
|
|
|
obj->yacc = -4;
|
|
|
|
obj->yvelocity = -4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_grabbed_object(struct object_t *obj) {
|
|
|
|
struct object_t *obj37 = &g_vars.objects[37];
|
|
|
|
|
|
|
|
if (obj->type != 0 && g_vars.two_players_flag != 0) {
|
|
|
|
--obj37;
|
|
|
|
}
|
|
|
|
switch (obj->grab_state) {
|
|
|
|
case 0:
|
|
|
|
if (obj37->type == 100) {
|
|
|
|
obj->carry_crate_flag = 0;
|
|
|
|
obj->grab_state = 1;
|
|
|
|
play_sound(SOUND_3);
|
|
|
|
if (obj->unk2E == 0) {
|
|
|
|
obj->unk2E = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
obj37->type = 2;
|
|
|
|
obj37->visible_flag = 1;
|
|
|
|
obj37->xpos = obj->xpos;
|
|
|
|
obj37->ypos = obj->ypos - 30;
|
|
|
|
obj37->screen_xpos = obj->screen_xpos;
|
|
|
|
obj37->screen_ypos = obj->screen_ypos - 30;
|
|
|
|
obj37->animframes_ptr = animframes_059d + (obj37->type * 116 / 4);
|
|
|
|
obj37->anim_num = 1;
|
|
|
|
obj37->facing_left = obj->facing_left;
|
|
|
|
obj37->sprite_type = obj->sprite_type;
|
|
|
|
obj37->yvelocity = obj->yvelocity;
|
|
|
|
obj37->xvelocity = obj->xvelocity;
|
|
|
|
obj37->yacc = obj->yacc;
|
|
|
|
obj37->xacc = obj->xacc;
|
|
|
|
obj37->unk5D = obj->type;
|
|
|
|
obj37->xpos16 = obj->xpos16;
|
|
|
|
obj37->ypos16 = obj->ypos16;
|
|
|
|
obj->grab_state = 1;
|
|
|
|
if (obj->carry_crate_flag != 0) {
|
|
|
|
play_sound(SOUND_5);
|
|
|
|
obj->grab_state = 0;
|
|
|
|
obj37->grab_state = 2;
|
|
|
|
obj37->ypos += 10;
|
|
|
|
obj->unk3D = 0;
|
|
|
|
obj37->moving_direction = 0;
|
|
|
|
obj->carry_crate_flag = 0;
|
|
|
|
}
|
|
|
|
if (triggers_get_tile_type(obj37->xpos16, obj37->ypos16 - 2) > 5 || obj37->ypos < 32 || obj37->xpos < 16) {
|
|
|
|
if (obj37->grab_type == 2) {
|
|
|
|
obj->grab_state = 0;
|
|
|
|
obj->unk3D = 0;
|
|
|
|
obj->carry_crate_flag = 0;
|
|
|
|
obj37->grab_state = 3;
|
|
|
|
obj37->moving_direction = 0;
|
|
|
|
obj37->anim_num = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
if (obj->grab_type == 0) {
|
|
|
|
if (do_level_throw_crate(obj)) {
|
|
|
|
obj->grab_state = 0;
|
|
|
|
}
|
|
|
|
} else if (obj->grab_type == 2 || obj->grab_type == 8) {
|
|
|
|
do_level_update_grabbed_object_type8(obj);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
if (obj->grab_type == 2 || obj->grab_type == 3) {
|
|
|
|
obj->grab_type = 3;
|
|
|
|
if (obj->anim_num >= 8) {
|
|
|
|
obj->type = 100;
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
obj->grab_state = 0;
|
|
|
|
obj->grab_type = 0;
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
obj->yacc = 2;
|
|
|
|
obj37->unk5D = 0;
|
|
|
|
}
|
|
|
|
} else if (obj->grab_type == 8) {
|
|
|
|
do_level_update_grabbed_object_type8(obj);
|
|
|
|
} else {
|
|
|
|
obj->type = 100;
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
obj->grab_state = 0;
|
|
|
|
obj->grab_type = 0;
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
obj->yacc = 2;
|
|
|
|
obj37->unk5D = 0;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
print_warning("do_level_update_grabbed_object: unhandled grab_state %d", obj->grab_state);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_level_update_panel_lifes(struct object_t *obj) {
|
|
|
|
struct object_t *obj39 = &g_vars.objects[OBJECT_NUM_PLAYER1];
|
|
|
|
struct object_t *obj40 = &g_vars.objects[OBJECT_NUM_PLAYER2];
|
|
|
|
if (!g_vars.two_players_flag) {
|
|
|
|
static const uint16_t data[] = { 216, 232, 248, 264, 280, 296 };
|
|
|
|
for (int i = 0; i < obj->data51; ++i) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[120 + i], 12, 16, data[i], 161);
|
|
|
|
}
|
|
|
|
for (int i = obj->data51; i < 5; ++i) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[119 + i], 12, 16, data[i], 161);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
static const uint8_t data[] = { 18, 21, 20, 19, 19, 19 };
|
|
|
|
if (obj->type == PLAYER_JAKE) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[101 + data[obj->data51]], 12, 16, 80, 161);
|
|
|
|
} else {
|
|
|
|
screen_draw_frame(g_res.spr_frames[101 + data[obj->data51]], 12, 16, 248, 161);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->data51 == 0) { // health
|
|
|
|
if (!g_vars.two_players_flag) {
|
2018-12-16 13:34:03 +01:00
|
|
|
obj->restart_level_flag = 1;
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.game_over_flag = 1;
|
|
|
|
} else {
|
|
|
|
if (obj->lifes_count != 1) {
|
|
|
|
--obj->lifes_count;
|
|
|
|
obj->data51 = 3;
|
|
|
|
do_level_update_panel_lifes(obj);
|
|
|
|
if (obj->type == PLAYER_JAKE) {
|
|
|
|
screen_draw_number(obj->lifes_count - 1, 48, 163, 2);
|
|
|
|
} else {
|
|
|
|
screen_draw_number(obj->lifes_count - 1, 216, 163, 2);
|
|
|
|
}
|
|
|
|
} else if (obj->type == PLAYER_JAKE) {
|
|
|
|
g_vars.player2_scrolling_flag = 1;
|
2018-08-12 14:27:20 +02:00
|
|
|
g_vars.switch_player_scrolling_flag = 1;
|
2018-07-08 16:08:53 +02:00
|
|
|
obj39->special_anim = 16;
|
|
|
|
g_vars.player2_dead_flag = 1;
|
|
|
|
screen_draw_frame(g_res.spr_frames[116], 12, 16, 8, 161);
|
|
|
|
} else { // PLAYER_ELWOOD
|
|
|
|
g_vars.player2_scrolling_flag = 0;
|
2018-08-12 14:27:20 +02:00
|
|
|
g_vars.switch_player_scrolling_flag = 1;
|
2018-07-08 16:08:53 +02:00
|
|
|
obj40->special_anim = 16;
|
|
|
|
g_vars.player1_dead_flag = 1;
|
|
|
|
screen_draw_frame(g_res.spr_frames[118], 12, 16, 176, 161);
|
|
|
|
}
|
|
|
|
if (g_vars.player2_dead_flag && g_vars.player1_dead_flag) {
|
|
|
|
g_vars.game_over_flag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_panel_vinyls(struct object_t *obj) {
|
|
|
|
if (obj->vinyls_count > 99) {
|
|
|
|
obj->vinyls_count -= 100;
|
|
|
|
if (!g_vars.two_players_flag && obj->data51 < 5) {
|
|
|
|
++obj->data51;
|
|
|
|
}
|
|
|
|
if (g_vars.two_players_flag && obj->data51 < 3) {
|
|
|
|
++obj->data51;
|
|
|
|
}
|
|
|
|
do_level_update_panel_lifes(obj);
|
|
|
|
}
|
|
|
|
if (!g_vars.two_players_flag) {
|
|
|
|
if (obj->vinyls_count != g_vars.vinyls_count) {
|
|
|
|
screen_draw_number(obj->vinyls_count, 192, 163, 2);
|
|
|
|
}
|
|
|
|
g_vars.vinyls_count = obj->vinyls_count;
|
|
|
|
} else {
|
|
|
|
if (obj->vinyls_count != g_vars.vinyls_count) {
|
|
|
|
screen_draw_number(obj->vinyls_count, 112, 163, 2);
|
|
|
|
}
|
|
|
|
g_vars.vinyls_count = obj->vinyls_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_panel_2nd_player() {
|
|
|
|
struct object_t *obj = &g_vars.objects[OBJECT_NUM_PLAYER2];
|
|
|
|
if (obj->vinyls_count > 99) {
|
|
|
|
obj->vinyls_count = 0;
|
|
|
|
if (!g_vars.two_players_flag && obj->data51 < 5) {
|
|
|
|
++obj->data51;
|
|
|
|
}
|
|
|
|
if (g_vars.two_players_flag && obj->data51 < 3) {
|
|
|
|
++obj->data51;
|
|
|
|
}
|
|
|
|
do_level_update_panel_lifes(obj);
|
|
|
|
}
|
|
|
|
if (obj->vinyls_count != g_vars.vinyls_count) {
|
|
|
|
screen_draw_number(obj->vinyls_count, 280, 163, 2);
|
|
|
|
g_vars.vinyls_count = obj->vinyls_count;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_level_panel() {
|
|
|
|
struct object_t *obj39 = &g_vars.objects[OBJECT_NUM_PLAYER1];
|
|
|
|
struct object_t *obj40 = &g_vars.objects[OBJECT_NUM_PLAYER2];
|
|
|
|
g_vars.vinyls_count = 0;
|
|
|
|
if (!g_vars.two_players_flag) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[123], 12, 320, 0, -12);
|
|
|
|
screen_draw_frame(g_res.spr_frames[124], 12, 320, 0, 161);
|
|
|
|
if (g_vars.player == PLAYER_JAKE) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[115], 12, 16, 24, 161);
|
|
|
|
} else {
|
|
|
|
screen_draw_frame(g_res.spr_frames[117], 12, 16, 24, 161);
|
|
|
|
}
|
|
|
|
for (int i = 0; i < obj39->data51; ++i) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[120], 12, 16, 216 + i * 16, 161);
|
|
|
|
}
|
|
|
|
screen_draw_number(obj39->vinyls_count, 192, 163, 2);
|
|
|
|
screen_draw_number(obj39->lifes_count, 64, 163, 2);
|
|
|
|
for (int i = 0; i < 5; ++i) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[135 + i], 12, 16, 80 + i * 32, -12);
|
|
|
|
}
|
|
|
|
if (obj39->data5F == 0) {
|
|
|
|
for (int i = 0; i < g_vars.level; ++i) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[140 + i], 12, 16, 80 + i * 32, -12);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = 0; i <= g_vars.level; ++i) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[140 + i], 12, 16, 80 + i * 32, -12);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
screen_draw_frame(g_res.spr_frames[123], 12, 320, 0, -12);
|
|
|
|
screen_draw_frame(g_res.spr_frames[124], 12, 320, 0, 161);
|
|
|
|
screen_draw_frame(g_res.spr_frames[115], 12, 16, 8, 161);
|
|
|
|
screen_draw_frame(g_res.spr_frames[117], 12, 16, 176, 161);
|
|
|
|
do_level_update_panel_lifes(obj39);
|
|
|
|
do_level_update_panel_lifes(obj40);
|
|
|
|
screen_draw_number(obj39->vinyls_count, 112, 163, 2);
|
|
|
|
screen_draw_number(obj40->vinyls_count, 280, 163, 2);
|
|
|
|
screen_draw_number(obj39->lifes_count, 48, 163, 2);
|
|
|
|
screen_draw_number(obj40->lifes_count, 216, 163, 2);
|
|
|
|
for (int i = 0; i < 5; ++i) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[135 + i], 12, 16, 80 + i * 32, -12);
|
|
|
|
}
|
|
|
|
if (obj39->data5F == 0) {
|
|
|
|
for (int i = 0; i < g_vars.level; ++i) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[140 + i], 12, 16, 80 + i * 32, -12);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (int i = 0; i <= g_vars.level; ++i) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[140 + i], 12, 16, 80 + i * 32, -12);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_level_enter_door(struct object_t *obj) {
|
|
|
|
static const uint8_t pos[] = { 74, 74, 77, 66, 102 };
|
|
|
|
for (int i = 0; i < MAX_DOORS; ++i) {
|
|
|
|
if (obj->xpos16 == g_vars.doors[i].src_x16 && obj->ypos16 == g_vars.doors[i].src_y16) {
|
|
|
|
screen_do_transition1(0);
|
|
|
|
obj->xpos = g_vars.doors[i].dst_x16 << 4;
|
|
|
|
obj->ypos = g_vars.doors[i].dst_y16 << 4;
|
|
|
|
if (obj->ypos > g_vars.screen_tilemap_h) {
|
2018-12-16 16:44:02 +01:00
|
|
|
obj->scrolling_lock_flag = 1;
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.screen_tilemap_yorigin = pos[g_vars.level] << 4;
|
|
|
|
const int w = TILEMAP_SCREEN_W / 16;
|
|
|
|
g_vars.screen_tilemap_xorigin = (((obj->xpos >> 4) / w) * w) << 4;
|
|
|
|
} else {
|
|
|
|
g_vars.screen_tilemap_xorigin = ((obj->xpos >> 4) - 10) << 4;
|
|
|
|
g_vars.screen_tilemap_yorigin = ((obj->ypos >> 4) - 6) << 4;
|
|
|
|
if (g_vars.screen_tilemap_yorigin + (TILEMAP_SCREEN_H + 16) > g_vars.screen_tilemap_h) {
|
|
|
|
g_vars.screen_tilemap_yorigin = g_vars.screen_tilemap_h - (TILEMAP_SCREEN_H + 16);
|
|
|
|
} else {
|
|
|
|
g_vars.screen_tilemap_yorigin += 16;
|
|
|
|
}
|
2018-12-16 16:44:02 +01:00
|
|
|
obj->scrolling_lock_flag = 0;
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
obj->screen_xpos = obj->xpos - g_vars.screen_tilemap_xorigin;
|
|
|
|
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
|
|
|
|
do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin);
|
|
|
|
do_level_update_scrolling2();
|
|
|
|
draw_level_panel();
|
|
|
|
do_level_update_panel_vinyls(obj);
|
|
|
|
if (g_vars.two_players_flag) {
|
|
|
|
do_level_update_panel_2nd_player();
|
|
|
|
}
|
|
|
|
screen_flip();
|
2018-12-16 13:34:03 +01:00
|
|
|
screen_do_transition1(1);
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->unk3D = 0;
|
|
|
|
obj->sprite_type = 0;
|
|
|
|
obj->yacc = 2;
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_input(struct object_t *obj) {
|
|
|
|
struct object_t *obj37 = &g_vars.objects[37];
|
|
|
|
int _si, _di;
|
|
|
|
|
|
|
|
obj->carry_crate_flag = 0;
|
|
|
|
if (obj->unk56 != 0) {
|
|
|
|
obj->special_anim = 27;
|
|
|
|
obj->xmaxvelocity = 112;
|
|
|
|
switch (obj->unk54) {
|
|
|
|
case 1:
|
|
|
|
obj->direction_ud = 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
obj->yacc = obj->yvelocity = -4;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
switch (obj->unk55) {
|
|
|
|
case 1:
|
|
|
|
obj->direction_lr = 1;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
obj->direction_lr = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->special_anim != 0 && obj->special_anim != 22) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
obj->xmaxvelocity = 48;
|
2018-07-08 16:39:28 +02:00
|
|
|
if (obj->trigger3_num == 0) {
|
|
|
|
triggers_update_tiles1(obj);
|
2018-07-08 16:08:53 +02:00
|
|
|
} else {
|
2018-07-08 16:39:28 +02:00
|
|
|
triggers_update_tiles2(obj);
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
2018-08-12 15:44:16 +02:00
|
|
|
if (g_vars.inp_key_space && g_vars.inp_key_up && !g_vars.inp_key_up_prev && !g_vars.player2_scrolling_flag) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->carry_crate_flag = 1;
|
|
|
|
do_level_enter_door(obj);
|
2018-08-12 15:44:16 +02:00
|
|
|
g_vars.inp_key_space_prev = g_vars.inp_key_space;
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
2018-08-12 15:44:16 +02:00
|
|
|
if (g_vars.inp_key_space != g_vars.inp_key_space_prev && !g_vars.inp_key_up) {
|
|
|
|
if (g_vars.inp_key_space) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->carry_crate_flag = 1;
|
|
|
|
}
|
2018-08-12 15:44:16 +02:00
|
|
|
g_vars.inp_key_space_prev = g_vars.inp_key_space;
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
2018-08-12 15:44:16 +02:00
|
|
|
if (g_vars.inp_key_right) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->direction_lr |= OBJECT_DIRECTION_RIGHT;
|
|
|
|
}
|
2018-08-12 15:44:16 +02:00
|
|
|
if (g_vars.inp_key_left) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->direction_lr |= OBJECT_DIRECTION_LEFT;
|
|
|
|
}
|
|
|
|
_si = triggers_get_tile_type(obj->xpos16, obj->ypos16);
|
2018-08-12 15:44:16 +02:00
|
|
|
if (g_vars.inp_key_up && !g_vars.inp_key_space) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->direction_ud = OBJECT_DIRECTION_UP;
|
2018-08-12 15:44:16 +02:00
|
|
|
if (!g_vars.inp_key_up_prev && obj->sprite_type != 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->yfriction = 0;
|
|
|
|
_di = triggers_get_tile_type(obj->xpos16, obj->ypos16 - 2);
|
|
|
|
if (_di == 10 && (_si == 0 || _si == 1)) {
|
|
|
|
if (obj->unk2E == 1 && obj->sprite_type != 4 && obj->blinking_counter == 0) {
|
|
|
|
if (obj37->type != 100) {
|
|
|
|
do_level_drop_grabbed_object(obj);
|
|
|
|
}
|
|
|
|
obj->special_anim = 18;
|
|
|
|
play_sound(SOUND_11);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (obj->grab_state != 0 && obj->grab_type == 0) {
|
|
|
|
obj->yfriction = 9;
|
|
|
|
} else {
|
|
|
|
obj->yfriction = 14;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-08-12 15:44:16 +02:00
|
|
|
} else if (g_vars.inp_key_down) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->direction_ud = 2;
|
|
|
|
if (!g_vars.inp_key_down_prev) {
|
|
|
|
obj->unk2B = 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
obj->direction_ud = 0;
|
|
|
|
}
|
|
|
|
g_vars.inp_key_up_prev = g_vars.inp_key_up;
|
|
|
|
g_vars.inp_key_down_prev = g_vars.inp_key_down;
|
|
|
|
if (obj->grab_state == 0) {
|
|
|
|
if (obj->carry_crate_flag != 0 && _si == 5) { // crate
|
|
|
|
obj->grab_type = 0;
|
|
|
|
obj->grab_state = 0;
|
|
|
|
do_level_reset_tiles(obj, 0);
|
|
|
|
g_vars.objects[37].grab_state = 0;
|
|
|
|
g_vars.objects[37].grab_type = 0;
|
|
|
|
do_level_update_grabbed_object(obj);
|
|
|
|
obj->carry_crate_flag = 0;
|
|
|
|
} else if (_si == 8) { // balloon
|
|
|
|
obj->grab_state = 0;
|
|
|
|
obj->grab_type = 2;
|
|
|
|
do_level_reset_tiles(obj, 0);
|
|
|
|
do_level_reset_tiles(obj, -1);
|
|
|
|
g_vars.objects[37].grab_state = 0;
|
|
|
|
g_vars.objects[37].grab_type = 2;
|
|
|
|
do_level_update_grabbed_object(obj);
|
|
|
|
obj->unk3D = 2;
|
|
|
|
} else if (_si == 9) { // umbrella
|
|
|
|
obj->grab_type = 8;
|
|
|
|
obj->grab_state = 0;
|
|
|
|
do_level_reset_tiles(obj, 0);
|
|
|
|
do_level_reset_tiles(obj, -1);
|
|
|
|
g_vars.objects[37].grab_state = 0;
|
|
|
|
g_vars.objects[37].grab_type = 8;
|
|
|
|
do_level_update_grabbed_object(obj);
|
|
|
|
obj->unk3D = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_scrolling(struct object_t *obj) {
|
2018-12-16 16:44:02 +01:00
|
|
|
if (obj->scrolling_lock_flag) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.screen_scrolling_dirmask = 0;
|
|
|
|
return;
|
|
|
|
}
|
2018-08-12 14:27:20 +02:00
|
|
|
if (g_vars.switch_player_scrolling_flag) {
|
2018-07-08 16:08:53 +02:00
|
|
|
if (obj->screen_xpos > (TILEMAP_SCREEN_W - 144)) {
|
|
|
|
g_vars.screen_scrolling_dirmask |= 2;
|
|
|
|
}
|
|
|
|
if (obj->screen_xpos < 144) {
|
|
|
|
g_vars.screen_scrolling_dirmask |= 1;
|
|
|
|
}
|
|
|
|
if ((g_vars.screen_scrolling_dirmask & 2) != 0 && obj->screen_xpos < TILEMAP_SCREEN_W / 2) {
|
|
|
|
g_vars.screen_scrolling_dirmask &= ~2;
|
2018-08-12 14:27:20 +02:00
|
|
|
g_vars.switch_player_scrolling_flag = 0;
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.inp_keyboard[0xC1] = 0;
|
|
|
|
}
|
|
|
|
if ((g_vars.screen_scrolling_dirmask & 1) != 0 && obj->screen_xpos > TILEMAP_SCREEN_W / 2) {
|
|
|
|
g_vars.screen_scrolling_dirmask &= ~1;
|
2018-08-12 14:27:20 +02:00
|
|
|
g_vars.switch_player_scrolling_flag = 0;
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.inp_keyboard[0xC1] = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
int _si = (obj->xvelocity >> 3) + obj->unk1C;
|
2018-08-12 14:27:20 +02:00
|
|
|
if (obj->screen_xpos > (TILEMAP_SCREEN_W - TILEMAP_SCROLL_W) && (g_vars.screen_tilemap_w * 16 - TILEMAP_SCREEN_W) > g_vars.screen_tilemap_xorigin) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.screen_scrolling_dirmask |= 2;
|
|
|
|
}
|
2018-08-12 14:27:20 +02:00
|
|
|
if (obj->screen_xpos < TILEMAP_SCROLL_W && g_vars.screen_tilemap_xorigin > 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.screen_scrolling_dirmask |= 1;
|
|
|
|
}
|
2018-08-12 14:27:20 +02:00
|
|
|
if ((g_vars.screen_scrolling_dirmask & 2) != 0 && (obj->screen_xpos < (TILEMAP_SCROLL_W - 16) || _si <= 0)) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.screen_scrolling_dirmask &= ~2;
|
|
|
|
}
|
2018-08-12 14:27:20 +02:00
|
|
|
if ((g_vars.screen_scrolling_dirmask & 1) != 0 && (obj->screen_xpos > (TILEMAP_SCREEN_W - (TILEMAP_SCROLL_W - 16)) || _si >= 0)) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.screen_scrolling_dirmask &= ~1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->screen_ypos < 64) {
|
|
|
|
g_vars.screen_scrolling_dirmask |= 8;
|
|
|
|
} else if (obj->screen_ypos > 144) {
|
|
|
|
g_vars.screen_scrolling_dirmask |= 4;
|
|
|
|
}
|
|
|
|
if ((g_vars.screen_scrolling_dirmask & 8) != 0 && obj->screen_ypos > 112) {
|
|
|
|
g_vars.screen_scrolling_dirmask &= ~8;
|
|
|
|
} else if ((g_vars.screen_scrolling_dirmask & 4) != 0 && obj->screen_ypos < 128) {
|
|
|
|
g_vars.screen_scrolling_dirmask &= ~4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_object_bounds(struct object_t *obj) {
|
|
|
|
int _si = g_vars.objects[OBJECT_NUM_PLAYER1].screen_xpos - obj->screen_xpos;
|
|
|
|
int _di = g_vars.objects[OBJECT_NUM_PLAYER1].screen_ypos - obj->screen_ypos;
|
|
|
|
if (g_vars.objects[OBJECT_NUM_PLAYER1].special_anim == 16) {
|
2018-07-27 16:02:05 +02:00
|
|
|
_si = GAME_SCREEN_W;
|
|
|
|
_di = GAME_SCREEN_H;
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
if (g_vars.two_players_flag) {
|
|
|
|
int tmp_dx = g_vars.objects[OBJECT_NUM_PLAYER2].screen_xpos - obj->screen_xpos;
|
|
|
|
int tmp_dy = g_vars.objects[OBJECT_NUM_PLAYER2].screen_ypos - obj->screen_ypos;
|
|
|
|
if (g_vars.objects[OBJECT_NUM_PLAYER2].special_anim == 16) {
|
2018-07-27 16:02:05 +02:00
|
|
|
tmp_dx = GAME_SCREEN_W;
|
|
|
|
tmp_dy = GAME_SCREEN_H;
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
2018-08-12 14:27:20 +02:00
|
|
|
if (abs(_si) >= abs(tmp_dx) && abs(_di) >= abs(tmp_dy)) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->player_xdist = tmp_dx;
|
|
|
|
obj->player_ydist = tmp_dy;
|
|
|
|
// obj->unk41 = 1;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
obj->player_xdist = _si;
|
|
|
|
obj->player_ydist = _di;
|
|
|
|
// obj->unk41 = 0;
|
|
|
|
}
|
|
|
|
|
2018-07-12 13:21:15 +02:00
|
|
|
void do_level_update_projectile(struct object_t *obj) {
|
2018-07-08 16:08:53 +02:00
|
|
|
struct object_t *obj38 = &g_vars.objects[38];
|
|
|
|
if (obj->unk42 == 0) {
|
2018-07-12 13:21:15 +02:00
|
|
|
if (obj38->type == 100) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->special_anim = 2;
|
|
|
|
obj->unk42 = 1;
|
|
|
|
}
|
|
|
|
} else if (obj->unk42 == 1) {
|
|
|
|
if (obj38->grab_type == 10 || obj->anim_num >= 7) {
|
|
|
|
obj38->type = 2;
|
2018-07-12 13:21:15 +02:00
|
|
|
obj38->visible_flag = 1;
|
2018-07-08 16:08:53 +02:00
|
|
|
static const uint8_t data[MAX_OBJECTS] = {
|
|
|
|
0, 0, 0, 0, 4, 5, 0, 0, 0, 0, 0, 0, 0, 6, 23, 0, 9, 9, 0, 10, 0,
|
|
|
|
11, 0, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0
|
|
|
|
};
|
|
|
|
obj38->grab_type = data[obj->type];
|
|
|
|
if (obj->anim_num == 7) {
|
|
|
|
if (obj38->grab_type == 10) {
|
|
|
|
play_sound(SOUND_16);
|
|
|
|
} else {
|
|
|
|
play_sound(SOUND_4);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch (obj38->grab_type) {
|
|
|
|
case 10:
|
|
|
|
obj38->xpos = obj->xpos;
|
|
|
|
obj38->ypos = obj->ypos;
|
|
|
|
obj38->xvelocity = 0;
|
|
|
|
break;
|
|
|
|
case 11:
|
|
|
|
case 13:
|
|
|
|
obj38->ypos = obj->ypos - 10;
|
|
|
|
obj38->xpos = obj->xpos + 32 - (obj->facing_left << 6);
|
|
|
|
obj38->xvelocity = obj38->yvelocity = 64 - (obj->facing_left << 7);
|
|
|
|
break;
|
|
|
|
case 12:
|
|
|
|
obj38->ypos = obj->ypos - 3;
|
|
|
|
obj38->xpos = obj->xpos + 16 - (obj->facing_left << 5);
|
|
|
|
obj38->xvelocity = obj38->yvelocity = 32 - (obj->facing_left << 6);
|
|
|
|
break;
|
2018-07-12 13:21:15 +02:00
|
|
|
default:
|
|
|
|
obj38->ypos = obj->ypos - 18;
|
|
|
|
obj38->xpos = obj->xpos + 32 - (obj->facing_left << 6);
|
|
|
|
obj38->xvelocity = obj38->yvelocity = 64 - (obj->facing_left << 7);
|
|
|
|
break;
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
const int num = obj38->type * 116 / 4;
|
|
|
|
assert(num < 1189);
|
|
|
|
obj38->animframes_ptr = animframes_059d + num;
|
|
|
|
obj38->anim_num = 1;
|
|
|
|
obj38->facing_left = obj->facing_left;
|
|
|
|
obj->unk42 = 0;
|
|
|
|
obj38->unk42 = 2;
|
|
|
|
obj38->unk5D = obj->type;
|
|
|
|
}
|
|
|
|
} else if (obj->unk42 == 2) {
|
|
|
|
if (obj->grab_type == 10) {
|
|
|
|
obj->yacc = 4;
|
|
|
|
obj->yvelocity = 4;
|
|
|
|
if (obj->screen_ypos > 150) {
|
|
|
|
obj->type = 0;
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
obj->grab_type = 0;
|
|
|
|
obj->unk42 = 0;
|
|
|
|
obj->unk5D = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
obj->direction_lr = obj->facing_left + 1;
|
|
|
|
obj->xacc = 64;
|
|
|
|
obj->xmaxvelocity = 400;
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
obj->yacc = 0;
|
|
|
|
if (obj->screen_xpos < 0 || obj->screen_xpos > GAME_SCREEN_W - 10 || obj->xpos < 32) {
|
|
|
|
obj->type = 100;
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
obj->grab_type = 0;
|
|
|
|
obj->unk42 = 0;
|
|
|
|
obj->unk5D = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_fixup_object_position(struct object_t *obj) {
|
|
|
|
int num, ret;
|
|
|
|
|
|
|
|
num = triggers_get_tile_type(obj->xpos16, obj->ypos16);
|
|
|
|
if (obj->grab_state != 0) {
|
|
|
|
num = 0;
|
|
|
|
}
|
|
|
|
switch (num) {
|
|
|
|
case 2:
|
|
|
|
case 14:
|
2018-12-16 13:34:03 +01:00
|
|
|
ret = triggers_tile_get_yoffset(obj);
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->ypos = ret + (obj->ypos & ~15);
|
|
|
|
obj->ypos16 = obj->ypos >> 4;
|
|
|
|
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
case 15:
|
|
|
|
--obj->ypos16;
|
2018-12-16 13:34:03 +01:00
|
|
|
ret = triggers_tile_get_yoffset(obj);
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->ypos = ret + (obj->ypos & ~15) - 16;
|
|
|
|
obj->ypos16 = obj->ypos >> 4;
|
|
|
|
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// gravity
|
|
|
|
static void do_level_fixup_object_unkA(struct object_t *obj) {
|
|
|
|
int16_t _si = triggers_get_tile_type(obj->xpos16, obj->ypos16);
|
|
|
|
if (obj->special_anim == 18) {
|
|
|
|
_si = 0;
|
|
|
|
obj->sprite_type = 0;
|
|
|
|
}
|
|
|
|
if (_si == 6) {
|
|
|
|
obj->yfriction = 0;
|
|
|
|
obj->sprite_type = 3;
|
|
|
|
if (obj->direction_ud == 1) {
|
|
|
|
if (triggers_get_tile_type(obj->xpos16, (obj->ypos - 2) >> 4) != 6) {
|
|
|
|
obj->yvelocity = -1;
|
|
|
|
} else {
|
|
|
|
obj->yvelocity = -2;
|
|
|
|
}
|
|
|
|
} else if (obj->direction_ud == 2) {
|
|
|
|
obj->yvelocity = 2;
|
|
|
|
} else {
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
}
|
|
|
|
} else if (_si == 7) {
|
|
|
|
if (obj->direction_ud != 0 && obj->unk2E != 0) {
|
|
|
|
obj->xpos = (obj->xpos + 7) & ~15;
|
|
|
|
obj->screen_xpos = obj->xpos - g_vars.screen_tilemap_xorigin;
|
|
|
|
obj->xpos16 = obj->xpos >> 4;
|
|
|
|
}
|
|
|
|
obj->yfriction = 0;
|
|
|
|
obj->sprite_type = 2;
|
|
|
|
if (obj->direction_ud == 1) {
|
|
|
|
if (triggers_get_tile_type(obj->xpos16, (obj->ypos - 2) >> 4) != 7) {
|
|
|
|
obj->yvelocity = -1;
|
|
|
|
} else {
|
|
|
|
obj->yvelocity = -2;
|
|
|
|
}
|
|
|
|
} else if (obj->direction_ud == 2) {
|
|
|
|
obj->yvelocity = 2;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (_si == 11 || _si == 12) {
|
|
|
|
obj->yfriction = 0;
|
|
|
|
obj->sprite_type = 4;
|
|
|
|
}
|
|
|
|
if (obj->yfriction != 0) {
|
|
|
|
obj->yvelocity -= obj->yfriction;
|
|
|
|
obj->yfriction = 0;
|
|
|
|
} else {
|
|
|
|
obj->yvelocity += obj->yacc;
|
|
|
|
if (obj->type < 2) {
|
|
|
|
if (obj->unk3D == 1 && obj->yvelocity > 0) {
|
|
|
|
obj->yacc = 1;
|
|
|
|
obj->yvelocity = obj->yacc;
|
|
|
|
} else if (obj->unk3D == 2) {
|
|
|
|
obj->yacc = -1;
|
|
|
|
obj->yvelocity = obj->yacc;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->yvelocity > obj->ymaxvelocity) {
|
|
|
|
obj->yvelocity = obj->ymaxvelocity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_fixup_object_ypos16(struct object_t *obj) {
|
|
|
|
if (obj->collide_flag == 0) {
|
|
|
|
if (obj->ypos < 32) {
|
|
|
|
obj->ypos = 32;
|
|
|
|
obj->screen_ypos = 32 - g_vars.screen_tilemap_yorigin;
|
|
|
|
obj->yvelocity = 0;
|
2018-12-16 16:44:02 +01:00
|
|
|
} else if (obj->ypos > g_vars.screen_tilemap_h && !obj->scrolling_lock_flag) {
|
2018-07-08 16:08:53 +02:00
|
|
|
obj->ypos = g_vars.screen_tilemap_h - 16;
|
|
|
|
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
|
|
|
|
obj->yvelocity = 0;
|
|
|
|
} else {
|
|
|
|
obj->ypos16 = obj->ypos >> 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// collision with bonus
|
|
|
|
static void do_level_handle_object_bonus_collision(struct object_t *obj, struct object_t *test_obj) {
|
|
|
|
if (obj->yvelocity < 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (test_obj->xpos + level_obj_w[test_obj->type] <= obj->xpos) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (test_obj->xpos - level_obj_w[test_obj->type] >= obj->xpos) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (test_obj->ypos - level_obj_h[test_obj->type] >= obj->ypos) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (obj->ypos >= test_obj->ypos) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
obj->yvelocity = test_obj->yvelocity;
|
|
|
|
obj->yacc = test_obj->yacc;
|
|
|
|
obj->unk1E = test_obj->unk1E;
|
|
|
|
obj->unk1C = test_obj->xvelocity >> 3;
|
|
|
|
obj->sprite_type = 1;
|
|
|
|
obj->ypos = test_obj->ypos - level_obj_h[test_obj->type] + 1;
|
|
|
|
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
|
|
|
|
obj->ypos16 = obj->ypos >> 4;
|
|
|
|
if ((obj->direction_ud & 2) != 0 && obj->grab_state == 0) {
|
|
|
|
obj->unk2E = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_level_player_hit(struct object_t *obj) {
|
|
|
|
if (obj->blinking_counter == 0) {
|
2018-07-27 16:02:05 +02:00
|
|
|
if (obj->data51 > 0 && (g_options.cheats & CHEATS_UNLIMITED_ENERGY) == 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
--obj->data51;
|
|
|
|
do_level_update_panel_lifes(obj);
|
|
|
|
}
|
|
|
|
if (obj->special_anim != 16) {
|
|
|
|
obj->blinking_counter = 75;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_handle_object_collision(struct object_t *obj) {
|
|
|
|
struct object_t *obj35 = &g_vars.objects[35];
|
|
|
|
if (obj->special_anim == 16) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (obj->type != 0 && g_vars.two_players_flag) {
|
|
|
|
obj35 = &g_vars.objects[34];
|
|
|
|
}
|
|
|
|
if (obj->type < 2) {
|
|
|
|
level_obj_h[obj->type] = (obj->unk2E == 0) ? 14 : 26;
|
|
|
|
}
|
|
|
|
if (obj->unk2F != 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (int i = 0; i < MAX_OBJECTS; ++i) {
|
|
|
|
struct object_t *current_obj = &g_vars.objects[i];
|
|
|
|
if (!current_obj->visible_flag || current_obj->type == 100) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (current_obj->type == obj->type) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const int current_obj_type = level_obj_type[current_obj->type];
|
|
|
|
if (current_obj_type == 0) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (current_obj_type == 1) {
|
|
|
|
do_level_handle_object_bonus_collision(obj, current_obj);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (current_obj_type == 2) {
|
|
|
|
if (current_obj->collide_flag != 0 || current_obj->special_anim == 16) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int x2 = obj->xpos + level_obj_w[obj->type];
|
|
|
|
int x1 = current_obj->xpos - level_obj_w[current_obj->type];
|
|
|
|
if (x2 < x1) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int y1 = current_obj->ypos - level_obj_h[current_obj->type];
|
|
|
|
if (y1 > obj->ypos) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
x1 = obj->xpos - level_obj_w[obj->type];
|
|
|
|
x2 = current_obj->xpos + level_obj_w[current_obj->type];
|
|
|
|
if (x1 > x2) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
int y2 = obj->ypos - level_obj_h[obj->type];
|
|
|
|
if (y2 > current_obj->ypos) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (obj->type == 0 || obj->type == 1) {
|
|
|
|
if (obj->blinking_counter == 0 && current_obj->type > 2 && obj->special_anim != 18 && !(g_options.cheats & CHEATS_NO_HIT)) {
|
|
|
|
if (obj->grab_state != 0) {
|
|
|
|
do_level_drop_grabbed_object(obj);
|
|
|
|
}
|
|
|
|
if (obj->sprite_type != 4) {
|
|
|
|
obj->special_anim = 18;
|
|
|
|
}
|
|
|
|
do_level_player_hit(obj);
|
|
|
|
play_sound(SOUND_11);
|
|
|
|
}
|
|
|
|
} else if (obj->type == 2) {
|
|
|
|
if (current_obj->type < 2) {
|
|
|
|
if (current_obj->blinking_counter == 0 && obj->unk5D > 1 && current_obj->special_anim != 18 && !(g_options.cheats & CHEATS_NO_HIT)) {
|
|
|
|
if (current_obj->grab_state != 0) {
|
|
|
|
do_level_drop_grabbed_object(current_obj);
|
|
|
|
}
|
|
|
|
if (current_obj->sprite_type != 4) {
|
|
|
|
current_obj->special_anim = 18;
|
|
|
|
}
|
|
|
|
do_level_player_hit(current_obj);
|
|
|
|
play_sound(SOUND_11);
|
|
|
|
}
|
|
|
|
} else if (current_obj->type > 2) {
|
|
|
|
if ((g_vars.objects[OBJECT_NUM_PLAYER1].grab_state == 0 && obj->unk5D == 0) || (g_vars.objects[OBJECT_NUM_PLAYER2].grab_state == 0 && obj->unk5D == 1)) {
|
|
|
|
if (obj35->type == 100) {
|
|
|
|
current_obj->collide_flag = 1;
|
|
|
|
current_obj->xmaxvelocity = 60;
|
|
|
|
if (obj->facing_left) {
|
|
|
|
current_obj->xvelocity = -60;
|
|
|
|
current_obj->data51 = 1;
|
|
|
|
} else {
|
|
|
|
current_obj->xvelocity = 60;
|
|
|
|
current_obj->data51 = 2;
|
|
|
|
}
|
|
|
|
current_obj->facing_left ^= 1;
|
|
|
|
if (current_obj->yvelocity >= 0) {
|
|
|
|
current_obj->yfriction = 12;
|
|
|
|
}
|
|
|
|
obj->type = 100;
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
play_sound(SOUND_11);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_handle_object_unk59(struct object_t *obj) {
|
|
|
|
if (obj->collide_flag == 0) {
|
|
|
|
if (obj->type != 2) {
|
|
|
|
if (obj->sprite_type == 0) {
|
|
|
|
if (obj->yvelocity < 0) {
|
|
|
|
level_call_trigger_func(obj, -2);
|
|
|
|
} else {
|
|
|
|
level_call_trigger_func(obj, 0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (obj->yvelocity < 0) {
|
|
|
|
level_call_trigger_func(obj, -2);
|
|
|
|
} else {
|
|
|
|
if (triggers_get_tile_type(obj->xpos16, obj->ypos16) != 7) {
|
|
|
|
if (triggers_get_tile_type(obj->xpos16, obj->ypos16) != 6) {
|
|
|
|
level_call_trigger_func(obj, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->type < 3) {
|
|
|
|
do_level_handle_object_collision(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_fixup_object_unk8(struct object_t *obj) {
|
|
|
|
if (obj->direction_lr & OBJECT_DIRECTION_RIGHT) {
|
|
|
|
obj->facing_left = 0;
|
|
|
|
if (obj->xvelocity < obj->xmaxvelocity) {
|
|
|
|
obj->xacc = obj->unk2D;
|
|
|
|
} else {
|
|
|
|
obj->xacc = 0;
|
|
|
|
}
|
|
|
|
} else if (obj->direction_lr & OBJECT_DIRECTION_LEFT) {
|
|
|
|
obj->facing_left = 1;
|
|
|
|
if (obj->xvelocity > -obj->xmaxvelocity) {
|
|
|
|
obj->xacc = -obj->unk2D;
|
|
|
|
} else {
|
|
|
|
obj->xacc = 0;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (obj->xvelocity < 0) {
|
|
|
|
obj->xacc = obj->unk2D;
|
|
|
|
if (obj->xvelocity > -obj->xacc) {
|
|
|
|
obj->xacc = -obj->xvelocity;
|
|
|
|
}
|
|
|
|
} else if (obj->xvelocity > 0) {
|
|
|
|
obj->xacc = -obj->unk2D;
|
|
|
|
if (obj->xvelocity < -obj->xacc) {
|
|
|
|
obj->xacc = -obj->xvelocity;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
obj->xacc = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
obj->xvelocity += obj->xacc + obj->unk2F;
|
|
|
|
if (obj->xvelocity > obj->xmaxvelocity) {
|
|
|
|
obj->xvelocity = obj->xmaxvelocity;
|
|
|
|
}
|
|
|
|
if (obj->xvelocity < -obj->xmaxvelocity) {
|
|
|
|
obj->xvelocity = -obj->xmaxvelocity;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_fixup_object_xpos16(struct object_t *obj) {
|
|
|
|
int _ax, _si;
|
|
|
|
|
|
|
|
_ax = obj->xvelocity + (obj->unk1C << 3);
|
|
|
|
if (_ax >= 0) {
|
|
|
|
_si = (obj->xvelocity >> 3) + obj->unk1C;
|
|
|
|
obj->tile012_xpos = (obj->xpos + _si + 8) >> 4;
|
|
|
|
obj->tile0_flags = triggers_get_next_tile_flags(obj->tile012_xpos, obj->ypos16);
|
|
|
|
obj->tile1_flags = triggers_get_next_tile_flags(obj->tile012_xpos, obj->ypos16 - 1);
|
|
|
|
obj->tile2_flags = triggers_get_next_tile_flags(obj->tile012_xpos, obj->ypos16 - 2);
|
|
|
|
if (obj->type != 2) {
|
|
|
|
if ((obj->tile0_flags & 1) != 0) {
|
|
|
|
obj->moving_direction ^= 1;
|
|
|
|
if (obj->sprite_type == 2) {
|
|
|
|
obj->direction_ud = 1;
|
|
|
|
}
|
|
|
|
if (obj->xvelocity > 0) {
|
|
|
|
obj->xvelocity = 0;
|
|
|
|
}
|
|
|
|
_si = 0;
|
|
|
|
} else if (obj->unk2E == 1 && (obj->tile1_flags & 1) != 0) {
|
|
|
|
obj->moving_direction ^= 1;
|
|
|
|
if (obj->xvelocity > 0) {
|
|
|
|
obj->xvelocity = 0;
|
|
|
|
}
|
|
|
|
_si = 0;
|
|
|
|
} else if (obj->unk2E == 2 && (obj->tile2_flags & 1) != 0) {
|
|
|
|
if (obj->xvelocity > 0) {
|
|
|
|
obj->xvelocity = 0;
|
|
|
|
}
|
|
|
|
_si = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->xpos < g_vars.screen_tilemap_w * 16 - 16) {
|
|
|
|
obj->xpos += _si;
|
|
|
|
obj->screen_xpos += _si;
|
|
|
|
obj->xpos16 = obj->xpos >> 4;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (obj->xvelocity < -8) {
|
|
|
|
_si = (obj->xvelocity >> 3) + obj->unk1C;
|
|
|
|
} else {
|
|
|
|
_si = obj->unk1C;
|
|
|
|
}
|
|
|
|
obj->tile012_xpos = (obj->xpos + _si - 8) >> 4;
|
|
|
|
obj->tile0_flags = triggers_get_next_tile_flags(obj->tile012_xpos, obj->ypos16);
|
|
|
|
obj->tile1_flags = triggers_get_next_tile_flags(obj->tile012_xpos, obj->ypos16 - 1);
|
|
|
|
obj->tile2_flags = triggers_get_next_tile_flags(obj->tile012_xpos, obj->ypos16 - 2);
|
|
|
|
if (obj->type != 2) {
|
|
|
|
if ((obj->tile0_flags & 2) != 0) {
|
|
|
|
obj->moving_direction ^= 1;
|
|
|
|
if (obj->sprite_type == 2) {
|
|
|
|
obj->direction_ud = 1;
|
|
|
|
}
|
|
|
|
if (obj->xvelocity < 0) {
|
|
|
|
obj->xvelocity = 0;
|
|
|
|
}
|
|
|
|
_si = 0;
|
|
|
|
} else if (obj->unk2E == 1 && (obj->tile1_flags & 2) != 0) {
|
|
|
|
obj->moving_direction ^= 1;
|
|
|
|
if (obj->xvelocity < 0) {
|
|
|
|
obj->xvelocity = 0;
|
|
|
|
}
|
|
|
|
_si = 0;
|
|
|
|
} else if (obj->unk2E == 2 && (obj->tile2_flags & 2) != 0) {
|
|
|
|
if (obj->xvelocity < 0) {
|
|
|
|
obj->xvelocity = 0;
|
|
|
|
}
|
|
|
|
_si = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->xpos > 16) {
|
|
|
|
obj->xpos += _si;
|
|
|
|
obj->screen_xpos += _si;
|
|
|
|
obj->xpos16 = obj->xpos >> 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_object_unk2E(struct object_t *obj) {
|
|
|
|
if (obj->direction_ud & 2) {
|
|
|
|
if (obj->grab_state == 0) {
|
|
|
|
if (triggers_get_tile_data(obj) != 0) {
|
|
|
|
obj->unk2E = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (obj->tile1_flags == 0 && obj->unk2E == 0) {
|
|
|
|
obj->unk2E = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const int num = triggers_get_tile_type(obj->xpos16, obj->ypos16);
|
|
|
|
if (num == 11 || num == 12) {
|
|
|
|
obj->unk2E = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void do_level_update_objects() {
|
|
|
|
const int bounding_box_x1 = g_vars.screen_tilemap_xorigin - 140;
|
|
|
|
const int bounding_box_x2 = g_vars.screen_tilemap_xorigin + TILEMAP_SCREEN_W + 140;
|
|
|
|
const int bounding_box_y1 = g_vars.screen_tilemap_yorigin - 100;
|
|
|
|
const int bounding_box_y2 = g_vars.screen_tilemap_yorigin + TILEMAP_SCREEN_H + 190;
|
|
|
|
for (int i = 0; i < MAX_OBJECTS; ++i) {
|
|
|
|
struct object_t *obj = &g_vars.objects[i];
|
|
|
|
print_debug(DBG_GAME, "update_objects #%d type %d pos %d,%d", i, obj->type, obj->xpos, obj->ypos);
|
|
|
|
obj->screen_xpos = obj->xpos - g_vars.screen_tilemap_xorigin;
|
|
|
|
obj->screen_ypos = obj->ypos - g_vars.screen_tilemap_yorigin;
|
|
|
|
obj->unk2B = 0;
|
|
|
|
obj->direction_lr = 0;
|
|
|
|
obj->direction_ud = 0;
|
|
|
|
if (obj->type < 2) {
|
2018-07-12 13:21:15 +02:00
|
|
|
if (g_vars.inp_keyboard[0xC1] != 0) { // F7, change player
|
2018-08-12 14:27:20 +02:00
|
|
|
if (!g_vars.switch_player_scrolling_flag && g_vars.two_players_flag) {
|
2018-12-16 16:44:02 +01:00
|
|
|
if (!g_vars.player2_scrolling_flag && !g_vars.objects[OBJECT_NUM_PLAYER1].scrolling_lock_flag) {
|
2018-07-12 13:21:15 +02:00
|
|
|
g_vars.player2_scrolling_flag = 1;
|
2018-08-12 14:27:20 +02:00
|
|
|
g_vars.switch_player_scrolling_flag = 1;
|
2018-12-16 16:44:02 +01:00
|
|
|
} else if (g_vars.player2_scrolling_flag && !g_vars.objects[OBJECT_NUM_PLAYER2].scrolling_lock_flag) {
|
2018-07-12 13:21:15 +02:00
|
|
|
g_vars.player2_scrolling_flag = 1;
|
2018-08-12 14:27:20 +02:00
|
|
|
g_vars.switch_player_scrolling_flag = 1;
|
2018-07-12 13:21:15 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
g_vars.inp_keyboard[0xC1] = 0;
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
if (obj->blinking_counter != 0) {
|
|
|
|
--obj->blinking_counter;
|
|
|
|
}
|
|
|
|
obj->yacc = 2;
|
|
|
|
if (i == OBJECT_NUM_PLAYER1) {
|
|
|
|
if (!g_vars.player2_dead_flag) {
|
|
|
|
do_level_update_input(obj);
|
|
|
|
do_level_update_object_unk2E(obj);
|
|
|
|
do_level_update_panel_vinyls(obj);
|
|
|
|
}
|
|
|
|
if (!g_vars.player2_scrolling_flag) {
|
|
|
|
do_level_update_scrolling(obj);
|
|
|
|
}
|
|
|
|
if (obj->data5F != 0 && !g_vars.found_music_instrument_flag) {
|
|
|
|
// found music instrument
|
|
|
|
if (g_vars.level < (MAX_LEVELS - 1)) {
|
|
|
|
static const uint8_t data[] = { 94, 81, 96, 26, 26, 3, 89, 52, 15, 96, 51, 20, 72, 27, 5 };
|
|
|
|
const uint8_t *p = data + g_vars.level * 3;
|
|
|
|
do_level_update_tile(p[0], p[1], p[2]);
|
|
|
|
}
|
|
|
|
g_vars.found_music_instrument_flag = 1;
|
|
|
|
}
|
|
|
|
} else if (g_vars.two_players_flag) {
|
|
|
|
if (!g_vars.player1_dead_flag) {
|
|
|
|
do_level_update_object_unk2E(obj);
|
|
|
|
do_level_update_panel_2nd_player();
|
|
|
|
}
|
|
|
|
if (g_vars.player2_scrolling_flag) {
|
|
|
|
do_level_update_scrolling(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (obj->type > 2 && obj->collide_flag == 0) {
|
2018-12-16 13:34:03 +01:00
|
|
|
const int x = g_vars.level_xpos[i];
|
|
|
|
const int y = g_vars.level_ypos[i];
|
2018-07-08 16:08:53 +02:00
|
|
|
if (obj->type == 32) {
|
|
|
|
obj->unk5D = i;
|
|
|
|
}
|
|
|
|
if (x > bounding_box_x1 && x < bounding_box_x2 && y > bounding_box_y1 && y < bounding_box_y2) {
|
|
|
|
obj->visible_flag = 1;
|
|
|
|
level_call_object_func(obj);
|
|
|
|
} else {
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
if (obj->type == 22 || obj->type == 35) {
|
|
|
|
obj->xpos = x;
|
|
|
|
obj->ypos = y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (obj->visible_flag != 0) {
|
|
|
|
do_level_update_object_bounds(obj);
|
|
|
|
if (obj->unk42 != 0) {
|
2018-07-12 13:21:15 +02:00
|
|
|
do_level_update_projectile(obj);
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
obj->unk2D = 10;
|
|
|
|
obj->unk1C = 0;
|
|
|
|
if (obj->sprite_type != 6) {
|
|
|
|
obj->sprite_type = 0;
|
|
|
|
}
|
|
|
|
do_level_fixup_object_position(obj);
|
|
|
|
do_level_fixup_object_unkA(obj);
|
|
|
|
obj->ypos += obj->yvelocity;
|
|
|
|
obj->screen_ypos += obj->yvelocity;
|
|
|
|
do_level_fixup_object_ypos16(obj);
|
|
|
|
do_level_handle_object_unk59(obj);
|
|
|
|
do_level_fixup_object_unk8(obj);
|
|
|
|
do_level_fixup_object_xpos16(obj);
|
|
|
|
if (obj->grab_state != 0) {
|
|
|
|
do_level_update_grabbed_object(obj);
|
|
|
|
}
|
|
|
|
if (obj->collide_flag != 0) {
|
|
|
|
if (obj->screen_ypos > 200) {
|
|
|
|
obj->visible_flag = 0;
|
|
|
|
}
|
|
|
|
obj->xmaxvelocity = 60;
|
|
|
|
if (obj->data51 == 1) {
|
|
|
|
obj->xvelocity = -60;
|
|
|
|
} else {
|
|
|
|
obj->xvelocity = 60;
|
|
|
|
}
|
|
|
|
obj->facing_left ^= 1;
|
|
|
|
obj->special_anim = 1;
|
|
|
|
}
|
|
|
|
obj->floor_ypos16 = obj->ypos16;
|
|
|
|
if (obj->type != 2) {
|
|
|
|
if (obj->special_anim != 0) {
|
|
|
|
do_level_add_sprite3(obj);
|
|
|
|
} else {
|
|
|
|
do_level_add_sprite1(obj);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
do_level_add_sprite2(obj);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (g_vars.triggers_counter != 0) {
|
|
|
|
if (g_vars.triggers_counter < 10) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[140 + g_vars.level], 12, 16, g_vars.level * 32 + 80, -12);
|
|
|
|
++g_vars.triggers_counter;
|
|
|
|
} else {
|
|
|
|
screen_draw_frame(g_res.spr_frames[145], 12, 16, g_vars.level * 32 + 80, -12);
|
|
|
|
++g_vars.triggers_counter;
|
|
|
|
if (g_vars.triggers_counter > 20) {
|
|
|
|
g_vars.triggers_counter = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-12-16 13:34:03 +01:00
|
|
|
if (!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag != 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.level_completed_flag = 1;
|
|
|
|
} else {
|
2018-12-16 13:34:03 +01:00
|
|
|
if (g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag != 0 && g_vars.objects[OBJECT_NUM_PLAYER2].level_complete_flag != 0) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.level_completed_flag = 1;
|
|
|
|
}
|
2018-12-16 13:34:03 +01:00
|
|
|
if (g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag != 0 && g_vars.player1_dead_flag) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.level_completed_flag = 1;
|
|
|
|
}
|
2018-12-16 13:34:03 +01:00
|
|
|
if (g_vars.objects[OBJECT_NUM_PLAYER2].level_complete_flag != 0 && g_vars.player2_dead_flag) {
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.level_completed_flag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (g_vars.level_completed_flag) {
|
|
|
|
++g_vars.update_objects_counter;
|
|
|
|
if (g_vars.update_objects_counter > 50) {
|
|
|
|
if (g_vars.level < (MAX_LEVELS - 1)) {
|
|
|
|
++g_vars.level;
|
|
|
|
} else {
|
|
|
|
g_vars.level = 0;
|
|
|
|
g_vars.play_level_flag = 0;
|
|
|
|
g_vars.level_completed_flag = 0;
|
|
|
|
}
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].unk60 = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER2].unk60 = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].data5F = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER2].data5F = 0;
|
2018-12-16 13:34:03 +01:00
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER2].level_complete_flag = 0;
|
2018-08-12 14:27:20 +02:00
|
|
|
// g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40;
|
2018-07-08 16:08:53 +02:00
|
|
|
screen_unk5();
|
2018-08-12 14:27:20 +02:00
|
|
|
// g_vars.screen_draw_offset += TILEMAP_OFFSET_Y * 40;
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.quit_level_flag = 1;
|
|
|
|
}
|
|
|
|
} else if (g_vars.game_over_flag) {
|
|
|
|
g_vars.screen_scrolling_dirmask = 0;
|
|
|
|
if ((!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].lifes_count == 1) || (g_vars.player2_dead_flag && g_vars.player1_dead_flag)) {
|
|
|
|
screen_draw_frame(g_res.spr_frames[127], 34, 160, 80, 63);
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].unk60 = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER2].unk60 = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].data5F = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER2].data5F = 0;
|
2018-12-16 13:34:03 +01:00
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].restart_level_flag = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER2].restart_level_flag = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].level_complete_flag = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER2].level_complete_flag = 0;
|
2018-07-08 16:08:53 +02:00
|
|
|
screen_vsync();
|
|
|
|
}
|
|
|
|
if (g_vars.objects[35].screen_ypos > 90) {
|
|
|
|
g_vars.objects[35].screen_ypos = 90;
|
|
|
|
g_vars.objects[35].ypos = g_vars.screen_tilemap_yorigin + 90;
|
|
|
|
}
|
|
|
|
++g_vars.update_objects_counter;
|
|
|
|
if (g_vars.objects[OBJECT_NUM_PLAYER1].yvelocity == 0) {
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].special_anim = 21;
|
|
|
|
} else {
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].special_anim = 2;
|
|
|
|
}
|
|
|
|
if (g_vars.update_objects_counter > 70) {
|
|
|
|
if (!g_vars.two_players_flag && g_vars.objects[OBJECT_NUM_PLAYER1].lifes_count == 1) {
|
|
|
|
g_vars.play_level_flag = 0;
|
|
|
|
}
|
2018-08-12 14:27:20 +02:00
|
|
|
// g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40;
|
2018-07-08 16:08:53 +02:00
|
|
|
screen_unk5();
|
2018-08-12 14:27:20 +02:00
|
|
|
// g_vars.screen_draw_offset += TILEMAP_OFFSET_Y * 40;
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.quit_level_flag = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_foreground_tiles() {
|
|
|
|
int x = g_vars.screen_tilemap_xorigin >> 4;
|
|
|
|
int y = g_vars.screen_tilemap_yorigin >> 4;
|
|
|
|
for (int j = 0; j < (TILEMAP_SCREEN_H / 16); ++j) {
|
|
|
|
const uint8_t *ptr = lookup_sql(x, y);
|
|
|
|
for (int i = 0; i < (TILEMAP_SCREEN_W / 16); ++i) {
|
|
|
|
uint8_t num = *ptr++;
|
|
|
|
const uint8_t *data = g_res.triggers[num].op_table2;
|
|
|
|
if (data) {
|
|
|
|
const int current = data[0];
|
|
|
|
num = data[current + 1];
|
|
|
|
}
|
|
|
|
const int avt_num = g_res.triggers[num].foreground_tile_num;
|
|
|
|
if (avt_num != 255) {
|
2018-08-12 14:27:20 +02:00
|
|
|
const int tile_y = g_vars.screen_tilemap_yoffset + j * 16 + TILEMAP_OFFSET_Y;
|
|
|
|
const int tile_x = g_vars.screen_tilemap_xoffset + i * 16;
|
2018-12-16 15:28:52 +01:00
|
|
|
g_sys.render_add_sprite(RENDER_SPR_FG, avt_num, tile_x, tile_y, 0);
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
++y;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void do_level() {
|
2018-07-16 14:43:34 +02:00
|
|
|
static const int W = 320 / 16;
|
2018-08-12 15:44:16 +02:00
|
|
|
for (int tile_num = 0; tile_num < 128; ++tile_num) {
|
2018-07-16 14:43:34 +02:00
|
|
|
g_vars.screen_tile_lut[tile_num] = (tile_num / W) * 640 + (tile_num % W);
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
|
|
|
g_vars.screen_tilemap_w = level_dim[g_vars.level * 2];
|
|
|
|
g_vars.screen_tilemap_h = level_dim[g_vars.level * 2 + 1];
|
|
|
|
for (int i = 0; i < MAX_TRIGGERS; ++i) {
|
|
|
|
g_res.triggers[i].unk16 = i;
|
|
|
|
}
|
2018-08-12 14:27:20 +02:00
|
|
|
g_vars.switch_player_scrolling_flag = 0;
|
2018-07-08 16:08:53 +02:00
|
|
|
init_level();
|
|
|
|
screen_clear(0);
|
|
|
|
do_level_redraw_tilemap(g_vars.screen_tilemap_xorigin, g_vars.screen_tilemap_yorigin);
|
|
|
|
if (g_options.amiga_copper_bars) {
|
|
|
|
g_sys.set_copper_bars(_copper_data + g_vars.level * 18);
|
|
|
|
}
|
|
|
|
g_vars.inp_keyboard[0xB9] = 0; // SPACE
|
2018-08-12 14:27:20 +02:00
|
|
|
// g_vars.screen_draw_offset = TILEMAP_OFFSET_Y * 40;
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.update_objects_counter = 0;
|
|
|
|
g_vars.game_over_flag = 0;
|
|
|
|
g_vars.level_completed_flag = 0;
|
|
|
|
g_vars.quit_level_flag = 0;
|
|
|
|
g_vars.player2_scrolling_flag = 0;
|
|
|
|
g_vars.found_music_instrument_flag = 0;
|
2018-12-16 15:28:52 +01:00
|
|
|
g_sys.render_set_sprites_clipping_rect(0, TILEMAP_OFFSET_Y, TILEMAP_SCREEN_W, TILEMAP_SCREEN_H);
|
2018-08-12 14:27:20 +02:00
|
|
|
bool screen_transition_flag = true;
|
2018-07-08 16:08:53 +02:00
|
|
|
do {
|
2018-07-08 16:39:28 +02:00
|
|
|
const uint32_t timestamp = g_sys.get_timestamp();
|
2018-07-08 16:08:53 +02:00
|
|
|
update_input();
|
2018-07-12 13:21:15 +02:00
|
|
|
if (g_vars.inp_keyboard[0xBF] != 0) { // F5, quit game
|
2018-07-08 16:08:53 +02:00
|
|
|
play_sound(SOUND_0);
|
|
|
|
g_vars.inp_keyboard[0xBF] = 0;
|
|
|
|
g_vars.quit_level_flag = 1;
|
|
|
|
g_vars.play_level_flag = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].unk60 = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER2].unk60 = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER1].data5F = 0;
|
|
|
|
g_vars.objects[OBJECT_NUM_PLAYER2].data5F = 0;
|
|
|
|
if (!g_vars.play_demo_flag) {
|
|
|
|
g_vars.start_level = 0;
|
|
|
|
}
|
|
|
|
} else if (g_vars.inp_keyboard[0xC4] != 0) { // F10
|
|
|
|
play_sound(SOUND_0);
|
|
|
|
while (g_vars.inp_keyboard[0xC4] != 0 && g_vars.inp_keyboard[0xB] == 0);
|
|
|
|
while (g_vars.inp_keyboard[0xC4] != 0 && g_vars.inp_keyboard[0xB] != 0);
|
|
|
|
}
|
|
|
|
// demo
|
|
|
|
do_level_update_scrolling2();
|
|
|
|
do_level_update_objects();
|
2018-08-12 14:27:20 +02:00
|
|
|
if (!g_res.amiga_data) {
|
2018-07-22 15:28:05 +02:00
|
|
|
draw_foreground_tiles();
|
2018-07-08 16:08:53 +02:00
|
|
|
}
|
2018-07-08 16:39:28 +02:00
|
|
|
++g_vars.level_loop_counter;
|
2018-07-22 15:28:05 +02:00
|
|
|
draw_level_panel();
|
2018-08-12 14:27:20 +02:00
|
|
|
|
|
|
|
if (screen_transition_flag) {
|
|
|
|
screen_transition_flag = false;
|
|
|
|
g_sys.update_screen(g_res.vga, 0);
|
|
|
|
screen_do_transition2();
|
|
|
|
} else {
|
|
|
|
g_sys.update_screen(g_res.vga, 1);
|
|
|
|
}
|
|
|
|
memset(g_res.vga, 0, GAME_SCREEN_W * GAME_SCREEN_H);
|
2018-07-22 15:28:05 +02:00
|
|
|
|
2018-07-08 16:39:28 +02:00
|
|
|
const int diff = (timestamp + (1000 / 30)) - g_sys.get_timestamp();
|
|
|
|
g_sys.sleep(diff < 10 ? 10 : diff);
|
2018-07-08 16:08:53 +02:00
|
|
|
screen_clear_sprites();
|
|
|
|
|
2018-07-16 14:43:34 +02:00
|
|
|
} while (!g_sys.input.quit && !g_vars.quit_level_flag);
|
2018-08-12 14:27:20 +02:00
|
|
|
// g_vars.screen_draw_offset -= TILEMAP_OFFSET_Y * 40;
|
2018-07-08 16:08:53 +02:00
|
|
|
screen_unk5();
|
|
|
|
if (g_options.amiga_copper_bars) {
|
|
|
|
g_sys.set_copper_bars(0);
|
|
|
|
}
|
2018-12-16 15:28:52 +01:00
|
|
|
g_sys.render_set_sprites_clipping_rect(0, 0, GAME_SCREEN_W, GAME_SCREEN_H);
|
2018-07-08 16:08:53 +02:00
|
|
|
g_vars.inp_keyboard[0xBF] = 0;
|
|
|
|
}
|