diff --git a/src/d_player.h b/src/d_player.h index 0fd123aec..36e1e34e1 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -278,6 +278,15 @@ typedef struct botvars_s } botvars_t; +typedef struct { + tic_t enter_tic, exit_tic; + tic_t zoom_in_speed, zoom_out_speed; + fixed_t dist; + angle_t pan; + fixed_t pan_speed; // in degrees + tic_t pan_accel, pan_back; +} sonicloopcamvars_t; + // player_t struct for loop state typedef struct { fixed_t radius; @@ -286,6 +295,7 @@ typedef struct { vector3_t origin; vector2_t shift; boolean flip; + sonicloopcamvars_t camera; } sonicloopvars_t; // ======================================================================== diff --git a/src/objects/loops.c b/src/objects/loops.c index dd9ea7c3b..7ae499fba 100644 --- a/src/objects/loops.c +++ b/src/objects/loops.c @@ -220,6 +220,7 @@ Obj_LoopEndpointCollide { player_t *player = toucher->player; sonicloopvars_t *s = &player->loop; + sonicloopcamvars_t *cam = &s->camera; mobj_t *anchor = end_anchor(end); mobj_t *center = anchor ? anchor_center(anchor) : NULL; @@ -272,6 +273,17 @@ Obj_LoopEndpointCollide s->flip = center_has_flip(center); + cam->enter_tic = leveltime; + cam->exit_tic = INFTICS; + + cam->zoom_out_speed = center->spawnpoint->args[2]; + cam->zoom_in_speed = center->spawnpoint->args[3]; + cam->dist = center->spawnpoint->args[4] * FRACUNIT; + cam->pan = FixedAngle(center->spawnpoint->args[5] * FRACUNIT); + cam->pan_speed = center->spawnpoint->args[6] * FRACUNIT; + cam->pan_accel = center->spawnpoint->args[7]; + cam->pan_back = center->spawnpoint->args[8]; + player->speed = 3 * (player->speed + toucher->momz) / 2; diff --git a/src/p_loop.c b/src/p_loop.c index 66a8f7db4..b8f4093f9 100644 --- a/src/p_loop.c +++ b/src/p_loop.c @@ -41,6 +41,7 @@ void P_HaltPlayerOrbit(player_t *player) player->mo->flags &= ~(MF_NOCLIPHEIGHT); player->loop.radius = 0; + player->loop.camera.exit_tic = leveltime; } void P_ExitPlayerOrbit(player_t *player) diff --git a/src/p_saveg.c b/src/p_saveg.c index 1fbe6d1d6..bd48bccb4 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -370,6 +370,16 @@ static void P_NetArchivePlayers(void) WRITEFIXED(save_p, players[i].loop.shift.y); WRITEUINT8(save_p, players[i].loop.flip); + // sonicloopcamvars_t + WRITEUINT32(save_p, players[i].loop.camera.enter_tic); + WRITEUINT32(save_p, players[i].loop.camera.exit_tic); + WRITEUINT32(save_p, players[i].loop.camera.zoom_in_speed); + WRITEUINT32(save_p, players[i].loop.camera.zoom_out_speed); + WRITEFIXED(save_p, players[i].loop.camera.dist); + WRITEANGLE(save_p, players[i].loop.camera.pan); + WRITEFIXED(save_p, players[i].loop.camera.pan_speed); + WRITEUINT32(save_p, players[i].loop.camera.pan_accel); + WRITEUINT32(save_p, players[i].loop.camera.pan_back); } } @@ -648,6 +658,17 @@ static void P_NetUnArchivePlayers(void) players[i].loop.shift.y = READFIXED(save_p); players[i].loop.flip = READUINT8(save_p); + // sonicloopcamvars_t + players[i].loop.camera.enter_tic = READUINT32(save_p); + players[i].loop.camera.exit_tic = READUINT32(save_p); + players[i].loop.camera.zoom_in_speed = READUINT32(save_p); + players[i].loop.camera.zoom_out_speed = READUINT32(save_p); + players[i].loop.camera.dist = READFIXED(save_p); + players[i].loop.camera.pan = READANGLE(save_p); + players[i].loop.camera.pan_speed = READFIXED(save_p); + players[i].loop.camera.pan_accel = READUINT32(save_p); + players[i].loop.camera.pan_back = READUINT32(save_p); + //players[i].viewheight = P_GetPlayerViewHeight(players[i]); // scale cannot be factored in at this point } } diff --git a/src/p_user.c b/src/p_user.c index c4d71017b..d469c2ca6 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -3026,6 +3026,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall subsector_t *newsubsec; #endif + sonicloopcamvars_t *loop = &player->loop.camera; + tic_t loop_out = leveltime - loop->enter_tic; + tic_t loop_in = max(leveltime, loop->exit_tic) - loop->exit_tic; + thiscam->old_x = thiscam->x; thiscam->old_y = thiscam->y; thiscam->old_z = thiscam->z; @@ -3147,6 +3151,58 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall camdist = FixedMul(cv_cam_dist[num].value, mapobjectscale); camheight = FixedMul(cv_cam_height[num].value, mapobjectscale); + if (loop_in < loop->zoom_in_speed) + { + fixed_t f = loop_out < loop->zoom_out_speed + ? (loop_out * FRACUNIT) / loop->zoom_out_speed + : FRACUNIT - ((loop_in * FRACUNIT) / loop->zoom_in_speed); + + camspeed -= FixedMul(f, camspeed - (FRACUNIT/10)); + camdist += FixedMul(f, loop->dist); + } + + if (loop_in < max(loop->pan_back, 1)) + { + fixed_t f = (loop_in * FRACUNIT) / max(loop->pan_back, 1); + + fixed_t dx = mo->x - thiscam->x; + fixed_t dy = mo->y - thiscam->y; + + angle_t th = R_PointToAngle2(0, 0, dx, dy); + fixed_t d = AngleFixed(focusangle - th); + + if (d > 180*FRACUNIT) + { + d -= (360*FRACUNIT); + } + + focusangle = th + FixedAngle(FixedMul(f, d)); + + if (loop_in == 0) + { + focusaiming = R_PointToAngle2(0, thiscam->z, FixedHypot(dx, dy), mo->z); + } + } + + if (loop_in == 0) + { + tic_t accel = max(loop->pan_accel, 1); + fixed_t f = (min(loop_out, accel) * FRACUNIT) / accel; + + INT32 turn = AngleDeltaSigned(focusangle, player->loop.yaw - loop->pan); + INT32 turnspeed = FixedAngle(FixedMul(f, loop->pan_speed)); + + if (turn > turnspeed) + { + if (turn < ANGLE_90) + { + turnspeed = -(turnspeed); + } + + focusangle += turnspeed; + } + } + if (timeover) { const INT32 timeovercam = max(0, min(180, (player->karthud[khud_timeovercam] - 2*TICRATE)*15)); @@ -4041,6 +4097,11 @@ DoABarrelRoll (player_t *player) fixed_t smoothing; + if (player->loop.radius) + { + return; + } + if (player->respawn) { player->tilt = 0;