Model tilts

- Add modeltilt variable, for more manual control of the model tilting. By default this just copies standingslope, but doesn't get cleared in the air.
- Shadows & trailing bananas now tilt to match the ground they are on.
- Rocket Sneakers & afterimages now tilt to match the player's current orientation.
This commit is contained in:
TehRealSalt 2019-05-28 17:21:22 -04:00
parent e1d73d0e35
commit c6a0a41d1a
8 changed files with 233 additions and 19 deletions

View file

@ -1186,11 +1186,11 @@ void HWR_DrawMD2(gr_vissprite_t *spr)
#ifdef USE_FTRANSFORM_ANGLEZ
// Slope rotation from Kart
p.anglez = 0.0f;
if (spr->mobj->standingslope)
if (spr->mobj->modeltilt)
{
fixed_t tempz = spr->mobj->standingslope->normal.z;
fixed_t tempy = spr->mobj->standingslope->normal.y;
fixed_t tempx = spr->mobj->standingslope->normal.x;
fixed_t tempz = spr->mobj->modeltilt->normal.z;
fixed_t tempy = spr->mobj->modeltilt->normal.y;
fixed_t tempx = spr->mobj->modeltilt->normal.x;
fixed_t tempangle = AngleFixed(R_PointToAngle2(0, 0, FixedSqrt(FixedMul(tempy, tempy) + FixedMul(tempz, tempz)), tempx));
p.anglez = FIXED_TO_FLOAT(tempangle);
tempangle = -AngleFixed(R_PointToAngle2(0, 0, tempz, tempy));

View file

@ -4093,6 +4093,86 @@ static void K_MoveHeldObjects(player_t *player)
if (R_PointToDist2(cur->x, cur->y, targx, targy) > 768*FRACUNIT)
P_TeleportMove(cur, targx, targy, cur->z);
#ifdef ESLOPE
// We gotta do ALL of this... just so that bananas can tilt in OGL :V
if (P_IsObjectOnGround(cur))
{
pslope_t *slope = NULL;
sector_t *sec = R_PointInSubsector(cur->x, cur->y)->sector;
boolean flip = (cur->eflags & MFE_VERTICALFLIP);
if (flip)
{
if (sec->c_slope)
{
slope = sec->c_slope;
targz = P_GetZAt(sec->c_slope, cur->x, cur->y);
}
else
targz = sec->ceilingheight;
}
else
{
if (sec->f_slope)
{
slope = sec->f_slope;
targz = P_GetZAt(sec->f_slope, cur->x, cur->y);
}
else
targz = sec->floorheight;
}
// Check FOFs for a better suited slope
if (sec->ffloors)
{
ffloor_t *rover;
for (rover = sec->ffloors; rover; rover = rover->next)
{
fixed_t surface;
if (!(rover->flags & FF_EXISTS))
continue;
if (!((rover->flags & FF_BLOCKOTHERS) || (rover->flags & FF_QUICKSAND)) || (rover->flags & FF_SWIMMABLE))
continue;
if (flip)
{
surface = *rover->bottomheight;
if (*rover->b_slope)
surface = P_GetZAt(*rover->b_slope, cur->x, cur->y);
if (surface < targz && surface > (cur->z + cur->height))
{
targz = surface;
if (*rover->b_slope)
slope = *rover->b_slope;
}
}
else
{
surface = *rover->topheight;
if (*rover->t_slope)
surface = P_GetZAt(*rover->t_slope, cur->x, cur->y);
if (surface > targz && surface < cur->z)
{
targz = surface;
if (*rover->t_slope)
slope = *rover->t_slope;
}
}
}
}
cur->standingslope = slope;
#ifdef HWRENDER
cur->modeltilt = cur->standingslope;
#endif
}
#endif
cur = cur->hnext;
}
}
@ -4182,6 +4262,9 @@ static void K_MoveHeldObjects(player_t *player)
P_TeleportMove(cur, targx, targy, targz);
K_FlipFromObject(cur, player->mo); // Update graviflip in real time thanks.
#ifdef HWRENDER
cur->modeltilt = player->mo->modeltilt;
#endif
num = (num+1) % 2;
cur = cur->hnext;
}

View file

