Implemented the Pterabyte grabbing mechanic

This commit is contained in:
MascaraSnake 2019-09-29 18:42:17 +02:00
parent 22e3c37e5d
commit 26ecab14d7
7 changed files with 165 additions and 8 deletions

View File

@ -234,7 +234,8 @@ typedef enum
CR_ZOOMTUBE,
CR_ROPEHANG,
CR_MACESPIN,
CR_MINECART
CR_MINECART,
CR_PTERABYTE
} carrytype_t; // pw_carry
// Player powers. (don't edit this comment)

View File

@ -8594,6 +8594,7 @@ struct {
{"CR_ROPEHANG",CR_ROPEHANG},
{"CR_MACESPIN",CR_MACESPIN},
{"CR_MINECART",CR_MINECART},
{"CR_PTERABYTE",CR_PTERABYTE},
// Ring weapons (ringweapons_t)
// Useful for A_GiveWeapon

View File

@ -13878,6 +13878,7 @@ void A_SpawnPterabytes(mobj_t *actor)
s = FINESINE(fa);
waypoint = P_SpawnMobjFromMobj(actor, FixedMul(c, rad), FixedMul(s, rad), 0, MT_PTERABYTEWAYPOINT);
waypoint->angle = ang + ANGLE_90;
P_SetTarget(&waypoint->tracer, actor);
ptera = P_SpawnMobjFromMobj(waypoint, 0, 0, 0, MT_PTERABYTE);
ptera->angle = waypoint->angle;
P_SetTarget(&ptera->tracer, waypoint);

View File

@ -456,6 +456,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (P_PlayerCanDamage(player, special)) // Do you possess the ability to subdue the object?
{
if (special->type == MT_PTERABYTE && special->target == player->mo && special->extravalue1 == 1)
return; // Can't hurt a Pterabyte if it's trying to pick you up
if ((P_MobjFlip(toucher)*toucher->momz < 0) && (elementalpierce != 1))
{
if (elementalpierce == 2)
@ -477,7 +480,12 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
P_TwinSpinRejuvenate(player, player->thokitem);
}
else
{
if (special->type == MT_PTERABYTE && special->target == player->mo)
return; // Don't hurt the player you're trying to grab
P_DamageMobj(toucher, special, special, 1, 0);
}
return;
}

View File

@ -490,6 +490,40 @@ static void P_DoFanAndGasJet(mobj_t *spring, mobj_t *object)
}
}
static void P_DoPterabyteCarry(player_t *player, mobj_t *ptera)
{
if (player->powers[pw_carry])
return;
if (ptera->extravalue1 != 1)
return; // Not swooping
if (ptera->target != player->mo)
return; // Not swooping for you!
if (player->spectator)
return;
if ((player->mo->eflags & MFE_VERTICALFLIP) != (ptera->eflags & MFE_VERTICALFLIP))
return; // Both should be in same gravity
if (ptera->eflags & MFE_VERTICALFLIP)
{
if (ptera->ceilingz - (ptera->z + ptera->height) < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return;
}
else if (ptera->z - ptera->floorz < player->mo->height - FixedMul(2*FRACUNIT, player->mo->scale))
return; // No room to pick up this guy!
P_ResetPlayer(player);
P_SetTarget(&player->mo->tracer, ptera);
player->powers[pw_carry] = CR_PTERABYTE;
S_StartSound(player->mo, sfx_s3k4a);
P_UnsetThingPosition(player->mo);
player->mo->x = ptera->x;
player->mo->y = ptera->y;
P_SetThingPosition(player->mo);
ptera->movefactor = 3*TICRATE;
}
static void P_DoTailsCarry(player_t *sonic, player_t *tails)
{
INT32 p;
@ -920,6 +954,9 @@ static boolean PIT_CheckThing(mobj_t *thing)
P_DamageMobj(thing, tmthing, tmthing, 1, 0);
}
if (thing->type == MT_PTERABYTE && tmthing->player)
P_DoPterabyteCarry(tmthing->player, thing);
if (thing->type == MT_VULTURE && tmthing->type == MT_VULTURE)
{
fixed_t dx = thing->x - tmthing->x;

View File

@ -9078,7 +9078,18 @@ void P_MobjThinker(mobj_t *mobj)
}
case MT_PTERABYTE:
{
if (mobj->extravalue1 == 0) // Hovering
if (mobj->extravalue1 & 4) // Cooldown after grabbing
{
if (mobj->movefactor)
mobj->movefactor--;
else
{
P_SetTarget(&mobj->target, NULL);
mobj->extravalue1 &= 3;
}
}
if ((mobj->extravalue1 & 3) == 0) // Hovering
{
fixed_t vdist, hdist, time;
fixed_t hspeed = 3*mobj->info->speed;
@ -9087,21 +9098,31 @@ void P_MobjThinker(mobj_t *mobj)
var1 = 1;
var2 = 0;
A_CapeChase(mobj);
if (mobj->target)
break; // Still carrying a player or in cooldown
P_LookForPlayers(mobj, true, false, 256*FRACUNIT);
if (!mobj->target)
break;
vdist = mobj->z - mobj->target->z;
vdist = mobj->z - mobj->target->z - mobj->target->height;
if (vdist <= 0)
{
P_SetTarget(&mobj->target, NULL);
break;
}
hdist = R_PointToDist2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
if (hdist > 450*FRACUNIT)
{
P_SetTarget(&mobj->target, NULL);
break;
}
P_SetMobjState(mobj, S_PTERABYTE_SWOOPDOWN);
mobj->extravalue1 = 1;
mobj->extravalue1++;
S_StartSound(mobj, mobj->info->attacksound);
time = FixedDiv(hdist, hspeed);
mobj->angle = R_PointToAngle2(mobj->x, mobj->y, mobj->target->x, mobj->target->y);
@ -9113,7 +9134,7 @@ void P_MobjThinker(mobj_t *mobj)
mobj->movecount = time >> FRACBITS;
mobj->reactiontime = mobj->movecount;
}
else if (mobj->extravalue1 == 1) // Swooping
else if ((mobj->extravalue1 & 3) == 1) // Swooping
{
mobj->reactiontime--;
mobj->momz += mobj->extravalue2;
@ -9128,8 +9149,9 @@ void P_MobjThinker(mobj_t *mobj)
else if (mobj->state - states == S_PTERABYTE_SWOOPUP)
{
P_SetMobjState(mobj, S_PTERABYTE_FLY1);
mobj->extravalue1 = 2;
P_SetTarget(&mobj->target, NULL);
mobj->extravalue1++;
if (mobj->target && mobj->target->tracer != mobj)
P_SetTarget(&mobj->target, NULL); // Failed to grab the target
mobj->momx = mobj->momy = mobj->momz = 0;
}
}
@ -9140,7 +9162,7 @@ void P_MobjThinker(mobj_t *mobj)
A_HomingChase(mobj);
if (P_AproxDistance(mobj->x - mobj->tracer->x, mobj->y - mobj->tracer->y) <= mobj->info->speed)
{
mobj->extravalue1 = 0;
mobj->extravalue1 -= 2;
mobj->momx = mobj->momy = mobj->momz = 0;
}
}

View File

@ -4279,6 +4279,9 @@ void P_DoJump(player_t *player, boolean soundandstate)
if (player->mo->ceilingz-player->mo->floorz <= player->mo->height-1)
return;
if (player->powers[pw_carry] == CR_PTERABYTE)
return;
// Jump this high.
if (player->powers[pw_carry] == CR_PLAYER)
{
@ -11518,6 +11521,36 @@ void P_PlayerThink(player_t *player)
}*/
}
// Checks if the mobj is above lava. Used by Pterabyte.
static boolean P_MobjAboveLava(mobj_t *mobj)
{
sector_t *sector = mobj->subsector->sector;
if (sector->ffloors)
{
ffloor_t *rover;
for (rover = sector->ffloors; rover; rover = rover->next)
{
if (!(rover->flags & FF_EXISTS) || !(rover->flags & FF_SWIMMABLE) || GETSECSPECIAL(rover->master->frontsector->special, 1) != 3)
continue;
if (mobj->eflags & MFE_VERTICALFLIP)
{
if (*rover->bottomheight <= mobj->ceilingz && *rover->bottomheight >= mobj->z)
return true;
}
else
{
if (*rover->topheight >= mobj->floorz && *rover->topheight <= mobj->z)
return true;
}
}
}
return false;
}
//
// P_PlayerAfterThink
//
@ -11831,6 +11864,60 @@ void P_PlayerAfterThink(player_t *player)
}
break;
}
case CR_PTERABYTE: // being carried by a Pterabyte
{
mobj_t *ptera = player->mo->tracer;
mobj_t *spawnpoint = ptera->tracer->tracer;
player->mo->height = FixedDiv(P_GetPlayerHeight(player), FixedDiv(14 * FRACUNIT, 10 * FRACUNIT));
if (ptera->health <= 0)
goto dropoff;
if (P_MobjAboveLava(ptera))
goto dropoff;
if (player->mo->eflags & MFE_VERTICALFLIP)
{
if ((ptera->z + ptera->height + player->mo->height + FixedMul(FRACUNIT, player->mo->scale)) <= ptera->ceilingz
&& (ptera->eflags & MFE_VERTICALFLIP)) // Reverse gravity check for the carrier - Flame
player->mo->z = ptera->z + ptera->height + FixedMul(FRACUNIT, player->mo->scale);
if (ptera->ceilingz - ptera->z > spawnpoint->ceilingz - spawnpoint->z + 512*FRACUNIT)
goto dropoff;
}
else
{
if ((ptera->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale)) >= ptera->floorz
&& !(ptera->eflags & MFE_VERTICALFLIP)) // Correct gravity check for the carrier - Flame
player->mo->z = ptera->z - player->mo->height - FixedMul(FRACUNIT, player->mo->scale);
if (ptera->z - ptera->floorz > spawnpoint->z - spawnpoint->floorz + 512 * FRACUNIT)
goto dropoff;
}
ptera->movefactor--;
if (!ptera->movefactor)
goto dropoff;
P_TryMove(player->mo, ptera->x, ptera->y, true);
player->mo->momx = ptera->momx;
player->mo->momy = ptera->momy;
player->mo->momz = ptera->momz;
if (P_AproxDistance(player->mo->x - ptera->x, player->mo->y - ptera->y) > player->mo->radius)
goto dropoff;
if (player->mo->state-states != S_PLAY_RIDE)
P_SetPlayerMobjState(player->mo, S_PLAY_RIDE);
break;
dropoff:
player->powers[pw_carry] = CR_NONE;
P_SetTarget(&player->mo->tracer, NULL);
ptera->movefactor = TICRATE;
ptera->extravalue1 |= 4;
break;
}
default:
break;
}