From aa08331c36a4f40ebb81040abc5f1db8870c750d Mon Sep 17 00:00:00 2001 From: Clownacy Date: Thu, 7 Feb 2019 15:10:46 +0000 Subject: [PATCH] Added IronHead and relevant NPCs Also added the AMJ TSC command, so getting the Spur works --- Makefile | 1 + src/Boss.cpp | 3 +- src/BossIronH.cpp | 207 ++++++++++++++++++++++++++++++++++++++++++++++ src/BossIronH.h | 3 + src/NpcAct.h | 9 +- src/NpcAct180.cpp | 139 ++++++++++++++++++++++++++++++- src/NpcAct260.cpp | 97 ++++++++++++++++++++++ src/NpcAct320.cpp | 75 +++++++++++++++++ src/NpcTbl.cpp | 10 +-- src/TextScr.cpp | 10 +++ 10 files changed, 546 insertions(+), 8 deletions(-) create mode 100644 src/BossIronH.cpp create mode 100644 src/BossIronH.h diff --git a/Makefile b/Makefile index 47e955eb..6a9fa4a8 100644 --- a/Makefile +++ b/Makefile @@ -43,6 +43,7 @@ SOURCES = \ Boss \ BossAlmo1 \ BossFrog \ + BossIronH \ BossLife \ BossOhm \ BossX \ diff --git a/src/Boss.cpp b/src/Boss.cpp index 3388b08b..3292eb22 100644 --- a/src/Boss.cpp +++ b/src/Boss.cpp @@ -6,6 +6,7 @@ #include "Boss.h" #include "BossAlmo1.h" #include "BossFrog.h" +#include "BossIronH.h" #include "BossOhm.h" #include "BossX.h" #include "NpChar.h" @@ -192,7 +193,7 @@ BOSSFUNCTION gpBossFuncTbl[10] = ActBossChar_Frog, ActBossChar_MonstX, ActBossChar_Core, - nullptr, //ActBossChar_Ironhead, + ActBossChar_Ironhead, nullptr, //ActBossChar_Twin, nullptr, //ActBossChar_Undead, nullptr, //ActBossChar_Press, diff --git a/src/BossIronH.cpp b/src/BossIronH.cpp new file mode 100644 index 00000000..370c7e17 --- /dev/null +++ b/src/BossIronH.cpp @@ -0,0 +1,207 @@ +#include "BossIronH.h" + +#include "Boss.h" +#include "Frame.h" +#include "Game.h" +#include "MyChar.h" +#include "Sound.h" +#include "WindowsWrapper.h" + +void ActBossChar_Ironhead(void) +{ + switch (gBoss[0].act_no) + { + case 0: + gBoss[0].cond = 0x80; + gBoss[0].exp = 1; + gBoss[0].direct = 2; + gBoss[0].act_no = 100; + gBoss[0].x = 0x14000; + gBoss[0].y = 0x10000; + gBoss[0].view.front = 0x5000; + gBoss[0].view.top = 0x1800; + gBoss[0].view.back = 0x3000; + gBoss[0].view.bottom = 0x1800; + gBoss[0].hit_voice = 54; + gBoss[0].hit.front = 0x2000; + gBoss[0].hit.top = 0x1400; + gBoss[0].hit.back = 0x2000; + gBoss[0].hit.bottom = 0x1400; + gBoss[0].bits = 0x8228; + gBoss[0].size = 3; + gBoss[0].damage = 10; + gBoss[0].code_event = 1000; + gBoss[0].life = 400; + break; + + case 100: + gBoss[0].act_no = 101; + gBoss[0].bits &= ~0x20; + gBoss[0].act_wait = 0; + // Fallthrough + case 101: + if (++gBoss[0].act_wait > 50) + { + gBoss[0].act_no = 250; + gBoss[0].act_wait = 0; + } + + if (gBoss[0].act_wait % 4 == 0) + SetNpChar(197, Random(15, 18) * 0x2000, Random(2, 13) * 0x2000, 0, 0, 0, 0, 0x100); + + break; + + case 250: + gBoss[0].act_no = 251; + + if (gBoss[0].direct == 2) + { + gBoss[0].x = 0x1E000; + gBoss[0].y = gMC.y; + } + else + { + gBoss[0].x = 0x5A000; + gBoss[0].y = Random(2, 13) * 0x2000; + } + + gBoss[0].tgt_x = gBoss[0].x; + gBoss[0].tgt_y = gBoss[0].y; + + gBoss[0].ym = Random(-0x200, 0x200); + gBoss[0].xm = Random(-0x200, 0x200); + + gBoss[0].bits |= 0x20; + // Fallthrough + case 251: + if (gBoss[0].direct == 2) + { + gBoss[0].tgt_x += 0x400; + } + else + { + gBoss[0].tgt_x -= 0x200; + + if (gMC.y > gBoss[0].tgt_y) + gBoss[0].tgt_y += 0x200; + else + gBoss[0].tgt_y -= 0x200; + } + + if (gBoss[0].tgt_x > gBoss[0].x) + gBoss[0].xm += 8; + else + gBoss[0].xm -= 8; + + if (gBoss[0].tgt_y > gBoss[0].y) + gBoss[0].ym += 8; + else + gBoss[0].ym -= 8; + + if (gBoss[0].ym > 0x200) + gBoss[0].ym = 0x200; + if (gBoss[0].ym < -0x200) + gBoss[0].ym = -0x200; + + gBoss[0].x += gBoss[0].xm; + gBoss[0].y += gBoss[0].ym; + + if (gBoss[0].direct == 2) + { + if (gBoss[0].x > 0x5A000) + { + gBoss[0].direct = 0; + gBoss[0].act_no = 100; + } + } + else + { + if (gBoss[0].x < 0x22000) + { + gBoss[0].direct = 2; + gBoss[0].act_no = 100; + } + } + + if (gBoss[0].direct == 0 && (++gBoss[0].act_wait == 300 || gBoss[0].act_wait == 310 || gBoss[0].act_wait == 320)) + { + PlaySoundObject(39, 1); + SetNpChar(198, gBoss[0].x + 0x1400, gBoss[0].y + 0x200, Random(-3, 0) * 0x200, Random(-3, 3) * 0x200, 2, 0, 0x100); + } + + if (++gBoss[0].ani_wait > 2) + { + gBoss[0].ani_wait = 0; + ++gBoss[0].ani_no; + } + + if (gBoss[0].ani_no > 7) + gBoss[0].ani_no = 0; + + break; + + case 1000: + gBoss[0].bits &= ~0x20; + gBoss[0].ani_no = 8; + gBoss[0].damage = 0; + gBoss[0].act_no = 1001; + gBoss[0].tgt_x = gBoss[0].x; + gBoss[0].tgt_y = gBoss[0].y; + SetQuake(20); + + for (int i = 0; i < 0x20; ++i) + SetNpChar(4, gBoss[0].x + (Random(-0x80, 0x80) * 0x200), gBoss[0].y + (Random(-0x40, 0x40) * 0x200), Random(-0x80, 0x80) * 0x200, Random(-0x80, 0x80) * 0x200, 0, 0, 0x100); + + DeleteNpCharCode(197, 1); + DeleteNpCharCode(271, 1); + DeleteNpCharCode(272, 1); + // Fallthrough + case 1001: + gBoss[0].tgt_x -= 0x200; + + gBoss[0].x = gBoss[0].tgt_x + (Random(-1, 1) * 0x200); + gBoss[0].y = gBoss[0].tgt_y + (Random(-1, 1) * 0x200); + + if (++gBoss[0].act_wait % 4 == 0) + SetNpChar(4, gBoss[0].x + (Random(-0x80u, 0x80) * 0x200), gBoss[0].y + (Random(-0x40u, 0x40) * 0x200), Random(-0x80, 0x80) * 0x200, Random(-0x80, 0x80) * 0x200, 0, 0, 0x100); + + break; + } + + RECT rc[9]; + RECT rcDamage[9]; + + rc[0] = {0, 0, 64, 24}; + rc[1] = {64, 0, 128, 24}; + rc[2] = {128, 0, 192, 24}; + rc[3] = {64, 0, 128, 24}; + rc[4] = {0, 0, 64, 24}; + rc[5] = {192, 0, 256, 24}; + rc[6] = {256, 0, 320, 24}; + rc[7] = {192, 0, 256, 24}; + rc[8] = {256, 48, 320, 72}; + + rcDamage[0] = {0, 24, 64, 48}; + rcDamage[1] = {64, 24, 128, 48}; + rcDamage[2] = {128, 24, 192, 48}; + rcDamage[3] = {64, 24, 128, 48}; + rcDamage[4] = {0, 24, 64, 48}; + rcDamage[5] = {192, 24, 256, 48}; + rcDamage[6] = {256, 24, 320, 48}; + rcDamage[7] = {192, 24, 256, 48}; + rcDamage[8] = {256, 48, 320, 72}; + + if (gBoss[0].shock) + { + static unsigned char flash; + + if ((++flash >> 1) % 2) + gBoss[0].rect = rc[gBoss[0].ani_no]; + else + gBoss[0].rect = rcDamage[gBoss[0].ani_no]; + } + else + { + gBoss[0].rect = rc[gBoss[0].ani_no]; + } +} \ No newline at end of file diff --git a/src/BossIronH.h b/src/BossIronH.h new file mode 100644 index 00000000..f2206910 --- /dev/null +++ b/src/BossIronH.h @@ -0,0 +1,3 @@ +#pragma once + +void ActBossChar_Ironhead(void); diff --git a/src/NpcAct.h b/src/NpcAct.h index 62d1414e..14bb958a 100644 --- a/src/NpcAct.h +++ b/src/NpcAct.h @@ -198,7 +198,9 @@ void ActNpc192(NPCHAR *npc); void ActNpc193(NPCHAR *npc); void ActNpc194(NPCHAR *npc); void ActNpc195(NPCHAR *npc); - +void ActNpc196(NPCHAR *npc); +void ActNpc197(NPCHAR *npc); +void ActNpc198(NPCHAR *npc); void ActNpc199(NPCHAR *npc); void ActNpc211(NPCHAR *npc); @@ -208,6 +210,9 @@ void ActNpc219(NPCHAR *npc); void ActNpc259(NPCHAR *npc); +void ActNpc271(NPCHAR *npc); +void ActNpc272(NPCHAR *npc); + void ActNpc278(NPCHAR *npc); void ActNpc292(NPCHAR *npc); @@ -219,6 +224,8 @@ void ActNpc300(NPCHAR *npc); void ActNpc302(NPCHAR *npc); void ActNpc334(NPCHAR *npc); +void ActNpc335(NPCHAR *npc); +void ActNpc336(NPCHAR *npc); void ActNpc355(NPCHAR *npc); diff --git a/src/NpcAct180.cpp b/src/NpcAct180.cpp index 70f15505..855f236e 100644 --- a/src/NpcAct180.cpp +++ b/src/NpcAct180.cpp @@ -12,6 +12,7 @@ #include "Frame.h" #include "Bullet.h" #include "Flags.h" +#include "NpcHit.h" //Curly AI void ActNpc180(NPCHAR *npc) @@ -1173,7 +1174,143 @@ void ActNpc194(NPCHAR *npc) //Grate void ActNpc195(NPCHAR *npc) { - npc->rect = {112, 64, 128, 80}; + RECT rc = {112, 64, 128, 80}; + npc->rect = rc; +} + +//Ironhead motion wall +void ActNpc196(NPCHAR *npc) +{ + RECT rcLeft = {112, 64, 144, 80}; + RECT rcRight = {112, 80, 144, 96}; + + npc->x -= 0xC00; + + if (npc->x <= 0x26000) + npc->x += 0x2C000; + + if (npc->direct == 0) + npc->rect = rcLeft; + else + npc->rect = rcRight; +} + +//Porcupine Fish +void ActNpc197(NPCHAR *npc) +{ + RECT rc[4]; + + rc[0] = {0, 0, 16, 16}; + rc[1] = {16, 0, 32, 16}; + rc[2] = {32, 0, 48, 16}; + rc[3] = {48, 0, 64, 16}; + + switch (npc->act_no) + { + case 0: + npc->act_no = 10; + npc->ani_wait = 0; + npc->ym = Random(-0x200, 0x200); + npc->xm = 0x800; + // Fallthrough + case 10: + if (++npc->ani_wait > 2) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 1) + npc->ani_no = 0; + + if (npc->xm < 0) + { + npc->damage = 3; + npc->act_no = 20; + } + + break; + + case 20: + npc->damage = 3; + + if (++npc->ani_wait > 0) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 3) + npc->ani_no = 2; + + if (npc->x < 0x6000) + { + npc->destroy_voice = 0; + LoseNpChar(npc, 1); + } + + break; + } + + if (npc->flag & 2) + npc->ym = 0x200; + if (npc->flag & 8) + npc->ym = -0x200; + + npc->xm -= 12; + + npc->x += npc->xm; + npc->y += npc->ym; + + npc->rect = rc[npc->ani_no]; +} + +//Ironhead projectile +void ActNpc198(NPCHAR *npc) +{ + RECT rcRight[3]; + + rcRight[0] = {208, 48, 224, 72}; + rcRight[1] = {224, 48, 240, 72}; + rcRight[2] = {240, 48, 256, 72}; + + switch (npc->act_no) + { + case 0: + if (++npc->act_wait > 20) + { + npc->act_no = 1; + npc->xm = 0; + npc->ym = 0; + npc->count1 = 0; + } + + break; + + case 1: + npc->xm += 0x20; + break; + } + + if (++npc->ani_wait > 0) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 2) + npc->ani_no = 0; + + npc->x += npc->xm; + npc->y += npc->ym; + + npc->rect = rcRight[npc->ani_no]; + + if (++npc->count1 > 100) + npc->cond = 0; + + if (npc->count1 % 4 == 1) + PlaySoundObject(46, 1); } //Water/wind particles diff --git a/src/NpcAct260.cpp b/src/NpcAct260.cpp index 1c24abcd..ce323873 100644 --- a/src/NpcAct260.cpp +++ b/src/NpcAct260.cpp @@ -8,6 +8,103 @@ #include "Sound.h" #include "Back.h" #include "Triangle.h" +#include "Caret.h" +#include "Map.h" + +// Ironhead block +void ActNpc271(NPCHAR *npc) +{ + if (npc->xm < 0 && npc->x < -0x2000) + { + VanishNpChar(npc); + } + else + { + if (npc->xm > 0 && npc->x > (gMap.width + 1) * 0x2000) + { + VanishNpChar(npc); + } + else + { + if (npc->act_no == 0) + { + npc->act_no = 1; + int a = Random(0, 9); + + if (a == 9) + { + npc->rect.left = 0; + npc->rect.right = 0x20; + npc->rect.top = 0x40; + npc->rect.bottom = 0x60; + npc->view.front = 0x2000; + npc->view.back = 0x2000; + npc->view.top = 0x2000; + npc->view.bottom = 0x2000; + npc->hit.front = 0x1800; + npc->hit.back = 0x1800; + npc->hit.top = 0x1800; + npc->hit.bottom = 0x1800; + } + else + { + npc->rect.left = 16 * (a % 3 + 7); + npc->rect.top = 16 * (a / 3); + npc->rect.right = npc->rect.left + 16; + npc->rect.bottom = npc->rect.top + 16; + } + + if (npc->direct == 0) + npc->xm = -2 * Random(0x100, 0x200); + else + npc->xm = 2 * Random(0x100, 0x200); + + npc->ym = Random(-0x200, 0x200); + } + + if (npc->ym < 0 && npc->y - npc->hit.top <= 0xFFF) + { + npc->ym = -npc->ym; + SetCaret(npc->x, npc->y - 0x1000, 13, 0); + SetCaret(npc->x, npc->y - 0x1000, 13, 0); + } + + if (npc->ym > 0 && npc->y + npc->hit.bottom > 0x1D000) + { + npc->ym = -npc->ym; + SetCaret(npc->x, npc->y + 0x1000, 13, 0); + SetCaret(npc->x, npc->y + 0x1000, 13, 0); + } + + npc->x += npc->xm; + npc->y += npc->ym; + } + } +} + +// Ironhead block generator +void ActNpc272(NPCHAR *npc) +{ + switch (npc->act_no) + { + case 0: + npc->act_no = 1; + npc->act_wait = Random(0, 200); + // Fallthrough + case 1: + if (npc->act_wait) + { + --npc->act_wait; + } + else + { + npc->act_no = 0; + SetNpChar(271, npc->x, npc->y + (Random(-32, 32) * 0x200), 0, 0, npc->direct, 0, 0x100); + } + + break; + } +} //Little family void ActNpc278(NPCHAR *npc) diff --git a/src/NpcAct320.cpp b/src/NpcAct320.cpp index 3530a0e8..7752ab1c 100644 --- a/src/NpcAct320.cpp +++ b/src/NpcAct320.cpp @@ -54,3 +54,78 @@ void ActNpc334(NPCHAR *npc) else npc->rect = rcRight[npc->ani_no]; } + +//Ikachan +void ActNpc335(NPCHAR *npc) +{ + RECT rc[3]; + + rc[0] = {0, 16, 16, 32}; + rc[1] = {16, 16, 32, 32}; + rc[2] = {32, 16, 48, 32}; + + switch (npc->act_no) + { + case 0: + npc->act_no = 1; + npc->act_wait = Random(3, 20); + // Fallthrough + case 1: + if (--npc->act_wait <= 0) + { + npc->act_no = 2; + npc->act_wait = Random(10, 50); + npc->ani_no = 1; + npc->xm = 0x600; + } + + break; + + case 2: + if (--npc->act_wait <= 0) + { + npc->act_no = 3; + npc->act_wait = Random(40, 50); + npc->ani_no = 2; + npc->ym = Random(-0x100, 0x100); + } + + break; + + case 3: + if (--npc->act_wait <= 0) + { + npc->act_no = 1; + npc->act_wait = 0; + npc->ani_no = 0; + } + + break; + } + + npc->xm -= 0x10; + + npc->x += npc->xm; + npc->y += npc->ym; + + npc->rect = rc[npc->ani_no]; +} + +//Ikachan generator +void ActNpc336(NPCHAR *npc) +{ + switch (npc->act_no) + { + case 0: + if (gMC.shock) + npc->cond = 0; + + break; + + case 10: + if (++npc->act_wait % 4 == 1 ) + SetNpChar(335, npc->x, npc->y + (Random(0, 13) * 0x2000), 0, 0, 0, 0, 0); + + break; + } +} diff --git a/src/NpcTbl.cpp b/src/NpcTbl.cpp index caa2fb3a..b74849cb 100644 --- a/src/NpcTbl.cpp +++ b/src/NpcTbl.cpp @@ -252,9 +252,9 @@ NPCFUNCTION gpNpcFuncTbl[361] = ActNpc193, ActNpc194, ActNpc195, - nullptr, - nullptr, - nullptr, + ActNpc196, + ActNpc197, + ActNpc198, ActNpc199, nullptr, nullptr, @@ -391,8 +391,8 @@ NPCFUNCTION gpNpcFuncTbl[361] = nullptr, nullptr, ActNpc334, - nullptr, - nullptr, + ActNpc335, + ActNpc336, nullptr, nullptr, nullptr, diff --git a/src/TextScr.cpp b/src/TextScr.cpp index 2bdaac91..09eba4ba 100644 --- a/src/TextScr.cpp +++ b/src/TextScr.cpp @@ -889,6 +889,16 @@ int TextScriptProc() else gTS.p_read += 13; } + else if (IS_COMMAND('A','M','J')) + { + x = GetTextScriptNo(gTS.p_read + 4); + z = GetTextScriptNo(gTS.p_read + 9); + + if (CheckArms(x)) + JumpTextScript(z); + else + gTS.p_read += 13; + } else if (IS_COMMAND('U','N','J')) { x = GetTextScriptNo(gTS.p_read + 4);