@ -2881,14 +2881,24 @@ boolean P_TryMove(mobj_t *thing, fixed_t x, fixed_t y, boolean allowdropoff)
P_HandleSlopeLanding(thing, tmfloorslope);
if (thing->momz <= 0)
{
thing->standingslope = tmfloorslope;
#ifdef HWRENDER
thing->modeltilt = thing->standingslope;
#endif
}
}
else if (thing->z+thing->height >= tmceilingz && (thing->eflags & MFE_VERTICALFLIP)) {
if (!startingonground && tmceilingslope)
P_HandleSlopeLanding(thing, tmceilingslope);
if (thing->momz >= 0)
{
thing->standingslope = tmceilingslope;
#ifdef HWRENDER
thing->modeltilt = thing->standingslope;
#endif
}
}
}
else // don't set standingslope if you're not going to clip against it
@ -4691,7 +4701,7 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height)
if (!(rover->flags & FF_EXISTS))
continue;
if ((!(rover->flags & FF_SOLID || rover->flags & FF_QUICKSAND) || (rover->flags & FF_SWIMMABLE)))
if (!((rover->flags & FF_SOLID) || (rover->flags & FF_QUICKSAND)) || (rover->flags & FF_SWIMMABLE))
continue;
topheight = *rover->topheight;

View file

