From 6dfef794a49a03f024f133ed0b61c805c6e660f0 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 12 Feb 2017 01:28:12 +0000 Subject: [PATCH 1/5] Metal Sonic's bounce attack is much nicer. Also, a bunch of other minor tweaks. --- src/info.c | 6 ++--- src/p_mobj.c | 72 ++++++++++++++++++++++++++++++++-------------------- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/info.c b/src/info.c index fdea617c1..705cb17d8 100644 --- a/src/info.c +++ b/src/info.c @@ -1372,11 +1372,11 @@ state_t states[NUMSTATES] = {SPR_METL, 13, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BLOCK {SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER - {SPR_METL, 9, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH + {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN - {SPR_METL, 0, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH + {SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH {SPR_METL, 3, 4, {NULL}, 0, 0, S_METALSONIC_FLEE2}, // S_METALSONIC_FLEE1 {SPR_METL, 4, 4, {A_BossScream}, 0, 0, S_METALSONIC_FLEE3}, // S_METALSONIC_FLEE2 {SPR_METL, 5, 4, {NULL}, 0, 0, S_METALSONIC_FLEE4}, // S_METALSONIC_FLEE3 @@ -4961,7 +4961,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = 16*FRACUNIT, // radius 48*FRACUNIT, // height 0, // display offset - sfx_mspogo, // mass + sfx_s3k5a, // mass 3, // damage sfx_mswarp, // activesound MF_NOGRAVITY|MF_BOSS|MF_SLIDEME, // flags diff --git a/src/p_mobj.c b/src/p_mobj.c index 39682a7ef..aaae5efd0 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5641,6 +5641,15 @@ static void P_Boss7Thinker(mobj_t *mobj) } +#define vectorise mobj->movedir = ANGLE_11hh - FixedAngle(FixedMul(AngleFixed(ANGLE_11hh), FixedDiv((mobj->info->spawnhealth - mobj->health)<info->spawnhealth-1)<movedir = InvAngle(mobj->movedir);\ + mobj->threshold = 6 + (FixedMul(24<info->spawnhealth - mobj->health)<info->spawnhealth-1)<>FRACBITS);\ + if (mobj->info->activesound)\ + S_StartSound(mobj, mobj->info->activesound);\ + if (mobj->info->painchance)\ + P_SetMobjState(mobj, mobj->info->painchance) + // Metal Sonic battle boss // You CAN put multiple Metal Sonics in a single map // because I am a totally competent programmer who can do shit right. @@ -5745,7 +5754,8 @@ static void P_Boss9Thinker(mobj_t *mobj) } if (spawner) { mobj_t *missile = P_SpawnMissile(spawner, mobj, MT_MSGATHER); - missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/4); + if (mobj->health > mobj->info->damage) + missile->momz = FixedDiv(missile->momz, 7*FRACUNIT/5); if (dist == 0) missile->fuse = 0; else @@ -5757,16 +5767,22 @@ static void P_Boss9Thinker(mobj_t *mobj) // Pre-threshold reactiontime stuff for attack phases if (mobj->reactiontime && mobj->movecount == 3) { + mobj->reactiontime--; + if (mobj->movedir == 0 || mobj->movedir == 2) { // Pausing between bounces in the pinball phase if (mobj->target->player->powers[pw_tailsfly]) // Trying to escape, eh? mobj->watertop = mobj->target->z + mobj->target->momz*6; // Readjust your aim. >:3 else mobj->watertop = mobj->target->floorz + 16*FRACUNIT; - if (!(mobj->threshold%4)) + + if (!(mobj->threshold%4)) { mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); + if (!mobj->reactiontime) + S_StartSound(mobj, sfx_zoom); // zoom! + } } - // Pausing between energy ball shots - mobj->reactiontime--; + // else -- Pausing between energy ball shots + return; } @@ -5838,20 +5854,28 @@ static void P_Boss9Thinker(mobj_t *mobj) P_InstaThrust(mobj, mobj->angle, 30*FRACUNIT); if (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true)) { // Hit a wall? Find a direction to bounce mobj->threshold--; - if (mobj->threshold) { - P_SetMobjState(mobj, mobj->state->nextstate); - if (mobj->info->mass) - S_StartSound(mobj, mobj->info->mass); - if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. - mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); - mobj->reactiontime = TICRATE; // targetting time - } else { // No homing, just use P_BounceMove - P_BounceMove(mobj); - mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); - mobj->reactiontime = TICRATE/4; // just a pause before you bounce away - } - mobj->momx = mobj->momy = 0; + P_SetMobjState(mobj, mobj->state->nextstate); + if (!mobj->threshold) { // failed bounce! + S_StartSound(mobj, sfx_mspogo); + P_BounceMove(mobj); + mobj->angle = R_PointToAngle2(0,0,mobj->momx, mobj->momy); + P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); + mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + mobj->flags &= ~MF_PAIN; + mobj->fuse = 10*TICRATE; + mobj->movecount = 0; + vectorise; + } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. + S_StartSound(mobj, sfx_s3k5a); + mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); + mobj->reactiontime = TICRATE - 5*(mobj->info->damage - mobj->health); // targetting time + } else { // No homing, just use P_BounceMove + S_StartSound(mobj, sfx_s3kaa); // make the bounces distinct... + P_BounceMove(mobj); + mobj->angle = R_PointToAngle2(0,0,mobj->momx,mobj->momy); + mobj->reactiontime = 1; // TICRATE/4; // just a pause before you bounce away } + mobj->momx = mobj->momy = 0; } return; } @@ -5978,9 +6002,9 @@ static void P_Boss9Thinker(mobj_t *mobj) S_StartSound(mobj, mobj->info->seesound); P_SetMobjState(mobj, mobj->info->seestate); if (mobj->movedir == 2) - mobj->threshold = 16; // bounce 16 times + mobj->threshold = 12; // bounce 12 times else - mobj->threshold = 32; // bounce 32 times + mobj->threshold = 24; // bounce 24 times mobj->watertop = mobj->target->floorz + 16*FRACUNIT; P_LinedefExecute(LE_PINCHPHASE, mobj, NULL); } else { @@ -6063,14 +6087,7 @@ static void P_Boss9Thinker(mobj_t *mobj) if (danger) { // An incoming attack is detected! What should we do?! // Go into vector form! - mobj->movedir = ANGLE_11hh - FixedAngle(FixedMul(AngleFixed(ANGLE_11hh), FixedDiv((mobj->info->spawnhealth - mobj->health)<info->spawnhealth-1)<movedir = InvAngle(mobj->movedir); - mobj->threshold = 6 + (FixedMul(24<info->spawnhealth - mobj->health)<info->spawnhealth-1)<>FRACBITS); - if (mobj->info->activesound) - S_StartSound(mobj, mobj->info->activesound); - if (mobj->info->painchance) - P_SetMobjState(mobj, mobj->info->painchance); + vectorise; return; } @@ -6085,6 +6102,7 @@ static void P_Boss9Thinker(mobj_t *mobj) } } } +#undef vectorise // // P_GetClosestAxis From 5f3cfc67294d006e29a8665a93dc7db7c61b3a60 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Sun, 12 Feb 2017 14:16:52 +0000 Subject: [PATCH 2/5] Some cleanup. --- src/p_mobj.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index aaae5efd0..65be4d78d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5858,11 +5858,10 @@ static void P_Boss9Thinker(mobj_t *mobj) if (!mobj->threshold) { // failed bounce! S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); - mobj->angle = R_PointToAngle2(0,0,mobj->momx, mobj->momy); - P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); + mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); mobj->watertop = mobj->target->floorz + 32*FRACUNIT; mobj->flags &= ~MF_PAIN; - mobj->fuse = 10*TICRATE; + mobj->fuse = 0; mobj->movecount = 0; vectorise; } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. @@ -5884,8 +5883,9 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->angle += mobj->movedir; P_InstaThrust(mobj, mobj->angle, -speed); while (!P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true) && tries++ < 16) { - mobj->angle += mobj->movedir; - P_InstaThrust(mobj, mobj->angle, -speed); + S_StartSound(mobj, sfx_mspogo); + P_BounceMove(mobj); + mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); } mobj->momx = mobj->momy = 0; mobj->threshold--; From 3feac5bc90a1fc9a14c8e91131a4f6138af15098 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 13 Feb 2017 18:04:08 +0000 Subject: [PATCH 3/5] bad bounce https://gfycat.com/DeliciousReliableGentoopenguin --- src/dehacked.c | 2 +- src/info.c | 4 ++-- src/info.h | 2 +- src/p_mobj.c | 23 ++++++++++++++++++++--- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/dehacked.c b/src/dehacked.c index c71c55ac1..748a3dc69 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -4772,11 +4772,11 @@ static const char *const STATE_LIST[] = { // array length left dynamic for sanit "S_METALSONIC_FLOAT", "S_METALSONIC_VECTOR", "S_METALSONIC_STUN", - "S_METALSONIC_BLOCK", "S_METALSONIC_RAISE", "S_METALSONIC_GATHER", "S_METALSONIC_DASH", "S_METALSONIC_BOUNCE", + "S_METALSONIC_BADBOUNCE", "S_METALSONIC_SHOOT", "S_METALSONIC_PAIN", "S_METALSONIC_DEATH", diff --git a/src/info.c b/src/info.c index 705cb17d8..6b3019781 100644 --- a/src/info.c +++ b/src/info.c @@ -1369,11 +1369,11 @@ state_t states[NUMSTATES] = {SPR_METL, 4, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_FLOAT {SPR_METL, 12, -1, {NULL}, 0, 0, S_METALSONIC_STUN}, // S_METALSONIC_VECTOR {SPR_METL, 0, -1, {NULL}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_STUN - {SPR_METL, 13, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BLOCK {SPR_METL, 13, 40, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_RAISE {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_GATHER {SPR_METL, 15, -1, {NULL}, 0, 0, S_METALSONIC_BOUNCE},// S_METALSONIC_DASH {SPR_METL, 14, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BOUNCE + {SPR_METL, 16, -1, {NULL}, 0, 0, S_NULL}, // S_METALSONIC_BADBOUNCE {SPR_METL, 13, -1, {NULL}, 0, 0, S_METALSONIC_GATHER},// S_METALSONIC_SHOOT {SPR_METL, 11, 40, {A_Pain}, 0, 0, S_METALSONIC_FLOAT}, // S_METALSONIC_PAIN {SPR_METL, 11, -1, {A_BossDeath}, 0, 0, S_NULL}, // S_METALSONIC_DEATH @@ -4952,7 +4952,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_METALSONIC_PAIN, // painstate S_METALSONIC_VECTOR,// painchance sfx_dmpain, // painsound - S_METALSONIC_BLOCK, // meleestate + S_METALSONIC_BADBOUNCE, // meleestate S_METALSONIC_SHOOT, // missilestate S_METALSONIC_DEATH, // deathstate S_METALSONIC_FLEE1, // xdeathstate diff --git a/src/info.h b/src/info.h index 1a6c14a70..0cca7896e 100644 --- a/src/info.h +++ b/src/info.h @@ -1575,11 +1575,11 @@ typedef enum state S_METALSONIC_FLOAT, S_METALSONIC_VECTOR, S_METALSONIC_STUN, - S_METALSONIC_BLOCK, S_METALSONIC_RAISE, S_METALSONIC_GATHER, S_METALSONIC_DASH, S_METALSONIC_BOUNCE, + S_METALSONIC_BADBOUNCE, S_METALSONIC_SHOOT, S_METALSONIC_PAIN, S_METALSONIC_DEATH, diff --git a/src/p_mobj.c b/src/p_mobj.c index 65be4d78d..fb7ee5a43 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5694,6 +5694,19 @@ static void P_Boss9Thinker(mobj_t *mobj) if (mobj->health <= 0) return; + if ((statenum_t)(mobj->state-states) == mobj->info->meleestate) + { + P_InstaThrust(mobj, mobj->angle, -4*FRACUNIT); + P_TryMove(mobj, mobj->x+mobj->momx, mobj->y+mobj->momy, true); + mobj->momz -= gravity; + if (mobj->z < mobj->watertop) + { + mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + P_SetMobjState(mobj, mobj->info->spawnstate); + } + return; + } + if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))) { P_BossTargetPlayer(mobj, false); @@ -5711,6 +5724,10 @@ static void P_Boss9Thinker(mobj_t *mobj) } else if (!mobj->fuse) mobj->fuse = 10*TICRATE; + + // reset to flying so everything gets properly re-initialised + mobj->threshold = 0; + mobj->movecount = 0; } // AI goes here. @@ -5859,11 +5876,11 @@ static void P_Boss9Thinker(mobj_t *mobj) S_StartSound(mobj, sfx_mspogo); P_BounceMove(mobj); mobj->angle = R_PointToAngle2(mobj->momx, mobj->momy,0,0); - mobj->watertop = mobj->target->floorz + 32*FRACUNIT; + mobj->momz = 4*FRACUNIT; mobj->flags &= ~MF_PAIN; - mobj->fuse = 0; + mobj->fuse = 10*TICRATE; mobj->movecount = 0; - vectorise; + P_SetMobjState(mobj, mobj->info->meleestate); } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. S_StartSound(mobj, sfx_s3k5a); mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x + mobj->target->momx*4, mobj->target->y + mobj->target->momy*4); From a04ae45a93397fcd4d90726159b482ddacd1f4e6 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Mon, 13 Feb 2017 18:53:16 +0000 Subject: [PATCH 4/5] MORE CUES --- src/p_mobj.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/p_mobj.c b/src/p_mobj.c index fb7ee5a43..33bcf0ce4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5880,6 +5880,7 @@ static void P_Boss9Thinker(mobj_t *mobj) mobj->flags &= ~MF_PAIN; mobj->fuse = 10*TICRATE; mobj->movecount = 0; + P_SpawnMobjFromMobj(mobj, 0, 0, 0, MT_CYBRAKDEMON_VILE_EXPLOSION); P_SetMobjState(mobj, mobj->info->meleestate); } else if (!(mobj->threshold%4)) { // We've decided to lock onto the player this bounce. S_StartSound(mobj, sfx_s3k5a); From 758bec6963226d0645da9dc01fc6b48333899e35 Mon Sep 17 00:00:00 2001 From: toasterbabe Date: Tue, 14 Feb 2017 02:07:08 +0000 Subject: [PATCH 5/5] Fixed a bunch of awkwardness where Metal wouldn't reset himself properly when his target died. --- src/p_mobj.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/p_mobj.c b/src/p_mobj.c index 33bcf0ce4..0edc2c484 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -5709,25 +5709,30 @@ static void P_Boss9Thinker(mobj_t *mobj) if ((!mobj->target || !(mobj->target->flags & MF_SHOOTABLE))) { + if (mobj->tracer) + P_RemoveMobj(mobj->tracer); P_BossTargetPlayer(mobj, false); if (mobj->target && (!P_IsObjectOnGround(mobj->target) || mobj->target->player->pflags & PF_SPINNING)) P_SetTarget(&mobj->target, NULL); // Wait for them to hit the ground first if (!mobj->target) // Still no target, aww. { // Reset the boss. + if (mobj->tracer) + P_RemoveMobj(mobj->tracer); P_SetMobjState(mobj, mobj->info->spawnstate); mobj->fuse = 0; mobj->momx = FixedDiv(mobj->momx, FRACUNIT + (FRACUNIT>>2)); mobj->momy = FixedDiv(mobj->momy, FRACUNIT + (FRACUNIT>>2)); mobj->momz = FixedDiv(mobj->momz, FRACUNIT + (FRACUNIT>>2)); + mobj->watertop = mobj->floorz + 32*FRACUNIT; + mobj->momz = (mobj->watertop - mobj->z)>>3; + mobj->threshold = 0; + mobj->movecount = 0; + mobj->flags = mobj->info->flags; return; } else if (!mobj->fuse) mobj->fuse = 10*TICRATE; - - // reset to flying so everything gets properly re-initialised - mobj->threshold = 0; - mobj->movecount = 0; } // AI goes here.