diff --git a/msvc2003/devilution/comparer-config.toml b/msvc2003/devilution/comparer-config.toml index 70a76dca..686672c6 100644 --- a/msvc2003/devilution/comparer-config.toml +++ b/msvc2003/devilution/comparer-config.toml @@ -2294,6 +2294,58 @@ addr = 0x4704F0 name = "CountAliveNpChar" addr = 0x470560 +[[func]] +name = "JadgeHitNpCharBlock" +addr = 0x4705C0 + +[[func]] +name = "JudgeHitNpCharTriangleA" +addr = 0x470870 + +[[func]] +name = "JudgeHitNpCharTriangleB" +addr = 0x470970 + +[[func]] +name = "JudgeHitNpCharTriangleC" +addr = 0x470A70 + +[[func]] +name = "JudgeHitNpCharTriangleD" +addr = 0x470B70 + +[[func]] +name = "JudgeHitNpCharTriangleE" +addr = 0x470C70 + +[[func]] +name = "JudgeHitNpCharTriangleF" +addr = 0x470D80 + +[[func]] +name = "JudgeHitNpCharTriangleG" +addr = 0x470E90 + +[[func]] +name = "JudgeHitNpCharTriangleH" +addr = 0x470FA0 + +[[func]] +name = "JudgeHitNpCharWater" +addr = 0x4710B0 + +[[func]] +name = "HitNpCharMap" +addr = 0x471160 + +[[func]] +name = "LoseNpChar" +addr = 0x471B80 + +[[func]] +name = "HitNpCharBullet" +addr = 0x471D50 + [[func]] name = "LoadNpcTable" addr = 0x472400 diff --git a/src/NpcHit.cpp b/src/NpcHit.cpp index a3f0a840..a3e12f90 100644 --- a/src/NpcHit.cpp +++ b/src/NpcHit.cpp @@ -1,5 +1,7 @@ #include "NpcHit.h" +#include "WindowsWrapper.h" + #include "Back.h" #include "Bullet.h" #include "Caret.h" @@ -16,40 +18,40 @@ void JadgeHitNpCharBlock(NPCHAR *npc, int x, int y) { int hit = 0; - if (npc->y - npc->hit.top < ((2 * y + 1) << 12) - 0x600 - && npc->y + npc->hit.bottom > ((2 * y - 1) << 12) + 0x600 - && npc->x - npc->hit.back < (2 * x + 1) << 12 - && npc->x - npc->hit.back > x << 13) + 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 = ((2 * x + 1) << 12) + npc->hit.back; + npc->x = ((x * 0x10 + 8) * 0x200) + npc->hit.back; hit |= 1; } - if (npc->y - npc->hit.top < ((2 * y + 1) << 12) - 0x600 - && npc->y + npc->hit.bottom > ((2 * y - 1) << 12) + 0x600 - && npc->hit.back + npc->x > (2 * x - 1) << 12 - && npc->hit.back + npc->x < x << 13) + 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 = ((2 * x - 1) << 12) - npc->hit.back; + npc->x = ((x * 0x10 - 8) * 0x200) - npc->hit.back; hit |= 4; } - if (npc->x - npc->hit.back < ((2 * x + 1) << 12) - 0x600 - && npc->hit.back + npc->x > ((2 * x - 1) << 12) + 0x600 - && npc->y - npc->hit.top < (2 * y + 1) << 12 - && npc->y - npc->hit.top > y << 13) + 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 = ((2 * y + 1) << 12) + npc->hit.top; + npc->y = ((y * 0x10 + 8) * 0x200) + npc->hit.top; npc->ym = 0; hit |= 2; } - if (npc->x - npc->hit.back < ((2 * x + 1) << 12) - 0x600 - && npc->hit.back + npc->x > ((2 * x - 1) << 12) + 0x600 - && npc->y + npc->hit.bottom > (2 * y - 1) << 12 - && npc->y + npc->hit.bottom < y << 13) + 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 = ((2 * y - 1) << 12) - npc->hit.bottom; + npc->y = ((y * 0x10 - 8) * 0x200) - npc->hit.bottom; npc->ym = 0; hit |= 8; } @@ -61,20 +63,20 @@ void JudgeHitNpCharTriangleA(NPCHAR *npc, int x, int y) { int hit = 0; - if (npc->x < (2 * x + 1) << 12 - && npc->x > (2 * x - 1) << 12 - && npc->y - npc->hit.top < (y << 13) - (-0x2000 * x + npc->x) / 2 + 0x800 - && npc->y + npc->hit.bottom > (2 * y - 1) << 12) + 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 = npc->hit.top + (y << 13) - (-0x2000 * x + npc->x) / 2 + 0x800; + 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; + hit |= 2; } npc->flag |= hit; @@ -84,20 +86,20 @@ void JudgeHitNpCharTriangleB(NPCHAR *npc, int x, int y) { int hit = 0; - if (npc->x < (2 * x + 1) << 12 - && npc->x > (2 * x - 1) << 12 - && npc->y - npc->hit.top < (y << 13) - (-0x2000 * x + npc->x) / 2 - 0x800 - && npc->y + npc->hit.bottom > (2 * y - 1) << 12) + 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 = npc->hit.top + (y << 13) - (-0x2000 * x + npc->x) / 2 - 0x800; + 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; + hit |= 2; } npc->flag |= hit; @@ -107,20 +109,20 @@ void JudgeHitNpCharTriangleC(NPCHAR *npc, int x, int y) { int hit = 0; - if (npc->x < (2 * x + 1) << 12 - && npc->x > (2 * x - 1) << 12 - && npc->y - npc->hit.top < (y << 13) + (-0x2000 * x + npc->x) / 2 - 0x800 - && npc->y + npc->hit.bottom > (2 * y - 1) << 12) + 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 = npc->hit.top + (y << 13) + (-0x2000 * x + npc->x) / 2 - 0x800; + 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; + hit |= 2; } npc->flag |= hit; @@ -130,20 +132,20 @@ void JudgeHitNpCharTriangleD(NPCHAR *npc, int x, int y) { int hit = 0; - if (npc->x < (2 * x + 1) << 12 - && npc->x > (2 * x - 1) << 12 - && npc->y - npc->hit.top < (y << 13) + (-0x2000 * x + npc->x) / 2 + 0x800 - && npc->y + npc->hit.bottom > (2 * y - 1) << 12) + 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 = npc->hit.top + (y << 13) + (-0x2000 * x + npc->x) / 2 + 0x800; + 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; + hit |= 2; } npc->flag |= hit; @@ -151,22 +153,24 @@ void JudgeHitNpCharTriangleD(NPCHAR *npc, int x, int y) void JudgeHitNpCharTriangleE(NPCHAR *npc, int x, int y) { - int hit = 0x10000; + int hit = 0; - if ( npc->x < (2 * x + 1) << 12 - && npc->x > (2 * x - 1) << 12 - && npc->y + npc->hit.bottom > (y << 13) + (-0x2000 * x + npc->x) / 2 - 0x800 - && npc->y - npc->hit.top < (2 * y + 1) << 12 ) + 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 << 13) + (-0x2000 * x + npc->x) / 2 - 0x800 - npc->hit.bottom; + 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 = 0x10028; + hit |= 0x28; } npc->flag |= hit; @@ -174,22 +178,24 @@ void JudgeHitNpCharTriangleE(NPCHAR *npc, int x, int y) void JudgeHitNpCharTriangleF(NPCHAR *npc, int x, int y) { - int hit = 0x20000; + int hit = 0; - if ( npc->x < (2 * x + 1) << 12 - && npc->x > (2 * x - 1) << 12 - && npc->y + npc->hit.bottom > (y << 13) + (-0x2000 * x + npc->x) / 2 + 0x800 - && npc->y - npc->hit.top < (2 * y + 1) << 12 ) + 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 << 13) + (-0x2000 * x + npc->x) / 2 + 0x800 - npc->hit.bottom; + 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 = 0x20028; + hit |= 0x28; } npc->flag |= hit; @@ -197,22 +203,24 @@ void JudgeHitNpCharTriangleF(NPCHAR *npc, int x, int y) void JudgeHitNpCharTriangleG(NPCHAR *npc, int x, int y) { - int hit = 0x40000; + int hit = 0; - if ( npc->x < (2 * x + 1) << 12 - && npc->x > (2 * x - 1) << 12 - && npc->y + npc->hit.bottom > (y << 13) - (-0x2000 * x + npc->x) / 2 + 0x800 - && npc->y - npc->hit.top < (2 * y + 1) << 12 ) + 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 << 13) - (-0x2000 * x + npc->x) / 2 + 0x800 - npc->hit.bottom; + 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 = 0x40018; + hit |= 0x18; } npc->flag |= hit; @@ -220,22 +228,24 @@ void JudgeHitNpCharTriangleG(NPCHAR *npc, int x, int y) void JudgeHitNpCharTriangleH(NPCHAR *npc, int x, int y) { - int hit = 0x80000; + int hit = 0; - if ( npc->x < (2 * x + 1) << 12 - && npc->x > (2 * x - 1) << 12 - && npc->y + npc->hit.bottom > (y << 13) - (-0x2000 * x + npc->x) / 2 - 0x800 - && npc->y - npc->hit.top < (2 * y + 1) << 12 ) + 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 << 13) - (-0x2000 * x + npc->x) / 2 - 0x800 - npc->hit.bottom; + 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 = 0x80018; + hit |= 0x18; } npc->flag |= hit; @@ -245,19 +255,24 @@ void JudgeHitNpCharWater(NPCHAR *npc, int x, int y) { int hit = 0; - if (npc->x - npc->hit.back < (4 * (2 * x + 1) - 1) << 10 - && npc->hit.back + npc->x > (4 * (2 * x - 1) + 1) << 10 - && npc->y - npc->hit.top < (4 * (2 * y + 1) - 1) << 10 - && npc->y + npc->hit.bottom > (4 * (2 * y - 1) + 1) << 10) - hit = 0x100; + 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 offy[9]; + int judg, x, y; + int offx[9]; + int offy[9]; + + int i; + int j; offx[0] = 0; offx[1] = 1; @@ -279,133 +294,162 @@ void HitNpCharMap() offy[7] = 2; offy[8] = 2; - for (int i = 0; i < NPC_MAX; i++) + for (i = 0; i < NPC_MAX; i++) { - if ((gNPC[i].cond & 0x80) && !(gNPC[i].bits & 8)) + if ((gNPC[i].cond & 0x80) == 0) + continue; + + if (gNPC[i].bits & 8) + continue; + + if (gNPC[i].size >= 3) { - int judg, x, y; - if (gNPC[i].size <= 2) + 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])) { - judg = 4; - x = gNPC[i].x / 0x2000; - y = gNPC[i].y / 0x2000; - } - else - { - judg = 9; - x = (gNPC[i].x - 0x1000) / 0x2000; - y = (gNPC[i].y - 0x1000) / 0x2000; - } - - gNPC[i].flag = 0; - - for (int j = 0; j < judg; j++) - { - switch (GetAttribute(x + offx[j], y + offy[j])) - { - //Water - case 0x02: - case 0x60: - case 0x62: - JudgeHitNpCharWater(&gNPC[i], 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; - //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; - //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; + case 0x51: + JudgeHitNpCharTriangleB(&gNPC[i], x + offx[j], y + offy[j]); + break; - //No NPC block - case 0x44: - if (!(gNPC[i].bits & npc_ignore44)) - JadgeHitNpCharBlock(&gNPC[i], x + offx[j], y + offy[j]); - break; + case 0x52: + JudgeHitNpCharTriangleC(&gNPC[i], x + offx[j], y + offy[j]); + break; - //Slopes - case 0x50: - JudgeHitNpCharTriangleA(&gNPC[i], x + offx[j], y + offy[j]); - break; + case 0x53: + JudgeHitNpCharTriangleD(&gNPC[i], x + offx[j], y + offy[j]); + break; - case 0x51: - JudgeHitNpCharTriangleB(&gNPC[i], x + offx[j], y + offy[j]); - break; + case 0x54: + JudgeHitNpCharTriangleE(&gNPC[i], x + offx[j], y + offy[j]); + break; - case 0x52: - JudgeHitNpCharTriangleC(&gNPC[i], x + offx[j], y + offy[j]); - break; + case 0x55: + JudgeHitNpCharTriangleF(&gNPC[i], x + offx[j], y + offy[j]); + break; - case 0x53: - JudgeHitNpCharTriangleD(&gNPC[i], x + offx[j], y + offy[j]); - break; + case 0x56: + JudgeHitNpCharTriangleG(&gNPC[i], x + offx[j], y + offy[j]); + break; - case 0x54: - JudgeHitNpCharTriangleE(&gNPC[i], x + offx[j], y + offy[j]); - break; + case 0x57: + JudgeHitNpCharTriangleH(&gNPC[i], x + offx[j], y + offy[j]); + break; - case 0x55: - JudgeHitNpCharTriangleF(&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; - case 0x56: - JudgeHitNpCharTriangleG(&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; - case 0x57: - JudgeHitNpCharTriangleH(&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; - //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 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 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 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 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 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 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 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) @@ -414,7 +458,7 @@ void HitNpCharMap() } } -void LoseNpChar(NPCHAR *npc, bool bVanish) +void LoseNpChar(NPCHAR *npc, BOOL bVanish) { //Play death sound PlaySoundObject(npc->destroy_voice, 1); @@ -436,19 +480,35 @@ void LoseNpChar(NPCHAR *npc, bool bVanish) //Create drop if (npc->exp) { - int v3 = Random(1, 5); - char v4; + int val; - if (v3 == 1) + switch (Random(1, 5)) { - if (npc->exp <= 6) - SetLifeObject(npc->x, npc->y, 2); - else - SetLifeObject(npc->x, npc->y, 6); - } - else if (v3 != 2 || (npc->exp <= 6 ? (v4 = SetBulletObject(npc->x, npc->y, 1)) : (v4 = SetBulletObject(npc->x, npc->y, 3)), !v4)) //TODO: what the FUCK - { - SetExpObjects(npc->x, npc->y, npc->exp); + 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); } } @@ -456,100 +516,113 @@ void LoseNpChar(NPCHAR *npc, bool bVanish) SetNPCFlag(npc->code_flag); //Create value view - if (!(npc->bits & npc_showDamage)) - { - npc->cond = 0; - } - else + 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() { - for (int n = 0; n < NPC_MAX; n++) + int n; + int b; + BOOL bHit; + + for (n = 0; n < NPC_MAX; n++) { - if ((gNPC[n].cond & 0x80) && (!(gNPC[n].bits & npc_shootable) || !(gNPC[n].bits & npc_interact))) + 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++) { - for (int 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) { - if (gBul[b].cond & 0x80 && gBul[b].damage != -1) + //Damage NPC + if (gNPC[n].bits & npc_shootable) { - //Check if bullet touches npc - bool 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; + gNPC[n].life -= gBul[b].damage; - if (bHit) + if (gNPC[n].life < 1) { - //Damage NPC - if (gNPC[n].bits & npc_shootable) + 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) { - gNPC[n].life -= gBul[b].damage; - - if (gNPC[n].life > 0) - { - 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 - { - 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; - } - } - //Hit invulnerable NPC - 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 - && !(gBul[b].bbits & 0x10)) - { - 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; + 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; } - --gBul[b].life; + 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; + } - if (gNPC[n].cond & 8) - LoseNpChar(&gNPC[n], true); + --gBul[b].life; + } } + + if (gNPC[n].cond & 8) + LoseNpChar(&gNPC[n], TRUE); } } diff --git a/src/NpcHit.h b/src/NpcHit.h index 50f65e88..1fe8a6d1 100644 --- a/src/NpcHit.h +++ b/src/NpcHit.h @@ -1,5 +1,7 @@ #pragma once +#include "WindowsWrapper.h" + #include "NpChar.h" void JadgeHitNpCharBlock(NPCHAR *npc, int x, int y); @@ -13,5 +15,5 @@ void JudgeHitNpCharTriangleG(NPCHAR *npc, int x, int y); void JudgeHitNpCharTriangleH(NPCHAR *npc, int x, int y); void JudgeHitNpCharWater(NPCHAR *npc, int x, int y); void HitNpCharMap(); -void LoseNpChar(NPCHAR *npc, bool bVanish); +void LoseNpChar(NPCHAR *npc, BOOL bVanish); void HitNpCharBullet();