diff --git a/src/d_player.h b/src/d_player.h index 19a998f74..b75a6f51f 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -499,6 +499,8 @@ typedef struct player_s fixed_t bob; angle_t viewrollangle; + // camera tilt + // TODO: expose to lua angle_t tilt; angle_t angleturn; @@ -527,6 +529,8 @@ typedef struct player_s tic_t airtime; // Keep track of how long you've been in the air boolean driftInput; // Whenever or not try drifting. boolean airFailsafe; // Whenever or not try the air boost + INT32 aizDriftTilt; + INT32 aizDriftTurn; UINT8 trickpanel; // Trick panel state boolean trickdelay; // Prevent tricks until control stick is neutral diff --git a/src/doomstat.h b/src/doomstat.h index 522108913..159f83172 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -301,7 +301,6 @@ extern struct quake { // camera offsets and duration fixed_t x,y,z; - angle_t roll; UINT16 time; // location, radius, and intensity... diff --git a/src/hardware/hw_main.c b/src/hardware/hw_main.c index b797a19c4..2c2f21406 100644 --- a/src/hardware/hw_main.c +++ b/src/hardware/hw_main.c @@ -64,6 +64,7 @@ static void HWR_ProjectSprite(mobj_t *thing); #ifdef HWPRECIP static void HWR_ProjectPrecipitationSprite(precipmobj_t *thing); #endif +static void HWR_RollTransform(FTransform *tr, angle_t roll); void HWR_AddTransparentFloor(levelflat_t *levelflat, extrasubsector_t *xsub, boolean isceiling, fixed_t fixedheight, INT32 lightlevel, INT32 alpha, sector_t *FOFSector, FBITFIELD blend, boolean fogplane, extracolormap_t *planecolormap); void HWR_AddTransparentPolyobjectFloor(levelflat_t *levelflat, polyobj_t *polysector, boolean isceiling, fixed_t fixedheight, @@ -5205,7 +5206,8 @@ static void HWR_ProjectSprite(mobj_t *thing) if (spriterotangle != 0 && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { - rollangle = R_GetRollAngle(spriterotangle); + rollangle = R_GetRollAngle(vflip + ? InvAngle(spriterotangle) : spriterotangle); rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); if (rotsprite != NULL) @@ -5743,14 +5745,8 @@ static void HWR_DrawSkyBackground(player_t *player) dometransform.scalez = 1; dometransform.fovxangle = fpov; // Tails dometransform.fovyangle = fpov; // Tails - if (player->viewrollangle != 0) - { - fixed_t rol = AngleFixed(player->viewrollangle); - dometransform.rollangle = FIXED_TO_FLOAT(rol); - dometransform.roll = true; - dometransform.rollx = 1.0f; - dometransform.rollz = 0.0f; - } + HWR_RollTransform(&dometransform, + R_ViewRollAngle(player)); dometransform.splitscreen = r_splitscreen; HWR_GetTexture(texturetranslation[skytexture]); @@ -6042,14 +6038,7 @@ void HWR_RenderSkyboxView(player_t *player) atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails - if (player->viewrollangle != 0) - { - fixed_t rol = AngleFixed(player->viewrollangle); - atransform.rollangle = FIXED_TO_FLOAT(rol); - atransform.roll = true; - atransform.rollx = 1.0f; - atransform.rollz = 0.0f; - } + HWR_RollTransform(&atransform, R_ViewRollAngle(player)); atransform.splitscreen = r_splitscreen; gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); @@ -6160,6 +6149,18 @@ void HWR_RenderSkyboxView(player_t *player) // ========================================================================== // // ========================================================================== + +static void HWR_RollTransform(FTransform *tr, angle_t roll) +{ + if (roll != 0) + { + tr->rollangle = roll / (float)ANG1; + tr->roll = true; + tr->rollx = 1.0f; + tr->rollz = 0.0f; + } +} + void HWR_RenderPlayerView(void) { player_t * player = &players[displayplayers[viewssnum]]; @@ -6249,14 +6250,7 @@ void HWR_RenderPlayerView(void) atransform.fovxangle = fpov; // Tails atransform.fovyangle = fpov; // Tails - if (player->viewrollangle != 0) - { - fixed_t rol = AngleFixed(player->viewrollangle); - atransform.rollangle = FIXED_TO_FLOAT(rol); - atransform.roll = true; - atransform.rollx = 1.0f; - atransform.rollz = 0.0f; - } + HWR_RollTransform(&atransform, R_ViewRollAngle(player)); atransform.splitscreen = r_splitscreen; gl_fovlud = (float)(1.0l/tan((double)(fpov*M_PIl/360l))); diff --git a/src/k_kart.c b/src/k_kart.c index fb899360a..ec7166c77 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -1920,6 +1920,15 @@ void K_KartMoveAnimation(player_t *player) turndir = 1; } + // Use drift frames when sliptiding + if (player->aizDriftTurn) + { + drift = (player->kartstuff[k_aizdriftstrat]); + + if (drift) + turndir = 0; + } + if (lookback == true && drift == 0) { // Prioritize looking back frames over turning @@ -7351,8 +7360,35 @@ static void K_KartDrift(player_t *player, boolean onground) player->kartstuff[k_aizdriftstrat] = ((player->kartstuff[k_drift] > 0) ? 1 : -1); } else if (player->kartstuff[k_aizdriftstrat] && !player->kartstuff[k_drift]) + { K_SpawnAIZDust(player); + if (abs(player->aizDriftTilt) < ANGLE_22h) + { + player->aizDriftTilt = + (abs(player->aizDriftTilt) + ANGLE_11hh / 4) * + player->kartstuff[k_aizdriftstrat]; + } + + if (abs(player->aizDriftTurn) < ANGLE_112h) + { + player->aizDriftTurn = + (abs(player->aizDriftTurn) + ANGLE_11hh) * + player->kartstuff[k_aizdriftstrat]; + } + } + + if (!K_Sliptiding(player)) + { + player->aizDriftTilt -= player->aizDriftTilt / 4; + player->aizDriftTurn -= player->aizDriftTurn / 4; + + if (abs(player->aizDriftTilt) < ANGLE_11hh / 4) + player->aizDriftTilt = 0; + if (abs(player->aizDriftTurn) < ANGLE_11hh) + player->aizDriftTurn = 0; + } + if (player->kartstuff[k_drift] && ((buttons & BT_BRAKE) || !(buttons & BT_ACCELERATE)) @@ -7539,6 +7575,12 @@ boolean K_PlayerEBrake(player_t *player) && player->powers[pw_nocontrol] == 0; } +SINT8 K_Sliptiding(player_t *player) +{ + const INT32 *p = player->kartstuff; + return p[k_drift] ? 0 : p[k_aizdriftstrat]; +} + static void K_KartSpindashDust(mobj_t *parent) { fixed_t rad = FixedDiv(FixedHypot(parent->radius, parent->radius), parent->scale); diff --git a/src/k_kart.h b/src/k_kart.h index da40df761..8a862ba71 100644 --- a/src/k_kart.h +++ b/src/k_kart.h @@ -96,6 +96,7 @@ UINT16 K_GetKartButtons(player_t *player); SINT8 K_GetForwardMove(player_t *player); fixed_t K_3dKartMovement(player_t *player); boolean K_PlayerEBrake(player_t *player); +SINT8 K_Sliptiding(player_t *player); void K_AdjustPlayerFriction(player_t *player); void K_MoveKartPlayer(player_t *player, boolean onground); void K_CheckSpectateStatus(void); diff --git a/src/p_local.h b/src/p_local.h index a04f1f197..7c71c7ebf 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -523,6 +523,7 @@ void P_Thrust(mobj_t *mo, angle_t angle, fixed_t move); void P_ExplodeMissile(mobj_t *mo); void P_CheckGravity(mobj_t *mo, boolean affect); void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope); +void P_SetPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw); fixed_t P_ScaleFromMap(fixed_t n, fixed_t scale); fixed_t P_GetMobjHead(const mobj_t *); fixed_t P_GetMobjFeet(const mobj_t *); diff --git a/src/p_mobj.c b/src/p_mobj.c index fff2a78f1..49165162d 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1250,6 +1250,17 @@ void P_SetPitchRollFromSlope(mobj_t *mo, pslope_t *slope) } } +// +// P_SetPitchRoll +// +void P_SetPitchRoll(mobj_t *mo, angle_t pitch, angle_t yaw) +{ + pitch = InvAngle(pitch); + yaw >>= ANGLETOFINESHIFT; + mo->roll = FixedMul(pitch, FINESINE (yaw)); + mo->pitch = FixedMul(pitch, FINECOSINE (yaw)); +} + #define STOPSPEED (FRACUNIT) // @@ -1662,6 +1673,10 @@ void P_XYMovement(mobj_t *mo) { mo->momz = transfermomz; mo->standingslope = NULL; + P_SetPitchRoll(mo, ANGLE_90, + transferslope->xydirection + + (transferslope->zangle + & ANGLE_180)); if (player) { player->powers[pw_justlaunched] = 2; diff --git a/src/p_tick.c b/src/p_tick.c index ca02b1513..b79a1fa29 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -657,17 +657,10 @@ void P_Ticker(boolean run) quake.z = M_RandomRange(-ir,ir); if (cv_windowquake.value) I_CursedWindowMovement(FixedInt(quake.x), FixedInt(quake.y)); - ir >>= 2; - ir = M_RandomRange(-ir,ir); - if (ir < 0) - ir = ANGLE_MAX - FixedAngle(-ir); - else - ir = FixedAngle(ir); - quake.roll = ir; --quake.time; } else - quake.x = quake.y = quake.z = quake.roll = 0; + quake.x = quake.y = quake.z = 0; if (metalplayback) G_ReadMetalTic(metalplayback); diff --git a/src/p_user.c b/src/p_user.c index 09b8865fd..938d0956f 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2223,7 +2223,11 @@ void P_MovePlayer(player_t *player) { player->drawangle = player->mo->angle; - if (player->kartstuff[k_drift] != 0) + if (player->aizDriftTurn) + { + player->drawangle += player->aizDriftTurn; + } + else if (player->kartstuff[k_drift] != 0) { INT32 a = (ANGLE_45 / 5) * player->kartstuff[k_drift]; player->drawangle += a; @@ -4251,11 +4255,7 @@ Quaketilt (player_t *player) INT32 delta = (INT32)( player->mo->angle - moma ); fixed_t speed; - boolean sliptiding = - ( - player->kartstuff[k_aizdriftstrat] != 0 && - player->kartstuff[k_drift] == 0 - ); + boolean sliptiding = K_Sliptiding(player); if (delta == (INT32)ANGLE_180)/* FUCK YOU HAVE A HACK */ { @@ -4299,52 +4299,37 @@ DoABarrelRoll (player_t *player) angle_t slope; angle_t delta; + fixed_t smoothing; + if (player->exiting) { return; } - if (player->mo->standingslope) - { - slope = player->mo->standingslope->zangle; - } - else + slope = InvAngle(R_GetPitchRollAngle(player->mo)); + + if (AbsAngle(slope) < ANGLE_11hh) { slope = 0; } - if (abs((INT32)slope) > ANGLE_11hh) + if (AbsAngle(slope) > ANGLE_45) { - delta = ( player->mo->angle - player->mo->standingslope->xydirection ); - slope = -(FixedMul(FINESINE (delta>>ANGLETOFINESHIFT), slope)); - } - else - { - slope = 0; + slope = slope & ANGLE_180 ? InvAngle(ANGLE_45) : ANGLE_45; } slope -= Quaketilt(player); - delta = (INT32)( slope - player->tilt )/ 32; + delta = slope - player->tilt; + smoothing = FixedDiv(AbsAngle(slope), ANGLE_45); + + delta = FixedDiv(delta, 33 * + FixedDiv(FRACUNIT, FRACUNIT + smoothing)); if (delta) player->tilt += delta; else player->tilt = slope; - - if (cv_tilting.value) - { - player->viewrollangle = player->tilt; - - if (cv_actionmovie.value) - { - player->viewrollangle += quake.roll; - } - } - else - { - player->viewrollangle = 0; - } } // diff --git a/src/r_main.c b/src/r_main.c index d895c4e10..d8b93144d 100644 --- a/src/r_main.c +++ b/src/r_main.c @@ -629,7 +629,7 @@ void R_CheckViewMorph(int s) float fisheyemap[MAXVIDWIDTH/2 + 1]; #endif - angle_t rollangle = players[displayplayers[s]].viewrollangle; + angle_t rollangle = R_ViewRollAngle(&players[displayplayers[s]]); #ifdef WOUGHMP_WOUGHMP fixed_t fisheye = cv_cam2_turnmultiplier.value; // temporary test value #endif @@ -936,6 +936,30 @@ void R_ApplyViewMorph(int s) width*vid.bpp, height, width*vid.bpp, vid.width); } +static inline int intsign(int n) { + return n < 0 ? -1 : n > 0 ? 1 : 0; +} + +angle_t R_ViewRollAngle(const player_t *player) +{ + angle_t roll = player->viewrollangle; + + if (cv_tilting.value) + { + roll += player->tilt; + + if (cv_actionmovie.value) + { + int xs = intsign(quake.x), + ys = intsign(quake.y), + zs = intsign(quake.z); + roll += (xs ^ ys ^ zs) * ANG1; + } + } + + return roll; +} + // // R_SetViewSize diff --git a/src/r_main.h b/src/r_main.h index d58773a73..49e028149 100644 --- a/src/r_main.h +++ b/src/r_main.h @@ -115,6 +115,7 @@ void R_Init(void); void R_CheckViewMorph(int split); void R_ApplyViewMorph(int split); +angle_t R_ViewRollAngle(const player_t *player); // just sets setsizeneeded true extern boolean setsizeneeded; diff --git a/src/r_patch.h b/src/r_patch.h index c04a3b275..c6d222617 100644 --- a/src/r_patch.h +++ b/src/r_patch.h @@ -39,6 +39,7 @@ patch_t *Patch_GetRotatedSprite( boolean flip, boolean adjustfeet, void *info, INT32 rotationangle); INT32 R_GetRollAngle(angle_t rollangle); +angle_t R_GetPitchRollAngle(mobj_t *mobj); angle_t R_SpriteRotationAngle(mobj_t *mobj); #endif diff --git a/src/r_patchrotation.c b/src/r_patchrotation.c index 769e4c92b..6149bab24 100644 --- a/src/r_patchrotation.c +++ b/src/r_patchrotation.c @@ -14,12 +14,13 @@ #include "z_zone.h" #include "w_wad.h" #include "r_main.h" // R_PointToAngle +#include "k_kart.h" // K_Sliptiding #ifdef ROTSPRITE fixed_t rollcosang[ROTANGLES]; fixed_t rollsinang[ROTANGLES]; -angle_t R_SpriteRotationAngle(mobj_t *mobj) +angle_t R_GetPitchRollAngle(mobj_t *mobj) { angle_t viewingAngle = R_PointToAngle(mobj->x, mobj->y); @@ -28,7 +29,30 @@ angle_t R_SpriteRotationAngle(mobj_t *mobj) angle_t rollOrPitch = FixedMul(mobj->pitch, pitchMul) + FixedMul(mobj->roll, rollMul); - return (rollOrPitch + mobj->rollangle); + return rollOrPitch; +} + +angle_t R_SpriteRotationAngle(mobj_t *mobj) +{ + angle_t viewingAngle = R_PointToAngle(mobj->x, mobj->y); + angle_t angleDelta = (viewingAngle - mobj->angle); + + angle_t sliptideLift = mobj->player + ? mobj->player->aizDriftTilt : 0; + + angle_t rollOrPitch = R_GetPitchRollAngle(mobj); + angle_t rollAngle = (rollOrPitch + mobj->rollangle); + + if (sliptideLift) + { + /* (from side) tilt downward if turning + toward camera, upward if away. */ + rollAngle += + FixedMul(sliptideLift, FINESINE(AbsAngle(angleDelta) >> ANGLETOFINESHIFT)) + + FixedMul(sliptideLift, FINECOSINE(angleDelta >> ANGLETOFINESHIFT)); + } + + return rollAngle; } INT32 R_GetRollAngle(angle_t rollangle) diff --git a/src/r_things.c b/src/r_things.c index 4713fd61b..bb848a679 100644 --- a/src/r_things.c +++ b/src/r_things.c @@ -1581,7 +1581,8 @@ static void R_ProjectSprite(mobj_t *thing) if (spriterotangle && !(splat && !(thing->renderflags & RF_NOSPLATROLLANGLE))) { - rollangle = R_GetRollAngle(spriterotangle); + rollangle = R_GetRollAngle(vflip + ? InvAngle(spriterotangle) : spriterotangle); rotsprite = Patch_GetRotatedSprite(sprframe, (thing->frame & FF_FRAMEMASK), rot, flip, false, sprinfo, rollangle); if (rotsprite != NULL) diff --git a/src/tables.h b/src/tables.h index a34b95ad2..e9ce14484 100644 --- a/src/tables.h +++ b/src/tables.h @@ -93,6 +93,12 @@ FUNCMATH FUNCINLINE static ATTRINLINE angle_t InvAngle(angle_t a) { return (ANGLE_MAX-a)+1; } + +// 315 = 45 +FUNCMATH FUNCINLINE static ATTRINLINE angle_t AbsAngle(angle_t a) +{ + return a & ANGLE_180 ? InvAngle(a) : a; +} // angle_t to fixed_t f(ANGLE_45) = 45*FRACUNIT FUNCMATH fixed_t AngleFixed(angle_t af); // fixed_t to angle_t f(45*FRACUNIT) = ANGLE_45