628 lines
14 KiB
C++
628 lines
14 KiB
C++
#include "NpcHit.h"
|
|
|
|
#include "WindowsWrapper.h"
|
|
|
|
#include "Back.h"
|
|
#include "Bullet.h"
|
|
#include "Caret.h"
|
|
#include "Flags.h"
|
|
#include "Game.h"
|
|
#include "Map.h"
|
|
#include "MyChar.h"
|
|
#include "NpChar.h"
|
|
#include "Sound.h"
|
|
#include "TextScr.h"
|
|
#include "ValueView.h"
|
|
|
|
void JadgeHitNpCharBlock(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
if (npc->y - npc->hit.top < (y * 0x10 + 5) * 0x200
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 - 5) * 0x200
|
|
&& npc->x - npc->hit.back < (x * 0x10 + 8) * 0x200
|
|
&& npc->x - npc->hit.back > x * 0x10 * 0x200)
|
|
{
|
|
npc->x = ((x * 0x10 + 8) * 0x200) + npc->hit.back;
|
|
hit |= 1;
|
|
}
|
|
|
|
if (npc->y - npc->hit.top < (y * 0x10 + 5) * 0x200
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 - 5) * 0x200
|
|
&& npc->x + npc->hit.back > (x * 0x10 - 8) * 0x200
|
|
&& npc->x + npc->hit.back < x * 0x10 * 0x200)
|
|
{
|
|
npc->x = ((x * 0x10 - 8) * 0x200) - npc->hit.back;
|
|
hit |= 4;
|
|
}
|
|
|
|
if (npc->x - npc->hit.back < (x * 0x10 + 5) * 0x200
|
|
&& npc->x + npc->hit.back > (x * 0x10 - 5) * 0x200
|
|
&& npc->y - npc->hit.top < (y * 0x10 + 8) * 0x200
|
|
&& npc->y - npc->hit.top > y * 0x10 * 0x200)
|
|
{
|
|
npc->y = ((y * 0x10 + 8) * 0x200) + npc->hit.top;
|
|
npc->ym = 0;
|
|
hit |= 2;
|
|
}
|
|
|
|
if (npc->x - npc->hit.back < (x * 0x10 + 5) * 0x200
|
|
&& npc->x + npc->hit.back > (x * 0x10 - 5) * 0x200
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 - 8) * 0x200
|
|
&& npc->y + npc->hit.bottom < y * 0x10 * 0x200)
|
|
{
|
|
npc->y = ((y * 0x10 - 8) * 0x200) - npc->hit.bottom;
|
|
npc->ym = 0;
|
|
hit |= 8;
|
|
}
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void JudgeHitNpCharTriangleA(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
if (npc->x < (x * 0x10 + 8) * 0x200
|
|
&& npc->x > (x * 0x10 - 8) * 0x200
|
|
&& npc->y - npc->hit.top < (y * 0x10 * 0x200) - ((npc->x - (x * 0x10 * 0x200)) / 2) + 0x800
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 - 8) * 0x200)
|
|
{
|
|
//Clip
|
|
npc->y = (y * 0x10 * 0x200) - ((npc->x - (x * 0x10 * 0x200)) / 2) + 0x800 + npc->hit.top;
|
|
|
|
//Halt momentum
|
|
if (npc->ym < 0)
|
|
npc->ym = 0;
|
|
|
|
//Set that hit a ceiling
|
|
hit |= 2;
|
|
}
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void JudgeHitNpCharTriangleB(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
if (npc->x < (x * 0x10 + 8) * 0x200
|
|
&& npc->x > (x * 0x10 - 8) * 0x200
|
|
&& npc->y - npc->hit.top < (y * 0x10 * 0x200) - ((npc->x - (x * 0x10 * 0x200)) / 2) - 0x800
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 - 8) * 0x200)
|
|
{
|
|
//Clip
|
|
npc->y = (y * 0x10 * 0x200) - ((npc->x - (x * 0x10 * 0x200)) / 2) - 0x800 + npc->hit.top;
|
|
|
|
//Halt momentum
|
|
if (npc->ym < 0)
|
|
npc->ym = 0;
|
|
|
|
//Set that hit a ceiling
|
|
hit |= 2;
|
|
}
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void JudgeHitNpCharTriangleC(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
if (npc->x < (x * 0x10 + 8) * 0x200
|
|
&& npc->x > (x * 0x10 - 8) * 0x200
|
|
&& npc->y - npc->hit.top < (y * 0x10 * 0x200) + ((npc->x - (x * 0x10 * 0x200)) / 2) - 0x800
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 - 8) * 0x200)
|
|
{
|
|
//Clip
|
|
npc->y = (y * 0x10 * 0x200) + ((npc->x - (x * 0x10 * 0x200)) / 2) - 0x800 + npc->hit.top;
|
|
|
|
//Halt momentum
|
|
if (npc->ym < 0)
|
|
npc->ym = 0;
|
|
|
|
//Set that hit a ceiling
|
|
hit |= 2;
|
|
}
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void JudgeHitNpCharTriangleD(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
if (npc->x < (x * 0x10 + 8) * 0x200
|
|
&& npc->x > (x * 0x10 - 8) * 0x200
|
|
&& npc->y - npc->hit.top < (y * 0x10 * 0x200) + ((npc->x - (x * 0x10 * 0x200)) / 2) + 0x800
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 - 8) * 0x200)
|
|
{
|
|
//Clip
|
|
npc->y = (y * 0x10 * 0x200) + ((npc->x - (x * 0x10 * 0x200)) / 2) + 0x800 + npc->hit.top;
|
|
|
|
//Halt momentum
|
|
if (npc->ym < 0)
|
|
npc->ym = 0;
|
|
|
|
//Set that hit a ceiling
|
|
hit |= 2;
|
|
}
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void JudgeHitNpCharTriangleE(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
hit |= 0x10000;
|
|
|
|
if (npc->x < (x * 0x10 + 8) * 0x200
|
|
&& npc->x > (x * 0x10 - 8) * 0x200
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 * 0x200) + ((npc->x - (x * 0x10 * 0x200)) / 2) - 0x800
|
|
&& npc->y - npc->hit.top < (y * 0x10 + 8) * 0x200)
|
|
{
|
|
//Clip
|
|
npc->y = (y * 0x10 * 0x200) + ((npc->x - (x * 0x10 * 0x200)) / 2) - 0x800 - npc->hit.bottom;
|
|
|
|
//Halt momentum
|
|
if (npc->ym > 0)
|
|
npc->ym = 0;
|
|
|
|
//Set that hit this slope
|
|
hit |= 0x28;
|
|
}
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void JudgeHitNpCharTriangleF(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
hit |= 0x20000;
|
|
|
|
if (npc->x < (x * 0x10 + 8) * 0x200
|
|
&& npc->x >= (x * 0x10 - 8) * 0x200 // Note that this function uses '>='. I'm not sure if this is a bug.
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 * 0x200) + ((npc->x - (x * 0x10 * 0x200)) / 2) + 0x800
|
|
&& npc->y - npc->hit.top < (y * 0x10 + 8) * 0x200)
|
|
{
|
|
//Clip
|
|
npc->y = (y * 0x10 * 0x200) + ((npc->x - (x * 0x10 * 0x200)) / 2) + 0x800 - npc->hit.bottom;
|
|
|
|
//Halt momentum
|
|
if (npc->ym > 0)
|
|
npc->ym = 0;
|
|
|
|
//Set that hit this slope
|
|
hit |= 0x28;
|
|
}
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void JudgeHitNpCharTriangleG(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
hit |= 0x40000;
|
|
|
|
if (npc->x < (x * 0x10 + 8) * 0x200
|
|
&& npc->x > (x * 0x10 - 8) * 0x200
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 * 0x200) - ((npc->x - (x * 0x10 * 0x200)) / 2) + 0x800
|
|
&& npc->y - npc->hit.top < (y * 0x10 + 8) * 0x200)
|
|
{
|
|
//Clip
|
|
npc->y = (y * 0x10 * 0x200) - ((npc->x - (x * 0x10 * 0x200)) / 2) + 0x800 - npc->hit.bottom;
|
|
|
|
//Halt momentum
|
|
if (npc->ym > 0)
|
|
npc->ym = 0;
|
|
|
|
//Set that hit this slope
|
|
hit |= 0x18;
|
|
}
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void JudgeHitNpCharTriangleH(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
hit |= 0x80000;
|
|
|
|
if (npc->x < (x * 0x10 + 8) * 0x200
|
|
&& npc->x > (x * 0x10 - 8) * 0x200
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 * 0x200) - ((npc->x - (x * 0x10 * 0x200)) / 2) - 0x800
|
|
&& npc->y - npc->hit.top < (y * 0x10 + 8) * 0x200)
|
|
{
|
|
//Clip
|
|
npc->y = (y * 0x10 * 0x200) - ((npc->x - (x * 0x10 * 0x200)) / 2) - 0x800 - npc->hit.bottom;
|
|
|
|
//Halt momentum
|
|
if (npc->ym > 0)
|
|
npc->ym = 0;
|
|
|
|
//Set that hit this slope
|
|
hit |= 0x18;
|
|
}
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void JudgeHitNpCharWater(NPCHAR *npc, int x, int y)
|
|
{
|
|
int hit = 0;
|
|
|
|
if (npc->x - npc->hit.back < (x * 0x10 + 6) * 0x200
|
|
&& npc->x + npc->hit.back > (x * 0x10 - 6) * 0x200
|
|
&& npc->y - npc->hit.top < (y * 0x10 + 6) * 0x200
|
|
&& npc->y + npc->hit.bottom > (y * 0x10 - 6) * 0x200)
|
|
hit |= 0x100;
|
|
|
|
npc->flag |= hit;
|
|
}
|
|
|
|
void HitNpCharMap()
|
|
{
|
|
int judg, x, y;
|
|
|
|
int offx[9];
|
|
int offy[9];
|
|
|
|
int i;
|
|
int j;
|
|
|
|
offx[0] = 0;
|
|
offx[1] = 1;
|
|
offx[2] = 0;
|
|
offx[3] = 1;
|
|
offx[4] = 2;
|
|
offx[5] = 2;
|
|
offx[6] = 2;
|
|
offx[7] = 0;
|
|
offx[8] = 1;
|
|
|
|
offy[0] = 0;
|
|
offy[1] = 0;
|
|
offy[2] = 1;
|
|
offy[3] = 1;
|
|
offy[4] = 0;
|
|
offy[5] = 1;
|
|
offy[6] = 2;
|
|
offy[7] = 2;
|
|
offy[8] = 2;
|
|
|
|
for (i = 0; i < NPC_MAX; i++)
|
|
{
|
|
if ((gNPC[i].cond & 0x80) == 0)
|
|
continue;
|
|
|
|
if (gNPC[i].bits & 8)
|
|
continue;
|
|
|
|
if (gNPC[i].size >= 3)
|
|
{
|
|
judg = 9;
|
|
x = (gNPC[i].x - 0x1000) / 0x10 / 0x200;
|
|
y = (gNPC[i].y - 0x1000) / 0x10 / 0x200;
|
|
}
|
|
else
|
|
{
|
|
judg = 4;
|
|
x = gNPC[i].x / 0x10 / 0x200;
|
|
y = gNPC[i].y / 0x10 / 0x200;
|
|
}
|
|
|
|
gNPC[i].flag = 0;
|
|
|
|
for (j = 0; j < judg; j++)
|
|
{
|
|
switch (GetAttribute(x + offx[j], y + offy[j]))
|
|
{
|
|
//No NPC block
|
|
case 0x44:
|
|
if (gNPC[i].bits & npc_ignore44)
|
|
break;
|
|
// Fallthrough
|
|
//Block
|
|
case 0x03:
|
|
case 0x05:
|
|
case 0x41:
|
|
case 0x43:
|
|
JadgeHitNpCharBlock(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
//Slopes
|
|
case 0x50:
|
|
JudgeHitNpCharTriangleA(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x51:
|
|
JudgeHitNpCharTriangleB(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x52:
|
|
JudgeHitNpCharTriangleC(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x53:
|
|
JudgeHitNpCharTriangleD(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x54:
|
|
JudgeHitNpCharTriangleE(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x55:
|
|
JudgeHitNpCharTriangleF(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x56:
|
|
JudgeHitNpCharTriangleG(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x57:
|
|
JudgeHitNpCharTriangleH(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
//Water
|
|
case 0x02:
|
|
case 0x60:
|
|
case 0x62:
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
//Water block
|
|
case 0x04:
|
|
case 0x61:
|
|
case 0x64:
|
|
JadgeHitNpCharBlock(&gNPC[i], x + offx[j], y + offy[j]);
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
//Water slopes
|
|
case 0x70:
|
|
JudgeHitNpCharTriangleA(&gNPC[i], x + offx[j], y + offy[j]);
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x71:
|
|
JudgeHitNpCharTriangleB(&gNPC[i], x + offx[j], y + offy[j]);
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x72:
|
|
JudgeHitNpCharTriangleC(&gNPC[i], x + offx[j], y + offy[j]);
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x73:
|
|
JudgeHitNpCharTriangleD(&gNPC[i], x + offx[j], y + offy[j]);
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x74:
|
|
JudgeHitNpCharTriangleE(&gNPC[i], x + offx[j], y + offy[j]);
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x75:
|
|
JudgeHitNpCharTriangleF(&gNPC[i], x + offx[j], y + offy[j]);
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x76:
|
|
JudgeHitNpCharTriangleG(&gNPC[i], x + offx[j], y + offy[j]);
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0x77:
|
|
JudgeHitNpCharTriangleH(&gNPC[i], x + offx[j], y + offy[j]);
|
|
JudgeHitNpCharWater(&gNPC[i], x + offx[j], y + offy[j]);
|
|
break;
|
|
|
|
case 0xA0:
|
|
gNPC[i].flag |= 0x100;
|
|
// Fallthrough
|
|
case 0x80:
|
|
gNPC[i].flag |= 0x1000;
|
|
break;
|
|
|
|
case 0xA1:
|
|
gNPC[i].flag |= 0x100;
|
|
// Fallthrough
|
|
case 0x81:
|
|
gNPC[i].flag |= 0x2000;
|
|
break;
|
|
|
|
case 0xA2:
|
|
gNPC[i].flag |= 0x100;
|
|
// Fallthrough
|
|
case 0x82:
|
|
gNPC[i].flag |= 0x4000;
|
|
break;
|
|
|
|
case 0xA3:
|
|
gNPC[i].flag |= 0x100;
|
|
// Fallthrough
|
|
case 0x83:
|
|
gNPC[i].flag |= 0x8000;
|
|
break;
|
|
}
|
|
|
|
if (gNPC[i].y > gWaterY + 0x800)
|
|
gNPC[i].flag |= 0x100;
|
|
}
|
|
}
|
|
}
|
|
|
|
void LoseNpChar(NPCHAR *npc, BOOL bVanish)
|
|
{
|
|
//Play death sound
|
|
PlaySoundObject(npc->destroy_voice, 1);
|
|
|
|
//Create smoke
|
|
switch (npc->size)
|
|
{
|
|
case 1:
|
|
SetDestroyNpChar(npc->x, npc->y, npc->view.back, 3);
|
|
break;
|
|
case 2:
|
|
SetDestroyNpChar(npc->x, npc->y, npc->view.back, 7);
|
|
break;
|
|
case 3:
|
|
SetDestroyNpChar(npc->x, npc->y, npc->view.back, 12);
|
|
break;
|
|
}
|
|
|
|
//Create drop
|
|
if (npc->exp)
|
|
{
|
|
int val;
|
|
|
|
switch (Random(1, 5))
|
|
{
|
|
case 1:
|
|
// Spawn health
|
|
if (npc->exp > 6)
|
|
val = 6;
|
|
else
|
|
val = 2;
|
|
|
|
SetLifeObject(npc->x, npc->y, val);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
// Spawn missile launcher ammo
|
|
if (npc->exp > 6)
|
|
val = 3;
|
|
else
|
|
val = 1;
|
|
|
|
if (SetBulletObject(npc->x, npc->y, val))
|
|
break;
|
|
|
|
// Fallthrough
|
|
default:
|
|
// Spawn weapon energy
|
|
SetExpObjects(npc->x, npc->y, npc->exp);
|
|
}
|
|
}
|
|
|
|
//Set flag
|
|
SetNPCFlag(npc->code_flag);
|
|
|
|
//Create value view
|
|
if (npc->bits & npc_showDamage)
|
|
{
|
|
if ((npc->bits & npc_showDamage) && npc->damage_view)
|
|
SetValueView(&npc->x, &npc->y, npc->damage_view);
|
|
if (bVanish)
|
|
VanishNpChar(npc);
|
|
}
|
|
else
|
|
{
|
|
npc->cond = 0;
|
|
}
|
|
}
|
|
|
|
void HitNpCharBullet()
|
|
{
|
|
int n;
|
|
int b;
|
|
BOOL bHit;
|
|
|
|
for (n = 0; n < NPC_MAX; n++)
|
|
{
|
|
if ((gNPC[n].cond & 0x80) == 0)
|
|
continue;
|
|
|
|
if (gNPC[n].bits & npc_shootable && gNPC[n].bits & npc_interact)
|
|
continue;
|
|
|
|
for (b = 0; b < BULLET_MAX; b++)
|
|
{
|
|
if ((gBul[b].cond & 0x80) == 0)
|
|
continue;
|
|
|
|
if (gBul[b].damage == -1)
|
|
continue;
|
|
|
|
//Check if bullet touches npc
|
|
bHit = FALSE;
|
|
if (gNPC[n].bits & npc_shootable
|
|
&& gNPC[n].x - gNPC[n].hit.back < gBul[b].x + gBul[b].enemyXL
|
|
&& gNPC[n].x + gNPC[n].hit.back > gBul[b].x - gBul[b].enemyXL
|
|
&& gNPC[n].y - gNPC[n].hit.top < gBul[b].y + gBul[b].enemyYL
|
|
&& gNPC[n].y + gNPC[n].hit.bottom > gBul[b].y - gBul[b].enemyYL)
|
|
bHit = TRUE;
|
|
else if (gNPC[n].bits & npc_invulnerable
|
|
&& gNPC[n].x - gNPC[n].hit.back < gBul[b].x + gBul[b].blockXL
|
|
&& gNPC[n].x + gNPC[n].hit.back > gBul[b].x - gBul[b].blockXL
|
|
&& gNPC[n].y - gNPC[n].hit.top < gBul[b].y + gBul[b].blockYL
|
|
&& gNPC[n].y + gNPC[n].hit.bottom > gBul[b].y - gBul[b].blockYL)
|
|
bHit = TRUE;
|
|
|
|
if (bHit)
|
|
{
|
|
//Damage NPC
|
|
if (gNPC[n].bits & npc_shootable)
|
|
{
|
|
gNPC[n].life -= gBul[b].damage;
|
|
|
|
if (gNPC[n].life < 1)
|
|
{
|
|
gNPC[n].life = 0;
|
|
|
|
if (gNPC[n].bits & npc_showDamage)
|
|
gNPC[n].damage_view -= gBul[b].damage;
|
|
|
|
if ((gMC.cond & 0x80) && gNPC[n].bits & npc_eventDie)
|
|
StartTextScript(gNPC[n].code_event);
|
|
else
|
|
gNPC[n].cond |= 8;
|
|
}
|
|
else
|
|
{
|
|
if (gNPC[n].shock < 14)
|
|
{
|
|
SetCaret((gBul[b].x + gNPC[n].x) / 2, (gBul[b].y + gNPC[n].y) / 2, 11, 0);
|
|
SetCaret((gBul[b].x + gNPC[n].x) / 2, (gBul[b].y + gNPC[n].y) / 2, 11, 0);
|
|
SetCaret((gBul[b].x + gNPC[n].x) / 2, (gBul[b].y + gNPC[n].y) / 2, 11, 0);
|
|
PlaySoundObject(gNPC[n].hit_voice, 1);
|
|
gNPC[n].shock = 16;
|
|
}
|
|
|
|
if (gNPC[n].bits & npc_showDamage)
|
|
gNPC[n].damage_view -= gBul[b].damage;
|
|
}
|
|
}
|
|
else if (gBul[b].code_bullet == 13
|
|
|| gBul[b].code_bullet == 14
|
|
|| gBul[b].code_bullet == 15
|
|
|| gBul[b].code_bullet == 28
|
|
|| gBul[b].code_bullet == 29
|
|
|| gBul[b].code_bullet == 30)
|
|
{
|
|
// Strange empty case that's needed for accurate assembly
|
|
}
|
|
else if ((gBul[b].bbits & 0x10) == 0)
|
|
{
|
|
//Hit invulnerable NPC
|
|
SetCaret((gBul[b].x + gNPC[n].x) / 2, (gBul[b].y + gNPC[n].y) / 2, 2, 2);
|
|
PlaySoundObject(31, 1);
|
|
gBul[b].life = 0;
|
|
continue;
|
|
}
|
|
|
|
--gBul[b].life;
|
|
}
|
|
}
|
|
|
|
if (gNPC[n].cond & 8)
|
|
LoseNpChar(&gNPC[n], TRUE);
|
|
}
|
|
}
|