Merge branch 'metal_unsuck' into 'master'

Making Metal's pinch cues suck less

Does what it says on the tin. Give it a shot with <root>/toaster/metaltest.wad to skip the race and go directly to the boss to see what it does!

See merge request !70
This commit is contained in:
Monster Iestyn 2017-03-10 14:20:36 -05:00
commit 4f80bd82a5
4 changed files with 77 additions and 36 deletions

View File

@ -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",

View File

@ -1369,14 +1369,14 @@ 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, 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, 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, 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
@ -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
@ -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

View File

@ -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,

View File

@ -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)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS)));\
if (P_RandomChance(FRACUNIT/2))\
mobj->movedir = InvAngle(mobj->movedir);\
mobj->threshold = 6 + (FixedMul(24<<FRACBITS, FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS))>>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.
@ -5685,19 +5694,41 @@ 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)))
{
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)
@ -5745,7 +5776,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 +5789,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 +5876,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(mobj->momx, mobj->momy,0,0);
mobj->momz = 4*FRACUNIT;
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);
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;
}
@ -5860,8 +5906,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--;
@ -5978,9 +6025,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 +6110,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)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS)));
if (P_RandomChance(FRACUNIT/2))
mobj->movedir = InvAngle(mobj->movedir);
mobj->threshold = 6 + (FixedMul(24<<FRACBITS, FixedDiv((mobj->info->spawnhealth - mobj->health)<<FRACBITS, (mobj->info->spawnhealth-1)<<FRACBITS))>>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 +6125,7 @@ static void P_Boss9Thinker(mobj_t *mobj)
}
}
}
#undef vectorise
//
// P_GetClosestAxis