2018-07-14 15:42:18 +00:00
|
|
|
/*
|
|
|
|
* xrick/src/e_them.c
|
|
|
|
*
|
|
|
|
* Copyright (C) 1998-2002 BigOrno (bigorno@bigorno.net). All rights reserved.
|
|
|
|
*
|
|
|
|
* The use and distribution terms for this software are contained in the file
|
|
|
|
* named README, which can be found in the root of this distribution. By
|
|
|
|
* using this software in any fashion, you are agreeing to be bound by the
|
|
|
|
* terms of this license.
|
|
|
|
*
|
|
|
|
* You must not remove this notice, or any other, from this software.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "system.h"
|
|
|
|
#include "game.h"
|
|
|
|
#include "ents.h"
|
|
|
|
#include "e_them.h"
|
|
|
|
|
|
|
|
#include "e_rick.h"
|
|
|
|
#include "e_bomb.h"
|
|
|
|
#include "e_bullet.h"
|
|
|
|
#include "maps.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
#define TYPE_1A (0x00)
|
|
|
|
#define TYPE_1B (0xff)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* public vars
|
|
|
|
*/
|
|
|
|
U32 e_them_rndseed = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* local vars
|
|
|
|
*/
|
|
|
|
static U16 e_them_rndnbr = 0;
|
|
|
|
|
2018-07-14 18:04:18 +00:00
|
|
|
#ifdef IIGS
|
|
|
|
#pragma noroot
|
|
|
|
segment "e";
|
|
|
|
#endif
|
|
|
|
|
2018-07-14 15:42:18 +00:00
|
|
|
/*
|
|
|
|
* Check if entity boxtests with a lethal e_them i.e. something lethal
|
|
|
|
* in slot 0 and 4 to 8.
|
|
|
|
*
|
|
|
|
* ASM 122E
|
|
|
|
*
|
|
|
|
* e: entity slot number.
|
|
|
|
* ret: TRUE/boxtests, FALSE/not
|
|
|
|
*/
|
|
|
|
U8
|
2018-09-20 23:57:09 +00:00
|
|
|
u_themtest(ent_t* pEnt)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
2018-09-20 23:57:09 +00:00
|
|
|
ent_t* pI;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
if ((ent_ents[0].n & ENT_LETHAL) && u_boxtest(pEnt, ent_ents))
|
2018-07-14 15:42:18 +00:00
|
|
|
return TRUE;
|
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
for (pI = &ent_ents[4]; pI < &ent_ents[9]; pI++)
|
|
|
|
if ((pI->n & ENT_LETHAL) && u_boxtest(pEnt, pI))
|
2018-07-14 15:42:18 +00:00
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Go zombie
|
|
|
|
*
|
|
|
|
* ASM 237B
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_gozombie(ent_t* pEnt)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
|
|
|
#define offsx c1
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->n = 0x47; /* zombie entity */
|
|
|
|
pEnt->front = TRUE;
|
|
|
|
pEnt->offsy = -0x0400;
|
2018-07-14 15:42:18 +00:00
|
|
|
#ifdef ENABLE_SOUND
|
|
|
|
syssnd_play(WAV_DIE, 1);
|
|
|
|
#endif
|
|
|
|
game_score += 50;
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->flags & ENT_FLG_ONCE) {
|
2018-07-14 15:42:18 +00:00
|
|
|
/* make sure entity won't be activated again */
|
2018-09-20 23:57:09 +00:00
|
|
|
map_marks[pEnt->mark].ent |= MAP_MARK_NACT;
|
2018-07-14 15:42:18 +00:00
|
|
|
}
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->offsx = (pEnt->x >= 0x80 ? -0x02 : 0x02);
|
2018-07-14 15:42:18 +00:00
|
|
|
#undef offsx
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Action sub-function for e_them _t1a and _t1b
|
|
|
|
*
|
|
|
|
* Those two types move horizontally, and fall if they have to.
|
|
|
|
* Type 1a moves horizontally over a given distance and then
|
|
|
|
* u-turns and repeats; type 1b is more subtle as it does u-turns
|
|
|
|
* in order to move horizontally towards rick.
|
|
|
|
*
|
|
|
|
* ASM 2242
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t1_action2(ent_t* pEnt, U8 type)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
|
|
|
#define offsx c1
|
|
|
|
#define step_count c2
|
|
|
|
U32 i;
|
|
|
|
S16 x, y;
|
|
|
|
U8 env0, env1;
|
|
|
|
|
|
|
|
/* by default, try vertical move. calculate new y */
|
2018-09-20 23:57:09 +00:00
|
|
|
i = (((S32)pEnt->y) << 8) + ((S32)pEnt->offsy) + ((U32)pEnt->ylow);
|
2018-07-14 15:42:18 +00:00
|
|
|
y = i >> 8;
|
|
|
|
|
|
|
|
/* deactivate if outside vertical boundaries */
|
|
|
|
/* no need to test zero since e_them _t1a/b don't go up */
|
|
|
|
/* FIXME what if they got scrolled out ? */
|
|
|
|
if (y > 0x140) {
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->n = 0;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* test environment */
|
2018-09-20 23:57:09 +00:00
|
|
|
u_envtest(pEnt->x, y, FALSE, &env0, &env1);
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
if (!(env1 & (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP))) {
|
|
|
|
/* vertical move possible: falling */
|
|
|
|
if (env1 & MAP_EFLG_LETHAL) {
|
|
|
|
/* lethal entities kill e_them */
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
/* save, cleanup and return */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->y = y;
|
|
|
|
pEnt->ylow = i;
|
|
|
|
pEnt->offsy += 0x0080;
|
|
|
|
if (pEnt->offsy > 0x0800)
|
|
|
|
pEnt->offsy = 0x0800;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* vertical move not possible. calculate new sprite */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->sprite = pEnt->sprbase
|
|
|
|
+ ent_sprseq[(pEnt->x & 0x1c) >> 3]
|
|
|
|
+ (pEnt->offsx < 0 ? 0x03 : 0x00);
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* reset offsy */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->offsy = 0x0080;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* align to ground */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->y &= 0xfff8;
|
|
|
|
pEnt->y |= 0x0003;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* latency: if not zero then decrease and return */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->latency > 0) {
|
|
|
|
pEnt->latency--;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* horizontal move. calculate new x */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->offsx == 0) /* not supposed to move -> don't */
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
x = pEnt->x + pEnt->offsx;
|
|
|
|
if (pEnt->x < 0 || pEnt->x > 0xe8) {
|
2018-07-14 15:42:18 +00:00
|
|
|
/* U-turn and return if reaching horizontal boundaries */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->step_count = 0;
|
|
|
|
pEnt->offsx = -pEnt->offsx;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* test environment */
|
2018-09-20 23:57:09 +00:00
|
|
|
u_envtest(x, pEnt->y, FALSE, &env0, &env1);
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
if (env1 & (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)) {
|
|
|
|
/* horizontal move not possible: u-turn and return */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->step_count = 0;
|
|
|
|
pEnt->offsx = -pEnt->offsx;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* horizontal move possible */
|
|
|
|
if (env1 & MAP_EFLG_LETHAL) {
|
|
|
|
/* lethal entities kill e_them */
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->x = x;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* depending on type, */
|
|
|
|
if (type == TYPE_1B) {
|
|
|
|
/* set direction to move horizontally towards rick */
|
2018-09-20 23:57:09 +00:00
|
|
|
if ((pEnt->x & 0x1e) != 0x10) /* prevents too frequent u-turns */
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->offsx = (pEnt->x < E_RICK_ENT.x) ? 0x02 : -0x02;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* set direction according to step counter */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->step_count++;
|
2018-07-14 15:42:18 +00:00
|
|
|
/* FIXME why trig_x (b16) ?? */
|
2018-09-20 23:57:09 +00:00
|
|
|
if ((pEnt->trig_x >> 1) > pEnt->step_count)
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* type is 1A and step counter reached its limit: u-turn */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->step_count = 0;
|
|
|
|
pEnt->offsx = -pEnt->offsx;
|
2018-07-14 15:42:18 +00:00
|
|
|
#undef offsx
|
|
|
|
#undef step_count
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* ASM 21CF
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t1_action(ent_t* pEnt, U8 type)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t1_action2(pEnt, type);
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* lethal entities kill them */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (u_themtest(pEnt)) {
|
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* bullet kills them */
|
|
|
|
if (E_BULLET_ENT.n &&
|
2018-09-20 23:57:09 +00:00
|
|
|
u_fboxtest(pEnt, E_BULLET_ENT.x + (e_bullet_offsx < 0 ? 0 : 0x18),
|
2018-07-14 15:42:18 +00:00
|
|
|
E_BULLET_ENT.y)) {
|
|
|
|
E_BULLET_ENT.n = 0;
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* bomb kills them */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (e_bomb_lethal && e_bomb_hit(pEnt)) {
|
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* rick stops them */
|
|
|
|
if (E_RICK_STTST(E_RICK_STSTOP) &&
|
2018-09-20 23:57:09 +00:00
|
|
|
u_fboxtest(pEnt, e_rick_stop_x, e_rick_stop_y))
|
|
|
|
pEnt->latency = 0x14;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* they kill rick */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (e_rick_boxtest(pEnt))
|
2018-07-14 15:42:18 +00:00
|
|
|
e_rick_gozombie();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Action function for e_them _t1a type (stays within boundaries)
|
|
|
|
*
|
|
|
|
* ASM 2452
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t1a_action(ent_t* pEnt)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t1_action(pEnt, TYPE_1A);
|
2018-07-14 15:42:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Action function for e_them _t1b type (runs for rick)
|
|
|
|
*
|
|
|
|
* ASM 21CA
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t1b_action(ent_t* pEnt)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t1_action(pEnt, TYPE_1B);
|
2018-07-14 15:42:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Action function for e_them _z (zombie) type
|
|
|
|
*
|
|
|
|
* ASM 23B8
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_z_action(ent_t* pEnt)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
|
|
|
#define offsx c1
|
|
|
|
U32 i;
|
|
|
|
|
|
|
|
/* calc new sprite */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->sprite = pEnt->sprbase
|
|
|
|
+ ((pEnt->x & 0x04) ? 0x07 : 0x06);
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* calc new y */
|
2018-09-20 23:57:09 +00:00
|
|
|
i = (((S32)pEnt->y) << 8) + ((S32)pEnt->offsy) + ((U32)pEnt->ylow);
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* deactivate if out of vertical boundaries */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->y < 0 || pEnt->y > 0x0140) {
|
|
|
|
pEnt->n = 0;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->offsy += 0x0080;
|
|
|
|
pEnt->ylow = i;
|
|
|
|
pEnt->y = i >> 8;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* calc new x */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->x += pEnt->offsx;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* must stay within horizontal boundaries */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->x < 0)
|
|
|
|
pEnt->x = 0;
|
|
|
|
if (pEnt->x > 0xe8)
|
|
|
|
pEnt->x = 0xe8;
|
2018-07-14 15:42:18 +00:00
|
|
|
#undef offsx
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Action sub-function for e_them _t2.
|
|
|
|
*
|
|
|
|
* Must document what it does.
|
|
|
|
*
|
|
|
|
* ASM 2792
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t2_action2(ent_t* pEnt)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
|
|
|
#define flgclmb c1
|
|
|
|
#define offsx c2
|
|
|
|
U32 i;
|
|
|
|
S16 x, y, yd;
|
|
|
|
U8 env0, env1;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* vars required by the Black Magic (tm) performance at the
|
|
|
|
* end of this function.
|
|
|
|
*/
|
|
|
|
static U16 bx;
|
2018-07-14 18:04:18 +00:00
|
|
|
static U8 *bl = (U8*)&bx;
|
|
|
|
U8 *bh = bl+1;
|
2018-07-14 15:42:18 +00:00
|
|
|
static U16 cx;
|
2018-07-14 18:04:18 +00:00
|
|
|
static U8 *cl = (U8*)&cx;
|
|
|
|
U8 *ch = cl+1;
|
|
|
|
static U16 *sl = (U16*)&e_them_rndseed;
|
|
|
|
U16 *sh = sl+1;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/*sys_printf("e_them_t2 ------------------------------\n");*/
|
|
|
|
|
|
|
|
/* latency: if not zero then decrease */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->latency > 0) pEnt->latency--;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* climbing? */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->flgclmb != TRUE) goto climbing_not;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* CLIMBING */
|
|
|
|
|
|
|
|
/*sys_printf("e_them_t2 climbing\n");*/
|
|
|
|
|
|
|
|
/* latency: if not zero then return */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->latency > 0) return;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* calc new sprite */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->sprite = pEnt->sprbase + 0x08 +
|
|
|
|
(((pEnt->x ^ pEnt->y) & 0x04) ? 1 : 0);
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* reached rick's level? */
|
2018-09-20 23:57:09 +00:00
|
|
|
if ((pEnt->y & 0xfe) != (E_RICK_ENT.y & 0xfe)) goto ymove;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
xmove:
|
|
|
|
/* calc new x and test environment */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->offsx = (pEnt->x < E_RICK_ENT.x) ? 0x02 : -0x02;
|
|
|
|
x = pEnt->x + pEnt->offsx;
|
|
|
|
u_envtest(x, pEnt->y, FALSE, &env0, &env1);
|
2018-07-14 15:42:18 +00:00
|
|
|
if (env1 & (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP))
|
|
|
|
return;
|
|
|
|
if (env1 & MAP_EFLG_LETHAL) {
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->x = x;
|
2018-07-14 15:42:18 +00:00
|
|
|
if (env1 & (MAP_EFLG_VERT|MAP_EFLG_CLIMB)) /* still climbing */
|
|
|
|
return;
|
|
|
|
goto climbing_not; /* not climbing anymore */
|
|
|
|
|
|
|
|
ymove:
|
|
|
|
/* calc new y and test environment */
|
2018-09-20 23:57:09 +00:00
|
|
|
yd = pEnt->y < E_RICK_ENT.y ? 0x02 : -0x02;
|
|
|
|
y = pEnt->y + yd;
|
2018-07-14 15:42:18 +00:00
|
|
|
if (y < 0 || y > 0x0140) {
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->n = 0;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-09-20 23:57:09 +00:00
|
|
|
u_envtest(pEnt->x, y, FALSE, &env0, &env1);
|
2018-07-14 15:42:18 +00:00
|
|
|
if (env1 & (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP)) {
|
|
|
|
if (yd < 0)
|
|
|
|
goto xmove; /* can't go up */
|
|
|
|
else
|
|
|
|
goto climbing_not; /* can't go down */
|
|
|
|
}
|
|
|
|
/* can move */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->y = y;
|
2018-07-14 15:42:18 +00:00
|
|
|
if (env1 & (MAP_EFLG_VERT|MAP_EFLG_CLIMB)) /* still climbing */
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* NOT CLIMBING */
|
|
|
|
|
|
|
|
climbing_not:
|
|
|
|
/*sys_printf("e_them_t2 climbing NOT\n");*/
|
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->flgclmb = FALSE; /* not climbing */
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* calc new y (falling) and test environment */
|
2018-09-20 23:57:09 +00:00
|
|
|
i = (pEnt->y << 8) + pEnt->offsy + pEnt->ylow;
|
2018-07-14 15:42:18 +00:00
|
|
|
y = i >> 8;
|
2018-09-20 23:57:09 +00:00
|
|
|
u_envtest(pEnt->x, y, FALSE, &env0, &env1);
|
2018-07-14 15:42:18 +00:00
|
|
|
if (!(env1 & (MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP))) {
|
|
|
|
/*sys_printf("e_them_t2 y move OK\n");*/
|
|
|
|
/* can go there */
|
|
|
|
if (env1 & MAP_EFLG_LETHAL) {
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (y > 0x0140) { /* deactivate if outside */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->n = 0;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!(env1 & MAP_EFLG_VERT)) {
|
|
|
|
/* save */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->y = y;
|
|
|
|
pEnt->ylow = i;
|
|
|
|
pEnt->offsy += 0x0080;
|
|
|
|
if (pEnt->offsy > 0x0800)
|
|
|
|
pEnt->offsy = 0x0800;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
2018-09-20 23:57:09 +00:00
|
|
|
if (((pEnt->x & 0x07) == 0x04) && (y < E_RICK_ENT.y)) {
|
2018-07-14 15:42:18 +00:00
|
|
|
/*sys_printf("e_them_t2 climbing00\n");*/
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->flgclmb = TRUE; /* climbing */
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*sys_printf("e_them_t2 ymove nok or ...\n");*/
|
|
|
|
/* can't go there, or ... */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->y = (pEnt->y & 0xf8) | 0x03; /* align to ground */
|
|
|
|
pEnt->offsy = 0x0100;
|
|
|
|
if (pEnt->latency != 00)
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
if ((env1 & MAP_EFLG_CLIMB) &&
|
2018-09-20 23:57:09 +00:00
|
|
|
((pEnt->x & 0x0e) == 0x04) &&
|
|
|
|
(pEnt->y > E_RICK_ENT.y)) {
|
2018-07-14 15:42:18 +00:00
|
|
|
/*sys_printf("e_them_t2 climbing01\n");*/
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->flgclmb = TRUE; /* climbing */
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* calc new sprite */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->sprite = pEnt->sprbase +
|
|
|
|
ent_sprseq[(pEnt->offsx < 0 ? 4 : 0) +
|
|
|
|
((pEnt->x & 0x0e) >> 3)];
|
|
|
|
/*sys_printf("e_them_t2 sprite %02x\n", pEnt->sprite);*/
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->offsx == 0)
|
|
|
|
pEnt->offsx = 2;
|
|
|
|
x = pEnt->x + pEnt->offsx;
|
2018-07-14 15:42:18 +00:00
|
|
|
/*sys_printf("e_them_t2 xmove x=%02x\n", x);*/
|
|
|
|
if (x < 0xe8) {
|
2018-09-20 23:57:09 +00:00
|
|
|
u_envtest(x, pEnt->y, FALSE, &env0, &env1);
|
2018-07-14 15:42:18 +00:00
|
|
|
if (!(env1 & (MAP_EFLG_VERT|MAP_EFLG_SOLID|MAP_EFLG_SPAD|MAP_EFLG_WAYUP))) {
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->x = x;
|
2018-07-14 15:42:18 +00:00
|
|
|
if ((x & 0x1e) != 0x08)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Black Magic (tm)
|
|
|
|
*
|
|
|
|
* this is obviously some sort of randomizer to define a direction
|
|
|
|
* for the entity. it is an exact copy of what the assembler code
|
|
|
|
* does but I can't explain.
|
|
|
|
*/
|
|
|
|
bx = e_them_rndnbr + *sh + *sl + 0x0d;
|
|
|
|
cx = *sh;
|
|
|
|
*bl ^= *ch;
|
|
|
|
*bl ^= *cl;
|
|
|
|
*bl ^= *bh;
|
|
|
|
e_them_rndnbr = bx;
|
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->offsx = (*bl & 0x01) ? -0x02 : 0x02;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* back to normal */
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* U-turn */
|
|
|
|
/*sys_printf("e_them_t2 u-turn\n");*/
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->offsx == 0)
|
|
|
|
pEnt->offsx = 2;
|
2018-07-14 15:42:18 +00:00
|
|
|
else
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->offsx = -pEnt->offsx;
|
2018-07-14 15:42:18 +00:00
|
|
|
#undef offsx
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Action function for e_them _t2 type
|
|
|
|
*
|
|
|
|
* ASM 2718
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t2_action(ent_t* pEnt)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t2_action2(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* they kill rick */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (e_rick_boxtest(pEnt))
|
2018-07-14 15:42:18 +00:00
|
|
|
e_rick_gozombie();
|
|
|
|
|
|
|
|
/* lethal entities kill them */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (u_themtest(pEnt)) {
|
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* bullet kills them */
|
|
|
|
if (E_BULLET_ENT.n &&
|
2018-09-20 23:57:09 +00:00
|
|
|
u_fboxtest(pEnt, E_BULLET_ENT.x + (e_bullet_offsx < 0 ? 00 : 0x18),
|
2018-07-14 15:42:18 +00:00
|
|
|
E_BULLET_ENT.y)) {
|
|
|
|
E_BULLET_ENT.n = 0;
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* bomb kills them */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (e_bomb_lethal && e_bomb_hit(pEnt)) {
|
|
|
|
e_them_gozombie(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* rick stops them */
|
|
|
|
if (E_RICK_STTST(E_RICK_STSTOP) &&
|
2018-09-20 23:57:09 +00:00
|
|
|
u_fboxtest(pEnt, e_rick_stop_x, e_rick_stop_y))
|
|
|
|
pEnt->latency = 0x14;
|
2018-07-14 15:42:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Action sub-function for e_them _t3
|
|
|
|
*
|
|
|
|
* FIXME always starts asleep??
|
|
|
|
*
|
|
|
|
* Waits until triggered by something, then execute move steps from
|
|
|
|
* ent_mvstep with sprite from ent_sprseq. When done, either restart
|
|
|
|
* or disappear.
|
|
|
|
*
|
|
|
|
* Not always lethal ... but if lethal, kills rick.
|
|
|
|
*
|
|
|
|
* ASM: 255A
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t3_action2(ent_t* pEnt)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
|
|
|
#define sproffs c1
|
|
|
|
#define step_count c2
|
|
|
|
U8 i;
|
|
|
|
S16 x, y;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
|
|
|
|
/* calc new sprite */
|
2018-09-20 23:57:09 +00:00
|
|
|
i = ent_sprseq[pEnt->sprbase + pEnt->sproffs];
|
2018-07-14 15:42:18 +00:00
|
|
|
if (i == 0xff)
|
2018-09-20 23:57:09 +00:00
|
|
|
i = ent_sprseq[pEnt->sprbase];
|
|
|
|
pEnt->sprite = i;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->sproffs != 0) { /* awake */
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* rotate sprseq */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (ent_sprseq[pEnt->sprbase + pEnt->sproffs] != 0xff)
|
|
|
|
pEnt->sproffs++;
|
|
|
|
if (ent_sprseq[pEnt->sprbase + pEnt->sproffs] == 0xff)
|
|
|
|
pEnt->sproffs = 1;
|
2018-07-14 15:42:18 +00:00
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->step_count < ent_mvstep[pEnt->step_no].count) {
|
2018-07-14 15:42:18 +00:00
|
|
|
/*
|
|
|
|
* still running this step: try to increment x and y while
|
|
|
|
* checking that they remain within boudaries. if so, return.
|
|
|
|
* else switch to next step.
|
|
|
|
*/
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->step_count++;
|
|
|
|
x = pEnt->x + ((S16)(ent_mvstep[pEnt->step_no].dx));
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* check'n save */
|
|
|
|
if (x > 0 && x < 0xe8) {
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->x = x;
|
2018-07-14 15:42:18 +00:00
|
|
|
/*FIXME*/
|
|
|
|
/*
|
2018-09-20 23:57:09 +00:00
|
|
|
y = ent_mvstep[pEnt->step_no].dy;
|
2018-07-14 15:42:18 +00:00
|
|
|
if (y < 0)
|
|
|
|
y += 0xff00;
|
2018-09-20 23:57:09 +00:00
|
|
|
y += pEnt->y;
|
2018-07-14 15:42:18 +00:00
|
|
|
*/
|
2018-09-20 23:57:09 +00:00
|
|
|
y = pEnt->y + ((S16)(ent_mvstep[pEnt->step_no].dy));
|
2018-07-14 15:42:18 +00:00
|
|
|
if (y > 0 && y < 0x0140) {
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->y = y;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* step is done, or x or y is outside boundaries. try to
|
|
|
|
* switch to next step
|
|
|
|
*/
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->step_no++;
|
|
|
|
if (ent_mvstep[pEnt->step_no].count != 0xff) {
|
2018-07-14 15:42:18 +00:00
|
|
|
/* there is a next step: init and loop */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->step_count = 0;
|
2018-07-14 15:42:18 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* there is no next step: restart or deactivate */
|
|
|
|
if (!E_RICK_STTST(E_RICK_STZOMBIE) &&
|
2018-09-20 23:57:09 +00:00
|
|
|
!(pEnt->flags & ENT_FLG_ONCE)) {
|
2018-07-14 15:42:18 +00:00
|
|
|
/* loop this entity */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->sproffs = 0;
|
|
|
|
pEnt->n &= ~ENT_LETHAL;
|
|
|
|
if (pEnt->flags & ENT_FLG_LETHALR)
|
|
|
|
pEnt->n |= ENT_LETHAL;
|
|
|
|
pEnt->x = pEnt->xsave;
|
|
|
|
pEnt->y = pEnt->ysave;
|
|
|
|
if (pEnt->y < 0 || pEnt->y > 0x140) {
|
|
|
|
pEnt->n = 0;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* deactivate this entity */
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->n = 0;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-09-20 23:57:09 +00:00
|
|
|
else { /* pEnt->sprseq1 == 0 -- waiting */
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* ugly GOTOs */
|
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->flags & ENT_FLG_TRIGRICK) { /* reacts to rick */
|
2018-07-14 15:42:18 +00:00
|
|
|
/* wake up if triggered by rick */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (u_trigbox(pEnt, E_RICK_ENT.x + 0x0C, E_RICK_ENT.y + 0x0A))
|
2018-07-14 15:42:18 +00:00
|
|
|
goto wakeup;
|
|
|
|
}
|
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->flags & ENT_FLG_TRIGSTOP) { /* reacts to rick "stop" */
|
2018-07-14 15:42:18 +00:00
|
|
|
/* wake up if triggered by rick "stop" */
|
|
|
|
if (E_RICK_STTST(E_RICK_STSTOP) &&
|
2018-09-20 23:57:09 +00:00
|
|
|
u_trigbox(pEnt, e_rick_stop_x, e_rick_stop_y))
|
2018-07-14 15:42:18 +00:00
|
|
|
goto wakeup;
|
|
|
|
}
|
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->flags & ENT_FLG_TRIGBULLET) { /* reacts to bullets */
|
2018-07-14 15:42:18 +00:00
|
|
|
/* wake up if triggered by bullet */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (E_BULLET_ENT.n && u_trigbox(pEnt, e_bullet_xc, e_bullet_yc)) {
|
2018-07-14 15:42:18 +00:00
|
|
|
E_BULLET_ENT.n = 0;
|
|
|
|
goto wakeup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-20 23:57:09 +00:00
|
|
|
if (pEnt->flags & ENT_FLG_TRIGBOMB) { /* reacts to bombs */
|
2018-07-14 15:42:18 +00:00
|
|
|
/* wake up if triggered by bomb */
|
2018-09-20 23:57:09 +00:00
|
|
|
if (e_bomb_lethal && u_trigbox(pEnt, e_bomb_xc, e_bomb_yc))
|
2018-07-14 15:42:18 +00:00
|
|
|
goto wakeup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* not triggered: keep waiting */
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* something triggered the entity: wake up */
|
|
|
|
/* initialize step counter */
|
|
|
|
wakeup:
|
|
|
|
if E_RICK_STTST(E_RICK_STZOMBIE)
|
|
|
|
return;
|
|
|
|
#ifdef ENABLE_SOUND
|
|
|
|
/*
|
|
|
|
* FIXME the sound should come from a table, there are 10 of them
|
|
|
|
* but I dont have the table yet. must rip the data off the game...
|
|
|
|
* FIXME is it 8 of them, not 10?
|
|
|
|
* FIXME testing below...
|
|
|
|
*/
|
2018-09-20 23:57:09 +00:00
|
|
|
syssnd_play(WAV_ENTITY[(pEnt->trigsnd & 0x1F) - 0x14], 1);
|
2018-07-14 15:42:18 +00:00
|
|
|
/*syssnd_play(WAV_ENTITY[0], 1);*/
|
|
|
|
#endif
|
2018-09-20 23:57:09 +00:00
|
|
|
pEnt->n &= ~ENT_LETHAL;
|
|
|
|
if (pEnt->flags & ENT_FLG_LETHALI)
|
|
|
|
pEnt->n |= ENT_LETHAL;
|
|
|
|
pEnt->sproffs = 1;
|
|
|
|
pEnt->step_count = 0;
|
|
|
|
pEnt->step_no = pEnt->step_no_i;
|
2018-07-14 15:42:18 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#undef step_count
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Action function for e_them _t3 type
|
|
|
|
*
|
|
|
|
* ASM 2546
|
|
|
|
*/
|
|
|
|
void
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t3_action(ent_t* pEnt)
|
2018-07-14 15:42:18 +00:00
|
|
|
{
|
2018-09-20 23:57:09 +00:00
|
|
|
e_them_t3_action2(pEnt);
|
2018-07-14 15:42:18 +00:00
|
|
|
|
|
|
|
/* if lethal, can kill rick */
|
2018-09-20 23:57:09 +00:00
|
|
|
if ((pEnt->n & ENT_LETHAL) &&
|
|
|
|
!E_RICK_STTST(E_RICK_STZOMBIE) && e_rick_boxtest(pEnt)) { /* CALL 1130 */
|
2018-07-14 15:42:18 +00:00
|
|
|
e_rick_gozombie();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* eof */
|
|
|
|
|
|
|
|
|