@ -1816,6 +1816,9 @@ void P_XYMovement(mobj_t *mo)
// Now compare the Zs of the different quantizations
if (oldangle-newangle > ANG30 && oldangle-newangle < ANGLE_180) { // Allow for a bit of sticking - this value can be adjusted later
mo->standingslope = oldslope;
#ifdef HWRENDER
mo->modeltilt = mo->standingslope;
#endif
P_SlopeLaunch(mo);
//CONS_Printf("launched off of slope - ");
@ -2389,6 +2392,9 @@ static boolean P_ZMovement(mobj_t *mo)
if (((mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope) && (mo->type != MT_STEAM))
{
mo->standingslope = (mo->eflags & MFE_VERTICALFLIP) ? tmceilingslope : tmfloorslope;
#ifdef HWRENDER
mo->modeltilt = mo->standingslope;
#endif
P_ReverseQuantizeMomentumToSlope(&mom, mo->standingslope);
}
#endif
@ -6173,7 +6179,12 @@ void P_RunShadows(void)
for (mobj = shadowcap; mobj; mobj = next)
{
fixed_t floorz;
boolean flip;
fixed_t newz;
sector_t *sec;
#ifdef ESLOPE
pslope_t *slope = NULL;
#endif
next = mobj->hnext;
P_SetTarget(&mobj->hnext, NULL);
@ -6184,16 +6195,106 @@ void P_RunShadows(void)
continue; // shouldn't you already be dead?
}
if (mobj->target->player)
floorz = mobj->target->floorz;
else // FOR SOME REASON, plain floorz is not reliable for normal objects, only players?!
floorz = P_FloorzAtPos(mobj->target->x, mobj->target->y, mobj->target->z, mobj->target->height);
K_MatchGenericExtraFlags(mobj, mobj->target);
flip = (mobj->eflags & MFE_VERTICALFLIP);
if (((mobj->target->eflags & MFE_VERTICALFLIP) && mobj->target->z+mobj->target->height > mobj->target->ceilingz)
|| (!(mobj->target->eflags & MFE_VERTICALFLIP) && mobj->target->z < floorz))
mobj->flags2 |= MF2_DONTDRAW;
sec = R_PointInSubsector(mobj->target->x, mobj->target->y)->sector;
if (flip)
{
#ifdef ESLOPE
if (sec->c_slope)
{
slope = sec->c_slope;
newz = P_GetZAt(sec->c_slope, mobj->target->x, mobj->target->y);
}
else
#endif
newz = sec->ceilingheight;
}
else
{
#ifdef ESLOPE
if (sec->f_slope)
{
slope = sec->f_slope;
newz = P_GetZAt(sec->f_slope, mobj->target->x, mobj->target->y);
}
else
#endif
newz = sec->floorheight;
}
// Check FOFs for a better suited slope
if (sec->ffloors)
{
ffloor_t *rover;
for (rover = sec->ffloors; rover; rover = rover->next)
{
fixed_t surface;
if (!(rover->flags & FF_EXISTS))
continue;
if ((!(((rover->flags & FF_BLOCKPLAYER && mobj->target->player)
|| (rover->flags & FF_BLOCKOTHERS && !mobj->target->player))
|| (rover->flags & FF_QUICKSAND))
|| (rover->flags & FF_SWIMMABLE)))
continue;
if (flip)
{
surface = *rover->bottomheight;
#ifdef ESLOPE
if (*rover->b_slope)
surface = P_GetZAt(*rover->b_slope, mobj->target->x, mobj->target->y);
#endif
if (surface < newz && surface > (mobj->target->z + mobj->target->height))
{
newz = surface;
#ifdef ESLOPE
if (*rover->b_slope)
slope = *rover->b_slope;
#endif
}
}
else
{
surface = *rover->topheight;
#ifdef ESLOPE
if (*rover->t_slope)
surface = P_GetZAt(*rover->t_slope, mobj->target->x, mobj->target->y);
#endif
if (surface > newz && surface < mobj->target->z)
{
newz = surface;
#ifdef ESLOPE
if (*rover->t_slope)
slope = *rover->t_slope;
#endif
}
}
}
}
mobj->standingslope = slope;
#ifdef HWRENDER
mobj->modeltilt = mobj->standingslope;
#endif
if (flip)
{
if ((mobj->target->z + mobj->target->height) > newz)
mobj->flags2 |= MF2_DONTDRAW;
}
else
{
if (mobj->target->z < newz)
mobj->flags2 |= MF2_DONTDRAW;
}
// First scale to the same radius
P_SetScale(mobj, FixedDiv(mobj->target->radius, mobj->info->radius));
@ -6205,13 +6306,12 @@ void P_RunShadows(void)
P_TeleportMove(mobj, dest->x, dest->y, mobj->target->z);
if (((mobj->eflags & MFE_VERTICALFLIP) && (mobj->ceilingz > mobj->z+mobj->height))
|| (!(mobj->eflags & MFE_VERTICALFLIP) && (floorz < mobj->z)))
if ((flip && newz > (mobj->z + mobj->height)) || (!flip && newz < mobj->z))
{
INT32 i;
fixed_t prevz;
mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : floorz);
mobj->z = newz;
for (i = 0; i < MAXFFLOORS; i++)
{
@ -6223,7 +6323,7 @@ void P_RunShadows(void)
// Check new position to see if you should still be on that ledge
P_TeleportMove(mobj, dest->x, dest->y, mobj->z);
mobj->z = (mobj->eflags & MFE_VERTICALFLIP ? mobj->ceilingz : floorz);
mobj->z = newz;
if (mobj->z == prevz)
break;
@ -8132,6 +8232,9 @@ void P_MobjThinker(mobj_t *mobj)
P_TeleportMove(mobj, mobj->target->x + P_ReturnThrustX(mobj, mobj->angle+ANGLE_180, mobj->target->radius),
mobj->target->y + P_ReturnThrustY(mobj, mobj->angle+ANGLE_180, mobj->target->radius), mobj->target->z);
P_SetScale(mobj, mobj->target->scale);
#ifdef HWRENDER
mobj->modeltilt = mobj->target->modeltilt;
#endif
{
player_t *p = NULL;

View file

@ -370,6 +370,9 @@ typedef struct mobj_s
#ifdef ESLOPE
struct pslope_s *standingslope; // The slope that the object is standing on (shouldn't need synced in savegames, right?)
#ifdef HWRENDER
struct pslope_s *modeltilt; // Slope used for model tilting. Also is not synched, this is totally visual.
#endif
#endif
boolean colorized; // Whether the mobj uses the rainbow colormap

View file

@ -2144,7 +2144,12 @@ static void LoadMobjThinker(actionf_p1 thinker)
mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
#ifdef ESLOPE
if (diff2 & MD2_SLOPE)
{
mobj->standingslope = P_SlopeById(READUINT16(save_p));
#ifdef HWRENDER
mobj->modeltilt = mobj->standingslope;
#endif
}
#endif
if (diff2 & MD2_COLORIZED)
mobj->colorized = READUINT8(save_p);

View file

@ -827,6 +827,9 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
if (P_MobjFlip(thing)*(thing->momz) < 0) { // falling, land on slope
thing->momz = -P_MobjFlip(thing);
thing->standingslope = slope;
#ifdef HWRENDER
thing->modeltilt = thing->standingslope;
#endif
}
return;
}
@ -843,6 +846,9 @@ void P_HandleSlopeLanding(mobj_t *thing, pslope_t *slope)
thing->momz = -P_MobjFlip(thing);
thing->standingslope = slope;
#ifdef HWRENDER
thing->modeltilt = thing->standingslope;
#endif
}
}

View file

@ -1675,12 +1675,16 @@ mobj_t *P_SpawnGhostMobj(mobj_t *mobj)
ghost->frame |= tr_trans50<<FF_TRANSSHIFT;
ghost->fuse = ghost->info->damage;
ghost->skin = mobj->skin;
ghost->standingslope = mobj->standingslope;
#ifdef HWRENDER
ghost->modeltilt = mobj->modeltilt;
#endif
if (mobj->flags2 & MF2_OBJECTFLIP)
ghost->flags |= MF2_OBJECTFLIP;
if (!(mobj->flags & MF_DONTENCOREMAP))
mobj->flags &= ~MF_DONTENCOREMAP;
ghost->flags &= ~MF_DONTENCOREMAP;
return ghost;
}