diff --git a/Makefile b/Makefile index 130cf8db..1c29b353 100644 --- a/Makefile +++ b/Makefile @@ -45,7 +45,10 @@ SOURCES = \ Map \ MapName \ MyChar \ + MycHit \ + NpcAct000 \ NpChar \ + NpcHit \ NpcTbl \ Organya \ PixTone \ diff --git a/src/Back.h b/src/Back.h index 6294ddd5..62fd9102 100644 --- a/src/Back.h +++ b/src/Back.h @@ -11,6 +11,7 @@ struct BACK int fx; }; +extern BACK gBack; extern int gWaterY; bool InitBack(char *fName, int type); diff --git a/src/Frame.cpp b/src/Frame.cpp index b74aa3fe..be66ba17 100644 --- a/src/Frame.cpp +++ b/src/Frame.cpp @@ -23,9 +23,9 @@ void MoveFrame3() if (gFrame.y <= -0x200) gFrame.y = 0; - if (gFrame.x > ((((map_w - 1) << 4) - WINDOW_WIDTH)) << 9); + if (gFrame.x > ((((map_w - 1) << 4) - WINDOW_WIDTH)) << 9) gFrame.x = (((map_w - 1) << 4) - WINDOW_WIDTH) << 9; - if (gFrame.y > ((((map_l - 1) << 4) - WINDOW_HEIGHT)) << 9); + if (gFrame.y > ((((map_l - 1) << 4) - WINDOW_HEIGHT)) << 9) gFrame.y = (((map_l - 1) << 4) - WINDOW_HEIGHT) << 9; //Quake @@ -74,9 +74,9 @@ void SetFramePosition(int fx, int fy) if (gFrame.y <= -0x200) gFrame.y = 0; - if (gFrame.x > ((((map_w - 1) << 4) - WINDOW_WIDTH)) << 9); + if (gFrame.x > ((((map_w - 1) << 4) - WINDOW_WIDTH)) << 9) gFrame.x = (((map_w - 1) << 4) - WINDOW_WIDTH) << 9; - if (gFrame.y > ((((map_l - 1) << 4) - WINDOW_HEIGHT)) << 9); + if (gFrame.y > ((((map_l - 1) << 4) - WINDOW_HEIGHT)) << 9) gFrame.y = (((map_l - 1) << 4) - WINDOW_HEIGHT) << 9; } @@ -89,25 +89,25 @@ void SetFrameMyChar() int16_t map_w, map_l; GetMapData(0, &map_w, &map_l); - gFrame.x = mc_x - 81920; - gFrame.y = mc_y - 61440; + gFrame.x = mc_x - (WINDOW_WIDTH << 9); + gFrame.y = mc_y - (WINDOW_HEIGHT << 9); //Keep in bounds if (gFrame.x <= -0x200) gFrame.x = 0; if (gFrame.y <= -0x200) gFrame.y = 0; - - if (gFrame.x > ((((map_w - 1) << 4) - WINDOW_WIDTH)) << 9); + + if (gFrame.x > ((((map_w - 1) << 4) - WINDOW_WIDTH)) << 9) gFrame.x = (((map_w - 1) << 4) - WINDOW_WIDTH) << 9; - if (gFrame.y > ((((map_l - 1) << 4) - WINDOW_HEIGHT)) << 9); + if (gFrame.y > ((((map_l - 1) << 4) - WINDOW_HEIGHT)) << 9) gFrame.y = (((map_l - 1) << 4) - WINDOW_HEIGHT) << 9; } void SetFrameTargetMyChar(int wait) { - gFrame.tgt_x = &gMC.x; - gFrame.tgt_y = &gMC.y; + gFrame.tgt_x = &gMC.tgt_x; + gFrame.tgt_y = &gMC.tgt_y; gFrame.wait = wait; } diff --git a/src/Game.cpp b/src/Game.cpp index 7c23497d..0050f0e7 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -7,6 +7,7 @@ #include "Tags.h" #include "NpcTbl.h" #include "NpChar.h" +#include "NpcHit.h" #include "Generic.h" #include "GenericLoad.h" #include "TextScr.h" @@ -16,6 +17,7 @@ #include "Escape.h" #include "Stage.h" #include "MyChar.h" +#include "MycHit.h" #include "Caret.h" #include "Map.h" #include "Main.h" @@ -132,11 +134,11 @@ int ModeOpening() ActNpChar(); //ActBossChar(); ActBack(); - //ResetMyCharFlag(); - //HitMyCharMap(); + ResetMyCharFlag(); + HitMyCharMap(); //HitMyCharNpChar(); //HitMyCharBoss(); - //HitNpCharMap(); + HitNpCharMap(); //HitBossMap(); //HitBossBullet(); //ActCaret(); @@ -321,7 +323,7 @@ int ModeTitle() } //Update carets - //ActCaret(); + ActCaret(); //Animate character cursor if ( ++anime >= 40 ) @@ -384,7 +386,7 @@ int ModeTitle() PutBitmap3(&grcGame, 116, char_y, &char_rc, char_surf); //Draw carets - //PutCaret(0, 0); + PutCaret(0, 0); //if (time_counter) // PutTimeCounter(16, 8); @@ -408,6 +410,124 @@ int ModeTitle() return 0; } + return 3; +} + +int ModeAction() +{ + int frame_x = 0; + int frame_y = 0; + + bool swPlay = true; + + //Reset stuff + gCounter = 0; + grcGame.left = 0; + g_GameFlags = 3; + + //Initialize everything + InitMyChar(); + InitNpChar(); + //InitBullet(); + InitCaret(); + //InitStar(); + InitFade(); + //InitFlash(); + //ClearArmsData(); + //ClearItemData(); + //ClearPermitStage(); + //StartMapping(); + InitFlags(); + //InitBossLife(); + + TransferStage(2, 94, 5, 6); + ChangeMusic(mus_MischievousRobot); + SetFrameTargetMyChar(16); + SetFrameMyChar(); + + while (true) + { + //Get pressed keys + GetTrg(); + + //Escape menu + if (gKey & KEY_ESCAPE) + { + int escRet = Call_Escape(); + if (escRet == 0) + return 0; + if (escRet == 2) + return 1; + } + + if (swPlay & 1 && g_GameFlags & 1) + { + if (g_GameFlags & 2) + ActMyChar(true); + else + ActMyChar(false); + + //ActStar(); + ActNpChar(); + //ActBossChar(); + //ActValueView(); + ActBack(); + ResetMyCharFlag(); + HitMyCharMap(); + //HitMyCharNpChar(); + //HitMyCharBoss(); + HitNpCharMap(); + //HitBossMap(); + //HitBulletMap(); + //HitNpCharBullet(); + //HitBossBullet(); + //if (g_GameFlags & 2) + // ShootBullet(); + //ActBullet(); + ActCaret(); + MoveFrame3(); + //ActFlash(frame_x, frame_y); + + if (g_GameFlags & 2) + AnimationMyChar(true); + else + AnimationMyChar(false); + } + + if (g_GameFlags & 8) + { + ActionCredit(); + ActionIllust(); + ActionStripper(); + } + + ProcFade(); + CortBox(&grcFull, 0x000020); + GetFramePosition(&frame_x, &frame_y); + PutBack(frame_x, frame_y); + PutStage_Back(frame_x, frame_y); + //PutBossChar(frame_x, frame_y); + PutNpChar(frame_x, frame_y); + //PutBullet(frame_x, frame_y); + PutMyChar(frame_x, frame_y); + //PutStar(frame_x, frame_y); + PutMapDataVector(frame_x, frame_y); + PutStage_Front(frame_x, frame_y); + PutFront(frame_x, frame_y); + //PutFlash(); + PutCaret(frame_x, frame_y); + //PutValueView(frame_x, frame_y); + //PutBossLife(); + PutFade(); + + PutMapName(false); + + PutFramePerSecound(); + if (!Flip_SystemTask()) + break; + ++gCounter; + } + return 0; } @@ -432,8 +552,8 @@ bool Game() mode = ModeOpening(); if (mode == 2) mode = ModeTitle(); - //if (mode == 3) - // mode = ModeAction(); + if (mode == 3) + mode = ModeAction(); } EndMapData(); diff --git a/src/Map.cpp b/src/Map.cpp index 8d302605..c250f148 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -132,8 +132,8 @@ bool ChangeMapParts(int x, int y, uint8_t no) void PutStage_Back(int fx, int fy) { //Get range to draw - int num_x = WINDOW_WIDTH / 2 + 1; - int num_y = WINDOW_HEIGHT / 2 + 1; + int num_x = (WINDOW_WIDTH >> 4) + 1; + int num_y = (WINDOW_HEIGHT >> 4) + 1; int put_x = (fx / 0x200 + 8) / 16; int put_y = (fy / 0x200 + 8) / 16; @@ -165,8 +165,8 @@ void PutStage_Front(int fx, int fy) RECT rcSnack = {256, 48, 272, 64}; //Get range to draw - int num_x = WINDOW_WIDTH / 2 + 1; - int num_y = WINDOW_HEIGHT / 2 + 1; + int num_x = (WINDOW_WIDTH >> 4) + 1; + int num_y = (WINDOW_HEIGHT >> 4) + 1; int put_x = (fx / 0x200 + 8) / 16; int put_y = (fy / 0x200 + 8) / 16; @@ -199,8 +199,8 @@ void PutStage_Front(int fx, int fy) void PutMapDataVector(int fx, int fy) { //Get range to draw - int num_x = WINDOW_WIDTH / 2 + 1; - int num_y = WINDOW_HEIGHT / 2 + 1; + int num_x = (WINDOW_WIDTH >> 4) + 1; + int num_y = (WINDOW_HEIGHT >> 4) + 1; int put_x = (fx / 0x200 + 8) / 16; int put_y = (fy / 0x200 + 8) / 16; diff --git a/src/MyChar.cpp b/src/MyChar.cpp index 4a4df29d..f9a4b250 100644 --- a/src/MyChar.cpp +++ b/src/MyChar.cpp @@ -4,9 +4,12 @@ #include "WindowsWrapper.h" #include "MyChar.h" +#include "NpChar.h" #include "Draw.h" #include "Sound.h" #include "KeyControl.h" +#include "Game.h" +#include "Caret.h" MYCHAR gMC; @@ -138,6 +141,577 @@ void ShowMyChar(bool bShow) gMC.cond |= 2; } +void PutMyChar(int fx, int fy) +{ + if ((gMC.cond & 0x80u) && !(gMC.cond & 2)) + { + //Draw weapon + gMC.rect_arms.left = 24 * 0;//(gArmsData[gSelectedArms].code % 13); + gMC.rect_arms.right = gMC.rect_arms.left + 24; + gMC.rect_arms.top = 96 * 0;//(gArmsData[gSelectedArms].code / 13); + gMC.rect_arms.bottom = gMC.rect_arms.top + 16; + + if (gMC.direct == 2) + { + gMC.rect_arms.top += 16; + gMC.rect_arms.bottom += 16; + } + + int arms_offset_y; + if (gMC.up) + { + arms_offset_y = -4; + gMC.rect_arms.top += 32; + gMC.rect_arms.bottom += 32; + } + else if (gMC.down) + { + arms_offset_y = 4; + gMC.rect_arms.top += 64; + gMC.rect_arms.bottom += 64; + } + else + { + arms_offset_y = 0; + } + + if (gMC.ani_no == 1 || gMC.ani_no == 3 || gMC.ani_no == 6 || gMC.ani_no == 8) + ++gMC.rect_arms.top; + + if (gMC.direct) + PutBitmap3( + &grcGame, + (gMC.x - gMC.view.left) / 0x200 - fx / 0x200, + arms_offset_y + (gMC.y - gMC.view.top) / 0x200 - fy / 0x200, + &gMC.rect_arms, + 11); + else + PutBitmap3( + &grcGame, + (gMC.x - gMC.view.left) / 0x200 - fx / 0x200 - 8, + arms_offset_y + (gMC.y - gMC.view.top) / 0x200 - fy / 0x200, + &gMC.rect_arms, + 11); + + if (!((gMC.shock >> 1) & 1)) + { + //Draw player + RECT rect = gMC.rect; + if (gMC.equip & 0x40) + { + rect.top += 32; + rect.bottom += 32; + } + + PutBitmap3(&grcGame, (gMC.x - gMC.view.left) / 0x200 - fx / 0x200, (gMC.y - gMC.view.top) / 0x200 - fy / 0x200, &rect, 16); + + //Draw airtank + RECT rcBubble[2]; + rcBubble[0] = {56, 96, 80, 120}; + rcBubble[1] = {80, 96, 104, 120}; + + ++gMC.bubble; + if (gMC.equip & 0x10 && gMC.flag & 0x100) + PutBitmap3(&grcGame, gMC.x / 0x200 - 12 - fx / 0x200, gMC.y / 0x200 - 12 - fy / 0x200, &rcBubble[(gMC.bubble >> 1) & 1], 19); + else if (gMC.unit == 1) + PutBitmap3(&grcGame, gMC.x / 0x200 - 12 - fx / 0x200, gMC.y / 0x200 - 12 - fy / 0x200, &rcBubble[(gMC.bubble >> 1) & 1], 19); + } + } +} + +void ActMyChar_Normal(bool bKey) +{ + if (!(gMC.cond & 2)) + { + //Get speeds and accelerations + int max_dash; + int gravity1; + int gravity2; + int jump; + int dash1; + int dash2; + int resist; + + if (gMC.flag & 0x100) + { + max_dash = 0x196; + gravity1 = 0x28; + gravity2 = 0x10; + jump = 0x280; + dash1 = 0x2A; + dash2 = 0x10; + resist = 0x19; + } + else + { + max_dash = 0x32C; + gravity1 = 0x50; + gravity2 = 0x20; + jump = 0x500; + dash1 = 0x55; + dash2 = 0x20; + resist = 0x33; + } + + //Don't create "?" effect + gMC.ques = 0; + + //If can't control player, stop boosting + if (!bKey) + gMC.boost_sw = 0; + + //Movement on the ground + if (gMC.flag & 8 || gMC.flag & 0x10 || gMC.flag & 0x20) + { + //Stop boosting and refuel + gMC.boost_sw = 0; + + if (gMC.equip & 1) + { + gMC.boost_cnt = 50; + } + else if (gMC.equip & 0x20) + { + gMC.boost_cnt = 50; + } + else + { + gMC.boost_cnt = 0; + } + + //Move in direction held + if (bKey) + { + if (gKeyTrg != gKeyDown || gKey != gKeyDown || (gMC.cond & 1) || g_GameFlags & 4) + { + if (gKey != gKeyDown) + { + if (gKey & gKeyLeft && gMC.xm > -max_dash) + gMC.xm -= dash1; + if (gKey & gKeyRight && gMC.xm < max_dash) + gMC.xm += dash1; + + if (gKey & gKeyLeft) + gMC.direct = 0; + if (gKey & gKeyRight) + gMC.direct = 2; + } + } + else + { + gMC.cond |= 1; + gMC.ques = 1; + } + } + + //Friction + if (!(gMC.cond & 0x20)) + { + if (gMC.xm < 0) + { + if (gMC.xm <= -resist) + gMC.xm += resist; + else + gMC.xm = 0; + } + if (gMC.xm > 0) + { + if (gMC.xm >= resist) + gMC.xm -= resist; + else + gMC.xm = 0; + } + } + } + else + { + //Start boosting + if (bKey) + { + if (gMC.equip & 0x21 && gKeyTrg & gKeyJump && gMC.boost_cnt) + { + //Booster 0.8 + if (gMC.equip & 1) + { + gMC.boost_sw = 1; + if (gMC.ym > 0x100) + gMC.ym /= 2; + } + + //Booster 2.0 + if (gMC.equip & 0x20) + { + if (gKey & gKeyUp) + { + gMC.boost_sw = 2; + gMC.xm = 0; + gMC.ym = -0x5FF; + } + else if ( gKey & gKeyLeft ) + { + gMC.boost_sw = 1; + gMC.ym = 0; + gMC.xm = -0x5FF; + } + else if ( gKey & gKeyRight ) + { + gMC.boost_sw = 1; + gMC.ym = 0; + gMC.xm = 0x5FF; + } + else if ( gKey & gKeyDown ) + { + gMC.boost_sw = 3; + gMC.xm = 0; + gMC.ym = 0x5FF; + } + else + { + gMC.boost_sw = 2; + gMC.xm = 0; + gMC.ym = -0x5FF; + } + } + } + + //Move left and right + if ( gKey & gKeyLeft && gMC.xm > -max_dash ) + gMC.xm -= dash2; + if ( gKey & gKeyRight && gMC.xm < max_dash ) + gMC.xm += dash2; + + if ( gKey & gKeyLeft ) + gMC.direct = 0; + if ( gKey & gKeyRight ) + gMC.direct = 2; + } + + //Slow down when stopped boosting (Booster 2.0) + if (gMC.equip & 0x20 && gMC.boost_sw && (!(gKey & gKeyJump) || !gMC.boost_cnt)) + { + if (gMC.boost_sw == 1) + gMC.xm /= 2; + else if (gMC.boost_sw == 2) + gMC.ym /= 2; + } + + //Stop boosting + if (!gMC.boost_cnt || !(gKey & gKeyJump)) + gMC.boost_sw = 0; + } + + //Jumping + if ( bKey ) + { + //Look up and down + gMC.up = (gKey & gKeyUp) != 0; + gMC.down = gKey & gKeyDown && !(gMC.flag & 8); + + if (gKeyTrg & gKeyJump + && (gMC.flag & 8 || gMC.flag & 0x10 || gMC.flag & 0x20) + && !(gMC.flag & 0x2000)) + { + gMC.ym = -jump; + PlaySoundObject(15, 1); + } + } + + //Stop interacting when moved + if (bKey && (gKeyShot | gKeyJump | gKeyUp | gKeyRight | gKeyLeft) & gKey) + gMC.cond &= ~1; + + //Booster losing fuel + if (gMC.boost_sw && gMC.boost_cnt) + --gMC.boost_cnt; + + //Wind / current forces + if (gMC.flag & 0x1000) + gMC.xm -= 0x88; + if (gMC.flag & 0x2000) + gMC.ym -= 0x80; + if (gMC.flag & 0x4000) + gMC.xm += 0x88; + if (gMC.flag & 0x8000) + gMC.ym += 0x55; + + //Booster 2.0 forces and effects + if (gMC.equip & 0x20 && gMC.boost_sw) + { + if (gMC.boost_sw == 1) + { + //Go up when going into a wall + if (gMC.flag & 5) + gMC.ym = -0x100; + + //Move in direction facing + if (!gMC.direct) + gMC.xm -= 0x20; + if (gMC.direct == 2) + gMC.xm += 0x20; + + //Boost particles (and sound) + if (gKeyTrg & gKeyJump || gMC.boost_cnt % 3 == 1) + { + if (!gMC.direct) + SetCaret(gMC.x + 0x400, gMC.y + 0x400, 7, 2); + if (gMC.direct == 2) + SetCaret(gMC.x - 0x400, gMC.y + 0x400, 7, 0); + + PlaySoundObject(113, 1); + } + } + else if (gMC.boost_sw == 2) + { + //Move upwards + gMC.ym -= 0x20; + + //Boost particles (and sound) + if (gKeyTrg & gKeyJump || gMC.boost_cnt % 3 == 1) + { + SetCaret(gMC.x, gMC.y + 0xC00, 7, 3); + PlaySoundObject(113, 1); + } + } + else if (gMC.boost_sw == 3 && (gKeyTrg & gKeyJump || gMC.boost_cnt % 3 == 1)) + { + //Boost particles (and sound) + SetCaret(gMC.x, gMC.y - 0xC00, 7, 1); + PlaySoundObject(113, 1); + } + } + //Upwards wind/current + else if (gMC.flag & 0x2000) + { + gMC.ym += gravity1; + } + //Booster 0.8 + else if (gMC.equip & 1 && gMC.boost_sw && gMC.ym > -0x400) + { + //Upwards force + gMC.ym -= 0x20; + + if (!(gMC.boost_cnt % 3)) + { + SetCaret(gMC.x, gMC.hit.bottom / 2 + gMC.y, 7, 3); + PlaySoundObject(113, 1); + } + + //Bounce off of ceiling + if (gMC.flag & 2) + gMC.ym = 0x200; + } + //Gravity while jump is held + else if (gMC.ym < 0 && bKey && gKey & gKeyJump) + { + gMC.ym += gravity2; + } + //Normal gravity + else + { + gMC.ym += gravity1; + } + + //Keep player on slopes + if (bKey && !(gKeyTrg & gKeyJump)) + { + if (gMC.flag & 0x10 && gMC.xm < 0) + gMC.ym = -gMC.xm; + if (gMC.flag & 0x20 && gMC.xm > 0) + gMC.ym = gMC.xm; + if (gMC.flag & 8 && gMC.flag & 0x80000 && gMC.xm < 0) + gMC.ym = 0x400; + if (gMC.flag & 8 && gMC.flag & 0x10000 && gMC.xm > 0) + gMC.ym = 0x400; + if (gMC.flag & 8 && gMC.flag & 0x20000 && gMC.flag & 0x40000) + gMC.ym = 0x400; + } + + //Limit speed + if (!(gMC.flag & 0x100) || gMC.flag & 0xF000) + { + if (gMC.xm < -0x5FF) + gMC.xm = -0x5FF; + if (gMC.xm > 0x5FF) + gMC.xm = 0x5FF; + if (gMC.ym < -0x5FF) + gMC.ym = -0x5FF; + if (gMC.ym > 0x5FF) + gMC.ym = 0x5FF; + } + else + { + if (gMC.xm < -0x2FF) + gMC.xm = -0x2FF; + if (gMC.xm > 0x2FF) + gMC.xm = 0x2FF; + if (gMC.ym < -0x2FF) + gMC.ym = -0x2FF; + if (gMC.ym > 0x2FF) + gMC.ym = 0x2FF; + } + + //Water splashing + if (!gMC.sprash && gMC.flag & 0x100) + { + int dir; + if (gMC.flag & 0x800) + dir = 2; + else + dir = 0; + + if (gMC.flag & 8 || gMC.ym <= 0x200) + { + if (gMC.xm > 0x200 || gMC.xm < -0x200) + { + for (int a = 0; a < 8; a++) + SetNpChar(73, gMC.x + (Random(-8, 8) << 9), gMC.y, gMC.xm + Random(-0x200, 0x200), gMC.ym + Random(-0x200, 0x80), dir, 0, 0); + + PlaySoundObject(56, 1); + } + } + else + { + for (int a = 0; a < 8; a++) + SetNpChar(73, gMC.x + (Random(-8, 8) << 9), gMC.y, gMC.xm + Random(-0x200, 0x200), Random(-0x200, 0x80) - gMC.ym / 2, dir, 0, 0); + + PlaySoundObject(56, 1); + } + + gMC.sprash = 1; + } + + if (!(gMC.flag & 0x100)) + gMC.sprash = 0; + + //Spike damage + //if (gMC.flag & 0x400) + // DamageMyChar(10); + + //Camera + if (gMC.direct) + { + gMC.index_x += 0x200; + if (gMC.index_x > 0x8000) + gMC.index_x = 0x8000; + } + else + { + gMC.index_x -= 0x200; + if (gMC.index_x < -0x8000) + gMC.index_x = -0x8000; + } + if (gKey & gKeyUp && bKey) + { + gMC.index_y -= 0x200; + if (gMC.index_y < -0x8000) + gMC.index_y = -0x8000; + } + else if (gKey & gKeyDown && bKey) + { + gMC.index_y += 0x200; + if (gMC.index_y > 0x8000) + gMC.index_y = 0x8000; + } + else + { + if (gMC.index_y > 0x200) + gMC.index_y -= 0x200; + if (gMC.index_y < -0x200) + gMC.index_y += 0x200; + } + + gMC.tgt_x = gMC.x + gMC.index_x; + gMC.tgt_y = gMC.y + gMC.index_y; + + //Change position + if (gMC.xm > resist || gMC.xm < -resist) + gMC.x += gMC.xm; + gMC.y += gMC.ym; + } +} + +void AirProcess() +{ + /* + if ( unk_81C8598 & 0x10 ) + { + unk_81C8624 = 1000; + unk_81C8628 = 0; + } + else + { + if ( gMC.flag & 0x100 ) + { + if ( --unk_81C8624 <= 0 ) + { + if ( (unsigned __int8)GetNPCFlag(4000) ) + { + StartTextScript(1100); + } + else + { + StartTextScript(41); + if ( dir ) + SetCaret(x, y, 8, 2); + else + SetCaret(x, y, 8, 0); + gMC.cond &= 0x7Fu; + } + } + } + else + { + unk_81C8624 = 1000; + } + if ( gMC.flag & 0x100 ) + { + unk_81C8628 = 60; + } + else if ( unk_81C8628 ) + { + --unk_81C8628; + } + } + */ +} + +void ActMyChar(bool bKey) +{ + if (gMC.cond & 0x80) + { + if (gMC.exp_wait) + --gMC.exp_wait; + + if (gMC.shock) + { + --gMC.shock; + } + else if (gMC.exp_count) + { + //SetValueView(&x, &y, gMC.exp_count); + gMC.exp_count = 0; + } + + switch (gMC.unit) + { + case 0: + if (!(g_GameFlags & 4) && bKey) + AirProcess(); + ActMyChar_Normal(bKey); + break; + + case 1: + //ActMyChar_Stream(bKey); + break; + + default: + break; + } + + gMC.cond &= ~0x20; + } +} + void GetMyCharPosition(int *x, int *y) { *x = gMC.x; diff --git a/src/MyChar.h b/src/MyChar.h index cc6afcac..cbd7aacf 100644 --- a/src/MyChar.h +++ b/src/MyChar.h @@ -51,6 +51,9 @@ extern MYCHAR gMC; void InitMyChar(); void AnimationMyChar(bool bKey); void ShowMyChar(bool bShow); +void PutMyChar(int fx, int fy); +void ActMyChar_Normal(bool bKey); +void ActMyChar(bool bKey); void GetMyCharPosition(int *x, int *y); void SetMyCharPosition(int x, int y); void MoveMyChar(int x, int y); diff --git a/src/MycHit.cpp b/src/MycHit.cpp new file mode 100644 index 00000000..8b56f62e --- /dev/null +++ b/src/MycHit.cpp @@ -0,0 +1,567 @@ +#include + +#include "WindowsWrapper.h" + +#include "MyChar.h" +#include "Map.h" +#include "Sound.h" +#include "Caret.h" +#include "Back.h" +#include "KeyControl.h" + +void ResetMyCharFlag() +{ + gMC.flag = 0; +} + +void PutlittleStar() +{ + if (!(gMC.cond & 2) && gMC.ym < -0x200) + { + PlaySoundObject(3, 1); + SetCaret(gMC.x, gMC.y - gMC.hit.top, 13, 0); + SetCaret(gMC.x, gMC.y - gMC.hit.top, 13, 0); + } +} + +int JudgeHitMyCharBlock(int x, int y) +{ + int hit = 0; + + //Left wall + if (gMC.y - gMC.hit.top < (2 * (2 * y + 1) - 1) << 11 + && gMC.y + gMC.hit.bottom > (2 * (2 * y - 1) + 1) << 11 + && gMC.x - gMC.hit.left < (2 * x + 1) << 12 + && gMC.x - gMC.hit.left > x << 13) + { + //Clip + gMC.x = ((2 * x + 1) << 12) + gMC.hit.left; + + //Halt momentum + if (gMC.xm < -0x180) + gMC.xm = -0x180; + if (!(gKey & gKeyLeft) && gMC.xm < 0) + gMC.xm = 0; + + //Set that a left wall was hit + hit |= 1; + } + + //Right wall + if (gMC.y - gMC.hit.top < (2 * (2 * y + 1) - 1) << 11 + && gMC.y + gMC.hit.bottom > (2 * (2 * y - 1) + 1) << 11 + && gMC.x + gMC.hit.right > (2 * x - 1) << 12 + && gMC.x + gMC.hit.left < x << 13) + { + //Clip + gMC.x = ((2 * x - 1) << 12) - gMC.hit.right; + + //Halt momentum + if (gMC.xm > 0x180) + gMC.xm = 0x180; + if (!(gKey & gKeyRight) && gMC.xm > 0) + gMC.xm = 0; + + //Set that a right wall was hit + hit |= 4; + } + + //Ceiling + if (gMC.x - gMC.hit.right < ((2 * x + 1) << 12) - 0x600 + && gMC.x + gMC.hit.right > ((2 * x - 1) << 12) + 0x600 + && gMC.y - gMC.hit.top < (2 * y + 1) << 12 + && gMC.y - gMC.hit.top > y << 13) + { + //Clip + gMC.y = ((2 * y + 1) << 12) + gMC.hit.top; + + //Halt momentum + if (!(gMC.cond & 2) && gMC.ym < -0x200) + PutlittleStar(); + if (gMC.ym < 0) + gMC.ym = 0; + + //Set that a ceiling was hit + hit |= 2; + } + + //Floor + if (gMC.x - gMC.hit.right < ((2 * x + 1) << 12) - 0x600 + && gMC.x + gMC.hit.right > ((2 * x - 1) << 12) + 0x600 + && gMC.y + gMC.hit.bottom > (2 * y - 1) << 12 + && gMC.y + gMC.hit.bottom < y << 13) + { + //Clip + gMC.y = ((2 * y - 1) << 12) - gMC.hit.bottom; + + //Halt momentum + if (gMC.ym > 0x400) + PlaySoundObject(23, 1); + if (gMC.ym > 0) + gMC.ym = 0; + + //Set that a floor was hit + hit |= 8; + } + + return hit; +} + +int JudgeHitMyCharTriangleA(int x, int y) +{ + int hit = 0; + + if (gMC.x < (2 * x + 1) << 12 + && gMC.x > (2 * x - 1) << 12 + && gMC.y - gMC.hit.top < (y << 13) - (-0x2000 * x + gMC.x) / 2 + 0x800 + && gMC.y + gMC.hit.bottom > (2 * y - 1) << 12) + { + //Clip + gMC.y = (y << 13) - (-0x2000 * x + gMC.x) / 2 + 0x800 + gMC.hit.top; + + //Halt momentum + if (!(gMC.cond & 2) && gMC.ym < -0x200) + PutlittleStar(); + if (gMC.ym < 0) + gMC.ym = 0; + + //Set that hit a ceiling + hit |= 2; + } + + return hit; +} + +int JudgeHitMyCharTriangleB(int x, int y) +{ + int hit = 0; + + if (gMC.x < (2 * x + 1) << 12 + && gMC.x > (2 * x - 1) << 12 + && gMC.y - gMC.hit.top < (y << 13) - (-0x2000 * x + gMC.x) / 2 - 0x800 + && gMC.y + gMC.hit.bottom > (2 * y - 1) << 12) + { + //Clip + gMC.y = (y << 13) - (-0x2000 * x + gMC.x) / 2 - 0x800 + gMC.hit.top; + + //Halt momentum + if (!(gMC.cond & 2) && gMC.ym < -0x200) + PutlittleStar(); + if (gMC.ym < 0) + gMC.ym = 0; + + //Set that hit a ceiling + hit |= 2; + } + + return hit; +} + +int JudgeHitMyCharTriangleC(int x, int y) +{ + int hit = 0; + + if (gMC.x < (2 * x + 1) << 12 + && gMC.x > (2 * x - 1) << 12 + && gMC.y - gMC.hit.top < (y << 13) + (-0x2000 * x + gMC.x) / 2 - 0x800 + && gMC.y + gMC.hit.bottom > (2 * y - 1) << 12) + { + //Clip + gMC.y = (y << 13) - (-0x2000 * x + gMC.x) / 2 - 0x800 + gMC.hit.top; + + //Halt momentum + if (!(gMC.cond & 2) && gMC.ym < -0x200) + PutlittleStar(); + if (gMC.ym < 0) + gMC.ym = 0; + + //Set that hit a ceiling + hit |= 2; + } + + return hit; +} + +int JudgeHitMyCharTriangleD(int x, int y) +{ + int hit = 0; + + if (gMC.x < (2 * x + 1) << 12 + && gMC.x > (2 * x - 1) << 12 + && gMC.y - gMC.hit.top < (y << 13) + (-0x2000 * x + gMC.x) / 2 + 0x800 + && gMC.y + gMC.hit.bottom > (2 * y - 1) << 12) + { + //Clip + gMC.y = (y << 13) + (-0x2000 * x + gMC.x) / 2 + 0x800 + gMC.hit.top; + + //Halt momentum + if (!(gMC.cond & 2) && gMC.ym < -0x200) + PutlittleStar(); + if (gMC.ym < 0) + gMC.ym = 0; + + //Set that hit a ceiling + hit |= 2; + } + + return hit; +} + +int JudgeHitMyCharTriangleE(int x, int y) +{ + int hit = 0x10000; + + if (gMC.x < (2 * x + 1) << 12 + && gMC.x > (2 * x - 1) << 12 + && gMC.y + gMC.hit.bottom > (y << 13) + (-0x2000 * x + gMC.x) / 2 - 0x800 + && gMC.y - gMC.hit.top < (2 * y + 1) << 12) + { + //Clip + gMC.y = (y << 13) + (-0x2000 * x + gMC.x) / 2 - 0x800 - gMC.hit.bottom; + + //Halt momentum + if (gMC.ym > 0x400) + PlaySoundObject(23, 1); + if (gMC.ym > 0) + gMC.ym = 0; + + //Set that hit this slope + hit = 0x10028; + } + + return hit; +} + +int JudgeHitMyCharTriangleF(int x, int y) +{ + int hit = 0x20000; + + if (gMC.x < (2 * x + 1) << 12 + && gMC.x > (2 * x - 1) << 12 + && gMC.y + gMC.hit.bottom > (y << 13) + (-0x2000 * x + gMC.x) / 2 + 0x800 + && gMC.y - gMC.hit.top < (2 * y + 1) << 12) + { + //Clip + gMC.y = (y << 13) + (-0x2000 * x + gMC.x) / 2 + 0x800 - gMC.hit.bottom; + + //Halt momentum + if (gMC.ym > 0x400) + PlaySoundObject(23, 1); + if (gMC.ym > 0) + gMC.ym = 0; + + //Set that hit this slope + hit = 0x20028; + } + + return hit; +} + +int JudgeHitMyCharTriangleG(int x, int y) +{ + int hit = 0x40000; + + if (gMC.x < (2 * x + 1) << 12 + && gMC.x > (2 * x - 1) << 12 + && gMC.y + gMC.hit.bottom > (y << 13) - (-0x2000 * x + gMC.x) / 2 + 0x800 + && gMC.y - gMC.hit.top < (2 * y + 1) << 12) + { + //Clip + gMC.y = (y << 13) - (-0x2000 * x + gMC.x) / 2 + 0x800 - gMC.hit.bottom; + + //Halt momentum + if (gMC.ym > 0x400) + PlaySoundObject(23, 1); + if (gMC.ym > 0) + gMC.ym = 0; + + //Set that hit this slope + hit = 0x40018; + } + + return hit; +} + +int JudgeHitMyCharTriangleH(int x, int y) +{ + int hit = 0x80000; + + if (gMC.x < (2 * x + 1) << 12 + && gMC.x > (2 * x - 1) << 12 + && gMC.y + gMC.hit.bottom > (y << 13) - (-0x2000 * x + gMC.x) / 2 - 0x800 + && gMC.y - gMC.hit.top < (2 * y + 1) << 12) + { + //Clip + gMC.y = (y << 13) - (-0x2000 * x + gMC.x) / 2 - 0x800 - gMC.hit.bottom; + + //Halt momentum + if (gMC.ym > 0x400) + PlaySoundObject(23, 1); + if (gMC.ym > 0) + gMC.ym = 0; + + //Set that hit this slope + hit = 0x80018; + } + + return hit; +} + +int JudgeHitMyCharWater(int x, int y) +{ + int hit = 0; + + if (gMC.x - gMC.hit.right < ((2 * x + 1) << 12) - 0x600 + && gMC.x + gMC.hit.right > ((2 * x - 1) << 12) + 0x600 + && gMC.y - gMC.hit.top < ((2 * y + 1) << 12) - 0x600 + && gMC.y + gMC.hit.bottom > y << 13) + hit = 0x100; + + return hit; +} + +int JudgeHitMyCharDamage(int x, int y) +{ + int hit = 0; + + if (gMC.x - 0x800 < (4 * x + 1) << 11 + && gMC.x + 0x800 > (4 * x - 1) << 11 + && gMC.y - 0x800 < (y << 13) + 0x600 + && gMC.y + 0x800 > (y << 13) - 0x600) + hit = 0x400; + + return hit; +} + +int JudgeHitMyCharDamageW(int x, int y) +{ + int hit = 0; + + if (gMC.x - 0x800 < (4 * x + 1) << 11 + && gMC.x + 0x800 > (4 * x - 1) << 11 + && gMC.y - 0x800 < (y << 13) + 0x600 + && gMC.y + 0x800 > (y << 13) - 0x600) + hit = 0xD00; + + return hit; +} + +int JudgeHitMyCharVectLeft(int x, int y) +{ + int hit = 0; + if (gMC.x - gMC.hit.right < (4 * (2 * x + 1) - 1) << 10 + && gMC.x + gMC.hit.right > (4 * (2 * x - 1) + 1) << 10 + && gMC.y - gMC.hit.top < (4 * (2 * y + 1) - 1) << 10 + && gMC.y + gMC.hit.bottom > (4 * (2 * y - 1) + 1) << 10) + hit = 0x1000; + + return hit; +} + +int JudgeHitMyCharVectUp(int x, int y) +{ + int hit = 0; + if (gMC.x - gMC.hit.right < (4 * (2 * x + 1) - 1) << 10 + && gMC.x + gMC.hit.right > (4 * (2 * x - 1) + 1) << 10 + && gMC.y - gMC.hit.top < (4 * (2 * y + 1) - 1) << 10 + && gMC.y + gMC.hit.bottom > (4 * (2 * y - 1) + 1) << 10) + hit = 0x2000; + + return hit; +} + +int JudgeHitMyCharVectRight(int x, int y) +{ + int hit = 0; + if (gMC.x - gMC.hit.right < (4 * (2 * x + 1) - 1) << 10 + && gMC.x + gMC.hit.right > (4 * (2 * x - 1) + 1) << 10 + && gMC.y - gMC.hit.top < (4 * (2 * y + 1) - 1) << 10 + && gMC.y + gMC.hit.bottom > (4 * (2 * y - 1) + 1) << 10) + hit = 0x4000; + + return hit; +} + +int JudgeHitMyCharVectDown(int x, int y) +{ + int hit = 0; + if (gMC.x - gMC.hit.right < (4 * (2 * x + 1) - 1) << 10 + && gMC.x + gMC.hit.right > (4 * (2 * x - 1) + 1) << 10 + && gMC.y - gMC.hit.top < (4 * (2 * y + 1) - 1) << 10 + && gMC.y + gMC.hit.bottom > (4 * (2 * y - 1) + 1) << 10) + hit = 0x8000; + + return hit; +} + +void HitMyCharMap() +{ + int x = gMC.x / 0x2000; + int y = gMC.y / 0x2000; + + int offy[4]; + int offx[4]; + offx[0] = 0; + offx[1] = 1; + offx[2] = 0; + offx[3] = 1; + offy[0] = 0; + offy[1] = 0; + offy[2] = 1; + offy[3] = 1; + + uint8_t atrb[4]; + for (int i = 0; i < 4; i++) + { + atrb[i] = GetAttribute(x + offx[i], y + offy[i]); + + switch (atrb[i]) + { + //Water + case 0x02: + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + //Block + case 0x05: + case 0x41: + case 0x43: + case 0x46: + gMC.flag |= JudgeHitMyCharBlock(x + offx[i], y + offy[i]); + break; + + //Slopes + case 0x50: + gMC.flag |= JudgeHitMyCharTriangleA(x + offx[i], y + offy[i]); + break; + + case 0x51: + gMC.flag |= JudgeHitMyCharTriangleB(x + offx[i], y + offy[i]); + break; + + case 0x52: + gMC.flag |= JudgeHitMyCharTriangleC(x + offx[i], y + offy[i]); + break; + + case 0x53: + gMC.flag |= JudgeHitMyCharTriangleD(x + offx[i], y + offy[i]); + break; + + case 0x54: + gMC.flag |= JudgeHitMyCharTriangleE(x + offx[i], y + offy[i]); + break; + + case 0x55: + gMC.flag |= JudgeHitMyCharTriangleF(x + offx[i], y + offy[i]); + break; + + case 0x56: + gMC.flag |= JudgeHitMyCharTriangleG(x + offx[i], y + offy[i]); + break; + + case 0x57: + gMC.flag |= JudgeHitMyCharTriangleH(x + offx[i], y + offy[i]); + break; + + //Water and water blocks + case 0x60: + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0x61: + gMC.flag |= JudgeHitMyCharBlock(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + //Spikes + case 0x62: + gMC.flag |= JudgeHitMyCharDamageW(x + offx[i], y + offy[i]); + break; + + //Water slopes + case 0x70: + gMC.flag |= JudgeHitMyCharTriangleA(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0x71: + gMC.flag |= JudgeHitMyCharTriangleB(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0x72: + gMC.flag |= JudgeHitMyCharTriangleC(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0x73: + gMC.flag |= JudgeHitMyCharTriangleD(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0x74: + gMC.flag |= JudgeHitMyCharTriangleE(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0x75: + gMC.flag |= JudgeHitMyCharTriangleF(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0x76: + gMC.flag |= JudgeHitMyCharTriangleG(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0x77: + gMC.flag |= JudgeHitMyCharTriangleH(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + //Wind + case 0x80: + gMC.flag |= JudgeHitMyCharVectLeft(x + offx[i], y + offy[i]); + break; + + case 0x81: + gMC.flag |= JudgeHitMyCharVectUp(x + offx[i], y + offy[i]); + break; + + case 0x82: + gMC.flag |= JudgeHitMyCharVectRight(x + offx[i], y + offy[i]); + break; + + case 0x83: + gMC.flag |= JudgeHitMyCharVectDown(x + offx[i], y + offy[i]); + break; + + //Water current + case 0xA0: + gMC.flag |= JudgeHitMyCharVectLeft(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0xA1: + gMC.flag |= JudgeHitMyCharVectUp(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0xA2: + gMC.flag |= JudgeHitMyCharVectRight(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + case 0xA3: + gMC.flag |= JudgeHitMyCharVectDown(x + offx[i], y + offy[i]); + gMC.flag |= JudgeHitMyCharWater(x + offx[i], y + offy[i]); + break; + + default: + break; + } + } + + if (gMC.y > gWaterY + 0x800) + gMC.flag |= 0x100; +} diff --git a/src/MycHit.h b/src/MycHit.h new file mode 100644 index 00000000..a4337edc --- /dev/null +++ b/src/MycHit.h @@ -0,0 +1,3 @@ +#pragma once +void ResetMyCharFlag(); +void HitMyCharMap(); diff --git a/src/NpcAct.h b/src/NpcAct.h new file mode 100644 index 00000000..3065ae60 --- /dev/null +++ b/src/NpcAct.h @@ -0,0 +1,7 @@ +#include "NpChar.h" +void ActNpc000(NPCHAR *npc); +void ActNpc001(NPCHAR *npc); +void ActNpc002(NPCHAR *npc); +void ActNpc003(NPCHAR *npc); +void ActNpc004(NPCHAR *npc); +void ActNpc005(NPCHAR *npc); diff --git a/src/NpcAct000.cpp b/src/NpcAct000.cpp new file mode 100644 index 00000000..0aabd340 --- /dev/null +++ b/src/NpcAct000.cpp @@ -0,0 +1,486 @@ +#include "WindowsWrapper.h" + +#include "MyChar.h" +#include "NpChar.h" +#include "Game.h" +#include "Sound.h" +#include "Back.h" +#include "Triangle.h" + +//Null +void ActNpc000(NPCHAR *npc) +{ + if (!npc->act_no) + { + npc->act_no = 1; + if (npc->direct == 2) + npc->y += 0x2000; + } + + npc->rect = {0, 0, 16, 16}; +} + +//Experience +void ActNpc001(NPCHAR *npc) +{ + //When not in wind + if (gBack.type != 5 && gBack.type != 6) + { + if (!npc->act_no) + { + //Set state + npc->act_no = 1; + npc->ani_no = Random(0, 4); + + //Random speed + npc->xm = Random(-0x200, 0x200); + npc->ym = Random(-0x400, 0); + + //Random direction (reverse animation or not) + if (Random(0, 1) != 0) + npc->direct = 0; + else + npc->direct = 2; + } + + //Gravity + if (npc->flag & 0x100) + npc->ym += 21; + else + npc->ym += 42; + + //Bounce off walls + if (npc->flag & 1 && npc->xm < 0) + npc->xm = -npc->xm; + if (npc->flag & 4 && npc->xm > 0) + npc->xm = -npc->xm; + + //Bounce off ceiling + if (npc->flag & 2 && npc->ym < 0) + npc->ym = -npc->ym; + + //Bounce off floor + if (npc->flag & 8) + { + PlaySoundObject(45, 1); + npc->ym = -0x280; + npc->xm = 2 * npc->xm / 3; + } + + //Play bounce song (and try to clip out of floor if stuck) + if (npc->flag & 0xD) + { + PlaySoundObject(45, 1); + if (++npc->count2 > 2) + npc->y -= 512; + } + else + { + npc->count2 = 0; + } + + //Limit speed + if (npc->xm < -0x5FF) + npc->xm = -0x5FF; + if (npc->xm > 0x5FF) + npc->xm = 0x5FF; + if (npc->ym < -0x5FF) + npc->ym = -0x5FF; + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + } + //In wind + else + { + if (!npc->act_no) + { + //Set state + npc->act_no = 1; + + //Set random speed + npc->ym = Random(-0x80, 0x80); + npc->xm = Random(0x7F, 0x100); + } + + //Blow to the left + npc->xm -= 8; + + //Destroy when off-screen + if (npc->x <= 0x9FFF) + npc->cond = 0; + + //Limit speed (except pixel applied it to the X position) + if (npc->x < -0x5FF) + npc->x = -0x5FF; + + //Bounce off walls + if (npc->flag & 1) + npc->xm = 0x100; + if (npc->flag & 2) + npc->ym = 0x40; + if (npc->flag & 8) + npc->ym = -0x40; + } + + //Move + npc->x += npc->xm; + npc->y += npc->ym; + + //Get framerects + RECT rect[6]; + rect[0] = {0x00, 0x10, 0x10, 0x20}; + rect[1] = {0x10, 0x10, 0x20, 0x20}; + rect[2] = {0x20, 0x10, 0x30, 0x20}; + rect[3] = {0x30, 0x10, 0x40, 0x20}; + rect[4] = {0x40, 0x10, 0x50, 0x20}; + rect[5] = {0x50, 0x10, 0x60, 0x20}; + + RECT rcNo = {0, 0, 0, 0}; + + //Animate + ++npc->ani_wait; + + if (npc->direct) + { + if (npc->ani_wait > 2) + { + npc->ani_wait = 0; + if (--npc->ani_no < 0) + npc->ani_no = 5; + } + } + else if (npc->ani_wait > 2) + { + npc->ani_wait = 0; + if (++npc->ani_no > 5) + npc->ani_no = 0; + } + + npc->rect = rect[npc->ani_no]; + + //Size + if (npc->act_no) + { + if (npc->exp == 5) + { + npc->rect.top += 16; + npc->rect.bottom += 16; + } + else if (npc->exp == 20) + { + npc->rect.top += 32; + npc->rect.bottom += 32; + } + + npc->act_no = 1; + } + + //Delete after 500 frames + if (++npc->count1 > 500 && npc->ani_no == 5 && npc->ani_wait == 2) + npc->cond = 0; + + //Blink after 400 frames + if (npc->count1 > 400) + { + if (npc->count1 / 2 & 1) + npc->rect = rcNo; + } +} + +//Behemoth +void ActNpc002(NPCHAR *npc) +{ + //Rects + RECT rcLeft[7]; + rcLeft[0] = {32, 0, 64, 24}; + rcLeft[1] = {0, 0, 32, 24}; + rcLeft[2] = {32, 0, 64, 24}; + rcLeft[3] = {64, 0, 96, 24}; + rcLeft[4] = {96, 0, 128, 24}; + rcLeft[5] = {128, 0, 160, 24}; + rcLeft[6] = {160, 0, 192, 24}; + + RECT rcUp[7]; + rcUp[0] = {32, 24, 64, 48}; + rcUp[1] = {0, 24, 32, 48}; + rcUp[2] = {32, 24, 64, 48}; + rcUp[3] = {64, 24, 96, 48}; + rcUp[4] = {96, 24, 128, 48}; + rcUp[5] = {128, 24, 160, 48}; + rcUp[6] = {160, 24, 192, 48}; + + //Turn when touching a wall + if (npc->flag & 1) + npc->direct = 2; + else if (npc->flag & 4) + npc->direct = 0; + + switch (npc->act_no) + { + case 1: //Shot + npc->xm = 7 * npc->xm / 8; + + if (++npc->count1 > 40) + { + if (npc->shock) + { + npc->count1 = 0; + npc->act_no = 2; + npc->ani_no = 6; + npc->ani_wait = 0; + npc->damage = 5; + } + else + { + npc->act_no = 0; + npc->ani_wait = 0; + } + } + break; + case 2: //Charge + if (npc->direct) + npc->xm = 0x400; + else + npc->xm = -0x400; + + if (++npc->count1 > 200) + { + npc->act_no = 0; + npc->damage = 1; + } + + if (++npc->ani_wait > 5) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 6) + npc->ani_no = 5; + break; + case 0: //Walking + if (npc->direct) + npc->xm = 0x100; + else + npc->xm = -0x100; + + if (++npc->ani_wait > 8) + { + npc->ani_wait = 0; + ++npc->ani_no; + } + + if (npc->ani_no > 3) + npc->ani_no = 0; + + if (npc->shock) + { + npc->count1 = 0; + npc->act_no = 1; + npc->ani_no = 4; + } + break; + } + + //Gravity + npc->ym += 0x40; + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + + //Move + npc->x += npc->xm; + npc->y += npc->ym; + + //Set framerect + if (npc->direct) + npc->rect = rcUp[npc->ani_no]; + else + npc->rect = rcLeft[npc->ani_no]; +} + +//Dead enemy (make sure damage shown doesn't teleport to a new loaded npc) +void ActNpc003(NPCHAR *npc) +{ + if (++npc->count1 > 100) + npc->cond = 0; + + npc->rect = {0, 0, 0, 0}; +} + +//Smoke +void ActNpc004(NPCHAR *npc) +{ + RECT rcLeft[8]; + RECT rcUp[8]; + + rcLeft[0] = {16, 0, 17, 1}; + rcLeft[1] = {16, 0, 32, 16}; + rcLeft[2] = {32, 0, 48, 16}; + rcLeft[3] = {48, 0, 64, 16}; + rcLeft[4] = {64, 0, 80, 16}; + rcLeft[5] = {80, 0, 96, 16}; + rcLeft[6] = {96, 0, 112, 16}; + rcLeft[7] = {112, 0, 128, 16}; + + rcUp[0] = {16, 0, 17, 1}; + rcUp[1] = {80, 48, 96, 64}; + rcUp[2] = {0, 128, 16, 144}; + rcUp[3] = {16, 128, 32, 144}; + rcUp[4] = {32, 128, 48, 144}; + rcUp[5] = {48, 128, 64, 144}; + rcUp[6] = {64, 128, 80, 144}; + rcUp[7] = {80, 128, 96, 144}; + + if (npc->act_no) + { + //Slight drag + npc->xm = 20 * npc->xm / 21; + npc->ym = 20 * npc->ym / 21; + + //Move + npc->x += npc->xm; + npc->y += npc->ym; + } + else + { + //Move in random direction at random speed + if (!npc->direct || npc->direct == 1) + { + uint8_t deg = Random(0, 0xFF); + npc->xm = GetCos(deg) * Random(0x200, 0x5FF) / 0x200; + npc->ym = GetSin(deg) * Random(0x200, 0x5FF) / 0x200; + } + + //Set state + npc->ani_no = Random(0, 4); + npc->ani_wait = Random(0, 3); + npc->act_no = 1; + } + + //Animate + if (++npc->ani_wait > 4) + { + npc->ani_wait = 0; + npc->ani_no++; + } + + //Set framerect + if (npc->ani_no < 8) + { + if (npc->direct == 1) + npc->rect = rcUp[npc->ani_no]; + if (!npc->direct) + npc->rect = rcLeft[npc->ani_no]; + if (npc->direct == 2) + npc->rect = rcLeft[npc->ani_no]; + } + else + { + //Destroy if over + npc->cond = 0; + } +} + +//Critter (Green, Egg Corridor) +void ActNpc005(NPCHAR *npc) +{ + RECT rcLeft[3]; + RECT rcRight[3]; + + rcLeft[0] = {0, 48, 16, 64}; + rcLeft[1] = {16, 48, 32, 64}; + rcLeft[2] = {32, 48, 48, 64}; + + rcRight[0] = {0, 64, 16, 80}; + rcRight[1] = {16, 64, 32, 80}; + rcRight[2] = {32, 64, 48, 80}; + + switch (npc->act_no) + { + case 0: //Init + npc->y += 0x600; + npc->act_no = 1; + + case 1: //Waiting + //Look at player + if (npc->x <= gMC.x) + npc->direct = 2; + else + npc->direct = 0; + + //Open eyes near player + if (npc->act_wait < 8 || npc->x - 0xE000 >= gMC.x || npc->x + 0xE000 <= gMC.x || npc->y - 0xA000 >= gMC.y || npc->y + 0xA000 <= gMC.y) + { + if (npc->act_wait < 8) + ++npc->act_wait; + npc->ani_no = 0; + } + else + { + npc->ani_no = 1; + } + + //Jump if attacked + if (npc->shock) + { + npc->act_no = 2; + npc->ani_no = 0; + npc->act_wait = 0; + } + + //Jump if player is nearby + if (npc->act_wait >= 8 && npc->x - 0x6000 < gMC.x && npc->x + 0x6000 > gMC.x && npc->y - 0xA000 < gMC.y && npc->y + 0x6000 > gMC.y) + { + npc->act_no = 2; + npc->ani_no = 0; + npc->act_wait = 0; + } + break; + + case 2: //Going to jump + if (++npc->act_wait > 8) + { + //Set jump state + npc->act_no = 3; + npc->ani_no = 2; + + //Jump + npc->ym = -0x5FF; + PlaySoundObject(30, 1); + + //Jump in facing direction + if (npc->direct) + npc->xm = 0x100; + else + npc->xm = -0x100; + } + break; + + case 3: //Jumping + //Land + if (npc->flag & 8) + { + npc->xm = 0; + npc->act_wait = 0; + npc->ani_no = 0; + npc->act_no = 1; + PlaySoundObject(23, 1); + } + break; + } + + //Gravity + npc->ym += 64; + if (npc->ym > 0x5FF) + npc->ym = 0x5FF; + + //Move + npc->x += npc->xm; + npc->y += npc->ym; + + //Set framerect + if (npc->direct) + npc->rect = rcRight[npc->ani_no]; + else + npc->rect = rcLeft[npc->ani_no]; +} \ No newline at end of file diff --git a/src/NpcHit.cpp b/src/NpcHit.cpp new file mode 100644 index 00000000..d048eece --- /dev/null +++ b/src/NpcHit.cpp @@ -0,0 +1,401 @@ +#include "NpChar.h" +#include "Map.h" + +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) + { + npc->x = ((2 * x + 1) << 12) + 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) + { + npc->x = ((2 * x - 1) << 12) - 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) + { + npc->y = ((2 * y + 1) << 12) + 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) + { + npc->y = ((2 * y - 1) << 12) - 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 < (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) + { + //Clip + npc->y = npc->hit.top + (y << 13) - (-0x2000 * x + npc->x) / 2 + 0x800; + + //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 < (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) + { + //Clip + npc->y = npc->hit.top + (y << 13) - (-0x2000 * x + npc->x) / 2 - 0x800; + + //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 < (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) + { + //Clip + npc->y = npc->hit.top + (y << 13) + (-0x2000 * x + npc->x) / 2 - 0x800; + + //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 < (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) + { + //Clip + npc->y = npc->hit.top + (y << 13) + (-0x2000 * x + npc->x) / 2 + 0x800; + + //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 = 0x10000; + + 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 ) + { + //Clip + npc->y = (y << 13) + (-0x2000 * x + npc->x) / 2 - 0x800 - npc->hit.bottom; + + //Halt momentum + if (npc->ym > 0) + npc->ym = 0; + + //Set that hit this slope + hit = 0x10028; + } + + npc->flag |= hit; +} + +void JudgeHitNpCharTriangleF(NPCHAR *npc, int x, int y) +{ + int hit = 0x20000; + + 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 ) + { + //Clip + npc->y = (y << 13) + (-0x2000 * x + npc->x) / 2 + 0x800 - npc->hit.bottom; + + //Halt momentum + if (npc->ym > 0) + npc->ym = 0; + + //Set that hit this slope + hit = 0x20028; + } + + npc->flag |= hit; +} + +void JudgeHitNpCharTriangleG(NPCHAR *npc, int x, int y) +{ + int hit = 0x40000; + + 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 ) + { + //Clip + npc->y = (y << 13) - (-0x2000 * x + npc->x) / 2 + 0x800 - npc->hit.bottom; + + //Halt momentum + if (npc->ym > 0) + npc->ym = 0; + + //Set that hit this slope + hit = 0x40018; + } + + npc->flag |= hit; +} + +void JudgeHitNpCharTriangleH(NPCHAR *npc, int x, int y) +{ + int hit = 0x80000; + + 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 ) + { + //Clip + npc->y = (y << 13) - (-0x2000 * x + npc->x) / 2 - 0x800 - npc->hit.bottom; + + //Halt momentum + if (npc->ym > 0) + npc->ym = 0; + + //Set that hit this slope + hit = 0x80018; + } + + npc->flag |= hit; +} + +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; + + npc->flag |= hit; +} + +void HitNpCharMap() +{ + int offy[9]; + int offx[9]; + + 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 (int i = 0; i < NPC_MAX; i++) + { + if ((gNPC[i].cond & 0x80) && !(gNPC[i].bits & 8)) + { + int judg, x, y; + if (gNPC[i].size <= 2) + { + 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]); + break; + + //Block + case 0x03: + case 0x05: + case 0x41: + case 0x43: + JadgeHitNpCharBlock(&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; + + //No NPC block + case 0x44: + if (!(gNPC[i].bits & npc_ignore44)) + 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 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; + } + } + } + } +} \ No newline at end of file diff --git a/src/NpcHit.h b/src/NpcHit.h new file mode 100644 index 00000000..3b17635b --- /dev/null +++ b/src/NpcHit.h @@ -0,0 +1,4 @@ +#pragma once +#include "NpChar.h" + +void HitNpCharMap(); diff --git a/src/NpcTbl.cpp b/src/NpcTbl.cpp index 3e64427a..6071cd21 100644 --- a/src/NpcTbl.cpp +++ b/src/NpcTbl.cpp @@ -3,6 +3,7 @@ #include #include "NpcTbl.h" +#include "NpcAct.h" NPC_TABLE *gNpcTable; @@ -55,12 +56,12 @@ void ReleaseNpcTable() //Npc function table NPCFUNCTION gpNpcFuncTbl[] = { - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, + &ActNpc000, + &ActNpc001, + &ActNpc002, + &ActNpc003, + &ActNpc004, + &ActNpc005, nullptr, nullptr, nullptr,